arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
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 := &eth.RollupConstants{}
145	rollupVariables := &eth.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 := &eth.AuctionConstants{
157		BlocksPerSlot: 40,
158	}
159	auctionVariables := &eth.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] = &eth.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 = &eth.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}