Skip to content

Commit 6ace6b2

Browse files
OttoAllmendingerllm-git
andcommitted
build(wasm-utxo): update miniscript to bitgo.5 and enforce sane+drop mode
Update rust-miniscript dependency from bitgo.3 to bitgo.5. Change all descriptor parsing to use `ExtParams::sane().drop()` by default, allowing r: wrappers while maintaining other safety checks. The `fromStringExt` method now always enables drop mode, with other flags remaining opt-in for taproot leaf validation. Issue: BTC-3357 Co-authored-by: llm-git <llm-git@ttll.de>
1 parent bde2415 commit 6ace6b2

4 files changed

Lines changed: 21 additions & 31 deletions

File tree

packages/wasm-utxo/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/wasm-utxo/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ inspect = ["dep:num-bigint", "dep:serde", "dep:serde_json", "dep:hex"]
2727
[dependencies]
2828
wasm-bindgen = "0.2"
2929
js-sys = "0.3"
30-
miniscript = { git = "https://github.com/BitGo/rust-miniscript", tag = "miniscript-13.0.0-bitgo.3" }
30+
miniscript = { git = "https://github.com/BitGo/rust-miniscript", tag = "miniscript-13.0.0-bitgo.5" }
3131
bech32 = "0.11"
3232
musig2 = { version = "0.3.1", default-features = false, features = ["k256"] }
3333
getrandom = { version = "0.2", features = ["js"] }

packages/wasm-utxo/src/wasm/descriptor.rs

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::wasm::try_into_js_value::TryIntoJsValue;
44
use miniscript::bitcoin::secp256k1::{Secp256k1, Signing};
55
use miniscript::bitcoin::ScriptBuf;
66
use miniscript::descriptor::KeyMap;
7+
use miniscript::miniscript::analyzable::ExtParams;
78
use miniscript::{DefiniteDescriptorKey, Descriptor, DescriptorPublicKey};
89
use std::fmt;
910
use std::str::FromStr;
@@ -112,12 +113,16 @@ impl WrapDescriptor {
112113
secp: &Secp256k1<C>,
113114
descriptor: &str,
114115
) -> Result<WrapDescriptor, WasmUtxoError> {
115-
let (desc, keys) = Descriptor::parse_descriptor(secp, descriptor)?;
116+
let (desc, keys) =
117+
Descriptor::parse_descriptor_ext(secp, descriptor, &ExtParams::sane().drop())?;
116118
Ok(WrapDescriptor(WrapDescriptorEnum::Derivable(desc, keys)))
117119
}
118120

119121
fn from_string_definite(descriptor: &str) -> Result<WrapDescriptor, WasmUtxoError> {
120-
let desc = Descriptor::<DefiniteDescriptorKey>::from_str(descriptor)?;
122+
let desc = Descriptor::<DefiniteDescriptorKey>::from_str_ext(
123+
descriptor,
124+
&ExtParams::sane().drop(),
125+
)?;
121126
Ok(WrapDescriptor(WrapDescriptorEnum::Definite(desc)))
122127
}
123128

@@ -150,31 +155,24 @@ impl WrapDescriptor {
150155
"derivable" => WrapDescriptor::from_string_derivable(&Secp256k1::new(), descriptor),
151156
"definite" => WrapDescriptor::from_string_definite(descriptor),
152157
"string" => {
153-
let desc = Descriptor::<String>::from_str(descriptor)?;
158+
let desc =
159+
Descriptor::<String>::from_str_ext(descriptor, &ExtParams::sane().drop())?;
154160
Ok(WrapDescriptor(WrapDescriptorEnum::String(desc)))
155161
}
156162
_ => Err(WasmUtxoError::new("Invalid descriptor type")),
157163
}
158164
}
159165

