From a8ac35059a3a507128152140ca84a7738fdbfbda Mon Sep 17 00:00:00 2001 From: Eduard S Date: Mon, 21 Dec 2020 17:36:21 +0100 Subject: [PATCH] Test purger, fix some nonces - Test all the purger functions - Fix nonces set by til (previously til started with nonce 1 for pool l2txs, but the correct implementation is to start with nonce 0) - Rename L2DB.CheckNonces to L2DB.invalidateOldNoncesQuery - Rename L2DB.checkNoncesQuery to L2DB.InvalidateOldNonces Related https://github.com/hermeznetwork/hermez-node/issues/392 (Fix checkNoncesQuery) Resolve https://github.com/hermeznetwork/hermez-node/issues/396 --- coordinator/coordinator.go | 5 +- coordinator/coordinator_test.go | 4 +- coordinator/purger.go | 20 +-- coordinator/purger_test.go | 286 +++++++++++++++++++++++++++++++- db/l2db/l2db.go | 14 +- db/l2db/l2db_test.go | 29 ++-- test/til/txs.go | 4 +- test/til/txs_test.go | 12 +- 8 files changed, 325 insertions(+), 49 deletions(-) diff --git a/coordinator/coordinator.go b/coordinator/coordinator.go index bf0b0d9..52852fd 100644 --- a/coordinator/coordinator.go +++ b/coordinator/coordinator.go @@ -245,7 +245,7 @@ func (c *Coordinator) syncStats(ctx context.Context, stats *synchronizer.Stats) if c.pipeline == nil { // Mark invalid in Pool due to forged L2Txs // for _, batch := range batches { - // if err := poolMarkInvalidOldNoncesFromL2Txs(c.l2DB, + // if err := c.l2DB.InvalidateOldNonces( // idxsNonceFromL2Txs(batch.L2Txs), batch.Batch.BatchNum); err != nil { // return err // } @@ -850,8 +850,7 @@ func (p *Pipeline) forgeBatch(ctx context.Context, batchNum common.BatchNum, sel // the poolL2Txs selected. Will mark as invalid the txs that have a // (fromIdx, nonce) which already appears in the selected txs (includes // all the nonces smaller than the current one) - err = poolMarkInvalidOldNoncesFromL2Txs(p.l2DB, idxsNonceFromPoolL2Txs(poolL2Txs), - batchInfo.BatchNum) + err = p.l2DB.InvalidateOldNonces(idxsNonceFromPoolL2Txs(poolL2Txs), batchInfo.BatchNum) if err != nil { return nil, tracerr.Wrap(err) } diff --git a/coordinator/coordinator_test.go b/coordinator/coordinator_test.go index 2a12b95..3207ae0 100644 --- a/coordinator/coordinator_test.go +++ b/coordinator/coordinator_test.go @@ -92,13 +92,11 @@ var nLevels uint32 = 32 //nolint:deadcode,unused var maxFeeTxs uint32 = 64 //nolint:deadcode,varcheck func newTestModules(t *testing.T) modules { - nLevels := 32 - var err error syncDBPath, err = ioutil.TempDir("", "tmpSyncDB") require.NoError(t, err) deleteme = append(deleteme, syncDBPath) - syncStateDB, err := statedb.NewStateDB(syncDBPath, statedb.TypeSynchronizer, nLevels) + syncStateDB, err := statedb.NewStateDB(syncDBPath, statedb.TypeSynchronizer, 48) assert.NoError(t, err) pass := os.Getenv("POSTGRES_PASS") diff --git a/coordinator/purger.go b/coordinator/purger.go index 852060f..4f7379e 100644 --- a/coordinator/purger.go +++ b/coordinator/purger.go @@ -35,10 +35,10 @@ type Purger struct { // CanPurge returns true if it's a good time to purge according to the // configuration func (p *Purger) CanPurge(blockNum, batchNum int64) bool { - if blockNum > p.lastPurgeBlock+p.cfg.PurgeBlockDelay { + if blockNum >= p.lastPurgeBlock+p.cfg.PurgeBlockDelay { return true } - if batchNum > p.lastPurgeBatch+p.cfg.PurgeBatchDelay { + if batchNum >= p.lastPurgeBatch+p.cfg.PurgeBatchDelay { return true } return false @@ -47,10 +47,10 @@ func (p *Purger) CanPurge(blockNum, batchNum int64) bool { // CanInvalidate returns true if it's a good time to invalidate according to // the configuration func (p *Purger) CanInvalidate(blockNum, batchNum int64) bool { - if blockNum > p.lastInvalidateBlock+p.cfg.InvalidateBlockDelay { + if blockNum >= p.lastInvalidateBlock+p.cfg.InvalidateBlockDelay { return true } - if batchNum > p.lastInvalidateBatch+p.cfg.InvalidateBatchDelay { + if batchNum >= p.lastInvalidateBatch+p.cfg.InvalidateBatchDelay { return true } return false @@ -114,15 +114,6 @@ func idxsNonceFromPoolL2Txs(txs []common.PoolL2Tx) []common.IdxNonce { return idxsNonce } -// poolMarkInvalidOldNoncesFromL2Txs marks as invalid the txs in the pool that -// contain nonces equal or older to the highest nonce used in a forged l2Tx for -// the -// corresponding sender account -func poolMarkInvalidOldNoncesFromL2Txs(l2DB *l2db.L2DB, - idxsNonce []common.IdxNonce, batchNum common.BatchNum) error { - return l2DB.CheckNonces(idxsNonce, batchNum) -} - // poolMarkInvalidOldNonces marks as invalid txs in the pool that contain // nonces equal or older to the nonce of the corresponding sender account func poolMarkInvalidOldNonces(l2DB *l2db.L2DB, stateDB *statedb.LocalStateDB, @@ -147,9 +138,8 @@ func poolMarkInvalidOldNonces(l2DB *l2db.L2DB, stateDB *statedb.LocalStateDB, return tracerr.Wrap(fmt.Errorf("unexpected stateDB error with idx %v: %w", idx, err)) } } - fmt.Printf("DBG acc: %#v\n", acc) idxsNonce[i].Idx = idx idxsNonce[i].Nonce = acc.Nonce } - return l2DB.CheckNonces(idxsNonce, batchNum) + return l2DB.InvalidateOldNonces(idxsNonce, batchNum) } diff --git a/coordinator/purger_test.go b/coordinator/purger_test.go index 6849688..c2b88ad 100644 --- a/coordinator/purger_test.go +++ b/coordinator/purger_test.go @@ -1,3 +1,287 @@ package coordinator -// TODO: Test purger functions +import ( + "io/ioutil" + "os" + "testing" + "time" + + "github.com/hermeznetwork/hermez-node/common" + dbUtils "github.com/hermeznetwork/hermez-node/db" + "github.com/hermeznetwork/hermez-node/db/l2db" + "github.com/hermeznetwork/hermez-node/db/statedb" + "github.com/hermeznetwork/hermez-node/test" + "github.com/hermeznetwork/hermez-node/test/til" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func newL2DB(t *testing.T) *l2db.L2DB { + pass := os.Getenv("POSTGRES_PASS") + db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez") + require.NoError(t, err) + test.WipeDB(db) + return l2db.NewL2DB(db, 10, 100, 24*time.Hour) +} + +func newStateDB(t *testing.T) *statedb.LocalStateDB { + syncDBPath, err := ioutil.TempDir("", "tmpSyncDB") + require.NoError(t, err) + deleteme = append(deleteme, syncDBPath) + syncStateDB, err := statedb.NewStateDB(syncDBPath, statedb.TypeSynchronizer, 48) + assert.NoError(t, err) + stateDBPath, err := ioutil.TempDir("", "tmpStateDB") + require.NoError(t, err) + deleteme = append(deleteme, stateDBPath) + stateDB, err := statedb.NewLocalStateDB(stateDBPath, syncStateDB, statedb.TypeTxSelector, 0) + require.NoError(t, err) + return stateDB +} + +func TestCanPurgeCanInvalidate(t *testing.T) { + cfg := PurgerCfg{ + PurgeBatchDelay: 2, + PurgeBlockDelay: 6, + InvalidateBatchDelay: 4, + InvalidateBlockDelay: 8, + } + p := Purger{ + cfg: cfg, + } + startBlockNum := int64(1000) + startBatchNum := int64(10) + blockNum := startBlockNum + batchNum := startBatchNum + + assert.True(t, p.CanPurge(blockNum, batchNum)) + p.lastPurgeBlock = startBlockNum + p.lastPurgeBatch = startBatchNum + assert.False(t, p.CanPurge(blockNum, batchNum)) + + blockNum = startBlockNum + cfg.PurgeBlockDelay - 1 + batchNum = startBatchNum + cfg.PurgeBatchDelay - 1 + assert.False(t, p.CanPurge(blockNum, batchNum)) + blockNum = startBlockNum + cfg.PurgeBlockDelay - 1 + batchNum = startBatchNum + cfg.PurgeBatchDelay + assert.True(t, p.CanPurge(blockNum, batchNum)) + blockNum = startBlockNum + cfg.PurgeBlockDelay + batchNum = startBatchNum + cfg.PurgeBatchDelay - 1 + assert.True(t, p.CanPurge(blockNum, batchNum)) + + assert.True(t, p.CanInvalidate(blockNum, batchNum)) + p.lastInvalidateBlock = startBlockNum + p.lastInvalidateBatch = startBatchNum + assert.False(t, p.CanInvalidate(blockNum, batchNum)) + + blockNum = startBlockNum + cfg.InvalidateBlockDelay - 1 + batchNum = startBatchNum + cfg.InvalidateBatchDelay - 1 + assert.False(t, p.CanInvalidate(blockNum, batchNum)) + blockNum = startBlockNum + cfg.InvalidateBlockDelay - 1 + batchNum = startBatchNum + cfg.InvalidateBatchDelay + assert.True(t, p.CanInvalidate(blockNum, batchNum)) + blockNum = startBlockNum + cfg.InvalidateBlockDelay + batchNum = startBatchNum + cfg.InvalidateBatchDelay - 1 + assert.True(t, p.CanInvalidate(blockNum, batchNum)) +} + +func TestPurgeMaybeInvalidateMaybe(t *testing.T) { + cfg := PurgerCfg{ + PurgeBatchDelay: 2, + PurgeBlockDelay: 6, + InvalidateBatchDelay: 4, + InvalidateBlockDelay: 8, + } + p := Purger{ + cfg: cfg, + } + l2DB := newL2DB(t) + stateDB := newStateDB(t) + + startBlockNum := int64(1000) + startBatchNum := int64(10) + + p.lastPurgeBlock = startBlockNum + p.lastPurgeBatch = startBatchNum + + blockNum := startBlockNum + cfg.PurgeBlockDelay - 1 + batchNum := startBatchNum + cfg.PurgeBatchDelay - 1 + ok, err := p.PurgeMaybe(l2DB, blockNum, batchNum) + require.NoError(t, err) + assert.False(t, ok) + // At this point the purger will purge. The second time it doesn't + // because it the first time it has updates the last time it did. + blockNum = startBlockNum + cfg.PurgeBlockDelay - 1 + batchNum = startBatchNum + cfg.PurgeBatchDelay + ok, err = p.PurgeMaybe(l2DB, blockNum, batchNum) + require.NoError(t, err) + assert.True(t, ok) + ok, err = p.PurgeMaybe(l2DB, blockNum, batchNum) + require.NoError(t, err) + assert.False(t, ok) + + p.lastInvalidateBlock = startBlockNum + p.lastInvalidateBatch = startBatchNum + + blockNum = startBlockNum + cfg.InvalidateBlockDelay - 1 + batchNum = startBatchNum + cfg.InvalidateBatchDelay - 1 + ok, err = p.InvalidateMaybe(l2DB, stateDB, blockNum, batchNum) + require.NoError(t, err) + assert.False(t, ok) + // At this point the purger will invaidate. The second time it doesn't + // because it the first time it has updates the last time it did. + blockNum = startBlockNum + cfg.InvalidateBlockDelay - 1 + batchNum = startBatchNum + cfg.InvalidateBatchDelay + ok, err = p.InvalidateMaybe(l2DB, stateDB, blockNum, batchNum) + require.NoError(t, err) + assert.True(t, ok) + ok, err = p.InvalidateMaybe(l2DB, stateDB, blockNum, batchNum) + require.NoError(t, err) + assert.False(t, ok) +} + +func TestIdxsNonce(t *testing.T) { + inputIdxsNonce := []common.IdxNonce{ + {Idx: 256, Nonce: 1}, + {Idx: 256, Nonce: 2}, + {Idx: 257, Nonce: 3}, + {Idx: 258, Nonce: 5}, + {Idx: 258, Nonce: 2}, + } + expectedIdxsNonce := map[common.Idx]common.Nonce{ + common.Idx(256): common.Nonce(2), + common.Idx(257): common.Nonce(3), + common.Idx(258): common.Nonce(5), + } + + l2txs := make([]common.L2Tx, len(inputIdxsNonce)) + for i, idxNonce := range inputIdxsNonce { + l2txs[i].FromIdx = idxNonce.Idx + l2txs[i].Nonce = idxNonce.Nonce + } + idxsNonce := idxsNonceFromL2Txs(l2txs) + assert.Equal(t, len(expectedIdxsNonce), len(idxsNonce)) + for _, idxNonce := range idxsNonce { + nonce := expectedIdxsNonce[idxNonce.Idx] + assert.Equal(t, nonce, idxNonce.Nonce) + } + + pooll2txs := make([]common.PoolL2Tx, len(inputIdxsNonce)) + for i, idxNonce := range inputIdxsNonce { + pooll2txs[i].FromIdx = idxNonce.Idx + pooll2txs[i].Nonce = idxNonce.Nonce + } + idxsNonce = idxsNonceFromPoolL2Txs(pooll2txs) + assert.Equal(t, len(expectedIdxsNonce), len(idxsNonce)) + for _, idxNonce := range idxsNonce { + nonce := expectedIdxsNonce[idxNonce.Idx] + assert.Equal(t, nonce, idxNonce.Nonce) + } +} + +func TestPoolMarkInvalidOldNonces(t *testing.T) { + l2DB := newL2DB(t) + stateDB := newStateDB(t) + + set0 := ` + Type: Blockchain + + CreateAccountDeposit(0) A: 1000 // Idx=256 + CreateAccountDeposit(0) B: 1000 // Idx=257 + CreateAccountDeposit(0) C: 1000 // Idx=258 + CreateAccountDeposit(0) D: 1000 // Idx=259 + + > batchL1 + > batchL1 + > block + ` + tc := til.NewContext(common.RollupConstMaxL1UserTx) + blocks, err := tc.GenerateBlocks(set0) + require.NoError(t, err) + tilCfgExtra := til.ConfigExtra{ + CoordUser: "A", + } + // Call FillBlocksExtra to fill `Batch.CreatedAccounts` + err = tc.FillBlocksExtra(blocks, &tilCfgExtra) + require.NoError(t, err) + require.Equal(t, 4, len(blocks[0].Rollup.Batches[1].CreatedAccounts)) // sanity check + + for _, acc := range blocks[0].Rollup.Batches[1].CreatedAccounts { + _, err := stateDB.CreateAccount(acc.Idx, &acc) //nolint:gosec + require.NoError(t, err) + } + + setPool0 := ` + Type: PoolL2 + PoolTransfer(0) A-B: 10 (1) + PoolTransfer(0) A-C: 10 (1) + PoolTransfer(0) A-D: 10 (1) + PoolTransfer(0) B-A: 10 (1) + PoolTransfer(0) B-C: 10 (1) + PoolTransfer(0) C-A: 10 (1) + ` + // We expect the following nonces + nonces0 := map[string]int64{"A": 3, "B": 2, "C": 1, "D": 0} + l2txs0, err := tc.GeneratePoolL2Txs(setPool0) + assert.Nil(t, err) + assert.Equal(t, 6, len(l2txs0)) + for _, tx := range l2txs0 { + require.NoError(t, l2DB.AddTxTest(&tx)) //nolint:gosec + } + + // Update the accounts in the StateDB, making the txs in the setPool0 + // invalid + for name, user := range tc.Users { + for _, _acc := range user.Accounts { + require.Equal(t, common.Nonce(nonces0[name]), _acc.Nonce) // sanity check + acc, err := stateDB.GetAccount(_acc.Idx) + require.NoError(t, err) + require.Equal(t, common.Nonce(0), acc.Nonce) // sanity check + acc.Nonce = _acc.Nonce + _, err = stateDB.UpdateAccount(acc.Idx, acc) + require.NoError(t, err) + } + } + + setPool1 := ` + Type: PoolL2 + PoolTransfer(0) A-B: 10 (1) + PoolTransfer(0) A-C: 10 (1) + PoolTransfer(0) A-D: 10 (1) + PoolTransfer(0) B-A: 10 (1) + PoolTransfer(0) B-C: 10 (1) + PoolTransfer(0) C-A: 10 (1) + ` + // We expect the following nonces + nonces1 := map[string]int64{"A": 6, "B": 4, "C": 2, "D": 0} + l2txs1, err := tc.GeneratePoolL2Txs(setPool1) + require.NoError(t, err) + assert.Equal(t, 6, len(l2txs1)) + for _, tx := range l2txs1 { + require.NoError(t, l2DB.AddTxTest(&tx)) //nolint:gosec + } + + for name, user := range tc.Users { + for _, _acc := range user.Accounts { + require.Equal(t, common.Nonce(nonces1[name]), _acc.Nonce) // sanity check + acc, err := stateDB.GetAccount(_acc.Idx) + require.NoError(t, err) + require.Equal(t, common.Nonce(nonces0[name]), acc.Nonce) // sanity check + } + } + + // Now we should have 12 txs in the pool, all marked as pending. Since + // we updated the stateDB with the nonces after setPool0, the first 6 + // txs will be marked as invalid + + pendingTxs, err := l2DB.GetPendingTxs() + require.NoError(t, err) + assert.Equal(t, 12, len(pendingTxs)) + + batchNum := common.BatchNum(1) + err = poolMarkInvalidOldNonces(l2DB, stateDB, batchNum) + require.NoError(t, err) + + pendingTxs, err = l2DB.GetPendingTxs() + require.NoError(t, err) + assert.Equal(t, 6, len(pendingTxs)) +} diff --git a/db/l2db/l2db.go b/db/l2db/l2db.go index 0c53635..20d0785 100644 --- a/db/l2db/l2db.go +++ b/db/l2db/l2db.go @@ -268,7 +268,7 @@ func (l2db *L2DB) GetPendingUniqueFromIdxs() ([]common.Idx, error) { return idxs, nil } -var checkNoncesQuery = fmt.Sprintf(` +var invalidateOldNoncesQuery = fmt.Sprintf(` UPDATE tx_pool SET state = '%s', batch_num = %%d @@ -276,20 +276,22 @@ var checkNoncesQuery = fmt.Sprintf(` (NULL::::BIGINT, NULL::::BIGINT), (:idx, :nonce) ) as updated_acc (idx, nonce) - WHERE tx_pool.from_idx = updated_acc.idx AND tx_pool.nonce <= updated_acc.nonce; - `, common.PoolL2TxStateInvalid) + WHERE tx_pool.state = '%s' AND + tx_pool.from_idx = updated_acc.idx AND + tx_pool.nonce < updated_acc.nonce; + `, common.PoolL2TxStateInvalid, common.PoolL2TxStatePending) -// CheckNonces invalidate txs with nonces that are smaller or equal than their +// InvalidateOldNonces invalidate txs with nonces that are smaller or equal than their // respective accounts nonces. The state of the affected txs will be changed // from Pending to Invalid -func (l2db *L2DB) CheckNonces(updatedAccounts []common.IdxNonce, batchNum common.BatchNum) (err error) { +func (l2db *L2DB) InvalidateOldNonces(updatedAccounts []common.IdxNonce, batchNum common.BatchNum) (err error) { if len(updatedAccounts) == 0 { return nil } // Fill the batch_num in the query with Sprintf because we are using a // named query which works with slices, and doens't handle an extra // individual argument. - query := fmt.Sprintf(checkNoncesQuery, batchNum) + query := fmt.Sprintf(invalidateOldNoncesQuery, batchNum) if _, err := sqlx.NamedExec(l2db.db, query, updatedAccounts); err != nil { return tracerr.Wrap(err) } diff --git a/db/l2db/l2db_test.go b/db/l2db/l2db_test.go index 7c49935..1cb57ec 100644 --- a/db/l2db/l2db_test.go +++ b/db/l2db/l2db_test.go @@ -16,6 +16,7 @@ import ( "github.com/hermeznetwork/hermez-node/test/til" "github.com/hermeznetwork/tracerr" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var l2DB *L2DB @@ -217,7 +218,7 @@ func TestGetPending(t *testing.T) { func TestStartForging(t *testing.T) { // Generate txs - const fakeBatchNum common.BatchNum = 33 + var fakeBatchNum common.BatchNum = 33 err := prepareHistoryDB(historyDB) if err != nil { log.Error("Error prepare historyDB", err) @@ -243,13 +244,13 @@ func TestStartForging(t *testing.T) { fetchedTx, err := l2DB.GetTxAPI(id) assert.NoError(t, err) assert.Equal(t, common.PoolL2TxStateForging, fetchedTx.State) - assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum) + assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum) } } func TestDoneForging(t *testing.T) { // Generate txs - const fakeBatchNum common.BatchNum = 33 + var fakeBatchNum common.BatchNum = 33 err := prepareHistoryDB(historyDB) if err != nil { log.Error("Error prepare historyDB", err) @@ -288,13 +289,13 @@ func TestDoneForging(t *testing.T) { fetchedTx, err := l2DB.GetTxAPI(id) assert.NoError(t, err) assert.Equal(t, common.PoolL2TxStateForged, fetchedTx.State) - assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum) + assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum) } } func TestInvalidate(t *testing.T) { // Generate txs - const fakeBatchNum common.BatchNum = 33 + var fakeBatchNum common.BatchNum = 33 err := prepareHistoryDB(historyDB) if err != nil { log.Error("Error prepare historyDB", err) @@ -320,13 +321,13 @@ func TestInvalidate(t *testing.T) { fetchedTx, err := l2DB.GetTxAPI(id) assert.NoError(t, err) assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State) - assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum) + assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum) } } -func TestCheckNonces(t *testing.T) { +func TestInvalidateOldNonces(t *testing.T) { // Generate txs - const fakeBatchNum common.BatchNum = 33 + var fakeBatchNum common.BatchNum = 33 err := prepareHistoryDB(historyDB) if err != nil { log.Error("Error prepare historyDB", err) @@ -335,7 +336,7 @@ func TestCheckNonces(t *testing.T) { assert.NoError(t, err) // Update Accounts currentNonce var updateAccounts []common.IdxNonce - const currentNonce = common.Nonce(1) + var currentNonce = common.Nonce(1) for i := range accs { updateAccounts = append(updateAccounts, common.IdxNonce{ Idx: accs[i].Idx, @@ -345,21 +346,23 @@ func TestCheckNonces(t *testing.T) { // Add txs to DB var invalidTxIDs []common.TxID for i := range poolL2Txs { - if poolL2Txs[i].Nonce <= currentNonce { + if poolL2Txs[i].Nonce < currentNonce { invalidTxIDs = append(invalidTxIDs, poolL2Txs[i].TxID) } err := l2DB.AddTxTest(&poolL2Txs[i]) assert.NoError(t, err) } + // sanity check + require.Greater(t, len(invalidTxIDs), 0) - err = l2DB.CheckNonces(updateAccounts, fakeBatchNum) + err = l2DB.InvalidateOldNonces(updateAccounts, fakeBatchNum) assert.NoError(t, err) // Fetch txs and check that they've been updated correctly for _, id := range invalidTxIDs { fetchedTx, err := l2DB.GetTxAPI(id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State) - assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum) + assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum) } } diff --git a/test/til/txs.go b/test/til/txs.go index 53a0052..9214f91 100644 --- a/test/til/txs.go +++ b/test/til/txs.go @@ -597,7 +597,6 @@ func (tc *Context) generatePoolL2Txs() ([]common.PoolL2Tx, error) { return nil, tracerr.Wrap(fmt.Errorf("Line %d: %s", inst.LineNum, err.Error())) } } - tc.Users[inst.From].Accounts[inst.TokenID].Nonce++ // if account of receiver does not exist, don't use // ToIdx, and use only ToEthAddr & ToBJJ tx := common.PoolL2Tx{ @@ -612,6 +611,7 @@ func (tc *Context) generatePoolL2Txs() ([]common.PoolL2Tx, error) { RqToBJJ: common.EmptyBJJComp, Type: inst.Typ, } + tc.Users[inst.From].Accounts[inst.TokenID].Nonce++ if tx.Type == common.TxTypeTransfer { tx.ToIdx = tc.Users[inst.To].Accounts[inst.TokenID].Idx tx.ToEthAddr = tc.Users[inst.To].Addr @@ -639,7 +639,6 @@ func (tc *Context) generatePoolL2Txs() ([]common.PoolL2Tx, error) { txs = append(txs, tx) case common.TxTypeExit: - tc.Users[inst.From].Accounts[inst.TokenID].Nonce++ tx := common.PoolL2Tx{ FromIdx: tc.Users[inst.From].Accounts[inst.TokenID].Idx, ToIdx: common.Idx(1), // as is an Exit @@ -650,6 +649,7 @@ func (tc *Context) generatePoolL2Txs() ([]common.PoolL2Tx, error) { State: common.PoolL2TxStatePending, Type: common.TxTypeExit, } + tc.Users[inst.From].Accounts[inst.TokenID].Nonce++ nTx, err := common.NewPoolL2Tx(&tx) if err != nil { return nil, tracerr.Wrap(fmt.Errorf("Line %d: %s", inst.LineNum, err.Error())) diff --git a/test/til/txs_test.go b/test/til/txs_test.go index 8eda471..00f3888 100644 --- a/test/til/txs_test.go +++ b/test/til/txs_test.go @@ -218,9 +218,9 @@ func TestGeneratePoolL2Txs(t *testing.T) { assert.Equal(t, tc.Users["User1"].Addr.Hex(), poolL2Txs[5].ToEthAddr.Hex()) assert.Equal(t, tc.Users["User1"].BJJ.Public().String(), poolL2Txs[5].ToBJJ.String()) - assert.Equal(t, common.Nonce(1), poolL2Txs[0].Nonce) - assert.Equal(t, common.Nonce(2), poolL2Txs[3].Nonce) - assert.Equal(t, common.Nonce(3), poolL2Txs[8].Nonce) + assert.Equal(t, common.Nonce(0), poolL2Txs[0].Nonce) + assert.Equal(t, common.Nonce(1), poolL2Txs[3].Nonce) + assert.Equal(t, common.Nonce(2), poolL2Txs[8].Nonce) assert.Equal(t, tc.Users["B"].Addr.Hex(), poolL2Txs[9].ToEthAddr.Hex()) assert.Equal(t, common.EmptyBJJComp, poolL2Txs[9].ToBJJ) @@ -238,9 +238,9 @@ func TestGeneratePoolL2Txs(t *testing.T) { ` poolL2Txs, err = tc.GeneratePoolL2Txs(set) require.NoError(t, err) - assert.Equal(t, common.Nonce(6), poolL2Txs[0].Nonce) - assert.Equal(t, common.Nonce(2), poolL2Txs[1].Nonce) - assert.Equal(t, common.Nonce(7), poolL2Txs[2].Nonce) + assert.Equal(t, common.Nonce(5), poolL2Txs[0].Nonce) + assert.Equal(t, common.Nonce(1), poolL2Txs[1].Nonce) + assert.Equal(t, common.Nonce(6), poolL2Txs[2].Nonce) // check that a PoolL2Tx can be done to a non existing ToIdx set = `