arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
Load ethereum private key

Load an ethereum keystore when the node is started in coordinator mode.  The
private key corresponding to the forger address must be imported into the
keystore before running the node in coordinator mode.  You can see an examples
in `cli/node/load-sk-example.sh`.
Eduard S eduard@iden3.io
Tue, 29 Dec 2020 17:21:45 +0100
commit

42791181a1dc050b5a88be42a82f21a0218983c4

parent

88f924e9dd54ec2aefc00387c7c4198030c79339

M cli/node/cfg.buidler.toml → 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 @@ [Coordinator.BatchBuilder]

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
A 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
M cli/node/main.go → 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 @@

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) + } + acc, err := keyStore.ImportECDSA(sk, cfg.Coordinator.EthClient.Keystore.Password) if err != nil { return tracerr.Wrap(err) } - fmt.Println("TODO", cfg) - 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 @@ }

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",
M config/config.go → config/config.go

@@ -83,6 +83,10 @@ Attempts int `validate:"required"`

// 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 @@ Debug 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 } }
M coordinator/coordinator.go → coordinator/coordinator.go

@@ -4,6 +4,7 @@ import (

"context" "fmt" "math/big" + "os" "strings" "sync" "time"

@@ -111,6 +112,12 @@ return nil, tracerr.Wrap(fmt.Errorf("invalid value for Config.EthClientAttempts (%v < 1)",

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 @@ c.txManager = txManager

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 @@ log.Infow("Coordinator: forging state begin", "block",

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) 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 @@ log.Info("Coordinator done")

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 @@ if c.stats == nil {

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 @@ "block", t.lastBlock)

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 @@ var receipt *types.Receipt

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 @@ batchBuilder *batchbuilder.BatchBuilder,

purger *Purger, txManager *TxManager, provers []prover.Client, + stats *synchronizer.Stats, scConsts *synchronizer.SCConsts, ) (*Pipeline, error) { proversPool := NewProversPool(len(provers))

@@ -647,6 +658,7 @@ proversPool: proversPool,

purger: purger, txManager: txManager, consts: *scConsts, + stats: *stats, statsCh: make(chan synchronizer.Stats, queueLen), }, nil }

@@ -697,7 +709,7 @@ go func() {

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 @@ p.stats = syncStats

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 @@ continue

} // 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 @@ go func() {

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 @@ if !p.started {

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 @@ return tracerr.Wrap(err)

} 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 @@ }

return false } -func (p *Pipeline) prepareForgeBatchArgs(batchInfo *BatchInfo) *eth.RollupForgeBatchArgs { +func prepareForgeBatchArgs(batchInfo *BatchInfo) *eth.RollupForgeBatchArgs { proof := batchInfo.Proof zki := batchInfo.ZKInputs return &eth.RollupForgeBatchArgs{
M coordinator/coordinator_test.go → coordinator/coordinator_test.go

@@ -10,7 +10,10 @@ "sync"

"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 @@ "github.com/hermeznetwork/hermez-node/test/til"

"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 @@ var timer timer

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

@@ -438,8 +443,6 @@ require.Equal(t, 0.5, pipeline.cfg.L1BatchTimeoutPerc)

require.Equal(t, int64(9), ethClientSetup.RollupVariables.ForgeL1L2BatchTimeout) l1BatchTimeoutPerc := pipeline.cfg.L1BatchTimeoutPerc l1BatchTimeout := ethClientSetup.RollupVariables.ForgeL1L2BatchTimeout - - var stats synchronizer.Stats startBlock := int64(100)

@@ -576,11 +579,6 @@ ethClient := test.NewClient(true, &timer, &bidder, ethClientSetup)

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 @@ syncStats := sync.Stats()

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

@@ -711,6 +712,80 @@

cancel() wg.Wait() 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, &eth.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
M db/statedb/statedb_test.go → db/statedb/statedb_test.go

@@ -112,6 +112,10 @@ // executing a Reset (discarding the last 'testkey1'&'testvalue1' data)

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)
M eth/client.go → eth/client.go

@@ -65,7 +65,10 @@ }

// 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)
M eth/ethereum.go → eth/ethereum.go

@@ -73,6 +73,7 @@

// 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 @@ }

// 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 @@ ReceiptTimeout: defaultReceiptTimeout,

IntervalReceiptLoop: defaultIntervalReceiptLoop, } } - return &EthereumClient{ + c := &EthereumClient{ client: client, account: account, ks: ks,

@@ -100,6 +101,12 @@ ReceiptTimeout: config.ReceiptTimeout * time.Second,

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 @@ inc.Div(inc, new(big.Int).SetUint64(c.config.GasPriceDiv))

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) }
M eth/ethereum_test.go → eth/ethereum_test.go

@@ -11,7 +11,8 @@

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)
M eth/main_test.go → eth/main_test.go

@@ -164,7 +164,10 @@ log.Fatal(err)

} // 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 @@ if err != nil {

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() }
M node/node.go → node/node.go

@@ -7,6 +7,8 @@ "net/http"

"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 @@ if err != nil {

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 @@ GasPriceDiv: cfg.Coordinator.EthClient.GasPriceDiv,

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, &eth.ClientConfig{ + client, err := eth.NewClient(ethClient, account, keyStore, &eth.ClientConfig{ Ethereum: ethCfg, Rollup: eth.RollupConfig{ Address: cfg.SmartContracts.Rollup,