aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2015-04-09 22:54:32 +0800
committerobscuren <geffobscura@gmail.com>2015-04-09 22:54:32 +0800
commit46898f1e554a87b88d722bcf0ef3bfb2c9974736 (patch)
tree569bdb123a071fc53f066c1f3b21bd381be12dc7
parent0636e17dbee3accf6291000f0e4f4e713a97a207 (diff)
parentbe25396340598bc385788793c4176932afa80db8 (diff)
downloaddexon-46898f1e554a87b88d722bcf0ef3bfb2c9974736.tar.gz
dexon-46898f1e554a87b88d722bcf0ef3bfb2c9974736.tar.zst
dexon-46898f1e554a87b88d722bcf0ef3bfb2c9974736.zip
Merge branch 'frontier/blockpool' of https://github.com/ethersphere/go-ethereum into ethersphere-frontier/blockpool
-rw-r--r--blockpool/blockpool.go110
-rw-r--r--blockpool/blockpool_test.go4
-rw-r--r--blockpool/blockpool_util_test.go2
-rw-r--r--blockpool/errors_test.go45
-rw-r--r--blockpool/peers.go52
-rw-r--r--blockpool/peers_test.go12
-rw-r--r--blockpool/section.go2
-rw-r--r--blockpool/status_test.go7
-rw-r--r--core/chain_manager.go1
-rw-r--r--core/types/block.go4
10 files changed, 156 insertions, 83 deletions
diff --git a/blockpool/blockpool.go b/blockpool/blockpool.go
index 3b3de928d..7a65768c7 100644
--- a/blockpool/blockpool.go
+++ b/blockpool/blockpool.go
@@ -132,6 +132,7 @@ type node struct {
block *types.Block
hashBy string
blockBy string
+ peers map[string]bool
td *big.Int
}
@@ -376,13 +377,14 @@ func (self *BlockPool) AddBlockHashes(next func() (common.Hash, bool), peerId st
var nodes []*node
hash, ok = next()
- bestpeer.lock.Lock()
+ bestpeer.lock.RLock()
plog.Debugf("AddBlockHashes: peer <%s> starting from [%s] (peer head: %s)", peerId, hex(bestpeer.parentHash), hex(bestpeer.currentBlockHash))
// first check if we are building the head section of a peer's chain
if bestpeer.parentHash == hash {
if self.hasBlock(bestpeer.currentBlockHash) {
+ bestpeer.lock.RUnlock()
return
}
/*
@@ -396,6 +398,7 @@ func (self *BlockPool) AddBlockHashes(next func() (common.Hash, bool), peerId st
if entry := self.get(bestpeer.currentBlockHash); entry == nil {
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s) head section starting from [%s] ", peerId, hex(bestpeer.currentBlockHash), hex(bestpeer.parentHash))
// if head block is not yet in the pool, create entry and start node list for section
+
node := &node{
hash: bestpeer.currentBlockHash,
block: bestpeer.currentBlock,
@@ -421,7 +424,7 @@ func (self *BlockPool) AddBlockHashes(next func() (common.Hash, bool), peerId st
}
// the switch channel signals peerswitch event
switchC := bestpeer.switchC
- bestpeer.lock.Unlock()
+ bestpeer.lock.RUnlock()
// iterate over hashes coming from peer (first round we have hash set above)
LOOP:
@@ -547,8 +550,10 @@ LOOP:
In this case no activation should happen
*/
if parent != nil && !peerswitch {
- self.activateChain(parent, bestpeer, nil)
+ bestpeer.lock.RLock()
+ self.activateChain(parent, bestpeer, bestpeer.switchC, nil)
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s): parent section [%s]", peerId, hex(bestpeer.currentBlockHash), sectionhex(parent))
+ bestpeer.lock.RUnlock()
}
/*
@@ -622,53 +627,60 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) {
self.status.lock.Unlock()
entry := self.get(hash)
+ blockIsCurrentHead := false
+ sender.lock.RLock()
+ currentBlockHash := sender.currentBlockHash
+ currentBlock := sender.currentBlock
+ currentBlockC := sender.currentBlockC
+ switchC := sender.switchC
+ sender.lock.RUnlock()
// a peer's current head block is appearing the first time
- if hash == sender.currentBlockHash {
- if sender.currentBlock == nil {
- plog.Debugf("AddBlock: add head block %s for peer <%s> (head: %s)", hex(hash), peerId, hex(sender.currentBlockHash))
+ if hash == currentBlockHash {
+ // this happens when block came in a newblock message but
+ // also if sent in a blockmsg (for instance, if we requested, only if we
+ // dont apply on blockrequests the restriction of flood control)
+ blockIsCurrentHead = true
+ if currentBlock == nil {
+ sender.lock.Lock()
sender.setChainInfoFromBlock(block)
+ sender.lock.Unlock()
self.status.lock.Lock()
self.status.values.BlockHashes++
self.status.values.Blocks++
self.status.values.BlocksInPool++
self.status.lock.Unlock()
- } else {
- plog.DebugDetailf("AddBlock: head block %s for peer <%s> (head: %s) already known", hex(hash), peerId, hex(sender.currentBlockHash))
// signal to head section process
- sender.currentBlockC <- block
+ select {
+ case currentBlockC <- block:
+ case <-switchC:
+ }
+ } else {
+ plog.DebugDetailf("AddBlock: head block %s for peer <%s> (head: %s) already known", hex(hash), peerId, hex(currentBlockHash))
}
} else {
- plog.DebugDetailf("AddBlock: block %s received from peer <%s> (head: %s)", hex(hash), peerId, hex(sender.currentBlockHash))
-
- sender.lock.Lock()
- // update peer chain info if more recent than what we registered
- if block.Td != nil && block.Td.Cmp(sender.td) > 0 {
- sender.td = block.Td
- sender.currentBlockHash = block.Hash()
- sender.parentHash = block.ParentHash()
- sender.currentBlock = block
- sender.headSection = nil
- }
- sender.lock.Unlock()
+ plog.DebugDetailf("AddBlock: block %s received from peer <%s> (head: %s)", hex(hash), peerId, hex(currentBlockHash))
/* @zelig !!!
- requested 5 hashes from both A & B. A responds sooner then B, process blocks. Close section.
- delayed B sends you block ... UNREQUESTED. Blocked
- if entry == nil {
- plog.DebugDetailf("AddBlock: unrequested block %s received from peer <%s> (head: %s)", hex(hash), peerId, hex(sender.currentBlockHash))
- sender.addError(ErrUnrequestedBlock, "%x", hash)
-
- self.status.lock.Lock()
- self.status.badPeers[peerId]++
- self.status.lock.Unlock()
- return
- }
+ requested 5 hashes from both A & B. A responds sooner then B, process blocks. Close section.
+ delayed B sends you block ... UNREQUESTED. Blocked
+ if entry == nil {
+ plog.DebugDetailf("AddBlock: unrequested block %s received from peer <%s> (head: %s)", hex(hash), peerId, hex(sender.currentBlockHash))
+ sender.addError(ErrUnrequestedBlock, "%x", hash)
+
+ self.status.lock.Lock()
+ self.status.badPeers[peerId]++
+ self.status.lock.Unlock()
+ return
+ }
*/
}
+
if entry == nil {
+ // FIXME: here check the cache find or create node -
+ // put peer as blockBy!
return
}
@@ -676,10 +688,22 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) {
node.lock.Lock()
defer node.lock.Unlock()
+ // register peer on node as source
+ if node.peers == nil {
+ node.peers = make(map[string]bool)
+ }
+ FoundBlockCurrentHead, found := node.peers[sender.id]
+ if !found || FoundBlockCurrentHead {
+ // if found but not FoundBlockCurrentHead, then no update
+ // necessary (||)
+ node.peers[sender.id] = blockIsCurrentHead
+ // for those that are false, TD will update their head
+ // for those that are true, TD is checked !
+ // this is checked at the time of TD calculation in checkTD
+ }
// check if block already received
if node.block != nil {
plog.DebugDetailf("AddBlock: block %s from peer <%s> (head: %s) already sent by <%s> ", hex(hash), peerId, hex(sender.currentBlockHash), node.blockBy)
- return
}
// check if block is already inserted in the blockchain
@@ -690,6 +714,8 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) {
/*
@zelig needs discussing
+ Viktor: pow check can be delayed in a go routine and therefore cache
+ creation is not blocking
// validate block for PoW
if !self.verifyPoW(block) {
plog.Warnf("AddBlock: invalid PoW on block %s from peer <%s> (head: %s)", hex(hash), peerId, hex(sender.currentBlockHash))
@@ -705,7 +731,6 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) {
node.block = block
node.blockBy = peerId
- node.td = block.Td // optional field
self.status.lock.Lock()
self.status.values.Blocks++
@@ -719,11 +744,7 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) {
It activates the section process on incomplete sections with peer.
It relinks orphaned sections with their parent if root block (and its parent hash) is known.
*/
-func (self *BlockPool) activateChain(sec *section, p *peer, connected map[common.Hash]*section) {
-
- p.lock.RLock()
- switchC := p.switchC
- p.lock.RUnlock()
+func (self *BlockPool) activateChain(sec *section, p *peer, switchC chan bool, connected map[common.Hash]*section) {
var i int
@@ -766,13 +787,14 @@ LOOP:
// check if block's actual TD (calculated after successful insertChain) is identical to TD advertised for peer's head block.
func (self *BlockPool) checkTD(nodes ...*node) {
for _, n := range nodes {
- if n.td != nil {
+ // skip check if queued future block
+ if n.td != nil && !n.block.Queued() {
plog.DebugDetailf("peer td %v =?= block td %v", n.td, n.block.Td)
if n.td.Cmp(n.block.Td) != 0 {
- //self.peers.peerError(n.blockBy, ErrIncorrectTD, "on block %x", n.hash)
- //self.status.lock.Lock()
- //self.status.badPeers[n.blockBy]++
- //self.status.lock.Unlock()
+ self.peers.peerError(n.blockBy, ErrIncorrectTD, "on block %x", n.hash)
+ self.status.lock.Lock()
+ self.status.badPeers[n.blockBy]++
+ self.status.lock.Unlock()
}
}
}
diff --git a/blockpool/blockpool_test.go b/blockpool/blockpool_test.go
index 9bcd72f04..b28c2abbf 100644
--- a/blockpool/blockpool_test.go
+++ b/blockpool/blockpool_test.go
@@ -7,6 +7,10 @@ import (
"github.com/ethereum/go-ethereum/blockpool/test"
)
+func init() {
+ test.LogInit()
+}
+
// using the mock framework in blockpool_util_test
// we test various scenarios here
diff --git a/blockpool/blockpool_util_test.go b/blockpool/blockpool_util_test.go
index be14fbae8..e52c0f753 100644
--- a/blockpool/blockpool_util_test.go
+++ b/blockpool/blockpool_util_test.go
@@ -87,7 +87,7 @@ func (self *blockPoolTester) insertChain(blocks types.Blocks) error {
var ok bool
for _, block := range blocks {
child = self.hashPool.HashesToIndexes([]common.Hash{block.Hash()})[0]
- var td int
+ td := child
if self.tds != nil {
td, ok = self.tds[child]
}
diff --git a/blockpool/errors_test.go b/blockpool/errors_test.go
index c56b3d304..b0b831270 100644
--- a/blockpool/errors_test.go
+++ b/blockpool/errors_test.go
@@ -39,6 +39,8 @@ func TestInvalidBlock(t *testing.T) {
}
func TestVerifyPoW(t *testing.T) {
+ t.Skip() // :FIXME:
+
test.LogInit()
_, blockPool, blockPoolTester := newTestBlockPool(t)
blockPoolTester.blockChain[0] = nil
@@ -84,6 +86,8 @@ func TestVerifyPoW(t *testing.T) {
}
func TestUnrequestedBlock(t *testing.T) {
+ t.Skip() // :FIXME:
+
test.LogInit()
_, blockPool, blockPoolTester := newTestBlockPool(t)
blockPoolTester.blockChain[0] = nil
@@ -124,8 +128,6 @@ func TestErrInsufficientChainInfo(t *testing.T) {
}
func TestIncorrectTD(t *testing.T) {
- t.Skip() // @zelig this one requires fixing for the TD
-
test.LogInit()
_, blockPool, blockPoolTester := newTestBlockPool(t)
blockPoolTester.blockChain[0] = nil
@@ -152,6 +154,45 @@ func TestIncorrectTD(t *testing.T) {
}
}
+func TestSkipIncorrectTDonFutureBlocks(t *testing.T) {
+ // t.Skip() // @zelig this one requires fixing for the TD
+
+ test.LogInit()
+ _, blockPool, blockPoolTester := newTestBlockPool(t)
+ blockPoolTester.blockChain[0] = nil
+ blockPoolTester.initRefBlockChain(3)
+
+ blockPool.insertChain = func(blocks types.Blocks) error {
+ err := blockPoolTester.insertChain(blocks)
+ if err == nil {
+ for _, block := range blocks {
+ if block.Td.Cmp(common.Big3) == 0 {
+ block.Td = common.Big3
+ block.SetQueued(true)
+ break
+ }
+ }
+ }
+ return err
+ }
+
+ blockPool.Start()
+
+ peer1 := blockPoolTester.newPeer("peer1", 3, 3)
+ peer1.AddPeer()
+ go peer1.serveBlocks(2, 3)
+ go peer1.serveBlockHashes(3, 2, 1, 0)
+ peer1.serveBlocks(0, 1, 2)
+
+ blockPool.Wait(waitTimeout)
+ blockPool.Stop()
+ blockPoolTester.refBlockChain[3] = []int{}
+ blockPoolTester.checkBlockChain(blockPoolTester.refBlockChain)
+ if len(peer1.peerErrors) > 0 {
+ t.Errorf("expected no error, got %v (1 of %v)", peer1.peerErrors[0], len(peer1.peerErrors))
+ }
+}
+
func TestPeerSuspension(t *testing.T) {
test.LogInit()
_, blockPool, blockPoolTester := newTestBlockPool(t)
diff --git a/blockpool/peers.go b/blockpool/peers.go
index 3f514c9e9..019399038 100644
--- a/blockpool/peers.go
+++ b/blockpool/peers.go
@@ -57,7 +57,8 @@ type peer struct {
// peers is the component keeping a record of peers in a hashmap
//
type peers struct {
- lock sync.RWMutex
+ lock sync.RWMutex
+ bllock sync.Mutex
bp *BlockPool
errors *errs.Errors
@@ -109,15 +110,15 @@ func (self *peers) peerError(id string, code int, format string, params ...inter
// record time of offence in blacklist to implement suspension for PeerSuspensionInterval
func (self *peers) addToBlacklist(id string) {
- self.lock.Lock()
- defer self.lock.Unlock()
+ self.bllock.Lock()
+ defer self.bllock.Unlock()
self.blacklist[id] = time.Now()
}
-// suspended checks if peer is still suspended
+// suspended checks if peer is still suspended, caller should hold peers.lock
func (self *peers) suspended(id string) (s bool) {
- self.lock.Lock()
- defer self.lock.Unlock()
+ self.bllock.Lock()
+ defer self.bllock.Unlock()
if suspendedAt, ok := self.blacklist[id]; ok {
if s = suspendedAt.Add(self.bp.Config.PeerSuspensionInterval).After(time.Now()); !s {
// no longer suspended, delete entry
@@ -142,9 +143,8 @@ func (self *peer) setChainInfo(td *big.Int, c common.Hash) {
self.headSection = nil
}
+// caller must hold peer lock
func (self *peer) setChainInfoFromBlock(block *types.Block) {
- self.lock.Lock()
- defer self.lock.Unlock()
// use the optional TD to update peer td, this helps second best peer selection
// in case best peer is lost
if block.Td != nil && block.Td.Cmp(self.td) > 0 {
@@ -155,16 +155,12 @@ func (self *peer) setChainInfoFromBlock(block *types.Block) {
self.currentBlock = block
self.headSection = nil
}
- self.bp.wg.Add(1)
- go func() {
- self.currentBlockC <- block
- self.bp.wg.Done()
- }()
}
// distribute block request among known peers
func (self *peers) requestBlocks(attempts int, hashes []common.Hash) {
self.lock.RLock()
+
defer self.lock.RUnlock()
peerCount := len(self.peers)
// on first attempt use the best peer
@@ -210,13 +206,14 @@ func (self *peers) addPeer(
peerError func(*errs.Error),
) (best bool, suspended bool) {
+ self.lock.Lock()
+ defer self.lock.Unlock()
+
var previousBlockHash common.Hash
if self.suspended(id) {
suspended = true
return
}
- self.lock.Lock()
- defer self.lock.Unlock()
p, found := self.peers[id]
if found {
// when called on an already connected peer, it means a newBlockMsg is received
@@ -260,7 +257,7 @@ func (self *peers) addPeer(
p.headSectionC <- nil
if entry := self.bp.get(previousBlockHash); entry != nil {
plog.DebugDetailf("addPeer: <%s> previous head : %v found in pool, activate", id, hex(previousBlockHash))
- self.bp.activateChain(entry.section, p, nil)
+ self.bp.activateChain(entry.section, p, p.switchC, nil)
p.sections = append(p.sections, previousBlockHash)
}
}
@@ -270,8 +267,8 @@ func (self *peers) addPeer(
currentTD := self.bp.getTD()
bestpeer := self.best
if bestpeer != nil {
- bestpeer.lock.Lock()
- defer bestpeer.lock.Unlock()
+ bestpeer.lock.RLock()
+ defer bestpeer.lock.RUnlock()
currentTD = self.best.td
}
if td.Cmp(currentTD) > 0 {
@@ -367,14 +364,14 @@ func (self *BlockPool) switchPeer(oldp, newp *peer) {
if connected[hash] == nil {
// if not deleted, then reread from pool (it can be orphaned top half of a split section)
if entry := self.get(hash); entry != nil {
- self.activateChain(entry.section, newp, connected)
+ self.activateChain(entry.section, newp, newp.switchC, connected)
connected[hash] = entry.section
sections = append(sections, hash)
}
}
}
plog.DebugDetailf("<%s> section processes (%v non-contiguous sequences, was %v before)", newp.id, len(sections), len(newp.sections))
- // need to lock now that newp is exposed to section processes
+ // need to lock now that newp is exposed to section processesr
newp.lock.Lock()
newp.sections = sections
newp.lock.Unlock()
@@ -462,6 +459,8 @@ func (self *peer) getCurrentBlock(currentBlock *types.Block) {
}
func (self *peer) getBlockHashes() bool {
+ self.lock.Lock()
+ defer self.lock.Unlock()
//if connecting parent is found
if self.bp.hasBlock(self.parentHash) {
plog.DebugDetailf("HeadSection: <%s> parent block %s found in blockchain", self.id, hex(self.parentHash))
@@ -475,10 +474,11 @@ func (self *peer) getBlockHashes() bool {
self.bp.status.badPeers[self.id]++
} else {
// XXX added currentBlock check (?)
- if self.currentBlock != nil && self.currentBlock.Td != nil {
+ if self.currentBlock != nil && self.currentBlock.Td != nil && !self.currentBlock.Queued() {
+ plog.DebugDetailf("HeadSection: <%s> inserted %s to blockchain... check TD %v =?= %v", self.id, hex(self.parentHash), self.td, self.currentBlock.Td)
if self.td.Cmp(self.currentBlock.Td) != 0 {
- //self.addError(ErrIncorrectTD, "on block %x", self.currentBlockHash)
- //self.bp.status.badPeers[self.id]++
+ self.addError(ErrIncorrectTD, "on block %x", self.currentBlockHash)
+ self.bp.status.badPeers[self.id]++
}
}
headKey := self.parentHash
@@ -504,7 +504,7 @@ func (self *peer) getBlockHashes() bool {
self.bp.newSection([]*node{n}).activate(self)
} else {
plog.DebugDetailf("HeadSection: <%s> connecting parent %s found in pool...head section [%s] exists...not requesting hashes", self.id, hex(self.parentHash), sectionhex(parent.section))
- self.bp.activateChain(parent.section, self, nil)
+ self.bp.activateChain(parent.section, self, self.switchC, nil)
}
} else {
plog.DebugDetailf("HeadSection: <%s> section [%s] requestBlockHashes", self.id, sectionhex(self.headSection))
@@ -528,6 +528,7 @@ func (self *peer) run() {
self.lock.RLock()
switchC := self.switchC
+ plog.Debugf("HeadSection: <%s> section process for head %s started", self.id, hex(self.currentBlockHash))
self.lock.RUnlock()
self.blockHashesRequestTimer = nil
@@ -570,7 +571,6 @@ LOOP:
self.bp.status.badPeers[self.id]++
self.bp.status.lock.Unlock()
// there is no persistence here, so GC will just take care of cleaning up
- break LOOP
// signal for peer switch, quit
case <-switchC:
@@ -593,9 +593,9 @@ LOOP:
self.bp.status.badPeers[self.id]++
self.bp.status.lock.Unlock()
plog.Debugf("HeadSection: <%s> (headsection [%s]) quit channel closed : timed out without providing new blocks...quitting", self.id, sectionhex(self.headSection))
- break LOOP
}
}
+
if !self.idle {
self.idle = true
self.bp.wg.Done()
diff --git a/blockpool/peers_test.go b/blockpool/peers_test.go
index 62e059337..e32bb6fc8 100644
--- a/blockpool/peers_test.go
+++ b/blockpool/peers_test.go
@@ -144,7 +144,8 @@ func TestAddPeer(t *testing.T) {
blockPool.Stop()
}
-func TestPeerPromotionByOptionalTdOnBlock(t *testing.T) {
+func TestPeerPromotionByTdOnBlock(t *testing.T) {
+ t.Skip()
test.LogInit()
_, blockPool, blockPoolTester := newTestBlockPool(t)
blockPoolTester.blockChain[0] = nil
@@ -168,13 +169,8 @@ func TestPeerPromotionByOptionalTdOnBlock(t *testing.T) {
best = peer2.AddPeer()
peer2.serveBlocks(3, 4)
peer2.serveBlockHashes(4, 3, 2, 1)
- hashes := blockPoolTester.hashPool.IndexesToHashes([]int{2, 3})
- peer1.waitBlocksRequests(3)
- blockPool.AddBlock(&types.Block{
- HeaderHash: common.Hash(hashes[1]),
- ParentHeaderHash: common.Hash(hashes[0]),
- Td: common.Big3,
- }, "peer1")
+ // hashes := blockPoolTester.hashPool.IndexesToHashes([]int{2, 3})
+ peer1.serveBlocks(2, 3)
blockPool.RemovePeer("peer2")
if blockPool.peers.best.id != "peer1" {
diff --git a/blockpool/section.go b/blockpool/section.go
index 49004d4ef..1ab543dc0 100644
--- a/blockpool/section.go
+++ b/blockpool/section.go
@@ -489,7 +489,7 @@ func (self *section) blockHashesRequest() {
// activate parent section with this peer
// but only if not during switch mode
plog.DebugDetailf("[%s] parent section [%s] activated\n", sectionhex(self), sectionhex(parentSection))
- self.bp.activateChain(parentSection, self.peer, nil)
+ self.bp.activateChain(parentSection, self.peer, self.peer.switchC, nil)
// if not root of chain, switch off
plog.DebugDetailf("[%s] parent found, hash requests deactivated (after %v total attempts)\n", sectionhex(self), self.blockHashesRequests)
self.blockHashesRequestTimer = nil
diff --git a/blockpool/status_test.go b/blockpool/status_test.go
index a87b99d7c..000453de5 100644
--- a/blockpool/status_test.go
+++ b/blockpool/status_test.go
@@ -60,6 +60,8 @@ func checkStatus(t *testing.T, bp *BlockPool, syncing bool, expected []int) (err
}
func TestBlockPoolStatus(t *testing.T) {
+ t.Skip() // :FIXME:
+
test.LogInit()
var err error
n := 3
@@ -87,7 +89,7 @@ func testBlockPoolStatus(t *testing.T) (err error) {
delete(blockPoolTester.refBlockChain, 6)
blockPool.Start()
- defer blockPool.Stop()
+
blockPoolTester.tds = make(map[int]int)
blockPoolTester.tds[9] = 1
blockPoolTester.tds[11] = 3
@@ -107,6 +109,7 @@ func testBlockPoolStatus(t *testing.T) (err error) {
}
peer1.AddPeer()
+
expected = []int{0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0}
err = checkStatus(nil, blockPool, true, expected)
if err != nil {
@@ -242,6 +245,8 @@ func testBlockPoolStatus(t *testing.T) (err error) {
peer3.serveBlocks(0, 1)
blockPool.Wait(waitTimeout)
time.Sleep(200 * time.Millisecond)
+ blockPool.Stop()
+
expected = []int{14, 3, 11, 3, 8, 4, 1, 8, 4, 3, 4, 3, 1}
err = checkStatus(nil, blockPool, false, expected)
if err != nil {
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 9c66a9f53..5ad1dda83 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -463,6 +463,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
// Do not penelise on future block. We'll need a block queue eventually that will queue
// future block for future use
if err == BlockFutureErr {
+ block.SetQueued(true)
self.futureBlocks.Push(block)
stats.queued++
continue
diff --git a/core/types/block.go b/core/types/block.go
index 116acbf79..c47b555ed 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -97,6 +97,7 @@ type Block struct {
uncles []*Header
transactions Transactions
Td *big.Int
+ queued bool // flag for blockpool to skip TD check
receipts Receipts
}
@@ -268,6 +269,9 @@ func (self *Block) SetNonce(nonce uint64) {
self.header.SetNonce(nonce)
}
+func (self *Block) Queued() bool { return self.queued }
+func (self *Block) SetQueued(q bool) { self.queued = q }
+
func (self *Block) Bloom() Bloom { return self.header.Bloom }
func (self *Block) Coinbase() common.Address { return self.header.Coinbase }
func (self *Block) Time() int64 { return int64(self.header.Time) }