diff --git a/cli/node/cfg.buidler.toml b/cli/node/cfg.buidler.toml index e45a14d..b7cb0c0 100644 --- a/cli/node/cfg.buidler.toml +++ b/cli/node/cfg.buidler.toml @@ -38,7 +38,8 @@ TokenHEZ = "0x5D94e3e7aeC542aB0F9129B9a7BAdeb5B3Ca0f77" TokenHEZName = "Hermez Network Token" [Coordinator] -ForgerAddress = "0x6BB84Cc84D4A34467aD12a2039A312f7029e2071" +# ForgerAddress = "0x05c23b938a85ab26A36E6314a0D02080E9ca6BeD" # Non-Boot Coordinator +ForgerAddress = "0xb4124ceb3451635dacedd11767f004d8a28c6ee7" # Boot Coordinator ConfirmBlocks = 10 L1BatchTimeoutPerc = 0.6 ProofServerPollInterval = "1s" @@ -60,7 +61,7 @@ Path = "/tmp/iden3-test/hermez/txselector" Path = "/tmp/iden3-test/hermez/batchbuilder" [[Coordinator.ServerProofs]] -URL = "http://localhost:3000" +URL = "http://localhost:3000/api" [Coordinator.EthClient] CallGasLimit = 300000 @@ -73,8 +74,13 @@ CheckLoopInterval = "500ms" Attempts = 8 AttemptsDelay = "200ms" +[Coordinator.EthClient.Keystore] +Path = "/tmp/iden3-test/hermez/ethkeystore" +Password = "yourpasswordhere" + [Coordinator.API] Coordinator = true [Coordinator.Debug] BatchPath = "/tmp/iden3-test/hermez/batchesdebug" +LightScrypt = true diff --git a/cli/node/load-sk-example.sh b/cli/node/load-sk-example.sh new file mode 100755 index 0000000..bfaaff2 --- /dev/null +++ b/cli/node/load-sk-example.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +# Non-Boot Coordinator +go run . --mode coord --cfg cfg.buidler.toml importkey --privatekey 0x30f5fddb34cd4166adb2c6003fa6b18f380fd2341376be42cf1c7937004ac7a3 + +# Boot Coordinator +go run . --mode coord --cfg cfg.buidler.toml importkey --privatekey 0xa8a54b2d8197bc0b19bb8a084031be71835580a01e70a45a13babd16c9bc1563 diff --git a/cli/node/main.go b/cli/node/main.go index 833ac3c..92513a2 100644 --- a/cli/node/main.go +++ b/cli/node/main.go @@ -4,7 +4,10 @@ import ( "fmt" "os" "os/signal" + "strings" + ethKeystore "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/crypto" "github.com/hermeznetwork/hermez-node/config" "github.com/hermeznetwork/hermez-node/log" "github.com/hermeznetwork/hermez-node/node" @@ -15,18 +18,41 @@ import ( const ( flagCfg = "cfg" flagMode = "mode" + flagSK = "privatekey" modeSync = "sync" modeCoord = "coord" ) -func cmdInit(c *cli.Context) error { - log.Info("Init") - cfg, err := parseCli(c) +func cmdImportKey(c *cli.Context) error { + _cfg, err := parseCli(c) + if err != nil { + return tracerr.Wrap(fmt.Errorf("error parsing flags and config: %w", err)) + } + if _cfg.mode != node.ModeCoordinator { + return tracerr.Wrap(fmt.Errorf("importkey must use mode coordinator")) + } + cfg := _cfg.node + + scryptN := ethKeystore.StandardScryptN + scryptP := ethKeystore.StandardScryptP + if cfg.Coordinator.Debug.LightScrypt { + scryptN = ethKeystore.LightScryptN + scryptP = ethKeystore.LightScryptP + } + keyStore := ethKeystore.NewKeyStore(cfg.Coordinator.EthClient.Keystore.Path, + scryptN, scryptP) + hexKey := c.String(flagSK) + hexKey = strings.TrimPrefix(hexKey, "0x") + sk, err := crypto.HexToECDSA(hexKey) if err != nil { return tracerr.Wrap(err) } - fmt.Println("TODO", cfg) - return tracerr.Wrap(err) + acc, err := keyStore.ImportECDSA(sk, cfg.Coordinator.EthClient.Keystore.Password) + if err != nil { + return tracerr.Wrap(err) + } + log.Infow("Imported private key", "addr", acc.Address.Hex()) + return nil } func cmdRun(c *cli.Context) error { @@ -122,10 +148,16 @@ func main() { app.Commands = []*cli.Command{ { - Name: "init", + Name: "importkey", Aliases: []string{}, - Usage: "Initialize the hermez-node", - Action: cmdInit, + Usage: "Import ethereum private key", + Action: cmdImportKey, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: flagSK, + Usage: "ethereum `PRIVATE_KEY` in hex", + Required: true, + }}, }, { Name: "run", diff --git a/config/config.go b/config/config.go index 42e79da..0c63a0e 100644 --- a/config/config.go +++ b/config/config.go @@ -83,6 +83,10 @@ type Coordinator struct { // AttemptsDelay is delay between attempts do do an eth client // RPC call AttemptsDelay Duration `validate:"required"` + Keystore struct { + Path string `validate:"required"` + Password string `validate:"required"` + } `validate:"required"` } `validate:"required"` API struct { Coordinator bool @@ -91,6 +95,9 @@ type Coordinator struct { // BatchPath if set, specifies the path where batchInfo is stored // in JSON in every step/update of the pipeline BatchPath string + // LightScrypt if set, uses light parameters for the ethereum + // keystore encryption algorithm. + LightScrypt bool } } diff --git a/coordinator/coordinator.go b/coordinator/coordinator.go index 9f078d7..b10e229 100644 --- a/coordinator/coordinator.go +++ b/coordinator/coordinator.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "math/big" + "os" "strings" "sync" "time" @@ -111,6 +112,12 @@ func NewCoordinator(cfg Config, cfg.EthClientAttempts)) } + if cfg.DebugBatchPath != "" { + if err := os.MkdirAll(cfg.DebugBatchPath, 0744); err != nil { + return nil, tracerr.Wrap(err) + } + } + purger := Purger{ cfg: cfg.Purger, lastPurgeBlock: 0, @@ -147,9 +154,10 @@ func NewCoordinator(cfg Config, return &c, nil } -func (c *Coordinator) newPipeline(ctx context.Context) (*Pipeline, error) { +func (c *Coordinator) newPipeline(ctx context.Context, + stats *synchronizer.Stats) (*Pipeline, error) { return NewPipeline(ctx, c.cfg, c.historyDB, c.l2DB, c.txSelector, - c.batchBuilder, c.purger, c.txManager, c.provers, &c.consts) + c.batchBuilder, c.purger, c.txManager, c.provers, stats, &c.consts) } // MsgSyncBlock indicates an update to the Synchronizer stats @@ -226,7 +234,7 @@ func (c *Coordinator) syncStats(ctx context.Context, stats *synchronizer.Stats) stats.Eth.LastBlock.Num, "batch", stats.Sync.LastBatch) batchNum := common.BatchNum(stats.Sync.LastBatch) var err error - if c.pipeline, err = c.newPipeline(ctx); err != nil { + if c.pipeline, err = c.newPipeline(ctx, stats); err != nil { return tracerr.Wrap(err) } if err := c.pipeline.Start(batchNum, stats.Sync.LastForgeL1TxsNum, @@ -295,22 +303,16 @@ func (c *Coordinator) handleStopPipeline(ctx context.Context, reason string) err func (c *Coordinator) handleMsg(ctx context.Context, msg interface{}) error { switch msg := msg.(type) { case MsgSyncBlock: - if err := c.handleMsgSyncBlock(ctx, &msg); common.IsErrDone(err) { - return nil - } else if err != nil { + if err := c.handleMsgSyncBlock(ctx, &msg); err != nil { return tracerr.Wrap(fmt.Errorf("Coordinator.handleMsgSyncBlock error: %w", err)) } case MsgSyncReorg: - if err := c.handleReorg(ctx, &msg.Stats); common.IsErrDone(err) { - return nil - } else if err != nil { + if err := c.handleReorg(ctx, &msg.Stats); err != nil { return tracerr.Wrap(fmt.Errorf("Coordinator.handleReorg error: %w", err)) } case MsgStopPipeline: log.Infow("Coordinator received MsgStopPipeline", "reason", msg.Reason) - if err := c.handleStopPipeline(ctx, msg.Reason); common.IsErrDone(err) { - return nil - } else if err != nil { + if err := c.handleStopPipeline(ctx, msg.Reason); err != nil { return tracerr.Wrap(fmt.Errorf("Coordinator.handleStopPipeline: %w", err)) } default: @@ -341,7 +343,9 @@ func (c *Coordinator) Start() { c.wg.Done() return case msg := <-c.msgCh: - if err := c.handleMsg(c.ctx, msg); err != nil { + if err := c.handleMsg(c.ctx, msg); c.ctx.Err() != nil { + continue + } else if err != nil { log.Errorw("Coordinator.handleMsg", "err", err) waitDuration = time.Duration(c.cfg.SyncRetryInterval) continue @@ -352,7 +356,9 @@ func (c *Coordinator) Start() { waitDuration = time.Duration(longWaitDuration) continue } - if err := c.syncStats(c.ctx, c.stats); err != nil { + if err := c.syncStats(c.ctx, c.stats); c.ctx.Err() != nil { + continue + } else if err != nil { log.Errorw("Coordinator.syncStats", "err", err) waitDuration = time.Duration(c.cfg.SyncRetryInterval) continue @@ -456,7 +462,8 @@ func (t *TxManager) rollupForgeBatch(ctx context.Context, batchInfo *BatchInfo) return tracerr.Wrap(err) } log.Errorw("TxManager ethClient.RollupForgeBatch", - "attempt", attempt, "err", err, "block", t.lastBlock) + "attempt", attempt, "err", err, "block", t.lastBlock, + "batchNum", batchInfo.BatchNum) } else { break } @@ -484,6 +491,9 @@ func (t *TxManager) ethTransactionReceipt(ctx context.Context, batchInfo *BatchI var err error for attempt := 0; attempt < t.cfg.EthClientAttempts; attempt++ { receipt, err = t.ethClient.EthTransactionReceipt(ctx, txHash) + if ctx.Err() != nil { + continue + } if err != nil { log.Errorw("TxManager ethClient.EthTransactionReceipt", "attempt", attempt, "err", err) @@ -621,6 +631,7 @@ func NewPipeline(ctx context.Context, purger *Purger, txManager *TxManager, provers []prover.Client, + stats *synchronizer.Stats, scConsts *synchronizer.SCConsts, ) (*Pipeline, error) { proversPool := NewProversPool(len(provers)) @@ -647,6 +658,7 @@ func NewPipeline(ctx context.Context, purger: purger, txManager: txManager, consts: *scConsts, + stats: *stats, statsCh: make(chan synchronizer.Stats, queueLen), }, nil } @@ -697,7 +709,7 @@ func (p *Pipeline) Start(batchNum common.BatchNum, lastForgeL1TxsNum int64, for { select { case <-p.ctx.Done(): - log.Debug("Pipeline forgeBatch loop done") + log.Info("Pipeline forgeBatch loop done") p.wg.Done() return case syncStats := <-p.statsCh: @@ -705,7 +717,7 @@ func (p *Pipeline) Start(batchNum common.BatchNum, lastForgeL1TxsNum int64, default: batchNum = p.batchNum + 1 batchInfo, err := p.forgeBatch(p.ctx, batchNum, selectionConfig) - if common.IsErrDone(err) { + if p.ctx.Err() != nil { continue } else if err != nil { log.Errorw("forgeBatch", "err", err) @@ -713,14 +725,16 @@ func (p *Pipeline) Start(batchNum common.BatchNum, lastForgeL1TxsNum int64, } // 6. Wait for an available server proof (blocking call) serverProof, err := p.proversPool.Get(p.ctx) - if common.IsErrDone(err) { + if p.ctx.Err() != nil { continue } else if err != nil { log.Errorw("proversPool.Get", "err", err) continue } batchInfo.ServerProof = serverProof - if err := p.sendServerProof(p.ctx, batchInfo); err != nil { + if err := p.sendServerProof(p.ctx, batchInfo); p.ctx.Err() != nil { + continue + } else if err != nil { log.Errorw("sendServerProof", "err", err) batchInfo.ServerProof = nil p.proversPool.Add(serverProof) @@ -737,17 +751,17 @@ func (p *Pipeline) Start(batchNum common.BatchNum, lastForgeL1TxsNum int64, for { select { case <-p.ctx.Done(): - log.Debug("Pipeline waitServerProofSendEth loop done") + log.Info("Pipeline waitServerProofSendEth loop done") p.wg.Done() return case batchInfo := <-batchChSentServerProof: err := p.waitServerProof(p.ctx, batchInfo) - if common.IsErrDone(err) { - continue - } // We are done with this serverProof, add it back to the pool p.proversPool.Add(batchInfo.ServerProof) batchInfo.ServerProof = nil + if p.ctx.Err() != nil { + continue + } if err != nil { log.Errorw("waitServerProof", "err", err) continue @@ -765,7 +779,7 @@ func (p *Pipeline) Stop(ctx context.Context) { log.Fatal("Pipeline already stopped") } p.started = false - log.Debug("Stopping Pipeline...") + log.Info("Stopping Pipeline...") p.cancel() p.wg.Wait() for _, prover := range p.provers { @@ -899,7 +913,7 @@ func (p *Pipeline) waitServerProof(ctx context.Context, batchInfo *BatchInfo) er } batchInfo.Proof = proof batchInfo.PublicInputs = pubInputs - batchInfo.ForgeBatchArgs = p.prepareForgeBatchArgs(batchInfo) + batchInfo.ForgeBatchArgs = prepareForgeBatchArgs(batchInfo) batchInfo.TxStatus = TxStatusPending p.cfg.debugBatchStore(batchInfo) return nil @@ -921,7 +935,7 @@ func (p *Pipeline) shouldL1L2Batch() bool { return false } -func (p *Pipeline) prepareForgeBatchArgs(batchInfo *BatchInfo) *eth.RollupForgeBatchArgs { +func prepareForgeBatchArgs(batchInfo *BatchInfo) *eth.RollupForgeBatchArgs { proof := batchInfo.Proof zki := batchInfo.ZKInputs return ð.RollupForgeBatchArgs{ diff --git a/coordinator/coordinator_test.go b/coordinator/coordinator_test.go index 16cfcc9..21fa24a 100644 --- a/coordinator/coordinator_test.go +++ b/coordinator/coordinator_test.go @@ -10,7 +10,10 @@ import ( "testing" "time" + ethKeystore "github.com/ethereum/go-ethereum/accounts/keystore" ethCommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" "github.com/hermeznetwork/hermez-node/batchbuilder" "github.com/hermeznetwork/hermez-node/common" dbUtils "github.com/hermeznetwork/hermez-node/db" @@ -26,6 +29,7 @@ import ( "github.com/hermeznetwork/hermez-node/txprocessor" "github.com/hermeznetwork/hermez-node/txselector" "github.com/hermeznetwork/tracerr" + "github.com/iden3/go-merkletree" "github.com/iden3/go-merkletree/db/pebble" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -428,8 +432,9 @@ func TestPipelineShouldL1L2Batch(t *testing.T) { ctx := context.Background() ethClient := test.NewClient(true, &timer, &bidder, ethClientSetup) modules := newTestModules(t) + var stats synchronizer.Stats coord := newTestCoordinator(t, forger, ethClient, ethClientSetup, modules) - pipeline, err := coord.newPipeline(ctx) + pipeline, err := coord.newPipeline(ctx, &stats) require.NoError(t, err) pipeline.vars = coord.vars @@ -439,8 +444,6 @@ func TestPipelineShouldL1L2Batch(t *testing.T) { l1BatchTimeoutPerc := pipeline.cfg.L1BatchTimeoutPerc l1BatchTimeout := ethClientSetup.RollupVariables.ForgeL1L2BatchTimeout - var stats synchronizer.Stats - startBlock := int64(100) // @@ -576,11 +579,6 @@ func TestPipeline1(t *testing.T) { modules := newTestModules(t) coord := newTestCoordinator(t, forger, ethClient, ethClientSetup, modules) sync := newTestSynchronizer(t, ethClient, ethClientSetup, modules) - pipeline, err := coord.newPipeline(ctx) - require.NoError(t, err) - - require.NotNil(t, sync) - require.NotNil(t, pipeline) // preload the synchronier (via the test ethClient) some tokens and // users with positive balances @@ -589,6 +587,9 @@ func TestPipeline1(t *testing.T) { batchNum := common.BatchNum(syncStats.Sync.LastBatch) syncSCVars := sync.SCVars() + pipeline, err := coord.newPipeline(ctx, syncStats) + require.NoError(t, err) + // Insert some l2txs in the Pool setPool := ` Type: PoolL2 @@ -713,6 +714,80 @@ func TestCoordinatorStress(t *testing.T) { coord.Stop() } +func TestRollupForgeBatch(t *testing.T) { + if os.Getenv("TEST_ROLLUP_FORGE_BATCH") == "" { + return + } + const web3URL = "http://localhost:8545" + const password = "test" + addr := ethCommon.HexToAddress("0xb4124ceb3451635dacedd11767f004d8a28c6ee7") + sk, err := crypto.HexToECDSA( + "a8a54b2d8197bc0b19bb8a084031be71835580a01e70a45a13babd16c9bc1563") + require.NoError(t, err) + rollupAddr := ethCommon.HexToAddress("0x8EEaea23686c319133a7cC110b840d1591d9AeE0") + pathKeystore, err := ioutil.TempDir("", "tmpKeystore") + require.NoError(t, err) + deleteme = append(deleteme, pathKeystore) + ctx := context.Background() + batchInfo := &BatchInfo{} + proofClient := &prover.MockClient{} + chainID := uint16(0) + + ethClient, err := ethclient.Dial(web3URL) + require.NoError(t, err) + ethCfg := eth.EthereumConfig{ + CallGasLimit: 300000, + DeployGasLimit: 1000000, + GasPriceDiv: 100, + ReceiptTimeout: 60 * time.Second, + IntervalReceiptLoop: 500 * time.Millisecond, + } + scryptN := ethKeystore.LightScryptN + scryptP := ethKeystore.LightScryptP + keyStore := ethKeystore.NewKeyStore(pathKeystore, + scryptN, scryptP) + account, err := keyStore.ImportECDSA(sk, password) + require.NoError(t, err) + require.Equal(t, account.Address, addr) + err = keyStore.Unlock(account, password) + require.NoError(t, err) + + client, err := eth.NewClient(ethClient, &account, keyStore, ð.ClientConfig{ + Ethereum: ethCfg, + Rollup: eth.RollupConfig{ + Address: rollupAddr, + }, + Auction: eth.AuctionConfig{ + Address: ethCommon.Address{}, + TokenHEZ: eth.TokenConfig{ + Address: ethCommon.Address{}, + Name: "HEZ", + }, + }, + WDelayer: eth.WDelayerConfig{ + Address: ethCommon.Address{}, + }, + }) + require.NoError(t, err) + + zkInputs := common.NewZKInputs(chainID, 100, 24, 512, 32, big.NewInt(1)) + zkInputs.Metadata.NewStateRootRaw = &merkletree.Hash{1} + zkInputs.Metadata.NewExitRootRaw = &merkletree.Hash{2} + batchInfo.ZKInputs = zkInputs + err = proofClient.CalculateProof(ctx, batchInfo.ZKInputs) + require.NoError(t, err) + + proof, pubInputs, err := proofClient.GetProof(ctx) + require.NoError(t, err) + batchInfo.Proof = proof + batchInfo.PublicInputs = pubInputs + + batchInfo.ForgeBatchArgs = prepareForgeBatchArgs(batchInfo) + _, err = client.RollupForgeBatch(batchInfo.ForgeBatchArgs) + require.NoError(t, err) + batchInfo.Proof = proof +} + // TODO: Test Reorg // TODO: Test Pipeline // TODO: Test TxMonitor diff --git a/db/statedb/statedb_test.go b/db/statedb/statedb_test.go index f9a41ca..d1d8412 100644 --- a/db/statedb/statedb_test.go +++ b/db/statedb/statedb_test.go @@ -112,6 +112,10 @@ func TestNewStateDBIntermediateState(t *testing.T) { sdb, err = NewStateDB(dir, 128, TypeTxSelector, 0) assert.NoError(t, err) + bn, err = sdb.db.GetCurrentBatch() + assert.NoError(t, err) + assert.Equal(t, common.BatchNum(1), bn) + v, err = sdb.db.DB().Get(k0) assert.NoError(t, err) assert.Equal(t, v0, v) diff --git a/eth/client.go b/eth/client.go index 4401b0d..f86fccf 100644 --- a/eth/client.go +++ b/eth/client.go @@ -65,7 +65,10 @@ type ClientConfig struct { // NewClient creates a new Client to interact with Ethereum and the Hermez smart contracts. func NewClient(client *ethclient.Client, account *accounts.Account, ks *ethKeystore.KeyStore, cfg *ClientConfig) (*Client, error) { - ethereumClient := NewEthereumClient(client, account, ks, &cfg.Ethereum) + ethereumClient, err := NewEthereumClient(client, account, ks, &cfg.Ethereum) + if err != nil { + return nil, tracerr.Wrap(err) + } auctionClient, err := NewAuctionClient(ethereumClient, cfg.Auction.Address, cfg.Auction.TokenHEZ) if err != nil { return nil, tracerr.Wrap(err) diff --git a/eth/ethereum.go b/eth/ethereum.go index 4327307..d2b2426 100644 --- a/eth/ethereum.go +++ b/eth/ethereum.go @@ -73,6 +73,7 @@ type EthereumConfig struct { // EthereumClient is an ethereum client to call Smart Contract methods and check blockchain information. type EthereumClient struct { client *ethclient.Client + chainID *big.Int account *accounts.Account ks *ethKeystore.KeyStore ReceiptTimeout time.Duration @@ -82,7 +83,7 @@ type EthereumClient struct { // NewEthereumClient creates a EthereumClient instance. The account is not mandatory (it can // be nil). If the account is nil, CallAuth will fail with ErrAccountNil. -func NewEthereumClient(client *ethclient.Client, account *accounts.Account, ks *ethKeystore.KeyStore, config *EthereumConfig) *EthereumClient { +func NewEthereumClient(client *ethclient.Client, account *accounts.Account, ks *ethKeystore.KeyStore, config *EthereumConfig) (*EthereumClient, error) { if config == nil { config = &EthereumConfig{ CallGasLimit: defaultCallGasLimit, @@ -92,7 +93,7 @@ func NewEthereumClient(client *ethclient.Client, account *accounts.Account, ks * IntervalReceiptLoop: defaultIntervalReceiptLoop, } } - return &EthereumClient{ + c := &EthereumClient{ client: client, account: account, ks: ks, @@ -100,6 +101,12 @@ func NewEthereumClient(client *ethclient.Client, account *accounts.Account, ks * config: config, opts: newCallOpts(), } + chainID, err := c.EthChainID() + if err != nil { + return nil, tracerr.Wrap(err) + } + c.chainID = chainID + return c, nil } // EthChainID returns the ChainID of the ethereum network @@ -147,8 +154,7 @@ func (c *EthereumClient) CallAuth(gasLimit uint64, gasPrice.Add(gasPrice, inc) log.Debugw("Transaction metadata", "gasPrice", gasPrice) - // TODO: Set the correct chainID - auth, err := bind.NewKeyStoreTransactorWithChainID(c.ks, *c.account, big.NewInt(0)) + auth, err := bind.NewKeyStoreTransactorWithChainID(c.ks, *c.account, c.chainID) if err != nil { return nil, tracerr.Wrap(err) } diff --git a/eth/ethereum_test.go b/eth/ethereum_test.go index 5162344..1813894 100644 --- a/eth/ethereum_test.go +++ b/eth/ethereum_test.go @@ -11,7 +11,8 @@ import ( func TestEthERC20(t *testing.T) { ethClient, err := ethclient.Dial(ethClientDialURL) require.Nil(t, err) - client := NewEthereumClient(ethClient, auxAccount, ks, nil) + client, err := NewEthereumClient(ethClient, auxAccount, ks, nil) + require.Nil(t, err) consts, err := client.EthERC20Consts(tokenHEZAddressConst) require.Nil(t, err) diff --git a/eth/main_test.go b/eth/main_test.go index 9b0242a..d04f879 100644 --- a/eth/main_test.go +++ b/eth/main_test.go @@ -164,7 +164,10 @@ func TestMain(m *testing.M) { } // Controllable Governance Address - ethereumClientGov := NewEthereumClient(ethClient, governanceAccount, ks, nil) + ethereumClientGov, err := NewEthereumClient(ethClient, governanceAccount, ks, nil) + if err != nil { + log.Fatal(err) + } auctionClient, err = NewAuctionClient(ethereumClientGov, auctionAddressConst, tokenHEZ) if err != nil { log.Fatal(err) @@ -186,10 +189,22 @@ func TestMain(m *testing.M) { log.Fatal(err) } - ethereumClientEmergencyCouncil = NewEthereumClient(ethClient, emergencyCouncilAccount, ks, nil) - ethereumClientAux = NewEthereumClient(ethClient, auxAccount, ks, nil) - ethereumClientAux2 = NewEthereumClient(ethClient, aux2Account, ks, nil) - ethereumClientHermez = NewEthereumClient(ethClient, hermezRollupTestAccount, ks, nil) + ethereumClientEmergencyCouncil, err = NewEthereumClient(ethClient, emergencyCouncilAccount, ks, nil) + if err != nil { + log.Fatal(err) + } + ethereumClientAux, err = NewEthereumClient(ethClient, auxAccount, ks, nil) + if err != nil { + log.Fatal(err) + } + ethereumClientAux2, err = NewEthereumClient(ethClient, aux2Account, ks, nil) + if err != nil { + log.Fatal(err) + } + ethereumClientHermez, err = NewEthereumClient(ethClient, hermezRollupTestAccount, ks, nil) + if err != nil { + log.Fatal(err) + } exitVal = m.Run() } diff --git a/node/node.go b/node/node.go index 0a3df78..1d21c7b 100644 --- a/node/node.go +++ b/node/node.go @@ -7,6 +7,8 @@ import ( "sync" "time" + "github.com/ethereum/go-ethereum/accounts" + ethKeystore "github.com/ethereum/go-ethereum/accounts/keystore" ethCommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/gin-contrib/cors" @@ -87,6 +89,8 @@ func NewNode(mode Mode, cfg *config.Node) (*Node, error) { return nil, tracerr.Wrap(err) } var ethCfg eth.EthereumConfig + var account *accounts.Account + var keyStore *ethKeystore.KeyStore if mode == ModeCoordinator { ethCfg = eth.EthereumConfig{ CallGasLimit: cfg.Coordinator.EthClient.CallGasLimit, @@ -95,8 +99,31 @@ func NewNode(mode Mode, cfg *config.Node) (*Node, error) { ReceiptTimeout: cfg.Coordinator.EthClient.ReceiptTimeout.Duration, IntervalReceiptLoop: cfg.Coordinator.EthClient.ReceiptLoopInterval.Duration, } + + scryptN := ethKeystore.StandardScryptN + scryptP := ethKeystore.StandardScryptP + if cfg.Coordinator.Debug.LightScrypt { + scryptN = ethKeystore.LightScryptN + scryptP = ethKeystore.LightScryptP + } + keyStore = ethKeystore.NewKeyStore(cfg.Coordinator.EthClient.Keystore.Path, + scryptN, scryptP) + if !keyStore.HasAddress(cfg.Coordinator.ForgerAddress) { + return nil, tracerr.Wrap(fmt.Errorf( + "ethereum keystore doesn't have the key for address %v", + cfg.Coordinator.ForgerAddress)) + } + account = &accounts.Account{ + Address: cfg.Coordinator.ForgerAddress, + } + if err := keyStore.Unlock(*account, + cfg.Coordinator.EthClient.Keystore.Password); err != nil { + return nil, tracerr.Wrap(err) + } + log.Infow("Forger ethereum account unlocked in the keystore", + "addr", cfg.Coordinator.ForgerAddress) } - client, err := eth.NewClient(ethClient, nil, nil, ð.ClientConfig{ + client, err := eth.NewClient(ethClient, account, keyStore, ð.ClientConfig{ Ethereum: ethCfg, Rollup: eth.RollupConfig{ Address: cfg.SmartContracts.Rollup,