Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R4R: Don't serialize Account Number and Sequence Number in signatures #2977

Merged
merged 2 commits into from
Dec 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ BREAKING CHANGES
* Gaia
- [#128](https://github.com/tendermint/devops/issues/128) Updated CircleCI job to trigger website build on every push to master/develop.
* SDK
- [auth] \#2952 Signatures are no longer serialized on chain with the account number and sequence number

* Tendermint

Expand Down
14 changes: 9 additions & 5 deletions cmd/gaia/app/benchmarks/txsize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ import (

// This will fail half the time with the second output being 173
// This is due to secp256k1 signatures not being constant size.
// This will be resolved when updating to tendermint v0.24.0
// nolint: vet
func ExampleTxSendSize() {
cdc := app.MakeCodec()
var gas uint64 = 1

priv1 := secp256k1.GenPrivKeySecp256k1([]byte{0})
addr1 := sdk.AccAddress(priv1.PubKey().Address())
priv2 := secp256k1.GenPrivKeySecp256k1([]byte{1})
Expand All @@ -25,11 +26,14 @@ func ExampleTxSendSize() {
Inputs: []bank.Input{bank.NewInput(addr1, coins)},
Outputs: []bank.Output{bank.NewOutput(addr2, coins)},
}
sig, _ := priv1.Sign(msg1.GetSignBytes())
sigs := []auth.StdSignature{{nil, sig, 0, 0}}
tx := auth.NewStdTx([]sdk.Msg{msg1}, auth.NewStdFee(0, coins...), sigs, "")
fee := auth.NewStdFee(gas, coins...)
signBytes := auth.StdSignBytes("example-chain-ID",
1, 1, fee, []sdk.Msg{msg1}, "")
sig, _ := priv1.Sign(signBytes)
sigs := []auth.StdSignature{{nil, sig}}
tx := auth.NewStdTx([]sdk.Msg{msg1}, fee, sigs, "")
fmt.Println(len(cdc.MustMarshalBinaryBare([]sdk.Msg{msg1})))
fmt.Println(len(cdc.MustMarshalBinaryBare(tx)))
// output: 80
// 167
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously the benchmark masked the true tx size, since it omitted account number, sequence number, and gas (as they were the default value). This increase is due to gas, but removal of accnum and sequence number will increase space savings.

// 169
}
48 changes: 12 additions & 36 deletions x/auth/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,14 @@ func NewAnteHandler(am AccountKeeper, fck FeeCollectionKeeper) sdk.AnteHandler {
// When simulating, this would just be a 0-length slice.
stdSigs := stdTx.GetSignatures()
signerAddrs := stdTx.GetSigners()

// create the list of all sign bytes
signBytesList := getSignBytesList(newCtx.ChainID(), stdTx, stdSigs)
signerAccs, res := getSignerAccs(newCtx, am, signerAddrs)
if !res.IsOK() {
return newCtx, res, true
}
res = validateAccNumAndSequence(ctx, signerAccs, stdSigs)
if !res.IsOK() {
return newCtx, res, true
}

isGenesis := ctx.BlockHeight() == 0
// create the list of all sign bytes
signBytesList := getSignBytesList(newCtx.ChainID(), stdTx, signerAccs, isGenesis)
cwgoes marked this conversation as resolved.
Show resolved Hide resolved

// first sig pays the fees
if !stdTx.Fee.Amount.IsZero() {
Expand Down Expand Up @@ -129,31 +126,6 @@ func getSignerAccs(ctx sdk.Context, am AccountKeeper, addrs []sdk.AccAddress) (a
return
}

func validateAccNumAndSequence(ctx sdk.Context, accs []Account, sigs []StdSignature) sdk.Result {
for i := 0; i < len(accs); i++ {
// On InitChain, make sure account number == 0
if ctx.BlockHeight() == 0 && sigs[i].AccountNumber != 0 {
return sdk.ErrInvalidSequence(
fmt.Sprintf("Invalid account number for BlockHeight == 0. Got %d, expected 0", sigs[i].AccountNumber)).Result()
}

// Check account number.
accnum := accs[i].GetAccountNumber()
if ctx.BlockHeight() != 0 && accnum != sigs[i].AccountNumber {
return sdk.ErrInvalidSequence(
fmt.Sprintf("Invalid account number. Got %d, expected %d", sigs[i].AccountNumber, accnum)).Result()
}

// Check sequence number.
seq := accs[i].GetSequence()
if seq != sigs[i].Sequence {
return sdk.ErrInvalidSequence(
fmt.Sprintf("Invalid sequence. Got %d, expected %d", sigs[i].Sequence, seq)).Result()
}
}
return sdk.Result{}
}

// verify the signature and increment the sequence.
// if the account doesn't have a pubkey, set it.
func processSig(ctx sdk.Context,
Expand Down Expand Up @@ -297,11 +269,15 @@ func setGasMeter(simulate bool, ctx sdk.Context, stdTx StdTx) sdk.Context {
return ctx.WithGasMeter(sdk.NewGasMeter(stdTx.Fee.Gas))
}

func getSignBytesList(chainID string, stdTx StdTx, stdSigs []StdSignature) (signatureBytesList [][]byte) {
signatureBytesList = make([][]byte, len(stdSigs))
for i := 0; i < len(stdSigs); i++ {
func getSignBytesList(chainID string, stdTx StdTx, accs []Account, genesis bool) (signatureBytesList [][]byte) {
signatureBytesList = make([][]byte, len(accs))
for i := 0; i < len(accs); i++ {
accNum := accs[i].GetAccountNumber()
if genesis {
accNum = 0
}
signatureBytesList[i] = StdSignBytes(chainID,
stdSigs[i].AccountNumber, stdSigs[i].Sequence,
accNum, accs[i].GetSequence(),
stdTx.Fee, stdTx.Msgs, stdTx.Memo)
}
return
Expand Down
20 changes: 10 additions & 10 deletions x/auth/ante_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func newTestTx(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey, accNums
if err != nil {
panic(err)
}
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: sig, AccountNumber: accNums[i], Sequence: seqs[i]}
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: sig}
}
tx := NewStdTx(msgs, fee, sigs, "")
return tx
Expand All @@ -88,7 +88,7 @@ func newTestTxWithMemo(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey,
if err != nil {
panic(err)
}
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: sig, AccountNumber: accNums[i], Sequence: seqs[i]}
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: sig}
}
tx := NewStdTx(msgs, fee, sigs, memo)
return tx
Expand All @@ -102,7 +102,7 @@ func newTestTxWithSignBytes(msgs []sdk.Msg, privs []crypto.PrivKey, accNums []ui
if err != nil {
panic(err)
}
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: sig, AccountNumber: accNums[i], Sequence: seqs[i]}
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: sig}
}
tx := NewStdTx(msgs, fee, sigs, memo)
return tx
Expand Down Expand Up @@ -200,7 +200,7 @@ func TestAnteHandlerAccountNumbers(t *testing.T) {
// new tx from wrong account number
seqs = []uint64{1}
tx = newTestTx(ctx, msgs, privs, []uint64{1}, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidSequence)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)

// from correct account number
seqs = []uint64{1}
Expand All @@ -213,7 +213,7 @@ func TestAnteHandlerAccountNumbers(t *testing.T) {
msgs = []sdk.Msg{msg1, msg2}
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{1, 0}, []uint64{2, 0}
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidSequence)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)

// correct account numbers
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{0, 1}, []uint64{2, 0}
Expand Down Expand Up @@ -260,7 +260,7 @@ func TestAnteHandlerAccountNumbersAtBlockHeightZero(t *testing.T) {
// new tx from wrong account number
seqs = []uint64{1}
tx = newTestTx(ctx, msgs, privs, []uint64{1}, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidSequence)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)

// from correct account number
seqs = []uint64{1}
Expand All @@ -273,7 +273,7 @@ func TestAnteHandlerAccountNumbersAtBlockHeightZero(t *testing.T) {
msgs = []sdk.Msg{msg1, msg2}
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{1, 0}, []uint64{2, 0}
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidSequence)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)

