Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit aa849b7

Browse files
committedOct 25, 2024
Avoid panic when policies containing x-only keys are compiled for Segwitv0
Temporary workaround pending rust-bitcoin/rust-miniscript#761
1 parent 95760dc commit aa849b7

File tree

3 files changed

+21
-11
lines changed

3 files changed

+21
-11
lines changed
 

‎src/error.rs

+4
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@ pub enum RuntimeError {
190190
#[error("sh() can only wrap wsh() or wpkh()")]
191191
InvalidShUse,
192192

193+
// Can be removed once this is handled as an Err by rust-miniscript (https://github.com/rust-bitcoin/rust-miniscript/pull/761)
194+
#[error("x-only keys not allowed in Segwitv0 wsh()")]
195+
InvalidWshXonly,
196+
193197
#[error("Transaction input #{0} does not exists")]
194198
TxInputNotFound(usize),
195199

‎src/playground.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ use serde_wasm_bindgen::to_value;
55
use wasm_bindgen::prelude::*;
66

77
use miniscript::bitcoin::{Address, Network, ScriptBuf};
8-
use miniscript::{Descriptor, MiniscriptKey};
8+
use miniscript::{Descriptor, ForEachKey, MiniscriptKey};
99

10-
use crate::util::{DescriptorExt, TapInfoExt};
11-
use crate::{
12-
parse, Error, Evaluate, Execute, ExprRepr, Library, PrettyDisplay, Scope, ScopeRef, Value,
13-
};
10+
use crate::util::{DescriptorExt, PrettyDisplay, TapInfoExt};
11+
use crate::{parse, Error, Evaluate, Execute, ExprRepr, Library, Scope, ScopeRef, Value};
1412

1513
#[derive(Serialize)]
1614
pub struct PlaygroundResult {
@@ -29,15 +27,18 @@ pub fn run_playground(code: &str, network: &str) -> Result<JsValue, JsValue> {
2927
let _run_playground = || -> Result<PlaygroundResult, Error> {
3028
let network = Network::from_str(network)?;
3129

32-
let value = eval(code)?;
33-
3430
let (mut policy, mut desc, mut script, mut addr, mut key, mut tapinfo, mut other) =
3531
(None, None, None, None, None, None, None);
3632

37-
match value {
33+
match eval(code)? {
3834
Value::Policy(policy_) => {
39-
// Convert policies into a wsh() descriptor
40-
desc = Some(Descriptor::new_wsh(policy_.compile()?)?);
35+
// Compile policies into a wsh() descriptor
36+
if policy_.for_each_key(|pk| !pk.is_x_only_key()) {
37+
// Has to explicitly check for x-only keys as a temporary workaround to avoid panicking
38+
// https://github.com/rust-bitcoin/rust-miniscript/pull/761
39+
let ms = policy_.compile().ok();
40+
desc = ms.and_then(|ms| Descriptor::new_wsh(ms).ok());
41+
}
4142
policy = Some(policy_);
4243
}
4344
Value::Descriptor(desc_) => desc = Some(desc_),

‎src/stdlib/miniscript.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::convert::{TryFrom, TryInto};
22
use std::{fmt, sync::Arc};
33

44
use miniscript::descriptor::{ShInner, WshInner};
5-
use miniscript::{ScriptContext, Threshold};
5+
use miniscript::{ForEachKey, MiniscriptKey, ScriptContext, Threshold};
66

77
use crate::runtime::scope::{Mutable, ScopeRef};
88
use crate::runtime::{Array, Error, Evaluate, ExprRepr, Result, Value};
@@ -166,6 +166,11 @@ pub mod fns {
166166
pub fn wsh(args: Array, _: &ScopeRef) -> Result<Value> {
167167
Ok(match args.arg_into()? {
168168
Value::Policy(policy) => {
169+
// Temporary workaround to avoid panicking (https://github.com/rust-bitcoin/rust-miniscript/pull/761)
170+
ensure!(
171+
policy.for_each_key(|pk| !pk.is_x_only_key()),
172+
Error::InvalidWshXonly
173+
);
169174
let miniscript = policy.compile()?;
170175
Descriptor::new_wsh(miniscript)?.into()
171176
}

0 commit comments

Comments
 (0)
Please sign in to comment.