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.

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