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.

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