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.

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