diff --git a/common/batch.go b/common/batch.go index 1d7206f..8a76a93 100644 --- a/common/batch.go +++ b/common/batch.go @@ -18,6 +18,7 @@ type Batch struct { CollectedFees map[TokenID]*big.Int `meddler:"fees_collected,json"` StateRoot *big.Int `meddler:"state_root,bigint"` NumAccounts int `meddler:"num_accounts"` + LastIdx int64 `meddler:"last_idx"` ExitRoot *big.Int `meddler:"exit_root,bigint"` ForgeL1TxsNum *int64 `meddler:"forge_l1_txs_num"` // optional, Only when the batch forges L1 txs. Identifier that corresponds to the group of L1 txs forged in the current batch. SlotNum int64 `meddler:"slot_num"` // Slot in which the batch is forged diff --git a/db/historydb/historydb.go b/db/historydb/historydb.go index e60a160..b7eae25 100644 --- a/db/historydb/historydb.go +++ b/db/historydb/historydb.go @@ -71,6 +71,16 @@ func (hdb *HistoryDB) GetBlock(blockNum int64) (*common.Block, error) { return block, err } +// GetAllBlocks retrieve all blocks from the DB +func (hdb *HistoryDB) GetAllBlocks() ([]common.Block, error) { + var blocks []*common.Block + err := meddler.QueryAll( + hdb.db, &blocks, + "SELECT * FROM block;", + ) + return db.SlicePtrsToSlice(blocks).([]common.Block), err +} + // GetBlocks retrieve blocks from the DB, given a range of block numbers defined by from and to func (hdb *HistoryDB) GetBlocks(from, to int64) ([]common.Block, error) { var blocks []*common.Block @@ -257,6 +267,16 @@ func (hdb *HistoryDB) GetBatchesAPI( }, nil } +// GetAllBatches retrieve all batches from the DB +func (hdb *HistoryDB) GetAllBatches() ([]common.Batch, error) { + var batches []*common.Batch + err := meddler.QueryAll( + hdb.db, &batches, + "SELECT * FROM batch;", + ) + return db.SlicePtrsToSlice(batches).([]common.Batch), err +} + // GetBatches retrieve batches from the DB, given a range of batch numbers defined by from and to func (hdb *HistoryDB) GetBatches(from, to common.BatchNum) ([]common.Batch, error) { var batches []*common.Batch @@ -898,6 +918,19 @@ func (hdb *HistoryDB) GetExits( // ) // } +// GetAllL1UserTxs returns all L1UserTxs from the DB +func (hdb *HistoryDB) GetAllL1UserTxs() ([]common.L1Tx, error) { + var txs []*common.L1Tx + err := meddler.QueryAll( + hdb.db, &txs, + `SELECT tx.id, tx.to_forge_l1_txs_num, tx.position, tx.user_origin, + tx.from_idx, tx.from_eth_addr, tx.from_bjj, tx.to_idx, tx.token_id, tx.amount, + tx.load_amount, tx.eth_block_num, tx.type, tx.batch_num + FROM tx WHERE is_l1 = TRUE AND user_origin = TRUE;`, + ) + return db.SlicePtrsToSlice(txs).([]common.L1Tx), err +} + // GetL1UserTxs gets L1 User Txs to be forged in the L1Batch with toForgeL1TxsNum. func (hdb *HistoryDB) GetL1UserTxs(toForgeL1TxsNum int64) ([]common.L1Tx, error) { var txs []*common.L1Tx diff --git a/db/historydb/historydb_test.go b/db/historydb/historydb_test.go index 8570415..db2ecfc 100644 --- a/db/historydb/historydb_test.go +++ b/db/historydb/historydb_test.go @@ -1,12 +1,12 @@ package historydb import ( + "fmt" "math" "math/big" "os" "testing" - ethCommon "github.com/ethereum/go-ethereum/common" "github.com/hermeznetwork/hermez-node/common" dbUtils "github.com/hermeznetwork/hermez-node/db" "github.com/hermeznetwork/hermez-node/log" @@ -406,25 +406,10 @@ func TestGetL1UserTxs(t *testing.T) { require.Equal(t, 5, len(blocks[0].L1UserTxs)) // fmt.Printf("DBG Blocks: %+v\n", blocks) - // TODO: Move this logic to `func (tc *TestContext) GenerateBlocks(set string) ([]common.BlockData, error)` toForgeL1TxsNum := int64(1) - for i := range blocks { - block := &blocks[i] - block.Block.EthBlockNum = int64(i) - for j := range block.AddedTokens { - token := &block.AddedTokens[j] - token.EthAddr = ethCommon.BigToAddress(big.NewInt(int64(i*len(blocks) + j))) - } - for j := range block.L1UserTxs { - l1Tx := &block.L1UserTxs[j] - l1Tx.UserOrigin = true - l1Tx.Position = j - l1Tx.ToForgeL1TxsNum = &toForgeL1TxsNum - } - } for i := range blocks { - // fmt.Printf("DBG %+v\n", blocks[i]) + fmt.Printf("DBG %+v\n", blocks[i]) // fmt.Printf("DBG Batches %+v\n", blocks[i].Batches) // for _, l1Tx := range blocks[i].L1UserTxs { // fmt.Printf("DBG l1UserTx %+v\n", l1Tx) @@ -433,25 +418,6 @@ func TestGetL1UserTxs(t *testing.T) { require.Nil(t, err) } - // // TODO: Use til to generate a set with some L1UserTxs - // l1Txs := []common.L1Tx{} - // l1Tx, err := common.NewL1Tx(&common.L1Tx{ - // ToForgeL1TxsNum: &toForgeL1TxsNum, - // Position: 0, - // UserOrigin: true, - // FromIdx: 0, - // FromEthAddr: ethCommon.Address{}, // ethCommon.HexToAddress("0xff"), - // FromBJJ: nil, - // ToIdx: 0, - // TokenID: 1, - // Amount: big.NewInt(0), - // LoadAmount: big.NewInt(0), - // }) - // require.Nil(t, err) - // l1Txs = append(l1Txs, *l1Tx) - - // require.Nil(t, historyDB.AddL1Txs(l1Txs)) - l1UserTxs, err := historyDB.GetL1UserTxs(toForgeL1TxsNum) require.Nil(t, err) assert.Equal(t, 5, len(l1UserTxs)) diff --git a/db/migrations/0001.sql b/db/migrations/0001.sql index 1e6ebfd..fa6646a 100644 --- a/db/migrations/0001.sql +++ b/db/migrations/0001.sql @@ -23,6 +23,7 @@ CREATE TABLE batch ( fees_collected BYTEA NOT NULL, state_root BYTEA NOT NULL, num_accounts BIGINT NOT NULL, + last_idx BIGINT NOT NULL, exit_root BYTEA NOT NULL, forge_l1_txs_num BIGINT, slot_num BIGINT NOT NULL, diff --git a/synchronizer/synchronizer.go b/synchronizer/synchronizer.go index ba41677..f24d598 100644 --- a/synchronizer/synchronizer.go +++ b/synchronizer/synchronizer.go @@ -3,6 +3,7 @@ package synchronizer import ( "context" "database/sql" + "fmt" "github.com/ethereum/go-ethereum" "github.com/hermeznetwork/hermez-node/common" @@ -343,7 +344,7 @@ func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*rollupData, error) { } batchNum := common.BatchNum(evtForgeBatch.BatchNum) - forgeL1TxsNum := nextForgeL1TxsNum + nextForgeL1TxsNumCpy := nextForgeL1TxsNum var l1UserTxs []common.L1Tx // Check if this is a L1Batch to get L1 Tx from it if forgeBatchArgs.L1Batch { @@ -352,7 +353,7 @@ func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*rollupData, error) { // that stateDB can process them. // First try to find them in HistoryDB. - l1UserTxs, err := s.historyDB.GetL1UserTxs(forgeL1TxsNum) + l1UserTxs, err := s.historyDB.GetL1UserTxs(nextForgeL1TxsNumCpy) if len(l1UserTxs) == 0 { // If not found in the DB, try to find them in // this block. This could happen because in a @@ -365,7 +366,7 @@ func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*rollupData, error) { // closed empty, so we leave `l1UserTxs` as an // empty slice. for _, l1UserTx := range rollupData.l1UserTxs { - if *l1UserTx.ToForgeL1TxsNum == forgeL1TxsNum { + if *l1UserTx.ToForgeL1TxsNum == nextForgeL1TxsNumCpy { l1UserTxs = append(l1UserTxs, l1UserTx) } } @@ -373,26 +374,26 @@ func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*rollupData, error) { if err != nil { return nil, err } + nextForgeL1TxsNum++ position = len(l1UserTxs) - - // Get L1 Coordinator Txs - for i := range forgeBatchArgs.L1CoordinatorTxs { - l1CoordinatorTx := forgeBatchArgs.L1CoordinatorTxs[i] - l1CoordinatorTx.Position = position - l1CoordinatorTx.ToForgeL1TxsNum = &forgeL1TxsNum - l1CoordinatorTx.UserOrigin = false - l1CoordinatorTx.EthBlockNum = blockNum - l1CoordinatorTx.BatchNum = &batchNum - l1Tx, err := common.NewL1Tx(&l1CoordinatorTx) - if err != nil { - return nil, err - } - - batchData.L1CoordinatorTxs = append(batchData.L1CoordinatorTxs, *l1Tx) - position++ + } + // Get L1 Coordinator Txs + for i := range forgeBatchArgs.L1CoordinatorTxs { + l1CoordinatorTx := forgeBatchArgs.L1CoordinatorTxs[i] + l1CoordinatorTx.Position = position + // l1CoordinatorTx.ToForgeL1TxsNum = &forgeL1TxsNum + l1CoordinatorTx.UserOrigin = false + l1CoordinatorTx.EthBlockNum = blockNum + l1CoordinatorTx.BatchNum = &batchNum + l1Tx, err := common.NewL1Tx(&l1CoordinatorTx) + if err != nil { + return nil, err } - nextForgeL1TxsNum++ + + batchData.L1CoordinatorTxs = append(batchData.L1CoordinatorTxs, *l1Tx) + position++ + fmt.Println("DGB l1coordtx") } // Insert all the txs forged in this batch (l1UserTxs, @@ -443,12 +444,14 @@ func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*rollupData, error) { ForgerAddr: *sender, // CollectedFees: , TODO: Clarify where to get them if they are still needed StateRoot: forgeBatchArgs.NewStRoot, - NumAccounts: numAccounts, + NumAccounts: numAccounts, // TODO: Calculate this value + LastIdx: forgeBatchArgs.NewLastIdx, ExitRoot: forgeBatchArgs.NewExitRoot, SlotNum: slotNum, } if forgeBatchArgs.L1Batch { - batch.ForgeL1TxsNum = &forgeL1TxsNum + batch.ForgeL1TxsNum = &nextForgeL1TxsNumCpy + batchData.L1Batch = true } batchData.Batch = batch rollupData.batches = append(rollupData.batches, *batchData) diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index da51a0a..7d962f8 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -2,8 +2,6 @@ package synchronizer import ( "context" - "crypto/ecdsa" - "encoding/binary" "fmt" "io/ioutil" "math/big" @@ -11,14 +9,13 @@ import ( "testing" ethCommon "github.com/ethereum/go-ethereum/common" - ethCrypto "github.com/ethereum/go-ethereum/crypto" "github.com/hermeznetwork/hermez-node/common" dbUtils "github.com/hermeznetwork/hermez-node/db" "github.com/hermeznetwork/hermez-node/db/historydb" "github.com/hermeznetwork/hermez-node/db/statedb" "github.com/hermeznetwork/hermez-node/eth" "github.com/hermeznetwork/hermez-node/test" - "github.com/iden3/go-iden3-crypto/babyjub" + "github.com/hermeznetwork/hermez-node/test/til" "github.com/jinzhu/copier" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -34,13 +31,11 @@ func (t *timer) Time() int64 { return currentTime } -type tokenData struct { - TokenID common.TokenID - Addr ethCommon.Address - Consts eth.ERC20Consts -} - func TestSync(t *testing.T) { + // + // Setup + // + ctx := context.Background() // Int State DB dir, err := ioutil.TempDir("", "tmpdb") @@ -62,131 +57,242 @@ func TestSync(t *testing.T) { // Init eth client var timer timer clientSetup := test.NewClientSetupExample() + bootCoordAddr := clientSetup.AuctionVariables.BootCoordinator client := test.NewClient(true, &timer, ðCommon.Address{}, clientSetup) // Create Synchronizer s, err := NewSynchronizer(client, historyDB, stateDB) require.Nil(t, err) + // + // First Sync from an initial state + // + // Test Sync for rollup genesis block - blockData, _, err := s.Sync2(ctx, nil) + syncBlock, discards, err := s.Sync2(ctx, nil) require.Nil(t, err) - require.NotNil(t, blockData) - assert.Equal(t, int64(1), blockData.Block.EthBlockNum) - blocks, err := s.historyDB.GetBlocks(0, 9999) + require.Nil(t, discards) + require.NotNil(t, syncBlock) + assert.Equal(t, int64(1), syncBlock.Block.EthBlockNum) + dbBlocks, err := s.historyDB.GetAllBlocks() require.Nil(t, err) - assert.Equal(t, 1, len(blocks)) - assert.Equal(t, int64(1), blocks[0].EthBlockNum) + assert.Equal(t, 1, len(dbBlocks)) + assert.Equal(t, int64(1), dbBlocks[0].EthBlockNum) - /* - // Test Sync for a block with new Tokens and L1UserTxs - // accounts := test.GenerateKeys(t, []string{"A", "B", "C", "D"}) - l1UserTxs, _, _, _ := test.GenerateTestTxsFromSet(t, ` - A (1): 10 - A (2): 20 - B (1): 5 - C (1): 8 - D (3): 15 - > advance batch - `) - require.Greater(t, len(l1UserTxs[0]), 0) - // require.Greater(t, len(tokens), 0) - - for i := 1; i <= 3; i++ { - _, err := client.RollupAddToken(ethCommon.BigToAddress(big.NewInt(int64(i*10000))), - clientSetup.RollupVariables.FeeAddToken) - require.Nil(t, err) - } + // Sync again and expect no new blocks + syncBlock, discards, err = s.Sync2(ctx, nil) + require.Nil(t, err) + require.Nil(t, discards) + require.Nil(t, syncBlock) - for i := range l1UserTxs[0] { - client.CtlAddL1TxUser(&l1UserTxs[0][i]) - } - client.CtlMineBlock() + // + // Generate blockchain and smart contract data, and fill the test smart contracts + // - err = s.Sync(context.Background()) - require.Nil(t, err) + // Generate blockchain data with til + set1 := ` + Type: Blockchain - getTokens, err := s.historyDB.GetTokens() - require.Nil(t, err) - assert.Equal(t, 3, len(getTokens)) - */ + AddToken(1) + AddToken(2) + AddToken(3) - // Generate tokens vector - numTokens := 3 - tokens := make([]tokenData, numTokens) - for i := 1; i <= numTokens; i++ { - addr := ethCommon.BigToAddress(big.NewInt(int64(i * 10000))) - consts := eth.ERC20Consts{ - Name: fmt.Sprintf("Token %d", i), - Symbol: fmt.Sprintf("TK%d", i), - Decimals: uint64(i * 2), - } - tokens[i-1] = tokenData{common.TokenID(i), addr, consts} - } + CreateAccountDeposit(1) A: 20 // Idx=256+1 + CreateAccountDeposit(2) A: 20 // Idx=256+2 + CreateAccountDeposit(1) B: 5 // Idx=256+3 + CreateAccountDeposit(1) C: 5 // Idx=256+4 + CreateAccountDeposit(1) D: 5 // Idx=256+5 - numUsers := 4 - keys := make([]*userKeys, numUsers) - for i := range keys { - keys[i] = genKeys(i) - } + CreateAccountDepositCoordinator(2) B // Idx=256+0 - // Generate some L1UserTxs of type deposit - l1UserTxs := make([]*common.L1Tx, 5) - for i := range l1UserTxs { - l1UserTxs[i] = &common.L1Tx{ - FromIdx: common.Idx(0), - FromEthAddr: keys[i%numUsers].Addr, - FromBJJ: keys[i%numUsers].BJJPK, - Amount: big.NewInt(0), - LoadAmount: big.NewInt((int64(i) + 1) * 1000), - TokenID: common.TokenID(i%numTokens + 1), + > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs + > batchL1 // forge defined L1UserTxs, freeze L1UserTxs{nil} + > block + + ` + tc := til.NewContext(eth.RollupConstMaxL1UserTx) + blocks, err := tc.GenerateBlocks(set1) + require.Nil(t, err) + require.Equal(t, 1, len(blocks)) + require.Equal(t, 3, len(blocks[0].AddedTokens)) + require.Equal(t, 5, len(blocks[0].L1UserTxs)) + require.Equal(t, 2, len(blocks[0].Batches)) + + tokenConsts := map[common.TokenID]eth.ERC20Consts{} + // Generate extra required data + for _, block := range blocks { + for _, token := range block.AddedTokens { + consts := eth.ERC20Consts{ + Name: fmt.Sprintf("Token %d", token.TokenID), + Symbol: fmt.Sprintf("TK%d", token.TokenID), + Decimals: 18, + } + tokenConsts[token.TokenID] = consts + client.CtlAddERC20(token.EthAddr, consts) } } - // Add tokens to ethereum, and to rollup - for _, token := range tokens { - client.CtlAddERC20(token.Addr, token.Consts) - _, err := client.RollupAddTokenSimple(token.Addr, clientSetup.RollupVariables.FeeAddToken) - require.Nil(t, err) + // Add block data to the smart contracts + for _, block := range blocks { + for _, token := range block.AddedTokens { + _, err := client.RollupAddTokenSimple(token.EthAddr, clientSetup.RollupVariables.FeeAddToken) + require.Nil(t, err) + } + for _, tx := range block.L1UserTxs { + client.CtlSetAddr(tx.FromEthAddr) + _, err := client.RollupL1UserTxERC20ETH(tx.FromBJJ, int64(tx.FromIdx), tx.LoadAmount, tx.Amount, + uint32(tx.TokenID), int64(tx.ToIdx)) + require.Nil(t, err) + } + client.CtlSetAddr(bootCoordAddr) + for _, batch := range block.Batches { + _, err := client.RollupForgeBatch(ð.RollupForgeBatchArgs{ + NewLastIdx: batch.Batch.LastIdx, + NewStRoot: batch.Batch.StateRoot, + NewExitRoot: batch.Batch.ExitRoot, + L1CoordinatorTxs: batch.L1CoordinatorTxs, + L1CoordinatorTxsAuths: [][]byte{}, // Intentionally empty + L2TxsData: batch.L2Txs, + FeeIdxCoordinator: []common.Idx{}, // TODO + // Circuit selector + VerifierIdx: 0, // Intentionally empty + L1Batch: batch.L1Batch, + ProofA: [2]*big.Int{}, // Intentionally empty + ProofB: [2][2]*big.Int{}, // Intentionally empty + ProofC: [2]*big.Int{}, // Intentionally empty + }) + require.Nil(t, err) + } + // Mine block and sync + client.CtlMineBlock() } - // Add L1Txs to rollup - for i := range l1UserTxs { - tx := l1UserTxs[i] - _, err := client.RollupL1UserTxERC20ETH(tx.FromBJJ, int64(tx.FromIdx), tx.LoadAmount, tx.Amount, - uint32(tx.TokenID), int64(tx.ToIdx)) - require.Nil(t, err) + // + // Sync to synchronize the current state from the test smart contracts + // + + syncBlock, discards, err = s.Sync2(ctx, nil) + require.Nil(t, err) + require.Nil(t, discards) + require.NotNil(t, syncBlock) + assert.Equal(t, int64(2), syncBlock.Block.EthBlockNum) + + // Fill extra fields not generated by til in til block + openToForge := int64(0) + toForgeL1TxsNum := int64(0) + for i := range blocks { + block := &blocks[i] + for j := range block.Batches { + batch := &block.Batches[j] + if batch.L1Batch { + // Set BatchNum for forged L1UserTxs to til blocks + bn := batch.Batch.BatchNum + for k := range blocks { + block := &blocks[k] + for l := range block.L1UserTxs { + tx := &block.L1UserTxs[l] + if *tx.ToForgeL1TxsNum == openToForge { + tx.BatchNum = &bn + } + } + } + openToForge++ + } + + batch.Batch.EthBlockNum = block.Block.EthBlockNum + batch.Batch.ForgerAddr = bootCoordAddr // til doesn't fill the batch forger addr + if batch.L1Batch { + toForgeL1TxsNumCpy := toForgeL1TxsNum + batch.Batch.ForgeL1TxsNum = &toForgeL1TxsNumCpy // til doesn't fill the ForgeL1TxsNum + toForgeL1TxsNum++ + } + + batchNum := batch.Batch.BatchNum + for j := range batch.L1CoordinatorTxs { + tx := &batch.L1CoordinatorTxs[j] + tx.BatchNum = &batchNum + tx.EthBlockNum = batch.Batch.EthBlockNum + nTx, err := common.NewL1Tx(tx) + require.Nil(t, err) + *tx = *nTx + } + } } - // Mine block and sync - client.CtlMineBlock() + block := blocks[0] - blockData, _, err = s.Sync2(ctx, nil) + // + // Check Sync output and HistoryDB state against expected values + // generated by til + // + + // Check Blocks + dbBlocks, err = s.historyDB.GetAllBlocks() require.Nil(t, err) - require.NotNil(t, blockData) - assert.Equal(t, int64(2), blockData.Block.EthBlockNum) + assert.Equal(t, 2, len(dbBlocks)) + assert.Equal(t, int64(2), dbBlocks[1].EthBlockNum) + assert.NotEqual(t, dbBlocks[1].Hash, dbBlocks[0].Hash) + assert.Greater(t, dbBlocks[1].Timestamp.Unix(), dbBlocks[0].Timestamp.Unix()) - // Check tokens in DB + // Check Tokens + assert.Equal(t, len(block.AddedTokens), len(syncBlock.AddedTokens)) dbTokens, err := s.historyDB.GetAllTokens() require.Nil(t, err) - assert.Equal(t, len(tokens), len(dbTokens)) - assert.Equal(t, len(tokens), len(blockData.AddedTokens)) - for i := range tokens { - token := tokens[i] - addToken := blockData.AddedTokens[i] + assert.Equal(t, len(block.AddedTokens), len(dbTokens)) + for i, token := range block.AddedTokens { dbToken := dbTokens[i] + syncToken := syncBlock.AddedTokens[i] + + assert.Equal(t, block.Block.EthBlockNum, syncToken.EthBlockNum) + assert.Equal(t, token.TokenID, syncToken.TokenID) + assert.Equal(t, token.EthAddr, syncToken.EthAddr) + tokenConst := tokenConsts[token.TokenID] + assert.Equal(t, tokenConst.Name, syncToken.Name) + assert.Equal(t, tokenConst.Symbol, syncToken.Symbol) + assert.Equal(t, tokenConst.Decimals, syncToken.Decimals) + + var tokenCpy historydb.TokenRead + //nolint:gosec + require.Nil(t, copier.Copy(&tokenCpy, &token)) // copy common.Token to historydb.TokenRead + require.Nil(t, copier.Copy(&tokenCpy, &tokenConst)) // copy common.Token to historydb.TokenRead + tokenCpy.ItemID = dbToken.ItemID // we don't care about ItemID + assert.Equal(t, tokenCpy, dbToken) + } + + // Check L1UserTxs + assert.Equal(t, len(block.L1UserTxs), len(syncBlock.L1UserTxs)) + dbL1UserTxs, err := s.historyDB.GetAllL1UserTxs() + require.Nil(t, err) + assert.Equal(t, len(block.L1UserTxs), len(dbL1UserTxs)) + // Ignore BatchNum in syncBlock.L1UserTxs because this value is set by the HistoryDB + for i := range syncBlock.L1UserTxs { + syncBlock.L1UserTxs[i].BatchNum = block.L1UserTxs[i].BatchNum + } + assert.Equal(t, block.L1UserTxs, syncBlock.L1UserTxs) + assert.Equal(t, block.L1UserTxs, dbL1UserTxs) - assert.Equal(t, int64(2), addToken.EthBlockNum) - assert.Equal(t, token.TokenID, addToken.TokenID) - assert.Equal(t, token.Addr, addToken.EthAddr) - assert.Equal(t, token.Consts.Name, addToken.Name) - assert.Equal(t, token.Consts.Symbol, addToken.Symbol) - assert.Equal(t, token.Consts.Decimals, addToken.Decimals) - - var addTokenCpy historydb.TokenRead - require.Nil(t, copier.Copy(&addTokenCpy, &addToken)) // copy common.Token to historydb.TokenRead - addTokenCpy.ItemID = dbToken.ItemID // we don't care about ItemID - assert.Equal(t, addTokenCpy, dbToken) + // Check Batches + assert.Equal(t, len(block.Batches), len(syncBlock.Batches)) + dbBatches, err := s.historyDB.GetAllBatches() + require.Nil(t, err) + assert.Equal(t, len(block.Batches), len(dbBatches)) + + for i, batch := range block.Batches { + batchNum := batch.Batch.BatchNum + dbBatch := dbBatches[i] + syncBatch := syncBlock.Batches[i] + + // We don't care about TotalFeesUSD. Use the syncBatch that + // has a TotalFeesUSD inserted by the HistoryDB + batch.Batch.TotalFeesUSD = syncBatch.Batch.TotalFeesUSD + batch.CreatedAccounts = syncBatch.CreatedAccounts // til doesn't output CreatedAccounts + + // fmt.Printf("DBG Batch %d %+v\n", i, batch) + // fmt.Printf("DBG Batch Sync %d %+v\n", i, syncBatch) + // assert.Equal(t, batch.L1CoordinatorTxs, syncBatch.L1CoordinatorTxs) + fmt.Printf("DBG BatchNum: %d, LastIdx: %d\n", batchNum, batch.Batch.LastIdx) + assert.Equal(t, batch, syncBatch) + assert.Equal(t, batch.Batch, dbBatch) } // Check L1UserTxs in DB @@ -213,28 +319,3 @@ func TestSync(t *testing.T) { require.Nil(t, err) */ } - -type userKeys struct { - BJJSK *babyjub.PrivateKey - BJJPK *babyjub.PublicKey - Addr ethCommon.Address -} - -func genKeys(i int) *userKeys { - i++ // i = 0 doesn't work for the ecdsa key generation - var sk babyjub.PrivateKey - binary.LittleEndian.PutUint64(sk[:], uint64(i)) - - // eth address - var key ecdsa.PrivateKey - key.D = big.NewInt(int64(i)) // only for testing - key.PublicKey.X, key.PublicKey.Y = ethCrypto.S256().ScalarBaseMult(key.D.Bytes()) - key.Curve = ethCrypto.S256() - addr := ethCrypto.PubkeyToAddress(key.PublicKey) - - return &userKeys{ - BJJSK: &sk, - BJJPK: sk.Public(), - Addr: addr, - } -} diff --git a/test/ethclient.go b/test/ethclient.go index a9b630d..2956d69 100644 --- a/test/ethclient.go +++ b/test/ethclient.go @@ -674,7 +674,7 @@ func (c *Client) RollupL1UserTxERC20ETH( TokenID: common.TokenID(tokenID), ToIdx: common.Idx(toIdx), ToForgeL1TxsNum: &toForgeL1TxsNum, - Position: len(queue.L1TxQueue) - 1, + Position: len(queue.L1TxQueue), UserOrigin: true, }) if err != nil { diff --git a/test/til/txs.go b/test/til/txs.go index 7862fee..0ab20c4 100644 --- a/test/til/txs.go +++ b/test/til/txs.go @@ -15,6 +15,16 @@ import ( "github.com/iden3/go-iden3-crypto/babyjub" ) +func newBatchData(batchNum int) common.BatchData { + return common.BatchData{ + L1CoordinatorTxs: []common.L1Tx{}, + L2Txs: []common.L2Tx{}, + Batch: common.Batch{ + BatchNum: common.BatchNum(batchNum), + StateRoot: big.NewInt(0), ExitRoot: big.NewInt(0)}, + } +} + // Context contains the data of the test type Context struct { Instructions []instruction @@ -37,6 +47,7 @@ type Context struct { l1CoordinatorTxs []L1Tx l2Txs []L2Tx } + blockNum int64 } // NewContext returns a new Context @@ -51,14 +62,14 @@ func NewContext(rollupConstMaxL1UserTx int) *Context { idx: common.UserThreshold, // We use some placeholder values for StateRoot and ExitTree // because these values will never be nil - currBatch: common.BatchData{Batch: common.Batch{ - BatchNum: common.BatchNum(currBatchNum), - StateRoot: big.NewInt(0), ExitRoot: big.NewInt(0)}}, + currBatch: newBatchData(currBatchNum), currBatchNum: currBatchNum, // start with 2 queues, one for toForge, and the other for openToForge queues: make([][]L1Tx, 2), toForgeNum: 0, openToForge: 1, + //nolint:gomnd + blockNum: 2, // rollup genesis blockNum } } @@ -135,6 +146,7 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) { fromIdxName: inst.from, L1Tx: tx, } + tc.currBatchTest.l1CoordinatorTxs = append(tc.currBatchTest.l1CoordinatorTxs, testTx) case common.TxTypeCreateAccountDeposit, common.TxTypeCreateAccountDepositTransfer: // tx source: L1UserTx if err := tc.checkIfTokenIsRegistered(inst); err != nil { @@ -263,6 +275,7 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) { if err = tc.calculateIdxForL1Txs(true, tc.currBatchTest.l1CoordinatorTxs); err != nil { return nil, err } + tc.currBatch.L1Batch = true if err = tc.setIdxs(); err != nil { log.Error(err) return nil, err @@ -275,12 +288,20 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) { tc.queues = append(tc.queues, newQueue) } case typeNewBlock: + tc.currBlock.Block = common.Block{ + EthBlockNum: tc.blockNum, + } blocks = append(blocks, tc.currBlock) + tc.blockNum++ tc.currBlock = common.BlockData{} case typeAddToken: newToken := common.Token{ + EthAddr: ethCommon.BigToAddress(big.NewInt(int64(inst.tokenID * 100))), //nolint:gomnd + // Name: fmt.Sprintf("Token %d", inst.tokenID), + // Symbol: fmt.Sprintf("TK%d", inst.tokenID), + // Decimals: 18, TokenID: inst.tokenID, - EthBlockNum: int64(len(blocks)), + EthBlockNum: tc.blockNum, } if inst.tokenID != tc.lastRegisteredTokenID+1 { return nil, fmt.Errorf("Line %d: AddToken TokenID should be sequential, expected TokenID: %d, defined TokenID: %d", inst.lineNum, tc.lastRegisteredTokenID+1, inst.tokenID) @@ -353,10 +374,10 @@ func (tc *Context) setIdxs() error { tc.currBatch.L2Txs = append(tc.currBatch.L2Txs, testTx.L2Tx) } + tc.currBatch.Batch.LastIdx = int64(tc.idx - 1) // `-1` because tc.idx is the next available idx tc.currBlock.Batches = append(tc.currBlock.Batches, tc.currBatch) tc.currBatchNum++ - tc.currBatch = common.BatchData{Batch: tc.currBatch.Batch} - tc.currBatch.Batch.BatchNum = common.BatchNum(tc.currBatchNum) + tc.currBatch = newBatchData(tc.currBatchNum) tc.currBatchTest.l1CoordinatorTxs = nil tc.currBatchTest.l2Txs = nil return nil @@ -375,6 +396,8 @@ func (tc *Context) addToL1Queue(tx L1Tx) error { 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]) // 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 {