diff --git a/client/tx/legacy.go b/client/tx/legacy.go index 2648a520c..71f0fe8c4 100644 --- a/client/tx/legacy.go +++ b/client/tx/legacy.go @@ -6,28 +6,28 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" "github.com/cosmos/cosmos-sdk/x/auth/signing" - "github.com/cosmos/cosmos-sdk/x/auth/types" ) // ConvertTxToStdTx converts a transaction to the legacy StdTx format -func ConvertTxToStdTx(codec *codec.LegacyAmino, tx signing.Tx) (types.StdTx, error) { - if stdTx, ok := tx.(types.StdTx); ok { +func ConvertTxToStdTx(codec *codec.LegacyAmino, tx signing.Tx) (legacytx.StdTx, error) { + if stdTx, ok := tx.(legacytx.StdTx); ok { return stdTx, nil } - aminoTxConfig := types.StdTxConfig{Cdc: codec} + aminoTxConfig := legacytx.StdTxConfig{Cdc: codec} builder := aminoTxConfig.NewTxBuilder() err := CopyTx(tx, builder) if err != nil { - return types.StdTx{}, err + return legacytx.StdTx{}, err } - stdTx, ok := builder.GetTx().(types.StdTx) + stdTx, ok := builder.GetTx().(legacytx.StdTx) if !ok { - return types.StdTx{}, fmt.Errorf("expected %T, got %+v", types.StdTx{}, builder.GetTx()) + return legacytx.StdTx{}, fmt.Errorf("expected %T, got %+v", legacytx.StdTx{}, builder.GetTx()) } return stdTx, nil @@ -58,13 +58,13 @@ func CopyTx(tx signing.Tx, builder client.TxBuilder) error { return nil } -func ConvertAndEncodeStdTx(txConfig client.TxConfig, stdTx types.StdTx) ([]byte, error) { +func ConvertAndEncodeStdTx(txConfig client.TxConfig, stdTx legacytx.StdTx) ([]byte, error) { builder := txConfig.NewTxBuilder() var theTx sdk.Tx // check if we need a StdTx anyway, in that case don't copy - if _, ok := builder.GetTx().(types.StdTx); ok { + if _, ok := builder.GetTx().(legacytx.StdTx); ok { theTx = stdTx } else { err := CopyTx(stdTx, builder) diff --git a/client/tx/legacy_test.go b/client/tx/legacy_test.go index 786ebc767..4884faa83 100644 --- a/client/tx/legacy_test.go +++ b/client/tx/legacy_test.go @@ -14,10 +14,10 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/testdata" "github.com/cosmos/cosmos-sdk/types" signing2 "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/cosmos/cosmos-sdk/x/auth/tx" - types3 "github.com/cosmos/cosmos-sdk/x/auth/types" - types2 "github.com/cosmos/cosmos-sdk/x/bank/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) const ( @@ -29,7 +29,7 @@ var ( fee = types.NewCoins(types.NewInt64Coin("bam", 100)) _, pub1, addr1 = testdata.KeyTestPubAddr() _, _, addr2 = testdata.KeyTestPubAddr() - msg = types2.NewMsgSend(addr1, addr2, types.NewCoins(types.NewInt64Coin("wack", 10000))) + msg = banktypes.NewMsgSend(addr1, addr2, types.NewCoins(types.NewInt64Coin("wack", 10000))) sig = signing2.SignatureV2{ PubKey: pub1, Data: &signing2.SingleSignatureData{ @@ -60,7 +60,7 @@ func (s *TestSuite) SetupSuite() { encCfg := simapp.MakeEncodingConfig() s.encCfg = encCfg s.protoCfg = tx.NewTxConfig(codec.NewProtoCodec(encCfg.InterfaceRegistry), tx.DefaultSignModes) - s.aminoCfg = types3.StdTxConfig{Cdc: encCfg.Amino} + s.aminoCfg = legacytx.StdTxConfig{Cdc: encCfg.Amino} } func (s *TestSuite) TestCopyTx() { @@ -111,7 +111,7 @@ func (s *TestSuite) TestConvertTxToStdTx() { // std tx aminoBuilder := s.aminoCfg.NewTxBuilder() buildTestTx(s.T(), aminoBuilder) - stdTx = aminoBuilder.GetTx().(types3.StdTx) + stdTx = aminoBuilder.GetTx().(legacytx.StdTx) stdTx2, err := tx2.ConvertTxToStdTx(s.encCfg.Amino, stdTx) s.Require().NoError(err) s.Require().Equal(stdTx, stdTx2) @@ -121,7 +121,7 @@ func (s *TestSuite) TestConvertAndEncodeStdTx() { // convert amino -> proto -> amino aminoBuilder := s.aminoCfg.NewTxBuilder() buildTestTx(s.T(), aminoBuilder) - stdTx := aminoBuilder.GetTx().(types3.StdTx) + stdTx := aminoBuilder.GetTx().(legacytx.StdTx) txBz, err := tx2.ConvertAndEncodeStdTx(s.protoCfg, stdTx) s.Require().NoError(err) decodedTx, err := s.protoCfg.TxDecoder()(txBz) diff --git a/crypto/keys/multisig/multisig_test.go b/crypto/keys/multisig/multisig_test.go index d04531b94..96ed9a612 100644 --- a/crypto/keys/multisig/multisig_test.go +++ b/crypto/keys/multisig/multisig_test.go @@ -8,7 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec/types" crypto "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" "github.com/stretchr/testify/require" @@ -262,8 +262,8 @@ func TestMultiSigMigration(t *testing.T) { err := multisig.AddSignatureFromPubKey(multisignature, sigs[0], pkSet[0], pkSet) // create a StdSignature for msg, and convert it to sigV2 - sig := authtypes.StdSignature{PubKey: pkSet[1], Signature: msg} - sigV2, err := authtypes.StdSignatureToSignatureV2(cdc, sig) + sig := legacytx.StdSignature{PubKey: pkSet[1], Signature: msg} + sigV2, err := legacytx.StdSignatureToSignatureV2(cdc, sig) require.NoError(t, multisig.AddSignatureV2(multisignature, sigV2, pkSet)) require.NoError(t, err) diff --git a/simapp/params/amino.go b/simapp/params/amino.go index 67ee2d54d..ff9b05a9f 100644 --- a/simapp/params/amino.go +++ b/simapp/params/amino.go @@ -5,7 +5,7 @@ package params import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" ) // MakeEncodingConfig creates an EncodingConfig for an amino based test configuration. @@ -17,7 +17,7 @@ func MakeEncodingConfig() EncodingConfig { return EncodingConfig{ InterfaceRegistry: interfaceRegistry, Marshaler: marshaler, - TxConfig: authtypes.StdTxConfig{Cdc: cdc}, + TxConfig: legacytx.StdTxConfig{Cdc: cdc}, Amino: cdc, } } diff --git a/x/auth/ante/ante_test.go b/x/auth/ante/ante_test.go index 670985f78..1fd13e77f 100644 --- a/x/auth/ante/ante_test.go +++ b/x/auth/ante/ante_test.go @@ -954,7 +954,7 @@ func TestCountSubkeys(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(T *testing.T) { - require.Equal(t, tc.want, types.CountSubKeys(tc.args.pub)) + require.Equal(t, tc.want, ante.CountSubKeys(tc.args.pub)) }) } } diff --git a/x/auth/ante/basic.go b/x/auth/ante/basic.go index b73b95656..f722e51a0 100644 --- a/x/auth/ante/basic.go +++ b/x/auth/ante/basic.go @@ -8,12 +8,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" - "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -var ( - _ sdk.TxWithMemo = (*types.StdTx)(nil) // assert StdTx implements TxWithMemo ) // ValidateBasicDecorator will call tx.ValidateBasic and return any non-nil error. @@ -79,7 +75,7 @@ func (vmd ValidateMemoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate // CONTRACT: If simulate=true, then signatures must either be completely filled // in or empty. // CONTRACT: To use this decorator, signatures of transaction must be represented -// as types.StdSignature otherwise simulate mode will incorrectly estimate gas cost. +// as legacytx.StdSignature otherwise simulate mode will incorrectly estimate gas cost. type ConsumeTxSizeGasDecorator struct { ak AccountKeeper } @@ -126,7 +122,7 @@ func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, sim } // use stdsignature to mock the size of a full signature - simSig := types.StdSignature{ //nolint:staticcheck // this will be removed when proto is ready + simSig := legacytx.StdSignature{ //nolint:staticcheck // this will be removed when proto is ready Signature: simSecp256k1Sig[:], PubKey: pubkey, } diff --git a/x/auth/ante/fee.go b/x/auth/ante/fee.go index 47ef35b73..5da4dbbaf 100644 --- a/x/auth/ante/fee.go +++ b/x/auth/ante/fee.go @@ -8,10 +8,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/types" ) -var ( - _ sdk.FeeTx = (*types.StdTx)(nil) // assert StdTx implements FeeTx -) - // MempoolFeeDecorator will check if the transaction's fee is at least as large // as the local validator's minimum gasFee (defined in validator config). // If fee is too low, decorator returns error and tx is rejected from mempool. diff --git a/x/auth/ante/setup.go b/x/auth/ante/setup.go index 1e3e8eb68..5f21aba8b 100644 --- a/x/auth/ante/setup.go +++ b/x/auth/ante/setup.go @@ -5,11 +5,11 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" ) var ( - _ GasTx = (*types.StdTx)(nil) // assert StdTx implements GasTx + _ GasTx = (*legacytx.StdTx)(nil) // assert StdTx implements GasTx ) // GasTx defines a Tx with a GetGas() method which is needed to use SetUpContextDecorator diff --git a/x/auth/ante/sigverify.go b/x/auth/ante/sigverify.go index 05bc583b1..4c091bb94 100644 --- a/x/auth/ante/sigverify.go +++ b/x/auth/ante/sigverify.go @@ -5,13 +5,16 @@ import ( "encoding/hex" "fmt" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" + kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/cosmos/cosmos-sdk/x/auth/types" ) @@ -22,7 +25,7 @@ var ( simSecp256k1Pubkey = &secp256k1.PubKey{Key: key} simSecp256k1Sig [64]byte - _ authsigning.SigVerifiableTx = (*types.StdTx)(nil) // assert StdTx implements SigVerifiableTx + _ authsigning.SigVerifiableTx = (*legacytx.StdTx)(nil) // assert StdTx implements SigVerifiableTx ) func init() { @@ -340,7 +343,7 @@ func (vscd ValidateSigCountDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, sim sigCount := 0 for _, pk := range pubKeys { - sigCount += types.CountSubKeys(pk) + sigCount += CountSubKeys(pk) if uint64(sigCount) > params.TxSigLimit { return ctx, sdkerrors.Wrapf(sdkerrors.ErrTooManySignatures, "signatures: %d, limit: %d", sigCount, params.TxSigLimit) @@ -420,3 +423,18 @@ func GetSignerAcc(ctx sdk.Context, ak AccountKeeper, addr sdk.AccAddress) (types return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", addr) } + +// CountSubKeys counts the total number of keys for a multi-sig public key. +func CountSubKeys(pub crypto.PubKey) int { + v, ok := pub.(*kmultisig.LegacyAminoPubKey) + if !ok { + return 1 + } + + numKeys := 0 + for _, subkey := range v.GetPubKeys() { + numKeys += CountSubKeys(subkey) + } + + return numKeys +} diff --git a/x/auth/ante/sigverify_test.go b/x/auth/ante/sigverify_test.go index 58d1dea8b..3144a1f9c 100644 --- a/x/auth/ante/sigverify_test.go +++ b/x/auth/ante/sigverify_test.go @@ -16,8 +16,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth/ante" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" "github.com/cosmos/cosmos-sdk/x/auth/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) func (suite *AnteTestSuite) TestSetPubKey() { @@ -75,8 +75,8 @@ func (suite *AnteTestSuite) TestConsumeSignatureVerificationGas() { multisignature1 := multisig.NewMultisig(len(pkSet1)) expectedCost1 := expectedGasCostByKeys(pkSet1) for i := 0; i < len(pkSet1); i++ { - stdSig := types.StdSignature{PubKey: pkSet1[i], Signature: sigSet1[i]} - sigV2, err := types.StdSignatureToSignatureV2(cdc, stdSig) + stdSig := legacytx.StdSignature{PubKey: pkSet1[i], Signature: sigSet1[i]} + sigV2, err := legacytx.StdSignatureToSignatureV2(cdc, stdSig) suite.Require().NoError(err) err = multisig.AddSignatureV2(multisignature1, sigV2, pkSet1) suite.Require().NoError(err) @@ -196,7 +196,7 @@ func (suite *AnteTestSuite) TestSigVerification_ExplicitAmino() { // Set up TxConfig. aminoCdc := codec.NewLegacyAmino() // We're using TestMsg amino encoding in some tests, so register it here. - txConfig := authtypes.StdTxConfig{Cdc: aminoCdc} + txConfig := legacytx.StdTxConfig{Cdc: aminoCdc} suite.clientCtx = client.Context{}. WithTxConfig(txConfig) diff --git a/x/auth/client/rest/broadcast.go b/x/auth/client/rest/broadcast.go index 37daf5084..e0020515d 100644 --- a/x/auth/client/rest/broadcast.go +++ b/x/auth/client/rest/broadcast.go @@ -8,13 +8,13 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/types/rest" - "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" ) // BroadcastReq defines a tx broadcasting request. type BroadcastReq struct { - Tx types.StdTx `json:"tx" yaml:"tx"` - Mode string `json:"mode" yaml:"mode"` + Tx legacytx.StdTx `json:"tx" yaml:"tx"` + Mode string `json:"mode" yaml:"mode"` } // BroadcastTxRequest implements a tx broadcasting handler that is responsible diff --git a/x/auth/client/rest/decode.go b/x/auth/client/rest/decode.go index f42cc09c4..ca72487a8 100644 --- a/x/auth/client/rest/decode.go +++ b/x/auth/client/rest/decode.go @@ -11,7 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" clienttx "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/types/rest" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" ) type ( @@ -21,7 +21,7 @@ type ( } // DecodeResp defines a tx decoding response. - DecodeResp authtypes.StdTx + DecodeResp legacytx.StdTx ) // DecodeTxRequestHandlerFn returns the decode tx REST handler. In particular, @@ -61,21 +61,21 @@ func DecodeTxRequestHandlerFn(clientCtx client.Context) http.HandlerFunc { // convertToStdTx converts tx proto binary bytes retrieved from Tendermint into // a StdTx. Returns the StdTx, as well as a flag denoting if the function // successfully converted or not. -func convertToStdTx(w http.ResponseWriter, clientCtx client.Context, txBytes []byte) (authtypes.StdTx, bool) { +func convertToStdTx(w http.ResponseWriter, clientCtx client.Context, txBytes []byte) (legacytx.StdTx, bool) { txI, err := clientCtx.TxConfig.TxDecoder()(txBytes) if rest.CheckBadRequestError(w, err) { - return authtypes.StdTx{}, false + return legacytx.StdTx{}, false } tx, ok := txI.(signing.Tx) if !ok { - rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("%+v is not backwards compatible with %T", tx, authtypes.StdTx{})) - return authtypes.StdTx{}, false + rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("%+v is not backwards compatible with %T", tx, legacytx.StdTx{})) + return legacytx.StdTx{}, false } stdTx, err := clienttx.ConvertTxToStdTx(clientCtx.LegacyAmino, tx) if rest.CheckBadRequestError(w, err) { - return authtypes.StdTx{}, false + return legacytx.StdTx{}, false } return stdTx, true diff --git a/x/auth/client/rest/encode.go b/x/auth/client/rest/encode.go index e3930a1f8..1fbc3b94f 100644 --- a/x/auth/client/rest/encode.go +++ b/x/auth/client/rest/encode.go @@ -9,7 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/types/rest" - "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" ) // EncodeResp defines a tx encoding response. @@ -22,7 +22,7 @@ type EncodeResp struct { // and responds with base64-encoded bytes. func EncodeTxRequestHandlerFn(clientCtx client.Context) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var req types.StdTx + var req legacytx.StdTx body, err := ioutil.ReadAll(r.Body) if rest.CheckBadRequestError(w, err) { diff --git a/x/auth/client/rest/rest_test.go b/x/auth/client/rest/rest_test.go index de3c8fee2..7ae6fe824 100644 --- a/x/auth/client/rest/rest_test.go +++ b/x/auth/client/rest/rest_test.go @@ -15,7 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/tx/signing" authclient "github.com/cosmos/cosmos-sdk/x/auth/client" rest2 "github.com/cosmos/cosmos-sdk/x/auth/client/rest" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -44,57 +44,53 @@ func (s *IntegrationTestSuite) TearDownSuite() { s.network.Cleanup() } -func (s *IntegrationTestSuite) TestEncodeDecode() { - val := s.network.Validators[0] - +func mkTx() legacytx.StdTx { // NOTE: this uses StdTx explicitly, don't migrate it! - stdTx := authtypes.StdTx{ + return legacytx.StdTx{ Msgs: []sdk.Msg{&types.MsgSend{}}, - Fee: authtypes.StdFee{ + Fee: legacytx.StdFee{ Amount: sdk.Coins{sdk.NewInt64Coin("foo", 10)}, Gas: 10000, }, Memo: "FOOBAR", } +} + +func (s *IntegrationTestSuite) TestEncodeDecode() { + var require = s.Require() + val := s.network.Validators[0] + stdTx := mkTx() // NOTE: this uses amino explicitly, don't migrate it! cdc := val.ClientCtx.LegacyAmino bz, err := cdc.MarshalJSON(stdTx) - s.Require().NoError(err) + require.NoError(err) res, err := rest.PostRequest(fmt.Sprintf("%s/txs/encode", val.APIAddress), "application/json", bz) - s.Require().NoError(err) + require.NoError(err) var encodeResp rest2.EncodeResp err = cdc.UnmarshalJSON(res, &encodeResp) - s.Require().NoError(err) + require.NoError(err) bz, err = cdc.MarshalJSON(rest2.DecodeReq{Tx: encodeResp.Tx}) - s.Require().NoError(err) + require.NoError(err) res, err = rest.PostRequest(fmt.Sprintf("%s/txs/decode", val.APIAddress), "application/json", bz) - s.Require().NoError(err) + require.NoError(err) var respWithHeight rest.ResponseWithHeight err = cdc.UnmarshalJSON(res, &respWithHeight) - s.Require().NoError(err) + require.NoError(err) var decodeResp rest2.DecodeResp err = cdc.UnmarshalJSON(respWithHeight.Result, &decodeResp) - s.Require().NoError(err) - s.Require().Equal(stdTx, authtypes.StdTx(decodeResp)) + require.NoError(err) + require.Equal(stdTx, legacytx.StdTx(decodeResp)) } func (s *IntegrationTestSuite) TestBroadcastTxRequest() { - // NOTE: this uses StdTx explicitly, don't migrate it! - stdTx := authtypes.StdTx{ - Msgs: []sdk.Msg{&types.MsgSend{}}, - Fee: authtypes.StdFee{ - Amount: sdk.Coins{sdk.NewInt64Coin("foo", 10)}, - Gas: 10000, - }, - Memo: "FOOBAR", - } + stdTx := mkTx() // we just test with async mode because this tx will fail - all we care about is that it got encoded and broadcast correctly res, err := s.broadcastReq(stdTx, "async") @@ -182,8 +178,8 @@ func (s *IntegrationTestSuite) TestMultipleSyncBroadcastTxRequests() { } } -func (s *IntegrationTestSuite) createTestStdTx(val *network.Validator, sequence uint64) authtypes.StdTx { - txConfig := authtypes.StdTxConfig{Cdc: s.cfg.LegacyAmino} +func (s *IntegrationTestSuite) createTestStdTx(val *network.Validator, sequence uint64) legacytx.StdTx { + txConfig := legacytx.StdTxConfig{Cdc: s.cfg.LegacyAmino} msg := &types.MsgSend{ FromAddress: val.Address, @@ -212,17 +208,16 @@ func (s *IntegrationTestSuite) createTestStdTx(val *network.Validator, sequence err := authclient.SignTx(txFactory, val.ClientCtx, val.Moniker, txBuilder, true) s.Require().NoError(err) - stdTx := txBuilder.GetTx().(authtypes.StdTx) + stdTx := txBuilder.GetTx().(legacytx.StdTx) return stdTx } -func (s *IntegrationTestSuite) broadcastReq(stdTx authtypes.StdTx, mode string) ([]byte, error) { +func (s *IntegrationTestSuite) broadcastReq(stdTx legacytx.StdTx, mode string) ([]byte, error) { val := s.network.Validators[0] // NOTE: this uses amino explicitly, don't migrate it! cdc := val.ClientCtx.LegacyAmino - req := rest2.BroadcastReq{ Tx: stdTx, Mode: mode, diff --git a/x/auth/client/tx.go b/x/auth/client/tx.go index e3af34132..79570d519 100644 --- a/x/auth/client/tx.go +++ b/x/auth/client/tx.go @@ -16,7 +16,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" ) // Codec defines the x/auth account codec to be used for use with the @@ -156,7 +156,7 @@ func populateAccountFromState( func GetTxEncoder(cdc *codec.LegacyAmino) (encoder sdk.TxEncoder) { encoder = sdk.GetConfig().GetTxEncoder() if encoder == nil { - encoder = authtypes.DefaultTxEncoder(cdc) + encoder = legacytx.DefaultTxEncoder(cdc) } return encoder diff --git a/x/auth/client/tx_test.go b/x/auth/client/tx_test.go index bf433f1e3..e87ce21a3 100644 --- a/x/auth/client/tx_test.go +++ b/x/auth/client/tx_test.go @@ -5,20 +5,18 @@ import ( "strings" "testing" + "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/testdata" - authclient "github.com/cosmos/cosmos-sdk/x/auth/client" - - "github.com/cosmos/cosmos-sdk/client" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/codec" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" + authclient "github.com/cosmos/cosmos-sdk/x/auth/client" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) @@ -49,7 +47,7 @@ func TestParseQueryResponse(t *testing.T) { func TestDefaultTxEncoder(t *testing.T) { cdc := makeCodec() - defaultEncoder := authtypes.DefaultTxEncoder(cdc) + defaultEncoder := legacytx.DefaultTxEncoder(cdc) encoder := authclient.GetTxEncoder(cdc) compareEncoders(t, defaultEncoder, encoder) @@ -142,7 +140,7 @@ func TestBatchScanner_Scan(t *testing.T) { func compareEncoders(t *testing.T, expected sdk.TxEncoder, actual sdk.TxEncoder) { msgs := []sdk.Msg{testdata.NewTestMsg(addr)} - tx := authtypes.NewStdTx(msgs, authtypes.StdFee{}, []authtypes.StdSignature{}, "") + tx := legacytx.NewStdTx(msgs, legacytx.StdFee{}, []legacytx.StdSignature{}, "") defaultEncoderBytes, err := expected(tx) require.NoError(t, err) diff --git a/x/auth/legacy/legacytx/amino_signing.go b/x/auth/legacy/legacytx/amino_signing.go new file mode 100644 index 000000000..d09b1b30a --- /dev/null +++ b/x/auth/legacy/legacytx/amino_signing.go @@ -0,0 +1,91 @@ +package legacytx + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/crypto/types/multisig" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/cosmos/cosmos-sdk/x/auth/signing" +) + +// stdTxSignModeHandler is a SignModeHandler that handles SIGN_MODE_LEGACY_AMINO_JSON +type stdTxSignModeHandler struct{} + +func NewStdTxSignModeHandler() signing.SignModeHandler { + return &stdTxSignModeHandler{} +} + +// assert interface implementation +var _ signing.SignModeHandler = stdTxSignModeHandler{} + +// DefaultMode implements SignModeHandler.DefaultMode +func (h stdTxSignModeHandler) DefaultMode() signingtypes.SignMode { + return signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON +} + +// Modes implements SignModeHandler.Modes +func (stdTxSignModeHandler) Modes() []signingtypes.SignMode { + return []signingtypes.SignMode{signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON} +} + +// DefaultMode implements SignModeHandler.GetSignBytes +func (stdTxSignModeHandler) GetSignBytes(mode signingtypes.SignMode, data signing.SignerData, tx sdk.Tx) ([]byte, error) { + if mode != signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON { + return nil, fmt.Errorf("expected %s, got %s", signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, mode) + } + + stdTx, ok := tx.(StdTx) + if !ok { + return nil, fmt.Errorf("expected %T, got %T", StdTx{}, tx) + } + + return StdSignBytes( + data.ChainID, data.AccountNumber, data.Sequence, stdTx.GetTimeoutHeight(), StdFee{Amount: stdTx.GetFee(), Gas: stdTx.GetGas()}, tx.GetMsgs(), stdTx.GetMemo(), + ), nil +} + +// SignatureDataToAminoSignature converts a SignatureData to amino-encoded signature bytes. +// Only SIGN_MODE_LEGACY_AMINO_JSON is supported. +func SignatureDataToAminoSignature(cdc *codec.LegacyAmino, data signingtypes.SignatureData) ([]byte, error) { + switch data := data.(type) { + case *signingtypes.SingleSignatureData: + if data.SignMode != signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON { + return nil, fmt.Errorf("wrong SignMode. Expected %s, got %s", + signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, data.SignMode) + } + + return data.Signature, nil + case *signingtypes.MultiSignatureData: + aminoMSig, err := MultiSignatureDataToAminoMultisignature(cdc, data) + if err != nil { + return nil, err + } + + return cdc.MarshalBinaryBare(aminoMSig) + default: + return nil, fmt.Errorf("unexpected signature data %T", data) + } +} + +// MultiSignatureDataToAminoMultisignature converts a MultiSignatureData to an AminoMultisignature. +// Only SIGN_MODE_LEGACY_AMINO_JSON is supported. +func MultiSignatureDataToAminoMultisignature(cdc *codec.LegacyAmino, mSig *signingtypes.MultiSignatureData) (multisig.AminoMultisignature, error) { + n := len(mSig.Signatures) + sigs := make([][]byte, n) + + for i := 0; i < n; i++ { + var err error + sigs[i], err = SignatureDataToAminoSignature(cdc, mSig.Signatures[i]) + if err != nil { + return multisig.AminoMultisignature{}, sdkerrors.Wrapf(err, "Unable to convert Signature Data to signature %d", i) + } + } + + return multisig.AminoMultisignature{ + BitArray: mSig.BitArray, + Sigs: sigs, + }, nil +} diff --git a/x/auth/types/amino_signing_test.go b/x/auth/legacy/legacytx/amino_signing_test.go similarity index 99% rename from x/auth/types/amino_signing_test.go rename to x/auth/legacy/legacytx/amino_signing_test.go index a436f0b22..7abccbfd8 100644 --- a/x/auth/types/amino_signing_test.go +++ b/x/auth/legacy/legacytx/amino_signing_test.go @@ -1,4 +1,4 @@ -package types +package legacytx import ( "testing" diff --git a/x/auth/legacy/legacytx/codec.go b/x/auth/legacy/legacytx/codec.go new file mode 100644 index 000000000..2bad4718e --- /dev/null +++ b/x/auth/legacy/legacytx/codec.go @@ -0,0 +1,9 @@ +package legacytx + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(StdTx{}, "cosmos-sdk/StdTx", nil) +} diff --git a/x/auth/types/client_tx_test.go b/x/auth/legacy/legacytx/config_test.go similarity index 84% rename from x/auth/types/client_tx_test.go rename to x/auth/legacy/legacytx/config_test.go index 2acdf0f97..95a37b1e4 100644 --- a/x/auth/types/client_tx_test.go +++ b/x/auth/legacy/legacytx/config_test.go @@ -1,4 +1,4 @@ -package types_test +package legacytx_test import ( "testing" @@ -9,8 +9,8 @@ import ( cryptoAmino "github.com/cosmos/cosmos-sdk/crypto/codec" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" "github.com/cosmos/cosmos-sdk/x/auth/testutil" - "github.com/cosmos/cosmos-sdk/x/auth/types" ) func testCodec() *codec.LegacyAmino { @@ -23,6 +23,6 @@ func testCodec() *codec.LegacyAmino { func TestStdTxConfig(t *testing.T) { cdc := testCodec() - txGen := types.StdTxConfig{Cdc: cdc} + txGen := legacytx.StdTxConfig{Cdc: cdc} suite.Run(t, testutil.NewTxConfigTestSuite(txGen)) } diff --git a/x/auth/legacy/legacytx/stdsign.go b/x/auth/legacy/legacytx/stdsign.go new file mode 100644 index 000000000..ee44171be --- /dev/null +++ b/x/auth/legacy/legacytx/stdsign.go @@ -0,0 +1,112 @@ +package legacytx + +import ( + "encoding/json" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/types/multisig" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/tendermint/tendermint/crypto" +) + +// Interface implementation checks +var _ codectypes.UnpackInterfacesMessage = StdTx{} + +// StdSignDoc is replay-prevention structure. +// It includes the result of msg.GetSignBytes(), +// as well as the ChainID (prevent cross chain replay) +// and the Sequence numbers for each signature (prevent +// inchain replay and enforce tx ordering per account). +type StdSignDoc struct { + AccountNumber uint64 `json:"account_number" yaml:"account_number"` + Sequence uint64 `json:"sequence" yaml:"sequence"` + TimeoutHeight uint64 `json:"timeout_height,omitempty" yaml:"timeout_height"` + ChainID string `json:"chain_id" yaml:"chain_id"` + Memo string `json:"memo" yaml:"memo"` + Fee json.RawMessage `json:"fee" yaml:"fee"` + Msgs []json.RawMessage `json:"msgs" yaml:"msgs"` +} + +// StdSignBytes returns the bytes to sign for a transaction. +func StdSignBytes(chainID string, accnum, sequence, timeout uint64, fee StdFee, msgs []sdk.Msg, memo string) []byte { + msgsBytes := make([]json.RawMessage, 0, len(msgs)) + for _, msg := range msgs { + msgsBytes = append(msgsBytes, json.RawMessage(msg.GetSignBytes())) + } + + bz, err := legacy.Cdc.MarshalJSON(StdSignDoc{ + AccountNumber: accnum, + ChainID: chainID, + Fee: json.RawMessage(fee.Bytes()), + Memo: memo, + Msgs: msgsBytes, + Sequence: sequence, + TimeoutHeight: timeout, + }) + if err != nil { + panic(err) + } + + return sdk.MustSortJSON(bz) +} + +// Deprecated: StdSignature represents a sig +type StdSignature struct { + crypto.PubKey `json:"pub_key" yaml:"pub_key"` // optional + Signature []byte `json:"signature" yaml:"signature"` +} + +// StdSignatureToSignatureV2 converts a StdSignature to a SignatureV2 +func StdSignatureToSignatureV2(cdc *codec.LegacyAmino, sig StdSignature) (signing.SignatureV2, error) { + pk := sig.GetPubKey() + data, err := pubKeySigToSigData(cdc, pk, sig.Signature) + if err != nil { + return signing.SignatureV2{}, err + } + + return signing.SignatureV2{ + PubKey: pk, + Data: data, + }, nil +} + +func pubKeySigToSigData(cdc *codec.LegacyAmino, key crypto.PubKey, sig []byte) (signing.SignatureData, error) { + multiPK, ok := key.(multisig.PubKey) + if !ok { + return &signing.SingleSignatureData{ + SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + Signature: sig, + }, nil + } + var multiSig multisig.AminoMultisignature + err := cdc.UnmarshalBinaryBare(sig, &multiSig) + if err != nil { + return nil, err + } + + sigs := multiSig.Sigs + sigDatas := make([]signing.SignatureData, len(sigs)) + pubKeys := multiPK.GetPubKeys() + bitArray := multiSig.BitArray + n := multiSig.BitArray.Count() + signatures := multisig.NewMultisig(n) + sigIdx := 0 + for i := 0; i < n; i++ { + if bitArray.GetIndex(i) { + data, err := pubKeySigToSigData(cdc, pubKeys[i], multiSig.Sigs[sigIdx]) + if err != nil { + return nil, sdkerrors.Wrapf(err, "Unable to convert Signature to SigData %d", sigIdx) + } + + sigDatas[sigIdx] = data + multisig.AddSignature(signatures, data, sigIdx) + sigIdx++ + } + } + + return signatures, nil +} diff --git a/x/auth/types/stdsignmsg.go b/x/auth/legacy/legacytx/stdsignmsg.go similarity index 98% rename from x/auth/types/stdsignmsg.go rename to x/auth/legacy/legacytx/stdsignmsg.go index b7d5e0718..07ee29a06 100644 --- a/x/auth/types/stdsignmsg.go +++ b/x/auth/legacy/legacytx/stdsignmsg.go @@ -1,4 +1,4 @@ -package types +package legacytx import ( "github.com/cosmos/cosmos-sdk/codec/types" diff --git a/x/auth/legacy/legacytx/stdtx.go b/x/auth/legacy/legacytx/stdtx.go new file mode 100644 index 000000000..81d670e74 --- /dev/null +++ b/x/auth/legacy/legacytx/stdtx.go @@ -0,0 +1,274 @@ +package legacytx + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/codec/legacy" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + txtypes "github.com/cosmos/cosmos-sdk/types/tx" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/tendermint/tendermint/crypto" + "gopkg.in/yaml.v2" +) + +// Interface implementation checks +var ( + _ sdk.Tx = (*StdTx)(nil) + _ codectypes.IntoAny = (*StdTx)(nil) + _ sdk.TxWithMemo = (*StdTx)(nil) + _ sdk.FeeTx = (*StdTx)(nil) +) + +// StdFee includes the amount of coins paid in fees and the maximum +// gas to be used by the transaction. The ratio yields an effective "gasprice", +// which must be above some miminum to be accepted into the mempool. +// [Deprecated] +type StdFee struct { + Amount sdk.Coins `json:"amount" yaml:"amount"` + Gas uint64 `json:"gas" yaml:"gas"` +} + +// Deprecated: NewStdFee returns a new instance of StdFee +func NewStdFee(gas uint64, amount sdk.Coins) StdFee { + return StdFee{ + Amount: amount, + Gas: gas, + } +} + +// GetGas returns the fee's (wanted) gas. +func (fee StdFee) GetGas() uint64 { + return fee.Gas +} + +// GetAmount returns the fee's amount. +func (fee StdFee) GetAmount() sdk.Coins { + return fee.Amount +} + +// Bytes returns the encoded bytes of a StdFee. +func (fee StdFee) Bytes() []byte { + if len(fee.Amount) == 0 { + fee.Amount = sdk.NewCoins() + } + + bz, err := legacy.Cdc.MarshalJSON(fee) + if err != nil { + panic(err) + } + + return bz +} + +// GasPrices returns the gas prices for a StdFee. +// +// NOTE: The gas prices returned are not the true gas prices that were +// originally part of the submitted transaction because the fee is computed +// as fee = ceil(gasWanted * gasPrices). +func (fee StdFee) GasPrices() sdk.DecCoins { + return sdk.NewDecCoinsFromCoins(fee.Amount...).QuoDec(sdk.NewDec(int64(fee.Gas))) +} + +// Deprecated +func NewStdSignature(pk crypto.PubKey, sig []byte) StdSignature { + return StdSignature{PubKey: pk, Signature: sig} +} + +// GetSignature returns the raw signature bytes. +func (ss StdSignature) GetSignature() []byte { + return ss.Signature +} + +// GetPubKey returns the public key of a signature as a crypto.PubKey using the +// Amino codec. +func (ss StdSignature) GetPubKey() crypto.PubKey { + return ss.PubKey +} + +// MarshalYAML returns the YAML representation of the signature. +func (ss StdSignature) MarshalYAML() (interface{}, error) { + var ( + bz []byte + pubkey string + err error + ) + + if ss.PubKey != nil { + pubkey, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, ss.GetPubKey()) + if err != nil { + return nil, err + } + } + + bz, err = yaml.Marshal(struct { + PubKey string + Signature string + }{ + PubKey: pubkey, + Signature: fmt.Sprintf("%X", ss.Signature), + }) + if err != nil { + return nil, err + } + + return string(bz), err +} + +// StdTx is the legacy transaction format for wrapping a Msg with Fee and Signatures. +// It only works with Amino, please prefer the new protobuf Tx in types/tx. +// NOTE: the first signature is the fee payer (Signatures must not be nil). +// Deprecated +type StdTx struct { + Msgs []sdk.Msg `json:"msg" yaml:"msg"` + Fee StdFee `json:"fee" yaml:"fee"` + Signatures []StdSignature `json:"signatures" yaml:"signatures"` + Memo string `json:"memo" yaml:"memo"` + TimeoutHeight uint64 `json:"timeout_height" yaml:"timeout_height"` +} + +// Deprecated +func NewStdTx(msgs []sdk.Msg, fee StdFee, sigs []StdSignature, memo string) StdTx { + return StdTx{ + Msgs: msgs, + Fee: fee, + Signatures: sigs, + Memo: memo, + } +} + +// GetMsgs returns the all the transaction's messages. +func (tx StdTx) GetMsgs() []sdk.Msg { return tx.Msgs } + +// ValidateBasic does a simple and lightweight validation check that doesn't +// require access to any other information. +func (tx StdTx) ValidateBasic() error { + stdSigs := tx.GetSignatures() + + if tx.Fee.Gas > txtypes.MaxGasWanted { + return sdkerrors.Wrapf( + sdkerrors.ErrInvalidRequest, + "invalid gas supplied; %d > %d", tx.Fee.Gas, txtypes.MaxGasWanted, + ) + } + if tx.Fee.Amount.IsAnyNegative() { + return sdkerrors.Wrapf( + sdkerrors.ErrInsufficientFee, + "invalid fee provided: %s", tx.Fee.Amount, + ) + } + if len(stdSigs) == 0 { + return sdkerrors.ErrNoSignatures + } + if len(stdSigs) != len(tx.GetSigners()) { + return sdkerrors.Wrapf( + sdkerrors.ErrUnauthorized, + "wrong number of signers; expected %d, got %d", len(tx.GetSigners()), len(stdSigs), + ) + } + + return nil +} + +// AsAny implements IntoAny.AsAny. +func (tx *StdTx) AsAny() *codectypes.Any { + return codectypes.UnsafePackAny(tx) +} + +// GetSigners returns the addresses that must sign the transaction. +// Addresses are returned in a deterministic order. +// They are accumulated from the GetSigners method for each Msg +// in the order they appear in tx.GetMsgs(). +// Duplicate addresses will be omitted. +func (tx StdTx) GetSigners() []sdk.AccAddress { + var signers []sdk.AccAddress + seen := map[string]bool{} + + for _, msg := range tx.GetMsgs() { + for _, addr := range msg.GetSigners() { + if !seen[addr.String()] { + signers = append(signers, addr) + seen[addr.String()] = true + } + } + } + + return signers +} + +// GetMemo returns the memo +func (tx StdTx) GetMemo() string { return tx.Memo } + +// GetTimeoutHeight returns the transaction's timeout height (if set). +func (tx StdTx) GetTimeoutHeight() uint64 { + return tx.TimeoutHeight +} + +// GetSignatures returns the signature of signers who signed the Msg. +// CONTRACT: Length returned is same as length of +// pubkeys returned from MsgKeySigners, and the order +// matches. +// CONTRACT: If the signature is missing (ie the Msg is +// invalid), then the corresponding signature is +// .Empty(). +func (tx StdTx) GetSignatures() [][]byte { + sigs := make([][]byte, len(tx.Signatures)) + for i, stdSig := range tx.Signatures { + sigs[i] = stdSig.Signature + } + return sigs +} + +// GetSignaturesV2 implements SigVerifiableTx.GetSignaturesV2 +func (tx StdTx) GetSignaturesV2() ([]signing.SignatureV2, error) { + res := make([]signing.SignatureV2, len(tx.Signatures)) + + for i, sig := range tx.Signatures { + var err error + res[i], err = StdSignatureToSignatureV2(legacy.Cdc, sig) + if err != nil { + return nil, sdkerrors.Wrapf(err, "Unable to convert signature %v to V2", sig) + } + } + + return res, nil +} + +// GetPubkeys returns the pubkeys of signers if the pubkey is included in the signature +// If pubkey is not included in the signature, then nil is in the slice instead +func (tx StdTx) GetPubKeys() []crypto.PubKey { + pks := make([]crypto.PubKey, len(tx.Signatures)) + + for i, stdSig := range tx.Signatures { + pks[i] = stdSig.GetPubKey() + } + + return pks +} + +// GetGas returns the Gas in StdFee +func (tx StdTx) GetGas() uint64 { return tx.Fee.Gas } + +// GetFee returns the FeeAmount in StdFee +func (tx StdTx) GetFee() sdk.Coins { return tx.Fee.Amount } + +// FeePayer returns the address that is responsible for paying fee +// StdTx returns the first signer as the fee payer +// If no signers for tx, return empty address +func (tx StdTx) FeePayer() sdk.AccAddress { + if tx.GetSigners() != nil { + return tx.GetSigners()[0] + } + return sdk.AccAddress{} +} + +func (tx StdTx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + for _, m := range tx.Msgs { + err := codectypes.UnpackInterfaces(m, unpacker) + if err != nil { + return err + } + } + return nil +} diff --git a/x/auth/types/client_tx.go b/x/auth/legacy/legacytx/stdtx_builder.go similarity index 67% rename from x/auth/types/client_tx.go rename to x/auth/legacy/legacytx/stdtx_builder.go index 04b289376..1b1a55c04 100644 --- a/x/auth/types/client_tx.go +++ b/x/auth/legacy/legacytx/stdtx_builder.go @@ -1,4 +1,4 @@ -package types +package legacytx import ( "fmt" @@ -6,6 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/tx/signing" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" ) @@ -18,6 +19,7 @@ type StdTxBuilder struct { cdc *codec.LegacyAmino } +// ensure interface implementation var _ client.TxBuilder = &StdTxBuilder{} // GetTx implements TxBuilder.GetTx @@ -34,14 +36,12 @@ func (s *StdTxBuilder) SetMsgs(msgs ...sdk.Msg) error { // SetSignatures implements TxBuilder.SetSignatures. func (s *StdTxBuilder) SetSignatures(signatures ...signing.SignatureV2) error { sigs := make([]StdSignature, len(signatures)) - + var err error for i, sig := range signatures { - stdSig, err := SignatureV2ToStdSignature(s.cdc, sig) + sigs[i], err = SignatureV2ToStdSignature(s.cdc, sig) if err != nil { return err } - - sigs[i] = stdSig } s.Signatures = sigs @@ -85,7 +85,7 @@ func (s StdTxConfig) NewTxBuilder() client.TxBuilder { func (s StdTxConfig) WrapTxBuilder(newTx sdk.Tx) (client.TxBuilder, error) { stdTx, ok := newTx.(StdTx) if !ok { - return nil, fmt.Errorf("expected %T, got %T", StdTx{}, newTx) + return nil, fmt.Errorf("wrong type, expected %T, got %T", stdTx, newTx) } return &StdTxBuilder{StdTx: stdTx, cdc: s.Cdc}, nil } @@ -96,7 +96,7 @@ func (s StdTxConfig) TxEncoder() sdk.TxEncoder { } func (s StdTxConfig) TxDecoder() sdk.TxDecoder { - return DefaultTxDecoder(s.Cdc) + return mkDecoder(s.Cdc.UnmarshalBinaryBare) } func (s StdTxConfig) TxJSONEncoder() sdk.TxEncoder { @@ -106,7 +106,7 @@ func (s StdTxConfig) TxJSONEncoder() sdk.TxEncoder { } func (s StdTxConfig) TxJSONDecoder() sdk.TxDecoder { - return DefaultJSONTxDecoder(s.Cdc) + return mkDecoder(s.Cdc.UnmarshalJSON) } func (s StdTxConfig) MarshalSignatureJSON(sigs []signing.SignatureV2) ([]byte, error) { @@ -144,3 +144,50 @@ func (s StdTxConfig) UnmarshalSignatureJSON(bz []byte) ([]signing.SignatureV2, e func (s StdTxConfig) SignModeHandler() authsigning.SignModeHandler { return stdTxSignModeHandler{} } + +// SignatureV2ToStdSignature converts a SignatureV2 to a StdSignature +// [Deprecated] +func SignatureV2ToStdSignature(cdc *codec.LegacyAmino, sig signing.SignatureV2) (StdSignature, error) { + var ( + sigBz []byte + err error + ) + + if sig.Data != nil { + sigBz, err = SignatureDataToAminoSignature(cdc, sig.Data) + if err != nil { + return StdSignature{}, err + } + } + + return StdSignature{ + PubKey: sig.PubKey, + Signature: sigBz, + }, nil +} + +// Unmarshaler is a generic type for Unmarshal functions +type Unmarshaler func(bytes []byte, ptr interface{}) error + +func mkDecoder(unmarshaler Unmarshaler) sdk.TxDecoder { + return func(txBytes []byte) (sdk.Tx, error) { + if len(txBytes) == 0 { + return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx bytes are empty") + } + var tx = StdTx{} + // StdTx.Msg is an interface. The concrete types + // are registered by MakeTxCodec + err := unmarshaler(txBytes, &tx) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error()) + } + return tx, nil + } +} + +// DefaultTxEncoder logic for standard transaction encoding +func DefaultTxEncoder(cdc *codec.LegacyAmino) sdk.TxEncoder { + return func(tx sdk.Tx) ([]byte, error) { + return cdc.MarshalBinaryBare(tx) + } +} diff --git a/x/auth/types/stdtx_test.go b/x/auth/legacy/legacytx/stdtx_test.go similarity index 98% rename from x/auth/types/stdtx_test.go rename to x/auth/legacy/legacytx/stdtx_test.go index 86bf72441..cc73db03d 100644 --- a/x/auth/types/stdtx_test.go +++ b/x/auth/legacy/legacytx/stdtx_test.go @@ -1,4 +1,4 @@ -package types +package legacytx import ( "fmt" @@ -26,6 +26,11 @@ var ( addr = sdk.AccAddress(priv.PubKey().Address()) ) +func init() { + var amino = codec.NewLegacyAmino() + RegisterLegacyAminoCodec(amino) +} + // Deprecated, use fee amount and gas limit separately on TxBuilder. func NewTestStdFee() StdFee { return NewStdFee(100000, @@ -156,7 +161,6 @@ func TestTxValidateBasic(t *testing.T) { func TestDefaultTxEncoder(t *testing.T) { cdc := codec.NewLegacyAmino() sdk.RegisterLegacyAminoCodec(cdc) - RegisterLegacyAminoCodec(cdc) cdc.RegisterConcrete(testdata.TestMsg{}, "cosmos-sdk/Test", nil) encoder := DefaultTxEncoder(cdc) @@ -207,7 +211,6 @@ func TestSignatureV2Conversions(t *testing.T) { _, pubKey, _ := testdata.KeyTestPubAddr() cdc := codec.NewLegacyAmino() sdk.RegisterLegacyAminoCodec(cdc) - RegisterLegacyAminoCodec(cdc) dummy := []byte("dummySig") sig := StdSignature{PubKey: pubKey, Signature: dummy} @@ -265,7 +268,6 @@ func TestGetSignaturesV2(t *testing.T) { cdc := codec.NewLegacyAmino() sdk.RegisterLegacyAminoCodec(cdc) cryptocodec.RegisterCrypto(cdc) - RegisterLegacyAminoCodec(cdc) fee := NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)}) sig := StdSignature{PubKey: pubKey, Signature: dummy} diff --git a/x/auth/signing/handler_map_test.go b/x/auth/signing/handler_map_test.go index 35a2f022d..6ca405661 100644 --- a/x/auth/signing/handler_map_test.go +++ b/x/auth/signing/handler_map_test.go @@ -8,8 +8,8 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" "github.com/cosmos/cosmos-sdk/x/auth/signing" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -17,7 +17,7 @@ func MakeTestHandlerMap() signing.SignModeHandler { return signing.NewSignModeHandlerMap( signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, []signing.SignModeHandler{ - authtypes.NewStdTxSignModeHandler(), + legacytx.NewStdTxSignModeHandler(), }, ) } @@ -30,7 +30,7 @@ func TestHandlerMap_GetSignBytes(t *testing.T) { coins := sdk.Coins{sdk.NewInt64Coin("foocoin", 10)} - fee := authtypes.StdFee{ + fee := legacytx.StdFee{ Amount: coins, Gas: 10000, } @@ -43,7 +43,7 @@ func TestHandlerMap_GetSignBytes(t *testing.T) { }, } - tx := authtypes.StdTx{ + tx := legacytx.StdTx{ Msgs: msgs, Fee: fee, Signatures: nil, @@ -57,7 +57,7 @@ func TestHandlerMap_GetSignBytes(t *testing.T) { ) handler := MakeTestHandlerMap() - aminoJSONHandler := authtypes.NewStdTxSignModeHandler() + aminoJSONHandler := legacytx.NewStdTxSignModeHandler() signingData := signing.SignerData{ ChainID: chainId, diff --git a/x/auth/signing/verify_test.go b/x/auth/signing/verify_test.go index c5bc0be31..351fa0138 100644 --- a/x/auth/signing/verify_test.go +++ b/x/auth/signing/verify_test.go @@ -14,6 +14,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/ante" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/cosmos/cosmos-sdk/x/auth/types" ) @@ -44,22 +45,22 @@ func TestVerifySignature(t *testing.T) { require.NoError(t, app.BankKeeper.SetBalances(ctx, addr, balances)) msgs := []sdk.Msg{testdata.NewTestMsg(addr)} - fee := types.NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)}) + fee := legacytx.NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)}) signerData := signing.SignerData{ ChainID: chainId, AccountNumber: acc.GetAccountNumber(), Sequence: acc.GetSequence(), } - signBytes := types.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.Sequence, 10, fee, msgs, memo) + signBytes := legacytx.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.Sequence, 10, fee, msgs, memo) signature, err := priv.Sign(signBytes) require.NoError(t, err) - stdSig := types.StdSignature{PubKey: pubKey, Signature: signature} - sigV2, err := types.StdSignatureToSignatureV2(cdc, stdSig) + stdSig := legacytx.StdSignature{PubKey: pubKey, Signature: signature} + sigV2, err := legacytx.StdSignatureToSignatureV2(cdc, stdSig) require.NoError(t, err) handler := MakeTestHandlerMap() - stdTx := types.NewStdTx(msgs, fee, []types.StdSignature{stdSig}, memo) + stdTx := legacytx.NewStdTx(msgs, fee, []legacytx.StdSignature{stdSig}, memo) stdTx.TimeoutHeight = 10 err = signing.VerifySignature(pubKey, signerData, sigV2.Data, handler, stdTx) require.NoError(t, err) @@ -68,18 +69,18 @@ func TestVerifySignature(t *testing.T) { multisigKey := kmultisig.NewLegacyAminoPubKey(2, pkSet) multisignature := multisig.NewMultisig(2) msgs = []sdk.Msg{testdata.NewTestMsg(addr, addr1)} - multiSignBytes := types.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.Sequence, 10, fee, msgs, memo) + multiSignBytes := legacytx.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.Sequence, 10, fee, msgs, memo) sig1, err := priv.Sign(multiSignBytes) require.NoError(t, err) - stdSig1 := types.StdSignature{PubKey: pubKey, Signature: sig1} - sig1V2, err := types.StdSignatureToSignatureV2(cdc, stdSig1) + stdSig1 := legacytx.StdSignature{PubKey: pubKey, Signature: sig1} + sig1V2, err := legacytx.StdSignatureToSignatureV2(cdc, stdSig1) require.NoError(t, err) sig2, err := priv1.Sign(multiSignBytes) require.NoError(t, err) - stdSig2 := types.StdSignature{PubKey: pubKey, Signature: sig2} - sig2V2, err := types.StdSignatureToSignatureV2(cdc, stdSig2) + stdSig2 := legacytx.StdSignature{PubKey: pubKey, Signature: sig2} + sig2V2, err := legacytx.StdSignatureToSignatureV2(cdc, stdSig2) require.NoError(t, err) err = multisig.AddSignatureFromPubKey(multisignature, sig1V2.Data, pkSet[0], pkSet) diff --git a/x/auth/testutil/suite.go b/x/auth/testutil/suite.go index cafc57884..518e502de 100644 --- a/x/auth/testutil/suite.go +++ b/x/auth/testutil/suite.go @@ -226,6 +226,7 @@ func sigDataEquals(data1, data2 signingtypes.SignatureData) bool { } func (s *TxConfigTestSuite) TestTxEncodeDecode() { + log := s.T().Log _, pubkey, addr := testdata.KeyTestPubAddr() feeAmount := sdk.Coins{sdk.NewInt64Coin("atom", 150)} gasLimit := uint64(50000) @@ -250,13 +251,13 @@ func (s *TxConfigTestSuite) TestTxEncodeDecode() { s.Require().NoError(err) tx := txBuilder.GetTx() - s.T().Log("encode transaction") + log("encode transaction") txBytes, err := s.TxConfig.TxEncoder()(tx) s.Require().NoError(err) s.Require().NotNil(txBytes) - - s.T().Log("decode transaction") + log("decode transaction", s.TxConfig) tx2, err := s.TxConfig.TxDecoder()(txBytes) + s.Require().NoError(err) tx3, ok := tx2.(signing.Tx) s.Require().True(ok) @@ -269,12 +270,12 @@ func (s *TxConfigTestSuite) TestTxEncodeDecode() { s.Require().Equal([]signingtypes.SignatureV2{sig}, tx3Sigs) s.Require().Equal([]crypto.PubKey{pubkey}, tx3.GetPubKeys()) - s.T().Log("JSON encode transaction") + log("JSON encode transaction") jsonTxBytes, err := s.TxConfig.TxJSONEncoder()(tx) s.Require().NoError(err) s.Require().NotNil(jsonTxBytes) - s.T().Log("JSON decode transaction") + log("JSON decode transaction") tx2, err = s.TxConfig.TxJSONDecoder()(jsonTxBytes) s.Require().NoError(err) tx3, ok = tx2.(signing.Tx) diff --git a/x/auth/tx/legacy_amino_json.go b/x/auth/tx/legacy_amino_json.go index 886824f3a..090e3d864 100644 --- a/x/auth/tx/legacy_amino_json.go +++ b/x/auth/tx/legacy_amino_json.go @@ -3,11 +3,10 @@ package tx import ( "fmt" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/auth/types" - sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" "github.com/cosmos/cosmos-sdk/x/auth/signing" ) @@ -47,10 +46,9 @@ func (s signModeLegacyAminoJSONHandler) GetSignBytes(mode signingtypes.SignMode, return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "SIGN_MODE_LEGACY_AMINO_JSON does not support protobuf extension options.") } - // nolint: staticcheck - return types.StdSignBytes( + return legacytx.StdSignBytes( data.ChainID, data.AccountNumber, data.Sequence, protoTx.GetTimeoutHeight(), - types.StdFee{Amount: protoTx.GetFee(), Gas: protoTx.GetGas()}, + legacytx.StdFee{Amount: protoTx.GetFee(), Gas: protoTx.GetGas()}, tx.GetMsgs(), protoTx.GetMemo(), ), nil } diff --git a/x/auth/tx/legacy_amino_json_test.go b/x/auth/tx/legacy_amino_json_test.go index f7e4bb7c7..3db335286 100644 --- a/x/auth/tx/legacy_amino_json_test.go +++ b/x/auth/tx/legacy_amino_json_test.go @@ -9,8 +9,8 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" "github.com/cosmos/cosmos-sdk/x/auth/signing" - "github.com/cosmos/cosmos-sdk/x/auth/types" ) var ( @@ -52,7 +52,7 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) { signBz, err := handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx) require.NoError(t, err) - expectedSignBz := types.StdSignBytes(chainId, accNum, seqNum, timeout, types.StdFee{ + expectedSignBz := legacytx.StdSignBytes(chainId, accNum, seqNum, timeout, legacytx.StdFee{ Amount: coins, Gas: gas, }, []sdk.Msg{msg}, memo) diff --git a/x/auth/types/amino_signing.go b/x/auth/types/amino_signing.go deleted file mode 100644 index 27fb7a3d7..000000000 --- a/x/auth/types/amino_signing.go +++ /dev/null @@ -1,44 +0,0 @@ -package types - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" - "github.com/cosmos/cosmos-sdk/x/auth/signing" -) - -// stdTxSignModeHandler is a SignModeHandler that handles SIGN_MODE_LEGACY_AMINO_JSON -type stdTxSignModeHandler struct{} - -func NewStdTxSignModeHandler() signing.SignModeHandler { - return &stdTxSignModeHandler{} -} - -var _ signing.SignModeHandler = stdTxSignModeHandler{} - -// DefaultMode implements SignModeHandler.DefaultMode -func (h stdTxSignModeHandler) DefaultMode() signingtypes.SignMode { - return signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON -} - -// Modes implements SignModeHandler.Modes -func (stdTxSignModeHandler) Modes() []signingtypes.SignMode { - return []signingtypes.SignMode{signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON} -} - -// DefaultMode implements SignModeHandler.GetSignBytes -func (stdTxSignModeHandler) GetSignBytes(mode signingtypes.SignMode, data signing.SignerData, tx sdk.Tx) ([]byte, error) { - if mode != signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON { - return nil, fmt.Errorf("expected %s, got %s", signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, mode) - } - - stdTx, ok := tx.(StdTx) - if !ok { - return nil, fmt.Errorf("expected %T, got %T", StdTx{}, tx) - } - - return StdSignBytes( - data.ChainID, data.AccountNumber, data.Sequence, stdTx.GetTimeoutHeight(), StdFee{Amount: stdTx.GetFee(), Gas: stdTx.GetGas()}, tx.GetMsgs(), stdTx.GetMemo(), - ), nil -} diff --git a/x/auth/types/codec.go b/x/auth/types/codec.go index 24ed5f32a..52b1eac4a 100644 --- a/x/auth/types/codec.go +++ b/x/auth/types/codec.go @@ -4,6 +4,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" ) // RegisterLegacyAminoCodec registers the account interfaces and concrete types on the @@ -14,7 +15,8 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterInterface((*AccountI)(nil), nil) cdc.RegisterConcrete(&BaseAccount{}, "cosmos-sdk/BaseAccount", nil) cdc.RegisterConcrete(&ModuleAccount{}, "cosmos-sdk/ModuleAccount", nil) - cdc.RegisterConcrete(StdTx{}, "cosmos-sdk/StdTx", nil) + + legacytx.RegisterLegacyAminoCodec(cdc) } // RegisterInterface associates protoName with AccountI interface @@ -35,15 +37,8 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { ) } -// RegisterKeyTypeCodec registers an external concrete type defined in -// another module for the internal ModuleCdc. -func RegisterKeyTypeCodec(o interface{}, name string) { - amino.RegisterConcrete(o, name, nil) -} - var ( - amino = codec.NewLegacyAmino() - + amino = codec.NewLegacyAmino() ModuleCdc = codec.NewAminoCodec(amino) ) diff --git a/x/auth/types/stdtx.go b/x/auth/types/stdtx.go deleted file mode 100644 index 214847ee9..000000000 --- a/x/auth/types/stdtx.go +++ /dev/null @@ -1,501 +0,0 @@ -package types - -import ( - "encoding/json" - "fmt" - - "github.com/cosmos/cosmos-sdk/types/tx/signing" - - "github.com/tendermint/tendermint/crypto" - yaml "gopkg.in/yaml.v2" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/codec/legacy" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" - "github.com/cosmos/cosmos-sdk/crypto/types/multisig" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// MaxGasWanted defines the max gas allowed. -const MaxGasWanted = uint64((1 << 63) - 1) - -// Deprecated: StdFee includes the amount of coins paid in fees and the maximum -// gas to be used by the transaction. The ratio yields an effective "gasprice", -// which must be above some miminum to be accepted into the mempool. -type StdFee struct { - Amount sdk.Coins `json:"amount" yaml:"amount"` - Gas uint64 `json:"gas" yaml:"gas"` -} - -// Deprecated: NewStdFee returns a new instance of StdFee -func NewStdFee(gas uint64, amount sdk.Coins) StdFee { - return StdFee{ - Amount: amount, - Gas: gas, - } -} - -// GetGas returns the fee's (wanted) gas. -func (fee StdFee) GetGas() uint64 { - return fee.Gas -} - -// GetAmount returns the fee's amount. -func (fee StdFee) GetAmount() sdk.Coins { - return fee.Amount -} - -// Bytes returns the encoded bytes of a StdFee. -func (fee StdFee) Bytes() []byte { - if len(fee.Amount) == 0 { - fee.Amount = sdk.NewCoins() - } - - bz, err := legacy.Cdc.MarshalJSON(fee) - if err != nil { - panic(err) - } - - return bz -} - -// GasPrices returns the gas prices for a StdFee. -// -// NOTE: The gas prices returned are not the true gas prices that were -// originally part of the submitted transaction because the fee is computed -// as fee = ceil(gasWanted * gasPrices). -func (fee StdFee) GasPrices() sdk.DecCoins { - return sdk.NewDecCoinsFromCoins(fee.Amount...).QuoDec(sdk.NewDec(int64(fee.Gas))) -} - -// Deprecated -func NewStdSignature(pk crypto.PubKey, sig []byte) StdSignature { - return StdSignature{PubKey: pk, Signature: sig} -} - -// GetSignature returns the raw signature bytes. -func (ss StdSignature) GetSignature() []byte { - return ss.Signature -} - -// GetPubKey returns the public key of a signature as a crypto.PubKey using the -// Amino codec. -func (ss StdSignature) GetPubKey() crypto.PubKey { - return ss.PubKey -} - -// MarshalYAML returns the YAML representation of the signature. -func (ss StdSignature) MarshalYAML() (interface{}, error) { - var ( - bz []byte - pubkey string - err error - ) - - if ss.PubKey != nil { - pubkey, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, ss.GetPubKey()) - if err != nil { - return nil, err - } - } - - bz, err = yaml.Marshal(struct { - PubKey string - Signature string - }{ - PubKey: pubkey, - Signature: fmt.Sprintf("%X", ss.Signature), - }) - if err != nil { - return nil, err - } - - return string(bz), err -} - -// CountSubKeys counts the total number of keys for a multi-sig public key. -func CountSubKeys(pub crypto.PubKey) int { - v, ok := pub.(*kmultisig.LegacyAminoPubKey) - if !ok { - return 1 - } - - numKeys := 0 - for _, subkey := range v.GetPubKeys() { - numKeys += CountSubKeys(subkey) - } - - return numKeys -} - -// --------------------------------------------------------------------------- -// DEPRECATED -// --------------------------------------------------------------------------- - -var ( - _ sdk.Tx = (*StdTx)(nil) - _ codectypes.IntoAny = (*StdTx)(nil) -) - -// StdTx is the legacy transaction format for wrapping a Msg with Fee and Signatures. -// It only works with Amino, please prefer the new protobuf Tx in types/tx. -// NOTE: the first signature is the fee payer (Signatures must not be nil). -type StdTx struct { - Msgs []sdk.Msg `json:"msg" yaml:"msg"` - Fee StdFee `json:"fee" yaml:"fee"` - Signatures []StdSignature `json:"signatures" yaml:"signatures"` - Memo string `json:"memo" yaml:"memo"` - TimeoutHeight uint64 `json:"timeout_height" yaml:"timeout_height"` -} - -// Deprecated -func NewStdTx(msgs []sdk.Msg, fee StdFee, sigs []StdSignature, memo string) StdTx { - return StdTx{ - Msgs: msgs, - Fee: fee, - Signatures: sigs, - Memo: memo, - } -} - -// GetMsgs returns the all the transaction's messages. -func (tx StdTx) GetMsgs() []sdk.Msg { return tx.Msgs } - -// ValidateBasic does a simple and lightweight validation check that doesn't -// require access to any other information. -func (tx StdTx) ValidateBasic() error { - stdSigs := tx.GetSignatures() - - if tx.Fee.Gas > MaxGasWanted { - return sdkerrors.Wrapf( - sdkerrors.ErrInvalidRequest, - "invalid gas supplied; %d > %d", tx.Fee.Gas, MaxGasWanted, - ) - } - if tx.Fee.Amount.IsAnyNegative() { - return sdkerrors.Wrapf( - sdkerrors.ErrInsufficientFee, - "invalid fee provided: %s", tx.Fee.Amount, - ) - } - if len(stdSigs) == 0 { - return sdkerrors.ErrNoSignatures - } - if len(stdSigs) != len(tx.GetSigners()) { - return sdkerrors.Wrapf( - sdkerrors.ErrUnauthorized, - "wrong number of signers; expected %d, got %d", len(tx.GetSigners()), len(stdSigs), - ) - } - - return nil -} - -// AsAny implements IntoAny.AsAny. -func (tx *StdTx) AsAny() *codectypes.Any { - return codectypes.UnsafePackAny(tx) -} - -// GetSigners returns the addresses that must sign the transaction. -// Addresses are returned in a deterministic order. -// They are accumulated from the GetSigners method for each Msg -// in the order they appear in tx.GetMsgs(). -// Duplicate addresses will be omitted. -func (tx StdTx) GetSigners() []sdk.AccAddress { - var signers []sdk.AccAddress - seen := map[string]bool{} - - for _, msg := range tx.GetMsgs() { - for _, addr := range msg.GetSigners() { - if !seen[addr.String()] { - signers = append(signers, addr) - seen[addr.String()] = true - } - } - } - - return signers -} - -// GetMemo returns the memo -func (tx StdTx) GetMemo() string { return tx.Memo } - -// GetTimeoutHeight returns the transaction's timeout height (if set). -func (tx StdTx) GetTimeoutHeight() uint64 { - return tx.TimeoutHeight -} - -// GetSignatures returns the signature of signers who signed the Msg. -// CONTRACT: Length returned is same as length of -// pubkeys returned from MsgKeySigners, and the order -// matches. -// CONTRACT: If the signature is missing (ie the Msg is -// invalid), then the corresponding signature is -// .Empty(). -func (tx StdTx) GetSignatures() [][]byte { - sigs := make([][]byte, len(tx.Signatures)) - for i, stdSig := range tx.Signatures { - sigs[i] = stdSig.Signature - } - return sigs -} - -// GetSignaturesV2 implements SigVerifiableTx.GetSignaturesV2 -func (tx StdTx) GetSignaturesV2() ([]signing.SignatureV2, error) { - res := make([]signing.SignatureV2, len(tx.Signatures)) - - for i, sig := range tx.Signatures { - var err error - res[i], err = StdSignatureToSignatureV2(legacy.Cdc, sig) - if err != nil { - return nil, sdkerrors.Wrapf(err, "Unable to convert signature %v to V2", sig) - } - } - - return res, nil -} - -// GetPubkeys returns the pubkeys of signers if the pubkey is included in the signature -// If pubkey is not included in the signature, then nil is in the slice instead -func (tx StdTx) GetPubKeys() []crypto.PubKey { - pks := make([]crypto.PubKey, len(tx.Signatures)) - - for i, stdSig := range tx.Signatures { - pks[i] = stdSig.GetPubKey() - } - - return pks -} - -// GetGas returns the Gas in StdFee -func (tx StdTx) GetGas() uint64 { return tx.Fee.Gas } - -// GetFee returns the FeeAmount in StdFee -func (tx StdTx) GetFee() sdk.Coins { return tx.Fee.Amount } - -// FeePayer returns the address that is responsible for paying fee -// StdTx returns the first signer as the fee payer -// If no signers for tx, return empty address -func (tx StdTx) FeePayer() sdk.AccAddress { - if tx.GetSigners() != nil { - return tx.GetSigners()[0] - } - return sdk.AccAddress{} -} - -// StdSignDoc is replay-prevention structure. -// It includes the result of msg.GetSignBytes(), -// as well as the ChainID (prevent cross chain replay) -// and the Sequence numbers for each signature (prevent -// inchain replay and enforce tx ordering per account). -type StdSignDoc struct { - AccountNumber uint64 `json:"account_number" yaml:"account_number"` - Sequence uint64 `json:"sequence" yaml:"sequence"` - TimeoutHeight uint64 `json:"timeout_height,omitempty" yaml:"timeout_height"` - ChainID string `json:"chain_id" yaml:"chain_id"` - Memo string `json:"memo" yaml:"memo"` - Fee json.RawMessage `json:"fee" yaml:"fee"` - Msgs []json.RawMessage `json:"msgs" yaml:"msgs"` -} - -// StdSignBytes returns the bytes to sign for a transaction. -func StdSignBytes(chainID string, accnum, sequence, timeout uint64, fee StdFee, msgs []sdk.Msg, memo string) []byte { - msgsBytes := make([]json.RawMessage, 0, len(msgs)) - for _, msg := range msgs { - msgsBytes = append(msgsBytes, json.RawMessage(msg.GetSignBytes())) - } - - bz, err := legacy.Cdc.MarshalJSON(StdSignDoc{ - AccountNumber: accnum, - ChainID: chainID, - Fee: json.RawMessage(fee.Bytes()), - Memo: memo, - Msgs: msgsBytes, - Sequence: sequence, - TimeoutHeight: timeout, - }) - if err != nil { - panic(err) - } - - return sdk.MustSortJSON(bz) -} - -// Deprecated: StdSignature represents a sig -type StdSignature struct { - crypto.PubKey `json:"pub_key" yaml:"pub_key"` // optional - Signature []byte `json:"signature" yaml:"signature"` -} - -// DefaultTxDecoder logic for standard transaction decoding -func DefaultTxDecoder(cdc *codec.LegacyAmino) sdk.TxDecoder { - return func(txBytes []byte) (sdk.Tx, error) { - var tx = StdTx{} - - if len(txBytes) == 0 { - return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx bytes are empty") - } - - // StdTx.Msg is an interface. The concrete types - // are registered by MakeTxCodec - err := cdc.UnmarshalBinaryBare(txBytes, &tx) - if err != nil { - return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error()) - } - - return tx, nil - } -} - -func DefaultJSONTxDecoder(cdc *codec.LegacyAmino) sdk.TxDecoder { - return func(txBytes []byte) (sdk.Tx, error) { - var tx = StdTx{} - - if len(txBytes) == 0 { - return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx bytes are empty") - } - - // StdTx.Msg is an interface. The concrete types - // are registered by MakeTxCodec - err := cdc.UnmarshalJSON(txBytes, &tx) - if err != nil { - return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error()) - } - - return tx, nil - } -} - -// DefaultTxEncoder logic for standard transaction encoding -func DefaultTxEncoder(cdc *codec.LegacyAmino) sdk.TxEncoder { - return func(tx sdk.Tx) ([]byte, error) { - return cdc.MarshalBinaryBare(tx) - } -} - -var _ codectypes.UnpackInterfacesMessage = StdTx{} - -func (tx StdTx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - for _, m := range tx.Msgs { - err := codectypes.UnpackInterfaces(m, unpacker) - if err != nil { - return err - } - } - return nil -} - -// StdSignatureToSignatureV2 converts a StdSignature to a SignatureV2 -func StdSignatureToSignatureV2(cdc *codec.LegacyAmino, sig StdSignature) (signing.SignatureV2, error) { - pk := sig.GetPubKey() - data, err := pubKeySigToSigData(cdc, pk, sig.Signature) - if err != nil { - return signing.SignatureV2{}, err - } - - return signing.SignatureV2{ - PubKey: pk, - Data: data, - }, nil -} - -// SignatureV2ToStdSignature converts a SignatureV2 to a StdSignature -func SignatureV2ToStdSignature(cdc *codec.LegacyAmino, sig signing.SignatureV2) (StdSignature, error) { - var ( - sigBz []byte - err error - ) - - if sig.Data != nil { - sigBz, err = SignatureDataToAminoSignature(cdc, sig.Data) - if err != nil { - return StdSignature{}, err - } - } - - return StdSignature{ - PubKey: sig.PubKey, - Signature: sigBz, - }, nil -} - -func pubKeySigToSigData(cdc *codec.LegacyAmino, key crypto.PubKey, sig []byte) (signing.SignatureData, error) { - multiPK, ok := key.(multisig.PubKey) - if !ok { - return &signing.SingleSignatureData{ - SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, - Signature: sig, - }, nil - } - var multiSig multisig.AminoMultisignature - err := cdc.UnmarshalBinaryBare(sig, &multiSig) - if err != nil { - return nil, err - } - - sigs := multiSig.Sigs - sigDatas := make([]signing.SignatureData, len(sigs)) - pubKeys := multiPK.GetPubKeys() - bitArray := multiSig.BitArray - n := multiSig.BitArray.Count() - signatures := multisig.NewMultisig(n) - sigIdx := 0 - for i := 0; i < n; i++ { - if bitArray.GetIndex(i) { - data, err := pubKeySigToSigData(cdc, pubKeys[i], multiSig.Sigs[sigIdx]) - if err != nil { - return nil, sdkerrors.Wrapf(err, "Unable to convert Signature to SigData %d", sigIdx) - } - - sigDatas[sigIdx] = data - multisig.AddSignature(signatures, data, sigIdx) - sigIdx++ - } - } - - return signatures, nil -} - -// MultiSignatureDataToAminoMultisignature converts a MultiSignatureData to an AminoMultisignature. -// Only SIGN_MODE_LEGACY_AMINO_JSON is supported. -func MultiSignatureDataToAminoMultisignature(cdc *codec.LegacyAmino, mSig *signing.MultiSignatureData) (multisig.AminoMultisignature, error) { - n := len(mSig.Signatures) - sigs := make([][]byte, n) - - for i := 0; i < n; i++ { - var err error - sigs[i], err = SignatureDataToAminoSignature(cdc, mSig.Signatures[i]) - if err != nil { - return multisig.AminoMultisignature{}, sdkerrors.Wrapf(err, "Unable to convert Signature Data to signature %d", i) - } - } - - return multisig.AminoMultisignature{ - BitArray: mSig.BitArray, - Sigs: sigs, - }, nil -} - -// SignatureDataToAminoSignature converts a SignatureData to amino-encoded signature bytes. -// Only SIGN_MODE_LEGACY_AMINO_JSON is supported. -func SignatureDataToAminoSignature(cdc *codec.LegacyAmino, data signing.SignatureData) ([]byte, error) { - switch data := data.(type) { - case *signing.SingleSignatureData: - if data.SignMode != signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON { - return nil, fmt.Errorf("expected %s, got %s", signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, data.SignMode) - } - - return data.Signature, nil - case *signing.MultiSignatureData: - aminoMSig, err := MultiSignatureDataToAminoMultisignature(cdc, data) - if err != nil { - return nil, err - } - - return cdc.MarshalBinaryBare(aminoMSig) - default: - return nil, fmt.Errorf("unexpected signature data %T", data) - } -} diff --git a/x/bank/client/rest/tx_test.go b/x/bank/client/rest/tx_test.go index 118816c79..a11985c24 100644 --- a/x/bank/client/rest/tx_test.go +++ b/x/bank/client/rest/tx_test.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/rest" authclient "github.com/cosmos/cosmos-sdk/x/auth/client" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" bankrest "github.com/cosmos/cosmos-sdk/x/bank/client/rest" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -43,25 +44,25 @@ func (s *IntegrationTestSuite) TestCoinSend() { }, stdTx.GetMsgs()) } -func submitSendReq(val *network.Validator, req bankrest.SendReq) (authtypes.StdTx, error) { +func submitSendReq(val *network.Validator, req bankrest.SendReq) (legacytx.StdTx, error) { url := fmt.Sprintf("%s/bank/accounts/%s/transfers", val.APIAddress, val.Address) // NOTE: this uses amino explicitly, don't migrate it! bz, err := val.ClientCtx.LegacyAmino.MarshalJSON(req) if err != nil { - return authtypes.StdTx{}, errors.Wrap(err, "error encoding SendReq to json") + return legacytx.StdTx{}, errors.Wrap(err, "error encoding SendReq to json") } res, err := rest.PostRequest(url, "application/json", bz) if err != nil { - return authtypes.StdTx{}, err + return legacytx.StdTx{}, err } - var tx authtypes.StdTx + var tx legacytx.StdTx // NOTE: this uses amino explicitly, don't migrate it! err = val.ClientCtx.LegacyAmino.UnmarshalJSON(res, &tx) if err != nil { - return authtypes.StdTx{}, errors.Wrap(err, "error unmarshaling to StdTx SendReq response") + return legacytx.StdTx{}, errors.Wrap(err, "error unmarshaling to StdTx SendReq response") } return tx, nil