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