diff --git a/cmd/geth/admin.go b/cmd/geth/admin.go index 49e2dc6f8b..2b99566386 100644 --- a/cmd/geth/admin.go +++ b/cmd/geth/admin.go @@ -70,6 +70,7 @@ func (js *jsre) adminBindings() { miner.Set("stop", js.stopMining) miner.Set("hashrate", js.hashrate) miner.Set("setExtra", js.setExtra) + miner.Set("setGasPrice", js.setGasPrice) admin.Set("debug", struct{}{}) t, _ = admin.Get("debug") @@ -236,6 +237,17 @@ func (js *jsre) setExtra(call otto.FunctionCall) otto.Value { return otto.UndefinedValue() } +func (js *jsre) setGasPrice(call otto.FunctionCall) otto.Value { + gasPrice, err := call.Argument(0).ToString() + if err != nil { + fmt.Println(err) + return otto.UndefinedValue() + } + + js.ethereum.Miner().SetGasPrice(common.String2Big(gasPrice)) + return otto.UndefinedValue() +} + func (js *jsre) hashrate(otto.FunctionCall) otto.Value { return js.re.ToVal(js.ethereum.Miner().HashRate()) } diff --git a/cmd/geth/main.go b/cmd/geth/main.go index fd6925e6db..723353b0bd 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -51,7 +51,7 @@ import _ "net/http/pprof" const ( ClientIdentifier = "Geth" - Version = "0.9.17" + Version = "0.9.18" ) var ( @@ -244,6 +244,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.MaxPeersFlag, utils.MaxPendingPeersFlag, utils.EtherbaseFlag, + utils.GasPriceFlag, utils.MinerThreadsFlag, utils.MiningEnabledFlag, utils.NATFlag, @@ -258,7 +259,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.ProtocolVersionFlag, utils.NetworkIdFlag, utils.RPCCORSDomainFlag, - utils.LogLevelFlag, + utils.VerbosityFlag, utils.BacktraceAtFlag, utils.LogToStdErrFlag, utils.LogVModuleFlag, diff --git a/cmd/mist/main.go b/cmd/mist/main.go index 9d92cc1754..098afc7e24 100644 --- a/cmd/mist/main.go +++ b/cmd/mist/main.go @@ -73,7 +73,7 @@ func init() { utils.DataDirFlag, utils.ListenPortFlag, utils.LogFileFlag, - utils.LogLevelFlag, + utils.VerbosityFlag, utils.MaxPeersFlag, utils.MaxPendingPeersFlag, utils.MinerThreadsFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index b18d9851f8..dd3b6c8a2f 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -4,6 +4,7 @@ import ( "crypto/ecdsa" "fmt" "log" + "math/big" "net/http" "os" "path" @@ -116,6 +117,11 @@ var ( Usage: "Public address for block mining rewards. By default the address of your primary account is used", Value: "primary", } + GasPriceFlag = cli.StringFlag{ + Name: "gasprice", + Usage: "Sets the minimal gasprice when mining transactions", + Value: new(big.Int).Mul(big.NewInt(10), common.Szabo).String(), + } UnlockedAccountFlag = cli.StringFlag{ Name: "unlock", @@ -133,8 +139,8 @@ var ( Name: "logfile", Usage: "Send log output to a file", } - LogLevelFlag = cli.IntFlag{ - Name: "loglevel", + VerbosityFlag = cli.IntFlag{ + Name: "verbosity", Usage: "Logging verbosity: 0-6 (0=silent, 1=error, 2=warn, 3=info, 4=core, 5=debug, 6=debug detail)", Value: int(logger.InfoLevel), } @@ -270,7 +276,7 @@ func GetNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) { func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { // Set verbosity on glog - glog.SetV(ctx.GlobalInt(LogLevelFlag.Name)) + glog.SetV(ctx.GlobalInt(VerbosityFlag.Name)) // Set the log type //glog.SetToStderr(ctx.GlobalBool(LogToStdErrFlag.Name)) glog.SetToStderr(true) @@ -290,7 +296,7 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { SkipBcVersionCheck: false, NetworkId: ctx.GlobalInt(NetworkIdFlag.Name), LogFile: ctx.GlobalString(LogFileFlag.Name), - LogLevel: ctx.GlobalInt(LogLevelFlag.Name), + Verbosity: ctx.GlobalInt(VerbosityFlag.Name), LogJSON: ctx.GlobalString(LogJSONFlag.Name), Etherbase: ctx.GlobalString(EtherbaseFlag.Name), MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name), @@ -305,6 +311,7 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { Shh: ctx.GlobalBool(WhisperEnabledFlag.Name), Dial: true, BootNodes: ctx.GlobalString(BootnodesFlag.Name), + GasPrice: common.String2Big(ctx.GlobalString(GasPriceFlag.Name)), } } diff --git a/eth/backend.go b/eth/backend.go index 0f23cde2fd..8f07894670 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "math/big" "os" "path" "path/filepath" @@ -53,12 +54,12 @@ type Config struct { BlockChainVersion int SkipBcVersionCheck bool // e.g. blockchain export - DataDir string - LogFile string - LogLevel int - LogJSON string - VmDebug bool - NatSpec bool + DataDir string + LogFile string + Verbosity int + LogJSON string + VmDebug bool + NatSpec bool MaxPeers int MaxPendingPeers int @@ -76,6 +77,7 @@ type Config struct { Dial bool Etherbase string + GasPrice *big.Int MinerThreads int AccountManager *accounts.Manager @@ -200,7 +202,7 @@ type Ethereum struct { func New(config *Config) (*Ethereum, error) { // Bootstrap database - logger.New(config.DataDir, config.LogFile, config.LogLevel) + logger.New(config.DataDir, config.LogFile, config.Verbosity) if len(config.LogJSON) > 0 { logger.NewJSONsystem(config.DataDir, config.LogJSON) } @@ -266,6 +268,8 @@ func New(config *Config) (*Ethereum, error) { eth.blockProcessor = core.NewBlockProcessor(stateDb, extraDb, eth.pow, eth.txPool, eth.chainManager, eth.EventMux()) eth.chainManager.SetProcessor(eth.blockProcessor) eth.miner = miner.New(eth, eth.pow, config.MinerThreads) + eth.miner.SetGasPrice(config.GasPrice) + eth.protocolManager = NewProtocolManager(config.ProtocolVersion, config.NetworkId, eth.eventMux, eth.txPool, eth.chainManager, eth.downloader) if config.Shh { eth.whisper = whisper.New() diff --git a/miner/miner.go b/miner/miner.go index bff0026dc4..d5ea9a1469 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -37,6 +37,15 @@ func (self *Miner) Mining() bool { return self.mining } +func (m *Miner) SetGasPrice(price *big.Int) { + // FIXME block tests set a nil gas price. Quick dirty fix + if price == nil { + return + } + + m.worker.gasPrice = price +} + func (self *Miner) Start(coinbase common.Address) { self.mining = true self.worker.coinbase = coinbase diff --git a/miner/worker.go b/miner/worker.go index 87d17dfd69..22493c2354 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -72,6 +72,7 @@ type worker struct { proc *core.BlockProcessor coinbase common.Address + gasPrice *big.Int extra []byte currentMu sync.Mutex @@ -93,6 +94,7 @@ func newWorker(coinbase common.Address, eth core.Backend) *worker { eth: eth, mux: eth.EventMux(), recv: make(chan *types.Block), + gasPrice: new(big.Int), chain: eth.ChainManager(), proc: eth.BlockProcessor(), possibleUncles: make(map[common.Hash]*types.Block), @@ -123,6 +125,9 @@ func (self *worker) pendingBlock() *types.Block { } func (self *worker) start() { + self.mu.Lock() + defer self.mu.Unlock() + // spin up agents for _, agent := range self.agents { agent.Start() @@ -132,6 +137,9 @@ func (self *worker) start() { } func (self *worker) stop() { + self.mu.Lock() + defer self.mu.Unlock() + if atomic.LoadInt32(&self.mining) == 1 { // stop all agents for _, agent := range self.agents { @@ -144,6 +152,9 @@ func (self *worker) stop() { } func (self *worker) register(agent Agent) { + self.mu.Lock() + defer self.mu.Unlock() + self.agents = append(self.agents, agent) agent.SetReturnCh(self.recv) } @@ -239,6 +250,12 @@ func (self *worker) makeCurrent() { self.current.coinbase.SetGasPool(core.CalcGasLimit(parent)) } +func (w *worker) setGasPrice(p *big.Int) { + w.mu.Lock() + defer w.mu.Unlock() + w.gasPrice = p +} + func (self *worker) commitNewWork() { self.mu.Lock() defer self.mu.Unlock() @@ -259,9 +276,23 @@ func (self *worker) commitNewWork() { ignoredTransactors = set.New() ) + const pct = int64(90) + // calculate the minimal gas price the miner accepts when sorting out transactions. + minprice := gasprice(self.gasPrice, pct) for _, tx := range transactions { // We can skip err. It has already been validated in the tx pool from, _ := tx.From() + + // check if it falls within margin + if tx.GasPrice().Cmp(minprice) < 0 { + // ignore the transaction and transactor. We ignore the transactor + // because nonce will fail after ignoring this transaction so there's + // no point + ignoredTransactors.Add(from) + glog.V(logger.Info).Infof("transaction(%x) below gas price (<%d%% ask price). All sequential txs from this address(%x) will fail\n", tx.Hash().Bytes()[:4], pct, from[:4]) + continue + } + // Move on to the next transaction when the transactor is in ignored transactions set // This may occur when a transaction hits the gas limit. When a gas limit is hit and // the transaction is processed (that could potentially be included in the block) it @@ -383,3 +414,12 @@ func (self *worker) HashRate() int64 { return tot } + +// gasprice calculates a reduced gas price based on the pct +// XXX Use big.Rat? +func gasprice(price *big.Int, pct int64) *big.Int { + p := new(big.Int).Set(price) + p.Div(p, big.NewInt(100)) + p.Mul(p, big.NewInt(pct)) + return p +} diff --git a/tests/block_test.go b/tests/block_test.go index 79e3335b1a..e72f2b5483 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -103,7 +103,7 @@ func testEthConfig() *eth.Config { return ð.Config{ DataDir: common.DefaultDataDir(), - LogLevel: 5, + Verbosity: 5, Etherbase: "primary", AccountManager: accounts.NewManager(ks), NewDB: func(path string) (common.Database, error) { return ethdb.NewMemDatabase() },