policy: Refactor PkOrF into an enum

For whatever reason we were using a struct as an enum, so we might as
well fix it in this PR since we are already breaking the API quite
badly.
This commit is contained in:
Alekos Filini 2022-05-24 10:39:17 +02:00
parent 308708952b
commit ff1abc63e0
No known key found for this signature in database
GPG Key ID: 431401E4A4530061
2 changed files with 31 additions and 48 deletions

View File

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add traits to reuse `Blockchain`s across multiple wallets (`BlockchainFactory` and `StatelessBlockchain`). - Add traits to reuse `Blockchain`s across multiple wallets (`BlockchainFactory` and `StatelessBlockchain`).
- Upgrade to rust-bitcoin `0.28` - Upgrade to rust-bitcoin `0.28`
- If using the `sqlite-db` feature all cached wallet data is deleted due to a possible UTXO inconsistency, a wallet.sync will recreate it - If using the `sqlite-db` feature all cached wallet data is deleted due to a possible UTXO inconsistency, a wallet.sync will recreate it
- Update `PkOrF` in the policy module to become an enum
## [v0.18.0] - [v0.17.0] ## [v0.18.0] - [v0.17.0]

View File

@ -67,17 +67,16 @@ use super::XKeyUtils;
use bitcoin::util::psbt::{Input as PsbtInput, PartiallySignedTransaction as Psbt}; use bitcoin::util::psbt::{Input as PsbtInput, PartiallySignedTransaction as Psbt};
use miniscript::psbt::PsbtInputSatisfier; use miniscript::psbt::PsbtInputSatisfier;
/// Raw public key or extended key fingerprint /// A unique identifier for a key
#[derive(Debug, Clone, Default, Serialize)] #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
pub struct PkOrF { #[serde(rename_all = "snake_case")]
#[serde(skip_serializing_if = "Option::is_none")] pub enum PkOrF {
pubkey: Option<PublicKey>, /// A legacy public key
#[serde(skip_serializing_if = "Option::is_none")] Pubkey(PublicKey),
x_only_pubkey: Option<XOnlyPublicKey>, /// A x-only public key
#[serde(skip_serializing_if = "Option::is_none")] XOnlyPubkey(XOnlyPublicKey),
pubkey_hash: Option<hash160::Hash>, /// An extended key fingerprint
#[serde(skip_serializing_if = "Option::is_none")] Fingerprint(Fingerprint),
fingerprint: Option<Fingerprint>,
} }
impl PkOrF { impl PkOrF {
@ -86,27 +85,18 @@ impl PkOrF {
DescriptorPublicKey::SinglePub(DescriptorSinglePub { DescriptorPublicKey::SinglePub(DescriptorSinglePub {
key: SinglePubKey::FullKey(pk), key: SinglePubKey::FullKey(pk),
.. ..
}) => PkOrF { }) => PkOrF::Pubkey(*pk),
pubkey: Some(*pk),
..Default::default()
},
DescriptorPublicKey::SinglePub(DescriptorSinglePub { DescriptorPublicKey::SinglePub(DescriptorSinglePub {
key: SinglePubKey::XOnly(pk), key: SinglePubKey::XOnly(pk),
.. ..
}) => PkOrF { }) => PkOrF::XOnlyPubkey(*pk),
x_only_pubkey: Some(*pk), DescriptorPublicKey::XPub(xpub) => PkOrF::Fingerprint(xpub.root_fingerprint(secp)),
..Default::default()
},
DescriptorPublicKey::XPub(xpub) => PkOrF {
fingerprint: Some(xpub.root_fingerprint(secp)),
..Default::default()
},
} }
} }
} }
/// An item that needs to be satisfied /// An item that needs to be satisfied
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(tag = "type", rename_all = "UPPERCASE")] #[serde(tag = "type", rename_all = "UPPERCASE")]
pub enum SatisfiableItem { pub enum SatisfiableItem {
// Leaves // Leaves
@ -260,7 +250,7 @@ where
} }
/// Represent if and how much a policy item is satisfied by the wallet's descriptor /// Represent if and how much a policy item is satisfied by the wallet's descriptor
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(tag = "type", rename_all = "UPPERCASE")] #[serde(tag = "type", rename_all = "UPPERCASE")]
pub enum Satisfaction { pub enum Satisfaction {
/// Only a partial satisfaction of some kind of threshold policy /// Only a partial satisfaction of some kind of threshold policy
@ -434,7 +424,7 @@ impl From<bool> for Satisfaction {
} }
/// Descriptor spending policy /// Descriptor spending policy
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Policy { pub struct Policy {
/// Identifier for this policy node /// Identifier for this policy node
pub id: String, pub id: String,
@ -1116,9 +1106,7 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert!(matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint));
matches!(&policy.item, EcdsaSignature(pk_or_f) if pk_or_f.fingerprint.unwrap() == fingerprint)
);
assert!(matches!(&policy.contribution, Satisfaction::None)); assert!(matches!(&policy.contribution, Satisfaction::None));
let desc = descriptor!(wpkh(prvkey)).unwrap(); let desc = descriptor!(wpkh(prvkey)).unwrap();
@ -1131,9 +1119,7 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert!(matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint));
matches!(&policy.item, EcdsaSignature(pk_or_f) if pk_or_f.fingerprint.unwrap() == fingerprint)
);
assert!( assert!(
matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == None) matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == None)
); );
@ -1157,8 +1143,8 @@ mod test {
assert!( assert!(
matches!(&policy.item, Multisig { keys, threshold } if threshold == &2usize matches!(&policy.item, Multisig { keys, threshold } if threshold == &2usize
&& keys[0].fingerprint.unwrap() == fingerprint0 && keys[0] == PkOrF::Fingerprint(fingerprint0)
&& keys[1].fingerprint.unwrap() == fingerprint1) && keys[1] == PkOrF::Fingerprint(fingerprint1))
); );
// TODO should this be "Satisfaction::None" since we have no prv keys? // TODO should this be "Satisfaction::None" since we have no prv keys?
// TODO should items and conditions not be empty? // TODO should items and conditions not be empty?
@ -1188,8 +1174,8 @@ mod test {
.unwrap(); .unwrap();
assert!( assert!(
matches!(&policy.item, Multisig { keys, threshold } if threshold == &2usize matches!(&policy.item, Multisig { keys, threshold } if threshold == &2usize
&& keys[0].fingerprint.unwrap() == fingerprint0 && keys[0] == PkOrF::Fingerprint(fingerprint0)
&& keys[1].fingerprint.unwrap() == fingerprint1) && keys[1] == PkOrF::Fingerprint(fingerprint1))
); );
assert!( assert!(
@ -1221,8 +1207,8 @@ mod test {
assert!( assert!(
matches!(&policy.item, Multisig { keys, threshold } if threshold == &1 matches!(&policy.item, Multisig { keys, threshold } if threshold == &1
&& keys[0].fingerprint.unwrap() == fingerprint0 && keys[0] == PkOrF::Fingerprint(fingerprint0)
&& keys[1].fingerprint.unwrap() == fingerprint1) && keys[1] == PkOrF::Fingerprint(fingerprint1))
); );
assert!( assert!(
matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2 matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2
@ -1253,8 +1239,8 @@ mod test {
assert!( assert!(
matches!(&policy.item, Multisig { keys, threshold } if threshold == &2 matches!(&policy.item, Multisig { keys, threshold } if threshold == &2
&& keys[0].fingerprint.unwrap() == fingerprint0 && keys[0] == PkOrF::Fingerprint(fingerprint0)
&& keys[1].fingerprint.unwrap() == fingerprint1) && keys[1] == PkOrF::Fingerprint(fingerprint1))
); );
assert!( assert!(
@ -1284,9 +1270,7 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert!(matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint));
matches!(&policy.item, EcdsaSignature(pk_or_f) if pk_or_f.fingerprint.unwrap() == fingerprint)
);
assert!(matches!(&policy.contribution, Satisfaction::None)); assert!(matches!(&policy.contribution, Satisfaction::None));
let desc = descriptor!(wpkh(prvkey)).unwrap(); let desc = descriptor!(wpkh(prvkey)).unwrap();
@ -1300,9 +1284,7 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert!(matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint));
matches!(&policy.item, EcdsaSignature(pk_or_f) if pk_or_f.fingerprint.unwrap() == fingerprint)
);
assert!( assert!(
matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == None) matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == None)
); );
@ -1329,8 +1311,8 @@ mod test {
assert!( assert!(
matches!(&policy.item, Multisig { keys, threshold } if threshold == &1 matches!(&policy.item, Multisig { keys, threshold } if threshold == &1
&& keys[0].fingerprint.unwrap() == fingerprint0 && keys[0] == PkOrF::Fingerprint(fingerprint0)
&& keys[1].fingerprint.unwrap() == fingerprint1) && keys[1] == PkOrF::Fingerprint(fingerprint1))
); );
assert!( assert!(
matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2 matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2