// correct account numbers
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{0, 0}, []uint64{2, 0}
Expand Down Expand Up @@ -322,7 +322,7 @@ func TestAnteHandlerSequences(t *testing.T) {
checkValidTx(t, anteHandler, ctx, tx, false)

// test sending it again fails (replay protection)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidSequence)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)

// fix sequence, should pass
seqs = []uint64{1}
Expand All @@ -339,14 +339,14 @@ func TestAnteHandlerSequences(t *testing.T) {
checkValidTx(t, anteHandler, ctx, tx, false)

// replay fails
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidSequence)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)

// tx from just second signer with incorrect sequence fails
msg = newTestMsg(addr2)
msgs = []sdk.Msg{msg}
privs, accnums, seqs = []crypto.PrivKey{priv2}, []uint64{1}, []uint64{0}
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidSequence)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)

// fix the sequence and it passes
tx = newTestTx(ctx, msgs, []crypto.PrivKey{priv2}, []uint64{1}, []uint64{1}, fee)
Expand Down
10 changes: 3 additions & 7 deletions x/auth/client/txbuilder/txbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,7 @@ func (bldr TxBuilder) BuildWithPubKey(name string, msgs []sdk.Msg) ([]byte, erro
}

sigs := []auth.StdSignature{{
AccountNumber: msg.AccountNumber,
Sequence: msg.Sequence,
PubKey: info.GetPubKey(),
PubKey: info.GetPubKey(),
}}

