1use core::fmt;
9use core::marker::PhantomData;
10use core::str::FromStr;
11
12use bitcoin::script;
13
14use crate::miniscript::context::ScriptContext;
15use crate::miniscript::decode::Terminal;
16use crate::miniscript::limits::MAX_PUBKEYS_PER_MULTISIG;
17use crate::miniscript::satisfy::{Placeholder, Satisfaction};
18use crate::plan::AssetProvider;
19use crate::prelude::*;
20use crate::sync::Arc;
21use crate::{
22 expression, policy, script_num_size, Error, ForEachKey, Miniscript, MiniscriptKey, Satisfier,
23 Threshold, ToPublicKey, TranslateErr, Translator,
24};
25
26#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
28pub struct SortedMultiVec<Pk: MiniscriptKey, Ctx: ScriptContext> {
29 inner: Threshold<Pk, MAX_PUBKEYS_PER_MULTISIG>,
30 phantom: PhantomData<Ctx>,
32}
33
34impl<Pk: MiniscriptKey, Ctx: ScriptContext> SortedMultiVec<Pk, Ctx> {
35 fn constructor_check(mut self) -> Result<Self, Error> {
36 let term: Terminal<Pk, Ctx> = Terminal::Multi(self.inner);
40 let ms = Miniscript::from_ast(term)?;
41 Ctx::check_local_validity(&ms)?;
44 if let Terminal::Multi(inner) = ms.node {
45 self.inner = inner;
46 Ok(self)
47 } else {
48 unreachable!()
49 }
50 }
51
52 pub fn new(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
56 let ret =
57 Self { inner: Threshold::new(k, pks).map_err(Error::Threshold)?, phantom: PhantomData };
58 ret.constructor_check()
59 }
60
61 pub fn from_tree(tree: &expression::Tree) -> Result<Self, Error>
63 where
64 Pk: FromStr,
65 <Pk as FromStr>::Err: fmt::Display,
66 {
67 let ret = Self {
68 inner: tree
69 .to_null_threshold()
70 .map_err(Error::ParseThreshold)?
71 .translate_by_index(|i| expression::terminal(&tree.args[i + 1], Pk::from_str))?,
72 phantom: PhantomData,
73 };
74 ret.constructor_check()
75 }
76
77 pub fn translate_pk<T, Q, FuncError>(
81 &self,
82 t: &mut T,
83 ) -> Result<SortedMultiVec<Q, Ctx>, TranslateErr<FuncError>>
84 where
85 T: Translator<Pk, Q, FuncError>,
86 Q: MiniscriptKey,
87 {
88 let ret = SortedMultiVec {
89 inner: self.inner.translate_ref(|pk| t.pk(pk))?,
90 phantom: PhantomData,
91 };
92 ret.constructor_check().map_err(TranslateErr::OuterError)
93 }
94
95 pub fn k(&self) -> usize { self.inner.k() }
97
98 pub fn n(&self) -> usize { self.inner.n() }
100
101 pub fn pks(&self) -> &[Pk] { self.inner.data() }
107}
108
109impl<Pk: MiniscriptKey, Ctx: ScriptContext> ForEachKey<Pk> for SortedMultiVec<Pk, Ctx> {
110 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool {
111 self.pks().iter().all(pred)
112 }
113}
114
115impl<Pk: MiniscriptKey, Ctx: ScriptContext> SortedMultiVec<Pk, Ctx> {
116 pub fn sanity_check(&self) -> Result<(), Error> {
118 let ms: Miniscript<Pk, Ctx> =
119 Miniscript::from_ast(Terminal::Multi(self.inner.clone())).expect("Must typecheck");
120 ms.sanity_check().map_err(From::from)
121 }
122}
123
124impl<Pk: MiniscriptKey, Ctx: ScriptContext> SortedMultiVec<Pk, Ctx> {
125 pub fn sorted_node(&self) -> Terminal<Pk, Ctx>
127 where
128 Pk: ToPublicKey,
129 {
130 let mut thresh = self.inner.clone();
131 thresh.data_mut().sort_by(|a, b| {
133 a.to_public_key()
134 .inner
135 .serialize()
136 .partial_cmp(&b.to_public_key().inner.serialize())
137 .unwrap()
138 });
139 Terminal::Multi(thresh)
140 }
141
142 pub fn encode(&self) -> script::ScriptBuf
144 where
145 Pk: ToPublicKey,
146 {
147 self.sorted_node()
148 .encode(script::Builder::new())
149 .into_script()
150 }
151
152 pub fn satisfy<S>(&self, satisfier: S) -> Result<Vec<Vec<u8>>, Error>
155 where
156 Pk: ToPublicKey,
157 S: Satisfier<Pk>,
158 {
159 let ms = Miniscript::from_ast(self.sorted_node()).expect("Multi node typecheck");
160 ms.satisfy(satisfier)
161 }
162
163 pub fn build_template<P>(&self, provider: &P) -> Satisfaction<Placeholder<Pk>>
165 where
166 Pk: ToPublicKey,
167 P: AssetProvider<Pk>,
168 {
169 let ms = Miniscript::from_ast(self.sorted_node()).expect("Multi node typecheck");
170 ms.build_template(provider)
171 }
172
173 pub fn script_size(&self) -> usize {
181 script_num_size(self.k())
182 + 1
183 + script_num_size(self.n())
184 + self.pks().iter().map(|pk| Ctx::pk_len(pk)).sum::<usize>()
185 }
186
187 pub fn max_satisfaction_witness_elements(&self) -> usize { 2 + self.k() }
196
197 pub fn max_satisfaction_size(&self) -> usize { 1 + 73 * self.k() }
206}
207
208impl<Pk: MiniscriptKey, Ctx: ScriptContext> policy::Liftable<Pk> for SortedMultiVec<Pk, Ctx> {
209 fn lift(&self) -> Result<policy::semantic::Policy<Pk>, Error> {
210 Ok(policy::semantic::Policy::Thresh(
211 self.inner
212 .map_ref(|pk| Arc::new(policy::semantic::Policy::Key(pk.clone())))
213 .forget_maximum(),
214 ))
215 }
216}
217
218impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for SortedMultiVec<Pk, Ctx> {
219 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) }
220}
221
222impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for SortedMultiVec<Pk, Ctx> {
223 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
224 fmt::Display::fmt(&self.inner.display("sortedmulti", true), f)
225 }
226}
227
228#[cfg(test)]
229mod tests {
230 use bitcoin::secp256k1::PublicKey;
231
232 use super::*;
233 use crate::miniscript::context::Legacy;
234
235 #[test]
236 fn too_many_pubkeys() {
237 let pk = PublicKey::from_str(
239 "02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443",
240 )
241 .unwrap();
242
243 let over = 1 + MAX_PUBKEYS_PER_MULTISIG;
244
245 let mut pks = Vec::new();
246 for _ in 0..over {
247 pks.push(pk);
248 }
249
250 let res: Result<SortedMultiVec<PublicKey, Legacy>, Error> = SortedMultiVec::new(0, pks);
251 let error = res.expect_err("constructor should err");
252
253 match error {
254 Error::Threshold(_) => {} other => panic!("unexpected error: {:?}", other),
256 }
257 }
258}