]> Untitled Git - bdk/commitdiff
use bitcoind and electrsd crate to launch daemons
authorRiccardo Casatta <riccardo@casatta.it>
Thu, 17 Jun 2021 11:48:46 +0000 (13:48 +0200)
committerRiccardo Casatta <riccardo@casatta.it>
Tue, 29 Jun 2021 09:32:26 +0000 (11:32 +0200)
.github/workflows/cont_integration.yml
Cargo.toml
src/blockchain/electrum.rs
src/blockchain/esplora.rs
src/blockchain/rpc.rs
src/testutils/blockchain_tests.rs
src/testutils/mod.rs

index 71a49cab104711d2f85fed62e2b10b43a5567408..b2fee531e27623161e4169903ec38f97dc044521 100644 (file)
@@ -82,22 +82,13 @@ jobs:
       matrix:
         blockchain:
           - name: electrum
-            container: bitcoindevkit/electrs:0.4.0
-            start: /root/electrs --network regtest --cookie-file $GITHUB_WORKSPACE/.bitcoin/regtest/.cookie --jsonrpc-import
-          - name: esplora
-            container: bitcoindevkit/esplora:0.4.0
-            start: /root/electrs --network regtest -vvv --daemon-dir $GITHUB_WORKSPACE/.bitcoin --jsonrpc-import --electrum-rpc-addr=0.0.0.0:60401 --http-addr 0.0.0.0:3002
+            container: bitcoindevkit/electrs
           - name: rpc
-            container: bitcoindevkit/electrs:0.4.0
-            start: /root/electrs --network regtest --cookie-file $GITHUB_WORKSPACE/.bitcoin/regtest/.cookie --jsonrpc-import
+            container: bitcoindevkit/electrs
     container: ${{ matrix.blockchain.container }}
     env:
-      BDK_RPC_AUTH: COOKIEFILE
-      BDK_RPC_COOKIEFILE: ${{ github.workspace }}/.bitcoin/regtest/.cookie
-      BDK_RPC_URL: 127.0.0.1:18443
-      BDK_RPC_WALLET: bdk-test
-      BDK_ELECTRUM_URL: tcp://127.0.0.1:60401
-      BDK_ESPLORA_URL: http://127.0.0.1:3002
+      ELECTRS_EXE: /root/electrs
+      BITCOIND_EXE: /root/bitcoind
     steps:
       - name: Checkout
         uses: actions/checkout@v2
@@ -119,10 +110,6 @@ jobs:
         run: $HOME/.cargo/bin/rustup set profile minimal
       - name: Update toolchain
         run: $HOME/.cargo/bin/rustup update
-      - name: Start core
-        run: ./ci/start-core.sh
-      - name: start ${{ matrix.blockchain.name }}
-        run: nohup ${{ matrix.blockchain.start }} & sleep 5
       - name: Test
         run: $HOME/.cargo/bin/cargo test --features test-${{ matrix.blockchain.name }},test-blockchains --no-default-features ${{ matrix.blockchain.name }}::bdk_blockchain_tests
 
index df6d39f6da5f2232ba096875abc0dc6712368d0d..d30587bba1b703f1223d82646b35fdbc76e873d3 100644 (file)
@@ -72,6 +72,7 @@ env_logger = "0.7"
 clap = "2.33"
 serial_test = "0.4"
 bitcoind = "0.11.0"
+electrsd = "0.3.0"
 
 [[example]]
 name = "address_validator"
index 4d8926af8822d196eb94a00e319fc5b325d7b215..45deb3f7498713fa5ec4676b36cc49642b4f06a3 100644 (file)
@@ -169,9 +169,10 @@ impl ConfigurableBlockchain for ElectrumBlockchain {
     }
 }
 
