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