From e731b79e9613106dc7cae03caaa5654784214d85 Mon Sep 17 00:00:00 2001 From: Eduard S Date: Tue, 10 Nov 2020 11:27:50 +0100 Subject: [PATCH] Fix exit table, set delayed_withdrawn in exits - In exit table, `instant_withdrawn`, `delayed_withdraw_request`, and `delayed_withdrawn` were referencing batch_num. But these actions happen outside a batch, so they should reference a block_num. - Process delayed withdrawns: - In Synchronizer, first match a Rollup delayed withdrawn request, with the WDelayer deposit (via TxHash), and store the owner and token associated with the delayed withdrawn. - In HistoryDB: store the owner and token of a delayed withdrawal request in the exit_tree, and set delayed_withdrawn when the withdraw is done in the WDelayer. - Update dependency of sqlx to master - Last release of sqlx is from 2018 October, and it doesn't support `NamedQuery` with a slice of structs, which is used in this commit. --- api/api_test.go | 2 +- common/block.go | 20 +++++- common/exittree.go | 4 ++ db/historydb/historydb.go | 121 +++++++++++++++++---------------- db/historydb/historydb_test.go | 68 +++++++++++------- db/l2db/l2db.go | 4 +- db/migrations/0001.sql | 8 ++- db/utils.go | 3 +- eth/rollup.go | 2 + eth/wdelayer.go | 2 + go.mod | 2 +- go.sum | 2 + synchronizer/synchronizer.go | 38 +++++++++-- test/ethclient.go | 55 ++++++++++----- test/historydb.go | 17 ++--- test/til/txs.go | 8 +-- 16 files changed, 226 insertions(+), 130 deletions(-) diff --git a/api/api_test.go b/api/api_test.go index 4408264..ad47d37 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -222,7 +222,7 @@ func TestMain(m *testing.M) { // Gen exits and add them to DB const totalExits = 40 // TODO: UPDATE with til - exits := test.GenExitTree(totalExits, batches, accs) + exits := test.GenExitTree(totalExits, batches, accs, blocks) err = api.h.AddExitTree(exits) if err != nil { panic(err) diff --git a/common/block.go b/common/block.go index 0f12346..b8647ce 100644 --- a/common/block.go +++ b/common/block.go @@ -1,6 +1,7 @@ package common import ( + "math/big" "time" ethCommon "github.com/ethereum/go-ethereum/common" @@ -51,15 +52,30 @@ func NewAuctionData() AuctionData { } } +// WDelayerTransfer represents a transfer (either deposit or withdrawal) in the +// WDelayer smart contract +type WDelayerTransfer struct { + Owner ethCommon.Address + Token ethCommon.Address + Amount *big.Int + // TxHash ethCommon.Hash // hash of the transaction in which the wdelayer transfer happened +} + // WDelayerData contains information returned by the WDelayer smart contract type WDelayerData struct { - Vars *WDelayerVariables + Vars *WDelayerVariables + Deposits []WDelayerTransfer + DepositsByTxHash map[ethCommon.Hash]*WDelayerTransfer + Withdrawals []WDelayerTransfer } // NewWDelayerData creates an empty WDelayerData. func NewWDelayerData() WDelayerData { return WDelayerData{ - Vars: nil, + Vars: nil, + Deposits: make([]WDelayerTransfer, 0), + DepositsByTxHash: make(map[ethCommon.Hash]*WDelayerTransfer), + Withdrawals: make([]WDelayerTransfer, 0), } } diff --git a/common/exittree.go b/common/exittree.go index 2e68a77..0dd5bcc 100644 --- a/common/exittree.go +++ b/common/exittree.go @@ -3,6 +3,7 @@ package common import ( "math/big" + ethCommon "github.com/ethereum/go-ethereum/common" "github.com/iden3/go-merkletree" ) @@ -30,4 +31,7 @@ type WithdrawInfo struct { Idx Idx NumExitRoot BatchNum InstantWithdraw bool + TxHash ethCommon.Hash // hash of the transaction in which the withdraw happened + Owner ethCommon.Address + Token ethCommon.Address } diff --git a/db/historydb/historydb.go b/db/historydb/historydb.go index d1a9d87..cc62b3c 100644 --- a/db/historydb/historydb.go +++ b/db/historydb/historydb.go @@ -503,48 +503,72 @@ func (hdb *HistoryDB) addExitTree(d meddler.DB, exitTree []common.ExitInfo) erro ) } -type exitID struct { - batchNum int64 - idx int64 -} - -func (hdb *HistoryDB) updateExitTree(d meddler.DB, blockNum int64, - instantWithdrawn []exitID, delayedWithdrawRequest []exitID) error { - // helperQueryExitIDTuples is a helper function to build the query with - // an array of tuples in the arguments side built from []exitID - helperQueryExitIDTuples := func(queryTmpl string, blockNum int64, exits []exitID) (string, []interface{}) { - args := make([]interface{}, len(exits)*2+1) - holder := "" - args[0] = blockNum - for i, v := range exits { - args[1+i*2+0] = v.batchNum - args[1+i*2+1] = v.idx - holder += "(?, ?)," +func (hdb *HistoryDB) updateExitTree(d sqlx.Ext, blockNum int64, + rollupWithdrawals []common.WithdrawInfo, wDelayerWithdrawals []common.WDelayerTransfer) error { + type withdrawal struct { + BatchNum int64 `db:"batch_num"` + AccountIdx int64 `db:"account_idx"` + InstantWithdrawn *int64 `db:"instant_withdrawn"` + DelayedWithdrawRequest *int64 `db:"delayed_withdraw_request"` + DelayedWithdrawn *int64 `db:"delayed_withdrawn"` + Owner *ethCommon.Address `db:"owner"` + Token *ethCommon.Address `db:"token"` + } + withdrawals := make([]withdrawal, len(rollupWithdrawals)+len(wDelayerWithdrawals)) + for i := range rollupWithdrawals { + info := &rollupWithdrawals[i] + withdrawals[i] = withdrawal{ + BatchNum: int64(info.NumExitRoot), + AccountIdx: int64(info.Idx), + } + if info.InstantWithdraw { + withdrawals[i].InstantWithdrawn = &blockNum + } else { + withdrawals[i].DelayedWithdrawRequest = &blockNum + withdrawals[i].Owner = &info.Owner + withdrawals[i].Token = &info.Token } - query := fmt.Sprintf(queryTmpl, holder[:len(holder)-1]) - return hdb.db.Rebind(query), args } - - if len(instantWithdrawn) > 0 { - query, args := helperQueryExitIDTuples( - `UPDATE exit_tree SET instant_withdrawn = ? WHERE (batch_num, account_idx) IN (%s);`, - blockNum, - instantWithdrawn, - ) - if _, err := hdb.db.DB.Exec(query, args...); err != nil { - return err + for i := range wDelayerWithdrawals { + info := &wDelayerWithdrawals[i] + withdrawals[len(rollupWithdrawals)+i] = withdrawal{ + DelayedWithdrawn: &blockNum, + Owner: &info.Owner, + Token: &info.Token, } } - if len(delayedWithdrawRequest) > 0 { - query, args := helperQueryExitIDTuples( - `UPDATE exit_tree SET delayed_withdraw_request = ? WHERE (batch_num, account_idx) IN (%s);`, - blockNum, - delayedWithdrawRequest, - ) - if _, err := hdb.db.DB.Exec(query, args...); err != nil { + // In VALUES we set an initial row of NULLs to set the types of each + // variable passed as argument + query := ` + UPDATE exit_tree e SET + instant_withdrawn = d.instant_withdrawn, + delayed_withdraw_request = CASE + WHEN e.delayed_withdraw_request IS NOT NULL THEN e.delayed_withdraw_request + ELSE d.delayed_withdraw_request + END, + delayed_withdrawn = d.delayed_withdrawn, + owner = d.owner, + token = d.token + FROM (VALUES + (NULL::::BIGINT, NULL::::BIGINT, NULL::::BIGINT, NULL::::BIGINT, NULL::::BIGINT, NULL::::BYTEA, NULL::::BYTEA), + (:batch_num, + :account_idx, + :instant_withdrawn, + :delayed_withdraw_request, + :delayed_withdrawn, + :owner, + :token) + ) as d (batch_num, account_idx, instant_withdrawn, delayed_withdraw_request, delayed_withdrawn, owner, token) + WHERE + (d.batch_num IS NOT NULL AND e.batch_num = d.batch_num AND e.account_idx = d.account_idx) OR + (d.delayed_withdrawn IS NOT NULL AND e.delayed_withdrawn IS NULL AND e.owner = d.owner AND e.token = d.token) + ` + if len(withdrawals) > 0 { + if _, err := sqlx.NamedQuery(d, query, withdrawals); err != nil { return err } } + return nil } @@ -1210,7 +1234,7 @@ func (hdb *HistoryDB) setWDelayerVars(d meddler.DB, wDelayer *common.WDelayerVar // exist in the smart contracts. func (hdb *HistoryDB) SetInitialSCVars(rollup *common.RollupVariables, auction *common.AuctionVariables, wDelayer *common.WDelayerVariables) error { - txn, err := hdb.db.Begin() + txn, err := hdb.db.Beginx() if err != nil { return err } @@ -1242,7 +1266,7 @@ func (hdb *HistoryDB) SetInitialSCVars(rollup *common.RollupVariables, // the pagination system of the API/DB depends on this. Within blocks, all // items should also be in the correct order (Accounts, Tokens, Txs, etc.) func (hdb *HistoryDB) AddBlockSCData(blockData *common.BlockData) (err error) { - txn, err := hdb.db.Begin() + txn, err := hdb.db.Beginx() if err != nil { return err } @@ -1340,28 +1364,11 @@ func (hdb *HistoryDB) AddBlockSCData(blockData *common.BlockData) (err error) { } } - if len(blockData.Rollup.Withdrawals) > 0 { - instantWithdrawn := []exitID{} - delayedWithdrawRequest := []exitID{} - for _, withdraw := range blockData.Rollup.Withdrawals { - exitID := exitID{ - batchNum: int64(withdraw.NumExitRoot), - idx: int64(withdraw.Idx), - } - if withdraw.InstantWithdraw { - instantWithdrawn = append(instantWithdrawn, exitID) - } else { - delayedWithdrawRequest = append(delayedWithdrawRequest, exitID) - } - } - if err := hdb.updateExitTree(txn, blockData.Block.EthBlockNum, - instantWithdrawn, delayedWithdrawRequest); err != nil { - return err - } + if err := hdb.updateExitTree(txn, blockData.Block.EthBlockNum, + blockData.Rollup.Withdrawals, blockData.WDelayer.Withdrawals); err != nil { + return err } - // TODO: Process WDelayer withdrawals - return txn.Commit() } diff --git a/db/historydb/historydb_test.go b/db/historydb/historydb_test.go index e7ac563..b31e84f 100644 --- a/db/historydb/historydb_test.go +++ b/db/historydb/historydb_test.go @@ -481,7 +481,7 @@ func TestExitTree(t *testing.T) { const nAccounts = 3 accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches) assert.NoError(t, historyDB.AddAccounts(accs)) - exitTree := test.GenExitTree(nBatches, batches, accs) + exitTree := test.GenExitTree(nBatches, batches, accs, blocks) err = historyDB.AddExitTree(exitTree) assert.NoError(t, err) } @@ -509,7 +509,6 @@ func TestGetL1UserTxs(t *testing.T) { // Sanity check require.Equal(t, 1, len(blocks)) require.Equal(t, 5, len(blocks[0].Rollup.L1UserTxs)) - // fmt.Printf("DBG Blocks: %+v\n", blocks) toForgeL1TxsNum := int64(1) @@ -597,14 +596,15 @@ func TestUpdateExitTree(t *testing.T) { ForceExit(1) A: 100 ForceExit(1) B: 80 - Exit(1) C: 50 (200) - Exit(1) D: 30 (200) + Exit(1) C: 50 (172) + Exit(1) D: 30 (172) > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{3} > batchL1 // forge L1UserTxs{3}, freeze defined L1UserTxs{nil} > block // blockNum=3 > block // blockNum=4 (empty block) + > block // blockNum=5 (empty block) ` tc := til.NewContext(common.RollupConstMaxL1UserTx) @@ -617,39 +617,33 @@ func TestUpdateExitTree(t *testing.T) { err = tc.FillBlocksExtra(blocks, &tilCfgExtra) assert.Nil(t, err) - // Add all blocks except for the last one - for i := range blocks[:len(blocks)-1] { + // Add all blocks except for the last two + for i := range blocks[:len(blocks)-2] { err = historyDB.AddBlockSCData(&blocks[i]) require.Nil(t, err) } - // Add withdraws to the last block, and insert block into the DB - block := &blocks[len(blocks)-1] + // Add withdraws to the second-to-last block, and insert block into the DB + block := &blocks[len(blocks)-2] require.Equal(t, int64(4), block.Block.EthBlockNum) + tokenAddr := blocks[0].Rollup.AddedTokens[0].EthAddr + // block.WDelayer.Deposits = append(block.WDelayer.Deposits, + // common.WDelayerTransfer{Owner: tc.UsersByIdx[257].Addr, Token: tokenAddr, Amount: big.NewInt(80)}, // 257 + // common.WDelayerTransfer{Owner: tc.UsersByIdx[259].Addr, Token: tokenAddr, Amount: big.NewInt(15)}, // 259 + // ) block.Rollup.Withdrawals = append(block.Rollup.Withdrawals, common.WithdrawInfo{Idx: 256, NumExitRoot: 4, InstantWithdraw: true}, - common.WithdrawInfo{Idx: 257, NumExitRoot: 4, InstantWithdraw: false}, + common.WithdrawInfo{Idx: 257, NumExitRoot: 4, InstantWithdraw: false, + Owner: tc.UsersByIdx[257].Addr, Token: tokenAddr}, common.WithdrawInfo{Idx: 258, NumExitRoot: 3, InstantWithdraw: true}, - common.WithdrawInfo{Idx: 259, NumExitRoot: 3, InstantWithdraw: false}, + common.WithdrawInfo{Idx: 259, NumExitRoot: 3, InstantWithdraw: false, + Owner: tc.UsersByIdx[259].Addr, Token: tokenAddr}, ) err = historyDB.addBlock(historyDB.db, &block.Block) require.Nil(t, err) - // update exit trees in DB - instantWithdrawn := []exitID{} - delayedWithdrawRequest := []exitID{} - for _, withdraw := range block.Rollup.Withdrawals { - exitID := exitID{ - batchNum: int64(withdraw.NumExitRoot), - idx: int64(withdraw.Idx), - } - if withdraw.InstantWithdraw { - instantWithdrawn = append(instantWithdrawn, exitID) - } else { - delayedWithdrawRequest = append(delayedWithdrawRequest, exitID) - } - } - err = historyDB.updateExitTree(historyDB.db, block.Block.EthBlockNum, instantWithdrawn, delayedWithdrawRequest) + err = historyDB.updateExitTree(historyDB.db, block.Block.EthBlockNum, + block.Rollup.Withdrawals, block.WDelayer.Withdrawals) require.Nil(t, err) // Check that exits in DB match with the expected values @@ -668,6 +662,30 @@ func TestUpdateExitTree(t *testing.T) { assert.Equal(t, &block.Block.EthBlockNum, dbExitsByIdx[withdraw.Idx].DelayedWithdrawRequest) } } + + // Add delayed withdraw to the last block, and insert block into the DB + block = &blocks[len(blocks)-1] + require.Equal(t, int64(5), block.Block.EthBlockNum) + block.WDelayer.Withdrawals = append(block.WDelayer.Withdrawals, + common.WDelayerTransfer{ + Owner: tc.UsersByIdx[257].Addr, + Token: tokenAddr, + Amount: big.NewInt(80), + }) + err = historyDB.addBlock(historyDB.db, &block.Block) + require.Nil(t, err) + + err = historyDB.updateExitTree(historyDB.db, block.Block.EthBlockNum, + block.Rollup.Withdrawals, block.WDelayer.Withdrawals) + require.Nil(t, err) + + // Check that delayed withdrawn has been set + dbExits, err = historyDB.GetAllExits() + require.Nil(t, err) + for _, dbExit := range dbExits { + dbExitsByIdx[dbExit.AccountIdx] = dbExit + } + require.Equal(t, &block.Block.EthBlockNum, dbExitsByIdx[257].DelayedWithdrawn) } // setTestBlocks WARNING: this will delete the blocks and recreate them diff --git a/db/l2db/l2db.go b/db/l2db/l2db.go index df53255..a90d77e 100644 --- a/db/l2db/l2db.go +++ b/db/l2db/l2db.go @@ -235,7 +235,7 @@ func (l2db *L2DB) InvalidateTxs(txIDs []common.TxID, batchNum common.BatchNum) e // CheckNonces 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 -> Invalid func (l2db *L2DB) CheckNonces(updatedAccounts []common.Account, batchNum common.BatchNum) (err error) { - txn, err := l2db.db.Begin() + txn, err := l2db.db.Beginx() if err != nil { return err } @@ -280,7 +280,7 @@ func (l2db *L2DB) Reorg(lastValidBatch common.BatchNum) error { // Purge deletes transactions that have been forged or marked as invalid for longer than the safety period // it also deletes txs that has been in the L2DB for longer than the ttl if maxTxs has been exceeded func (l2db *L2DB) Purge(currentBatchNum common.BatchNum) (err error) { - txn, err := l2db.db.Begin() + txn, err := l2db.db.Beginx() if err != nil { return err } diff --git a/db/migrations/0001.sql b/db/migrations/0001.sql index 3bf9938..1f1c4bf 100644 --- a/db/migrations/0001.sql +++ b/db/migrations/0001.sql @@ -109,9 +109,11 @@ CREATE TABLE exit_tree ( account_idx BIGINT REFERENCES account (idx) ON DELETE CASCADE, merkle_proof BYTEA NOT NULL, balance BYTEA NOT NULL, - instant_withdrawn BIGINT REFERENCES batch (batch_num) ON DELETE SET NULL, - delayed_withdraw_request BIGINT REFERENCES batch (batch_num) ON DELETE SET NULL, - delayed_withdrawn BIGINT REFERENCES batch (batch_num) ON DELETE SET NULL + instant_withdrawn BIGINT REFERENCES block (eth_block_num) ON DELETE SET NULL, + delayed_withdraw_request BIGINT REFERENCES block (eth_block_num) ON DELETE SET NULL, + owner BYTEA, + token BYTEA, + delayed_withdrawn BIGINT REFERENCES block (eth_block_num) ON DELETE SET NULL ); -- +migrate StatementBegin diff --git a/db/utils.go b/db/utils.go index 2e62c17..8f3e1e1 100644 --- a/db/utils.go +++ b/db/utils.go @@ -1,7 +1,6 @@ package db import ( - "database/sql" "encoding/base64" "fmt" "math/big" @@ -180,7 +179,7 @@ func SlicePtrsToSlice(slice interface{}) interface{} { } // Rollback an sql transaction, and log the error if it's not nil -func Rollback(txn *sql.Tx) { +func Rollback(txn *sqlx.Tx) { err := txn.Rollback() if err != nil { log.Errorw("Rollback", "err", err) diff --git a/eth/rollup.go b/eth/rollup.go index 23d14bc..bbe9739 100644 --- a/eth/rollup.go +++ b/eth/rollup.go @@ -91,6 +91,7 @@ type RollupEventWithdraw struct { Idx uint64 NumExitRoot uint64 InstantWithdraw bool + TxHash ethCommon.Hash // Hash of the transaction that generated this event } // RollupEvents is the list of events in a block of the Rollup Smart Contract @@ -577,6 +578,7 @@ func (c *RollupClient) RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethC if instantWithdraw == 1 { withdraw.InstantWithdraw = true } + withdraw.TxHash = vLog.TxHash rollupEvents.Withdraw = append(rollupEvents.Withdraw, withdraw) } } diff --git a/eth/wdelayer.go b/eth/wdelayer.go index 2a38f9b..05dcad7 100644 --- a/eth/wdelayer.go +++ b/eth/wdelayer.go @@ -30,6 +30,7 @@ type WDelayerEventDeposit struct { Token ethCommon.Address Amount *big.Int DepositTimestamp uint64 + TxHash ethCommon.Hash // Hash of the transaction that generated this event } // WDelayerEventWithdraw is an event of the WithdrawalDelayer Smart Contract @@ -411,6 +412,7 @@ func (c *WDelayerClient) WDelayerEventsByBlock(blockNum int64) (*WDelayerEvents, } deposit.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes()) deposit.Token = ethCommon.BytesToAddress(vLog.Topics[2].Bytes()) + deposit.TxHash = vLog.TxHash wdelayerEvents.Deposit = append(wdelayerEvents.Deposit, deposit) case logWDelayerWithdraw: diff --git a/go.mod b/go.mod index 80e98ad..e6205e6 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/iden3/go-iden3-crypto v0.0.6-0.20201016142444-94e92e88fb4e github.com/iden3/go-merkletree v0.0.0-20201103115630-ad30c8309b44 github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a - github.com/jmoiron/sqlx v1.2.0 + github.com/jmoiron/sqlx v1.2.1-0.20200615141059-0794cb1f47ee github.com/joho/godotenv v1.3.0 github.com/lib/pq v1.8.0 github.com/mattn/go-sqlite3 v2.0.3+incompatible diff --git a/go.sum b/go.sum index 1432eea..1b9b0cc 100644 --- a/go.sum +++ b/go.sum @@ -343,6 +343,8 @@ github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/jmoiron/sqlx v1.2.1-0.20200615141059-0794cb1f47ee h1:59lyMGvZusByi7Rvctn8cxdVAjhiOnqCv3G5DrYApYQ= +github.com/jmoiron/sqlx v1.2.1-0.20200615141059-0794cb1f47ee/go.mod h1:ClpsPFzLpSBl7MvJ+BhV0JHz4vmKRBarpvZ9644v9Oo= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= diff --git a/synchronizer/synchronizer.go b/synchronizer/synchronizer.go index bc2df8b..52bcdde 100644 --- a/synchronizer/synchronizer.go +++ b/synchronizer/synchronizer.go @@ -213,17 +213,30 @@ func (s *Synchronizer) Sync2(ctx context.Context, lastSavedBlock *common.Block) } // Get data from the WithdrawalDelayer contract - wdelayerData, err := s.wdelayerSync(ethBlock) + wDelayerData, err := s.wdelayerSync(ethBlock) if err != nil { return nil, nil, err } + for i := range rollupData.Withdrawals { + withdrawal := &rollupData.Withdrawals[i] + if !withdrawal.InstantWithdraw { + wDelayerTransfer, ok := wDelayerData.DepositsByTxHash[withdrawal.TxHash] + if !ok { + return nil, nil, fmt.Errorf("WDelayer deposit corresponding to " + + "non-instant rollup withdrawal not found") + } + withdrawal.Owner = wDelayerTransfer.Owner + withdrawal.Token = wDelayerTransfer.Token + } + } + // Group all the block data into the structs to save into HistoryDB blockData := common.BlockData{ Block: *ethBlock, Rollup: *rollupData, Auction: *auctionData, - WDelayer: *wdelayerData, + WDelayer: *wDelayerData, } // log.Debugw("Sync()", "block", blockData) @@ -481,7 +494,6 @@ func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*common.RollupData, e } // Get Batch information - // fmt.Printf("DBG: %#v\n", forgeBatchArgs.FeeIdxCoordinator) batch := common.Batch{ BatchNum: batchNum, EthBlockNum: blockNum, @@ -547,6 +559,7 @@ func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*common.RollupData, e Idx: common.Idx(evtWithdraw.Idx), NumExitRoot: common.BatchNum(evtWithdraw.NumExitRoot), InstantWithdraw: evtWithdraw.InstantWithdraw, + TxHash: evtWithdraw.TxHash, }) } @@ -677,10 +690,25 @@ func (s *Synchronizer) wdelayerSync(ethBlock *common.Block) (*common.WDelayerDat return nil, eth.ErrBlockHashMismatchEvent } + for _, evt := range wDelayerEvents.Deposit { + wDelayerData.Deposits = append(wDelayerData.Deposits, common.WDelayerTransfer{ + Owner: evt.Owner, + Token: evt.Token, + Amount: evt.Amount, + }) + wDelayerData.DepositsByTxHash[evt.TxHash] = + &wDelayerData.Deposits[len(wDelayerData.Deposits)-1] + } + for _, evt := range wDelayerEvents.Withdraw { + wDelayerData.Withdrawals = append(wDelayerData.Withdrawals, common.WDelayerTransfer{ + Owner: evt.Owner, + Token: evt.Token, + Amount: evt.Amount, + }) + } + varsUpdate := false - // TODO Deposit - // TODO Withdraw // TODO EscapeHatchWithdrawal for range wDelayerEvents.EmergencyModeEnabled { s.vars.WDelayer.EmergencyMode = true diff --git a/test/ethclient.go b/test/ethclient.go index 536eee4..ea30d70 100644 --- a/test/ethclient.go +++ b/test/ethclient.go @@ -45,6 +45,16 @@ func (w *WDelayerBlock) addTransaction(tx *types.Transaction) *types.Transaction return tx } +func (w *WDelayerBlock) deposit(txHash ethCommon.Hash, owner, token ethCommon.Address, amount *big.Int) { + w.Events.Deposit = append(w.Events.Deposit, eth.WDelayerEventDeposit{ + Owner: owner, + Token: token, + Amount: amount, + DepositTimestamp: uint64(w.Eth.Time), + TxHash: txHash, + }) +} + // RollupBlock stores all the data related to the Rollup SC from an ethereum block type RollupBlock struct { State eth.RollupState @@ -57,6 +67,7 @@ type RollupBlock struct { func (r *RollupBlock) addTransaction(tx *types.Transaction) *types.Transaction { txHash := tx.Hash() + fmt.Printf("DBG txHash %v\n", txHash.Hex()) r.Txs[txHash] = tx return tx } @@ -769,29 +780,36 @@ func (c *Client) RollupWithdrawMerkleProof(babyPubKey *babyjub.PublicKey, tokenI } r.State.ExitNullifierMap[numExitRoot][idx] = true + type data struct { + BabyPubKey *babyjub.PublicKey + TokenID uint32 + NumExitRoot int64 + Idx int64 + Amount *big.Int + Siblings []*big.Int + InstantWithdraw bool + } + tx = r.addTransaction(newTransaction("withdrawMerkleProof", data{ + BabyPubKey: babyPubKey, + TokenID: tokenID, + NumExitRoot: numExitRoot, + Idx: idx, + Amount: amount, + Siblings: siblings, + InstantWithdraw: instantWithdraw, + })) r.Events.Withdraw = append(r.Events.Withdraw, eth.RollupEventWithdraw{ Idx: uint64(idx), NumExitRoot: uint64(numExitRoot), InstantWithdraw: instantWithdraw, + TxHash: tx.Hash(), }) - type data struct { - babyPubKey *babyjub.PublicKey - tokenID uint32 - numExitRoot int64 - idx int64 - amount *big.Int - siblings []*big.Int - instantWithdraw bool - } - return r.addTransaction(newTransaction("withdrawMerkleProof", data{ - babyPubKey: babyPubKey, - tokenID: tokenID, - numExitRoot: numExitRoot, - idx: idx, - amount: amount, - siblings: siblings, - instantWithdraw: instantWithdraw, - })), nil + + if !instantWithdraw { + w := nextBlock.WDelayer + w.deposit(tx.Hash(), *c.addr, r.State.TokenList[int(tokenID)], amount) + } + return tx, nil } type transactionData struct { @@ -804,6 +822,7 @@ func newTransaction(name string, value interface{}) *types.Transaction { if err != nil { panic(err) } + fmt.Printf("DBG dataJSON: %v\n", string(data)) return types.NewTransaction(0, ethCommon.Address{}, nil, 0, nil, data) } diff --git a/test/historydb.go b/test/historydb.go index b963889..38898bb 100644 --- a/test/historydb.go +++ b/test/historydb.go @@ -372,7 +372,7 @@ func GenBids(nBids int, blocks []common.Block, coords []common.Coordinator) []co // GenExitTree generates an exitTree (as an array of Exits) //nolint:gomnd -func GenExitTree(n int, batches []common.Batch, accounts []common.Account) []common.ExitInfo { +func GenExitTree(n int, batches []common.Batch, accounts []common.Account, blocks []common.Block) []common.ExitInfo { exitTree := make([]common.ExitInfo, n) for i := 0; i < n; i++ { exitTree[i] = common.ExitInfo{ @@ -397,17 +397,14 @@ func GenExitTree(n int, batches []common.Batch, accounts []common.Account) []com Balance: big.NewInt(int64(i) * 1000), } if i%2 == 0 { - instant := new(int64) - *instant = int64(batches[(i+1)%len(batches)].BatchNum) - exitTree[i].InstantWithdrawn = instant + instant := int64(blocks[i%len(blocks)].EthBlockNum) + exitTree[i].InstantWithdrawn = &instant } else if i%3 == 0 { - delayedReq := new(int64) - *delayedReq = int64(batches[(i+1)%len(batches)].BatchNum) - exitTree[i].DelayedWithdrawRequest = delayedReq + delayedReq := int64(blocks[i%len(blocks)].EthBlockNum) + exitTree[i].DelayedWithdrawRequest = &delayedReq if i%9 == 0 { - delayed := new(int64) - *delayed = int64(batches[(i+2)%len(batches)].BatchNum) - exitTree[i].DelayedWithdrawn = delayed + delayed := int64(blocks[i%len(blocks)].EthBlockNum) + exitTree[i].DelayedWithdrawn = &delayed } } } diff --git a/test/til/txs.go b/test/til/txs.go index 8c74255..829261b 100644 --- a/test/til/txs.go +++ b/test/til/txs.go @@ -51,7 +51,7 @@ type Context struct { Instructions []instruction userNames []string Users map[string]*User // Name -> *User - usersByIdx map[int]*User + UsersByIdx map[int]*User accountsByIdx map[int]*Account LastRegisteredTokenID common.TokenID l1CreatedAccounts map[string]*Account // (Name, TokenID) -> *Account @@ -81,7 +81,7 @@ func NewContext(rollupConstMaxL1UserTx int) *Context { return &Context{ Users: make(map[string]*User), l1CreatedAccounts: make(map[string]*Account), - usersByIdx: make(map[int]*User), + UsersByIdx: make(map[int]*User), accountsByIdx: make(map[int]*Account), LastRegisteredTokenID: 0, @@ -393,7 +393,7 @@ func (tc *Context) calculateIdxForL1Txs(isCoordinatorTxs bool, txs []L1Tx) error } tc.l1CreatedAccounts[idxTokenIDToString(tx.fromIdxName, tx.L1Tx.TokenID)] = tc.Users[tx.fromIdxName].Accounts[tx.L1Tx.TokenID] tc.accountsByIdx[tc.idx] = tc.Users[tx.fromIdxName].Accounts[tx.L1Tx.TokenID] - tc.usersByIdx[tc.idx] = tc.Users[tx.fromIdxName] + tc.UsersByIdx[tc.idx] = tc.Users[tx.fromIdxName] tc.idx++ } if isCoordinatorTxs { @@ -745,7 +745,7 @@ func (tc *Context) FillBlocksExtra(blocks []common.BlockData, cfg *ConfigExtra) tx := &l1Txs[k] if tx.Type == common.TxTypeCreateAccountDeposit || tx.Type == common.TxTypeCreateAccountDepositTransfer { - user, ok := tc.usersByIdx[tc.extra.idx] + user, ok := tc.UsersByIdx[tc.extra.idx] if !ok { return fmt.Errorf("Created account with idx: %v not found", tc.extra.idx) }