mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 09:23:48 +00:00
core: optimize HasBlock check
This avoids a random database read to get the number.
This commit is contained in:
parent
9956e2a2ca
commit
d4486f0cb0
6 changed files with 19 additions and 11 deletions
|
|
@ -164,7 +164,7 @@ func ImportChain(chain *core.BlockChain, fn string) error {
|
||||||
|
|
||||||
func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool {
|
func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool {
|
||||||
for _, b := range bs {
|
for _, b := range bs {
|
||||||
if !chain.HasBlock(b.Hash()) {
|
if !chain.HasBlock(b.Hash(), b.NumberU64()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -516,8 +516,12 @@ func (bc *BlockChain) GetBodyRLP(hash common.Hash) rlp.RawValue {
|
||||||
|
|
||||||
// HasBlock checks if a block is fully present in the database or not, caching
|
// HasBlock checks if a block is fully present in the database or not, caching
|
||||||
// it if present.
|
// it if present.
|
||||||
func (bc *BlockChain) HasBlock(hash common.Hash) bool {
|
func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool {
|
||||||
return bc.GetBlockByHash(hash) != nil
|
if bc.blockCache.Contains(hash) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
ok, _ := bc.chainDb.Has(blockBodyKey(hash, number))
|
||||||
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasBlockAndState checks if a block and associated state trie is fully present
|
// HasBlockAndState checks if a block and associated state trie is fully present
|
||||||
|
|
@ -723,7 +727,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
return i, fmt.Errorf("containing header #%d [%x…] unknown", block.Number(), block.Hash().Bytes()[:4])
|
return i, fmt.Errorf("containing header #%d [%x…] unknown", block.Number(), block.Hash().Bytes()[:4])
|
||||||
}
|
}
|
||||||
// Skip if the entire data is already known
|
// Skip if the entire data is already known
|
||||||
if bc.HasBlock(block.Hash()) {
|
if bc.HasBlock(block.Hash(), block.NumberU64()) {
|
||||||
stats.ignored++
|
stats.ignored++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -793,7 +797,7 @@ func (bc *BlockChain) WriteBlock(block *types.Block) (status WriteStatus, err er
|
||||||
bc.mu.Lock()
|
bc.mu.Lock()
|
||||||
defer bc.mu.Unlock()
|
defer bc.mu.Unlock()
|
||||||
|
|
||||||
if bc.HasBlock(block.Hash()) {
|
if bc.HasBlock(block.Hash(), block.NumberU64()) {
|
||||||
log.Trace("Block existed", "hash", block.Hash())
|
log.Trace("Block existed", "hash", block.Hash())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ func GetHeader(db DatabaseReader, hash common.Hash, number uint64) *types.Header
|
||||||
|
|
||||||
// GetBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
|
// GetBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
|
||||||
func GetBodyRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue {
|
func GetBodyRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue {
|
||||||
data, _ := db.Get(append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...))
|
data, _ := db.Get(blockBodyKey(hash, number))
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,6 +178,10 @@ func headerKey(hash common.Hash, number uint64) []byte {
|
||||||
return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
|
return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func blockBodyKey(hash common.Hash, number uint64) []byte {
|
||||||
|
return append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
|
||||||
|
}
|
||||||
|
|
||||||
// GetBody retrieves the block body (transactons, uncles) corresponding to the
|
// GetBody retrieves the block body (transactons, uncles) corresponding to the
|
||||||
// hash, nil if none found.
|
// hash, nil if none found.
|
||||||
func GetBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body {
|
func GetBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body {
|
||||||
|
|
|
||||||
|
|
@ -241,7 +241,7 @@ func (api *PrivateAdminAPI) ExportChain(file string) (bool, error) {
|
||||||
|
|
||||||
func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool {
|
func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool {
|
||||||
for _, b := range bs {
|
for _, b := range bs {
|
||||||
if !chain.HasBlock(b.Hash()) {
|
if !chain.HasBlock(b.Hash(), b.NumberU64()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -609,7 +609,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
|
||||||
// Schedule all the unknown hashes for retrieval
|
// Schedule all the unknown hashes for retrieval
|
||||||
unknown := make(newBlockHashesData, 0, len(announces))
|
unknown := make(newBlockHashesData, 0, len(announces))
|
||||||
for _, block := range announces {
|
for _, block := range announces {
|
||||||
if !pm.blockchain.HasBlock(block.Hash) {
|
if !pm.blockchain.HasBlock(block.Hash, block.Number) {
|
||||||
unknown = append(unknown, block)
|
unknown = append(unknown, block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -699,7 +699,7 @@ func (pm *ProtocolManager) BroadcastBlock(block *types.Block, propagate bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Otherwise if the block is indeed in out own chain, announce it
|
// Otherwise if the block is indeed in out own chain, announce it
|
||||||
if pm.blockchain.HasBlock(hash) {
|
if pm.blockchain.HasBlock(hash, block.NumberU64()) {
|
||||||
for _, peer := range peers {
|
for _, peer := range peers {
|
||||||
peer.SendNewBlockHashes([]common.Hash{hash}, []uint64{block.NumberU64()})
|
peer.SendNewBlockHashes([]common.Hash{hash}, []uint64{block.NumberU64()})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -252,8 +252,8 @@ func (self *LightChain) GetBodyRLP(ctx context.Context, hash common.Hash) (rlp.R
|
||||||
|
|
||||||
// HasBlock checks if a block is fully present in the database or not, caching
|
// HasBlock checks if a block is fully present in the database or not, caching
|
||||||
// it if present.
|
// it if present.
|
||||||
func (bc *LightChain) HasBlock(hash common.Hash) bool {
|
func (bc *LightChain) HasBlock(hash common.Hash, number uint64) bool {
|
||||||
blk, _ := bc.GetBlockByHash(NoOdr, hash)
|
blk, _ := bc.GetBlock(NoOdr, hash, number)
|
||||||
return blk != nil
|
return blk != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue