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.

1819 lines
56 KiB

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