Patch for concurrent iterator & others (onto v1.11.6) #386

Closed
roysc wants to merge 1565 commits from v1.11.6-statediff-v5 into master
6 changed files with 63 additions and 75 deletions
Showing only changes of commit 2b44ef5f93 - Show all commits

View File

@ -146,7 +146,7 @@ func startLightServer(t *testing.T) *gethrpc {
t.Logf("Importing keys to geth") t.Logf("Importing keys to geth")
runGeth(t, "account", "import", "--datadir", datadir, "--password", "./testdata/password.txt", "--lightkdf", "./testdata/key.prv").WaitExit() runGeth(t, "account", "import", "--datadir", datadir, "--password", "./testdata/password.txt", "--lightkdf", "./testdata/key.prv").WaitExit()
account := "0x02f0d131f1f97aef08aec6e3291b957d9efe7105" account := "0x02f0d131f1f97aef08aec6e3291b957d9efe7105"
server := startGethWithIpc(t, "lightserver", "--allow-insecure-unlock", "--datadir", datadir, "--password", "./testdata/password.txt", "--unlock", account, "--mine", "--light.serve=100", "--light.maxpeers=1", "--nodiscover", "--nat=extip:127.0.0.1", "--verbosity=4") server := startGethWithIpc(t, "lightserver", "--allow-insecure-unlock", "--datadir", datadir, "--password", "./testdata/password.txt", "--unlock", account, "--miner.etherbase=0x02f0d131f1f97aef08aec6e3291b957d9efe7105", "--mine", "--light.serve=100", "--light.maxpeers=1", "--nodiscover", "--nat=extip:127.0.0.1", "--verbosity=4")
return server return server
} }

View File

@ -538,8 +538,7 @@ var (
} }
MinerEtherbaseFlag = &cli.StringFlag{ MinerEtherbaseFlag = &cli.StringFlag{
Name: "miner.etherbase", Name: "miner.etherbase",
Usage: "Public address for block mining rewards (default = first account)", Usage: "0x prefixed public address for block mining rewards",
Value: "0",
Category: flags.MinerCategory, Category: flags.MinerCategory,
} }
MinerExtraDataFlag = &cli.StringFlag{ MinerExtraDataFlag = &cli.StringFlag{
@ -1343,25 +1342,15 @@ func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error
return accs[index], nil return accs[index], nil
} }
// setEtherbase retrieves the etherbase either from the directly specified // setEtherbase retrieves the etherbase from the directly specified command line flags.
// command line flags or from the keystore if CLI indexed. func setEtherbase(ctx *cli.Context, cfg *ethconfig.Config) {
func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *ethconfig.Config) {
// Extract the current etherbase
var etherbase string
if ctx.IsSet(MinerEtherbaseFlag.Name) { if ctx.IsSet(MinerEtherbaseFlag.Name) {
etherbase = ctx.String(MinerEtherbaseFlag.Name) b, err := hexutil.Decode(ctx.String(MinerEtherbaseFlag.Name))
} if err != nil || len(b) != common.AddressLength {
// Convert the etherbase into an address and configure it log.Info("Failed to decode etherbase", "err", err)
if etherbase != "" { return
if ks != nil {
account, err := MakeAddress(ks, etherbase)
if err != nil {
Fatalf("Invalid miner etherbase: %v", err)
}
cfg.Miner.Etherbase = account.Address
} else {
Fatalf("No etherbase configured")
} }
cfg.Miner.Etherbase = common.BytesToAddress(b)
} }
} }
@ -1739,11 +1728,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(LightServeFlag.Name) && ctx.Uint64(TxLookupLimitFlag.Name) != 0 { if ctx.IsSet(LightServeFlag.Name) && ctx.Uint64(TxLookupLimitFlag.Name) != 0 {
log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited") log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited")
} }
var ks *keystore.KeyStore setEtherbase(ctx, cfg)
if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
ks = keystores[0].(*keystore.KeyStore)
}
setEtherbase(ctx, ks, cfg)
setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light") setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light")
setTxPool(ctx, &cfg.TxPool) setTxPool(ctx, &cfg.TxPool)
setEthash(ctx, cfg) setEthash(ctx, cfg)
@ -1921,6 +1906,14 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
// when we're definitely concerned with only one account. // when we're definitely concerned with only one account.
passphrase = list[0] passphrase = list[0]
} }
// Unlock the developer account by local keystore.
var ks *keystore.KeyStore
if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
ks = keystores[0].(*keystore.KeyStore)
}
if ks == nil {
Fatalf("Keystore is not available")
}
// setEtherbase has been called above, configuring the miner address from command line flags. // setEtherbase has been called above, configuring the miner address from command line flags.
if cfg.Miner.Etherbase != (common.Address{}) { if cfg.Miner.Etherbase != (common.Address{}) {
developer = accounts.Account{Address: cfg.Miner.Etherbase} developer = accounts.Account{Address: cfg.Miner.Etherbase}

View File

@ -329,18 +329,6 @@ func (s *Ethereum) Etherbase() (eb common.Address, err error) {
if etherbase != (common.Address{}) { if etherbase != (common.Address{}) {
return etherbase, nil return etherbase, nil
} }
if wallets := s.AccountManager().Wallets(); len(wallets) > 0 {
if accounts := wallets[0].Accounts(); len(accounts) > 0 {
etherbase := accounts[0].Address
s.lock.Lock()
s.etherbase = etherbase
s.lock.Unlock()
log.Info("Etherbase automatically configured", "address", etherbase)
return etherbase, nil
}
}
return common.Address{}, fmt.Errorf("etherbase must be explicitly specified") return common.Address{}, fmt.Errorf("etherbase must be explicitly specified")
} }
@ -456,7 +444,7 @@ func (s *Ethereum) StartMining(threads int) error {
// introduced to speed sync times. // introduced to speed sync times.
atomic.StoreUint32(&s.handler.acceptTxs, 1) atomic.StoreUint32(&s.handler.acceptTxs, 1)
go s.miner.Start(eb) go s.miner.Start()
} }
return nil return nil
} }

