From 50bab8f820ea7612734701eddee60eb8349c5e90 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Fri, 21 Aug 2020 16:20:47 +0200 Subject: [PATCH] Put AccountSequence in SignerInfo (#6997) * WIP test the grounds * Update ADR020 * Fix compile errors * Fix ADR * Make ante tests pass * Fix remaining ante handler tests * Simplify code * Fix x/bank app_test * Fix tests * Remove useless accSeq from signerdata * Fix test * Update simapp/helpers/test_helpers.go Co-authored-by: Alexander Bezobchuk * Update simapp/helpers/test_helpers.go Co-authored-by: Alexander Bezobchuk * Update x/auth/client/cli/tx_multisign.go Co-authored-by: Alexander Bezobchuk * Address rewview * Update x/auth/ante/sigverify.go Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> * Update x/auth/ante/sigverify_test.go Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> * Update x/auth/tx/builder_test.go Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> * Update x/auth/tx/builder_test.go Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> * Update x/auth/tx/direct_test.go Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> * Update x/auth/tx/builder_test.go Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> * AccSeq -> Seq * Address reviews * Better variable naming * Fix variable assign * Remove old SetSignerInfo * Fix test * proto-gen * Make proto-gen * Reput gw comment * Add Changelog * Update x/bank/app_test.go Co-authored-by: Alexander Bezobchuk * Update x/bank/app_test.go Co-authored-by: Alexander Bezobchuk Co-authored-by: Alexander Bezobchuk Co-authored-by: SaReN Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> --- client/testutil/suite.go | 22 ++- client/tx/tx.go | 24 ++- .../adr-020-protobuf-transaction-encoding.md | 95 +++++----- proto/cosmos/tx/signing/v1beta1/signing.proto | 5 + proto/cosmos/tx/v1beta1/tx.proto | 9 +- simapp/helpers/test_helpers.go | 14 +- simapp/test_helpers.go | 4 +- types/errors/errors.go | 4 + types/tx/signing/signature.go | 3 + types/tx/signing/signing.pb.go | 105 ++++++---- types/tx/tx.pb.go | 179 +++++++++--------- x/auth/ante/ante_test.go | 14 +- x/auth/ante/sigverify.go | 38 ++-- x/auth/ante/sigverify_test.go | 5 +- x/auth/ante/testutil_test.go | 13 +- x/auth/client/cli/cli_test.go | 2 +- x/auth/client/cli/tx_multisign.go | 13 +- x/auth/client/cli/validate_sigs.go | 6 +- x/auth/signing/handler_map_test.go | 6 +- x/auth/signing/sign_mode_handler.go | 8 +- x/auth/signing/verify_test.go | 10 +- x/auth/tx/builder.go | 63 +----- x/auth/tx/builder_test.go | 6 +- x/auth/tx/direct.go | 13 +- x/auth/tx/direct_test.go | 21 +- x/auth/tx/legacy_amino_json.go | 2 +- x/auth/tx/legacy_amino_json_test.go | 6 +- x/auth/tx/sigs.go | 5 +- x/auth/types/account_test.go | 2 +- x/auth/types/amino_signing.go | 2 +- x/auth/types/amino_signing_test.go | 6 +- x/auth/types/client_tx.go | 9 - x/bank/app_test.go | 10 +- 33 files changed, 375 insertions(+), 349 deletions(-) diff --git a/client/testutil/suite.go b/client/testutil/suite.go index 9b1c29d41a..4bc0257238 100644 --- a/client/testutil/suite.go +++ b/client/testutil/suite.go @@ -100,13 +100,15 @@ func (s *TxConfigTestSuite) TestTxBuilderSetSignatures() { s.Require().Contains(signModeHandler.Modes(), signModeHandler.DefaultMode()) // set SignatureV2 without actual signature bytes + seq1 := uint64(2) // Arbitrary account sequence sigData1 := &signingtypes.SingleSignatureData{SignMode: signModeHandler.DefaultMode()} - sig1 := signingtypes.SignatureV2{PubKey: pubkey, Data: sigData1} + sig1 := signingtypes.SignatureV2{PubKey: pubkey, Data: sigData1, Sequence: seq1} + mseq := uint64(4) // Arbitrary account sequence msigData := multisig.NewMultisig(2) multisig.AddSignature(msigData, &signingtypes.SingleSignatureData{SignMode: signModeHandler.DefaultMode()}, 0) multisig.AddSignature(msigData, &signingtypes.SingleSignatureData{SignMode: signModeHandler.DefaultMode()}, 1) - msig := signingtypes.SignatureV2{PubKey: multisigPk, Data: msigData} + msig := signingtypes.SignatureV2{PubKey: multisigPk, Data: msigData, Sequence: mseq} // fail validation without required signers err = txBuilder.SetSignatures(sig1) @@ -128,9 +130,9 @@ func (s *TxConfigTestSuite) TestTxBuilderSetSignatures() { // sign transaction signerData := signing.SignerData{ - ChainID: "test", - AccountNumber: 1, - AccountSequence: 2, + ChainID: "test", + AccountNumber: 1, + Sequence: seq1, } signBytes, err := signModeHandler.GetSignBytes(signModeHandler.DefaultMode(), signerData, sigTx) s.Require().NoError(err) @@ -138,9 +140,9 @@ func (s *TxConfigTestSuite) TestTxBuilderSetSignatures() { s.Require().NoError(err) signerData = signing.SignerData{ - ChainID: "test", - AccountNumber: 3, - AccountSequence: 4, + ChainID: "test", + AccountNumber: 3, + Sequence: mseq, } mSignBytes, err := signModeHandler.GetSignBytes(signModeHandler.DefaultMode(), signerData, sigTx) s.Require().NoError(err) @@ -156,8 +158,8 @@ func (s *TxConfigTestSuite) TestTxBuilderSetSignatures() { // set signature sigData1.Signature = sigBz - sig1 = signingtypes.SignatureV2{PubKey: pubkey, Data: sigData1} - msig = signingtypes.SignatureV2{PubKey: multisigPk, Data: msigData} + sig1 = signingtypes.SignatureV2{PubKey: pubkey, Data: sigData1, Sequence: seq1} + msig = signingtypes.SignatureV2{PubKey: multisigPk, Data: msigData, Sequence: mseq} err = txBuilder.SetSignatures(sig1, msig) s.Require().NoError(err) sigTx = txBuilder.GetTx() diff --git a/client/tx/tx.go b/client/tx/tx.go index bcffbc321e..64f8ba2b7e 100644 --- a/client/tx/tx.go +++ b/client/tx/tx.go @@ -322,6 +322,7 @@ func PrepareFactory(clientCtx client.Context, txf Factory) (Factory, error) { func SignWithPrivKey( signMode signing.SignMode, signerData authsigning.SignerData, txBuilder client.TxBuilder, priv crypto.PrivKey, txConfig client.TxConfig, + accSeq uint64, ) (signing.SignatureV2, error) { var sigV2 signing.SignatureV2 @@ -344,8 +345,9 @@ func SignWithPrivKey( } sigV2 = signing.SignatureV2{ - PubKey: priv.PubKey(), - Data: &sigData, + PubKey: priv.PubKey(), + Data: &sigData, + Sequence: accSeq, } return sigV2, nil @@ -372,12 +374,12 @@ func Sign(txf Factory, name string, txBuilder client.TxBuilder) error { pubKey := key.GetPubKey() signerData := authsigning.SignerData{ - ChainID: txf.chainID, - AccountNumber: txf.accountNumber, - AccountSequence: txf.sequence, + ChainID: txf.chainID, + AccountNumber: txf.accountNumber, + Sequence: txf.sequence, } - // For SIGN_MODE_DIRECT, calling SetSignatures calls SetSignerInfos on + // For SIGN_MODE_DIRECT, calling SetSignatures calls setSignerInfos on // TxBuilder under the hood, and SignerInfos is needed to generated the // sign bytes. This is the reason for setting SetSignatures here, with a // nil signature. @@ -390,8 +392,9 @@ func Sign(txf Factory, name string, txBuilder client.TxBuilder) error { Signature: nil, } sig := signing.SignatureV2{ - PubKey: pubKey, - Data: &sigData, + PubKey: pubKey, + Data: &sigData, + Sequence: txf.Sequence(), } if err := txBuilder.SetSignatures(sig); err != nil { return err @@ -415,8 +418,9 @@ func Sign(txf Factory, name string, txBuilder client.TxBuilder) error { Signature: sigBytes, } sig = signing.SignatureV2{ - PubKey: pubKey, - Data: &sigData, + PubKey: pubKey, + Data: &sigData, + Sequence: txf.Sequence(), } // And here the tx is populated with the signature diff --git a/docs/architecture/adr-020-protobuf-transaction-encoding.md b/docs/architecture/adr-020-protobuf-transaction-encoding.md index 885e713420..cdea6817ec 100644 --- a/docs/architecture/adr-020-protobuf-transaction-encoding.md +++ b/docs/architecture/adr-020-protobuf-transaction-encoding.md @@ -9,6 +9,7 @@ - 2020 May 14: Describe public key encoding - 2020 June 08: Store `TxBody` and `AuthInfo` as bytes in `SignDoc`; Document `TxRaw` as broadcast and storage type. - 2020 August 07: Use ADR 027 for serializing `SignDoc`. +- 2020 August 19: Move sequence field from `SignDoc` to `SignerInfo`. ## Status @@ -29,7 +30,7 @@ querying. However, this ADR solely focuses on transactions. Querying should be addressed in a future ADR, but it should build off of these proposals. Based on detailed discussions ([\#6030](https://github.com/cosmos/cosmos-sdk/issues/6030) -and [\#6078](https://github.com/cosmos/cosmos-sdk/issues/6078)), the original +and [\#6078](https://github.com/cosmos/cosmos-sdk/issues/6078)), the original design for transactions was changed substantially from an `oneof` /JSON-signing approach to the approach described below. @@ -38,15 +39,15 @@ approach to the approach described below. ### Transactions Since interface values are encoded with `google.protobuf.Any` in state (see [ADR 019](adr-019-protobuf-state-encoding.md)), - `sdk.Msg`s are encoding with `Any` in transactions. - - One of the main goals of using `Any` to encode interface values is to have a - core set of types which is reused by apps so that - clients can safely be compatible with as many chains as possible. - - It is one of the goals of this specification to provide a flexible cross-chain transaction - format that can serve a wide variety of use cases without breaking client - compatibility. +`sdk.Msg`s are encoding with `Any` in transactions. + +One of the main goals of using `Any` to encode interface values is to have a +core set of types which is reused by apps so that +clients can safely be compatible with as many chains as possible. + +It is one of the goals of this specification to provide a flexible cross-chain transaction +format that can serve a wide variety of use cases without breaking client +compatibility. In order to facilitate signing, transactions are separated into `TxBody`, which will be re-used by `SignDoc` below, and `signatures`: @@ -106,20 +107,24 @@ message SignerInfo { // ModeInfo describes the signing mode of the signer and is a nested // structure to support nested multisig pubkey's ModeInfo mode_info = 2; + // sequence is the sequence of the account, which describes the + // number of committed transactions signed by a given address. It is used to prevent + // replay attacks. + uint64 sequence = 3; } message ModeInfo { oneof sum { Single single = 1; Multi multi = 2; - } - + } + // Single is the mode info for a single signer. It is structured as a message // to allow for additional fields such as locale for SIGN_MODE_TEXTUAL in the future message Single { SignMode mode = 1; } - + // Multi is the mode info for a multisig public key message Multi { // bitarray specifies which keys within the multisig are signing @@ -128,7 +133,7 @@ message ModeInfo { // which could include nested multisig public keys repeated ModeInfo mode_infos = 2; } -} +} enum SignMode { SIGN_MODE_UNSPECIFIED = 0; @@ -136,7 +141,7 @@ enum SignMode { SIGN_MODE_DIRECT = 1; SIGN_MODE_TEXTUAL = 2; - + SIGN_MODE_LEGACY_AMINO_JSON = 127; } ``` @@ -158,10 +163,10 @@ attempt to upstream important improvements to `Tx`. All of the signing modes below aim to provide the following guarantees: -* **No Malleability**: `TxBody` and `AuthInfo` cannot change once the transaction -is signed -* **Predictable Gas**: if I am signing a transaction where I am paying a fee, -the final gas is fully dependent on what I am signing +- **No Malleability**: `TxBody` and `AuthInfo` cannot change once the transaction + is signed +- **Predictable Gas**: if I am signing a transaction where I am paying a fee, + the final gas is fully dependent on what I am signing These guarantees give the maximum amount confidence to message signers that manipulation of `Tx`s by intermediaries can't result in any meaningful changes. @@ -171,11 +176,11 @@ manipulation of `Tx`s by intermediaries can't result in any meaningful changes. The "direct" signing behavior is to sign the raw `TxBody` bytes as broadcast over the wire. This has the advantages of: -* requiring the minimum additional client capabilities beyond a standard protocol -buffers implementation -* leaving effectively zero holes for transaction malleability (i.e. there are no -subtle differences between the signing and encoding formats which could -potentially be exploited by an attacker) +- requiring the minimum additional client capabilities beyond a standard protocol + buffers implementation +- leaving effectively zero holes for transaction malleability (i.e. there are no + subtle differences between the signing and encoding formats which could + potentially be exploited by an attacker) Signatures are structured using the `SignDoc` below which reuses the serialization of `TxBody` and `AuthInfo` and only adds the fields which are needed for signatures: @@ -189,7 +194,6 @@ message SignDoc { bytes auth_info = 2; string chain_id = 3; uint64 account_number = 4; - uint64 account_sequence = 5; } ``` @@ -233,7 +237,7 @@ endpoint before broadcasting. As was discussed extensively in [\#6078](https://github.com/cosmos/cosmos-sdk/issues/6078), there is a desire for a human-readable signing encoding, especially for hardware wallets like the [Ledger](https://www.ledger.com) which display -transaction contents to users before signing. JSON was an attempt at this but +transaction contents to users before signing. JSON was an attempt at this but falls short of the ideal. `SIGN_MODE_TEXTUAL` is intended as a placeholder for a human-readable @@ -254,11 +258,11 @@ by `SIGN_MODE_TEXTUAL` when it is implemented. Unknown fields in protobuf messages should generally be rejected by transaction processors because: -* important data may be present in the unknown fields, that if ignored, will -cause unexpected behavior for clients -* they present a malleability vulnerability where attackers can bloat tx size -by adding random uninterpreted data to unsigned content (i.e. the master `Tx`, -not `TxBody`) +- important data may be present in the unknown fields, that if ignored, will + cause unexpected behavior for clients +- they present a malleability vulnerability where attackers can bloat tx size + by adding random uninterpreted data to unsigned content (i.e. the master `Tx`, + not `TxBody`) There are also scenarios where we may choose to safely ignore unknown fields (https://github.com/cosmos/cosmos-sdk/issues/6078#issuecomment-624400188) to @@ -269,10 +273,11 @@ the range of 1024-2047) be considered non-critical fields that can safely be ignored if unknown. To handle this we will need a unknown field filter that: -* always rejects unknown fields in unsigned content (i.e. top-level `Tx` and -unsigned parts of `AuthInfo` if present based on the signing mode) -* rejects unknown fields in all messages (including nested `Any`s) other than -fields with bit 11 set + +- always rejects unknown fields in unsigned content (i.e. top-level `Tx` and + unsigned parts of `AuthInfo` if present based on the signing mode) +- rejects unknown fields in all messages (including nested `Any`s) other than + fields with bit 11 set This will likely need to be a custom protobuf parser pass that takes message bytes and `FileDescriptor`s and returns a boolean result. @@ -284,17 +289,18 @@ so a natural solution might be to use `Any` as we are doing for other interfaces There are, however, a limited number of public keys in existence and new ones aren't created overnight. The proposed solution is to use a `oneof` that: -* attempts to catalog all known key types even if a given app can't use them all -* has an `Any` member that can be used when a key type isn't present in the `oneof` +- attempts to catalog all known key types even if a given app can't use them all +- has an `Any` member that can be used when a key type isn't present in the `oneof` Ex: + ```proto message PublicKey { oneof sum { bytes secp256k1 = 1; bytes ed25519 = 2; ... - google.protobuf.Any any_pubkey = 15; + google.protobuf.Any any_pubkey = 15; } } ``` @@ -372,7 +378,7 @@ can gracefully transition away from Amino JSON. ### `SIGN_MODE_DIRECT_AUX` -(*Documented as option (3) in https://github.com/cosmos/cosmos-sdk/issues/6078#issuecomment-628026933) +(\*Documented as option (3) in https://github.com/cosmos/cosmos-sdk/issues/6078#issuecomment-628026933) We could add a mode `SIGN_MODE_DIRECT_AUX` to support scenarios where multiple signatures @@ -399,7 +405,7 @@ fees or gas and thus can just sign `TxBody`. To generate a signature in `SIGN_MODE_DIRECT_AUX` these steps would be followed: 1. Encode `SignDocAux` (with the same requirement that fields must be serialized -in order): + in order): ```proto // types/types.proto @@ -420,18 +426,17 @@ message SignDocAux { PublicKey public_key = 2; string chain_id = 3; uint64 account_number = 4; - uint64 account_sequence = 5; } ``` 2. Sign the encoded `SignDocAux` bytes 3. Send their signature and `SignerInfo` to primary signer who will then -sign and broadcast the final transaction (with `SIGN_MODE_DIRECT` and `AuthInfo` -added) once enough signatures have been collected + sign and broadcast the final transaction (with `SIGN_MODE_DIRECT` and `AuthInfo` + added) once enough signatures have been collected ### `SIGN_MODE_DIRECT_RELAXED` -(*Documented as option (1)(a) in https://github.com/cosmos/cosmos-sdk/issues/6078#issuecomment-628026933*) +(_Documented as option (1)(a) in https://github.com/cosmos/cosmos-sdk/issues/6078#issuecomment-628026933_) This is a variation of `SIGN_MODE_DIRECT` where multiple signers wouldn't need to coordinate public keys and signing modes in advance. It would involve an alternate @@ -451,7 +456,7 @@ too burdensome. ### Negative - `google.protobuf.Any` type URLs increase transaction size although the effect -may be negligible or compression may be able to mitigate it. + may be negligible or compression may be able to mitigate it. ### Neutral diff --git a/proto/cosmos/tx/signing/v1beta1/signing.proto b/proto/cosmos/tx/signing/v1beta1/signing.proto index 74913e3ea3..a436453090 100644 --- a/proto/cosmos/tx/signing/v1beta1/signing.proto +++ b/proto/cosmos/tx/signing/v1beta1/signing.proto @@ -38,6 +38,11 @@ message SignatureDescriptor { Data data = 2; + // sequence is the sequence of the account, which describes the + // number of committed transactions signed by a given address. It is used to prevent + // replay attacks. + uint64 sequence = 3; + // Data represents signature data message Data { // sum is the oneof that specifies whether this represents single or multi-signature data diff --git a/proto/cosmos/tx/v1beta1/tx.proto b/proto/cosmos/tx/v1beta1/tx.proto index e0238a8a2b..3989504889 100644 --- a/proto/cosmos/tx/v1beta1/tx.proto +++ b/proto/cosmos/tx/v1beta1/tx.proto @@ -54,10 +54,6 @@ message SignDoc { // account_number is the account number of the account in state uint64 account_number = 4; - - // account_sequence starts at 1 rather than 0 to avoid the case where - // the default 0 value must be omitted in protobuf serialization - uint64 account_sequence = 5; } // TxBody is the body of a transaction that all signers sign over. @@ -112,6 +108,11 @@ message SignerInfo { // mode_info describes the signing mode of the signer and is a nested // structure to support nested multisig pubkey's ModeInfo mode_info = 2; + + // sequence is the sequence of the account, which describes the + // number of committed transactions signed by a given address. It is used to prevent + // replay attacks. + uint64 sequence = 3; } // ModeInfo describes the signing mode of a single or nested multisig signer. diff --git a/simapp/helpers/test_helpers.go b/simapp/helpers/test_helpers.go index c567bbb483..9e8a4d9714 100644 --- a/simapp/helpers/test_helpers.go +++ b/simapp/helpers/test_helpers.go @@ -20,7 +20,7 @@ const ( ) // GenTx generates a signed mock transaction. -func GenTx(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, chainID string, accnums []uint64, seq []uint64, priv ...crypto.PrivKey) (sdk.Tx, error) { +func GenTx(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, chainID string, accNums, accSeqs []uint64, priv ...crypto.PrivKey) (sdk.Tx, error) { sigs := make([]signing.SignatureV2, len(priv)) // create a random length memo @@ -30,12 +30,15 @@ func GenTx(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, ch signMode := gen.SignModeHandler().DefaultMode() + // 1st round: set SignatureV2 with empty signatures, to set correct + // signer infos. for i, p := range priv { sigs[i] = signing.SignatureV2{ PubKey: p.PubKey(), Data: &signing.SingleSignatureData{ SignMode: signMode, }, + Sequence: accSeqs[i], } } @@ -51,12 +54,13 @@ func GenTx(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, ch tx.SetMemo(memo) tx.SetFeeAmount(feeAmt) tx.SetGasLimit(gas) + + // 2nd round: once all signer infos are set, every signer can sign. for i, p := range priv { - // use a empty chainID for ease of testing signerData := authsign.SignerData{ - ChainID: chainID, - AccountNumber: accnums[i], - AccountSequence: seq[i], + ChainID: chainID, + AccountNumber: accNums[i], + Sequence: accSeqs[i], } signBytes, err := gen.SignModeHandler().GetSignBytes(signMode, signerData, tx.GetTx()) if err != nil { diff --git a/simapp/test_helpers.go b/simapp/test_helpers.go index a8675db974..d694cb0b71 100644 --- a/simapp/test_helpers.go +++ b/simapp/test_helpers.go @@ -319,7 +319,7 @@ func CheckBalance(t *testing.T, app *SimApp, addr sdk.AccAddress, balances sdk.C // returned. func SignCheckDeliver( t *testing.T, txGen client.TxConfig, app *bam.BaseApp, header tmproto.Header, msgs []sdk.Msg, - chainID string, accNums, seq []uint64, expSimPass, expPass bool, priv ...crypto.PrivKey, + chainID string, accNums, accSeqs []uint64, expSimPass, expPass bool, priv ...crypto.PrivKey, ) (sdk.GasInfo, *sdk.Result, error) { tx, err := helpers.GenTx( @@ -329,7 +329,7 @@ func SignCheckDeliver( helpers.DefaultGenTxGas, chainID, accNums, - seq, + accSeqs, priv..., ) require.NoError(t, err) diff --git a/types/errors/errors.go b/types/errors/errors.go index c59f6ba552..ed0f625010 100644 --- a/types/errors/errors.go +++ b/types/errors/errors.go @@ -113,6 +113,10 @@ var ( // ErrUnknownExtensionOptions defines an error for unknown extension options. ErrUnknownExtensionOptions = Register(RootCodespace, 31, "unknown extension options") + // ErrWrongSequence defines an error where the account sequence defined in + // the signer info doesn't match the account's actual sequence number. + ErrWrongSequence = Register(RootCodespace, 32, "incorrect account sequence") + // ErrPanic is only set when we recover from a panic, so we know to // redact potentially sensitive system info ErrPanic = Register(UndefinedCodespace, 111222, "panic") diff --git a/types/tx/signing/signature.go b/types/tx/signing/signature.go index bfe832a5b1..dd080bcb8e 100644 --- a/types/tx/signing/signature.go +++ b/types/tx/signing/signature.go @@ -18,6 +18,9 @@ type SignatureV2 struct { // Data is the actual data of the signature which includes SignMode's and // the signatures themselves for either single or multi-signatures. Data SignatureData + + // Sequence is the sequence of this account. + Sequence uint64 } // SignatureDataToProto converts a SignatureData to SignatureDescriptor_Data. diff --git a/types/tx/signing/signing.pb.go b/types/tx/signing/signing.pb.go index 207965ad1a..c9a04ac233 100644 --- a/types/tx/signing/signing.pb.go +++ b/types/tx/signing/signing.pb.go @@ -115,6 +115,10 @@ type SignatureDescriptor struct { // public_key is the public key of the signer PublicKey *types.PublicKey `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` Data *SignatureDescriptor_Data `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + // sequence is the sequence of the account, which describes the + // number of committed transactions signed by a given address. It is used to prevent + // replay attacks. + Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"` } func (m *SignatureDescriptor) Reset() { *m = SignatureDescriptor{} } @@ -164,6 +168,13 @@ func (m *SignatureDescriptor) GetData() *SignatureDescriptor_Data { return nil } +func (m *SignatureDescriptor) GetSequence() uint64 { + if m != nil { + return m.Sequence + } + return 0 +} + // Data represents signature data type SignatureDescriptor_Data struct { // sum is the oneof that specifies whether this represents single or multi-signature data @@ -376,39 +387,40 @@ func init() { } var fileDescriptor_9a54958ff3d0b1b9 = []byte{ - // 506 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x93, 0xcd, 0x6e, 0xd3, 0x40, - 0x10, 0xc7, 0xed, 0x7c, 0xa9, 0x9d, 0x22, 0x14, 0x96, 0x56, 0x4a, 0x03, 0x32, 0x55, 0x11, 0xa2, - 0x02, 0x75, 0xad, 0xa6, 0x07, 0x04, 0xb7, 0x24, 0x36, 0x69, 0xa0, 0x71, 0x8a, 0x9d, 0x4a, 0xc0, - 0xc5, 0x5a, 0x3b, 0xc6, 0xac, 0x1a, 0x67, 0x2d, 0xef, 0x1a, 0x35, 0x27, 0x5e, 0x81, 0x97, 0xe0, - 0x39, 0xb8, 0x72, 0xec, 0x91, 0x23, 0x4a, 0x24, 0x9e, 0x03, 0xc5, 0x1f, 0x49, 0x90, 0x0a, 0xa8, - 0x39, 0xd9, 0x33, 0x3b, 0xf3, 0xfb, 0xff, 0x57, 0xb3, 0x03, 0x8f, 0x5d, 0xc6, 0x03, 0xc6, 0x55, - 0x71, 0xa9, 0x72, 0xea, 0x8f, 0xe9, 0xd8, 0x57, 0x3f, 0x1d, 0x39, 0x9e, 0x20, 0x47, 0x79, 0x8c, - 0xc3, 0x88, 0x09, 0x86, 0x76, 0xd3, 0x42, 0x2c, 0x2e, 0x71, 0x7e, 0x90, 0x15, 0xd6, 0x73, 0x86, - 0x43, 0xb8, 0xa7, 0xba, 0xd1, 0x24, 0x14, 0x6c, 0x01, 0x49, 0xc3, 0x94, 0xb1, 0xff, 0x01, 0xb6, - 0x2d, 0xea, 0x8f, 0x89, 0x88, 0x23, 0x4f, 0xf3, 0xb8, 0x1b, 0xd1, 0x50, 0xb0, 0x88, 0x23, 0x03, - 0x80, 0xe7, 0x79, 0x5e, 0x93, 0xf7, 0x8a, 0x07, 0x5b, 0x0d, 0x8c, 0xff, 0x2a, 0x88, 0xaf, 0x81, - 0x98, 0x2b, 0x84, 0xfd, 0x5f, 0x25, 0xb8, 0x7b, 0x4d, 0x0d, 0xd2, 0x00, 0xc2, 0xd8, 0x19, 0x51, - 0xd7, 0xbe, 0xf0, 0x26, 0x35, 0x79, 0x4f, 0x3e, 0xd8, 0x6a, 0x3c, 0xca, 0x75, 0xe6, 0xee, 0x71, - 0x66, 0x37, 0x17, 0x3a, 0x4b, 0xaa, 0x5f, 0x7b, 0x13, 0x73, 0x33, 0xcc, 0x7f, 0x51, 0x07, 0x4a, - 0x43, 0x22, 0x48, 0xad, 0x90, 0xf4, 0x1f, 0xdf, 0xcc, 0x27, 0xd6, 0x88, 0x20, 0x66, 0x02, 0xa8, - 0x7f, 0x2b, 0x42, 0x69, 0x1e, 0xa2, 0x01, 0x54, 0x38, 0x1d, 0xfb, 0x23, 0x2f, 0xf3, 0xf4, 0x62, - 0x0d, 0x26, 0xb6, 0x12, 0xc2, 0x89, 0x64, 0x66, 0x2c, 0xf4, 0x06, 0xca, 0x41, 0x3c, 0x12, 0x34, - 0x33, 0xfa, 0x7c, 0x1d, 0x68, 0x6f, 0x0e, 0x38, 0x91, 0xcc, 0x94, 0x54, 0xb7, 0xa1, 0x92, 0xca, - 0xa0, 0x67, 0x50, 0x0a, 0xd8, 0x30, 0x35, 0x7c, 0xbb, 0xf1, 0xf0, 0x3f, 0xec, 0x1e, 0x1b, 0x7a, - 0x66, 0xd2, 0x80, 0xee, 0xc3, 0xe6, 0x62, 0x52, 0x89, 0xb3, 0x5b, 0xe6, 0x32, 0x51, 0xff, 0x2a, - 0x43, 0x39, 0xd1, 0x44, 0x1d, 0xd8, 0x70, 0xa8, 0x20, 0x51, 0x44, 0xf2, 0x49, 0x3d, 0xfd, 0xd7, - 0xa4, 0xda, 0x2c, 0x08, 0x89, 0x2b, 0x5a, 0x54, 0x34, 0xe7, 0x2d, 0xe6, 0xa2, 0x19, 0x59, 0x7f, - 0x3c, 0xae, 0x42, 0xf2, 0xb8, 0xd6, 0x1a, 0xda, 0x0a, 0xa6, 0x55, 0x86, 0x22, 0x8f, 0x83, 0x27, - 0x1c, 0x36, 0xf2, 0xeb, 0xa1, 0x5d, 0xd8, 0xb1, 0xba, 0x1d, 0xc3, 0xee, 0xf5, 0x35, 0xdd, 0x3e, - 0x37, 0xac, 0x33, 0xbd, 0xdd, 0x7d, 0xd9, 0xd5, 0xb5, 0xaa, 0x84, 0xb6, 0xa1, 0xba, 0x3c, 0xd2, - 0xba, 0xa6, 0xde, 0x1e, 0x54, 0x65, 0xb4, 0x03, 0x77, 0x96, 0xd9, 0x81, 0xfe, 0x76, 0x70, 0xde, - 0x3c, 0xad, 0x16, 0xd0, 0x03, 0xb8, 0xb7, 0x4c, 0x9f, 0xea, 0x9d, 0x66, 0xfb, 0x9d, 0xdd, 0xec, - 0x75, 0x8d, 0xbe, 0xfd, 0xca, 0xea, 0x1b, 0xd5, 0xcf, 0xad, 0xce, 0xf7, 0xa9, 0x22, 0x5f, 0x4d, - 0x15, 0xf9, 0xe7, 0x54, 0x91, 0xbf, 0xcc, 0x14, 0xe9, 0x6a, 0xa6, 0x48, 0x3f, 0x66, 0x8a, 0xf4, - 0xfe, 0xd0, 0xa7, 0xe2, 0x63, 0xec, 0x60, 0x97, 0x05, 0x6a, 0xb6, 0x93, 0xe9, 0xe7, 0x90, 0x0f, - 0x2f, 0x54, 0x31, 0x09, 0xbd, 0xd5, 0x45, 0x77, 0x2a, 0xc9, 0x56, 0x1e, 0xff, 0x0e, 0x00, 0x00, - 0xff, 0xff, 0x63, 0x6d, 0x8a, 0xc7, 0x04, 0x04, 0x00, 0x00, + // 525 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0xcd, 0x6e, 0xd3, 0x40, + 0x10, 0xc7, 0xed, 0xe6, 0x43, 0xe9, 0x14, 0xa1, 0xb0, 0xb4, 0x52, 0x1a, 0x90, 0x89, 0x8a, 0x10, + 0x11, 0xa8, 0xb6, 0x9a, 0x1e, 0x10, 0xdc, 0x92, 0xd8, 0xa4, 0x81, 0x26, 0x29, 0x76, 0x2a, 0x01, + 0x17, 0x6b, 0xed, 0x2c, 0x61, 0xd5, 0xd8, 0x6b, 0xbc, 0x6b, 0xd4, 0x9c, 0x90, 0x78, 0x02, 0x5e, + 0x82, 0xe7, 0xe0, 0xca, 0xb1, 0x47, 0x8e, 0x28, 0x79, 0x11, 0x14, 0x7f, 0x24, 0x41, 0x2a, 0x20, + 0x72, 0xb2, 0x67, 0x76, 0xe6, 0xf7, 0xff, 0xaf, 0x66, 0x77, 0xe1, 0xa1, 0xcb, 0xb8, 0xc7, 0xb8, + 0x26, 0x2e, 0x35, 0x4e, 0xc7, 0x3e, 0xf5, 0xc7, 0xda, 0xc7, 0x23, 0x87, 0x08, 0x7c, 0x94, 0xc5, + 0x6a, 0x10, 0x32, 0xc1, 0xd0, 0x7e, 0x52, 0xa8, 0x8a, 0x4b, 0x35, 0x5b, 0x48, 0x0b, 0xab, 0x19, + 0xc3, 0xc1, 0x9c, 0x68, 0x6e, 0x38, 0x0d, 0x04, 0x5b, 0x42, 0x92, 0x30, 0x61, 0x1c, 0xbc, 0x83, + 0x5d, 0x8b, 0x8e, 0x7d, 0x2c, 0xa2, 0x90, 0xe8, 0x84, 0xbb, 0x21, 0x0d, 0x04, 0x0b, 0x39, 0xea, + 0x03, 0xf0, 0x2c, 0xcf, 0x2b, 0x72, 0x2d, 0x57, 0xdf, 0x69, 0xa8, 0xea, 0x1f, 0x05, 0xd5, 0x6b, + 0x20, 0xe6, 0x1a, 0xe1, 0xe0, 0x73, 0x01, 0x6e, 0x5f, 0x53, 0x83, 0x74, 0x80, 0x20, 0x72, 0x26, + 0xd4, 0xb5, 0x2f, 0xc8, 0xb4, 0x22, 0xd7, 0xe4, 0xfa, 0x4e, 0xe3, 0x41, 0xa6, 0xb3, 0x70, 0xaf, + 0xa6, 0x76, 0x33, 0xa1, 0xb3, 0xb8, 0xfa, 0x25, 0x99, 0x9a, 0xdb, 0x41, 0xf6, 0x8b, 0x3a, 0x90, + 0x1f, 0x61, 0x81, 0x2b, 0x5b, 0x71, 0xff, 0xf1, 0xff, 0xf9, 0x54, 0x75, 0x2c, 0xb0, 0x19, 0x03, + 0x50, 0x15, 0x4a, 0x9c, 0x7c, 0x88, 0x88, 0xef, 0x92, 0x4a, 0xae, 0x26, 0xd7, 0xf3, 0xe6, 0x32, + 0xae, 0x7e, 0xcb, 0x41, 0x7e, 0x51, 0x8a, 0x86, 0x50, 0xe4, 0xd4, 0x1f, 0x4f, 0x48, 0xea, 0xf7, + 0xd9, 0x06, 0x7a, 0xaa, 0x15, 0x13, 0x4e, 0x24, 0x33, 0x65, 0xa1, 0x57, 0x50, 0xf0, 0xa2, 0x89, + 0xa0, 0xe9, 0x26, 0x9e, 0x6e, 0x02, 0xed, 0x2d, 0x00, 0x27, 0x92, 0x99, 0x90, 0xaa, 0x36, 0x14, + 0x13, 0x19, 0xf4, 0x04, 0xf2, 0x1e, 0x1b, 0x25, 0x86, 0x6f, 0x36, 0xee, 0xff, 0x83, 0xdd, 0x63, + 0x23, 0x62, 0xc6, 0x0d, 0xe8, 0x2e, 0x6c, 0x2f, 0xa7, 0x18, 0x3b, 0xbb, 0x61, 0xae, 0x12, 0xd5, + 0xaf, 0x32, 0x14, 0x62, 0x4d, 0xd4, 0x81, 0x92, 0x43, 0x05, 0x0e, 0x43, 0x9c, 0x4d, 0xf1, 0xf1, + 0xdf, 0xa6, 0xd8, 0x66, 0x5e, 0x80, 0x5d, 0xd1, 0xa2, 0xa2, 0xb9, 0x68, 0x31, 0x97, 0xcd, 0xc8, + 0xfa, 0xed, 0xe0, 0x6d, 0xc5, 0x07, 0x6f, 0xa3, 0x81, 0xae, 0x61, 0x5a, 0x05, 0xc8, 0xf1, 0xc8, + 0x7b, 0xc4, 0xa1, 0x94, 0x6d, 0x0f, 0xed, 0xc3, 0x9e, 0xd5, 0xed, 0xf4, 0xed, 0xde, 0x40, 0x37, + 0xec, 0xf3, 0xbe, 0x75, 0x66, 0xb4, 0xbb, 0xcf, 0xbb, 0x86, 0x5e, 0x96, 0xd0, 0x2e, 0x94, 0x57, + 0x4b, 0x7a, 0xd7, 0x34, 0xda, 0xc3, 0xb2, 0x8c, 0xf6, 0xe0, 0xd6, 0x2a, 0x3b, 0x34, 0x5e, 0x0f, + 0xcf, 0x9b, 0xa7, 0xe5, 0x2d, 0x74, 0x0f, 0xee, 0xac, 0xd2, 0xa7, 0x46, 0xa7, 0xd9, 0x7e, 0x63, + 0x37, 0x7b, 0xdd, 0xfe, 0xc0, 0x7e, 0x61, 0x0d, 0xfa, 0xe5, 0x4f, 0xad, 0xce, 0xf7, 0x99, 0x22, + 0x5f, 0xcd, 0x14, 0xf9, 0xe7, 0x4c, 0x91, 0xbf, 0xcc, 0x15, 0xe9, 0x6a, 0xae, 0x48, 0x3f, 0xe6, + 0x8a, 0xf4, 0xf6, 0x70, 0x4c, 0xc5, 0xfb, 0xc8, 0x51, 0x5d, 0xe6, 0x69, 0xe9, 0x7d, 0x4d, 0x3e, + 0x87, 0x7c, 0x74, 0xa1, 0x89, 0x69, 0x40, 0xd6, 0x1f, 0x01, 0xa7, 0x18, 0xdf, 0xd8, 0xe3, 0x5f, + 0x01, 0x00, 0x00, 0xff, 0xff, 0x05, 0x81, 0x3c, 0x0b, 0x20, 0x04, 0x00, 0x00, } func (m *SignatureDescriptors) Marshal() (dAtA []byte, err error) { @@ -468,6 +480,11 @@ func (m *SignatureDescriptor) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Sequence != 0 { + i = encodeVarintSigning(dAtA, i, uint64(m.Sequence)) + i-- + dAtA[i] = 0x18 + } if m.Data != nil { { size, err := m.Data.MarshalToSizedBuffer(dAtA[:i]) @@ -693,6 +710,9 @@ func (m *SignatureDescriptor) Size() (n int) { l = m.Data.Size() n += 1 + l + sovSigning(uint64(l)) } + if m.Sequence != 0 { + n += 1 + sovSigning(uint64(m.Sequence)) + } return n } @@ -961,6 +981,25 @@ func (m *SignatureDescriptor) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) + } + m.Sequence = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSigning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Sequence |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipSigning(dAtA[iNdEx:]) diff --git a/types/tx/tx.pb.go b/types/tx/tx.pb.go index 0738293590..b2265028f0 100644 --- a/types/tx/tx.pb.go +++ b/types/tx/tx.pb.go @@ -174,9 +174,6 @@ type SignDoc struct { ChainId string `protobuf:"bytes,3,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` // account_number is the account number of the account in state AccountNumber uint64 `protobuf:"varint,4,opt,name=account_number,json=accountNumber,proto3" json:"account_number,omitempty"` - // account_sequence starts at 1 rather than 0 to avoid the case where - // the default 0 value must be omitted in protobuf serialization - AccountSequence uint64 `protobuf:"varint,5,opt,name=account_sequence,json=accountSequence,proto3" json:"account_sequence,omitempty"` } func (m *SignDoc) Reset() { *m = SignDoc{} } @@ -240,13 +237,6 @@ func (m *SignDoc) GetAccountNumber() uint64 { return 0 } -func (m *SignDoc) GetAccountSequence() uint64 { - if m != nil { - return m.AccountSequence - } - return 0 -} - // TxBody is the body of a transaction that all signers sign over. type TxBody struct { // messages is a list of messages to be executed. The required signers of those messages define @@ -408,6 +398,10 @@ type SignerInfo struct { // mode_info describes the signing mode of the signer and is a nested // structure to support nested multisig pubkey's ModeInfo *ModeInfo `protobuf:"bytes,2,opt,name=mode_info,json=modeInfo,proto3" json:"mode_info,omitempty"` + // sequence is the sequence of the account, which describes the + // number of committed transactions signed by a given address. It is used to prevent + // replay attacks. + Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"` } func (m *SignerInfo) Reset() { *m = SignerInfo{} } @@ -457,6 +451,13 @@ func (m *SignerInfo) GetModeInfo() *ModeInfo { return nil } +func (m *SignerInfo) GetSequence() uint64 { + if m != nil { + return m.Sequence + } + return 0 +} + // ModeInfo describes the signing mode of a single or nested multisig signer. type ModeInfo struct { // sum is the oneof that specifies whether this represents a single or nested @@ -723,59 +724,59 @@ func init() { func init() { proto.RegisterFile("cosmos/tx/v1beta1/tx.proto", fileDescriptor_96d1575ffde80842) } var fileDescriptor_96d1575ffde80842 = []byte{ - // 830 bytes of a gzipped FileDescriptorProto + // 823 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4f, 0x6f, 0xdc, 0x44, - 0x14, 0x5f, 0xef, 0xbf, 0xec, 0xbe, 0x24, 0x4d, 0x3b, 0xaa, 0xd0, 0x66, 0xa3, 0xba, 0xc1, 0x28, - 0xb0, 0x08, 0xd5, 0x6e, 0xc3, 0x81, 0x3f, 0x42, 0x82, 0x6c, 0x4b, 0x49, 0x05, 0x05, 0x34, 0xc9, - 0xa9, 0x17, 0x6b, 0xec, 0x9d, 0x78, 0x47, 0x5d, 0xcf, 0x2c, 0x9e, 0x71, 0xb1, 0x3f, 0x01, 0x97, - 0x22, 0x71, 0xe1, 0x4b, 0xf0, 0x1d, 0xb8, 0xf7, 0xd8, 0x23, 0x07, 0x04, 0x28, 0xf9, 0x20, 0xa0, - 0x19, 0x8f, 0xdd, 0x50, 0xa2, 0xdd, 0x0b, 0xa7, 0x7d, 0xf3, 0xe6, 0xf7, 0xfb, 0xbd, 0xdf, 0xbe, - 0x37, 0xcf, 0x30, 0x8e, 0x85, 0x4c, 0x85, 0x0c, 0x54, 0x11, 0x3c, 0xbb, 0x17, 0x51, 0x45, 0xee, - 0x05, 0xaa, 0xf0, 0x97, 0x99, 0x50, 0x02, 0xdd, 0xa8, 0xee, 0x7c, 0x55, 0xf8, 0xf6, 0x6e, 0x7c, - 0x33, 0x11, 0x89, 0x30, 0xb7, 0x81, 0x8e, 0x2a, 0xe0, 0xf8, 0x1d, 0x2b, 0x12, 0x11, 0x49, 0x83, - 0x38, 0x2b, 0x97, 0x4a, 0x34, 0x6a, 0xd5, 0xd1, 0x02, 0xdd, 0xcb, 0xc0, 0x06, 0x21, 0x18, 0x7f, - 0x4d, 0x48, 0x15, 0x81, 0x64, 0x09, 0x67, 0x3c, 0x69, 0x50, 0xf6, 0x6c, 0x81, 0xbb, 0x89, 0x10, - 0xc9, 0x82, 0x06, 0xe6, 0x14, 0xe5, 0x67, 0x01, 0xe1, 0x65, 0x75, 0xe5, 0xfd, 0xe8, 0x40, 0xfb, - 0xb4, 0x40, 0x77, 0xa0, 0x1b, 0x89, 0x59, 0x39, 0x72, 0xf6, 0x9d, 0xc9, 0xe6, 0xe1, 0xae, 0xff, - 0x9f, 0xff, 0xe2, 0x9f, 0x16, 0x53, 0x31, 0x2b, 0xb1, 0x81, 0xa1, 0x0f, 0x61, 0x48, 0x72, 0x35, - 0x0f, 0x19, 0x3f, 0x13, 0xa3, 0xb6, 0xe1, 0xec, 0x5d, 0xc1, 0x39, 0xca, 0xd5, 0xfc, 0x11, 0x3f, - 0x13, 0x78, 0x40, 0x6c, 0x84, 0x5c, 0x00, 0xed, 0x8d, 0xa8, 0x3c, 0xa3, 0x72, 0xd4, 0xd9, 0xef, - 0x4c, 0xb6, 0xf0, 0xa5, 0x8c, 0xc7, 0xa1, 0x77, 0x5a, 0x60, 0xf2, 0x3d, 0xba, 0x05, 0xa0, 0x4b, - 0x85, 0x51, 0xa9, 0xa8, 0x34, 0xbe, 0xb6, 0xf0, 0x50, 0x67, 0xa6, 0x3a, 0x81, 0xde, 0x86, 0x9d, - 0xc6, 0x81, 0xc5, 0xb4, 0x0d, 0x66, 0xbb, 0x2e, 0x55, 0xe1, 0xd6, 0xd5, 0xfb, 0xd5, 0x81, 0x8d, - 0x13, 0x96, 0xf0, 0x07, 0x22, 0xfe, 0xbf, 0x4a, 0xee, 0xc2, 0x20, 0x9e, 0x13, 0xc6, 0x43, 0x36, - 0x1b, 0x75, 0xf6, 0x9d, 0xc9, 0x10, 0x6f, 0x98, 0xf3, 0xa3, 0x19, 0x3a, 0x80, 0x6b, 0x24, 0x8e, - 0x45, 0xce, 0x55, 0xc8, 0xf3, 0x34, 0xa2, 0xd9, 0xa8, 0xbb, 0xef, 0x4c, 0xba, 0x78, 0xdb, 0x66, - 0xbf, 0x36, 0x49, 0xf4, 0x2e, 0x5c, 0xaf, 0x61, 0x92, 0x7e, 0x97, 0x53, 0x1e, 0xd3, 0x51, 0xcf, - 0x00, 0x77, 0x6c, 0xfe, 0xc4, 0xa6, 0xbd, 0x9f, 0xdb, 0xd0, 0xaf, 0x46, 0x83, 0xee, 0xc2, 0x20, - 0xa5, 0x52, 0x92, 0xc4, 0x98, 0xef, 0x4c, 0x36, 0x0f, 0x6f, 0xfa, 0xd5, 0xe0, 0xfd, 0x7a, 0xf0, - 0xfe, 0x11, 0x2f, 0x71, 0x83, 0x42, 0x08, 0xba, 0x29, 0x4d, 0xab, 0x09, 0x0e, 0xb1, 0x89, 0xb5, - 0x45, 0xc5, 0x52, 0x2a, 0x72, 0x15, 0xce, 0x29, 0x4b, 0xe6, 0xca, 0xfc, 0x87, 0x2e, 0xde, 0xb6, - 0xd9, 0x63, 0x93, 0x44, 0x53, 0xb8, 0x41, 0x0b, 0x45, 0xb9, 0x64, 0x82, 0x87, 0x62, 0xa9, 0x98, - 0xe0, 0x72, 0xf4, 0xf7, 0xc6, 0x8a, 0xb2, 0xd7, 0x1b, 0xfc, 0x37, 0x15, 0x1c, 0x3d, 0x01, 0x97, - 0x0b, 0x1e, 0xc6, 0x19, 0x53, 0x2c, 0x26, 0x8b, 0xf0, 0x0a, 0xc1, 0x9d, 0x15, 0x82, 0x7b, 0x5c, - 0xf0, 0xfb, 0x96, 0xfb, 0xf9, 0x6b, 0xda, 0xde, 0x33, 0x18, 0xd4, 0xaf, 0x0f, 0x7d, 0x06, 0x5b, - 0x7a, 0xe2, 0x34, 0x33, 0xa3, 0xab, 0x9b, 0x73, 0xeb, 0x8a, 0x07, 0x7b, 0x62, 0x60, 0xe6, 0xc9, - 0x6e, 0xca, 0x26, 0x96, 0x68, 0x02, 0x9d, 0x33, 0x4a, 0xed, 0x4b, 0x7f, 0xe3, 0x0a, 0xe2, 0x43, - 0x4a, 0xb1, 0x86, 0x78, 0xcf, 0x1d, 0x80, 0x57, 0x2a, 0xe8, 0x01, 0xc0, 0x32, 0x8f, 0x16, 0x2c, - 0x0e, 0x9f, 0xd2, 0x7a, 0xbb, 0x0e, 0x6a, 0xbe, 0xde, 0x6b, 0xdf, 0x6e, 0x7c, 0x2d, 0xf4, 0xad, - 0x41, 0x7f, 0x49, 0x4b, 0x3c, 0x5c, 0xd6, 0xa1, 0x5e, 0xb7, 0x54, 0xcc, 0xe8, 0xba, 0x75, 0x7b, - 0x2c, 0x66, 0xb4, 0x5a, 0xb7, 0xd4, 0x46, 0xde, 0xef, 0x6d, 0x18, 0xd4, 0x69, 0xf4, 0x09, 0xf4, - 0x25, 0xe3, 0xc9, 0x82, 0x5a, 0x23, 0xde, 0x0a, 0x0d, 0xff, 0xc4, 0x20, 0x8f, 0x5b, 0xd8, 0x72, - 0xd0, 0x47, 0xd0, 0x4b, 0xf3, 0x85, 0x62, 0xd6, 0xc0, 0x9b, 0xab, 0xc8, 0x8f, 0x35, 0xf0, 0xb8, - 0x85, 0x2b, 0xc6, 0xf8, 0x08, 0xfa, 0x95, 0x1c, 0xfa, 0x00, 0xba, 0xda, 0x9b, 0x31, 0x70, 0xed, - 0xf0, 0xad, 0x4b, 0x1a, 0xf5, 0x17, 0xeb, 0xf2, 0x28, 0xb4, 0x1e, 0x36, 0x84, 0xf1, 0x73, 0x07, - 0x7a, 0x46, 0x15, 0x7d, 0x01, 0x83, 0x88, 0x29, 0x92, 0x65, 0xa4, 0x6e, 0xe8, 0x7b, 0xab, 0x1a, - 0x7a, 0x5f, 0xa4, 0x4b, 0x12, 0xab, 0x29, 0x53, 0x47, 0x9a, 0x82, 0x1b, 0x32, 0xfa, 0x18, 0xa0, - 0xe9, 0xaa, 0x5e, 0xe5, 0xce, 0xba, 0xb6, 0x0e, 0xeb, 0xb6, 0xca, 0x69, 0x0f, 0x3a, 0x32, 0x4f, - 0xbd, 0x1f, 0x1c, 0xe8, 0x3c, 0xa4, 0x14, 0xc5, 0xd0, 0x27, 0xa9, 0xde, 0x4b, 0xfb, 0xb6, 0x76, - 0xff, 0xe5, 0xe8, 0x95, 0x15, 0xc6, 0xa7, 0x77, 0x5f, 0xfc, 0x71, 0xbb, 0xf5, 0xcb, 0x9f, 0xb7, - 0x27, 0x09, 0x53, 0xf3, 0x3c, 0xf2, 0x63, 0x91, 0x06, 0xf6, 0x3b, 0x5e, 0xfd, 0xdc, 0x91, 0xb3, - 0xa7, 0x81, 0x2a, 0x97, 0x54, 0x1a, 0x82, 0xc4, 0x56, 0x1a, 0xed, 0xc1, 0x30, 0x21, 0x32, 0x5c, - 0xb0, 0x94, 0x29, 0x33, 0x84, 0x2e, 0x1e, 0x24, 0x44, 0x7e, 0xa5, 0xcf, 0xd3, 0x4f, 0x5f, 0x9c, - 0xbb, 0xce, 0xcb, 0x73, 0xd7, 0xf9, 0xeb, 0xdc, 0x75, 0x7e, 0xba, 0x70, 0x5b, 0x2f, 0x2f, 0xdc, - 0xd6, 0x6f, 0x17, 0x6e, 0xeb, 0xc9, 0xc1, 0xfa, 0x42, 0x81, 0x2a, 0xa2, 0xbe, 0xd9, 0xad, 0xf7, - 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0x43, 0xc7, 0xe9, 0x47, 0xe3, 0x06, 0x00, 0x00, + 0x14, 0x5f, 0xef, 0x6e, 0x36, 0xde, 0x97, 0xa4, 0xa5, 0xa3, 0x0a, 0x6d, 0x36, 0xaa, 0x1b, 0x8c, + 0x02, 0x2b, 0xa1, 0xda, 0x6d, 0x38, 0xf0, 0x47, 0x48, 0x90, 0x6d, 0x29, 0xa9, 0xa0, 0x80, 0x26, + 0x39, 0xf5, 0x62, 0x8d, 0xbd, 0x13, 0xef, 0xa8, 0xeb, 0x99, 0xc5, 0x33, 0x2e, 0xf6, 0x27, 0xe0, + 0x02, 0x12, 0x42, 0xe2, 0x3b, 0x20, 0x3e, 0x49, 0x8f, 0x3d, 0x72, 0x40, 0x80, 0x92, 0x0f, 0x02, + 0x9a, 0xf1, 0xd8, 0x0d, 0x25, 0xda, 0xbd, 0x70, 0xda, 0x79, 0x6f, 0x7e, 0xbf, 0xdf, 0xfb, 0xed, + 0x7b, 0xf3, 0x0c, 0xe3, 0x44, 0xc8, 0x4c, 0xc8, 0x50, 0x95, 0xe1, 0xb3, 0x7b, 0x31, 0x55, 0xe4, + 0x5e, 0xa8, 0xca, 0x60, 0x99, 0x0b, 0x25, 0xd0, 0x8d, 0xfa, 0x2e, 0x50, 0x65, 0x60, 0xef, 0xc6, + 0x37, 0x53, 0x91, 0x0a, 0x73, 0x1b, 0xea, 0x53, 0x0d, 0x1c, 0xbf, 0x6d, 0x45, 0x62, 0x22, 0x69, + 0x98, 0xe4, 0xd5, 0x52, 0x89, 0x56, 0xad, 0x0e, 0x2d, 0xd0, 0xbb, 0x0c, 0x6c, 0x11, 0x82, 0xf1, + 0x57, 0x84, 0x54, 0x19, 0x4a, 0x96, 0x72, 0xc6, 0xd3, 0x16, 0x65, 0x63, 0x0b, 0xdc, 0x4d, 0x85, + 0x48, 0x17, 0x34, 0x34, 0x51, 0x5c, 0x9c, 0x85, 0x84, 0x57, 0xf5, 0x95, 0xff, 0x83, 0x03, 0xdd, + 0xd3, 0x12, 0xdd, 0x81, 0x7e, 0x2c, 0x66, 0xd5, 0xc8, 0xd9, 0x77, 0x26, 0x5b, 0x87, 0xbb, 0xc1, + 0x7f, 0xfe, 0x4b, 0x70, 0x5a, 0x4e, 0xc5, 0xac, 0xc2, 0x06, 0x86, 0xde, 0x87, 0x21, 0x29, 0xd4, + 0x3c, 0x62, 0xfc, 0x4c, 0x8c, 0xba, 0x86, 0xb3, 0x77, 0x05, 0xe7, 0xa8, 0x50, 0xf3, 0x47, 0xfc, + 0x4c, 0x60, 0x97, 0xd8, 0x13, 0xf2, 0x00, 0xb4, 0x37, 0xa2, 0x8a, 0x9c, 0xca, 0x51, 0x6f, 0xbf, + 0x37, 0xd9, 0xc6, 0x97, 0x32, 0x3e, 0x87, 0x8d, 0xd3, 0x12, 0x93, 0x6f, 0xd1, 0x2d, 0x00, 0x5d, + 0x2a, 0x8a, 0x2b, 0x45, 0xa5, 0xf1, 0xb5, 0x8d, 0x87, 0x3a, 0x33, 0xd5, 0x09, 0xf4, 0x16, 0x5c, + 0x6f, 0x1d, 0x58, 0x4c, 0xd7, 0x60, 0x76, 0x9a, 0x52, 0x35, 0x6e, 0x5d, 0xbd, 0x9f, 0x1c, 0xd8, + 0x3c, 0x61, 0x29, 0x7f, 0x20, 0x92, 0xff, 0xab, 0xe4, 0x2e, 0xb8, 0xc9, 0x9c, 0x30, 0x1e, 0xb1, + 0xd9, 0xa8, 0xb7, 0xef, 0x4c, 0x86, 0x78, 0xd3, 0xc4, 0x8f, 0x66, 0xe8, 0x00, 0xae, 0x91, 0x24, + 0x11, 0x05, 0x57, 0x11, 0x2f, 0xb2, 0x98, 0xe6, 0xa3, 0xfe, 0xbe, 0x33, 0xe9, 0xe3, 0x1d, 0x9b, + 0xfd, 0xd2, 0x24, 0xfd, 0x9f, 0xbb, 0x30, 0xa8, 0xfb, 0x8d, 0xee, 0x82, 0x9b, 0x51, 0x29, 0x49, + 0x6a, 0x1c, 0xf5, 0x26, 0x5b, 0x87, 0x37, 0x83, 0x7a, 0x9a, 0x41, 0x33, 0xcd, 0xe0, 0x88, 0x57, + 0xb8, 0x45, 0x21, 0x04, 0xfd, 0x8c, 0x66, 0xf5, 0x58, 0x86, 0xd8, 0x9c, 0x75, 0x5d, 0xc5, 0x32, + 0x2a, 0x0a, 0x15, 0xcd, 0x29, 0x4b, 0xe7, 0xca, 0x18, 0xeb, 0xe3, 0x1d, 0x9b, 0x3d, 0x36, 0x49, + 0x34, 0x85, 0x1b, 0xb4, 0x54, 0x94, 0x4b, 0x26, 0x78, 0x24, 0x96, 0x8a, 0x09, 0x2e, 0x47, 0x7f, + 0x6f, 0xae, 0x28, 0xfb, 0x5a, 0x8b, 0xff, 0xaa, 0x86, 0xa3, 0x27, 0xe0, 0x71, 0xc1, 0xa3, 0x24, + 0x67, 0x8a, 0x25, 0x64, 0x11, 0x5d, 0x21, 0x78, 0x7d, 0x85, 0xe0, 0x1e, 0x17, 0xfc, 0xbe, 0xe5, + 0x7e, 0xfa, 0x8a, 0xb6, 0xff, 0x0c, 0xdc, 0xe6, 0x49, 0xa1, 0x4f, 0x60, 0x5b, 0x8f, 0x91, 0xe6, + 0x66, 0x1e, 0x4d, 0x73, 0x6e, 0x5d, 0xf1, 0x0a, 0x4f, 0x0c, 0xcc, 0xbc, 0xc3, 0x2d, 0xd9, 0x9e, + 0x25, 0x9a, 0x40, 0xef, 0x8c, 0x52, 0xfb, 0x7c, 0x5f, 0xbf, 0x82, 0xf8, 0x90, 0x52, 0xac, 0x21, + 0xfe, 0x2f, 0x0e, 0xc0, 0x4b, 0x15, 0xf4, 0x00, 0x60, 0x59, 0xc4, 0x0b, 0x96, 0x44, 0x4f, 0x69, + 0xb3, 0x32, 0x07, 0x0d, 0x5f, 0x2f, 0x6b, 0x60, 0xd7, 0xb8, 0x11, 0xfa, 0xda, 0xa0, 0x3f, 0xa7, + 0x15, 0x1e, 0x2e, 0x9b, 0xa3, 0xde, 0xa1, 0x4c, 0xcc, 0xe8, 0xba, 0x1d, 0x7a, 0x2c, 0x66, 0xb4, + 0xde, 0xa1, 0xcc, 0x9e, 0xd0, 0x18, 0x5c, 0x49, 0xbf, 0x29, 0x28, 0x4f, 0xa8, 0x9d, 0x63, 0x1b, + 0xfb, 0xbf, 0x77, 0xc1, 0x6d, 0x28, 0xe8, 0x23, 0x18, 0x48, 0xc6, 0xd3, 0x05, 0xb5, 0x26, 0xfd, + 0x15, 0xfa, 0xc1, 0x89, 0x41, 0x1e, 0x77, 0xb0, 0xe5, 0xa0, 0x0f, 0x60, 0x23, 0x2b, 0x16, 0x8a, + 0x59, 0x73, 0x6f, 0xac, 0x22, 0x3f, 0xd6, 0xc0, 0xe3, 0x0e, 0xae, 0x19, 0xe3, 0x23, 0x18, 0xd4, + 0x72, 0xe8, 0x3d, 0xe8, 0x6b, 0xdf, 0xc6, 0xc0, 0xb5, 0xc3, 0x37, 0x2f, 0x69, 0x34, 0x9f, 0xa8, + 0xcb, 0x63, 0xd2, 0x7a, 0xd8, 0x10, 0xc6, 0xdf, 0x3b, 0xb0, 0x61, 0x54, 0xd1, 0x67, 0xe0, 0xc6, + 0x4c, 0x91, 0x3c, 0x27, 0x4d, 0xb3, 0xdf, 0x59, 0xd5, 0xec, 0xfb, 0x22, 0x5b, 0x92, 0x44, 0x4d, + 0x99, 0x3a, 0xd2, 0x14, 0xdc, 0x92, 0xd1, 0x87, 0x00, 0x6d, 0xc7, 0xf5, 0xee, 0xf6, 0xd6, 0xb5, + 0x7c, 0xd8, 0xb4, 0x5c, 0x4e, 0x37, 0xa0, 0x27, 0x8b, 0xcc, 0xff, 0xce, 0x81, 0xde, 0x43, 0x4a, + 0x51, 0x02, 0x03, 0x92, 0xe9, 0x8d, 0xb5, 0xef, 0x6e, 0xf7, 0x5f, 0x8e, 0x5e, 0x5a, 0x61, 0x7c, + 0x7a, 0xf7, 0xf9, 0x1f, 0xb7, 0x3b, 0xbf, 0xfe, 0x79, 0x7b, 0x92, 0x32, 0x35, 0x2f, 0xe2, 0x20, + 0x11, 0x59, 0x68, 0x3f, 0xdc, 0xf5, 0xcf, 0x1d, 0x39, 0x7b, 0x1a, 0xaa, 0x6a, 0x49, 0xa5, 0x21, + 0x48, 0x6c, 0xa5, 0xd1, 0x1e, 0x0c, 0x53, 0x22, 0xa3, 0x05, 0xcb, 0x98, 0x32, 0x43, 0xe8, 0x63, + 0x37, 0x25, 0xf2, 0x0b, 0x1d, 0x4f, 0x3f, 0x7e, 0x7e, 0xee, 0x39, 0x2f, 0xce, 0x3d, 0xe7, 0xaf, + 0x73, 0xcf, 0xf9, 0xf1, 0xc2, 0xeb, 0xbc, 0xb8, 0xf0, 0x3a, 0xbf, 0x5d, 0x78, 0x9d, 0x27, 0x07, + 0xeb, 0x0b, 0x85, 0xaa, 0x8c, 0x07, 0x66, 0xef, 0xde, 0xfd, 0x27, 0x00, 0x00, 0xff, 0xff, 0x1d, + 0xe3, 0xfb, 0xd0, 0xd4, 0x06, 0x00, 0x00, } func (m *Tx) Marshal() (dAtA []byte, err error) { @@ -900,11 +901,6 @@ func (m *SignDoc) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.AccountSequence != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.AccountSequence)) - i-- - dAtA[i] = 0x28 - } if m.AccountNumber != 0 { i = encodeVarintTx(dAtA, i, uint64(m.AccountNumber)) i-- @@ -1084,6 +1080,11 @@ func (m *SignerInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Sequence != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Sequence)) + i-- + dAtA[i] = 0x18 + } if m.ModeInfo != nil { { size, err := m.ModeInfo.MarshalToSizedBuffer(dAtA[:i]) @@ -1382,9 +1383,6 @@ func (m *SignDoc) Size() (n int) { if m.AccountNumber != 0 { n += 1 + sovTx(uint64(m.AccountNumber)) } - if m.AccountSequence != 0 { - n += 1 + sovTx(uint64(m.AccountSequence)) - } return n } @@ -1455,6 +1453,9 @@ func (m *SignerInfo) Size() (n int) { l = m.ModeInfo.Size() n += 1 + l + sovTx(uint64(l)) } + if m.Sequence != 0 { + n += 1 + sovTx(uint64(m.Sequence)) + } return n } @@ -2007,25 +2008,6 @@ func (m *SignDoc) Unmarshal(dAtA []byte) error { break } } - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field AccountSequence", wireType) - } - m.AccountSequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.AccountSequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -2480,6 +2462,25 @@ func (m *SignerInfo) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) + } + m.Sequence = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Sequence |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) diff --git a/x/auth/ante/ante_test.go b/x/auth/ante/ante_test.go index e5c701c8ba..698cb62e91 100644 --- a/x/auth/ante/ante_test.go +++ b/x/auth/ante/ante_test.go @@ -358,7 +358,7 @@ func (suite *AnteTestSuite) TestAnteHandlerSequences() { }, false, false, - sdkerrors.ErrUnauthorized, + sdkerrors.ErrWrongSequence, }, { "fix sequence, should pass", @@ -387,7 +387,7 @@ func (suite *AnteTestSuite) TestAnteHandlerSequences() { func() {}, false, false, - sdkerrors.ErrUnauthorized, + sdkerrors.ErrWrongSequence, }, { "tx from just second signer with incorrect sequence fails", @@ -398,7 +398,7 @@ func (suite *AnteTestSuite) TestAnteHandlerSequences() { }, false, false, - sdkerrors.ErrUnauthorized, + sdkerrors.ErrWrongSequence, }, { "fix the sequence and it passes", @@ -704,7 +704,7 @@ func (suite *AnteTestSuite) TestAnteHandlerBadSignBytes() { }, false, false, - sdkerrors.ErrUnauthorized, + sdkerrors.ErrWrongSequence, }, { "test wrong accNums", @@ -816,7 +816,7 @@ func (suite *AnteTestSuite) TestAnteHandlerSetPubKey() { }, false, false, - sdkerrors.ErrUnauthorized, // because of wrong accSeq + sdkerrors.ErrWrongSequence, }, { "test public key not found", @@ -862,7 +862,7 @@ func (suite *AnteTestSuite) TestAnteHandlerSetPubKey() { }, false, false, - sdkerrors.ErrUnauthorized, + sdkerrors.ErrWrongSequence, }, { "make sure previous public key has been set after wrong signature", @@ -874,7 +874,7 @@ func (suite *AnteTestSuite) TestAnteHandlerSetPubKey() { }, false, false, - sdkerrors.ErrUnauthorized, + sdkerrors.ErrWrongSequence, }, } diff --git a/x/auth/ante/sigverify.go b/x/auth/ante/sigverify.go index a11dd6ec88..16c3c07151 100644 --- a/x/auth/ante/sigverify.go +++ b/x/auth/ante/sigverify.go @@ -141,8 +141,9 @@ func (sgcd SigGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula // make a SignatureV2 with PubKey filled in from above sig = signing.SignatureV2{ - PubKey: pubKey, - Data: sig.Data, + PubKey: pubKey, + Data: sig.Data, + Sequence: sig.Sequence, } err = sgcd.sigGasConsumer(ctx.GasMeter(), sig, params) @@ -188,10 +189,7 @@ func (svd SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul return ctx, err } - // stdSigs contains the sequence number, account number, and signatures. - // When simulating, this would just be a 0-length slice. signerAddrs := sigTx.GetSigners() - signerAccs := make([]types.AccountI, len(signerAddrs)) // check that signer length and signature length are the same if len(sigs) != len(signerAddrs) { @@ -204,14 +202,20 @@ func (svd SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul return ctx, err } - signerAccs[i] = acc - // retrieve pubkey - pubKey := signerAccs[i].GetPubKey() + pubKey := acc.GetPubKey() if !simulate && pubKey == nil { return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set") } + // Check account sequence number. + if sig.Sequence != acc.GetSequence() { + return ctx, sdkerrors.Wrapf( + sdkerrors.ErrWrongSequence, + "account sequence mismatch, expected %d, got %d", acc.GetSequence(), sig.Sequence, + ) + } + // retrieve signer data genesis := ctx.BlockHeight() == 0 chainID := ctx.ChainID() @@ -220,9 +224,9 @@ func (svd SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul accNum = acc.GetAccountNumber() } signerData := authsigning.SignerData{ - ChainID: chainID, - AccountNumber: accNum, - AccountSequence: acc.GetSequence(), + ChainID: chainID, + AccountNumber: accNum, + Sequence: acc.GetSequence(), } if !simulate { @@ -230,7 +234,7 @@ func (svd SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul if err != nil { return ctx, sdkerrors.Wrapf( sdkerrors.ErrUnauthorized, - "signature verification failed; verify correct account number (%d), account sequence (%d), and chain-id (%s)", signerAccs[i].GetAccountNumber(), signerAccs[i].GetSequence(), ctx.ChainID()) + "signature verification failed; please verify account number (%d) and chain-id (%s)", acc.GetAccountNumber(), ctx.ChainID()) } } } @@ -333,7 +337,7 @@ func DefaultSigVerificationGasConsumer( if !ok { return fmt.Errorf("expected %T, got, %T", &signing.MultiSignatureData{}, sig.Data) } - err := ConsumeMultisignatureVerificationGas(meter, multisignature, pubkey, params) + err := ConsumeMultisignatureVerificationGas(meter, multisignature, pubkey, params, sig.Sequence) if err != nil { return err } @@ -346,7 +350,8 @@ func DefaultSigVerificationGasConsumer( // ConsumeMultisignatureVerificationGas consumes gas from a GasMeter for verifying a multisig pubkey signature func ConsumeMultisignatureVerificationGas( - meter sdk.GasMeter, sig *signing.MultiSignatureData, pubkey multisig.PubKey, params types.Params, + meter sdk.GasMeter, sig *signing.MultiSignatureData, pubkey multisig.PubKey, + params types.Params, accSeq uint64, ) error { size := sig.BitArray.Count() @@ -357,8 +362,9 @@ func ConsumeMultisignatureVerificationGas( continue } sigV2 := signing.SignatureV2{ - PubKey: pubkey.GetPubKeys()[i], - Data: sig.Signatures[sigIndex], + PubKey: pubkey.GetPubKeys()[i], + Data: sig.Signatures[sigIndex], + Sequence: accSeq, } err := DefaultSigVerificationGasConsumer(meter, sigV2, params) if err != nil { diff --git a/x/auth/ante/sigverify_test.go b/x/auth/ante/sigverify_test.go index 7e78a31dd9..93b794b565 100644 --- a/x/auth/ante/sigverify_test.go +++ b/x/auth/ante/sigverify_test.go @@ -100,8 +100,9 @@ func (suite *AnteTestSuite) TestConsumeSignatureVerificationGas() { } for _, tt := range tests { sigV2 := signing.SignatureV2{ - PubKey: tt.args.pubkey, - Data: tt.args.sig, + PubKey: tt.args.pubkey, + Data: tt.args.sig, + Sequence: 0, // Arbitrary account sequence } err := ante.DefaultSigVerificationGasConsumer(tt.args.meter, sigV2, tt.args.params) diff --git a/x/auth/ante/testutil_test.go b/x/auth/ante/testutil_test.go index 6736d2a096..5ab35b7f19 100644 --- a/x/auth/ante/testutil_test.go +++ b/x/auth/ante/testutil_test.go @@ -89,13 +89,14 @@ func (suite *AnteTestSuite) CreateTestTx(privs []crypto.PrivKey, accNums []uint6 // First round: we gather all the signer infos. We use the "set empty // signature" hack to do that. var sigsV2 []signing.SignatureV2 - for _, priv := range privs { + for i, priv := range privs { sigV2 := signing.SignatureV2{ PubKey: priv.PubKey(), Data: &signing.SingleSignatureData{ SignMode: suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), Signature: nil, }, + Sequence: accSeqs[i], } sigsV2 = append(sigsV2, sigV2) @@ -109,11 +110,13 @@ func (suite *AnteTestSuite) CreateTestTx(privs []crypto.PrivKey, accNums []uint6 sigsV2 = []signing.SignatureV2{} for i, priv := range privs { signerData := xauthsigning.SignerData{ - ChainID: chainID, - AccountNumber: accNums[i], - AccountSequence: accSeqs[i], + ChainID: chainID, + AccountNumber: accNums[i], + Sequence: accSeqs[i], } - sigV2, err := tx.SignWithPrivKey(suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData, suite.txBuilder, priv, suite.clientCtx.TxConfig) + sigV2, err := tx.SignWithPrivKey( + suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData, + suite.txBuilder, priv, suite.clientCtx.TxConfig, accSeqs[i]) if err != nil { return nil, err } diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/cli/cli_test.go index db80407502..9e102abda0 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/cli/cli_test.go @@ -614,7 +614,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() { // Does not work in offline mode. _, err = authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), "--offline", sign1File.Name(), sign2File.Name()) - s.Require().EqualError(err, "couldn't verify signature") + s.Require().EqualError(err, "couldn't verify signature: unable to verify single signer signature") val1.ClientCtx.Offline = false multiSigWith2Signatures, err := authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name()) diff --git a/x/auth/client/cli/tx_multisign.go b/x/auth/client/cli/tx_multisign.go index 523153e5b3..a7c866f616 100644 --- a/x/auth/client/cli/tx_multisign.go +++ b/x/auth/client/cli/tx_multisign.go @@ -116,15 +116,15 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) error { } signingData := signing.SignerData{ - ChainID: txFactory.ChainID(), - AccountNumber: txFactory.AccountNumber(), - AccountSequence: txFactory.Sequence(), + ChainID: txFactory.ChainID(), + AccountNumber: txFactory.AccountNumber(), + Sequence: txFactory.Sequence(), } for _, sig := range sigs { err = signing.VerifySignature(sig.PubKey, signingData, sig.Data, txCfg.SignModeHandler(), txBuilder.GetTx()) if err != nil { - return fmt.Errorf("couldn't verify signature") + return fmt.Errorf("couldn't verify signature: %w", err) } if err := multisig.AddSignatureV2(multisigSig, sig, multisigPub.PubKeys); err != nil { @@ -134,8 +134,9 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) error { } sigV2 := signingtypes.SignatureV2{ - PubKey: multisigPub, - Data: multisigSig, + PubKey: multisigPub, + Data: multisigSig, + Sequence: txFactory.Sequence(), } err = txBuilder.SetSignatures(sigV2) diff --git a/x/auth/client/cli/validate_sigs.go b/x/auth/client/cli/validate_sigs.go index 3d1c50b811..06d24011d2 100644 --- a/x/auth/client/cli/validate_sigs.go +++ b/x/auth/client/cli/validate_sigs.go @@ -108,9 +108,9 @@ func printAndValidateSigs( } signingData := authsigning.SignerData{ - ChainID: chainID, - AccountNumber: accNum, - AccountSequence: accSeq, + ChainID: chainID, + AccountNumber: accNum, + Sequence: accSeq, } err = authsigning.VerifySignature(pubKey, signingData, sig.Data, signModeHandler, sigTx) if err != nil { diff --git a/x/auth/signing/handler_map_test.go b/x/auth/signing/handler_map_test.go index e419cff836..3d28117581 100644 --- a/x/auth/signing/handler_map_test.go +++ b/x/auth/signing/handler_map_test.go @@ -61,9 +61,9 @@ func TestHandlerMap_GetSignBytes(t *testing.T) { aminoJSONHandler := authtypes.NewStdTxSignModeHandler() signingData := signing.SignerData{ - ChainID: chainId, - AccountNumber: accNum, - AccountSequence: seqNum, + ChainID: chainId, + AccountNumber: accNum, + Sequence: seqNum, } signBz, err := handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx) require.NoError(t, err) diff --git a/x/auth/signing/sign_mode_handler.go b/x/auth/signing/sign_mode_handler.go index 31ddcdd518..e70246ee27 100644 --- a/x/auth/signing/sign_mode_handler.go +++ b/x/auth/signing/sign_mode_handler.go @@ -29,7 +29,9 @@ type SignerData struct { // AccountNumber is the account number of the signer AccountNumber uint64 - // AccountSequence is the account sequence number of the signer that is used - // for replay protection - AccountSequence uint64 + // Sequence is the account sequence number of the signer that is used + // for replay protection. This field is only useful for Legacy Amino signing, + // since in SIGN_MODE_DIRECT the account sequence is already in the signer + // info. + Sequence uint64 } diff --git a/x/auth/signing/verify_test.go b/x/auth/signing/verify_test.go index 02fe2c2a7b..3a8d82c236 100644 --- a/x/auth/signing/verify_test.go +++ b/x/auth/signing/verify_test.go @@ -45,11 +45,11 @@ func TestVerifySignature(t *testing.T) { msgs := []sdk.Msg{testdata.NewTestMsg(addr)} fee := types.NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)}) signerData := signing.SignerData{ - ChainID: chainId, - AccountNumber: acc.GetAccountNumber(), - AccountSequence: acc.GetSequence(), + ChainID: chainId, + AccountNumber: acc.GetAccountNumber(), + Sequence: acc.GetSequence(), } - signBytes := types.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.AccountSequence, 10, fee, msgs, memo) + signBytes := types.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.Sequence, 10, fee, msgs, memo) signature, err := priv.Sign(signBytes) require.NoError(t, err) @@ -67,7 +67,7 @@ func TestVerifySignature(t *testing.T) { multisigKey := multisig.NewPubKeyMultisigThreshold(2, pkSet) multisignature := multisig.NewMultisig(2) msgs = []sdk.Msg{testdata.NewTestMsg(addr, addr1)} - multiSignBytes := types.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.AccountSequence, 10, fee, msgs, memo) + multiSignBytes := types.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.Sequence, 10, fee, msgs, memo) sig1, err := priv.Sign(multiSignBytes) require.NoError(t, err) diff --git a/x/auth/tx/builder.go b/x/auth/tx/builder.go index 26b273d054..710472d5c7 100644 --- a/x/auth/tx/builder.go +++ b/x/auth/tx/builder.go @@ -1,7 +1,6 @@ package tx import ( - "bytes" "fmt" "github.com/gogo/protobuf/proto" @@ -241,8 +240,9 @@ func (t *builder) GetSignaturesV2() ([]signing.SignatureV2, error) { return nil, err } res[i] = signing.SignatureV2{ - PubKey: pubKeys[i], - Data: sigData, + PubKey: pubKeys[i], + Data: sigData, + Sequence: si.GetSequence(), } } @@ -320,6 +320,7 @@ func (t *builder) SetSignatures(signatures ...signing.SignatureV2) error { signerInfos[i] = &tx.SignerInfo{ PublicKey: pk, ModeInfo: modeInfo, + Sequence: sig.Sequence, } } @@ -335,63 +336,7 @@ func (t *builder) setSignerInfos(infos []*tx.SignerInfo) { t.authInfoBz = nil // set cached pubKeys to nil because they no longer match tx.AuthInfo t.pubKeys = nil -} -// getSignerIndex returns the index of a public key in the GetSigners array. It -// returns an error if the publicKey is not in GetSigners. -func (t *builder) getSignerIndex(pubKey crypto.PubKey) (int, error) { - if pubKey == nil { - return -1, sdkerrors.Wrap( - sdkerrors.ErrInvalidPubKey, - "public key is empty", - ) - } - - for i, signer := range t.GetSigners() { - if bytes.Equal(signer.Bytes(), pubKey.Address().Bytes()) { - return i, nil - } - } - - return -1, sdkerrors.Wrapf( - sdkerrors.ErrInvalidPubKey, - "public key %s is not a signer of this tx, call SetMsgs first", pubKey, - ) -} - -// SetSignerInfo implements TxBuilder.SetSignerInfo. -func (t *builder) SetSignerInfo(pubKey crypto.PubKey, modeInfo *tx.ModeInfo) error { - signerIndex, err := t.getSignerIndex(pubKey) - if err != nil { - return err - } - - pk, err := t.pubkeyCodec.Encode(pubKey) - if err != nil { - return err - } - - n := len(t.GetSigners()) - // If t.tx.AuthInfo.SignerInfos is empty, we just initialize with some - // empty data. - if len(t.tx.AuthInfo.SignerInfos) == 0 { - t.tx.AuthInfo.SignerInfos = make([]*tx.SignerInfo, n) - for i := 1; i < n; i++ { - t.tx.AuthInfo.SignerInfos[i] = &tx.SignerInfo{} - } - } - - t.tx.AuthInfo.SignerInfos[signerIndex] = &tx.SignerInfo{ - PublicKey: pk, - ModeInfo: modeInfo, - } - - // set authInfoBz to nil because the cached authInfoBz no longer matches tx.AuthInfo - t.authInfoBz = nil - // set cached pubKeys to nil because they no longer match tx.AuthInfo - t.pubKeys = nil - - return nil } func (t *builder) setSignatures(sigs [][]byte) { diff --git a/x/auth/tx/builder_test.go b/x/auth/tx/builder_test.go index 2205f4cb5f..9d5a26c310 100644 --- a/x/auth/tx/builder_test.go +++ b/x/auth/tx/builder_test.go @@ -25,8 +25,8 @@ func TestTxBuilder(t *testing.T) { cdc := std.DefaultPublicKeyCodec{} memo := "sometestmemo" - msgs := []sdk.Msg{testdata.NewTestMsg(addr)} + accSeq := uint64(2) // Arbitrary account sequence pk, err := cdc.Encode(pubkey) require.NoError(t, err) @@ -41,6 +41,7 @@ func TestTxBuilder(t *testing.T) { }, }, }, + Sequence: accSeq, }) var sig signing.SignatureV2 @@ -50,6 +51,7 @@ func TestTxBuilder(t *testing.T) { SignMode: signing.SignMode_SIGN_MODE_DIRECT, Signature: legacy.Cdc.MustMarshalBinaryBare(pubkey), }, + Sequence: accSeq, } fee := txtypes.Fee{Amount: sdk.NewCoins(sdk.NewInt64Coin("atom", 150)), GasLimit: 20000} @@ -144,6 +146,7 @@ func TestBuilderValidateBasic(t *testing.T) { SignMode: signing.SignMode_SIGN_MODE_DIRECT, Signature: legacy.Cdc.MustMarshalBinaryBare(pubKey1), }, + Sequence: 0, // Arbitrary account sequence } sig2 = signing.SignatureV2{ @@ -152,6 +155,7 @@ func TestBuilderValidateBasic(t *testing.T) { SignMode: signing.SignMode_SIGN_MODE_DIRECT, Signature: legacy.Cdc.MustMarshalBinaryBare(pubKey2), }, + Sequence: 0, // Arbitrary account sequence } err := txBuilder.SetMsgs(msgs...) diff --git a/x/auth/tx/direct.go b/x/auth/tx/direct.go index 9e2c46de73..130c1489f3 100644 --- a/x/auth/tx/direct.go +++ b/x/auth/tx/direct.go @@ -39,18 +39,17 @@ func (signModeDirectHandler) GetSignBytes(mode signingtypes.SignMode, data signi bodyBz := protoTx.getBodyBytes() authInfoBz := protoTx.getAuthInfoBytes() - return DirectSignBytes(bodyBz, authInfoBz, data.ChainID, data.AccountNumber, data.AccountSequence) + return DirectSignBytes(bodyBz, authInfoBz, data.ChainID, data.AccountNumber) } // DirectSignBytes returns the SIGN_MODE_DIRECT sign bytes for the provided TxBody bytes, AuthInfo bytes, chain ID, // account number and sequence. -func DirectSignBytes(bodyBytes, authInfoBytes []byte, chainID string, accnum, sequence uint64) ([]byte, error) { +func DirectSignBytes(bodyBytes, authInfoBytes []byte, chainID string, accnum uint64) ([]byte, error) { signDoc := types.SignDoc{ - BodyBytes: bodyBytes, - AuthInfoBytes: authInfoBytes, - ChainId: chainID, - AccountNumber: accnum, - AccountSequence: sequence, + BodyBytes: bodyBytes, + AuthInfoBytes: authInfoBytes, + ChainId: chainID, + AccountNumber: accnum, } return signDoc.Marshal() } diff --git a/x/auth/tx/direct_test.go b/x/auth/tx/direct_test.go index e4c9a19d98..8d665a0787 100644 --- a/x/auth/tx/direct_test.go +++ b/x/auth/tx/direct_test.go @@ -28,6 +28,7 @@ func TestDirectModeHandler(t *testing.T) { memo := "sometestmemo" msgs := []sdk.Msg{testdata.NewTestMsg(addr)} + accSeq := uint64(2) // Arbitrary account sequence pk, err := pubKeyCdc.Encode(pubkey) require.NoError(t, err) @@ -42,14 +43,16 @@ func TestDirectModeHandler(t *testing.T) { }, }, }, + Sequence: accSeq, }) sigData := &signingtypes.SingleSignatureData{ SignMode: signingtypes.SignMode_SIGN_MODE_DIRECT, } sig := signingtypes.SignatureV2{ - PubKey: pubkey, - Data: sigData, + PubKey: pubkey, + Data: sigData, + Sequence: accSeq, } fee := txtypes.Fee{Amount: sdk.NewCoins(sdk.NewInt64Coin("atom", 150)), GasLimit: 20000} @@ -69,9 +72,8 @@ func TestDirectModeHandler(t *testing.T) { require.Len(t, modeHandler.Modes(), 1) signingData := signing.SignerData{ - ChainID: "test-chain", - AccountNumber: 1, - AccountSequence: 1, + ChainID: "test-chain", + AccountNumber: 1, } signBytes, err := modeHandler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_DIRECT, signingData, txBuilder.GetTx()) @@ -104,11 +106,10 @@ func TestDirectModeHandler(t *testing.T) { t.Log("verify GetSignBytes with generating sign bytes by marshaling SignDoc") signDoc := txtypes.SignDoc{ - AccountNumber: 1, - AccountSequence: 1, - AuthInfoBytes: authInfoBytes, - BodyBytes: bodyBytes, - ChainId: "test-chain", + AccountNumber: 1, + AuthInfoBytes: authInfoBytes, + BodyBytes: bodyBytes, + ChainId: "test-chain", } expectedSignBytes, err := signDoc.Marshal() diff --git a/x/auth/tx/legacy_amino_json.go b/x/auth/tx/legacy_amino_json.go index c03e14a1a7..5c10f3c689 100644 --- a/x/auth/tx/legacy_amino_json.go +++ b/x/auth/tx/legacy_amino_json.go @@ -49,7 +49,7 @@ func (s signModeLegacyAminoJSONHandler) GetSignBytes(mode signingtypes.SignMode, // nolint: staticcheck return types.StdSignBytes( - data.ChainID, data.AccountNumber, data.AccountSequence, protoTx.GetTimeoutHeight(), + data.ChainID, data.AccountNumber, data.Sequence, protoTx.GetTimeoutHeight(), types.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 8631745ab4..c5ffad7cc0 100644 --- a/x/auth/tx/legacy_amino_json_test.go +++ b/x/auth/tx/legacy_amino_json_test.go @@ -46,9 +46,9 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) { handler := signModeLegacyAminoJSONHandler{} signingData := signing.SignerData{ - ChainID: chainId, - AccountNumber: accNum, - AccountSequence: seqNum, + ChainID: chainId, + AccountNumber: accNum, + Sequence: seqNum, } signBz, err := handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx) require.NoError(t, err) diff --git a/x/auth/tx/sigs.go b/x/auth/tx/sigs.go index e2035e3a3a..18f8bc4948 100644 --- a/x/auth/tx/sigs.go +++ b/x/auth/tx/sigs.go @@ -144,8 +144,9 @@ func (g config) UnmarshalSignatureJSON(bz []byte) ([]signing.SignatureV2, error) data := signing.SignatureDataFromProto(desc.Data) sigs[i] = signing.SignatureV2{ - PubKey: pubKey, - Data: data, + PubKey: pubKey, + Data: data, + Sequence: desc.Sequence, } } diff --git a/x/auth/types/account_test.go b/x/auth/types/account_test.go index aab4893fc5..3d30b6b45c 100644 --- a/x/auth/types/account_test.go +++ b/x/auth/types/account_test.go @@ -48,7 +48,7 @@ func TestBaseAddressPubKey(t *testing.T) { require.EqualValues(t, addr2, acc2.GetAddress()) } -func TestBaseAccountSequence(t *testing.T) { +func TestBaseSequence(t *testing.T) { _, _, addr := testdata.KeyTestPubAddr() acc := types.NewBaseAccountWithAddress(addr) seq := uint64(7) diff --git a/x/auth/types/amino_signing.go b/x/auth/types/amino_signing.go index 4712a20185..27fb7a3d7a 100644 --- a/x/auth/types/amino_signing.go +++ b/x/auth/types/amino_signing.go @@ -39,6 +39,6 @@ func (stdTxSignModeHandler) GetSignBytes(mode signingtypes.SignMode, data signin } return StdSignBytes( - data.ChainID, data.AccountNumber, data.AccountSequence, stdTx.GetTimeoutHeight(), StdFee{Amount: stdTx.GetFee(), Gas: stdTx.GetGas()}, tx.GetMsgs(), stdTx.GetMemo(), + 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/amino_signing_test.go b/x/auth/types/amino_signing_test.go index b451fe26b1..a321ddfa3d 100644 --- a/x/auth/types/amino_signing_test.go +++ b/x/auth/types/amino_signing_test.go @@ -46,9 +46,9 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) { handler := stdTxSignModeHandler{} signingData := signing.SignerData{ - ChainID: chainId, - AccountNumber: accNum, - AccountSequence: seqNum, + ChainID: chainId, + AccountNumber: accNum, + Sequence: seqNum, } signBz, err := handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx) require.NoError(t, err) diff --git a/x/auth/types/client_tx.go b/x/auth/types/client_tx.go index ec7c61d312..04b2893763 100644 --- a/x/auth/types/client_tx.go +++ b/x/auth/types/client_tx.go @@ -3,12 +3,9 @@ package types import ( "fmt" - "github.com/tendermint/tendermint/crypto" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - txtypes "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/types/tx/signing" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" ) @@ -34,12 +31,6 @@ func (s *StdTxBuilder) SetMsgs(msgs ...sdk.Msg) error { return nil } -// SetSignerInfo implements TxBuilder.SetSignerInfo. -func (s *StdTxBuilder) SetSignerInfo(_ crypto.PubKey, _ *txtypes.ModeInfo) error { - // SetSignerInfo is a no-op for amino StdTx - return nil -} - // SetSignatures implements TxBuilder.SetSignatures. func (s *StdTxBuilder) SetSignatures(signatures ...signing.SignatureV2) error { sigs := make([]StdSignature, len(signatures)) diff --git a/x/bank/app_test.go b/x/bank/app_test.go index bc04ab839a..c554d53574 100644 --- a/x/bank/app_test.go +++ b/x/bank/app_test.go @@ -22,6 +22,7 @@ type ( } appTestCase struct { + desc string expSimPass bool expPass bool msgs []sdk.Msg @@ -216,6 +217,7 @@ func TestMsgMultiSendWithAccounts(t *testing.T) { testCases := []appTestCase{ { + desc: "make a valid tx", msgs: []sdk.Msg{multiSendMsg1}, accNums: []uint64{0}, accSeqs: []uint64{0}, @@ -228,17 +230,19 @@ func TestMsgMultiSendWithAccounts(t *testing.T) { }, }, { + desc: "wrong accNum should pass Simulate, but not Deliver", msgs: []sdk.Msg{multiSendMsg1, multiSendMsg2}, - accNums: []uint64{0}, - accSeqs: []uint64{0}, + accNums: []uint64{1}, // wrong account number + accSeqs: []uint64{1}, expSimPass: true, // doesn't check signature expPass: false, privKeys: []crypto.PrivKey{priv1}, }, { + desc: "wrong accSeq should not pass Simulate", msgs: []sdk.Msg{multiSendMsg5}, accNums: []uint64{0}, - accSeqs: []uint64{0}, + accSeqs: []uint64{0}, // wrong account sequence expSimPass: false, expPass: false, privKeys: []crypto.PrivKey{priv1},