|
12 | 12 | // If not, see <http://creativecommons.org/publicdomain/zero/1.0/>. |
13 | 13 | // |
14 | 14 |
|
| 15 | +use miniscript::types; |
15 | 16 | use miniscript::types::extra_props::{ |
16 | 17 | MAX_OPS_PER_SCRIPT, MAX_SCRIPTSIG_SIZE, MAX_SCRIPT_ELEMENT_SIZE, MAX_SCRIPT_SIZE, |
17 | 18 | MAX_STANDARD_P2WSH_SCRIPT_SIZE, MAX_STANDARD_P2WSH_STACK_ITEMS, |
18 | 19 | }; |
19 | 20 | use std::fmt; |
| 21 | +use Error; |
20 | 22 | use {Miniscript, MiniscriptKey, Terminal}; |
21 | | - |
22 | 23 | /// Error for Script Context |
23 | 24 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
24 | 25 | pub enum ScriptContextError { |
@@ -49,9 +50,6 @@ pub enum ScriptContextError { |
49 | 50 | MaxRedeemScriptSizeExceeded, |
50 | 51 | /// The policy rules of bitcoin core only permit Script size upto 1650 bytes |
51 | 52 | MaxScriptSigSizeExceeded, |
52 | | - /// Anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...) |
53 | | - /// up to n=3 is invalid by standardness (bare) |
54 | | - NonStandardBareScript, |
55 | 53 | } |
56 | 54 |
|
57 | 55 | impl fmt::Display for ScriptContextError { |
@@ -90,12 +88,6 @@ impl fmt::Display for ScriptContextError { |
90 | 88 | "Atleast one satisfaction in Miniscript would be larger than \ |
91 | 89 | MAX_SCRIPTSIG_SIZE scriptsig" |
92 | 90 | ), |
93 | | - ScriptContextError::NonStandardBareScript => write!( |
94 | | - f, |
95 | | - "Anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...) \ |
96 | | - up to n=3 is invalid by standardness (bare). |
97 | | - " |
98 | | - ), |
99 | 91 | } |
100 | 92 | } |
101 | 93 | } |
@@ -137,8 +129,6 @@ pub trait ScriptContext: |
137 | 129 | /// it is safe to discard them. (unless explicity disabled by non-standard flag) |
138 | 130 | /// For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey |
139 | 131 | /// scripts over 3600 bytes are invalid. |
140 | | - /// In Bare context, only c:pk(key) (P2PK), |
141 | | - /// c:pk_h(key) (P2PKH), and thresh_m(k,...) up to n=3 are allowed |
142 | 132 | /// Post Tapscript upgrade, this would have to consider other nodes. |
143 | 133 | /// This does *NOT* recursively check the miniscript fragments. |
144 | 134 | fn check_non_satisfaction_policy_rules<Pk: MiniscriptKey, Ctx: ScriptContext>( |
@@ -189,6 +179,39 @@ pub trait ScriptContext: |
189 | 179 | Self::check_satisfaction_policy_rules(ms)?; |
190 | 180 | Ok(()) |
191 | 181 | } |
| 182 | + |
| 183 | + /// Check whether the top-level is type B |
| 184 | + fn top_level_type_check<Pk: MiniscriptKey, Ctx: ScriptContext>( |
| 185 | + ms: &Miniscript<Pk, Ctx>, |
| 186 | + ) -> Result<(), Error> { |
| 187 | + if ms.ty.corr.base != types::Base::B { |
| 188 | + return Err(Error::NonTopLevel(format!("{:?}", ms))); |
| 189 | + } |
| 190 | + Ok(()) |
| 191 | + } |
| 192 | + |
| 193 | + /// Other top level checks that are context specific |
| 194 | + fn other_top_level_checks<Pk: MiniscriptKey, Ctx: ScriptContext>( |
| 195 | + _ms: &Miniscript<Pk, Ctx>, |
| 196 | + ) -> Result<(), Error> { |
| 197 | + Ok(()) |
| 198 | + } |
| 199 | + |
| 200 | + /// Check top level consensus rules. |
| 201 | + // All the preivous check_ were applied at each fragment while parsing script |
| 202 | + // Because if any of sub-miniscripts failed the reource level check, the entire |
| 203 | + // miniscript would also be invalid. However, there are certain checks like |
| 204 | + // in Bare context, only c:pk(key) (P2PK), |
| 205 | + // c:pk_h(key) (P2PKH), and thresh_m(k,...) up to n=3 are allowed |
| 206 | + // that are only applicable at the top-level |
| 207 | + // We can also combine the top-level check for Base::B here |
| 208 | + // even though it does not depend on context, but helps in cleaner code |
| 209 | + fn top_level_checks<Pk: MiniscriptKey, Ctx: ScriptContext>( |
| 210 | + ms: &Miniscript<Pk, Ctx>, |
| 211 | + ) -> Result<(), Error> { |
| 212 | + Self::top_level_type_check(ms)?; |
| 213 | + Self::other_top_level_checks(ms) |
| 214 | + } |
192 | 215 | } |
193 | 216 |
|
194 | 217 | /// Legacy ScriptContext |
@@ -345,14 +368,17 @@ impl ScriptContext for Bare { |
345 | 368 | Ok(()) |
346 | 369 | } |
347 | 370 |
|
348 | | - fn check_non_satisfaction_policy_rules<Pk: MiniscriptKey, Ctx: ScriptContext>( |
| 371 | + fn other_top_level_checks<Pk: MiniscriptKey, Ctx: ScriptContext>( |
349 | 372 | ms: &Miniscript<Pk, Ctx>, |
350 | | - ) -> Result<(), ScriptContextError> { |
| 373 | + ) -> Result<(), Error> { |
351 | 374 | match &ms.node { |
352 | | - Terminal::PkH(_pkh) => Ok(()), |
353 | | - Terminal::PkK(_pk) => Ok(()), |
| 375 | + Terminal::Check(ref ms) => match &ms.node { |
| 376 | + Terminal::PkH(_pkh) => Ok(()), |
| 377 | + Terminal::PkK(_pk) => Ok(()), |
| 378 | + _ => Err(Error::NonStandardBareScript), |
| 379 | + }, |
354 | 380 | Terminal::Multi(_k, subs) if subs.len() <= 3 => Ok(()), |
355 | | - _ => Err(ScriptContextError::NonStandardBareScript), |
| 381 | + _ => Err(Error::NonStandardBareScript), |
356 | 382 | } |
357 | 383 | } |
358 | 384 | } |
|
0 commit comments