View File

@ -45,7 +45,7 @@ type Backend interface {
// Config is the configuration parameters of mining. // Config is the configuration parameters of mining.
type Config struct { type Config struct {
Etherbase common.Address `toml:",omitempty"` // Public address for block mining rewards (default = first account) Etherbase common.Address `toml:",omitempty"` // Public address for block mining rewards
Notify []string `toml:",omitempty"` // HTTP URL list to be notified of new work packages (only useful in ethash). Notify []string `toml:",omitempty"` // HTTP URL list to be notified of new work packages (only useful in ethash).
NotifyFull bool `toml:",omitempty"` // Notify with pending block headers instead of work packages NotifyFull bool `toml:",omitempty"` // Notify with pending block headers instead of work packages
ExtraData hexutil.Bytes `toml:",omitempty"` // Block extra data set by the miner ExtraData hexutil.Bytes `toml:",omitempty"` // Block extra data set by the miner
@ -73,25 +73,24 @@ var DefaultConfig = Config{
// Miner creates blocks and searches for proof-of-work values. // Miner creates blocks and searches for proof-of-work values.
type Miner struct { type Miner struct {
mux *event.TypeMux mux *event.TypeMux
worker *worker eth Backend
coinbase common.Address engine consensus.Engine
eth Backend exitCh chan struct{}
engine consensus.Engine startCh chan struct{}
exitCh chan struct{} stopCh chan struct{}
startCh chan common.Address worker *worker
stopCh chan struct{}
wg sync.WaitGroup wg sync.WaitGroup
} }
func New(eth Backend, config *Config, chainConfig *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, isLocalBlock func(header *types.Header) bool) *Miner { func New(eth Backend, config *Config, chainConfig *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, isLocalBlock func(header *types.Header) bool) *Miner {
miner := &Miner{ miner := &Miner{
eth: eth,
mux: mux, mux: mux,
eth: eth,
engine: engine, engine: engine,
exitCh: make(chan struct{}), exitCh: make(chan struct{}),
startCh: make(chan common.Address), startCh: make(chan struct{}),
stopCh: make(chan struct{}), stopCh: make(chan struct{}),
worker: newWorker(config, chainConfig, engine, eth, mux, isLocalBlock, true), worker: newWorker(config, chainConfig, engine, eth, mux, isLocalBlock, true),
} }
@ -138,20 +137,17 @@ func (miner *Miner) update() {
case downloader.FailedEvent: case downloader.FailedEvent:
canStart = true canStart = true
if shouldStart { if shouldStart {
miner.SetEtherbase(miner.coinbase)
miner.worker.start() miner.worker.start()
} }
case downloader.DoneEvent: case downloader.DoneEvent:
canStart = true canStart = true
if shouldStart { if shouldStart {
miner.SetEtherbase(miner.coinbase)
miner.worker.start() miner.worker.start()
} }
// Stop reacting to downloader events // Stop reacting to downloader events
events.Unsubscribe() events.Unsubscribe()
} }
case addr := <-miner.startCh: case <-miner.startCh:
miner.SetEtherbase(addr)
if canStart { if canStart {
miner.worker.start() miner.worker.start()
} }
@ -166,8 +162,8 @@ func (miner *Miner) update() {
} }
} }
func (miner *Miner) Start(coinbase common.Address) { func (miner *Miner) Start() {
miner.startCh <- coinbase miner.startCh <- struct{}{}
} }
func (miner *Miner) Stop() { func (miner *Miner) Stop() {
@ -223,7 +219,6 @@ func (miner *Miner) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
} }
func (miner *Miner) SetEtherbase(addr common.Address) { func (miner *Miner) SetEtherbase(addr common.Address) {
miner.coinbase = addr
miner.worker.setEtherbase(addr) miner.worker.setEtherbase(addr)
} }

View File

@ -86,7 +86,8 @@ func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent)
func TestMiner(t *testing.T) { func TestMiner(t *testing.T) {
miner, mux, cleanup := createMiner(t) miner, mux, cleanup := createMiner(t)
defer cleanup(false) defer cleanup(false)
miner.Start(common.HexToAddress("0x12345"))
miner.Start()
waitForMiningState(t, miner, true) waitForMiningState(t, miner, true)
// Start the downloader // Start the downloader
mux.Post(downloader.StartEvent{}) mux.Post(downloader.StartEvent{})
@ -114,7 +115,8 @@ func TestMiner(t *testing.T) {
func TestMinerDownloaderFirstFails(t *testing.T) { func TestMinerDownloaderFirstFails(t *testing.T) {
miner, mux, cleanup := createMiner(t) miner, mux, cleanup := createMiner(t)
defer cleanup(false) defer cleanup(false)
miner.Start(common.HexToAddress("0x12345"))
miner.Start()
waitForMiningState(t, miner, true) waitForMiningState(t, miner, true)
// Start the downloader // Start the downloader
mux.Post(downloader.StartEvent{}) mux.Post(downloader.StartEvent{})
@ -146,7 +148,8 @@ func TestMinerDownloaderFirstFails(t *testing.T) {
func TestMinerStartStopAfterDownloaderEvents(t *testing.T) { func TestMinerStartStopAfterDownloaderEvents(t *testing.T) {
miner, mux, cleanup := createMiner(t) miner, mux, cleanup := createMiner(t)
defer cleanup(false) defer cleanup(false)
miner.Start(common.HexToAddress("0x12345"))
miner.Start()
waitForMiningState(t, miner, true) waitForMiningState(t, miner, true)
// Start the downloader // Start the downloader
mux.Post(downloader.StartEvent{}) mux.Post(downloader.StartEvent{})
@ -159,7 +162,7 @@ func TestMinerStartStopAfterDownloaderEvents(t *testing.T) {
miner.Stop() miner.Stop()
waitForMiningState(t, miner, false) waitForMiningState(t, miner, false)
miner.Start(common.HexToAddress("0x678910")) miner.Start()
waitForMiningState(t, miner, true) waitForMiningState(t, miner, true)
miner.Stop() miner.Stop()
@ -170,13 +173,13 @@ func TestStartWhileDownload(t *testing.T) {
miner, mux, cleanup := createMiner(t) miner, mux, cleanup := createMiner(t)
defer cleanup(false) defer cleanup(false)
waitForMiningState(t, miner, false) waitForMiningState(t, miner, false)
miner.Start(common.HexToAddress("0x12345")) miner.Start()
waitForMiningState(t, miner, true) waitForMiningState(t, miner, true)
// Stop the downloader and wait for the update loop to run // Stop the downloader and wait for the update loop to run
mux.Post(downloader.StartEvent{}) mux.Post(downloader.StartEvent{})
waitForMiningState(t, miner, false) waitForMiningState(t, miner, false)
// Starting the miner after the downloader should not work // Starting the miner after the downloader should not work
miner.Start(common.HexToAddress("0x12345")) miner.Start()
waitForMiningState(t, miner, false) waitForMiningState(t, miner, false)
} }
@ -184,7 +187,7 @@ func TestStartStopMiner(t *testing.T) {
miner, _, cleanup := createMiner(t) miner, _, cleanup := createMiner(t)
defer cleanup(false) defer cleanup(false)
waitForMiningState(t, miner, false) waitForMiningState(t, miner, false)
miner.Start(common.HexToAddress("0x12345")) miner.Start()
waitForMiningState(t, miner, true) waitForMiningState(t, miner, true)
miner.Stop() miner.Stop()
waitForMiningState(t, miner, false) waitForMiningState(t, miner, false)
@ -194,7 +197,7 @@ func TestCloseMiner(t *testing.T) {
miner, _, cleanup := createMiner(t) miner, _, cleanup := createMiner(t)
defer cleanup(true) defer cleanup(true)
waitForMiningState(t, miner, false) waitForMiningState(t, miner, false)
miner.Start(common.HexToAddress("0x12345")) miner.Start()
waitForMiningState(t, miner, true) waitForMiningState(t, miner, true)
// Terminate the miner and wait for the update loop to run // Terminate the miner and wait for the update loop to run
miner.Close() miner.Close()
@ -206,21 +209,21 @@ func TestCloseMiner(t *testing.T) {
func TestMinerSetEtherbase(t *testing.T) { func TestMinerSetEtherbase(t *testing.T) {
miner, mux, cleanup := createMiner(t) miner, mux, cleanup := createMiner(t)
defer cleanup(false) defer cleanup(false)
// Start with a 'bad' mining address miner.Start()
miner.Start(common.HexToAddress("0xdead"))
waitForMiningState(t, miner, true) waitForMiningState(t, miner, true)
// Start the downloader // Start the downloader
mux.Post(downloader.StartEvent{}) mux.Post(downloader.StartEvent{})
waitForMiningState(t, miner, false) waitForMiningState(t, miner, false)
// Now user tries to configure proper mining address // Now user tries to configure proper mining address
miner.Start(common.HexToAddress("0x1337")) miner.Start()
// Stop the downloader and wait for the update loop to run // Stop the downloader and wait for the update loop to run
mux.Post(downloader.DoneEvent{}) mux.Post(downloader.DoneEvent{})
waitForMiningState(t, miner, true) waitForMiningState(t, miner, true)
// The miner should now be using the good address
if got, exp := miner.coinbase, common.HexToAddress("0x1337"); got != exp { coinbase := common.HexToAddress("0xdeedbeef")
t.Fatalf("Wrong coinbase, got %x expected %x", got, exp) miner.SetEtherbase(coinbase)
if addr := miner.worker.etherbase(); addr != coinbase {
t.Fatalf("Unexpected etherbase want %x got %x", coinbase, addr)
} }
} }

View File

@ -276,12 +276,14 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
chainConfig: chainConfig, chainConfig: chainConfig,
engine: engine, engine: engine,
eth: eth, eth: eth,
mux: mux,
chain: eth.BlockChain(), chain: eth.BlockChain(),
mux: mux,
isLocalBlock: isLocalBlock, isLocalBlock: isLocalBlock,
localUncles: make(map[common.Hash]*types.Block), localUncles: make(map[common.Hash]*types.Block),
remoteUncles: make(map[common.Hash]*types.Block), remoteUncles: make(map[common.Hash]*types.Block),
unconfirmed: newUnconfirmedBlocks(eth.BlockChain(), sealingLogAtDepth), unconfirmed: newUnconfirmedBlocks(eth.BlockChain(), sealingLogAtDepth),
coinbase: config.Etherbase,
extra: config.ExtraData,
pendingTasks: make(map[common.Hash]*task), pendingTasks: make(map[common.Hash]*task),
txsCh: make(chan core.NewTxsEvent, txChanSize), txsCh: make(chan core.NewTxsEvent, txChanSize),
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
@ -290,8 +292,8 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
getWorkCh: make(chan *getWorkReq), getWorkCh: make(chan *getWorkReq),
taskCh: make(chan *task), taskCh: make(chan *task),
resultCh: make(chan *types.Block, resultQueueSize), resultCh: make(chan *types.Block, resultQueueSize),
exitCh: make(chan struct{}),
startCh: make(chan struct{}, 1), startCh: make(chan struct{}, 1),
exitCh: make(chan struct{}),
resubmitIntervalCh: make(chan time.Duration), resubmitIntervalCh: make(chan time.Duration),
resubmitAdjustCh: make(chan *intervalAdjust, resubmitAdjustChanSize), resubmitAdjustCh: make(chan *intervalAdjust, resubmitAdjustChanSize),
} }
@ -340,6 +342,13 @@ func (w *worker) setEtherbase(addr common.Address) {
w.coinbase = addr w.coinbase = addr
} }
// etherbase retrieves the configured etherbase address.
func (w *worker) etherbase() common.Address {
w.mu.RLock()
defer w.mu.RUnlock()
return w.coinbase
}
func (w *worker) setGasCeil(ceil uint64) { func (w *worker) setGasCeil(ceil uint64) {
w.mu.Lock() w.mu.Lock()
defer w.mu.Unlock() defer w.mu.Unlock()
@ -1114,11 +1123,11 @@ func (w *worker) commitWork(interrupt *int32, noempty bool, timestamp int64) {
// Set the coinbase if the worker is running or it's required // Set the coinbase if the worker is running or it's required
var coinbase common.Address var coinbase common.Address
if w.isRunning() { if w.isRunning() {
if w.coinbase == (common.Address{}) { coinbase = w.etherbase()
if coinbase == (common.Address{}) {
log.Error("Refusing to mine without etherbase") log.Error("Refusing to mine without etherbase")
return return
} }
coinbase = w.coinbase // Use the preset address as the fee recipient
} }
work, err := w.prepareWork(&generateParams{ work, err := w.prepareWork(&generateParams{
timestamp: uint64(timestamp), timestamp: uint64(timestamp),