return bldr.Codec.MarshalBinaryLengthPrefixed(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo))
Expand Down Expand Up @@ -206,9 +204,7 @@ func MakeSignature(name, passphrase string, msg StdSignMsg) (sig auth.StdSignatu
return
}
return auth.StdSignature{
AccountNumber: msg.AccountNumber,
Sequence: msg.Sequence,
PubKey: pubkey,
Signature: sigBytes,
PubKey: pubkey,
Signature: sigBytes,
}, nil
}
2 changes: 0 additions & 2 deletions x/auth/stdtx.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,6 @@ func StdSignBytes(chainID string, accnum uint64, sequence uint64, fee StdFee, ms
type StdSignature struct {
crypto.PubKey `json:"pub_key"` // optional
Signature []byte `json:"signature"`
AccountNumber uint64 `json:"account_number"`
Sequence uint64 `json:"sequence"`
}

// logic for standard transaction decoding
Expand Down
15 changes: 1 addition & 14 deletions x/bank/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func TestMsgSendWithAccounts(t *testing.T) {
msgs: []sdk.Msg{sendMsg1, sendMsg2},
accNums: []uint64{0},
accSeqs: []uint64{0},
expSimPass: false,
expSimPass: true, // doesn't check signature
expPass: false,
privKeys: []crypto.PrivKey{priv1},
},
Expand All @@ -136,19 +136,6 @@ func TestMsgSendWithAccounts(t *testing.T) {
mock.CheckBalance(t, mapp, eb.addr, eb.coins)
}
}

// bumping the tx nonce number without resigning should be an auth error
cwgoes marked this conversation as resolved.
Show resolved Hide resolved
mapp.BeginBlock(abci.RequestBeginBlock{})

tx := mock.GenTx([]sdk.Msg{sendMsg1}, []uint64{0}, []uint64{0}, priv1)
tx.Signatures[0].Sequence = 1

res := mapp.Deliver(tx)
require.EqualValues(t, sdk.CodeUnauthorized, res.Code, res.Log)
require.EqualValues(t, sdk.CodespaceRoot, res.Codespace)

// resigning the tx with the bumped sequence should work
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg1, sendMsg2}, []uint64{0}, []uint64{1}, true, true, priv1)
}

func TestMsgSendMultipleOut(t *testing.T) {
Expand Down
6 changes: 2 additions & 4 deletions x/mock/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,8 @@ func GenTx(msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKe
}

sigs[i] = auth.StdSignature{
PubKey: p.PubKey(),
Signature: sig,
AccountNumber: accnums[i],
Sequence: seq[i],
PubKey: p.PubKey(),
Signature: sig,
}
}

Expand Down