160-
fn from_string_definite_ext(
161-
descriptor: &str,
162-
ext_params: &miniscript::miniscript::analyzable::ExtParams,
163-
) -> Result<WrapDescriptor, WasmUtxoError> {
164-
let desc = Descriptor::<DefiniteDescriptorKey>::from_str_ext(descriptor, ext_params)?;
165-
Ok(WrapDescriptor(WrapDescriptorEnum::Definite(desc)))
166-
}
167-
168166
/// Parse a descriptor string with custom ExtParams for taproot leaf validation.
169167
///
170168
/// This allows control over which miniscript analysis checks are applied to
171-
/// taproot leaves. All options default to false (sane behavior).
169+
/// taproot leaves. The `drop` flag is always enabled; other flags default to false.
172170
///
173171
/// # Arguments
174172
/// * `descriptor` - A string containing the descriptor to parse
175173
/// * `pk_type` - The type of public key ("definite" only for now)
176174
/// * `ext_params_config` - JavaScript object with optional boolean flags:
177-
/// - `drop`: Allow drop operations (r: wrapper)
175+
/// - `drop`: Allow drop operations (r: wrapper) — always enabled
178176
/// - `topUnsafe`: Allow scripts without signatures on all paths
179177
/// - `resourceLimitations`: Allow scripts exceeding resource limits
180178
/// - `timelockMixing`: Allow CSV + CLTV mixing
@@ -184,14 +182,8 @@ impl WrapDescriptor {
184182
///
185183
/// # Example
186184
/// ```javascript
187-
/// // Allow r:older() only (for sBTC)
188-
/// Descriptor.fromStringExt(desc, "definite", { drop: true })
189-
///
190-
/// // Allow multiple extensions
191-
/// Descriptor.fromStringExt(desc, "definite", { drop: true, malleability: true })
192-
///
193-
/// // All sane (default)
194-
/// Descriptor.fromStringExt(desc, "definite", {})
185+
/// // r:older() is always allowed; add extra flags as needed
186+
/// Descriptor.fromStringExt(desc, "definite", { malleability: true })
195187
/// ```
196188
#[wasm_bindgen(js_name = fromStringExt, skip_typescript)]
197189
pub fn from_string_ext(
@@ -203,10 +195,7 @@ impl WrapDescriptor {
203195
Ok(get_field::<Option<bool>>(&ext_params_config, key)?.unwrap_or(false))
204196
};
205197

206-
let mut params = miniscript::miniscript::analyzable::ExtParams::sane();
207-
if flag("drop")? {
208-
params = params.drop();
209-
}
198+
let mut params = ExtParams::sane().drop();
210199
if flag("topUnsafe")? {
211200
params = params.top_unsafe();
212201
}
@@ -227,7 +216,10 @@ impl WrapDescriptor {
227216
}
228217

229218
match pk_type {
230-
"definite" => WrapDescriptor::from_string_definite_ext(descriptor, &params),
219+
"definite" => {
220+
let desc = Descriptor::<DefiniteDescriptorKey>::from_str_ext(descriptor, &params)?;
221+
Ok(WrapDescriptor(WrapDescriptorEnum::Definite(desc)))
222+
}
231223
_ => Err(WasmUtxoError::new(
232224
"fromStringExt only supports 'definite' pk_type",
233225
)),

packages/wasm-utxo/test/sbtc.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import * as assert from "assert";
22
import * as utxolib from "@bitgo/utxo-lib";
33
import { Descriptor } from "../js/index.js";
4-
import type { ExtParamsConfig } from "../js/index.js";
54

65
// sBTC protocol uses two taproot script leaves:
76
// 1. Deposit leaf: allows the signers to spend with a protocol payload
@@ -43,10 +42,9 @@ type SbtcDescriptorNode = {
4342

4443
describe("sBTC taproot descriptor", function () {
4544
// Use fromStringExt with { drop: true } to enable r:older() in taproot
46-
const descriptor = Descriptor.fromStringExt(
45+
const descriptor = Descriptor.fromString(
4746
getSbtcDescriptor(SIGNERS_KEY, DEPOSIT_LEAF, RECLAIM_LEAF),
4847
"definite",
49-
{ drop: true } satisfies ExtParamsConfig,
5048
);
5149

5250
it("parses successfully with fromStringExt", () => {

0 commit comments

Comments
 (0)