]> Untitled Git - bdk/commitdiff
test(esplora): add async_ext and blocking_ext integration tests
authorSteve Myers <steve@notmandatory.org>
Mon, 4 Sep 2023 05:20:45 +0000 (00:20 -0500)
committerSteve Myers <steve@notmandatory.org>
Tue, 26 Sep 2023 02:09:40 +0000 (21:09 -0500)
crates/esplora/Cargo.toml
crates/esplora/src/async_ext.rs
crates/esplora/tests/async_ext.rs [new file with mode: 0644]
crates/esplora/tests/blocking_ext.rs [new file with mode: 0644]

index 33c60104ae0a4299ad1ae1d45ec3f64bcfac2869..49af68a991b28c55d803c86bab38400ee4885286 100644 (file)
@@ -21,6 +21,10 @@ futures = { version = "0.3.26", optional = true }
 bitcoin = { version = "0.30.0", optional = true, default-features = false }
 miniscript = { version = "10.0.0", optional = true, default-features = false }
 
+[dev-dependencies]
+electrsd = { version= "0.25.0", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] }
+tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
+
 [features]
 default = ["std", "async-https", "blocking"]
 std = ["bdk_chain/std"]
index a0c3d9d3bbf3ccd6e40d58258eeb2e70a8292893..98c47253fafc72f896091be1a283c4d4afccdd09 100644 (file)
@@ -21,8 +21,8 @@ use crate::{anchor_from_status, ASSUME_FINAL_DEPTH};
 pub trait EsploraAsyncExt {
     /// Prepare an [`LocalChain`] update with blocks fetched from Esplora.
     ///
-    /// * `prev_tip` is the previous tip of [`LocalChain::tip`].
-    /// * `get_heights` is the block heights that we are interested in fetching from Esplora.
+    /// * `local_tip` is the previous tip of [`LocalChain::tip`].
+    /// * `request_heights` is the block heights that we are interested in fetching from Esplora.
     ///
     /// The result of this method can be applied to [`LocalChain::apply_update`].
     ///
diff --git a/crates/esplora/tests/async_ext.rs b/crates/esplora/tests/async_ext.rs
new file mode 100644 (file)
index 0000000..3b64d7b
--- /dev/null
@@ -0,0 +1,117 @@
+use bdk_esplora::EsploraAsyncExt;
+use electrsd::bitcoind::bitcoincore_rpc::RpcApi;
+use electrsd::bitcoind::{self, anyhow, BitcoinD};
+use electrsd::{Conf, ElectrsD};
+use esplora_client::{self, AsyncClient, Builder};
+use std::str::FromStr;
+use std::thread::sleep;
+use std::time::Duration;
+
+use bdk_chain::bitcoin::{Address, Amount, BlockHash, Txid};
+
+struct TestEnv {
+    bitcoind: BitcoinD,
+    #[allow(dead_code)]
+    electrsd: ElectrsD,
+    client: AsyncClient,
+}
+
+impl TestEnv {
+    fn new() -> Result<Self, anyhow::Error> {
+        let bitcoind_exe =
+            bitcoind::downloaded_exe_path().expect("bitcoind version feature must be enabled");
+        let bitcoind = BitcoinD::new(bitcoind_exe).unwrap();
+
+        let mut electrs_conf = Conf::default();
+        electrs_conf.http_enabled = true;
+        let electrs_exe =
+            electrsd::downloaded_exe_path().expect("electrs version feature must be enabled");
+        let electrsd = ElectrsD::with_conf(electrs_exe, &bitcoind, &electrs_conf)?;
+
+        let base_url = format!("http://{}", &electrsd.esplora_url.clone().unwrap());
+        let client = Builder::new(base_url.as_str()).build_async()?;
+
+        Ok(Self {
+            bitcoind,
+            electrsd,
+            client,
+        })
+    }
+
+    fn mine_blocks(
+        &self,
+        count: usize,
+        address: Option<Address>,
+    ) -> anyhow::Result<Vec<BlockHash>> {
+        let coinbase_address = match address {
+            Some(address) => address,
+            None => self
+                .bitcoind
+                .client
+                .get_new_address(None, None)?
+                .assume_checked(),
+        };
+        let block_hashes = self
+            .bitcoind
+            .client
+            .generate_to_address(count as _, &coinbase_address)?;
+        Ok(block_hashes)
+    }
+}
+
+#[tokio::test]
+pub async fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> {
+    let env = TestEnv::new()?;
+    let receive_address0 =
+        Address::from_str("bcrt1qc6fweuf4xjvz4x3gx3t9e0fh4hvqyu2qw4wvxm")?.assume_checked();
+    let receive_address1 =
+        Address::from_str("bcrt1qfjg5lv3dvc9az8patec8fjddrs4aqtauadnagr")?.assume_checked();
+
+    let misc_spks = [
+        receive_address0.script_pubkey(),
+        receive_address1.script_pubkey(),
+    ];
+
+    let _block_hashes = env.mine_blocks(101, None)?;
+    let txid1 = env.bitcoind.client.send_to_address(
+        &receive_address1,
+        Amount::from_sat(10000),
+        None,
+        None,
+        None,
+        None,
+        Some(1),
+        None,
+    )?;
+    let txid2 = env.bitcoind.client.send_to_address(
+        &receive_address0,
+        Amount::from_sat(20000),
+        None,
+        None,
+        None,
+        None,
+        Some(1),
+        None,
+    )?;
+    let _block_hashes = env.mine_blocks(1, None)?;
+    while env.client.get_height().await.unwrap() < 102 {
+        sleep(Duration::from_millis(10))
+    }
+
+    let graph_update = env
+        .client
+        .scan_txs(
+            misc_spks.into_iter(),
+            vec![].into_iter(),
+            vec![].into_iter(),
+            1,
+        )
+        .await?;
+
+    let mut graph_update_txids: Vec<Txid> = graph_update.full_txs().map(|tx| tx.txid).collect();
+    graph_update_txids.sort();
+    let mut expected_txids = vec![txid1, txid2];
+    expected_txids.sort();
+    assert_eq!(graph_update_txids, expected_txids);
+    Ok(())
+}
diff --git a/crates/esplora/tests/blocking_ext.rs b/crates/esplora/tests/blocking_ext.rs
new file mode 100644 (file)
index 0000000..6c31994
--- /dev/null
@@ -0,0 +1,114 @@
+use bdk_esplora::EsploraExt;
+use electrsd::bitcoind::bitcoincore_rpc::RpcApi;
+use electrsd::bitcoind::{self, anyhow, BitcoinD};
+use electrsd::{Conf, ElectrsD};
+use esplora_client::{self, BlockingClient, Builder};
+use std::str::FromStr;
+use std::thread::sleep;
+use std::time::Duration;
+
+use bdk_chain::bitcoin::{Address, Amount, BlockHash, Txid};
+
+struct TestEnv {
+    bitcoind: BitcoinD,
+    #[allow(dead_code)]
+    electrsd: ElectrsD,
+    client: BlockingClient,
+}
+
+impl TestEnv {
+    fn new() -> Result<Self, anyhow::Error> {
+        let bitcoind_exe =
+            bitcoind::downloaded_exe_path().expect("bitcoind version feature must be enabled");
+        let bitcoind = BitcoinD::new(bitcoind_exe).unwrap();
+
+        let mut electrs_conf = Conf::default();
+        electrs_conf.http_enabled = true;
+        let electrs_exe =
+            electrsd::downloaded_exe_path().expect("electrs version feature must be enabled");
+        let electrsd = ElectrsD::with_conf(electrs_exe, &bitcoind, &electrs_conf)?;
+
+        let base_url = format!("http://{}", &electrsd.esplora_url.clone().unwrap());
+        let client = Builder::new(base_url.as_str()).build_blocking()?;
+
+        Ok(Self {
+            bitcoind,
+            electrsd,
+            client,
+        })
+    }
+
+    fn mine_blocks(
+        &self,
+        count: usize,
+        address: Option<Address>,
+    ) -> anyhow::Result<Vec<BlockHash>> {
+        let coinbase_address = match address {
+            Some(address) => address,
+            None => self
+                .bitcoind
+                .client
+                .get_new_address(None, None)?
+                .assume_checked(),
+        };
+        let block_hashes = self
+            .bitcoind
+            .client
+            .generate_to_address(count as _, &coinbase_address)?;
+        Ok(block_hashes)
+    }
+}
+
+#[test]
+pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> {
+    let env = TestEnv::new()?;
+    let receive_address0 =
+        Address::from_str("bcrt1qc6fweuf4xjvz4x3gx3t9e0fh4hvqyu2qw4wvxm")?.assume_checked();
+    let receive_address1 =
+        Address::from_str("bcrt1qfjg5lv3dvc9az8patec8fjddrs4aqtauadnagr")?.assume_checked();
+
+    let misc_spks = [
+        receive_address0.script_pubkey(),
+        receive_address1.script_pubkey(),
+    ];
+
+    let _block_hashes = env.mine_blocks(101, None)?;
+    let txid1 = env.bitcoind.client.send_to_address(
+        &receive_address1,
+        Amount::from_sat(10000),
+        None,
+        None,
+        None,
+        None,
+        Some(1),
+        None,
+    )?;
+    let txid2 = env.bitcoind.client.send_to_address(
+        &receive_address0,
+        Amount::from_sat(20000),
+        None,
+        None,
+        None,
+        None,
+        Some(1),
+        None,
+    )?;
+    let _block_hashes = env.mine_blocks(1, None)?;
+    while env.client.get_height().unwrap() < 102 {
+        sleep(Duration::from_millis(10))
+    }
+
+    let graph_update = env.client.scan_txs(
+        misc_spks.into_iter(),
+        vec![].into_iter(),
+        vec![].into_iter(),
+        1,
+    )?;
+
+    let mut graph_update_txids: Vec<Txid> = graph_update.full_txs().map(|tx| tx.txid).collect();
+    graph_update_txids.sort();
+    let mut expected_txids = vec![txid1, txid2];
+    expected_txids.sort();
+    assert_eq!(graph_update_txids, expected_txids);
+    Ok(())
+}