}
}
-impl From<ChainPosition<ConfirmationTimeHeightAnchor>> for ConfirmationTime {
- fn from(observed_as: ChainPosition<ConfirmationTimeHeightAnchor>) -> Self {
+impl From<ChainPosition<ConfirmationBlockTime>> for ConfirmationTime {
+ fn from(observed_as: ChainPosition<ConfirmationBlockTime>) -> Self {
match observed_as {
ChainPosition::Confirmed(a) => Self::Confirmed {
- height: a.confirmation_height,
+ height: a.block_id.height,
time: a.confirmation_time,
},
ChainPosition::Unconfirmed(last_seen) => Self::Unconfirmed { last_seen },
}
}
-/// An [`Anchor`] implementation that also records the exact confirmation height of the transaction.
-///
-/// Note that the confirmation block and the anchor block can be different here.
+/// An [`Anchor`] implementation that also records the exact confirmation time of the transaction.
///
/// Refer to [`Anchor`] for more details.
#[derive(Debug, Default, Clone, PartialEq, Eq, Copy, PartialOrd, Ord, core::hash::Hash)]
derive(serde::Deserialize, serde::Serialize),
serde(crate = "serde_crate")
)]
-pub struct ConfirmationHeightAnchor {
- /// The exact confirmation height of the transaction.
- ///
- /// It is assumed that this value is never larger than the height of the anchor block.
- pub confirmation_height: u32,
+pub struct ConfirmationBlockTime {
/// The anchor block.
- pub anchor_block: BlockId,
-}
-
-impl Anchor for ConfirmationHeightAnchor {
- fn anchor_block(&self) -> BlockId {
- self.anchor_block
- }
-
- fn confirmation_height_upper_bound(&self) -> u32 {
- self.confirmation_height
- }
-}
-
-impl AnchorFromBlockPosition for ConfirmationHeightAnchor {
- fn from_block_position(_block: &bitcoin::Block, block_id: BlockId, _tx_pos: usize) -> Self {
- Self {
- anchor_block: block_id,
- confirmation_height: block_id.height,
- }
- }
-}
-
-/// An [`Anchor`] implementation that also records the exact confirmation time and height of the
-/// transaction.
-///
-/// Note that the confirmation block and the anchor block can be different here.
-///
-/// Refer to [`Anchor`] for more details.
-#[derive(Debug, Default, Clone, PartialEq, Eq, Copy, PartialOrd, Ord, core::hash::Hash)]
-#[cfg_attr(
- feature = "serde",
- derive(serde::Deserialize, serde::Serialize),
- serde(crate = "serde_crate")
-)]
-pub struct ConfirmationTimeHeightAnchor {
- /// The confirmation height of the transaction being anchored.
- pub confirmation_height: u32,
+ pub block_id: BlockId,
/// The confirmation time of the transaction being anchored.
pub confirmation_time: u64,
- /// The anchor block.
- pub anchor_block: BlockId,
}
-impl Anchor for ConfirmationTimeHeightAnchor {
+impl Anchor for ConfirmationBlockTime {
fn anchor_block(&self) -> BlockId {
- self.anchor_block
+ self.block_id
}
fn confirmation_height_upper_bound(&self) -> u32 {
- self.confirmation_height
+ self.block_id.height
}
}
-impl AnchorFromBlockPosition for ConfirmationTimeHeightAnchor {
+impl AnchorFromBlockPosition for ConfirmationBlockTime {
fn from_block_position(block: &bitcoin::Block, block_id: BlockId, _tx_pos: usize) -> Self {
Self {
- anchor_block: block_id,
- confirmation_height: block_id.height,
+ block_id,
confirmation_time: block.header.time as _,
}
}
#[test]
fn chain_position_ord() {
- let unconf1 = ChainPosition::<ConfirmationHeightAnchor>::Unconfirmed(10);
- let unconf2 = ChainPosition::<ConfirmationHeightAnchor>::Unconfirmed(20);
- let conf1 = ChainPosition::Confirmed(ConfirmationHeightAnchor {
- confirmation_height: 9,
- anchor_block: BlockId {
- height: 20,
+ let unconf1 = ChainPosition::<ConfirmationBlockTime>::Unconfirmed(10);
+ let unconf2 = ChainPosition::<ConfirmationBlockTime>::Unconfirmed(20);
+ let conf1 = ChainPosition::Confirmed(ConfirmationBlockTime {
+ confirmation_time: 20,
+ block_id: BlockId {
+ height: 9,
..Default::default()
},
});
- let conf2 = ChainPosition::Confirmed(ConfirmationHeightAnchor {
- confirmation_height: 12,
- anchor_block: BlockId {
- height: 15,
+ let conf2 = ChainPosition::Confirmed(ConfirmationBlockTime {
+ confirmation_time: 15,
+ block_id: BlockId {
+ height: 12,
..Default::default()
},
});
//! Helper types for spk-based blockchain clients.
use crate::{
- collections::BTreeMap, local_chain::CheckPoint, ConfirmationTimeHeightAnchor, Indexed, TxGraph,
+ collections::BTreeMap, local_chain::CheckPoint, ConfirmationBlockTime, Indexed, TxGraph,
};
use alloc::boxed::Box;
use bitcoin::{OutPoint, Script, ScriptBuf, Txid};
/// Data returned from a spk-based blockchain client sync.
///
/// See also [`SyncRequest`].
-pub struct SyncResult<A = ConfirmationTimeHeightAnchor> {
+pub struct SyncResult<A = ConfirmationBlockTime> {
/// The update to apply to the receiving [`TxGraph`].
pub graph_update: TxGraph<A>,
/// The update to apply to the receiving [`LocalChain`](crate::local_chain::LocalChain).
/// Data returned from a spk-based blockchain client full scan.
///
/// See also [`FullScanRequest`].
-pub struct FullScanResult<K, A = ConfirmationTimeHeightAnchor> {
+pub struct FullScanResult<K, A = ConfirmationBlockTime> {
/// The update to apply to the receiving [`LocalChain`](crate::local_chain::LocalChain).
pub graph_update: TxGraph<A>,
/// The update to apply to the receiving [`TxGraph`].
/// # use bdk_chain::local_chain::LocalChain;
/// # use bdk_chain::tx_graph::TxGraph;
/// # use bdk_chain::BlockId;
-/// # use bdk_chain::ConfirmationHeightAnchor;
-/// # use bdk_chain::ConfirmationTimeHeightAnchor;
+/// # use bdk_chain::ConfirmationBlockTime;
/// # use bdk_chain::example_utils::*;
/// # use bitcoin::hashes::Hash;
/// // Initialize the local chain with two blocks.
/// },
/// );
///
-/// // Insert `tx` into a `TxGraph` that uses `ConfirmationHeightAnchor` as the anchor type.
-/// // This anchor records the anchor block and the confirmation height of the transaction.
-/// // When a transaction is anchored with `ConfirmationHeightAnchor`, the anchor block and
-/// // confirmation block can be different. However, the confirmation block cannot be higher than
-/// // the anchor block and both blocks must be in the same chain for the anchor to be valid.
-/// let mut graph_b = TxGraph::<ConfirmationHeightAnchor>::default();
-/// let _ = graph_b.insert_tx(tx.clone());
-/// graph_b.insert_anchor(
-/// tx.compute_txid(),
-/// ConfirmationHeightAnchor {
-/// anchor_block: BlockId {
-/// height: 2,
-/// hash: Hash::hash("second".as_bytes()),
-/// },
-/// confirmation_height: 1,
-/// },
-/// );
-///
-/// // Insert `tx` into a `TxGraph` that uses `ConfirmationTimeHeightAnchor` as the anchor type.
-/// // This anchor records the anchor block, the confirmation height and time of the transaction.
-/// // When a transaction is anchored with `ConfirmationTimeHeightAnchor`, the anchor block and
-/// // confirmation block can be different. However, the confirmation block cannot be higher than
-/// // the anchor block and both blocks must be in the same chain for the anchor to be valid.
-/// let mut graph_c = TxGraph::<ConfirmationTimeHeightAnchor>::default();
+/// // Insert `tx` into a `TxGraph` that uses `ConfirmationBlockTime` as the anchor type.
+/// // This anchor records the anchor block and the confirmation time of the transaction. When a
+/// // transaction is anchored with `ConfirmationBlockTime`, the anchor block and confirmation block
+/// // of the transaction is the same block.
+/// let mut graph_c = TxGraph::<ConfirmationBlockTime>::default();
/// let _ = graph_c.insert_tx(tx.clone());
/// graph_c.insert_anchor(
/// tx.compute_txid(),
-/// ConfirmationTimeHeightAnchor {
-/// anchor_block: BlockId {
+/// ConfirmationBlockTime {
+/// block_id: BlockId {
/// height: 2,
/// hash: Hash::hash("third".as_bytes()),
/// },
-/// confirmation_height: 1,
/// confirmation_time: 123,
/// },
/// );
indexed_tx_graph::{self, IndexedTxGraph},
indexer::keychain_txout::KeychainTxOutIndex,
local_chain::LocalChain,
- tx_graph, Balance, ChainPosition, ConfirmationHeightAnchor, DescriptorExt, Merge,
+ tx_graph, Balance, ChainPosition, ConfirmationBlockTime, DescriptorExt, Merge,
};
use bitcoin::{
secp256k1::Secp256k1, Amount, OutPoint, Script, ScriptBuf, Transaction, TxIn, TxOut,
let spk_0 = descriptor.at_derivation_index(0).unwrap().script_pubkey();
let spk_1 = descriptor.at_derivation_index(9).unwrap().script_pubkey();
- let mut graph = IndexedTxGraph::<ConfirmationHeightAnchor, KeychainTxOutIndex<()>>::new(
+ let mut graph = IndexedTxGraph::<ConfirmationBlockTime, KeychainTxOutIndex<()>>::new(
KeychainTxOutIndex::new(10),
);
let _ = graph
let (desc_2, _) =
Descriptor::parse_descriptor(&Secp256k1::signing_only(), common::DESCRIPTORS[3]).unwrap();
- let mut graph = IndexedTxGraph::<ConfirmationHeightAnchor, KeychainTxOutIndex<String>>::new(
+ let mut graph = IndexedTxGraph::<ConfirmationBlockTime, KeychainTxOutIndex<String>>::new(
KeychainTxOutIndex::new(10),
);
local_chain
.get(height)
.map(|cp| cp.block_id())
- .map(|anchor_block| ConfirmationHeightAnchor {
- anchor_block,
- confirmation_height: anchor_block.height,
+ .map(|block_id| ConfirmationBlockTime {
+ block_id,
+ confirmation_time: 100,
}),
)
}));
// A helper lambda to extract and filter data from the graph.
let fetch =
- |height: u32,
- graph: &IndexedTxGraph<ConfirmationHeightAnchor, KeychainTxOutIndex<String>>| {
+ |height: u32, graph: &IndexedTxGraph<ConfirmationBlockTime, KeychainTxOutIndex<String>>| {
let chain_tip = local_chain
.get(height)
.map(|cp| cp.block_id())
collections::*,
local_chain::LocalChain,
tx_graph::{ChangeSet, TxGraph},
- Anchor, BlockId, ChainOracle, ChainPosition, ConfirmationHeightAnchor, Merge,
+ Anchor, BlockId, ChainOracle, ChainPosition, ConfirmationBlockTime, Merge,
};
use bitcoin::{
absolute, hashes::Hash, transaction, Amount, BlockHash, OutPoint, ScriptBuf, SignedAmount,
..common::new_tx(0)
};
- let mut graph = TxGraph::<ConfirmationHeightAnchor>::default();
+ let mut graph = TxGraph::<ConfirmationBlockTime>::default();
let _ = graph.insert_tx(tx_0.clone());
let _ = graph.insert_tx(tx_1.clone());
for (ht, tx) in [(95, &tx_0), (98, &tx_1)] {
let _ = graph.insert_anchor(
tx.compute_txid(),
- ConfirmationHeightAnchor {
- anchor_block: tip.block_id(),
- confirmation_height: ht,
+ ConfirmationBlockTime {
+ block_id: tip.get(ht).unwrap().block_id(),
+ confirmation_time: 100,
},
);
}
OutPoint::new(tx_0.compute_txid(), 0)
),
Some((
- ChainPosition::Confirmed(&ConfirmationHeightAnchor {
- anchor_block: tip.block_id(),
- confirmation_height: 98
+ ChainPosition::Confirmed(&ConfirmationBlockTime {
+ block_id: BlockId {
+ hash: tip.get(98).unwrap().hash(),
+ height: 98,
+ },
+ confirmation_time: 100
}),
tx_1.compute_txid(),
)),
assert_eq!(
graph.get_chain_position(&local_chain, tip.block_id(), tx_0.compute_txid()),
// Some(ObservedAs::Confirmed(&local_chain.get_block(95).expect("block expected"))),
- Some(ChainPosition::Confirmed(&ConfirmationHeightAnchor {
- anchor_block: tip.block_id(),
- confirmation_height: 95
+ Some(ChainPosition::Confirmed(&ConfirmationBlockTime {
+ block_id: BlockId {
+ hash: tip.get(95).unwrap().hash(),
+ height: 95,
+ },
+ confirmation_time: 100
}))
);
local_chain::CheckPoint,
spk_client::{FullScanRequest, FullScanResult, SyncRequest, SyncResult},
tx_graph::TxGraph,
- Anchor, BlockId, ConfirmationTimeHeightAnchor,
+ Anchor, BlockId, ConfirmationBlockTime,
};
use electrum_client::{ElectrumApi, Error, HeaderNotification};
use std::{
) -> Result<FullScanResult<K>, Error> {
let (tip, latest_blocks) =
fetch_tip_and_latest_blocks(&self.inner, request.chain_tip.clone())?;
- let mut graph_update = TxGraph::<ConfirmationTimeHeightAnchor>::default();
+ let mut graph_update = TxGraph::<ConfirmationBlockTime>::default();
let mut last_active_indices = BTreeMap::<K, u32>::new();
- for (keychain, keychain_spks) in request.spks_by_keychain {
+ for (keychain, spks) in request.spks_by_keychain {
if let Some(last_active_index) =
- self.populate_with_spks(&mut graph_update, keychain_spks, stop_gap, batch_size)?
+ self.populate_with_spks(&mut graph_update, spks, stop_gap, batch_size)?
{
last_active_indices.insert(keychain, last_active_index);
}
/// Transactions that contains an output with requested spk, or spends form an output with
/// requested spk will be added to `graph_update`. Anchors of the aforementioned transactions are
/// also included.
- ///
- /// Checkpoints (in `cps`) are used to create anchors. The `tx_cache` is self-explanatory.
- fn populate_with_spks<I: Ord + Clone>(
+ fn populate_with_spks(
&self,
- graph_update: &mut TxGraph<ConfirmationTimeHeightAnchor>,
- mut spks: impl Iterator<Item = (I, ScriptBuf)>,
+ graph_update: &mut TxGraph<ConfirmationBlockTime>,
+ mut spks: impl Iterator<Item = (u32, ScriptBuf)>,
stop_gap: usize,
batch_size: usize,
- ) -> Result<Option<I>, Error> {
+ ) -> Result<Option<u32>, Error> {
let mut unused_spk_count = 0_usize;
- let mut last_active_index = Option::<I>::None;
+ let mut last_active_index = Option::<u32>::None;
loop {
let spks = (0..batch_size)
for ((spk_index, _spk), spk_history) in spks.into_iter().zip(spk_histories) {
if spk_history.is_empty() {
- unused_spk_count += 1;
- if unused_spk_count > stop_gap {
+ unused_spk_count = unused_spk_count.saturating_add(1);
+ if unused_spk_count >= stop_gap {
return Ok(last_active_index);
}
continue;
///
/// Transactions in which the outpoint resides, and transactions that spend from the outpoint are
/// included. Anchors of the aforementioned transactions are included.
- ///
- /// Checkpoints (in `cps`) are used to create anchors. The `tx_cache` is self-explanatory.
fn populate_with_outpoints(
&self,
- graph_update: &mut TxGraph<ConfirmationTimeHeightAnchor>,
+ graph_update: &mut TxGraph<ConfirmationBlockTime>,
outpoints: impl IntoIterator<Item = OutPoint>,
) -> Result<(), Error> {
for outpoint in outpoints {
/// Populate the `graph_update` with transactions/anchors of the provided `txids`.
fn populate_with_txids(
&self,
- graph_update: &mut TxGraph<ConfirmationTimeHeightAnchor>,
+ graph_update: &mut TxGraph<ConfirmationBlockTime>,
txids: impl IntoIterator<Item = Txid>,
) -> Result<(), Error> {
for txid in txids {
// An anchor is inserted if the transaction is validated to be in a confirmed block.
fn validate_merkle_for_anchor(
&self,
- graph_update: &mut TxGraph<ConfirmationTimeHeightAnchor>,
+ graph_update: &mut TxGraph<ConfirmationBlockTime>,
txid: Txid,
confirmation_height: i32,
) -> Result<(), Error> {
if is_confirmed_tx {
let _ = graph_update.insert_anchor(
txid,
- ConfirmationTimeHeightAnchor {
- confirmation_height: merkle_res.block_height as u32,
+ ConfirmationBlockTime {
confirmation_time: header.time as u64,
- anchor_block: BlockId {
+ block_id: BlockId {
height: merkle_res.block_height as u32,
hash: header.block_hash(),
},
// which we do not have by default. This data is needed to calculate the transaction fee.
fn fetch_prev_txout(
&self,
- graph_update: &mut TxGraph<ConfirmationTimeHeightAnchor>,
+ graph_update: &mut TxGraph<ConfirmationBlockTime>,
) -> Result<(), Error> {
let full_txs: Vec<Arc<Transaction>> =
graph_update.full_txs().map(|tx_node| tx_node.tx).collect();
let agreement_height = agreement_cp.as_ref().map(CheckPoint::height);
let new_tip = new_blocks
- .clone()
- .into_iter()
+ .iter()
// Prune `new_blocks` to only include blocks that are actually new.
- .filter(|(height, _)| Some(*height) > agreement_height)
- .map(|(height, hash)| BlockId { height, hash })
+ .filter(|(height, _)| Some(*<&u32>::clone(height)) > agreement_height)
+ .map(|(height, hash)| BlockId {
+ height: *height,
+ hash: *hash,
+ })
.fold(agreement_cp, |prev_cp, block| {
Some(match prev_cp {
Some(cp) => cp.push(block).expect("must extend checkpoint"),
bitcoin::{hashes::Hash, Address, Amount, ScriptBuf, Txid, WScriptHash},
local_chain::LocalChain,
spk_client::{FullScanRequest, SyncRequest},
- Balance, ConfirmationTimeHeightAnchor, IndexedTxGraph, SpkTxOutIndex,
+ Balance, ConfirmationBlockTime, IndexedTxGraph, SpkTxOutIndex,
};
use bdk_electrum::BdkElectrumClient;
use bdk_testenv::{anyhow, bitcoincore_rpc::RpcApi, TestEnv};
fn get_balance(
recv_chain: &LocalChain,
- recv_graph: &IndexedTxGraph<ConfirmationTimeHeightAnchor, SpkTxOutIndex<()>>,
+ recv_graph: &IndexedTxGraph<ConfirmationBlockTime, SpkTxOutIndex<()>>,
) -> anyhow::Result<Balance> {
let chain_tip = recv_chain.tip().block_id();
let outpoints = recv_graph.index.outpoints().clone();
// Setup receiver.
let (mut recv_chain, _) = LocalChain::from_genesis_hash(env.bitcoind.client.get_block_hash(0)?);
- let mut recv_graph = IndexedTxGraph::<ConfirmationTimeHeightAnchor, _>::new({
+ let mut recv_graph = IndexedTxGraph::<ConfirmationBlockTime, _>::new({
let mut recv_index = SpkTxOutIndex::default();
recv_index.insert_spk((), spk_to_track.clone());
recv_index
// Setup receiver.
let (mut recv_chain, _) = LocalChain::from_genesis_hash(env.bitcoind.client.get_block_hash(0)?);
- let mut recv_graph = IndexedTxGraph::<ConfirmationTimeHeightAnchor, _>::new({
+ let mut recv_graph = IndexedTxGraph::<ConfirmationBlockTime, _>::new({
let mut recv_index = SpkTxOutIndex::default();
recv_index.insert_spk((), spk_to_track.clone());
recv_index
env.mine_blocks(101, Some(addr_to_mine))?;
// Create transactions that are tracked by our receiver.
+ let mut txids = vec![];
+ let mut hashes = vec![];
for _ in 0..REORG_COUNT {
- env.send(&addr_to_track, SEND_AMOUNT)?;
- env.mine_blocks(1, None)?;
+ txids.push(env.send(&addr_to_track, SEND_AMOUNT)?);
+ hashes.extend(env.mine_blocks(1, None)?);
}
// Sync up to tip.
// Retain a snapshot of all anchors before reorg process.
let initial_anchors = update.graph_update.all_anchors();
+ let anchors: Vec<_> = initial_anchors.iter().cloned().collect();
+ assert_eq!(anchors.len(), REORG_COUNT);
+ for i in 0..REORG_COUNT {
+ let (anchor, txid) = anchors[i];
+ assert_eq!(anchor.block_id.hash, hashes[i]);
+ assert_eq!(txid, txids[i]);
+ }
// Check if initial balance is correct.
assert_eq!(
bitcoin::{BlockHash, OutPoint, ScriptBuf, TxOut, Txid},
collections::BTreeMap,
local_chain::CheckPoint,
- BlockId, ConfirmationTimeHeightAnchor, TxGraph,
+ BlockId, ConfirmationBlockTime, TxGraph,
};
use bdk_chain::{Anchor, Indexed};
use esplora_client::{Amount, TxStatus};
>,
stop_gap: usize,
parallel_requests: usize,
-) -> Result<(TxGraph<ConfirmationTimeHeightAnchor>, BTreeMap<K, u32>), Error> {
+) -> Result<(TxGraph<ConfirmationBlockTime>, BTreeMap<K, u32>), Error> {
type TxsOfSpkIndex = (u32, Vec<esplora_client::Tx>);
let parallel_requests = Ord::max(parallel_requests, 1);
- let mut graph = TxGraph::<ConfirmationTimeHeightAnchor>::default();
+ let mut graph = TxGraph::<ConfirmationBlockTime>::default();
let mut last_active_indexes = BTreeMap::<K, u32>::new();
for (keychain, spks) in keychain_spks {
txids: impl IntoIterator<IntoIter = impl Iterator<Item = Txid> + Send> + Send,
outpoints: impl IntoIterator<IntoIter = impl Iterator<Item = OutPoint> + Send> + Send,
parallel_requests: usize,
-) -> Result<TxGraph<ConfirmationTimeHeightAnchor>, Error> {
+) -> Result<TxGraph<ConfirmationBlockTime>, Error> {
let mut graph = full_scan_for_index_and_graph(
client,
[(
use bdk_chain::{
bitcoin::{Amount, BlockHash, OutPoint, ScriptBuf, TxOut, Txid},
local_chain::CheckPoint,
- BlockId, ConfirmationTimeHeightAnchor, TxGraph,
+ BlockId, ConfirmationBlockTime, TxGraph,
};
use bdk_chain::{Anchor, Indexed};
use esplora_client::TxStatus;
keychain_spks: BTreeMap<K, impl IntoIterator<Item = Indexed<ScriptBuf>>>,
stop_gap: usize,
parallel_requests: usize,
-) -> Result<(TxGraph<ConfirmationTimeHeightAnchor>, BTreeMap<K, u32>), Error> {
+) -> Result<(TxGraph<ConfirmationBlockTime>, BTreeMap<K, u32>), Error> {
type TxsOfSpkIndex = (u32, Vec<esplora_client::Tx>);
let parallel_requests = Ord::max(parallel_requests, 1);
- let mut tx_graph = TxGraph::<ConfirmationTimeHeightAnchor>::default();
+ let mut tx_graph = TxGraph::<ConfirmationBlockTime>::default();
let mut last_active_indices = BTreeMap::<K, u32>::new();
for (keychain, spks) in keychain_spks {
txids: impl IntoIterator<Item = Txid>,
outpoints: impl IntoIterator<Item = OutPoint>,
parallel_requests: usize,
-) -> Result<TxGraph<ConfirmationTimeHeightAnchor>, Error> {
+) -> Result<TxGraph<ConfirmationBlockTime>, Error> {
let (mut tx_graph, _) = full_scan_for_index_and_graph_blocking(
client,
{
//! [`TxGraph`]: bdk_chain::tx_graph::TxGraph
//! [`example_esplora`]: https://github.com/bitcoindevkit/bdk/tree/master/example-crates/example_esplora
-use bdk_chain::{BlockId, ConfirmationTimeHeightAnchor};
+use bdk_chain::{BlockId, ConfirmationBlockTime};
use esplora_client::TxStatus;
pub use esplora_client;
#[cfg(feature = "async")]
pub use async_ext::*;
-fn anchor_from_status(status: &TxStatus) -> Option<ConfirmationTimeHeightAnchor> {
+fn anchor_from_status(status: &TxStatus) -> Option<ConfirmationBlockTime> {
if let TxStatus {
block_height: Some(height),
block_hash: Some(hash),
..
} = status.clone()
{
- Some(ConfirmationTimeHeightAnchor {
- anchor_block: BlockId { height, hash },
- confirmation_height: height,
+ Some(ConfirmationBlockTime {
+ block_id: BlockId { height, hash },
confirmation_time: time,
})
} else {
use bdk_chain::bitcoin::{secp256k1, BlockHash, OutPoint};
use bdk_chain::miniscript::Descriptor;
use bdk_chain::CombinedChangeSet;
- use bdk_chain::{
- indexed_tx_graph, tx_graph, BlockId, ConfirmationHeightAnchor,
- ConfirmationTimeHeightAnchor, DescriptorExt,
- };
+ use bdk_chain::{indexed_tx_graph, tx_graph, BlockId, ConfirmationBlockTime, DescriptorExt};
use std::str::FromStr;
use std::sync::Arc;
}
#[test]
- fn insert_and_load_aggregate_changesets_with_confirmation_time_height_anchor() {
+ fn insert_and_load_aggregate_changesets_with_confirmation_block_time_anchor() {
let (test_changesets, agg_test_changesets) =
- create_test_changesets(&|height, time, hash| ConfirmationTimeHeightAnchor {
- confirmation_height: height,
+ create_test_changesets(&|height, time, hash| ConfirmationBlockTime {
confirmation_time: time,
- anchor_block: (height, hash).into(),
+ block_id: (height, hash).into(),
});
let conn = Connection::open_in_memory().expect("in memory connection");
- let mut store = Store::<Keychain, ConfirmationTimeHeightAnchor>::new(conn)
- .expect("create new memory db store");
-
- test_changesets.iter().for_each(|changeset| {
- store.write(changeset).expect("write changeset");
- });
-
- let agg_changeset = store.read().expect("aggregated changeset");
-
- assert_eq!(agg_changeset, Some(agg_test_changesets));
- }
-
- #[test]
- fn insert_and_load_aggregate_changesets_with_confirmation_height_anchor() {
- let (test_changesets, agg_test_changesets) =
- create_test_changesets(&|height, _time, hash| ConfirmationHeightAnchor {
- confirmation_height: height,
- anchor_block: (height, hash).into(),
- });
-
- let conn = Connection::open_in_memory().expect("in memory connection");
- let mut store = Store::<Keychain, ConfirmationHeightAnchor>::new(conn)
+ let mut store = Store::<Keychain, ConfirmationBlockTime>::new(conn)
.expect("create new memory db store");
test_changesets.iter().for_each(|changeset| {
let blockheight = if include_blockheight {
wallet.transactions().next().map_or(0, |canonical_tx| {
match canonical_tx.chain_position {
- bdk_chain::ChainPosition::Confirmed(a) => a.confirmation_height,
+ bdk_chain::ChainPosition::Confirmed(a) => a.block_id.height,
bdk_chain::ChainPosition::Unconfirmed(_) => 0,
}
})
use core::str::FromStr;
use crate::std::string::ToString;
- use bdk_chain::{BlockId, ConfirmationTimeHeightAnchor};
+ use bdk_chain::{BlockId, ConfirmationBlockTime};
use bitcoin::hashes::Hash;
use bitcoin::{transaction, BlockHash, Network, Transaction};
};
let txid = transaction.compute_txid();
let block_id = BlockId {
- height: 5001,
+ height: 5000,
hash: BlockHash::all_zeros(),
};
wallet.insert_checkpoint(block_id).unwrap();
+ wallet
+ .insert_checkpoint(BlockId {
+ height: 5001,
+ hash: BlockHash::all_zeros(),
+ })
+ .unwrap();
wallet.insert_tx(transaction);
- let anchor = ConfirmationTimeHeightAnchor {
- confirmation_height: 5000,
+ let anchor = ConfirmationBlockTime {
confirmation_time: 0,
- anchor_block: block_id,
+ block_id,
};
let mut graph = TxGraph::default();
let _ = graph.insert_anchor(txid, anchor);
},
spk_client::{FullScanRequest, FullScanResult, SyncRequest, SyncResult},
tx_graph::{CanonicalTx, TxGraph, TxNode},
- BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeHeightAnchor, FullTxOut, Indexed,
+ BlockId, ChainPosition, ConfirmationBlockTime, ConfirmationTime, FullTxOut, Indexed,
IndexedTxGraph, Merge,
};
use bitcoin::sighash::{EcdsaSighashType, TapSighashType};
signers: Arc<SignersContainer>,
change_signers: Arc<SignersContainer>,
chain: LocalChain,
- indexed_graph: IndexedTxGraph<ConfirmationTimeHeightAnchor, KeychainTxOutIndex<KeychainKind>>,
+ indexed_graph: IndexedTxGraph<ConfirmationBlockTime, KeychainTxOutIndex<KeychainKind>>,
stage: ChangeSet,
network: Network,
secp: SecpCtx,
pub last_active_indices: BTreeMap<KeychainKind, u32>,
/// Update for the wallet's internal [`TxGraph`].
- pub graph: TxGraph<ConfirmationTimeHeightAnchor>,
+ pub graph: TxGraph<ConfirmationBlockTime>,
/// Update for the wallet's internal [`LocalChain`].
///
}
/// The changes made to a wallet by applying an [`Update`].
-pub type ChangeSet = bdk_chain::CombinedChangeSet<KeychainKind, ConfirmationTimeHeightAnchor>;
+pub type ChangeSet = bdk_chain::CombinedChangeSet<KeychainKind, ConfirmationBlockTime>;
/// A derived address and the index it was found at.
/// For convenience this automatically derefs to `Address`
/// match canonical_tx.chain_position {
/// ChainPosition::Confirmed(anchor) => println!(
/// "tx is confirmed at height {}, we know this since {}:{} is in the best chain",
- /// anchor.confirmation_height, anchor.anchor_block.height, anchor.anchor_block.hash,
+ /// anchor.block_id.height, anchor.block_id.height, anchor.block_id.hash,
/// ),
/// ChainPosition::Unconfirmed(last_seen) => println!(
/// "tx is last seen at {}, it is unconfirmed as it is not anchored in the best chain",
pub fn get_tx(
&self,
txid: Txid,
- ) -> Option<CanonicalTx<'_, Arc<Transaction>, ConfirmationTimeHeightAnchor>> {
+ ) -> Option<CanonicalTx<'_, Arc<Transaction>, ConfirmationBlockTime>> {
let graph = self.indexed_graph.graph();
Some(CanonicalTx {
/// Iterate over the transactions in the wallet.
pub fn transactions(
&self,
- ) -> impl Iterator<Item = CanonicalTx<'_, Arc<Transaction>, ConfirmationTimeHeightAnchor>> + '_
- {
+ ) -> impl Iterator<Item = CanonicalTx<'_, Arc<Transaction>, ConfirmationBlockTime>> + '_ {
self.indexed_graph
.graph()
.list_canonical_txs(&self.chain, self.chain.tip().block_id())
.graph()
.get_chain_position(&self.chain, chain_tip, input.previous_output.txid)
.map(|chain_position| match chain_position {
- ChainPosition::Confirmed(a) => a.confirmation_height,
+ ChainPosition::Confirmed(a) => a.block_id.height,
ChainPosition::Unconfirmed(_) => u32::MAX,
});
let current_height = sign_options
}
/// Get a reference to the inner [`TxGraph`].
- pub fn tx_graph(&self) -> &TxGraph<ConfirmationTimeHeightAnchor> {
+ pub fn tx_graph(&self) -> &TxGraph<ConfirmationBlockTime> {
self.indexed_graph.graph()
}
/// because they haven't been broadcast.
pub fn unbroadcast_transactions(
&self,
- ) -> impl Iterator<Item = TxNode<'_, Arc<Transaction>, ConfirmationTimeHeightAnchor>> {
+ ) -> impl Iterator<Item = TxNode<'_, Arc<Transaction>, ConfirmationBlockTime>> {
self.tx_graph().txs_with_no_anchor_or_last_seen()
}
}
}
-impl AsRef<bdk_chain::tx_graph::TxGraph<ConfirmationTimeHeightAnchor>> for Wallet {
- fn as_ref(&self) -> &bdk_chain::tx_graph::TxGraph<ConfirmationTimeHeightAnchor> {
+impl AsRef<bdk_chain::tx_graph::TxGraph<ConfirmationBlockTime>> for Wallet {
+ fn as_ref(&self) -> &bdk_chain::tx_graph::TxGraph<ConfirmationBlockTime> {
self.indexed_graph.graph()
}
}
fn new_local_utxo(
keychain: KeychainKind,
derivation_index: u32,
- full_txo: FullTxOut<ConfirmationTimeHeightAnchor>,
+ full_txo: FullTxOut<ConfirmationBlockTime>,
) -> LocalOutput {
LocalOutput {
outpoint: full_txo.outpoint,
macro_rules! doctest_wallet {
() => {{
use $crate::bitcoin::{BlockHash, Transaction, absolute, TxOut, Network, hashes::Hash};
- use $crate::chain::{ConfirmationTimeHeightAnchor, BlockId, TxGraph};
+ use $crate::chain::{ConfirmationBlockTime, BlockId, TxGraph};
use $crate::wallet::{Update, Wallet};
use $crate::KeychainKind;
let descriptor = "tr([73c5da0a/86'/0'/0']tprv8fMn4hSKPRC1oaCPqxDb1JWtgkpeiQvZhsr8W2xuy3GEMkzoArcAWTfJxYb6Wj8XNNDWEjfYKK4wGQXh3ZUXhDF2NcnsALpWTeSwarJt7Vc/0/*)";
}],
};
let txid = tx.txid();
- let block = BlockId { height: 1_000, hash: BlockHash::all_zeros() };
- let _ = wallet.insert_checkpoint(block);
+ let block_id = BlockId { height: 500, hash: BlockHash::all_zeros() };
+ let _ = wallet.insert_checkpoint(block_id);
+ let _ = wallet.insert_checkpoint(BlockId { height: 1_000, hash: BlockHash::all_zeros() });
let _ = wallet.insert_tx(tx);
- let anchor = ConfirmationTimeHeightAnchor {
- confirmation_height: 500,
+ let anchor = ConfirmationBlockTime {
confirmation_time: 50_000,
- anchor_block: block,
+ block_id,
};
let mut graph = TxGraph::default();
let _ = graph.insert_anchor(txid, anchor);
#![allow(unused)]
-use bdk_chain::{BlockId, ConfirmationTime, ConfirmationTimeHeightAnchor, TxGraph};
+use bdk_chain::{BlockId, ConfirmationBlockTime, ConfirmationTime, TxGraph};
use bdk_wallet::{
wallet::{Update, Wallet},
KeychainKind, LocalOutput,
],
};
+ wallet
+ .insert_checkpoint(BlockId {
+ height: 42,
+ hash: BlockHash::all_zeros(),
+ })
+ .unwrap();
wallet
.insert_checkpoint(BlockId {
height: 1_000,
.local_chain()
.range(height..)
.last()
- .map(|anchor_cp| ConfirmationTimeHeightAnchor {
- anchor_block: anchor_cp.block_id(),
- confirmation_height: height,
+ .map(|anchor_cp| ConfirmationBlockTime {
+ block_id: anchor_cp.block_id(),
confirmation_time: time,
})
.expect("confirmation height cannot be greater than tip");
indexed_tx_graph,
indexer::keychain_txout,
local_chain::{self, LocalChain},
- ConfirmationTimeHeightAnchor, IndexedTxGraph, Merge,
+ ConfirmationBlockTime, IndexedTxGraph, Merge,
};
use example_cli::{
anyhow,
type ChangeSet = (
local_chain::ChangeSet,
- indexed_tx_graph::ChangeSet<ConfirmationTimeHeightAnchor, keychain_txout::ChangeSet<Keychain>>,
+ indexed_tx_graph::ChangeSet<ConfirmationBlockTime, keychain_txout::ChangeSet<Keychain>>,
);
#[derive(Debug)]
indexer::keychain_txout,
local_chain::{self, LocalChain},
spk_client::{FullScanRequest, SyncRequest},
- ConfirmationHeightAnchor, Merge,
+ ConfirmationBlockTime, Merge,
};
use bdk_electrum::{
electrum_client::{self, Client, ElectrumApi},
type ChangeSet = (
local_chain::ChangeSet,
- indexed_tx_graph::ChangeSet<ConfirmationHeightAnchor, keychain_txout::ChangeSet<Keychain>>,
+ indexed_tx_graph::ChangeSet<ConfirmationBlockTime, keychain_txout::ChangeSet<Keychain>>,
);
fn main() -> anyhow::Result<()> {
let chain_changeset = chain.apply_update(chain_update)?;
let mut indexed_tx_graph_changeset =
- indexed_tx_graph::ChangeSet::<ConfirmationHeightAnchor, _>::default();
+ indexed_tx_graph::ChangeSet::<ConfirmationBlockTime, _>::default();
if let Some(keychain_update) = keychain_update {
let keychain_changeset = graph.index.reveal_to_target_multi(&keychain_update);
indexed_tx_graph_changeset.merge(keychain_changeset.into());
}
- indexed_tx_graph_changeset.merge(graph.apply_update(graph_update.map_anchors(|a| {
- ConfirmationHeightAnchor {
- confirmation_height: a.confirmation_height,
- anchor_block: a.anchor_block,
- }
- })));
+ indexed_tx_graph_changeset.merge(graph.apply_update(graph_update));
(chain_changeset, indexed_tx_graph_changeset)
};
indexer::keychain_txout,
local_chain::{self, LocalChain},
spk_client::{FullScanRequest, SyncRequest},
- ConfirmationTimeHeightAnchor, Merge,
+ ConfirmationBlockTime, Merge,
};
use bdk_esplora::{esplora_client, EsploraExt};
type ChangeSet = (
local_chain::ChangeSet,
- indexed_tx_graph::ChangeSet<ConfirmationTimeHeightAnchor, keychain_txout::ChangeSet<Keychain>>,
+ indexed_tx_graph::ChangeSet<ConfirmationBlockTime, keychain_txout::ChangeSet<Keychain>>,
);
#[derive(Subcommand, Debug, Clone)]