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.

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