1use core::convert::TryFrom;
12use core::fmt;
13
14use bellscoin::script::PushBytes;
15use bellscoin::{script, Address, Network, ScriptBuf};
16
17use super::checksum::{self, verify_checksum};
18use super::{SortedMultiVec, Wpkh, Wsh};
19use crate::expression::{self, FromTree};
20use crate::miniscript::context::ScriptContext;
21use crate::policy::{semantic, Liftable};
22use crate::prelude::*;
23use crate::util::{varint_len, witness_to_scriptsig};
24use crate::{
25 push_opcode_size, Error, ForEachKey, Legacy, Miniscript, MiniscriptKey, Satisfier, Segwitv0,
26 ToPublicKey, TranslateErr, TranslatePk, Translator,
27};
28
29#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
31pub struct Sh<Pk: MiniscriptKey> {
32 inner: ShInner<Pk>,
34}
35
36#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
38pub enum ShInner<Pk: MiniscriptKey> {
39 Wsh(Wsh<Pk>),
41 Wpkh(Wpkh<Pk>),
43 SortedMulti(SortedMultiVec<Pk, Legacy>),
45 Ms(Miniscript<Pk, Legacy>),
47}
48
49impl<Pk: MiniscriptKey> Liftable<Pk> for Sh<Pk> {
50 fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
51 match self.inner {
52 ShInner::Wsh(ref wsh) => wsh.lift(),
53 ShInner::Wpkh(ref pk) => Ok(semantic::Policy::Key(pk.as_inner().clone())),
54 ShInner::SortedMulti(ref smv) => smv.lift(),
55 ShInner::Ms(ref ms) => ms.lift(),
56 }
57 }
58}
59
60impl<Pk: MiniscriptKey> fmt::Debug for Sh<Pk> {
61 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62 match self.inner {
63 ShInner::Wsh(ref wsh_inner) => write!(f, "sh({:?})", wsh_inner),
64 ShInner::Wpkh(ref pk) => write!(f, "sh({:?})", pk),
65 ShInner::SortedMulti(ref smv) => write!(f, "sh({:?})", smv),
66 ShInner::Ms(ref ms) => write!(f, "sh({:?})", ms),
67 }
68 }
69}
70
71impl<Pk: MiniscriptKey> fmt::Display for Sh<Pk> {
72 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73 use fmt::Write;
74 let mut wrapped_f = checksum::Formatter::new(f);
75 match self.inner {
76 ShInner::Wsh(ref wsh) => write!(wrapped_f, "sh({:#})", wsh)?,
77 ShInner::Wpkh(ref pk) => write!(wrapped_f, "sh({:#})", pk)?,
78 ShInner::SortedMulti(ref smv) => write!(wrapped_f, "sh({})", smv)?,
79 ShInner::Ms(ref ms) => write!(wrapped_f, "sh({})", ms)?,
80 }
81 wrapped_f.write_checksum_if_not_alt()
82 }
83}
84
85impl_from_tree!(
86 Sh<Pk>,
87 fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
88 if top.name == "sh" && top.args.len() == 1 {
89 let top = &top.args[0];
90 let inner = match top.name {
91 "wsh" => ShInner::Wsh(Wsh::from_tree(top)?),
92 "wpkh" => ShInner::Wpkh(Wpkh::from_tree(top)?),
93 "sortedmulti" => ShInner::SortedMulti(SortedMultiVec::from_tree(top)?),
94 _ => {
95 let sub = Miniscript::from_tree(top)?;
96 Legacy::top_level_checks(&sub)?;
97 ShInner::Ms(sub)
98 }
99 };
100 Ok(Sh { inner })
101 } else {
102 Err(Error::Unexpected(format!(
103 "{}({} args) while parsing sh descriptor",
104 top.name,
105 top.args.len(),
106 )))
107 }
108 }
109);
110
111impl_from_str!(
112 Sh<Pk>,
113 type Err = Error;,
114 fn from_str(s: &str) -> Result<Self, Self::Err> {
115 let desc_str = verify_checksum(s)?;
116 let top = expression::Tree::from_str(desc_str)?;
117 Self::from_tree(&top)
118 }
119);
120
121impl<Pk: MiniscriptKey> Sh<Pk> {
122 pub fn into_inner(self) -> ShInner<Pk> {
124 self.inner
125 }
126
127 pub fn as_inner(&self) -> &ShInner<Pk> {
129 &self.inner
130 }
131
132 pub fn new(ms: Miniscript<Pk, Legacy>) -> Result<Self, Error> {
134 Legacy::top_level_checks(&ms)?;
136 Ok(Self {
137 inner: ShInner::Ms(ms),
138 })
139 }
140
141 pub fn new_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
144 Ok(Self {
147 inner: ShInner::SortedMulti(SortedMultiVec::new(k, pks)?),
148 })
149 }
150
151 pub fn new_wsh(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
153 Ok(Self {
154 inner: ShInner::Wsh(Wsh::new(ms)?),
155 })
156 }
157
158 pub fn new_with_wsh(wsh: Wsh<Pk>) -> Self {
160 Self {
161 inner: ShInner::Wsh(wsh),
162 }
163 }
164
165 pub fn sanity_check(&self) -> Result<(), Error> {
167 match self.inner {
168 ShInner::Wsh(ref wsh) => wsh.sanity_check()?,
169 ShInner::Wpkh(ref wpkh) => wpkh.sanity_check()?,
170 ShInner::SortedMulti(ref smv) => smv.sanity_check()?,
171 ShInner::Ms(ref ms) => ms.sanity_check()?,
172 }
173 Ok(())
174 }
175
176 pub fn new_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
179 Ok(Self {
182 inner: ShInner::Wsh(Wsh::new_sortedmulti(k, pks)?),
183 })
184 }
185
186 pub fn new_wpkh(pk: Pk) -> Result<Self, Error> {
188 Ok(Self {
189 inner: ShInner::Wpkh(Wpkh::new(pk)?),
190 })
191 }
192
193 pub fn new_with_wpkh(wpkh: Wpkh<Pk>) -> Self {
195 Self {
196 inner: ShInner::Wpkh(wpkh),
197 }
198 }
199
200 pub fn max_weight_to_satisfy(&self) -> Result<usize, Error> {
214 let (scriptsig_size, witness_size) = match self.inner {
215 ShInner::Wsh(ref wsh) => {
217 let scriptsig_size = 1 + 1 + 1 + 32;
219 let witness_size = wsh.max_weight_to_satisfy()?;
220 (scriptsig_size, witness_size)
221 }
222 ShInner::SortedMulti(ref smv) => {
223 let ss = smv.script_size();
224 let ps = push_opcode_size(ss);
225 let scriptsig_size = ps + ss + smv.max_satisfaction_size();
226 (scriptsig_size, 0)
227 }
228 ShInner::Wpkh(ref wpkh) => {
230 let scriptsig_size = 1 + 1 + 1 + 20;
232 let witness_size = wpkh.max_weight_to_satisfy();
233 (scriptsig_size, witness_size)
234 }
235 ShInner::Ms(ref ms) => {
236 let ss = ms.script_size();
237 let ps = push_opcode_size(ss);
238 let scriptsig_size = ps + ss + ms.max_satisfaction_size()?;
239 (scriptsig_size, 0)
240 }
241 };
242
243 let scriptsig_varint_diff = varint_len(scriptsig_size) - varint_len(0);
245
246 Ok(4 * (scriptsig_varint_diff + scriptsig_size) + witness_size)
247 }
248
249 #[deprecated(note = "use max_weight_to_satisfy instead")]
259 #[allow(deprecated)]
260 pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
261 Ok(match self.inner {
262 ShInner::Wsh(ref wsh) => 4 * 35 + wsh.max_satisfaction_weight()?,
264 ShInner::SortedMulti(ref smv) => {
265 let ss = smv.script_size();
266 let ps = push_opcode_size(ss);
267 let scriptsig_len = ps + ss + smv.max_satisfaction_size();
268 4 * (varint_len(scriptsig_len) + scriptsig_len)
269 }
270 ShInner::Wpkh(ref wpkh) => 4 * 23 + wpkh.max_satisfaction_weight(),
272 ShInner::Ms(ref ms) => {
273 let ss = ms.script_size();
274 let ps = push_opcode_size(ss);
275 let scriptsig_len = ps + ss + ms.max_satisfaction_size()?;
276 4 * (varint_len(scriptsig_len) + scriptsig_len)
277 }
278 })
279 }
280}
281
282impl<Pk: MiniscriptKey + ToPublicKey> Sh<Pk> {
283 pub fn script_pubkey(&self) -> ScriptBuf {
285 match self.inner {
286 ShInner::Wsh(ref wsh) => wsh.script_pubkey().to_p2sh(),
287 ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey().to_p2sh(),
288 ShInner::SortedMulti(ref smv) => smv.encode().to_p2sh(),
289 ShInner::Ms(ref ms) => ms.encode().to_p2sh(),
290 }
291 }
292
293 pub fn address(&self, network: Network) -> Address {
295 let addr = self.address_fallible(network);
296
297 assert!(addr.is_ok());
299 addr.expect("only fails if size > MAX_SCRIPT_ELEMENT_SIZE")
300 }
301
302 fn address_fallible(&self, network: Network) -> Result<Address, Error> {
303 let script = match self.inner {
304 ShInner::Wsh(ref wsh) => wsh.script_pubkey(),
305 ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey(),
306 ShInner::SortedMulti(ref smv) => smv.encode(),
307 ShInner::Ms(ref ms) => ms.encode(),
308 };
309 let address = Address::p2sh(&script, network)?;
310
311 Ok(address)
312 }
313
314 pub fn inner_script(&self) -> ScriptBuf {
316 match self.inner {
317 ShInner::Wsh(ref wsh) => wsh.inner_script(),
318 ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey(),
319 ShInner::SortedMulti(ref smv) => smv.encode(),
320 ShInner::Ms(ref ms) => ms.encode(),
321 }
322 }
323
324 pub fn ecdsa_sighash_script_code(&self) -> ScriptBuf {
326 match self.inner {
327 ShInner::Wsh(ref wsh) => wsh.ecdsa_sighash_script_code(),
330 ShInner::SortedMulti(ref smv) => smv.encode(),
331 ShInner::Wpkh(ref wpkh) => wpkh.ecdsa_sighash_script_code(),
332 ShInner::Ms(ref ms) => ms.encode(),
334 }
335 }
336
337 pub fn unsigned_script_sig(&self) -> ScriptBuf {
345 match self.inner {
346 ShInner::Wsh(ref wsh) => {
347 let witness_script = wsh.inner_script().to_v0_p2wsh();
349 let push_bytes = <&PushBytes>::try_from(witness_script.as_bytes())
350 .expect("Witness script is not too large");
351 script::Builder::new().push_slice(&push_bytes).into_script()
352 }
353 ShInner::Wpkh(ref wpkh) => {
354 let redeem_script = wpkh.script_pubkey();
355 let push_bytes: &PushBytes =
356 <&PushBytes>::try_from(redeem_script.as_bytes()).expect("Script not too large");
357 script::Builder::new().push_slice(&push_bytes).into_script()
358 }
359 ShInner::SortedMulti(..) | ShInner::Ms(..) => ScriptBuf::new(),
360 }
361 }
362
363 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
367 where
368 S: Satisfier<Pk>,
369 {
370 let script_sig = self.unsigned_script_sig();
371 match self.inner {
372 ShInner::Wsh(ref wsh) => {
373 let (witness, _) = wsh.get_satisfaction(satisfier)?;
374 Ok((witness, script_sig))
375 }
376 ShInner::Wpkh(ref wpkh) => {
377 let (witness, _) = wpkh.get_satisfaction(satisfier)?;
378 Ok((witness, script_sig))
379 }
380 ShInner::SortedMulti(ref smv) => {
381 let mut script_witness = smv.satisfy(satisfier)?;
382 script_witness.push(smv.encode().into_bytes());
383 let script_sig = witness_to_scriptsig(&script_witness);
384 let witness = vec![];
385 Ok((witness, script_sig))
386 }
387 ShInner::Ms(ref ms) => {
388 let mut script_witness = ms.satisfy(satisfier)?;
389 script_witness.push(ms.encode().into_bytes());
390 let script_sig = witness_to_scriptsig(&script_witness);
391 let witness = vec![];
392 Ok((witness, script_sig))
393 }
394 }
395 }
396
397 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
401 where
402 S: Satisfier<Pk>,
403 {
404 let script_sig = self.unsigned_script_sig();
405 match self.inner {
406 ShInner::Wsh(ref wsh) => {
407 let (witness, _) = wsh.get_satisfaction_mall(satisfier)?;
408 Ok((witness, script_sig))
409 }
410 ShInner::Ms(ref ms) => {
411 let mut script_witness = ms.satisfy_malleable(satisfier)?;
412 script_witness.push(ms.encode().into_bytes());
413 let script_sig = witness_to_scriptsig(&script_witness);
414 let witness = vec![];
415 Ok((witness, script_sig))
416 }
417 _ => self.get_satisfaction(satisfier),
418 }
419 }
420}
421
422impl<Pk: MiniscriptKey> ForEachKey<Pk> for Sh<Pk> {
423 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool {
424 match self.inner {
425 ShInner::Wsh(ref wsh) => wsh.for_each_key(pred),
426 ShInner::SortedMulti(ref smv) => smv.for_each_key(pred),
427 ShInner::Wpkh(ref wpkh) => wpkh.for_each_key(pred),
428 ShInner::Ms(ref ms) => ms.for_each_key(pred),
429 }
430 }
431}
432
433impl<P, Q> TranslatePk<P, Q> for Sh<P>
434where
435 P: MiniscriptKey,
436 Q: MiniscriptKey,
437{
438 type Output = Sh<Q>;
439
440 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, TranslateErr<E>>
441 where
442 T: Translator<P, Q, E>,
443 {
444 let inner = match self.inner {
445 ShInner::Wsh(ref wsh) => ShInner::Wsh(wsh.translate_pk(t)?),
446 ShInner::Wpkh(ref wpkh) => ShInner::Wpkh(wpkh.translate_pk(t)?),
447 ShInner::SortedMulti(ref smv) => ShInner::SortedMulti(smv.translate_pk(t)?),
448 ShInner::Ms(ref ms) => ShInner::Ms(ms.translate_pk(t)?),
449 };
450 Ok(Sh { inner })
451 }
452}