+#[cfg(test)]
 #[cfg(feature = "test-blockchains")]
 crate::bdk_blockchain_tests! {
-    fn test_instance() -> ElectrumBlockchain {
-        ElectrumBlockchain::from(Client::new(&testutils::blockchain_tests::get_electrum_url()).unwrap())
+    fn test_instance(test_client: &TestClient) -> ElectrumBlockchain {
+        ElectrumBlockchain::from(Client::new(&test_client.electrsd.electrum_url).unwrap())
     }
 }
index ff85f22f67986fefb8768bb0b4c5d5f18609dce5..d866992d7d805e5c62082d984572f001a3ec47b7 100644 (file)
@@ -415,9 +415,10 @@ impl_error!(std::num::ParseIntError, Parsing, EsploraError);
 impl_error!(consensus::encode::Error, BitcoinEncoding, EsploraError);
 impl_error!(bitcoin::hashes::hex::Error, Hex, EsploraError);
 
+#[cfg(test)]
 #[cfg(feature = "test-blockchains")]
 crate::bdk_blockchain_tests! {
-    fn test_instance() -> EsploraBlockchain {
-        EsploraBlockchain::new(std::env::var("BDK_ESPLORA_URL").unwrap_or("127.0.0.1:3002".into()).as_str(), None)
+    fn test_instance(test_client: &TestClient) -> EsploraBlockchain {
+        EsploraBlockchain::new(test_client.electrsd.esplora_url.as_ref().unwrap(), None)
     }
 }
index fbd204cb3b09b82c5b3c6c83fd7c1c1d521ee6da..63664c68d5ea6b3e94d8e392b2a0b135edcb6f1a 100644 (file)
@@ -419,27 +419,14 @@ fn list_wallet_dir(client: &Client) -> Result<Vec<String>, Error> {
     Ok(result.wallets.into_iter().map(|n| n.name).collect())
 }
 
+#[cfg(test)]
 #[cfg(feature = "test-blockchains")]
 crate::bdk_blockchain_tests! {
 
-    fn test_instance() -> RpcBlockchain {
-        let url = std::env::var("BDK_RPC_URL").unwrap_or_else(|_| "127.0.0.1:18443".to_string());
-        let url = format!("http://{}", url);
-
-        // TODO same code in `fn get_auth` in testutils, make it public there
-        let auth = match std::env::var("BDK_RPC_AUTH").as_ref().map(String::as_ref) {
-            Ok("USER_PASS") => Auth::UserPass(
-                std::env::var("BDK_RPC_USER").unwrap(),
-                std::env::var("BDK_RPC_PASS").unwrap(),
-            ),
-            _ => Auth::CookieFile(std::path::PathBuf::from(
-                std::env::var("BDK_RPC_COOKIEFILE")
-                    .unwrap_or_else(|_| "/home/user/.bitcoin/regtest/.cookie".to_string()),
-            )),
-        };
+    fn test_instance(test_client: &TestClient) -> RpcBlockchain {
         let config = RpcConfig {
-            url,
-            auth,
+            url: test_client.bitcoind.rpc_url(),
+            auth: Auth::CookieFile(test_client.bitcoind.params.cookie_file.clone()),
             network: Network::Regtest,
             wallet_name: format!("client-wallet-test-{:?}", std::time::SystemTime::now() ),
             skip_blocks: None,
@@ -486,10 +473,8 @@ mod test {
     }
     fn create_bitcoind(args: Vec<&str>) -> BitcoinD {
         let exe = std::env::var("BITCOIND_EXE").unwrap();
-        let conf = Conf {
-            args,
-            ..Default::default()
-        };
+        let mut conf = Conf::default();
+        conf.args.extend(args);
         bitcoind::BitcoinD::with_conf(exe, &conf).unwrap()
     }
 
@@ -498,7 +483,7 @@ mod test {
 
     #[test]
     fn test_rpc_wallet_setup() {
-        env_logger::try_init().unwrap();
+        let _ = env_logger::try_init();
         let bitcoind = create_bitcoind(vec![]);
         let node_address = bitcoind.client.get_new_address(None, None).unwrap();
         let blockchain = create_rpc(&bitcoind, DESCRIPTOR_PUB, Network::Regtest).unwrap();
index 776d0f5e33949f6b487f59ab173cad538cdcbe78..713c0ef6fa221da2930fdb8edf2221fa7a8d3b93 100644 (file)
@@ -5,31 +5,37 @@ use bitcoin::hashes::sha256d;
 use bitcoin::{Address, Amount, Script, Transaction, Txid};
 pub use bitcoincore_rpc::bitcoincore_rpc_json::AddressType;
 pub use bitcoincore_rpc::{Auth, Client as RpcClient, RpcApi};
+use bitcoind::BitcoinD;
 use core::str::FromStr;
+use electrsd::ElectrsD;
 pub use electrum_client::{Client as ElectrumClient, ElectrumApi};
 #[allow(unused_imports)]
 use log::{debug, error, info, trace};
 use std::collections::HashMap;
 use std::env;
 use std::ops::Deref;
-use std::path::PathBuf;
 use std::time::Duration;
 
 pub struct TestClient {
-    client: RpcClient,
-    electrum: ElectrumClient,
+    pub bitcoind: BitcoinD,
+    pub electrsd: ElectrsD,
 }
 
 impl TestClient {
-    pub fn new(rpc_host_and_wallet: String, rpc_wallet_name: String) -> Self {
-        let client = RpcClient::new(
-            format!("http://{}/wallet/{}", rpc_host_and_wallet, rpc_wallet_name),
-            get_auth(),
-        )
-        .unwrap();
-        let electrum = ElectrumClient::new(&get_electrum_url()).unwrap();
+    pub fn new(bitcoind_exe: String, electrs_exe: String) -> Self {
+        debug!("launching {} and {}", &bitcoind_exe, &electrs_exe);
+        let bitcoind = BitcoinD::new(bitcoind_exe).unwrap();
+        let electrsd = ElectrsD::new(electrs_exe, &bitcoind, false, false).unwrap(); // TODO http_enabled should be true only for esplora
+
+        let node_address = bitcoind.client.get_new_address(None, None).unwrap();
+        bitcoind
+            .client
+            .generate_to_address(101, &node_address)
+            .unwrap();
 
-        TestClient { client, electrum }
+        let mut test_client = TestClient { bitcoind, electrsd };
+        TestClient::wait_for_block(&mut test_client, 101);
+        test_client
     }
 
     fn wait_for_tx(&mut self, txid: Txid, monitor_script: &Script) {
@@ -37,7 +43,8 @@ impl TestClient {
         exponential_backoff_poll(|| {
             trace!("wait_for_tx {}", txid);
 
-            self.electrum
+            self.electrsd
+                .client
                 .script_get_history(monitor_script)
                 .unwrap()
                 .iter()
@@ -46,12 +53,12 @@ impl TestClient {
     }
 
     fn wait_for_block(&mut self, min_height: usize) {
-        self.electrum.block_headers_subscribe().unwrap();
+        self.electrsd.client.block_headers_subscribe().unwrap();
 
         loop {
             let header = exponential_backoff_poll(|| {
-                self.electrum.ping().unwrap();
-                self.electrum.block_headers_pop().unwrap()
+                self.electrsd.client.ping().unwrap();
+                self.electrsd.client.block_headers_pop().unwrap()
             });
             if header.height >= min_height {
                 break;
@@ -96,10 +103,13 @@ impl TestClient {
             .unwrap();
 
         // broadcast through electrum so that it caches the tx immediately
+
         let txid = self
-            .electrum
+            .electrsd
+            .client
             .transaction_broadcast(&deserialize(&tx.hex).unwrap())
             .unwrap();
+        debug!("broadcasted to electrum {}", txid);
 
         if let Some(num) = meta_tx.min_confirmations {
             self.generate(num, None);
@@ -209,7 +219,7 @@ impl TestClient {
         let block_hex: String = serialize(&block).to_hex();
         debug!("generated block hex: {}", block_hex);
 
-        self.electrum.block_headers_subscribe().unwrap();
+        self.electrsd.client.block_headers_subscribe().unwrap();
 
         let submit_result: serde_json::Value =
             self.call("submitblock", &[block_hex.into()]).unwrap();
@@ -237,7 +247,7 @@ impl TestClient {
     }
 
     pub fn invalidate(&mut self, num_blocks: u64) {
-        self.electrum.block_headers_subscribe().unwrap();
+        self.electrsd.client.block_headers_subscribe().unwrap();
 
         let best_hash = self.get_best_block_hash().unwrap();
         let initial_height = self.get_block_info(&best_hash).unwrap().height;
@@ -288,16 +298,16 @@ impl Deref for TestClient {
     type Target = RpcClient;
 
     fn deref(&self) -> &Self::Target {
-        &self.client
+        &self.bitcoind.client
     }
 }
 
 impl Default for TestClient {
     fn default() -> Self {
-        let rpc_host_and_port =
-            env::var("BDK_RPC_URL").unwrap_or_else(|_| "127.0.0.1:18443".to_string());
-        let wallet = env::var("BDK_RPC_WALLET").unwrap_or_else(|_| "bdk-test".to_string());
-        Self::new(rpc_host_and_port, wallet)
+        let bitcoind_exe =
+            env::var("BITCOIND_EXE").unwrap_or_else(|_| "/root/bitcoind".to_string());
+        let electrs_exe = env::var("ELECTRS_EXE").unwrap_or_else(|_| "/root/electrs".to_string());
+        Self::new(bitcoind_exe, electrs_exe)
     }
 }
 
@@ -317,20 +327,6 @@ where
     }
 }
 
-// TODO: we currently only support env vars, we could also parse a toml file
-fn get_auth() -> Auth {
-    match env::var("BDK_RPC_AUTH").as_ref().map(String::as_ref) {
-        Ok("USER_PASS") => Auth::UserPass(
-            env::var("BDK_RPC_USER").unwrap(),
-            env::var("BDK_RPC_PASS").unwrap(),
-        ),
-        _ => Auth::CookieFile(PathBuf::from(
-            env::var("BDK_RPC_COOKIEFILE")
-                .unwrap_or_else(|_| "/home/user/.bitcoin/regtest/.cookie".to_string()),
-        )),
-    }
-}
-
 /// This macro runs blockchain tests against a `Blockchain` implementation. It requires access to a
 /// Bitcoin core wallet via RPC. At the moment you have to dig into the code yourself and look at
 /// the setup required to run the tests yourself.
@@ -590,7 +586,6 @@ macro_rules! bdk_blockchain_tests {
                 let tx = psbt.extract_tx();
                 println!("{}", bitcoin::consensus::encode::serialize_hex(&tx));
                 wallet.broadcast(tx).unwrap();
-
                 wallet.sync(noop_progress(), None).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), details.received, "incorrect balance after send");
 
index 5d7146bd036e50281a7725227e989848b571f3fd..3e4dfec276c6532e8ae67e6fe1e7070513f3f367 100644 (file)
@@ -10,6 +10,7 @@
 // licenses.
 #![allow(missing_docs)]
 
+#[cfg(test)]
 #[cfg(feature = "test-blockchains")]
 pub mod blockchain_tests;