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/swarm/access_test.go b/cmd/swarm/access_test.go index 163eb2b4d6..7a8bcf9d3d 100644 --- a/cmd/swarm/access_test.go +++ b/cmd/swarm/access_test.go @@ -13,6 +13,9 @@ // // You should have received a copy of the GNU General Public License // along with go-ethereum. If not, see . + +// +build !windows + package main import ( 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..629ce5bd24 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -18,7 +18,7 @@ package miner import ( "bytes" - "fmt" + "errors" "math/big" "sync" "sync/atomic" @@ -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), @@ -615,13 +620,16 @@ func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error { func (w *worker) commitUncle(env *environment, uncle *types.Header) error { hash := uncle.Hash() if env.uncles.Contains(hash) { - return fmt.Errorf("uncle not unique") + return errors.New("uncle not unique") + } + if env.header.ParentHash == uncle.ParentHash { + return errors.New("uncle is sibling") } if !env.ancestors.Contains(uncle.ParentHash) { - return fmt.Errorf("uncle's parent unknown (%x)", uncle.ParentHash[0:4]) + return errors.New("uncle's parent unknown") } if env.family.Contains(hash) { - return fmt.Errorf("uncle already in family (%x)", hash) + return errors.New("uncle already included") } env.uncles.Add(uncle.Hash()) return nil @@ -807,7 +815,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), } @@ -847,29 +855,24 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool) { if w.config.DAOForkSupport && w.config.DAOForkBlock != nil && w.config.DAOForkBlock.Cmp(header.Number) == 0 { misc.ApplyDAOHardFork(env.state) } - - // compute uncles for the new block. - var ( - uncles []*types.Header - badUncles []common.Hash - ) + // Accumulate the uncles for the current block + for hash, uncle := range w.possibleUncles { + if uncle.NumberU64()+staleThreshold <= header.Number.Uint64() { + delete(w.possibleUncles, hash) + } + } + uncles := make([]*types.Header, 0, 2) for hash, uncle := range w.possibleUncles { if len(uncles) == 2 { break } if err := w.commitUncle(env, uncle.Header()); err != nil { - log.Trace("Bad uncle found and will be removed", "hash", hash) - log.Trace(fmt.Sprint(uncle)) - - badUncles = append(badUncles, hash) + log.Trace("Possible uncle rejected", "hash", hash, "reason", err) } else { log.Debug("Committing new uncle to block", "hash", hash) uncles = append(uncles, uncle.Header()) } } - for _, hash := range badUncles { - delete(w.possibleUncles, hash) - } if !noempty { // Create an empty block based on temporary copied state for sealing in advance without waiting block diff --git a/miner/worker_test.go b/miner/worker_test.go index 16708c18c6..6de1177cdc 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -45,8 +45,8 @@ var ( testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) testBankFunds = big.NewInt(1000000000000000000) - acc1Key, _ = crypto.GenerateKey() - acc1Addr = crypto.PubkeyToAddress(acc1Key.PublicKey) + testUserKey, _ = crypto.GenerateKey() + testUserAddress = crypto.PubkeyToAddress(testUserKey.PublicKey) // Test transactions pendingTxs []*types.Transaction @@ -62,9 +62,9 @@ func init() { Period: 10, Epoch: 30000, } - tx1, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), types.HomesteadSigner{}, testBankKey) + tx1, _ := types.SignTx(types.NewTransaction(0, testUserAddress, big.NewInt(1000), params.TxGas, nil, nil), types.HomesteadSigner{}, testBankKey) pendingTxs = append(pendingTxs, tx1) - tx2, _ := types.SignTx(types.NewTransaction(1, acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), types.HomesteadSigner{}, testBankKey) + tx2, _ := types.SignTx(types.NewTransaction(1, testUserAddress, big.NewInt(1000), params.TxGas, nil, nil), types.HomesteadSigner{}, testBankKey) newTxs = append(newTxs, tx2) } @@ -77,7 +77,7 @@ type testWorkerBackend struct { uncleBlock *types.Block } -func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine) *testWorkerBackend { +func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine, n int) *testWorkerBackend { var ( db = ethdb.NewMemDatabase() gspec = core.Genesis{ @@ -92,14 +92,28 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine copy(gspec.ExtraData[32:], testBankAddress[:]) case *ethash.Ethash: default: - t.Fatal("unexpect consensus engine type") + t.Fatalf("unexpected consensus engine type: %T", engine) } genesis := gspec.MustCommit(db) chain, _ := core.NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}) txpool := core.NewTxPool(testTxPoolConfig, chainConfig, chain) - blocks, _ := core.GenerateChain(chainConfig, genesis, engine, db, 1, func(i int, gen *core.BlockGen) { - gen.SetCoinbase(acc1Addr) + + // Generate a small n-block chain and an uncle block for it + if n > 0 { + blocks, _ := core.GenerateChain(chainConfig, genesis, engine, db, n, func(i int, gen *core.BlockGen) { + gen.SetCoinbase(testBankAddress) + }) + if _, err := chain.InsertChain(blocks); err != nil { + t.Fatalf("failed to insert origin chain: %v", err) + } + } + parent := genesis + if n > 0 { + parent = chain.GetBlockByHash(chain.CurrentBlock().ParentHash()) + } + blocks, _ := core.GenerateChain(chainConfig, parent, engine, db, 1, func(i int, gen *core.BlockGen) { + gen.SetCoinbase(testUserAddress) }) return &testWorkerBackend{ @@ -116,10 +130,10 @@ func (b *testWorkerBackend) PostChainEvents(events []interface{}) { b.chain.PostChainEvents(events, nil) } -func newTestWorker(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine) (*worker, *testWorkerBackend) { - backend := newTestWorkerBackend(t, chainConfig, engine) +func newTestWorker(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine, blocks int) (*worker, *testWorkerBackend) { + backend := newTestWorkerBackend(t, chainConfig, engine, blocks) 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 } @@ -134,24 +148,24 @@ func TestPendingStateAndBlockClique(t *testing.T) { func testPendingStateAndBlock(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine) { defer engine.Close() - w, b := newTestWorker(t, chainConfig, engine) + w, b := newTestWorker(t, chainConfig, engine, 0) defer w.close() // Ensure snapshot has been updated. time.Sleep(100 * time.Millisecond) block, state := w.pending() if block.NumberU64() != 1 { - t.Errorf("block number mismatch, has %d, want %d", block.NumberU64(), 1) + t.Errorf("block number mismatch: have %d, want %d", block.NumberU64(), 1) } - if balance := state.GetBalance(acc1Addr); balance.Cmp(big.NewInt(1000)) != 0 { - t.Errorf("account balance mismatch, has %d, want %d", balance, 1000) + if balance := state.GetBalance(testUserAddress); balance.Cmp(big.NewInt(1000)) != 0 { + t.Errorf("account balance mismatch: have %d, want %d", balance, 1000) } b.txPool.AddLocals(newTxs) // Ensure the new tx events has been processed time.Sleep(100 * time.Millisecond) block, state = w.pending() - if balance := state.GetBalance(acc1Addr); balance.Cmp(big.NewInt(2000)) != 0 { - t.Errorf("account balance mismatch, has %d, want %d", balance, 2000) + if balance := state.GetBalance(testUserAddress); balance.Cmp(big.NewInt(2000)) != 0 { + t.Errorf("account balance mismatch: have %d, want %d", balance, 2000) } } @@ -165,7 +179,7 @@ func TestEmptyWorkClique(t *testing.T) { func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine) { defer engine.Close() - w, _ := newTestWorker(t, chainConfig, engine) + w, _ := newTestWorker(t, chainConfig, engine, 0) defer w.close() var ( @@ -179,10 +193,10 @@ func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consens receiptLen, balance = 1, big.NewInt(1000) } if len(task.receipts) != receiptLen { - t.Errorf("receipt number mismatch has %d, want %d", len(task.receipts), receiptLen) + t.Errorf("receipt number mismatch: have %d, want %d", len(task.receipts), receiptLen) } - if task.state.GetBalance(acc1Addr).Cmp(balance) != 0 { - t.Errorf("account balance mismatch has %d, want %d", task.state.GetBalance(acc1Addr), balance) + if task.state.GetBalance(testUserAddress).Cmp(balance) != 0 { + t.Errorf("account balance mismatch: have %d, want %d", task.state.GetBalance(testUserAddress), balance) } } @@ -219,19 +233,19 @@ func TestStreamUncleBlock(t *testing.T) { ethash := ethash.NewFaker() defer ethash.Close() - w, b := newTestWorker(t, ethashChainConfig, ethash) + w, b := newTestWorker(t, ethashChainConfig, ethash, 1) defer w.close() var taskCh = make(chan struct{}) taskIndex := 0 w.newTaskHook = func(task *task) { - if task.block.NumberU64() == 1 { + if task.block.NumberU64() == 2 { if taskIndex == 2 { - has := task.block.Header().UncleHash + have := task.block.Header().UncleHash want := types.CalcUncleHash([]*types.Header{b.uncleBlock.Header()}) - if has != want { - t.Errorf("uncle hash mismatch, has %s, want %s", has.Hex(), want.Hex()) + if have != want { + t.Errorf("uncle hash mismatch: have %s, want %s", have.Hex(), want.Hex()) } } taskCh <- struct{}{} @@ -248,12 +262,12 @@ func TestStreamUncleBlock(t *testing.T) { // Ensure worker has finished initialization for { b := w.pendingBlock() - if b != nil && b.NumberU64() == 1 { + if b != nil && b.NumberU64() == 2 { break } } - w.start() + // Ignore the first two works for i := 0; i < 2; i += 1 { select { @@ -282,7 +296,7 @@ func TestRegenerateMiningBlockClique(t *testing.T) { func testRegenerateMiningBlock(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine) { defer engine.Close() - w, b := newTestWorker(t, chainConfig, engine) + w, b := newTestWorker(t, chainConfig, engine, 0) defer w.close() var taskCh = make(chan struct{}) @@ -293,10 +307,10 @@ func testRegenerateMiningBlock(t *testing.T, chainConfig *params.ChainConfig, en if taskIndex == 2 { receiptLen, balance := 2, big.NewInt(2000) if len(task.receipts) != receiptLen { - t.Errorf("receipt number mismatch has %d, want %d", len(task.receipts), receiptLen) + t.Errorf("receipt number mismatch: have %d, want %d", len(task.receipts), receiptLen) } - if task.state.GetBalance(acc1Addr).Cmp(balance) != 0 { - t.Errorf("account balance mismatch has %d, want %d", task.state.GetBalance(acc1Addr), balance) + if task.state.GetBalance(testUserAddress).Cmp(balance) != 0 { + t.Errorf("account balance mismatch: have %d, want %d", task.state.GetBalance(testUserAddress), balance) } } taskCh <- struct{}{} @@ -347,7 +361,7 @@ func TestAdjustIntervalClique(t *testing.T) { func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine) { defer engine.Close() - w, _ := newTestWorker(t, chainConfig, engine) + w, _ := newTestWorker(t, chainConfig, engine, 0) defer w.close() w.skipSealHook = func(task *task) bool { @@ -387,10 +401,10 @@ func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine co // Check interval if minInterval != wantMinInterval { - t.Errorf("resubmit min interval mismatch want %s has %s", wantMinInterval, minInterval) + t.Errorf("resubmit min interval mismatch: have %v, want %v ", minInterval, wantMinInterval) } if recommitInterval != wantRecommitInterval { - t.Errorf("resubmit interval mismatch want %s has %s", wantRecommitInterval, recommitInterval) + t.Errorf("resubmit interval mismatch: have %v, want %v", recommitInterval, wantRecommitInterval) } result = append(result, float64(recommitInterval.Nanoseconds())) index += 1 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. diff --git a/whisper/whisperv5/whisper.go b/whisper/whisperv5/whisper.go index 8e0662327a..4655458214 100644 --- a/whisper/whisperv5/whisper.go +++ b/whisper/whisperv5/whisper.go @@ -717,7 +717,7 @@ func (w *Whisper) expire() { w.stats.messagesCleared++ w.stats.memoryCleared += sz w.stats.memoryUsed -= sz - return true + return false }) w.expirations[expiry].Clear() delete(w.expirations, expiry) diff --git a/whisper/whisperv5/whisper_test.go b/whisper/whisperv5/whisper_test.go index 8af085292a..a7bd17e4d8 100644 --- a/whisper/whisperv5/whisper_test.go +++ b/whisper/whisperv5/whisper_test.go @@ -487,27 +487,34 @@ func TestExpiry(t *testing.T) { if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } - params.TTL = 1 - msg, err := NewSentMessage(params) - if err != nil { - t.Fatalf("failed to create new message with seed %d: %s.", seed, err) - } - env, err := msg.Wrap(params) - if err != nil { - t.Fatalf("failed Wrap with seed %d: %s.", seed, err) - } - err = w.Send(env) - if err != nil { - t.Fatalf("failed to send envelope with seed %d: %s.", seed, err) + messagesCount := 5 + + // Send a few messages one after another. Due to low PoW and expiration buckets + // with one second resolution, it covers a case when there are multiple items + // in a single expiration bucket. + for i := 0; i < messagesCount; i++ { + msg, err := NewSentMessage(params) + if err != nil { + t.Fatalf("failed to create new message with seed %d: %s.", seed, err) + } + env, err := msg.Wrap(params) + if err != nil { + t.Fatalf("failed Wrap with seed %d: %s.", seed, err) + } + + err = w.Send(env) + if err != nil { + t.Fatalf("failed to send envelope with seed %d: %s.", seed, err) + } } // wait till received or timeout var received, expired bool for j := 0; j < 20; j++ { time.Sleep(100 * time.Millisecond) - if len(w.Envelopes()) > 0 { + if len(w.Envelopes()) == messagesCount { received = true break } diff --git a/whisper/whisperv6/whisper.go b/whisper/whisperv6/whisper.go index 34c1256a6f..be633e7ff6 100644 --- a/whisper/whisperv6/whisper.go +++ b/whisper/whisperv6/whisper.go @@ -900,7 +900,7 @@ func (whisper *Whisper) expire() { whisper.stats.messagesCleared++ whisper.stats.memoryCleared += sz whisper.stats.memoryUsed -= sz - return true + return false }) whisper.expirations[expiry].Clear() delete(whisper.expirations, expiry) diff --git a/whisper/whisperv6/whisper_test.go b/whisper/whisperv6/whisper_test.go index 7fe256309e..895bb2b969 100644 --- a/whisper/whisperv6/whisper_test.go +++ b/whisper/whisperv6/whisper_test.go @@ -465,27 +465,34 @@ func TestExpiry(t *testing.T) { if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } - params.TTL = 1 - msg, err := NewSentMessage(params) - if err != nil { - t.Fatalf("failed to create new message with seed %d: %s.", seed, err) - } - env, err := msg.Wrap(params) - if err != nil { - t.Fatalf("failed Wrap with seed %d: %s.", seed, err) - } - err = w.Send(env) - if err != nil { - t.Fatalf("failed to send envelope with seed %d: %s.", seed, err) + messagesCount := 5 + + // Send a few messages one after another. Due to low PoW and expiration buckets + // with one second resolution, it covers a case when there are multiple items + // in a single expiration bucket. + for i := 0; i < messagesCount; i++ { + msg, err := NewSentMessage(params) + if err != nil { + t.Fatalf("failed to create new message with seed %d: %s.", seed, err) + } + env, err := msg.Wrap(params) + if err != nil { + t.Fatalf("failed Wrap with seed %d: %s.", seed, err) + } + + err = w.Send(env) + if err != nil { + t.Fatalf("failed to send envelope with seed %d: %s.", seed, err) + } } // wait till received or timeout var received, expired bool for j := 0; j < 20; j++ { time.Sleep(100 * time.Millisecond) - if len(w.Envelopes()) > 0 { + if len(w.Envelopes()) == messagesCount { received = true break }