eth: accept transactions when starting CPU mining (#13882)

This commit is contained in:
Péter Szilágyi 2017-04-10 11:43:01 +03:00 committed by Felix Lange
parent f32b72ca5d
commit bfe5eb7f8c
6 changed files with 18 additions and 10 deletions

@ -301,7 +301,7 @@ func startNode(ctx *cli.Context, stack *node.Node) {
th.SetThreads(threads) th.SetThreads(threads)
} }
} }
if err := ethereum.StartMining(); err != nil { if err := ethereum.StartMining(true); err != nil {
utils.Fatalf("Failed to start mining: %v", err) utils.Fatalf("Failed to start mining: %v", err)
} }
} }

@ -103,7 +103,7 @@ func (api *PublicMinerAPI) SubmitWork(nonce types.BlockNonce, solution, digest c
// result[2], 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty // result[2], 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty
func (api *PublicMinerAPI) GetWork() ([3]string, error) { func (api *PublicMinerAPI) GetWork() ([3]string, error) {
if !api.e.IsMining() { if !api.e.IsMining() {
if err := api.e.StartMining(); err != nil { if err := api.e.StartMining(false); err != nil {
return [3]string{}, err return [3]string{}, err
} }
} }
@ -153,7 +153,7 @@ func (api *PrivateMinerAPI) Start(threads *int) error {
} }
// Start the miner and return // Start the miner and return
if !api.e.IsMining() { if !api.e.IsMining() {
return api.e.StartMining() return api.e.StartMining(true)
} }
return nil return nil
} }

@ -22,6 +22,7 @@ import (
"math/big" "math/big"
"regexp" "regexp"
"sync" "sync"
"sync/atomic"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -326,12 +327,19 @@ func (self *Ethereum) SetEtherbase(etherbase common.Address) {
self.miner.SetEtherbase(etherbase) self.miner.SetEtherbase(etherbase)
} }
func (s *Ethereum) StartMining() error { func (s *Ethereum) StartMining(local bool) error {
eb, err := s.Etherbase() eb, err := s.Etherbase()
if err != nil { if err != nil {
log.Error("Cannot start mining without etherbase", "err", err) log.Error("Cannot start mining without etherbase", "err", err)
return fmt.Errorf("etherbase missing: %v", err) return fmt.Errorf("etherbase missing: %v", err)
} }
if local {
// If local (CPU) mining is started, we can disable the transaction rejection
// mechanism introduced to speed sync times. CPU mining on mainnet is ludicrous
// so noone will ever hit this path, whereas marking sync done on CPU mining
// will ensure that private networks work in single miner mode too.
atomic.StoreUint32(&s.protocolManager.acceptTxs, 1)
}
go s.miner.Start(eb) go s.miner.Start(eb)
return nil return nil
} }

@ -62,8 +62,8 @@ func errResp(code errCode, format string, v ...interface{}) error {
type ProtocolManager struct { type ProtocolManager struct {
networkId int networkId int
fastSync uint32 // Flag whether fast sync is enabled (gets disabled if we already have blocks) fastSync uint32 // Flag whether fast sync is enabled (gets disabled if we already have blocks)
synced uint32 // Flag whether we're considered synchronised (enables transaction processing) acceptTxs uint32 // Flag whether we're considered synchronised (enables transaction processing)
txpool txPool txpool txPool
blockchain *core.BlockChain blockchain *core.BlockChain
@ -171,7 +171,7 @@ func NewProtocolManager(config *params.ChainConfig, fastSync bool, networkId int
return blockchain.CurrentBlock().NumberU64() return blockchain.CurrentBlock().NumberU64()
} }
inserter := func(blocks types.Blocks) (int, error) { inserter := func(blocks types.Blocks) (int, error) {
atomic.StoreUint32(&manager.synced, 1) // Mark initial sync done on any fetcher import atomic.StoreUint32(&manager.acceptTxs, 1) // Mark initial sync done on any fetcher import
return manager.blockchain.InsertChain(blocks) return manager.blockchain.InsertChain(blocks)
} }
manager.fetcher = fetcher.New(blockchain.GetBlockByHash, validator, manager.BroadcastBlock, heighter, inserter, manager.removePeer) manager.fetcher = fetcher.New(blockchain.GetBlockByHash, validator, manager.BroadcastBlock, heighter, inserter, manager.removePeer)
@ -643,7 +643,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
case msg.Code == TxMsg: case msg.Code == TxMsg:
// Transactions arrived, make sure we have a valid and fresh chain to handle them // Transactions arrived, make sure we have a valid and fresh chain to handle them
if atomic.LoadUint32(&pm.synced) == 0 { if atomic.LoadUint32(&pm.acceptTxs) == 0 {
break break
} }
// Transactions can be processed, parse all of them and deliver to the pool // Transactions can be processed, parse all of them and deliver to the pool

@ -94,7 +94,7 @@ func TestRecvTransactions63(t *testing.T) { testRecvTransactions(t, 63) }
func testRecvTransactions(t *testing.T, protocol int) { func testRecvTransactions(t *testing.T, protocol int) {
txAdded := make(chan []*types.Transaction) txAdded := make(chan []*types.Transaction)
pm := newTestProtocolManagerMust(t, false, 0, nil, txAdded) pm := newTestProtocolManagerMust(t, false, 0, nil, txAdded)
pm.synced = 1 // mark synced to accept transactions pm.acceptTxs = 1 // mark synced to accept transactions
p, _ := newTestPeer("peer", protocol, pm, true) p, _ := newTestPeer("peer", protocol, pm, true)
defer pm.Stop() defer pm.Stop()
defer p.close() defer p.close()

@ -188,7 +188,7 @@ func (pm *ProtocolManager) synchronise(peer *peer) {
if err := pm.downloader.Synchronise(peer.id, pHead, pTd, mode); err != nil { if err := pm.downloader.Synchronise(peer.id, pHead, pTd, mode); err != nil {
return return
} }
atomic.StoreUint32(&pm.synced, 1) // Mark initial sync done atomic.StoreUint32(&pm.acceptTxs, 1) // Mark initial sync done
if head := pm.blockchain.CurrentBlock(); head.NumberU64() > 0 { if head := pm.blockchain.CurrentBlock(); head.NumberU64() > 0 {
// We've completed a sync cycle, notify all peers of new state. This path is // We've completed a sync cycle, notify all peers of new state. This path is
// essential in star-topology networks where a gateway node needs to notify // essential in star-topology networks where a gateway node needs to notify