Merge pull request #888 from obscuren/develop

miner, flags: Configurable gas price & log flag change
This commit is contained in:
Jeffrey Wilcke 2015-05-09 04:13:16 -07:00
commit e289b0a1c1
8 changed files with 88 additions and 15 deletions

View File

@ -70,6 +70,7 @@ func (js *jsre) adminBindings() {
miner.Set("stop", js.stopMining) miner.Set("stop", js.stopMining)
miner.Set("hashrate", js.hashrate) miner.Set("hashrate", js.hashrate)
miner.Set("setExtra", js.setExtra) miner.Set("setExtra", js.setExtra)
miner.Set("setGasPrice", js.setGasPrice)
admin.Set("debug", struct{}{}) admin.Set("debug", struct{}{})
t, _ = admin.Get("debug") t, _ = admin.Get("debug")
@ -236,6 +237,17 @@ func (js *jsre) setExtra(call otto.FunctionCall) otto.Value {
return otto.UndefinedValue() 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 { func (js *jsre) hashrate(otto.FunctionCall) otto.Value {
return js.re.ToVal(js.ethereum.Miner().HashRate()) return js.re.ToVal(js.ethereum.Miner().HashRate())
} }

View File

@ -51,7 +51,7 @@ import _ "net/http/pprof"
const ( const (
ClientIdentifier = "Geth" ClientIdentifier = "Geth"
Version = "0.9.17" Version = "0.9.18"
) )
var ( var (
@ -244,6 +244,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
utils.MaxPeersFlag, utils.MaxPeersFlag,
utils.MaxPendingPeersFlag, utils.MaxPendingPeersFlag,
utils.EtherbaseFlag, utils.EtherbaseFlag,
utils.GasPriceFlag,
utils.MinerThreadsFlag, utils.MinerThreadsFlag,
utils.MiningEnabledFlag, utils.MiningEnabledFlag,
utils.NATFlag, utils.NATFlag,
@ -258,7 +259,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
utils.ProtocolVersionFlag, utils.ProtocolVersionFlag,
utils.NetworkIdFlag, utils.NetworkIdFlag,
utils.RPCCORSDomainFlag, utils.RPCCORSDomainFlag,
utils.LogLevelFlag, utils.VerbosityFlag,
utils.BacktraceAtFlag, utils.BacktraceAtFlag,
utils.LogToStdErrFlag, utils.LogToStdErrFlag,
utils.LogVModuleFlag, utils.LogVModuleFlag,

View File

@ -73,7 +73,7 @@ func init() {
utils.DataDirFlag, utils.DataDirFlag,
utils.ListenPortFlag, utils.ListenPortFlag,
utils.LogFileFlag, utils.LogFileFlag,
utils.LogLevelFlag, utils.VerbosityFlag,
utils.MaxPeersFlag, utils.MaxPeersFlag,
utils.MaxPendingPeersFlag, utils.MaxPendingPeersFlag,
utils.MinerThreadsFlag, utils.MinerThreadsFlag,

View File

@ -4,6 +4,7 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"fmt" "fmt"
"log" "log"
"math/big"
"net/http" "net/http"
"os" "os"
"path" "path"
@ -116,6 +117,11 @@ var (
Usage: "Public address for block mining rewards. By default the address of your primary account is used", Usage: "Public address for block mining rewards. By default the address of your primary account is used",
Value: "primary", 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{ UnlockedAccountFlag = cli.StringFlag{
Name: "unlock", Name: "unlock",
@ -133,8 +139,8 @@ var (
Name: "logfile", Name: "logfile",
Usage: "Send log output to a file", Usage: "Send log output to a file",
} }
LogLevelFlag = cli.IntFlag{ VerbosityFlag = cli.IntFlag{
Name: "loglevel", Name: "verbosity",
Usage: "Logging verbosity: 0-6 (0=silent, 1=error, 2=warn, 3=info, 4=core, 5=debug, 6=debug detail)", Usage: "Logging verbosity: 0-6 (0=silent, 1=error, 2=warn, 3=info, 4=core, 5=debug, 6=debug detail)",
Value: int(logger.InfoLevel), 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 { func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
// Set verbosity on glog // Set verbosity on glog
glog.SetV(ctx.GlobalInt(LogLevelFlag.Name)) glog.SetV(ctx.GlobalInt(VerbosityFlag.Name))
// Set the log type // Set the log type
//glog.SetToStderr(ctx.GlobalBool(LogToStdErrFlag.Name)) //glog.SetToStderr(ctx.GlobalBool(LogToStdErrFlag.Name))
glog.SetToStderr(true) glog.SetToStderr(true)
@ -290,7 +296,7 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
SkipBcVersionCheck: false, SkipBcVersionCheck: false,
NetworkId: ctx.GlobalInt(NetworkIdFlag.Name), NetworkId: ctx.GlobalInt(NetworkIdFlag.Name),
LogFile: ctx.GlobalString(LogFileFlag.Name), LogFile: ctx.GlobalString(LogFileFlag.Name),
LogLevel: ctx.GlobalInt(LogLevelFlag.Name), Verbosity: ctx.GlobalInt(VerbosityFlag.Name),
LogJSON: ctx.GlobalString(LogJSONFlag.Name), LogJSON: ctx.GlobalString(LogJSONFlag.Name),
Etherbase: ctx.GlobalString(EtherbaseFlag.Name), Etherbase: ctx.GlobalString(EtherbaseFlag.Name),
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.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), Shh: ctx.GlobalBool(WhisperEnabledFlag.Name),
Dial: true, Dial: true,
BootNodes: ctx.GlobalString(BootnodesFlag.Name), BootNodes: ctx.GlobalString(BootnodesFlag.Name),
GasPrice: common.String2Big(ctx.GlobalString(GasPriceFlag.Name)),
} }
} }

View File

@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"math/big"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
@ -53,12 +54,12 @@ type Config struct {
BlockChainVersion int BlockChainVersion int
SkipBcVersionCheck bool // e.g. blockchain export SkipBcVersionCheck bool // e.g. blockchain export
DataDir string DataDir string
LogFile string LogFile string
LogLevel int Verbosity int
LogJSON string LogJSON string
VmDebug bool VmDebug bool
NatSpec bool NatSpec bool
MaxPeers int MaxPeers int
MaxPendingPeers int MaxPendingPeers int
@ -76,6 +77,7 @@ type Config struct {
Dial bool Dial bool
Etherbase string Etherbase string
GasPrice *big.Int
MinerThreads int MinerThreads int
AccountManager *accounts.Manager AccountManager *accounts.Manager
@ -200,7 +202,7 @@ type Ethereum struct {
func New(config *Config) (*Ethereum, error) { func New(config *Config) (*Ethereum, error) {
// Bootstrap database // Bootstrap database
logger.New(config.DataDir, config.LogFile, config.LogLevel) logger.New(config.DataDir, config.LogFile, config.Verbosity)
if len(config.LogJSON) > 0 { if len(config.LogJSON) > 0 {
logger.NewJSONsystem(config.DataDir, config.LogJSON) 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.blockProcessor = core.NewBlockProcessor(stateDb, extraDb, eth.pow, eth.txPool, eth.chainManager, eth.EventMux())
eth.chainManager.SetProcessor(eth.blockProcessor) eth.chainManager.SetProcessor(eth.blockProcessor)
eth.miner = miner.New(eth, eth.pow, config.MinerThreads) 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) eth.protocolManager = NewProtocolManager(config.ProtocolVersion, config.NetworkId, eth.eventMux, eth.txPool, eth.chainManager, eth.downloader)
if config.Shh { if config.Shh {
eth.whisper = whisper.New() eth.whisper = whisper.New()

View File

@ -37,6 +37,15 @@ func (self *Miner) Mining() bool {
return self.mining 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) { func (self *Miner) Start(coinbase common.Address) {
self.mining = true self.mining = true
self.worker.coinbase = coinbase self.worker.coinbase = coinbase

View File

@ -72,6 +72,7 @@ type worker struct {
proc *core.BlockProcessor proc *core.BlockProcessor
coinbase common.Address coinbase common.Address
gasPrice *big.Int
extra []byte extra []byte
currentMu sync.Mutex currentMu sync.Mutex
@ -93,6 +94,7 @@ func newWorker(coinbase common.Address, eth core.Backend) *worker {
eth: eth, eth: eth,
mux: eth.EventMux(), mux: eth.EventMux(),
recv: make(chan *types.Block), recv: make(chan *types.Block),
gasPrice: new(big.Int),
chain: eth.ChainManager(), chain: eth.ChainManager(),
proc: eth.BlockProcessor(), proc: eth.BlockProcessor(),
possibleUncles: make(map[common.Hash]*types.Block), possibleUncles: make(map[common.Hash]*types.Block),
@ -123,6 +125,9 @@ func (self *worker) pendingBlock() *types.Block {
} }
func (self *worker) start() { func (self *worker) start() {
self.mu.Lock()
defer self.mu.Unlock()
// spin up agents // spin up agents
for _, agent := range self.agents { for _, agent := range self.agents {
agent.Start() agent.Start()
@ -132,6 +137,9 @@ func (self *worker) start() {
} }
func (self *worker) stop() { func (self *worker) stop() {
self.mu.Lock()
defer self.mu.Unlock()
if atomic.LoadInt32(&self.mining) == 1 { if atomic.LoadInt32(&self.mining) == 1 {
// stop all agents // stop all agents
for _, agent := range self.agents { for _, agent := range self.agents {
@ -144,6 +152,9 @@ func (self *worker) stop() {
} }
func (self *worker) register(agent Agent) { func (self *worker) register(agent Agent) {
self.mu.Lock()
defer self.mu.Unlock()
self.agents = append(self.agents, agent) self.agents = append(self.agents, agent)
agent.SetReturnCh(self.recv) agent.SetReturnCh(self.recv)
} }
@ -239,6 +250,12 @@ func (self *worker) makeCurrent() {
self.current.coinbase.SetGasPool(core.CalcGasLimit(parent)) 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() { func (self *worker) commitNewWork() {
self.mu.Lock() self.mu.Lock()
defer self.mu.Unlock() defer self.mu.Unlock()
@ -259,9 +276,23 @@ func (self *worker) commitNewWork() {
ignoredTransactors = set.New() 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 { for _, tx := range transactions {
// We can skip err. It has already been validated in the tx pool // We can skip err. It has already been validated in the tx pool
from, _ := tx.From() 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 // 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 // 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 // the transaction is processed (that could potentially be included in the block) it
@ -383,3 +414,12 @@ func (self *worker) HashRate() int64 {
return tot 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
}

View File

@ -103,7 +103,7 @@ func testEthConfig() *eth.Config {
return &eth.Config{ return &eth.Config{
DataDir: common.DefaultDataDir(), DataDir: common.DefaultDataDir(),
LogLevel: 5, Verbosity: 5,
Etherbase: "primary", Etherbase: "primary",
AccountManager: accounts.NewManager(ks), AccountManager: accounts.NewManager(ks),
NewDB: func(path string) (common.Database, error) { return ethdb.NewMemDatabase() }, NewDB: func(path string) (common.Database, error) { return ethdb.NewMemDatabase() },