Skip to content

Commit 51126d3

Browse files
committed
Add taproot tests
Also update block count in generatetoaddress for fast execution of integration tests
1 parent c25fc05 commit 51126d3

File tree

2 files changed

+83
-18
lines changed

2 files changed

+83
-18
lines changed

integration_test/src/main.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ extern crate miniscript;
1010

1111
use bitcoincore_rpc::{Auth, Client, RpcApi};
1212

13-
mod test_desc;
1413
mod test_cpp;
14+
mod test_desc;
1515
mod test_util;
1616
use test_util::TestData;
1717

@@ -68,4 +68,62 @@ fn main() {
6868

6969
let testdata = TestData::new_fixed_data(50);
7070
test_cpp::test_from_cpp_ms(&cl, &testdata);
71+
72+
test_descs(&cl, &testdata);
73+
}
74+
75+
fn test_descs(cl: &Client, testdata: &TestData) {
76+
// K : Compressed key available
77+
// K!: Compressed key with corresponding secret key unknown
78+
// X: X-only key available
79+
// X!: X-only key with corresponding secret key unknown
80+
81+
// Test 1: Simple spend with internal key
82+
let wit = test_desc::test_desc_satisfy(cl, testdata, "tr(X)");
83+
assert!(wit.len() == 1);
84+
85+
// Test 2: Same as above, but with leaves
86+
let wit = test_desc::test_desc_satisfy(cl, testdata, "tr(X,{pk(X1!),pk(X2!)})");
87+
assert!(wit.len() == 1);
88+
89+
// Test 3: Force to spend with script spend. Unknown internal key and only one known script path
90+
// X! -> Internal key unknown
91+
// Leaf 1 -> pk(X1) with X1 known
92+
// Leaf 2-> and_v(v:pk(X2),pk(X3!)) with partial witness only to X2 known
93+
let wit = test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1),and_v(v:pk(X2),pk(X3!))})");
94+
assert!(wit.len() == 3); // control block, script and signature
95+
96+
// Test 4: Force to spend with script spend. Unknown internal key and multiple script paths
97+
// Should select the one with minimum weight
98+
// X! -> Internal key unknown
99+
// Leaf 1 -> pk(X1!) with X1 unknown
100+
// Leaf 2-> and_v(v:pk(X2),pk(X3)) X2 and X3 known
101+
let wit = test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1),and_v(v:pk(X2),pk(X3))})");
102+
assert!(wit.len() == 3); // control block, script and one signatures
103+
104+
// Test 5: When everything is available, we should select the key spend path
105+
let wit = test_desc::test_desc_satisfy(cl, testdata, "tr(X,{pk(X1),and_v(v:pk(X2),pk(X3!))})");
106+
assert!(wit.len() == 1); // control block, script and signature
107+
108+
// Test 6: Test the new multi_a opcodes
109+
test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),multi_a(1,X2,X3!,X4!,X5!)})");
110+
test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),multi_a(2,X2,X3,X4!,X5!)})");
111+
test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),multi_a(3,X2,X3,X4,X5!)})");
112+
test_desc::test_desc_satisfy(cl, testdata, "tr(X!,{pk(X1!),multi_a(4,X2,X3,X4,X5)})");
113+
114+
// Misc tests for other descriptors that we support
115+
// Keys
116+
test_desc::test_desc_satisfy(cl, testdata, "wpkh(K)");
117+
test_desc::test_desc_satisfy(cl, testdata, "pkh(K)");
118+
test_desc::test_desc_satisfy(cl, testdata, "sh(wpkh(K))");
119+
120+
// sorted multi
121+
test_desc::test_desc_satisfy(cl, testdata, "sh(sortedmulti(2,K1,K2,K3))");
122+
test_desc::test_desc_satisfy(cl, testdata, "wsh(sortedmulti(2,K1,K2,K3))");
123+
test_desc::test_desc_satisfy(cl, testdata, "sh(wsh(sortedmulti(2,K1,K2,K3)))");
124+
125+
// Miniscripts
126+
test_desc::test_desc_satisfy(cl, testdata, "sh(and_v(v:pk(K1),pk(K2)))");
127+
test_desc::test_desc_satisfy(cl, testdata, "wsh(and_v(v:pk(K1),pk(K2)))");
128+
test_desc::test_desc_satisfy(cl, testdata, "sh(wsh(and_v(v:pk(K1),pk(K2))))");
71129
}

