diff options
author | Felföldi Zsolt <zsfelfoldi@gmail.com> | 2018-06-12 21:52:54 +0800 |
---|---|---|
committer | Péter Szilágyi <peterke@gmail.com> | 2018-06-12 21:52:54 +0800 |
commit | 049f5b357200406c01f7bf2d2e2936d1d28a319b (patch) | |
tree | ef73043730c3d77359b9163ab6cbb2f053e5cf86 /core | |
parent | 0255951587ef0eada5d162f3404bc481f70a2ce2 (diff) | |
download | go-tangerine-049f5b357200406c01f7bf2d2e2936d1d28a319b.tar.gz go-tangerine-049f5b357200406c01f7bf2d2e2936d1d28a319b.tar.zst go-tangerine-049f5b357200406c01f7bf2d2e2936d1d28a319b.zip |
core, eth, les: more efficient hash-based header chain retrieval (#16946)
Diffstat (limited to 'core')
-rw-r--r-- | core/blockchain.go | 12 | ||||
-rw-r--r-- | core/headerchain.go | 37 |
2 files changed, 49 insertions, 0 deletions
diff --git a/core/blockchain.go b/core/blockchain.go index ea26fa034..34832252a 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1524,6 +1524,18 @@ func (bc *BlockChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []com return bc.hc.GetBlockHashesFromHash(hash, max) } +// GetAncestor retrieves the Nth ancestor of a given block. It assumes that either the given block or +// a close ancestor of it is canonical. maxNonCanonical points to a downwards counter limiting the +// number of blocks to be individually checked before we reach the canonical chain. +// +// Note: ancestor == 0 returns the same block, 1 returns its parent and so on. +func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) { + bc.chainmu.Lock() + defer bc.chainmu.Unlock() + + return bc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical) +} + // 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 { diff --git a/core/headerchain.go b/core/headerchain.go index 2ac0cccc7..6e759ed1c 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -307,6 +307,43 @@ func (hc *HeaderChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []co return chain } +// GetAncestor retrieves the Nth ancestor of a given block. It assumes that either the given block or +// a close ancestor of it is canonical. maxNonCanonical points to a downwards counter limiting the +// number of blocks to be individually checked before we reach the canonical chain. +// +// Note: ancestor == 0 returns the same block, 1 returns its parent and so on. +func (hc *HeaderChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) { + if ancestor > number { + return common.Hash{}, 0 + } + if ancestor == 1 { + // in this case it is cheaper to just read the header + if header := hc.GetHeader(hash, number); header != nil { + return header.ParentHash, number - 1 + } else { + return common.Hash{}, 0 + } + } + for ancestor != 0 { + if rawdb.ReadCanonicalHash(hc.chainDb, number) == hash { + number -= ancestor + return rawdb.ReadCanonicalHash(hc.chainDb, number), number + } + if *maxNonCanonical == 0 { + return common.Hash{}, 0 + } + *maxNonCanonical-- + ancestor-- + header := hc.GetHeader(hash, number) + if header == nil { + return common.Hash{}, 0 + } + hash = header.ParentHash + number-- + } + return hash, number +} + // 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 { |