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.

853 lines
26 KiB

Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator 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.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator 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.
4 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`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator 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.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
  1. package synchronizer
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "math/big"
  8. "os"
  9. "sort"
  10. "testing"
  11. "time"
  12. ethCommon "github.com/ethereum/go-ethereum/common"
  13. "github.com/hermeznetwork/hermez-node/common"
  14. dbUtils "github.com/hermeznetwork/hermez-node/db"
  15. "github.com/hermeznetwork/hermez-node/db/historydb"
  16. "github.com/hermeznetwork/hermez-node/db/statedb"
  17. "github.com/hermeznetwork/hermez-node/eth"
  18. "github.com/hermeznetwork/hermez-node/test"
  19. "github.com/hermeznetwork/hermez-node/test/til"
  20. "github.com/jinzhu/copier"
  21. "github.com/stretchr/testify/assert"
  22. "github.com/stretchr/testify/require"
  23. )
  24. var tokenConsts = map[common.TokenID]eth.ERC20Consts{}
  25. type timer struct {
  26. time int64
  27. }
  28. func (t *timer) Time() int64 {
  29. currentTime := t.time
  30. t.time++
  31. return currentTime
  32. }
  33. func accountsCmp(accounts []common.Account) func(i, j int) bool {
  34. return func(i, j int) bool { return accounts[i].Idx < accounts[j].Idx }
  35. }
  36. // Check Sync output and HistoryDB state against expected values generated by
  37. // til
  38. func checkSyncBlock(t *testing.T, s *Synchronizer, blockNum int, block,
  39. syncBlock *common.BlockData) {
  40. // Check Blocks
  41. dbBlocks, err := s.historyDB.GetAllBlocks()
  42. require.NoError(t, err)
  43. dbBlocks = dbBlocks[1:] // ignore block 0, added by default in the DB
  44. assert.Equal(t, blockNum, len(dbBlocks))
  45. assert.Equal(t, int64(blockNum), dbBlocks[blockNum-1].Num)
  46. assert.NotEqual(t, dbBlocks[blockNum-1].Hash, dbBlocks[blockNum-2].Hash)
  47. assert.Greater(t, dbBlocks[blockNum-1].Timestamp.Unix(), dbBlocks[blockNum-2].Timestamp.Unix())
  48. // Check Tokens
  49. assert.Equal(t, len(block.Rollup.AddedTokens), len(syncBlock.Rollup.AddedTokens))
  50. dbTokens, err := s.historyDB.GetAllTokens()
  51. require.NoError(t, err)
  52. dbTokens = dbTokens[1:] // ignore token 0, added by default in the DB
  53. for i, token := range block.Rollup.AddedTokens {
  54. dbToken := dbTokens[i]
  55. syncToken := syncBlock.Rollup.AddedTokens[i]
  56. assert.Equal(t, block.Block.Num, syncToken.EthBlockNum)
  57. assert.Equal(t, token.TokenID, syncToken.TokenID)
  58. assert.Equal(t, token.EthAddr, syncToken.EthAddr)
  59. tokenConst := tokenConsts[token.TokenID]
  60. assert.Equal(t, tokenConst.Name, syncToken.Name)
  61. assert.Equal(t, tokenConst.Symbol, syncToken.Symbol)
  62. assert.Equal(t, tokenConst.Decimals, syncToken.Decimals)
  63. var tokenCpy historydb.TokenWithUSD
  64. //nolint:gosec
  65. require.Nil(t, copier.Copy(&tokenCpy, &token)) // copy common.Token to historydb.TokenWithUSD
  66. require.Nil(t, copier.Copy(&tokenCpy, &tokenConst)) // copy common.Token to historydb.TokenWithUSD
  67. tokenCpy.ItemID = dbToken.ItemID // we don't care about ItemID
  68. assert.Equal(t, tokenCpy, dbToken)
  69. }
  70. // Check submitted L1UserTxs
  71. assert.Equal(t, len(block.Rollup.L1UserTxs), len(syncBlock.Rollup.L1UserTxs))
  72. dbL1UserTxs, err := s.historyDB.GetAllL1UserTxs()
  73. require.NoError(t, err)
  74. // Ignore BatchNum in syncBlock.L1UserTxs because this value is set by
  75. // the HistoryDB. Also ignore EffectiveAmount & EffectiveDepositAmount
  76. // because this value is set by StateDB.ProcessTxs.
  77. for i := range syncBlock.Rollup.L1UserTxs {
  78. syncBlock.Rollup.L1UserTxs[i].BatchNum = block.Rollup.L1UserTxs[i].BatchNum
  79. assert.Nil(t, syncBlock.Rollup.L1UserTxs[i].EffectiveDepositAmount)
  80. assert.Nil(t, syncBlock.Rollup.L1UserTxs[i].EffectiveAmount)
  81. }
  82. assert.Equal(t, block.Rollup.L1UserTxs, syncBlock.Rollup.L1UserTxs)
  83. for _, tx := range block.Rollup.L1UserTxs {
  84. var dbTx *common.L1Tx
  85. // Find tx in DB output
  86. for _, _dbTx := range dbL1UserTxs {
  87. if *tx.ToForgeL1TxsNum == *_dbTx.ToForgeL1TxsNum &&
  88. tx.Position == _dbTx.Position {
  89. dbTx = new(common.L1Tx)
  90. *dbTx = _dbTx
  91. // NOTE: Overwrite EffectiveFromIdx in L1UserTx
  92. // from db because we don't expect
  93. // EffectiveFromIdx to be set yet, as this tx
  94. // is not in yet forged
  95. dbTx.EffectiveFromIdx = 0
  96. break
  97. }
  98. }
  99. // If the tx has been forged in this block, this will be
  100. // reflected in the DB, and so the Effective values will be
  101. // already set
  102. if dbTx.BatchNum != nil {
  103. tx.EffectiveAmount = tx.Amount
  104. tx.EffectiveDepositAmount = tx.DepositAmount
  105. }
  106. assert.Equal(t, &tx, dbTx) //nolint:gosec
  107. }
  108. // Check Batches
  109. assert.Equal(t, len(block.Rollup.Batches), len(syncBlock.Rollup.Batches))
  110. dbBatches, err := s.historyDB.GetAllBatches()
  111. require.NoError(t, err)
  112. dbL1CoordinatorTxs, err := s.historyDB.GetAllL1CoordinatorTxs()
  113. require.NoError(t, err)
  114. dbL2Txs, err := s.historyDB.GetAllL2Txs()
  115. require.NoError(t, err)
  116. dbExits, err := s.historyDB.GetAllExits()
  117. require.NoError(t, err)
  118. // dbL1CoordinatorTxs := []common.L1Tx{}
  119. for i, batch := range block.Rollup.Batches {
  120. var dbBatch *common.Batch
  121. // Find batch in DB output
  122. for _, _dbBatch := range dbBatches {
  123. if batch.Batch.BatchNum == _dbBatch.BatchNum {
  124. dbBatch = new(common.Batch)
  125. *dbBatch = _dbBatch
  126. break
  127. }
  128. }
  129. syncBatch := syncBlock.Rollup.Batches[i]
  130. // We don't care about TotalFeesUSD. Use the syncBatch that
  131. // has a TotalFeesUSD inserted by the HistoryDB
  132. batch.Batch.TotalFeesUSD = syncBatch.Batch.TotalFeesUSD
  133. assert.Equal(t, batch.CreatedAccounts, syncBatch.CreatedAccounts)
  134. batch.Batch.NumAccounts = len(batch.CreatedAccounts)
  135. // Test field by field to facilitate debugging of errors
  136. assert.Equal(t, len(batch.L1UserTxs), len(syncBatch.L1UserTxs))
  137. // NOTE: EffectiveFromIdx is set to til L1UserTxs in
  138. // `FillBlocksForgedL1UserTxs` function
  139. for j := range syncBatch.L1UserTxs {
  140. assert.NotEqual(t, 0, syncBatch.L1UserTxs[j].EffectiveFromIdx)
  141. }
  142. assert.Equal(t, batch.L1UserTxs, syncBatch.L1UserTxs)
  143. // NOTE: EffectiveFromIdx is set to til L1CoordinatorTxs in
  144. // `FillBlocksExtra` function
  145. for j := range syncBatch.L1CoordinatorTxs {
  146. assert.NotEqual(t, 0, syncBatch.L1CoordinatorTxs[j].EffectiveFromIdx)
  147. }
  148. assert.Equal(t, batch.L1CoordinatorTxs, syncBatch.L1CoordinatorTxs)
  149. assert.Equal(t, batch.L2Txs, syncBatch.L2Txs)
  150. // In exit tree, we only check AccountIdx and Balance, because
  151. // it's what we have precomputed before.
  152. require.Equal(t, len(batch.ExitTree), len(syncBatch.ExitTree))
  153. for j := range batch.ExitTree {
  154. exit := &batch.ExitTree[j]
  155. assert.Equal(t, exit.AccountIdx, syncBatch.ExitTree[j].AccountIdx)
  156. assert.Equal(t, exit.Balance, syncBatch.ExitTree[j].Balance)
  157. *exit = syncBatch.ExitTree[j]
  158. }
  159. assert.Equal(t, batch.Batch, syncBatch.Batch)
  160. // Ignore updated accounts
  161. syncBatch.UpdatedAccounts = nil
  162. assert.Equal(t, batch, syncBatch)
  163. assert.Equal(t, &batch.Batch, dbBatch) //nolint:gosec
  164. // Check forged L1UserTxs from DB, and check effective values
  165. // in sync output
  166. for j, tx := range batch.L1UserTxs {
  167. var dbTx *common.L1Tx
  168. // Find tx in DB output
  169. for _, _dbTx := range dbL1UserTxs {
  170. if *tx.BatchNum == *_dbTx.BatchNum &&
  171. tx.Position == _dbTx.Position {
  172. dbTx = new(common.L1Tx)
  173. *dbTx = _dbTx
  174. break
  175. }
  176. }
  177. assert.Equal(t, &tx, dbTx) //nolint:gosec
  178. syncTx := &syncBlock.Rollup.Batches[i].L1UserTxs[j]
  179. assert.Equal(t, syncTx.DepositAmount, syncTx.EffectiveDepositAmount)
  180. assert.Equal(t, syncTx.Amount, syncTx.EffectiveAmount)
  181. }
  182. // Check L1CoordinatorTxs from DB
  183. for _, tx := range batch.L1CoordinatorTxs {
  184. var dbTx *common.L1Tx
  185. // Find tx in DB output
  186. for _, _dbTx := range dbL1CoordinatorTxs {
  187. if *tx.BatchNum == *_dbTx.BatchNum &&
  188. tx.Position == _dbTx.Position {
  189. dbTx = new(common.L1Tx)
  190. *dbTx = _dbTx
  191. break
  192. }
  193. }
  194. assert.Equal(t, &tx, dbTx) //nolint:gosec
  195. }
  196. // Check L2Txs from DB
  197. for _, tx := range batch.L2Txs {
  198. var dbTx *common.L2Tx
  199. // Find tx in DB output
  200. for _, _dbTx := range dbL2Txs {
  201. if tx.BatchNum == _dbTx.BatchNum &&
  202. tx.Position == _dbTx.Position {
  203. dbTx = new(common.L2Tx)
  204. *dbTx = _dbTx
  205. break
  206. }
  207. }
  208. assert.Equal(t, &tx, dbTx) //nolint:gosec
  209. }
  210. // Check Exits from DB
  211. for _, exit := range batch.ExitTree {
  212. var dbExit *common.ExitInfo
  213. // Find exit in DB output
  214. for _, _dbExit := range dbExits {
  215. if exit.BatchNum == _dbExit.BatchNum &&
  216. exit.AccountIdx == _dbExit.AccountIdx {
  217. dbExit = new(common.ExitInfo)
  218. *dbExit = _dbExit
  219. break
  220. }
  221. }
  222. // Compare MerkleProof in JSON because unmarshaled 0
  223. // big.Int leaves the internal big.Int array at nil,
  224. // and gives trouble when comparing big.Int with
  225. // internal big.Int array != nil but empty.
  226. mtp, err := json.Marshal(exit.MerkleProof)
  227. require.NoError(t, err)
  228. dbMtp, err := json.Marshal(dbExit.MerkleProof)
  229. require.NoError(t, err)
  230. assert.Equal(t, mtp, dbMtp)
  231. dbExit.MerkleProof = exit.MerkleProof
  232. assert.Equal(t, &exit, dbExit) //nolint:gosec
  233. }
  234. }
  235. // Compare accounts from HistoryDB with StateDB (they should match)
  236. dbAccounts, err := s.historyDB.GetAllAccounts()
  237. require.NoError(t, err)
  238. sdbAccounts, err := s.stateDB.TestGetAccounts()
  239. require.NoError(t, err)
  240. assertEqualAccountsHistoryDBStateDB(t, dbAccounts, sdbAccounts)
  241. }
  242. func assertEqualAccountsHistoryDBStateDB(t *testing.T, hdbAccs, sdbAccs []common.Account) {
  243. assert.Equal(t, len(hdbAccs), len(sdbAccs))
  244. sort.SliceStable(hdbAccs, accountsCmp(hdbAccs))
  245. sort.SliceStable(sdbAccs, accountsCmp(sdbAccs))
  246. for i := range hdbAccs {
  247. hdbAcc := hdbAccs[i]
  248. sdbAcc := sdbAccs[i]
  249. assert.Equal(t, hdbAcc.Idx, sdbAcc.Idx)
  250. assert.Equal(t, hdbAcc.TokenID, sdbAcc.TokenID)
  251. assert.Equal(t, hdbAcc.EthAddr, sdbAcc.EthAddr)
  252. assert.Equal(t, hdbAcc.BJJ, sdbAcc.BJJ)
  253. }
  254. }
  255. // ethAddTokens adds the tokens from the blocks to the blockchain
  256. func ethAddTokens(blocks []common.BlockData, client *test.Client) {
  257. for _, block := range blocks {
  258. for _, token := range block.Rollup.AddedTokens {
  259. consts := eth.ERC20Consts{
  260. Name: fmt.Sprintf("Token %d", token.TokenID),
  261. Symbol: fmt.Sprintf("TK%d", token.TokenID),
  262. Decimals: 18,
  263. }
  264. tokenConsts[token.TokenID] = consts
  265. client.CtlAddERC20(token.EthAddr, consts)
  266. }
  267. }
  268. }
  269. var chainID uint16 = 0
  270. var deleteme = []string{}
  271. func TestMain(m *testing.M) {
  272. exitVal := m.Run()
  273. for _, dir := range deleteme {
  274. if err := os.RemoveAll(dir); err != nil {
  275. panic(err)
  276. }
  277. }
  278. os.Exit(exitVal)
  279. }
  280. func newTestModules(t *testing.T) (*statedb.StateDB, *historydb.HistoryDB) {
  281. // Int State DB
  282. dir, err := ioutil.TempDir("", "tmpdb")
  283. require.NoError(t, err)
  284. deleteme = append(deleteme, dir)
  285. stateDB, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
  286. Type: statedb.TypeSynchronizer, NLevels: 32})
  287. require.NoError(t, err)
  288. // Init History DB
  289. pass := os.Getenv("POSTGRES_PASS")
  290. db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
  291. require.NoError(t, err)
  292. historyDB := historydb.NewHistoryDB(db, db, nil)
  293. // Clear DB
  294. test.WipeDB(historyDB.DB())
  295. return stateDB, historyDB
  296. }
  297. func newBigInt(s string) *big.Int {
  298. v, ok := new(big.Int).SetString(s, 10)
  299. if !ok {
  300. panic(fmt.Errorf("Can't set big.Int from %s", s))
  301. }
  302. return v
  303. }
  304. func TestSyncGeneral(t *testing.T) {
  305. //
  306. // Setup
  307. //
  308. stateDB, historyDB := newTestModules(t)
  309. // Init eth client
  310. var timer timer
  311. clientSetup := test.NewClientSetupExample()
  312. clientSetup.ChainID = big.NewInt(int64(chainID))
  313. bootCoordAddr := clientSetup.AuctionVariables.BootCoordinator
  314. client := test.NewClient(true, &timer, &ethCommon.Address{}, clientSetup)
  315. // Create Synchronizer
  316. s, err := NewSynchronizer(client, historyDB, stateDB, Config{
  317. StatsRefreshPeriod: 0 * time.Second,
  318. })
  319. require.NoError(t, err)
  320. ctx := context.Background()
  321. //
  322. // First Sync from an initial state
  323. //
  324. stats := s.Stats()
  325. assert.Equal(t, false, stats.Synced())
  326. // Test Sync for rollup genesis block
  327. syncBlock, discards, err := s.Sync(ctx, nil)
  328. require.NoError(t, err)
  329. require.Nil(t, discards)
  330. require.NotNil(t, syncBlock)
  331. require.Nil(t, syncBlock.Rollup.Vars)
  332. require.Nil(t, syncBlock.Auction.Vars)
  333. require.Nil(t, syncBlock.WDelayer.Vars)
  334. assert.Equal(t, int64(1), syncBlock.Block.Num)
  335. stats = s.Stats()
  336. assert.Equal(t, int64(1), stats.Eth.FirstBlockNum)
  337. assert.Equal(t, int64(1), stats.Eth.LastBlock.Num)
  338. assert.Equal(t, int64(1), stats.Sync.LastBlock.Num)
  339. vars := s.SCVars()
  340. assert.Equal(t, clientSetup.RollupVariables, vars.Rollup)
  341. assert.Equal(t, clientSetup.AuctionVariables, vars.Auction)
  342. assert.Equal(t, clientSetup.WDelayerVariables, vars.WDelayer)
  343. dbBlocks, err := s.historyDB.GetAllBlocks()
  344. require.NoError(t, err)
  345. assert.Equal(t, 2, len(dbBlocks))
  346. assert.Equal(t, int64(1), dbBlocks[1].Num)
  347. // Sync again and expect no new blocks
  348. syncBlock, discards, err = s.Sync(ctx, nil)
  349. require.NoError(t, err)
  350. require.Nil(t, discards)
  351. require.Nil(t, syncBlock)
  352. //
  353. // Generate blockchain and smart contract data, and fill the test smart contracts
  354. //
  355. // Generate blockchain data with til
  356. set1 := `
  357. Type: Blockchain
  358. AddToken(1)
  359. AddToken(2)
  360. AddToken(3)
  361. CreateAccountDeposit(1) C: 2000 // Idx=256+2=258
  362. CreateAccountDeposit(2) A: 2000 // Idx=256+3=259
  363. CreateAccountDeposit(1) D: 500 // Idx=256+4=260
  364. CreateAccountDeposit(2) B: 500 // Idx=256+5=261
  365. CreateAccountDeposit(2) C: 500 // Idx=256+6=262
  366. CreateAccountCoordinator(1) A // Idx=256+0=256
  367. CreateAccountCoordinator(1) B // Idx=256+1=257
  368. > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{5}
  369. > batchL1 // forge defined L1UserTxs{5}, freeze L1UserTxs{nil}
  370. > block // blockNum=2
  371. CreateAccountDepositTransfer(1) E-A: 1000, 200 // Idx=256+7=263
  372. ForceTransfer(1) C-B: 80
  373. ForceExit(1) A: 100
  374. ForceExit(1) B: 80
  375. ForceTransfer(1) A-D: 100
  376. Transfer(1) C-A: 100 (126)
  377. Exit(1) C: 50 (100)
  378. Exit(1) D: 30 (100)
  379. > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{3}
  380. > batchL1 // forge L1UserTxs{3}, freeze defined L1UserTxs{nil}
  381. > block // blockNum=3
  382. `
  383. tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
  384. tilCfgExtra := til.ConfigExtra{
  385. BootCoordAddr: bootCoordAddr,
  386. CoordUser: "A",
  387. }
  388. blocks, err := tc.GenerateBlocks(set1)
  389. require.NoError(t, err)
  390. // Sanity check
  391. require.Equal(t, 2, len(blocks))
  392. // blocks 0 (blockNum=2)
  393. i := 0
  394. require.Equal(t, 2, int(blocks[i].Block.Num))
  395. require.Equal(t, 3, len(blocks[i].Rollup.AddedTokens))
  396. require.Equal(t, 5, len(blocks[i].Rollup.L1UserTxs))
  397. require.Equal(t, 2, len(blocks[i].Rollup.Batches))
  398. require.Equal(t, 2, len(blocks[i].Rollup.Batches[0].L1CoordinatorTxs))
  399. // Set StateRoots for batches manually (til doesn't set it)
  400. blocks[i].Rollup.Batches[0].Batch.StateRoot =
  401. newBigInt("18906357591508007884273218035694076596537737437965299189312069102730480717391")
  402. blocks[i].Rollup.Batches[1].Batch.StateRoot =
  403. newBigInt("9513185123401321669660637227182204000277156839501731093239187625486561933297")
  404. // blocks 1 (blockNum=3)
  405. i = 1
  406. require.Equal(t, 3, int(blocks[i].Block.Num))
  407. require.Equal(t, 5, len(blocks[i].Rollup.L1UserTxs))
  408. require.Equal(t, 2, len(blocks[i].Rollup.Batches))
  409. require.Equal(t, 3, len(blocks[i].Rollup.Batches[0].L2Txs))
  410. // Set StateRoots for batches manually (til doesn't set it)
  411. blocks[i].Rollup.Batches[0].Batch.StateRoot =
  412. newBigInt("13060270878200012606074130020925677466793317216609491464427188889005039616594")
  413. blocks[i].Rollup.Batches[1].Batch.StateRoot =
  414. newBigInt("21427104994652624302859637783375978708867165042357535792408500519060088086054")
  415. // Generate extra required data
  416. ethAddTokens(blocks, client)
  417. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  418. require.NoError(t, err)
  419. tc.FillBlocksL1UserTxsBatchNum(blocks)
  420. err = tc.FillBlocksForgedL1UserTxs(blocks)
  421. require.NoError(t, err)
  422. // Add block data to the smart contracts
  423. err = client.CtlAddBlocks(blocks)
  424. require.NoError(t, err)
  425. //
  426. // Sync to synchronize the current state from the test smart contracts,
  427. // and check the outcome
  428. //
  429. // Block 2
  430. syncBlock, discards, err = s.Sync(ctx, nil)
  431. require.NoError(t, err)
  432. require.Nil(t, discards)
  433. require.NotNil(t, syncBlock)
  434. assert.Nil(t, syncBlock.Rollup.Vars)
  435. assert.Nil(t, syncBlock.Auction.Vars)
  436. assert.Nil(t, syncBlock.WDelayer.Vars)
  437. assert.Equal(t, int64(2), syncBlock.Block.Num)
  438. stats = s.Stats()
  439. assert.Equal(t, int64(1), stats.Eth.FirstBlockNum)
  440. assert.Equal(t, int64(3), stats.Eth.LastBlock.Num)
  441. assert.Equal(t, int64(2), stats.Sync.LastBlock.Num)
  442. checkSyncBlock(t, s, 2, &blocks[0], syncBlock)
  443. // Block 3
  444. syncBlock, discards, err = s.Sync(ctx, nil)
  445. assert.NoError(t, err)
  446. require.NoError(t, err)
  447. require.Nil(t, discards)
  448. require.NotNil(t, syncBlock)
  449. assert.Nil(t, syncBlock.Rollup.Vars)
  450. assert.Nil(t, syncBlock.Auction.Vars)
  451. assert.Nil(t, syncBlock.WDelayer.Vars)
  452. assert.Equal(t, int64(3), syncBlock.Block.Num)
  453. stats = s.Stats()
  454. assert.Equal(t, int64(1), stats.Eth.FirstBlockNum)
  455. assert.Equal(t, int64(3), stats.Eth.LastBlock.Num)
  456. assert.Equal(t, int64(3), stats.Sync.LastBlock.Num)
  457. checkSyncBlock(t, s, 3, &blocks[1], syncBlock)
  458. // Block 4
  459. // Generate 2 withdraws manually
  460. _, err = client.RollupWithdrawMerkleProof(tc.Users["A"].BJJ.Public().Compress(), 1, 4, 256,
  461. big.NewInt(100), []*big.Int{}, true)
  462. require.NoError(t, err)
  463. _, err = client.RollupWithdrawMerkleProof(tc.Users["C"].BJJ.Public().Compress(), 1, 3, 258,
  464. big.NewInt(50), []*big.Int{}, false)
  465. require.NoError(t, err)
  466. client.CtlMineBlock()
  467. syncBlock, discards, err = s.Sync(ctx, nil)
  468. require.NoError(t, err)
  469. require.Nil(t, discards)
  470. require.NotNil(t, syncBlock)
  471. assert.Nil(t, syncBlock.Rollup.Vars)
  472. assert.Nil(t, syncBlock.Auction.Vars)
  473. assert.Nil(t, syncBlock.WDelayer.Vars)
  474. assert.Equal(t, int64(4), syncBlock.Block.Num)
  475. stats = s.Stats()
  476. assert.Equal(t, int64(1), stats.Eth.FirstBlockNum)
  477. assert.Equal(t, int64(4), stats.Eth.LastBlock.Num)
  478. assert.Equal(t, int64(4), stats.Sync.LastBlock.Num)
  479. vars = s.SCVars()
  480. assert.Equal(t, clientSetup.RollupVariables, vars.Rollup)
  481. assert.Equal(t, clientSetup.AuctionVariables, vars.Auction)
  482. assert.Equal(t, clientSetup.WDelayerVariables, vars.WDelayer)
  483. dbExits, err := s.historyDB.GetAllExits()
  484. require.NoError(t, err)
  485. foundA1, foundC1 := false, false
  486. for _, exit := range dbExits {
  487. if exit.AccountIdx == 256 && exit.BatchNum == 4 {
  488. foundA1 = true
  489. assert.Equal(t, int64(4), *exit.InstantWithdrawn)
  490. }
  491. if exit.AccountIdx == 258 && exit.BatchNum == 3 {
  492. foundC1 = true
  493. assert.Equal(t, int64(4), *exit.DelayedWithdrawRequest)
  494. }
  495. }
  496. assert.True(t, foundA1)
  497. assert.True(t, foundC1)
  498. // Block 5
  499. // Update variables manually
  500. rollupVars, auctionVars, wDelayerVars, err := s.historyDB.GetSCVars()
  501. require.NoError(t, err)
  502. rollupVars.ForgeL1L2BatchTimeout = 42
  503. _, err = client.RollupUpdateForgeL1L2BatchTimeout(rollupVars.ForgeL1L2BatchTimeout)
  504. require.NoError(t, err)
  505. auctionVars.OpenAuctionSlots = 17
  506. _, err = client.AuctionSetOpenAuctionSlots(auctionVars.OpenAuctionSlots)
  507. require.NoError(t, err)
  508. wDelayerVars.WithdrawalDelay = 99
  509. _, err = client.WDelayerChangeWithdrawalDelay(wDelayerVars.WithdrawalDelay)
  510. require.NoError(t, err)
  511. client.CtlMineBlock()
  512. syncBlock, discards, err = s.Sync(ctx, nil)
  513. require.NoError(t, err)
  514. require.Nil(t, discards)
  515. require.NotNil(t, syncBlock)
  516. assert.NotNil(t, syncBlock.Rollup.Vars)
  517. assert.NotNil(t, syncBlock.Auction.Vars)
  518. assert.NotNil(t, syncBlock.WDelayer.Vars)
  519. assert.Equal(t, int64(5), syncBlock.Block.Num)
  520. stats = s.Stats()
  521. assert.Equal(t, int64(1), stats.Eth.FirstBlockNum)
  522. assert.Equal(t, int64(5), stats.Eth.LastBlock.Num)
  523. assert.Equal(t, int64(5), stats.Sync.LastBlock.Num)
  524. vars = s.SCVars()
  525. assert.NotEqual(t, clientSetup.RollupVariables, vars.Rollup)
  526. assert.NotEqual(t, clientSetup.AuctionVariables, vars.Auction)
  527. assert.NotEqual(t, clientSetup.WDelayerVariables, vars.WDelayer)
  528. dbRollupVars, dbAuctionVars, dbWDelayerVars, err := s.historyDB.GetSCVars()
  529. require.NoError(t, err)
  530. // Set EthBlockNum for Vars to the blockNum in which they were updated (should be 5)
  531. rollupVars.EthBlockNum = syncBlock.Block.Num
  532. auctionVars.EthBlockNum = syncBlock.Block.Num
  533. wDelayerVars.EthBlockNum = syncBlock.Block.Num
  534. assert.Equal(t, rollupVars, dbRollupVars)
  535. assert.Equal(t, auctionVars, dbAuctionVars)
  536. assert.Equal(t, wDelayerVars, dbWDelayerVars)
  537. //
  538. // Reorg test
  539. //
  540. // Redo blocks 2-5 (as a reorg) only leaving:
  541. // - 2 create account transactions
  542. // - 2 add tokens
  543. // We add a 6th block so that the synchronizer can detect the reorg
  544. set2 := `
  545. Type: Blockchain
  546. AddToken(1)
  547. AddToken(2)
  548. CreateAccountDeposit(1) C: 2000 // Idx=256+1=257
  549. CreateAccountCoordinator(1) A // Idx=256+0=256
  550. > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{1}
  551. > batchL1 // forge defined L1UserTxs{1}, freeze L1UserTxs{nil}
  552. > block // blockNum=2
  553. > block // blockNum=3
  554. > block // blockNum=4
  555. > block // blockNum=5
  556. > block // blockNum=6
  557. `
  558. tc = til.NewContext(chainID, common.RollupConstMaxL1UserTx)
  559. tilCfgExtra = til.ConfigExtra{
  560. BootCoordAddr: bootCoordAddr,
  561. CoordUser: "A",
  562. }
  563. blocks, err = tc.GenerateBlocks(set2)
  564. require.NoError(t, err)
  565. // Set StateRoots for batches manually (til doesn't set it)
  566. blocks[0].Rollup.Batches[0].Batch.StateRoot =
  567. newBigInt("11218510534825843475100588932060366395781087435899915642332104464234485046683")
  568. blocks[0].Rollup.Batches[1].Batch.StateRoot =
  569. newBigInt("20283020730369146334077598087403837297563965802277806438205710455191646998983")
  570. for i := 0; i < 4; i++ {
  571. client.CtlRollback()
  572. }
  573. block := client.CtlLastBlock()
  574. require.Equal(t, int64(1), block.Num)
  575. // Generate extra required data
  576. ethAddTokens(blocks, client)
  577. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  578. require.NoError(t, err)
  579. tc.FillBlocksL1UserTxsBatchNum(blocks)
  580. // Add block data to the smart contracts
  581. err = client.CtlAddBlocks(blocks)
  582. require.NoError(t, err)
  583. // First sync detects the reorg and discards 4 blocks
  584. syncBlock, discards, err = s.Sync(ctx, nil)
  585. require.NoError(t, err)
  586. expetedDiscards := int64(4)
  587. require.Equal(t, &expetedDiscards, discards)
  588. require.Nil(t, syncBlock)
  589. stats = s.Stats()
  590. assert.Equal(t, false, stats.Synced())
  591. assert.Equal(t, int64(6), stats.Eth.LastBlock.Num)
  592. vars = s.SCVars()
  593. assert.Equal(t, clientSetup.RollupVariables, vars.Rollup)
  594. assert.Equal(t, clientSetup.AuctionVariables, vars.Auction)
  595. assert.Equal(t, clientSetup.WDelayerVariables, vars.WDelayer)
  596. // At this point, the DB only has data up to block 1
  597. dbBlock, err := s.historyDB.GetLastBlock()
  598. require.NoError(t, err)
  599. assert.Equal(t, int64(1), dbBlock.Num)
  600. // Accounts in HistoryDB and StateDB must be empty
  601. dbAccounts, err := s.historyDB.GetAllAccounts()
  602. require.NoError(t, err)
  603. sdbAccounts, err := s.stateDB.TestGetAccounts()
  604. require.NoError(t, err)
  605. assert.Equal(t, 0, len(dbAccounts))
  606. assertEqualAccountsHistoryDBStateDB(t, dbAccounts, sdbAccounts)
  607. // Sync blocks 2-6
  608. for i := 0; i < 5; i++ {
  609. syncBlock, discards, err = s.Sync(ctx, nil)
  610. require.NoError(t, err)
  611. require.Nil(t, discards)
  612. require.NotNil(t, syncBlock)
  613. assert.Nil(t, syncBlock.Rollup.Vars)
  614. assert.Nil(t, syncBlock.Auction.Vars)
  615. assert.Nil(t, syncBlock.WDelayer.Vars)
  616. assert.Equal(t, int64(2+i), syncBlock.Block.Num)
  617. stats = s.Stats()
  618. assert.Equal(t, int64(1), stats.Eth.FirstBlockNum)
  619. assert.Equal(t, int64(6), stats.Eth.LastBlock.Num)
  620. assert.Equal(t, int64(2+i), stats.Sync.LastBlock.Num)
  621. if i == 4 {
  622. assert.Equal(t, true, stats.Synced())
  623. } else {
  624. assert.Equal(t, false, stats.Synced())
  625. }
  626. vars = s.SCVars()
  627. assert.Equal(t, clientSetup.RollupVariables, vars.Rollup)
  628. assert.Equal(t, clientSetup.AuctionVariables, vars.Auction)
  629. assert.Equal(t, clientSetup.WDelayerVariables, vars.WDelayer)
  630. }
  631. dbBlock, err = s.historyDB.GetLastBlock()
  632. require.NoError(t, err)
  633. assert.Equal(t, int64(6), dbBlock.Num)
  634. // Accounts in HistoryDB and StateDB is only 2 entries
  635. dbAccounts, err = s.historyDB.GetAllAccounts()
  636. require.NoError(t, err)
  637. sdbAccounts, err = s.stateDB.TestGetAccounts()
  638. require.NoError(t, err)
  639. assert.Equal(t, 2, len(dbAccounts))
  640. assertEqualAccountsHistoryDBStateDB(t, dbAccounts, sdbAccounts)
  641. }
  642. func TestSyncForgerCommitment(t *testing.T) {
  643. stateDB, historyDB := newTestModules(t)
  644. // Init eth client
  645. var timer timer
  646. clientSetup := test.NewClientSetupExample()
  647. clientSetup.ChainID = big.NewInt(int64(chainID))
  648. clientSetup.AuctionConstants.GenesisBlockNum = 2
  649. clientSetup.AuctionConstants.BlocksPerSlot = 4
  650. clientSetup.AuctionVariables.SlotDeadline = 2
  651. bootCoordAddr := clientSetup.AuctionVariables.BootCoordinator
  652. client := test.NewClient(true, &timer, &ethCommon.Address{}, clientSetup)
  653. // Create Synchronizer
  654. s, err := NewSynchronizer(client, historyDB, stateDB, Config{
  655. StatsRefreshPeriod: 0 * time.Second,
  656. })
  657. require.NoError(t, err)
  658. ctx := context.Background()
  659. set := `
  660. Type: Blockchain
  661. // Slot = 0
  662. > block // 2
  663. > block // 3
  664. > block // 4
  665. > block // 5
  666. // Slot = 1
  667. > block // 6
  668. > batch
  669. > block // 7
  670. > block // 8
  671. > block // 9
  672. // Slot = 2
  673. > block // 10
  674. > block // 11
  675. > batch
  676. > block // 12
  677. > block // 13
  678. `
  679. // For each block, true when the slot that belongs to the following
  680. // block has forgerCommitment
  681. commitment := map[int64]bool{
  682. 2: false,
  683. 3: false,
  684. 4: false,
  685. 5: false,
  686. 6: false,
  687. 7: true,
  688. 8: true,
  689. 9: false,
  690. 10: false,
  691. 11: false,
  692. 12: false,
  693. 13: false,
  694. }
  695. tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
  696. blocks, err := tc.GenerateBlocks(set)
  697. assert.NoError(t, err)
  698. tilCfgExtra := til.ConfigExtra{
  699. BootCoordAddr: bootCoordAddr,
  700. CoordUser: "A",
  701. }
  702. err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
  703. require.NoError(t, err)
  704. // for i := range blocks {
  705. // for j := range blocks[i].Rollup.Batches {
  706. // blocks[i].Rollup.Batches[j].Batch.SlotNum = int64(i) / 4
  707. // }
  708. // }
  709. // be in sync
  710. for {
  711. syncBlock, discards, err := s.Sync(ctx, nil)
  712. require.NoError(t, err)
  713. require.Nil(t, discards)
  714. if syncBlock == nil {
  715. break
  716. }
  717. }
  718. stats := s.Stats()
  719. require.Equal(t, int64(1), stats.Sync.LastBlock.Num)
  720. // Store ForgerComitmnent observed at every block by the live synchronizer
  721. syncCommitment := map[int64]bool{}
  722. // Store ForgerComitmnent observed at every block by a synchronizer that is restarted
  723. syncRestartedCommitment := map[int64]bool{}
  724. for _, block := range blocks {
  725. // Add block data to the smart contracts
  726. err = client.CtlAddBlocks([]common.BlockData{block})
  727. require.NoError(t, err)
  728. syncBlock, discards, err := s.Sync(ctx, nil)
  729. require.NoError(t, err)
  730. require.Nil(t, discards)
  731. if syncBlock == nil {
  732. break
  733. }
  734. stats := s.Stats()
  735. require.True(t, stats.Synced())
  736. syncCommitment[syncBlock.Block.Num] = stats.Sync.Auction.CurrentSlot.ForgerCommitment
  737. s2, err := NewSynchronizer(client, historyDB, stateDB, Config{
  738. StatsRefreshPeriod: 0 * time.Second,
  739. })
  740. require.NoError(t, err)
  741. stats = s2.Stats()
  742. require.True(t, stats.Synced())
  743. syncRestartedCommitment[syncBlock.Block.Num] = stats.Sync.Auction.CurrentSlot.ForgerCommitment
  744. }
  745. assert.Equal(t, commitment, syncCommitment)
  746. assert.Equal(t, commitment, syncRestartedCommitment)
  747. }