Skip to content

Commit ae3c98e

Browse files
committed
Move only: Rework Integration Test and makes things more modular
Easier for writing future tests. There are no new tests added in this commit. This only moves cpp tests into test_cpp, deletes read_file.rs and moves common utilities to test_util.rs
1 parent bc2d097 commit ae3c98e

File tree

6 files changed

+565
-362
lines changed

6 files changed

+565
-362
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@ fuzz/hfuzz_workspace
1717

1818
#Vscode project files
1919
.vscode
20+
21+
#Intergration test files
22+
integration_test/bitcoin-*

integration_test/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ miniscript = {path = "../"}
1010
bitcoincore-rpc = {git = "https://github.com/sanket1729/rust-bitcoincore-rpc",rev = "bcc35944b3dd636cdff9710f90f8e0cfcab28f27"}
1111
bitcoin = "0.28.0-rc.1"
1212
log = "0.4"
13+
rand = "0.8.4"

integration_test/src/main.rs

Lines changed: 6 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,11 @@ extern crate log;
88
extern crate bitcoin;
99
extern crate miniscript;
1010

11-
use bitcoincore_rpc::{json, Auth, Client, RpcApi};
11+
use bitcoincore_rpc::{Auth, Client, RpcApi};
1212

13-
use bitcoin::secp256k1;
14-
use bitcoin::util::psbt;
15-
use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
16-
use bitcoin::{Amount, OutPoint, Transaction, TxIn, TxOut, Txid};
17-
mod read_file;
18-
use miniscript::miniscript::iter;
19-
use miniscript::psbt::PsbtExt;
20-
use miniscript::DescriptorTrait;
21-
use miniscript::MiniscriptKey;
22-
use miniscript::{Miniscript, Segwitv0};
23-
use std::collections::BTreeMap;
13+
mod test_cpp;
14+
mod test_util;
15+
use test_util::TestData;
2416

2517
struct StdLogger;
2618

@@ -45,11 +37,6 @@ impl log::Log for StdLogger {
4537

4638
static LOGGER: StdLogger = StdLogger;
4739

48-
/// Quickly create a BTC amount.
49-
fn btc<F: Into<f64>>(btc: F) -> Amount {
50-
Amount::from_btc(btc.into()).unwrap()
51-
}
52-
5340
fn get_rpc_url() -> String {
5441
return std::env::var("RPC_URL").expect("RPC_URL must be set");
5542
}
@@ -64,23 +51,6 @@ fn get_auth() -> bitcoincore_rpc::Auth {
6451
};
6552
}
6653

