///
/// 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
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?
}
// 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?);
}
}
///
/// 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
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()
}
// 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)?);
}
}