Skip to content

Commit e9d0cd9

Browse files
committed
Merge #1569: Introduce bdk_core
a5d076f chore(core)!: s/tx_graph::Update/TxUpdate/ (LLFourn) dafb9aa feat(bitcoind_rpc)!: depend on `bdk_core` instead of `bdk_chain` (志宇) fea8eed feat(esplora)!: depend on `bdk_core` instead of `bdk_chain` (志宇) 0d302f5 feat(electrum)!: depend on `bdk_core` instead of `bdk_chain` (志宇) ab0315d feat!: move `spk_client`s to `bdk_core` (志宇) bdea871 feat!: move `tx_graph::Update` to `bdk_core` (志宇) 77e31c7 feat!: move `CheckPoint` to `bdk_core` (志宇) a86c878 refactor(chain): change `CheckPoint::apply_changeset` (志宇) 6f7626a feat!: introduce `bdk_core` (志宇) Pull request description: Based on #1568 Closes #1543 ### Description Introduce `bdk_core` crate. Move types over from `bdk_chain`. Chain sources (`bdk_electrum`, `bdk_esplora` and `bdk_bitcoind_rpc`) now only depend on `bdk_core`. ### Notes to the reviewers Please review commit-by-commit. I've moved things over, but slight API changes were necessary (mentioned in the commit messages). ### Changelog notice * Add `bdk_core` crate which contains core types that were previously in `bdk_chain`. Including: `BlockId`, `ConfirmationBlockTime`, `CheckPoint`, `CheckPointIter`, `tx_graph::Update` and `spk_client`-types. * Change chain sources (`bdk_esplora`, `bdk_electrum` and `bdk_bitcoind_rpc`) to only depend on `bdk_core`. ### Checklists #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing ACKs for top commit: LLFourn: Self-ACK: a5d076f evanlinjin: ACK a5d076f Tree-SHA512: 13ecd0a2d2fc840b281977f07dc11fed27459f77c676af470134d2184db4a1fc352073ef82b1622e04fc60edb885e587ae8b9909c9bafb4ae63fcd51325d1cad
2 parents dad9545 + a5d076f commit e9d0cd9

39 files changed

+847
-725
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ resolver = "2"
33
members = [
44
"crates/wallet",
55
"crates/chain",
6+
"crates/core",
67
"crates/file_store",
78
"crates/electrum",
89
"crates/esplora",

crates/bitcoind_rpc/Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ readme = "README.md"
1515
[dependencies]
1616
bitcoin = { version = "0.32.0", default-features = false }
1717
bitcoincore-rpc = { version = "0.19.0" }
18-
bdk_chain = { path = "../chain", version = "0.17", default-features = false }
18+
bdk_core = { path = "../core", version = "0.1", default-features = false }
1919

2020
[dev-dependencies]
2121
bdk_testenv = { path = "../testenv", default-features = false }
22+
bdk_chain = { path = "../chain", version = "0.17" }
2223

2324
[features]
2425
default = ["std"]
25-
std = ["bitcoin/std", "bdk_chain/std"]
26-
serde = ["bitcoin/serde", "bdk_chain/serde"]
26+
std = ["bitcoin/std", "bdk_core/std"]
27+
serde = ["bitcoin/serde", "bdk_core/serde"]

crates/bitcoind_rpc/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//! mempool.
1010
#![warn(missing_docs)]
1111

12-
use bdk_chain::{local_chain::CheckPoint, BlockId};
12+
use bdk_core::{BlockId, CheckPoint};
1313
use bitcoin::{block::Header, Block, BlockHash, Transaction};
1414
pub use bitcoincore_rpc;
1515
use bitcoincore_rpc::bitcoincore_rpc_json;

crates/chain/Cargo.toml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ readme = "README.md"
1414

1515
[dependencies]
1616
bitcoin = { version = "0.32.0", default-features = false }
17+
bdk_core = { path = "../core", version = "0.1", default-features = false }
1718
serde = { version = "1", optional = true, features = ["derive", "rc"] }
18-
19-
# Use hashbrown as a feature flag to have HashSet and HashMap from it.
20-
hashbrown = { version = "0.9.1", optional = true, features = ["serde"] }
2119
miniscript = { version = "12.0.0", optional = true, default-features = false }
2220

2321
# Feature dependencies
@@ -30,6 +28,7 @@ proptest = "1.2.0"
3028

3129
[features]
3230
default = ["std", "miniscript"]
33-
std = ["bitcoin/std", "miniscript?/std"]
34-
serde = ["dep:serde", "bitcoin/serde", "miniscript?/serde"]
31+
std = ["bitcoin/std", "miniscript?/std", "bdk_core/std"]
32+
serde = ["dep:serde", "bitcoin/serde", "miniscript?/serde", "bdk_core/serde"]
33+
hashbrown = ["bdk_core/hashbrown"]
3534
rusqlite = ["std", "dep:rusqlite", "serde", "serde_json"]

crates/chain/src/chain_data.rs

Lines changed: 5 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use bitcoin::{hashes::Hash, BlockHash, OutPoint, TxOut, Txid};
1+
use crate::ConfirmationBlockTime;
2+
use bitcoin::{OutPoint, TxOut, Txid};
23

3-
use crate::{Anchor, AnchorFromBlockPosition, COINBASE_MATURITY};
4+
use crate::{Anchor, COINBASE_MATURITY};
45

56
/// Represents the observed position of some chain data.
67
///
@@ -82,92 +83,6 @@ impl From<ChainPosition<ConfirmationBlockTime>> for ConfirmationTime {
8283
}
8384
}
8485

