Skip to content

Commit

Permalink
Inline descriptor inner types
Browse files Browse the repository at this point in the history
The `ShInner` and `WshInner` enum's provide no benefit that I can
discern. Both include only tuple variants with private tuple fields. We
can therefore inline the enums into `Sh` and `Wsh` respectively with no
loss of type safety. Doing so marginally simplifies the code, the
biggest benefit is it stops devs wondering why there is an inner type.
  • Loading branch information
tcharding committed Aug 7, 2023
1 parent b01bd69 commit c4d1957
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 214 deletions.
2 changes: 1 addition & 1 deletion bitcoind-tests/tests/test_cpp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) {
for i in 0..psbts.len() {
let ms = if let Descriptor::Wsh(wsh) = &desc_vec[i] {
match wsh.as_inner() {
miniscript::descriptor::WshInner::Ms(ms) => ms,
miniscript::descriptor::Wsh::Ms(ms) => ms,
_ => unreachable!(),
}
} else {
Expand Down
16 changes: 8 additions & 8 deletions bitcoind-tests/tests/test_desc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,28 +225,28 @@ pub fn test_desc_satisfy(
Descriptor::Pkh(pk) => find_sk_single_key(*pk.as_inner(), testdata),
Descriptor::Wpkh(pk) => find_sk_single_key(*pk.as_inner(), testdata),
Descriptor::Sh(sh) => match sh.as_inner() {
miniscript::descriptor::ShInner::Wsh(wsh) => match wsh.as_inner() {
miniscript::descriptor::WshInner::SortedMulti(ref smv) => {
miniscript::descriptor::Sh::Wsh(wsh) => match wsh.as_inner() {
miniscript::descriptor::Wsh::SortedMulti(ref smv) => {
let ms = Miniscript::from_ast(smv.sorted_node()).unwrap();
find_sks_ms(&ms, testdata)
}
miniscript::descriptor::WshInner::Ms(ref ms) => find_sks_ms(&ms, testdata),
miniscript::descriptor::Wsh::Ms(ref ms) => find_sks_ms(&ms, testdata),
},
miniscript::descriptor::ShInner::Wpkh(pk) => {
miniscript::descriptor::Sh::Wpkh(pk) => {
find_sk_single_key(*pk.as_inner(), testdata)
}
miniscript::descriptor::ShInner::SortedMulti(smv) => {
miniscript::descriptor::Sh::SortedMulti(smv) => {
let ms = Miniscript::from_ast(smv.sorted_node()).unwrap();
find_sks_ms(&ms, testdata)
}
miniscript::descriptor::ShInner::Ms(ms) => find_sks_ms(&ms, testdata),
miniscript::descriptor::Sh::Ms(ms) => find_sks_ms(&ms, testdata),
},
Descriptor::Wsh(wsh) => match wsh.as_inner() {
miniscript::descriptor::WshInner::SortedMulti(ref smv) => {
miniscript::descriptor::Wsh::SortedMulti(ref smv) => {
let ms = Miniscript::from_ast(smv.sorted_node()).unwrap();
find_sks_ms(&ms, testdata)
}
miniscript::descriptor::WshInner::Ms(ref ms) => find_sks_ms(&ms, testdata),
miniscript::descriptor::Wsh::Ms(ref ms) => find_sks_ms(&ms, testdata),
},
Descriptor::Tr(_tr) => unreachable!("Tr checked earlier"),
};
Expand Down
24 changes: 12 additions & 12 deletions src/descriptor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ mod tr;

// Descriptor Exports
pub use self::bare::{Bare, Pkh};
pub use self::segwitv0::{Wpkh, Wsh, WshInner};
pub use self::sh::{Sh, ShInner};
pub use self::segwitv0::{Wpkh, Wsh};
pub use self::sh::Sh;
pub use self::sortedmulti::SortedMultiVec;
pub use self::tr::{TapTree, Tr};

Expand Down Expand Up @@ -267,18 +267,18 @@ impl<Pk: MiniscriptKey> Descriptor<Pk> {
Descriptor::Bare(ref _bare) => DescriptorType::Bare,
Descriptor::Pkh(ref _pkh) => DescriptorType::Pkh,
Descriptor::Wpkh(ref _wpkh) => DescriptorType::Wpkh,
Descriptor::Sh(ref sh) => match sh.as_inner() {
ShInner::Wsh(ref wsh) => match wsh.as_inner() {
WshInner::SortedMulti(ref _smv) => DescriptorType::ShWshSortedMulti,
WshInner::Ms(ref _ms) => DescriptorType::ShWsh,
Descriptor::Sh(ref sh) => match sh {
Sh::Wsh(ref wsh) => match wsh {
Wsh::SortedMulti(ref _smv) => DescriptorType::ShWshSortedMulti,
Wsh::Ms(ref _ms) => DescriptorType::ShWsh,
},
ShInner::Wpkh(ref _wpkh) => DescriptorType::ShWpkh,
ShInner::SortedMulti(ref _smv) => DescriptorType::ShSortedMulti,
ShInner::Ms(ref _ms) => DescriptorType::Sh,
Sh::Wpkh(ref _wpkh) => DescriptorType::ShWpkh,
Sh::SortedMulti(ref _smv) => DescriptorType::ShSortedMulti,
Sh::Ms(ref _ms) => DescriptorType::Sh,
},
Descriptor::Wsh(ref wsh) => match wsh.as_inner() {
WshInner::SortedMulti(ref _smv) => DescriptorType::WshSortedMulti,
WshInner::Ms(ref _ms) => DescriptorType::Wsh,
Descriptor::Wsh(ref wsh) => match wsh {
Wsh::SortedMulti(ref _smv) => DescriptorType::WshSortedMulti,
Wsh::Ms(ref _ms) => DescriptorType::Wsh,
},
Descriptor::Tr(ref _tr) => DescriptorType::Tr,
}
Expand Down
117 changes: 46 additions & 71 deletions src/descriptor/segwitv0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,38 +23,26 @@ use crate::{

/// A Segwitv0 wsh descriptor
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct Wsh<Pk: MiniscriptKey> {
/// underlying miniscript
inner: WshInner<Pk>,
pub enum Wsh<Pk: MiniscriptKey> {
/// Sorted Multi
SortedMulti(SortedMultiVec<Pk, Segwitv0>),
/// Wsh Miniscript
Ms(Miniscript<Pk, Segwitv0>),
}

impl<Pk: MiniscriptKey> Wsh<Pk> {
/// Get the Inner
pub fn into_inner(self) -> WshInner<Pk> {
self.inner
}

/// Get a reference to inner
pub fn as_inner(&self) -> &WshInner<Pk> {
&self.inner
}

/// Create a new wsh descriptor
pub fn new(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
// do the top-level checks
Segwitv0::top_level_checks(&ms)?;
Ok(Self {
inner: WshInner::Ms(ms),
})
Ok(Self::Ms(ms))
}

/// Create a new sortedmulti wsh descriptor
pub fn new_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
// The context checks will be carried out inside new function for
// sortedMultiVec
Ok(Self {
inner: WshInner::SortedMulti(SortedMultiVec::new(k, pks)?),
})
Ok(Self::SortedMulti(SortedMultiVec::new(k, pks)?))
}

/// Get the descriptor without the checksum
Expand All @@ -65,9 +53,9 @@ impl<Pk: MiniscriptKey> Wsh<Pk> {

/// Checks whether the descriptor is safe.
pub fn sanity_check(&self) -> Result<(), Error> {
match self.inner {
WshInner::SortedMulti(ref smv) => smv.sanity_check()?,
WshInner::Ms(ref ms) => ms.sanity_check()?,
match *self {
Wsh::SortedMulti(ref smv) => smv.sanity_check()?,
Wsh::Ms(ref ms) => ms.sanity_check()?,
}
Ok(())
}
Expand All @@ -81,13 +69,13 @@ impl<Pk: MiniscriptKey> Wsh<Pk> {
/// # Errors
/// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
pub fn max_weight_to_satisfy(&self) -> Result<usize, Error> {
let (redeem_script_size, max_sat_elems, max_sat_size) = match self.inner {
WshInner::SortedMulti(ref smv) => (
let (redeem_script_size, max_sat_elems, max_sat_size) = match *self {
Wsh::SortedMulti(ref smv) => (
smv.script_size(),
smv.max_satisfaction_witness_elements(),
smv.max_satisfaction_size(),
),
WshInner::Ms(ref ms) => (
Wsh::Ms(ref ms) => (
ms.script_size(),
ms.max_satisfaction_witness_elements()?,
ms.max_satisfaction_size()?,
Expand All @@ -111,13 +99,13 @@ impl<Pk: MiniscriptKey> Wsh<Pk> {
/// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
#[deprecated(note = "use max_weight_to_satisfy instead")]
pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
let (script_size, max_sat_elems, max_sat_size) = match self.inner {
WshInner::SortedMulti(ref smv) => (
let (script_size, max_sat_elems, max_sat_size) = match *self {
Wsh::SortedMulti(ref smv) => (
smv.script_size(),
smv.max_satisfaction_witness_elements(),
smv.max_satisfaction_size(),
),
WshInner::Ms(ref ms) => (
Wsh::Ms(ref ms) => (
ms.script_size(),
ms.max_satisfaction_witness_elements()?,
ms.max_satisfaction_size()?,
Expand All @@ -139,17 +127,17 @@ impl<Pk: MiniscriptKey + ToPublicKey> Wsh<Pk> {

/// Obtains the corresponding script pubkey for this descriptor.
pub fn address(&self, network: Network) -> Address {
match self.inner {
WshInner::SortedMulti(ref smv) => Address::p2wsh(&smv.encode(), network),
WshInner::Ms(ref ms) => Address::p2wsh(&ms.encode(), network),
match *self {
Wsh::SortedMulti(ref smv) => Address::p2wsh(&smv.encode(), network),
Wsh::Ms(ref ms) => Address::p2wsh(&ms.encode(), network),
}
}

/// Obtains the underlying miniscript for this descriptor.
pub fn inner_script(&self) -> ScriptBuf {
match self.inner {
WshInner::SortedMulti(ref smv) => smv.encode(),
WshInner::Ms(ref ms) => ms.encode(),
match *self {
Wsh::SortedMulti(ref smv) => smv.encode(),
Wsh::Ms(ref ms) => ms.encode(),
}
}

Expand All @@ -165,9 +153,9 @@ impl<Pk: MiniscriptKey + ToPublicKey> Wsh<Pk> {
where
S: Satisfier<Pk>,
{
let mut witness = match self.inner {
WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
WshInner::Ms(ref ms) => ms.satisfy(satisfier)?,
let mut witness = match *self {
Wsh::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
Wsh::Ms(ref ms) => ms.satisfy(satisfier)?,
};
let witness_script = self.inner_script();
witness.push(witness_script.into_bytes());
Expand All @@ -182,30 +170,21 @@ impl<Pk: MiniscriptKey + ToPublicKey> Wsh<Pk> {
where
S: Satisfier<Pk>,
{
let mut witness = match self.inner {
WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
WshInner::Ms(ref ms) => ms.satisfy_malleable(satisfier)?,
let mut witness = match *self {
Wsh::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
Wsh::Ms(ref ms) => ms.satisfy_malleable(satisfier)?,
};
witness.push(self.inner_script().into_bytes());
let script_sig = ScriptBuf::new();
Ok((witness, script_sig))
}
}

/// Wsh Inner
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum WshInner<Pk: MiniscriptKey> {
/// Sorted Multi
SortedMulti(SortedMultiVec<Pk, Segwitv0>),
/// Wsh Miniscript
Ms(Miniscript<Pk, Segwitv0>),
}

impl<Pk: MiniscriptKey> Liftable<Pk> for Wsh<Pk> {
fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
match self.inner {
WshInner::SortedMulti(ref smv) => smv.lift(),
WshInner::Ms(ref ms) => ms.lift(),
match *self {
Wsh::SortedMulti(ref smv) => smv.lift(),
Wsh::Ms(ref ms) => ms.lift(),
}
}
}
Expand All @@ -216,15 +195,11 @@ impl_from_tree!(
if top.name == "wsh" && top.args.len() == 1 {
let top = &top.args[0];
if top.name == "sortedmulti" {
return Ok(Wsh {
inner: WshInner::SortedMulti(SortedMultiVec::from_tree(top)?),
});
return Ok(Wsh::SortedMulti(SortedMultiVec::from_tree(top)?));
}
let sub = Miniscript::from_tree(top)?;
Segwitv0::top_level_checks(&sub)?;
Ok(Wsh {
inner: WshInner::Ms(sub),
})
Ok(Wsh::Ms(sub))
} else {
Err(Error::Unexpected(format!(
"{}({} args) while parsing wsh descriptor",
Expand All @@ -237,9 +212,9 @@ impl_from_tree!(

impl<Pk: MiniscriptKey> fmt::Debug for Wsh<Pk> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.inner {
WshInner::SortedMulti(ref smv) => write!(f, "wsh({:?})", smv),
WshInner::Ms(ref ms) => write!(f, "wsh({:?})", ms),
match *self {
Wsh::SortedMulti(ref smv) => write!(f, "wsh({:?})", smv),
Wsh::Ms(ref ms) => write!(f, "wsh({:?})", ms),
}
}
}
Expand All @@ -248,9 +223,9 @@ impl<Pk: MiniscriptKey> fmt::Display for Wsh<Pk> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use fmt::Write;
let mut wrapped_f = checksum::Formatter::new(f);
match self.inner {
WshInner::SortedMulti(ref smv) => write!(wrapped_f, "wsh({})", smv)?,
WshInner::Ms(ref ms) => write!(wrapped_f, "wsh({})", ms)?,
match *self {
Wsh::SortedMulti(ref smv) => write!(wrapped_f, "wsh({})", smv)?,
Wsh::Ms(ref ms) => write!(wrapped_f, "wsh({})", ms)?,
}
wrapped_f.write_checksum_if_not_alt()
}
Expand All @@ -268,9 +243,9 @@ impl_from_str!(

impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wsh<Pk> {
fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool {
match self.inner {
WshInner::SortedMulti(ref smv) => smv.for_each_key(pred),
WshInner::Ms(ref ms) => ms.for_each_key(pred),
match *self {
Wsh::SortedMulti(ref smv) => smv.for_each_key(pred),
Wsh::Ms(ref ms) => ms.for_each_key(pred),
}
}
}
Expand All @@ -286,11 +261,11 @@ where
where
T: Translator<P, Q, E>,
{
let inner = match self.inner {
WshInner::SortedMulti(ref smv) => WshInner::SortedMulti(smv.translate_pk(t)?),
WshInner::Ms(ref ms) => WshInner::Ms(ms.translate_pk(t)?),
let wsh = match *self {
Wsh::SortedMulti(ref smv) => Wsh::SortedMulti(smv.translate_pk(t)?),
Wsh::Ms(ref ms) => Wsh::Ms(ms.translate_pk(t)?),
};
Ok(Wsh { inner })
Ok(wsh)
}
}

Expand Down
Loading

0 comments on commit c4d1957

Please sign in to comment.