You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1030 lines
32 KiB

Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
  1. package historydb
  2. import (
  3. "database/sql"
  4. "math"
  5. "math/big"
  6. "os"
  7. "testing"
  8. "time"
  9. ethCommon "github.com/ethereum/go-ethereum/common"
  10. "github.com/hermeznetwork/hermez-node/common"
  11. dbUtils "github.com/hermeznetwork/hermez-node/db"
  12. "github.com/hermeznetwork/hermez-node/log"
  13. "github.com/hermeznetwork/hermez-node/test"
  14. "github.com/hermeznetwork/hermez-node/test/til"
  15. "github.com/hermeznetwork/tracerr"
  16. "github.com/stretchr/testify/assert"
  17. "github.com/stretchr/testify/require"
  18. )
  19. var historyDB *HistoryDB
  20. // In order to run the test you need to run a Posgres DB with
  21. // a database named "history" that is accessible by
  22. // user: "hermez"
  23. // pass: set it using the env var POSTGRES_PASS
  24. // This can be achieved by running: POSTGRES_PASS=your_strong_pass && sudo docker run --rm --name hermez-db-test -p 5432:5432 -e POSTGRES_DB=history -e POSTGRES_USER=hermez -e POSTGRES_PASSWORD=$POSTGRES_PASS -d postgres && sleep 2s && sudo docker exec -it hermez-db-test psql -a history -U hermez -c "CREATE DATABASE l2;"
  25. // After running the test you can stop the container by running: sudo docker kill hermez-db-test
  26. // If you already did that for the L2DB you don't have to do it again
  27. func TestMain(m *testing.M) {
  28. // init DB
  29. pass := os.Getenv("POSTGRES_PASS")
  30. db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
  31. if err != nil {
  32. panic(err)
  33. }
  34. historyDB = NewHistoryDB(db)
  35. if err != nil {
  36. panic(err)
  37. }
  38. // Run tests
  39. result := m.Run()
  40. // Close DB
  41. if err := db.Close(); err != nil {
  42. log.Error("Error closing the history DB:", err)
  43. }
  44. os.Exit(result)
  45. }
  46. func TestBlocks(t *testing.T) {
  47. var fromBlock, toBlock int64
  48. fromBlock = 0
  49. toBlock = 7
  50. // Reset DB
  51. test.WipeDB(historyDB.DB())
  52. // Generate blocks using til
  53. set1 := `
  54. Type: Blockchain
  55. // block 0 is stored as default in the DB
  56. // block 1 does not exist
  57. > block // blockNum=2
  58. > block // blockNum=3
  59. > block // blockNum=4
  60. > block // blockNum=5
  61. > block // blockNum=6
  62. `
  63. tc := til.NewContext(1)
  64. blocks, err := tc.GenerateBlocks(set1)
  65. require.NoError(t, err)
  66. // Save timestamp of a block with UTC and change it without UTC
  67. timestamp := time.Now().Add(time.Second * 13)
  68. blocks[fromBlock].Block.Timestamp = timestamp
  69. // Insert blocks into DB
  70. for i := 0; i < len(blocks); i++ {
  71. err := historyDB.AddBlock(&blocks[i].Block)
  72. assert.NoError(t, err)
  73. }
  74. // Add block 0 to the generated blocks
  75. blocks = append(
  76. []common.BlockData{{Block: test.Block0}}, //nolint:gofmt
  77. blocks...,
  78. )
  79. // Get all blocks from DB
  80. fetchedBlocks, err := historyDB.GetBlocks(fromBlock, toBlock)
  81. assert.Equal(t, len(blocks), len(fetchedBlocks))
  82. // Compare generated vs getted blocks
  83. assert.NoError(t, err)
  84. for i := range fetchedBlocks {
  85. assertEqualBlock(t, &blocks[i].Block, &fetchedBlocks[i])
  86. }
  87. // Compare saved timestamp vs getted
  88. nameZoneUTC, offsetUTC := timestamp.UTC().Zone()
  89. zoneFetchedBlock, offsetFetchedBlock := fetchedBlocks[fromBlock].Timestamp.Zone()
  90. assert.Equal(t, nameZoneUTC, zoneFetchedBlock)
  91. assert.Equal(t, offsetUTC, offsetFetchedBlock)
  92. // Get blocks from the DB one by one
  93. for i := int64(2); i < toBlock; i++ { // avoid block 0 for simplicity
  94. fetchedBlock, err := historyDB.GetBlock(i)
  95. assert.NoError(t, err)
  96. assertEqualBlock(t, &blocks[i-1].Block, fetchedBlock)
  97. }
  98. // Get last block
  99. lastBlock, err := historyDB.GetLastBlock()
  100. assert.NoError(t, err)
  101. assertEqualBlock(t, &blocks[len(blocks)-1].Block, lastBlock)
  102. }
  103. func assertEqualBlock(t *testing.T, expected *common.Block, actual *common.Block) {
  104. assert.Equal(t, expected.Num, actual.Num)
  105. assert.Equal(t, expected.Hash, actual.Hash)
  106. assert.Equal(t, expected.Timestamp.Unix(), actual.Timestamp.Unix())
  107. }
  108. func TestBatches(t *testing.T) {
  109. // Reset DB
  110. test.WipeDB(historyDB.DB())
  111. // Generate batches using til (and blocks for foreign key)
  112. set := `
  113. Type: Blockchain
  114. AddToken(1) // Will have value in USD
  115. AddToken(2) // Will NOT have value in USD
  116. CreateAccountDeposit(1) A: 2000
  117. CreateAccountDeposit(2) A: 2000
  118. CreateAccountDeposit(1) B: 1000
  119. CreateAccountDeposit(2) B: 1000
  120. > batchL1
  121. > batchL1
  122. Transfer(1) A-B: 100 (5)
  123. Transfer(2) B-A: 100 (199)
  124. > batch // batchNum=2, L2 only batch, forges transfers (mixed case of with(out) USD value)
  125. > block
  126. Transfer(1) A-B: 100 (5)
  127. > batch // batchNum=3, L2 only batch, forges transfer (with USD value)
  128. Transfer(2) B-A: 100 (199)
  129. > batch // batchNum=4, L2 only batch, forges transfer (without USD value)
  130. > block
  131. `
  132. tc := til.NewContext(common.RollupConstMaxL1UserTx)
  133. tilCfgExtra := til.ConfigExtra{
  134. BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
  135. CoordUser: "A",
  136. }
  137. blocks, err := tc.GenerateBlocks(set)
  138. require.Nil(t, err)
  139. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  140. assert.Nil(t, err)
  141. // Insert to DB
  142. batches := []common.Batch{}
  143. tokensValue := make(map[common.TokenID]float64)
  144. lastL1TxsNum := new(int64)
  145. lastL1BatchBlockNum := int64(0)
  146. for _, block := range blocks {
  147. // Insert block
  148. assert.NoError(t, historyDB.AddBlock(&block.Block))
  149. // Insert tokens
  150. for i, token := range block.Rollup.AddedTokens {
  151. assert.NoError(t, historyDB.AddToken(&token)) //nolint:gosec
  152. if i%2 != 0 {
  153. // Set value to the token
  154. value := (float64(i) + 5) * 5.389329
  155. assert.NoError(t, historyDB.UpdateTokenValue(token.Symbol, value))
  156. tokensValue[token.TokenID] = value / math.Pow(10, float64(token.Decimals))
  157. }
  158. }
  159. // Combine all generated batches into single array
  160. for _, batch := range block.Rollup.Batches {
  161. batches = append(batches, batch.Batch)
  162. forgeTxsNum := batch.Batch.ForgeL1TxsNum
  163. if forgeTxsNum != nil && (lastL1TxsNum == nil || *lastL1TxsNum < *forgeTxsNum) {
  164. *lastL1TxsNum = *forgeTxsNum
  165. lastL1BatchBlockNum = batch.Batch.EthBlockNum
  166. }
  167. }
  168. }
  169. // Insert batches
  170. assert.NoError(t, historyDB.AddBatches(batches))
  171. // Set expected total fee
  172. for _, batch := range batches {
  173. total := .0
  174. for tokenID, amount := range batch.CollectedFees {
  175. af := new(big.Float).SetInt(amount)
  176. amountFloat, _ := af.Float64()
  177. total += tokensValue[tokenID] * amountFloat
  178. }
  179. batch.TotalFeesUSD = &total
  180. }
  181. // Get batches from the DB
  182. fetchedBatches, err := historyDB.GetBatches(0, common.BatchNum(len(batches)+1))
  183. assert.NoError(t, err)
  184. assert.Equal(t, len(batches), len(fetchedBatches))
  185. for i, fetchedBatch := range fetchedBatches {
  186. assert.Equal(t, batches[i], fetchedBatch)
  187. }
  188. // Test GetLastBatchNum
  189. fetchedLastBatchNum, err := historyDB.GetLastBatchNum()
  190. assert.NoError(t, err)
  191. assert.Equal(t, batches[len(batches)-1].BatchNum, fetchedLastBatchNum)
  192. // Test GetLastL1TxsNum
  193. fetchedLastL1TxsNum, err := historyDB.GetLastL1TxsNum()
  194. assert.NoError(t, err)
  195. assert.Equal(t, lastL1TxsNum, fetchedLastL1TxsNum)
  196. // Test GetLastL1BatchBlockNum
  197. fetchedLastL1BatchBlockNum, err := historyDB.GetLastL1BatchBlockNum()
  198. assert.NoError(t, err)
  199. assert.Equal(t, lastL1BatchBlockNum, fetchedLastL1BatchBlockNum)
  200. }
  201. func TestBids(t *testing.T) {
  202. const fromBlock int64 = 1
  203. const toBlock int64 = 5
  204. // Prepare blocks in the DB
  205. blocks := setTestBlocks(fromBlock, toBlock)
  206. // Generate fake coordinators
  207. const nCoords = 5
  208. coords := test.GenCoordinators(nCoords, blocks)
  209. err := historyDB.AddCoordinators(coords)
  210. assert.NoError(t, err)
  211. // Generate fake bids
  212. const nBids = 20
  213. bids := test.GenBids(nBids, blocks, coords)
  214. err = historyDB.AddBids(bids)
  215. assert.NoError(t, err)
  216. // Fetch bids
  217. fetchedBids, err := historyDB.GetAllBids()
  218. assert.NoError(t, err)
  219. // Compare fetched bids vs generated bids
  220. for i, bid := range fetchedBids {
  221. assert.Equal(t, bids[i], bid)
  222. }
  223. }
  224. func TestTokens(t *testing.T) {
  225. const fromBlock int64 = 1
  226. const toBlock int64 = 5
  227. // Prepare blocks in the DB
  228. blocks := setTestBlocks(fromBlock, toBlock)
  229. // Generate fake tokens
  230. const nTokens = 5
  231. tokens, ethToken := test.GenTokens(nTokens, blocks)
  232. err := historyDB.AddTokens(tokens)
  233. assert.NoError(t, err)
  234. tokens = append([]common.Token{ethToken}, tokens...)
  235. limit := uint(10)
  236. // Fetch tokens
  237. fetchedTokens, _, err := historyDB.GetTokens(nil, nil, "", nil, &limit, OrderAsc)
  238. assert.NoError(t, err)
  239. // Compare fetched tokens vs generated tokens
  240. // All the tokens should have USDUpdate setted by the DB trigger
  241. for i, token := range fetchedTokens {
  242. assert.Equal(t, tokens[i].TokenID, token.TokenID)
  243. assert.Equal(t, tokens[i].EthBlockNum, token.EthBlockNum)
  244. assert.Equal(t, tokens[i].EthAddr, token.EthAddr)
  245. assert.Equal(t, tokens[i].Name, token.Name)
  246. assert.Equal(t, tokens[i].Symbol, token.Symbol)
  247. assert.Nil(t, token.USD)
  248. assert.Nil(t, token.USDUpdate)
  249. }
  250. // Update token value
  251. for i, token := range tokens {
  252. value := 1.01 * float64(i)
  253. assert.NoError(t, historyDB.UpdateTokenValue(token.Symbol, value))
  254. }
  255. // Fetch tokens
  256. fetchedTokens, _, err = historyDB.GetTokens(nil, nil, "", nil, &limit, OrderAsc)
  257. assert.NoError(t, err)
  258. // Compare fetched tokens vs generated tokens
  259. // All the tokens should have USDUpdate setted by the DB trigger
  260. for i, token := range fetchedTokens {
  261. value := 1.01 * float64(i)
  262. assert.Equal(t, value, *token.USD)
  263. nameZone, offset := token.USDUpdate.Zone()
  264. assert.Equal(t, "UTC", nameZone)
  265. assert.Equal(t, 0, offset)
  266. }
  267. }
  268. func TestAccounts(t *testing.T) {
  269. const fromBlock int64 = 1
  270. const toBlock int64 = 5
  271. // Prepare blocks in the DB
  272. blocks := setTestBlocks(fromBlock, toBlock)
  273. // Generate fake tokens
  274. const nTokens = 5
  275. tokens, ethToken := test.GenTokens(nTokens, blocks)
  276. err := historyDB.AddTokens(tokens)
  277. assert.NoError(t, err)
  278. tokens = append([]common.Token{ethToken}, tokens...)
  279. // Generate fake batches
  280. const nBatches = 10
  281. batches := test.GenBatches(nBatches, blocks)
  282. err = historyDB.AddBatches(batches)
  283. assert.NoError(t, err)
  284. // Generate fake accounts
  285. const nAccounts = 3
  286. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  287. err = historyDB.AddAccounts(accs)
  288. assert.NoError(t, err)
  289. // Fetch accounts
  290. fetchedAccs, err := historyDB.GetAllAccounts()
  291. assert.NoError(t, err)
  292. // Compare fetched accounts vs generated accounts
  293. for i, acc := range fetchedAccs {
  294. accs[i].Balance = nil
  295. assert.Equal(t, accs[i], acc)
  296. }
  297. }
  298. func TestTxs(t *testing.T) {
  299. // Reset DB
  300. test.WipeDB(historyDB.DB())
  301. set := `
  302. Type: Blockchain
  303. AddToken(1)
  304. AddToken(2)
  305. CreateAccountDeposit(1) A: 10
  306. CreateAccountDeposit(1) B: 10
  307. > batchL1
  308. > batchL1
  309. > block
  310. CreateAccountDepositTransfer(1) C-A: 20, 10
  311. CreateAccountCoordinator(1) User0
  312. > batchL1
  313. > batchL1
  314. > block
  315. Deposit(1) B: 10
  316. Deposit(1) C: 10
  317. Transfer(1) C-A : 10 (1)
  318. Transfer(1) B-C : 10 (1)
  319. Transfer(1) A-B : 10 (1)
  320. Exit(1) A: 10 (1)
  321. > batch
  322. > block
  323. DepositTransfer(1) A-B: 10, 10
  324. > batchL1
  325. > block
  326. ForceTransfer(1) A-B: 10
  327. ForceExit(1) A: 5
  328. > batchL1
  329. > batchL1
  330. > block
  331. CreateAccountDeposit(2) D: 10
  332. > batchL1
  333. > block
  334. CreateAccountDeposit(2) E: 10
  335. > batchL1
  336. > batchL1
  337. > block
  338. `
  339. tc := til.NewContext(common.RollupConstMaxL1UserTx)
  340. tilCfgExtra := til.ConfigExtra{
  341. BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
  342. CoordUser: "A",
  343. }
  344. blocks, err := tc.GenerateBlocks(set)
  345. require.Nil(t, err)
  346. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  347. assert.Nil(t, err)
  348. // Sanity check
  349. require.Equal(t, 7, len(blocks))
  350. require.Equal(t, 2, len(blocks[0].Rollup.L1UserTxs))
  351. require.Equal(t, 1, len(blocks[1].Rollup.L1UserTxs))
  352. require.Equal(t, 2, len(blocks[2].Rollup.L1UserTxs))
  353. require.Equal(t, 1, len(blocks[3].Rollup.L1UserTxs))
  354. require.Equal(t, 2, len(blocks[4].Rollup.L1UserTxs))
  355. require.Equal(t, 1, len(blocks[5].Rollup.L1UserTxs))
  356. require.Equal(t, 1, len(blocks[6].Rollup.L1UserTxs))
  357. var null *common.BatchNum = nil
  358. var txID common.TxID
  359. // Insert blocks into DB
  360. for i := range blocks {
  361. if i == len(blocks)-1 {
  362. blocks[i].Block.Timestamp = time.Now()
  363. dbL1Txs, err := historyDB.GetAllL1UserTxs()
  364. assert.NoError(t, err)
  365. // Check batch_num is nil before forging
  366. assert.Equal(t, null, dbL1Txs[len(dbL1Txs)-1].BatchNum)
  367. // Save this TxId
  368. txID = dbL1Txs[len(dbL1Txs)-1].TxID
  369. }
  370. err = historyDB.AddBlockSCData(&blocks[i])
  371. assert.NoError(t, err)
  372. }
  373. // Check blocks
  374. dbBlocks, err := historyDB.GetAllBlocks()
  375. assert.NoError(t, err)
  376. assert.Equal(t, len(blocks)+1, len(dbBlocks))
  377. // Check batches
  378. batches, err := historyDB.GetAllBatches()
  379. assert.NoError(t, err)
  380. assert.Equal(t, 11, len(batches))
  381. // Check L1 Transactions
  382. dbL1Txs, err := historyDB.GetAllL1UserTxs()
  383. assert.NoError(t, err)
  384. assert.Equal(t, 10, len(dbL1Txs))
  385. // Tx Type
  386. assert.Equal(t, common.TxTypeCreateAccountDeposit, dbL1Txs[0].Type)
  387. assert.Equal(t, common.TxTypeCreateAccountDeposit, dbL1Txs[1].Type)
  388. assert.Equal(t, common.TxTypeCreateAccountDepositTransfer, dbL1Txs[2].Type)
  389. assert.Equal(t, common.TxTypeDeposit, dbL1Txs[3].Type)
  390. assert.Equal(t, common.TxTypeDeposit, dbL1Txs[4].Type)
  391. assert.Equal(t, common.TxTypeDepositTransfer, dbL1Txs[5].Type)
  392. assert.Equal(t, common.TxTypeForceTransfer, dbL1Txs[6].Type)
  393. assert.Equal(t, common.TxTypeForceExit, dbL1Txs[7].Type)
  394. assert.Equal(t, common.TxTypeCreateAccountDeposit, dbL1Txs[8].Type)
  395. assert.Equal(t, common.TxTypeCreateAccountDeposit, dbL1Txs[9].Type)
  396. // Tx ID
  397. assert.Equal(t, "0x000000000000000001000000", dbL1Txs[0].TxID.String())
  398. assert.Equal(t, "0x000000000000000001000100", dbL1Txs[1].TxID.String())
  399. assert.Equal(t, "0x000000000000000003000000", dbL1Txs[2].TxID.String())
  400. assert.Equal(t, "0x000000000000000005000000", dbL1Txs[3].TxID.String())
  401. assert.Equal(t, "0x000000000000000005000100", dbL1Txs[4].TxID.String())
  402. assert.Equal(t, "0x000000000000000005000200", dbL1Txs[5].TxID.String())
  403. assert.Equal(t, "0x000000000000000006000000", dbL1Txs[6].TxID.String())
  404. assert.Equal(t, "0x000000000000000006000100", dbL1Txs[7].TxID.String())
  405. assert.Equal(t, "0x000000000000000008000000", dbL1Txs[8].TxID.String())
  406. assert.Equal(t, "0x000000000000000009000000", dbL1Txs[9].TxID.String())
  407. // Tx From IDx
  408. assert.Equal(t, common.Idx(0), dbL1Txs[0].FromIdx)
  409. assert.Equal(t, common.Idx(0), dbL1Txs[1].FromIdx)
  410. assert.Equal(t, common.Idx(0), dbL1Txs[2].FromIdx)
  411. assert.NotEqual(t, common.Idx(0), dbL1Txs[3].FromIdx)
  412. assert.NotEqual(t, common.Idx(0), dbL1Txs[4].FromIdx)
  413. assert.NotEqual(t, common.Idx(0), dbL1Txs[5].FromIdx)
  414. assert.NotEqual(t, common.Idx(0), dbL1Txs[6].FromIdx)
  415. assert.NotEqual(t, common.Idx(0), dbL1Txs[7].FromIdx)
  416. assert.Equal(t, common.Idx(0), dbL1Txs[8].FromIdx)
  417. assert.Equal(t, common.Idx(0), dbL1Txs[9].FromIdx)
  418. assert.Equal(t, common.Idx(0), dbL1Txs[9].FromIdx)
  419. assert.Equal(t, dbL1Txs[5].FromIdx, dbL1Txs[6].FromIdx)
  420. assert.Equal(t, dbL1Txs[5].FromIdx, dbL1Txs[7].FromIdx)
  421. // Tx to IDx
  422. assert.Equal(t, dbL1Txs[2].ToIdx, dbL1Txs[5].FromIdx)
  423. assert.Equal(t, dbL1Txs[5].ToIdx, dbL1Txs[3].FromIdx)
  424. assert.Equal(t, dbL1Txs[6].ToIdx, dbL1Txs[3].FromIdx)
  425. // Token ID
  426. assert.Equal(t, common.TokenID(1), dbL1Txs[0].TokenID)
  427. assert.Equal(t, common.TokenID(1), dbL1Txs[1].TokenID)
  428. assert.Equal(t, common.TokenID(1), dbL1Txs[2].TokenID)
  429. assert.Equal(t, common.TokenID(1), dbL1Txs[3].TokenID)
  430. assert.Equal(t, common.TokenID(1), dbL1Txs[4].TokenID)
  431. assert.Equal(t, common.TokenID(1), dbL1Txs[5].TokenID)
  432. assert.Equal(t, common.TokenID(1), dbL1Txs[6].TokenID)
  433. assert.Equal(t, common.TokenID(1), dbL1Txs[7].TokenID)
  434. assert.Equal(t, common.TokenID(2), dbL1Txs[8].TokenID)
  435. assert.Equal(t, common.TokenID(2), dbL1Txs[9].TokenID)
  436. // Batch Number
  437. var bn common.BatchNum = common.BatchNum(2)
  438. assert.Equal(t, &bn, dbL1Txs[0].BatchNum)
  439. assert.Equal(t, &bn, dbL1Txs[1].BatchNum)
  440. bn = common.BatchNum(4)
  441. assert.Equal(t, &bn, dbL1Txs[2].BatchNum)
  442. bn = common.BatchNum(7)
  443. assert.Equal(t, &bn, dbL1Txs[3].BatchNum)
  444. assert.Equal(t, &bn, dbL1Txs[4].BatchNum)
  445. assert.Equal(t, &bn, dbL1Txs[5].BatchNum)
  446. bn = common.BatchNum(8)
  447. assert.Equal(t, &bn, dbL1Txs[6].BatchNum)
  448. assert.Equal(t, &bn, dbL1Txs[7].BatchNum)
  449. bn = common.BatchNum(10)
  450. assert.Equal(t, &bn, dbL1Txs[8].BatchNum)
  451. bn = common.BatchNum(11)
  452. assert.Equal(t, &bn, dbL1Txs[9].BatchNum)
  453. // eth_block_num
  454. assert.Equal(t, int64(2), dbL1Txs[0].EthBlockNum)
  455. assert.Equal(t, int64(2), dbL1Txs[1].EthBlockNum)
  456. assert.Equal(t, int64(3), dbL1Txs[2].EthBlockNum)
  457. assert.Equal(t, int64(4), dbL1Txs[3].EthBlockNum)
  458. assert.Equal(t, int64(4), dbL1Txs[4].EthBlockNum)
  459. assert.Equal(t, int64(5), dbL1Txs[5].EthBlockNum)
  460. assert.Equal(t, int64(6), dbL1Txs[6].EthBlockNum)
  461. assert.Equal(t, int64(6), dbL1Txs[7].EthBlockNum)
  462. assert.Equal(t, int64(7), dbL1Txs[8].EthBlockNum)
  463. assert.Equal(t, int64(8), dbL1Txs[9].EthBlockNum)
  464. // User Origin
  465. assert.Equal(t, true, dbL1Txs[0].UserOrigin)
  466. assert.Equal(t, true, dbL1Txs[1].UserOrigin)
  467. assert.Equal(t, true, dbL1Txs[2].UserOrigin)
  468. assert.Equal(t, true, dbL1Txs[3].UserOrigin)
  469. assert.Equal(t, true, dbL1Txs[4].UserOrigin)
  470. assert.Equal(t, true, dbL1Txs[5].UserOrigin)
  471. assert.Equal(t, true, dbL1Txs[6].UserOrigin)
  472. assert.Equal(t, true, dbL1Txs[7].UserOrigin)
  473. assert.Equal(t, true, dbL1Txs[8].UserOrigin)
  474. assert.Equal(t, true, dbL1Txs[9].UserOrigin)
  475. // Deposit Amount
  476. assert.Equal(t, big.NewInt(10), dbL1Txs[0].DepositAmount)
  477. assert.Equal(t, big.NewInt(10), dbL1Txs[1].DepositAmount)
  478. assert.Equal(t, big.NewInt(20), dbL1Txs[2].DepositAmount)
  479. assert.Equal(t, big.NewInt(10), dbL1Txs[3].DepositAmount)
  480. assert.Equal(t, big.NewInt(10), dbL1Txs[4].DepositAmount)
  481. assert.Equal(t, big.NewInt(10), dbL1Txs[5].DepositAmount)
  482. assert.Equal(t, big.NewInt(0), dbL1Txs[6].DepositAmount)
  483. assert.Equal(t, big.NewInt(0), dbL1Txs[7].DepositAmount)
  484. assert.Equal(t, big.NewInt(10), dbL1Txs[8].DepositAmount)
  485. assert.Equal(t, big.NewInt(10), dbL1Txs[9].DepositAmount)
  486. // Check saved txID's batch_num is not nil
  487. assert.Equal(t, txID, dbL1Txs[len(dbL1Txs)-2].TxID)
  488. assert.NotEqual(t, null, dbL1Txs[len(dbL1Txs)-2].BatchNum)
  489. // Check Coordinator TXs
  490. coordTxs, err := historyDB.GetAllL1CoordinatorTxs()
  491. assert.NoError(t, err)
  492. assert.Equal(t, 1, len(coordTxs))
  493. assert.Equal(t, common.TxTypeCreateAccountDeposit, coordTxs[0].Type)
  494. assert.Equal(t, false, coordTxs[0].UserOrigin)
  495. // Check L2 TXs
  496. dbL2Txs, err := historyDB.GetAllL2Txs()
  497. assert.NoError(t, err)
  498. assert.Equal(t, 4, len(dbL2Txs))
  499. // Tx Type
  500. assert.Equal(t, common.TxTypeTransfer, dbL2Txs[0].Type)
  501. assert.Equal(t, common.TxTypeTransfer, dbL2Txs[1].Type)
  502. assert.Equal(t, common.TxTypeTransfer, dbL2Txs[2].Type)
  503. assert.Equal(t, common.TxTypeExit, dbL2Txs[3].Type)
  504. // Tx ID
  505. assert.Equal(t, "0x020000000001030000000001", dbL2Txs[0].TxID.String())
  506. assert.Equal(t, "0x020000000001010000000001", dbL2Txs[1].TxID.String())
  507. assert.Equal(t, "0x020000000001000000000001", dbL2Txs[2].TxID.String())
  508. assert.Equal(t, "0x020000000001000000000002", dbL2Txs[3].TxID.String())
  509. // Tx From and To IDx
  510. assert.Equal(t, dbL2Txs[0].ToIdx, dbL2Txs[2].FromIdx)
  511. assert.Equal(t, dbL2Txs[1].ToIdx, dbL2Txs[0].FromIdx)
  512. assert.Equal(t, dbL2Txs[2].ToIdx, dbL2Txs[1].FromIdx)
  513. // Batch Number
  514. assert.Equal(t, common.BatchNum(5), dbL2Txs[0].BatchNum)
  515. assert.Equal(t, common.BatchNum(5), dbL2Txs[1].BatchNum)
  516. assert.Equal(t, common.BatchNum(5), dbL2Txs[2].BatchNum)
  517. assert.Equal(t, common.BatchNum(5), dbL2Txs[3].BatchNum)
  518. // eth_block_num
  519. assert.Equal(t, int64(4), dbL2Txs[0].EthBlockNum)
  520. assert.Equal(t, int64(4), dbL2Txs[1].EthBlockNum)
  521. assert.Equal(t, int64(4), dbL2Txs[2].EthBlockNum)
  522. // Amount
  523. assert.Equal(t, big.NewInt(10), dbL2Txs[0].Amount)
  524. assert.Equal(t, big.NewInt(10), dbL2Txs[1].Amount)
  525. assert.Equal(t, big.NewInt(10), dbL2Txs[2].Amount)
  526. assert.Equal(t, big.NewInt(10), dbL2Txs[3].Amount)
  527. }
  528. func TestExitTree(t *testing.T) {
  529. nBatches := 17
  530. blocks := setTestBlocks(1, 10)
  531. batches := test.GenBatches(nBatches, blocks)
  532. err := historyDB.AddBatches(batches)
  533. assert.NoError(t, err)
  534. const nTokens = 50
  535. tokens, ethToken := test.GenTokens(nTokens, blocks)
  536. err = historyDB.AddTokens(tokens)
  537. assert.NoError(t, err)
  538. tokens = append([]common.Token{ethToken}, tokens...)
  539. const nAccounts = 3
  540. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  541. assert.NoError(t, historyDB.AddAccounts(accs))
  542. exitTree := test.GenExitTree(nBatches, batches, accs, blocks)
  543. err = historyDB.AddExitTree(exitTree)
  544. assert.NoError(t, err)
  545. }
  546. func TestGetUnforgedL1UserTxs(t *testing.T) {
  547. test.WipeDB(historyDB.DB())
  548. set := `
  549. Type: Blockchain
  550. AddToken(1)
  551. AddToken(2)
  552. AddToken(3)
  553. CreateAccountDeposit(1) A: 20
  554. CreateAccountDeposit(2) A: 20
  555. CreateAccountDeposit(1) B: 5
  556. CreateAccountDeposit(1) C: 5
  557. CreateAccountDeposit(1) D: 5
  558. > block
  559. `
  560. tc := til.NewContext(128)
  561. blocks, err := tc.GenerateBlocks(set)
  562. require.Nil(t, err)
  563. // Sanity check
  564. require.Equal(t, 1, len(blocks))
  565. require.Equal(t, 5, len(blocks[0].Rollup.L1UserTxs))
  566. toForgeL1TxsNum := int64(1)
  567. for i := range blocks {
  568. err = historyDB.AddBlockSCData(&blocks[i])
  569. require.Nil(t, err)
  570. }
  571. l1UserTxs, err := historyDB.GetUnforgedL1UserTxs(toForgeL1TxsNum)
  572. require.Nil(t, err)
  573. assert.Equal(t, 5, len(l1UserTxs))
  574. assert.Equal(t, blocks[0].Rollup.L1UserTxs, l1UserTxs)
  575. // No l1UserTxs for this toForgeL1TxsNum
  576. l1UserTxs, err = historyDB.GetUnforgedL1UserTxs(2)
  577. require.Nil(t, err)
  578. assert.Equal(t, 0, len(l1UserTxs))
  579. }
  580. func exampleInitSCVars() (*common.RollupVariables, *common.AuctionVariables, *common.WDelayerVariables) {
  581. //nolint:govet
  582. rollup := &common.RollupVariables{
  583. 0,
  584. big.NewInt(10),
  585. 12,
  586. 13,
  587. [5]common.BucketParams{},
  588. false,
  589. }
  590. //nolint:govet
  591. auction := &common.AuctionVariables{
  592. 0,
  593. ethCommon.BigToAddress(big.NewInt(2)),
  594. ethCommon.BigToAddress(big.NewInt(3)),
  595. "https://boot.coord.com",
  596. [6]*big.Int{
  597. big.NewInt(1), big.NewInt(2), big.NewInt(3),
  598. big.NewInt(4), big.NewInt(5), big.NewInt(6),
  599. },
  600. 0,
  601. 2,
  602. 4320,
  603. [3]uint16{10, 11, 12},
  604. 1000,
  605. 20,
  606. }
  607. //nolint:govet
  608. wDelayer := &common.WDelayerVariables{
  609. 0,
  610. ethCommon.BigToAddress(big.NewInt(2)),
  611. ethCommon.BigToAddress(big.NewInt(3)),
  612. 13,
  613. 14,
  614. false,
  615. }
  616. return rollup, auction, wDelayer
  617. }
  618. func TestSetInitialSCVars(t *testing.T) {
  619. test.WipeDB(historyDB.DB())
  620. _, _, _, err := historyDB.GetSCVars()
  621. assert.Equal(t, sql.ErrNoRows, tracerr.Unwrap(err))
  622. rollup, auction, wDelayer := exampleInitSCVars()
  623. err = historyDB.SetInitialSCVars(rollup, auction, wDelayer)
  624. require.Nil(t, err)
  625. dbRollup, dbAuction, dbWDelayer, err := historyDB.GetSCVars()
  626. assert.Nil(t, err)
  627. require.Equal(t, rollup, dbRollup)
  628. require.Equal(t, auction, dbAuction)
  629. require.Equal(t, wDelayer, dbWDelayer)
  630. }
  631. func TestSetL1UserTxEffectiveAmounts(t *testing.T) {
  632. test.WipeDB(historyDB.DB())
  633. set := `
  634. Type: Blockchain
  635. AddToken(1)
  636. CreateAccountDeposit(1) A: 2000
  637. CreateAccountDeposit(1) B: 500
  638. CreateAccountDeposit(1) C: 500
  639. > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{*}
  640. > block // blockNum=2
  641. > batchL1 // forge defined L1UserTxs{*}
  642. > block // blockNum=3
  643. `
  644. tc := til.NewContext(common.RollupConstMaxL1UserTx)
  645. tilCfgExtra := til.ConfigExtra{
  646. BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
  647. CoordUser: "A",
  648. }
  649. blocks, err := tc.GenerateBlocks(set)
  650. require.Nil(t, err)
  651. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  652. assert.Nil(t, err)
  653. err = tc.FillBlocksForgedL1UserTxs(blocks)
  654. require.Nil(t, err)
  655. // Add only first block so that the L1UserTxs are not marked as forged
  656. for i := range blocks[:1] {
  657. err = historyDB.AddBlockSCData(&blocks[i])
  658. require.Nil(t, err)
  659. }
  660. // Add second batch to trigger the update of the batch_num,
  661. // while avoiding the implicit call of setL1UserTxEffectiveAmounts
  662. err = historyDB.addBlock(historyDB.db, &blocks[1].Block)
  663. assert.NoError(t, err)
  664. err = historyDB.addBatch(historyDB.db, &blocks[1].Rollup.Batches[0].Batch)
  665. assert.NoError(t, err)
  666. require.Nil(t, err)
  667. // Set the Effective{Amount,DepositAmount} of the L1UserTxs that are forged in the second block
  668. l1Txs := blocks[1].Rollup.Batches[0].L1UserTxs
  669. require.Equal(t, 3, len(l1Txs))
  670. // Change some values to test all cases
  671. l1Txs[1].EffectiveAmount = big.NewInt(0)
  672. l1Txs[2].EffectiveDepositAmount = big.NewInt(0)
  673. l1Txs[2].EffectiveAmount = big.NewInt(0)
  674. err = historyDB.setL1UserTxEffectiveAmounts(historyDB.db, l1Txs)
  675. require.NoError(t, err)
  676. dbL1Txs, err := historyDB.GetAllL1UserTxs()
  677. require.NoError(t, err)
  678. for i, tx := range dbL1Txs {
  679. log.Infof("%d %v %v", i, tx.EffectiveAmount, tx.EffectiveDepositAmount)
  680. assert.NotNil(t, tx.EffectiveAmount)
  681. assert.NotNil(t, tx.EffectiveDepositAmount)
  682. switch tx.TxID {
  683. case l1Txs[0].TxID:
  684. assert.Equal(t, l1Txs[0].DepositAmount, tx.EffectiveDepositAmount)
  685. assert.Equal(t, l1Txs[0].Amount, tx.EffectiveAmount)
  686. case l1Txs[1].TxID:
  687. assert.Equal(t, l1Txs[1].DepositAmount, tx.EffectiveDepositAmount)
  688. assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
  689. case l1Txs[2].TxID:
  690. assert.Equal(t, big.NewInt(0), tx.EffectiveDepositAmount)
  691. assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
  692. }
  693. }
  694. }
  695. func TestUpdateExitTree(t *testing.T) {
  696. test.WipeDB(historyDB.DB())
  697. set := `
  698. Type: Blockchain
  699. AddToken(1)
  700. CreateAccountDeposit(1) C: 2000 // Idx=256+2=258
  701. CreateAccountDeposit(1) D: 500 // Idx=256+3=259
  702. CreateAccountCoordinator(1) A // Idx=256+0=256
  703. CreateAccountCoordinator(1) B // Idx=256+1=257
  704. > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{5}
  705. > batchL1 // forge defined L1UserTxs{5}, freeze L1UserTxs{nil}
  706. > block // blockNum=2
  707. ForceExit(1) A: 100
  708. ForceExit(1) B: 80
  709. Exit(1) C: 50 (172)
  710. Exit(1) D: 30 (172)
  711. > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{3}
  712. > batchL1 // forge L1UserTxs{3}, freeze defined L1UserTxs{nil}
  713. > block // blockNum=3
  714. > block // blockNum=4 (empty block)
  715. > block // blockNum=5 (empty block)
  716. `
  717. tc := til.NewContext(common.RollupConstMaxL1UserTx)
  718. tilCfgExtra := til.ConfigExtra{
  719. BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
  720. CoordUser: "A",
  721. }
  722. blocks, err := tc.GenerateBlocks(set)
  723. require.Nil(t, err)
  724. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  725. assert.Nil(t, err)
  726. // Add all blocks except for the last two
  727. for i := range blocks[:len(blocks)-2] {
  728. err = historyDB.AddBlockSCData(&blocks[i])
  729. require.Nil(t, err)
  730. }
  731. // Add withdraws to the second-to-last block, and insert block into the DB
  732. block := &blocks[len(blocks)-2]
  733. require.Equal(t, int64(4), block.Block.Num)
  734. tokenAddr := blocks[0].Rollup.AddedTokens[0].EthAddr
  735. // block.WDelayer.Deposits = append(block.WDelayer.Deposits,
  736. // common.WDelayerTransfer{Owner: tc.UsersByIdx[257].Addr, Token: tokenAddr, Amount: big.NewInt(80)}, // 257
  737. // common.WDelayerTransfer{Owner: tc.UsersByIdx[259].Addr, Token: tokenAddr, Amount: big.NewInt(15)}, // 259
  738. // )
  739. block.Rollup.Withdrawals = append(block.Rollup.Withdrawals,
  740. common.WithdrawInfo{Idx: 256, NumExitRoot: 4, InstantWithdraw: true},
  741. common.WithdrawInfo{Idx: 257, NumExitRoot: 4, InstantWithdraw: false,
  742. Owner: tc.UsersByIdx[257].Addr, Token: tokenAddr},
  743. common.WithdrawInfo{Idx: 258, NumExitRoot: 3, InstantWithdraw: true},
  744. common.WithdrawInfo{Idx: 259, NumExitRoot: 3, InstantWithdraw: false,
  745. Owner: tc.UsersByIdx[259].Addr, Token: tokenAddr},
  746. )
  747. err = historyDB.addBlock(historyDB.db, &block.Block)
  748. require.Nil(t, err)
  749. err = historyDB.updateExitTree(historyDB.db, block.Block.Num,
  750. block.Rollup.Withdrawals, block.WDelayer.Withdrawals)
  751. require.Nil(t, err)
  752. // Check that exits in DB match with the expected values
  753. dbExits, err := historyDB.GetAllExits()
  754. require.Nil(t, err)
  755. assert.Equal(t, 4, len(dbExits))
  756. dbExitsByIdx := make(map[common.Idx]common.ExitInfo)
  757. for _, dbExit := range dbExits {
  758. dbExitsByIdx[dbExit.AccountIdx] = dbExit
  759. }
  760. for _, withdraw := range block.Rollup.Withdrawals {
  761. assert.Equal(t, withdraw.NumExitRoot, dbExitsByIdx[withdraw.Idx].BatchNum)
  762. if withdraw.InstantWithdraw {
  763. assert.Equal(t, &block.Block.Num, dbExitsByIdx[withdraw.Idx].InstantWithdrawn)
  764. } else {
  765. assert.Equal(t, &block.Block.Num, dbExitsByIdx[withdraw.Idx].DelayedWithdrawRequest)
  766. }
  767. }
  768. // Add delayed withdraw to the last block, and insert block into the DB
  769. block = &blocks[len(blocks)-1]
  770. require.Equal(t, int64(5), block.Block.Num)
  771. block.WDelayer.Withdrawals = append(block.WDelayer.Withdrawals,
  772. common.WDelayerTransfer{
  773. Owner: tc.UsersByIdx[257].Addr,
  774. Token: tokenAddr,
  775. Amount: big.NewInt(80),
  776. })
  777. err = historyDB.addBlock(historyDB.db, &block.Block)
  778. require.Nil(t, err)
  779. err = historyDB.updateExitTree(historyDB.db, block.Block.Num,
  780. block.Rollup.Withdrawals, block.WDelayer.Withdrawals)
  781. require.Nil(t, err)
  782. // Check that delayed withdrawn has been set
  783. dbExits, err = historyDB.GetAllExits()
  784. require.Nil(t, err)
  785. for _, dbExit := range dbExits {
  786. dbExitsByIdx[dbExit.AccountIdx] = dbExit
  787. }
  788. require.Equal(t, &block.Block.Num, dbExitsByIdx[257].DelayedWithdrawn)
  789. }
  790. func TestGetBestBidCoordinator(t *testing.T) {
  791. test.WipeDB(historyDB.DB())
  792. rollup, auction, wDelayer := exampleInitSCVars()
  793. err := historyDB.SetInitialSCVars(rollup, auction, wDelayer)
  794. require.Nil(t, err)
  795. tc := til.NewContext(common.RollupConstMaxL1UserTx)
  796. blocks, err := tc.GenerateBlocks(`
  797. Type: Blockchain
  798. > block // blockNum=2
  799. `)
  800. require.Nil(t, err)
  801. err = historyDB.AddBlockSCData(&blocks[0])
  802. require.Nil(t, err)
  803. coords := []common.Coordinator{
  804. {
  805. Bidder: ethCommon.BigToAddress(big.NewInt(1)),
  806. Forger: ethCommon.BigToAddress(big.NewInt(2)),
  807. EthBlockNum: 2,
  808. URL: "foo",
  809. },
  810. {
  811. Bidder: ethCommon.BigToAddress(big.NewInt(3)),
  812. Forger: ethCommon.BigToAddress(big.NewInt(4)),
  813. EthBlockNum: 2,
  814. URL: "bar",
  815. },
  816. }
  817. err = historyDB.addCoordinators(historyDB.db, coords)
  818. require.Nil(t, err)
  819. err = historyDB.addBids(historyDB.db, []common.Bid{
  820. {
  821. SlotNum: 10,
  822. BidValue: big.NewInt(10),
  823. EthBlockNum: 2,
  824. Bidder: coords[0].Bidder,
  825. },
  826. {
  827. SlotNum: 10,
  828. BidValue: big.NewInt(20),
  829. EthBlockNum: 2,
  830. Bidder: coords[1].Bidder,
  831. },
  832. })
  833. require.Nil(t, err)
  834. forger10, err := historyDB.GetBestBidCoordinator(10)
  835. require.Nil(t, err)
  836. require.Equal(t, coords[1].Forger, forger10.Forger)
  837. require.Equal(t, coords[1].Bidder, forger10.Bidder)
  838. require.Equal(t, coords[1].URL, forger10.URL)
  839. _, err = historyDB.GetBestBidCoordinator(11)
  840. require.Equal(t, sql.ErrNoRows, tracerr.Unwrap(err))
  841. }
  842. func TestAddBucketUpdates(t *testing.T) {
  843. test.WipeDB(historyDB.DB())
  844. const fromBlock int64 = 1
  845. const toBlock int64 = 5 + 1
  846. setTestBlocks(fromBlock, toBlock)
  847. bucketUpdates := []common.BucketUpdate{
  848. {
  849. EthBlockNum: 4,
  850. NumBucket: 0,
  851. BlockStamp: 4,
  852. Withdrawals: big.NewInt(123),
  853. },
  854. {
  855. EthBlockNum: 5,
  856. NumBucket: 2,
  857. BlockStamp: 5,
  858. Withdrawals: big.NewInt(42),
  859. },
  860. }
  861. err := historyDB.addBucketUpdates(historyDB.db, bucketUpdates)
  862. require.NoError(t, err)
  863. dbBucketUpdates, err := historyDB.GetAllBucketUpdates()
  864. require.NoError(t, err)
  865. assert.Equal(t, bucketUpdates, dbBucketUpdates)
  866. }
  867. func TestAddTokenExchanges(t *testing.T) {
  868. test.WipeDB(historyDB.DB())
  869. const fromBlock int64 = 1
  870. const toBlock int64 = 5 + 1
  871. setTestBlocks(fromBlock, toBlock)
  872. tokenExchanges := []common.TokenExchange{
  873. {
  874. EthBlockNum: 4,
  875. Address: ethCommon.BigToAddress(big.NewInt(111)),
  876. ValueUSD: 12345,
  877. },
  878. {
  879. EthBlockNum: 5,
  880. Address: ethCommon.BigToAddress(big.NewInt(222)),
  881. ValueUSD: 67890,
  882. },
  883. }
  884. err := historyDB.addTokenExchanges(historyDB.db, tokenExchanges)
  885. require.NoError(t, err)
  886. dbTokenExchanges, err := historyDB.GetAllTokenExchanges()
  887. require.NoError(t, err)
  888. assert.Equal(t, tokenExchanges, dbTokenExchanges)
  889. }
  890. func TestAddEscapeHatchWithdrawals(t *testing.T) {
  891. test.WipeDB(historyDB.DB())
  892. const fromBlock int64 = 1
  893. const toBlock int64 = 5 + 1
  894. setTestBlocks(fromBlock, toBlock)
  895. escapeHatchWithdrawals := []common.WDelayerEscapeHatchWithdrawal{
  896. {
  897. EthBlockNum: 4,
  898. Who: ethCommon.BigToAddress(big.NewInt(111)),
  899. To: ethCommon.BigToAddress(big.NewInt(222)),
  900. TokenAddr: ethCommon.BigToAddress(big.NewInt(333)),
  901. Amount: big.NewInt(10002),
  902. },
  903. {
  904. EthBlockNum: 5,
  905. Who: ethCommon.BigToAddress(big.NewInt(444)),
  906. To: ethCommon.BigToAddress(big.NewInt(555)),
  907. TokenAddr: ethCommon.BigToAddress(big.NewInt(666)),
  908. Amount: big.NewInt(20003),
  909. },
  910. }
  911. err := historyDB.addEscapeHatchWithdrawals(historyDB.db, escapeHatchWithdrawals)
  912. require.NoError(t, err)
  913. dbEscapeHatchWithdrawals, err := historyDB.GetAllEscapeHatchWithdrawals()
  914. require.NoError(t, err)
  915. assert.Equal(t, escapeHatchWithdrawals, dbEscapeHatchWithdrawals)
  916. }
  917. // setTestBlocks WARNING: this will delete the blocks and recreate them
  918. func setTestBlocks(from, to int64) []common.Block {
  919. test.WipeDB(historyDB.DB())
  920. blocks := test.GenBlocks(from, to)
  921. if err := historyDB.AddBlocks(blocks); err != nil {
  922. panic(err)
  923. }
  924. return blocks
  925. }