]> Untitled Git - bdk/commitdiff
chore(esplora): Clarify consistency guarantees
authorLLFourn <lloyd.fourn@gmail.com>
Tue, 30 Jan 2024 02:57:06 +0000 (13:57 +1100)
committerLLFourn <lloyd.fourn@gmail.com>
Tue, 30 Jan 2024 02:57:06 +0000 (13:57 +1100)
crates/esplora/src/async_ext.rs
crates/esplora/src/blocking_ext.rs

index 4a6196be7a55e45d968a80c61a9872358e1c6ad2..53edd25c617394a24fd56f69c0b10209d4db5b28 100644 (file)
@@ -26,6 +26,12 @@ pub trait EsploraAsyncExt {
     ///
     /// The result of this method can be applied to [`LocalChain::apply_update`].
     ///
+    /// ## Consistency
+    ///
+    /// The chain update returned is guaranteed to be consistent as long as there is not a *large* re-org
+    /// during the call. The size of re-org we can tollerate is server dependent but will be at
+    /// least 10.
+    ///
     /// [`LocalChain`]: bdk_chain::local_chain::LocalChain
     /// [`LocalChain::tip`]: bdk_chain::local_chain::LocalChain::tip
     /// [`LocalChain::apply_update`]: bdk_chain::local_chain::LocalChain::apply_update
@@ -85,9 +91,8 @@ impl EsploraAsyncExt for esplora_client::AsyncClient {
         local_tip: CheckPoint,
         request_heights: impl IntoIterator<IntoIter = impl Iterator<Item = u32> + Send> + Send,
     ) -> Result<local_chain::Update, Error> {
-        // Atomically fetch latest blocks from Esplora. This way, we avoid creating an update with
-        // an inconsistent set of blocks (assuming that a reorg depth cannot be greater than the
-        // latest blocks fetched).
+        // Fetch latest N (server dependent) blocks from Esplora. The server guarantees these are
+        // consistent.
         let mut fetched_blocks = self
             .get_blocks(None)
             .await?
@@ -109,6 +114,10 @@ impl EsploraAsyncExt for esplora_client::AsyncClient {
             }
             // only fetch what is missing
             if let btree_map::Entry::Vacant(entry) = fetched_blocks.entry(height) {
+                // ❗The return value of `get_block_hash` is not strictly guaranteed to be consistent
+                // with the chain at the time of `get_blocks` above (there could have been a deep
+                // re-org). Since `get_blocks` returns 10 (or so) blocks we are assuming that it's
+                // not possible to have a re-org deeper than that.
                 entry.insert(self.get_block_hash(height).await?);
             }
         }
index 0764be050cbfe95c5e0fdd325cafcffc29eeee50..81599fd5bbc7441da9194a0e395335d399e4e927 100644 (file)
@@ -24,6 +24,12 @@ pub trait EsploraExt {
     ///
     /// The result of this method can be applied to [`LocalChain::apply_update`].
     ///
+    /// ## Consistency
+    ///
+    /// The chain update returned is guaranteed to be consistent as long as there is not a *large* re-org
+    /// during the call. The size of re-org we can tollerate is server dependent but will be at
+    /// least 10.
+    ///
     /// [`LocalChain`]: bdk_chain::local_chain::LocalChain
     /// [`LocalChain::tip`]: bdk_chain::local_chain::LocalChain::tip
     /// [`LocalChain::apply_update`]: bdk_chain::local_chain::LocalChain::apply_update
@@ -78,9 +84,8 @@ impl EsploraExt for esplora_client::BlockingClient {
         local_tip: CheckPoint,
         request_heights: impl IntoIterator<Item = u32>,
     ) -> Result<local_chain::Update, Error> {
-        // Atomically fetch latest blocks from Esplora. This way, we avoid creating an update with
-        // an inconsistent set of blocks (assuming that a reorg depth cannot be greater than the
-        // latest blocks fetched).
+        // Fetch latest N (server dependent) blocks from Esplora. The server guarantees these are
+        // consistent.
         let mut fetched_blocks = self
             .get_blocks(None)?
             .into_iter()
@@ -101,6 +106,10 @@ impl EsploraExt for esplora_client::BlockingClient {
             }
             // only fetch what is missing
             if let btree_map::Entry::Vacant(entry) = fetched_blocks.entry(height) {
+                // ❗The return value of `get_block_hash` is not strictly guaranteed to be consistent
+                // with the chain at the time of `get_blocks` above (there could have been a deep
+                // re-org). Since `get_blocks` returns 10 (or so) blocks we are assuming that it's
+                // not possible to have a re-org deeper than that.
                 entry.insert(self.get_block_hash(height)?);
             }
         }