@@ -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