1use core::convert::TryFrom;
9use core::fmt;
10
11use bitcoin::{Address, Network, ScriptBuf, Weight};
12
13use super::checksum::verify_checksum;
14use super::SortedMultiVec;
15use crate::descriptor::{write_descriptor, DefiniteDescriptorKey};
16use crate::expression::{self, FromTree};
17use crate::miniscript::context::{ScriptContext, ScriptContextError};
18use crate::miniscript::satisfy::{Placeholder, Satisfaction, Witness};
19use crate::plan::AssetProvider;
20use crate::policy::{semantic, Liftable};
21use crate::prelude::*;
22use crate::util::varint_len;
23use crate::{
24 Error, ForEachKey, FromStrKey, Miniscript, MiniscriptKey, Satisfier, Segwitv0, ToPublicKey,
25 TranslateErr, TranslatePk, Translator,
26};
27#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
29pub struct Wsh<Pk: MiniscriptKey> {
30 inner: WshInner<Pk>,
32}
33
34impl<Pk: MiniscriptKey> Wsh<Pk> {
35 pub fn into_inner(self) -> WshInner<Pk> { self.inner }
37
38 pub fn as_inner(&self) -> &WshInner<Pk> { &self.inner }
40
41 pub fn new(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
43 Segwitv0::top_level_checks(&ms)?;
45 Ok(Self { inner: WshInner::Ms(ms) })
46 }
47
48 pub fn new_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
50 Ok(Self { inner: WshInner::SortedMulti(SortedMultiVec::new(k, pks)?) })
53 }
54
55 #[deprecated(since = "8.0.0", note = "use format!(\"{:#}\") instead")]
57 pub fn to_string_no_checksum(&self) -> String { format!("{:#}", self) }
58
59 pub fn sanity_check(&self) -> Result<(), Error> {
61 match self.inner {
62 WshInner::SortedMulti(ref smv) => smv.sanity_check()?,
63 WshInner::Ms(ref ms) => ms.sanity_check()?,
64 }
65 Ok(())
66 }
67
68 pub fn max_weight_to_satisfy(&self) -> Result<Weight, Error> {
77 let (redeem_script_size, max_sat_elems, max_sat_size) = match self.inner {
78 WshInner::SortedMulti(ref smv) => (
79 smv.script_size(),
80 smv.max_satisfaction_witness_elements(),
81 smv.max_satisfaction_size(),
82 ),
83 WshInner::Ms(ref ms) => (
84 ms.script_size(),
85 ms.max_satisfaction_witness_elements()?,
86 ms.max_satisfaction_size()?,
87 ),
88 };
89 let stack_varint_diff = varint_len(max_sat_elems) - varint_len(0);
92
93 Ok(Weight::from_wu(
94 (stack_varint_diff + varint_len(redeem_script_size) + redeem_script_size + max_sat_size)
95 as u64,
96 ))
97 }
98
99 #[deprecated(
109 since = "10.0.0",
110 note = "Use max_weight_to_satisfy instead. The method to count bytes was redesigned and the results will differ from max_weight_to_satisfy. For more details check rust-bitcoin/rust-miniscript#476."
111 )]
112 pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
113 let (script_size, max_sat_elems, max_sat_size) = match self.inner {
114 WshInner::SortedMulti(ref smv) => (
115 smv.script_size(),
116 smv.max_satisfaction_witness_elements(),
117 smv.max_satisfaction_size(),
118 ),
119 WshInner::Ms(ref ms) => (
120 ms.script_size(),
121 ms.max_satisfaction_witness_elements()?,
122 ms.max_satisfaction_size()?,
123 ),
124 };
125 Ok(4 + varint_len(script_size) +
127 script_size +
128 varint_len(max_sat_elems) +
129 max_sat_size)
130 }
131}
132
133impl<Pk: MiniscriptKey + ToPublicKey> Wsh<Pk> {
134 pub fn script_pubkey(&self) -> ScriptBuf { self.inner_script().to_p2wsh() }
136
137 pub fn address(&self, network: Network) -> Address {
139 match self.inner {
140 WshInner::SortedMulti(ref smv) => Address::p2wsh(&smv.encode(), network),
141 WshInner::Ms(ref ms) => Address::p2wsh(&ms.encode(), network),
142 }
143 }
144
145 pub fn inner_script(&self) -> ScriptBuf {
147 match self.inner {
148 WshInner::SortedMulti(ref smv) => smv.encode(),
149 WshInner::Ms(ref ms) => ms.encode(),
150 }
151 }
152
153 pub fn ecdsa_sighash_script_code(&self) -> ScriptBuf { self.inner_script() }
155
156 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
160 where
161 S: Satisfier<Pk>,
162 {
163 let mut witness = match self.inner {
164 WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
165 WshInner::Ms(ref ms) => ms.satisfy(satisfier)?,
166 };
167 let witness_script = self.inner_script();
168 witness.push(witness_script.into_bytes());
169 let script_sig = ScriptBuf::new();
170 Ok((witness, script_sig))
171 }
172
173 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
177 where
178 S: Satisfier<Pk>,
179 {
180 let mut witness = match self.inner {
181 WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
182 WshInner::Ms(ref ms) => ms.satisfy_malleable(satisfier)?,
183 };
184 witness.push(self.inner_script().into_bytes());
185 let script_sig = ScriptBuf::new();
186 Ok((witness, script_sig))
187 }
188}
189
190impl Wsh<DefiniteDescriptorKey> {
191 pub fn plan_satisfaction<P>(
193 &self,
194 provider: &P,
195 ) -> Satisfaction<Placeholder<DefiniteDescriptorKey>>
196 where
197 P: AssetProvider<DefiniteDescriptorKey>,
198 {
199 match &self.inner {
200 WshInner::SortedMulti(sm) => sm.build_template(provider),
201 WshInner::Ms(ms) => ms.build_template(provider),
202 }
203 }
204
205 pub fn plan_satisfaction_mall<P>(
207 &self,
208 provider: &P,
209 ) -> Satisfaction<Placeholder<DefiniteDescriptorKey>>
210 where
211 P: AssetProvider<DefiniteDescriptorKey>,
212 {
213 match &self.inner {
214 WshInner::SortedMulti(sm) => sm.build_template(provider),
215 WshInner::Ms(ms) => ms.build_template_mall(provider),
216 }
217 }
218}
219
220#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
222pub enum WshInner<Pk: MiniscriptKey> {
223 SortedMulti(SortedMultiVec<Pk, Segwitv0>),
225 Ms(Miniscript<Pk, Segwitv0>),
227}
228
229impl<Pk: MiniscriptKey> Liftable<Pk> for Wsh<Pk> {
230 fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
231 match self.inner {
232 WshInner::SortedMulti(ref smv) => smv.lift(),
233 WshInner::Ms(ref ms) => ms.lift(),
234 }
235 }
236}
237
238impl<Pk: FromStrKey> crate::expression::FromTree for Wsh<Pk> {
239 fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
240 if top.name == "wsh" && top.args.len() == 1 {
241 let top = &top.args[0];
242 if top.name == "sortedmulti" {
243 return Ok(Wsh { inner: WshInner::SortedMulti(SortedMultiVec::from_tree(top)?) });
244 }
245 let sub = Miniscript::from_tree(top)?;
246 Segwitv0::top_level_checks(&sub)?;
247 Ok(Wsh { inner: WshInner::Ms(sub) })
248 } else {
249 Err(Error::Unexpected(format!(
250 "{}({} args) while parsing wsh descriptor",
251 top.name,
252 top.args.len(),
253 )))
254 }
255 }
256}
257
258impl<Pk: MiniscriptKey> fmt::Debug for Wsh<Pk> {
259 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
260 match self.inner {
261 WshInner::SortedMulti(ref smv) => write!(f, "wsh({:?})", smv),
262 WshInner::Ms(ref ms) => write!(f, "wsh({:?})", ms),
263 }
264 }
265}
266
267impl<Pk: MiniscriptKey> fmt::Display for Wsh<Pk> {
268 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
269 match self.inner {
270 WshInner::SortedMulti(ref smv) => write_descriptor!(f, "wsh({})", smv),
271 WshInner::Ms(ref ms) => write_descriptor!(f, "wsh({})", ms),
272 }
273 }
274}
275
276impl<Pk: FromStrKey> core::str::FromStr for Wsh<Pk> {
277 type Err = Error;
278 fn from_str(s: &str) -> Result<Self, Self::Err> {
279 let desc_str = verify_checksum(s)?;
280 let top = expression::Tree::from_str(desc_str)?;
281 Wsh::<Pk>::from_tree(&top)
282 }
283}
284
285impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wsh<Pk> {
286 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool {
287 match self.inner {
288 WshInner::SortedMulti(ref smv) => smv.for_each_key(pred),
289 WshInner::Ms(ref ms) => ms.for_each_key(pred),
290 }
291 }
292}
293
294impl<P, Q> TranslatePk<P, Q> for Wsh<P>
295where
296 P: MiniscriptKey,
297 Q: MiniscriptKey,
298{
299 type Output = Wsh<Q>;
300
301 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, TranslateErr<E>>
302 where
303 T: Translator<P, Q, E>,
304 {
305 let inner = match self.inner {
306 WshInner::SortedMulti(ref smv) => WshInner::SortedMulti(smv.translate_pk(t)?),
307 WshInner::Ms(ref ms) => WshInner::Ms(ms.translate_pk(t)?),
308 };
309 Ok(Wsh { inner })
310 }
311}
312
313#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
315pub struct Wpkh<Pk: MiniscriptKey> {
316 pk: Pk,
318}
319
320impl<Pk: MiniscriptKey> Wpkh<Pk> {
321 pub fn new(pk: Pk) -> Result<Self, ScriptContextError> {
323 match Segwitv0::check_pk(&pk) {
325 Ok(_) => Ok(Wpkh { pk }),
326 Err(e) => Err(e),
327 }
328 }
329
330 pub fn into_inner(self) -> Pk { self.pk }
332
333 pub fn as_inner(&self) -> &Pk { &self.pk }
335
336 #[deprecated(since = "8.0.0", note = "use format!(\"{:#}\") instead")]
338 pub fn to_string_no_checksum(&self) -> String { format!("{:#}", self) }
339
340 pub fn sanity_check(&self) -> Result<(), Error> {
342 if self.pk.is_uncompressed() {
343 Err(Error::ContextError(ScriptContextError::CompressedOnly(self.pk.to_string())))
344 } else {
345 Ok(())
346 }
347 }
348
349 pub fn max_weight_to_satisfy(&self) -> Weight {
355 let stack_items_size = 73 + Segwitv0::pk_len(&self.pk);
357 let stack_varint_diff = varint_len(2) - varint_len(0);
359 Weight::from_wu((stack_varint_diff + stack_items_size) as u64)
360 }
361
362 #[deprecated(
369 since = "10.0.0",
370 note = "Use max_weight_to_satisfy instead. The method to count bytes was redesigned and the results will differ from max_weight_to_satisfy. For more details check rust-bitcoin/rust-miniscript#476."
371 )]
372 pub fn max_satisfaction_weight(&self) -> usize { 4 + 1 + 73 + Segwitv0::pk_len(&self.pk) }
373}
374
375impl<Pk: MiniscriptKey + ToPublicKey> Wpkh<Pk> {
376 pub fn script_pubkey(&self) -> ScriptBuf {
378 let pk = self.pk.to_public_key();
379 let compressed = bitcoin::key::CompressedPublicKey::try_from(pk)
380 .expect("wpkh descriptors have compressed keys");
381
382 let addr = Address::p2wpkh(&compressed, Network::Bitcoin);
383 addr.script_pubkey()
384 }
385
386 pub fn address(&self, network: Network) -> Address {
388 let pk = self.pk.to_public_key();
389 let compressed = bitcoin::key::CompressedPublicKey::try_from(pk)
390 .expect("Rust Miniscript types don't allow uncompressed pks in segwit descriptors");
391
392 Address::p2wpkh(&compressed, network)
393 }
394
395 pub fn inner_script(&self) -> ScriptBuf { self.script_pubkey() }
397
398 pub fn ecdsa_sighash_script_code(&self) -> ScriptBuf {
400 let addr = Address::p2pkh(self.pk.to_public_key(), Network::Bitcoin);
405 addr.script_pubkey()
406 }
407
408 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
412 where
413 S: Satisfier<Pk>,
414 {
415 if let Some(sig) = satisfier.lookup_ecdsa_sig(&self.pk) {
416 let sig_vec = sig.to_vec();
417 let script_sig = ScriptBuf::new();
418 let witness = vec![sig_vec, self.pk.to_public_key().to_bytes()];
419 Ok((witness, script_sig))
420 } else {
421 Err(Error::MissingSig(self.pk.to_public_key()))
422 }
423 }
424
425 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
429 where
430 S: Satisfier<Pk>,
431 {
432 self.get_satisfaction(satisfier)
433 }
434}
435
436impl Wpkh<DefiniteDescriptorKey> {
437 pub fn plan_satisfaction<P>(
439 &self,
440 provider: &P,
441 ) -> Satisfaction<Placeholder<DefiniteDescriptorKey>>
442 where
443 P: AssetProvider<DefiniteDescriptorKey>,
444 {
445 let stack = if provider.provider_lookup_ecdsa_sig(&self.pk) {
446 let stack = vec![
447 Placeholder::EcdsaSigPk(self.pk.clone()),
448 Placeholder::Pubkey(self.pk.clone(), Segwitv0::pk_len(&self.pk)),
449 ];
450 Witness::Stack(stack)
451 } else {
452 Witness::Unavailable
453 };
454
455 Satisfaction { stack, has_sig: true, relative_timelock: None, absolute_timelock: None }
456 }
457
458 pub fn plan_satisfaction_mall<P>(
460 &self,
461 provider: &P,
462 ) -> Satisfaction<Placeholder<DefiniteDescriptorKey>>
463 where
464 P: AssetProvider<DefiniteDescriptorKey>,
465 {
466 self.plan_satisfaction(provider)
467 }
468}
469
470impl<Pk: MiniscriptKey> fmt::Debug for Wpkh<Pk> {
471 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "wpkh({:?})", self.pk) }
472}
473
474impl<Pk: MiniscriptKey> fmt::Display for Wpkh<Pk> {
475 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
476 write_descriptor!(f, "wpkh({})", self.pk)
477 }
478}
479
480impl<Pk: MiniscriptKey> Liftable<Pk> for Wpkh<Pk> {
481 fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
482 Ok(semantic::Policy::Key(self.pk.clone()))
483 }
484}
485
486impl<Pk: FromStrKey> crate::expression::FromTree for Wpkh<Pk> {
487 fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
488 if top.name == "wpkh" && top.args.len() == 1 {
489 Ok(Wpkh::new(expression::terminal(&top.args[0], |pk| Pk::from_str(pk))?)?)
490 } else {
491 Err(Error::Unexpected(format!(
492 "{}({} args) while parsing wpkh descriptor",
493 top.name,
494 top.args.len(),
495 )))
496 }
497 }
498}
499
500impl<Pk: FromStrKey> core::str::FromStr for Wpkh<Pk> {
501 type Err = Error;
502 fn from_str(s: &str) -> Result<Self, Self::Err> {
503 let desc_str = verify_checksum(s)?;
504 let top = expression::Tree::from_str(desc_str)?;
505 Self::from_tree(&top)
506 }
507}
508
509impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wpkh<Pk> {
510 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool { pred(&self.pk) }
511}
512
513impl<P, Q> TranslatePk<P, Q> for Wpkh<P>
514where
515 P: MiniscriptKey,
516 Q: MiniscriptKey,
517{
518 type Output = Wpkh<Q>;
519
520 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, TranslateErr<E>>
521 where
522 T: Translator<P, Q, E>,
523 {
524 let res = Wpkh::new(t.pk(&self.pk)?);
525 match res {
526 Ok(pk) => Ok(pk),
527 Err(e) => Err(TranslateErr::OuterError(Error::from(e))),
528 }
529 }
530}