]> Untitled Git - bdk/commitdiff
fix(core): `push` now errors on `prev_blockhash` mismatch
author志宇 <hello@evanlinjin.me>
Tue, 13 Jan 2026 06:02:00 +0000 (14:02 +0800)
committer志宇 <hello@evanlinjin.me>
Wed, 22 Apr 2026 04:48:17 +0000 (04:48 +0000)
crates/core/src/checkpoint.rs

index bff833621777dd5fb5c2554efe73e8005dbee1ea..168922177401999833828c451364438a5e53e87c 100644 (file)
@@ -349,21 +349,30 @@ where
 
     /// Puts another checkpoint onto the linked list representing the blockchain.
     ///
-    /// Returns an `Err(self)` if the block you are pushing on is not at a greater height that the
-    /// one you are pushing on to.
+    /// Returns an `Err(self)` if:
+    /// * The block you are pushing on is not at a greater height that the one you are pushing on to.
+    /// * The `prev_blockhash` does not match.
     pub fn push(self, height: u32, data: D) -> Result<Self, Self> {
-        if self.height() < height {
-            Ok(Self(Arc::new(CPInner {
-                block_id: BlockId {
-                    height,
-                    hash: data.to_blockhash(),
-                },
-                data,
-                prev: Some(self.0),
-            })))
-        } else {
-            Err(self)
+        // Reject if trying to push at or below current height - chain must grow forward.
+        if height <= self.height() {
+            return Err(self);
         }
+
+        // For contiguous height, ensure prev_blockhash does not conflict.
+        if let Some(prev_blockhash) = data.prev_blockhash() {
+            if self.height() + 1 == height && self.hash() != prev_blockhash {
+                return Err(self);
+            }
+        }
+
+        Ok(Self(Arc::new(CPInner {
+            block_id: BlockId {
+                height,
+                hash: data.to_blockhash(),
+            },
+            data,
+            prev: Some(self.0),
+        })))
     }
 }