1use core::fmt;
22
23use bitcoin::blockdata::script;
24use bitcoin::{Address, Network, Script};
25
26use super::checksum::{self, verify_checksum};
27use super::{SortedMultiVec, Wpkh, Wsh};
28use crate::expression::{self, FromTree};
29use crate::miniscript::context::ScriptContext;
30use crate::policy::{semantic, Liftable};
31use crate::prelude::*;
32use crate::util::{varint_len, witness_to_scriptsig};
33use crate::{
34 push_opcode_size, Error, ForEachKey, Legacy, Miniscript, MiniscriptKey, Satisfier, Segwitv0,
35 ToPublicKey, TranslatePk, Translator,
36};
37
38#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
40pub struct Sh<Pk: MiniscriptKey> {
41 inner: ShInner<Pk>,
43}
44
45#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
47pub enum ShInner<Pk: MiniscriptKey> {
48 Wsh(Wsh<Pk>),
50 Wpkh(Wpkh<Pk>),
52 SortedMulti(SortedMultiVec<Pk, Legacy>),
54 Ms(Miniscript<Pk, Legacy>),
56}
57
58impl<Pk: MiniscriptKey> Liftable<Pk> for Sh<Pk> {
59 fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
60 match self.inner {
61 ShInner::Wsh(ref wsh) => wsh.lift(),
62 ShInner::Wpkh(ref pk) => Ok(semantic::Policy::Key(pk.as_inner().clone())),
63 ShInner::SortedMulti(ref smv) => smv.lift(),
64 ShInner::Ms(ref ms) => ms.lift(),
65 }
66 }
67}
68
69impl<Pk: MiniscriptKey> fmt::Debug for Sh<Pk> {
70 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71 match self.inner {
72 ShInner::Wsh(ref wsh_inner) => write!(f, "sh({:?})", wsh_inner),
73 ShInner::Wpkh(ref pk) => write!(f, "sh({:?})", pk),
74 ShInner::SortedMulti(ref smv) => write!(f, "sh({:?})", smv),
75 ShInner::Ms(ref ms) => write!(f, "sh({:?})", ms),
76 }
77 }
78}
79
80impl<Pk: MiniscriptKey> fmt::Display for Sh<Pk> {
81 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
82 use fmt::Write;
83 let mut wrapped_f = checksum::Formatter::new(f);
84 match self.inner {
85 ShInner::Wsh(ref wsh) => write!(wrapped_f, "sh({:#})", wsh)?,
86 ShInner::Wpkh(ref pk) => write!(wrapped_f, "sh({:#})", pk)?,
87 ShInner::SortedMulti(ref smv) => write!(wrapped_f, "sh({})", smv)?,
88 ShInner::Ms(ref ms) => write!(wrapped_f, "sh({})", ms)?,
89 }
90 wrapped_f.write_checksum_if_not_alt()
91 }
92}
93
94impl_from_tree!(
95 Sh<Pk>,
96 fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
97 if top.name == "sh" && top.args.len() == 1 {
98 let top = &top.args[0];
99 let inner = match top.name {
100 "wsh" => ShInner::Wsh(Wsh::from_tree(top)?),
101 "wpkh" => ShInner::Wpkh(Wpkh::from_tree(top)?),
102 "sortedmulti" => ShInner::SortedMulti(SortedMultiVec::from_tree(top)?),
103 _ => {
104 let sub = Miniscript::from_tree(top)?;
105 Legacy::top_level_checks(&sub)?;
106 ShInner::Ms(sub)
107 }
108 };
109 Ok(Sh { inner })
110 } else {
111 Err(Error::Unexpected(format!(
112 "{}({} args) while parsing sh descriptor",
113 top.name,
114 top.args.len(),
115 )))
116 }
117 }
118);
119
120impl_from_str!(
121 Sh<Pk>,
122 type Err = Error;,
123 fn from_str(s: &str) -> Result<Self, Self::Err> {
124 let desc_str = verify_checksum(s)?;
125 let top = expression::Tree::from_str(desc_str)?;
126 Self::from_tree(&top)
127 }
128);
129
130impl<Pk: MiniscriptKey> Sh<Pk> {
131 pub fn into_inner(self) -> ShInner<Pk> {
133 self.inner
134 }
135
136 pub fn as_inner(&self) -> &ShInner<Pk> {
138 &self.inner
139 }
140
141 pub fn new(ms: Miniscript<Pk, Legacy>) -> Result<Self, Error> {
143 Legacy::top_level_checks(&ms)?;
145 Ok(Self {
146 inner: ShInner::Ms(ms),
147 })
148 }
149
150 pub fn new_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
153 Ok(Self {
156 inner: ShInner::SortedMulti(SortedMultiVec::new(k, pks)?),
157 })
158 }
159
160 pub fn new_wsh(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
162 Ok(Self {
163 inner: ShInner::Wsh(Wsh::new(ms)?),
164 })
165 }
166
167 pub fn new_with_wsh(wsh: Wsh<Pk>) -> Self {
169 Self {
170 inner: ShInner::Wsh(wsh),
171 }
172 }
173
174 pub fn sanity_check(&self) -> Result<(), Error> {
176 match self.inner {
177 ShInner::Wsh(ref wsh) => wsh.sanity_check()?,
178 ShInner::Wpkh(ref wpkh) => wpkh.sanity_check()?,
179 ShInner::SortedMulti(ref smv) => smv.sanity_check()?,
180 ShInner::Ms(ref ms) => ms.sanity_check()?,
181 }
182 Ok(())
183 }
184
185 pub fn new_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
188 Ok(Self {
191 inner: ShInner::Wsh(Wsh::new_sortedmulti(k, pks)?),
192 })
193 }
194
195 pub fn new_wpkh(pk: Pk) -> Result<Self, Error> {
197 Ok(Self {
198 inner: ShInner::Wpkh(Wpkh::new(pk)?),
199 })
200 }
201
202 pub fn new_with_wpkh(wpkh: Wpkh<Pk>) -> Self {
204 Self {
205 inner: ShInner::Wpkh(wpkh),
206 }
207 }
208
209 pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
219 Ok(match self.inner {
220 ShInner::Wsh(ref wsh) => 4 * 35 + wsh.max_satisfaction_weight()?,
222 ShInner::SortedMulti(ref smv) => {
223 let ss = smv.script_size();
224 let ps = push_opcode_size(ss);
225 let scriptsig_len = ps + ss + smv.max_satisfaction_size();
226 4 * (varint_len(scriptsig_len) + scriptsig_len)
227 }
228 ShInner::Wpkh(ref wpkh) => 4 * 23 + wpkh.max_satisfaction_weight(),
230 ShInner::Ms(ref ms) => {
231 let ss = ms.script_size();
232 let ps = push_opcode_size(ss);
233 let scriptsig_len = ps + ss + ms.max_satisfaction_size()?;
234 4 * (varint_len(scriptsig_len) + scriptsig_len)
235 }
236 })
237 }
238}
239
240impl<Pk: MiniscriptKey + ToPublicKey> Sh<Pk> {
241 pub fn script_pubkey(&self) -> Script {
243 match self.inner {
244 ShInner::Wsh(ref wsh) => wsh.script_pubkey().to_p2sh(),
245 ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey().to_p2sh(),
246 ShInner::SortedMulti(ref smv) => smv.encode().to_p2sh(),
247 ShInner::Ms(ref ms) => ms.encode().to_p2sh(),
248 }
249 }
250
251 pub fn address(&self, network: Network) -> Address {
253 let addr = self.address_fallible(network);
254
255 assert!(addr.is_ok());
257 addr.expect("only fails if size > MAX_SCRIPT_ELEMENT_SIZE")
258 }
259
260 fn address_fallible(&self, network: Network) -> Result<Address, Error> {
261 let script = match self.inner {
262 ShInner::Wsh(ref wsh) => wsh.script_pubkey(),
263 ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey(),
264 ShInner::SortedMulti(ref smv) => smv.encode(),
265 ShInner::Ms(ref ms) => ms.encode(),
266 };
267 let address = Address::p2sh(&script, network)?;
268
269 Ok(address)
270 }
271
272 pub fn inner_script(&self) -> Script {
274 match self.inner {
275 ShInner::Wsh(ref wsh) => wsh.inner_script(),
276 ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey(),
277 ShInner::SortedMulti(ref smv) => smv.encode(),
278 ShInner::Ms(ref ms) => ms.encode(),
279 }
280 }
281
282 pub fn ecdsa_sighash_script_code(&self) -> Script {
284 match self.inner {
285 ShInner::Wsh(ref wsh) => wsh.ecdsa_sighash_script_code(),
288 ShInner::SortedMulti(ref smv) => smv.encode(),
289 ShInner::Wpkh(ref wpkh) => wpkh.ecdsa_sighash_script_code(),
290 ShInner::Ms(ref ms) => ms.encode(),
292 }
293 }
294
295 pub fn unsigned_script_sig(&self) -> Script {
303 match self.inner {
304 ShInner::Wsh(ref wsh) => {
305 let witness_script = wsh.inner_script();
307 script::Builder::new()
308 .push_slice(&witness_script.to_v0_p2wsh()[..])
309 .into_script()
310 }
311 ShInner::Wpkh(ref wpkh) => {
312 let redeem_script = wpkh.script_pubkey();
313 script::Builder::new()
314 .push_slice(&redeem_script[..])
315 .into_script()
316 }
317 ShInner::SortedMulti(..) | ShInner::Ms(..) => Script::new(),
318 }
319 }
320
321 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
325 where
326 S: Satisfier<Pk>,
327 {
328 let script_sig = self.unsigned_script_sig();
329 match self.inner {
330 ShInner::Wsh(ref wsh) => {
331 let (witness, _) = wsh.get_satisfaction(satisfier)?;
332 Ok((witness, script_sig))
333 }
334 ShInner::Wpkh(ref wpkh) => {
335 let (witness, _) = wpkh.get_satisfaction(satisfier)?;
336 Ok((witness, script_sig))
337 }
338 ShInner::SortedMulti(ref smv) => {
339 let mut script_witness = smv.satisfy(satisfier)?;
340 script_witness.push(smv.encode().into_bytes());
341 let script_sig = witness_to_scriptsig(&script_witness);
342 let witness = vec![];
343 Ok((witness, script_sig))
344 }
345 ShInner::Ms(ref ms) => {
346 let mut script_witness = ms.satisfy(satisfier)?;
347 script_witness.push(ms.encode().into_bytes());
348 let script_sig = witness_to_scriptsig(&script_witness);
349 let witness = vec![];
350 Ok((witness, script_sig))
351 }
352 }
353 }
354
355 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
359 where
360 S: Satisfier<Pk>,
361 {
362 let script_sig = self.unsigned_script_sig();
363 match self.inner {
364 ShInner::Wsh(ref wsh) => {
365 let (witness, _) = wsh.get_satisfaction_mall(satisfier)?;
366 Ok((witness, script_sig))
367 }
368 ShInner::Ms(ref ms) => {
369 let mut script_witness = ms.satisfy_malleable(satisfier)?;
370 script_witness.push(ms.encode().into_bytes());
371 let script_sig = witness_to_scriptsig(&script_witness);
372 let witness = vec![];
373 Ok((witness, script_sig))
374 }
375 _ => self.get_satisfaction(satisfier),
376 }
377 }
378}
379
380impl<Pk: MiniscriptKey> ForEachKey<Pk> for Sh<Pk> {
381 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
382 where
383 Pk: 'a,
384 {
385 match self.inner {
386 ShInner::Wsh(ref wsh) => wsh.for_each_key(pred),
387 ShInner::SortedMulti(ref smv) => smv.for_each_key(pred),
388 ShInner::Wpkh(ref wpkh) => wpkh.for_each_key(pred),
389 ShInner::Ms(ref ms) => ms.for_each_key(pred),
390 }
391 }
392}
393
394impl<P, Q> TranslatePk<P, Q> for Sh<P>
395where
396 P: MiniscriptKey,
397 Q: MiniscriptKey,
398{
399 type Output = Sh<Q>;
400
401 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
402 where
403 T: Translator<P, Q, E>,
404 {
405 let inner = match self.inner {
406 ShInner::Wsh(ref wsh) => ShInner::Wsh(wsh.translate_pk(t)?),
407 ShInner::Wpkh(ref wpkh) => ShInner::Wpkh(wpkh.translate_pk(t)?),
408 ShInner::SortedMulti(ref smv) => ShInner::SortedMulti(smv.translate_pk(t)?),
409 ShInner::Ms(ref ms) => ShInner::Ms(ms.translate_pk(t)?),
410 };
411 Ok(Sh { inner })
412 }
413}