arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
Add StateDB txprocessor tests using txtest generators

Add StateDB tx processor tests using tx test generators:
- update statedb/ tx processors
- add statedb tx processors tests
arnaucube root@arnaucube.com
Tue, 25 Aug 2020 19:19:02 +0200
commit

be95de18fc94f9b3f3a99c5655e888447ceb4bb7

parent

e98b511436685dbd2474bc4682d6b8cf21709a59

3 files changed, 124 insertions(+), 35 deletions(-)

jump to
M db/statedb/txprocessors.go → db/statedb/txprocessors.go

@@ -30,16 +30,15 @@ func (s *StateDB) ProcessTxs(cmpExitTree bool, l1usertxs, l1coordinatortxs []*common.L1Tx, l2txs []*common.L2Tx) (*common.ZKInputs, []*ExitInfo, error) {

var err error var exitTree *merkletree.MerkleTree exits := make(map[common.Idx]common.Account) - if cmpExitTree { - // TBD if ExitTree is only in memory or stored in disk, for the moment - // only needed in memory - exitTree, err = merkletree.NewMerkleTree(memory.NewMemoryStorage(), s.mt.MaxLevels()) - if err != nil { - return nil, nil, err - } + + // TBD if ExitTree is only in memory or stored in disk, for the moment + // only needed in memory + exitTree, err = merkletree.NewMerkleTree(memory.NewMemoryStorage(), s.mt.MaxLevels()) + if err != nil { + return nil, nil, err } - for _, tx := range l1usertxs { + for _, tx := range l1coordinatortxs { exitIdx, exitAccount, err := s.processL1Tx(exitTree, tx) if err != nil { return nil, nil, err

@@ -48,7 +47,7 @@ if exitIdx != nil && cmpExitTree {

exits[*exitIdx] = *exitAccount } } - for _, tx := range l1coordinatortxs { + for _, tx := range l1usertxs { exitIdx, exitAccount, err := s.processL1Tx(exitTree, tx) if err != nil { return nil, nil, err

@@ -108,29 +107,6 @@ // HistoryDB for the concrete BatchNum

return nil, exitInfos, nil } -// processL2Tx process the given L2Tx applying the needed updates to -// the StateDB depending on the transaction Type. -func (s *StateDB) processL2Tx(exitTree *merkletree.MerkleTree, tx *common.L2Tx) (*common.Idx, *common.Account, error) { - switch tx.Type { - case common.TxTypeTransfer: - // go to the MT account of sender and receiver, and update - // balance & nonce - err := s.applyTransfer(tx.Tx()) - if err != nil { - return nil, nil, err - } - case common.TxTypeExit: - // execute exit flow - exitAccount, err := s.applyExit(exitTree, tx.Tx()) - if err != nil { - return nil, nil, err - } - return &tx.FromIdx, exitAccount, nil - default: - } - return nil, nil, nil -} - // processL1Tx process the given L1Tx applying the needed updates to the // StateDB depending on the transaction Type. func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx) (*common.Idx, *common.Account, error) {

@@ -182,6 +158,29 @@ return &tx.FromIdx, exitAccount, nil

default: } + return nil, nil, nil +} + +// processL2Tx process the given L2Tx applying the needed updates to +// the StateDB depending on the transaction Type. +func (s *StateDB) processL2Tx(exitTree *merkletree.MerkleTree, tx *common.L2Tx) (*common.Idx, *common.Account, error) { + switch tx.Type { + case common.TxTypeTransfer: + // go to the MT account of sender and receiver, and update + // balance & nonce + err := s.applyTransfer(tx.Tx()) + if err != nil { + return nil, nil, err + } + case common.TxTypeExit: + // execute exit flow + exitAccount, err := s.applyExit(exitTree, tx.Tx()) + if err != nil { + return nil, nil, err + } + return &tx.FromIdx, exitAccount, nil + default: + } return nil, nil, nil }
A db/statedb/txprocessors_test.go

@@ -0,0 +1,93 @@

+package statedb + +import ( + "io/ioutil" + "strings" + "testing" + + "github.com/hermeznetwork/hermez-node/common" + "github.com/hermeznetwork/hermez-node/test" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestProcessTxs(t *testing.T) { + dir, err := ioutil.TempDir("", "tmpdb") + require.Nil(t, err) + + sdb, err := NewStateDB(dir, true, 32) + assert.Nil(t, err) + + // generate test transactions from test.SetTest0 code + parser := test.NewParser(strings.NewReader(test.SetTest0)) + instructions, err := parser.Parse() + assert.Nil(t, err) + + l1Txs, coordinatorL1Txs, poolL2Txs := test.GenerateTestTxs(t, instructions) + assert.Equal(t, 29, len(l1Txs[0])) + assert.Equal(t, 0, len(coordinatorL1Txs[0])) + assert.Equal(t, 21, len(poolL2Txs[0])) + + // iterate for each batch + for i := 0; i < len(l1Txs); i++ { + l2Txs := common.PoolL2TxsToL2Txs(poolL2Txs[i]) + + _, _, err := sdb.ProcessTxs(true, l1Txs[i], coordinatorL1Txs[i], l2Txs) + require.Nil(t, err) + } + + acc, err := sdb.GetAccount(common.Idx(1)) + assert.Nil(t, err) + assert.Equal(t, "23", acc.Balance.String()) +} + +func TestProcessTxsBatchByBatch(t *testing.T) { + dir, err := ioutil.TempDir("", "tmpdb") + require.Nil(t, err) + + sdb, err := NewStateDB(dir, true, 32) + assert.Nil(t, err) + + // generate test transactions from test.SetTest0 code + parser := test.NewParser(strings.NewReader(test.SetTest0)) + instructions, err := parser.Parse() + assert.Nil(t, err) + + l1Txs, coordinatorL1Txs, poolL2Txs := test.GenerateTestTxs(t, instructions) + assert.Equal(t, 29, len(l1Txs[0])) + assert.Equal(t, 0, len(coordinatorL1Txs[0])) + assert.Equal(t, 21, len(poolL2Txs[0])) + assert.Equal(t, 5, len(l1Txs[1])) + assert.Equal(t, 1, len(coordinatorL1Txs[1])) + assert.Equal(t, 55, len(poolL2Txs[1])) + assert.Equal(t, 10, len(l1Txs[2])) + assert.Equal(t, 0, len(coordinatorL1Txs[2])) + assert.Equal(t, 7, len(poolL2Txs[2])) + + // use first batch + l2txs := common.PoolL2TxsToL2Txs(poolL2Txs[0]) + _, exitInfos, err := sdb.ProcessTxs(true, l1Txs[0], coordinatorL1Txs[0], l2txs) + require.Nil(t, err) + assert.Equal(t, 0, len(exitInfos)) + acc, err := sdb.GetAccount(common.Idx(1)) + assert.Nil(t, err) + assert.Equal(t, "28", acc.Balance.String()) + + // use second batch + l2txs = common.PoolL2TxsToL2Txs(poolL2Txs[1]) + _, exitInfos, err = sdb.ProcessTxs(true, l1Txs[1], coordinatorL1Txs[1], l2txs) + require.Nil(t, err) + assert.Equal(t, 5, len(exitInfos)) + acc, err = sdb.GetAccount(common.Idx(1)) + assert.Nil(t, err) + assert.Equal(t, "48", acc.Balance.String()) + + // use third batch + l2txs = common.PoolL2TxsToL2Txs(poolL2Txs[2]) + _, exitInfos, err = sdb.ProcessTxs(true, l1Txs[2], coordinatorL1Txs[2], l2txs) + require.Nil(t, err) + assert.Equal(t, 1, len(exitInfos)) + acc, err = sdb.GetAccount(common.Idx(1)) + assert.Nil(t, err) + assert.Equal(t, "23", acc.Balance.String()) +}
M test/sets.go → test/sets.go

@@ -164,6 +164,3 @@ H-O (1): 5 1

I-H (1): 5 1 A (1) E: 5 ` - -// cases to add: -// - L2 tx from B to A, when B still does not have tokens, which will receive from C