eth,les: add hash-lookup that is easier on memory

This commit is contained in:
Martin Holst Swende 2018-06-05 11:55:01 +02:00
parent 400332b99d
commit 319c8d044c
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
6 changed files with 41 additions and 2 deletions

View file

@ -1523,6 +1523,12 @@ func (bc *BlockChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []com
return bc.hc.GetBlockHashesFromHash(hash, max)
}
// GetAncestorBlockHashFromHash retrieves the block hash for the ancestor of a given
// hash, fetching towards the genesis block.
func (bc *BlockChain) GetAncestorBlockHashFromHash(hash common.Hash, max uint64) common.Hash {
return bc.hc.GetAncestorBlockHashFromHash(hash, max)
}
// GetHeaderByNumber retrieves a block header from the database by number,
// caching it (associated with its hash) if found.
func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header {

View file

@ -307,6 +307,27 @@ func (hc *HeaderChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []co
return chain
}
// GetAncestorBlockHashFromHash retrieves the block hash for the ancestor of a given
// hash, fetching towards the genesis block.
func (hc *HeaderChain) GetAncestorBlockHashFromHash(hash common.Hash, max uint64) common.Hash {
// Get the origin header from which to fetch
header := hc.GetHeaderByHash(hash)
if header == nil {
return common.Hash{}
}
// Iterate the headers until enough is collected or the genesis reached
next := common.Hash{}
for i := uint64(0); i < max; i++ {
next = header.ParentHash
if header = hc.GetHeader(next, header.Number.Uint64()-1); header == nil {
return common.Hash{}
}
if header.Number.Sign() == 0 {
return common.Hash{}
}
}
return next
}
// GetTd retrieves a block's total difficulty in the canonical chain from the
// database by hash and number, caching it if found.
func (hc *HeaderChain) GetTd(hash common.Hash, number uint64) *big.Int {

View file

@ -387,7 +387,7 @@ 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 {
if pm.blockchain.GetAncestorBlockHashFromHash(header.Hash(), query.Skip+1) == query.Origin.Hash {
query.Origin.Hash = header.Hash()
} else {
unknown = true

View file

@ -84,6 +84,7 @@ type BlockChain interface {
Rollback(chain []common.Hash)
GetHeaderByNumber(number uint64) *types.Header
GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash
GetAncestorBlockHashFromHash(hash common.Hash, max uint64) common.Hash
Genesis() *types.Block
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
}
@ -465,7 +466,7 @@ 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 {
if pm.blockchain.GetAncestorBlockHashFromHash(header.Hash(), query.Skip+1) == query.Origin.Hash {
query.Origin.Hash = header.Hash()
} else {
unknown = true

View file

@ -75,6 +75,11 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 1},
[]common.Hash{bc.GetBlockByNumber(limit / 2).Hash()},
},
// Overflow attack
{
&getBlockHeadersData{Origin: hashOrNumber{Hash:bc.GetBlockByNumber(1).Hash()}, Amount: 1,Skip:0xFFFFFFFFFFFFFFFF},
[]common.Hash{},
},
// Multiple headers should be retrievable in both directions
{
&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3},

View file

@ -433,6 +433,12 @@ func (self *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []c
return self.hc.GetBlockHashesFromHash(hash, max)
}
// GetAncestorBlockHashFromHash retrieves the block hash for the ancestor of a given
// hash, fetching towards the genesis block.
func (self *LightChain) GetAncestorBlockHashFromHash(hash common.Hash, max uint64) common.Hash{
return self.hc.GetAncestorBlockHashFromHash(hash, max)
}
// GetHeaderByNumber retrieves a block header from the database by number,
// caching it (associated with its hash) if found.
func (self *LightChain) GetHeaderByNumber(number uint64) *types.Header {