1use core::fmt;
20
21use bitcoin::{self, Address, Network, Script};
22
23use super::checksum::{self, verify_checksum};
24use super::SortedMultiVec;
25use crate::expression::{self, FromTree};
26use crate::miniscript::context::{ScriptContext, ScriptContextError};
27use crate::policy::{semantic, Liftable};
28use crate::prelude::*;
29use crate::util::varint_len;
30use crate::{
31 Error, ForEachKey, Miniscript, MiniscriptKey, Satisfier, Segwitv0, ToPublicKey, TranslatePk,
32 Translator,
33};
34#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
36pub struct Wsh<Pk: MiniscriptKey> {
37 inner: WshInner<Pk>,
39}
40
41impl<Pk: MiniscriptKey> Wsh<Pk> {
42 pub fn into_inner(self) -> WshInner<Pk> {
44 self.inner
45 }
46
47 pub fn as_inner(&self) -> &WshInner<Pk> {
49 &self.inner
50 }
51
52 pub fn new(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
54 Segwitv0::top_level_checks(&ms)?;
56 Ok(Self {
57 inner: WshInner::Ms(ms),
58 })
59 }
60
61 pub fn new_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
63 Ok(Self {
66 inner: WshInner::SortedMulti(SortedMultiVec::new(k, pks)?),
67 })
68 }
69
70 #[deprecated(since = "8.0.0", note = "use format!(\"{:#}\") instead")]
72 pub fn to_string_no_checksum(&self) -> String {
73 format!("{:#}", self)
74 }
75
76 pub fn sanity_check(&self) -> Result<(), Error> {
78 match self.inner {
79 WshInner::SortedMulti(ref smv) => smv.sanity_check()?,
80 WshInner::Ms(ref ms) => ms.sanity_check()?,
81 }
82 Ok(())
83 }
84
85 pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
95 let (script_size, max_sat_elems, max_sat_size) = match self.inner {
96 WshInner::SortedMulti(ref smv) => (
97 smv.script_size(),
98 smv.max_satisfaction_witness_elements(),
99 smv.max_satisfaction_size(),
100 ),
101 WshInner::Ms(ref ms) => (
102 ms.script_size(),
103 ms.max_satisfaction_witness_elements()?,
104 ms.max_satisfaction_size()?,
105 ),
106 };
107 Ok(4 + varint_len(script_size) +
109 script_size +
110 varint_len(max_sat_elems) +
111 max_sat_size)
112 }
113}
114
115impl<Pk: MiniscriptKey + ToPublicKey> Wsh<Pk> {
116 pub fn script_pubkey(&self) -> Script {
118 self.inner_script().to_v0_p2wsh()
119 }
120
121 pub fn address(&self, network: Network) -> Address {
123 match self.inner {
124 WshInner::SortedMulti(ref smv) => Address::p2wsh(&smv.encode(), network),
125 WshInner::Ms(ref ms) => Address::p2wsh(&ms.encode(), network),
126 }
127 }
128
129 pub fn inner_script(&self) -> Script {
131 match self.inner {
132 WshInner::SortedMulti(ref smv) => smv.encode(),
133 WshInner::Ms(ref ms) => ms.encode(),
134 }
135 }
136
137 pub fn ecdsa_sighash_script_code(&self) -> Script {
139 self.inner_script()
140 }
141
142 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
146 where
147 S: Satisfier<Pk>,
148 {
149 let mut witness = match self.inner {
150 WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
151 WshInner::Ms(ref ms) => ms.satisfy(satisfier)?,
152 };
153 let witness_script = self.inner_script();
154 witness.push(witness_script.into_bytes());
155 let script_sig = Script::new();
156 Ok((witness, script_sig))
157 }
158
159 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
163 where
164 S: Satisfier<Pk>,
165 {
166 let mut witness = match self.inner {
167 WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
168 WshInner::Ms(ref ms) => ms.satisfy_malleable(satisfier)?,
169 };
170 witness.push(self.inner_script().into_bytes());
171 let script_sig = Script::new();
172 Ok((witness, script_sig))
173 }
174}
175
176#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
178pub enum WshInner<Pk: MiniscriptKey> {
179 SortedMulti(SortedMultiVec<Pk, Segwitv0>),
181 Ms(Miniscript<Pk, Segwitv0>),
183}
184
185impl<Pk: MiniscriptKey> Liftable<Pk> for Wsh<Pk> {
186 fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
187 match self.inner {
188 WshInner::SortedMulti(ref smv) => smv.lift(),
189 WshInner::Ms(ref ms) => ms.lift(),
190 }
191 }
192}
193
194impl_from_tree!(
195 Wsh<Pk>,
196 fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
197 if top.name == "wsh" && top.args.len() == 1 {
198 let top = &top.args[0];
199 if top.name == "sortedmulti" {
200 return Ok(Wsh {
201 inner: WshInner::SortedMulti(SortedMultiVec::from_tree(top)?),
202 });
203 }
204 let sub = Miniscript::from_tree(top)?;
205 Segwitv0::top_level_checks(&sub)?;
206 Ok(Wsh {
207 inner: WshInner::Ms(sub),
208 })
209 } else {
210 Err(Error::Unexpected(format!(
211 "{}({} args) while parsing wsh descriptor",
212 top.name,
213 top.args.len(),
214 )))
215 }
216 }
217);
218
219impl<Pk: MiniscriptKey> fmt::Debug for Wsh<Pk> {
220 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221 match self.inner {
222 WshInner::SortedMulti(ref smv) => write!(f, "wsh({:?})", smv),
223 WshInner::Ms(ref ms) => write!(f, "wsh({:?})", ms),
224 }
225 }
226}
227
228impl<Pk: MiniscriptKey> fmt::Display for Wsh<Pk> {
229 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
230 use fmt::Write;
231 let mut wrapped_f = checksum::Formatter::new(f);
232 match self.inner {
233 WshInner::SortedMulti(ref smv) => write!(wrapped_f, "wsh({})", smv)?,
234 WshInner::Ms(ref ms) => write!(wrapped_f, "wsh({})", ms)?,
235 }
236 wrapped_f.write_checksum_if_not_alt()
237 }
238}
239
240impl_from_str!(
241 Wsh<Pk>,
242 type Err = Error;,
243 fn from_str(s: &str) -> Result<Self, Self::Err> {
244 let desc_str = verify_checksum(s)?;
245 let top = expression::Tree::from_str(desc_str)?;
246 Wsh::<Pk>::from_tree(&top)
247 }
248);
249
250impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wsh<Pk> {
251 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
252 where
253 Pk: 'a,
254 {
255 match self.inner {
256 WshInner::SortedMulti(ref smv) => smv.for_each_key(pred),
257 WshInner::Ms(ref ms) => ms.for_each_key(pred),
258 }
259 }
260}
261
262impl<P, Q> TranslatePk<P, Q> for Wsh<P>
263where
264 P: MiniscriptKey,
265 Q: MiniscriptKey,
266{
267 type Output = Wsh<Q>;
268
269 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
270 where
271 T: Translator<P, Q, E>,
272 {
273 let inner = match self.inner {
274 WshInner::SortedMulti(ref smv) => WshInner::SortedMulti(smv.translate_pk(t)?),
275 WshInner::Ms(ref ms) => WshInner::Ms(ms.translate_pk(t)?),
276 };
277 Ok(Wsh { inner })
278 }
279}
280
281#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
283pub struct Wpkh<Pk: MiniscriptKey> {
284 pk: Pk,
286}
287
288impl<Pk: MiniscriptKey> Wpkh<Pk> {
289 pub fn new(pk: Pk) -> Result<Self, Error> {
291 if pk.is_uncompressed() {
293 Err(Error::ContextError(ScriptContextError::CompressedOnly(
294 pk.to_string(),
295 )))
296 } else {
297 Ok(Self { pk })
298 }
299 }
300
301 pub fn into_inner(self) -> Pk {
303 self.pk
304 }
305
306 pub fn as_inner(&self) -> &Pk {
308 &self.pk
309 }
310
311 #[deprecated(since = "8.0.0", note = "use format!(\"{:#}\") instead")]
313 pub fn to_string_no_checksum(&self) -> String {
314 format!("{:#}", self)
315 }
316
317 pub fn sanity_check(&self) -> Result<(), Error> {
319 if self.pk.is_uncompressed() {
320 Err(Error::ContextError(ScriptContextError::CompressedOnly(
321 self.pk.to_string(),
322 )))
323 } else {
324 Ok(())
325 }
326 }
327
328 pub fn max_satisfaction_weight(&self) -> usize {
335 4 + 1 + 73 + Segwitv0::pk_len(&self.pk)
336 }
337}
338
339impl<Pk: MiniscriptKey + ToPublicKey> Wpkh<Pk> {
340 pub fn script_pubkey(&self) -> Script {
342 let addr = Address::p2wpkh(&self.pk.to_public_key(), Network::Bitcoin)
343 .expect("wpkh descriptors have compressed keys");
344 addr.script_pubkey()
345 }
346
347 pub fn address(&self, network: Network) -> Address {
349 Address::p2wpkh(&self.pk.to_public_key(), network)
350 .expect("Rust Miniscript types don't allow uncompressed pks in segwit descriptors")
351 }
352
353 pub fn inner_script(&self) -> Script {
355 self.script_pubkey()
356 }
357
358 pub fn ecdsa_sighash_script_code(&self) -> Script {
360 let addr = Address::p2pkh(&self.pk.to_public_key(), Network::Bitcoin);
365 addr.script_pubkey()
366 }
367
368 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
372 where
373 S: Satisfier<Pk>,
374 {
375 if let Some(sig) = satisfier.lookup_ecdsa_sig(&self.pk) {
376 let sig_vec = sig.to_vec();
377 let script_sig = Script::new();
378 let witness = vec![sig_vec, self.pk.to_public_key().to_bytes()];
379 Ok((witness, script_sig))
380 } else {
381 Err(Error::MissingSig(self.pk.to_public_key()))
382 }
383 }
384
385 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
389 where
390 S: Satisfier<Pk>,
391 {
392 self.get_satisfaction(satisfier)
393 }
394}
395
396impl<Pk: MiniscriptKey> fmt::Debug for Wpkh<Pk> {
397 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
398 write!(f, "wpkh({:?})", self.pk)
399 }
400}
401
402impl<Pk: MiniscriptKey> fmt::Display for Wpkh<Pk> {
403 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
404 use fmt::Write;
405 let mut wrapped_f = checksum::Formatter::new(f);
406 write!(wrapped_f, "wpkh({})", self.pk)?;
407 wrapped_f.write_checksum_if_not_alt()
408 }
409}
410
411impl<Pk: MiniscriptKey> Liftable<Pk> for Wpkh<Pk> {
412 fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
413 Ok(semantic::Policy::Key(self.pk.clone()))
414 }
415}
416
417impl_from_tree!(
418 Wpkh<Pk>,
419 fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
420 if top.name == "wpkh" && top.args.len() == 1 {
421 Ok(Wpkh::new(expression::terminal(&top.args[0], |pk| {
422 Pk::from_str(pk)
423 })?)?)
424 } else {
425 Err(Error::Unexpected(format!(
426 "{}({} args) while parsing wpkh descriptor",
427 top.name,
428 top.args.len(),
429 )))
430 }
431 }
432);
433
434impl_from_str!(
435 Wpkh<Pk>,
436 type Err = Error;,
437 fn from_str(s: &str) -> Result<Self, Self::Err> {
438 let desc_str = verify_checksum(s)?;
439 let top = expression::Tree::from_str(desc_str)?;
440 Self::from_tree(&top)
441 }
442);
443
444impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wpkh<Pk> {
445 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool
446 where
447 Pk: 'a,
448 {
449 pred(&self.pk)
450 }
451}
452
453impl<P, Q> TranslatePk<P, Q> for Wpkh<P>
454where
455 P: MiniscriptKey,
456 Q: MiniscriptKey,
457{
458 type Output = Wpkh<Q>;
459
460 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
461 where
462 T: Translator<P, Q, E>,
463 {
464 Ok(Wpkh::new(t.pk(&self.pk)?).expect("Uncompressed keys in Wpkh"))
465 }
466}