nonce testing

This commit is contained in:
rigel rozanski 2017-07-12 06:10:17 -04:00 committed by Ethan Frey
parent 16b039534d
commit 6e07dbe7c3
5 changed files with 78 additions and 26 deletions

View File

@ -90,7 +90,7 @@ func doSendTx(cmd *cobra.Command, args []string) error {
if seq < 0 {
return fmt.Errorf("sequence must be greater than 0")
}
tx = nonce.NewTx(tx, uint32(seq), nonceAccount) // XXX - what is the nonceAccount here!!!
tx = nonce.NewTx(uint32(seq), nonceAccount, tx)
// Note: this is single sig (no multi sig yet)
stx := auth.NewSig(tx)

View File

@ -12,7 +12,6 @@ import (
var (
errDecoding = fmt.Errorf("Error decoding input")
errNoAccount = fmt.Errorf("No such account")
errUnauthorized = fmt.Errorf("Unauthorized")
errInvalidSignature = fmt.Errorf("Invalid Signature")
errTooLarge = fmt.Errorf("Input size too large")
@ -139,17 +138,13 @@ func IsNoChainErr(err error) bool {
func ErrNoNonce() TMError {
return WithCode(errNoNonce, unauthorized)
}
func ErrBadNonce() TMError {
return WithCode(errBadNonce, unauthorized)
func ErrBadNonce(got, expected uint32) TMError {
return WithCode(fmt.Errorf("Bad nonce seqence, got %d, expected %d", got, expected), unauthorized)
}
func ErrNotMember() TMError {
return WithCode(errBadNonce, unauthorized)
}
func ErrNoAccount() TMError {
return WithCode(errNoAccount, unknownAddress)
}
func ErrWrongChain(chain string) TMError {
msg := errors.Wrap(errWrongChain, chain)
return WithCode(msg, unauthorized)

View File

@ -10,10 +10,10 @@ import (
)
func getSeq(store state.KVStore, key []byte) (seq uint32, err error) {
// fmt.Printf("load: %X\n", key)
data := store.Get(key)
if len(data) == 0 {
return seq, errors.ErrNoAccount()
//if the key is not stored, its a new key with a sequence of zero!
return 0, nil
}
err = wire.ReadBinaryBytes(data, &seq)
if err != nil {

View File

@ -20,31 +20,24 @@ const (
)
func init() {
basecoin.TxMapper.RegisterImplementation(&Tx{}, TypeNonce, ByteNonce)
basecoin.TxMapper.RegisterImplementation(Tx{}, TypeNonce, ByteNonce)
}
// Tx - XXX fill in
type Tx struct {
Tx basecoin.Tx `json:p"tx"`
Sequence uint32
Signers []basecoin.Actor // or simple []data.Bytes (they are only pubkeys...)
seqKey []byte //key to store the sequence number
Sequence uint32 `json:"sequence"`
Signers []basecoin.Actor `json:"signers"`
Tx basecoin.Tx `json:"tx"`
}
var _ basecoin.TxInner = &Tx{}
// NewTx wraps the tx with a signable nonce
func NewTx(tx basecoin.Tx, sequence uint32, signers []basecoin.Actor) basecoin.Tx {
//Generate the sequence key as the hash of the list of signers, sorted by address
sort.Sort(basecoin.ByAddress(signers))
seqKey := merkle.SimpleHashFromBinary(signers)
func NewTx(sequence uint32, signers []basecoin.Actor, tx basecoin.Tx) basecoin.Tx {
return (Tx{
Tx: tx,
Sequence: sequence,
Signers: signers,
seqKey: seqKey,
Tx: tx,
}).Wrap()
}
@ -59,13 +52,17 @@ func (n Tx) ValidateBasic() error {
// CheckIncrementSeq - XXX fill in
func (n Tx) CheckIncrementSeq(ctx basecoin.Context, store state.KVStore) error {
//Generate the sequence key as the hash of the list of signers, sorted by address
sort.Sort(basecoin.ByAddress(n.Signers))
seqKey := merkle.SimpleHashFromBinary(n.Signers)
// check the current state
cur, err := getSeq(store, n.seqKey)
cur, err := getSeq(store, seqKey)
if err != nil {
return err
}
if n.Sequence != cur+1 {
return errors.ErrBadNonce()
return errors.ErrBadNonce(n.Sequence, cur+1)
}
// make sure they all signed
@ -76,7 +73,7 @@ func (n Tx) CheckIncrementSeq(ctx basecoin.Context, store state.KVStore) error {
}
//finally increment the sequence by 1
err = setSeq(store, n.seqKey, cur+1)
err = setSeq(store, seqKey, cur+1)
if err != nil {
return err
}

60
modules/nonce/tx_test.go Normal file
View File

@ -0,0 +1,60 @@
package nonce
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/basecoin/state"
"github.com/tendermint/tmlibs/log"
)
func TestNonce(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
// generic args here...
chainID := "my-chain"
height := uint64(100)
ctx := stack.NewContext(chainID, height, log.NewNopLogger())
store := state.NewMemKVStore()
act1 := basecoin.Actor{ChainID: chainID, App: "fooz", Address: []byte{1, 2, 3, 4}}
act2 := basecoin.Actor{ChainID: chainID, App: "fooz", Address: []byte{1, 1, 1, 1}}
act3 := basecoin.Actor{ChainID: chainID, App: "fooz", Address: []byte{3, 3, 3, 3}}
testList := []struct {
valid bool
seq uint32
actors []basecoin.Actor
}{
{false, 0, []basecoin.Actor{act1}},
{true, 1, []basecoin.Actor{act1}},
{false, 777, []basecoin.Actor{act1}},
{true, 2, []basecoin.Actor{act1}},
{false, 0, []basecoin.Actor{act1, act2}},
{true, 1, []basecoin.Actor{act1, act2}},
{true, 2, []basecoin.Actor{act1, act2}},
{true, 3, []basecoin.Actor{act1, act2}},
{false, 2, []basecoin.Actor{act1, act2}},
{false, 2, []basecoin.Actor{act1, act2, act3}},
{true, 1, []basecoin.Actor{act1, act2, act3}},
}
for _, test := range testList {
tx := NewTx(test.seq, test.actors, basecoin.Tx{})
nonceTx, ok := tx.Unwrap().(Tx)
require.True(ok)
err := nonceTx.CheckIncrementSeq(ctx, store)
if test.valid {
assert.Nil(err, "%v,%v: %+v", test.seq, test.actors, err)
} else {
assert.NotNil(err, "%v,%v", test.seq, test.actors)
}
}
}