From f65a6047b4b61bc0f65a0fab25e2b6c7f2785ce3 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Thu, 29 Oct 2020 18:19:54 +0100 Subject: [PATCH] Add Til set w minimum flow, small fixes at StateDB --- db/statedb/statedb.go | 3 + db/statedb/txprocessors.go | 9 ++- db/statedb/txprocessors_test.go | 137 +++++++++++++++++++++++++++++++- db/statedb/utils.go | 12 +-- db/statedb/utils_test.go | 4 +- test/til/sets.go | 128 +++++++++++++++++++++++++++++ test/til/sets_test.go | 11 ++- test/til/txs.go | 42 ++++++---- 8 files changed, 319 insertions(+), 27 deletions(-) diff --git a/db/statedb/statedb.go b/db/statedb/statedb.go index f0ce3dd..9958000 100644 --- a/db/statedb/statedb.go +++ b/db/statedb/statedb.go @@ -28,6 +28,9 @@ var ( // ErrToIdxNotFound is used when trying to get the ToIdx from ToEthAddr // or ToEthAddr&ToBJJ ErrToIdxNotFound = errors.New("ToIdx can not be found") + // ErrGetIdxNoCase is used when trying to get the Idx from EthAddr & + // BJJ with not compatible combination + ErrGetIdxNoCase = errors.New("Can not get Idx due unexpected combination of ethereum Address & BabyJubJub PublicKey") // KeyCurrentBatch is used as key in the db to store the current BatchNum KeyCurrentBatch = []byte("k:currentbatch") diff --git a/db/statedb/txprocessors.go b/db/statedb/txprocessors.go index 4e91a5a..ff9a3be 100644 --- a/db/statedb/txprocessors.go +++ b/db/statedb/txprocessors.go @@ -264,7 +264,7 @@ func (s *StateDB) getTokenIDsBigInt(l1usertxs, l1coordinatortxs []common.L1Tx, l // AccountsDB (in the StateDB) acc, err := s.GetAccount(l2txs[i].FromIdx) if err != nil { - log.Errorf("ToIdx %d not found: %s", l2txs[i].ToIdx, err.Error()) + log.Errorf("could not get account to determine TokenID of L2Tx: FromIdx %d not found: %s", l2txs[i].FromIdx, err.Error()) return nil, err } tokenIDs[acc.TokenID] = true @@ -397,7 +397,6 @@ func (s *StateDB) processL2Tx(coordIdxsMap map[common.TokenID]common.Idx, collec // case when tx.Type== common.TxTypeTransferToEthAddr or common.TxTypeTransferToBJJ tx.AuxToIdx, err = s.GetIdxByEthAddrBJJ(tx.ToEthAddr, tx.ToBJJ, tx.TokenID) if err != nil { - log.Error(err) return nil, nil, false, err } } @@ -607,6 +606,7 @@ func (s *StateDB) applyTransfer(coordIdxsMap map[common.TokenID]common.Idx, coll fee := common.CalcFeeAmount(tx.Amount, *tx.Fee) feeAndAmount := new(big.Int).Add(tx.Amount, fee) accSender.Balance = new(big.Int).Sub(accSender.Balance, feeAndAmount) + // send the fee to the Idx of the Coordinator for the TokenID accCoord, err := s.GetAccount(coordIdxsMap[accSender.TokenID]) if err != nil { @@ -623,6 +623,8 @@ func (s *StateDB) applyTransfer(coordIdxsMap map[common.TokenID]common.Idx, coll collected.Add(collected, fee) } } + } else { + accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount) } // add amount-feeAmount to the receiver @@ -676,7 +678,6 @@ func (s *StateDB) applyCreateAccountDepositTransfer(tx *common.L1Tx) error { PublicKey: tx.FromBJJ, EthAddr: tx.FromEthAddr, } - accSender.Balance = new(big.Int).Add(accSender.Balance, tx.LoadAmount) accReceiver, err := s.GetAccount(tx.ToIdx) if err != nil { return err @@ -762,6 +763,8 @@ func (s *StateDB) applyExit(coordIdxsMap map[common.TokenID]common.Idx, collecte collected.Add(collected, fee) } } + } else { + acc.Balance = new(big.Int).Sub(acc.Balance, tx.Amount) } p, err := s.UpdateAccount(tx.FromIdx, acc) diff --git a/db/statedb/txprocessors_test.go b/db/statedb/txprocessors_test.go index 6f66866..64c088c 100644 --- a/db/statedb/txprocessors_test.go +++ b/db/statedb/txprocessors_test.go @@ -15,6 +15,139 @@ import ( "github.com/stretchr/testify/require" ) +func checkBalance(t *testing.T, tc *til.Context, sdb *StateDB, username string, tokenid int, expected string) { + idx := tc.Users[username].Accounts[common.TokenID(tokenid)].Idx + acc, err := sdb.GetAccount(idx) + require.Nil(t, err) + assert.Equal(t, expected, acc.Balance.String()) +} + +func TestProcessTxsBalances(t *testing.T) { + dir, err := ioutil.TempDir("", "tmpdb") + require.Nil(t, err) + defer assert.Nil(t, os.RemoveAll(dir)) + + sdb, err := NewStateDB(dir, TypeSynchronizer, 32) + assert.Nil(t, err) + + // generate test transactions from test.SetBlockchain0 code + tc := til.NewContext(eth.RollupConstMaxL1UserTx) + blocks, err := tc.GenerateBlocks(til.SetBlockchainMinimumFlow0) + require.Nil(t, err) + + // Coordinator Idx where to send the fees + coordIdxs := []common.Idx{256, 257} + + log.Debug("block:0 batch:0, only L1CoordinatorTxs") + _, err = sdb.ProcessTxs(nil, nil, blocks[0].Batches[0].L1CoordinatorTxs, nil) + require.Nil(t, err) + + log.Debug("block:0 batch:1") + l1UserTxs := []common.L1Tx{} + l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Batches[1].L2Txs) + _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[1].L1CoordinatorTxs, l2Txs) + require.Nil(t, err) + + log.Debug("block:0 batch:2") + l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[2].Batch.ForgeL1TxsNum]) + l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[2].L2Txs) + _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[2].L1CoordinatorTxs, l2Txs) + require.Nil(t, err) + checkBalance(t, tc, sdb, "A", 0, "500") + + log.Debug("block:0 batch:3") + l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[3].Batch.ForgeL1TxsNum]) + l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[3].L2Txs) + _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[3].L1CoordinatorTxs, l2Txs) + require.Nil(t, err) + checkBalance(t, tc, sdb, "A", 0, "500") + checkBalance(t, tc, sdb, "A", 1, "500") + + log.Debug("block:0 batch:4") + l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[4].Batch.ForgeL1TxsNum]) + l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[4].L2Txs) + _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[4].L1CoordinatorTxs, l2Txs) + require.Nil(t, err) + checkBalance(t, tc, sdb, "A", 0, "500") + checkBalance(t, tc, sdb, "A", 1, "500") + + log.Debug("block:0 batch:5") + l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[5].Batch.ForgeL1TxsNum]) + l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[5].L2Txs) + _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[5].L1CoordinatorTxs, l2Txs) + require.Nil(t, err) + checkBalance(t, tc, sdb, "A", 0, "600") + checkBalance(t, tc, sdb, "A", 1, "500") + checkBalance(t, tc, sdb, "B", 0, "400") + + log.Debug("block:0 batch:6") + l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[6].Batch.ForgeL1TxsNum]) + l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[6].L2Txs) + _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[6].L1CoordinatorTxs, l2Txs) + require.Nil(t, err) + checkBalance(t, tc, sdb, "Coord", 0, "10") + checkBalance(t, tc, sdb, "Coord", 1, "20") + checkBalance(t, tc, sdb, "A", 0, "600") + checkBalance(t, tc, sdb, "A", 1, "280") + checkBalance(t, tc, sdb, "B", 0, "290") + checkBalance(t, tc, sdb, "B", 1, "200") + checkBalance(t, tc, sdb, "C", 0, "100") + checkBalance(t, tc, sdb, "D", 0, "800") + + log.Debug("block:0 batch:7") + l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[7].Batch.ForgeL1TxsNum]) + l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[7].L2Txs) + _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[7].L1CoordinatorTxs, l2Txs) + require.Nil(t, err) + checkBalance(t, tc, sdb, "Coord", 0, "35") + checkBalance(t, tc, sdb, "Coord", 1, "30") + checkBalance(t, tc, sdb, "A", 0, "430") + checkBalance(t, tc, sdb, "A", 1, "280") + checkBalance(t, tc, sdb, "B", 0, "390") + checkBalance(t, tc, sdb, "B", 1, "90") + checkBalance(t, tc, sdb, "C", 0, "45") + checkBalance(t, tc, sdb, "C", 1, "100") + checkBalance(t, tc, sdb, "D", 0, "800") + + log.Debug("block:1 batch:0") + l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Batches[0].Batch.ForgeL1TxsNum]) + l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Batches[0].L2Txs) + _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Batches[0].L1CoordinatorTxs, l2Txs) + require.Nil(t, err) + checkBalance(t, tc, sdb, "Coord", 0, "75") + checkBalance(t, tc, sdb, "Coord", 1, "30") + checkBalance(t, tc, sdb, "A", 0, "730") + checkBalance(t, tc, sdb, "A", 1, "280") + checkBalance(t, tc, sdb, "B", 0, "380") + checkBalance(t, tc, sdb, "B", 1, "90") + checkBalance(t, tc, sdb, "C", 0, "845") + checkBalance(t, tc, sdb, "C", 1, "100") + checkBalance(t, tc, sdb, "D", 0, "470") + + log.Debug("block:1 batch:1") + l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Batches[1].Batch.ForgeL1TxsNum]) + l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Batches[1].L2Txs) + _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Batches[1].L1CoordinatorTxs, l2Txs) + require.Nil(t, err) + + // use Set of PoolL2 txs + poolL2Txs, err := tc.GeneratePoolL2Txs(til.SetPoolL2MinimumFlow0) + assert.Nil(t, err) + + _, err = sdb.ProcessTxs(coordIdxs, []common.L1Tx{}, []common.L1Tx{}, poolL2Txs) + require.Nil(t, err) + checkBalance(t, tc, sdb, "Coord", 0, "105") + checkBalance(t, tc, sdb, "Coord", 1, "40") + checkBalance(t, tc, sdb, "A", 0, "510") + checkBalance(t, tc, sdb, "A", 1, "170") + checkBalance(t, tc, sdb, "B", 0, "480") + checkBalance(t, tc, sdb, "B", 1, "190") + checkBalance(t, tc, sdb, "C", 0, "845") + checkBalance(t, tc, sdb, "C", 1, "100") + checkBalance(t, tc, sdb, "D", 0, "360") + checkBalance(t, tc, sdb, "F", 0, "100") +} + func TestProcessTxsSynchronizer(t *testing.T) { dir, err := ioutil.TempDir("", "tmpdb") require.Nil(t, err) @@ -121,7 +254,7 @@ func TestProcessTxsSynchronizer(t *testing.T) { assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String()) acc, err = sdb.GetAccount(idxA1) assert.Nil(t, err) - assert.Equal(t, "82", acc.Balance.String()) + assert.Equal(t, "77", acc.Balance.String()) idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx acc, err = sdb.GetAccount(idxB0) @@ -195,7 +328,7 @@ func TestProcessTxsBatchBuilder(t *testing.T) { require.Nil(t, err) acc, err = sdb.GetAccount(idxA1) assert.Nil(t, err) - assert.Equal(t, "82", acc.Balance.String()) + assert.Equal(t, "77", acc.Balance.String()) idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx acc, err = sdb.GetAccount(idxB0) diff --git a/db/statedb/utils.go b/db/statedb/utils.go index 360ab9c..f38609f 100644 --- a/db/statedb/utils.go +++ b/db/statedb/utils.go @@ -63,6 +63,7 @@ func (s *StateDB) setIdxByEthAddrBJJ(idx common.Idx, addr ethCommon.Address, pk if err != nil { return err } + // store Addr-idx k = concatEthAddrTokenID(addr, tokenID) err = tx.Put(append(PrefixKeyAddr, k...), idxBytes[:]) @@ -83,11 +84,11 @@ func (s *StateDB) GetIdxByEthAddr(addr ethCommon.Address, tokenID common.TokenID k := concatEthAddrTokenID(addr, tokenID) b, err := s.db.Get(append(PrefixKeyAddr, k...)) if err != nil { - return common.Idx(0), ErrToIdxNotFound + return common.Idx(0), fmt.Errorf("GetIdxByEthAddr: %s: ToEthAddr: %s, TokenID: %d", ErrToIdxNotFound, addr.Hex(), tokenID) } idx, err := common.IdxFromBytes(b) if err != nil { - return common.Idx(0), ErrToIdxNotFound + return common.Idx(0), fmt.Errorf("GetIdxByEthAddr: %s: ToEthAddr: %s, TokenID: %d", err, addr.Hex(), tokenID) } return idx, nil } @@ -99,6 +100,7 @@ func (s *StateDB) GetIdxByEthAddr(addr ethCommon.Address, tokenID common.TokenID // the StateDB. func (s *StateDB) GetIdxByEthAddrBJJ(addr ethCommon.Address, pk *babyjub.PublicKey, tokenID common.TokenID) (common.Idx, error) { if !bytes.Equal(addr.Bytes(), common.EmptyAddr.Bytes()) && pk == nil { + // ToEthAddr // case ToEthAddr!=0 && ToBJJ=0 return s.GetIdxByEthAddr(addr, tokenID) } else if !bytes.Equal(addr.Bytes(), common.EmptyAddr.Bytes()) && pk != nil { @@ -106,16 +108,16 @@ func (s *StateDB) GetIdxByEthAddrBJJ(addr ethCommon.Address, pk *babyjub.PublicK k := concatEthAddrBJJTokenID(addr, pk, tokenID) b, err := s.db.Get(append(PrefixKeyAddrBJJ, k...)) if err != nil { - return common.Idx(0), ErrToIdxNotFound + return common.Idx(0), fmt.Errorf("GetIdxByEthAddrBJJ: %s: ToEthAddr: %s, ToBJJ: %s, TokenID: %d", ErrToIdxNotFound, addr.Hex(), pk, tokenID) } idx, err := common.IdxFromBytes(b) if err != nil { - return common.Idx(0), ErrToIdxNotFound + return common.Idx(0), fmt.Errorf("GetIdxByEthAddrBJJ: %s: ToEthAddr: %s, ToBJJ: %s, TokenID: %d", err, addr.Hex(), pk, tokenID) } return idx, nil } // rest of cases (included case ToEthAddr==0) are not possible - return common.Idx(0), ErrToIdxNotFound + return common.Idx(0), fmt.Errorf("GetIdxByEthAddrBJJ: Not found, %s: ToEthAddr: %s, ToBJJ: %s, TokenID: %d", ErrGetIdxNoCase, addr.Hex(), pk, tokenID) } func (s *StateDB) getTokenIDsFromIdxs(idxs []common.Idx) (map[common.TokenID]common.Idx, error) { diff --git a/db/statedb/utils_test.go b/db/statedb/utils_test.go index 84a4ab8..9fd3e5d 100644 --- a/db/statedb/utils_test.go +++ b/db/statedb/utils_test.go @@ -1,6 +1,7 @@ package statedb import ( + "fmt" "io/ioutil" "math/big" "os" @@ -82,7 +83,8 @@ func TestGetIdx(t *testing.T) { // expect error when trying to get Idx by addr2 & pk2 idxR, err = sdb.GetIdxByEthAddrBJJ(addr2, pk2, tokenID0) assert.NotNil(t, err) - assert.Equal(t, ErrToIdxNotFound, err) + expectedErr := fmt.Errorf("GetIdxByEthAddrBJJ: %s: ToEthAddr: %s, ToBJJ: %s, TokenID: %d", ErrToIdxNotFound, addr2.Hex(), pk2, tokenID0) + assert.Equal(t, expectedErr, err) assert.Equal(t, common.Idx(0), idxR) // expect error when trying to get Idx by addr with not used TokenID _, err = sdb.GetIdxByEthAddr(addr, tokenID1) diff --git a/test/til/sets.go b/test/til/sets.go index b163fc3..9a95580 100644 --- a/test/til/sets.go +++ b/test/til/sets.go @@ -202,3 +202,131 @@ PoolTransfer(1) A-C: 3 (1) PoolTransferToEthAddr(1) A-C: 3 (1) PoolTransferToBJJ(1) A-C: 3 (1) ` + +// Minimum flow + +// SetBlockchainMinimumFlow0 contains a set of transactions with a minimal flow +var SetBlockchainMinimumFlow0 = ` +Type: Blockchain + +AddToken(1) + + +// Coordinator accounts, Idxs: 256, 257 +CreateAccountCoordinator(0) Coord +CreateAccountCoordinator(1) Coord + +// close Block:0, Batch:0 +> batch // forge L1Coord{2} + +CreateAccountDeposit(0) A: 500 +CreateAccountDeposit(1) C: 0 +CreateAccountCoordinator(0) C + +// close Block:0, Batch:1 +> batchL1 // freeze L1User{2}, forge L1Coord{1} +// Expected balances: +// Coord(0): 0, Coord(1): 0 +// C(0): 0 + +CreateAccountDeposit(1) A: 500 + +// close Block:0, Batch:2 +> batchL1 // freeze L1User{1}, forge L1User{2} +// Expected balances: +// Coord(0): 0, Coord(1): 0 +// A(0): 500 +// C(0): 0, C(1): 0 + +// close Block:0, Batch:3 +> batchL1 // freeze L1User{nil}, forge L1User{1} +// Expected balances: +// Coord(0): 0, Coord(1): 0 +// A(0): 500, A(1): 500 +// C(0): 0 + + +CreateAccountDepositTransfer(0) B-A: 500, 100 + +// close Block:0, Batch:4 +> batchL1 // freeze L1User{1}, forge L1User{nil} +CreateAccountDeposit(0) D: 800 + +// close Block:0, Batch:5 +> batchL1 // freeze L1User{1}, forge L1User{1} +// Expected balances: +// Coord(0): 0, Coord(1): 0 +// A(0): 600, A(1): 500 +// B(0): 400 +// C(0): 0 + +CreateAccountCoordinator(1) B + +Transfer(1) A-B: 200 (200) +Transfer(0) B-C: 100 (200) + +// close Block:0, Batch:6 +> batchL1 // forge L1User{1}, forge L1Coord{2}, forge L2{2} +// Expected balances: +// Coord(0): 10, Coord(1): 20 +// A(0): 600, A(1): 280 +// B(0): 290, B(1): 200 +// C(0): 100, C(1): 0 +// D(0): 800 + +Deposit(0) C: 500 +DepositTransfer(0) C-D: 400, 100 + +Transfer(0) A-B: 100 (200) +Transfer(0) C-A: 50 (200) +Transfer(1) B-C: 100 (200) +Exit(0) A: 100 (200) + +ForceTransfer(0) D-B: 200 +ForceExit(0) B: 100 + +// close Block:0, Batch:7 +> batchL1 // freeze L1User{4}, forge L1User{nil}, forge L2{4} +> block +// Expected balances: +// Coord(0): 35, Coord(1): 30 +// A(0): 430, A(1): 280 +// B(0): 390, B(1): 90 +// C(0): 45, C(1): 100 +// D(0): 800 + +Transfer(0) D-A: 300 (200) +Transfer(0) B-D: 100 (200) + +// close Block:1, Batch:0 +> batchL1 // freeze L1User{nil}, forge L1User{4}, forge L2{1} +// Expected balances: +// Coord(0): 75, Coord(1): 30 +// A(0): 730, A(1): 280 +// B(0): 380, B(1): 90 +// C(0): 845, C(1): 100 +// D(0): 470 + +CreateAccountCoordinator(0) F + +> batch // forge L1CoordinatorTx{1} +> block +` + +// SetPoolL2MinimumFlow0 contains a set of transactions with a minimal flow +var SetPoolL2MinimumFlow0 = ` +Type: PoolL2 + +PoolTransfer(0) A-B: 100 (200) +PoolTransferToEthAddr(0) D-F: 100 (200) +PoolExit(0) A: 100 (200) +PoolTransferToEthAddr(1) A-B: 100 (200) + +// Expected balances: +// Coord(0): 105, Coord(1): 40 +// A(0): 510, A(1): 170 +// B(0): 480, B(1): 190 +// C(0): 845, C(1): 100 +// D(0): 360 +// F(0): 100 +` diff --git a/test/til/sets_test.go b/test/til/sets_test.go index cad790b..508eaec 100644 --- a/test/til/sets_test.go +++ b/test/til/sets_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestCompileSets(t *testing.T) { +func TestCompileSetsBase(t *testing.T) { parser := newParser(strings.NewReader(SetBlockchain0)) _, err := parser.parse() assert.Nil(t, err) @@ -22,3 +22,12 @@ func TestCompileSets(t *testing.T) { _, err = tc.GeneratePoolL2Txs(SetPool0) assert.Nil(t, err) } + +func TestCompileSetsMinimumFlow(t *testing.T) { + // minimum flow + tc := NewContext(eth.RollupConstMaxL1UserTx) + _, err := tc.GenerateBlocks(SetBlockchainMinimumFlow0) + assert.Nil(t, err) + _, err = tc.GeneratePoolL2Txs(SetPoolL2MinimumFlow0) + assert.Nil(t, err) +} diff --git a/test/til/txs.go b/test/til/txs.go index 92244ab..5dba6ab 100644 --- a/test/til/txs.go +++ b/test/til/txs.go @@ -49,8 +49,8 @@ type Context struct { currBlock common.BlockData currBatch common.BatchData currBatchNum int - queues [][]L1Tx - toForgeNum int + Queues [][]L1Tx + ToForgeNum int openToForge int currBatchTest struct { l1CoordinatorTxs []L1Tx @@ -75,8 +75,8 @@ func NewContext(rollupConstMaxL1UserTx int) *Context { currBatch: newBatchData(currBatchNum), currBatchNum: currBatchNum, // start with 2 queues, one for toForge, and the other for openToForge - queues: make([][]L1Tx, 2), - toForgeNum: 0, + Queues: make([][]L1Tx, 2), + ToForgeNum: 0, openToForge: 1, //nolint:gomnd blockNum: 2, // rollup genesis blockNum @@ -301,8 +301,8 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) { return nil, err } case typeNewBatchL1: - // for each L1UserTx of the queues[ToForgeNum], calculate the Idx - if err = tc.calculateIdxForL1Txs(false, tc.queues[tc.toForgeNum]); err != nil { + // for each L1UserTx of the Queues[ToForgeNum], calculate the Idx + if err = tc.calculateIdxForL1Txs(false, tc.Queues[tc.ToForgeNum]); err != nil { return nil, err } if err = tc.calculateIdxForL1Txs(true, tc.currBatchTest.l1CoordinatorTxs); err != nil { @@ -313,12 +313,14 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) { log.Error(err) return nil, err } + toForgeL1TxsNum := int64(tc.openToForge) + tc.currBatch.Batch.ForgeL1TxsNum = &toForgeL1TxsNum // advance batch - tc.toForgeNum++ - if tc.toForgeNum == tc.openToForge { + tc.ToForgeNum++ + if tc.ToForgeNum == tc.openToForge { tc.openToForge++ newQueue := []L1Tx{} - tc.queues = append(tc.queues, newQueue) + tc.Queues = append(tc.Queues, newQueue) } case typeNewBlock: blocks = append(blocks, tc.currBlock) @@ -349,12 +351,12 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) { // calculateIdxsForL1Txs calculates new Idx for new created accounts. If // 'isCoordinatorTxs==true', adds the tx to tc.currBatch.L1CoordinatorTxs. func (tc *Context) calculateIdxForL1Txs(isCoordinatorTxs bool, txs []L1Tx) error { - // for each batch.L1CoordinatorTxs of the queues[ToForgeNum], calculate the Idx + // for each batch.L1CoordinatorTxs of the Queues[ToForgeNum], calculate the Idx for i := 0; i < len(txs); i++ { tx := txs[i] if tx.L1Tx.Type == common.TxTypeCreateAccountDeposit || tx.L1Tx.Type == common.TxTypeCreateAccountDepositTransfer { if tc.Users[tx.fromIdxName].Accounts[tx.L1Tx.TokenID] != nil { // if account already exists, return error - return fmt.Errorf("Can not create same account twice (same User & same TokenID) (this is a design property of Til)") + return fmt.Errorf("Can not create same account twice (same User (%s) & same TokenID (%d)) (this is a design property of Til)", tx.fromIdxName, tx.L1Tx.TokenID) } tc.Users[tx.fromIdxName].Accounts[tx.L1Tx.TokenID] = &Account{ Idx: common.Idx(tc.idx), @@ -418,19 +420,19 @@ func (tc *Context) setIdxs() error { // addToL1Queue adds the L1Tx into the queue that is open and has space func (tc *Context) addToL1Queue(tx L1Tx) error { - if len(tc.queues[tc.openToForge]) >= tc.rollupConstMaxL1UserTx { + if len(tc.Queues[tc.openToForge]) >= tc.rollupConstMaxL1UserTx { // if current OpenToForge queue reached its Max, move into a // new queue tc.openToForge++ newQueue := []L1Tx{} - tc.queues = append(tc.queues, newQueue) + tc.Queues = append(tc.Queues, newQueue) } // Fill L1UserTx specific parameters tx.L1Tx.UserOrigin = true toForgeL1TxsNum := int64(tc.openToForge) tx.L1Tx.ToForgeL1TxsNum = &toForgeL1TxsNum tx.L1Tx.EthBlockNum = tc.blockNum - tx.L1Tx.Position = len(tc.queues[tc.openToForge]) + tx.L1Tx.Position = len(tc.Queues[tc.openToForge]) // When an L1UserTx is generated, all idxs must be available (except when idx == 0 or idx == 1) if tx.L1Tx.Type != common.TxTypeCreateAccountDeposit && tx.L1Tx.Type != common.TxTypeCreateAccountDepositTransfer { @@ -457,7 +459,7 @@ func (tc *Context) addToL1Queue(tx L1Tx) error { } tx.L1Tx = *nTx - tc.queues[tc.openToForge] = append(tc.queues[tc.openToForge], tx) + tc.Queues[tc.openToForge] = append(tc.Queues[tc.openToForge], tx) tc.currBlock.L1UserTxs = append(tc.currBlock.L1UserTxs, tx.L1Tx) return nil @@ -554,6 +556,7 @@ func (tc *Context) GeneratePoolL2Txs(set string) ([]common.PoolL2Tx, error) { tx := common.PoolL2Tx{ FromIdx: tc.Users[inst.from].Accounts[inst.tokenID].Idx, ToIdx: common.Idx(1), // as is an Exit + Fee: common.FeeSelector(inst.fee), TokenID: inst.tokenID, Amount: big.NewInt(int64(inst.amount)), Nonce: tc.Users[inst.from].Accounts[inst.tokenID].Nonce, @@ -608,3 +611,12 @@ func (tc *Context) generateKeys(userNames []string) { tc.Users[userNames[i-1]] = &u } } + +// L1TxsToCommonL1Txs converts an array of []til.L1Tx to []common.L1Tx +func L1TxsToCommonL1Txs(l1 []L1Tx) []common.L1Tx { + var r []common.L1Tx + for i := 0; i < len(l1); i++ { + r = append(r, l1[i].L1Tx) + } + return r +}