Compare commits
13 Commits
v1.0.0-alp
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c256280eda | ||
|
|
c01983d02a | ||
|
|
fef70d5e8f | ||
|
|
c3544c9b8c | ||
|
|
b290b29502 | ||
|
|
d77a7f2ff1 | ||
|
|
3d44ffaef2 | ||
|
|
2efa299d04 | ||
|
|
2647aff4bc | ||
|
|
c151d8fd23 | ||
|
|
2c324d3759 | ||
|
|
5489f905a4 | ||
|
|
022d5a21cf |
2
.github/workflows/audit.yml
vendored
2
.github/workflows/audit.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
security_audit:
|
security_audit:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: actions-rs/audit-check@v1
|
- uses: actions-rs/audit-check@v1
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
2
.github/workflows/code_coverage.yml
vendored
2
.github/workflows/code_coverage.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: Install lcov tools
|
- name: Install lcov tools
|
||||||
run: sudo apt-get install lcov -y
|
run: sudo apt-get install lcov -y
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
|
|||||||
11
.github/workflows/cont_integration.yml
vendored
11
.github/workflows/cont_integration.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
- --all-features
|
- --all-features
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -32,7 +32,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cargo update -p zstd-sys --precise "2.0.8+zstd.1.5.5"
|
cargo update -p zstd-sys --precise "2.0.8+zstd.1.5.5"
|
||||||
cargo update -p time --precise "0.3.20"
|
cargo update -p time --precise "0.3.20"
|
||||||
cargo update -p jobserver --precise "0.1.26"
|
|
||||||
cargo update -p home --precise "0.5.5"
|
cargo update -p home --precise "0.5.5"
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cargo build ${{ matrix.features }}
|
run: cargo build ${{ matrix.features }}
|
||||||
@@ -44,7 +43,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -75,7 +74,7 @@ jobs:
|
|||||||
CFLAGS: -I/usr/include
|
CFLAGS: -I/usr/include
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
# Install a recent version of clang that supports wasm32
|
# Install a recent version of clang that supports wasm32
|
||||||
- run: wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - || exit 1
|
- run: wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - || exit 1
|
||||||
- run: sudo apt-get update || exit 1
|
- run: sudo apt-get update || exit 1
|
||||||
@@ -101,7 +100,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -115,7 +114,7 @@ jobs:
|
|||||||
clippy_check:
|
clippy_check:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v4
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|||||||
4
.github/workflows/nightly_docs.yml
vendored
4
.github/workflows/nightly_docs.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: Set default toolchain
|
- name: Set default toolchain
|
||||||
run: rustup default nightly-2022-12-14
|
run: rustup default nightly-2022-12-14
|
||||||
- name: Set profile
|
- name: Set profile
|
||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout `bitcoindevkit.org`
|
- name: Checkout `bitcoindevkit.org`
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ssh-key: ${{ secrets.DOCS_PUSH_SSH_KEY }}
|
ssh-key: ${{ secrets.DOCS_PUSH_SSH_KEY }}
|
||||||
repository: bitcoindevkit/bitcoindevkit.org
|
repository: bitcoindevkit/bitcoindevkit.org
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bdk"
|
name = "bdk"
|
||||||
homepage = "https://bitcoindevkit.org"
|
homepage = "https://bitcoindevkit.org"
|
||||||
version = "1.0.0-alpha.6"
|
version = "1.0.0-alpha.7"
|
||||||
repository = "https://github.com/bitcoindevkit/bdk"
|
repository = "https://github.com/bitcoindevkit/bdk"
|
||||||
documentation = "https://docs.rs/bdk"
|
documentation = "https://docs.rs/bdk"
|
||||||
description = "A modern, lightweight, descriptor-based wallet library"
|
description = "A modern, lightweight, descriptor-based wallet library"
|
||||||
@@ -18,7 +18,7 @@ miniscript = { version = "10.0.0", features = ["serde"], default-features = fals
|
|||||||
bitcoin = { version = "0.30.0", features = ["serde", "base64", "rand-std"], default-features = false }
|
bitcoin = { version = "0.30.0", features = ["serde", "base64", "rand-std"], default-features = false }
|
||||||
serde = { version = "^1.0", features = ["derive"] }
|
serde = { version = "^1.0", features = ["derive"] }
|
||||||
serde_json = { version = "^1.0" }
|
serde_json = { version = "^1.0" }
|
||||||
bdk_chain = { path = "../chain", version = "0.10.0", features = ["miniscript", "serde"], default-features = false }
|
bdk_chain = { path = "../chain", version = "0.11.0", features = ["miniscript", "serde"], default-features = false }
|
||||||
|
|
||||||
# Optional dependencies
|
# Optional dependencies
|
||||||
bip39 = { version = "2.0", optional = true }
|
bip39 = { version = "2.0", optional = true }
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ impl<'a, D, Cs: Clone, Ctx> Clone for TxBuilder<'a, D, Cs, Ctx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// methods supported by both contexts, for any CoinSelectionAlgorithm
|
// methods supported by both contexts, for any CoinSelectionAlgorithm
|
||||||
impl<'a, D, Cs: CoinSelectionAlgorithm, Ctx: TxBuilderContext> TxBuilder<'a, D, Cs, Ctx> {
|
impl<'a, D, Cs, Ctx> TxBuilder<'a, D, Cs, Ctx> {
|
||||||
/// Set a custom fee rate
|
/// Set a custom fee rate
|
||||||
/// The fee_rate method sets the mining fee paid by the transaction as a rate on its size.
|
/// The fee_rate method sets the mining fee paid by the transaction as a rate on its size.
|
||||||
/// This means that the total fee paid is equal to this rate * size of the transaction in virtual Bytes (vB) or Weight Unit (wu).
|
/// This means that the total fee paid is equal to this rate * size of the transaction in virtual Bytes (vB) or Weight Unit (wu).
|
||||||
@@ -574,20 +574,6 @@ impl<'a, D, Cs: CoinSelectionAlgorithm, Ctx: TxBuilderContext> TxBuilder<'a, D,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finish building the transaction.
|
|
||||||
///
|
|
||||||
/// Returns a new [`Psbt`] per [`BIP174`].
|
|
||||||
///
|
|
||||||
/// [`BIP174`]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
|
|
||||||
pub fn finish(self) -> Result<Psbt, CreateTxError<D::WriteError>>
|
|
||||||
where
|
|
||||||
D: PersistBackend<ChangeSet>,
|
|
||||||
{
|
|
||||||
self.wallet
|
|
||||||
.borrow_mut()
|
|
||||||
.create_tx(self.coin_selection, self.params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enable signaling RBF
|
/// Enable signaling RBF
|
||||||
///
|
///
|
||||||
/// This will use the default nSequence value of `0xFFFFFFFD`.
|
/// This will use the default nSequence value of `0xFFFFFFFD`.
|
||||||
@@ -634,6 +620,22 @@ impl<'a, D, Cs: CoinSelectionAlgorithm, Ctx: TxBuilderContext> TxBuilder<'a, D,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, D, Cs: CoinSelectionAlgorithm, Ctx> TxBuilder<'a, D, Cs, Ctx> {
|
||||||
|
/// Finish building the transaction.
|
||||||
|
///
|
||||||
|
/// Returns a new [`Psbt`] per [`BIP174`].
|
||||||
|
///
|
||||||
|
/// [`BIP174`]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
|
||||||
|
pub fn finish(self) -> Result<Psbt, CreateTxError<D::WriteError>>
|
||||||
|
where
|
||||||
|
D: PersistBackend<ChangeSet>,
|
||||||
|
{
|
||||||
|
self.wallet
|
||||||
|
.borrow_mut()
|
||||||
|
.create_tx(self.coin_selection, self.params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// Error returned from [`TxBuilder::add_utxo`] and [`TxBuilder::add_utxos`]
|
/// Error returned from [`TxBuilder::add_utxo`] and [`TxBuilder::add_utxos`]
|
||||||
pub enum AddUtxoError {
|
pub enum AddUtxoError {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bdk_bitcoind_rpc"
|
name = "bdk_bitcoind_rpc"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.63"
|
rust-version = "1.63"
|
||||||
homepage = "https://bitcoindevkit.org"
|
homepage = "https://bitcoindevkit.org"
|
||||||
@@ -16,7 +16,7 @@ readme = "README.md"
|
|||||||
# For no-std, remember to enable the bitcoin/no-std feature
|
# For no-std, remember to enable the bitcoin/no-std feature
|
||||||
bitcoin = { version = "0.30", default-features = false }
|
bitcoin = { version = "0.30", default-features = false }
|
||||||
bitcoincore-rpc = { version = "0.17" }
|
bitcoincore-rpc = { version = "0.17" }
|
||||||
bdk_chain = { path = "../chain", version = "0.10", default-features = false }
|
bdk_chain = { path = "../chain", version = "0.11", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bitcoind = { version = "0.33", features = ["25_0"] }
|
bitcoind = { version = "0.33", features = ["25_0"] }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bdk_chain"
|
name = "bdk_chain"
|
||||||
version = "0.10.0"
|
version = "0.11.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.63"
|
rust-version = "1.63"
|
||||||
homepage = "https://bitcoindevkit.org"
|
homepage = "https://bitcoindevkit.org"
|
||||||
@@ -18,7 +18,6 @@ bitcoin = { version = "0.30.0", default-features = false }
|
|||||||
serde_crate = { package = "serde", version = "1", optional = true, features = ["derive"] }
|
serde_crate = { package = "serde", version = "1", optional = true, features = ["derive"] }
|
||||||
|
|
||||||
# Use hashbrown as a feature flag to have HashSet and HashMap from it.
|
# Use hashbrown as a feature flag to have HashSet and HashMap from it.
|
||||||
# note versions > 0.9.1 breaks ours 1.57.0 MSRV.
|
|
||||||
hashbrown = { version = "0.9.1", optional = true, features = ["serde"] }
|
hashbrown = { version = "0.9.1", optional = true, features = ["serde"] }
|
||||||
miniscript = { version = "10.0.0", optional = true, default-features = false }
|
miniscript = { version = "10.0.0", optional = true, default-features = false }
|
||||||
|
|
||||||
|
|||||||
@@ -326,12 +326,17 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
self.lookahead
|
self.lookahead
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Store lookahead scripts until `target_index`.
|
/// Store lookahead scripts until `target_index` (inclusive).
|
||||||
///
|
///
|
||||||
/// This does not change the `lookahead` setting.
|
/// This does not change the global `lookahead` setting.
|
||||||
pub fn lookahead_to_target(&mut self, keychain: &K, target_index: u32) {
|
pub fn lookahead_to_target(&mut self, keychain: &K, target_index: u32) {
|
||||||
let next_index = self.next_store_index(keychain);
|
let (next_index, _) = self.next_index(keychain);
|
||||||
if let Some(temp_lookahead) = target_index.checked_sub(next_index).filter(|&v| v > 0) {
|
|
||||||
|
let temp_lookahead = (target_index + 1)
|
||||||
|
.checked_sub(next_index)
|
||||||
|
.filter(|&index| index > 0);
|
||||||
|
|
||||||
|
if let Some(temp_lookahead) = temp_lookahead {
|
||||||
self.replenish_lookahead(keychain, temp_lookahead);
|
self.replenish_lookahead(keychain, temp_lookahead);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -454,6 +454,21 @@ impl<A> TxGraph<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A: Clone + Ord> TxGraph<A> {
|
||||||
|
/// Transform the [`TxGraph`] to have [`Anchor`]s of another type.
|
||||||
|
///
|
||||||
|
/// This takes in a closure of signature `FnMut(A) -> A2` which is called for each [`Anchor`] to
|
||||||
|
/// transform it.
|
||||||
|
pub fn map_anchors<A2: Clone + Ord, F>(self, f: F) -> TxGraph<A2>
|
||||||
|
where
|
||||||
|
F: FnMut(A) -> A2,
|
||||||
|
{
|
||||||
|
let mut new_graph = TxGraph::<A2>::default();
|
||||||
|
new_graph.apply_changeset(self.initial_changeset().map_anchors(f));
|
||||||
|
new_graph
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<A: Clone + Ord> TxGraph<A> {
|
impl<A: Clone + Ord> TxGraph<A> {
|
||||||
/// Construct a new [`TxGraph`] from a list of transactions.
|
/// Construct a new [`TxGraph`] from a list of transactions.
|
||||||
pub fn new(txs: impl IntoIterator<Item = Transaction>) -> Self {
|
pub fn new(txs: impl IntoIterator<Item = Transaction>) -> Self {
|
||||||
@@ -1294,6 +1309,26 @@ impl<A: Ord> Append for ChangeSet<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A: Ord> ChangeSet<A> {
|
||||||
|
/// Transform the [`ChangeSet`] to have [`Anchor`]s of another type.
|
||||||
|
///
|
||||||
|
/// This takes in a closure of signature `FnMut(A) -> A2` which is called for each [`Anchor`] to
|
||||||
|
/// transform it.
|
||||||
|
pub fn map_anchors<A2: Ord, F>(self, mut f: F) -> ChangeSet<A2>
|
||||||
|
where
|
||||||
|
F: FnMut(A) -> A2,
|
||||||
|
{
|
||||||
|
ChangeSet {
|
||||||
|
txs: self.txs,
|
||||||
|
txouts: self.txouts,
|
||||||
|
anchors: BTreeSet::<(A2, Txid)>::from_iter(
|
||||||
|
self.anchors.into_iter().map(|(a, txid)| (f(a), txid)),
|
||||||
|
),
|
||||||
|
last_seen: self.last_seen,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<A> AsRef<TxGraph<A>> for TxGraph<A> {
|
impl<A> AsRef<TxGraph<A>> for TxGraph<A> {
|
||||||
fn as_ref(&self) -> &TxGraph<A> {
|
fn as_ref(&self) -> &TxGraph<A> {
|
||||||
self
|
self
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use rand::distributions::{Alphanumeric, DistString};
|
use rand::distributions::{Alphanumeric, DistString};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use bdk_chain::{tx_graph::TxGraph, BlockId, SpkTxOutIndex};
|
use bdk_chain::{tx_graph::TxGraph, Anchor, SpkTxOutIndex};
|
||||||
use bitcoin::{
|
use bitcoin::{
|
||||||
locktime::absolute::LockTime, secp256k1::Secp256k1, OutPoint, ScriptBuf, Sequence, Transaction,
|
locktime::absolute::LockTime, secp256k1::Secp256k1, OutPoint, ScriptBuf, Sequence, Transaction,
|
||||||
TxIn, TxOut, Txid, Witness,
|
TxIn, TxOut, Txid, Witness,
|
||||||
@@ -49,11 +49,11 @@ impl TxOutTemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn init_graph<'a>(
|
pub fn init_graph<'a, A: Anchor + Clone + 'a>(
|
||||||
tx_templates: impl IntoIterator<Item = &'a TxTemplate<'a, BlockId>>,
|
tx_templates: impl IntoIterator<Item = &'a TxTemplate<'a, A>>,
|
||||||
) -> (TxGraph<BlockId>, SpkTxOutIndex<u32>, HashMap<&'a str, Txid>) {
|
) -> (TxGraph<A>, SpkTxOutIndex<u32>, HashMap<&'a str, Txid>) {
|
||||||
let (descriptor, _) = Descriptor::parse_descriptor(&Secp256k1::signing_only(), "tr(tprv8ZgxMBicQKsPd3krDUsBAmtnRsK3rb8u5yi1zhQgMhF1tR8MW7xfE4rnrbbsrbPR52e7rKapu6ztw1jXveJSCGHEriUGZV7mCe88duLp5pj/86'/1'/0'/0/*)").unwrap();
|
let (descriptor, _) = Descriptor::parse_descriptor(&Secp256k1::signing_only(), "tr(tprv8ZgxMBicQKsPd3krDUsBAmtnRsK3rb8u5yi1zhQgMhF1tR8MW7xfE4rnrbbsrbPR52e7rKapu6ztw1jXveJSCGHEriUGZV7mCe88duLp5pj/86'/1'/0'/0/*)").unwrap();
|
||||||
let mut graph = TxGraph::<BlockId>::default();
|
let mut graph = TxGraph::<A>::default();
|
||||||
let mut spk_index = SpkTxOutIndex::default();
|
let mut spk_index = SpkTxOutIndex::default();
|
||||||
(0..10).for_each(|index| {
|
(0..10).for_each(|index| {
|
||||||
spk_index.insert_spk(
|
spk_index.insert_spk(
|
||||||
@@ -126,7 +126,7 @@ pub fn init_graph<'a>(
|
|||||||
spk_index.scan(&tx);
|
spk_index.scan(&tx);
|
||||||
let _ = graph.insert_tx(tx.clone());
|
let _ = graph.insert_tx(tx.clone());
|
||||||
for anchor in tx_tmp.anchors.iter() {
|
for anchor in tx_tmp.anchors.iter() {
|
||||||
let _ = graph.insert_anchor(tx.txid(), *anchor);
|
let _ = graph.insert_anchor(tx.txid(), anchor.clone());
|
||||||
}
|
}
|
||||||
if let Some(seen_at) = tx_tmp.last_seen {
|
if let Some(seen_at) = tx_tmp.last_seen {
|
||||||
let _ = graph.insert_seen_at(tx.txid(), seen_at);
|
let _ = graph.insert_seen_at(tx.txid(), seen_at);
|
||||||
|
|||||||
@@ -386,3 +386,103 @@ fn test_non_wildcard_derivations() {
|
|||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check that calling `lookahead_to_target` stores the expected spks.
|
||||||
|
#[test]
|
||||||
|
fn lookahead_to_target() {
|
||||||
|
#[derive(Default)]
|
||||||
|
struct TestCase {
|
||||||
|
/// Global lookahead value.
|
||||||
|
lookahead: u32,
|
||||||
|
/// Last revealed index for external keychain.
|
||||||
|
external_last_revealed: Option<u32>,
|
||||||
|
/// Last revealed index for internal keychain.
|
||||||
|
internal_last_revealed: Option<u32>,
|
||||||
|
/// Call `lookahead_to_target(External, u32)`.
|
||||||
|
external_target: Option<u32>,
|
||||||
|
/// Call `lookahead_to_target(Internal, u32)`.
|
||||||
|
internal_target: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let test_cases = &[
|
||||||
|
TestCase {
|
||||||
|
lookahead: 0,
|
||||||
|
external_target: Some(100),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TestCase {
|
||||||
|
lookahead: 10,
|
||||||
|
internal_target: Some(99),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TestCase {
|
||||||
|
lookahead: 100,
|
||||||
|
internal_target: Some(9),
|
||||||
|
external_target: Some(10),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TestCase {
|
||||||
|
lookahead: 12,
|
||||||
|
external_last_revealed: Some(2),
|
||||||
|
internal_last_revealed: Some(2),
|
||||||
|
internal_target: Some(15),
|
||||||
|
external_target: Some(13),
|
||||||
|
},
|
||||||
|
TestCase {
|
||||||
|
lookahead: 13,
|
||||||
|
external_last_revealed: Some(100),
|
||||||
|
internal_last_revealed: Some(21),
|
||||||
|
internal_target: Some(120),
|
||||||
|
external_target: Some(130),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for t in test_cases {
|
||||||
|
let (mut index, _, _) = init_txout_index(t.lookahead);
|
||||||
|
|
||||||
|
if let Some(last_revealed) = t.external_last_revealed {
|
||||||
|
let _ = index.reveal_to_target(&TestKeychain::External, last_revealed);
|
||||||
|
}
|
||||||
|
if let Some(last_revealed) = t.internal_last_revealed {
|
||||||
|
let _ = index.reveal_to_target(&TestKeychain::Internal, last_revealed);
|
||||||
|
}
|
||||||
|
|
||||||
|
let keychain_test_cases = [
|
||||||
|
(
|
||||||
|
TestKeychain::External,
|
||||||
|
t.external_last_revealed,
|
||||||
|
t.external_target,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
TestKeychain::Internal,
|
||||||
|
t.internal_last_revealed,
|
||||||
|
t.internal_target,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
for (keychain, last_revealed, target) in keychain_test_cases {
|
||||||
|
if let Some(target) = target {
|
||||||
|
let original_last_stored_index = match last_revealed {
|
||||||
|
Some(last_revealed) => Some(last_revealed + t.lookahead),
|
||||||
|
None => t.lookahead.checked_sub(1),
|
||||||
|
};
|
||||||
|
let exp_last_stored_index = match original_last_stored_index {
|
||||||
|
Some(original_last_stored_index) => {
|
||||||
|
Ord::max(target, original_last_stored_index)
|
||||||
|
}
|
||||||
|
None => target,
|
||||||
|
};
|
||||||
|
index.lookahead_to_target(&keychain, target);
|
||||||
|
let keys = index
|
||||||
|
.inner()
|
||||||
|
.all_spks()
|
||||||
|
.range((keychain.clone(), 0)..=(keychain.clone(), u32::MAX))
|
||||||
|
.map(|(k, _)| k.clone())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let exp_keys = core::iter::repeat(keychain)
|
||||||
|
.zip(0_u32..=exp_last_stored_index)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
assert_eq!(keys, exp_keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ use bdk_chain::{
|
|||||||
use bitcoin::{
|
use bitcoin::{
|
||||||
absolute, hashes::Hash, BlockHash, OutPoint, ScriptBuf, Transaction, TxIn, TxOut, Txid,
|
absolute, hashes::Hash, BlockHash, OutPoint, ScriptBuf, Transaction, TxIn, TxOut, Txid,
|
||||||
};
|
};
|
||||||
|
use common::*;
|
||||||
use core::iter;
|
use core::iter;
|
||||||
|
use rand::RngCore;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1178,3 +1180,86 @@ fn test_missing_blocks() {
|
|||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
/// The `map_anchors` allow a caller to pass a function to reconstruct the [`TxGraph`] with any [`Anchor`],
|
||||||
|
/// even though the function is non-deterministic.
|
||||||
|
fn call_map_anchors_with_non_deterministic_anchor() {
|
||||||
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Copy, PartialOrd, Ord, core::hash::Hash)]
|
||||||
|
/// A non-deterministic anchor
|
||||||
|
pub struct NonDeterministicAnchor {
|
||||||
|
pub anchor_block: BlockId,
|
||||||
|
pub non_deterministic_field: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
let template = [
|
||||||
|
TxTemplate {
|
||||||
|
tx_name: "tx1",
|
||||||
|
inputs: &[TxInTemplate::Bogus],
|
||||||
|
outputs: &[TxOutTemplate::new(10000, Some(1))],
|
||||||
|
anchors: &[block_id!(1, "A")],
|
||||||
|
last_seen: None,
|
||||||
|
},
|
||||||
|
TxTemplate {
|
||||||
|
tx_name: "tx2",
|
||||||
|
inputs: &[TxInTemplate::PrevTx("tx1", 0)],
|
||||||
|
outputs: &[TxOutTemplate::new(20000, Some(2))],
|
||||||
|
anchors: &[block_id!(2, "B")],
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TxTemplate {
|
||||||
|
tx_name: "tx3",
|
||||||
|
inputs: &[TxInTemplate::PrevTx("tx2", 0)],
|
||||||
|
outputs: &[TxOutTemplate::new(30000, Some(3))],
|
||||||
|
anchors: &[block_id!(3, "C"), block_id!(4, "D")],
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let (graph, _, _) = init_graph(&template);
|
||||||
|
let new_graph = graph.clone().map_anchors(|a| NonDeterministicAnchor {
|
||||||
|
anchor_block: a,
|
||||||
|
// A non-deterministic value
|
||||||
|
non_deterministic_field: rand::thread_rng().next_u32(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check all the details in new_graph reconstruct as well
|
||||||
|
|
||||||
|
let mut full_txs_vec: Vec<_> = graph.full_txs().collect();
|
||||||
|
full_txs_vec.sort();
|
||||||
|
let mut new_txs_vec: Vec<_> = new_graph.full_txs().collect();
|
||||||
|
new_txs_vec.sort();
|
||||||
|
let mut new_txs = new_txs_vec.iter();
|
||||||
|
|
||||||
|
for tx_node in full_txs_vec.iter() {
|
||||||
|
let new_txnode = new_txs.next().unwrap();
|
||||||
|
assert_eq!(new_txnode.txid, tx_node.txid);
|
||||||
|
assert_eq!(new_txnode.tx, tx_node.tx);
|
||||||
|
assert_eq!(
|
||||||
|
new_txnode.last_seen_unconfirmed,
|
||||||
|
tx_node.last_seen_unconfirmed
|
||||||
|
);
|
||||||
|
assert_eq!(new_txnode.anchors.len(), tx_node.anchors.len());
|
||||||
|
|
||||||
|
let mut new_anchors: Vec<_> = new_txnode.anchors.iter().map(|a| a.anchor_block).collect();
|
||||||
|
new_anchors.sort();
|
||||||
|
let mut old_anchors: Vec<_> = tx_node.anchors.iter().copied().collect();
|
||||||
|
old_anchors.sort();
|
||||||
|
assert_eq!(new_anchors, old_anchors);
|
||||||
|
}
|
||||||
|
assert!(new_txs.next().is_none());
|
||||||
|
|
||||||
|
let new_graph_anchors: Vec<_> = new_graph
|
||||||
|
.all_anchors()
|
||||||
|
.iter()
|
||||||
|
.map(|i| i.0.anchor_block)
|
||||||
|
.collect();
|
||||||
|
assert_eq!(
|
||||||
|
new_graph_anchors,
|
||||||
|
vec![
|
||||||
|
block_id!(1, "A"),
|
||||||
|
block_id!(2, "B"),
|
||||||
|
block_id!(3, "C"),
|
||||||
|
block_id!(4, "D"),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bdk_electrum"
|
name = "bdk_electrum"
|
||||||
version = "0.8.0"
|
version = "0.9.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
homepage = "https://bitcoindevkit.org"
|
homepage = "https://bitcoindevkit.org"
|
||||||
repository = "https://github.com/bitcoindevkit/bdk"
|
repository = "https://github.com/bitcoindevkit/bdk"
|
||||||
@@ -12,6 +12,6 @@ readme = "README.md"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bdk_chain = { path = "../chain", version = "0.10.0", default-features = false }
|
bdk_chain = { path = "../chain", version = "0.11.0", default-features = false }
|
||||||
electrum-client = { version = "0.18" }
|
electrum-client = { version = "0.18" }
|
||||||
#rustls = { version = "=0.21.1", optional = true, features = ["dangerous_configuration"] }
|
#rustls = { version = "=0.21.1", optional = true, features = ["dangerous_configuration"] }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bdk_esplora"
|
name = "bdk_esplora"
|
||||||
version = "0.8.0"
|
version = "0.9.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
homepage = "https://bitcoindevkit.org"
|
homepage = "https://bitcoindevkit.org"
|
||||||
repository = "https://github.com/bitcoindevkit/bdk"
|
repository = "https://github.com/bitcoindevkit/bdk"
|
||||||
@@ -12,7 +12,7 @@ readme = "README.md"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bdk_chain = { path = "../chain", version = "0.10.0", default-features = false }
|
bdk_chain = { path = "../chain", version = "0.11.0", default-features = false }
|
||||||
esplora-client = { version = "0.6.0", default-features = false }
|
esplora-client = { version = "0.6.0", default-features = false }
|
||||||
async-trait = { version = "0.1.66", optional = true }
|
async-trait = { version = "0.1.66", optional = true }
|
||||||
futures = { version = "0.3.26", optional = true }
|
futures = { version = "0.3.26", optional = true }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bdk_file_store"
|
name = "bdk_file_store"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
repository = "https://github.com/bitcoindevkit/bdk"
|
repository = "https://github.com/bitcoindevkit/bdk"
|
||||||
@@ -11,7 +11,7 @@ authors = ["Bitcoin Dev Kit Developers"]
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bdk_chain = { path = "../chain", version = "0.10.0", features = [ "serde", "miniscript" ] }
|
bdk_chain = { path = "../chain", version = "0.11.0", features = [ "serde", "miniscript" ] }
|
||||||
bincode = { version = "1" }
|
bincode = { version = "1" }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user