1use core::fmt;
10use std::fmt::Write;
11use std::str::FromStr;
12
13use elements::{self, secp256k1_zkp, Address, Script};
14
15use super::checksum::verify_checksum;
16use super::{SortedMultiVec, ELMTS_STR};
17use crate::descriptor::checksum;
18use crate::expression::{self, FromTree};
19use crate::miniscript::context::{ScriptContext, ScriptContextError};
20use crate::policy::{semantic, Liftable};
21use crate::util::varint_len;
22use crate::{
23 elementssig_to_rawsig, Error, ForEachKey, Miniscript, MiniscriptKey, Satisfier, Segwitv0,
24 ToPublicKey, TranslatePk, Translator,
25};
26#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
28pub struct Wsh<Pk: MiniscriptKey> {
29 inner: WshInner<Pk>,
31}
32
33impl<Pk: MiniscriptKey> Wsh<Pk> {
34 pub fn into_inner(self) -> WshInner<Pk> {
36 self.inner
37 }
38
39 pub fn as_inner(&self) -> &WshInner<Pk> {
41 &self.inner
42 }
43
44 pub fn new(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
46 Segwitv0::top_level_checks(&ms)?;
48 Ok(Self {
49 inner: WshInner::Ms(ms),
50 })
51 }
52
53 pub fn new_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
55 Ok(Self {
58 inner: WshInner::SortedMulti(SortedMultiVec::new(k, pks)?),
59 })
60 }
61
62 pub fn to_string_no_el_pref(&self, f: &mut checksum::Formatter) -> fmt::Result {
64 match self.inner {
65 WshInner::SortedMulti(ref smv) => write!(f, "wsh({})", smv),
66 WshInner::Ms(ref ms) => write!(f, "wsh({})", ms),
67 }
68 }
69
70 pub fn sanity_check(&self) -> Result<(), Error> {
72 match self.inner {
73 WshInner::SortedMulti(ref smv) => smv.sanity_check()?,
74 WshInner::Ms(ref ms) => ms.sanity_check()?,
75 }
76 Ok(())
77 }
78
79 pub fn max_weight_to_satisfy(&self) -> Result<usize, Error> {
88 let (redeem_script_size, max_sat_elems, max_sat_size) = match self.inner {
89 WshInner::SortedMulti(ref smv) => (
90 smv.script_size(),
91 smv.max_satisfaction_witness_elements(),
92 smv.max_satisfaction_size(),
93 ),
94 WshInner::Ms(ref ms) => (
95 ms.script_size(),
96 ms.max_satisfaction_witness_elements()?,
97 ms.max_satisfaction_size()?,
98 ),
99 };
100 let stack_varint_diff = varint_len(max_sat_elems) - varint_len(0);
103
104 Ok(stack_varint_diff + varint_len(redeem_script_size) + redeem_script_size + max_sat_size)
105 }
106
107 #[deprecated(note = "use max_weight_to_satisfy instead")]
117 pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
118 let (script_size, max_sat_elems, max_sat_size) = match self.inner {
119 WshInner::SortedMulti(ref smv) => (
120 smv.script_size(),
121 smv.max_satisfaction_witness_elements(),
122 smv.max_satisfaction_size(),
123 ),
124 WshInner::Ms(ref ms) => (
125 ms.script_size(),
126 ms.max_satisfaction_witness_elements()?,
127 ms.max_satisfaction_size()?,
128 ),
129 };
130 Ok(4 + varint_len(script_size) +
132 script_size +
133 varint_len(max_sat_elems) +
134 max_sat_size)
135 }
136}
137
138#[rustfmt::skip]
139impl_block_str!(
140 Wsh<Pk>,
141 pub(super) fn from_inner_tree(top: &expression::Tree<'_>, ) -> Result<Self, Error>
143 {
144 if top.name == "wsh" && top.args.len() == 1 {
145 let top = &top.args[0];
146 if top.name == "sortedmulti" {
147 return Ok(Wsh {
148 inner: WshInner::SortedMulti(SortedMultiVec::from_tree(top)?),
149 });
150 }
151 let sub = Miniscript::from_tree(top)?;
152 Segwitv0::top_level_checks(&sub)?;
153 Ok(Wsh {
154 inner: WshInner::Ms(sub),
155 })
156 } else {
157 Err(Error::Unexpected(format!(
158 "{}({} args) while parsing wsh descriptor",
159 top.name,
160 top.args.len(),
161 )))
162 }
163 }
164);
165
166impl<Pk: MiniscriptKey + ToPublicKey> Wsh<Pk> {
167 pub fn script_pubkey(&self) -> Script {
169 self.inner_script().to_v0_p2wsh()
170 }
171
172 pub fn address(
174 &self,
175 blinder: Option<secp256k1_zkp::PublicKey>,
176 params: &'static elements::AddressParams,
177 ) -> elements::Address {
178 match self.inner {
179 WshInner::SortedMulti(ref smv) => {
180 elements::Address::p2wsh(&smv.encode(), blinder, params)
181 }
182 WshInner::Ms(ref ms) => elements::Address::p2wsh(&ms.encode(), blinder, params),
183 }
184 }
185
186 pub fn inner_script(&self) -> Script {
188 match self.inner {
189 WshInner::SortedMulti(ref smv) => smv.encode(),
190 WshInner::Ms(ref ms) => ms.encode(),
191 }
192 }
193
194 pub fn ecdsa_sighash_script_code(&self) -> Script {
196 self.inner_script()
197 }
198
199 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
203 where
204 S: Satisfier<Pk>,
205 {
206 let mut witness = match self.inner {
207 WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
208 WshInner::Ms(ref ms) => ms.satisfy(satisfier)?,
209 };
210 let witness_script = self.inner_script();
211 witness.push(witness_script.into_bytes());
212 let script_sig = Script::new();
213 Ok((witness, script_sig))
214 }
215
216 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
220 where
221 S: Satisfier<Pk>,
222 {
223 let mut witness = match self.inner {
224 WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
225 WshInner::Ms(ref ms) => ms.satisfy_malleable(satisfier)?,
226 };
227 witness.push(self.inner_script().into_bytes());
228 let script_sig = Script::new();
229 Ok((witness, script_sig))
230 }
231}
232
233#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
235pub enum WshInner<Pk: MiniscriptKey> {
236 SortedMulti(SortedMultiVec<Pk, Segwitv0>),
238 Ms(Miniscript<Pk, Segwitv0>),
242}
243
244impl<Pk: MiniscriptKey> Liftable<Pk> for Wsh<Pk> {
245 fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
246 match self.inner {
247 WshInner::SortedMulti(ref smv) => smv.lift(),
248 WshInner::Ms(ref ms) => ms.lift(),
249 }
250 }
251}
252
253impl_from_tree!(
254 Wsh<Pk>,
255 fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
256 if top.name == "elwsh" && top.args.len() == 1 {
257 let top = &top.args[0];
258 if top.name == "sortedmulti" {
259 return Ok(Wsh {
260 inner: WshInner::SortedMulti(SortedMultiVec::from_tree(top)?),
261 });
262 }
263 let sub = Miniscript::from_tree(top)?;
264 Segwitv0::top_level_checks(&sub)?;
265 Ok(Wsh {
266 inner: WshInner::Ms(sub),
267 })
268 } else {
269 Err(Error::Unexpected(format!(
270 "{}({} args) while parsing wsh descriptor",
271 top.name,
272 top.args.len(),
273 )))
274 }
275 }
276);
277
278impl<Pk: MiniscriptKey> fmt::Debug for Wsh<Pk> {
279 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
280 match self.inner {
281 WshInner::SortedMulti(ref smv) => write!(f, "{}wsh({:?})", ELMTS_STR, smv),
282 WshInner::Ms(ref ms) => write!(f, "{}wsh({:?})", ELMTS_STR, ms),
283 }
284 }
285}
286
287impl<Pk: MiniscriptKey> fmt::Display for Wsh<Pk> {
288 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
289 let mut wrapped_f = checksum::Formatter::new(f);
290 match self.inner {
291 WshInner::SortedMulti(ref smv) => write!(wrapped_f, "{}wsh({})", ELMTS_STR, smv)?,
292 WshInner::Ms(ref ms) => write!(wrapped_f, "{}wsh({})", ELMTS_STR, ms)?,
293 }
294 wrapped_f.write_checksum_if_not_alt()
295 }
296}
297
298impl_from_str!(
299 Wsh<Pk>,
300 type Err = Error;,
301 fn from_str(s: &str) -> Result<Self, Self::Err> {
302 let desc_str = verify_checksum(s)?;
303 let top = expression::Tree::from_str(desc_str)?;
304 Wsh::<Pk>::from_tree(&top)
305 }
306);
307
308impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wsh<Pk> {
309 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
310 where
311 Pk: 'a,
312 {
313 match self.inner {
314 WshInner::SortedMulti(ref smv) => smv.for_each_key(pred),
315 WshInner::Ms(ref ms) => ms.for_each_key(pred),
316 }
317 }
318}
319
320impl<P: MiniscriptKey, Q: MiniscriptKey> TranslatePk<P, Q> for Wsh<P> {
321 type Output = Wsh<Q>;
322
323 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
324 where
325 T: Translator<P, Q, E>,
326 {
327 let inner = match self.inner {
328 WshInner::SortedMulti(ref smv) => WshInner::SortedMulti(smv.translate_pk(t)?),
329 WshInner::Ms(ref ms) => WshInner::Ms(ms.translate_pk(t)?),
330 };
331 Ok(Wsh { inner })
332 }
333}
334
335#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
337pub struct Wpkh<Pk: MiniscriptKey> {
338 pk: Pk,
340}
341
342impl<Pk: MiniscriptKey> Wpkh<Pk> {
343 pub fn new(pk: Pk) -> Result<Self, Error> {
345 if pk.is_uncompressed() {
347 Err(Error::ContextError(ScriptContextError::CompressedOnly(
348 pk.to_string(),
349 )))
350 } else {
351 Ok(Self { pk })
352 }
353 }
354
355 pub fn into_inner(self) -> Pk {
357 self.pk
358 }
359
360 pub fn as_inner(&self) -> &Pk {
362 &self.pk
363 }
364
365 pub fn to_string_no_el_pref(&self, f: &mut checksum::Formatter) -> fmt::Result {
367 write!(f, "wpkh({})", self.pk)
368 }
369
370 pub fn sanity_check(&self) -> Result<(), Error> {
372 if self.pk.is_uncompressed() {
373 Err(Error::ContextError(ScriptContextError::CompressedOnly(
374 self.pk.to_string(),
375 )))
376 } else {
377 Ok(())
378 }
379 }
380
381 pub fn max_weight_to_satisfy(&self) -> usize {
387 let stack_items_size = 73 + Segwitv0::pk_len(&self.pk);
389 let stack_varint_diff = varint_len(2) - varint_len(0);
391 stack_varint_diff + stack_items_size
392 }
393
394 pub fn max_satisfaction_weight(&self) -> usize {
401 4 + 1 + 73 + Segwitv0::pk_len(&self.pk)
402 }
403
404 pub(super) fn from_inner_tree(top: &expression::Tree<'_>) -> Result<Self, Error>
406 where
407 Pk: FromStr,
408 <Pk as FromStr>::Err: ToString,
409 {
410 if top.name == "wpkh" && top.args.len() == 1 {
411 Ok(Wpkh::new(expression::terminal(&top.args[0], |pk| {
412 Pk::from_str(pk)
413 })?)?)
414 } else {
415 Err(Error::Unexpected(format!(
416 "{}({} args) while parsing wpkh descriptor",
417 top.name,
418 top.args.len(),
419 )))
420 }
421 }
422}
423
424impl<Pk: MiniscriptKey + ToPublicKey> Wpkh<Pk> {
425 pub fn script_pubkey(&self) -> Script {
427 let addr = self.address(None, &elements::AddressParams::ELEMENTS);
428 addr.script_pubkey()
429 }
430
431 pub fn address(
433 &self,
434 blinder: Option<secp256k1_zkp::PublicKey>,
435 params: &'static elements::AddressParams,
436 ) -> elements::Address {
437 Address::p2wpkh(&self.pk.to_public_key(), blinder, params)
438 }
439
440 pub fn inner_script(&self) -> Script {
442 self.script_pubkey()
443 }
444
445 pub fn ecdsa_sighash_script_code(&self) -> Script {
447 let addr = elements::Address::p2pkh(
452 &self.pk.to_public_key(),
453 None,
454 &elements::AddressParams::ELEMENTS,
455 );
456 addr.script_pubkey()
459 }
460
461 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
465 where
466 S: Satisfier<Pk>,
467 {
468 if let Some(sig) = satisfier.lookup_ecdsa_sig(&self.pk) {
469 let sig_vec = elementssig_to_rawsig(&sig);
470 let script_sig = Script::new();
471 let witness = vec![sig_vec, self.pk.to_public_key().to_bytes()];
472 Ok((witness, script_sig))
473 } else {
474 Err(Error::MissingSig(self.pk.to_public_key()))
475 }
476 }
477
478 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
482 where
483 S: Satisfier<Pk>,
484 {
485 self.get_satisfaction(satisfier)
486 }
487}
488
489impl<Pk: MiniscriptKey> fmt::Debug for Wpkh<Pk> {
490 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
491 write!(f, "{}wpkh({:?})", ELMTS_STR, self.pk)
492 }
493}
494
495impl<Pk: MiniscriptKey> fmt::Display for Wpkh<Pk> {
496 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
497 let mut wrapped_f = checksum::Formatter::new(f);
498 write!(wrapped_f, "{}wpkh({})", ELMTS_STR, self.pk)?;
499 wrapped_f.write_checksum_if_not_alt()
500 }
501}
502
503impl<Pk: MiniscriptKey> Liftable<Pk> for Wpkh<Pk> {
504 fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
505 Ok(semantic::Policy::Key(self.pk.clone()))
506 }
507}
508
509impl_from_tree!(
510 Wpkh<Pk>,
511 fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
512 if top.name == "elwpkh" && top.args.len() == 1 {
513 Ok(Wpkh::new(expression::terminal(&top.args[0], |pk| {
514 Pk::from_str(pk)
515 })?)?)
516 } else {
517 Err(Error::Unexpected(format!(
518 "{}({} args) while parsing wpkh descriptor",
519 top.name,
520 top.args.len(),
521 )))
522 }
523 }
524);
525
526impl_from_str!(
527 Wpkh<Pk>,
528 type Err = Error;,
529 fn from_str(s: &str) -> Result<Self, Self::Err> {
530 let desc_str = verify_checksum(s)?;
531 let top = expression::Tree::from_str(desc_str)?;
532 Self::from_tree(&top)
533 }
534);
535
536impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wpkh<Pk> {
537 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool
538 where
539 Pk: 'a,
540 {
541 pred(&self.pk)
542 }
543}
544
545impl<P: MiniscriptKey, Q: MiniscriptKey> TranslatePk<P, Q> for Wpkh<P> {
546 type Output = Wpkh<Q>;
547
548 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
549 where
550 T: Translator<P, Q, E>,
551 {
552 Ok(Wpkh::new(t.pk(&self.pk)?).expect("Uncompressed keys in Wpkh"))
553 }
554}