From dd08b8fd0026e00410845b735d0541949269a53f Mon Sep 17 00:00:00 2001 From: Qi Zhou Date: Mon, 7 Mar 2022 18:59:03 -0800 Subject: [PATCH] update galileo testnet with 4 validators --- cmd/geth/main.go | 2 + cmd/utils/flags.go | 18 +++++++ consensus/tendermint/adapter/store.go | 11 ++-- consensus/tendermint/tendermint.go | 78 +++++++++++++-------------- core/genesis.go | 9 +++- eth/backend.go | 16 ++++++ eth/ethconfig/config.go | 8 +-- 7 files changed, 94 insertions(+), 48 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 040d136db1ba..fac09625b289 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -149,6 +149,8 @@ var ( utils.Web3QTestnetFlag, utils.Web3QGalileoFlag, utils.Web3QMainnetFlag, + utils.ValPortFlag, + utils.ValNodeKeyFlag, utils.VMEnableDebugFlag, utils.NetworkIdFlag, utils.EthStatsURLFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 58dc945e9136..412bb8bf4c17 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -173,6 +173,14 @@ var ( Name: "web3q_mainnet", Usage: "Web3Q mainnet", } + ValPortFlag = cli.Int64Flag{ + Name: "validator.port", + Usage: "Validator P2P port", + } + ValNodeKeyFlag = cli.StringFlag{ + Name: "validator.nodekey", + Usage: "Validator P2P node key file", + } DeveloperFlag = cli.BoolFlag{ Name: "dev", Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled", @@ -1412,6 +1420,15 @@ func setEthash(ctx *cli.Context, cfg *ethconfig.Config) { } } +func setTendermint(ctx *cli.Context, cfg *ethconfig.Config) { + if ctx.GlobalIsSet(ValPortFlag.Name) { + cfg.ValP2pPort = ctx.GlobalUint(ValPortFlag.Name) + } + if ctx.GlobalIsSet(ValNodeKeyFlag.Name) { + cfg.ValNodeKey = ctx.GlobalString(ValNodeKeyFlag.Name) + } +} + func setMiner(ctx *cli.Context, cfg *miner.Config) { if ctx.GlobalIsSet(MinerNotifyFlag.Name) { cfg.Notify = strings.Split(ctx.GlobalString(MinerNotifyFlag.Name), ",") @@ -1522,6 +1539,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { setGPO(ctx, &cfg.GPO, ctx.GlobalString(SyncModeFlag.Name) == "light") setTxPool(ctx, &cfg.TxPool) setEthash(ctx, cfg) + setTendermint(ctx, cfg) setMiner(ctx, &cfg.Miner) setWhitelist(ctx, cfg) setLes(ctx, cfg) diff --git a/consensus/tendermint/adapter/store.go b/consensus/tendermint/adapter/store.go index b73d906811b4..10da859734b7 100644 --- a/consensus/tendermint/adapter/store.go +++ b/consensus/tendermint/adapter/store.go @@ -15,13 +15,13 @@ import ( type Store struct { chain *core.BlockChain verifyHeaderFunc func(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error - makeBlock func(parentHash common.Hash, coinbase common.Address, timestamp uint64) (block *types.FullBlock) + makeBlock func(parentHash common.Hash, coinbase common.Address, timestamp uint64) (block *types.Block, err error) } func NewStore( chain *core.BlockChain, verifyHeaderFunc func(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error, - makeBlock func(parentHash common.Hash, coinbase common.Address, timestamp uint64) (block *types.FullBlock)) *Store { + makeBlock func(parentHash common.Hash, coinbase common.Address, timestamp uint64) (block *types.Block, err error)) *Store { return &Store{chain: chain, verifyHeaderFunc: verifyHeaderFunc, makeBlock: makeBlock} } @@ -170,5 +170,10 @@ func (s *Store) MakeBlock(state *pbft.ChainState, height uint64, timestamp = pbft.MedianTime(commit, state.LastValidators) } - return s.makeBlock(state.LastBlockID, proposerAddress, timestamp) + block, err := s.makeBlock(state.LastBlockID, proposerAddress, timestamp) + if err != nil { + panic("failed to make a block") + } + + return &types.FullBlock{Block: block, LastCommit: commit} } diff --git a/consensus/tendermint/tendermint.go b/consensus/tendermint/tendermint.go index 4cb01585417c..22a68e2a44f0 100644 --- a/consensus/tendermint/tendermint.go +++ b/consensus/tendermint/tendermint.go @@ -20,11 +20,11 @@ package tendermint import ( "bytes" "context" - "crypto/ecdsa" "errors" "fmt" "io/ioutil" "math/big" + "os" "sync" "time" @@ -40,12 +40,12 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" p2pcrypto "github.com/libp2p/go-libp2p-core/crypto" + "github.com/libp2p/go-libp2p-core/peer" ) // Clique proof-of-authority protocol constants. @@ -137,28 +137,11 @@ func (c *Tendermint) Init(chain *core.BlockChain, makeBlock func(parent common.H c.rootCtxCancel = rootCtxCancel c.rootCtx = rootCtx - makeFullBlock := func(parentHash common.Hash, coinbase common.Address, timestamp uint64) *types.FullBlock { - log.Info("Making a block", "parent", parentHash) - block, err := makeBlock(parentHash, coinbase, timestamp) - if err != nil { - log.Warn("makeBlock", "err", err) - return nil - } - if block == nil { - log.Warn("makeBlock returns nil block") - return nil - } - parentHeader := chain.GetHeaderByHash(block.ParentHash()) - if parentHeader == nil { - return nil - } - return &types.FullBlock{Block: block, LastCommit: parentHeader.Commit} - } // datastore - store := adapter.NewStore(chain, c.VerifyHeader, makeFullBlock) + store := adapter.NewStore(chain, c.VerifyHeader, makeBlock) // p2p key - p2pPriv, err := loadP2pKey(c.config.NodeKeyPath) + p2pPriv, err := getOrCreateNodeKey(c.config.NodeKeyPath) if err != nil { return } @@ -226,38 +209,55 @@ func (c *Tendermint) Init(chain *core.BlockChain, makeBlock func(parent common.H log.Warn("consensusState.Start", "err", err) } + p2pserver.SetConsensusState(consensusState) + log.Info("Chamber consensus engine started", "networkd_id", c.config.NetworkID) return } -func loadP2pKey(filename string) (key p2pcrypto.PrivKey, err error) { - b, err := ioutil.ReadFile(filename) +func getOrCreateNodeKey(path string) (p2pcrypto.PrivKey, error) { + b, err := ioutil.ReadFile(path) if err != nil { - err = fmt.Errorf("failed to read node key: %w", err) - return - } - key, err = p2pcrypto.UnmarshalPrivateKey(b) - if err != nil { - err = fmt.Errorf("failed to unmarshal node key: %w", err) - return + if os.IsNotExist(err) { + log.Info("No node key found, generating a new one...", "path", path) + + priv, _, err := p2pcrypto.GenerateKeyPair(p2pcrypto.Ed25519, -1) + if err != nil { + panic(err) + } + + s, err := p2pcrypto.MarshalPrivateKey(priv) + if err != nil { + panic(err) + } + + err = ioutil.WriteFile(path, s, 0600) + if err != nil { + return nil, fmt.Errorf("failed to write node key: %w", err) + } + + return priv, nil + } else { + return nil, fmt.Errorf("failed to read node key: %w", err) + } } - return -} -// loadValidatorKey loads a serialized guardian key from disk. -func loadValidatorKey(filename string) (*ecdsa.PrivateKey, error) { - b, err := ioutil.ReadFile(filename) + priv, err := p2pcrypto.UnmarshalPrivateKey(b) if err != nil { - return nil, fmt.Errorf("failed to open file: %w", err) + return nil, fmt.Errorf("failed to unmarshal node key: %w", err) } - gk, err := crypto.ToECDSA(b) + peerID, err := peer.IDFromPrivateKey(priv) if err != nil { - return nil, fmt.Errorf("failed to deserialize raw key data: %w", err) + panic(err) } - return gk, nil + log.Info("Found existing node key", + "path", path, + "peerID", peerID) + + return priv, nil } // Author implements consensus.Engine, returning the Ethereum address recovered diff --git a/core/genesis.go b/core/genesis.go index 64ec74d583e8..c7ae34ef13e4 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -451,8 +451,13 @@ func DefaultWeb3QGalileoGenesisBlock() *Genesis { Alloc: map[common.Address]GenesisAccount{ common.HexToAddress("0x0E961a6A6235eFDB9a0F0BC753E395211B77cc28"): {Balance: new(big.Int).Mul(big.NewInt(1000000000000000000), big.NewInt(1000000000))}, // 1e9 Ether }, - NextValidators: []common.Address{common.HexToAddress("0xC7B6Ad1038b5a79c12B066d6E3e8972f3EceaDe7")}, - NextValidatorPowers: []uint64{1}, + NextValidators: []common.Address{ + common.HexToAddress("0xC7B6Ad1038b5a79c12B066d6E3e8972f3EceaDe7"), + common.HexToAddress("0x90a7bff0b4b11f365367d4c9fe084223c850b229"), + common.HexToAddress("0x9b29ad441b195b641aa0a45ad4085c51da62fe54"), + common.HexToAddress("0x1b47a4d3266213354d59ecaf338a4698177819d1"), + }, + NextValidatorPowers: []uint64{1, 1, 1, 1}, } } diff --git a/eth/backend.go b/eth/backend.go index 95269665fff7..baf901b1aee0 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -141,6 +141,22 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { return nil, genesisErr } + if chainConfig.Tendermint != nil { + // Setup default network id if it is empty. + if chainConfig.Tendermint.NetworkID == "" { + chainConfig.Tendermint.NetworkID = "evm_" + chainConfig.ChainID.String() + } + // Setup p2p port + if config.ValP2pPort != 0 { + chainConfig.Tendermint.P2pPort = config.ValP2pPort + } + // Setup p2p node key + // TODO: Use node key in default datadir + if config.ValNodeKey != "" { + chainConfig.Tendermint.NodeKeyPath = config.ValNodeKey + } + } + log.Info("Initialised chain configuration", "config", chainConfig) if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, stack.ResolvePath(config.TrieCleanCacheJournal)); err != nil { diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index e12c714fc090..4729a420c67c 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -209,6 +209,10 @@ type Config struct { // OverrideTerminalTotalDifficulty (TODO: remove after the fork) OverrideTerminalTotalDifficulty *big.Int `toml:",omitempty"` + + // Validator config + ValP2pPort uint + ValNodeKey string } // CreateConsensusEngine creates a consensus engine for the given chain configuration. @@ -218,10 +222,6 @@ func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, co if chainConfig.Clique != nil { engine = clique.New(chainConfig.Clique, db) } else if chainConfig.Tendermint != nil { - // Setup default network id if it is empty. - if chainConfig.Tendermint.NetworkID == "" { - chainConfig.Tendermint.NetworkID = "evm_" + chainConfig.ChainID.String() - } engine = tendermint.New(chainConfig.Tendermint) return engine } else {