Update test ethclient and coordinator
@@ -1,6 +1,7 @@
package coordinator import ( + "github.com/ethereum/go-ethereum/core/types" "github.com/hermeznetwork/hermez-node/common" )@@ -18,6 +19,7 @@ L1UserTxsExtra []*common.L1Tx
L1OperatorTxs []*common.L1Tx L2Txs []*common.PoolL2Tx // FeesInfo + ethTx *types.Transaction } // NewBatchInfo creates a new BatchInfo with the given batchNum &@@ -52,3 +54,8 @@ // SetProof sets the Proof to the BatchInfo data structure
func (bi *BatchInfo) SetProof(proof *Proof) { bi.proof = proof } + +// SetEthTx sets the ethTx to the BatchInfo data structure +func (bi *BatchInfo) SetEthTx(ethTx *types.Transaction) { + bi.ethTx = ethTx +}
@@ -1,18 +1,18 @@
package coordinator import ( + "context" "fmt" - "sync" + "time" ethCommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/hermeznetwork/hermez-node/batchbuilder" "github.com/hermeznetwork/hermez-node/common" "github.com/hermeznetwork/hermez-node/db/historydb" "github.com/hermeznetwork/hermez-node/eth" "github.com/hermeznetwork/hermez-node/log" "github.com/hermeznetwork/hermez-node/txselector" - kvdb "github.com/iden3/go-merkletree/db" - "github.com/iden3/go-merkletree/db/memory" ) var errTODO = fmt.Errorf("TODO")@@ -28,9 +28,9 @@ }
// Coordinator implements the Coordinator type type Coordinator struct { - forging bool - rw *sync.RWMutex - isForgeSeq bool // WIP just for testing while implementing + forging bool + // rw *sync.RWMutex + // isForgeSeq bool // WIP just for testing while implementing config Config@@ -42,8 +42,9 @@ hdb *historydb.HistoryDB
txsel *txselector.TxSelector batchBuilder *batchbuilder.BatchBuilder - ethClient eth.ClientInterface - ethTxStore kvdb.Storage + ethClient eth.ClientInterface + ethTxs []*types.Transaction + // ethTxStore kvdb.Storage } // NewCoordinator creates a new Coordinator@@ -64,17 +65,30 @@ hdb: hdb,
txsel: txsel, batchBuilder: bb, ethClient: ethClient, - ethTxStore: memory.NewMemoryStorage(), - rw: &sync.RWMutex{}, + + ethTxs: make([]*types.Transaction, 0), + // ethTxStore: memory.NewMemoryStorage(), + // rw: &sync.RWMutex{}, } return &c } +// TODO(Edu): Change the current design of the coordinator structur: +// - Move Start and Stop functions (from node/node.go) here +// - Add concept of StartPipeline, StopPipeline, that spawns and stops the goroutines +// - Add a Manager that calls StartPipeline and StopPipeline, checks when it's time to forge, schedules new batches, etc. +// - Add a TxMonitor that monitors successful ForgeBatch ethereum transactions and waits for N blocks of confirmation, and reports back errors to the Manager. + // ForgeLoopFn is the function ran in a loop that checks if it's time to forge // and forges a batch if so and sends it to outBatchCh. Returns true if it's // the coordinator turn to forge. func (c *Coordinator) ForgeLoopFn(outBatchCh chan *BatchInfo, stopCh chan bool) (forgetime bool, err error) { - if !c.isForgeSequence() { + // TODO: Move the logic to check if it's forge time or not outside the pipeline + isForgeSequence, err := c.isForgeSequence() + if err != nil { + return false, err + } + if !isForgeSequence { if c.forging { log.Info("ForgeLoopFn: forging state end") c.forging = false@@ -106,6 +120,12 @@ // handleReorg() function decides if the reorg must restart the pipeline or not
// if c.synchronizer.Reorg(): _ = c.handleReorg() + defer func() { + if err == ErrStop { + log.Info("ForgeLoopFn: forgeLoopFn stopped") + } + }() + // 0. Wait for an available server proof // blocking call serverProof, err := c.serverProofPool.Get(stopCh)@@ -134,10 +154,14 @@
// GetProofCallForgeLoopFn is the function ran in a loop that gets a forged // batch via inBatchCh, waits for the proof server to finish, calls the ForgeBatch // function in the Rollup Smart Contract, and sends the batch to outBatchCh. -func (c *Coordinator) GetProofCallForgeLoopFn(inBatchCh, outBatchCh chan *BatchInfo, stopCh chan bool) error { +func (c *Coordinator) GetProofCallForgeLoopFn(inBatchCh, outBatchCh chan *BatchInfo, stopCh chan bool) (err error) { + defer func() { + if err == ErrStop { + log.Info("GetProofCallForgeLoopFn: forgeLoopFn stopped") + } + }() select { case <-stopCh: - log.Info("GetProofCallForgeLoopFn: forgeLoopFn stopped") return ErrStop case batchInfo := <-inBatchCh: log.Debugw("GetProofCallForgeLoopFn: getProofCallForge start", "batchNum", batchInfo.batchNum)@@ -153,14 +177,18 @@
// ForgeCallConfirmLoopFn is the function ran in a loop that gets a batch that // has been sent to the Rollup Smart Contract via inBatchCh and waits for the // ethereum transaction confirmation. -func (c *Coordinator) ForgeCallConfirmLoopFn(inBatchCh chan *BatchInfo, stopCh chan bool) error { +func (c *Coordinator) ForgeCallConfirmLoopFn(inBatchCh chan *BatchInfo, stopCh chan bool) (err error) { + defer func() { + if err == ErrStop { + log.Info("ForgeCallConfirmLoopFn: forgeConfirmLoopFn stopped") + } + }() select { case <-stopCh: - log.Info("ForgeCallConfirmLoopFn: forgeConfirmLoopFn stopped") return ErrStop case batchInfo := <-inBatchCh: log.Debugw("ForgeCallConfirmLoopFn: forgeCallConfirm start", "batchNum", batchInfo.batchNum) - if err := c.forgeCallConfirm(batchInfo); err != nil { + if err := c.forgeCallConfirm(batchInfo, stopCh); err != nil { return err } log.Debugw("ForgeCallConfirmLoopFn: forgeCallConfirm end", "batchNum", batchInfo.batchNum)@@ -244,13 +272,15 @@ return err
} batchInfo.SetProof(proof) forgeBatchArgs := c.prepareForgeBatchArgs(batchInfo) - _, err = c.ethClient.RollupForgeBatch(forgeBatchArgs) + ethTx, err := c.ethClient.RollupForgeBatch(forgeBatchArgs) if err != nil { return err } + // TODO: Move this to the next step (forgeCallConfirm) log.Debugf("ethClient ForgeCall sent, batchNum: %d", c.batchNum) + batchInfo.SetEthTx(ethTx) - // TODO once tx data type is defined, store ethTx (returned by ForgeCall) + // TODO(FUTURE) once tx data type is defined, store ethTx (returned by ForgeCall) // TBD if use ethTxStore as a disk k-v database, or use a Queue // tx, err := c.ethTxStore.NewTx() // if err != nil {@@ -264,13 +294,46 @@
return nil } -func (c *Coordinator) forgeCallConfirm(batchInfo *BatchInfo) error { +func (c *Coordinator) forgeCallConfirm(batchInfo *BatchInfo, stopCh chan bool) error { // TODO strategy of this sequence TBD // confirm eth txs and mark them as accepted sequence + // IDEA: Keep an array in Coordinator with the list of sent ethTx. + // Here, loop over them and only delete them once the number of + // confirmed blocks is over a configured value. If the tx is rejected, + // return error. // ethTx := ethTxStore.GetFirstPending() // waitForAccepted(ethTx) // blocking call, returns once the ethTx is mined // ethTxStore.MarkAccepted(ethTx) - return nil + txID := batchInfo.ethTx.Hash() + // TODO: Follow EthereumClient.waitReceipt logic + count := 0 + // TODO: Define this waitTime in the config + waitTime := 100 * time.Millisecond //nolint:gomnd + select { + case <-time.After(waitTime): + receipt, err := c.ethClient.EthTransactionReceipt(context.TODO(), txID) + if err != nil { + return err + } + if receipt != nil { + if receipt.Status == types.ReceiptStatusFailed { + return fmt.Errorf("receipt status is failed") + } else if receipt.Status == types.ReceiptStatusSuccessful { + return nil + } + } + // TODO: Call go-ethereum: + // if err == nil && receipt == nil : + // `func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) {` + count++ + if time.Duration(count)*waitTime > 60*time.Second { + log.Warnw("Waiting for ethTx receipt for more than 60 seconds", "tx", batchInfo.ethTx) + // TODO: Decide if we resend the Tx with higher gas price + } + case <-stopCh: + return ErrStop + } + return fmt.Errorf("timeout") } func (c *Coordinator) handleReorg() error {@@ -278,10 +341,17 @@ return nil // TODO
} // isForgeSequence returns true if the node is the Forger in the current ethereum block -func (c *Coordinator) isForgeSequence() bool { - c.rw.RLock() - defer c.rw.RUnlock() - return c.isForgeSeq // TODO +func (c *Coordinator) isForgeSequence() (bool, error) { + // TODO: Consider checking if we can forge by quering the Synchronizer instead of using ethClient + blockNum, err := c.ethClient.EthCurrentBlock() + if err != nil { + return false, err + } + addr, err := c.ethClient.EthAddress() + if err != nil { + return false, err + } + return c.ethClient.AuctionCanForge(*addr, blockNum+1) } func (c *Coordinator) purgeRemoveByTimeout() error {
@@ -2,10 +2,12 @@ package coordinator
import ( "io/ioutil" + "math/big" "os" "testing" "time" + ethCommon "github.com/ethereum/go-ethereum/common" "github.com/hermeznetwork/hermez-node/batchbuilder" dbUtils "github.com/hermeznetwork/hermez-node/db" "github.com/hermeznetwork/hermez-node/db/historydb"@@ -65,8 +67,9 @@ log.Debugw("Starting CoordNode...")
cn.stopForge = make(chan bool) cn.stopGetProofCallForge = make(chan bool) cn.stopForgeCallConfirm = make(chan bool) - batchCh0 := make(chan *BatchInfo) - batchCh1 := make(chan *BatchInfo) + queueSize := 8 + batchCh0 := make(chan *BatchInfo, queueSize) + batchCh1 := make(chan *BatchInfo, queueSize) go func() { for {@@ -78,6 +81,7 @@ if forge, err := cn.c.ForgeLoopFn(batchCh0, cn.stopForge); err == ErrStop {
return } else if err != nil { log.Errorw("CoordNode ForgeLoopFn", "error", err) + time.Sleep(200 * time.Millisecond) // Avoid overflowing log with errors } else if !forge { time.Sleep(200 * time.Millisecond) }@@ -133,17 +137,38 @@ t.time++
return currentTime } +func waitForSlot(t *testing.T, c *test.Client, slot int64) { + for { + blockNum, err := c.EthCurrentBlock() + require.Nil(t, err) + nextBlockSlot, err := c.AuctionGetSlotNumber(blockNum + 1) + require.Nil(t, err) + if nextBlockSlot == slot { + break + } + c.CtlMineBlock() + } +} + func TestCoordinator(t *testing.T) { txsel, bb := newTestModules(t) conf := Config{} hdb := &historydb.HistoryDB{} - serverProofs := []ServerProofInterface{&ServerProof{}, &ServerProof{}} + serverProofs := []ServerProofInterface{&ServerProofMock{}, &ServerProofMock{}} var timer timer ethClientSetup := test.NewClientSetupExample() - addr := ethClientSetup.AuctionVariables.BootCoordinator - ethClient := test.NewClient(true, &timer, addr, ethClientSetup) + addr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6") + ethClient := test.NewClient(true, &timer, &addr, ethClientSetup) + + // Bid for slot 2 and 4 + _, err := ethClient.AuctionRegisterCoordinator(addr, "https://foo.bar") + require.Nil(t, err) + _, err = ethClient.AuctionBid(2, big.NewInt(9999), addr) + require.Nil(t, err) + _, err = ethClient.AuctionBid(4, big.NewInt(9999), addr) + require.Nil(t, err) c := NewCoordinator(conf, hdb, txsel, bb, serverProofs, ethClient) cn := NewCoordNode(c)@@ -151,24 +176,18 @@ cn.Start()
time.Sleep(1 * time.Second) // simulate forgeSequence time + waitForSlot(t, ethClient, 2) log.Info("simulate entering in forge time") - c.rw.Lock() - c.isForgeSeq = true - c.rw.Unlock() time.Sleep(1 * time.Second) // simulate going out from forgeSequence + waitForSlot(t, ethClient, 3) log.Info("simulate going out from forge time") - c.rw.Lock() - c.isForgeSeq = false - c.rw.Unlock() time.Sleep(1 * time.Second) // simulate entering forgeSequence time again + waitForSlot(t, ethClient, 4) log.Info("simulate entering in forge time again") - c.rw.Lock() - c.isForgeSeq = true - c.rw.Unlock() time.Sleep(2 * time.Second) // simulate stopping forgerLoop by channel
@@ -28,11 +28,13 @@
// CalculateProof sends the *common.ZKInputs to the ServerProof to compute the // Proof func (p *ServerProof) CalculateProof(zkInputs *common.ZKInputs) error { + log.Error("TODO") return errTODO } // GetProof retreives the Proof from the ServerProof func (p *ServerProof) GetProof(stopCh chan bool) (*Proof, error) { + log.Error("TODO") return nil, errTODO }
@@ -240,11 +240,11 @@ AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address) (bool, error)
AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (*types.Transaction, error) // Slot Info + AuctionGetSlotNumber(blockNum int64) (int64, error) AuctionGetCurrentSlotNumber() (int64, error) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) AuctionGetSlotSet(slot int64) (*big.Int, error) - AuctionGetSlotNumber(blockNum int64) (*big.Int, error) // Bidding // AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int,@@ -698,7 +698,7 @@ return minBidSlotSet, nil
} // AuctionGetSlotNumber is the interface to call the smart contract function -func (c *AuctionClient) AuctionGetSlotNumber(blockNum int64) (*big.Int, error) { +func (c *AuctionClient) AuctionGetSlotNumber(blockNum int64) (int64, error) { var slot *big.Int if err := c.client.Call(func(ec *ethclient.Client) error { auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)@@ -709,9 +709,9 @@ blockNumBig := big.NewInt(blockNum)
slot, err = auction.GetSlotNumber(nil, blockNumBig) return err }); err != nil { - return big.NewInt(0), err + return 0, err } - return slot, nil + return slot.Int64(), nil } // AuctionBid is the interface to call the smart contract function
@@ -21,6 +21,8 @@ type EthereumInterface interface {
EthCurrentBlock() (int64, error) // EthHeaderByNumber(context.Context, *big.Int) (*types.Header, error) EthBlockByNumber(context.Context, int64) (*common.Block, error) + EthAddress() (*ethCommon.Address, error) + EthTransactionReceipt(context.Context, ethCommon.Hash) (*types.Receipt, error) } var (@@ -88,6 +90,14 @@
// Account returns the underlying ethereum account func (c *EthereumClient) Account() *accounts.Account { return c.account +} + +// EthAddress returns the ethereum address of the account loaded into the EthereumClient +func (c *EthereumClient) EthAddress() (*ethCommon.Address, error) { + if c.account == nil { + return nil, ErrAccountNil + } + return &c.account.Address, nil } // CallAuth performs a Smart Contract method call that requires authorization.@@ -186,16 +196,21 @@ defer cancel()
return c.waitReceipt(ctx, tx, 0) } +// EthTransactionReceipt returns the transaction receipt of the given txHash +func (c *EthereumClient) EthTransactionReceipt(ctx context.Context, txHash ethCommon.Hash) (*types.Receipt, error) { + return c.client.TransactionReceipt(ctx, txHash) +} + func (c *EthereumClient) waitReceipt(ctx context.Context, tx *types.Transaction, timeout time.Duration) (*types.Receipt, error) { var err error var receipt *types.Receipt - txid := tx.Hash() - log.Debugw("Waiting for receipt", "tx", txid.Hex()) + txHash := tx.Hash() + log.Debugw("Waiting for receipt", "tx", txHash.Hex()) start := time.Now() for { - receipt, err = c.client.TransactionReceipt(ctx, txid) + receipt, err = c.client.TransactionReceipt(ctx, txHash) if receipt != nil || time.Since(start) >= timeout { break }@@ -203,15 +218,15 @@ time.Sleep(c.config.IntervalReceiptLoop * time.Millisecond)
} if receipt != nil && receipt.Status == types.ReceiptStatusFailed { - log.Errorw("Failed transaction", "tx", txid.Hex()) + log.Errorw("Failed transaction", "tx", txHash.Hex()) return receipt, ErrReceiptStatusFailed } if receipt == nil { - log.Debugw("Pendingtransaction / Wait receipt timeout", "tx", txid.Hex(), "lasterr", err) + log.Debugw("Pendingtransaction / Wait receipt timeout", "tx", txHash.Hex(), "lasterr", err) return receipt, ErrReceiptNotReceived } - log.Debugw("Successful transaction", "tx", txid.Hex()) + log.Debugw("Successful transaction", "tx", txHash.Hex()) return receipt, err }
@@ -234,6 +234,8 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=@@ -494,6 +496,7 @@ github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.5.2 h1:qLvObTrvO/XRCqmkKxUlOBc48bI3efyDuAZe25QiF0w= github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=@@ -510,6 +513,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shirou/gopsutil v2.20.5+incompatible h1:tYH07UPoQt0OCQdgWWMgYHy3/a9bcxNpBIysykNIP7I= github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=@@ -581,6 +586,8 @@ github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=@@ -648,6 +655,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=@@ -672,6 +681,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=@@ -681,6 +692,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=@@ -732,15 +745,24 @@ golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200308013534-11ec41452d41 h1:9Di9iYgOt9ThCipBxChBVhgNipDoE5mxO84rQV7D0FE= golang.org/x/tools v0.0.0-20200308013534-11ec41452d41/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200731060945-b5fad4ed8dd6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200914163123-ea50a3c84940 h1:151ExL+g/k/wnhOqV+O1OliaTi0FR2UxQEEcpAhzzw8= +golang.org/x/tools v0.0.0-20200914163123-ea50a3c84940/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20200929223013-bf155c11ec6f h1:7+Nz9MyPqt2qMCTvNiRy1G0zYfkB7UCa+ayT6uVvbyI= +golang.org/x/tools/gopls v0.5.0 h1:XEmO9RylgmaXp33iGrWfCGopVYDGBmLy+KmsIsfIo8Y= +golang.org/x/tools/gopls v0.5.0/go.mod h1:bm7s/5W/faSLxWyOWFtTI+5lZQQVdtksvEXdIfkFE74= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=@@ -764,6 +786,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=@@ -796,6 +819,7 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=@@ -808,5 +832,11 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75k= +honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +mvdan.cc/gofumpt v0.0.0-20200802201014-ab5a8192947d h1:t8TAw9WgTLghti7RYkpPmqk4JtQ3+wcP5GgZqgWeWLQ= +mvdan.cc/gofumpt v0.0.0-20200802201014-ab5a8192947d/go.mod h1:bzrjFmaD6+xqohD3KYP0H2FEuxknnBmyyOxdhLdaIws= +mvdan.cc/xurls/v2 v2.2.0 h1:NSZPykBXJFCetGZykLAxaL6SIpvbVy/UFEniIfHAa8A= +mvdan.cc/xurls/v2 v2.2.0/go.mod h1:EV1RMtya9D6G5DMYPGD8zTQzaHet6Jh8gFlRgGRJeO8= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
@@ -144,8 +144,9 @@ n.stoppedForge = make(chan bool)
n.stoppedGetProofCallForge = make(chan bool) n.stoppedForgeCallConfirm = make(chan bool) - batchCh0 := make(chan *coordinator.BatchInfo) - batchCh1 := make(chan *coordinator.BatchInfo) + queueSize := 1 + batchCh0 := make(chan *coordinator.BatchInfo, queueSize) + batchCh1 := make(chan *coordinator.BatchInfo, queueSize) go func() { defer func() { n.stoppedForge <- true }()
@@ -33,8 +33,15 @@ type RollupBlock struct {
State eth.RollupState Vars eth.RollupVariables Events eth.RollupEvents + Txs map[ethCommon.Hash]*types.Transaction Constants *eth.RollupConstants Eth *EthereumBlock +} + +func (r *RollupBlock) addTransaction(tx *types.Transaction) *types.Transaction { + txHash := tx.Hash() + r.Txs[txHash] = tx + return tx } var (@@ -49,8 +56,15 @@ type AuctionBlock struct {
State eth.AuctionState Vars eth.AuctionVariables Events eth.AuctionEvents + Txs map[ethCommon.Hash]*types.Transaction Constants *eth.AuctionConstants Eth *EthereumBlock +} + +func (a *AuctionBlock) addTransaction(tx *types.Transaction) *types.Transaction { + txHash := tx.Hash() + a.Txs[txHash] = tx + return tx } func (a *AuctionBlock) getSlotNumber(blockNumber int64) int64 {@@ -286,7 +300,7 @@ // values for testing, working with deterministic results.
type Client struct { rw *sync.RWMutex log bool - addr ethCommon.Address + addr *ethCommon.Address rollupConstants *eth.RollupConstants auctionConstants *eth.AuctionConstants blocks map[int64]*Block@@ -302,7 +316,7 @@ }
// NewClient returns a new test Client that implements the eth.IClient // interface, at the given initialBlockNumber. -func NewClient(l bool, timer Timer, addr ethCommon.Address, setup *ClientSetup) *Client { +func NewClient(l bool, timer Timer, addr *ethCommon.Address, setup *ClientSetup) *Client { blocks := make(map[int64]*Block) blockNum := int64(0)@@ -326,6 +340,7 @@ LastToForgeL1TxsNum: 1,
CurrentIdx: 0, }, Vars: *setup.RollupVariables, + Txs: make(map[ethCommon.Hash]*types.Transaction), Events: eth.NewRollupEvents(), Constants: setup.RollupConstants, },@@ -336,6 +351,7 @@ PendingBalances: make(map[ethCommon.Address]*big.Int),
Coordinators: make(map[ethCommon.Address]*eth.Coordinator), }, Vars: *setup.AuctionVariables, + Txs: make(map[ethCommon.Hash]*types.Transaction), Events: eth.NewAuctionEvents(), Constants: setup.AuctionConstants, },@@ -468,6 +484,30 @@ }
return c.blockNum, nil } +// EthTransactionReceipt returns the transaction receipt of the given txHash +func (c *Client) EthTransactionReceipt(ctx context.Context, txHash ethCommon.Hash) (*types.Receipt, error) { + c.rw.RLock() + defer c.rw.RUnlock() + + for i := int64(0); i < c.blockNum; i++ { + b := c.blocks[i] + _, ok := b.Rollup.Txs[txHash] + if !ok { + _, ok = b.Auction.Txs[txHash] + } + if ok { + return &types.Receipt{ + TxHash: txHash, + Status: types.ReceiptStatusSuccessful, + BlockHash: b.Eth.Hash, + BlockNumber: big.NewInt(b.Eth.BlockNum), + }, nil + } + } + + return nil, nil +} + // func newHeader(number *big.Int) *types.Header { // return &types.Header{ // Number: number,@@ -499,6 +539,14 @@ ParentHash: block.Eth.ParentHash,
}, nil } +// EthAddress returns the ethereum address of the account loaded into the Client +func (c *Client) EthAddress() (*ethCommon.Address, error) { + if c.addr == nil { + return nil, eth.ErrAccountNil + } + return c.addr, nil +} + var errTODO = fmt.Errorf("TODO: Not implemented yet") //@@ -533,7 +581,7 @@ Name string
Value interface{} } -func (c *Client) newTransaction(name string, value interface{}) *types.Transaction { +func newTransaction(name string, value interface{}) *types.Transaction { data, err := json.Marshal(transactionData{name, value}) if err != nil { panic(err)@@ -548,9 +596,12 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } a := c.nextBlock().Auction - ok, err := a.canForge(c.addr, a.Eth.BlockNum) + ok, err := a.canForge(*c.addr, a.Eth.BlockNum) if err != nil { return nil, err }@@ -561,11 +612,15 @@
// TODO: Verify proof // Auction - err = a.forge(c.addr) + err = a.forge(*c.addr) if err != nil { return nil, err } + // TODO: If successful, store the tx in a successful array. + // TODO: If failed, store the tx in a failed array. + // TODO: Add method to move the tx to another block, reapply it there, and possibly go from successful to failed. + return c.addBatch(args) }@@ -595,7 +650,7 @@ r.State.LastToForgeL1TxsNum++
r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct() } } - ethTx := c.newTransaction("forgebatch", args) + ethTx := r.addTransaction(newTransaction("forgebatch", args)) c.forgeBatchArgsPending[ethTx.Hash()] = args r.Events.ForgeBatch = append(r.Events.ForgeBatch, eth.RollupEventForgeBatch{ BatchNum: int64(len(r.State.ExitRoots)),@@ -611,6 +666,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } nextBlock := c.nextBlock() r := nextBlock.Rollup@@ -622,7 +680,7 @@ r.State.TokenMap[tokenAddress] = true
r.State.TokenList = append(r.State.TokenList, tokenAddress) r.Events.AddToken = append(r.Events.AddToken, eth.RollupEventAddToken{Address: tokenAddress, TokenID: uint32(len(r.State.TokenList) - 1)}) - return c.newTransaction("addtoken", tokenAddress), nil + return r.addTransaction(newTransaction("addtoken", tokenAddress)), nil } // RollupWithdrawSNARK is the interface to call the smart contract function@@ -636,6 +694,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -647,6 +708,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -658,6 +722,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -669,6 +736,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -689,6 +759,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -700,6 +773,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -711,6 +787,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -722,6 +801,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -760,6 +842,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -771,6 +856,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -835,6 +923,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -855,6 +946,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -875,6 +969,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -895,6 +992,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -915,6 +1015,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -935,6 +1038,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -955,6 +1061,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -977,6 +1086,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -988,6 +1100,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } nextBlock := c.nextBlock() a := nextBlock.Auction@@ -996,14 +1111,14 @@ if _, ok := a.State.Coordinators[forgerAddress]; ok {
return nil, fmt.Errorf("Already registered") } a.State.Coordinators[forgerAddress] = ð.Coordinator{ - WithdrawalAddress: c.addr, + WithdrawalAddress: *c.addr, URL: URL, } a.Events.NewCoordinator = append(a.Events.NewCoordinator, eth.AuctionEventNewCoordinator{ ForgerAddress: forgerAddress, - WithdrawalAddress: c.addr, + WithdrawalAddress: *c.addr, CoordinatorURL: URL, })@@ -1011,7 +1126,7 @@ type data struct {
ForgerAddress ethCommon.Address URL string } - return c.newTransaction("registercoordinator", data{forgerAddress, URL}), nil + return a.addTransaction(newTransaction("registercoordinator", data{forgerAddress, URL})), nil } // AuctionIsRegisteredCoordinator is the interface to call the smart contract function@@ -1029,11 +1144,24 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO } +// AuctionGetSlotNumber is the interface to call the smart contract function +func (c *Client) AuctionGetSlotNumber(blockNum int64) (int64, error) { + c.rw.RLock() + defer c.rw.RUnlock() + + currentBlock := c.currentBlock() + a := currentBlock.Auction + return a.getSlotNumber(blockNum), nil +} + // AuctionGetCurrentSlotNumber is the interface to call the smart contract function func (c *Client) AuctionGetCurrentSlotNumber() (int64, error) { c.rw.RLock()@@ -1070,15 +1198,6 @@ log.Error("TODO")
return nil, errTODO } -// AuctionGetSlotNumber is the interface to call the smart contract function -func (c *Client) AuctionGetSlotNumber(blockNum int64) (*big.Int, error) { - c.rw.RLock() - defer c.rw.RUnlock() - - log.Error("TODO") - return nil, errTODO -} - // AuctionTokensReceived is the interface to call the smart contract function // func (c *Client) AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int, userData, operatorData []byte) error { // return errTODO@@ -1090,6 +1209,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { func() { c.revertIfErr(err, cpy) }() }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } nextBlock := c.nextBlock() a := nextBlock.Auction@@ -1130,7 +1252,7 @@ Slot int64
BidAmount *big.Int Forger ethCommon.Address } - return c.newTransaction("bid", data{slot, bidAmount, forger}), nil + return a.addTransaction(newTransaction("bid", data{slot, bidAmount, forger})), nil } // AuctionMultiBid is the interface to call the smart contract function@@ -1139,6 +1261,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO@@ -1165,6 +1290,9 @@ c.rw.Lock()
defer c.rw.Unlock() cpy := c.nextBlock().copy() defer func() { c.revertIfErr(err, cpy) }() + if c.addr == nil { + return nil, eth.ErrAccountNil + } log.Error("TODO") return nil, errTODO
@@ -31,7 +31,7 @@ func TestClientInterface(t *testing.T) {
var c eth.ClientInterface var timer timer clientSetup := NewClientSetupExample() - client := NewClient(true, &timer, ethCommon.Address{}, clientSetup) + client := NewClient(true, &timer, ðCommon.Address{}, clientSetup) c = client require.NotNil(t, c) }@@ -39,7 +39,7 @@
func TestClientEth(t *testing.T) { var timer timer clientSetup := NewClientSetupExample() - c := NewClient(true, &timer, ethCommon.Address{}, clientSetup) + c := NewClient(true, &timer, ðCommon.Address{}, clientSetup) blockNum, err := c.EthCurrentBlock() require.Nil(t, err) assert.Equal(t, int64(0), blockNum)@@ -76,7 +76,7 @@ clientSetup.AuctionVariables.OpenAuctionSlots = 4320
clientSetup.AuctionVariables.DefaultSlotSetBid = [6]*big.Int{ big.NewInt(1000), big.NewInt(1100), big.NewInt(1200), big.NewInt(1300), big.NewInt(1400), big.NewInt(1500)} - c := NewClient(true, &timer, addrWithdraw, clientSetup) + c := NewClient(true, &timer, &addrWithdraw, clientSetup) // Check several cases in which bid doesn't succed, and also do 2 successful bids.@@ -124,7 +124,7 @@ token1Addr := ethCommon.HexToAddress("0x6b175474e89094c44da98b954eedeac495271d0f")
var timer timer clientSetup := NewClientSetupExample() - c := NewClient(true, &timer, ethCommon.Address{}, clientSetup) + c := NewClient(true, &timer, ðCommon.Address{}, clientSetup) // Add a token