@@ -15,9 +15,29 @@ use miniscript::psbt::{PsbtExt, PsbtInputExt};
15
15
use miniscript:: { Descriptor , DescriptorPublicKey } ;
16
16
17
17
fn main ( ) {
18
- // Defining the descriptor
18
+ // Defining the descriptor keys
19
19
let secp256k1 = secp256k1:: Secp256k1 :: new ( ) ;
20
- let s = "wsh(t:or_c(pk(027a3565454fe1b749bccaef22aff72843a9c3efefd7b16ac54537a0c23f0ec0de),v:thresh(1,pkh(032d672a1a91cc39d154d366cd231983661b0785c7f27bc338447565844f4a6813),a:pkh(03417129311ed34c242c012cd0a3e0b9bca0065f742d0dfb63c78083ea6a02d4d9),a:pkh(025a687659658baeabdfc415164528065be7bcaade19342241941e556557f01e28))))#7hut9ukn" ;
20
+ let keys = vec ! [
21
+ "027a3565454fe1b749bccaef22aff72843a9c3efefd7b16ac54537a0c23f0ec0de" ,
22
+ "032d672a1a91cc39d154d366cd231983661b0785c7f27bc338447565844f4a6813" ,
23
+ "03417129311ed34c242c012cd0a3e0b9bca0065f742d0dfb63c78083ea6a02d4d9" ,
24
+ "025a687659658baeabdfc415164528065be7bcaade19342241941e556557f01e28" ,
25
+ ] ;
26
+ // The wsh descriptor indicates a Witness Script Hash, meaning the descriptor is for a SegWit script.
27
+ // wsh(or(pk(A),thresh(1,pkh(B),pkh(C),pkh(D))))
28
+
29
+ // Let's break it down:
30
+ // t:or_c specifies an "or" construct, which means the script can be satisfied by one of the given conditions:
31
+ // pk(A) OR thresh(1,pkh(B),pkh(C),pkh(D))
32
+ // Inside threshold condition atleast 1 out of all given conditions should satisfy.
33
+
34
+ // By constructing transactions using this wsh descriptor and signing them appropriately,
35
+ // you can create flexible spending policies that enable different spending paths and conditions depending on the
36
+ // transaction's inputs and outputs.
37
+ let s = format ! (
38
+ "wsh(t:or_c(pk({}),v:thresh(1,pkh({}),a:pkh({}),a:pkh({}))))#7hut9ukn" ,
39
+ keys[ 0 ] , keys[ 1 ] , keys[ 2 ] , keys[ 3 ]
40
+ ) ;
21
41
let bridge_descriptor = Descriptor :: from_str ( & s) . expect ( "parse descriptor string" ) ;
22
42
23
43
assert ! ( bridge_descriptor. sanity_check( ) . is_ok( ) ) ;
@@ -116,10 +136,12 @@ fn main() {
116
136
value : amount * 4 / 5 ,
117
137
} ) ;
118
138
119
- // Plan the Transaction using available assets
120
- // The descriptor is : or(pk(A),thresh(1,pkh(B),pkh(C),pkh(D)))
121
- // For the context of planning in this example, We will only provide the key A as an asset
122
- // This will satisfy the pk(A) and since we have an OR, This should be sufficient to satisfy the given policy.
139
+ // Consider that out of all the keys required to sign the descriptor, we only have some handful of assets.
140
+ // We can plan the PSBT with only few assets(keys or hashes) if that are enough for satisfying any policy.
141
+ //
142
+ // Here for example assume that we only have one key available i.e Key A(as seen from the descriptor above)
143
+ // Key A is enough to satisfy the given descriptor because it is OR.
144
+ // We have to add the key to `Asset` and then obtain plan with only available signature if the descriptor can be satisfied.
123
145
let mut assets = Assets :: new ( ) ;
124
146
assets = assets. add (
125
147
DescriptorPublicKey :: from_str (
@@ -128,12 +150,14 @@ fn main() {
128
150
. unwrap ( ) ,
129
151
) ;
130
152
131
- // Obtain the result of the plan based on provided assets
132
- let result = bridge_descriptor. clone ( ) . get_plan ( & assets) ;
153
+ // Obtain the Plan based on available Assets
154
+ let plan = bridge_descriptor. clone ( ) . get_plan ( & assets) . unwrap ( ) ;
133
155
134
156
// Creating a PSBT Input
135
157
let mut input = psbt:: Input :: default ( ) ;
136
- result. unwrap ( ) . update_psbt_input ( & mut input) ;
158
+
159
+ // Update the PSBT input from the result which we have obtained from the Plan.
160
+ plan. update_psbt_input ( & mut input) ;
137
161
input
138
162
. update_with_descriptor_unchecked ( & bridge_descriptor)
139
163
. unwrap ( ) ;
@@ -158,16 +182,11 @@ fn main() {
158
182
159
183
// Finally construct the signature and add to psbt
160
184
let sig1 = secp256k1. sign_ecdsa ( & msg, & sk1) ;
161
- let pk1 = backup1_private. public_key ( & secp256k1) ;
185
+ let key_a = backup1_private. public_key ( & secp256k1) ;
162
186
assert ! ( secp256k1. verify_ecdsa( & msg, & sig1, & pk1. inner) . is_ok( ) ) ;
163
187
164
- // Second key just in case
165
- let sig2 = secp256k1. sign_ecdsa ( & msg, & sk2) ;
166
- let pk2 = backup2_private. public_key ( & secp256k1) ;
167
- assert ! ( secp256k1. verify_ecdsa( & msg, & sig2, & pk2. inner) . is_ok( ) ) ;
168
-
169
188
psbt. inputs [ 0 ] . partial_sigs . insert (
170
- pk1 ,
189
+ key_a ,
171
190
bitcoin:: ecdsa:: Signature {
172
191
sig : sig1,
173
192
hash_ty : hash_ty,
0 commit comments