mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
eth: queue for parent block while fetching a block with unknown parent
This commit is contained in:
parent
4687391213
commit
0d71b2fc98
2 changed files with 49 additions and 9 deletions
|
|
@ -67,6 +67,12 @@ type chainInsertFn func(types.Blocks) (int, error)
|
||||||
// peerDropFn is a callback type for dropping a peer detected as malicious.
|
// peerDropFn is a callback type for dropping a peer detected as malicious.
|
||||||
type peerDropFn func(id string)
|
type peerDropFn func(id string)
|
||||||
|
|
||||||
|
// peerHeaderRequesterFn is a callback type for sending a header retrieval request.
|
||||||
|
type peerHeaderRequesterFn func(string) func(common.Hash) error
|
||||||
|
|
||||||
|
// peerBodyRequesterFn is a callback type for sending a body retrieval request.
|
||||||
|
type peerBodyRequesterFn func(string) func([]common.Hash) error
|
||||||
|
|
||||||
// announce is the hash notification of the availability of a new block in the
|
// announce is the hash notification of the availability of a new block in the
|
||||||
// network.
|
// network.
|
||||||
type announce struct {
|
type announce struct {
|
||||||
|
|
@ -135,6 +141,8 @@ type Fetcher struct {
|
||||||
chainHeight chainHeightFn // Retrieves the current chain's height
|
chainHeight chainHeightFn // Retrieves the current chain's height
|
||||||
insertChain chainInsertFn // Injects a batch of blocks into the chain
|
insertChain chainInsertFn // Injects a batch of blocks into the chain
|
||||||
dropPeer peerDropFn // Drops a peer for misbehaving
|
dropPeer peerDropFn // Drops a peer for misbehaving
|
||||||
|
headerRequest peerHeaderRequesterFn
|
||||||
|
bodyRequest peerBodyRequesterFn
|
||||||
|
|
||||||
// Testing hooks
|
// Testing hooks
|
||||||
announceChangeHook func(common.Hash, bool) // Method to call upon adding or deleting a hash from the announce list
|
announceChangeHook func(common.Hash, bool) // Method to call upon adding or deleting a hash from the announce list
|
||||||
|
|
@ -145,7 +153,7 @@ type Fetcher struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a block fetcher to retrieve blocks based on hash announcements.
|
// New creates a block fetcher to retrieve blocks based on hash announcements.
|
||||||
func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, insertChain chainInsertFn, dropPeer peerDropFn) *Fetcher {
|
func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, insertChain chainInsertFn, dropPeer peerDropFn, headerRequest peerHeaderRequesterFn, bodyRequest peerBodyRequesterFn) *Fetcher {
|
||||||
return &Fetcher{
|
return &Fetcher{
|
||||||
notify: make(chan *announce),
|
notify: make(chan *announce),
|
||||||
inject: make(chan *inject),
|
inject: make(chan *inject),
|
||||||
|
|
@ -167,6 +175,8 @@ func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBloc
|
||||||
chainHeight: chainHeight,
|
chainHeight: chainHeight,
|
||||||
insertChain: insertChain,
|
insertChain: insertChain,
|
||||||
dropPeer: dropPeer,
|
dropPeer: dropPeer,
|
||||||
|
headerRequest: headerRequest,
|
||||||
|
bodyRequest: bodyRequest,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -296,18 +306,36 @@ func (f *Fetcher) loop() {
|
||||||
}
|
}
|
||||||
// If too high up the chain or phase, continue later
|
// If too high up the chain or phase, continue later
|
||||||
number := op.block.NumberU64()
|
number := op.block.NumberU64()
|
||||||
if number > height+1 {
|
|
||||||
f.queue.Push(op, -int64(number))
|
|
||||||
if f.queueChangeHook != nil {
|
|
||||||
f.queueChangeHook(hash, true)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// Otherwise if fresh and still unknown, try and import
|
// Otherwise if fresh and still unknown, try and import
|
||||||
if number+maxUncleDist < height || f.getBlock(hash) != nil {
|
if number+maxUncleDist < height || f.getBlock(hash) != nil {
|
||||||
f.forgetBlock(hash)
|
f.forgetBlock(hash)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
parentHash := op.block.ParentHash()
|
||||||
|
if f.getBlock(parentHash) == nil {
|
||||||
|
f.queue.Push(op, -int64(number))
|
||||||
|
if f.queueChangeHook != nil {
|
||||||
|
f.queueChangeHook(hash, true)
|
||||||
|
}
|
||||||
|
if len(f.announced[parentHash]) > 0 {
|
||||||
|
// only request for parent hash once
|
||||||
|
break
|
||||||
|
}
|
||||||
|
headerRequestFn := f.headerRequest(op.origin)
|
||||||
|
bodyRequestFn := f.bodyRequest(op.origin)
|
||||||
|
if headerRequestFn == nil || bodyRequestFn == nil {
|
||||||
|
log.Info("Peer lost while fetching for parent", "peer", op.origin)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
log.Info("Notify of parent hash", "hash", parentHash, "number", op.block.NumberU64()-1, "peer", op.origin)
|
||||||
|
err := f.Notify(op.origin, parentHash, op.block.NumberU64()-1, time.Now(), headerRequestFn, bodyRequestFn)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to notify of parent block", "error", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
break
|
||||||
|
}
|
||||||
f.insert(op.origin, op.block)
|
f.insert(op.origin, op.block)
|
||||||
}
|
}
|
||||||
// Wait for an outside event to occur
|
// Wait for an outside event to occur
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,19 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne
|
||||||
atomic.StoreUint32(&manager.acceptTxs, 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)
|
headerRequest := func(id string) func(common.Hash) error {
|
||||||
|
if peer := manager.peers.Peer(id); peer != nil {
|
||||||
|
return peer.RequestOneHeader
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
bodyRequest := func(id string) func([]common.Hash) error {
|
||||||
|
if peer := manager.peers.Peer(id); peer != nil {
|
||||||
|
return peer.RequestBodies
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
manager.fetcher = fetcher.New(blockchain.GetBlockByHash, validator, manager.BroadcastBlock, heighter, inserter, manager.removePeer, headerRequest, bodyRequest)
|
||||||
|
|
||||||
return manager, nil
|
return manager, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue