Skip to content

Commit da2683b

Browse files
committed
Enable tests in Elements mode
Using the `elementsd` crate to spawn a regtest elements envirnoment.
1 parent 728b3a0 commit da2683b

File tree

5 files changed

+144
-43
lines changed

5 files changed

+144
-43
lines changed

Cargo.lock

Lines changed: 30 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ electrum-client = { version = "0.8", optional = true }
6262

6363
[dev-dependencies]
6464
bitcoind = { version = "0.20.0", features = [ "22_0" ] }
65+
elementsd = { version = "0.3.0", features = [ "0_21_0" ] }
6566
electrumd = { version = "0.1.0", features = [ "4_1_5" ] }
6667
ureq = { version = "2.4", default-features = false, features = [ "json" ] }
6768
tempfile = "3.0"
@@ -83,4 +84,9 @@ rev = "d988bd7ed9cf539b8fea0da042efa5a4e1eef86f"
8384
# not yet published on crates.io
8485
[patch.crates-io.electrumd]
8586
git = "https://github.com/shesek/electrumd"
86-
rev = "ea32146dc1db378d4444cd713a27a8ea3919c4c0"
87+
rev = "ea32146dc1db378d4444cd713a27a8ea3919c4c0"
88+
89+
# pending https://github.com/RCasatta/elementsd/pull/1
90+
[patch.crates-io.elementsd]
91+
git = "https://github.com/shesek/elementsd"
92+
rev = "86d9c3d480f72963c81671705ac84af89d4d1b4b"

tests/common.rs

Lines changed: 76 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@ use std::sync::{Arc, Once, RwLock};
22
use std::{env, net};
33

44
use stderrlog::StdErrLog;
5+
use tempfile::TempDir;
56

6-
use bitcoind::{
7-
bitcoincore_rpc::{self, RpcApi},
8-
BitcoinD,
9-
};
7+
use serde_json::{json, Value};
8+
9+
#[cfg(not(feature = "liquid"))]
10+
use bitcoind::{self as noded, BitcoinD as NodeD};
11+
#[cfg(feature = "liquid")]
12+
use elementsd::{self as noded, ElementsD as NodeD};
13+
14+
use noded::bitcoincore_rpc::{self, RpcApi};
1015

1116
use electrs::{
12-
chain::{self, Network},
17+
chain::{self, Address, BlockHash, Network, Txid},
1318
config::{self, Config},
1419
daemon::Daemon,
1520
electrum::RPC as ElectrumRPC,
@@ -18,28 +23,49 @@ use electrs::{
1823
rest,
1924
signal::Waiter,
2025
};
21-
use tempfile::TempDir;
2226

2327
pub fn init_tester() -> Result<TestRunner> {
2428
let log = init_log();
2529

26-
let mut bitcoind_conf = bitcoind::Conf::default();
27-
bitcoind_conf.view_stdout = true;
30+
// Setup the bitcoind/elementsd config
31+
let mut node_conf = noded::Conf::default();
32+
{
33+
#[cfg(not(feature = "liquid"))]
34+
let node_conf = &mut node_conf;
35+
#[cfg(feature = "liquid")]
36+
let node_conf = &mut node_conf.0;
37+
38+
#[cfg(feature = "liquid")]
39+
{
40+
node_conf.args.push("-anyonecanspendaremine=1");
41+
}
42+
43+
node_conf.view_stdout = true;
44+
}
45+
46+
// Setup node
47+
let node = NodeD::with_conf(noded::downloaded_exe_path().unwrap(), &node_conf).unwrap();
48+
49+
#[cfg(not(feature = "liquid"))]
50+
let (node_client, params) = (&node.client, &node.params);
51+
#[cfg(feature = "liquid")]
52+
let (node_client, params) = (node.client(), &node.params());
2853

29-
let bitcoind =
30-
BitcoinD::with_conf(bitcoind::downloaded_exe_path().unwrap(), &bitcoind_conf).unwrap();
54+
log::info!("node params: {:?}", params);
3155

32-
init_node(&bitcoind.client).chain_err(|| "failed initializing node")?;
56+
generate(node_client, 101).chain_err(|| "failed initializing blocks")?;
3357

34-
log::info!("bitcoind: {:?}", bitcoind.params);
58+
// Needed to claim the initialfreecoins are our own
59+
// See https://github.com/ElementsProject/elements/issues/956
60+
#[cfg(feature = "liquid")]
61+
node_client.call::<Value>("rescanblockchain", &[])?;
3562

3663
#[cfg(not(feature = "liquid"))]
3764
let network_type = Network::Regtest;
3865
#[cfg(feature = "liquid")]
3966
let network_type = Network::LiquidRegtest;
4067

41-
let daemon_subdir = bitcoind
42-
.params
68+
let daemon_subdir = params
4369
.datadir
4470
.join(config::get_network_subdir(network_type).unwrap());
4571

@@ -51,7 +77,7 @@ pub fn init_tester() -> Result<TestRunner> {
5177
db_path: electrsdb.path().to_path_buf(),
5278
daemon_dir: daemon_subdir.clone(),
5379
blocks_dir: daemon_subdir.join("blocks"),
54-
daemon_rpc_addr: bitcoind.params.rpc_socket.into(),
80+
daemon_rpc_addr: params.rpc_socket.into(),
5581
cookie: None,
5682
electrum_rpc_addr: rand_available_addr(),
5783
http_addr: rand_available_addr(),
@@ -95,13 +121,14 @@ pub fn init_tester() -> Result<TestRunner> {
95121

96122
let store = Arc::new(Store::open(&config.db_path.join("newindex"), &config));
97123

98-
let fetch_from = if !env::var("JSONRPC_IMPORT").is_ok() {
124+
let fetch_from = if !env::var("JSONRPC_IMPORT").is_ok() && !cfg!(feature = "liquid") {
99125
// run the initial indexing from the blk files then switch to using the jsonrpc,
100126
// similarly to how electrs is typically used.
101127
FetchFrom::BlkFiles
102128
} else {
103129
// when JSONRPC_IMPORT is set, use the jsonrpc for the initial indexing too.
104130
// this runs faster on small regtest chains and can be useful for quicker local development iteration.
131+
// this is also used on liquid regtest, which currently fails to parse the BlkFiles due to the magic bytes
105132
FetchFrom::Bitcoind
106133
};
107134

@@ -134,7 +161,7 @@ pub fn init_tester() -> Result<TestRunner> {
134161

135162
Ok(TestRunner {
136163
config,
137-
bitcoind,
164+
node,
138165
_electrsdb: electrsdb,
139166
indexer,
140167
query,
@@ -146,7 +173,8 @@ pub fn init_tester() -> Result<TestRunner> {
146173

147174
pub struct TestRunner {
148175
config: Arc<Config>,
149-
bitcoind: BitcoinD,
176+
/// bitcoind::BitcoinD or an elementsd::ElementsD in liquid mode
177+
node: NodeD,
150178
_electrsdb: TempDir, // rm'd when dropped
151179
indexer: Indexer,
152180
query: Arc<Query>,
@@ -156,8 +184,11 @@ pub struct TestRunner {
156184
}
157185

158186
impl TestRunner {
159-
pub fn bitcoind(&self) -> &bitcoincore_rpc::Client {
160-
&self.bitcoind.client
187+
pub fn node_client(&self) -> &bitcoincore_rpc::Client {
188+
#[cfg(not(feature = "liquid"))]
189+
return &self.node.client;
190+
#[cfg(feature = "liquid")]
191+
return &self.node.client();
161192
}
162193

163194
pub fn sync(&mut self) -> Result<()> {
@@ -169,18 +200,17 @@ impl TestRunner {
169200
Ok(())
170201
}
171202

172-
pub fn mine(&mut self) -> Result<chain::BlockHash> {
173-
let addr = self.bitcoind.client.get_new_address(None, None)?;
174-
let mut generated = self.bitcoind.client.generate_to_address(1, &addr)?;
203+
pub fn mine(&mut self) -> Result<BlockHash> {
204+
let mut generated = generate(self.node_client(), 1)?;
175205
self.sync()?;
176206
Ok(generated.remove(0))
177207
}
178208

179-
pub fn send(&mut self, addr: &chain::Address, amount: bitcoin::Amount) -> Result<chain::Txid> {
180-
let txid = self
181-
.bitcoind
182-
.client
183-
.send_to_address(addr, amount, None, None, None, None, None, None)?;
209+
pub fn send(&mut self, addr: &Address, amount: bitcoin::Amount) -> Result<Txid> {
210+
let txid = self.node_client().call(
211+
"sendtoaddress",
212+
&[addr.to_string().into(), json!(amount.as_btc())],
213+
)?;
184214
self.sync()?;
185215
Ok(txid)
186216
}
@@ -206,10 +236,15 @@ pub fn init_electrum_tester() -> Result<(ElectrumRPC, net::SocketAddr, TestRunne
206236
Ok((electrum_server, tester.config.electrum_rpc_addr, tester))
207237
}
208238

209-
fn init_node(client: &bitcoincore_rpc::Client) -> bitcoincore_rpc::Result<()> {
210-
let addr = client.get_new_address(None, None)?;
211-
client.generate_to_address(101, &addr)?;
212-
Ok(())
239+
fn generate(
240+
client: &bitcoincore_rpc::Client,
241+
num_blocks: u32,
242+
) -> bitcoincore_rpc::Result<Vec<BlockHash>> {
243+
let addr = client.call::<Address>("getnewaddress", &[])?;
244+
client.call(
245+
"generatetoaddress",
246+
&[num_blocks.into(), addr.to_string().into()],
247+
)
213248
}
214249

215250
fn init_log() -> StdErrLog {
@@ -256,6 +291,10 @@ error_chain::error_chain! {
256291
description("ureq error")
257292
display("ureq error: {:?}", e)
258293
}
294+
Json(e: serde_json::Error) {
295+
description("JSON error")
296+
display("JSON error: {:?}", e)
297+
}
259298
}
260299
}
261300

@@ -284,3 +323,8 @@ impl From<ureq::Error> for Error {
284323
Error::from(ErrorKind::Ureq(e))
285324
}
286325
}
326+
impl From<serde_json::Error> for Error {
327+
fn from(e: serde_json::Error) -> Self {
328+
Error::from(ErrorKind::Json(e))
329+
}
330+
}

tests/electrum.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use electrumd::ElectrumD;
77

88
use electrs::chain::Address;
99

10-
#[test]
10+
/// Test the Electrum RPC server using an headless Electrum wallet
11+
/// This only runs on Bitcoin (non-Liquid) mode.
12+
#[cfg_attr(not(feature = "liquid"), test)]
1113
fn test_electrum() -> Result<()> {
1214
// Spawn an Electrs Electrum RPC server
1315
let (electrum_server, electrum_addr, mut tester) = common::init_electrum_tester().unwrap();
@@ -100,14 +102,14 @@ fn test_electrum() -> Result<()> {
100102
// Send an outgoing payment
101103
electrum_wallet.call(
102104
"broadcast",
103-
&json!([ electrum_wallet.call(
105+
&json!([electrum_wallet.call(
104106
"payto",
105107
&json!({
106-
"destination": tester.bitcoind().get_new_address(None, None)?,
108+
"destination": tester.node_client().get_new_address(None, None)?,
107109
"amount": 0.16,
108110
"fee": 0.001,
109111
}),
110-
)? ]),
112+
)?]),
111113
)?;
112114
notify_wallet();
113115
assert_balance(0.3, -0.161);

0 commit comments

Comments
 (0)