From 661d0fd7e8055b9710a73a3967041cb14363a6d0 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 11 Mar 2018 00:57:39 +0100 Subject: [PATCH] types: StdSignDoc includes sequence for each sig --- examples/basecoin/app/app_test.go | 14 +++++++------- types/tx_msg.go | 19 ++++++++++--------- x/auth/ante.go | 12 +++++++----- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index 595d75f380..148f0411fc 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -69,9 +69,9 @@ func TestMsgs(t *testing.T) { } chainID := "" - sequence := int64(0) + sequences := []int64{0} for i, m := range msgs { - sig := priv1.Sign(sdk.StdSignBytes(chainID, sequence, m.msg)) + sig := priv1.Sign(sdk.StdSignBytes(chainID, sequences, m.msg)) tx := sdk.NewStdTx(m.msg, []sdk.StdSignature{{ PubKey: priv1.PubKey(), Signature: sig, @@ -169,8 +169,8 @@ func TestSendMsgWithAccounts(t *testing.T) { // Sign the tx chainID := "" // TODO: InitChain should get the ChainID - sequence := int64(0) - sig := priv1.Sign(sdk.StdSignBytes(chainID, sequence, sendMsg)) + sequences := []int64{0} + sig := priv1.Sign(sdk.StdSignBytes(chainID, sequences, sendMsg)) tx := sdk.NewStdTx(sendMsg, []sdk.StdSignature{{ PubKey: priv1.PubKey(), Signature: sig, @@ -197,13 +197,13 @@ func TestSendMsgWithAccounts(t *testing.T) { assert.Equal(t, sdk.CodeInvalidSequence, res.Code, res.Log) // bumping the txnonce number without resigning should be an auth error - sequence += 1 - tx.Signatures[0].Sequence = sequence + tx.Signatures[0].Sequence = 1 res = bapp.Deliver(tx) assert.Equal(t, sdk.CodeUnauthorized, res.Code, res.Log) // resigning the tx with the bumped sequence should work - sig = priv1.Sign(sdk.StdSignBytes(chainID, sequence, tx.Msg)) + sequences = []int64{1} + sig = priv1.Sign(sdk.StdSignBytes(chainID, sequences, tx.Msg)) tx.Signatures[0].Signature = sig res = bapp.Deliver(tx) assert.Equal(t, sdk.CodeOK, res.Code, res.Log) diff --git a/types/tx_msg.go b/types/tx_msg.go index c88107c518..63f9347265 100644 --- a/types/tx_msg.go +++ b/types/tx_msg.go @@ -71,19 +71,20 @@ func (tx StdTx) GetSignatures() []StdSignature { return tx.Signatures } // StdSignDoc is replay-prevention structure. // It includes the result of msg.GetSignBytes(), // as well as the ChainID (prevent cross chain replay) -// and the Sequence (prevent inchain replay). +// and the Sequence numbers for each signature (prevent +// inchain replay and enforce tx ordering per account). type StdSignDoc struct { - ChainID string `json:"chain_id"` - Sequence int64 `json:"sequence"` - MsgBytes []byte `json:"msg_bytes"` - AltBytes []byte `json:"alt_bytes"` // TODO: do we really want this ? + ChainID string `json:"chain_id"` + Sequences []int64 `json:"sequences"` + MsgBytes []byte `json:"msg_bytes"` + AltBytes []byte `json:"alt_bytes"` // TODO: do we really want this ? } -func StdSignBytes(chainID string, sequence int64, msg Msg) []byte { +func StdSignBytes(chainID string, sequences []int64, msg Msg) []byte { bz, err := json.Marshal(StdSignDoc{ - ChainID: chainID, - Sequence: sequence, - MsgBytes: msg.GetSignBytes(), + ChainID: chainID, + Sequences: sequences, + MsgBytes: msg.GetSignBytes(), }) if err != nil { panic(err) diff --git a/x/auth/ante.go b/x/auth/ante.go index 7ab677e88d..f54435e21a 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -31,15 +31,17 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler { // Collect accounts to set in the context var signerAccs = make([]sdk.Account, len(signerAddrs)) - // First sig is the fee payer. - // signBytes uses the sequence of the fee payer - // (ie. the first account) - payerAddr, payerSig := signerAddrs[0], sigs[0] - signBytes := sdk.StdSignBytes(ctx.ChainID(), payerSig.Sequence, msg) + // Get the sign bytes by collecting all sequence numbers + sequences := make([]int64, len(signerAddrs)) + for i := 0; i < len(signerAddrs); i++ { + sequences[i] = sigs[i].Sequence + } + signBytes := sdk.StdSignBytes(ctx.ChainID(), sequences, msg) // Check fee payer sig and nonce, and deduct fee. // This is done first because it only // requires fetching 1 account. + payerAddr, payerSig := signerAddrs[0], sigs[0] payerAcc, res := processSig(ctx, accountMapper, payerAddr, payerSig, signBytes) if !res.IsOK() { return ctx, res, true