}
Ok(tip)
}
+
+#[cfg(test)]
+mod test {
+ use crate::{bdk_electrum_client::TxUpdate, BdkElectrumClient};
+ use bdk_chain::bitcoin::{OutPoint, Transaction, TxIn};
+ use bdk_core::collections::BTreeMap;
+ use bdk_testenv::{utils::new_tx, TestEnv};
+ use std::sync::Arc;
+
+ #[cfg(feature = "default")]
+ #[test]
+ fn test_fetch_prev_txout_with_coinbase() {
+ let env = TestEnv::new().unwrap();
+ let electrum_client =
+ electrum_client::Client::new(env.electrsd.electrum_url.as_str()).unwrap();
+ let client = BdkElectrumClient::new(electrum_client);
+
+ // Create a coinbase transaction.
+ let coinbase_tx = Transaction {
+ input: vec![TxIn {
+ previous_output: OutPoint::null(),
+ ..Default::default()
+ }],
+ ..new_tx(0)
+ };
+
+ assert!(coinbase_tx.is_coinbase());
+
+ // Test that `fetch_prev_txout` does not process coinbase transactions. Calling
+ // `fetch_prev_txout` on a coinbase transaction will trigger a `fetch_tx` on a transaction
+ // with a txid of all zeros. If `fetch_prev_txout` attempts to fetch this transaction, this
+ // assertion will fail.
+ let mut tx_update = TxUpdate {
+ txs: vec![Arc::new(coinbase_tx)],
+ ..Default::default()
+ };
+ assert!(client.fetch_prev_txout(&mut tx_update).is_ok());
+
+ // Ensure that the txouts are empty.
+ assert_eq!(tx_update.txouts, BTreeMap::default());
+ }
+}
Ok(())
}
+
+#[test]
+fn test_sync_with_coinbase() -> anyhow::Result<()> {
+ let env = TestEnv::new()?;
+ let electrum_client = electrum_client::Client::new(env.electrsd.electrum_url.as_str())?;
+ let client = BdkElectrumClient::new(electrum_client);
+
+ // Setup address.
+ let spk_to_track = ScriptBuf::new_p2wsh(&WScriptHash::all_zeros());
+ let addr_to_track = Address::from_script(&spk_to_track, bdk_chain::bitcoin::Network::Regtest)?;
+
+ // Setup receiver.
+ let (mut recv_chain, _) = LocalChain::from_genesis_hash(env.bitcoind.client.get_block_hash(0)?);
+ let mut recv_graph = IndexedTxGraph::<ConfirmationBlockTime, _>::new({
+ let mut recv_index = SpkTxOutIndex::default();
+ recv_index.insert_spk((), spk_to_track.clone());
+ recv_index
+ });
+
+ // Mine some blocks.
+ env.mine_blocks(101, Some(addr_to_track))?;
+ env.wait_until_electrum_sees_block(Duration::from_secs(6))?;
+
+ // Check to see if electrum syncs properly.
+ assert!(sync_with_electrum(
+ &client,
+ [spk_to_track.clone()],
+ &mut recv_chain,
+ &mut recv_graph,
+ )
+ .is_ok());
+
+ Ok(())
+}