integration_test/src/test_desc.rs

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use bitcoin::util::{psbt, sighash};
1313
use bitcoin::{self, Amount, OutPoint, SchnorrSig, Script, Transaction, TxIn, TxOut, Txid};
1414
use bitcoincore_rpc::{json, Client, RpcApi};
1515
use miniscript::miniscript::iter;
16-
use miniscript::psbt::PbstOps;
16+
use miniscript::psbt::PsbtExt;
1717
use miniscript::{Descriptor, DescriptorTrait, Miniscript, ToPublicKey};
1818
use miniscript::{MiniscriptKey, ScriptContext};
1919
use std::collections::BTreeMap;
@@ -40,17 +40,17 @@ fn get_vout(cl: &Client, txid: Txid, value: u64, spk: Script) -> (OutPoint, TxOu
4040
unreachable!("Only call get vout on functions which have the expected outpoint");
4141
}
4242

43-
pub fn test_desc_satisfy(cl: &Client, testdata: &TestData, desc: String) -> Witness {
43+
pub fn test_desc_satisfy(cl: &Client, testdata: &TestData, desc: &str) -> Witness {
4444
let secp = secp256k1::Secp256k1::new();
4545
let sks = &testdata.secretdata.sks;
4646
let xonly_keypairs = &testdata.secretdata.x_only_keypairs;
4747
let pks = &testdata.pubdata.pks;
4848
let x_only_pks = &testdata.pubdata.x_only_pks;
4949
// Generate some blocks
5050
let blocks = cl
51-
.generate_to_address(500, &cl.get_new_address(None, None).unwrap())
51+
.generate_to_address(1, &cl.get_new_address(None, None).unwrap())
5252
.unwrap();
53-
assert_eq!(blocks.len(), 500);
53+
assert_eq!(blocks.len(), 1);
5454

5555
let desc = test_util::parse_test_desc(&desc, &testdata.pubdata);
5656
let derived_desc = desc.derived_descriptor(&secp, 0).unwrap();
@@ -69,9 +69,9 @@ pub fn test_desc_satisfy(cl: &Client, testdata: &TestData, desc: String) -> Witn
6969
.unwrap();
7070
// Wait for the funds to mature.
7171
let blocks = cl
72-
.generate_to_address(50, &cl.get_new_address(None, None).unwrap())
72+
.generate_to_address(2, &cl.get_new_address(None, None).unwrap())
7373
.unwrap();
74-
assert_eq!(blocks.len(), 50);
74+
assert_eq!(blocks.len(), 2);
7575
// Create a PSBT for each transaction.
7676
// Spend one input and spend one output for simplicity.
7777
let mut psbt = Psbt {
@@ -95,8 +95,8 @@ pub fn test_desc_satisfy(cl: &Client, testdata: &TestData, desc: String) -> Witn
9595
txin.previous_output = outpoint;
9696
// set the sequence to a non-final number for the locktime transactions to be
9797
// processed correctly.
98-
// We waited 50 blocks, keep 49 for safety
99-
txin.sequence = 49;
98+
// We waited 2 blocks, keep 1 for safety
99+
txin.sequence = 1;
100100
psbt.unsigned_tx.input.push(txin);
101101
// Get a new script pubkey from the node so that
102102
// the node wallet tracks the receiving transaction
@@ -112,7 +112,7 @@ pub fn test_desc_satisfy(cl: &Client, testdata: &TestData, desc: String) -> Witn
112112
input.witness_utxo = Some(witness_utxo.clone());
113113
psbt.inputs.push(input);
114114
psbt.outputs.push(psbt::Output::default());
115-
psbt.update_desc(0, &desc, 0..0).unwrap();
115+
psbt.update_desc(0, &desc, None).unwrap();
116116

117117
// --------------------------------------------
118118
// Sign the transactions with all keys
@@ -134,7 +134,9 @@ pub fn test_desc_satisfy(cl: &Client, testdata: &TestData, desc: String) -> Witn
134134

135135
if let Some(mut internal_keypair) = internal_keypair {
136136
// ---------------------- Tr key spend --------------------
137-
internal_keypair.tweak_add_assign(&secp, tr.spend_info().tap_tweak().as_ref());
137+
internal_keypair
138+
.tweak_add_assign(&secp, tr.spend_info().tap_tweak().as_ref())
139+
.expect("Tweaking failed");
138140
let sighash_msg = sighash_cache
139141
.taproot_key_spend_signature_hash(0, &prevouts, hash_ty)
140142
.unwrap();
@@ -218,7 +220,10 @@ pub fn test_desc_satisfy(cl: &Client, testdata: &TestData, desc: String) -> Witn
218220
},
219221
Descriptor::Tr(_tr) => unreachable!("Tr checked earlier"),
220222
};
221-
let msg = psbt.sighash_msg(0, &mut sighash_cache, None).unwrap().to_secp_msg();
223+
let msg = psbt
224+
.sighash_msg(0, &mut sighash_cache, None)
225+
.unwrap()
226+
.to_secp_msg();
222227

223228
// Fixme: Take a parameter
224229
let hash_ty = bitcoin::EcdsaSigHashType::All;
@@ -227,6 +232,7 @@ pub fn test_desc_satisfy(cl: &Client, testdata: &TestData, desc: String) -> Witn
227232
for sk in sks_reqd {
228233
let sig = secp.sign_ecdsa(&msg, &sk);
229234
let pk = pks[sks.iter().position(|&x| x == sk).unwrap()];
235+
assert!(secp.verify_ecdsa(&msg, &sig, &pk.inner).is_ok());
230236
psbt.inputs[0].partial_sigs.insert(
231237
pk.inner,
232238
bitcoin::EcdsaSig {
@@ -257,9 +263,12 @@ pub fn test_desc_satisfy(cl: &Client, testdata: &TestData, desc: String) -> Witn
257263
println!("Testing descriptor: {}", desc);
258264
// Finalize the transaction using psbt
259265
// Let miniscript do it's magic!
260-
if let Err(e) = psbt.finalize(&secp) {
266+
if let Err(e) = psbt.finalize_mut(&secp) {
261267
// All miniscripts should satisfy
262-
panic!("Could not satisfy non-malleably: error{} desc:{} ", e, desc);
268+
panic!(
269+
"Could not satisfy non-malleably: error{} desc:{} ",
270+
e[0], desc
271+
);
263272
}
264273
let tx = psbt.extract(&secp).expect("Extraction error");
265274

@@ -272,7 +281,7 @@ pub fn test_desc_satisfy(cl: &Client, testdata: &TestData, desc: String) -> Witn
272281

273282
// Finally mine the blocks and await confirmations
274283
let _blocks = cl
275-
.generate_to_address(10, &cl.get_new_address(None, None).unwrap())
284+
.generate_to_address(1, &cl.get_new_address(None, None).unwrap())
276285
.unwrap();
277286
// Get the required transactions from the node mined in the blocks.
278287
// Check whether the transaction is mined in blocks
@@ -310,8 +319,6 @@ fn find_sks_ms<Ctx: ScriptContext>(
310319
fn find_sk_single_key(pk: bitcoin::PublicKey, testdata: &TestData) -> Vec<secp256k1::SecretKey> {
311320
let sks = &testdata.secretdata.sks;
312321
let pks = &testdata.pubdata.pks;
313-
let i = pks
314-
.iter()
315-
.position(|&x| x.to_public_key() == pk);
322+
let i = pks.iter().position(|&x| x.to_public_key() == pk);
316323
i.map(|idx| vec![sks[idx]]).unwrap_or(Vec::new())
317324
}

0 commit comments

Comments
 (0)