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) getEpoch(slot int64) int64 {
69 return slot % int64(len(a.Vars.MinBidEpoch))
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 epoch := a.getEpoch(slot)
78 var prevBid *big.Int
79 slotState, ok := a.State.Slots[slot]
80 // If the bidAmount for a slot is 0 it means that it has not yet been bid, so the midBid will be the minimum
81 // bid for the slot time plus the outbidding set, otherwise it will be the bidAmount plus the outbidding
82 if !ok || slotState.BidAmount.Cmp(big.NewInt(0)) == 0 {
83 prevBid = a.Vars.MinBidEpoch[epoch]
84 } else {
85 prevBid = slotState.BidAmount
86 }
87 outBid := new(big.Int).Set(prevBid)
88 outBid.Mul(outBid, big.NewInt(int64(a.Vars.Outbidding)))
89 outBid.Div(outBid, big.NewInt(100)) //nolint:gomnd
90 outBid.Add(prevBid, outBid)
91 return outBid, nil
92}
93
94// EthereumBlock stores all the generic data related to the an ethereum block
95type EthereumBlock struct {
96 BlockNum int64
97 Time int64
98 Hash ethCommon.Hash
99 ParentHash ethCommon.Hash
100 // state ethState
101}
102
103// Block represents a ethereum block
104type Block struct {
105 Rollup *RollupBlock
106 Auction *AuctionBlock
107 Eth *EthereumBlock
108}
109
110// Next prepares the successive block.
111func (b *Block) Next() *Block {
112 blockNextRaw, err := copystructure.Copy(b)
113 if err != nil {
114 panic(err)
115 }
116 blockNext := blockNextRaw.(*Block)
117 blockNext.Rollup.Events = eth.NewRollupEvents()
118 blockNext.Auction.Events = eth.NewAuctionEvents()
119 blockNext.Eth = &EthereumBlock{
120 BlockNum: b.Eth.BlockNum + 1,
121 ParentHash: b.Eth.Hash,
122 }
123 blockNext.Rollup.Constants = b.Rollup.Constants
124 blockNext.Auction.Constants = b.Auction.Constants
125 blockNext.Rollup.Eth = blockNext.Eth
126 blockNext.Auction.Eth = blockNext.Eth
127 return blockNext
128}
129
130// ClientSetup is used to initialize the constants of the Smart Contracts and
131// other details of the test Client
132type ClientSetup struct {
133 RollupConstants *eth.RollupConstants
134 RollupVariables *eth.RollupVariables
135 AuctionConstants *eth.AuctionConstants
136 AuctionVariables *eth.AuctionVariables
137 VerifyProof bool
138}
139
140// NewClientSetupExample returns a ClientSetup example with hardcoded realistic values.
141// TODO: Fill all values that are currently default.
142//nolint:gomnd
143func NewClientSetupExample() *ClientSetup {
144 rollupConstants := ð.RollupConstants{}
145 rollupVariables := ð.RollupVariables{
146 MaxTxVerifiers: make([]int, 0),
147 TokenHEZ: ethCommon.Address{},
148 GovernanceAddress: ethCommon.Address{},
149 SafetyBot: ethCommon.Address{},
150 ConsensusContract: ethCommon.Address{},
151 WithdrawalContract: ethCommon.Address{},
152 FeeAddToken: big.NewInt(1),
153 ForgeL1Timeout: 16,
154 FeeL1UserTx: big.NewInt(2),
155 }
156 auctionConstants := ð.AuctionConstants{
157 BlocksPerSlot: 40,
158 }
159 auctionVariables := ð.AuctionVariables{
160 DonationAddress: ethCommon.Address{},
161 BootCoordinator: ethCommon.Address{},
162 MinBidEpoch: [6]*big.Int{
163 big.NewInt(10), big.NewInt(11), big.NewInt(12),
164 big.NewInt(13), big.NewInt(14), big.NewInt(15)},
165 ClosedAuctionSlots: 2,
166 OpenAuctionSlots: 100,
167 AllocationRatio: [3]uint8{},
168 Outbidding: 10,
169 SlotDeadline: 20,
170 }
171 return &ClientSetup{
172 RollupConstants: rollupConstants,
173 RollupVariables: rollupVariables,
174 AuctionConstants: auctionConstants,
175 AuctionVariables: auctionVariables,
176 }
177}
178
179// Timer is an interface to simulate a source of time, useful to advance time
180// virtually.
181type Timer interface {
182 Time() int64
183}
184
185// type forgeBatchArgs struct {
186// ethTx *types.Transaction
187// blockNum int64
188// blockHash ethCommon.Hash
189// }
190
191// Client implements the eth.ClientInterface interface, allowing to manipulate the
192// values for testing, working with deterministic results.
193type Client struct {
194 rw *sync.RWMutex
195 log bool
196 addr ethCommon.Address
197 rollupConstants *eth.RollupConstants
198 auctionConstants *eth.AuctionConstants
199 blocks map[int64]*Block
200 // state state
201 blockNum int64 // last mined block num
202 maxBlockNum int64 // highest block num calculated
203 timer Timer
204 hasher hasher
205
206 forgeBatchArgsPending map[ethCommon.Hash]*eth.RollupForgeBatchArgs
207 forgeBatchArgs map[ethCommon.Hash]*eth.RollupForgeBatchArgs
208}
209
210// NewClient returns a new test Client that implements the eth.IClient
211// interface, at the given initialBlockNumber.
212func NewClient(l bool, timer Timer, addr ethCommon.Address, setup *ClientSetup) *Client {
213 blocks := make(map[int64]*Block)
214 blockNum := int64(0)
215
216 hasher := hasher{}
217 // Add ethereum genesis block
218 mapL1TxQueue := make(map[int64]*eth.QueueStruct)
219 mapL1TxQueue[0] = eth.NewQueueStruct()
220 mapL1TxQueue[1] = eth.NewQueueStruct()
221 blockCurrent := Block{
222 Rollup: &RollupBlock{
223 State: eth.RollupState{
224 StateRoot: big.NewInt(0),
225 ExitRoots: make([]*big.Int, 0),
226 ExitNullifierMap: make(map[[256 / 8]byte]bool),
227 TokenList: make([]ethCommon.Address, 0),
228 TokenMap: make(map[ethCommon.Address]bool),
229 MapL1TxQueue: mapL1TxQueue,
230 LastL1L2Batch: 0,
231 CurrentToForgeL1TxsNum: 0,
232 LastToForgeL1TxsNum: 1,
233 CurrentIdx: 0,
234 },
235 Vars: *setup.RollupVariables,
236 Events: eth.NewRollupEvents(),
237 Constants: setup.RollupConstants,
238 },
239 Auction: &AuctionBlock{
240 State: eth.AuctionState{
241 Slots: make(map[int64]*eth.SlotState),
242 PendingBalances: make(map[ethCommon.Address]*big.Int),
243 Coordinators: make(map[ethCommon.Address]*eth.Coordinator),
244 },
245 Vars: *setup.AuctionVariables,
246 Events: eth.NewAuctionEvents(),
247 Constants: setup.AuctionConstants,
248 },
249 Eth: &EthereumBlock{
250 BlockNum: blockNum,
251 Time: timer.Time(),
252 Hash: hasher.Next(),
253 ParentHash: ethCommon.Hash{},
254 },
255 }
256 blockCurrent.Rollup.Eth = blockCurrent.Eth
257 blockCurrent.Auction.Eth = blockCurrent.Eth
258 blocks[blockNum] = &blockCurrent
259 blockNext := blockCurrent.Next()
260 blocks[blockNum+1] = blockNext
261
262 return &Client{
263 rw: &sync.RWMutex{},
264 log: l,
265 addr: addr,
266 rollupConstants: setup.RollupConstants,
267 auctionConstants: setup.AuctionConstants,
268 blocks: blocks,
269 timer: timer,
270 hasher: hasher,
271 forgeBatchArgsPending: make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs),
272 forgeBatchArgs: make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs),
273 }
274}
275
276//
277// Mock Control
278//
279
280// Debugf calls log.Debugf if c.log is true
281func (c *Client) Debugf(template string, args ...interface{}) {
282 if c.log {
283 log.Debugf(template, args...)
284 }
285}
286
287// Debugw calls log.Debugw if c.log is true
288func (c *Client) Debugw(template string, kv ...interface{}) {
289 if c.log {
290 log.Debugw(template, kv...)
291 }
292}
293
294type hasher struct {
295 counter uint64
296}
297
298// Next returns the next hash
299func (h *hasher) Next() ethCommon.Hash {
300 var hash ethCommon.Hash
301 binary.LittleEndian.PutUint64(hash[:], h.counter)
302 h.counter++
303 return hash
304}
305
306func (c *Client) nextBlock() *Block {
307 return c.blocks[c.blockNum+1]
308}
309
310func (c *Client) currentBlock() *Block {
311 return c.blocks[c.blockNum]
312}
313
314// CtlMineBlock moves one block forward
315func (c *Client) CtlMineBlock() {
316 c.rw.Lock()
317 defer c.rw.Unlock()
318
319 blockCurrent := c.nextBlock()
320 c.blockNum++
321 c.maxBlockNum = c.blockNum
322 blockCurrent.Eth.Time = c.timer.Time()
323 blockCurrent.Eth.Hash = c.hasher.Next()
324 for ethTxHash, forgeBatchArgs := range c.forgeBatchArgsPending {
325 c.forgeBatchArgs[ethTxHash] = forgeBatchArgs
326 }
327 c.forgeBatchArgsPending = make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs)
328
329 blockNext := blockCurrent.Next()
330 c.blocks[c.blockNum+1] = blockNext
331 c.Debugw("TestClient mined block", "blockNum", c.blockNum)
332}
333
334// CtlRollback discards the last mined block. Use this to replace a mined
335// block to simulate reorgs.
336func (c *Client) CtlRollback() {
337 c.rw.Lock()
338 defer c.rw.Unlock()
339
340 if c.blockNum == 0 {
341 panic("Can't rollback at blockNum = 0")
342 }
343 delete(c.blocks, c.blockNum+1) // delete next block
344 delete(c.blocks, c.blockNum) // delete current block
345 c.blockNum--
346 blockCurrent := c.blocks[c.blockNum]
347 blockNext := blockCurrent.Next()
348 c.blocks[c.blockNum+1] = blockNext
349}
350
351//
352// Ethereum
353//
354
355// EthCurrentBlock returns the current blockNum
356func (c *Client) EthCurrentBlock() (int64, error) {
357 c.rw.RLock()
358 defer c.rw.RUnlock()
359
360 if c.blockNum < c.maxBlockNum {
361 panic("blockNum has decreased. " +
362 "After a rollback you must mine to reach the same or higher blockNum")
363 }
364 return c.blockNum, nil
365}
366
367// func newHeader(number *big.Int) *types.Header {
368// return &types.Header{
369// Number: number,
370// Time: uint64(number.Int64()),
371// }
372// }
373
374// EthHeaderByNumber returns the *types.Header for the given block number in a
375// deterministic way.
376// func (c *Client) EthHeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
377// return newHeader(number), nil
378// }
379
380// EthBlockByNumber returns the *common.Block for the given block number in a
381// deterministic way.
382func (c *Client) EthBlockByNumber(ctx context.Context, blockNum int64) (*common.Block, error) {
383 c.rw.RLock()
384 defer c.rw.RUnlock()
385
386 block, ok := c.blocks[blockNum]
387 if !ok {
388 return nil, fmt.Errorf("block not found")
389 }
390 return &common.Block{
391 EthBlockNum: blockNum,
392 Timestamp: time.Unix(block.Eth.Time, 0),
393 Hash: block.Eth.Hash,
394 ParentHash: block.Eth.ParentHash,
395 }, nil
396}
397
398var errTODO = fmt.Errorf("TODO: Not implemented yet")
399
400//
401// Rollup
402//
403
404// CtlAddL1TxUser adds an L1TxUser to the L1UserTxs queue of the Rollup
405func (c *Client) CtlAddL1TxUser(l1Tx *common.L1Tx) {
406 c.rw.Lock()
407 defer c.rw.Unlock()
408
409 nextBlock := c.nextBlock()
410 r := nextBlock.Rollup
411 queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
412 if len(queue.L1TxQueue) >= c.rollupConstants.MaxL1UserTx {
413 r.State.LastToForgeL1TxsNum++
414 r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
415 queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
416 }
417 if int64(l1Tx.FromIdx) > r.State.CurrentIdx {
418 panic("l1Tx.FromIdx > r.State.CurrentIdx")
419 }
420 if int(l1Tx.TokenID)+1 > len(r.State.TokenList) {
421 panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
422 }
423 queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
424 r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{L1Tx: *l1Tx})
425}
426
427type transactionData struct {
428 Name string
429 Value interface{}
430}
431
432func (c *Client) newTransaction(name string, value interface{}) *types.Transaction {
433 data, err := json.Marshal(transactionData{name, value})
434 if err != nil {
435 panic(err)
436 }
437 return types.NewTransaction(0, ethCommon.Address{}, nil, 0, nil,
438 data)
439}
440
441// RollupForgeBatch is the interface to call the smart contract function
442func (c *Client) RollupForgeBatch(*eth.RollupForgeBatchArgs) (*types.Transaction, error) {
443 c.rw.Lock()
444 defer c.rw.Unlock()
445
446 return nil, errTODO
447}
448
449// CtlAddBatch adds forged batch to the Rollup, without checking any ZKProof
450func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
451 c.rw.Lock()
452 defer c.rw.Unlock()
453
454 nextBlock := c.nextBlock()
455 r := nextBlock.Rollup
456 r.State.StateRoot = args.NewStRoot
457 if args.NewLastIdx < r.State.CurrentIdx {
458 panic("args.NewLastIdx < r.State.CurrentIdx")
459 }
460 r.State.CurrentIdx = args.NewLastIdx
461 r.State.ExitRoots = append(r.State.ExitRoots, args.NewExitRoot)
462 if args.L1Batch {
463 r.State.CurrentToForgeL1TxsNum++
464 if r.State.CurrentToForgeL1TxsNum == r.State.LastToForgeL1TxsNum {
465 r.State.LastToForgeL1TxsNum++
466 r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
467 }
468 }
469 ethTx := c.newTransaction("forgebatch", args)
470 c.forgeBatchArgsPending[ethTx.Hash()] = args
471 r.Events.ForgeBatch = append(r.Events.ForgeBatch, eth.RollupEventForgeBatch{
472 BatchNum: int64(len(r.State.ExitRoots)),
473 EthTxHash: ethTx.Hash(),
474 })
475}
476
477// RollupAddToken is the interface to call the smart contract function
478func (c *Client) RollupAddToken(tokenAddress ethCommon.Address) (*types.Transaction, error) {
479 c.rw.Lock()
480 defer c.rw.Unlock()
481
482 nextBlock := c.nextBlock()
483 r := nextBlock.Rollup
484 if _, ok := r.State.TokenMap[tokenAddress]; ok {
485 return nil, fmt.Errorf("Token %v already registered", tokenAddress)
486 }
487
488 r.State.TokenMap[tokenAddress] = true
489 r.State.TokenList = append(r.State.TokenList, tokenAddress)
490 r.Events.AddToken = append(r.Events.AddToken, eth.RollupEventAddToken{Address: tokenAddress,
491 TokenID: uint32(len(r.State.TokenList) - 1)})
492 return c.newTransaction("addtoken", tokenAddress), nil
493}
494
495// RollupWithdrawSNARK is the interface to call the smart contract function
496// func (c *Client) RollupWithdrawSNARK() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
497// return nil, errTODO
498// }
499
500// RollupWithdrawMerkleProof is the interface to call the smart contract function
501func (c *Client) RollupWithdrawMerkleProof(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey, numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (*types.Transaction, error) {
502 c.rw.Lock()
503 defer c.rw.Unlock()
504
505 return nil, errTODO
506}
507
508// RollupForceExit is the interface to call the smart contract function
509func (c *Client) RollupForceExit(fromIdx int64, amountF utils.Float16, tokenID int64) (*types.Transaction, error) {
510 c.rw.Lock()
511 defer c.rw.Unlock()
512
513 return nil, errTODO
514}
515
516// RollupForceTransfer is the interface to call the smart contract function
517func (c *Client) RollupForceTransfer(fromIdx int64, amountF utils.Float16, tokenID, toIdx int64) (*types.Transaction, error) {
518 c.rw.Lock()
519 defer c.rw.Unlock()
520
521 return nil, errTODO
522}
523
524// RollupCreateAccountDepositTransfer is the interface to call the smart contract function
525func (c *Client) RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey, loadAmountF, amountF utils.Float16, tokenID int64, toIdx int64) (*types.Transaction, error) {
526 c.rw.Lock()
527 defer c.rw.Unlock()
528
529 return nil, errTODO
530}
531
532// RollupDepositTransfer is the interface to call the smart contract function
533func (c *Client) RollupDepositTransfer(fromIdx int64, loadAmountF, amountF utils.Float16, tokenID int64, toIdx int64) (*types.Transaction, error) {
534 c.rw.Lock()
535 defer c.rw.Unlock()
536
537 return nil, errTODO
538}
539
540// RollupDeposit is the interface to call the smart contract function
541func (c *Client) RollupDeposit(fromIdx int64, loadAmountF utils.Float16, tokenID int64) (*types.Transaction, error) {
542 c.rw.Lock()
543 defer c.rw.Unlock()
544
545 return nil, errTODO
546}
547
548// RollupCreateAccountDepositFromRelayer is the interface to call the smart contract function
549func (c *Client) RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte, babyPubKey babyjub.PublicKey, loadAmountF utils.Float16) (*types.Transaction, error) {
550 c.rw.Lock()
551 defer c.rw.Unlock()
552
553 return nil, errTODO
554}
555
556// RollupCreateAccountDeposit is the interface to call the smart contract function
557func (c *Client) RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF utils.Float16, tokenID int64) (*types.Transaction, error) {
558 c.rw.Lock()
559 defer c.rw.Unlock()
560
561 return nil, errTODO
562}
563
564// RollupGetTokenAddress is the interface to call the smart contract function
565func (c *Client) RollupGetTokenAddress(tokenID int64) (*ethCommon.Address, error) {
566 c.rw.RLock()
567 defer c.rw.RUnlock()
568
569 return nil, errTODO
570}
571
572// RollupGetL1TxFromQueue is the interface to call the smart contract function
573func (c *Client) RollupGetL1TxFromQueue(queue int64, position int64) ([]byte, error) {
574 c.rw.RLock()
575 defer c.rw.RUnlock()
576
577 return nil, errTODO
578}
579
580// RollupGetQueue is the interface to call the smart contract function
581func (c *Client) RollupGetQueue(queue int64) ([]byte, error) {
582 c.rw.RLock()
583 defer c.rw.RUnlock()
584
585 return nil, errTODO
586}
587
588// RollupUpdateForgeL1Timeout is the interface to call the smart contract function
589func (c *Client) RollupUpdateForgeL1Timeout(newForgeL1Timeout int64) (*types.Transaction, error) {
590 c.rw.Lock()
591 defer c.rw.Unlock()
592
593 return nil, errTODO
594}
595
596// RollupUpdateFeeL1UserTx is the interface to call the smart contract function
597func (c *Client) RollupUpdateFeeL1UserTx(newFeeL1UserTx *big.Int) (*types.Transaction, error) {
598 c.rw.Lock()
599 defer c.rw.Unlock()
600
601 return nil, errTODO
602}
603
604// RollupUpdateFeeAddToken is the interface to call the smart contract function
605func (c *Client) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (*types.Transaction, error) {
606 c.rw.Lock()
607 defer c.rw.Unlock()
608
609 return nil, errTODO
610}
611
612// RollupUpdateTokensHEZ is the interface to call the smart contract function
613func (c *Client) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (*types.Transaction, error) {
614 c.rw.Lock()
615 defer c.rw.Unlock()
616
617 return nil, errTODO
618}
619
620// RollupUpdateGovernance is the interface to call the smart contract function
621// func (c *Client) RollupUpdateGovernance() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
622// return nil, errTODO
623// }
624
625// RollupConstants returns the Constants of the Rollup Smart Contract
626func (c *Client) RollupConstants() (*eth.RollupConstants, error) {
627 c.rw.RLock()
628 defer c.rw.RUnlock()
629
630 return nil, errTODO
631}
632
633// RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
634func (c *Client) RollupEventsByBlock(blockNum int64) (*eth.RollupEvents, *ethCommon.Hash, error) {
635 c.rw.RLock()
636 defer c.rw.RUnlock()
637
638 block, ok := c.blocks[blockNum]
639 if !ok {
640 return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
641 }
642 return &block.Rollup.Events, &block.Eth.Hash, nil
643}
644
645// RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
646func (c *Client) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*eth.RollupForgeBatchArgs, error) {
647 c.rw.RLock()
648 defer c.rw.RUnlock()
649
650 forgeBatchArgs, ok := c.forgeBatchArgs[ethTxHash]
651 if !ok {
652 return nil, fmt.Errorf("transaction not found")
653 }
654 return forgeBatchArgs, nil
655}
656
657//
658// Auction
659//
660
661// AuctionSetSlotDeadline is the interface to call the smart contract function
662func (c *Client) AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error) {
663 c.rw.Lock()
664 defer c.rw.Unlock()
665
666 return nil, errTODO
667}
668
669// AuctionGetSlotDeadline is the interface to call the smart contract function
670func (c *Client) AuctionGetSlotDeadline() (uint8, error) {
671 c.rw.RLock()
672 defer c.rw.RUnlock()
673
674 return 0, errTODO
675}
676
677// AuctionSetOpenAuctionSlots is the interface to call the smart contract function
678func (c *Client) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (*types.Transaction, error) {
679 c.rw.Lock()
680 defer c.rw.Unlock()
681
682 return nil, errTODO
683}
684
685// AuctionGetOpenAuctionSlots is the interface to call the smart contract function
686func (c *Client) AuctionGetOpenAuctionSlots() (uint16, error) {
687 c.rw.RLock()
688 defer c.rw.RUnlock()
689
690 return 0, errTODO
691}
692
693// AuctionSetClosedAuctionSlots is the interface to call the smart contract function
694func (c *Client) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (*types.Transaction, error) {
695 c.rw.Lock()
696 defer c.rw.Unlock()
697
698 return nil, errTODO
699}
700
701// AuctionGetClosedAuctionSlots is the interface to call the smart contract function
702func (c *Client) AuctionGetClosedAuctionSlots() (uint16, error) {
703 c.rw.RLock()
704 defer c.rw.RUnlock()
705
706 return 0, errTODO
707}
708
709// AuctionSetOutbidding is the interface to call the smart contract function
710func (c *Client) AuctionSetOutbidding(newOutbidding uint8) (*types.Transaction, error) {
711 c.rw.Lock()
712 defer c.rw.Unlock()
713
714 return nil, errTODO
715}
716
717// AuctionGetOutbidding is the interface to call the smart contract function
718func (c *Client) AuctionGetOutbidding() (uint8, error) {
719 c.rw.RLock()
720 defer c.rw.RUnlock()
721
722 return 0, errTODO
723}
724
725// AuctionSetAllocationRatio is the interface to call the smart contract function
726func (c *Client) AuctionSetAllocationRatio(newAllocationRatio [3]uint8) (*types.Transaction, error) {
727 c.rw.Lock()
728 defer c.rw.Unlock()
729
730 return nil, errTODO
731}
732
733// AuctionGetAllocationRatio is the interface to call the smart contract function
734func (c *Client) AuctionGetAllocationRatio() ([3]uint8, error) {
735 c.rw.RLock()
736 defer c.rw.RUnlock()
737
738 return [3]uint8{}, errTODO
739}
740
741// AuctionSetDonationAddress is the interface to call the smart contract function
742func (c *Client) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (*types.Transaction, error) {
743 c.rw.Lock()
744 defer c.rw.Unlock()
745
746 return nil, errTODO
747}
748
749// AuctionGetDonationAddress is the interface to call the smart contract function
750func (c *Client) AuctionGetDonationAddress() (*ethCommon.Address, error) {
751 c.rw.RLock()
752 defer c.rw.RUnlock()
753
754 return nil, errTODO
755}
756
757// AuctionSetBootCoordinator is the interface to call the smart contract function
758func (c *Client) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (*types.Transaction, error) {
759 c.rw.Lock()
760 defer c.rw.Unlock()
761
762 return nil, errTODO
763}
764
765// AuctionGetBootCoordinator is the interface to call the smart contract function
766func (c *Client) AuctionGetBootCoordinator() (*ethCommon.Address, error) {
767 c.rw.RLock()
768 defer c.rw.RUnlock()
769
770 currentBlock := c.currentBlock()
771 a := currentBlock.Auction
772
773 return &a.Vars.BootCoordinator, nil
774}
775
776// AuctionChangeEpochMinBid is the interface to call the smart contract function
777func (c *Client) AuctionChangeEpochMinBid(slotEpoch int64, newInitialMinBid *big.Int) (*types.Transaction, error) {
778 c.rw.Lock()
779 defer c.rw.Unlock()
780
781 return nil, errTODO
782}
783
784// AuctionRegisterCoordinator is the interface to call the smart contract function
785func (c *Client) AuctionRegisterCoordinator(forgerAddress ethCommon.Address, URL string) (*types.Transaction, error) {
786 c.rw.Lock()
787 defer c.rw.Unlock()
788
789 nextBlock := c.nextBlock()
790 a := nextBlock.Auction
791
792 if _, ok := a.State.Coordinators[forgerAddress]; ok {
793 return nil, fmt.Errorf("Already registered")
794 }
795 a.State.Coordinators[forgerAddress] = ð.Coordinator{
796 WithdrawalAddress: c.addr,
797 URL: URL,
798 }
799
800 a.Events.NewCoordinator = append(a.Events.NewCoordinator,
801 eth.AuctionEventNewCoordinator{
802 ForgerAddress: forgerAddress,
803 WithdrawalAddress: c.addr,
804 URL: URL,
805 })
806
807 type data struct {
808 ForgerAddress ethCommon.Address
809 URL string
810 }
811 return c.newTransaction("registercoordinator", data{forgerAddress, URL}), nil
812}
813
814// AuctionIsRegisteredCoordinator is the interface to call the smart contract function
815func (c *Client) AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address) (bool, error) {
816 c.rw.RLock()
817 defer c.rw.RUnlock()
818
819 return false, errTODO
820}
821
822// AuctionUpdateCoordinatorInfo is the interface to call the smart contract function
823func (c *Client) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (*types.Transaction, error) {
824 c.rw.Lock()
825 defer c.rw.Unlock()
826
827 return nil, errTODO
828}
829
830// AuctionGetCurrentSlotNumber is the interface to call the smart contract function
831func (c *Client) AuctionGetCurrentSlotNumber() (int64, error) {
832 c.rw.RLock()
833 defer c.rw.RUnlock()
834
835 return 0, errTODO
836}
837
838// AuctionGetMinBidBySlot is the interface to call the smart contract function
839func (c *Client) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
840 c.rw.RLock()
841 defer c.rw.RUnlock()
842
843 return nil, errTODO
844}
845
846// AuctionGetMinBidEpoch is the interface to call the smart contract function
847func (c *Client) AuctionGetMinBidEpoch(epoch uint8) (*big.Int, error) {
848 c.rw.RLock()
849 defer c.rw.RUnlock()
850
851 return nil, errTODO
852}
853
854// AuctionTokensReceived is the interface to call the smart contract function
855// func (c *Client) AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int, userData, operatorData []byte) error {
856// return errTODO
857// }
858
859// AuctionBid is the interface to call the smart contract function
860func (c *Client) AuctionBid(slot int64, bidAmount *big.Int, forger ethCommon.Address) (*types.Transaction, error) {
861 c.rw.Lock()
862 defer c.rw.Unlock()
863
864 nextBlock := c.nextBlock()
865 a := nextBlock.Auction
866
867 if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
868 return nil, errBidClosed
869 }
870
871 if slot >= a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots)+int64(a.Vars.OpenAuctionSlots) {
872 return nil, errBidNotOpen
873 }
874
875 minBid, err := a.getMinBidBySlot(slot)
876 if err != nil {
877 return nil, err
878 }
879 if bidAmount.Cmp(minBid) == -1 {
880 return nil, errBidBelowMin
881 }
882
883 if _, ok := a.State.Coordinators[forger]; !ok {
884 return nil, errCoordNotReg
885 }
886
887 slotState, ok := a.State.Slots[slot]
888 if !ok {
889 slotState = ð.SlotState{}
890 a.State.Slots[slot] = slotState
891 }
892 slotState.Forger = forger
893 slotState.BidAmount = bidAmount
894
895 a.Events.NewBid = append(a.Events.NewBid,
896 eth.AuctionEventNewBid{Slot: slot, BidAmount: bidAmount, CoordinatorForger: forger})
897
898 type data struct {
899 Slot int64
900 BidAmount *big.Int
901 Forger ethCommon.Address
902 }
903 return c.newTransaction("bid", data{slot, bidAmount, forger}), nil
904}
905
906// AuctionMultiBid is the interface to call the smart contract function
907func (c *Client) AuctionMultiBid(startingSlot int64, endingSlot int64, slotEpoch [6]bool, maxBid, closedMinBid, budget *big.Int, forger ethCommon.Address) (*types.Transaction, error) {
908 c.rw.Lock()
909 defer c.rw.Unlock()
910
911 return nil, errTODO
912}
913
914// AuctionCanForge is the interface to call the smart contract function
915func (c *Client) AuctionCanForge(forger ethCommon.Address) (bool, error) {
916 c.rw.RLock()
917 defer c.rw.RUnlock()
918
919 return false, errTODO
920}
921
922// AuctionForge is the interface to call the smart contract function
923// func (c *Client) AuctionForge(forger ethCommon.Address) (bool, error) {
924// return false, errTODO
925// }
926
927// AuctionClaimHEZ is the interface to call the smart contract function
928func (c *Client) AuctionClaimHEZ() (*types.Transaction, error) {
929 c.rw.Lock()
930 defer c.rw.Unlock()
931
932 return nil, errTODO
933}
934
935// AuctionConstants returns the Constants of the Auction Smart Contract
936func (c *Client) AuctionConstants() (*eth.AuctionConstants, error) {
937 c.rw.RLock()
938 defer c.rw.RUnlock()
939
940 return c.auctionConstants, nil
941}
942
943// AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract
944func (c *Client) AuctionEventsByBlock(blockNum int64) (*eth.AuctionEvents, *ethCommon.Hash, error) {
945 c.rw.RLock()
946 defer c.rw.RUnlock()
947
948 block, ok := c.blocks[blockNum]
949 if !ok {
950 return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
951 }
952 return &block.Auction.Events, &block.Eth.Hash, nil
953}