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.

1917 lines
57 KiB

Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
Fix eth events query and sync inconsistent state - kvdb - Fix path in Last when doing `setNew` - Only close if db != nil, and after closing, always set db to nil - This will avoid a panic in the case where the db is closed but there's an error soon after, and a future call tries to close again. This is because pebble.Close() will panic if the db is already closed. - Avoid calling pebble methods when a the Storage interface already implements that method (like Close). - statedb - In test, avoid calling KVDB method if the same method is available for the StateDB (like MakeCheckpoint, CurrentBatch). - eth - In *EventByBlock methods, take blockHash as input argument and use it when querying the event logs. Previously the blockHash was only taken from the logs results *only if* there was any log. This caused the following issue: if there was no logs, it was not possible to know if the result was from the expected block or an uncle block! By querying logs by blockHash we make sure that even if there are no logs, they are from the right block. - Note that now the function can either be called with a blockNum or blockHash, but not both at the same time. - sync - If there's an error during call to Sync call resetState, which internally resets the stateDB to avoid stale checkpoints (and a corresponding invalid increase in the StateDB batchNum). - During a Sync, after very batch processed, make sure that the StateDB currentBatch corresponds to the batchNum in the smart contract log/event.
3 years ago
  1. package test
  2. import (
  3. "context"
  4. "encoding/binary"
  5. "encoding/json"
  6. "fmt"
  7. "math/big"
  8. "reflect"
  9. "sync"
  10. "time"
  11. "github.com/ethereum/go-ethereum"
  12. "github.com/ethereum/go-ethereum/accounts/abi/bind"
  13. ethKeystore "github.com/ethereum/go-ethereum/accounts/keystore"
  14. ethCommon "github.com/ethereum/go-ethereum/common"
  15. "github.com/ethereum/go-ethereum/core/types"
  16. "github.com/hermeznetwork/hermez-node/common"
  17. "github.com/hermeznetwork/hermez-node/eth"
  18. "github.com/hermeznetwork/hermez-node/log"
  19. "github.com/hermeznetwork/tracerr"
  20. "github.com/iden3/go-iden3-crypto/babyjub"
  21. "github.com/mitchellh/copystructure"
  22. )
  23. func init() {
  24. copystructure.Copiers[reflect.TypeOf(big.Int{})] =
  25. func(raw interface{}) (interface{}, error) {
  26. in := raw.(big.Int)
  27. out := new(big.Int).Set(&in)
  28. return *out, nil
  29. }
  30. }
  31. // WDelayerBlock stores all the data related to the WDelayer SC from an ethereum block
  32. type WDelayerBlock struct {
  33. // State eth.WDelayerState // TODO
  34. Vars common.WDelayerVariables
  35. Events eth.WDelayerEvents
  36. Txs map[ethCommon.Hash]*types.Transaction
  37. Constants *common.WDelayerConstants
  38. Eth *EthereumBlock
  39. }
  40. func (w *WDelayerBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  41. txHash := tx.Hash()
  42. w.Txs[txHash] = tx
  43. return tx
  44. }
  45. func (w *WDelayerBlock) deposit(txHash ethCommon.Hash, owner, token ethCommon.Address,
  46. amount *big.Int) {
  47. w.Events.Deposit = append(w.Events.Deposit, eth.WDelayerEventDeposit{
  48. Owner: owner,
  49. Token: token,
  50. Amount: amount,
  51. DepositTimestamp: uint64(w.Eth.Time),
  52. TxHash: txHash,
  53. })
  54. }
  55. // RollupBlock stores all the data related to the Rollup SC from an ethereum block
  56. type RollupBlock struct {
  57. State eth.RollupState
  58. Vars common.RollupVariables
  59. Events eth.RollupEvents
  60. Txs map[ethCommon.Hash]*types.Transaction
  61. Constants *common.RollupConstants
  62. Eth *EthereumBlock
  63. }
  64. func (r *RollupBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  65. txHash := tx.Hash()
  66. r.Txs[txHash] = tx
  67. return tx
  68. }
  69. var (
  70. errBidClosed = fmt.Errorf("Bid has already been closed")
  71. errBidNotOpen = fmt.Errorf("Bid has not been opened yet")
  72. errBidBelowMin = fmt.Errorf("Bid below minimum")
  73. errCoordNotReg = fmt.Errorf("Coordinator not registered")
  74. )
  75. // AuctionBlock stores all the data related to the Auction SC from an ethereum block
  76. type AuctionBlock struct {
  77. State eth.AuctionState
  78. Vars common.AuctionVariables
  79. Events eth.AuctionEvents
  80. Txs map[ethCommon.Hash]*types.Transaction
  81. Constants *common.AuctionConstants
  82. Eth *EthereumBlock
  83. }
  84. func (a *AuctionBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  85. txHash := tx.Hash()
  86. a.Txs[txHash] = tx
  87. return tx
  88. }
  89. func (a *AuctionBlock) getSlotNumber(blockNumber int64) int64 {
  90. if a.Eth.BlockNum >= a.Constants.GenesisBlockNum {
  91. return (blockNumber - a.Constants.GenesisBlockNum) / int64(a.Constants.BlocksPerSlot)
  92. }
  93. return 0
  94. }
  95. func (a *AuctionBlock) getCurrentSlotNumber() int64 {
  96. return a.getSlotNumber(a.Eth.BlockNum)
  97. }
  98. func (a *AuctionBlock) getSlotSet(slot int64) int64 {
  99. return slot % int64(len(a.Vars.DefaultSlotSetBid))
  100. }
  101. func (a *AuctionBlock) getMinBidBySlot(slot int64) (*big.Int, error) {
  102. if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
  103. return nil, tracerr.Wrap(errBidClosed)
  104. }
  105. slotSet := a.getSlotSet(slot)
  106. // fmt.Println("slot:", slot, "slotSet:", slotSet)
  107. var prevBid *big.Int
  108. slotState, ok := a.State.Slots[slot]
  109. if !ok {
  110. slotState = eth.NewSlotState()
  111. a.State.Slots[slot] = slotState
  112. }
  113. // If the bidAmount for a slot is 0 it means that it has not yet been
  114. // bid, so the midBid will be the minimum bid for the slot time plus
  115. // the outbidding set, otherwise it will be the bidAmount plus the
  116. // outbidding
  117. if slotState.BidAmount.Cmp(big.NewInt(0)) == 0 {
  118. prevBid = a.Vars.DefaultSlotSetBid[slotSet]
  119. } else {
  120. prevBid = slotState.BidAmount
  121. }
  122. outBid := new(big.Int).Set(prevBid)
  123. // fmt.Println("outBid:", outBid)
  124. outBid.Mul(outBid, big.NewInt(int64(a.Vars.Outbidding)))
  125. outBid.Div(outBid, big.NewInt(10000)) //nolint:gomnd
  126. outBid.Add(prevBid, outBid)
  127. // fmt.Println("minBid:", outBid)
  128. return outBid, nil
  129. }
  130. func (a *AuctionBlock) forge(forger ethCommon.Address) error {
  131. if ok, err := a.canForge(forger, a.Eth.BlockNum); err != nil {
  132. return tracerr.Wrap(err)
  133. } else if !ok {
  134. return tracerr.Wrap(fmt.Errorf("Can't forge"))
  135. }
  136. slotToForge := a.getSlotNumber(a.Eth.BlockNum)
  137. slotState, ok := a.State.Slots[slotToForge]
  138. if !ok {
  139. slotState = eth.NewSlotState()
  140. a.State.Slots[slotToForge] = slotState
  141. }
  142. if !slotState.ForgerCommitment {
  143. // Get the relativeBlock to check if the slotDeadline has been exceeded
  144. relativeBlock := a.Eth.BlockNum - (a.Constants.GenesisBlockNum +
  145. (slotToForge * int64(a.Constants.BlocksPerSlot)))
  146. if relativeBlock < int64(a.Vars.SlotDeadline) {
  147. slotState.ForgerCommitment = true
  148. }
  149. }
  150. slotState.Fulfilled = true
  151. a.Events.NewForge = append(a.Events.NewForge, eth.AuctionEventNewForge{
  152. Forger: forger,
  153. SlotToForge: slotToForge,
  154. })
  155. return nil
  156. }
  157. func (a *AuctionBlock) canForge(forger ethCommon.Address, blockNum int64) (bool, error) {
  158. if blockNum < a.Constants.GenesisBlockNum {
  159. return false, tracerr.Wrap(fmt.Errorf("Auction has not started yet"))
  160. }
  161. slotToForge := a.getSlotNumber(blockNum)
  162. // Get the relativeBlock to check if the slotDeadline has been exceeded
  163. relativeBlock := blockNum - (a.Constants.GenesisBlockNum + (slotToForge *
  164. int64(a.Constants.BlocksPerSlot)))
  165. // If the closedMinBid is 0 it means that we have to take as minBid the
  166. // one that is set for this slot set, otherwise the one that has been
  167. // saved will be used
  168. var minBid *big.Int
  169. slotState, ok := a.State.Slots[slotToForge]
  170. if !ok {
  171. slotState = eth.NewSlotState()
  172. a.State.Slots[slotToForge] = slotState
  173. }
  174. if slotState.ClosedMinBid.Cmp(big.NewInt(0)) == 0 {
  175. minBid = a.Vars.DefaultSlotSetBid[a.getSlotSet(slotToForge)]
  176. } else {
  177. minBid = slotState.ClosedMinBid
  178. }
  179. if !slotState.ForgerCommitment && (relativeBlock >= int64(a.Vars.SlotDeadline)) {
  180. // if the relative block has exceeded the slotDeadline and no
  181. // batch has been forged, anyone can forge
  182. return true, nil
  183. } else if coord, ok := a.State.Coordinators[slotState.Bidder]; ok &&
  184. coord.Forger == forger && slotState.BidAmount.Cmp(minBid) >= 0 {
  185. // if forger bidAmount has exceeded the minBid it can forge
  186. return true, nil
  187. } else if a.Vars.BootCoordinator == forger && slotState.BidAmount.Cmp(minBid) == -1 {
  188. // if it's the boot coordinator and it has not been bid or the
  189. // bid is below the minimum it can forge
  190. return true, nil
  191. } else {
  192. return false, nil
  193. }
  194. }
  195. // EthereumBlock stores all the generic data related to the an ethereum block
  196. type EthereumBlock struct {
  197. BlockNum int64
  198. Time int64
  199. Hash ethCommon.Hash
  200. ParentHash ethCommon.Hash
  201. Tokens map[ethCommon.Address]eth.ERC20Consts
  202. Nonce uint64
  203. // state ethState
  204. }
  205. // Block represents a ethereum block
  206. type Block struct {
  207. Rollup *RollupBlock
  208. Auction *AuctionBlock
  209. WDelayer *WDelayerBlock
  210. Eth *EthereumBlock
  211. }
  212. func (b *Block) copy() *Block {
  213. bCopyRaw, err := copystructure.Copy(b)
  214. if err != nil {
  215. panic(err)
  216. }
  217. bCopy := bCopyRaw.(*Block)
  218. return bCopy
  219. }
  220. // Next prepares the successive block.
  221. func (b *Block) Next() *Block {
  222. blockNext := b.copy()
  223. blockNext.Rollup.Events = eth.NewRollupEvents()
  224. blockNext.Auction.Events = eth.NewAuctionEvents()
  225. blockNext.Eth.BlockNum = b.Eth.BlockNum + 1
  226. blockNext.Eth.ParentHash = b.Eth.Hash
  227. blockNext.Rollup.Constants = b.Rollup.Constants
  228. blockNext.Auction.Constants = b.Auction.Constants
  229. blockNext.WDelayer.Constants = b.WDelayer.Constants
  230. blockNext.Rollup.Eth = blockNext.Eth
  231. blockNext.Auction.Eth = blockNext.Eth
  232. blockNext.WDelayer.Eth = blockNext.Eth
  233. return blockNext
  234. }
  235. // ClientSetup is used to initialize the constants of the Smart Contracts and
  236. // other details of the test Client
  237. type ClientSetup struct {
  238. RollupConstants *common.RollupConstants
  239. RollupVariables *common.RollupVariables
  240. AuctionConstants *common.AuctionConstants
  241. AuctionVariables *common.AuctionVariables
  242. WDelayerConstants *common.WDelayerConstants
  243. WDelayerVariables *common.WDelayerVariables
  244. VerifyProof bool
  245. ChainID *big.Int
  246. }
  247. // NewClientSetupExample returns a ClientSetup example with hardcoded realistic
  248. // values. With this setup, the rollup genesis will be block 1, and block 0
  249. // and 1 will be premined.
  250. //nolint:gomnd
  251. func NewClientSetupExample() *ClientSetup {
  252. initialMinimalBidding, ok := new(big.Int).SetString("10000000000000000000", 10) // 10 * (1e18)
  253. if !ok {
  254. panic("bad initialMinimalBidding")
  255. }
  256. tokenHEZ := ethCommon.HexToAddress("0x51D243D62852Bba334DD5cc33f242BAc8c698074")
  257. governanceAddress := ethCommon.HexToAddress("0x688EfD95BA4391f93717CF02A9aED9DBD2855cDd")
  258. rollupConstants := &common.RollupConstants{
  259. Verifiers: []common.RollupVerifierStruct{
  260. {
  261. MaxTx: 2048,
  262. NLevels: 32,
  263. },
  264. },
  265. TokenHEZ: tokenHEZ,
  266. HermezGovernanceAddress: governanceAddress,
  267. HermezAuctionContract: ethCommon.HexToAddress("0x8E442975805fb1908f43050c9C1A522cB0e28D7b"),
  268. WithdrawDelayerContract: ethCommon.HexToAddress("0x5CB7979cBdbf65719BEE92e4D15b7b7Ed3D79114"),
  269. }
  270. rollupVariables := &common.RollupVariables{
  271. FeeAddToken: big.NewInt(11),
  272. ForgeL1L2BatchTimeout: 10,
  273. WithdrawalDelay: 80,
  274. Buckets: []common.BucketParams{},
  275. }
  276. auctionConstants := &common.AuctionConstants{
  277. BlocksPerSlot: 40,
  278. InitialMinimalBidding: initialMinimalBidding,
  279. GenesisBlockNum: 1,
  280. GovernanceAddress: governanceAddress,
  281. TokenHEZ: tokenHEZ,
  282. HermezRollup: ethCommon.HexToAddress("0x474B6e29852257491cf283EfB1A9C61eBFe48369"),
  283. }
  284. auctionVariables := &common.AuctionVariables{
  285. DonationAddress: ethCommon.HexToAddress("0x61Ed87CF0A1496b49A420DA6D84B58196b98f2e7"),
  286. BootCoordinator: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
  287. BootCoordinatorURL: "https://boot.coordinator.com",
  288. DefaultSlotSetBid: [6]*big.Int{
  289. initialMinimalBidding, initialMinimalBidding, initialMinimalBidding,
  290. initialMinimalBidding, initialMinimalBidding, initialMinimalBidding,
  291. },
  292. ClosedAuctionSlots: 2,
  293. OpenAuctionSlots: 4320,
  294. AllocationRatio: [3]uint16{4000, 4000, 2000},
  295. Outbidding: 1000,
  296. SlotDeadline: 20,
  297. }
  298. wDelayerConstants := &common.WDelayerConstants{
  299. MaxWithdrawalDelay: 60 * 60 * 24 * 7 * 2, // 2 weeks
  300. MaxEmergencyModeTime: 60 * 60 * 24 * 7 * 26, // 26 weeks
  301. HermezRollup: auctionConstants.HermezRollup,
  302. }
  303. wDelayerVariables := &common.WDelayerVariables{
  304. HermezGovernanceAddress: ethCommon.HexToAddress("0xcfD0d163AE6432a72682323E2C3A5a69e6B37D12"),
  305. EmergencyCouncilAddress: ethCommon.HexToAddress("0x2730700932a4FDB97B9268A3Ca29f97Ea5fd7EA0"),
  306. WithdrawalDelay: 60,
  307. EmergencyModeStartingBlock: 0,
  308. EmergencyMode: false,
  309. }
  310. return &ClientSetup{
  311. RollupConstants: rollupConstants,
  312. RollupVariables: rollupVariables,
  313. AuctionConstants: auctionConstants,
  314. AuctionVariables: auctionVariables,
  315. WDelayerConstants: wDelayerConstants,
  316. WDelayerVariables: wDelayerVariables,
  317. VerifyProof: false,
  318. ChainID: big.NewInt(0),
  319. }
  320. }
  321. // Timer is an interface to simulate a source of time, useful to advance time
  322. // virtually.
  323. type Timer interface {
  324. Time() int64
  325. }
  326. // type forgeBatchArgs struct {
  327. // ethTx *types.Transaction
  328. // blockNum int64
  329. // blockHash ethCommon.Hash
  330. // }
  331. type batch struct {
  332. ForgeBatchArgs eth.RollupForgeBatchArgs
  333. Sender ethCommon.Address
  334. }
  335. // Client implements the eth.ClientInterface interface, allowing to manipulate the
  336. // values for testing, working with deterministic results.
  337. type Client struct {
  338. rw *sync.RWMutex
  339. log bool
  340. addr *ethCommon.Address
  341. chainID *big.Int
  342. rollupConstants *common.RollupConstants
  343. auctionConstants *common.AuctionConstants
  344. wDelayerConstants *common.WDelayerConstants
  345. blocks map[int64]*Block
  346. // state state
  347. blockNum int64 // last mined block num
  348. maxBlockNum int64 // highest block num calculated
  349. timer Timer
  350. hasher hasher
  351. forgeBatchArgsPending map[ethCommon.Hash]*batch
  352. forgeBatchArgs map[ethCommon.Hash]*batch
  353. startBlock int64
  354. }
  355. // NewClient returns a new test Client that implements the eth.IClient
  356. // interface, at the given initialBlockNumber.
  357. func NewClient(l bool, timer Timer, addr *ethCommon.Address, setup *ClientSetup) *Client {
  358. blocks := make(map[int64]*Block)
  359. blockNum := int64(0)
  360. hasher := hasher{}
  361. // Add ethereum genesis block
  362. mapL1TxQueue := make(map[int64]*eth.QueueStruct)
  363. mapL1TxQueue[0] = eth.NewQueueStruct()
  364. mapL1TxQueue[1] = eth.NewQueueStruct()
  365. blockCurrent := &Block{
  366. Rollup: &RollupBlock{
  367. State: eth.RollupState{
  368. StateRoot: big.NewInt(0),
  369. ExitRoots: make([]*big.Int, 1),
  370. ExitNullifierMap: make(map[int64]map[int64]bool),
  371. // TokenID = 0 is ETH. Set first entry in TokenList with 0x0 address for ETH.
  372. TokenList: []ethCommon.Address{{}},
  373. TokenMap: make(map[ethCommon.Address]bool),
  374. MapL1TxQueue: mapL1TxQueue,
  375. LastL1L2Batch: 0,
  376. CurrentToForgeL1TxsNum: 0,
  377. LastToForgeL1TxsNum: 1,
  378. CurrentIdx: 0,
  379. },
  380. Vars: *setup.RollupVariables,
  381. Txs: make(map[ethCommon.Hash]*types.Transaction),
  382. Events: eth.NewRollupEvents(),
  383. Constants: setup.RollupConstants,
  384. },
  385. Auction: &AuctionBlock{
  386. State: eth.AuctionState{
  387. Slots: make(map[int64]*eth.SlotState),
  388. PendingBalances: make(map[ethCommon.Address]*big.Int),
  389. Coordinators: make(map[ethCommon.Address]*eth.Coordinator),
  390. },
  391. Vars: *setup.AuctionVariables,
  392. Txs: make(map[ethCommon.Hash]*types.Transaction),
  393. Events: eth.NewAuctionEvents(),
  394. Constants: setup.AuctionConstants,
  395. },
  396. WDelayer: &WDelayerBlock{
  397. // State: TODO
  398. Vars: *setup.WDelayerVariables,
  399. Txs: make(map[ethCommon.Hash]*types.Transaction),
  400. Events: eth.NewWDelayerEvents(),
  401. Constants: setup.WDelayerConstants,
  402. },
  403. Eth: &EthereumBlock{
  404. BlockNum: blockNum,
  405. Time: timer.Time(),
  406. Hash: hasher.Next(),
  407. ParentHash: ethCommon.Hash{},
  408. Tokens: make(map[ethCommon.Address]eth.ERC20Consts),
  409. },
  410. }
  411. blockCurrent.Rollup.Eth = blockCurrent.Eth
  412. blockCurrent.Auction.Eth = blockCurrent.Eth
  413. blocks[blockNum] = blockCurrent
  414. blockNext := blockCurrent.Next()
  415. blocks[blockNum+1] = blockNext
  416. c := Client{
  417. rw: &sync.RWMutex{},
  418. log: l,
  419. addr: addr,
  420. rollupConstants: setup.RollupConstants,
  421. auctionConstants: setup.AuctionConstants,
  422. wDelayerConstants: setup.WDelayerConstants,
  423. blocks: blocks,
  424. timer: timer,
  425. hasher: hasher,
  426. forgeBatchArgsPending: make(map[ethCommon.Hash]*batch),
  427. forgeBatchArgs: make(map[ethCommon.Hash]*batch),
  428. blockNum: blockNum,
  429. maxBlockNum: blockNum,
  430. }
  431. if c.startBlock == 0 {
  432. c.startBlock = 2
  433. }
  434. for i := int64(1); i < c.startBlock; i++ {
  435. c.CtlMineBlock()
  436. }
  437. return &c
  438. }
  439. //
  440. // Mock Control
  441. //
  442. func (c *Client) setNextBlock(block *Block) {
  443. c.blocks[c.blockNum+1] = block
  444. }
  445. func (c *Client) revertIfErr(err error, block *Block) {
  446. if err != nil {
  447. log.Infow("TestClient revert", "block", block.Eth.BlockNum, "err", err)
  448. c.setNextBlock(block)
  449. }
  450. }
  451. // Debugf calls log.Debugf if c.log is true
  452. func (c *Client) Debugf(template string, args ...interface{}) {
  453. if c.log {
  454. log.Debugf(template, args...)
  455. }
  456. }
  457. // Debugw calls log.Debugw if c.log is true
  458. func (c *Client) Debugw(template string, kv ...interface{}) {
  459. if c.log {
  460. log.Debugw(template, kv...)
  461. }
  462. }
  463. type hasher struct {
  464. counter uint64
  465. }
  466. // Next returns the next hash
  467. func (h *hasher) Next() ethCommon.Hash {
  468. var hash ethCommon.Hash
  469. binary.LittleEndian.PutUint64(hash[:], h.counter)
  470. h.counter++
  471. return hash
  472. }
  473. func (c *Client) nextBlock() *Block {
  474. return c.blocks[c.blockNum+1]
  475. }
  476. func (c *Client) currentBlock() *Block {
  477. return c.blocks[c.blockNum]
  478. }
  479. // CtlSetAddr sets the address of the client
  480. func (c *Client) CtlSetAddr(addr ethCommon.Address) {
  481. c.addr = &addr
  482. }
  483. // CtlMineBlock moves one block forward
  484. func (c *Client) CtlMineBlock() {
  485. c.rw.Lock()
  486. defer c.rw.Unlock()
  487. blockCurrent := c.nextBlock()
  488. c.blockNum++
  489. c.maxBlockNum = c.blockNum
  490. blockCurrent.Eth.Time = c.timer.Time()
  491. blockCurrent.Eth.Hash = c.hasher.Next()
  492. for ethTxHash, forgeBatchArgs := range c.forgeBatchArgsPending {
  493. c.forgeBatchArgs[ethTxHash] = forgeBatchArgs
  494. }
  495. c.forgeBatchArgsPending = make(map[ethCommon.Hash]*batch)
  496. blockNext := blockCurrent.Next()
  497. c.blocks[c.blockNum+1] = blockNext
  498. c.Debugw("TestClient mined block", "blockNum", c.blockNum)
  499. }
  500. // CtlRollback discards the last mined block. Use this to replace a mined
  501. // block to simulate reorgs.
  502. func (c *Client) CtlRollback() {
  503. c.rw.Lock()
  504. defer c.rw.Unlock()
  505. if c.blockNum == 0 {
  506. panic("Can't rollback at blockNum = 0")
  507. }
  508. delete(c.blocks, c.blockNum+1) // delete next block
  509. delete(c.blocks, c.blockNum) // delete current block
  510. c.blockNum--
  511. blockCurrent := c.blocks[c.blockNum]
  512. blockNext := blockCurrent.Next()
  513. c.blocks[c.blockNum+1] = blockNext
  514. }
  515. //
  516. // Ethereum
  517. //
  518. // CtlLastBlock returns the last blockNum without checks
  519. func (c *Client) CtlLastBlock() *common.Block {
  520. c.rw.RLock()
  521. defer c.rw.RUnlock()
  522. block := c.blocks[c.blockNum]
  523. return &common.Block{
  524. Num: c.blockNum,
  525. Timestamp: time.Unix(block.Eth.Time, 0),
  526. Hash: block.Eth.Hash,
  527. ParentHash: block.Eth.ParentHash,
  528. }
  529. }
  530. // CtlLastForgedBatch returns the last batchNum without checks
  531. func (c *Client) CtlLastForgedBatch() int64 {
  532. c.rw.RLock()
  533. defer c.rw.RUnlock()
  534. currentBlock := c.currentBlock()
  535. e := currentBlock.Rollup
  536. return int64(len(e.State.ExitRoots)) - 1
  537. }
  538. // EthChainID returns the ChainID of the ethereum network
  539. func (c *Client) EthChainID() (*big.Int, error) {
  540. return c.chainID, nil
  541. }
  542. // EthPendingNonceAt returns the account nonce of the given account in the pending
  543. // state. This is the nonce that should be used for the next transaction.
  544. func (c *Client) EthPendingNonceAt(ctx context.Context, account ethCommon.Address) (uint64, error) {
  545. // NOTE: For now Client doesn't simulate nonces
  546. return 0, nil
  547. }
  548. // EthNonceAt returns the account nonce of the given account. The block number can
  549. // be nil, in which case the nonce is taken from the latest known block.
  550. func (c *Client) EthNonceAt(ctx context.Context, account ethCommon.Address,
  551. blockNumber *big.Int) (uint64, error) {
  552. // NOTE: For now Client doesn't simulate nonces
  553. return 0, nil
  554. }
  555. // EthSuggestGasPrice retrieves the currently suggested gas price to allow a
  556. // timely execution of a transaction.
  557. func (c *Client) EthSuggestGasPrice(ctx context.Context) (*big.Int, error) {
  558. // NOTE: For now Client doesn't simulate gasPrice
  559. return big.NewInt(0), nil
  560. }
  561. // EthKeyStore returns the keystore in the Client
  562. func (c *Client) EthKeyStore() *ethKeystore.KeyStore {
  563. return nil
  564. }
  565. // EthCall runs the transaction as a call (without paying) in the local node at
  566. // blockNum.
  567. func (c *Client) EthCall(ctx context.Context, tx *types.Transaction,
  568. blockNum *big.Int) ([]byte, error) {
  569. return nil, tracerr.Wrap(common.ErrTODO)
  570. }
  571. // EthLastBlock returns the last blockNum
  572. func (c *Client) EthLastBlock() (int64, error) {
  573. c.rw.RLock()
  574. defer c.rw.RUnlock()
  575. if c.blockNum < c.maxBlockNum {
  576. panic("blockNum has decreased. " +
  577. "After a rollback you must mine to reach the same or higher blockNum")
  578. }
  579. return c.blockNum, nil
  580. }
  581. // EthTransactionReceipt returns the transaction receipt of the given txHash
  582. func (c *Client) EthTransactionReceipt(ctx context.Context,
  583. txHash ethCommon.Hash) (*types.Receipt, error) {
  584. c.rw.RLock()
  585. defer c.rw.RUnlock()
  586. for i := int64(0); i < c.blockNum; i++ {
  587. b := c.blocks[i]
  588. _, ok := b.Rollup.Txs[txHash]
  589. if !ok {
  590. _, ok = b.Auction.Txs[txHash]
  591. }
  592. if ok {
  593. return &types.Receipt{
  594. TxHash: txHash,
  595. Status: types.ReceiptStatusSuccessful,
  596. BlockHash: b.Eth.Hash,
  597. BlockNumber: big.NewInt(b.Eth.BlockNum),
  598. }, nil
  599. }
  600. }
  601. return nil, nil
  602. }
  603. // CtlAddERC20 adds an ERC20 token to the blockchain.
  604. func (c *Client) CtlAddERC20(tokenAddr ethCommon.Address, constants eth.ERC20Consts) {
  605. nextBlock := c.nextBlock()
  606. e := nextBlock.Eth
  607. e.Tokens[tokenAddr] = constants
  608. }
  609. // EthERC20Consts returns the constants defined for a particular ERC20 Token instance.
  610. func (c *Client) EthERC20Consts(tokenAddr ethCommon.Address) (*eth.ERC20Consts, error) {
  611. currentBlock := c.currentBlock()
  612. e := currentBlock.Eth
  613. if constants, ok := e.Tokens[tokenAddr]; ok {
  614. return &constants, nil
  615. }
  616. return nil, tracerr.Wrap(fmt.Errorf("tokenAddr not found"))
  617. }
  618. // func newHeader(number *big.Int) *types.Header {
  619. // return &types.Header{
  620. // Number: number,
  621. // Time: uint64(number.Int64()),
  622. // }
  623. // }
  624. // EthHeaderByNumber returns the *types.Header for the given block number in a
  625. // deterministic way.
  626. // func (c *Client) EthHeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
  627. // return newHeader(number), nil
  628. // }
  629. // EthBlockByNumber returns the *common.Block for the given block number in a
  630. // deterministic way. If number == -1, the latests known block is returned.
  631. func (c *Client) EthBlockByNumber(ctx context.Context, blockNum int64) (*common.Block, error) {
  632. c.rw.RLock()
  633. defer c.rw.RUnlock()
  634. if blockNum > c.blockNum {
  635. return nil, ethereum.NotFound
  636. }
  637. if blockNum == -1 {
  638. blockNum = c.blockNum
  639. }
  640. block := c.blocks[blockNum]
  641. return &common.Block{
  642. Num: blockNum,
  643. Timestamp: time.Unix(block.Eth.Time, 0),
  644. Hash: block.Eth.Hash,
  645. ParentHash: block.Eth.ParentHash,
  646. }, nil
  647. }
  648. // EthAddress returns the ethereum address of the account loaded into the Client
  649. func (c *Client) EthAddress() (*ethCommon.Address, error) {
  650. if c.addr == nil {
  651. return nil, tracerr.Wrap(eth.ErrAccountNil)
  652. }
  653. return c.addr, nil
  654. }
  655. var errTODO = fmt.Errorf("TODO: Not implemented yet")
  656. //
  657. // Rollup
  658. //
  659. // CtlAddL1TxUser adds an L1TxUser to the L1UserTxs queue of the Rollup
  660. // func (c *Client) CtlAddL1TxUser(l1Tx *common.L1Tx) {
  661. // c.rw.Lock()
  662. // defer c.rw.Unlock()
  663. //
  664. // nextBlock := c.nextBlock()
  665. // r := nextBlock.Rollup
  666. // queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  667. // if len(queue.L1TxQueue) >= eth.RollupConstMaxL1UserTx {
  668. // r.State.LastToForgeL1TxsNum++
  669. // r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
  670. // queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  671. // }
  672. // if int64(l1Tx.FromIdx) > r.State.CurrentIdx {
  673. // panic("l1Tx.FromIdx > r.State.CurrentIdx")
  674. // }
  675. // if int(l1Tx.TokenID)+1 > len(r.State.TokenList) {
  676. // panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
  677. // }
  678. // queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
  679. // r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
  680. // L1Tx: *l1Tx,
  681. // ToForgeL1TxsNum: r.State.LastToForgeL1TxsNum,
  682. // Position: len(queue.L1TxQueue) - 1,
  683. // })
  684. // }
  685. // RollupL1UserTxERC20Permit is the interface to call the smart contract function
  686. func (c *Client) RollupL1UserTxERC20Permit(fromBJJ babyjub.PublicKeyComp, fromIdx int64,
  687. depositAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64,
  688. deadline *big.Int) (tx *types.Transaction, err error) {
  689. log.Error("TODO")
  690. return nil, tracerr.Wrap(errTODO)
  691. }
  692. // RollupL1UserTxERC20ETH sends an L1UserTx to the Rollup.
  693. func (c *Client) RollupL1UserTxERC20ETH(
  694. fromBJJ babyjub.PublicKeyComp,
  695. fromIdx int64,
  696. depositAmount *big.Int,
  697. amount *big.Int,
  698. tokenID uint32,
  699. toIdx int64,
  700. ) (tx *types.Transaction, err error) {
  701. c.rw.Lock()
  702. defer c.rw.Unlock()
  703. cpy := c.nextBlock().copy()
  704. defer func() { c.revertIfErr(err, cpy) }()
  705. _, err = common.NewFloat40(amount)
  706. if err != nil {
  707. return nil, tracerr.Wrap(err)
  708. }
  709. _, err = common.NewFloat40(depositAmount)
  710. if err != nil {
  711. return nil, tracerr.Wrap(err)
  712. }
  713. nextBlock := c.nextBlock()
  714. r := nextBlock.Rollup
  715. queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  716. if len(queue.L1TxQueue) >= common.RollupConstMaxL1UserTx {
  717. r.State.LastToForgeL1TxsNum++
  718. r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
  719. queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  720. }
  721. if fromIdx > r.State.CurrentIdx {
  722. panic("l1Tx.FromIdx > r.State.CurrentIdx")
  723. }
  724. if int(tokenID)+1 > len(r.State.TokenList) {
  725. panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
  726. }
  727. toForgeL1TxsNum := r.State.LastToForgeL1TxsNum
  728. l1Tx, err := common.NewL1Tx(&common.L1Tx{
  729. FromIdx: common.Idx(fromIdx),
  730. FromEthAddr: *c.addr,
  731. FromBJJ: fromBJJ,
  732. Amount: amount,
  733. DepositAmount: depositAmount,
  734. TokenID: common.TokenID(tokenID),
  735. ToIdx: common.Idx(toIdx),
  736. ToForgeL1TxsNum: &toForgeL1TxsNum,
  737. Position: len(queue.L1TxQueue),
  738. UserOrigin: true,
  739. })
  740. if err != nil {
  741. return nil, tracerr.Wrap(err)
  742. }
  743. queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
  744. r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
  745. L1UserTx: *l1Tx,
  746. })
  747. return r.addTransaction(c.newTransaction("l1UserTxERC20ETH", l1Tx)), nil
  748. }
  749. // RollupL1UserTxERC777 is the interface to call the smart contract function
  750. // func (c *Client) RollupL1UserTxERC777(fromBJJ *babyjub.PublicKey, fromIdx int64,
  751. // depositAmount *big.Int, amount *big.Int, tokenID uint32,
  752. // toIdx int64) (*types.Transaction, error) {
  753. // log.Error("TODO")
  754. // return nil, errTODO
  755. // }
  756. // RollupRegisterTokensCount is the interface to call the smart contract function
  757. func (c *Client) RollupRegisterTokensCount() (*big.Int, error) {
  758. log.Error("TODO")
  759. return nil, tracerr.Wrap(errTODO)
  760. }
  761. // RollupLastForgedBatch is the interface to call the smart contract function
  762. func (c *Client) RollupLastForgedBatch() (int64, error) {
  763. c.rw.RLock()
  764. defer c.rw.RUnlock()
  765. currentBlock := c.currentBlock()
  766. e := currentBlock.Rollup
  767. return int64(len(e.State.ExitRoots)) - 1, nil
  768. }
  769. // RollupWithdrawCircuit is the interface to call the smart contract function
  770. func (c *Client) RollupWithdrawCircuit(proofA, proofC [2]*big.Int, proofB [2][2]*big.Int,
  771. tokenID uint32, numExitRoot, idx int64, amount *big.Int,
  772. instantWithdraw bool) (*types.Transaction, error) {
  773. log.Error("TODO")
  774. return nil, tracerr.Wrap(errTODO)
  775. }
  776. // RollupWithdrawMerkleProof is the interface to call the smart contract function
  777. func (c *Client) RollupWithdrawMerkleProof(babyPubKey babyjub.PublicKeyComp,
  778. tokenID uint32, numExitRoot, idx int64, amount *big.Int, siblings []*big.Int,
  779. instantWithdraw bool) (tx *types.Transaction, err error) {
  780. c.rw.Lock()
  781. defer c.rw.Unlock()
  782. cpy := c.nextBlock().copy()
  783. defer func() { c.revertIfErr(err, cpy) }()
  784. nextBlock := c.nextBlock()
  785. r := nextBlock.Rollup
  786. if int(numExitRoot) >= len(r.State.ExitRoots) {
  787. return nil, tracerr.Wrap(fmt.Errorf("numExitRoot >= len(r.State.ExitRoots)"))
  788. }
  789. if _, ok := r.State.ExitNullifierMap[numExitRoot][idx]; ok {
  790. return nil, tracerr.Wrap(fmt.Errorf("exit already withdrawn"))
  791. }
  792. r.State.ExitNullifierMap[numExitRoot][idx] = true
  793. babyPubKeyDecomp, err := babyPubKey.Decompress()
  794. if err != nil {
  795. return nil, tracerr.Wrap(err)
  796. }
  797. type data struct {
  798. BabyPubKey *babyjub.PublicKey
  799. TokenID uint32
  800. NumExitRoot int64
  801. Idx int64
  802. Amount *big.Int
  803. Siblings []*big.Int
  804. InstantWithdraw bool
  805. }
  806. tx = r.addTransaction(c.newTransaction("withdrawMerkleProof", data{
  807. BabyPubKey: babyPubKeyDecomp,
  808. TokenID: tokenID,
  809. NumExitRoot: numExitRoot,
  810. Idx: idx,
  811. Amount: amount,
  812. Siblings: siblings,
  813. InstantWithdraw: instantWithdraw,
  814. }))
  815. r.Events.Withdraw = append(r.Events.Withdraw, eth.RollupEventWithdraw{
  816. Idx: uint64(idx),
  817. NumExitRoot: uint64(numExitRoot),
  818. InstantWithdraw: instantWithdraw,
  819. TxHash: tx.Hash(),
  820. })
  821. if !instantWithdraw {
  822. w := nextBlock.WDelayer
  823. w.deposit(tx.Hash(), *c.addr, r.State.TokenList[int(tokenID)], amount)
  824. }
  825. return tx, nil
  826. }
  827. type transactionData struct {
  828. Name string
  829. Value interface{}
  830. }
  831. func (c *Client) newTransaction(name string, value interface{}) *types.Transaction {
  832. eth := c.nextBlock().Eth
  833. nonce := eth.Nonce
  834. eth.Nonce++
  835. data, err := json.Marshal(transactionData{name, value})
  836. if err != nil {
  837. panic(err)
  838. }
  839. return types.NewTransaction(nonce, ethCommon.Address{}, nil, 0, nil,
  840. data)
  841. }
  842. // RollupForgeBatch is the interface to call the smart contract function
  843. func (c *Client) RollupForgeBatch(args *eth.RollupForgeBatchArgs,
  844. auth *bind.TransactOpts) (tx *types.Transaction, err error) {
  845. c.rw.Lock()
  846. defer c.rw.Unlock()
  847. cpy := c.nextBlock().copy()
  848. defer func() { c.revertIfErr(err, cpy) }()
  849. if c.addr == nil {
  850. return nil, tracerr.Wrap(eth.ErrAccountNil)
  851. }
  852. a := c.nextBlock().Auction
  853. ok, err := a.canForge(*c.addr, a.Eth.BlockNum)
  854. if err != nil {
  855. return nil, tracerr.Wrap(err)
  856. }
  857. if !ok {
  858. return nil, tracerr.Wrap(fmt.Errorf(common.AuctionErrMsgCannotForge))
  859. }
  860. // TODO: Verify proof
  861. // Auction
  862. err = a.forge(*c.addr)
  863. if err != nil {
  864. return nil, tracerr.Wrap(err)
  865. }
  866. // TODO: If successful, store the tx in a successful array.
  867. // TODO: If failed, store the tx in a failed array.
  868. // TODO: Add method to move the tx to another block, reapply it there, and possibly go from
  869. // successful to failed.
  870. return c.addBatch(args)
  871. }
  872. // CtlAddBatch adds forged batch to the Rollup, without checking any ZKProof
  873. func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
  874. c.rw.Lock()
  875. defer c.rw.Unlock()
  876. if _, err := c.addBatch(args); err != nil {
  877. panic(err)
  878. }
  879. }
  880. func (c *Client) addBatch(args *eth.RollupForgeBatchArgs) (*types.Transaction, error) {
  881. nextBlock := c.nextBlock()
  882. r := nextBlock.Rollup
  883. r.State.StateRoot = args.NewStRoot
  884. if args.NewLastIdx < r.State.CurrentIdx {
  885. return nil, tracerr.Wrap(fmt.Errorf("args.NewLastIdx < r.State.CurrentIdx"))
  886. }
  887. r.State.CurrentIdx = args.NewLastIdx
  888. r.State.ExitNullifierMap[int64(len(r.State.ExitRoots))] = make(map[int64]bool)
  889. r.State.ExitRoots = append(r.State.ExitRoots, args.NewExitRoot)
  890. if args.L1Batch {
  891. r.State.CurrentToForgeL1TxsNum++
  892. if r.State.CurrentToForgeL1TxsNum == r.State.LastToForgeL1TxsNum {
  893. r.State.LastToForgeL1TxsNum++
  894. r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
  895. }
  896. }
  897. ethTx := r.addTransaction(c.newTransaction("forgebatch", args))
  898. c.forgeBatchArgsPending[ethTx.Hash()] = &batch{*args, *c.addr}
  899. r.Events.ForgeBatch = append(r.Events.ForgeBatch, eth.RollupEventForgeBatch{
  900. BatchNum: int64(len(r.State.ExitRoots)) - 1,
  901. EthTxHash: ethTx.Hash(),
  902. L1UserTxsLen: uint16(len(args.L1UserTxs)),
  903. })
  904. return ethTx, nil
  905. }
  906. // RollupAddTokenSimple is a wrapper around RollupAddToken that automatically
  907. // sets `deadlie`.
  908. func (c *Client) RollupAddTokenSimple(tokenAddress ethCommon.Address,
  909. feeAddToken *big.Int) (tx *types.Transaction, err error) {
  910. return c.RollupAddToken(tokenAddress, feeAddToken, big.NewInt(9999)) //nolint:gomnd
  911. }
  912. // RollupAddToken is the interface to call the smart contract function
  913. func (c *Client) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int,
  914. deadline *big.Int) (tx *types.Transaction, err error) {
  915. c.rw.Lock()
  916. defer c.rw.Unlock()
  917. cpy := c.nextBlock().copy()
  918. defer func() { c.revertIfErr(err, cpy) }()
  919. if c.addr == nil {
  920. return nil, tracerr.Wrap(eth.ErrAccountNil)
  921. }
  922. nextBlock := c.nextBlock()
  923. r := nextBlock.Rollup
  924. if _, ok := r.State.TokenMap[tokenAddress]; ok {
  925. return nil, tracerr.Wrap(fmt.Errorf("Token %v already registered", tokenAddress))
  926. }
  927. if feeAddToken.Cmp(r.Vars.FeeAddToken) != 0 {
  928. return nil,
  929. tracerr.Wrap(fmt.Errorf("Expected fee: %v but got: %v",
  930. r.Vars.FeeAddToken, feeAddToken))
  931. }
  932. r.State.TokenMap[tokenAddress] = true
  933. r.State.TokenList = append(r.State.TokenList, tokenAddress)
  934. r.Events.AddToken = append(r.Events.AddToken, eth.RollupEventAddToken{
  935. TokenAddress: tokenAddress,
  936. TokenID: uint32(len(r.State.TokenList) - 1)})
  937. return r.addTransaction(c.newTransaction("addtoken", tokenAddress)), nil
  938. }
  939. // RollupGetCurrentTokens is the interface to call the smart contract function
  940. func (c *Client) RollupGetCurrentTokens() (*big.Int, error) {
  941. c.rw.RLock()
  942. defer c.rw.RUnlock()
  943. log.Error("TODO")
  944. return nil, tracerr.Wrap(errTODO)
  945. }
  946. // RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
  947. func (c *Client) RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (tx *types.Transaction,
  948. err error) {
  949. c.rw.Lock()
  950. defer c.rw.Unlock()
  951. cpy := c.nextBlock().copy()
  952. defer func() { c.revertIfErr(err, cpy) }()
  953. if c.addr == nil {
  954. return nil, tracerr.Wrap(eth.ErrAccountNil)
  955. }
  956. nextBlock := c.nextBlock()
  957. r := nextBlock.Rollup
  958. r.Vars.ForgeL1L2BatchTimeout = newForgeL1Timeout
  959. r.Events.UpdateForgeL1L2BatchTimeout = append(r.Events.UpdateForgeL1L2BatchTimeout,
  960. eth.RollupEventUpdateForgeL1L2BatchTimeout{NewForgeL1L2BatchTimeout: newForgeL1Timeout})
  961. return r.addTransaction(c.newTransaction("updateForgeL1L2BatchTimeout", newForgeL1Timeout)), nil
  962. }
  963. // RollupUpdateFeeAddToken is the interface to call the smart contract function
  964. func (c *Client) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction,
  965. err error) {
  966. c.rw.Lock()
  967. defer c.rw.Unlock()
  968. cpy := c.nextBlock().copy()
  969. defer func() { c.revertIfErr(err, cpy) }()
  970. if c.addr == nil {
  971. return nil, tracerr.Wrap(eth.ErrAccountNil)
  972. }
  973. log.Error("TODO")
  974. return nil, tracerr.Wrap(errTODO)
  975. }
  976. // RollupUpdateTokensHEZ is the interface to call the smart contract function
  977. // func (c *Client) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (tx *types.Transaction,
  978. // err error) {
  979. // c.rw.Lock()
  980. // defer c.rw.Unlock()
  981. // cpy := c.nextBlock().copy()
  982. // defer func() { c.revertIfErr(err, cpy) }()
  983. //
  984. // log.Error("TODO")
  985. // return nil, errTODO
  986. // }
  987. // RollupUpdateGovernance is the interface to call the smart contract function
  988. // func (c *Client) RollupUpdateGovernance() (*types.Transaction, error) {
  989. // // TODO (Not defined in Hermez.sol)
  990. // return nil, errTODO
  991. // }
  992. // RollupConstants returns the Constants of the Rollup Smart Contract
  993. func (c *Client) RollupConstants() (*common.RollupConstants, error) {
  994. c.rw.RLock()
  995. defer c.rw.RUnlock()
  996. return c.rollupConstants, nil
  997. }
  998. // RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
  999. func (c *Client) RollupEventsByBlock(blockNum int64,
  1000. blockHash *ethCommon.Hash) (*eth.RollupEvents, error) {
  1001. c.rw.RLock()
  1002. defer c.rw.RUnlock()
  1003. block, ok := c.blocks[blockNum]
  1004. if !ok {
  1005. return nil, tracerr.Wrap(fmt.Errorf("Block %v doesn't exist", blockNum))
  1006. }
  1007. if blockHash != nil && *blockHash != block.Eth.Hash {
  1008. return nil, tracerr.Wrap(fmt.Errorf("Hash mismatch, requested %v got %v",
  1009. blockHash, block.Eth.Hash))
  1010. }
  1011. return &block.Rollup.Events, nil
  1012. }
  1013. // RollupEventInit returns the initialize event with its corresponding block number
  1014. func (c *Client) RollupEventInit() (*eth.RollupEventInitialize, int64, error) {
  1015. vars := c.blocks[0].Rollup.Vars
  1016. return &eth.RollupEventInitialize{
  1017. ForgeL1L2BatchTimeout: uint8(vars.ForgeL1L2BatchTimeout),
  1018. FeeAddToken: vars.FeeAddToken,
  1019. WithdrawalDelay: vars.WithdrawalDelay,
  1020. }, 1, nil
  1021. }
  1022. // RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract
  1023. // in the given transaction
  1024. func (c *Client) RollupForgeBatchArgs(ethTxHash ethCommon.Hash,
  1025. l1UserTxsLen uint16) (*eth.RollupForgeBatchArgs, *ethCommon.Address, error) {
  1026. c.rw.RLock()
  1027. defer c.rw.RUnlock()
  1028. batch, ok := c.forgeBatchArgs[ethTxHash]
  1029. if !ok {
  1030. return nil, nil, tracerr.Wrap(fmt.Errorf("transaction not found"))
  1031. }
  1032. return &batch.ForgeBatchArgs, &batch.Sender, nil
  1033. }
  1034. //
  1035. // Auction
  1036. //
  1037. // AuctionSetSlotDeadline is the interface to call the smart contract function
  1038. func (c *Client) AuctionSetSlotDeadline(newDeadline uint8) (tx *types.Transaction, err error) {
  1039. c.rw.Lock()
  1040. defer c.rw.Unlock()
  1041. cpy := c.nextBlock().copy()
  1042. defer func() { c.revertIfErr(err, cpy) }()
  1043. if c.addr == nil {
  1044. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1045. }
  1046. log.Error("TODO")
  1047. return nil, tracerr.Wrap(errTODO)
  1048. }
  1049. // AuctionGetSlotDeadline is the interface to call the smart contract function
  1050. func (c *Client) AuctionGetSlotDeadline() (uint8, error) {
  1051. c.rw.RLock()
  1052. defer c.rw.RUnlock()
  1053. log.Error("TODO")
  1054. return 0, tracerr.Wrap(errTODO)
  1055. }
  1056. // AuctionSetOpenAuctionSlots is the interface to call the smart contract function
  1057. func (c *Client) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction,
  1058. err error) {
  1059. c.rw.Lock()
  1060. defer c.rw.Unlock()
  1061. cpy := c.nextBlock().copy()
  1062. defer func() { c.revertIfErr(err, cpy) }()
  1063. if c.addr == nil {
  1064. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1065. }
  1066. nextBlock := c.nextBlock()
  1067. a := nextBlock.Auction
  1068. a.Vars.OpenAuctionSlots = newOpenAuctionSlots
  1069. a.Events.NewOpenAuctionSlots = append(a.Events.NewOpenAuctionSlots,
  1070. eth.AuctionEventNewOpenAuctionSlots{NewOpenAuctionSlots: newOpenAuctionSlots})
  1071. return a.addTransaction(c.newTransaction("setOpenAuctionSlots", newOpenAuctionSlots)), nil
  1072. }
  1073. // AuctionGetOpenAuctionSlots is the interface to call the smart contract function
  1074. func (c *Client) AuctionGetOpenAuctionSlots() (uint16, error) {
  1075. c.rw.RLock()
  1076. defer c.rw.RUnlock()
  1077. log.Error("TODO")
  1078. return 0, tracerr.Wrap(errTODO)
  1079. }
  1080. // AuctionSetClosedAuctionSlots is the interface to call the smart contract function
  1081. func (c *Client) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction,
  1082. err error) {
  1083. c.rw.Lock()
  1084. defer c.rw.Unlock()
  1085. cpy := c.nextBlock().copy()
  1086. defer func() { c.revertIfErr(err, cpy) }()
  1087. if c.addr == nil {
  1088. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1089. }
  1090. log.Error("TODO")
  1091. return nil, tracerr.Wrap(errTODO)
  1092. }
  1093. // AuctionGetClosedAuctionSlots is the interface to call the smart contract function
  1094. func (c *Client) AuctionGetClosedAuctionSlots() (uint16, error) {
  1095. c.rw.RLock()
  1096. defer c.rw.RUnlock()
  1097. log.Error("TODO")
  1098. return 0, tracerr.Wrap(errTODO)
  1099. }
  1100. // AuctionSetOutbidding is the interface to call the smart contract function
  1101. func (c *Client) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
  1102. c.rw.Lock()
  1103. defer c.rw.Unlock()
  1104. cpy := c.nextBlock().copy()
  1105. defer func() { c.revertIfErr(err, cpy) }()
  1106. if c.addr == nil {
  1107. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1108. }
  1109. log.Error("TODO")
  1110. return nil, tracerr.Wrap(errTODO)
  1111. }
  1112. // AuctionGetOutbidding is the interface to call the smart contract function
  1113. func (c *Client) AuctionGetOutbidding() (uint16, error) {
  1114. c.rw.RLock()
  1115. defer c.rw.RUnlock()
  1116. log.Error("TODO")
  1117. return 0, tracerr.Wrap(errTODO)
  1118. }
  1119. // AuctionSetAllocationRatio is the interface to call the smart contract function
  1120. func (c *Client) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction,
  1121. err error) {
  1122. c.rw.Lock()
  1123. defer c.rw.Unlock()
  1124. cpy := c.nextBlock().copy()
  1125. defer func() { c.revertIfErr(err, cpy) }()
  1126. if c.addr == nil {
  1127. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1128. }
  1129. log.Error("TODO")
  1130. return nil, tracerr.Wrap(errTODO)
  1131. }
  1132. // AuctionGetAllocationRatio is the interface to call the smart contract function
  1133. func (c *Client) AuctionGetAllocationRatio() ([3]uint16, error) {
  1134. c.rw.RLock()
  1135. defer c.rw.RUnlock()
  1136. log.Error("TODO")
  1137. return [3]uint16{}, tracerr.Wrap(errTODO)
  1138. }
  1139. // AuctionSetDonationAddress is the interface to call the smart contract function
  1140. func (c *Client) AuctionSetDonationAddress(
  1141. newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
  1142. c.rw.Lock()
  1143. defer c.rw.Unlock()
  1144. cpy := c.nextBlock().copy()
  1145. defer func() { c.revertIfErr(err, cpy) }()
  1146. if c.addr == nil {
  1147. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1148. }
  1149. log.Error("TODO")
  1150. return nil, tracerr.Wrap(errTODO)
  1151. }
  1152. // AuctionGetDonationAddress is the interface to call the smart contract function
  1153. func (c *Client) AuctionGetDonationAddress() (*ethCommon.Address, error) {
  1154. c.rw.RLock()
  1155. defer c.rw.RUnlock()
  1156. log.Error("TODO")
  1157. return nil, tracerr.Wrap(errTODO)
  1158. }
  1159. // AuctionSetBootCoordinator is the interface to call the smart contract function
  1160. func (c *Client) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address,
  1161. newBootCoordinatorURL string) (tx *types.Transaction, err error) {
  1162. c.rw.Lock()
  1163. defer c.rw.Unlock()
  1164. cpy := c.nextBlock().copy()
  1165. defer func() { c.revertIfErr(err, cpy) }()
  1166. if c.addr == nil {
  1167. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1168. }
  1169. log.Error("TODO")
  1170. return nil, tracerr.Wrap(errTODO)
  1171. }
  1172. // AuctionGetBootCoordinator is the interface to call the smart contract function
  1173. func (c *Client) AuctionGetBootCoordinator() (*ethCommon.Address, error) {
  1174. c.rw.RLock()
  1175. defer c.rw.RUnlock()
  1176. currentBlock := c.currentBlock()
  1177. a := currentBlock.Auction
  1178. return &a.Vars.BootCoordinator, nil
  1179. }
  1180. // AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
  1181. func (c *Client) AuctionChangeDefaultSlotSetBid(slotSet int64,
  1182. newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
  1183. c.rw.Lock()
  1184. defer c.rw.Unlock()
  1185. cpy := c.nextBlock().copy()
  1186. defer func() { c.revertIfErr(err, cpy) }()
  1187. if c.addr == nil {
  1188. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1189. }
  1190. log.Error("TODO")
  1191. return nil, tracerr.Wrap(errTODO)
  1192. }
  1193. // AuctionSetCoordinator is the interface to call the smart contract function
  1194. func (c *Client) AuctionSetCoordinator(forger ethCommon.Address,
  1195. URL string) (tx *types.Transaction, err error) {
  1196. c.rw.Lock()
  1197. defer c.rw.Unlock()
  1198. cpy := c.nextBlock().copy()
  1199. defer func() { c.revertIfErr(err, cpy) }()
  1200. if c.addr == nil {
  1201. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1202. }
  1203. nextBlock := c.nextBlock()
  1204. a := nextBlock.Auction
  1205. a.State.Coordinators[*c.addr] = &eth.Coordinator{
  1206. Forger: forger,
  1207. URL: URL,
  1208. }
  1209. a.Events.SetCoordinator = append(a.Events.SetCoordinator,
  1210. eth.AuctionEventSetCoordinator{
  1211. BidderAddress: *c.addr,
  1212. ForgerAddress: forger,
  1213. CoordinatorURL: URL,
  1214. })
  1215. type data struct {
  1216. BidderAddress ethCommon.Address
  1217. ForgerAddress ethCommon.Address
  1218. URL string
  1219. }
  1220. return a.addTransaction(c.newTransaction("registercoordinator", data{*c.addr, forger, URL})),
  1221. nil
  1222. }
  1223. // AuctionIsRegisteredCoordinator is the interface to call the smart contract function
  1224. func (c *Client) AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address) (bool, error) {
  1225. c.rw.RLock()
  1226. defer c.rw.RUnlock()
  1227. log.Error("TODO")
  1228. return false, tracerr.Wrap(errTODO)
  1229. }
  1230. // AuctionUpdateCoordinatorInfo is the interface to call the smart contract function
  1231. func (c *Client) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address,
  1232. newWithdrawAddress ethCommon.Address, newURL string) (tx *types.Transaction, err error) {
  1233. c.rw.Lock()
  1234. defer c.rw.Unlock()
  1235. cpy := c.nextBlock().copy()
  1236. defer func() { c.revertIfErr(err, cpy) }()
  1237. if c.addr == nil {
  1238. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1239. }
  1240. log.Error("TODO")
  1241. return nil, tracerr.Wrap(errTODO)
  1242. }
  1243. // AuctionGetSlotNumber is the interface to call the smart contract function
  1244. func (c *Client) AuctionGetSlotNumber(blockNum int64) (int64, error) {
  1245. c.rw.RLock()
  1246. defer c.rw.RUnlock()
  1247. currentBlock := c.currentBlock()
  1248. a := currentBlock.Auction
  1249. return a.getSlotNumber(blockNum), nil
  1250. }
  1251. // AuctionGetCurrentSlotNumber is the interface to call the smart contract function
  1252. func (c *Client) AuctionGetCurrentSlotNumber() (int64, error) {
  1253. c.rw.RLock()
  1254. defer c.rw.RUnlock()
  1255. log.Error("TODO")
  1256. return 0, tracerr.Wrap(errTODO)
  1257. }
  1258. // AuctionGetMinBidBySlot is the interface to call the smart contract function
  1259. func (c *Client) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
  1260. c.rw.RLock()
  1261. defer c.rw.RUnlock()
  1262. log.Error("TODO")
  1263. return nil, tracerr.Wrap(errTODO)
  1264. }
  1265. // AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
  1266. func (c *Client) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) {
  1267. c.rw.RLock()
  1268. defer c.rw.RUnlock()
  1269. log.Error("TODO")
  1270. return nil, tracerr.Wrap(errTODO)
  1271. }
  1272. // AuctionGetSlotSet is the interface to call the smart contract function
  1273. func (c *Client) AuctionGetSlotSet(slot int64) (*big.Int, error) {
  1274. c.rw.RLock()
  1275. defer c.rw.RUnlock()
  1276. log.Error("TODO")
  1277. return nil, tracerr.Wrap(errTODO)
  1278. }
  1279. // AuctionTokensReceived is the interface to call the smart contract function
  1280. // func (c *Client) AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int,
  1281. // userData, operatorData []byte) error {
  1282. // return errTODO
  1283. // }
  1284. // AuctionBidSimple is a wrapper around AuctionBid that automatically sets `amount` and `deadline`.
  1285. func (c *Client) AuctionBidSimple(slot int64, bidAmount *big.Int) (tx *types.Transaction,
  1286. err error) {
  1287. return c.AuctionBid(bidAmount, slot, bidAmount, big.NewInt(99999)) //nolint:gomnd
  1288. }
  1289. // AuctionBid is the interface to call the smart contract function. This
  1290. // implementation behaves as if any address has infinite tokens.
  1291. func (c *Client) AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int,
  1292. deadline *big.Int) (tx *types.Transaction, err error) {
  1293. c.rw.Lock()
  1294. defer c.rw.Unlock()
  1295. cpy := c.nextBlock().copy()
  1296. defer func() { func() { c.revertIfErr(err, cpy) }() }()
  1297. if c.addr == nil {
  1298. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1299. }
  1300. nextBlock := c.nextBlock()
  1301. a := nextBlock.Auction
  1302. if slot <= a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
  1303. return nil, tracerr.Wrap(errBidClosed)
  1304. }
  1305. if slot >
  1306. a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots)+int64(a.Vars.OpenAuctionSlots) {
  1307. return nil, tracerr.Wrap(errBidNotOpen)
  1308. }
  1309. minBid, err := a.getMinBidBySlot(slot)
  1310. if err != nil {
  1311. return nil, tracerr.Wrap(err)
  1312. }
  1313. if bidAmount.Cmp(minBid) == -1 {
  1314. return nil, tracerr.Wrap(errBidBelowMin)
  1315. }
  1316. if _, ok := a.State.Coordinators[*c.addr]; !ok {
  1317. return nil, tracerr.Wrap(errCoordNotReg)
  1318. }
  1319. slotState, ok := a.State.Slots[slot]
  1320. if !ok {
  1321. slotState = eth.NewSlotState()
  1322. a.State.Slots[slot] = slotState
  1323. }
  1324. slotState.Bidder = *c.addr
  1325. slotState.BidAmount = bidAmount
  1326. a.Events.NewBid = append(a.Events.NewBid,
  1327. eth.AuctionEventNewBid{Slot: slot, BidAmount: bidAmount, Bidder: *c.addr})
  1328. type data struct {
  1329. Slot int64
  1330. BidAmount *big.Int
  1331. Bidder ethCommon.Address
  1332. }
  1333. return a.addTransaction(c.newTransaction("bid", data{slot, bidAmount, *c.addr})), nil
  1334. }
  1335. // AuctionMultiBid is the interface to call the smart contract function. This
  1336. // implementation behaves as if any address has infinite tokens.
  1337. func (c *Client) AuctionMultiBid(amount *big.Int, startingSlot int64, endingSlot int64,
  1338. slotSet [6]bool, maxBid, closedMinBid, deadline *big.Int) (tx *types.Transaction, err error) {
  1339. c.rw.Lock()
  1340. defer c.rw.Unlock()
  1341. cpy := c.nextBlock().copy()
  1342. defer func() { c.revertIfErr(err, cpy) }()
  1343. if c.addr == nil {
  1344. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1345. }
  1346. log.Error("TODO")
  1347. return nil, tracerr.Wrap(errTODO)
  1348. }
  1349. // AuctionCanForge is the interface to call the smart contract function
  1350. func (c *Client) AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error) {
  1351. c.rw.RLock()
  1352. defer c.rw.RUnlock()
  1353. currentBlock := c.currentBlock()
  1354. a := currentBlock.Auction
  1355. return a.canForge(forger, blockNum)
  1356. }
  1357. // AuctionForge is the interface to call the smart contract function
  1358. func (c *Client) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
  1359. c.rw.Lock()
  1360. defer c.rw.Unlock()
  1361. cpy := c.nextBlock().copy()
  1362. defer func() { c.revertIfErr(err, cpy) }()
  1363. if c.addr == nil {
  1364. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1365. }
  1366. log.Error("TODO")
  1367. return nil, tracerr.Wrap(errTODO)
  1368. }
  1369. // AuctionClaimHEZ is the interface to call the smart contract function
  1370. func (c *Client) AuctionClaimHEZ() (tx *types.Transaction, err error) {
  1371. c.rw.Lock()
  1372. defer c.rw.Unlock()
  1373. cpy := c.nextBlock().copy()
  1374. defer func() { c.revertIfErr(err, cpy) }()
  1375. if c.addr == nil {
  1376. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1377. }
  1378. log.Error("TODO")
  1379. return nil, tracerr.Wrap(errTODO)
  1380. }
  1381. // AuctionGetClaimableHEZ is the interface to call the smart contract function
  1382. func (c *Client) AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error) {
  1383. c.rw.RLock()
  1384. defer c.rw.RUnlock()
  1385. log.Error("TODO")
  1386. return nil, tracerr.Wrap(errTODO)
  1387. }
  1388. // AuctionConstants returns the Constants of the Auction Smart Contract
  1389. func (c *Client) AuctionConstants() (*common.AuctionConstants, error) {
  1390. c.rw.RLock()
  1391. defer c.rw.RUnlock()
  1392. return c.auctionConstants, nil
  1393. }
  1394. // AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract
  1395. func (c *Client) AuctionEventsByBlock(blockNum int64,
  1396. blockHash *ethCommon.Hash) (*eth.AuctionEvents, error) {
  1397. c.rw.RLock()
  1398. defer c.rw.RUnlock()
  1399. block, ok := c.blocks[blockNum]
  1400. if !ok {
  1401. return nil, tracerr.Wrap(fmt.Errorf("Block %v doesn't exist", blockNum))
  1402. }
  1403. if blockHash != nil && *blockHash != block.Eth.Hash {
  1404. return nil, tracerr.Wrap(fmt.Errorf("Hash mismatch, requested %v got %v",
  1405. blockHash, block.Eth.Hash))
  1406. }
  1407. return &block.Auction.Events, nil
  1408. }
  1409. // AuctionEventInit returns the initialize event with its corresponding block number
  1410. func (c *Client) AuctionEventInit() (*eth.AuctionEventInitialize, int64, error) {
  1411. vars := c.blocks[0].Auction.Vars
  1412. return &eth.AuctionEventInitialize{
  1413. DonationAddress: vars.DonationAddress,
  1414. BootCoordinatorAddress: vars.BootCoordinator,
  1415. BootCoordinatorURL: vars.BootCoordinatorURL,
  1416. Outbidding: vars.Outbidding,
  1417. SlotDeadline: vars.SlotDeadline,
  1418. ClosedAuctionSlots: vars.ClosedAuctionSlots,
  1419. OpenAuctionSlots: vars.OpenAuctionSlots,
  1420. AllocationRatio: vars.AllocationRatio,
  1421. }, 1, nil
  1422. }
  1423. //
  1424. // WDelayer
  1425. //
  1426. // WDelayerGetHermezGovernanceAddress is the interface to call the smart contract function
  1427. func (c *Client) WDelayerGetHermezGovernanceAddress() (*ethCommon.Address, error) {
  1428. c.rw.RLock()
  1429. defer c.rw.RUnlock()
  1430. log.Error("TODO")
  1431. return nil, tracerr.Wrap(errTODO)
  1432. }
  1433. // WDelayerTransferGovernance is the interface to call the smart contract function
  1434. func (c *Client) WDelayerTransferGovernance(newAddress ethCommon.Address) (tx *types.Transaction,
  1435. err error) {
  1436. c.rw.Lock()
  1437. defer c.rw.Unlock()
  1438. cpy := c.nextBlock().copy()
  1439. defer func() { c.revertIfErr(err, cpy) }()
  1440. if c.addr == nil {
  1441. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1442. }
  1443. log.Error("TODO")
  1444. return nil, tracerr.Wrap(errTODO)
  1445. }
  1446. // WDelayerClaimGovernance is the interface to call the smart contract function
  1447. func (c *Client) WDelayerClaimGovernance() (tx *types.Transaction, err error) {
  1448. c.rw.Lock()
  1449. defer c.rw.Unlock()
  1450. cpy := c.nextBlock().copy()
  1451. defer func() { c.revertIfErr(err, cpy) }()
  1452. if c.addr == nil {
  1453. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1454. }
  1455. log.Error("TODO")
  1456. return nil, tracerr.Wrap(errTODO)
  1457. }
  1458. // WDelayerGetEmergencyCouncil is the interface to call the smart contract function
  1459. func (c *Client) WDelayerGetEmergencyCouncil() (*ethCommon.Address, error) {
  1460. c.rw.RLock()
  1461. defer c.rw.RUnlock()
  1462. log.Error("TODO")
  1463. return nil, tracerr.Wrap(errTODO)
  1464. }
  1465. // WDelayerTransferEmergencyCouncil is the interface to call the smart contract function
  1466. func (c *Client) WDelayerTransferEmergencyCouncil(newAddress ethCommon.Address) (
  1467. tx *types.Transaction, err error) {
  1468. c.rw.Lock()
  1469. defer c.rw.Unlock()
  1470. cpy := c.nextBlock().copy()
  1471. defer func() { c.revertIfErr(err, cpy) }()
  1472. if c.addr == nil {
  1473. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1474. }
  1475. log.Error("TODO")
  1476. return nil, tracerr.Wrap(errTODO)
  1477. }
  1478. // WDelayerClaimEmergencyCouncil is the interface to call the smart contract function
  1479. func (c *Client) WDelayerClaimEmergencyCouncil() (tx *types.Transaction, err error) {
  1480. c.rw.Lock()
  1481. defer c.rw.Unlock()
  1482. cpy := c.nextBlock().copy()
  1483. defer func() { c.revertIfErr(err, cpy) }()
  1484. if c.addr == nil {
  1485. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1486. }
  1487. log.Error("TODO")
  1488. return nil, tracerr.Wrap(errTODO)
  1489. }
  1490. // WDelayerIsEmergencyMode is the interface to call the smart contract function
  1491. func (c *Client) WDelayerIsEmergencyMode() (bool, error) {
  1492. c.rw.RLock()
  1493. defer c.rw.RUnlock()
  1494. log.Error("TODO")
  1495. return false, tracerr.Wrap(errTODO)
  1496. }
  1497. // WDelayerGetWithdrawalDelay is the interface to call the smart contract function
  1498. func (c *Client) WDelayerGetWithdrawalDelay() (int64, error) {
  1499. c.rw.RLock()
  1500. defer c.rw.RUnlock()
  1501. log.Error("TODO")
  1502. return 0, tracerr.Wrap(errTODO)
  1503. }
  1504. // WDelayerGetEmergencyModeStartingTime is the interface to call the smart contract function
  1505. func (c *Client) WDelayerGetEmergencyModeStartingTime() (int64, error) {
  1506. c.rw.RLock()
  1507. defer c.rw.RUnlock()
  1508. log.Error("TODO")
  1509. return 0, tracerr.Wrap(errTODO)
  1510. }
  1511. // WDelayerEnableEmergencyMode is the interface to call the smart contract function
  1512. func (c *Client) WDelayerEnableEmergencyMode() (tx *types.Transaction, err error) {
  1513. c.rw.Lock()
  1514. defer c.rw.Unlock()
  1515. cpy := c.nextBlock().copy()
  1516. defer func() { c.revertIfErr(err, cpy) }()
  1517. if c.addr == nil {
  1518. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1519. }
  1520. log.Error("TODO")
  1521. return nil, tracerr.Wrap(errTODO)
  1522. }
  1523. // WDelayerChangeWithdrawalDelay is the interface to call the smart contract function
  1524. func (c *Client) WDelayerChangeWithdrawalDelay(newWithdrawalDelay uint64) (tx *types.Transaction,
  1525. err error) {
  1526. c.rw.Lock()
  1527. defer c.rw.Unlock()
  1528. cpy := c.nextBlock().copy()
  1529. defer func() { c.revertIfErr(err, cpy) }()
  1530. if c.addr == nil {
  1531. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1532. }
  1533. nextBlock := c.nextBlock()
  1534. w := nextBlock.WDelayer
  1535. w.Vars.WithdrawalDelay = newWithdrawalDelay
  1536. w.Events.NewWithdrawalDelay = append(w.Events.NewWithdrawalDelay,
  1537. eth.WDelayerEventNewWithdrawalDelay{WithdrawalDelay: newWithdrawalDelay})
  1538. return w.addTransaction(c.newTransaction("changeWithdrawalDelay", newWithdrawalDelay)), nil
  1539. }
  1540. // WDelayerDepositInfo is the interface to call the smart contract function
  1541. func (c *Client) WDelayerDepositInfo(owner, token ethCommon.Address) (eth.DepositState, error) {
  1542. c.rw.RLock()
  1543. defer c.rw.RUnlock()
  1544. log.Error("TODO")
  1545. return eth.DepositState{}, tracerr.Wrap(errTODO)
  1546. }
  1547. // WDelayerDeposit is the interface to call the smart contract function
  1548. func (c *Client) WDelayerDeposit(onwer, token ethCommon.Address, amount *big.Int) (
  1549. tx *types.Transaction, err error) {
  1550. c.rw.Lock()
  1551. defer c.rw.Unlock()
  1552. cpy := c.nextBlock().copy()
  1553. defer func() { c.revertIfErr(err, cpy) }()
  1554. if c.addr == nil {
  1555. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1556. }
  1557. log.Error("TODO")
  1558. return nil, tracerr.Wrap(errTODO)
  1559. }
  1560. // WDelayerWithdrawal is the interface to call the smart contract function
  1561. func (c *Client) WDelayerWithdrawal(owner, token ethCommon.Address) (tx *types.Transaction,
  1562. err error) {
  1563. c.rw.Lock()
  1564. defer c.rw.Unlock()
  1565. cpy := c.nextBlock().copy()
  1566. defer func() { c.revertIfErr(err, cpy) }()
  1567. if c.addr == nil {
  1568. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1569. }
  1570. log.Error("TODO")
  1571. return nil, tracerr.Wrap(errTODO)
  1572. }
  1573. // WDelayerEscapeHatchWithdrawal is the interface to call the smart contract function
  1574. func (c *Client) WDelayerEscapeHatchWithdrawal(to, token ethCommon.Address, amount *big.Int) (
  1575. tx *types.Transaction, err error) {
  1576. c.rw.Lock()
  1577. defer c.rw.Unlock()
  1578. cpy := c.nextBlock().copy()
  1579. defer func() { c.revertIfErr(err, cpy) }()
  1580. if c.addr == nil {
  1581. return nil, tracerr.Wrap(eth.ErrAccountNil)
  1582. }
  1583. log.Error("TODO")
  1584. return nil, tracerr.Wrap(errTODO)
  1585. }
  1586. // WDelayerEventsByBlock returns the events in a block that happened in the WDelayer Contract
  1587. func (c *Client) WDelayerEventsByBlock(blockNum int64,
  1588. blockHash *ethCommon.Hash) (*eth.WDelayerEvents, error) {
  1589. c.rw.RLock()
  1590. defer c.rw.RUnlock()
  1591. block, ok := c.blocks[blockNum]
  1592. if !ok {
  1593. return nil, tracerr.Wrap(fmt.Errorf("Block %v doesn't exist", blockNum))
  1594. }
  1595. if blockHash != nil && *blockHash != block.Eth.Hash {
  1596. return nil, tracerr.Wrap(fmt.Errorf("Hash mismatch, requested %v got %v",
  1597. blockHash, block.Eth.Hash))
  1598. }
  1599. return &block.WDelayer.Events, nil
  1600. }
  1601. // WDelayerConstants returns the Constants of the WDelayer Contract
  1602. func (c *Client) WDelayerConstants() (*common.WDelayerConstants, error) {
  1603. c.rw.RLock()
  1604. defer c.rw.RUnlock()
  1605. return c.wDelayerConstants, nil
  1606. }
  1607. // WDelayerEventInit returns the initialize event with its corresponding block number
  1608. func (c *Client) WDelayerEventInit() (*eth.WDelayerEventInitialize, int64, error) {
  1609. vars := c.blocks[0].WDelayer.Vars
  1610. return &eth.WDelayerEventInitialize{
  1611. InitialWithdrawalDelay: vars.WithdrawalDelay,
  1612. InitialHermezGovernanceAddress: vars.HermezGovernanceAddress,
  1613. InitialEmergencyCouncil: vars.EmergencyCouncilAddress,
  1614. }, 1, nil
  1615. }
  1616. // CtlAddBlocks adds block data to the smarts contracts. The added blocks will
  1617. // appear as mined. Not thread safe.
  1618. func (c *Client) CtlAddBlocks(blocks []common.BlockData) (err error) {
  1619. // NOTE: We don't lock because internally we call public functions that
  1620. // lock already.
  1621. for _, block := range blocks {
  1622. nextBlock := c.nextBlock()
  1623. rollup := nextBlock.Rollup
  1624. auction := nextBlock.Auction
  1625. for _, token := range block.Rollup.AddedTokens {
  1626. if _, err := c.RollupAddTokenSimple(token.EthAddr,
  1627. rollup.Vars.FeeAddToken); err != nil {
  1628. return tracerr.Wrap(err)
  1629. }
  1630. }
  1631. for _, tx := range block.Rollup.L1UserTxs {
  1632. c.CtlSetAddr(tx.FromEthAddr)
  1633. if _, err := c.RollupL1UserTxERC20ETH(tx.FromBJJ, int64(tx.FromIdx),
  1634. tx.DepositAmount, tx.Amount, uint32(tx.TokenID),
  1635. int64(tx.ToIdx)); err != nil {
  1636. return tracerr.Wrap(err)
  1637. }
  1638. }
  1639. c.CtlSetAddr(auction.Vars.BootCoordinator)
  1640. for _, batch := range block.Rollup.Batches {
  1641. auths := make([][]byte, len(batch.L1CoordinatorTxs))
  1642. for i := range auths {
  1643. auths[i] = make([]byte, 65)
  1644. }
  1645. if _, err := c.RollupForgeBatch(&eth.RollupForgeBatchArgs{
  1646. NewLastIdx: batch.Batch.LastIdx,
  1647. NewStRoot: batch.Batch.StateRoot,
  1648. NewExitRoot: batch.Batch.ExitRoot,
  1649. L1CoordinatorTxs: batch.L1CoordinatorTxs,
  1650. L1CoordinatorTxsAuths: auths,
  1651. L2TxsData: batch.L2Txs,
  1652. FeeIdxCoordinator: batch.Batch.FeeIdxsCoordinator,
  1653. // Circuit selector
  1654. VerifierIdx: 0, // Intentionally empty
  1655. L1Batch: batch.L1Batch,
  1656. ProofA: [2]*big.Int{}, // Intentionally empty
  1657. ProofB: [2][2]*big.Int{}, // Intentionally empty
  1658. ProofC: [2]*big.Int{}, // Intentionally empty
  1659. }, nil); err != nil {
  1660. return tracerr.Wrap(err)
  1661. }
  1662. }
  1663. // Mine block and sync
  1664. c.CtlMineBlock()
  1665. }
  1666. return nil
  1667. }