Skip to content

Commit b22f5e6

Browse files
committed
Make corepc-node optional in payjoin-test-utils
Add a bitcoind feature flag to gate corepc-node dependency and move bitcoind helpers behind #[cfg(feature = "bitcoind")]. Downstream crates opt in via features = ["bitcoind"].
1 parent 117ce51 commit b22f5e6

7 files changed

Lines changed: 89 additions & 75 deletions

File tree

payjoin-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,5 @@ url = { version = "2.5.4", features = ["serde"] }
5555

5656
[dev-dependencies]
5757
nix = { version = "0.30.1", features = ["aio", "process", "signal"] }
58-
payjoin-test-utils = { version = "0.0.1" }
58+
payjoin-test-utils = { version = "0.0.1", features = ["bitcoind"] }
5959
tempfile = "3.20.0"

payjoin-ffi/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ exclude = ["tests"]
99
default = []
1010
csharp = ["dep:uniffi-bindgen-cs"]
1111
dart = ["dep:uniffi-dart"]
12-
_test-utils = ["payjoin-test-utils", "tokio"]
12+
_test-utils = ["payjoin-test-utils", "payjoin-test-utils/bitcoind", "tokio"]
1313
_manual-tls = ["payjoin/_manual-tls"]
1414
wasm_js = ["getrandom/js"]
1515

payjoin-ffi/javascript/test-utils/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ tokio = { version = "1.47.1", features = ["full"] }
1414

1515
[dependencies.payjoin-test-utils]
1616
path = "../../../payjoin-test-utils"
17+
features = ["bitcoind"]
1718

1819
[build-dependencies]
1920
napi-build = "=2.2.4"

payjoin-test-utils/Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ repository = "https://github.com/payjoin/rust-payjoin"
88
rust-version = "1.85"
99
license = "MIT"
1010

11+
[features]
12+
default = []
13+
bitcoind = ["corepc-node"]
14+
1115
[dependencies]
1216
axum-server = { version = "0.8", features = ["tls-rustls-no-provider"] }
1317
bitcoin = { version = "0.32.7", features = ["base64"] }
14-
corepc-node = { version = "0.10.0", features = ["download", "29_0"] }
18+
corepc-node = { version = "0.10.0", features = ["download", "29_0"], optional = true }
1519
http = "1.3.1"
1620
ohttp = { package = "bitcoin-ohttp", version = "0.6.0" }
1721
once_cell = "1.21.3"

