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.

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