miniscript_debug/descriptor/
sortedmulti.rs1use core::fmt;
20use core::marker::PhantomData;
21use core::str::FromStr;
22
23use bitcoin::blockdata::script;
24
25use crate::miniscript::context::ScriptContext;
26use crate::miniscript::decode::Terminal;
27use crate::miniscript::limits::MAX_PUBKEYS_PER_MULTISIG;
28use crate::prelude::*;
29use crate::{
30 errstr, expression, miniscript, policy, script_num_size, Error, ForEachKey, Miniscript,
31 MiniscriptKey, Satisfier, ToPublicKey, Translator,
32};
33
34#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
36pub struct SortedMultiVec<Pk: MiniscriptKey, Ctx: ScriptContext> {
37 pub k: usize,
39 pub pks: Vec<Pk>,
41 pub(crate) phantom: PhantomData<Ctx>,
43}
44
45impl<Pk: MiniscriptKey, Ctx: ScriptContext> SortedMultiVec<Pk, Ctx> {
46 pub fn new(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
50 if pks.len() > MAX_PUBKEYS_PER_MULTISIG {
52 return Err(Error::BadDescriptor("Too many public keys".to_string()));
53 }
54
55 let term: miniscript::decode::Terminal<Pk, Ctx> = Terminal::Multi(k, pks.clone());
59 let ms = Miniscript::from_ast(term)?;
60
61 Ctx::check_local_validity(&ms)?;
64
65 Ok(Self {
66 k,
67 pks,
68 phantom: PhantomData,
69 })
70 }
71 pub fn from_tree(tree: &expression::Tree) -> Result<Self, Error>
73 where
74 Pk: FromStr,
75 <Pk as FromStr>::Err: ToString,
76 {
77 if tree.args.is_empty() {
78 return Err(errstr("no arguments given for sortedmulti"));
79 }
80 let k = expression::parse_num(tree.args[0].name)?;
81 if k > (tree.args.len() - 1) as u32 {
82 return Err(errstr(
83 "higher threshold than there were keys in sortedmulti",
84 ));
85 }
86 let pks: Result<Vec<Pk>, _> = tree.args[1..]
87 .iter()
88 .map(|sub| expression::terminal(sub, Pk::from_str))
89 .collect();
90
91 pks.map(|pks| SortedMultiVec::new(k as usize, pks))?
92 }
93
94 pub fn translate_pk<T, Q, FuncError>(
98 &self,
99 t: &mut T,
100 ) -> Result<SortedMultiVec<Q, Ctx>, FuncError>
101 where
102 T: Translator<Pk, Q, FuncError>,
103 Q: MiniscriptKey,
104 {
105 let pks: Result<Vec<Q>, _> = self.pks.iter().map(|pk| t.pk(pk)).collect();
106 Ok(SortedMultiVec {
107 k: self.k,
108 pks: pks?,
109 phantom: PhantomData,
110 })
111 }
112}
113
114impl<Pk: MiniscriptKey, Ctx: ScriptContext> ForEachKey<Pk> for SortedMultiVec<Pk, Ctx> {
115 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool
116 where
117 Pk: 'a,
118 {
119 self.pks.iter().all(|key| pred(key))
120 }
121}
122
123impl<Pk: MiniscriptKey, Ctx: ScriptContext> SortedMultiVec<Pk, Ctx> {
124 pub fn sanity_check(&self) -> Result<(), Error> {
126 let ms: Miniscript<Pk, Ctx> =
127 Miniscript::from_ast(Terminal::Multi(self.k, self.pks.clone()))
128 .expect("Must typecheck");
129 ms.sanity_check()?;
131 Ok(())
132 }
133}
134
135impl<Pk: MiniscriptKey, Ctx: ScriptContext> SortedMultiVec<Pk, Ctx> {
136 pub fn sorted_node(&self) -> Terminal<Pk, Ctx>
138 where
139 Pk: ToPublicKey,
140 {
141 let mut pks = self.pks.clone();
142 pks.sort_by(|a, b| {
144 a.to_public_key()
145 .inner
146 .serialize()
147 .partial_cmp(&b.to_public_key().inner.serialize())
148 .unwrap()
149 });
150 Terminal::Multi(self.k, pks)
151 }
152
153 pub fn encode(&self) -> script::Script
155 where
156 Pk: ToPublicKey,
157 {
158 self.sorted_node()
159 .encode(script::Builder::new())
160 .into_script()
161 }
162
163 pub fn satisfy<S>(&self, satisfier: S) -> Result<Vec<Vec<u8>>, Error>
166 where
167 Pk: ToPublicKey,
168 S: Satisfier<Pk>,
169 {
170 let ms = Miniscript::from_ast(self.sorted_node()).expect("Multi node typecheck");
171 ms.satisfy(satisfier)
172 }
173
174 pub fn script_size(&self) -> usize {
182 script_num_size(self.k)
183 + 1
184 + script_num_size(self.pks.len())
185 + self.pks.iter().map(|pk| Ctx::pk_len(pk)).sum::<usize>()
186 }
187
188 pub fn max_satisfaction_witness_elements(&self) -> usize {
197 2 + self.k
198 }
199
200 pub fn max_satisfaction_size(&self) -> usize {
209 1 + 73 * self.k
210 }
211}
212
213impl<Pk: MiniscriptKey, Ctx: ScriptContext> policy::Liftable<Pk> for SortedMultiVec<Pk, Ctx> {
214 fn lift(&self) -> Result<policy::semantic::Policy<Pk>, Error> {
215 let ret = policy::semantic::Policy::Threshold(
216 self.k,
217 self.pks
218 .iter()
219 .map(|k| policy::semantic::Policy::Key(k.clone()))
220 .collect(),
221 );
222 Ok(ret)
223 }
224}
225
226impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for SortedMultiVec<Pk, Ctx> {
227 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
228 fmt::Display::fmt(self, f)
229 }
230}
231
232impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for SortedMultiVec<Pk, Ctx> {
233 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
234 write!(f, "sortedmulti({}", self.k)?;
235 for k in &self.pks {
236 write!(f, ",{}", k)?;
237 }
238 f.write_str(")")
239 }
240}
241
242#[cfg(test)]
243mod tests {
244 use bitcoin::secp256k1::PublicKey;
245 use miniscript::context::Legacy;
246
247 use super::*;
248
249 #[test]
250 fn too_many_pubkeys() {
251 let pk = PublicKey::from_str(
253 "02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443",
254 )
255 .unwrap();
256
257 let over = 1 + MAX_PUBKEYS_PER_MULTISIG;
258
259 let mut pks = Vec::new();
260 for _ in 0..over {
261 pks.push(pk.clone());
262 }
263
264 let res: Result<SortedMultiVec<PublicKey, Legacy>, Error> = SortedMultiVec::new(0, pks);
265 let error = res.err().expect("constructor should err");
266
267 match error {
268 Error::BadDescriptor(_) => {} other => panic!("unexpected error: {:?}", other),
270 }
271 }
272}