payjoin-test-utils/src/bitcoind.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
use bitcoin::Amount;
2+
use corepc_node::AddressType;
3+
use tracing::Level;
4+
5+
use crate::BoxError;
6+
7+
pub fn init_bitcoind() -> Result<corepc_node::Node, BoxError> {
8+
let bitcoind_exe = corepc_node::exe_path()?;
9+
let mut conf = corepc_node::Conf::default();
10+
conf.view_stdout = tracing::enabled!(target: "corepc", Level::TRACE);
11+
// conf.args.push("-txindex");
12+
let bitcoind = corepc_node::Node::with_conf(bitcoind_exe, &conf)?;
13+
Ok(bitcoind)
14+
}
15+
16+
pub fn init_bitcoind_sender_receiver(
17+
sender_address_type: Option<AddressType>,
18+
receiver_address_type: Option<AddressType>,
19+
) -> Result<(corepc_node::Node, corepc_node::Client, corepc_node::Client), BoxError> {
20+
let bitcoind = init_bitcoind()?;
21+
let mut wallets = create_and_fund_wallets(
22+
&bitcoind,
23+
vec![("receiver", receiver_address_type), ("sender", sender_address_type)],
24+
)?;
25+
let receiver = wallets.pop().expect("receiver to exist");
26+
let sender = wallets.pop().expect("sender to exist");
27+
28+
Ok((bitcoind, receiver, sender))
29+
}
30+
31+
fn create_and_fund_wallets<W: AsRef<str>>(
32+
bitcoind: &corepc_node::Node,
33+
wallets: Vec<(W, Option<AddressType>)>,
34+
) -> Result<Vec<corepc_node::Client>, BoxError> {
35+
let mut funded_wallets = vec![];
36+
let funding_wallet = bitcoind.create_wallet("funding_wallet")?;
37+
let funding_address = funding_wallet.new_address()?;
38+
// 100 blocks would work here, we add a extra block to cover fees between transfers
39+
bitcoind.client.generate_to_address(101 + wallets.len(), &funding_address)?;
40+
for (wallet_name, address_type) in wallets {
41+
let wallet = bitcoind.create_wallet(wallet_name)?;
42+
let address = wallet.get_new_address(None, address_type)?.into_model()?.0.assume_checked();
43+
funding_wallet.send_to_address(&address, Amount::from_btc(50.0)?)?;
44+
funded_wallets.push(wallet);
45+
}
46+
// Mine the block which funds the different wallets
47+
bitcoind.client.generate_to_address(1, &funding_address)?;
48+
49+
for wallet in funded_wallets.iter() {
50+
let balances = wallet.get_balances()?.into_model()?;
51+
assert_eq!(
52+
balances.mine.trusted,
53+
Amount::from_btc(50.0)?,
54+
"wallet doesn't have expected amount of bitcoin"
55+
);
56+
}
57+
58+
Ok(funded_wallets)
59+
}
60+
61+
pub fn init_bitcoind_multi_sender_single_reciever(
62+
number_of_senders: usize,
63+
) -> Result<(corepc_node::Node, Vec<corepc_node::Client>, corepc_node::Client), BoxError> {
64+
let bitcoind = init_bitcoind()?;
65+
let wallets_to_create =
66+
(0..number_of_senders + 1).map(|i| (format!("sender_{i}"), None)).collect::<Vec<_>>();
67+
let mut wallets = create_and_fund_wallets(&bitcoind, wallets_to_create)?;
68+
let receiver = wallets.pop().expect("receiver to exist");
69+
let senders = wallets;
70+
71+
Ok((bitcoind, senders, receiver))
72+
}

payjoin-test-utils/src/lib.rs

Lines changed: 8 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ use std::sync::Arc;
44
use std::time::Duration;
55

66
use axum_server::tls_rustls::RustlsConfig;
7-
use bitcoin::{Amount, Psbt};
8-
pub use corepc_node; // re-export for convenience
9-
use corepc_node::AddressType;
7+
use bitcoin::Psbt;
108
use http::StatusCode;
119
use ohttp::hpke::{Aead, Kdf, Kem};
1210
use ohttp::{KeyId, SymmetricSuite};
@@ -19,9 +17,15 @@ use rustls::pki_types::CertificateDer;
1917
use rustls::RootCertStore;
2018
use tempfile::tempdir;
2119
use tokio::task::JoinHandle;
22-
use tracing::Level;
2320
use tracing_subscriber::{EnvFilter, FmtSubscriber};
2421

22+
#[cfg(feature = "bitcoind")]
23+
mod bitcoind;
24+
#[cfg(feature = "bitcoind")]
25+
pub use bitcoind::*;
26+
#[cfg(feature = "bitcoind")]
27+
pub use corepc_node;
28+
2529
pub type BoxError = Box<dyn std::error::Error + 'static>;
2630
pub type BoxSendSyncError = Box<dyn std::error::Error + Send + Sync>;
2731

@@ -173,77 +177,10 @@ pub fn local_cert_key() -> rcgen::CertifiedKey<rcgen::KeyPair> {
173177
.expect("Failed to generate cert")
174178
}
175179

176-
pub fn init_bitcoind() -> Result<corepc_node::Node, BoxError> {
177-
let bitcoind_exe = corepc_node::exe_path()?;
178-
let mut conf = corepc_node::Conf::default();
179-
conf.view_stdout = tracing::enabled!(target: "corepc", Level::TRACE);
180-
// conf.args.push("-txindex");
181-
let bitcoind = corepc_node::Node::with_conf(bitcoind_exe, &conf)?;
182-
Ok(bitcoind)
183-
}
184-
185-
pub fn init_bitcoind_sender_receiver(
186-
sender_address_type: Option<AddressType>,
187-
receiver_address_type: Option<AddressType>,
188-
) -> Result<(corepc_node::Node, corepc_node::Client, corepc_node::Client), BoxError> {
189-
let bitcoind = init_bitcoind()?;
190-
let mut wallets = create_and_fund_wallets(
191-
&bitcoind,
192-
vec![("receiver", receiver_address_type), ("sender", sender_address_type)],
193-
)?;
194-
let receiver = wallets.pop().expect("receiver to exist");
195-
let sender = wallets.pop().expect("sender to exist");
196-
197-
Ok((bitcoind, receiver, sender))
198-
}
199-
200-
fn create_and_fund_wallets<W: AsRef<str>>(
201-
bitcoind: &corepc_node::Node,
202-
wallets: Vec<(W, Option<AddressType>)>,
203-
) -> Result<Vec<corepc_node::Client>, BoxError> {
204-
let mut funded_wallets = vec![];
205-
let funding_wallet = bitcoind.create_wallet("funding_wallet")?;
206-
let funding_address = funding_wallet.new_address()?;
207-
// 100 blocks would work here, we add a extra block to cover fees between transfers
208-
bitcoind.client.generate_to_address(101 + wallets.len(), &funding_address)?;
209-
for (wallet_name, address_type) in wallets {
210-
let wallet = bitcoind.create_wallet(wallet_name)?;
211-
let address = wallet.get_new_address(None, address_type)?.into_model()?.0.assume_checked();
212-
funding_wallet.send_to_address(&address, Amount::from_btc(50.0)?)?;
213-
funded_wallets.push(wallet);
214-
}
215-
// Mine the block which funds the different wallets
216-
bitcoind.client.generate_to_address(1, &funding_address)?;
217-
218-
for wallet in funded_wallets.iter() {
219-
let balances = wallet.get_balances()?.into_model()?;
220-
assert_eq!(
221-
balances.mine.trusted,
222-
Amount::from_btc(50.0)?,
223-
"wallet doesn't have expected amount of bitcoin"
224-
);
225-
}
226-
227-
Ok(funded_wallets)
228-
}
229-
230180
pub fn http_agent(cert_der: Vec<u8>) -> Result<Client, BoxSendSyncError> {
231181
Ok(http_agent_builder(cert_der).build()?)
232182
}
233183

234-
pub fn init_bitcoind_multi_sender_single_reciever(
235-
number_of_senders: usize,
236-
) -> Result<(corepc_node::Node, Vec<corepc_node::Client>, corepc_node::Client), BoxError> {
237-
let bitcoind = init_bitcoind()?;
238-
let wallets_to_create =
239-
(0..number_of_senders + 1).map(|i| (format!("sender_{i}"), None)).collect::<Vec<_>>();
240-
let mut wallets = create_and_fund_wallets(&bitcoind, wallets_to_create)?;
241-
let receiver = wallets.pop().expect("receiver to exist");
242-
let senders = wallets;
243-
244-
Ok((bitcoind, senders, receiver))
245-
}
246-
247184
fn http_agent_builder(cert_der: Vec<u8>) -> ClientBuilder {
248185
ClientBuilder::new().http1_only().use_rustls_tls().add_root_certificate(
249186
reqwest::tls::Certificate::from_der(cert_der.as_slice())

payjoin/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ web-time = "1.1.0"
6262

6363
[dev-dependencies]
6464
once_cell = "1.21.3"
65-
payjoin-test-utils = { version = "0.0.1" }
65+
payjoin-test-utils = { version = "0.0.1", features = ["bitcoind"] }
6666
tokio = { version = "1.47.1", features = ["full"] }
6767
tracing = "0.1.41"
6868

0 commit comments

Comments
 (0)