diff --git a/internal/cli/server/chains/developer.go b/internal/cli/server/chains/developer.go new file mode 100644 index 0000000000000000000000000000000000000000..61a8a186fdbdefd733ebe6882b3418a27083a572 --- /dev/null +++ b/internal/cli/server/chains/developer.go @@ -0,0 +1,47 @@ +package chains + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" +) + +// GetDeveloperChain returns the developer mode configs. +func GetDeveloperChain(period uint64, faucet common.Address) *Chain { + // Override the default period to the user requested one + config := *params.AllCliqueProtocolChanges + config.Clique = ¶ms.CliqueConfig{ + Period: period, + Epoch: config.Clique.Epoch, + } + + // Assemble and return the chain having genesis with the + // precompiles and faucet pre-funded + return &Chain{ + Hash: common.Hash{}, + NetworkId: 1337, + Genesis: &core.Genesis{ + Config: &config, + ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...), + GasLimit: 11500000, + BaseFee: big.NewInt(params.InitialBaseFee), + Difficulty: big.NewInt(1), + Alloc: map[common.Address]core.GenesisAccount{ + common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover + common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256 + common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD + common.BytesToAddress([]byte{4}): {Balance: big.NewInt(1)}, // Identity + common.BytesToAddress([]byte{5}): {Balance: big.NewInt(1)}, // ModExp + common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd + common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul + common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing + common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b + faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))}, + }, + }, + Bootnodes: []string{}, + } +} diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index 457ee53aa9973c24443f4611d7db2b26603e28f7..98bafb5a92f92a7375637a4b2cce9779c873b4a1 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -91,6 +91,9 @@ type Config struct { // GRPC has the grpc server related settings GRPC *GRPCConfig + + // Developer has the developer mode related settings + Developer *DeveloperConfig } type P2PConfig struct { @@ -365,6 +368,14 @@ type AccountsConfig struct { UseLightweightKDF bool `hcl:"use-lightweight-kdf,optional"` } +type DeveloperConfig struct { + // Enabled enables the developer mode + Enabled bool `hcl:"dev,optional"` + + // Period is the block period to use in developer mode + Period uint64 `hcl:"period,optional"` +} + func DefaultConfig() *Config { return &Config{ Chain: "mainnet", @@ -486,6 +497,10 @@ func DefaultConfig() *Config { GRPC: &GRPCConfig{ Addr: ":3131", }, + Developer: &DeveloperConfig{ + Enabled: false, + Period: 0, + }, } } @@ -573,6 +588,9 @@ func readConfigFile(path string) (*Config, error) { } func (c *Config) loadChain() error { + if c.Developer.Enabled { + return nil + } chain, ok := chains.GetChain(c.Chain) if !ok { return fmt.Errorf("chain '%s' not found", c.Chain) @@ -585,7 +603,7 @@ func (c *Config) loadChain() error { } // depending on the chain we have different cache values - if c.Chain != "mainnet" { + if c.Chain == "mainnet" { c.Cache.Cache = 4096 } else { c.Cache.Cache = 1024 @@ -599,8 +617,13 @@ func (c *Config) buildEth() (*ethconfig.Config, error) { return nil, err } n := ethconfig.Defaults - n.NetworkId = c.chain.NetworkId - n.Genesis = c.chain.Genesis + + // only update for non-developer mode as we don't yet + // have the chain object for it. + if !c.Developer.Enabled { + n.NetworkId = c.chain.NetworkId + n.Genesis = c.chain.Genesis + } n.HeimdallURL = c.Heimdall.URL n.WithoutHeimdall = c.Heimdall.Without @@ -640,6 +663,27 @@ func (c *Config) buildEth() (*ethconfig.Config, error) { } } + // update for developer mode + if c.Developer.Enabled { + // get developer mode chain config + c.chain = chains.GetDeveloperChain(c.Developer.Period, n.Miner.Etherbase) + + // update the parameters + n.NetworkId = c.chain.NetworkId + n.Genesis = c.chain.Genesis + + // Update cache + c.Cache.Cache = 1024 + + // Update sync mode + c.SyncMode = "full" + + // update miner gas price + if n.Miner.GasPrice == nil { + n.Miner.GasPrice = big.NewInt(1) + } + } + // discovery (this params should be in node.Config) { n.EthDiscoveryURLs = c.P2P.Discovery.DNS @@ -788,6 +832,20 @@ func (c *Config) buildNode() (*node.Config, error) { GraphQLVirtualHosts: c.JsonRPC.VHost, } + // dev mode + if c.Developer.Enabled { + cfg.UseLightweightKDF = true + + // disable p2p networking + c.P2P.NoDiscover = true + cfg.P2P.ListenAddr = "" + cfg.P2P.NoDial = true + cfg.P2P.DiscoveryV5 = false + + // data dir + cfg.DataDir = "" + } + // enable jsonrpc endpoints { if c.JsonRPC.Http.Enabled { diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index 09e5a7bf780f42156c745b7fe6c1419fd6204df6..7403fc6c88206b912b86dce1eaecd33879f85eec 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -461,5 +461,17 @@ func (c *Command) Flags() *flagset.Flagset { Usage: "Address and port to bind the GRPC server", Value: &c.cliConfig.GRPC.Addr, }) + + // developer + f.BoolFlag(&flagset.BoolFlag{ + Name: "dev", + Usage: "Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled", + Value: &c.cliConfig.Developer.Enabled, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "dev.period", + Usage: "Block period to use in developer mode (0 = mine only if transaction pending)", + Value: &c.cliConfig.Developer.Period, + }) return f }