Entry point for eth protocol to add block hashes received via BlockHashesMsg
only hashes from the best peer are handled
Only hashes from the best peer are handled
initiates further hash requests until a known parent is reached (unless cancelled by a peerSwitch event, i.e., when a better peer becomes best peer)
launches all block request processes on each chain section
Initiates further hash requests until a known parent is reached (unless cancelled by a peerSwitch event, i.e., when a better peer becomes best peer)
Launches all block request processes on each chain section
the first argument is an iterator function. Using this block hashes are decoded from the rlp message payload on demand. As a result, AddBlockHashes needs to run synchronously for one peer since the message is discarded if the caller thread returns.
The first argument is an iterator function. Using this block hashes are decoded from the rlp message payload on demand. As a result, AddBlockHashes needs to run synchronously for one peer since the message is discarded if the caller thread returns.
// otherwise set child section iff found node is the root of a section
// this is a possible scenario when a singleton head section was created
// on an earlier occasion this peer or another with the same block was best peer
// on an earlier occasion when this peer or another with the same block was best peer
ifentry.node==entry.section.bottom{
child=entry.section
plog.DebugDetailf("AddBlockHashes: peer <%s>: connects to child section root %s",peerId,hex(bestpeer.currentBlockHash))
...
...
@@ -375,7 +434,7 @@ LOOP:
default:
}
// if we reach the blockchain we stop reading more
// if we reach the blockchain we stop reading further blockhashes
ifself.hasBlock(hash){
// check if known block connecting the downloaded chain to our blockchain
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s) found block %s in the blockchain",peerId,hex(bestpeer.currentBlockHash),hex(hash))
...
...
@@ -412,10 +471,11 @@ LOOP:
// reached a known chain in the pool
ifentry.node==entry.section.bottom&&n==1{
/*
the first block hash received is an orphan in the pool
this also supports clients that (despite the spec) include <from> hash in their
The first block hash received is an orphan node in the pool
This also supports clients that (despite the spec) include <from> hash in their
response to hashes request. Note that by providing <from> we can link sections
without having to wait for the root block of the child section to arrive, so it allows for superior performance
without having to wait for the root block of the child section to arrive, so it allows for superior performance.
*/
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s) found head block [%s] as root of connecting child section [%s] skipping",peerId,hex(bestpeer.currentBlockHash),hex(hash),sectionhex(entry.section))
// record the entry's chain section as child section
...
...
@@ -447,9 +507,8 @@ LOOP:
plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s): %v nodes in new section",peerId,hex(bestpeer.currentBlockHash),len(nodes))
/*
handle forks where connecting node is mid-section
by splitting section at fork
no splitting needed if connecting node is head of a section
Handle forks where connecting node is mid-section by splitting section at fork.
No splitting needed if connecting node is head of a section.
plog.Debugf("HeadSection: <%s> section with head %s, idle: %v",self.id,hex(self.currentBlockHash),self.idle)
...
...
@@ -538,7 +584,7 @@ LOOP:
// quit
case<-quit:
self.peerError(self.bp.peers.errors.New(ErrIdleTooLong,"timed out without providing new blocks (td: %v, head: %s)...quitting",self.td,self.currentBlockHash))
self.peerError(self.bp.peers.errors.New(ErrIdleTooLong,"timed out without providing new blocks (td: %v, head: %s)...quitting",self.td,hex(self.currentBlockHash)))