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.

1319 lines
38 KiB

  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. ethCommon "github.com/ethereum/go-ethereum/common"
  12. "github.com/ethereum/go-ethereum/core/types"
  13. "github.com/hermeznetwork/hermez-node/common"
  14. "github.com/hermeznetwork/hermez-node/eth"
  15. "github.com/hermeznetwork/hermez-node/log"
  16. "github.com/iden3/go-iden3-crypto/babyjub"
  17. "github.com/mitchellh/copystructure"
  18. )
  19. func init() {
  20. copystructure.Copiers[reflect.TypeOf(big.Int{})] =
  21. func(raw interface{}) (interface{}, error) {
  22. in := raw.(big.Int)
  23. out := new(big.Int).Set(&in)
  24. return *out, nil
  25. }
  26. }
  27. // RollupBlock stores all the data related to the Rollup SC from an ethereum block
  28. type RollupBlock struct {
  29. State eth.RollupState
  30. Vars eth.RollupVariables
  31. Events eth.RollupEvents
  32. Txs map[ethCommon.Hash]*types.Transaction
  33. Constants *eth.RollupConstants
  34. Eth *EthereumBlock
  35. }
  36. func (r *RollupBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  37. txHash := tx.Hash()
  38. r.Txs[txHash] = tx
  39. return tx
  40. }
  41. var (
  42. errBidClosed = fmt.Errorf("Bid has already been closed")
  43. errBidNotOpen = fmt.Errorf("Bid has not been opened yet")
  44. errBidBelowMin = fmt.Errorf("Bid below minimum")
  45. errCoordNotReg = fmt.Errorf("Coordinator not registered")
  46. )
  47. // AuctionBlock stores all the data related to the Auction SC from an ethereum block
  48. type AuctionBlock struct {
  49. State eth.AuctionState
  50. Vars eth.AuctionVariables
  51. Events eth.AuctionEvents
  52. Txs map[ethCommon.Hash]*types.Transaction
  53. Constants *eth.AuctionConstants
  54. Eth *EthereumBlock
  55. }
  56. func (a *AuctionBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  57. txHash := tx.Hash()
  58. a.Txs[txHash] = tx
  59. return tx
  60. }
  61. func (a *AuctionBlock) getSlotNumber(blockNumber int64) int64 {
  62. if a.Eth.BlockNum >= a.Constants.GenesisBlockNum {
  63. return (blockNumber - a.Constants.GenesisBlockNum) / int64(a.Constants.BlocksPerSlot)
  64. }
  65. return 0
  66. }
  67. func (a *AuctionBlock) getCurrentSlotNumber() int64 {
  68. return a.getSlotNumber(a.Eth.BlockNum)
  69. }
  70. func (a *AuctionBlock) getSlotSet(slot int64) int64 {
  71. return slot % int64(len(a.Vars.DefaultSlotSetBid))
  72. }
  73. func (a *AuctionBlock) getMinBidBySlot(slot int64) (*big.Int, error) {
  74. if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
  75. return nil, errBidClosed
  76. }
  77. slotSet := a.getSlotSet(slot)
  78. // fmt.Println("slot:", slot, "slotSet:", slotSet)
  79. var prevBid *big.Int
  80. slotState, ok := a.State.Slots[slot]
  81. if !ok {
  82. slotState = eth.NewSlotState()
  83. a.State.Slots[slot] = slotState
  84. }
  85. // If the bidAmount for a slot is 0 it means that it has not yet been bid, so the midBid will be the minimum
  86. // bid for the slot time plus the outbidding set, otherwise it will be the bidAmount plus the outbidding
  87. if slotState.BidAmount.Cmp(big.NewInt(0)) == 0 {
  88. prevBid = a.Vars.DefaultSlotSetBid[slotSet]
  89. } else {
  90. prevBid = slotState.BidAmount
  91. }
  92. outBid := new(big.Int).Set(prevBid)
  93. // fmt.Println("outBid:", outBid)
  94. outBid.Mul(outBid, big.NewInt(int64(a.Vars.Outbidding)))
  95. outBid.Div(outBid, big.NewInt(10000)) //nolint:gomnd
  96. outBid.Add(prevBid, outBid)
  97. // fmt.Println("minBid:", outBid)
  98. return outBid, nil
  99. }
  100. func (a *AuctionBlock) forge(forger ethCommon.Address) error {
  101. if ok, err := a.canForge(forger, a.Eth.BlockNum); err != nil {
  102. return err
  103. } else if !ok {
  104. return fmt.Errorf("Can't forge")
  105. }
  106. slotToForge := a.getSlotNumber(a.Eth.BlockNum)
  107. slotState, ok := a.State.Slots[slotToForge]
  108. if !ok {
  109. slotState = eth.NewSlotState()
  110. a.State.Slots[slotToForge] = slotState
  111. }
  112. slotState.Fulfilled = true
  113. a.Events.NewForge = append(a.Events.NewForge, eth.AuctionEventNewForge{
  114. Forger: forger,
  115. CurrentSlot: slotToForge,
  116. })
  117. return nil
  118. }
  119. func (a *AuctionBlock) canForge(forger ethCommon.Address, blockNum int64) (bool, error) {
  120. if blockNum < a.Constants.GenesisBlockNum {
  121. return false, fmt.Errorf("Auction has not started yet")
  122. }
  123. slotToForge := a.getSlotNumber(blockNum)
  124. // Get the relativeBlock to check if the slotDeadline has been exceeded
  125. relativeBlock := blockNum - (a.Constants.GenesisBlockNum + (slotToForge * int64(a.Constants.BlocksPerSlot)))
  126. // If the closedMinBid is 0 it means that we have to take as minBid the one that is set for this slot set,
  127. // otherwise the one that has been saved will be used
  128. var minBid *big.Int
  129. slotState, ok := a.State.Slots[slotToForge]
  130. if !ok {
  131. slotState = eth.NewSlotState()
  132. a.State.Slots[slotToForge] = slotState
  133. }
  134. if slotState.ClosedMinBid.Cmp(big.NewInt(0)) == 0 {
  135. minBid = a.Vars.DefaultSlotSetBid[a.getSlotSet(slotToForge)]
  136. } else {
  137. minBid = slotState.ClosedMinBid
  138. }
  139. if !slotState.Fulfilled && (relativeBlock >= int64(a.Vars.SlotDeadline)) {
  140. // if the relative block has exceeded the slotDeadline and no batch has been forged, anyone can forge
  141. return true, nil
  142. } else if slotState.Forger == forger && slotState.BidAmount.Cmp(minBid) >= 0 {
  143. // if forger bidAmount has exceeded the minBid it can forge
  144. return true, nil
  145. } else if a.Vars.BootCoordinator == forger && slotState.BidAmount.Cmp(minBid) == -1 {
  146. // if it's the boot coordinator and it has not been bid or the bid is below the minimum it can forge
  147. return true, nil
  148. } else {
  149. return false, nil
  150. }
  151. }
  152. // EthereumBlock stores all the generic data related to the an ethereum block
  153. type EthereumBlock struct {
  154. BlockNum int64
  155. Time int64
  156. Hash ethCommon.Hash
  157. ParentHash ethCommon.Hash
  158. // state ethState
  159. }
  160. // Block represents a ethereum block
  161. type Block struct {
  162. Rollup *RollupBlock
  163. Auction *AuctionBlock
  164. Eth *EthereumBlock
  165. }
  166. func (b *Block) copy() *Block {
  167. bCopyRaw, err := copystructure.Copy(b)
  168. if err != nil {
  169. panic(err)
  170. }
  171. bCopy := bCopyRaw.(*Block)
  172. return bCopy
  173. }
  174. // Next prepares the successive block.
  175. func (b *Block) Next() *Block {
  176. blockNext := b.copy()
  177. blockNext.Rollup.Events = eth.NewRollupEvents()
  178. blockNext.Auction.Events = eth.NewAuctionEvents()
  179. blockNext.Eth = &EthereumBlock{
  180. BlockNum: b.Eth.BlockNum + 1,
  181. ParentHash: b.Eth.Hash,
  182. }
  183. blockNext.Rollup.Constants = b.Rollup.Constants
  184. blockNext.Auction.Constants = b.Auction.Constants
  185. blockNext.Rollup.Eth = blockNext.Eth
  186. blockNext.Auction.Eth = blockNext.Eth
  187. return blockNext
  188. }
  189. // ClientSetup is used to initialize the constants of the Smart Contracts and
  190. // other details of the test Client
  191. type ClientSetup struct {
  192. RollupConstants *eth.RollupConstants
  193. RollupVariables *eth.RollupVariables
  194. AuctionConstants *eth.AuctionConstants
  195. AuctionVariables *eth.AuctionVariables
  196. VerifyProof bool
  197. }
  198. // NewClientSetupExample returns a ClientSetup example with hardcoded realistic values.
  199. //nolint:gomnd
  200. func NewClientSetupExample() *ClientSetup {
  201. rfield, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
  202. if !ok {
  203. panic("bad rfield")
  204. }
  205. initialMinimalBidding, ok := new(big.Int).SetString("10000000000000000000", 10) // 10 * (1e18)
  206. if !ok {
  207. panic("bad initialMinimalBidding")
  208. }
  209. tokenHEZ := ethCommon.HexToAddress("0x51D243D62852Bba334DD5cc33f242BAc8c698074")
  210. governanceAddress := ethCommon.HexToAddress("0x688EfD95BA4391f93717CF02A9aED9DBD2855cDd")
  211. rollupConstants := &eth.RollupConstants{
  212. MaxAmountDeposit: new(big.Int).Lsh(big.NewInt(1), 128),
  213. MaxAmountL2: new(big.Int).Lsh(big.NewInt(1), 192),
  214. MaxTokens: 0xffffffff,
  215. MaxL1Tx: 256,
  216. MaxL1UserTx: 128,
  217. Rfield: rfield,
  218. L1CoordinatorBytes: 101,
  219. L1UserBytes: 68,
  220. L2Bytes: 11,
  221. MaxTxVerifiers: []int{512, 1024, 2048},
  222. TokenHEZ: tokenHEZ,
  223. GovernanceAddress: governanceAddress,
  224. SafetyBot: ethCommon.HexToAddress("0x84d8B79E84fe87B14ad61A554e740f6736bF4c20"),
  225. ConsensusContract: ethCommon.HexToAddress("0x8E442975805fb1908f43050c9C1A522cB0e28D7b"),
  226. WithdrawalContract: ethCommon.HexToAddress("0x5CB7979cBdbf65719BEE92e4D15b7b7Ed3D79114"),
  227. }
  228. rollupVariables := &eth.RollupVariables{
  229. FeeAddToken: big.NewInt(11),
  230. ForgeL1Timeout: 9,
  231. }
  232. auctionConstants := &eth.AuctionConstants{
  233. BlocksPerSlot: 40,
  234. InitialMinimalBidding: initialMinimalBidding,
  235. GenesisBlockNum: 0,
  236. GovernanceAddress: governanceAddress,
  237. TokenHEZ: tokenHEZ,
  238. HermezRollup: ethCommon.HexToAddress("0x474B6e29852257491cf283EfB1A9C61eBFe48369"),
  239. }
  240. auctionVariables := &eth.AuctionVariables{
  241. DonationAddress: ethCommon.HexToAddress("0x61Ed87CF0A1496b49A420DA6D84B58196b98f2e7"),
  242. BootCoordinator: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
  243. DefaultSlotSetBid: [6]*big.Int{
  244. big.NewInt(1000), big.NewInt(1100), big.NewInt(1200),
  245. big.NewInt(1300), big.NewInt(1400), big.NewInt(1500)},
  246. ClosedAuctionSlots: 2,
  247. OpenAuctionSlots: 4320,
  248. AllocationRatio: [3]uint16{4000, 4000, 2000},
  249. Outbidding: 1000,
  250. SlotDeadline: 20,
  251. }
  252. return &ClientSetup{
  253. RollupConstants: rollupConstants,
  254. RollupVariables: rollupVariables,
  255. AuctionConstants: auctionConstants,
  256. AuctionVariables: auctionVariables,
  257. }
  258. }
  259. // Timer is an interface to simulate a source of time, useful to advance time
  260. // virtually.
  261. type Timer interface {
  262. Time() int64
  263. }
  264. // type forgeBatchArgs struct {
  265. // ethTx *types.Transaction
  266. // blockNum int64
  267. // blockHash ethCommon.Hash
  268. // }
  269. // Client implements the eth.ClientInterface interface, allowing to manipulate the
  270. // values for testing, working with deterministic results.
  271. type Client struct {
  272. rw *sync.RWMutex
  273. log bool
  274. addr *ethCommon.Address
  275. rollupConstants *eth.RollupConstants
  276. auctionConstants *eth.AuctionConstants
  277. blocks map[int64]*Block
  278. // state state
  279. blockNum int64 // last mined block num
  280. maxBlockNum int64 // highest block num calculated
  281. timer Timer
  282. hasher hasher
  283. forgeBatchArgsPending map[ethCommon.Hash]*eth.RollupForgeBatchArgs
  284. forgeBatchArgs map[ethCommon.Hash]*eth.RollupForgeBatchArgs
  285. }
  286. // NewClient returns a new test Client that implements the eth.IClient
  287. // interface, at the given initialBlockNumber.
  288. func NewClient(l bool, timer Timer, addr *ethCommon.Address, setup *ClientSetup) *Client {
  289. blocks := make(map[int64]*Block)
  290. blockNum := int64(0)
  291. hasher := hasher{}
  292. // Add ethereum genesis block
  293. mapL1TxQueue := make(map[int64]*eth.QueueStruct)
  294. mapL1TxQueue[0] = eth.NewQueueStruct()
  295. mapL1TxQueue[1] = eth.NewQueueStruct()
  296. blockCurrent := Block{
  297. Rollup: &RollupBlock{
  298. State: eth.RollupState{
  299. StateRoot: big.NewInt(0),
  300. ExitRoots: make([]*big.Int, 0),
  301. ExitNullifierMap: make(map[[256 / 8]byte]bool),
  302. TokenList: make([]ethCommon.Address, 0),
  303. TokenMap: make(map[ethCommon.Address]bool),
  304. MapL1TxQueue: mapL1TxQueue,
  305. LastL1L2Batch: 0,
  306. CurrentToForgeL1TxsNum: 0,
  307. LastToForgeL1TxsNum: 1,
  308. CurrentIdx: 0,
  309. },
  310. Vars: *setup.RollupVariables,
  311. Txs: make(map[ethCommon.Hash]*types.Transaction),
  312. Events: eth.NewRollupEvents(),
  313. Constants: setup.RollupConstants,
  314. },
  315. Auction: &AuctionBlock{
  316. State: eth.AuctionState{
  317. Slots: make(map[int64]*eth.SlotState),
  318. PendingBalances: make(map[ethCommon.Address]*big.Int),
  319. Coordinators: make(map[ethCommon.Address]*eth.Coordinator),
  320. },
  321. Vars: *setup.AuctionVariables,
  322. Txs: make(map[ethCommon.Hash]*types.Transaction),
  323. Events: eth.NewAuctionEvents(),
  324. Constants: setup.AuctionConstants,
  325. },
  326. Eth: &EthereumBlock{
  327. BlockNum: blockNum,
  328. Time: timer.Time(),
  329. Hash: hasher.Next(),
  330. ParentHash: ethCommon.Hash{},
  331. },
  332. }
  333. blockCurrent.Rollup.Eth = blockCurrent.Eth
  334. blockCurrent.Auction.Eth = blockCurrent.Eth
  335. blocks[blockNum] = &blockCurrent
  336. blockNext := blockCurrent.Next()
  337. blocks[blockNum+1] = blockNext
  338. return &Client{
  339. rw: &sync.RWMutex{},
  340. log: l,
  341. addr: addr,
  342. rollupConstants: setup.RollupConstants,
  343. auctionConstants: setup.AuctionConstants,
  344. blocks: blocks,
  345. timer: timer,
  346. hasher: hasher,
  347. forgeBatchArgsPending: make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs),
  348. forgeBatchArgs: make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs),
  349. }
  350. }
  351. //
  352. // Mock Control
  353. //
  354. func (c *Client) setNextBlock(block *Block) {
  355. c.blocks[c.blockNum+1] = block
  356. }
  357. func (c *Client) revertIfErr(err error, block *Block) {
  358. if err != nil {
  359. log.Infow("TestClient revert", "block", block.Eth.BlockNum, "err", err)
  360. c.setNextBlock(block)
  361. }
  362. }
  363. // Debugf calls log.Debugf if c.log is true
  364. func (c *Client) Debugf(template string, args ...interface{}) {
  365. if c.log {
  366. log.Debugf(template, args...)
  367. }
  368. }
  369. // Debugw calls log.Debugw if c.log is true
  370. func (c *Client) Debugw(template string, kv ...interface{}) {
  371. if c.log {
  372. log.Debugw(template, kv...)
  373. }
  374. }
  375. type hasher struct {
  376. counter uint64
  377. }
  378. // Next returns the next hash
  379. func (h *hasher) Next() ethCommon.Hash {
  380. var hash ethCommon.Hash
  381. binary.LittleEndian.PutUint64(hash[:], h.counter)
  382. h.counter++
  383. return hash
  384. }
  385. func (c *Client) nextBlock() *Block {
  386. return c.blocks[c.blockNum+1]
  387. }
  388. func (c *Client) currentBlock() *Block {
  389. return c.blocks[c.blockNum]
  390. }
  391. // CtlMineBlock moves one block forward
  392. func (c *Client) CtlMineBlock() {
  393. c.rw.Lock()
  394. defer c.rw.Unlock()
  395. blockCurrent := c.nextBlock()
  396. c.blockNum++
  397. c.maxBlockNum = c.blockNum
  398. blockCurrent.Eth.Time = c.timer.Time()
  399. blockCurrent.Eth.Hash = c.hasher.Next()
  400. for ethTxHash, forgeBatchArgs := range c.forgeBatchArgsPending {
  401. c.forgeBatchArgs[ethTxHash] = forgeBatchArgs
  402. }
  403. c.forgeBatchArgsPending = make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs)
  404. blockNext := blockCurrent.Next()
  405. c.blocks[c.blockNum+1] = blockNext
  406. c.Debugw("TestClient mined block", "blockNum", c.blockNum)
  407. }
  408. // CtlRollback discards the last mined block. Use this to replace a mined
  409. // block to simulate reorgs.
  410. func (c *Client) CtlRollback() {
  411. c.rw.Lock()
  412. defer c.rw.Unlock()
  413. if c.blockNum == 0 {
  414. panic("Can't rollback at blockNum = 0")
  415. }
  416. delete(c.blocks, c.blockNum+1) // delete next block
  417. delete(c.blocks, c.blockNum) // delete current block
  418. c.blockNum--
  419. blockCurrent := c.blocks[c.blockNum]
  420. blockNext := blockCurrent.Next()
  421. c.blocks[c.blockNum+1] = blockNext
  422. }
  423. //
  424. // Ethereum
  425. //
  426. // EthCurrentBlock returns the current blockNum
  427. func (c *Client) EthCurrentBlock() (int64, error) {
  428. c.rw.RLock()
  429. defer c.rw.RUnlock()
  430. if c.blockNum < c.maxBlockNum {
  431. panic("blockNum has decreased. " +
  432. "After a rollback you must mine to reach the same or higher blockNum")
  433. }
  434. return c.blockNum, nil
  435. }
  436. // EthTransactionReceipt returns the transaction receipt of the given txHash
  437. func (c *Client) EthTransactionReceipt(ctx context.Context, txHash ethCommon.Hash) (*types.Receipt, error) {
  438. c.rw.RLock()
  439. defer c.rw.RUnlock()
  440. for i := int64(0); i < c.blockNum; i++ {
  441. b := c.blocks[i]
  442. _, ok := b.Rollup.Txs[txHash]
  443. if !ok {
  444. _, ok = b.Auction.Txs[txHash]
  445. }
  446. if ok {
  447. return &types.Receipt{
  448. TxHash: txHash,
  449. Status: types.ReceiptStatusSuccessful,
  450. BlockHash: b.Eth.Hash,
  451. BlockNumber: big.NewInt(b.Eth.BlockNum),
  452. }, nil
  453. }
  454. }
  455. return nil, nil
  456. }
  457. // func newHeader(number *big.Int) *types.Header {
  458. // return &types.Header{
  459. // Number: number,
  460. // Time: uint64(number.Int64()),
  461. // }
  462. // }
  463. // EthHeaderByNumber returns the *types.Header for the given block number in a
  464. // deterministic way.
  465. // func (c *Client) EthHeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
  466. // return newHeader(number), nil
  467. // }
  468. // EthBlockByNumber returns the *common.Block for the given block number in a
  469. // deterministic way.
  470. func (c *Client) EthBlockByNumber(ctx context.Context, blockNum int64) (*common.Block, error) {
  471. c.rw.RLock()
  472. defer c.rw.RUnlock()
  473. block, ok := c.blocks[blockNum]
  474. if !ok {
  475. return nil, fmt.Errorf("block not found")
  476. }
  477. return &common.Block{
  478. EthBlockNum: blockNum,
  479. Timestamp: time.Unix(block.Eth.Time, 0),
  480. Hash: block.Eth.Hash,
  481. ParentHash: block.Eth.ParentHash,
  482. }, nil
  483. }
  484. // EthAddress returns the ethereum address of the account loaded into the Client
  485. func (c *Client) EthAddress() (*ethCommon.Address, error) {
  486. if c.addr == nil {
  487. return nil, eth.ErrAccountNil
  488. }
  489. return c.addr, nil
  490. }
  491. var errTODO = fmt.Errorf("TODO: Not implemented yet")
  492. //
  493. // Rollup
  494. //
  495. // CtlAddL1TxUser adds an L1TxUser to the L1UserTxs queue of the Rollup
  496. func (c *Client) CtlAddL1TxUser(l1Tx *common.L1Tx) {
  497. c.rw.Lock()
  498. defer c.rw.Unlock()
  499. nextBlock := c.nextBlock()
  500. r := nextBlock.Rollup
  501. queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  502. if len(queue.L1TxQueue) >= c.rollupConstants.MaxL1UserTx {
  503. r.State.LastToForgeL1TxsNum++
  504. r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
  505. queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  506. }
  507. if int64(l1Tx.FromIdx) > r.State.CurrentIdx {
  508. panic("l1Tx.FromIdx > r.State.CurrentIdx")
  509. }
  510. if int(l1Tx.TokenID)+1 > len(r.State.TokenList) {
  511. panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
  512. }
  513. queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
  514. r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{L1Tx: *l1Tx})
  515. }
  516. type transactionData struct {
  517. Name string
  518. Value interface{}
  519. }
  520. func newTransaction(name string, value interface{}) *types.Transaction {
  521. data, err := json.Marshal(transactionData{name, value})
  522. if err != nil {
  523. panic(err)
  524. }
  525. return types.NewTransaction(0, ethCommon.Address{}, nil, 0, nil,
  526. data)
  527. }
  528. // RollupForgeBatch is the interface to call the smart contract function
  529. func (c *Client) RollupForgeBatch(args *eth.RollupForgeBatchArgs) (tx *types.Transaction, err error) {
  530. c.rw.Lock()
  531. defer c.rw.Unlock()
  532. cpy := c.nextBlock().copy()
  533. defer func() { c.revertIfErr(err, cpy) }()
  534. if c.addr == nil {
  535. return nil, eth.ErrAccountNil
  536. }
  537. a := c.nextBlock().Auction
  538. ok, err := a.canForge(*c.addr, a.Eth.BlockNum)
  539. if err != nil {
  540. return nil, err
  541. }
  542. if !ok {
  543. return nil, fmt.Errorf("incorrect slot")
  544. }
  545. // TODO: Verify proof
  546. // Auction
  547. err = a.forge(*c.addr)
  548. if err != nil {
  549. return nil, err
  550. }
  551. // TODO: If successful, store the tx in a successful array.
  552. // TODO: If failed, store the tx in a failed array.
  553. // TODO: Add method to move the tx to another block, reapply it there, and possibly go from successful to failed.
  554. return c.addBatch(args)
  555. }
  556. // CtlAddBatch adds forged batch to the Rollup, without checking any ZKProof
  557. func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
  558. c.rw.Lock()
  559. defer c.rw.Unlock()
  560. if _, err := c.addBatch(args); err != nil {
  561. panic(err)
  562. }
  563. }
  564. func (c *Client) addBatch(args *eth.RollupForgeBatchArgs) (*types.Transaction, error) {
  565. nextBlock := c.nextBlock()
  566. r := nextBlock.Rollup
  567. r.State.StateRoot = args.NewStRoot
  568. if args.NewLastIdx < r.State.CurrentIdx {
  569. return nil, fmt.Errorf("args.NewLastIdx < r.State.CurrentIdx")
  570. }
  571. r.State.CurrentIdx = args.NewLastIdx
  572. r.State.ExitRoots = append(r.State.ExitRoots, args.NewExitRoot)
  573. if args.L1Batch {
  574. r.State.CurrentToForgeL1TxsNum++
  575. if r.State.CurrentToForgeL1TxsNum == r.State.LastToForgeL1TxsNum {
  576. r.State.LastToForgeL1TxsNum++
  577. r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
  578. }
  579. }
  580. ethTx := r.addTransaction(newTransaction("forgebatch", args))
  581. c.forgeBatchArgsPending[ethTx.Hash()] = args
  582. r.Events.ForgeBatch = append(r.Events.ForgeBatch, eth.RollupEventForgeBatch{
  583. BatchNum: int64(len(r.State.ExitRoots)),
  584. EthTxHash: ethTx.Hash(),
  585. })
  586. return ethTx, nil
  587. }
  588. // RollupAddToken is the interface to call the smart contract function
  589. func (c *Client) RollupAddToken(tokenAddress ethCommon.Address) (tx *types.Transaction, err error) {
  590. c.rw.Lock()
  591. defer c.rw.Unlock()
  592. cpy := c.nextBlock().copy()
  593. defer func() { c.revertIfErr(err, cpy) }()
  594. if c.addr == nil {
  595. return nil, eth.ErrAccountNil
  596. }
  597. nextBlock := c.nextBlock()
  598. r := nextBlock.Rollup
  599. if _, ok := r.State.TokenMap[tokenAddress]; ok {
  600. return nil, fmt.Errorf("Token %v already registered", tokenAddress)
  601. }
  602. r.State.TokenMap[tokenAddress] = true
  603. r.State.TokenList = append(r.State.TokenList, tokenAddress)
  604. r.Events.AddToken = append(r.Events.AddToken, eth.RollupEventAddToken{Address: tokenAddress,
  605. TokenID: uint32(len(r.State.TokenList) - 1)})
  606. return r.addTransaction(newTransaction("addtoken", tokenAddress)), nil
  607. }
  608. // RollupWithdrawSNARK is the interface to call the smart contract function
  609. // func (c *Client) RollupWithdrawSNARK() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
  610. // return nil, errTODO
  611. // }
  612. // RollupWithdraw is the interface to call the smart contract function
  613. func (c *Client) RollupWithdraw(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey, numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (tx *types.Transaction, err error) {
  614. c.rw.Lock()
  615. defer c.rw.Unlock()
  616. cpy := c.nextBlock().copy()
  617. defer func() { c.revertIfErr(err, cpy) }()
  618. if c.addr == nil {
  619. return nil, eth.ErrAccountNil
  620. }
  621. log.Error("TODO")
  622. return nil, errTODO
  623. }
  624. // RollupForceExit is the interface to call the smart contract function
  625. func (c *Client) RollupForceExit(fromIdx int64, amountF common.Float16, tokenID int64) (tx *types.Transaction, err error) {
  626. c.rw.Lock()
  627. defer c.rw.Unlock()
  628. cpy := c.nextBlock().copy()
  629. defer func() { c.revertIfErr(err, cpy) }()
  630. if c.addr == nil {
  631. return nil, eth.ErrAccountNil
  632. }
  633. log.Error("TODO")
  634. return nil, errTODO
  635. }
  636. // RollupForceTransfer is the interface to call the smart contract function
  637. func (c *Client) RollupForceTransfer(fromIdx int64, amountF common.Float16, tokenID, toIdx int64) (tx *types.Transaction, err error) {
  638. c.rw.Lock()
  639. defer c.rw.Unlock()
  640. cpy := c.nextBlock().copy()
  641. defer func() { c.revertIfErr(err, cpy) }()
  642. if c.addr == nil {
  643. return nil, eth.ErrAccountNil
  644. }
  645. log.Error("TODO")
  646. return nil, errTODO
  647. }
  648. // RollupCreateAccountDepositTransfer is the interface to call the smart contract function
  649. func (c *Client) RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (tx *types.Transaction, err error) {
  650. c.rw.Lock()
  651. defer c.rw.Unlock()
  652. cpy := c.nextBlock().copy()
  653. defer func() { c.revertIfErr(err, cpy) }()
  654. if c.addr == nil {
  655. return nil, eth.ErrAccountNil
  656. }
  657. log.Error("TODO")
  658. return nil, errTODO
  659. }
  660. // RollupGetCurrentTokens is the interface to call the smart contract function
  661. func (c *Client) RollupGetCurrentTokens() (*big.Int, error) {
  662. c.rw.RLock()
  663. defer c.rw.RUnlock()
  664. log.Error("TODO")
  665. return nil, errTODO
  666. }
  667. // RollupDepositTransfer is the interface to call the smart contract function
  668. func (c *Client) RollupDepositTransfer(fromIdx int64, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (tx *types.Transaction, err error) {
  669. c.rw.Lock()
  670. defer c.rw.Unlock()
  671. cpy := c.nextBlock().copy()
  672. defer func() { c.revertIfErr(err, cpy) }()
  673. if c.addr == nil {
  674. return nil, eth.ErrAccountNil
  675. }
  676. log.Error("TODO")
  677. return nil, errTODO
  678. }
  679. // RollupDeposit is the interface to call the smart contract function
  680. func (c *Client) RollupDeposit(fromIdx int64, loadAmountF common.Float16, tokenID int64) (tx *types.Transaction, err error) {
  681. c.rw.Lock()
  682. defer c.rw.Unlock()
  683. cpy := c.nextBlock().copy()
  684. defer func() { c.revertIfErr(err, cpy) }()
  685. if c.addr == nil {
  686. return nil, eth.ErrAccountNil
  687. }
  688. log.Error("TODO")
  689. return nil, errTODO
  690. }
  691. // RollupCreateAccountDepositFromRelayer is the interface to call the smart contract function
  692. func (c *Client) RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte, babyPubKey babyjub.PublicKey, loadAmountF common.Float16) (tx *types.Transaction, err error) {
  693. c.rw.Lock()
  694. defer c.rw.Unlock()
  695. cpy := c.nextBlock().copy()
  696. defer func() { c.revertIfErr(err, cpy) }()
  697. if c.addr == nil {
  698. return nil, eth.ErrAccountNil
  699. }
  700. log.Error("TODO")
  701. return nil, errTODO
  702. }
  703. // RollupCreateAccountDeposit is the interface to call the smart contract function
  704. func (c *Client) RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF common.Float16, tokenID int64) (tx *types.Transaction, err error) {
  705. c.rw.Lock()
  706. defer c.rw.Unlock()
  707. cpy := c.nextBlock().copy()
  708. defer func() { c.revertIfErr(err, cpy) }()
  709. if c.addr == nil {
  710. return nil, eth.ErrAccountNil
  711. }
  712. log.Error("TODO")
  713. return nil, errTODO
  714. }
  715. // RollupGetTokenAddress is the interface to call the smart contract function
  716. // func (c *Client) RollupGetTokenAddress(tokenID int64) (*ethCommon.Address, error) {
  717. // c.rw.RLock()
  718. // defer c.rw.RUnlock()
  719. //
  720. // log.Error("TODO")
  721. // return nil, errTODO
  722. // }
  723. // RollupGetL1TxFromQueue is the interface to call the smart contract function
  724. // func (c *Client) RollupGetL1TxFromQueue(queue int64, position int64) ([]byte, error) {
  725. // c.rw.RLock()
  726. // defer c.rw.RUnlock()
  727. //
  728. // log.Error("TODO")
  729. // return nil, errTODO
  730. // }
  731. // RollupGetQueue is the interface to call the smart contract function
  732. // func (c *Client) RollupGetQueue(queue int64) ([]byte, error) {
  733. // c.rw.RLock()
  734. // defer c.rw.RUnlock()
  735. //
  736. // log.Error("TODO")
  737. // return nil, errTODO
  738. // }
  739. // RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
  740. func (c *Client) RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (tx *types.Transaction, err error) {
  741. c.rw.Lock()
  742. defer c.rw.Unlock()
  743. cpy := c.nextBlock().copy()
  744. defer func() { c.revertIfErr(err, cpy) }()
  745. if c.addr == nil {
  746. return nil, eth.ErrAccountNil
  747. }
  748. log.Error("TODO")
  749. return nil, errTODO
  750. }
  751. // RollupUpdateFeeAddToken is the interface to call the smart contract function
  752. func (c *Client) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction, err error) {
  753. c.rw.Lock()
  754. defer c.rw.Unlock()
  755. cpy := c.nextBlock().copy()
  756. defer func() { c.revertIfErr(err, cpy) }()
  757. if c.addr == nil {
  758. return nil, eth.ErrAccountNil
  759. }
  760. log.Error("TODO")
  761. return nil, errTODO
  762. }
  763. // RollupUpdateTokensHEZ is the interface to call the smart contract function
  764. // func (c *Client) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (tx *types.Transaction, err error) {
  765. // c.rw.Lock()
  766. // defer c.rw.Unlock()
  767. // cpy := c.nextBlock().copy()
  768. // defer func() { c.revertIfErr(err, cpy) }()
  769. //
  770. // log.Error("TODO")
  771. // return nil, errTODO
  772. // }
  773. // RollupUpdateGovernance is the interface to call the smart contract function
  774. // func (c *Client) RollupUpdateGovernance() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
  775. // return nil, errTODO
  776. // }
  777. // RollupConstants returns the Constants of the Rollup Smart Contract
  778. func (c *Client) RollupConstants() (*eth.RollupConstants, error) {
  779. c.rw.RLock()
  780. defer c.rw.RUnlock()
  781. log.Error("TODO")
  782. return nil, errTODO
  783. }
  784. // RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
  785. func (c *Client) RollupEventsByBlock(blockNum int64) (*eth.RollupEvents, *ethCommon.Hash, error) {
  786. c.rw.RLock()
  787. defer c.rw.RUnlock()
  788. block, ok := c.blocks[blockNum]
  789. if !ok {
  790. return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
  791. }
  792. return &block.Rollup.Events, &block.Eth.Hash, nil
  793. }
  794. // RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
  795. func (c *Client) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*eth.RollupForgeBatchArgs, error) {
  796. c.rw.RLock()
  797. defer c.rw.RUnlock()
  798. forgeBatchArgs, ok := c.forgeBatchArgs[ethTxHash]
  799. if !ok {
  800. return nil, fmt.Errorf("transaction not found")
  801. }
  802. return forgeBatchArgs, nil
  803. }
  804. //
  805. // Auction
  806. //
  807. // AuctionSetSlotDeadline is the interface to call the smart contract function
  808. func (c *Client) AuctionSetSlotDeadline(newDeadline uint8) (tx *types.Transaction, err error) {
  809. c.rw.Lock()
  810. defer c.rw.Unlock()
  811. cpy := c.nextBlock().copy()
  812. defer func() { c.revertIfErr(err, cpy) }()
  813. if c.addr == nil {
  814. return nil, eth.ErrAccountNil
  815. }
  816. log.Error("TODO")
  817. return nil, errTODO
  818. }
  819. // AuctionGetSlotDeadline is the interface to call the smart contract function
  820. func (c *Client) AuctionGetSlotDeadline() (uint8, error) {
  821. c.rw.RLock()
  822. defer c.rw.RUnlock()
  823. log.Error("TODO")
  824. return 0, errTODO
  825. }
  826. // AuctionSetOpenAuctionSlots is the interface to call the smart contract function
  827. func (c *Client) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
  828. c.rw.Lock()
  829. defer c.rw.Unlock()
  830. cpy := c.nextBlock().copy()
  831. defer func() { c.revertIfErr(err, cpy) }()
  832. if c.addr == nil {
  833. return nil, eth.ErrAccountNil
  834. }
  835. log.Error("TODO")
  836. return nil, errTODO
  837. }
  838. // AuctionGetOpenAuctionSlots is the interface to call the smart contract function
  839. func (c *Client) AuctionGetOpenAuctionSlots() (uint16, error) {
  840. c.rw.RLock()
  841. defer c.rw.RUnlock()
  842. log.Error("TODO")
  843. return 0, errTODO
  844. }
  845. // AuctionSetClosedAuctionSlots is the interface to call the smart contract function
  846. func (c *Client) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
  847. c.rw.Lock()
  848. defer c.rw.Unlock()
  849. cpy := c.nextBlock().copy()
  850. defer func() { c.revertIfErr(err, cpy) }()
  851. if c.addr == nil {
  852. return nil, eth.ErrAccountNil
  853. }
  854. log.Error("TODO")
  855. return nil, errTODO
  856. }
  857. // AuctionGetClosedAuctionSlots is the interface to call the smart contract function
  858. func (c *Client) AuctionGetClosedAuctionSlots() (uint16, error) {
  859. c.rw.RLock()
  860. defer c.rw.RUnlock()
  861. log.Error("TODO")
  862. return 0, errTODO
  863. }
  864. // AuctionSetOutbidding is the interface to call the smart contract function
  865. func (c *Client) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
  866. c.rw.Lock()
  867. defer c.rw.Unlock()
  868. cpy := c.nextBlock().copy()
  869. defer func() { c.revertIfErr(err, cpy) }()
  870. if c.addr == nil {
  871. return nil, eth.ErrAccountNil
  872. }
  873. log.Error("TODO")
  874. return nil, errTODO
  875. }
  876. // AuctionGetOutbidding is the interface to call the smart contract function
  877. func (c *Client) AuctionGetOutbidding() (uint16, error) {
  878. c.rw.RLock()
  879. defer c.rw.RUnlock()
  880. log.Error("TODO")
  881. return 0, errTODO
  882. }
  883. // AuctionSetAllocationRatio is the interface to call the smart contract function
  884. func (c *Client) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
  885. c.rw.Lock()
  886. defer c.rw.Unlock()
  887. cpy := c.nextBlock().copy()
  888. defer func() { c.revertIfErr(err, cpy) }()
  889. if c.addr == nil {
  890. return nil, eth.ErrAccountNil
  891. }
  892. log.Error("TODO")
  893. return nil, errTODO
  894. }
  895. // AuctionGetAllocationRatio is the interface to call the smart contract function
  896. func (c *Client) AuctionGetAllocationRatio() ([3]uint16, error) {
  897. c.rw.RLock()
  898. defer c.rw.RUnlock()
  899. log.Error("TODO")
  900. return [3]uint16{}, errTODO
  901. }
  902. // AuctionSetDonationAddress is the interface to call the smart contract function
  903. func (c *Client) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
  904. c.rw.Lock()
  905. defer c.rw.Unlock()
  906. cpy := c.nextBlock().copy()
  907. defer func() { c.revertIfErr(err, cpy) }()
  908. if c.addr == nil {
  909. return nil, eth.ErrAccountNil
  910. }
  911. log.Error("TODO")
  912. return nil, errTODO
  913. }
  914. // AuctionGetDonationAddress is the interface to call the smart contract function
  915. func (c *Client) AuctionGetDonationAddress() (*ethCommon.Address, error) {
  916. c.rw.RLock()
  917. defer c.rw.RUnlock()
  918. log.Error("TODO")
  919. return nil, errTODO
  920. }
  921. // AuctionSetBootCoordinator is the interface to call the smart contract function
  922. func (c *Client) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (tx *types.Transaction, err error) {
  923. c.rw.Lock()
  924. defer c.rw.Unlock()
  925. cpy := c.nextBlock().copy()
  926. defer func() { c.revertIfErr(err, cpy) }()
  927. if c.addr == nil {
  928. return nil, eth.ErrAccountNil
  929. }
  930. log.Error("TODO")
  931. return nil, errTODO
  932. }
  933. // AuctionGetBootCoordinator is the interface to call the smart contract function
  934. func (c *Client) AuctionGetBootCoordinator() (*ethCommon.Address, error) {
  935. c.rw.RLock()
  936. defer c.rw.RUnlock()
  937. currentBlock := c.currentBlock()
  938. a := currentBlock.Auction
  939. return &a.Vars.BootCoordinator, nil
  940. }
  941. // AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
  942. func (c *Client) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
  943. c.rw.Lock()
  944. defer c.rw.Unlock()
  945. cpy := c.nextBlock().copy()
  946. defer func() { c.revertIfErr(err, cpy) }()
  947. if c.addr == nil {
  948. return nil, eth.ErrAccountNil
  949. }
  950. log.Error("TODO")
  951. return nil, errTODO
  952. }
  953. // AuctionRegisterCoordinator is the interface to call the smart contract function
  954. func (c *Client) AuctionRegisterCoordinator(forgerAddress ethCommon.Address, URL string) (tx *types.Transaction, err error) {
  955. c.rw.Lock()
  956. defer c.rw.Unlock()
  957. cpy := c.nextBlock().copy()
  958. defer func() { c.revertIfErr(err, cpy) }()
  959. if c.addr == nil {
  960. return nil, eth.ErrAccountNil
  961. }
  962. nextBlock := c.nextBlock()
  963. a := nextBlock.Auction
  964. if _, ok := a.State.Coordinators[forgerAddress]; ok {
  965. return nil, fmt.Errorf("Already registered")
  966. }
  967. a.State.Coordinators[forgerAddress] = &eth.Coordinator{
  968. WithdrawalAddress: *c.addr,
  969. URL: URL,
  970. }
  971. a.Events.NewCoordinator = append(a.Events.NewCoordinator,
  972. eth.AuctionEventNewCoordinator{
  973. ForgerAddress: forgerAddress,
  974. WithdrawalAddress: *c.addr,
  975. CoordinatorURL: URL,
  976. })
  977. type data struct {
  978. ForgerAddress ethCommon.Address
  979. URL string
  980. }
  981. return a.addTransaction(newTransaction("registercoordinator", data{forgerAddress, URL})), nil
  982. }
  983. // AuctionIsRegisteredCoordinator is the interface to call the smart contract function
  984. func (c *Client) AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address) (bool, error) {
  985. c.rw.RLock()
  986. defer c.rw.RUnlock()
  987. log.Error("TODO")
  988. return false, errTODO
  989. }
  990. // AuctionUpdateCoordinatorInfo is the interface to call the smart contract function
  991. func (c *Client) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (tx *types.Transaction, err error) {
  992. c.rw.Lock()
  993. defer c.rw.Unlock()
  994. cpy := c.nextBlock().copy()
  995. defer func() { c.revertIfErr(err, cpy) }()
  996. if c.addr == nil {
  997. return nil, eth.ErrAccountNil
  998. }
  999. log.Error("TODO")
  1000. return nil, errTODO
  1001. }
  1002. // AuctionGetSlotNumber is the interface to call the smart contract function
  1003. func (c *Client) AuctionGetSlotNumber(blockNum int64) (int64, error) {
  1004. c.rw.RLock()
  1005. defer c.rw.RUnlock()
  1006. currentBlock := c.currentBlock()
  1007. a := currentBlock.Auction
  1008. return a.getSlotNumber(blockNum), nil
  1009. }
  1010. // AuctionGetCurrentSlotNumber is the interface to call the smart contract function
  1011. func (c *Client) AuctionGetCurrentSlotNumber() (int64, error) {
  1012. c.rw.RLock()
  1013. defer c.rw.RUnlock()
  1014. log.Error("TODO")
  1015. return 0, errTODO
  1016. }
  1017. // AuctionGetMinBidBySlot is the interface to call the smart contract function
  1018. func (c *Client) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
  1019. c.rw.RLock()
  1020. defer c.rw.RUnlock()
  1021. log.Error("TODO")
  1022. return nil, errTODO
  1023. }
  1024. // AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
  1025. func (c *Client) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) {
  1026. c.rw.RLock()
  1027. defer c.rw.RUnlock()
  1028. log.Error("TODO")
  1029. return nil, errTODO
  1030. }
  1031. // AuctionGetSlotSet is the interface to call the smart contract function
  1032. func (c *Client) AuctionGetSlotSet(slot int64) (*big.Int, error) {
  1033. c.rw.RLock()
  1034. defer c.rw.RUnlock()
  1035. log.Error("TODO")
  1036. return nil, errTODO
  1037. }
  1038. // AuctionTokensReceived is the interface to call the smart contract function
  1039. // func (c *Client) AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int, userData, operatorData []byte) error {
  1040. // return errTODO
  1041. // }
  1042. // AuctionBid is the interface to call the smart contract function
  1043. func (c *Client) AuctionBid(slot int64, bidAmount *big.Int, forger ethCommon.Address) (tx *types.Transaction, err error) {
  1044. c.rw.Lock()
  1045. defer c.rw.Unlock()
  1046. cpy := c.nextBlock().copy()
  1047. defer func() { func() { c.revertIfErr(err, cpy) }() }()
  1048. if c.addr == nil {
  1049. return nil, eth.ErrAccountNil
  1050. }
  1051. nextBlock := c.nextBlock()
  1052. a := nextBlock.Auction
  1053. if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
  1054. return nil, errBidClosed
  1055. }
  1056. if slot >= a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots)+int64(a.Vars.OpenAuctionSlots) {
  1057. return nil, errBidNotOpen
  1058. }
  1059. minBid, err := a.getMinBidBySlot(slot)
  1060. if err != nil {
  1061. return nil, err
  1062. }
  1063. if bidAmount.Cmp(minBid) == -1 {
  1064. return nil, errBidBelowMin
  1065. }
  1066. if _, ok := a.State.Coordinators[forger]; !ok {
  1067. return nil, errCoordNotReg
  1068. }
  1069. slotState, ok := a.State.Slots[slot]
  1070. if !ok {
  1071. slotState = eth.NewSlotState()
  1072. a.State.Slots[slot] = slotState
  1073. }
  1074. slotState.Forger = forger
  1075. slotState.BidAmount = bidAmount
  1076. a.Events.NewBid = append(a.Events.NewBid,
  1077. eth.AuctionEventNewBid{Slot: slot, BidAmount: bidAmount, CoordinatorForger: forger})
  1078. type data struct {
  1079. Slot int64
  1080. BidAmount *big.Int
  1081. Forger ethCommon.Address
  1082. }
  1083. return a.addTransaction(newTransaction("bid", data{slot, bidAmount, forger})), nil
  1084. }
  1085. // AuctionMultiBid is the interface to call the smart contract function
  1086. func (c *Client) AuctionMultiBid(startingSlot int64, endingSlot int64, slotSet [6]bool, maxBid, closedMinBid, budget *big.Int, forger ethCommon.Address) (tx *types.Transaction, err error) {
  1087. c.rw.Lock()
  1088. defer c.rw.Unlock()
  1089. cpy := c.nextBlock().copy()
  1090. defer func() { c.revertIfErr(err, cpy) }()
  1091. if c.addr == nil {
  1092. return nil, eth.ErrAccountNil
  1093. }
  1094. log.Error("TODO")
  1095. return nil, errTODO
  1096. }
  1097. // AuctionCanForge is the interface to call the smart contract function
  1098. func (c *Client) AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error) {
  1099. c.rw.RLock()
  1100. defer c.rw.RUnlock()
  1101. currentBlock := c.currentBlock()
  1102. a := currentBlock.Auction
  1103. return a.canForge(forger, blockNum)
  1104. }
  1105. // AuctionForge is the interface to call the smart contract function
  1106. // func (c *Client) AuctionForge(forger ethCommon.Address) (bool, error) {
  1107. // return false, errTODO
  1108. // }
  1109. // AuctionClaimHEZ is the interface to call the smart contract function
  1110. func (c *Client) AuctionClaimHEZ(claimAddress ethCommon.Address) (tx *types.Transaction, err error) {
  1111. c.rw.Lock()
  1112. defer c.rw.Unlock()
  1113. cpy := c.nextBlock().copy()
  1114. defer func() { c.revertIfErr(err, cpy) }()
  1115. if c.addr == nil {
  1116. return nil, eth.ErrAccountNil
  1117. }
  1118. log.Error("TODO")
  1119. return nil, errTODO
  1120. }
  1121. // AuctionConstants returns the Constants of the Auction Smart Contract
  1122. func (c *Client) AuctionConstants() (*eth.AuctionConstants, error) {
  1123. c.rw.RLock()
  1124. defer c.rw.RUnlock()
  1125. return c.auctionConstants, nil
  1126. }
  1127. // AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract
  1128. func (c *Client) AuctionEventsByBlock(blockNum int64) (*eth.AuctionEvents, *ethCommon.Hash, error) {
  1129. c.rw.RLock()
  1130. defer c.rw.RUnlock()
  1131. block, ok := c.blocks[blockNum]
  1132. if !ok {
  1133. return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
  1134. }
  1135. return &block.Auction.Events, &block.Eth.Hash, nil
  1136. }