@@ -83,11 +83,15 @@ def get_canonical_head(self) -> BlockHeaderAPI:
83
83
84
84
@classmethod
85
85
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 :
86
91
try :
87
- canonical_head_hash = db [SchemaV1 .make_canonical_head_hash_lookup_key ()]
92
+ return db [SchemaV1 .make_canonical_head_hash_lookup_key ()]
88
93
except KeyError :
89
94
raise CanonicalHeadNotFound ("No canonical head set for this chain" )
90
- return cls ._get_block_header_by_hash (db , Hash32 (canonical_head_hash ))
91
95
92
96
#
93
97
# Header API
@@ -173,7 +177,7 @@ def _persist_checkpoint_header(
173
177
)
174
178
previous_score = score - header .difficulty
175
179
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 )
177
181
178
182
@classmethod
179
183
def _persist_header_chain (
@@ -226,21 +230,21 @@ def _persist_header_chain(
226
230
score = cls ._set_hash_scores_to_db (db , curr_chain_head , score )
227
231
228
232
try :
229
- previous_canonical_head = cls ._get_canonical_head (db ). hash
233
+ previous_canonical_head = cls ._get_canonical_head_hash (db )
230
234
head_score = cls ._get_score (db , previous_canonical_head )
231
235
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 )
233
237
234
238
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 )
236
240
237
241
return tuple (), tuple ()
238
242
239
243
@classmethod
240
244
def _set_as_canonical_chain_head (
241
245
cls ,
242
246
db : DatabaseAPI ,
243
- block_hash : Hash32 ,
247
+ header : BlockHeaderAPI ,
244
248
genesis_parent_hash : Hash32 ,
245
249
) -> Tuple [Tuple [BlockHeaderAPI , ...], Tuple [BlockHeaderAPI , ...]]:
246
250
"""
@@ -250,12 +254,15 @@ def _set_as_canonical_chain_head(
250
254
:return: a tuple of the headers that are newly in the canonical chain, and the headers that
251
255
are no longer in the canonical chain
252
256
"""
257
+ # performance optimization, short circuit if we're just adding a single header
253
258
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 ()
259
266
260
267
new_canonical_headers = tuple (reversed (
261
268
cls ._find_new_ancestors (db , header , genesis_parent_hash )))
0 commit comments