Skip to content

Commit 84cf50e

Browse files
committed
policies: refactor policy enum
Turn it into a struct containing the original policy, so we don't have to repeat it in every enum arm when we add more arms.
1 parent 03a7434 commit 84cf50e

File tree

2 files changed

+43
-51
lines changed

2 files changed

+43
-51
lines changed

src/rust/bitbox02-rust/src/hww/api/bitcoin/common.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ impl Payload {
155155
keypath: &[u32],
156156
) -> Result<Self, Error> {
157157
let witness_script = policy.witness_script_at_keypath(keypath)?;
158-
match policy {
159-
super::policies::ParsedPolicy::Wsh { .. } => Ok(Payload {
158+
match &policy.descriptor {
159+
super::policies::Descriptor::Wsh { .. } => Ok(Payload {
160160
data: Sha256::digest(witness_script).to_vec(),
161161
output_type: BtcOutputType::P2wsh,
162162
}),

src/rust/bitbox02-rust/src/hww/api/bitcoin/policies.rs

Lines changed: 41 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -174,26 +174,26 @@ impl<'a> miniscript::Translator<String, bitcoin::PublicKey, Error>
174174

175175
/// See `ParsedPolicy`.
176176
#[derive(Debug)]
177-
pub struct Wsh<'a> {
178-
policy: &'a Policy,
177+
pub struct Wsh {
179178
miniscript_expr: miniscript::Miniscript<String, miniscript::Segwitv0>,
180179
}
181180

182-
/// Result of `parse()`.
181+
/// See `ParsedPolicy`.
183182
#[derive(Debug)]
184-
pub enum ParsedPolicy<'a> {
183+
pub enum Descriptor {
185184
// `wsh(...)` policies
186-
Wsh(Wsh<'a>),
185+
Wsh(Wsh),
187186
// `tr(...)` Taproot etc. in the future.
188187
}
189188

190-
impl<'a> ParsedPolicy<'a> {
191-
fn get_policy(&self) -> &Policy {
192-
match self {
193-
Self::Wsh(Wsh { policy, .. }) => policy,
194-
}
195-
}
189+
/// Result of `parse()`.
190+
#[derive(Debug)]
191+
pub struct ParsedPolicy<'a> {
192+
policy: &'a Policy,
193+
pub descriptor: Descriptor,
194+
}
196195

196+
impl<'a> ParsedPolicy<'a> {
197197
/// Check that it is impossible to create a derivation with duplicate pubkeys, assuming all the
198198
/// keys in the key vector are distinct.
199199
///
@@ -204,16 +204,13 @@ impl<'a> ParsedPolicy<'a> {
204204
/// Also checks that each key is used, e.g. if there are 3 keys in the key vector, @0, @1 and @2
205205
/// must be present.
206206
fn validate_keys(&self) -> Result<(), Error> {
207-
match self {
208-
Self::Wsh(Wsh {
209-
policy,
210-
miniscript_expr,
211-
}) => {
207+
match &self.descriptor {
208+
Descriptor::Wsh(Wsh { miniscript_expr }) => {
212209
// in "@key_index/<left;right>", keeps track of (key_index,left) and
213210
// (key_index,right) to check for duplicates.
214211
let mut derivations_seen: Vec<(usize, u32)> = Vec::new();
215212

216-
let mut keys_seen: Vec<bool> = vec![false; policy.keys.len()];
213+
let mut keys_seen: Vec<bool> = vec![false; self.policy.keys.len()];
217214

218215
for pk in miniscript_expr.iter_pk() {
219216
let (key_index, multipath_index_left, multipath_index_right) =
@@ -248,7 +245,7 @@ impl<'a> ParsedPolicy<'a> {
248245
pub fn validate(&self, coin: BtcCoin) -> Result<(), Error> {
249246
check_enabled(coin)?;
250247

251-
let policy = self.get_policy();
248+
let policy = self.policy;
252249

253250
if policy.keys.len() > MAX_KEYS {
254251
return Err(Error::InvalidInput);
@@ -297,13 +294,10 @@ impl<'a> ParsedPolicy<'a> {
297294
/// wsh(and_v(v:pk(@0/0/5),pk(@1/20/5))).
298295
/// The same derived using `is_change=true` derives: wsh(and_v(v:pk(@0/1/5),pk(@1/21/5)))
299296
pub fn witness_script(&self, is_change: bool, address_index: u32) -> Result<Vec<u8>, Error> {
300-
match self {
301-
Self::Wsh(Wsh {
302-
policy,
303-
miniscript_expr,
304-
}) => {
297+
match &self.descriptor {
298+
Descriptor::Wsh(Wsh { miniscript_expr }) => {
305299
let mut translator = WalletPolicyPkTranslator {
306-
keys: policy.keys.as_ref(),
300+
keys: self.policy.keys.as_ref(),
307301
is_change,
308302
address_index,
309303
};
@@ -322,27 +316,27 @@ impl<'a> ParsedPolicy<'a> {
322316
/// derived using keypath m/48'/1'/0'/3'/11/5 derives:
323317
/// wsh(and_v(v:pk(@0/11/5),pk(@1/21/5))).
324318
pub fn witness_script_at_keypath(&self, keypath: &[u32]) -> Result<Vec<u8>, Error> {
325-
match self {
326-
Self::Wsh(Wsh {
327-
policy,
328-
miniscript_expr,
329-
}) => {
330-
let (is_change, address_index) =
331-
get_change_and_address_index(miniscript_expr.iter_pk(), &policy.keys, keypath)?;
319+
match &self.descriptor {
320+
Descriptor::Wsh(Wsh { miniscript_expr }) => {
321+
let (is_change, address_index) = get_change_and_address_index(
322+
miniscript_expr.iter_pk(),
323+
&self.policy.keys,
324+
keypath,
325+
)?;
332326
self.witness_script(is_change, address_index)
333327
}
334328
}
335329
}
336330

337331
/// Returns true if the address-level keypath points to a change address.
338332
pub fn is_change_keypath(&self, keypath: &[u32]) -> Result<bool, Error> {
339-
match self {
340-
Self::Wsh(Wsh {
341-
policy,
342-
miniscript_expr,
343-
}) => {
344-
let (is_change, _) =
345-
get_change_and_address_index(miniscript_expr.iter_pk(), &policy.keys, keypath)?;
333+
match &self.descriptor {
334+
Descriptor::Wsh(Wsh { miniscript_expr }) => {
335+
let (is_change, _) = get_change_and_address_index(
336+
miniscript_expr.iter_pk(),
337+
&self.policy.keys,
338+
keypath,
339+
)?;
346340
Ok(is_change)
347341
}
348342
}
@@ -364,10 +358,10 @@ pub fn parse(policy: &Policy) -> Result<ParsedPolicy, Error> {
364358
miniscript::Miniscript::from_str(&desc[4..desc.len() - 1])
365359
.or(Err(Error::InvalidInput))?;
366360

367-
Ok(ParsedPolicy::Wsh(Wsh {
361+
Ok(ParsedPolicy {
368362
policy,
369-
miniscript_expr,
370-
}))
363+
descriptor: Descriptor::Wsh(Wsh { miniscript_expr }),
364+
})
371365
}
372366
_ => Err(Error::InvalidInput),
373367
}
@@ -595,10 +589,9 @@ mod tests {
595589
fn test_parse_wsh_miniscript() {
596590
// Parse a valid example and check that the keys are collected as is as strings.
597591
let policy = make_policy("wsh(pk(@0/**))", &[]);
598-
match parse(&policy).unwrap() {
599-
ParsedPolicy::Wsh(Wsh {
600-
ref miniscript_expr,
601-
..
592+
match &parse(&policy).unwrap().descriptor {
593+
Descriptor::Wsh(Wsh {
594+
miniscript_expr, ..
602595
}) => {
603596
assert_eq!(
604597
miniscript_expr.iter_pk().collect::<Vec<String>>(),
@@ -609,10 +602,9 @@ mod tests {
609602

610603
// Parse another valid example and check that the keys are collected as is as strings.
611604
let policy = make_policy("wsh(or_b(pk(@0/**),s:pk(@1/**)))", &[]);
612-
match parse(&policy).unwrap() {
613-
ParsedPolicy::Wsh(Wsh {
614-
ref miniscript_expr,
615-
..
605+
match &parse(&policy).unwrap().descriptor {
606+
Descriptor::Wsh(Wsh {
607+
miniscript_expr, ..
616608
}) => {
617609
assert_eq!(
618610
miniscript_expr.iter_pk().collect::<Vec<String>>(),

0 commit comments

Comments
 (0)