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.

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