85-
/// A reference to a block in the canonical chain.
86-
///
87-
/// `BlockId` implements [`Anchor`]. When a transaction is anchored to `BlockId`, the confirmation
88-
/// block and anchor block are the same block.
89-
#[derive(Debug, Clone, PartialEq, Eq, Copy, PartialOrd, Ord, core::hash::Hash)]
90-
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
91-
pub struct BlockId {
92-
/// The height of the block.
93-
pub height: u32,
94-
/// The hash of the block.
95-
pub hash: BlockHash,
96-
}
97-
98-
impl Anchor for BlockId {
99-
fn anchor_block(&self) -> Self {
100-
*self
101-
}
102-
}
103-
104-
impl AnchorFromBlockPosition for BlockId {
105-
fn from_block_position(_block: &bitcoin::Block, block_id: BlockId, _tx_pos: usize) -> Self {
106-
block_id
107-
}
108-
}
109-
110-
impl Default for BlockId {
111-
fn default() -> Self {
112-
Self {
113-
height: Default::default(),
114-
hash: BlockHash::all_zeros(),
115-
}
116-
}
117-
}
118-
119-
impl From<(u32, BlockHash)> for BlockId {
120-
fn from((height, hash): (u32, BlockHash)) -> Self {
121-
Self { height, hash }
122-
}
123-
}
124-
125-
impl From<BlockId> for (u32, BlockHash) {
126-
fn from(block_id: BlockId) -> Self {
127-
(block_id.height, block_id.hash)
128-
}
129-
}
130-
131-
impl From<(&u32, &BlockHash)> for BlockId {
132-
fn from((height, hash): (&u32, &BlockHash)) -> Self {
133-
Self {
134-
height: *height,
135-
hash: *hash,
136-
}
137-
}
138-
}
139-
140-
/// An [`Anchor`] implementation that also records the exact confirmation time of the transaction.
141-
///
142-
/// Refer to [`Anchor`] for more details.
143-
#[derive(Debug, Default, Clone, PartialEq, Eq, Copy, PartialOrd, Ord, core::hash::Hash)]
144-
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
145-
pub struct ConfirmationBlockTime {
146-
/// The anchor block.
147-
pub block_id: BlockId,
148-
/// The confirmation time of the transaction being anchored.
149-
pub confirmation_time: u64,
150-
}
151-
152-
impl Anchor for ConfirmationBlockTime {
153-
fn anchor_block(&self) -> BlockId {
154-
self.block_id
155-
}
156-
157-
fn confirmation_height_upper_bound(&self) -> u32 {
158-
self.block_id.height
159-
}
160-
}
161-
162-
impl AnchorFromBlockPosition for ConfirmationBlockTime {
163-
fn from_block_position(block: &bitcoin::Block, block_id: BlockId, _tx_pos: usize) -> Self {
164-
Self {
165-
block_id,
166-
confirmation_time: block.header.time as _,
167-
}
168-
}
169-
}
170-
17186
/// A `TxOut` with as much data as we can retrieve about it
17287
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
17388
pub struct FullTxOut<A> {
@@ -244,6 +159,8 @@ impl<A: Anchor> FullTxOut<A> {
244159

245160
#[cfg(test)]
246161
mod test {
162+
use crate::BlockId;
163+
247164
use super::*;
248165

249166
#[test]

crates/chain/src/example_utils.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
#![allow(unused)]
2+
use crate::BlockId;
23
use alloc::vec::Vec;
34
use bitcoin::{
45
consensus,
56
hashes::{hex::FromHex, Hash},
67
Transaction,
78
};
89

9-
use crate::BlockId;
10-
1110
pub const RAW_TX_1: &str = "0200000000010116d6174da7183d70d0a7d4dc314d517a7d135db79ad63515028b293a76f4f9d10000000000feffffff023a21fc8350060000160014531c405e1881ef192294b8813631e258bf98ea7a1027000000000000225120a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c024730440220591b1a172a122da49ba79a3e79f98aaa03fd7a372f9760da18890b6a327e6010022013e82319231da6c99abf8123d7c07e13cf9bd8d76e113e18dc452e5024db156d012102318a2d558b2936c52e320decd6d92a88d7f530be91b6fe0af5caf41661e77da3ef2e0100";
1211
pub const RAW_TX_2: &str = "02000000000101a688607020cfae91a61e7c516b5ef1264d5d77f17200c3866826c6c808ebf1620000000000feffffff021027000000000000225120a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c20fd48ff530600001600146886c525e41d4522042bd0b159dfbade2504a6bb024730440220740ff7e665cd20565d4296b549df8d26b941be3f1e3af89a0b60e50c0dbeb69a02206213ab7030cf6edc6c90d4ccf33010644261e029950a688dc0b1a9ebe6ddcc5a012102f2ac6b396a97853cb6cd62242c8ae4842024742074475023532a51e9c53194253e760100";
1312
pub const RAW_TX_3: &str = "0200000000010135d67ee47b557e68b8c6223958f597381965ed719f1207ee2b9e20432a24a5dc0100000000feffffff021027000000000000225120a82f29944d65b86ae6b5e5cc75e294ead6c59391a1edc5e016e3498c67fc7bbb62215a5055060000160014070df7671dea67a50c4799a744b5c9be8f4bac690247304402207ebf8d29f71fd03e7e6977b3ea78ca5fcc5c49a42ae822348fc401862fdd766c02201d7e4ff0684ecb008b6142f36ead1b0b4d615524c4f58c261113d361f4427e25012103e6a75e2fab85e5ecad641afc4ffba7222f998649d9f18cac92f0fcc8618883b3ee760100";

crates/chain/src/indexed_tx_graph.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ where
9090

9191
/// Apply an `update` directly.
9292
///
93-
/// `update` is a [`tx_graph::Update<A>`] and the resultant changes is returned as [`ChangeSet`].
93+
/// `update` is a [`tx_graph::TxUpdate<A>`] and the resultant changes is returned as [`ChangeSet`].
9494
#[cfg(feature = "std")]
9595
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
96-
pub fn apply_update(&mut self, update: tx_graph::Update<A>) -> ChangeSet<A, I::ChangeSet> {
96+
pub fn apply_update(&mut self, update: tx_graph::TxUpdate<A>) -> ChangeSet<A, I::ChangeSet> {
9797
let tx_graph = self.graph.apply_update(update);
9898
let indexer = self.index_tx_graph_changeset(&tx_graph);
9999
ChangeSet { tx_graph, indexer }
@@ -114,7 +114,7 @@ where
114114
/// set to the current time.
115115
pub fn apply_update_at(
116116
&mut self,
117-
update: tx_graph::Update<A>,
117+
update: tx_graph::TxUpdate<A>,
118118
seen_at: Option<u64>,
119119
) -> ChangeSet<A, I::ChangeSet> {
120120
let tx_graph = self.graph.apply_update_at(update, seen_at);

crates/chain/src/indexer/keychain_txout.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use crate::{
55
collections::*,
66
miniscript::{Descriptor, DescriptorPublicKey},
7+
spk_client::{FullScanRequestBuilder, SyncRequestBuilder},
78
spk_iter::BIP32_MAX_INDEX,
89
spk_txout::SpkTxOutIndex,
910
DescriptorExt, DescriptorId, Indexed, Indexer, KeychainIndexed, SpkIterator,
@@ -875,3 +876,43 @@ impl Merge for ChangeSet {
875876
self.last_revealed.is_empty()
876877
}
877878
}
879+
880+
/// Trait to extend [`SyncRequestBuilder`].
881+
pub trait SyncRequestBuilderExt<K> {
882+
/// Add [`Script`](bitcoin::Script)s that are revealed by the `indexer` of the given `spk_range`
883+
/// that will be synced against.
884+
fn revealed_spks_from_indexer<R>(self, indexer: &KeychainTxOutIndex<K>, spk_range: R) -> Self
885+
where
886+
R: core::ops::RangeBounds<K>;
887+
888+
/// Add [`Script`](bitcoin::Script)s that are revealed by the `indexer` but currently unused.
889+
fn unused_spks_from_indexer(self, indexer: &KeychainTxOutIndex<K>) -> Self;
890+
}
891+
892+
impl<K: Clone + Ord + core::fmt::Debug> SyncRequestBuilderExt<K> for SyncRequestBuilder<(K, u32)> {
893+
fn revealed_spks_from_indexer<R>(self, indexer: &KeychainTxOutIndex<K>, spk_range: R) -> Self
894+
where
895+
R: core::ops::RangeBounds<K>,
896+
{
897+
self.spks_with_indexes(indexer.revealed_spks(spk_range))
898+
}
899+
900+
fn unused_spks_from_indexer(self, indexer: &KeychainTxOutIndex<K>) -> Self {
901+
self.spks_with_indexes(indexer.unused_spks())
902+
}
903+
}
904+
905+
/// Trait to extend [`FullScanRequestBuilder`].
906+
pub trait FullScanRequestBuilderExt<K> {
907+
/// Add spk iterators for each keychain tracked in `indexer`.
908+
fn spks_from_indexer(self, indexer: &KeychainTxOutIndex<K>) -> Self;
909+
}
910+
911+
impl<K: Clone + Ord + core::fmt::Debug> FullScanRequestBuilderExt<K> for FullScanRequestBuilder<K> {
912+
fn spks_from_indexer(mut self, indexer: &KeychainTxOutIndex<K>) -> Self {
913+
for (keychain, spks) in indexer.all_unbounded_spk_iters() {
914+
self = self.spks_for_keychain(keychain, spks);
915+
}
916+
self
917+
}
918+
}

crates/chain/src/lib.rs

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ pub use indexer::spk_txout;
3838
pub use indexer::Indexer;
3939
pub mod local_chain;
4040
mod tx_data_traits;
41-
pub mod tx_graph;
4241
pub use tx_data_traits::*;
42+
pub mod tx_graph;
4343
pub use tx_graph::TxGraph;
4444
mod chain_oracle;
4545
pub use chain_oracle::*;
@@ -61,7 +61,9 @@ pub use indexer::keychain_txout;
6161
pub use spk_iter::*;
6262
#[cfg(feature = "rusqlite")]
6363
pub mod rusqlite_impl;
64-
pub mod spk_client;
64+
65+
pub extern crate bdk_core;
66+
pub use bdk_core::*;
6567

6668
#[allow(unused_imports)]
6769
#[macro_use]
@@ -75,45 +77,9 @@ pub extern crate serde;
7577
#[macro_use]
7678
extern crate std;
7779

78-
#[cfg(all(not(feature = "std"), feature = "hashbrown"))]
79-
extern crate hashbrown;
80-
81-
// When no-std use `alloc`'s Hash collections. This is activated by default
82-
#[cfg(all(not(feature = "std"), not(feature = "hashbrown")))]
83-
#[doc(hidden)]
84-
pub mod collections {
85-
#![allow(dead_code)]
86-
pub type HashSet<K> = alloc::collections::BTreeSet<K>;
87-
pub type HashMap<K, V> = alloc::collections::BTreeMap<K, V>;
88-
pub use alloc::collections::{btree_map as hash_map, *};
89-
}
90-
91-
// When we have std, use `std`'s all collections
92-
#[cfg(all(feature = "std", not(feature = "hashbrown")))]
93-
#[doc(hidden)]
94-
pub mod collections {
95-
pub use std::collections::{hash_map, *};
96-
}
97-
98-
// With this special feature `hashbrown`, use `hashbrown`'s hash collections, and else from `alloc`.
99-
#[cfg(feature = "hashbrown")]
100-
#[doc(hidden)]
101-
pub mod collections {
102-
#![allow(dead_code)]
103-
pub type HashSet<K> = hashbrown::HashSet<K>;
104-
pub type HashMap<K, V> = hashbrown::HashMap<K, V>;
105-
pub use alloc::collections::*;
106-
pub use hashbrown::hash_map;
107-
}
108-
10980
/// How many confirmations are needed f or a coinbase output to be spent.
11081
pub const COINBASE_MATURITY: u32 = 100;
11182

112-
/// A tuple of keychain index and `T` representing the indexed value.
113-
pub type Indexed<T> = (u32, T);
114-
/// A tuple of keychain `K`, derivation index (`u32`) and a `T` associated with them.
115-
pub type KeychainIndexed<K, T> = ((K, u32), T);
116-
11783
/// A wrapper that we use to impl remote traits for types in our crate or dependency crates.
11884
pub struct Impl<T>(pub T);
11985

@@ -137,3 +103,27 @@ impl<T> core::ops::Deref for Impl<T> {
137103
&self.0
138104
}
139105
}
106+
107+
/// A wrapper that we use to impl remote traits for types in our crate or dependency crates that impl [`Anchor`].
108+
pub struct AnchorImpl<T>(pub T);
109+
110+
impl<T> AnchorImpl<T> {
111+
/// Returns the inner `T`.
112+
pub fn into_inner(self) -> T {
113+
self.0
114+
}
115+
}
116+
117+
impl<T> From<T> for AnchorImpl<T> {
118+
fn from(value: T) -> Self {
119+
Self(value)
120+
}
121+
}
122+
123+
impl<T> core::ops::Deref for AnchorImpl<T> {
124+
type Target = T;
125+
126+
fn deref(&self) -> &Self::Target {
127+
&self.0
128+
}
129+
}

0 commit comments

Comments
 (0)