Skip to content

Commit a11cd3c

Browse files
committed
adding a point in time test with electrsd/esplora
1 parent 097c7a9 commit a11cd3c

File tree

3 files changed

+98
-4
lines changed

3 files changed

+98
-4
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ esplora-client = { version = "0.4", default-features = false, optional = true }
1616
log = "^0.4"
1717

1818
[features]
19-
use-esplora-blocking = ["esplora-client/blocking"]
19+
use-esplora-blocking = ["esplora-client/blocking", "bdk/use-esplora-blocking"]
2020

2121
[dev-dependencies]
2222
rstest = "^0.11"
2323
bdk-testutils = "^0.4"
2424
bdk = { version = "0.28", default-features = true }
25-
electrsd = { version = "0.23", features = ["bitcoind_22_0", "electrs_0_9_1"] }
25+
electrsd = { version = "0.23.1", features = ["bitcoind_23_0", "esplora_a33e97e1", "legacy"] }

tests/point_in_time.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#[cfg(feature = "use-esplora-blocking")]
2+
mod regtestenv;
3+
#[cfg(feature = "use-esplora-blocking")]
4+
use bdk::bitcoin::Network;
5+
#[cfg(feature = "use-esplora-blocking")]
6+
use bdk::blockchain::esplora::EsploraBlockchain;
7+
#[cfg(feature = "use-esplora-blocking")]
8+
use bdk::blockchain::{Blockchain, GetHeight};
9+
#[cfg(feature = "use-esplora-blocking")]
10+
use bdk::database::memory::MemoryDatabase;
11+
#[cfg(feature = "use-esplora-blocking")]
12+
use bdk::wallet::{SyncOptions, Wallet};
13+
#[cfg(feature = "use-esplora-blocking")]
14+
use bdk::Error;
15+
#[cfg(feature = "use-esplora-blocking")]
16+
use bdk::SignOptions;
17+
#[cfg(feature = "use-esplora-blocking")]
18+
use bdk_reserves::reserves::*;
19+
#[cfg(feature = "use-esplora-blocking")]
20+
use electrsd::bitcoind::bitcoincore_rpc::bitcoin::Address;
21+
#[cfg(feature = "use-esplora-blocking")]
22+
use esplora_client::Builder;
23+
#[cfg(feature = "use-esplora-blocking")]
24+
use regtestenv::RegTestEnv;
25+
#[cfg(feature = "use-esplora-blocking")]
26+
use std::str::FromStr;
27+
28+
fn construct_wallet(desc: &str, network: Network) -> Result<Wallet<MemoryDatabase>, Error> {
29+
let wallet = Wallet::new(desc, None, network, MemoryDatabase::default())?;
30+
31+
Ok(wallet)
32+
}
33+
34+
#[test]
35+
#[cfg(feature = "use-esplora-blocking")]
36+
fn point_in_time() {
37+
let wallet = construct_wallet(
38+
"wpkh(cTTgG6x13nQjAeECaCaDrjrUdcjReZBGspcmNavsnSRyXq7zXT7r)",
39+
Network::Regtest,
40+
)
41+
.unwrap();
42+
43+
let regtestenv = RegTestEnv::new();
44+
regtestenv.generate(&[&wallet]);
45+
let esplora_url = format!("http://{}", regtestenv.esplora_url().as_ref().unwrap());
46+
let client = Builder::new(&esplora_url).build_blocking().unwrap();
47+
let blockchain = EsploraBlockchain::from_client(client, 20);
48+
wallet.sync(&blockchain, SyncOptions::default()).unwrap();
49+
let old_height = blockchain.get_height().unwrap();
50+
let old_balance = wallet.get_balance().unwrap();
51+
52+
let message = "This belonged to me.";
53+
let mut psbt = wallet.create_proof(message).unwrap();
54+
let signopts = SignOptions {
55+
trust_witness_utxo: true,
56+
..Default::default()
57+
};
58+
let finalized = wallet.sign(&mut psbt, signopts.clone()).unwrap();
59+
let proof = psbt;
60+
assert!(finalized);
61+
62+
let spendable = proof
63+
.verify_reserve_proof(message, WalletAtHeight::new(&wallet, old_height))
64+
.unwrap();
65+
assert_eq!(spendable, old_balance.confirmed);
66+
67+
const MY_FOREIGN_ADDR: &str = "mpSFfNURcFTz2yJxBzRY9NhnozxeJ2AUC8";
68+
let foreign_addr = Address::from_str(MY_FOREIGN_ADDR).unwrap();
69+
let mut builder = wallet.build_tx();
70+
builder
71+
.add_recipient(foreign_addr.script_pubkey(), 1_000)
72+
.fee_rate(bdk::FeeRate::from_sat_per_vb(2.0));
73+
let (mut psbt, _) = builder.finish().unwrap();
74+
let finalized = wallet.sign(&mut psbt, signopts).unwrap();
75+
assert!(finalized);
76+
blockchain.broadcast(&psbt.extract_tx()).unwrap();
77+
regtestenv.generate_to_address(6, &foreign_addr);
78+
wallet.sync(&blockchain, SyncOptions::default()).unwrap();
79+
80+
let new_balance = wallet.get_balance().unwrap();
81+
assert_ne!(old_balance, new_balance);
82+
83+
let spendable = proof
84+
.verify_reserve_proof(message, WalletAtHeight::new(&wallet, old_height))
85+
.unwrap();
86+
assert_eq!(spendable, old_balance.confirmed);
87+
}

tests/regtestenv.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,26 @@ impl RegTestEnv {
3030

3131
let mut elect_conf = electrsd::Conf::default();
3232
elect_conf.view_stderr = false; // setting this to true will lead to very verbose logging
33+
elect_conf.http_enabled = true;
3334
let elect_exe =
3435
electrsd::downloaded_exe_path().expect("We should always have downloaded path");
3536
let electrsd = ElectrsD::with_conf(elect_exe, &bitcoind, &elect_conf).unwrap();
3637

3738
RegTestEnv { bitcoind, electrsd }
3839
}
3940

40-
/// returns the URL where a client can connect to the embedded electrum server
41+
/// returns the URL where an electrum client can connect to the embedded electrum server
4142
pub fn electrum_url(&self) -> &str {
4243
&self.electrsd.electrum_url
4344
}
4445

46+
/// returns the URL where an esplora client can connect to the embedded esplora server
47+
pub fn esplora_url(&self) -> &Option<String> {
48+
&self.electrsd.esplora_url
49+
}
50+
4551
/// generates some blocks to have some coins to test with
52+
/// @wallets: either a single wallet, or all the signer wallets that belong to the same multisig.
4653
pub fn generate(&self, wallets: &[&Wallet<MemoryDatabase>]) {
4754
let addr2 = wallets[0].get_address(AddressIndex::Peek(1)).unwrap();
4855
let addr1 = wallets[0].get_address(AddressIndex::Peek(0)).unwrap();
@@ -89,7 +96,7 @@ impl RegTestEnv {
8996
.for_each(|wallet| wallet.sync(&blockchain, SyncOptions::default()).unwrap());
9097
}
9198

92-
fn generate_to_address(&self, blocks: usize, address: &Address) {
99+
pub fn generate_to_address(&self, blocks: usize, address: &Address) {
93100
let old_height = self
94101
.electrsd
95102
.client

0 commit comments

Comments
 (0)