Skip to content

Commit aabfe04

Browse files
committed
Improve performance when importing a single header based on the chain head
1 parent 10df2a6 commit aabfe04

File tree

2 files changed

+28
-18
lines changed

2 files changed

+28
-18
lines changed

eth/db/chain.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,15 +93,18 @@ def get_block_uncles(self, uncles_hash: Hash32) -> Tuple[BlockHeaderAPI, ...]:
9393
def _set_as_canonical_chain_head(
9494
cls,
9595
db: DatabaseAPI,
96-
block_hash: Hash32,
96+
header: BlockHeaderAPI,
9797
genesis_parent_hash: Hash32,
9898
) -> Tuple[Tuple[BlockHeaderAPI, ...], Tuple[BlockHeaderAPI, ...]]:
99+
# performance optimization, short circuit if we're just adding a single header
99100
try:
100-
header = cls._get_block_header_by_hash(db, block_hash)
101-
except HeaderNotFound:
102-
raise ValueError(
103-
f"Cannot use unknown block hash as canonical head: {header.hash}"
104-
)
101+
current_canonical_head = cls._get_canonical_head_hash(db)
102+
except CanonicalHeadNotFound:
103+
current_canonical_head = None
104+
if current_canonical_head and header.parent_hash == current_canonical_head:
105+
cls._add_block_number_to_hash_lookup(db, header)
106+
db.set(SchemaV1.make_canonical_head_hash_lookup_key(), header.hash)
107+
return (header,), tuple()
105108

106109
new_canonical_headers = tuple(reversed(
107110
cls._find_new_ancestors(db, header, genesis_parent_hash)))

eth/db/header.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,15 @@ def get_canonical_head(self) -> BlockHeaderAPI:
8383

8484
@classmethod
8585
def _get_canonical_head(cls, db: DatabaseAPI) -> BlockHeaderAPI:
86+
canonical_head_hash = cls._get_canonical_head_hash(db)
87+
return cls._get_block_header_by_hash(db, Hash32(canonical_head_hash))
88+
89+
@classmethod
90+
def _get_canonical_head_hash(cls, db: DatabaseAPI) -> Hash32:
8691
try:
87-
canonical_head_hash = db[SchemaV1.make_canonical_head_hash_lookup_key()]
92+
return db[SchemaV1.make_canonical_head_hash_lookup_key()]
8893
except KeyError:
8994
raise CanonicalHeadNotFound("No canonical head set for this chain")
90-
return cls._get_block_header_by_hash(db, Hash32(canonical_head_hash))
9195

9296
#
9397
# Header API
@@ -173,7 +177,7 @@ def _persist_checkpoint_header(
173177
)
174178
previous_score = score - header.difficulty
175179
cls._set_hash_scores_to_db(db, header, previous_score)
176-
cls._set_as_canonical_chain_head(db, header.hash, header.parent_hash)
180+
cls._set_as_canonical_chain_head(db, header, header.parent_hash)
177181

178182
@classmethod
179183
def _persist_header_chain(
@@ -226,21 +230,21 @@ def _persist_header_chain(
226230
score = cls._set_hash_scores_to_db(db, curr_chain_head, score)
227231

228232
try:
229-
previous_canonical_head = cls._get_canonical_head(db).hash
233+
previous_canonical_head = cls._get_canonical_head_hash(db)
230234
head_score = cls._get_score(db, previous_canonical_head)
231235
except CanonicalHeadNotFound:
232-
return cls._set_as_canonical_chain_head(db, curr_chain_head.hash, genesis_parent_hash)
236+
return cls._set_as_canonical_chain_head(db, curr_chain_head, genesis_parent_hash)
233237

234238
if score > head_score:
235-
return cls._set_as_canonical_chain_head(db, curr_chain_head.hash, genesis_parent_hash)
239+
return cls._set_as_canonical_chain_head(db, curr_chain_head, genesis_parent_hash)
236240

237241
return tuple(), tuple()
238242

239243
@classmethod
240244
def _set_as_canonical_chain_head(
241245
cls,
242246
db: DatabaseAPI,
243-
block_hash: Hash32,
247+
header: BlockHeaderAPI,
244248
genesis_parent_hash: Hash32,
245249
) -> Tuple[Tuple[BlockHeaderAPI, ...], Tuple[BlockHeaderAPI, ...]]:
246250
"""
@@ -250,12 +254,15 @@ def _set_as_canonical_chain_head(
250254
:return: a tuple of the headers that are newly in the canonical chain, and the headers that
251255
are no longer in the canonical chain
252256
"""
257+
# performance optimization, short circuit if we're just adding a single header
253258
try:
254-
header = cls._get_block_header_by_hash(db, block_hash)
255-
except HeaderNotFound:
256-
raise ValueError(
257-
f"Cannot use unknown block hash as canonical head: {block_hash}"
258-
)
259+
current_canonical_head = cls._get_canonical_head_hash(db)
260+
except CanonicalHeadNotFound:
261+
current_canonical_head = None
262+
if current_canonical_head and header.parent_hash == current_canonical_head:
263+
cls._add_block_number_to_hash_lookup(db, header)
264+
db.set(SchemaV1.make_canonical_head_hash_lookup_key(), header.hash)
265+
return (header,), tuple()
259266

260267
new_canonical_headers = tuple(reversed(
261268
cls._find_new_ancestors(db, header, genesis_parent_hash)))

0 commit comments

Comments
 (0)