From e8f229b82ef99213f8f84b8a71f752b236024494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Wed, 29 Aug 2018 12:21:12 +0300 Subject: [PATCH] cmd, core, eth, miner, params: configurable gas floor and ceil --- cmd/geth/main.go | 2 +- cmd/geth/usage.go | 1 + cmd/puppeth/module_node.go | 11 +++++++++-- cmd/puppeth/wizard_node.go | 6 +++++- cmd/utils/flags.go | 27 ++++++++++++++++----------- core/bench_test.go | 3 ++- core/block_validator.go | 22 ++++++++++++++-------- core/chain_makers.go | 2 +- eth/backend.go | 2 +- eth/config.go | 6 +++++- eth/gasprice/gasprice.go | 2 +- eth/gen_config.go | 12 ++++++++++++ internal/ethapi/api.go | 2 +- miner/miner.go | 4 ++-- miner/stress_clique.go | 2 ++ miner/stress_ethash.go | 2 ++ miner/worker.go | 9 +++++++-- miner/worker_test.go | 2 +- params/denomination.go | 16 +++++----------- params/protocol_params.go | 4 ---- 20 files changed, 88 insertions(+), 49 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 0ed67d0d57..4d7e98698c 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -101,6 +101,7 @@ var ( utils.MinerNotifyFlag, utils.MinerGasTargetFlag, utils.MinerLegacyGasTargetFlag, + utils.MinerGasLimitFlag, utils.MinerGasPriceFlag, utils.MinerLegacyGasPriceFlag, utils.MinerEtherbaseFlag, @@ -236,7 +237,6 @@ func init() { // Start system runtime metrics collection go metrics.CollectProcessMetrics(3 * time.Second) - utils.SetupNetwork(ctx) return nil } diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go index 2f8260e0f6..a674eca4f1 100644 --- a/cmd/geth/usage.go +++ b/cmd/geth/usage.go @@ -189,6 +189,7 @@ var AppHelpFlagGroups = []flagGroup{ utils.MinerNotifyFlag, utils.MinerGasPriceFlag, utils.MinerGasTargetFlag, + utils.MinerGasLimitFlag, utils.MinerEtherbaseFlag, utils.MinerExtraDataFlag, utils.MinerRecommitIntervalFlag, diff --git a/cmd/puppeth/module_node.go b/cmd/puppeth/module_node.go index 8ad41555e1..038152a3e4 100644 --- a/cmd/puppeth/module_node.go +++ b/cmd/puppeth/module_node.go @@ -42,7 +42,7 @@ ADD genesis.json /genesis.json RUN \ echo 'geth --cache 512 init /genesis.json' > geth.sh && \{{if .Unlock}} echo 'mkdir -p /root/.ethereum/keystore/ && cp /signer.json /root/.ethereum/keystore/' >> geth.sh && \{{end}} - echo $'exec geth --networkid {{.NetworkID}} --cache 512 --port {{.Port}} --maxpeers {{.Peers}} {{.LightFlag}} --ethstats \'{{.Ethstats}}\' {{if .Bootnodes}}--bootnodes {{.Bootnodes}}{{end}} {{if .Etherbase}}--miner.etherbase {{.Etherbase}} --mine --miner.threads 1{{end}} {{if .Unlock}}--unlock 0 --password /signer.pass --mine{{end}} --miner.gastarget {{.GasTarget}} --miner.gasprice {{.GasPrice}}' >> geth.sh + echo $'exec geth --networkid {{.NetworkID}} --cache 512 --port {{.Port}} --maxpeers {{.Peers}} {{.LightFlag}} --ethstats \'{{.Ethstats}}\' {{if .Bootnodes}}--bootnodes {{.Bootnodes}}{{end}} {{if .Etherbase}}--miner.etherbase {{.Etherbase}} --mine --miner.threads 1{{end}} {{if .Unlock}}--unlock 0 --password /signer.pass --mine{{end}} --miner.gastarget {{.GasTarget}} --miner.gaslimit {{.GasLimit}} --miner.gasprice {{.GasPrice}}' >> geth.sh ENTRYPOINT ["/bin/sh", "geth.sh"] ` @@ -68,6 +68,7 @@ services: - STATS_NAME={{.Ethstats}} - MINER_NAME={{.Etherbase}} - GAS_TARGET={{.GasTarget}} + - GAS_LIMIT={{.GasLimit}} - GAS_PRICE={{.GasPrice}} logging: driver: "json-file" @@ -104,6 +105,7 @@ func deployNode(client *sshClient, network string, bootnodes []string, config *n "Ethstats": config.ethstats, "Etherbase": config.etherbase, "GasTarget": uint64(1000000 * config.gasTarget), + "GasLimit": uint64(1000000 * config.gasLimit), "GasPrice": uint64(1000000000 * config.gasPrice), "Unlock": config.keyJSON != "", }) @@ -122,6 +124,7 @@ func deployNode(client *sshClient, network string, bootnodes []string, config *n "Ethstats": config.ethstats[:strings.Index(config.ethstats, ":")], "Etherbase": config.etherbase, "GasTarget": config.gasTarget, + "GasLimit": config.gasLimit, "GasPrice": config.gasPrice, }) files[filepath.Join(workdir, "docker-compose.yaml")] = composefile.Bytes() @@ -160,6 +163,7 @@ type nodeInfos struct { keyJSON string keyPass string gasTarget float64 + gasLimit float64 gasPrice float64 } @@ -175,8 +179,9 @@ func (info *nodeInfos) Report() map[string]string { } if info.gasTarget > 0 { // Miner or signer node - report["Gas limit (baseline target)"] = fmt.Sprintf("%0.3f MGas", info.gasTarget) report["Gas price (minimum accepted)"] = fmt.Sprintf("%0.3f GWei", info.gasPrice) + report["Gas floor (baseline target)"] = fmt.Sprintf("%0.3f MGas", info.gasTarget) + report["Gas ceil (target maximum)"] = fmt.Sprintf("%0.3f MGas", info.gasLimit) if info.etherbase != "" { // Ethash proof-of-work miner @@ -217,6 +222,7 @@ func checkNode(client *sshClient, network string, boot bool) (*nodeInfos, error) totalPeers, _ := strconv.Atoi(infos.envvars["TOTAL_PEERS"]) lightPeers, _ := strconv.Atoi(infos.envvars["LIGHT_PEERS"]) gasTarget, _ := strconv.ParseFloat(infos.envvars["GAS_TARGET"], 64) + gasLimit, _ := strconv.ParseFloat(infos.envvars["GAS_LIMIT"], 64) gasPrice, _ := strconv.ParseFloat(infos.envvars["GAS_PRICE"], 64) // Container available, retrieve its node ID and its genesis json @@ -256,6 +262,7 @@ func checkNode(client *sshClient, network string, boot bool) (*nodeInfos, error) keyJSON: keyJSON, keyPass: keyPass, gasTarget: gasTarget, + gasLimit: gasLimit, gasPrice: gasPrice, } stats.enode = fmt.Sprintf("enode://%s@%s:%d", id, client.address, stats.port) diff --git a/cmd/puppeth/wizard_node.go b/cmd/puppeth/wizard_node.go index 9b22da4460..49b10a023a 100644 --- a/cmd/puppeth/wizard_node.go +++ b/cmd/puppeth/wizard_node.go @@ -50,7 +50,7 @@ func (w *wizard) deployNode(boot bool) { if boot { infos = &nodeInfos{port: 30303, peersTotal: 512, peersLight: 256} } else { - infos = &nodeInfos{port: 30303, peersTotal: 50, peersLight: 0, gasTarget: 4.7, gasPrice: 18} + infos = &nodeInfos{port: 30303, peersTotal: 50, peersLight: 0, gasTarget: 7.5, gasLimit: 10, gasPrice: 1} } } existed := err == nil @@ -152,6 +152,10 @@ func (w *wizard) deployNode(boot bool) { fmt.Printf("What gas limit should empty blocks target (MGas)? (default = %0.3f)\n", infos.gasTarget) infos.gasTarget = w.readDefaultFloat(infos.gasTarget) + fmt.Println() + fmt.Printf("What gas limit should full blocks target (MGas)? (default = %0.3f)\n", infos.gasLimit) + infos.gasLimit = w.readDefaultFloat(infos.gasLimit) + fmt.Println() fmt.Printf("What gas price should the signer require (GWei)? (default = %0.3f)\n", infos.gasPrice) infos.gasPrice = w.readDefaultFloat(infos.gasPrice) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 13430ad565..495bfe13e0 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -329,12 +329,17 @@ var ( MinerGasTargetFlag = cli.Uint64Flag{ Name: "miner.gastarget", Usage: "Target gas floor for mined blocks", - Value: params.GenesisGasLimit, + Value: eth.DefaultConfig.MinerGasFloor, } MinerLegacyGasTargetFlag = cli.Uint64Flag{ Name: "targetgaslimit", Usage: "Target gas floor for mined blocks (deprecated, use --miner.gastarget)", - Value: params.GenesisGasLimit, + Value: eth.DefaultConfig.MinerGasFloor, + } + MinerGasLimitFlag = cli.Uint64Flag{ + Name: "miner.gaslimit", + Usage: "Target gas ceiling for mined blocks", + Value: eth.DefaultConfig.MinerGasCeil, } MinerGasPriceFlag = BigFlag{ Name: "miner.gasprice", @@ -1146,6 +1151,15 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { if ctx.GlobalIsSet(MinerExtraDataFlag.Name) { cfg.MinerExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name)) } + if ctx.GlobalIsSet(MinerLegacyGasTargetFlag.Name) { + cfg.MinerGasFloor = ctx.GlobalUint64(MinerLegacyGasTargetFlag.Name) + } + if ctx.GlobalIsSet(MinerGasTargetFlag.Name) { + cfg.MinerGasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name) + } + if ctx.GlobalIsSet(MinerGasLimitFlag.Name) { + cfg.MinerGasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name) + } if ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) { cfg.MinerGasPrice = GlobalBig(ctx, MinerLegacyGasPriceFlag.Name) } @@ -1270,15 +1284,6 @@ func RegisterEthStatsService(stack *node.Node, url string) { } } -// SetupNetwork configures the system for either the main net or some test network. -func SetupNetwork(ctx *cli.Context) { - // TODO(fjl): move target gas limit into config - params.TargetGasLimit = ctx.GlobalUint64(MinerLegacyGasTargetFlag.Name) - if ctx.GlobalIsSet(MinerGasTargetFlag.Name) { - params.TargetGasLimit = ctx.GlobalUint64(MinerGasTargetFlag.Name) - } -} - func SetupMetrics(ctx *cli.Context) { if metrics.Enabled { log.Info("Enabling metrics collection") diff --git a/core/bench_test.go b/core/bench_test.go index 748aebe407..8d95456e9f 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -111,7 +111,8 @@ func init() { func genTxRing(naccounts int) func(int, *BlockGen) { from := 0 return func(i int, gen *BlockGen) { - gas := CalcGasLimit(gen.PrevBlock(i - 1)) + block := gen.PrevBlock(i - 1) + gas := CalcGasLimit(block, block.GasLimit(), block.GasLimit()) for { gas -= params.TxGas if gas < params.TxGas { diff --git a/core/block_validator.go b/core/block_validator.go index ecd6a89bc2..1329f62427 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -101,9 +101,11 @@ func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *stat return nil } -// CalcGasLimit computes the gas limit of the next block after parent. -// This is miner strategy, not consensus protocol. -func CalcGasLimit(parent *types.Block) uint64 { +// CalcGasLimit computes the gas limit of the next block after parent. It aims +// to keep the baseline gas above the provided floor, and increase it towards the +// ceil if the blocks are full. If the ceil is exceeded, it will always decrease +// the gas allowance. +func CalcGasLimit(parent *types.Block, gasFloor, gasCeil uint64) uint64 { // contrib = (parentGasUsed * 3 / 2) / 1024 contrib := (parent.GasUsed() + parent.GasUsed()/2) / params.GasLimitBoundDivisor @@ -121,12 +123,16 @@ func CalcGasLimit(parent *types.Block) uint64 { if limit < params.MinGasLimit { limit = params.MinGasLimit } - // however, if we're now below the target (TargetGasLimit) we increase the - // limit as much as we can (parentGasLimit / 1024 -1) - if limit < params.TargetGasLimit { + // If we're outside our allowed gas range, we try to hone towards them + if limit < gasFloor { limit = parent.GasLimit() + decay - if limit > params.TargetGasLimit { - limit = params.TargetGasLimit + if limit > gasFloor { + limit = gasFloor + } + } else if limit > gasCeil { + limit = parent.GasLimit() - decay + if limit < gasCeil { + limit = gasCeil } } return limit diff --git a/core/chain_makers.go b/core/chain_makers.go index c1e4b4264a..de0fc6be9e 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -240,7 +240,7 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S Difficulty: parent.Difficulty(), UncleHash: parent.UncleHash(), }), - GasLimit: CalcGasLimit(parent), + GasLimit: CalcGasLimit(parent, parent.GasLimit(), parent.GasLimit()), Number: new(big.Int).Add(parent.Number(), common.Big1), Time: time, } diff --git a/eth/backend.go b/eth/backend.go index 3032e1a6d3..9926225f24 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -173,7 +173,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { return nil, err } - eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine, config.MinerRecommit) + eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine, config.MinerRecommit, config.MinerGasFloor, config.MinerGasCeil) eth.miner.SetExtra(makeExtraData(config.MinerExtraData)) eth.APIBackend = &EthAPIBackend{eth, nil} diff --git a/eth/config.go b/eth/config.go index 517d7d8f3d..f1a402e370 100644 --- a/eth/config.go +++ b/eth/config.go @@ -48,7 +48,9 @@ var DefaultConfig = Config{ DatabaseCache: 768, TrieCache: 256, TrieTimeout: 60 * time.Minute, - MinerGasPrice: big.NewInt(18 * params.Shannon), + MinerGasFloor: 8000000, + MinerGasCeil: 8000000, + MinerGasPrice: big.NewInt(params.GWei), MinerRecommit: 3 * time.Second, TxPool: core.DefaultTxPoolConfig, @@ -99,6 +101,8 @@ type Config struct { Etherbase common.Address `toml:",omitempty"` MinerNotify []string `toml:",omitempty"` MinerExtraData []byte `toml:",omitempty"` + MinerGasFloor uint64 + MinerGasCeil uint64 MinerGasPrice *big.Int MinerRecommit time.Duration MinerNoverify bool diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index 54325692c6..3b8db78a1c 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -29,7 +29,7 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) -var maxPrice = big.NewInt(500 * params.Shannon) +var maxPrice = big.NewInt(500 * params.GWei) type Config struct { Blocks int diff --git a/eth/gen_config.go b/eth/gen_config.go index df4ffeb11f..d401a917d2 100644 --- a/eth/gen_config.go +++ b/eth/gen_config.go @@ -33,6 +33,8 @@ func (c Config) MarshalTOML() (interface{}, error) { Etherbase common.Address `toml:",omitempty"` MinerNotify []string `toml:",omitempty"` MinerExtraData hexutil.Bytes `toml:",omitempty"` + MinerGasFloor uint64 + MinerGasCeil uint64 MinerGasPrice *big.Int MinerRecommit time.Duration MinerNoverify bool @@ -57,6 +59,8 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.Etherbase = c.Etherbase enc.MinerNotify = c.MinerNotify enc.MinerExtraData = c.MinerExtraData + enc.MinerGasFloor = c.MinerGasFloor + enc.MinerGasCeil = c.MinerGasCeil enc.MinerGasPrice = c.MinerGasPrice enc.MinerRecommit = c.MinerRecommit enc.MinerNoverify = c.MinerNoverify @@ -85,6 +89,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { Etherbase *common.Address `toml:",omitempty"` MinerNotify []string `toml:",omitempty"` MinerExtraData *hexutil.Bytes `toml:",omitempty"` + MinerGasFloor *uint64 + MinerGasCeil *uint64 MinerGasPrice *big.Int MinerRecommit *time.Duration MinerNoverify *bool @@ -140,6 +146,12 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.MinerExtraData != nil { c.MinerExtraData = *dec.MinerExtraData } + if dec.MinerGasFloor != nil { + c.MinerGasFloor = *dec.MinerGasFloor + } + if dec.MinerGasCeil != nil { + c.MinerGasCeil = *dec.MinerGasCeil + } if dec.MinerGasPrice != nil { c.MinerGasPrice = dec.MinerGasPrice } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index a465a59046..f7379e228c 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -47,7 +47,7 @@ import ( ) const ( - defaultGasPrice = 50 * params.Shannon + defaultGasPrice = params.GWei ) // PublicEthereumAPI provides an API to access Ethereum related information. diff --git a/miner/miner.go b/miner/miner.go index c5a0c9d62a..7f194db261 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -52,13 +52,13 @@ type Miner struct { shouldStart int32 // should start indicates whether we should start after sync } -func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, recommit time.Duration) *Miner { +func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, recommit time.Duration, gasFloor, gasCeil uint64) *Miner { miner := &Miner{ eth: eth, mux: mux, engine: engine, exitCh: make(chan struct{}), - worker: newWorker(config, engine, eth, mux, recommit), + worker: newWorker(config, engine, eth, mux, recommit, gasFloor, gasCeil), canStart: 1, } go miner.update() diff --git a/miner/stress_clique.go b/miner/stress_clique.go index 8545b9413a..8961091d56 100644 --- a/miner/stress_clique.go +++ b/miner/stress_clique.go @@ -206,6 +206,8 @@ func makeSealer(genesis *core.Genesis, nodes []string) (*node.Node, error) { DatabaseHandles: 256, TxPool: core.DefaultTxPoolConfig, GPO: eth.DefaultConfig.GPO, + MinerGasFloor: genesis.GasLimit * 9 / 10, + MinerGasCeil: genesis.GasLimit * 11 / 10, MinerGasPrice: big.NewInt(1), MinerRecommit: time.Second, }) diff --git a/miner/stress_ethash.go b/miner/stress_ethash.go index 4ed8aeee4f..5ed11d73a5 100644 --- a/miner/stress_ethash.go +++ b/miner/stress_ethash.go @@ -186,6 +186,8 @@ func makeMiner(genesis *core.Genesis, nodes []string) (*node.Node, error) { TxPool: core.DefaultTxPoolConfig, GPO: eth.DefaultConfig.GPO, Ethash: eth.DefaultConfig.Ethash, + MinerGasFloor: genesis.GasLimit * 9 / 10, + MinerGasCeil: genesis.GasLimit * 11 / 10, MinerGasPrice: big.NewInt(1), MinerRecommit: time.Second, }) diff --git a/miner/worker.go b/miner/worker.go index ca68da6e94..5348cb3f1e 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -127,6 +127,9 @@ type worker struct { eth Backend chain *core.BlockChain + gasFloor uint64 + gasCeil uint64 + // Subscriptions mux *event.TypeMux txsCh chan core.NewTxsEvent @@ -171,13 +174,15 @@ type worker struct { resubmitHook func(time.Duration, time.Duration) // Method to call upon updating resubmitting interval. } -func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, recommit time.Duration) *worker { +func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, recommit time.Duration, gasFloor, gasCeil uint64) *worker { worker := &worker{ config: config, engine: engine, eth: eth, mux: mux, chain: eth.BlockChain(), + gasFloor: gasFloor, + gasCeil: gasCeil, possibleUncles: make(map[common.Hash]*types.Block), unconfirmed: newUnconfirmedBlocks(eth.BlockChain(), miningLogAtDepth), pendingTasks: make(map[common.Hash]*task), @@ -807,7 +812,7 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool) { header := &types.Header{ ParentHash: parent.Hash(), Number: num.Add(num, common.Big1), - GasLimit: core.CalcGasLimit(parent), + GasLimit: core.CalcGasLimit(parent, w.gasFloor, w.gasCeil), Extra: w.extra, Time: big.NewInt(tstamp), } diff --git a/miner/worker_test.go b/miner/worker_test.go index 16708c18c6..9f9a3b4a5e 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -119,7 +119,7 @@ func (b *testWorkerBackend) PostChainEvents(events []interface{}) { func newTestWorker(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine) (*worker, *testWorkerBackend) { backend := newTestWorkerBackend(t, chainConfig, engine) backend.txPool.AddLocals(pendingTxs) - w := newWorker(chainConfig, engine, backend, new(event.TypeMux), time.Second) + w := newWorker(chainConfig, engine, backend, new(event.TypeMux), time.Second, params.GenesisGasLimit, params.GenesisGasLimit) w.setEtherbase(testBankAddress) return w, backend } diff --git a/params/denomination.go b/params/denomination.go index 1a309827da..fb4da7f412 100644 --- a/params/denomination.go +++ b/params/denomination.go @@ -17,18 +17,12 @@ package params // These are the multipliers for ether denominations. -// Example: To get the wei value of an amount in 'douglas', use +// Example: To get the wei value of an amount in 'gwei', use // -// new(big.Int).Mul(value, big.NewInt(params.Douglas)) +// new(big.Int).Mul(value, big.NewInt(params.GWei)) // const ( - Wei = 1 - Ada = 1e3 - Babbage = 1e6 - Shannon = 1e9 - Szabo = 1e12 - Finney = 1e15 - Ether = 1e18 - Einstein = 1e21 - Douglas = 1e42 + Wei = 1 + GWei = 1e9 + Ether = 1e18 ) diff --git a/params/protocol_params.go b/params/protocol_params.go index 46624ac9a2..4b53b3320a 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -18,10 +18,6 @@ package params import "math/big" -var ( - TargetGasLimit = GenesisGasLimit // The artificial target -) - const ( GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations. MinGasLimit uint64 = 5000 // Minimum the gas limit may ever be.