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.

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