Skip to content

Commit d1335ff

Browse files
committed
Avoid panic when policies containing x-only keys are compiled for Segwitv0
Temporary workaround pending rust-bitcoin/rust-miniscript#761
1 parent 9e7f9fc commit d1335ff

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
@@ -202,6 +202,10 @@ pub enum RuntimeError {
202202
#[error("sh() can only wrap wsh() or wpkh()")]
203203
InvalidShUse,
204204

205+
// Can be removed once this is handled as an Err by rust-miniscript (https://github.com/rust-bitcoin/rust-miniscript/pull/761)
206+
#[error("x-only keys not allowed in Segwitv0 wsh()")]
207+
InvalidWshXonly,
208+
205209
#[error("Transaction input #{0} does not exists")]
206210
TxInputNotFound(usize),
207211

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
@@ -3,7 +3,7 @@ use std::{fmt, sync::Arc};
33

44
use bitcoin::ScriptBuf;
55
use miniscript::descriptor::{DescriptorType, ShInner, WshInner};
6-
use miniscript::{ScriptContext, Threshold};
6+
use miniscript::{ForEachKey, MiniscriptKey, ScriptContext, Threshold};
77

88
use crate::runtime::scope::{Mutable, ScopeRef};
99
use crate::runtime::{Array, Error, Evaluate, ExprRepr, FieldAccess, Result, Value};
@@ -170,6 +170,11 @@ pub mod fns {
170170
pub fn wsh(args: Array, _: &ScopeRef) -> Result<Value> {
171171
Ok(match args.arg_into()? {
172172
Value::Policy(policy) => {
173+
// Temporary workaround to avoid panicking (https://github.com/rust-bitcoin/rust-miniscript/pull/761)
174+
ensure!(
175+
policy.for_each_key(|pk| !pk.is_x_only_key()),
176+
Error::InvalidWshXonly
177+
);
173178
let miniscript = policy.compile()?;
174179
Descriptor::new_wsh(miniscript)?.into()
175180
}

0 commit comments

Comments
 (0)