]> Untitled Git - bdk/commitdiff
docs(core): require `CheckPoint` data to be determined by its block hash
author志宇 <hello@evanlinjin.me>
Thu, 15 Oct 2026 10:11:16 +0000 (10:11 +0000)
committer志宇 <hello@evanlinjin.me>
Thu, 15 Oct 2026 10:11:16 +0000 (10:11 +0000)
The `ToBlockHash` docs allowed data types with extra fields that the
block hash does not commit to. `CheckPoint` and `LocalChain` treat data
with equal hashes as interchangeable, so such fields could be silently
kept or dropped. State that the data must be fully determined by its
block hash and that anything else belongs outside the checkpoint.

Make the `BlockWithTime` test helper commit to its time field so it
follows the rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
crates/core/src/checkpoint.rs
crates/core/tests/test_checkpoint.rs

index a343e0dc915da9d39223629f42e2354a7ca18fe3..02c1f5cd992b6d3d92f297b3ba5294ff7e56991b 100644 (file)
@@ -149,11 +149,14 @@ impl<D> Drop for CPInner<D> {
 
 /// Trait that converts [`CheckPoint`] `data` to [`BlockHash`].
 ///
-/// Implementations of [`ToBlockHash`] must always return the block's consensus-defined hash. If
-/// your type contains extra fields (timestamps, metadata, etc.), these must be ignored. For
-/// example, [`BlockHash`] trivially returns itself, [`Header`] calls its `block_hash()`, and a
-/// wrapper type around a [`Header`] should delegate to the header's hash rather than derive one
-/// from other fields.
+/// Implementations of [`ToBlockHash`] must always return the block's consensus-defined hash. For
+/// example, [`BlockHash`] trivially returns itself and [`Header`] calls its `block_hash()`.
+///
+/// The data must be fully determined by its block hash: it may only contain a subset of what the
+/// block hash commits to, so two values with the same [`BlockHash`] are always identical.
+/// [`CheckPoint`] treats such values as interchangeable and may keep either one. Data that the
+/// block hash does not commit to (local metadata, the time a block was seen, etc.) must be stored
+/// outside of the checkpoint.
 pub trait ToBlockHash {
     /// Returns the [`BlockHash`] for the associated [`CheckPoint`] `data` type.
     fn to_blockhash(&self) -> BlockHash;
index fb5048e09d68299e96eb1e713299c6a500be7a6f..5798ebec0ba5e03a605d5cf1e575f2affe22b35b 100644 (file)
@@ -64,8 +64,10 @@ struct BlockWithTime(u32, u32);
 
 impl ToBlockHash for BlockWithTime {
     fn to_blockhash(&self) -> BlockHash {
-        // Generate a deterministic hash from the height
-        let hash_bytes = bitcoin::hashes::sha256d::Hash::hash(&self.0.to_le_bytes());
+        // Commit to every field so the data is fully determined by its hash.
+        let mut bytes = self.0.to_le_bytes().to_vec();
+        bytes.extend(self.1.to_le_bytes());
+        let hash_bytes = bitcoin::hashes::sha256d::Hash::hash(&bytes);
         BlockHash::from_raw_hash(hash_bytes)
     }
 }