67-
// Find the Outpoint by value.
68-
// Ideally, we should find by scriptPubkey, but this
69-
// works for temp test case
70-
fn get_vout(cl: &Client, txid: Txid, value: u64) -> (OutPoint, TxOut) {
71-
let tx = cl
72-
.get_transaction(&txid, None)
73-
.unwrap()
74-
.transaction()
75-
.unwrap();
76-
for (i, txout) in tx.output.into_iter().enumerate() {
77-
if txout.value == value {
78-
return (OutPoint::new(txid, i as u32), txout);
79-
}
80-
}
81-
unreachable!("Only call get vout on functions which have the expected outpoint");
82-
}
83-
8454
fn main() {
8555
log::set_logger(&LOGGER)
8656
.map(|()| log::set_max_level(log::LevelFilter::max()))
@@ -95,173 +65,6 @@ fn main() {
9565
cl.create_wallet("testwallet", None, None, None, None)
9666
.unwrap();
9767

98-
let testdata = read_file::TestData::new_fixed_data(50);
99-
let ms_vec = read_file::parse_miniscripts(&testdata.pubdata);
100-
let sks = testdata.secretdata.sks;
101-
let pks = testdata.pubdata.pks;
102-
// Generate some blocks
103-
let blocks = cl
104-
.generate_to_address(500, &cl.get_new_address(None, None).unwrap())
105-
.unwrap();
106-
assert_eq!(blocks.len(), 500);
107-
108-
// Next send some btc to each address corresponding to the miniscript
109-
let mut txids = vec![];
110-
for ms in ms_vec.iter() {
111-
let wsh = miniscript::Descriptor::new_wsh(ms.clone()).unwrap();
112-
let txid = cl
113-
.send_to_address(
114-
&wsh.address(bitcoin::Network::Regtest).unwrap(),
115-
btc(1),
116-
None,
117-
None,
118-
None,
119-
None,
120-
None,
121-
None,
122-
)
123-
.unwrap();
124-
txids.push(txid);
125-
}
126-
// Wait for the funds to mature.
127-
let blocks = cl
128-
.generate_to_address(50, &cl.get_new_address(None, None).unwrap())
129-
.unwrap();
130-
assert_eq!(blocks.len(), 50);
131-
// Create a PSBT for each transaction.
132-
// Spend one input and spend one output for simplicity.
133-
let mut psbts = vec![];
134-
for (ms, txid) in ms_vec.iter().zip(txids) {
135-
let mut psbt = Psbt {
136-
unsigned_tx: Transaction {
137-
version: 2,
138-
lock_time: 1_603_866_330, // time at 10/28/2020 @ 6:25am (UTC)
139-
input: vec![],
140-
output: vec![],
141-
},
142-
unknown: BTreeMap::new(),
143-
proprietary: BTreeMap::new(),
144-
xpub: BTreeMap::new(),
145-
version: 0,
146-
inputs: vec![],
147-
outputs: vec![],
148-
};
149-
// figure out the outpoint from the txid
150-
let (outpoint, witness_utxo) = get_vout(&cl, txid, btc(1.0).as_sat());
151-
let mut txin = TxIn::default();
152-
txin.previous_output = outpoint;
153-
// set the sequence to a non-final number for the locktime transactions to be
154-
// processed correctly.
155-
// We waited 50 blocks, keep 49 for safety
156-
txin.sequence = 49;
157-
psbt.unsigned_tx.input.push(txin);
158-
// Get a new script pubkey from the node so that
159-
// the node wallet tracks the receiving transaction
160-
// and we can check it by gettransaction RPC.
161-
let addr = cl
162-
.get_new_address(None, Some(json::AddressType::Bech32))
163-
.unwrap();
164-
psbt.unsigned_tx.output.push(TxOut {
165-
value: 99_999_000,
166-
script_pubkey: addr.script_pubkey(),
167-
});
168-
let mut input = psbt::Input::default();
169-
input.witness_utxo = Some(witness_utxo);
170-
input.witness_script = Some(ms.encode());
171-
psbt.inputs.push(input);
172-
psbt.outputs.push(psbt::Output::default());
173-
psbts.push(psbt);
174-
}
175-
176-
let mut spend_txids = vec![];
177-
// Sign the transactions with all keys
178-
// AKA the signer role of psbt
179-
for i in 0..psbts.len() {
180-
// Get all the pubkeys and the corresponding secret keys
181-
let ms: Miniscript<miniscript::bitcoin::PublicKey, Segwitv0> =
182-
Miniscript::parse_insane(psbts[i].inputs[0].witness_script.as_ref().unwrap()).unwrap();
183-
184-
let sks_reqd: Vec<_> = ms
185-
.iter_pk_pkh()
186-
.map(|pk_pkh| match pk_pkh {
187-
iter::PkPkh::PlainPubkey(pk) => sks[pks.iter().position(|&x| x == pk).unwrap()],
188-
iter::PkPkh::HashedPubkey(hash) => {
189-
sks[pks
190-
.iter()
191-
.position(|&pk| pk.to_pubkeyhash() == hash)
192-
.unwrap()]
193-
}
194-
})
195-
.collect();
196-
// Get the required sighash message
197-
let amt = btc(1).as_sat();
198-
let mut sighash_cache = bitcoin::util::sighash::SigHashCache::new(&psbts[i].unsigned_tx);
199-
let sighash_ty = bitcoin::EcdsaSigHashType::All;
200-
let sighash = sighash_cache
201-
.segwit_signature_hash(0, &ms.encode(), amt, sighash_ty)
202-
.unwrap();
203-
204-
// requires both signing and verification because we check the tx
205-
// after we psbt extract it
206-
let secp = secp256k1::Secp256k1::new();
207-
let msg = secp256k1::Message::from_slice(&sighash[..]).unwrap();
208-
209-
// Finally construct the signature and add to psbt
210-
for sk in sks_reqd {
211-
let sig = secp.sign_ecdsa(&msg, &sk);
212-
let pk = pks[sks.iter().position(|&x| x == sk).unwrap()];
213-
psbts[i].inputs[0].partial_sigs.insert(
214-
pk.inner,
215-
bitcoin::EcdsaSig {
216-
sig,
217-
hash_ty: sighash_ty,
218-
},
219-
);
220-
}
221-
// Add the hash preimages to the psbt
222-
psbts[i].inputs[0].sha256_preimages.insert(
223-
testdata.pubdata.sha256,
224-
testdata.secretdata.sha256_pre.to_vec(),
225-
);
226-
psbts[i].inputs[0].hash256_preimages.insert(
227-
testdata.pubdata.hash256,
228-
testdata.secretdata.hash256_pre.to_vec(),
229-
);
230-
println!("{}", ms);
231-
psbts[i].inputs[0].hash160_preimages.insert(
232-
testdata.pubdata.hash160,
233-
testdata.secretdata.hash160_pre.to_vec(),
234-
);
235-
psbts[i].inputs[0].ripemd160_preimages.insert(
236-
testdata.pubdata.ripemd160,
237-
testdata.secretdata.ripemd160_pre.to_vec(),
238-
);
239-
// Finalize the transaction using psbt
240-
// Let miniscript do it's magic!
241-
if let Err(e) = psbts[i].finalize_mall_mut(&secp) {
242-
// All miniscripts should satisfy
243-
panic!("Could not satisfy: error{} ms:{} at ind:{}", e[0], ms, i);
244-
} else {
245-
let tx = psbts[i].extract(&secp).unwrap();
246-
247-
// Send the transactions to bitcoin node for mining.
248-
// Regtest mode has standardness checks
249-
// Check whether the node accepts the transactions
250-
let txid = cl
251-
.send_raw_transaction(&tx)
252-
.expect(&format!("{} send tx failed for ms {}", i, ms));
253-
spend_txids.push(txid);
254-
}
255-
}
256-
// Finally mine the blocks and await confirmations
257-
let _blocks = cl
258-
.generate_to_address(10, &cl.get_new_address(None, None).unwrap())
259-
.unwrap();
260-
// Get the required transactions from the node mined in the blocks.
261-
for txid in spend_txids {
262-
// Check whether the transaction is mined in blocks
263-
// Assert that the confirmations are > 0.
264-
let num_conf = cl.get_transaction(&txid, None).unwrap().info.confirmations;
265-
assert!(num_conf > 0);
266-
}
68+
let testdata = TestData::new_fixed_data(50);
69+
test_cpp::test_from_cpp_ms(&cl, &testdata);
26770
}

0 commit comments

Comments
 (0)