Skip to content

Commit 5588c85

Browse files
Added electrum blockchain back-end and taproot tests to blockchain_tests
Co-authored-by: saikishore222 <saikishore.chsk@gmail.com>
1 parent 5220d7b commit 5588c85

File tree

4 files changed

+163
-32
lines changed

4 files changed

+163
-32
lines changed

src/blockchain/electrum.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,8 @@ mod test {
327327

328328
use super::*;
329329
use crate::database::MemoryDatabase;
330-
use crate::testutils::blockchain_tests::TestClient;
330+
use crate::make_blockchain_tests;
331+
use crate::testutils::blockchain_tests::{TestClient, BlockchainType};
331332
use crate::wallet::{AddressIndex, Wallet};
332333

333334
crate::bdk_blockchain_tests! {
@@ -336,6 +337,18 @@ mod test {
336337
}
337338
}
338339

340+
make_blockchain_tests![
341+
@type BlockchainType::ElectrumBlockchain,
342+
@tests (
343+
test_sync_simple,
344+
test_taproot_key_spend,
345+
test_taproot_script_spend,
346+
test_sign_taproot_core_keyspend_psbt,
347+
test_sign_taproot_core_scriptspend2_psbt,
348+
test_sign_taproot_core_scriptspend3_psbt,
349+
)
350+
];
351+
339352
fn get_factory() -> (TestClient, Arc<ElectrumBlockchain>) {
340353
let test_client = TestClient::default();
341354

src/blockchain/esplora/mod.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -166,20 +166,16 @@ pub mod test {
166166
use crate::testutils::blockchain_tests::BlockchainType;
167167
use crate::testutils::blockchain_tests::TestClient;
168168

169-
pub fn get_blockchain(test_client: &TestClient) -> EsploraBlockchain {
170-
EsploraBlockchain::new(
171-
&format!(
172-
"http://{}",
173-
test_client.electrsd.esplora_url.as_ref().unwrap()
174-
),
175-
20,
176-
)
177-
}
178-
169+
#[cfg(feature = "test-esplora")]
179170
make_blockchain_tests![
180171
@type BlockchainType::EsploraBlockchain,
181172
@tests (
182-
test_sync_simple
173+
test_sync_simple,
174+
test_taproot_key_spend,
175+
test_taproot_script_spend,
176+
test_sign_taproot_core_keyspend_psbt,
177+
test_sign_taproot_core_scriptspend2_psbt,
178+
test_sign_taproot_core_scriptspend3_psbt,
183179
)
184180
];
185181

src/blockchain/rpc.rs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -588,25 +588,6 @@ pub mod test {
588588
}
589589
}
590590

591-
pub fn get_blockchain(test_client: &TestClient) -> RpcBlockchain {
592-
let config = RpcConfig {
593-
url: test_client.bitcoind.rpc_url(),
594-
auth: Auth::Cookie {
595-
file: test_client.bitcoind.params.cookie_file.clone(),
596-
},
597-
network: Network::Regtest,
598-
wallet_name: format!(
599-
"client-wallet-test-{}",
600-
std::time::SystemTime::now()
601-
.duration_since(std::time::UNIX_EPOCH)
602-
.unwrap()
603-
.as_nanos()
604-
),
605-
skip_blocks: None,
606-
};
607-
RpcBlockchain::from_config(&config).unwrap()
608-
}
609-
610591
make_blockchain_tests![
611592
@type BlockchainType::RpcBlockchain,
612593
@tests (

src/testutils/blockchain_tests.rs

Lines changed: 142 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,8 @@ pub enum BlockchainType {
366366
RpcBlockchain,
367367
#[cfg(feature = "test-esplora")]
368368
EsploraBlockchain,
369+
#[cfg(feature = "test-electrum")]
370+
ElectrumBlockchain,
369371
}
370372

371373
#[cfg(test)]
@@ -377,6 +379,8 @@ pub mod test {
377379
use crate::blockchain::EsploraBlockchain;
378380
#[cfg(any(feature = "test-rpc", feature = "test-rpc-legacy"))]
379381
use crate::blockchain::{rpc::Auth, ConfigurableBlockchain, RpcBlockchain, RpcConfig};
382+
#[cfg(feature = "test-electrum")]
383+
use {crate::blockchain::ElectrumBlockchain, electrum_client::client::Client as electrum_client};
380384
use crate::database::MemoryDatabase;
381385
use crate::testutils;
382386
use crate::testutils::blockchain_tests::TestClient;
@@ -455,7 +459,7 @@ pub mod test {
455459
skip_blocks: None,
456460
};
457461
AnyBlockchain::Rpc(Box::new(RpcBlockchain::from_config(&config).unwrap()))
458-
}
462+
},
459463

460464
#[cfg(feature = "test-esplora")]
461465
BlockchainType::EsploraBlockchain => {
@@ -466,6 +470,13 @@ pub mod test {
466470
),
467471
20,
468472
)))
473+
},
474+
475+
#[cfg(feature = "test-electrum")]
476+
BlockchainType::ElectrumBlockchain => {
477+
AnyBlockchain::Electrum(Box::new(ElectrumBlockchain::from(
478+
electrum_client::new(&test_client.electrsd.electrum_url).unwrap())
479+
))
469480
}
470481
};
471482
let wallet = get_wallet_from_descriptors(&descriptors);
@@ -530,6 +541,136 @@ pub mod test {
530541
"incorrect confirmation time"
531542
);
532543
}
544+
545+
#[cfg(not(feature = "test-rpc-legacy"))]
546+
pub fn test_taproot_key_spend(chain_type: BlockchainType) {
547+
use crate::blockchain::Blockchain;
548+
549+
let (wallet, blockchain, descriptors, mut test_client) = init_wallet(WalletType::TaprootKeySpend, chain_type);
550+
551+
let _ = test_client.receive(testutils! {
552+
@tx ( (@external descriptors, 0) => 50_000 )
553+
});
554+
wallet.sync(&blockchain, SyncOptions::default()).unwrap();
555+
assert_eq!(wallet.get_balance().unwrap(), 50_000);
556+
557+
let tx = {
558+
let mut builder = wallet.build_tx();
559+
builder.add_recipient(test_client.get_node_address(None).script_pubkey(), 25_000);
560+
let (mut psbt, _details) = builder.finish().unwrap();
561+
wallet.sign(&mut psbt, Default::default()).unwrap();
562+
psbt.extract_tx()
563+
};
564+
blockchain.broadcast(&tx).unwrap();
565+
}
566+
567+
#[cfg(not(feature = "test-rpc-legacy"))]
568+
pub fn test_taproot_script_spend(chain_type: BlockchainType) {
569+
use crate::blockchain::Blockchain;
570+
571+
let (wallet, blockchain, descriptors, mut test_client) = init_wallet(WalletType::TaprootScriptSpend, chain_type);
572+
573+
let _ = test_client.receive(testutils! {
574+
@tx ( (@external descriptors, 0) => 50_000 ) ( @confirmations 6 )
575+
});
576+
wallet.sync(&blockchain, SyncOptions::default()).unwrap();
577+
assert_eq!(wallet.get_balance().unwrap(), 50_000);
578+
579+
let ext_policy = wallet.policies(KeychainKind::External).unwrap().unwrap();
580+
let int_policy = wallet.policies(KeychainKind::Internal).unwrap().unwrap();
581+
582+
let ext_path = vec![(ext_policy.id.clone(), vec![1])].into_iter().collect();
583+
let int_path = vec![(int_policy.id.clone(), vec![1])].into_iter().collect();
584+
585+
let tx = {
586+
let mut builder = wallet.build_tx();
587+
builder.add_recipient(test_client.get_node_address(None).script_pubkey(), 25_000)
588+
.policy_path(ext_path, KeychainKind::External)
589+
.policy_path(int_path, KeychainKind::Internal);
590+
let (mut psbt, _details) = builder.finish().unwrap();
591+
wallet.sign(&mut psbt, Default::default()).unwrap();
592+
psbt.extract_tx()
593+
};
594+
blockchain.broadcast(&tx).unwrap();
595+
}
596+
597+
#[cfg(not(feature = "test-rpc-legacy"))]
598+
pub fn test_sign_taproot_core_keyspend_psbt(chain_type: BlockchainType) {
599+
test_sign_taproot_core_psbt(WalletType::TaprootKeySpend, chain_type);
600+
}
601+
602+
#[cfg(not(feature = "test-rpc-legacy"))]
603+
pub fn test_sign_taproot_core_scriptspend2_psbt(chain_type: BlockchainType) {
604+
test_sign_taproot_core_psbt(WalletType::TaprootScriptSpend2, chain_type);
605+
}
606+
607+
#[cfg(not(feature = "test-rpc-legacy"))]
608+
pub fn test_sign_taproot_core_scriptspend3_psbt(chain_type: BlockchainType) {
609+
test_sign_taproot_core_psbt(WalletType::TaprootScriptSpend3, chain_type);
610+
}
611+
612+
#[cfg(not(feature = "test-rpc-legacy"))]
613+
fn test_sign_taproot_core_psbt(wallet_type: WalletType, chain_type: BlockchainType) {
614+
use std::str::FromStr;
615+
use serde_json;
616+
use bitcoincore_rpc::jsonrpc::serde_json::Value;
617+
use bitcoincore_rpc::{Auth, Client};
618+
619+
let (wallet, _blockchain, _descriptors, test_client) = init_wallet(wallet_type, chain_type);
620+
621+
// TODO replace once rust-bitcoincore-rpc with PR 174 released
622+
// https://github.com/rust-bitcoin/rust-bitcoincore-rpc/pull/174
623+
let _createwallet_result: Value = test_client.bitcoind.client.call("createwallet", &["taproot_wallet".into(), true.into(), true.into(), serde_json::to_value("").unwrap(), false.into(), true.into(), true.into(), false.into()]).expect("created wallet");
624+
625+
let external_descriptor = wallet.get_descriptor_for_keychain(KeychainKind::External);
626+
627+
// TODO replace once bitcoind released with support for rust-bitcoincore-rpc PR 174
628+
let taproot_wallet_client = Client::new(&test_client.bitcoind.rpc_url_with_wallet("taproot_wallet"), Auth::CookieFile(test_client.bitcoind.params.cookie_file.clone())).unwrap();
629+
630+
let descriptor_info = taproot_wallet_client.get_descriptor_info(external_descriptor.to_string().as_str()).expect("descriptor info");
631+
632+
let import_descriptor_args = json!([{
633+
"desc": descriptor_info.descriptor,
634+
"active": true,
635+
"timestamp": "now",
636+
"label":"taproot key spend",
637+
}]);
638+
let _importdescriptors_result: Value = taproot_wallet_client.call("importdescriptors", &[import_descriptor_args]).expect("import wallet");
639+
let generate_to_address: bitcoin::Address = taproot_wallet_client.call("getnewaddress", &["test address".into(), "bech32m".into()]).expect("new address");
640+
let _generatetoaddress_result = taproot_wallet_client.generate_to_address(101, &generate_to_address).expect("generated to address");
641+
let send_to_address = wallet.get_address(crate::wallet::AddressIndex::New).unwrap().address.to_string();
642+
let change_address = wallet.get_address(crate::wallet::AddressIndex::New).unwrap().address.to_string();
643+
let send_addr_amounts = json!([{
644+
send_to_address: "0.4321"
645+
}]);
646+
let send_options = json!({
647+
"change_address": change_address,
648+
"psbt": true,
649+
});
650+
let send_result: Value = taproot_wallet_client.call("send", &[send_addr_amounts, Value::Null, "unset".into(), Value::Null, send_options]).expect("send psbt");
651+
let core_psbt = send_result["psbt"].as_str().expect("core psbt str");
652+
653+
use bitcoin::util::psbt::PartiallySignedTransaction;
654+
655+
// Test parsing core created PSBT
656+
let mut psbt = PartiallySignedTransaction::from_str(&core_psbt).expect("core taproot psbt");
657+
658+
// Test signing core created PSBT
659+
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
660+
assert_eq!(finalized, true);
661+
662+
// Test with updated psbt
663+
let update_result: Value = taproot_wallet_client.call("utxoupdatepsbt", &[core_psbt.into()]).expect("update psbt utxos");
664+
let core_updated_psbt = update_result.as_str().expect("core updated psbt");
665+
666+
// Test parsing core created and updated PSBT
667+
let mut psbt = PartiallySignedTransaction::from_str(&core_updated_psbt).expect("core taproot psbt");
668+
669+
// Test signing core created and updated PSBT
670+
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
671+
assert_eq!(finalized, true);
672+
}
673+
533674
}
534675

535676
#[macro_export]

0 commit comments

Comments
 (0)