2021-03-03 13:22:05 -08:00
// Bitcoin Dev Kit
// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
2020-08-31 11:26:36 +02:00
//
2021-03-03 13:22:05 -08:00
// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
2020-08-31 11:26:36 +02:00
//
2021-03-03 13:22:05 -08:00
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
// You may not use this file except in accordance with one or both of these
// licenses.
2021-05-19 13:04:32 +10:00
#![ allow(missing_docs) ]
2020-08-31 11:26:36 +02:00
2021-06-17 13:48:46 +02:00
#[ cfg(test) ]
2021-05-19 15:52:51 +10:00
#[ cfg(feature = " test-blockchains " ) ]
pub mod blockchain_tests ;
2020-08-10 10:49:34 +02:00
2022-07-04 20:37:21 +08:00
#[ cfg(test) ]
#[ cfg(feature = " test-blockchains " ) ]
pub mod configurable_blockchain_tests ;
2022-04-14 17:20:46 +02:00
use bitcoin ::{ Address , Txid } ;
2020-08-10 10:49:34 +02:00
2022-02-17 23:36:40 +01:00
#[ derive(Clone, Debug) ]
pub struct TestIncomingInput {
pub txid : Txid ,
pub vout : u32 ,
pub sequence : Option < u32 > ,
}
impl TestIncomingInput {
pub fn new ( txid : Txid , vout : u32 , sequence : Option < u32 > ) -> Self {
Self {
txid ,
vout ,
sequence ,
}
}
#[ cfg(feature = " test-blockchains " ) ]
pub fn into_raw_tx_input ( self ) -> bitcoincore_rpc ::json ::CreateRawTransactionInput {
bitcoincore_rpc ::json ::CreateRawTransactionInput {
txid : self . txid ,
vout : self . vout ,
sequence : self . sequence ,
}
}
}
2020-08-10 10:49:34 +02:00
#[ derive(Clone, Debug) ]
pub struct TestIncomingOutput {
pub value : u64 ,
pub to_address : String ,
}
impl TestIncomingOutput {
pub fn new ( value : u64 , to_address : Address ) -> Self {
Self {
value ,
to_address : to_address . to_string ( ) ,
}
}
}
#[ derive(Clone, Debug) ]
pub struct TestIncomingTx {
2022-02-17 23:36:40 +01:00
pub input : Vec < TestIncomingInput > ,
2020-08-10 10:49:34 +02:00
pub output : Vec < TestIncomingOutput > ,
pub min_confirmations : Option < u64 > ,
pub locktime : Option < i64 > ,
pub replaceable : Option < bool > ,
}
impl TestIncomingTx {
pub fn new (
2022-02-17 23:36:40 +01:00
input : Vec < TestIncomingInput > ,
2020-08-10 10:49:34 +02:00
output : Vec < TestIncomingOutput > ,
min_confirmations : Option < u64 > ,
locktime : Option < i64 > ,
replaceable : Option < bool > ,
) -> Self {
Self {
2022-02-17 23:36:40 +01:00
input ,
2020-08-10 10:49:34 +02:00
output ,
min_confirmations ,
locktime ,
replaceable ,
}
}
2022-02-17 23:36:40 +01:00
pub fn add_input ( & mut self , input : TestIncomingInput ) {
self . input . push ( input ) ;
}
2020-08-10 10:49:34 +02:00
pub fn add_output ( & mut self , output : TestIncomingOutput ) {
self . output . push ( output ) ;
}
}
2021-05-19 13:04:32 +10:00
#[ doc(hidden) ]
2020-08-10 10:49:34 +02:00
#[ macro_export ]
macro_rules ! testutils {
( @ external $descriptors :expr , $child :expr ) = > ( {
2021-08-30 13:45:55 +10:00
use $crate ::bitcoin ::secp256k1 ::Secp256k1 ;
2022-10-25 11:15:43 +02:00
use $crate ::miniscript ::descriptor ::{ Descriptor , DescriptorPublicKey } ;
2020-08-12 12:51:50 +02:00
2020-11-16 22:07:38 +01:00
let secp = Secp256k1 ::new ( ) ;
2021-02-02 20:06:40 -05:00
let parsed = Descriptor ::< DescriptorPublicKey > ::parse_descriptor ( & secp , & $descriptors . 0 ) . expect ( " Failed to parse descriptor in `testutils!(@external)` " ) . 0 ;
2023-08-09 15:36:45 +02:00
parsed . at_derivation_index ( $child ) . unwrap ( ) . address ( bitcoin ::Network ::Regtest ) . expect ( " No address form " )
2020-08-10 10:49:34 +02:00
} ) ;
( @ internal $descriptors :expr , $child :expr ) = > ( {
2021-08-30 13:45:55 +10:00
use $crate ::bitcoin ::secp256k1 ::Secp256k1 ;
2022-10-25 11:15:43 +02:00
use $crate ::miniscript ::descriptor ::{ Descriptor , DescriptorPublicKey } ;
2021-02-02 20:06:40 -05:00
let secp = Secp256k1 ::new ( ) ;
let parsed = Descriptor ::< DescriptorPublicKey > ::parse_descriptor ( & secp , & $descriptors . 1. expect ( " Missing internal descriptor " ) ) . expect ( " Failed to parse descriptor in `testutils!(@internal)` " ) . 0 ;
2022-10-25 11:15:43 +02:00
parsed . at_derivation_index ( $child ) . address ( $crate ::bitcoin ::Network ::Regtest ) . expect ( " No address form " )
2020-08-10 10:49:34 +02:00
} ) ;
( @ e $descriptors :expr , $child :expr ) = > ( { testutils! ( @ external $descriptors , $child ) } ) ;
( @ i $descriptors :expr , $child :expr ) = > ( { testutils! ( @ internal $descriptors , $child ) } ) ;
2022-02-17 23:36:40 +01:00
( @ addr $addr :expr ) = > ( { $addr } ) ;
2020-08-10 10:49:34 +02:00
2022-02-17 23:36:40 +01:00
( @ tx ( $( ( $( $addr :tt ) * ) = > $amount :expr ) , + ) $( ( @ inputs $( ( $txid :expr , $vout :expr ) ) , + ) ) ? $( ( @ locktime $locktime :expr ) ) ? $( ( @ confirmations $confirmations :expr ) ) ? $( ( @ replaceable $replaceable :expr ) ) ? ) = > ( {
2021-05-19 16:10:06 +10:00
let outs = vec! [ $( $crate ::testutils ::TestIncomingOutput ::new ( $amount , testutils! ( $( $addr ) * ) ) ) , + ] ;
2022-02-17 23:36:40 +01:00
let _ins : Vec < $crate ::testutils ::TestIncomingInput > = vec! [ ] ;
$(
let _ins = vec! [ $( $crate ::testutils ::TestIncomingInput { txid : $txid , vout : $vout , sequence : None } ) , + ] ;
) ?
2020-08-10 10:49:34 +02:00
2021-05-19 16:10:06 +10:00
let locktime = None ::< i64 > $( . or ( Some ( $locktime ) ) ) ? ;
2020-08-10 10:49:34 +02:00
2021-05-19 16:10:06 +10:00
let min_confirmations = None ::< u64 > $( . or ( Some ( $confirmations ) ) ) ? ;
let replaceable = None ::< bool > $( . or ( Some ( $replaceable ) ) ) ? ;
2020-08-10 10:49:34 +02:00
2022-02-17 23:36:40 +01:00
$crate ::testutils ::TestIncomingTx ::new ( _ins , outs , min_confirmations , locktime , replaceable )
2020-08-10 10:49:34 +02:00
} ) ;
( @ literal $key :expr ) = > ( {
let key = $key . to_string ( ) ;
( key , None ::< String > , None ::< String > )
} ) ;
2021-05-19 13:04:32 +10:00
( @ generate_xprv $( $external_path :expr ) ? $( , $internal_path :expr ) ? ) = > ( {
2020-08-10 10:49:34 +02:00
use rand ::Rng ;
let mut seed = [ 0 u8 ; 32 ] ;
rand ::thread_rng ( ) . fill ( & mut seed [ .. ] ) ;
2023-08-09 15:36:45 +02:00
let key = $crate ::bitcoin ::bip32 ::ExtendedPrivKey ::new_master (
2021-08-30 13:45:55 +10:00
$crate ::bitcoin ::Network ::Testnet ,
2020-08-10 10:49:34 +02:00
& seed ,
) ;
2021-05-19 16:10:06 +10:00
let external_path = None ::< String > $( . or ( Some ( $external_path . to_string ( ) ) ) ) ? ;
let internal_path = None ::< String > $( . or ( Some ( $internal_path . to_string ( ) ) ) ) ? ;
2020-08-10 10:49:34 +02:00
( key . unwrap ( ) . to_string ( ) , external_path , internal_path )
} ) ;
( @ generate_wif ) = > ( {
use rand ::Rng ;
2021-08-30 13:45:55 +10:00
let mut key = [ 0 u8 ; $crate ::bitcoin ::secp256k1 ::constants ::SECRET_KEY_SIZE ] ;
2020-08-10 10:49:34 +02:00
rand ::thread_rng ( ) . fill ( & mut key [ .. ] ) ;
2021-08-30 13:45:55 +10:00
( $crate ::bitcoin ::PrivateKey {
2020-08-10 10:49:34 +02:00
compressed : true ,
2021-08-30 13:45:55 +10:00
network : $crate ::bitcoin ::Network ::Testnet ,
key : $crate ::bitcoin ::secp256k1 ::SecretKey ::from_slice ( & key ) . unwrap ( ) ,
2020-08-10 10:49:34 +02:00
} . to_string ( ) , None ::< String > , None ::< String > )
} ) ;
( @ keys ( $( $alias :expr = > ( $( $key_type :tt ) * ) ) , + ) ) = > ( {
let mut map = std ::collections ::HashMap ::new ( ) ;
$(
let alias : & str = $alias ;
map . insert ( alias , testutils! ( $( $key_type ) * ) ) ;
) +
map
} ) ;
2021-05-19 16:10:06 +10:00
( @ descriptors ( $external_descriptor :expr ) $( ( $internal_descriptor :expr ) ) ? $( ( @ keys $( $keys :tt ) * ) ) * ) = > ( {
2020-08-10 10:49:34 +02:00
use std ::str ::FromStr ;
use std ::collections ::HashMap ;
2022-10-25 11:15:43 +02:00
use std ::convert ::Infallible ;
2021-08-30 13:45:55 +10:00
use $crate ::miniscript ::descriptor ::Descriptor ;
use $crate ::miniscript ::TranslatePk ;
2020-08-12 12:51:50 +02:00
2022-10-25 11:15:43 +02:00
struct Translator {
keys : HashMap < & 'static str , ( String , Option < String > , Option < String > ) > ,
is_internal : bool ,
}
impl $crate ::miniscript ::Translator < String , String , Infallible > for Translator {
fn pk ( & mut self , pk : & String ) -> Result < String , Infallible > {
match self . keys . get ( pk . as_str ( ) ) {
Some ( ( key , ext_path , int_path ) ) = > {
let path = if self . is_internal { int_path } else { ext_path } ;
Ok ( format! ( " {} {} " , key , path . clone ( ) . unwrap_or_default ( ) ) )
}
None = > Ok ( pk . clone ( ) ) ,
}
}
fn sha256 ( & mut self , sha256 : & String ) -> Result < String , Infallible > { Ok ( sha256 . clone ( ) ) }
fn hash256 ( & mut self , hash256 : & String ) -> Result < String , Infallible > { Ok ( hash256 . clone ( ) ) }
fn ripemd160 ( & mut self , ripemd160 : & String ) -> Result < String , Infallible > { Ok ( ripemd160 . clone ( ) ) }
fn hash160 ( & mut self , hash160 : & String ) -> Result < String , Infallible > { Ok ( hash160 . clone ( ) ) }
}
2021-05-19 13:04:32 +10:00
#[ allow(unused_assignments, unused_mut) ]
2022-10-25 11:15:43 +02:00
let mut keys = HashMap ::new ( ) ;
2020-08-10 10:49:34 +02:00
$(
keys = testutils! { @ keys $( $keys ) * } ;
) *
2022-10-25 11:15:43 +02:00
let mut translator = Translator { keys , is_internal : false } ;
2020-08-10 10:49:34 +02:00
2022-10-25 11:15:43 +02:00
let external : Descriptor < String > = FromStr ::from_str ( $external_descriptor ) . unwrap ( ) ;
let external = external . translate_pk ( & mut translator ) . expect ( " Infallible conversion " ) ;
2020-08-12 12:51:50 +02:00
let external = external . to_string ( ) ;
2020-08-10 10:49:34 +02:00
2022-10-25 11:15:43 +02:00
translator . is_internal = true ;
2020-08-10 10:49:34 +02:00
2022-10-25 11:15:43 +02:00
let internal = None ::< String > $( . or ( {
let internal : Descriptor < String > = FromStr ::from_str ( $internal_descriptor ) . unwrap ( ) ;
let internal = internal . translate_pk ( & mut translator ) . expect ( " Infallible conversion " ) ;
Some ( internal . to_string ( ) )
2021-05-19 16:10:06 +10:00
} ) ) ? ;
2020-08-10 10:49:34 +02:00
( external , internal )
} )
}