|
|
|
@ -83,7 +83,7 @@ type BlockChain interface { |
|
|
|
|
InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) |
|
|
|
|
Rollback(chain []common.Hash) |
|
|
|
|
GetHeaderByNumber(number uint64) *types.Header |
|
|
|
|
GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash |
|
|
|
|
GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) |
|
|
|
|
Genesis() *types.Block |
|
|
|
|
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription |
|
|
|
|
} |
|
|
|
@ -419,6 +419,8 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
hashMode := query.Origin.Hash != (common.Hash{}) |
|
|
|
|
first := true |
|
|
|
|
maxNonCanonical := uint64(100) |
|
|
|
|
|
|
|
|
|
// Gather headers until the fetch or network limits is reached
|
|
|
|
|
var ( |
|
|
|
@ -430,14 +432,21 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { |
|
|
|
|
// Retrieve the next header satisfying the query
|
|
|
|
|
var origin *types.Header |
|
|
|
|
if hashMode { |
|
|
|
|
origin = pm.blockchain.GetHeaderByHash(query.Origin.Hash) |
|
|
|
|
if first { |
|
|
|
|
first = false |
|
|
|
|
origin = pm.blockchain.GetHeaderByHash(query.Origin.Hash) |
|
|
|
|
if origin != nil { |
|
|
|
|
query.Origin.Number = origin.Number.Uint64() |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
origin = pm.blockchain.GetHeader(query.Origin.Hash, query.Origin.Number) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
origin = pm.blockchain.GetHeaderByNumber(query.Origin.Number) |
|
|
|
|
} |
|
|
|
|
if origin == nil { |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
number := origin.Number.Uint64() |
|
|
|
|
headers = append(headers, origin) |
|
|
|
|
bytes += estHeaderRlpSize |
|
|
|
|
|
|
|
|
@ -445,14 +454,12 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { |
|
|
|
|
switch { |
|
|
|
|
case hashMode && query.Reverse: |
|
|
|
|
// Hash based traversal towards the genesis block
|
|
|
|
|
for i := 0; i < int(query.Skip)+1; i++ { |
|
|
|
|
if header := pm.blockchain.GetHeader(query.Origin.Hash, number); header != nil { |
|
|
|
|
query.Origin.Hash = header.ParentHash |
|
|
|
|
number-- |
|
|
|
|
} else { |
|
|
|
|
unknown = true |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
ancestor := query.Skip + 1 |
|
|
|
|
if ancestor == 0 { |
|
|
|
|
unknown = true |
|
|
|
|
} else { |
|
|
|
|
query.Origin.Hash, query.Origin.Number = pm.blockchain.GetAncestor(query.Origin.Hash, query.Origin.Number, ancestor, &maxNonCanonical) |
|
|
|
|
unknown = (query.Origin.Hash == common.Hash{}) |
|
|
|
|
} |
|
|
|
|
case hashMode && !query.Reverse: |
|
|
|
|
// Hash based traversal towards the leaf block
|
|
|
|
@ -466,8 +473,10 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { |
|
|
|
|
unknown = true |
|
|
|
|
} else { |
|
|
|
|
if header := pm.blockchain.GetHeaderByNumber(next); header != nil { |
|
|
|
|
if pm.blockchain.GetBlockHashesFromHash(header.Hash(), query.Skip+1)[query.Skip] == query.Origin.Hash { |
|
|
|
|
query.Origin.Hash = header.Hash() |
|
|
|
|
nextHash := header.Hash() |
|
|
|
|
expOldHash, _ := pm.blockchain.GetAncestor(nextHash, next, query.Skip+1, &maxNonCanonical) |
|
|
|
|
if expOldHash == query.Origin.Hash { |
|
|
|
|
query.Origin.Hash, query.Origin.Number = nextHash, next |
|
|
|
|
} else { |
|
|
|
|
unknown = true |
|
|
|
|
} |
|
|
|
|