Skip to content

Commit

Permalink
Avoid panic when policies containing x-only keys are compiled for Seg…
Browse files Browse the repository at this point in the history
…witv0

Temporary workaround pending rust-bitcoin/rust-miniscript#761
  • Loading branch information
shesek committed Oct 25, 2024
1 parent 95760dc commit aa849b7
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 11 deletions.
4 changes: 4 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ pub enum RuntimeError {
#[error("sh() can only wrap wsh() or wpkh()")]
InvalidShUse,

// Can be removed once this is handled as an Err by rust-miniscript (https://github.com/rust-bitcoin/rust-miniscript/pull/761)
#[error("x-only keys not allowed in Segwitv0 wsh()")]
InvalidWshXonly,

#[error("Transaction input #{0} does not exists")]
TxInputNotFound(usize),

Expand Down
21 changes: 11 additions & 10 deletions src/playground.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ use serde_wasm_bindgen::to_value;
use wasm_bindgen::prelude::*;

use miniscript::bitcoin::{Address, Network, ScriptBuf};
use miniscript::{Descriptor, MiniscriptKey};
use miniscript::{Descriptor, ForEachKey, MiniscriptKey};

use crate::util::{DescriptorExt, TapInfoExt};
use crate::{
parse, Error, Evaluate, Execute, ExprRepr, Library, PrettyDisplay, Scope, ScopeRef, Value,
};
use crate::util::{DescriptorExt, PrettyDisplay, TapInfoExt};
use crate::{parse, Error, Evaluate, Execute, ExprRepr, Library, Scope, ScopeRef, Value};

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

let value = eval(code)?;

let (mut policy, mut desc, mut script, mut addr, mut key, mut tapinfo, mut other) =
(None, None, None, None, None, None, None);

match value {
match eval(code)? {
Value::Policy(policy_) => {
// Convert policies into a wsh() descriptor
desc = Some(Descriptor::new_wsh(policy_.compile()?)?);
// Compile policies into a wsh() descriptor
if policy_.for_each_key(|pk| !pk.is_x_only_key()) {
// Has to explicitly check for x-only keys as a temporary workaround to avoid panicking
// https://github.com/rust-bitcoin/rust-miniscript/pull/761
let ms = policy_.compile().ok();
desc = ms.and_then(|ms| Descriptor::new_wsh(ms).ok());
}
policy = Some(policy_);
}
Value::Descriptor(desc_) => desc = Some(desc_),
Expand Down
7 changes: 6 additions & 1 deletion src/stdlib/miniscript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::convert::{TryFrom, TryInto};
use std::{fmt, sync::Arc};

use miniscript::descriptor::{ShInner, WshInner};
use miniscript::{ScriptContext, Threshold};
use miniscript::{ForEachKey, MiniscriptKey, ScriptContext, Threshold};

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

0 comments on commit aa849b7

Please # to comment.