@@ -8,19 +8,11 @@ extern crate log;
88extern crate bitcoin;
99extern 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
2517struct StdLogger ;
2618
@@ -45,11 +37,6 @@ impl log::Log for StdLogger {
4537
4638static 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-
5340fn 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-
8454fn 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