@@ -11,8 +11,10 @@ use miniscript::descriptor::{self, DescriptorPublicKey};
11
11
12
12
use super :: miniscript:: { multi_andor, AndOr } ;
13
13
use crate :: runtime:: scope:: { Mutable , Scope , ScopeRef } ;
14
- use crate :: runtime:: { Array , Error , Result , Value } ;
15
- use crate :: util:: { self , fmt_list, DescriptorExt , DescriptorPubKeyExt , PrettyDisplay , EC } ;
14
+ use crate :: runtime:: { Array , Error , FieldAccess , Result , Value } ;
15
+ use crate :: util:: {
16
+ self , fmt_list, DescriptorExt , DescriptorPubKeyExt , PrettyDisplay , TapInfoExt , EC ,
17
+ } ;
16
18
use crate :: { DescriptorDpk as Descriptor , ExprRepr , PolicyDpk as Policy } ;
17
19
18
20
pub fn attach_stdlib ( scope : & ScopeRef < Mutable > ) {
@@ -21,11 +23,7 @@ pub fn attach_stdlib(scope: &ScopeRef<Mutable>) {
21
23
// Taproot Descriptor/TaprootSpendInfo construction
22
24
scope. set_fn ( "tr" , fns:: tr) . unwrap ( ) ;
23
25
24
- // Functions for extracting information out of Descriptors/TaprootSpendInfo
25
- scope. set_fn ( "tr::internalKey" , fns:: internalKey) . unwrap ( ) ;
26
- scope. set_fn ( "tr::outputKey" , fns:: outputKey) . unwrap ( ) ;
27
- scope. set_fn ( "tr::merkleRoot" , fns:: merkleRoot) . unwrap ( ) ;
28
- scope. set_fn ( "tr::scripts" , fns:: scripts) . unwrap ( ) ;
26
+ // Construct the witness control block
29
27
scope. set_fn ( "tr::ctrl" , fns:: ctrl) . unwrap ( ) ;
30
28
31
29
// Convert a tr() descriptor into a TaprootSpendInfo
@@ -55,57 +53,9 @@ pub mod fns {
55
53
super :: tr ( a, b, & scope. borrow ( ) )
56
54
}
57
55
58
- /// tr::internalKey(TapInfo|Descriptor) -> PubKey
59
- ///
60
- /// Get the internal x-only key of the given TapInfo/Descriptor
61
- pub fn internalKey ( args : Array , _: & ScopeRef ) -> Result < Value > {
62
- Ok ( match args. arg_into ( ) ? {
63
- Value :: TapInfo ( tapinfo) => tapinfo. internal_key ( ) . into ( ) ,
64
- Value :: Descriptor ( Descriptor :: Tr ( tr) ) => tr. internal_key ( ) . clone ( ) . into ( ) ,
65
- _ => bail ! ( Error :: InvalidArguments ) ,
66
- } )
67
- }
68
-
69
- /// tr::outputKey(TapInfo) -> PubKey | (PubKey, Number)
70
- ///
71
- /// Get the output key of the given TapInfo, optionally with the parity as a tuple of (key, parity)
72
- pub fn outputKey ( args : Array , _: & ScopeRef ) -> Result < Value > {
73
- let ( tapinfo, with_parity) : ( TaprootSpendInfo , Option < bool > ) = args. args_into ( ) ?;
74
- let key = tapinfo. output_key ( ) ;
75
-
76
- Ok ( if with_parity. unwrap_or ( false ) {
77
- ( key, tapinfo. output_key_parity ( ) ) . into ( )
78
- } else {
79
- key. into ( )
80
- } )
81
- }
82
-
83
- /// tr::merkleRoot(TapInfo) -> Hash
84
- ///
85
- /// Get the merkle root hash of the given TapInfo
86
- pub fn merkleRoot ( args : Array , _: & ScopeRef ) -> Result < Value > {
87
- let tapinfo: TaprootSpendInfo = args. arg_into ( ) ?;
88
-
89
- Ok ( match tapinfo. merkle_root ( ) {
90
- None => Vec :: < u8 > :: new ( ) . into ( ) , // empty byte vector signifies an empty script tree
91
- Some ( root) => root. into ( ) ,
92
- } )
93
- }
94
-
95
- /// tr::scripts(TapInfo|Descriptor) -> Array<Script>
96
- ///
97
- /// Get an array of all scripts in the tree
98
- pub fn scripts ( args : Array , _: & ScopeRef ) -> Result < Value > {
99
- let tapinfo: TaprootSpendInfo = args. arg_into ( ) ?;
100
- let scripts = tapinfo. script_map ( ) . keys ( ) ;
101
- Ok ( Value :: array (
102
- scripts. map ( |( script, _) | script. clone ( ) . into ( ) ) . collect ( ) ,
103
- ) )
104
- }
105
-
106
56
/// tr::ctrl(TapInfo|Descriptor, Script|Policy, Byte version=TapScript) -> Array<Script>
107
57
///
108
- /// Get the control block for the given script/policy
58
+ /// Construct the witness control block for the given Script/Policy
109
59
pub fn ctrl ( args : Array , _: & ScopeRef ) -> Result < Value > {
110
60
let ( tapinfo, script_or_policy, leaf_ver) : ( TaprootSpendInfo , Value , Option < LeafVersion > ) =
111
61
args. args_into ( ) ?;
@@ -123,7 +73,7 @@ pub mod fns {
123
73
124
74
/// tr::tapinfo(Descriptor|TapInfo) -> TapInfo
125
75
///
126
- /// Convert the Tr Descriptor into a TapInfo (or return TapInfo as-is)
76
+ /// Convert Tr Descriptor into a TapInfo (or return TapInfo as-is)
127
77
pub fn tapinfo ( args : Array , _: & ScopeRef ) -> Result < Value > {
128
78
Ok ( Value :: TapInfo ( args. arg_into ( ) ?) )
129
79
}
@@ -148,15 +98,42 @@ pub mod fns {
148
98
}
149
99
}
150
100
101
+ // TaprootSpendInfo field accessors
102
+ impl FieldAccess for TaprootSpendInfo {
103
+ fn get_field ( self , field : & Value ) -> Option < Value > {
104
+ // Similar fields are available on tr() Descriptors
105
+ Some ( match field. as_str ( ) ? {
106
+ "script_pubkey" => self . script_pubkey ( ) . into ( ) ,
107
+ "witness_program" => self . witness_program ( ) . into ( ) ,
108
+ "address_type" => bitcoin:: AddressType :: P2tr . into ( ) ,
109
+
110
+ "internal_key" => self . internal_key ( ) . into ( ) ,
111
+ "merkle_root" => self . merkle_root ( ) ?. into ( ) ,
112
+ "output_key" => self . output_key ( ) . into ( ) ,
113
+ "output_key_parity" => self . output_key_parity ( ) . into ( ) ,
114
+ "scripts" => tap_scripts_to_val ( & self ) ,
115
+ _ => {
116
+ return None ;
117
+ }
118
+ } )
119
+ }
120
+ }
121
+
122
+ /// As a flat Array of Script, with no leaf versions
123
+ pub fn tap_scripts_to_val ( tapinfo : & TaprootSpendInfo ) -> Value {
124
+ let scripts_vers = tapinfo. script_map ( ) . keys ( ) ;
125
+ scripts_vers. map ( |( script, _) | script. clone ( ) ) . collect ( )
126
+ }
127
+
151
128
impl TryFrom < Value > for TaprootSpendInfo {
152
129
type Error = Error ;
153
130
fn try_from ( value : Value ) -> Result < Self > {
154
131
Ok ( match value {
155
132
Value :: TapInfo ( tapinfo) => tapinfo,
156
- Value :: Descriptor ( desc) => match desc . definite ( ) ? {
157
- miniscript :: Descriptor :: Tr ( tr_desc ) => ( * tr_desc . spend_info ( ) ) . clone ( ) ,
158
- _ => bail ! ( Error :: NotTapInfoLike ( Value :: Descriptor ( desc) . into( ) ) ) ,
159
- } ,
133
+ Value :: Descriptor ( desc) => ( * desc
134
+ . tap_info ( ) ?
135
+ . ok_or_else ( || Error :: NotTapInfoLike ( Value :: Descriptor ( desc) . into ( ) ) ) ? )
136
+ . clone ( ) ,
160
137
v => bail ! ( Error :: NotTapInfoLike ( v. into( ) ) ) ,
161
138
} )
162
139
}
0 commit comments