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.

1466 lines
46 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`.
3 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`.
3 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.
3 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.
3 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.
3 years ago
Update coordinator to work better under real net - cli / node - Update handler of SIGINT so that after 3 SIGINTs, the process terminates unconditionally - coordinator - Store stats without pointer - In all functions that send a variable via channel, check for context done to avoid deadlock (due to no process reading from the channel, which has no queue) when the node is stopped. - Abstract `canForge` so that it can be used outside of the `Coordinator` - In `canForge` check the blockNumber in current and next slot. - Update tests due to smart contract changes in slot handling, and minimum bid defaults - TxManager - Add consts, vars and stats to allow evaluating `canForge` - Add `canForge` method (not used yet) - Store batch and nonces status (last success and last pending) - Track nonces internally instead of relying on the ethereum node (this is required to work with ganache when there are pending txs) - Handle the (common) case of the receipt not being found after the tx is sent. - Don't start the main loop until we get an initial messae fo the stats and vars (so that in the loop the stats and vars are set to synchronizer values) - When a tx fails, check and discard all the failed transactions before sending the message to stop the pipeline. This will avoid sending consecutive messages of stop the pipeline when multiple txs are detected to be failed consecutively. Also, future txs of the same pipeline after a discarded txs are discarded, and their nonces reused. - Robust handling of nonces: - If geth returns nonce is too low, increase it - If geth returns nonce too hight, decrease it - If geth returns underpriced, increase gas price - If geth returns replace underpriced, increase gas price - Add support for resending transactions after a timeout - Store `BatchInfos` in a queue - Pipeline - When an error is found, stop forging batches and send a message to the coordinator to stop the pipeline with information of the failed batch number so that in a restart, non-failed batches are not repated. - When doing a reset of the stateDB, if possible reset from the local checkpoint instead of resetting from the synchronizer. This allows resetting from a batch that is valid but not yet sent / synced. - Every time a pipeline is started, assign it a number from a counter. This allows the TxManager to ignore batches from stopped pipelines, via a message sent by the coordinator. - Avoid forging when we haven't reached the rollup genesis block number. - Add config parameter `StartSlotBlocksDelay`: StartSlotBlocksDelay is the number of blocks of delay to wait before starting the pipeline when we reach a slot in which we can forge. - When detecting a reorg, only reset the pipeline if the batch from which the pipeline started changed and wasn't sent by us. - Add config parameter `ScheduleBatchBlocksAheadCheck`: ScheduleBatchBlocksAheadCheck is the number of blocks ahead in which the forger address is checked to be allowed to forge (apart from checking the next block), used to decide when to stop scheduling new batches (by stopping the pipeline). For example, if we are at block 10 and ScheduleBatchBlocksAheadCheck is 5, eventhough at block 11 we canForge, the pipeline will be stopped if we can't forge at block 15. This value should be the expected number of blocks it takes between scheduling a batch and having it mined. - Add config parameter `SendBatchBlocksMarginCheck`: SendBatchBlocksMarginCheck is the number of margin blocks ahead in which the coordinator is also checked to be allowed to forge, apart from the next block; used to decide when to stop sending batches to the smart contract. For example, if we are at block 10 and SendBatchBlocksMarginCheck is 5, eventhough at block 11 we canForge, the batch will be discarded if we can't forge at block 15. - Add config parameter `TxResendTimeout`: TxResendTimeout is the timeout after which a non-mined ethereum transaction will be resent (reusing the nonce) with a newly calculated gas price - Add config parameter `MaxGasPrice`: MaxGasPrice is the maximum gas price allowed for ethereum transactions - Add config parameter `NoReuseNonce`: NoReuseNonce disables reusing nonces of pending transactions for new replacement transactions. This is useful for testing with Ganache. - Extend BatchInfo with more useful information for debugging - eth / ethereum client - Add necessary methods to create the auth object for transactions manually so that we can set the nonce, gas price, gas limit, etc manually - Update `RollupForgeBatch` to take an auth object as input (so that the coordinator can set parameters manually) - synchronizer - In stats, add `NextSlot` - In stats, store full last batch instead of just last batch number - Instead of calculating a nextSlot from scratch every time, update the current struct (only updating the forger info if we are Synced) - Afer every processed batch, check that the calculated StateDB MTRoot matches the StateRoot found in the forgeBatch event.
3 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.
3 years ago
Update coordinator to work better under real net - cli / node - Update handler of SIGINT so that after 3 SIGINTs, the process terminates unconditionally - coordinator - Store stats without pointer - In all functions that send a variable via channel, check for context done to avoid deadlock (due to no process reading from the channel, which has no queue) when the node is stopped. - Abstract `canForge` so that it can be used outside of the `Coordinator` - In `canForge` check the blockNumber in current and next slot. - Update tests due to smart contract changes in slot handling, and minimum bid defaults - TxManager - Add consts, vars and stats to allow evaluating `canForge` - Add `canForge` method (not used yet) - Store batch and nonces status (last success and last pending) - Track nonces internally instead of relying on the ethereum node (this is required to work with ganache when there are pending txs) - Handle the (common) case of the receipt not being found after the tx is sent. - Don't start the main loop until we get an initial messae fo the stats and vars (so that in the loop the stats and vars are set to synchronizer values) - When a tx fails, check and discard all the failed transactions before sending the message to stop the pipeline. This will avoid sending consecutive messages of stop the pipeline when multiple txs are detected to be failed consecutively. Also, future txs of the same pipeline after a discarded txs are discarded, and their nonces reused. - Robust handling of nonces: - If geth returns nonce is too low, increase it - If geth returns nonce too hight, decrease it - If geth returns underpriced, increase gas price - If geth returns replace underpriced, increase gas price - Add support for resending transactions after a timeout - Store `BatchInfos` in a queue - Pipeline - When an error is found, stop forging batches and send a message to the coordinator to stop the pipeline with information of the failed batch number so that in a restart, non-failed batches are not repated. - When doing a reset of the stateDB, if possible reset from the local checkpoint instead of resetting from the synchronizer. This allows resetting from a batch that is valid but not yet sent / synced. - Every time a pipeline is started, assign it a number from a counter. This allows the TxManager to ignore batches from stopped pipelines, via a message sent by the coordinator. - Avoid forging when we haven't reached the rollup genesis block number. - Add config parameter `StartSlotBlocksDelay`: StartSlotBlocksDelay is the number of blocks of delay to wait before starting the pipeline when we reach a slot in which we can forge. - When detecting a reorg, only reset the pipeline if the batch from which the pipeline started changed and wasn't sent by us. - Add config parameter `ScheduleBatchBlocksAheadCheck`: ScheduleBatchBlocksAheadCheck is the number of blocks ahead in which the forger address is checked to be allowed to forge (apart from checking the next block), used to decide when to stop scheduling new batches (by stopping the pipeline). For example, if we are at block 10 and ScheduleBatchBlocksAheadCheck is 5, eventhough at block 11 we canForge, the pipeline will be stopped if we can't forge at block 15. This value should be the expected number of blocks it takes between scheduling a batch and having it mined. - Add config parameter `SendBatchBlocksMarginCheck`: SendBatchBlocksMarginCheck is the number of margin blocks ahead in which the coordinator is also checked to be allowed to forge, apart from the next block; used to decide when to stop sending batches to the smart contract. For example, if we are at block 10 and SendBatchBlocksMarginCheck is 5, eventhough at block 11 we canForge, the batch will be discarded if we can't forge at block 15. - Add config parameter `TxResendTimeout`: TxResendTimeout is the timeout after which a non-mined ethereum transaction will be resent (reusing the nonce) with a newly calculated gas price - Add config parameter `MaxGasPrice`: MaxGasPrice is the maximum gas price allowed for ethereum transactions - Add config parameter `NoReuseNonce`: NoReuseNonce disables reusing nonces of pending transactions for new replacement transactions. This is useful for testing with Ganache. - Extend BatchInfo with more useful information for debugging - eth / ethereum client - Add necessary methods to create the auth object for transactions manually so that we can set the nonce, gas price, gas limit, etc manually - Update `RollupForgeBatch` to take an auth object as input (so that the coordinator can set parameters manually) - synchronizer - In stats, add `NextSlot` - In stats, store full last batch instead of just last batch number - Instead of calculating a nextSlot from scratch every time, update the current struct (only updating the forger info if we are Synced) - Afer every processed batch, check that the calculated StateDB MTRoot matches the StateRoot found in the forgeBatch event.
3 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`.
3 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`.
3 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`.
3 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`.
3 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`.
3 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`.
3 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`.
3 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`.
3 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`.
3 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`.
3 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`.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 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.
3 years ago
  1. package historydb
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "math"
  6. "math/big"
  7. "os"
  8. "strings"
  9. "testing"
  10. "time"
  11. ethCommon "github.com/ethereum/go-ethereum/common"
  12. "github.com/hermeznetwork/hermez-node/common"
  13. dbUtils "github.com/hermeznetwork/hermez-node/db"
  14. "github.com/hermeznetwork/hermez-node/log"
  15. "github.com/hermeznetwork/hermez-node/test"
  16. "github.com/hermeznetwork/hermez-node/test/til"
  17. "github.com/hermeznetwork/tracerr"
  18. "github.com/stretchr/testify/assert"
  19. "github.com/stretchr/testify/require"
  20. )
  21. var historyDB *HistoryDB
  22. var historyDBWithACC *HistoryDB
  23. // In order to run the test you need to run a Posgres DB with
  24. // a database named "history" that is accessible by
  25. // user: "hermez"
  26. // pass: set it using the env var POSTGRES_PASS
  27. // 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;"
  28. // After running the test you can stop the container by running: sudo docker kill hermez-db-test
  29. // If you already did that for the L2DB you don't have to do it again
  30. func TestMain(m *testing.M) {
  31. // init DB
  32. pass := os.Getenv("POSTGRES_PASS")
  33. db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
  34. if err != nil {
  35. panic(err)
  36. }
  37. historyDB = NewHistoryDB(db, db, nil)
  38. if err != nil {
  39. panic(err)
  40. }
  41. apiConnCon := dbUtils.NewAPIConnectionController(1, time.Second)
  42. historyDBWithACC = NewHistoryDB(db, db, apiConnCon)
  43. // Run tests
  44. result := m.Run()
  45. // Close DB
  46. if err := db.Close(); err != nil {
  47. log.Error("Error closing the history DB:", err)
  48. }
  49. os.Exit(result)
  50. }
  51. func TestBlocks(t *testing.T) {
  52. var fromBlock, toBlock int64
  53. fromBlock = 0
  54. toBlock = 7
  55. // Reset DB
  56. test.WipeDB(historyDB.DB())
  57. // Generate blocks using til
  58. set1 := `
  59. Type: Blockchain
  60. // block 0 is stored as default in the DB
  61. // block 1 does not exist
  62. > block // blockNum=2
  63. > block // blockNum=3
  64. > block // blockNum=4
  65. > block // blockNum=5
  66. > block // blockNum=6
  67. `
  68. tc := til.NewContext(uint16(0), 1)
  69. blocks, err := tc.GenerateBlocks(set1)
  70. require.NoError(t, err)
  71. // Save timestamp of a block with UTC and change it without UTC
  72. timestamp := time.Now().Add(time.Second * 13)
  73. blocks[fromBlock].Block.Timestamp = timestamp
  74. // Insert blocks into DB
  75. for i := 0; i < len(blocks); i++ {
  76. err := historyDB.AddBlock(&blocks[i].Block)
  77. assert.NoError(t, err)
  78. }
  79. // Add block 0 to the generated blocks
  80. blocks = append(
  81. []common.BlockData{{Block: test.Block0}}, //nolint:gofmt
  82. blocks...,
  83. )
  84. // Get all blocks from DB
  85. fetchedBlocks, err := historyDB.getBlocks(fromBlock, toBlock)
  86. assert.Equal(t, len(blocks), len(fetchedBlocks))
  87. // Compare generated vs getted blocks
  88. assert.NoError(t, err)
  89. for i := range fetchedBlocks {
  90. assertEqualBlock(t, &blocks[i].Block, &fetchedBlocks[i])
  91. }
  92. // Compare saved timestamp vs getted
  93. nameZoneUTC, offsetUTC := timestamp.UTC().Zone()
  94. zoneFetchedBlock, offsetFetchedBlock := fetchedBlocks[fromBlock].Timestamp.Zone()
  95. assert.Equal(t, nameZoneUTC, zoneFetchedBlock)
  96. assert.Equal(t, offsetUTC, offsetFetchedBlock)
  97. // Get blocks from the DB one by one
  98. for i := int64(2); i < toBlock; i++ { // avoid block 0 for simplicity
  99. fetchedBlock, err := historyDB.GetBlock(i)
  100. assert.NoError(t, err)
  101. assertEqualBlock(t, &blocks[i-1].Block, fetchedBlock)
  102. }
  103. // Get last block
  104. lastBlock, err := historyDB.GetLastBlock()
  105. assert.NoError(t, err)
  106. assertEqualBlock(t, &blocks[len(blocks)-1].Block, lastBlock)
  107. }
  108. func assertEqualBlock(t *testing.T, expected *common.Block, actual *common.Block) {
  109. assert.Equal(t, expected.Num, actual.Num)
  110. assert.Equal(t, expected.Hash, actual.Hash)
  111. assert.Equal(t, expected.Timestamp.Unix(), actual.Timestamp.Unix())
  112. }
  113. func TestBatches(t *testing.T) {
  114. // Reset DB
  115. test.WipeDB(historyDB.DB())
  116. // Generate batches using til (and blocks for foreign key)
  117. set := `
  118. Type: Blockchain
  119. AddToken(1) // Will have value in USD
  120. AddToken(2) // Will NOT have value in USD
  121. CreateAccountDeposit(1) A: 2000
  122. CreateAccountDeposit(2) A: 2000
  123. CreateAccountDeposit(1) B: 1000
  124. CreateAccountDeposit(2) B: 1000
  125. > batchL1
  126. > batchL1
  127. Transfer(1) A-B: 100 (5)
  128. Transfer(2) B-A: 100 (199)
  129. > batch // batchNum=2, L2 only batch, forges transfers (mixed case of with(out) USD value)
  130. > block
  131. Transfer(1) A-B: 100 (5)
  132. > batch // batchNum=3, L2 only batch, forges transfer (with USD value)
  133. Transfer(2) B-A: 100 (199)
  134. > batch // batchNum=4, L2 only batch, forges transfer (without USD value)
  135. > block
  136. `
  137. tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
  138. tilCfgExtra := til.ConfigExtra{
  139. BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
  140. CoordUser: "A",
  141. }
  142. blocks, err := tc.GenerateBlocks(set)
  143. require.NoError(t, err)
  144. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  145. require.NoError(t, err)
  146. // Insert to DB
  147. batches := []common.Batch{}
  148. tokensValue := make(map[common.TokenID]float64)
  149. lastL1TxsNum := new(int64)
  150. lastL1BatchBlockNum := int64(0)
  151. for _, block := range blocks {
  152. // Insert block
  153. assert.NoError(t, historyDB.AddBlock(&block.Block))
  154. // Insert tokens
  155. for i, token := range block.Rollup.AddedTokens {
  156. assert.NoError(t, historyDB.AddToken(&token)) //nolint:gosec
  157. if i%2 != 0 {
  158. // Set value to the token
  159. value := (float64(i) + 5) * 5.389329
  160. assert.NoError(t, historyDB.UpdateTokenValue(token.Symbol, value))
  161. tokensValue[token.TokenID] = value / math.Pow(10, float64(token.Decimals))
  162. }
  163. }
  164. // Combine all generated batches into single array
  165. for _, batch := range block.Rollup.Batches {
  166. batches = append(batches, batch.Batch)
  167. forgeTxsNum := batch.Batch.ForgeL1TxsNum
  168. if forgeTxsNum != nil && (lastL1TxsNum == nil || *lastL1TxsNum < *forgeTxsNum) {
  169. *lastL1TxsNum = *forgeTxsNum
  170. lastL1BatchBlockNum = batch.Batch.EthBlockNum
  171. }
  172. }
  173. }
  174. // Insert batches
  175. assert.NoError(t, historyDB.AddBatches(batches))
  176. // Set expected total fee
  177. for _, batch := range batches {
  178. total := .0
  179. for tokenID, amount := range batch.CollectedFees {
  180. af := new(big.Float).SetInt(amount)
  181. amountFloat, _ := af.Float64()
  182. total += tokensValue[tokenID] * amountFloat
  183. }
  184. batch.TotalFeesUSD = &total
  185. }
  186. // Get batches from the DB
  187. fetchedBatches, err := historyDB.GetBatches(0, common.BatchNum(len(batches)+1))
  188. assert.NoError(t, err)
  189. assert.Equal(t, len(batches), len(fetchedBatches))
  190. for i, fetchedBatch := range fetchedBatches {
  191. assert.Equal(t, batches[i], fetchedBatch)
  192. }
  193. // Test GetLastBatchNum
  194. fetchedLastBatchNum, err := historyDB.GetLastBatchNum()
  195. assert.NoError(t, err)
  196. assert.Equal(t, batches[len(batches)-1].BatchNum, fetchedLastBatchNum)
  197. // Test GetLastBatch
  198. fetchedLastBatch, err := historyDB.GetLastBatch()
  199. assert.NoError(t, err)
  200. assert.Equal(t, &batches[len(batches)-1], fetchedLastBatch)
  201. // Test GetLastL1TxsNum
  202. fetchedLastL1TxsNum, err := historyDB.GetLastL1TxsNum()
  203. assert.NoError(t, err)
  204. assert.Equal(t, lastL1TxsNum, fetchedLastL1TxsNum)
  205. // Test GetLastL1BatchBlockNum
  206. fetchedLastL1BatchBlockNum, err := historyDB.GetLastL1BatchBlockNum()
  207. assert.NoError(t, err)
  208. assert.Equal(t, lastL1BatchBlockNum, fetchedLastL1BatchBlockNum)
  209. // Test GetBatch
  210. fetchedBatch, err := historyDB.GetBatch(1)
  211. require.NoError(t, err)
  212. assert.Equal(t, &batches[0], fetchedBatch)
  213. _, err = historyDB.GetBatch(common.BatchNum(len(batches) + 1))
  214. assert.Equal(t, sql.ErrNoRows, tracerr.Unwrap(err))
  215. }
  216. func TestBids(t *testing.T) {
  217. const fromBlock int64 = 1
  218. const toBlock int64 = 5
  219. // Prepare blocks in the DB
  220. blocks := setTestBlocks(fromBlock, toBlock)
  221. // Generate fake coordinators
  222. const nCoords = 5
  223. coords := test.GenCoordinators(nCoords, blocks)
  224. err := historyDB.AddCoordinators(coords)
  225. assert.NoError(t, err)
  226. // Generate fake bids
  227. const nBids = 20
  228. bids := test.GenBids(nBids, blocks, coords)
  229. err = historyDB.AddBids(bids)
  230. assert.NoError(t, err)
  231. // Fetch bids
  232. fetchedBids, err := historyDB.GetAllBids()
  233. assert.NoError(t, err)
  234. // Compare fetched bids vs generated bids
  235. for i, bid := range fetchedBids {
  236. assert.Equal(t, bids[i], bid)
  237. }
  238. }
  239. func TestTokens(t *testing.T) {
  240. const fromBlock int64 = 1
  241. const toBlock int64 = 5
  242. // Prepare blocks in the DB
  243. blocks := setTestBlocks(fromBlock, toBlock)
  244. // Generate fake tokens
  245. const nTokens = 5
  246. tokens, ethToken := test.GenTokens(nTokens, blocks)
  247. err := historyDB.AddTokens(tokens)
  248. assert.NoError(t, err)
  249. tokens = append([]common.Token{ethToken}, tokens...)
  250. // Fetch tokens
  251. fetchedTokens, err := historyDB.GetTokensTest()
  252. assert.NoError(t, err)
  253. // Compare fetched tokens vs generated tokens
  254. // All the tokens should have USDUpdate setted by the DB trigger
  255. for i, token := range fetchedTokens {
  256. assert.Equal(t, tokens[i].TokenID, token.TokenID)
  257. assert.Equal(t, tokens[i].EthBlockNum, token.EthBlockNum)
  258. assert.Equal(t, tokens[i].EthAddr, token.EthAddr)
  259. assert.Equal(t, tokens[i].Name, token.Name)
  260. assert.Equal(t, tokens[i].Symbol, token.Symbol)
  261. assert.Nil(t, token.USD)
  262. assert.Nil(t, token.USDUpdate)
  263. }
  264. // Update token value
  265. for i, token := range tokens {
  266. value := 1.01 * float64(i)
  267. assert.NoError(t, historyDB.UpdateTokenValue(token.Symbol, value))
  268. }
  269. // Fetch tokens
  270. fetchedTokens, err = historyDB.GetTokensTest()
  271. assert.NoError(t, err)
  272. // Compare fetched tokens vs generated tokens
  273. // All the tokens should have USDUpdate setted by the DB trigger
  274. for i, token := range fetchedTokens {
  275. value := 1.01 * float64(i)
  276. assert.Equal(t, value, *token.USD)
  277. nameZone, offset := token.USDUpdate.Zone()
  278. assert.Equal(t, "UTC", nameZone)
  279. assert.Equal(t, 0, offset)
  280. }
  281. }
  282. func TestTokensUTF8(t *testing.T) {
  283. // Reset DB
  284. test.WipeDB(historyDB.DB())
  285. const fromBlock int64 = 1
  286. const toBlock int64 = 5
  287. // Prepare blocks in the DB
  288. blocks := setTestBlocks(fromBlock, toBlock)
  289. // Generate fake tokens
  290. const nTokens = 5
  291. tokens, ethToken := test.GenTokens(nTokens, blocks)
  292. nonUTFTokens := make([]common.Token, len(tokens)+1)
  293. // Force token.name and token.symbol to be non UTF-8 Strings
  294. for i, token := range tokens {
  295. token.Name = fmt.Sprint("NON-UTF8-NAME-\xc5-", i)
  296. token.Symbol = fmt.Sprint("S-\xc5-", i)
  297. tokens[i] = token
  298. nonUTFTokens[i] = token
  299. }
  300. err := historyDB.AddTokens(tokens)
  301. assert.NoError(t, err)
  302. // Work with nonUTFTokens as tokens one gets updated and non UTF-8 characters are lost
  303. nonUTFTokens = append([]common.Token{ethToken}, nonUTFTokens...)
  304. // Fetch tokens
  305. fetchedTokens, err := historyDB.GetTokensTest()
  306. assert.NoError(t, err)
  307. // Compare fetched tokens vs generated tokens
  308. // All the tokens should have USDUpdate setted by the DB trigger
  309. for i, token := range fetchedTokens {
  310. assert.Equal(t, nonUTFTokens[i].TokenID, token.TokenID)
  311. assert.Equal(t, nonUTFTokens[i].EthBlockNum, token.EthBlockNum)
  312. assert.Equal(t, nonUTFTokens[i].EthAddr, token.EthAddr)
  313. assert.Equal(t, strings.ToValidUTF8(nonUTFTokens[i].Name, " "), token.Name)
  314. assert.Equal(t, strings.ToValidUTF8(nonUTFTokens[i].Symbol, " "), token.Symbol)
  315. assert.Nil(t, token.USD)
  316. assert.Nil(t, token.USDUpdate)
  317. }
  318. // Update token value
  319. for i, token := range nonUTFTokens {
  320. value := 1.01 * float64(i)
  321. assert.NoError(t, historyDB.UpdateTokenValue(token.Symbol, value))
  322. }
  323. // Fetch tokens
  324. fetchedTokens, err = historyDB.GetTokensTest()
  325. assert.NoError(t, err)
  326. // Compare fetched tokens vs generated tokens
  327. // All the tokens should have USDUpdate setted by the DB trigger
  328. for i, token := range fetchedTokens {
  329. value := 1.01 * float64(i)
  330. assert.Equal(t, value, *token.USD)
  331. nameZone, offset := token.USDUpdate.Zone()
  332. assert.Equal(t, "UTC", nameZone)
  333. assert.Equal(t, 0, offset)
  334. }
  335. }
  336. func TestAccounts(t *testing.T) {
  337. const fromBlock int64 = 1
  338. const toBlock int64 = 5
  339. // Prepare blocks in the DB
  340. blocks := setTestBlocks(fromBlock, toBlock)
  341. // Generate fake tokens
  342. const nTokens = 5
  343. tokens, ethToken := test.GenTokens(nTokens, blocks)
  344. err := historyDB.AddTokens(tokens)
  345. assert.NoError(t, err)
  346. tokens = append([]common.Token{ethToken}, tokens...)
  347. // Generate fake batches
  348. const nBatches = 10
  349. batches := test.GenBatches(nBatches, blocks)
  350. err = historyDB.AddBatches(batches)
  351. assert.NoError(t, err)
  352. // Generate fake accounts
  353. const nAccounts = 3
  354. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  355. err = historyDB.AddAccounts(accs)
  356. assert.NoError(t, err)
  357. // Fetch accounts
  358. fetchedAccs, err := historyDB.GetAllAccounts()
  359. assert.NoError(t, err)
  360. // Compare fetched accounts vs generated accounts
  361. for i, acc := range fetchedAccs {
  362. accs[i].Balance = nil
  363. assert.Equal(t, accs[i], acc)
  364. }
  365. // Test AccountBalances
  366. accUpdates := make([]common.AccountUpdate, len(accs))
  367. for i, acc := range accs {
  368. accUpdates[i] = common.AccountUpdate{
  369. EthBlockNum: batches[acc.BatchNum-1].EthBlockNum,
  370. BatchNum: acc.BatchNum,
  371. Idx: acc.Idx,
  372. Nonce: common.Nonce(i),
  373. Balance: big.NewInt(int64(i)),
  374. }
  375. }
  376. err = historyDB.AddAccountUpdates(accUpdates)
  377. require.NoError(t, err)
  378. fetchedAccBalances, err := historyDB.GetAllAccountUpdates()
  379. require.NoError(t, err)
  380. assert.Equal(t, accUpdates, fetchedAccBalances)
  381. }
  382. func TestTxs(t *testing.T) {
  383. // Reset DB
  384. test.WipeDB(historyDB.DB())
  385. set := `
  386. Type: Blockchain
  387. AddToken(1)
  388. AddToken(2)
  389. CreateAccountDeposit(1) A: 10
  390. CreateAccountDeposit(1) B: 10
  391. > batchL1
  392. > batchL1
  393. > block
  394. CreateAccountDepositTransfer(1) C-A: 20, 10
  395. CreateAccountCoordinator(1) User0
  396. > batchL1
  397. > batchL1
  398. > block
  399. Deposit(1) B: 10
  400. Deposit(1) C: 10
  401. Transfer(1) C-A : 10 (1)
  402. Transfer(1) B-C : 10 (1)
  403. Transfer(1) A-B : 10 (1)
  404. Exit(1) A: 10 (1)
  405. > batch
  406. > block
  407. DepositTransfer(1) A-B: 10, 10
  408. > batchL1
  409. > block
  410. ForceTransfer(1) A-B: 10
  411. ForceExit(1) A: 5
  412. > batchL1
  413. > batchL1
  414. > block
  415. CreateAccountDeposit(2) D: 10
  416. > batchL1
  417. > block
  418. CreateAccountDeposit(2) E: 10
  419. > batchL1
  420. > batchL1
  421. > block
  422. `
  423. tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
  424. tilCfgExtra := til.ConfigExtra{
  425. BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
  426. CoordUser: "A",
  427. }
  428. blocks, err := tc.GenerateBlocks(set)
  429. require.NoError(t, err)
  430. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  431. require.NoError(t, err)
  432. // Sanity check
  433. require.Equal(t, 7, len(blocks))
  434. require.Equal(t, 2, len(blocks[0].Rollup.L1UserTxs))
  435. require.Equal(t, 1, len(blocks[1].Rollup.L1UserTxs))
  436. require.Equal(t, 2, len(blocks[2].Rollup.L1UserTxs))
  437. require.Equal(t, 1, len(blocks[3].Rollup.L1UserTxs))
  438. require.Equal(t, 2, len(blocks[4].Rollup.L1UserTxs))
  439. require.Equal(t, 1, len(blocks[5].Rollup.L1UserTxs))
  440. require.Equal(t, 1, len(blocks[6].Rollup.L1UserTxs))
  441. var null *common.BatchNum = nil
  442. var txID common.TxID
  443. // Insert blocks into DB
  444. for i := range blocks {
  445. if i == len(blocks)-1 {
  446. blocks[i].Block.Timestamp = time.Now()
  447. dbL1Txs, err := historyDB.GetAllL1UserTxs()
  448. assert.NoError(t, err)
  449. // Check batch_num is nil before forging
  450. assert.Equal(t, null, dbL1Txs[len(dbL1Txs)-1].BatchNum)
  451. // Save this TxId
  452. txID = dbL1Txs[len(dbL1Txs)-1].TxID
  453. }
  454. err = historyDB.AddBlockSCData(&blocks[i])
  455. assert.NoError(t, err)
  456. }
  457. // Check blocks
  458. dbBlocks, err := historyDB.GetAllBlocks()
  459. assert.NoError(t, err)
  460. assert.Equal(t, len(blocks)+1, len(dbBlocks))
  461. // Check batches
  462. batches, err := historyDB.GetAllBatches()
  463. assert.NoError(t, err)
  464. assert.Equal(t, 11, len(batches))
  465. // Check L1 Transactions
  466. dbL1Txs, err := historyDB.GetAllL1UserTxs()
  467. assert.NoError(t, err)
  468. assert.Equal(t, 10, len(dbL1Txs))
  469. // Tx Type
  470. assert.Equal(t, common.TxTypeCreateAccountDeposit, dbL1Txs[0].Type)
  471. assert.Equal(t, common.TxTypeCreateAccountDeposit, dbL1Txs[1].Type)
  472. assert.Equal(t, common.TxTypeCreateAccountDepositTransfer, dbL1Txs[2].Type)
  473. assert.Equal(t, common.TxTypeDeposit, dbL1Txs[3].Type)
  474. assert.Equal(t, common.TxTypeDeposit, dbL1Txs[4].Type)
  475. assert.Equal(t, common.TxTypeDepositTransfer, dbL1Txs[5].Type)
  476. assert.Equal(t, common.TxTypeForceTransfer, dbL1Txs[6].Type)
  477. assert.Equal(t, common.TxTypeForceExit, dbL1Txs[7].Type)
  478. assert.Equal(t, common.TxTypeCreateAccountDeposit, dbL1Txs[8].Type)
  479. assert.Equal(t, common.TxTypeCreateAccountDeposit, dbL1Txs[9].Type)
  480. // Tx ID
  481. assert.Equal(t, "0x00e979da4b80d60a17ce56fa19278c6f3a7e1b43359fb8a8ea46d0264de7d653ab", dbL1Txs[0].TxID.String())
  482. assert.Equal(t, "0x00af9bf96eb60f2d618519402a2f6b07057a034fa2baefd379fe8e1c969f1c5cf4", dbL1Txs[1].TxID.String())
  483. assert.Equal(t, "0x00a256ee191905243320ea830840fd666a73c7b4e6f89ce4bd47ddf998dfee627a", dbL1Txs[2].TxID.String())
  484. assert.Equal(t, "0x00930696d03ae0a1e6150b6ccb88043cb539a4e06a7f8baf213029ce9a0600197e", dbL1Txs[3].TxID.String())
  485. assert.Equal(t, "0x00de8e41d49f23832f66364e8702c4b78237eb0c95542a94d34188e51696e74fc8", dbL1Txs[4].TxID.String())
  486. assert.Equal(t, "0x007a44d6d60b15f3789d4ff49d62377a70255bf13a8d42e41ef49bf4c7b77d2c1b", dbL1Txs[5].TxID.String())
  487. assert.Equal(t, "0x00c33f316240f8d33a973db2d0e901e4ac1c96de30b185fcc6b63dac4d0e147bd4", dbL1Txs[6].TxID.String())
  488. assert.Equal(t, "0x00b55f0882c5229d1be3d9d3c1a076290f249cd0bae5ae6e609234606befb91233", dbL1Txs[7].TxID.String())
  489. assert.Equal(t, "0x009133d4c8a412ca45f50bccdbcfdb8393b0dd8efe953d0cc3bcc82796b7a581b6", dbL1Txs[8].TxID.String())
  490. assert.Equal(t, "0x00f5e8ab141ac16d673e654ba7747c2f12e93ea2c50ba6c05563752ca531968c62", dbL1Txs[9].TxID.String())
  491. // Tx From IDx
  492. assert.Equal(t, common.Idx(0), dbL1Txs[0].FromIdx)
  493. assert.Equal(t, common.Idx(0), dbL1Txs[1].FromIdx)
  494. assert.Equal(t, common.Idx(0), dbL1Txs[2].FromIdx)
  495. assert.NotEqual(t, common.Idx(0), dbL1Txs[3].FromIdx)
  496. assert.NotEqual(t, common.Idx(0), dbL1Txs[4].FromIdx)
  497. assert.NotEqual(t, common.Idx(0), dbL1Txs[5].FromIdx)
  498. assert.NotEqual(t, common.Idx(0), dbL1Txs[6].FromIdx)
  499. assert.NotEqual(t, common.Idx(0), dbL1Txs[7].FromIdx)
  500. assert.Equal(t, common.Idx(0), dbL1Txs[8].FromIdx)
  501. assert.Equal(t, common.Idx(0), dbL1Txs[9].FromIdx)
  502. assert.Equal(t, common.Idx(0), dbL1Txs[9].FromIdx)
  503. assert.Equal(t, dbL1Txs[5].FromIdx, dbL1Txs[6].FromIdx)
  504. assert.Equal(t, dbL1Txs[5].FromIdx, dbL1Txs[7].FromIdx)
  505. // Tx to IDx
  506. assert.Equal(t, dbL1Txs[2].ToIdx, dbL1Txs[5].FromIdx)
  507. assert.Equal(t, dbL1Txs[5].ToIdx, dbL1Txs[3].FromIdx)
  508. assert.Equal(t, dbL1Txs[6].ToIdx, dbL1Txs[3].FromIdx)
  509. // Token ID
  510. assert.Equal(t, common.TokenID(1), dbL1Txs[0].TokenID)
  511. assert.Equal(t, common.TokenID(1), dbL1Txs[1].TokenID)
  512. assert.Equal(t, common.TokenID(1), dbL1Txs[2].TokenID)
  513. assert.Equal(t, common.TokenID(1), dbL1Txs[3].TokenID)
  514. assert.Equal(t, common.TokenID(1), dbL1Txs[4].TokenID)
  515. assert.Equal(t, common.TokenID(1), dbL1Txs[5].TokenID)
  516. assert.Equal(t, common.TokenID(1), dbL1Txs[6].TokenID)
  517. assert.Equal(t, common.TokenID(1), dbL1Txs[7].TokenID)
  518. assert.Equal(t, common.TokenID(2), dbL1Txs[8].TokenID)
  519. assert.Equal(t, common.TokenID(2), dbL1Txs[9].TokenID)
  520. // Batch Number
  521. var bn common.BatchNum = common.BatchNum(2)
  522. assert.Equal(t, &bn, dbL1Txs[0].BatchNum)
  523. assert.Equal(t, &bn, dbL1Txs[1].BatchNum)
  524. bn = common.BatchNum(4)
  525. assert.Equal(t, &bn, dbL1Txs[2].BatchNum)
  526. bn = common.BatchNum(7)
  527. assert.Equal(t, &bn, dbL1Txs[3].BatchNum)
  528. assert.Equal(t, &bn, dbL1Txs[4].BatchNum)
  529. assert.Equal(t, &bn, dbL1Txs[5].BatchNum)
  530. bn = common.BatchNum(8)
  531. assert.Equal(t, &bn, dbL1Txs[6].BatchNum)
  532. assert.Equal(t, &bn, dbL1Txs[7].BatchNum)
  533. bn = common.BatchNum(10)
  534. assert.Equal(t, &bn, dbL1Txs[8].BatchNum)
  535. bn = common.BatchNum(11)
  536. assert.Equal(t, &bn, dbL1Txs[9].BatchNum)
  537. // eth_block_num
  538. assert.Equal(t, int64(2), dbL1Txs[0].EthBlockNum)
  539. assert.Equal(t, int64(2), dbL1Txs[1].EthBlockNum)
  540. assert.Equal(t, int64(3), dbL1Txs[2].EthBlockNum)
  541. assert.Equal(t, int64(4), dbL1Txs[3].EthBlockNum)
  542. assert.Equal(t, int64(4), dbL1Txs[4].EthBlockNum)
  543. assert.Equal(t, int64(5), dbL1Txs[5].EthBlockNum)
  544. assert.Equal(t, int64(6), dbL1Txs[6].EthBlockNum)
  545. assert.Equal(t, int64(6), dbL1Txs[7].EthBlockNum)
  546. assert.Equal(t, int64(7), dbL1Txs[8].EthBlockNum)
  547. assert.Equal(t, int64(8), dbL1Txs[9].EthBlockNum)
  548. // User Origin
  549. assert.Equal(t, true, dbL1Txs[0].UserOrigin)
  550. assert.Equal(t, true, dbL1Txs[1].UserOrigin)
  551. assert.Equal(t, true, dbL1Txs[2].UserOrigin)
  552. assert.Equal(t, true, dbL1Txs[3].UserOrigin)
  553. assert.Equal(t, true, dbL1Txs[4].UserOrigin)
  554. assert.Equal(t, true, dbL1Txs[5].UserOrigin)
  555. assert.Equal(t, true, dbL1Txs[6].UserOrigin)
  556. assert.Equal(t, true, dbL1Txs[7].UserOrigin)
  557. assert.Equal(t, true, dbL1Txs[8].UserOrigin)
  558. assert.Equal(t, true, dbL1Txs[9].UserOrigin)
  559. // Deposit Amount
  560. assert.Equal(t, big.NewInt(10), dbL1Txs[0].DepositAmount)
  561. assert.Equal(t, big.NewInt(10), dbL1Txs[1].DepositAmount)
  562. assert.Equal(t, big.NewInt(20), dbL1Txs[2].DepositAmount)
  563. assert.Equal(t, big.NewInt(10), dbL1Txs[3].DepositAmount)
  564. assert.Equal(t, big.NewInt(10), dbL1Txs[4].DepositAmount)
  565. assert.Equal(t, big.NewInt(10), dbL1Txs[5].DepositAmount)
  566. assert.Equal(t, big.NewInt(0), dbL1Txs[6].DepositAmount)
  567. assert.Equal(t, big.NewInt(0), dbL1Txs[7].DepositAmount)
  568. assert.Equal(t, big.NewInt(10), dbL1Txs[8].DepositAmount)
  569. assert.Equal(t, big.NewInt(10), dbL1Txs[9].DepositAmount)
  570. // Check saved txID's batch_num is not nil
  571. assert.Equal(t, txID, dbL1Txs[len(dbL1Txs)-2].TxID)
  572. assert.NotEqual(t, null, dbL1Txs[len(dbL1Txs)-2].BatchNum)
  573. // Check Coordinator TXs
  574. coordTxs, err := historyDB.GetAllL1CoordinatorTxs()
  575. assert.NoError(t, err)
  576. assert.Equal(t, 1, len(coordTxs))
  577. assert.Equal(t, common.TxTypeCreateAccountDeposit, coordTxs[0].Type)
  578. assert.Equal(t, false, coordTxs[0].UserOrigin)
  579. // Check L2 TXs
  580. dbL2Txs, err := historyDB.GetAllL2Txs()
  581. assert.NoError(t, err)
  582. assert.Equal(t, 4, len(dbL2Txs))
  583. // Tx Type
  584. assert.Equal(t, common.TxTypeTransfer, dbL2Txs[0].Type)
  585. assert.Equal(t, common.TxTypeTransfer, dbL2Txs[1].Type)
  586. assert.Equal(t, common.TxTypeTransfer, dbL2Txs[2].Type)
  587. assert.Equal(t, common.TxTypeExit, dbL2Txs[3].Type)
  588. // Tx ID
  589. assert.Equal(t, "0x024e555248100b69a8aabf6d31719b9fe8a60dcc6c3407904a93c8d2d9ade18ee5", dbL2Txs[0].TxID.String())
  590. assert.Equal(t, "0x021ae87ca34d50ff35d98dfc0d7c95f2bf2e4ffeebb82ea71f43a8b0dfa5d36d89", dbL2Txs[1].TxID.String())
  591. assert.Equal(t, "0x024abce7f3f2382dc520ed557593f11dea1ee197e55b60402e664facc27aa19774", dbL2Txs[2].TxID.String())
  592. assert.Equal(t, "0x02f921ad9e7a6e59606570fe12a7dde0e36014197de0363b9b45e5097d6f2b1dd0", dbL2Txs[3].TxID.String())
  593. // Tx From and To IDx
  594. assert.Equal(t, dbL2Txs[0].ToIdx, dbL2Txs[2].FromIdx)
  595. assert.Equal(t, dbL2Txs[1].ToIdx, dbL2Txs[0].FromIdx)
  596. assert.Equal(t, dbL2Txs[2].ToIdx, dbL2Txs[1].FromIdx)
  597. // Batch Number
  598. assert.Equal(t, common.BatchNum(5), dbL2Txs[0].BatchNum)
  599. assert.Equal(t, common.BatchNum(5), dbL2Txs[1].BatchNum)
  600. assert.Equal(t, common.BatchNum(5), dbL2Txs[2].BatchNum)
  601. assert.Equal(t, common.BatchNum(5), dbL2Txs[3].BatchNum)
  602. // eth_block_num
  603. assert.Equal(t, int64(4), dbL2Txs[0].EthBlockNum)
  604. assert.Equal(t, int64(4), dbL2Txs[1].EthBlockNum)
  605. assert.Equal(t, int64(4), dbL2Txs[2].EthBlockNum)
  606. // Amount
  607. assert.Equal(t, big.NewInt(10), dbL2Txs[0].Amount)
  608. assert.Equal(t, big.NewInt(10), dbL2Txs[1].Amount)
  609. assert.Equal(t, big.NewInt(10), dbL2Txs[2].Amount)
  610. assert.Equal(t, big.NewInt(10), dbL2Txs[3].Amount)
  611. }
  612. func TestExitTree(t *testing.T) {
  613. nBatches := 17
  614. blocks := setTestBlocks(1, 10)
  615. batches := test.GenBatches(nBatches, blocks)
  616. err := historyDB.AddBatches(batches)
  617. assert.NoError(t, err)
  618. const nTokens = 50
  619. tokens, ethToken := test.GenTokens(nTokens, blocks)
  620. err = historyDB.AddTokens(tokens)
  621. assert.NoError(t, err)
  622. tokens = append([]common.Token{ethToken}, tokens...)
  623. const nAccounts = 3
  624. accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
  625. assert.NoError(t, historyDB.AddAccounts(accs))
  626. exitTree := test.GenExitTree(nBatches, batches, accs, blocks)
  627. err = historyDB.AddExitTree(exitTree)
  628. assert.NoError(t, err)
  629. }
  630. func TestGetUnforgedL1UserTxs(t *testing.T) {
  631. test.WipeDB(historyDB.DB())
  632. set := `
  633. Type: Blockchain
  634. AddToken(1)
  635. AddToken(2)
  636. AddToken(3)
  637. CreateAccountDeposit(1) A: 20
  638. CreateAccountDeposit(2) A: 20
  639. CreateAccountDeposit(1) B: 5
  640. CreateAccountDeposit(1) C: 5
  641. CreateAccountDeposit(1) D: 5
  642. > block
  643. `
  644. tc := til.NewContext(uint16(0), 128)
  645. blocks, err := tc.GenerateBlocks(set)
  646. require.NoError(t, err)
  647. // Sanity check
  648. require.Equal(t, 1, len(blocks))
  649. require.Equal(t, 5, len(blocks[0].Rollup.L1UserTxs))
  650. toForgeL1TxsNum := int64(1)
  651. for i := range blocks {
  652. err = historyDB.AddBlockSCData(&blocks[i])
  653. require.NoError(t, err)
  654. }
  655. l1UserTxs, err := historyDB.GetUnforgedL1UserTxs(toForgeL1TxsNum)
  656. require.NoError(t, err)
  657. assert.Equal(t, 5, len(l1UserTxs))
  658. assert.Equal(t, blocks[0].Rollup.L1UserTxs, l1UserTxs)
  659. count, err := historyDB.GetUnforgedL1UserTxsCount()
  660. require.NoError(t, err)
  661. assert.Equal(t, 5, count)
  662. // No l1UserTxs for this toForgeL1TxsNum
  663. l1UserTxs, err = historyDB.GetUnforgedL1UserTxs(2)
  664. require.NoError(t, err)
  665. assert.Equal(t, 0, len(l1UserTxs))
  666. }
  667. func exampleInitSCVars() (*common.RollupVariables, *common.AuctionVariables, *common.WDelayerVariables) {
  668. //nolint:govet
  669. rollup := &common.RollupVariables{
  670. 0,
  671. big.NewInt(10),
  672. 12,
  673. 13,
  674. [5]common.BucketParams{},
  675. false,
  676. }
  677. //nolint:govet
  678. auction := &common.AuctionVariables{
  679. 0,
  680. ethCommon.BigToAddress(big.NewInt(2)),
  681. ethCommon.BigToAddress(big.NewInt(3)),
  682. "https://boot.coord.com",
  683. [6]*big.Int{
  684. big.NewInt(1), big.NewInt(2), big.NewInt(3),
  685. big.NewInt(4), big.NewInt(5), big.NewInt(6),
  686. },
  687. 0,
  688. 2,
  689. 4320,
  690. [3]uint16{10, 11, 12},
  691. 1000,
  692. 20,
  693. }
  694. //nolint:govet
  695. wDelayer := &common.WDelayerVariables{
  696. 0,
  697. ethCommon.BigToAddress(big.NewInt(2)),
  698. ethCommon.BigToAddress(big.NewInt(3)),
  699. 13,
  700. 14,
  701. false,
  702. }
  703. return rollup, auction, wDelayer
  704. }
  705. func TestSetInitialSCVars(t *testing.T) {
  706. test.WipeDB(historyDB.DB())
  707. _, _, _, err := historyDB.GetSCVars()
  708. assert.Equal(t, sql.ErrNoRows, tracerr.Unwrap(err))
  709. rollup, auction, wDelayer := exampleInitSCVars()
  710. err = historyDB.SetInitialSCVars(rollup, auction, wDelayer)
  711. require.NoError(t, err)
  712. dbRollup, dbAuction, dbWDelayer, err := historyDB.GetSCVars()
  713. require.NoError(t, err)
  714. require.Equal(t, rollup, dbRollup)
  715. require.Equal(t, auction, dbAuction)
  716. require.Equal(t, wDelayer, dbWDelayer)
  717. }
  718. func TestSetExtraInfoForgedL1UserTxs(t *testing.T) {
  719. test.WipeDB(historyDB.DB())
  720. set := `
  721. Type: Blockchain
  722. AddToken(1)
  723. CreateAccountDeposit(1) A: 2000
  724. CreateAccountDeposit(1) B: 500
  725. CreateAccountDeposit(1) C: 500
  726. > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{*}
  727. > block // blockNum=2
  728. > batchL1 // forge defined L1UserTxs{*}
  729. > block // blockNum=3
  730. `
  731. tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
  732. tilCfgExtra := til.ConfigExtra{
  733. BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
  734. CoordUser: "A",
  735. }
  736. blocks, err := tc.GenerateBlocks(set)
  737. require.NoError(t, err)
  738. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  739. require.NoError(t, err)
  740. err = tc.FillBlocksForgedL1UserTxs(blocks)
  741. require.NoError(t, err)
  742. // Add only first block so that the L1UserTxs are not marked as forged
  743. for i := range blocks[:1] {
  744. err = historyDB.AddBlockSCData(&blocks[i])
  745. require.NoError(t, err)
  746. }
  747. // Add second batch to trigger the update of the batch_num,
  748. // while avoiding the implicit call of setExtraInfoForgedL1UserTxs
  749. err = historyDB.addBlock(historyDB.dbWrite, &blocks[1].Block)
  750. require.NoError(t, err)
  751. err = historyDB.addBatch(historyDB.dbWrite, &blocks[1].Rollup.Batches[0].Batch)
  752. require.NoError(t, err)
  753. err = historyDB.addAccounts(historyDB.dbWrite, blocks[1].Rollup.Batches[0].CreatedAccounts)
  754. require.NoError(t, err)
  755. // Set the Effective{Amount,DepositAmount} of the L1UserTxs that are forged in the second block
  756. l1Txs := blocks[1].Rollup.Batches[0].L1UserTxs
  757. require.Equal(t, 3, len(l1Txs))
  758. // Change some values to test all cases
  759. l1Txs[1].EffectiveAmount = big.NewInt(0)
  760. l1Txs[2].EffectiveDepositAmount = big.NewInt(0)
  761. l1Txs[2].EffectiveAmount = big.NewInt(0)
  762. err = historyDB.setExtraInfoForgedL1UserTxs(historyDB.dbWrite, l1Txs)
  763. require.NoError(t, err)
  764. dbL1Txs, err := historyDB.GetAllL1UserTxs()
  765. require.NoError(t, err)
  766. for i, tx := range dbL1Txs {
  767. log.Infof("%d %v %v", i, tx.EffectiveAmount, tx.EffectiveDepositAmount)
  768. assert.NotNil(t, tx.EffectiveAmount)
  769. assert.NotNil(t, tx.EffectiveDepositAmount)
  770. switch tx.TxID {
  771. case l1Txs[0].TxID:
  772. assert.Equal(t, l1Txs[0].DepositAmount, tx.EffectiveDepositAmount)
  773. assert.Equal(t, l1Txs[0].Amount, tx.EffectiveAmount)
  774. case l1Txs[1].TxID:
  775. assert.Equal(t, l1Txs[1].DepositAmount, tx.EffectiveDepositAmount)
  776. assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
  777. case l1Txs[2].TxID:
  778. assert.Equal(t, big.NewInt(0), tx.EffectiveDepositAmount)
  779. assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
  780. }
  781. }
  782. }
  783. func TestUpdateExitTree(t *testing.T) {
  784. test.WipeDB(historyDB.DB())
  785. set := `
  786. Type: Blockchain
  787. AddToken(1)
  788. CreateAccountDeposit(1) C: 2000 // Idx=256+2=258
  789. CreateAccountDeposit(1) D: 500 // Idx=256+3=259
  790. CreateAccountCoordinator(1) A // Idx=256+0=256
  791. CreateAccountCoordinator(1) B // Idx=256+1=257
  792. > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{5}
  793. > batchL1 // forge defined L1UserTxs{5}, freeze L1UserTxs{nil}
  794. > block // blockNum=2
  795. ForceExit(1) A: 100
  796. ForceExit(1) B: 80
  797. Exit(1) C: 50 (172)
  798. Exit(1) D: 30 (172)
  799. > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{3}
  800. > batchL1 // forge L1UserTxs{3}, freeze defined L1UserTxs{nil}
  801. > block // blockNum=3
  802. > block // blockNum=4 (empty block)
  803. > block // blockNum=5 (empty block)
  804. `
  805. tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
  806. tilCfgExtra := til.ConfigExtra{
  807. BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
  808. CoordUser: "A",
  809. }
  810. blocks, err := tc.GenerateBlocks(set)
  811. require.NoError(t, err)
  812. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  813. require.NoError(t, err)
  814. // Add all blocks except for the last two
  815. for i := range blocks[:len(blocks)-2] {
  816. err = historyDB.AddBlockSCData(&blocks[i])
  817. require.NoError(t, err)
  818. }
  819. // Add withdraws to the second-to-last block, and insert block into the DB
  820. block := &blocks[len(blocks)-2]
  821. require.Equal(t, int64(4), block.Block.Num)
  822. tokenAddr := blocks[0].Rollup.AddedTokens[0].EthAddr
  823. // block.WDelayer.Deposits = append(block.WDelayer.Deposits,
  824. // common.WDelayerTransfer{Owner: tc.UsersByIdx[257].Addr, Token: tokenAddr, Amount: big.NewInt(80)}, // 257
  825. // common.WDelayerTransfer{Owner: tc.UsersByIdx[259].Addr, Token: tokenAddr, Amount: big.NewInt(15)}, // 259
  826. // )
  827. block.Rollup.Withdrawals = append(block.Rollup.Withdrawals,
  828. common.WithdrawInfo{Idx: 256, NumExitRoot: 4, InstantWithdraw: true},
  829. common.WithdrawInfo{Idx: 257, NumExitRoot: 4, InstantWithdraw: false,
  830. Owner: tc.UsersByIdx[257].Addr, Token: tokenAddr},
  831. common.WithdrawInfo{Idx: 258, NumExitRoot: 3, InstantWithdraw: true},
  832. common.WithdrawInfo{Idx: 259, NumExitRoot: 3, InstantWithdraw: false,
  833. Owner: tc.UsersByIdx[259].Addr, Token: tokenAddr},
  834. )
  835. err = historyDB.addBlock(historyDB.dbWrite, &block.Block)
  836. require.NoError(t, err)
  837. err = historyDB.updateExitTree(historyDB.dbWrite, block.Block.Num,
  838. block.Rollup.Withdrawals, block.WDelayer.Withdrawals)
  839. require.NoError(t, err)
  840. // Check that exits in DB match with the expected values
  841. dbExits, err := historyDB.GetAllExits()
  842. require.NoError(t, err)
  843. assert.Equal(t, 4, len(dbExits))
  844. dbExitsByIdx := make(map[common.Idx]common.ExitInfo)
  845. for _, dbExit := range dbExits {
  846. dbExitsByIdx[dbExit.AccountIdx] = dbExit
  847. }
  848. for _, withdraw := range block.Rollup.Withdrawals {
  849. assert.Equal(t, withdraw.NumExitRoot, dbExitsByIdx[withdraw.Idx].BatchNum)
  850. if withdraw.InstantWithdraw {
  851. assert.Equal(t, &block.Block.Num, dbExitsByIdx[withdraw.Idx].InstantWithdrawn)
  852. } else {
  853. assert.Equal(t, &block.Block.Num, dbExitsByIdx[withdraw.Idx].DelayedWithdrawRequest)
  854. }
  855. }
  856. // Add delayed withdraw to the last block, and insert block into the DB
  857. block = &blocks[len(blocks)-1]
  858. require.Equal(t, int64(5), block.Block.Num)
  859. block.WDelayer.Withdrawals = append(block.WDelayer.Withdrawals,
  860. common.WDelayerTransfer{
  861. Owner: tc.UsersByIdx[257].Addr,
  862. Token: tokenAddr,
  863. Amount: big.NewInt(80),
  864. })
  865. err = historyDB.addBlock(historyDB.dbWrite, &block.Block)
  866. require.NoError(t, err)
  867. err = historyDB.updateExitTree(historyDB.dbWrite, block.Block.Num,
  868. block.Rollup.Withdrawals, block.WDelayer.Withdrawals)
  869. require.NoError(t, err)
  870. // Check that delayed withdrawn has been set
  871. dbExits, err = historyDB.GetAllExits()
  872. require.NoError(t, err)
  873. for _, dbExit := range dbExits {
  874. dbExitsByIdx[dbExit.AccountIdx] = dbExit
  875. }
  876. require.Equal(t, &block.Block.Num, dbExitsByIdx[257].DelayedWithdrawn)
  877. }
  878. func TestGetBestBidCoordinator(t *testing.T) {
  879. test.WipeDB(historyDB.DB())
  880. rollup, auction, wDelayer := exampleInitSCVars()
  881. err := historyDB.SetInitialSCVars(rollup, auction, wDelayer)
  882. require.NoError(t, err)
  883. tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
  884. blocks, err := tc.GenerateBlocks(`
  885. Type: Blockchain
  886. > block // blockNum=2
  887. `)
  888. require.NoError(t, err)
  889. err = historyDB.AddBlockSCData(&blocks[0])
  890. require.NoError(t, err)
  891. coords := []common.Coordinator{
  892. {
  893. Bidder: ethCommon.BigToAddress(big.NewInt(1)),
  894. Forger: ethCommon.BigToAddress(big.NewInt(2)),
  895. EthBlockNum: 2,
  896. URL: "foo",
  897. },
  898. {
  899. Bidder: ethCommon.BigToAddress(big.NewInt(3)),
  900. Forger: ethCommon.BigToAddress(big.NewInt(4)),
  901. EthBlockNum: 2,
  902. URL: "bar",
  903. },
  904. }
  905. err = historyDB.addCoordinators(historyDB.dbWrite, coords)
  906. require.NoError(t, err)
  907. bids := []common.Bid{
  908. {
  909. SlotNum: 10,
  910. BidValue: big.NewInt(10),
  911. EthBlockNum: 2,
  912. Bidder: coords[0].Bidder,
  913. },
  914. {
  915. SlotNum: 10,
  916. BidValue: big.NewInt(20),
  917. EthBlockNum: 2,
  918. Bidder: coords[1].Bidder,
  919. },
  920. }
  921. err = historyDB.addBids(historyDB.dbWrite, bids)
  922. require.NoError(t, err)
  923. forger10, err := historyDB.GetBestBidCoordinator(10)
  924. require.NoError(t, err)
  925. require.Equal(t, coords[1].Forger, forger10.Forger)
  926. require.Equal(t, coords[1].Bidder, forger10.Bidder)
  927. require.Equal(t, coords[1].URL, forger10.URL)
  928. require.Equal(t, bids[1].SlotNum, forger10.SlotNum)
  929. require.Equal(t, bids[1].BidValue, forger10.BidValue)
  930. for i := range forger10.DefaultSlotSetBid {
  931. require.Equal(t, auction.DefaultSlotSetBid[i], forger10.DefaultSlotSetBid[i])
  932. }
  933. _, err = historyDB.GetBestBidCoordinator(11)
  934. require.Equal(t, sql.ErrNoRows, tracerr.Unwrap(err))
  935. }
  936. func TestAddBucketUpdates(t *testing.T) {
  937. test.WipeDB(historyDB.DB())
  938. const fromBlock int64 = 1
  939. const toBlock int64 = 5 + 1
  940. setTestBlocks(fromBlock, toBlock)
  941. bucketUpdates := []common.BucketUpdate{
  942. {
  943. EthBlockNum: 4,
  944. NumBucket: 0,
  945. BlockStamp: 4,
  946. Withdrawals: big.NewInt(123),
  947. },
  948. {
  949. EthBlockNum: 5,
  950. NumBucket: 2,
  951. BlockStamp: 5,
  952. Withdrawals: big.NewInt(42),
  953. },
  954. }
  955. err := historyDB.addBucketUpdates(historyDB.dbWrite, bucketUpdates)
  956. require.NoError(t, err)
  957. dbBucketUpdates, err := historyDB.GetAllBucketUpdates()
  958. require.NoError(t, err)
  959. assert.Equal(t, bucketUpdates, dbBucketUpdates)
  960. }
  961. func TestAddTokenExchanges(t *testing.T) {
  962. test.WipeDB(historyDB.DB())
  963. const fromBlock int64 = 1
  964. const toBlock int64 = 5 + 1
  965. setTestBlocks(fromBlock, toBlock)
  966. tokenExchanges := []common.TokenExchange{
  967. {
  968. EthBlockNum: 4,
  969. Address: ethCommon.BigToAddress(big.NewInt(111)),
  970. ValueUSD: 12345,
  971. },
  972. {
  973. EthBlockNum: 5,
  974. Address: ethCommon.BigToAddress(big.NewInt(222)),
  975. ValueUSD: 67890,
  976. },
  977. }
  978. err := historyDB.addTokenExchanges(historyDB.dbWrite, tokenExchanges)
  979. require.NoError(t, err)
  980. dbTokenExchanges, err := historyDB.GetAllTokenExchanges()
  981. require.NoError(t, err)
  982. assert.Equal(t, tokenExchanges, dbTokenExchanges)
  983. }
  984. func TestAddEscapeHatchWithdrawals(t *testing.T) {
  985. test.WipeDB(historyDB.DB())
  986. const fromBlock int64 = 1
  987. const toBlock int64 = 5 + 1
  988. setTestBlocks(fromBlock, toBlock)
  989. escapeHatchWithdrawals := []common.WDelayerEscapeHatchWithdrawal{
  990. {
  991. EthBlockNum: 4,
  992. Who: ethCommon.BigToAddress(big.NewInt(111)),
  993. To: ethCommon.BigToAddress(big.NewInt(222)),
  994. TokenAddr: ethCommon.BigToAddress(big.NewInt(333)),
  995. Amount: big.NewInt(10002),
  996. },
  997. {
  998. EthBlockNum: 5,
  999. Who: ethCommon.BigToAddress(big.NewInt(444)),
  1000. To: ethCommon.BigToAddress(big.NewInt(555)),
  1001. TokenAddr: ethCommon.BigToAddress(big.NewInt(666)),
  1002. Amount: big.NewInt(20003),
  1003. },
  1004. }
  1005. err := historyDB.addEscapeHatchWithdrawals(historyDB.dbWrite, escapeHatchWithdrawals)
  1006. require.NoError(t, err)
  1007. dbEscapeHatchWithdrawals, err := historyDB.GetAllEscapeHatchWithdrawals()
  1008. require.NoError(t, err)
  1009. assert.Equal(t, escapeHatchWithdrawals, dbEscapeHatchWithdrawals)
  1010. }
  1011. func TestGetMetricsAPI(t *testing.T) {
  1012. test.WipeDB(historyDB.DB())
  1013. set := `
  1014. Type: Blockchain
  1015. AddToken(1)
  1016. CreateAccountDeposit(1) A: 1000 // numTx=1
  1017. CreateAccountDeposit(1) B: 2000 // numTx=2
  1018. CreateAccountDeposit(1) C: 3000 //numTx=3
  1019. // block 0 is stored as default in the DB
  1020. // block 1 does not exist
  1021. > batchL1 // numBatches=1
  1022. > batchL1 // numBatches=2
  1023. > block // blockNum=2
  1024. Transfer(1) C-A : 10 (1) // numTx=4
  1025. > batch // numBatches=3
  1026. > block // blockNum=3
  1027. Transfer(1) B-C : 10 (1) // numTx=5
  1028. > batch // numBatches=5
  1029. > block // blockNum=4
  1030. Transfer(1) A-B : 10 (1) // numTx=6
  1031. > batch // numBatches=5
  1032. > block // blockNum=5
  1033. Transfer(1) A-B : 10 (1) // numTx=7
  1034. > batch // numBatches=6
  1035. > block // blockNum=6
  1036. `
  1037. const numBatches int = 6
  1038. const numTx int = 7
  1039. const blockNum = 6 - 1
  1040. tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
  1041. tilCfgExtra := til.ConfigExtra{
  1042. BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
  1043. CoordUser: "A",
  1044. }
  1045. blocks, err := tc.GenerateBlocks(set)
  1046. require.NoError(t, err)
  1047. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  1048. require.NoError(t, err)
  1049. // Sanity check
  1050. require.Equal(t, blockNum, len(blocks))
  1051. // Adding one batch per block
  1052. // batch frequency can be chosen
  1053. const frequency int = 15
  1054. for i := range blocks {
  1055. blocks[i].Block.Timestamp = time.Now().Add(-time.Second * time.Duration(frequency*(len(blocks)-i)))
  1056. err = historyDB.AddBlockSCData(&blocks[i])
  1057. assert.NoError(t, err)
  1058. }
  1059. res, err := historyDBWithACC.GetMetricsAPI(common.BatchNum(numBatches))
  1060. assert.NoError(t, err)
  1061. assert.Equal(t, float64(numTx)/float64(numBatches), res.TransactionsPerBatch)
  1062. // Frequency is not exactly the desired one, some decimals may appear
  1063. // There is a -2 as time for first and last batch is not taken into account
  1064. assert.InEpsilon(t, float64(frequency)*float64(numBatches-2)/float64(numBatches), res.BatchFrequency, 0.01)
  1065. assert.InEpsilon(t, float64(numTx)/float64(frequency*blockNum-frequency), res.TransactionsPerSecond, 0.01)
  1066. assert.Equal(t, int64(3), res.TotalAccounts)
  1067. assert.Equal(t, int64(3), res.TotalBJJs)
  1068. // Til does not set fees
  1069. assert.Equal(t, float64(0), res.AvgTransactionFee)
  1070. }
  1071. func TestGetMetricsAPIMoreThan24Hours(t *testing.T) {
  1072. test.WipeDB(historyDB.DB())
  1073. testUsersLen := 3
  1074. var set []til.Instruction
  1075. for user := 0; user < testUsersLen; user++ {
  1076. set = append(set, til.Instruction{
  1077. Typ: common.TxTypeCreateAccountDeposit,
  1078. TokenID: common.TokenID(0),
  1079. DepositAmount: big.NewInt(1000000),
  1080. Amount: big.NewInt(0),
  1081. From: fmt.Sprintf("User%02d", user),
  1082. })
  1083. set = append(set, til.Instruction{Typ: til.TypeNewBlock})
  1084. }
  1085. set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
  1086. set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
  1087. set = append(set, til.Instruction{Typ: til.TypeNewBlock})
  1088. // Transfers
  1089. const numBlocks int = 30
  1090. for x := 0; x < numBlocks; x++ {
  1091. set = append(set, til.Instruction{
  1092. Typ: common.TxTypeTransfer,
  1093. TokenID: common.TokenID(0),
  1094. DepositAmount: big.NewInt(1),
  1095. Amount: big.NewInt(0),
  1096. From: "User00",
  1097. To: "User01",
  1098. })
  1099. set = append(set, til.Instruction{Typ: til.TypeNewBatch})
  1100. set = append(set, til.Instruction{Typ: til.TypeNewBlock})
  1101. }
  1102. var chainID uint16 = 0
  1103. tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
  1104. blocks, err := tc.GenerateBlocksFromInstructions(set)
  1105. assert.NoError(t, err)
  1106. tilCfgExtra := til.ConfigExtra{
  1107. CoordUser: "A",
  1108. }
  1109. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  1110. require.NoError(t, err)
  1111. const numBatches int = 2 + numBlocks
  1112. const blockNum = 4 + numBlocks
  1113. // Sanity check
  1114. require.Equal(t, blockNum, len(blocks))
  1115. // Adding one batch per block
  1116. // batch frequency can be chosen
  1117. const blockTime time.Duration = 3600 * time.Second
  1118. now := time.Now()
  1119. require.NoError(t, err)
  1120. for i := range blocks {
  1121. blocks[i].Block.Timestamp = now.Add(-time.Duration(len(blocks)-1-i) * blockTime)
  1122. err = historyDB.AddBlockSCData(&blocks[i])
  1123. assert.NoError(t, err)
  1124. }
  1125. res, err := historyDBWithACC.GetMetricsAPI(common.BatchNum(numBatches))
  1126. assert.NoError(t, err)
  1127. assert.InEpsilon(t, 1.0, res.TransactionsPerBatch, 0.1)
  1128. assert.InEpsilon(t, res.BatchFrequency, float64(blockTime/time.Second), 0.1)
  1129. assert.InEpsilon(t, 1.0/float64(blockTime/time.Second), res.TransactionsPerSecond, 0.1)
  1130. assert.Equal(t, int64(3), res.TotalAccounts)
  1131. assert.Equal(t, int64(3), res.TotalBJJs)
  1132. // Til does not set fees
  1133. assert.Equal(t, float64(0), res.AvgTransactionFee)
  1134. }
  1135. func TestGetMetricsAPIEmpty(t *testing.T) {
  1136. test.WipeDB(historyDB.DB())
  1137. _, err := historyDBWithACC.GetMetricsAPI(0)
  1138. assert.NoError(t, err)
  1139. }
  1140. func TestGetAvgTxFeeEmpty(t *testing.T) {
  1141. test.WipeDB(historyDB.DB())
  1142. _, err := historyDBWithACC.GetAvgTxFeeAPI()
  1143. assert.NoError(t, err)
  1144. }
  1145. func TestGetLastL1TxsNum(t *testing.T) {
  1146. test.WipeDB(historyDB.DB())
  1147. _, err := historyDB.GetLastL1TxsNum()
  1148. assert.NoError(t, err)
  1149. }
  1150. func TestGetLastTxsPosition(t *testing.T) {
  1151. test.WipeDB(historyDB.DB())
  1152. _, err := historyDB.GetLastTxsPosition(0)
  1153. assert.Equal(t, sql.ErrNoRows.Error(), err.Error())
  1154. }
  1155. func TestGetFirstBatchBlockNumBySlot(t *testing.T) {
  1156. test.WipeDB(historyDB.DB())
  1157. set := `
  1158. Type: Blockchain
  1159. // Slot = 0
  1160. > block // 2
  1161. > block // 3
  1162. > block // 4
  1163. > block // 5
  1164. // Slot = 1
  1165. > block // 6
  1166. > block // 7
  1167. > batch
  1168. > block // 8
  1169. > block // 9
  1170. // Slot = 2
  1171. > batch
  1172. > block // 10
  1173. > block // 11
  1174. > block // 12
  1175. > block // 13
  1176. `
  1177. tc := til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
  1178. blocks, err := tc.GenerateBlocks(set)
  1179. assert.NoError(t, err)
  1180. tilCfgExtra := til.ConfigExtra{
  1181. CoordUser: "A",
  1182. }
  1183. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  1184. require.NoError(t, err)
  1185. for i := range blocks {
  1186. for j := range blocks[i].Rollup.Batches {
  1187. blocks[i].Rollup.Batches[j].Batch.SlotNum = int64(i) / 4
  1188. }
  1189. }
  1190. // Add all blocks
  1191. for i := range blocks {
  1192. err = historyDB.AddBlockSCData(&blocks[i])
  1193. require.NoError(t, err)
  1194. }
  1195. _, err = historyDB.GetFirstBatchBlockNumBySlot(0)
  1196. require.Equal(t, sql.ErrNoRows, tracerr.Unwrap(err))
  1197. bn1, err := historyDB.GetFirstBatchBlockNumBySlot(1)
  1198. require.NoError(t, err)
  1199. assert.Equal(t, int64(8), bn1)
  1200. bn2, err := historyDB.GetFirstBatchBlockNumBySlot(2)
  1201. require.NoError(t, err)
  1202. assert.Equal(t, int64(10), bn2)
  1203. }
  1204. func TestTxItemID(t *testing.T) {
  1205. test.WipeDB(historyDB.DB())
  1206. testUsersLen := 10
  1207. var set []til.Instruction
  1208. for user := 0; user < testUsersLen; user++ {
  1209. set = append(set, til.Instruction{
  1210. Typ: common.TxTypeCreateAccountDeposit,
  1211. TokenID: common.TokenID(0),
  1212. DepositAmount: big.NewInt(1000000),
  1213. Amount: big.NewInt(0),
  1214. From: fmt.Sprintf("User%02d", user),
  1215. })
  1216. set = append(set, til.Instruction{Typ: til.TypeNewBlock})
  1217. }
  1218. set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
  1219. set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
  1220. set = append(set, til.Instruction{Typ: til.TypeNewBlock})
  1221. for user := 0; user < testUsersLen; user++ {
  1222. set = append(set, til.Instruction{
  1223. Typ: common.TxTypeDeposit,
  1224. TokenID: common.TokenID(0),
  1225. DepositAmount: big.NewInt(100000),
  1226. Amount: big.NewInt(0),
  1227. From: fmt.Sprintf("User%02d", user),
  1228. })
  1229. set = append(set, til.Instruction{Typ: til.TypeNewBlock})
  1230. }
  1231. set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
  1232. set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
  1233. set = append(set, til.Instruction{Typ: til.TypeNewBlock})
  1234. for user := 0; user < testUsersLen; user++ {
  1235. set = append(set, til.Instruction{
  1236. Typ: common.TxTypeDepositTransfer,
  1237. TokenID: common.TokenID(0),
  1238. DepositAmount: big.NewInt(10000 * int64(user+1)),
  1239. Amount: big.NewInt(1000 * int64(user+1)),
  1240. From: fmt.Sprintf("User%02d", user),
  1241. To: fmt.Sprintf("User%02d", (user+1)%testUsersLen),
  1242. })
  1243. set = append(set, til.Instruction{Typ: til.TypeNewBlock})
  1244. }
  1245. set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
  1246. set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
  1247. set = append(set, til.Instruction{Typ: til.TypeNewBlock})
  1248. for user := 0; user < testUsersLen; user++ {
  1249. set = append(set, til.Instruction{
  1250. Typ: common.TxTypeForceTransfer,
  1251. TokenID: common.TokenID(0),
  1252. Amount: big.NewInt(100 * int64(user+1)),
  1253. DepositAmount: big.NewInt(0),
  1254. From: fmt.Sprintf("User%02d", user),
  1255. To: fmt.Sprintf("User%02d", (user+1)%testUsersLen),
  1256. })
  1257. set = append(set, til.Instruction{Typ: til.TypeNewBlock})
  1258. }
  1259. set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
  1260. set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
  1261. set = append(set, til.Instruction{Typ: til.TypeNewBlock})
  1262. for user := 0; user < testUsersLen; user++ {
  1263. set = append(set, til.Instruction{
  1264. Typ: common.TxTypeForceExit,
  1265. TokenID: common.TokenID(0),
  1266. Amount: big.NewInt(10 * int64(user+1)),
  1267. DepositAmount: big.NewInt(0),
  1268. From: fmt.Sprintf("User%02d", user),
  1269. })
  1270. set = append(set, til.Instruction{Typ: til.TypeNewBlock})
  1271. }
  1272. set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
  1273. set = append(set, til.Instruction{Typ: til.TypeNewBatchL1})
  1274. set = append(set, til.Instruction{Typ: til.TypeNewBlock})
  1275. var chainID uint16 = 0
  1276. tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
  1277. blocks, err := tc.GenerateBlocksFromInstructions(set)
  1278. assert.NoError(t, err)
  1279. tilCfgExtra := til.ConfigExtra{
  1280. CoordUser: "A",
  1281. }
  1282. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  1283. require.NoError(t, err)
  1284. // Add all blocks
  1285. for i := range blocks {
  1286. err = historyDB.AddBlockSCData(&blocks[i])
  1287. require.NoError(t, err)
  1288. }
  1289. txs, err := historyDB.GetAllL1UserTxs()
  1290. require.NoError(t, err)
  1291. position := 0
  1292. for _, tx := range txs {
  1293. if tx.Position == 0 {
  1294. position = 0
  1295. }
  1296. assert.Equal(t, position, tx.Position)
  1297. position++
  1298. }
  1299. }
  1300. // setTestBlocks WARNING: this will delete the blocks and recreate them
  1301. func setTestBlocks(from, to int64) []common.Block {
  1302. test.WipeDB(historyDB.DB())
  1303. blocks := test.GenBlocks(from, to)
  1304. if err := historyDB.AddBlocks(blocks); err != nil {
  1305. panic(err)
  1306. }
  1307. return blocks
  1308. }