Skip to content

Commit 960d394

Browse files
committed
Use correct context in all constructors
Check descriptor keys are correctly used in all contexts
1 parent 2fb39ec commit 960d394

File tree

5 files changed

+75
-24
lines changed

5 files changed

+75
-24
lines changed

src/descriptor/bare.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use bitcoin::{Address, Network, Script};
2525

2626
use super::checksum::{self, verify_checksum};
2727
use crate::expression::{self, FromTree};
28-
use crate::miniscript::context::ScriptContext;
28+
use crate::miniscript::context::{ScriptContext, ScriptContextError};
2929
use crate::policy::{semantic, Liftable};
3030
use crate::prelude::*;
3131
use crate::util::{varint_len, witness_to_scriptsig};
@@ -197,9 +197,12 @@ pub struct Pkh<Pk: MiniscriptKey> {
197197

198198
impl<Pk: MiniscriptKey> Pkh<Pk> {
199199
/// Create a new Pkh descriptor
200-
pub fn new(pk: Pk) -> Self {
200+
pub fn new(pk: Pk) -> Result<Self, ScriptContextError> {
201201
// do the top-level checks
202-
Self { pk }
202+
match BareCtx::check_pk(&pk) {
203+
Ok(()) => Ok(Pkh { pk }),
204+
Err(e) => Err(e),
205+
}
203206
}
204207

205208
/// Get a reference to the inner key
@@ -305,7 +308,7 @@ impl_from_tree!(
305308
if top.name == "pkh" && top.args.len() == 1 {
306309
Ok(Pkh::new(expression::terminal(&top.args[0], |pk| {
307310
Pk::from_str(pk)
308-
})?))
311+
})?)?)
309312
} else {
310313
Err(Error::Unexpected(format!(
311314
"{}({} args) while parsing pkh descriptor",
@@ -346,6 +349,7 @@ where
346349
where
347350
T: Translator<P, Q, E>,
348351
{
349-
Ok(Pkh::new(t.pk(&self.pk)?))
352+
let res = Pkh::new(t.pk(&self.pk)?);
353+
Ok(res.expect("Expect will be fixed in next commit"))
350354
}
351355
}

src/descriptor/mod.rs

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,8 @@ impl<Pk: MiniscriptKey> Descriptor<Pk> {
188188
}
189189

190190
/// Create a new PkH descriptor
191-
pub fn new_pkh(pk: Pk) -> Self {
192-
Descriptor::Pkh(Pkh::new(pk))
191+
pub fn new_pkh(pk: Pk) -> Result<Self, Error> {
192+
Ok(Descriptor::Pkh(Pkh::new(pk)?))
193193
}
194194

195195
/// Create a new Wpkh descriptor
@@ -1156,7 +1156,7 @@ mod tests {
11561156
);
11571157
assert_eq!(bare.unsigned_script_sig(), bitcoin::Script::new());
11581158

1159-
let pkh = Descriptor::new_pkh(pk);
1159+
let pkh = Descriptor::new_pkh(pk).unwrap();
11601160
pkh.satisfy(&mut txin, &satisfier).expect("satisfaction");
11611161
assert_eq!(
11621162
txin,
@@ -1837,4 +1837,54 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
18371837
"tr(020000000000000000000000000000000000000000000000000000000000000002)",
18381838
);
18391839
}
1840+
1841+
#[test]
1842+
fn test_context_pks() {
1843+
let comp_key = bitcoin::PublicKey::from_str(
1844+
"02015e4cb53458bf813db8c79968e76e10d13ed6426a23fa71c2f41ba021c2a7ab",
1845+
)
1846+
.unwrap();
1847+
let x_only_key = bitcoin::XOnlyPublicKey::from_str(
1848+
"015e4cb53458bf813db8c79968e76e10d13ed6426a23fa71c2f41ba021c2a7ab",
1849+
)
1850+
.unwrap();
1851+
let uncomp_key = bitcoin::PublicKey::from_str("04015e4cb53458bf813db8c79968e76e10d13ed6426a23fa71c2f41ba021c2a7ab0d46021e9e69ef061eb25eab41ae206187b2b05e829559df59d78319bd9267b4").unwrap();
1852+
1853+
type Desc = Descriptor<DescriptorPublicKey>;
1854+
1855+
// Legacy tests, x-only keys are not supported
1856+
Desc::from_str(&format!("sh(pk({}))", comp_key)).unwrap();
1857+
Desc::from_str(&format!("sh(pk({}))", uncomp_key)).unwrap();
1858+
Desc::from_str(&format!("sh(pk({}))", x_only_key)).unwrap_err();
1859+
1860+
// bare tests, x-only keys not supported
1861+
Desc::from_str(&format!("pk({})", comp_key)).unwrap();
1862+
Desc::from_str(&format!("pk({})", uncomp_key)).unwrap();
1863+
Desc::from_str(&format!("pk({})", x_only_key)).unwrap_err();
1864+
1865+
// pkh tests, x-only keys not supported
1866+
Desc::from_str(&format!("pkh({})", comp_key)).unwrap();
1867+
Desc::from_str(&format!("pkh({})", uncomp_key)).unwrap();
1868+
Desc::from_str(&format!("pkh({})", x_only_key)).unwrap_err();
1869+
1870+
// wpkh tests, uncompressed and x-only keys not supported
1871+
Desc::from_str(&format!("wpkh({})", comp_key)).unwrap();
1872+
Desc::from_str(&format!("wpkh({})", uncomp_key)).unwrap_err();
1873+
Desc::from_str(&format!("wpkh({})", x_only_key)).unwrap_err();
1874+
1875+
// Segwitv0 tests, uncompressed and x-only keys not supported
1876+
Desc::from_str(&format!("wsh(pk({}))", comp_key)).unwrap();
1877+
Desc::from_str(&format!("wsh(pk({}))", uncomp_key)).unwrap_err();
1878+
Desc::from_str(&format!("wsh(pk({}))", x_only_key)).unwrap_err();
1879+
1880+
// Tap tests, key path
1881+
Desc::from_str(&format!("tr({})", comp_key)).unwrap();
1882+
Desc::from_str(&format!("tr({})", uncomp_key)).unwrap_err();
1883+
Desc::from_str(&format!("tr({})", x_only_key)).unwrap();
1884+
1885+
// Tap tests, script path
1886+
Desc::from_str(&format!("tr({},pk({}))", x_only_key, comp_key)).unwrap();
1887+
Desc::from_str(&format!("tr({},pk({}))", x_only_key, uncomp_key)).unwrap_err();
1888+
Desc::from_str(&format!("tr({},pk({}))", x_only_key, x_only_key)).unwrap();
1889+
}
18401890
}

src/descriptor/segwitv0.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -287,14 +287,11 @@ pub struct Wpkh<Pk: MiniscriptKey> {
287287

288288
impl<Pk: MiniscriptKey> Wpkh<Pk> {
289289
/// Create a new Wpkh descriptor
290-
pub fn new(pk: Pk) -> Result<Self, Error> {
290+
pub fn new(pk: Pk) -> Result<Self, ScriptContextError> {
291291
// do the top-level checks
292-
if pk.is_uncompressed() {
293-
Err(Error::ContextError(ScriptContextError::CompressedOnly(
294-
pk.to_string(),
295-
)))
296-
} else {
297-
Ok(Self { pk })
292+
match Segwitv0::check_pk(&pk) {
293+
Ok(_) => Ok(Wpkh { pk }),
294+
Err(e) => Err(e),
298295
}
299296
}
300297

src/descriptor/tr.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ use crate::policy::Liftable;
1919
use crate::prelude::*;
2020
use crate::util::{varint_len, witness_size};
2121
use crate::{
22-
errstr, Error, ForEachKey, MiniscriptKey, Satisfier, Tap, ToPublicKey, TranslatePk, Translator,
22+
errstr, Error, ForEachKey, MiniscriptKey, Satisfier, ScriptContext, Tap, ToPublicKey,
23+
TranslatePk, Translator,
2324
};
2425

2526
/// A Taproot Tree representation.
@@ -164,6 +165,7 @@ impl<Pk: MiniscriptKey> fmt::Debug for TapTree<Pk> {
164165
impl<Pk: MiniscriptKey> Tr<Pk> {
165166
/// Create a new [`Tr`] descriptor from internal key and [`TapTree`]
166167
pub fn new(internal_key: Pk, tree: Option<TapTree<Pk>>) -> Result<Self, Error> {
168+
Tap::check_pk(&internal_key)?;
167169
let nodes = tree.as_ref().map(|t| t.taptree_height()).unwrap_or(0);
168170

169171
if nodes <= TAPROOT_CONTROL_MAX_NODE_COUNT {
@@ -585,14 +587,12 @@ where
585587
where
586588
T: Translator<P, Q, E>,
587589
{
588-
let translate_desc = Tr {
589-
internal_key: translate.pk(&self.internal_key)?,
590-
tree: match &self.tree {
591-
Some(tree) => Some(tree.translate_helper(translate)?),
592-
None => None,
593-
},
594-
spend_info: Mutex::new(None),
590+
let tree = match &self.tree {
591+
Some(tree) => Some(tree.translate_helper(translate)?),
592+
None => None,
595593
};
594+
let translate_desc = Tr::new(translate.pk(&self.internal_key)?, tree)
595+
.expect("This will be removed in future");
596596
Ok(translate_desc)
597597
}
598598
}

src/psbt/finalizer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, In
158158
*script_pubkey == addr.script_pubkey()
159159
});
160160
match partial_sig_contains_pk {
161-
Some((pk, _sig)) => Ok(Descriptor::new_pkh(*pk)),
161+
Some((pk, _sig)) => Descriptor::new_pkh(*pk).map_err(|e| InputError::from(e)),
162162
None => Err(InputError::MissingPubkey),
163163
}
164164
} else if script_pubkey.is_v0_p2wpkh() {

0 commit comments

Comments
 (0)