1use core::fmt;
10
11use bellscoin::{Address, Network, ScriptBuf};
12
13use super::checksum::{self, verify_checksum};
14use super::SortedMultiVec;
15use crate::expression::{self, FromTree};
16use crate::miniscript::context::{ScriptContext, ScriptContextError};
17use crate::policy::{semantic, Liftable};
18use crate::prelude::*;
19use crate::util::varint_len;
20use crate::{
21 Error, ForEachKey, Miniscript, MiniscriptKey, Satisfier, Segwitv0, ToPublicKey, TranslateErr,
22 TranslatePk, Translator,
23};
24#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
26pub struct Wsh<Pk: MiniscriptKey> {
27 inner: WshInner<Pk>,
29}
30
31impl<Pk: MiniscriptKey> Wsh<Pk> {
32 pub fn into_inner(self) -> WshInner<Pk> {
34 self.inner
35 }
36
37 pub fn as_inner(&self) -> &WshInner<Pk> {
39 &self.inner
40 }
41
42 pub fn new(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
44 Segwitv0::top_level_checks(&ms)?;
46 Ok(Self {
47 inner: WshInner::Ms(ms),
48 })
49 }
50
51 pub fn new_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
53 Ok(Self {
56 inner: WshInner::SortedMulti(SortedMultiVec::new(k, pks)?),
57 })
58 }
59
60 #[deprecated(since = "8.0.0", note = "use format!(\"{:#}\") instead")]
62 pub fn to_string_no_checksum(&self) -> String {
63 format!("{:#}", self)
64 }
65
66 pub fn sanity_check(&self) -> Result<(), Error> {
68 match self.inner {
69 WshInner::SortedMulti(ref smv) => smv.sanity_check()?,
70 WshInner::Ms(ref ms) => ms.sanity_check()?,
71 }
72 Ok(())
73 }
74
75 pub fn max_weight_to_satisfy(&self) -> Result<usize, Error> {
84 let (redeem_script_size, max_sat_elems, max_sat_size) = match self.inner {
85 WshInner::SortedMulti(ref smv) => (
86 smv.script_size(),
87 smv.max_satisfaction_witness_elements(),
88 smv.max_satisfaction_size(),
89 ),
90 WshInner::Ms(ref ms) => (
91 ms.script_size(),
92 ms.max_satisfaction_witness_elements()?,
93 ms.max_satisfaction_size()?,
94 ),
95 };
96 let stack_varint_diff = varint_len(max_sat_elems) - varint_len(0);
99
100 Ok(stack_varint_diff + varint_len(redeem_script_size) + redeem_script_size + max_sat_size)
101 }
102
103 #[deprecated(note = "use max_weight_to_satisfy instead")]
113 pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
114 let (script_size, max_sat_elems, max_sat_size) = match self.inner {
115 WshInner::SortedMulti(ref smv) => (
116 smv.script_size(),
117 smv.max_satisfaction_witness_elements(),
118 smv.max_satisfaction_size(),
119 ),
120 WshInner::Ms(ref ms) => (
121 ms.script_size(),
122 ms.max_satisfaction_witness_elements()?,
123 ms.max_satisfaction_size()?,
124 ),
125 };
126 Ok(4 + varint_len(script_size) +
128 script_size +
129 varint_len(max_sat_elems) +
130 max_sat_size)
131 }
132}
133
134impl<Pk: MiniscriptKey + ToPublicKey> Wsh<Pk> {
135 pub fn script_pubkey(&self) -> ScriptBuf {
137 self.inner_script().to_v0_p2wsh()
138 }
139
140 pub fn address(&self, network: Network) -> Address {
142 match self.inner {
143 WshInner::SortedMulti(ref smv) => Address::p2wsh(&smv.encode(), network),
144 WshInner::Ms(ref ms) => Address::p2wsh(&ms.encode(), network),
145 }
146 }
147
148 pub fn inner_script(&self) -> ScriptBuf {
150 match self.inner {
151 WshInner::SortedMulti(ref smv) => smv.encode(),
152 WshInner::Ms(ref ms) => ms.encode(),
153 }
154 }
155
156 pub fn ecdsa_sighash_script_code(&self) -> ScriptBuf {
158 self.inner_script()
159 }
160
161 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
165 where
166 S: Satisfier<Pk>,
167 {
168 let mut witness = match self.inner {
169 WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
170 WshInner::Ms(ref ms) => ms.satisfy(satisfier)?,
171 };
172 let witness_script = self.inner_script();
173 witness.push(witness_script.into_bytes());
174 let script_sig = ScriptBuf::new();
175 Ok((witness, script_sig))
176 }
177
178 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
182 where
183 S: Satisfier<Pk>,
184 {
185 let mut witness = match self.inner {
186 WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
187 WshInner::Ms(ref ms) => ms.satisfy_malleable(satisfier)?,
188 };
189 witness.push(self.inner_script().into_bytes());
190 let script_sig = ScriptBuf::new();
191 Ok((witness, script_sig))
192 }
193}
194
195#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
197pub enum WshInner<Pk: MiniscriptKey> {
198 SortedMulti(SortedMultiVec<Pk, Segwitv0>),
200 Ms(Miniscript<Pk, Segwitv0>),
202}
203
204impl<Pk: MiniscriptKey> Liftable<Pk> for Wsh<Pk> {
205 fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
206 match self.inner {
207 WshInner::SortedMulti(ref smv) => smv.lift(),
208 WshInner::Ms(ref ms) => ms.lift(),
209 }
210 }
211}
212
213impl_from_tree!(
214 Wsh<Pk>,
215 fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
216 if top.name == "wsh" && top.args.len() == 1 {
217 let top = &top.args[0];
218 if top.name == "sortedmulti" {
219 return Ok(Wsh {
220 inner: WshInner::SortedMulti(SortedMultiVec::from_tree(top)?),
221 });
222 }
223 let sub = Miniscript::from_tree(top)?;
224 Segwitv0::top_level_checks(&sub)?;
225 Ok(Wsh {
226 inner: WshInner::Ms(sub),
227 })
228 } else {
229 Err(Error::Unexpected(format!(
230 "{}({} args) while parsing wsh descriptor",
231 top.name,
232 top.args.len(),
233 )))
234 }
235 }
236);
237
238impl<Pk: MiniscriptKey> fmt::Debug for Wsh<Pk> {
239 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
240 match self.inner {
241 WshInner::SortedMulti(ref smv) => write!(f, "wsh({:?})", smv),
242 WshInner::Ms(ref ms) => write!(f, "wsh({:?})", ms),
243 }
244 }
245}
246
247impl<Pk: MiniscriptKey> fmt::Display for Wsh<Pk> {
248 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
249 use fmt::Write;
250 let mut wrapped_f = checksum::Formatter::new(f);
251 match self.inner {
252 WshInner::SortedMulti(ref smv) => write!(wrapped_f, "wsh({})", smv)?,
253 WshInner::Ms(ref ms) => write!(wrapped_f, "wsh({})", ms)?,
254 }
255 wrapped_f.write_checksum_if_not_alt()
256 }
257}
258
259impl_from_str!(
260 Wsh<Pk>,
261 type Err = Error;,
262 fn from_str(s: &str) -> Result<Self, Self::Err> {
263 let desc_str = verify_checksum(s)?;
264 let top = expression::Tree::from_str(desc_str)?;
265 Wsh::<Pk>::from_tree(&top)
266 }
267);
268
269impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wsh<Pk> {
270 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool {
271 match self.inner {
272 WshInner::SortedMulti(ref smv) => smv.for_each_key(pred),
273 WshInner::Ms(ref ms) => ms.for_each_key(pred),
274 }
275 }
276}
277
278impl<P, Q> TranslatePk<P, Q> for Wsh<P>
279where
280 P: MiniscriptKey,
281 Q: MiniscriptKey,
282{
283 type Output = Wsh<Q>;
284
285 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, TranslateErr<E>>
286 where
287 T: Translator<P, Q, E>,
288 {
289 let inner = match self.inner {
290 WshInner::SortedMulti(ref smv) => WshInner::SortedMulti(smv.translate_pk(t)?),
291 WshInner::Ms(ref ms) => WshInner::Ms(ms.translate_pk(t)?),
292 };
293 Ok(Wsh { inner })
294 }
295}
296
297#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
299pub struct Wpkh<Pk: MiniscriptKey> {
300 pk: Pk,
302}
303
304impl<Pk: MiniscriptKey> Wpkh<Pk> {
305 pub fn new(pk: Pk) -> Result<Self, ScriptContextError> {
307 match Segwitv0::check_pk(&pk) {
309 Ok(_) => Ok(Wpkh { pk }),
310 Err(e) => Err(e),
311 }
312 }
313
314 pub fn into_inner(self) -> Pk {
316 self.pk
317 }
318
319 pub fn as_inner(&self) -> &Pk {
321 &self.pk
322 }
323
324 #[deprecated(since = "8.0.0", note = "use format!(\"{:#}\") instead")]
326 pub fn to_string_no_checksum(&self) -> String {
327 format!("{:#}", self)
328 }
329
330 pub fn sanity_check(&self) -> Result<(), Error> {
332 if self.pk.is_uncompressed() {
333 Err(Error::ContextError(ScriptContextError::CompressedOnly(
334 self.pk.to_string(),
335 )))
336 } else {
337 Ok(())
338 }
339 }
340
341 pub fn max_weight_to_satisfy(&self) -> usize {
347 let stack_items_size = 73 + Segwitv0::pk_len(&self.pk);
349 let stack_varint_diff = varint_len(2) - varint_len(0);
351 stack_varint_diff + stack_items_size
352 }
353
354 pub fn max_satisfaction_weight(&self) -> usize {
361 4 + 1 + 73 + Segwitv0::pk_len(&self.pk)
362 }
363}
364
365impl<Pk: MiniscriptKey + ToPublicKey> Wpkh<Pk> {
366 pub fn script_pubkey(&self) -> ScriptBuf {
368 let addr = Address::p2wpkh(&self.pk.to_public_key(), Network::Bellscoin)
369 .expect("wpkh descriptors have compressed keys");
370 addr.script_pubkey()
371 }
372
373 pub fn address(&self, network: Network) -> Address {
375 Address::p2wpkh(&self.pk.to_public_key(), network)
376 .expect("Rust Miniscript types don't allow uncompressed pks in segwit descriptors")
377 }
378
379 pub fn inner_script(&self) -> ScriptBuf {
381 self.script_pubkey()
382 }
383
384 pub fn ecdsa_sighash_script_code(&self) -> ScriptBuf {
386 let addr = Address::p2pkh(&self.pk.to_public_key(), Network::Bellscoin);
391 addr.script_pubkey()
392 }
393
394 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
398 where
399 S: Satisfier<Pk>,
400 {
401 if let Some(sig) = satisfier.lookup_ecdsa_sig(&self.pk) {
402 let sig_vec = sig.to_vec();
403 let script_sig = ScriptBuf::new();
404 let witness = vec![sig_vec, self.pk.to_public_key().to_bytes()];
405 Ok((witness, script_sig))
406 } else {
407 Err(Error::MissingSig(self.pk.to_public_key()))
408 }
409 }
410
411 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
415 where
416 S: Satisfier<Pk>,
417 {
418 self.get_satisfaction(satisfier)
419 }
420}
421
422impl<Pk: MiniscriptKey> fmt::Debug for Wpkh<Pk> {
423 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
424 write!(f, "wpkh({:?})", self.pk)
425 }
426}
427
428impl<Pk: MiniscriptKey> fmt::Display for Wpkh<Pk> {
429 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
430 use fmt::Write;
431 let mut wrapped_f = checksum::Formatter::new(f);
432 write!(wrapped_f, "wpkh({})", self.pk)?;
433 wrapped_f.write_checksum_if_not_alt()
434 }
435}
436
437impl<Pk: MiniscriptKey> Liftable<Pk> for Wpkh<Pk> {
438 fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
439 Ok(semantic::Policy::Key(self.pk.clone()))
440 }
441}
442
443impl_from_tree!(
444 Wpkh<Pk>,
445 fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
446 if top.name == "wpkh" && top.args.len() == 1 {
447 Ok(Wpkh::new(expression::terminal(&top.args[0], |pk| {
448 Pk::from_str(pk)
449 })?)?)
450 } else {
451 Err(Error::Unexpected(format!(
452 "{}({} args) while parsing wpkh descriptor",
453 top.name,
454 top.args.len(),
455 )))
456 }
457 }
458);
459
460impl_from_str!(
461 Wpkh<Pk>,
462 type Err = Error;,
463 fn from_str(s: &str) -> Result<Self, Self::Err> {
464 let desc_str = verify_checksum(s)?;
465 let top = expression::Tree::from_str(desc_str)?;
466 Self::from_tree(&top)
467 }
468);
469
470impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wpkh<Pk> {
471 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool {
472 pred(&self.pk)
473 }
474}
475
476impl<P, Q> TranslatePk<P, Q> for Wpkh<P>
477where
478 P: MiniscriptKey,
479 Q: MiniscriptKey,
480{
481 type Output = Wpkh<Q>;
482
483 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, TranslateErr<E>>
484 where
485 T: Translator<P, Q, E>,
486 {
487 let res = Wpkh::new(t.pk(&self.pk)?);
488 match res {
489 Ok(pk) => Ok(pk),
490 Err(e) => Err(TranslateErr::OuterError(Error::from(e))),
491 }
492 }
493}