nonce testing
This commit is contained in:
parent
16b039534d
commit
6e07dbe7c3
|
@ -90,7 +90,7 @@ func doSendTx(cmd *cobra.Command, args []string) error {
|
||||||
if seq < 0 {
|
if seq < 0 {
|
||||||
return fmt.Errorf("sequence must be greater than 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)
|
// Note: this is single sig (no multi sig yet)
|
||||||
stx := auth.NewSig(tx)
|
stx := auth.NewSig(tx)
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errDecoding = fmt.Errorf("Error decoding input")
|
errDecoding = fmt.Errorf("Error decoding input")
|
||||||
errNoAccount = fmt.Errorf("No such account")
|
|
||||||
errUnauthorized = fmt.Errorf("Unauthorized")
|
errUnauthorized = fmt.Errorf("Unauthorized")
|
||||||
errInvalidSignature = fmt.Errorf("Invalid Signature")
|
errInvalidSignature = fmt.Errorf("Invalid Signature")
|
||||||
errTooLarge = fmt.Errorf("Input size too large")
|
errTooLarge = fmt.Errorf("Input size too large")
|
||||||
|
@ -139,17 +138,13 @@ func IsNoChainErr(err error) bool {
|
||||||
func ErrNoNonce() TMError {
|
func ErrNoNonce() TMError {
|
||||||
return WithCode(errNoNonce, unauthorized)
|
return WithCode(errNoNonce, unauthorized)
|
||||||
}
|
}
|
||||||
func ErrBadNonce() TMError {
|
func ErrBadNonce(got, expected uint32) TMError {
|
||||||
return WithCode(errBadNonce, unauthorized)
|
return WithCode(fmt.Errorf("Bad nonce seqence, got %d, expected %d", got, expected), unauthorized)
|
||||||
}
|
}
|
||||||
func ErrNotMember() TMError {
|
func ErrNotMember() TMError {
|
||||||
return WithCode(errBadNonce, unauthorized)
|
return WithCode(errBadNonce, unauthorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ErrNoAccount() TMError {
|
|
||||||
return WithCode(errNoAccount, unknownAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ErrWrongChain(chain string) TMError {
|
func ErrWrongChain(chain string) TMError {
|
||||||
msg := errors.Wrap(errWrongChain, chain)
|
msg := errors.Wrap(errWrongChain, chain)
|
||||||
return WithCode(msg, unauthorized)
|
return WithCode(msg, unauthorized)
|
||||||
|
|
|
@ -10,10 +10,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func getSeq(store state.KVStore, key []byte) (seq uint32, err error) {
|
func getSeq(store state.KVStore, key []byte) (seq uint32, err error) {
|
||||||
// fmt.Printf("load: %X\n", key)
|
|
||||||
data := store.Get(key)
|
data := store.Get(key)
|
||||||
if len(data) == 0 {
|
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)
|
err = wire.ReadBinaryBytes(data, &seq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -20,31 +20,24 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
basecoin.TxMapper.RegisterImplementation(&Tx{}, TypeNonce, ByteNonce)
|
basecoin.TxMapper.RegisterImplementation(Tx{}, TypeNonce, ByteNonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tx - XXX fill in
|
// Tx - XXX fill in
|
||||||
type Tx struct {
|
type Tx struct {
|
||||||
Tx basecoin.Tx `json:p"tx"`
|
Sequence uint32 `json:"sequence"`
|
||||||
Sequence uint32
|
Signers []basecoin.Actor `json:"signers"`
|
||||||
Signers []basecoin.Actor // or simple []data.Bytes (they are only pubkeys...)
|
Tx basecoin.Tx `json:"tx"`
|
||||||
seqKey []byte //key to store the sequence number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ basecoin.TxInner = &Tx{}
|
var _ basecoin.TxInner = &Tx{}
|
||||||
|
|
||||||
// NewTx wraps the tx with a signable nonce
|
// NewTx wraps the tx with a signable nonce
|
||||||
func NewTx(tx basecoin.Tx, sequence uint32, signers []basecoin.Actor) basecoin.Tx {
|
func NewTx(sequence uint32, signers []basecoin.Actor, tx basecoin.Tx) 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)
|
|
||||||
|
|
||||||
return (Tx{
|
return (Tx{
|
||||||
Tx: tx,
|
|
||||||
Sequence: sequence,
|
Sequence: sequence,
|
||||||
Signers: signers,
|
Signers: signers,
|
||||||
seqKey: seqKey,
|
Tx: tx,
|
||||||
}).Wrap()
|
}).Wrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,13 +52,17 @@ func (n Tx) ValidateBasic() error {
|
||||||
// CheckIncrementSeq - XXX fill in
|
// CheckIncrementSeq - XXX fill in
|
||||||
func (n Tx) CheckIncrementSeq(ctx basecoin.Context, store state.KVStore) error {
|
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
|
// check the current state
|
||||||
cur, err := getSeq(store, n.seqKey)
|
cur, err := getSeq(store, seqKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if n.Sequence != cur+1 {
|
if n.Sequence != cur+1 {
|
||||||
return errors.ErrBadNonce()
|
return errors.ErrBadNonce(n.Sequence, cur+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure they all signed
|
// 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
|
//finally increment the sequence by 1
|
||||||
err = setSeq(store, n.seqKey, cur+1)
|
err = setSeq(store, seqKey, cur+1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue