Skip to content

Commit 0c8fb64

Browse files
committed
Merge #162: separate out elementsd tests into separate crate; allow overriding the binaries
2d14ff7 fix minimal versions of serde (Andrew Poelstra) a39988d ci: pin deps for 1.41.1 (Andrew Poelstra) febf493 remove unused fuzztarget feature (Andrew Poelstra) e630d82 commit a bitcoind and elementsd binary to the repo (Andrew Poelstra) f3acee0 elementsd-tests: clean up (Andrew Poelstra) da9deae elementsd-tests: make bitcoind and elementsd paths configurable (Andrew Poelstra) f773496 elementsd-tests: consolidate setup code (Andrew Poelstra) 7bbf981 move elementsd tests to their own crate (Andrew Poelstra) Pull request description: I need this to test this crate within Nix. ACKs for top commit: sanket1729: ACK 2d14ff7. We can debug `tx-pegin` test later Tree-SHA512: 44e293d1d587cf2bc5e4185e3babe054b6462172c637f7b01ece02523f9c34cf48f0a286f312077676b4740e4629dc2df54ba38b80d56abb9468beff21e7c8d9
2 parents f9bafed + 2d14ff7 commit 0c8fb64

File tree

9 files changed

+242
-240
lines changed

9 files changed

+242
-240
lines changed

Cargo.toml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,13 @@ edition = "2018"
1111

1212
[features]
1313
default = [ "json-contract" ]
14-
integration = [ "elementsd" ]
1514

1615
json-contract = [ "serde_json" ]
1716
"serde" = [
1817
"bitcoin/serde",
1918
"secp256k1-zkp/use-serde",
2019
"actual-serde"
2120
]
22-
"fuzztarget" = []
2321

2422
[dependencies]
2523
bitcoin = "0.29.1"
@@ -34,19 +32,14 @@ bitcoin_hashes = "0.11.0"
3432
# Used for ContractHash::from_json_contract.
3533
serde_json = { version = "1.0", optional = true }
3634

37-
actual-serde = { package="serde", version = "1.0", features=["derive"], optional = true }
38-
39-
# This should be an optional dev-dependency (only needed for integration tests),
40-
# but dev-dependency cannot be optional, and without optionality older toolchain try to compile it and fails
41-
elementsd = {version = "0.6.0", features=["0_21_0","bitcoind_22_0"], optional = true }
35+
actual-serde = { package="serde", version = "1.0.103", features=["derive"], optional = true }
4236

4337
[dev-dependencies]
4438
rand = "0.8"
4539
rand_chacha = "0.3"
46-
serde_test = "1.0"
40+
serde_test = "1.0.19"
4741
serde_json = "1.0"
4842
serde_cbor = "0.8" # older than latest version to support 1.41.1
49-
ryu = "<1.0.5"
5043
bincode = "1.3"
5144
base64 = "0.13.0"
5245

@@ -58,3 +51,7 @@ name = "raw_blind"
5851

5952
[[example]]
6053
name = "tx"
54+
55+
[workspace]
56+
members = ["elementsd-tests"]
57+
exclude = ["fuzz"]

contrib/test.sh

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ then
88
alias cargo="cargo +$TOOLCHAIN"
99
fi
1010

11+
# Pin dependencies as required if we are using MSRV toolchain.
12+
if cargo --version | grep "1\.41"; then
13+
# can be removed with elementsd 0.8.0
14+
cargo update -p zip --precise 0.5.6
15+
# 1.0.157 uses syn 2.0 which requires edition 2018
16+
cargo update -p serde --precise 1.0.156
17+
# 1.0.108 uses `matches!` macro so does not work with Rust 1.41.1, bad `syn` no biscuit.
18+
cargo update -p syn --precise 1.0.107
19+
fi
20+
1121
# Test without any features first
1222
cargo test --verbose --no-default-features
1323
# Then test with the default features
@@ -38,6 +48,8 @@ fi
3848
if [ "$DO_INTEGRATION" = true ]
3949
then
4050
(
41-
cargo test --features integration
51+
cd elementsd-tests
52+
cargo test
53+
cd ..
4254
)
4355
fi

elementsd-tests/Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "elementsd-tests"
3+
version = "0.1.0"
4+
authors = ["Andrew Poelstra <apoelstra@wpsoftware.net>"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
base64 = "0.13.0"
11+
elements = {path = "../"}
12+
elementsd = "0.6.0"
13+
rand = "0.8"
14+

elementsd-tests/bin/bitcoind

14.6 MB
Binary file not shown.

elementsd-tests/bin/elementsd

14.8 MB
Binary file not shown.

elementsd-tests/src/lib.rs

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
2+
#[cfg(test)]
3+
mod pset;
4+
#[cfg(test)]
5+
mod taproot;
6+
7+
use elementsd::bitcoincore_rpc::RpcApi;
8+
use elementsd::bitcoincore_rpc::jsonrpc::serde_json::{json, Value};
9+
#[cfg(test)]
10+
use elementsd::bitcoind::{self, BitcoinD};
11+
use elementsd::ElementsD;
12+
use std::str::FromStr;
13+
14+
trait Call {
15+
fn call(&self, cmd: &str, args: &[Value]) -> Value;
16+
fn decode_psbt(&self, psbt: &str) -> Option<Value>;
17+
fn get_new_address(&self) -> String;
18+
fn get_pegin_address(&self) -> (String, String);
19+
fn wallet_create_funded_psbt(&self, address: &str) -> String;
20+
fn expected_next(&self, psbt: &str) -> String;
21+
fn wallet_process_psbt(&self, psbt: &str) -> String;
22+
fn finalize_psbt(&self, psbt: &str) -> String;
23+
fn test_mempool_accept(&self, hex: &str) -> bool;
24+
fn get_first_prevout(&self) -> elements::OutPoint;
25+
fn generate(&self, blocks: u32);
26+
fn get_balances(&self) -> Value;
27+
28+
fn send_to_address(&self, addr: &str, amt: &str) -> String;
29+
fn get_transaction(&self, txid: &str) -> String;
30+
fn get_block_hash(&self, id: u32) -> String;
31+
fn send_raw_transaction(&self, hex: &str) -> String;
32+
}
33+
34+
impl Call for ElementsD {
35+
fn call(&self, cmd: &str, args: &[Value]) -> Value {
36+
self.client().call::<Value>(cmd, args).unwrap()
37+
}
38+
39+
fn decode_psbt(&self, psbt: &str) -> Option<Value> {
40+
self.client()
41+
.call::<Value>("decodepsbt", &[psbt.into()])
42+
.ok()
43+
}
44+
45+
fn get_new_address(&self) -> String {
46+
self.call("getnewaddress", &[])
47+
.as_str()
48+
.unwrap()
49+
.to_string()
50+
}
51+
52+
fn get_pegin_address(&self) -> (String, String) {
53+
let value = self.call("getpeginaddress", &[]);
54+
let mainchain_address = value.get("mainchain_address").unwrap();
55+
let mainchain_address = mainchain_address.as_str().unwrap().to_string();
56+
let claim_script = value.get("claim_script").unwrap();
57+
let claim_script = claim_script.as_str().unwrap().to_string();
58+
(mainchain_address, claim_script)
59+
}
60+
61+
fn wallet_create_funded_psbt(&self, address: &str) -> String {
62+
let value = self.call(
63+
"walletcreatefundedpsbt",
64+
&[json!([]), json!([{address.to_string(): "1"}])],
65+
);
66+
value.get("psbt").unwrap().as_str().unwrap().to_string()
67+
}
68+
69+
fn expected_next(&self, base64: &str) -> String {
70+
let value = self.call("analyzepsbt", &[base64.into()]);
71+
value.get("next").unwrap().as_str().unwrap().to_string()
72+
}
73+
74+
fn wallet_process_psbt(&self, base64: &str) -> String {
75+
let value = self.call("walletprocesspsbt", &[base64.into()]);
76+
value.get("psbt").unwrap().as_str().unwrap().to_string()
77+
}
78+
79+
fn finalize_psbt(&self, base64: &str) -> String {
80+
let value = self.call("finalizepsbt", &[base64.into()]);
81+
value.get("hex").unwrap().as_str().unwrap().to_string()
82+
}
83+
84+
fn test_mempool_accept(&self, hex: &str) -> bool {
85+
let result = self.call("testmempoolaccept", &[json!([hex])]);
86+
let allowed = result.get(0).unwrap().get("allowed");
87+
allowed.unwrap().as_bool().unwrap()
88+
}
89+
90+
fn get_first_prevout(&self) -> elements::OutPoint {
91+
let value = self.call("listunspent", &[]);
92+
let first = value.get(0).unwrap();
93+
let txid = first.get("txid").unwrap().as_str().unwrap();
94+
let vout = first.get("vout").unwrap().as_u64().unwrap();
95+
96+
elements::OutPoint::new(elements::Txid::from_str(txid).unwrap(), vout as u32)
97+
}
98+
99+
fn generate(&self, blocks: u32) {
100+
let address = self.get_new_address();
101+
let _value = self.call("generatetoaddress", &[blocks.into(), address.into()]);
102+
}
103+
104+
fn get_balances(&self) -> Value {
105+
self.call("getbalances", &[])
106+
}
107+
108+
fn get_transaction(&self, txid: &str) -> String {
109+
self.call("gettransaction", &[txid.into()])["hex"]
110+
.as_str()
111+
.unwrap()
112+
.to_string()
113+
}
114+
115+
fn send_to_address(&self, addr: &str, amt: &str) -> String {
116+
self.call("sendtoaddress", &[addr.into(), amt.into()])
117+
.as_str()
118+
.unwrap()
119+
.to_string()
120+
}
121+
122+
fn send_raw_transaction(&self, tx: &str) -> String {
123+
self.call("sendrawtransaction", &[tx.into()])
124+
.as_str()
125+
.unwrap()
126+
.to_string()
127+
}
128+
129+
fn get_block_hash(&self, id: u32) -> String {
130+
self.call("getblockhash", &[id.into()])
131+
.as_str()
132+
.unwrap()
133+
.to_string()
134+
}
135+
136+
}
137+
138+
#[cfg(test)]
139+
fn setup(validate_pegin: bool) -> (ElementsD, Option<BitcoinD>) {
140+
// Create env var BITCOIND_EXE_PATH to point to the ../bitcoind/bin/bitcoind binary
141+
let key = "BITCOIND_EXE";
142+
if std::env::var(key).is_err() {
143+
let mut root_path = std::env::current_dir().unwrap();
144+
while std::fs::metadata(root_path.join("LICENSE")).is_err() {
145+
if !root_path.pop() {
146+
panic!("Could not find LICENSE file; do not know where repo root is.");
147+
}
148+
}
149+
150+
let bitcoind_path = root_path
151+
.join("elementsd-tests")
152+
.join("bin")
153+
.join("bitcoind");
154+
std::env::set_var(key, bitcoind_path);
155+
}
156+
157+
// Create env var BITCOIND_EXE_PATH to point to the ../bitcoind/bin/bitcoind binary
158+
let key = "ELEMENTSD_EXE";
159+
if std::env::var(key).is_err() {
160+
let mut root_path = std::env::current_dir().unwrap();
161+
while std::fs::metadata(root_path.join("LICENSE")).is_err() {
162+
if !root_path.pop() {
163+
panic!("Could not find LICENSE file; do not know where repo root is.");
164+
}
165+
}
166+
167+
let bitcoind_path = root_path
168+
.join("elementsd-tests")
169+
.join("bin")
170+
.join("elementsd");
171+
std::env::set_var(key, bitcoind_path);
172+
}
173+
174+
let mut bitcoind = None;
175+
if validate_pegin {
176+
let bitcoind_exe = bitcoind::exe_path().unwrap();
177+
let bitcoind_conf = bitcoind::Conf::default();
178+
bitcoind = Some(bitcoind::BitcoinD::with_conf(&bitcoind_exe, &bitcoind_conf).unwrap());
179+
}
180+
181+
let conf = elementsd::Conf::new(bitcoind.as_ref());
182+
183+
let elementsd = ElementsD::with_conf(elementsd::exe_path().unwrap(), &conf).unwrap();
184+
185+
let create = elementsd.call("createwallet", &["wallet".into()]);
186+
assert_eq!(create.get("name").unwrap(), "wallet");
187+
188+
let rescan = elementsd.call("rescanblockchain", &[]);
189+
assert_eq!(rescan.get("stop_height").unwrap(), 0);
190+
191+
let balances = elementsd.call("getbalances", &[]);
192+
let mine = balances.get("mine").unwrap();
193+
let trusted = mine.get("trusted").unwrap();
194+
assert_eq!(trusted.get("bitcoin").unwrap(), 21.0);
195+
196+
(elementsd, bitcoind)
197+
}

0 commit comments

Comments
 (0)