Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(electrum)!: Update bdk_electrum to use merkle proofs #1489

Merged
merged 3 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 21 additions & 66 deletions crates/chain/src/chain_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ impl ConfirmationTime {
}
}

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 },
Expand Down Expand Up @@ -145,9 +145,7 @@ impl From<(&u32, &BlockHash)> for BlockId {
}
}

/// 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)]
Expand All @@ -156,70 +154,27 @@ impl From<(&u32, &BlockHash)> for BlockId {
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 {
LagginTimes marked this conversation as resolved.
Show resolved Hide resolved
/// 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 _,
}
}
Expand Down Expand Up @@ -305,19 +260,19 @@ mod test {

#[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()
},
});
Expand Down
6 changes: 3 additions & 3 deletions crates/chain/src/spk_client.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! 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};
Expand Down Expand Up @@ -176,7 +176,7 @@ impl SyncRequest {
/// 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).
Expand Down Expand Up @@ -317,7 +317,7 @@ impl<K: Ord + Clone> FullScanRequest<K> {
/// 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`].
Expand Down
37 changes: 8 additions & 29 deletions crates/chain/src/tx_data_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ use alloc::vec::Vec;
/// # 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.
Expand Down Expand Up @@ -50,39 +49,19 @@ use alloc::vec::Vec;
/// },
/// );
///
/// // 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,
/// },
/// );
Expand Down
15 changes: 7 additions & 8 deletions crates/chain/tests/test_indexed_tx_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use bdk_chain::{
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,
Expand All @@ -32,7 +32,7 @@ fn insert_relevant_txs() {
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
Expand Down Expand Up @@ -140,7 +140,7 @@ fn test_list_owned_txouts() {
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),
);

Expand Down Expand Up @@ -250,9 +250,9 @@ fn test_list_owned_txouts() {
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,
}),
)
}));
Expand All @@ -261,8 +261,7 @@ fn test_list_owned_txouts() {

// 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())
Expand Down
28 changes: 17 additions & 11 deletions crates/chain/tests/test_tx_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bdk_chain::{
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,
Expand Down Expand Up @@ -935,7 +935,7 @@ fn test_chain_spends() {
..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());
Expand All @@ -944,9 +944,9 @@ fn test_chain_spends() {
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,
},
);
}
Expand All @@ -959,9 +959,12 @@ fn test_chain_spends() {
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(),
)),
Expand All @@ -971,9 +974,12 @@ fn test_chain_spends() {
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
}))
);

Expand Down
Loading
Loading