refactor: premintsecrets from p2pk conditions

This commit is contained in:
thesimplekid
2024-02-18 22:29:51 +00:00
parent 675dba1716
commit 2bacda4a56
4 changed files with 111 additions and 37 deletions

View File

@@ -385,7 +385,7 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
Ok(())
}
/// Create Split Payload
/// Create Swap Payload
async fn create_swap(
&mut self,
mint_url: &UncheckedUrl,
@@ -393,7 +393,7 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
amount: Option<Amount>,
proofs: Proofs,
) -> Result<PreSwap, Error> {
// Since split is used to get the needed combination of tokens for a specific
// Since swap is used to get the needed combination of tokens for a specific
// amount first blinded messages are created for the amount
let active_keyset_id = self.active_mint_keyset(mint_url, unit).await?.unwrap();
@@ -510,6 +510,9 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
self.localstore
.add_pending_proofs(mint_url.clone(), proofs)
.await?;
self.localstore
.add_pending_proofs(mint_url.clone(), send_proofs.clone())
.await?;
self.localstore
.add_proofs(mint_url.clone(), keep_proofs)

View File

@@ -48,6 +48,8 @@ pub enum Error {
Key,
#[error("Invalid signature")]
InvalidSignature,
#[error("Locktime in past")]
LocktimeInPast,
/// Custom error
#[error("`{0}`")]
CustomError(String),

View File

@@ -100,7 +100,7 @@ pub mod wallet {
use super::{CurrencyUnit, MintProofs};
use crate::dhke::blind_message;
use crate::error::wallet;
use crate::nuts::{BlindedMessage, Id, Proofs, SecretKey};
use crate::nuts::{BlindedMessage, Id, P2PKConditions, Proofs, SecretKey};
use crate::secret::Secret;
use crate::url::UncheckedUrl;
use crate::{error, Amount};
@@ -134,28 +134,6 @@ pub mod wallet {
secrets: Vec<PreMint>,
}
// Implement Iterator for PreMintSecrets
impl Iterator for PreMintSecrets {
type Item = PreMint;
fn next(&mut self) -> Option<Self::Item> {
// Use the iterator of the vector
self.secrets.pop()
}
}
impl Ord for PreMintSecrets {
fn cmp(&self, other: &Self) -> Ordering {
self.secrets.cmp(&other.secrets)
}
}
impl PartialOrd for PreMintSecrets {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PreMintSecrets {
/// Outputs for speceifed amount with random secret
pub fn random(keyset_id: Id, amount: Amount) -> Result<Self, wallet::Error> {
@@ -278,6 +256,37 @@ pub mod wallet {
Ok(pre_mint_secrets)
}
#[cfg(feature = "nut11")]
pub fn with_p2pk_conditions(
keyset_id: Id,
amount: Amount,
conditions: P2PKConditions,
) -> Result<Self, wallet::Error> {
let amount_split = amount.split();
let mut output = Vec::with_capacity(amount_split.len());
for amount in amount_split {
let secret: Secret = conditions.clone().try_into().unwrap();
let (blinded, r) = blind_message(&secret.to_bytes()?, None)?;
let blinded_message = BlindedMessage {
amount,
b: blinded,
keyset_id,
};
output.push(PreMint {
secret,
blinded_message,
r: r.into(),
amount,
});
}
Ok(PreMintSecrets { secrets: output })
}
pub fn iter(&self) -> impl Iterator<Item = &PreMint> {
self.secrets.iter()
}
@@ -322,6 +331,28 @@ pub mod wallet {
}
}
// Implement Iterator for PreMintSecrets
impl Iterator for PreMintSecrets {
type Item = PreMint;
fn next(&mut self) -> Option<Self::Item> {
// Use the iterator of the vector
self.secrets.pop()
}
}
impl Ord for PreMintSecrets {
fn cmp(&self, other: &Self) -> Ordering {
self.secrets.cmp(&other.secrets)
}
}
impl PartialOrd for PreMintSecrets {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Token {
pub token: Vec<MintProofs>,

View File

@@ -80,13 +80,41 @@ impl PartialOrd for Proof {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct P2PKConditions {
#[serde(skip_serializing_if = "Option::is_none")]
pub locktime: Option<u64>,
pub pubkeys: Vec<PublicKey>,
pub refund_keys: Option<Vec<PublicKey>>,
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub refund_keys: Vec<PublicKey>,
#[serde(skip_serializing_if = "Option::is_none")]
pub num_sigs: Option<u64>,
pub sig_flag: SigFlag,
}
impl P2PKConditions {
pub fn new(
locktime: Option<u64>,
pubkeys: Vec<PublicKey>,
refund_keys: Vec<PublicKey>,
num_sigs: Option<u64>,
sig_flag: Option<SigFlag>,
) -> Result<Self, Error> {
if let Some(locktime) = locktime {
if locktime.lt(&unix_time()) {
return Err(Error::LocktimeInPast);
}
}
Ok(Self {
locktime,
pubkeys,
refund_keys,
num_sigs,
sig_flag: sig_flag.unwrap_or_default(),
})
}
}
impl TryFrom<P2PKConditions> for Secret {
type Error = Error;
fn try_from(conditions: P2PKConditions) -> Result<Secret, Self::Error> {
@@ -119,7 +147,7 @@ impl TryFrom<P2PKConditions> for Secret {
tags.push(Tag::NSigs(num_sigs).as_vec());
}
if let Some(refund_keys) = refund_keys {
if !refund_keys.is_empty() {
tags.push(Tag::Refund(refund_keys).as_vec())
}
@@ -136,6 +164,15 @@ impl TryFrom<P2PKConditions> for Secret {
}
}
impl TryFrom<P2PKConditions> for crate::secret::Secret {
type Error = Error;
fn try_from(conditions: P2PKConditions) -> Result<crate::secret::Secret, Self::Error> {
let secret: Secret = conditions.try_into()?;
secret.try_into()
}
}
impl TryFrom<Secret> for P2PKConditions {
type Error = Error;
fn try_from(secret: Secret) -> Result<P2PKConditions, Self::Error> {
@@ -171,11 +208,11 @@ impl TryFrom<Secret> for P2PKConditions {
let refund_keys = if let Some(tag) = tags.get(&TagKind::Refund) {
match tag {
Tag::Refund(keys) => Some(keys.clone()),
_ => None,
Tag::Refund(keys) => keys.clone(),
_ => vec![],
}
} else {
None
vec![]
};
let sig_flag = if let Some(tag) = tags.get(&TagKind::SigFlag) {
@@ -246,9 +283,9 @@ impl Proof {
if let Some(locktime) = spending_conditions.locktime {
// If lock time has passed check if refund witness signature is valid
if locktime.lt(&unix_time()) {
if let Some(refund_pubkeys) = &spending_conditions.refund_keys {
if !spending_conditions.refund_keys.is_empty() {
for s in &self.witness.signatures {
for v in refund_pubkeys {
for v in &spending_conditions.refund_keys {
let sig = Signature::try_from(s.as_bytes())
.map_err(|_| Error::InvalidSignature)?;
let v: VerifyingKey = v.clone().try_into()?;
@@ -325,10 +362,11 @@ where
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, Hash)]
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, Hash)]
pub enum SigFlag {
SigAll,
#[default]
SigInputs,
SigAll,
Custom(String),
}
@@ -506,10 +544,10 @@ mod tests {
)
.unwrap(),
],
refund_keys: Some(vec![PublicKey::from_str(
refund_keys: vec![PublicKey::from_str(
"033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e",
)
.unwrap()]),
.unwrap()],
num_sigs: Some(2),
sig_flag: SigFlag::SigAll,
};
@@ -545,7 +583,7 @@ mod tests {
let conditions = P2PKConditions {
locktime: None,
pubkeys: vec![v_key.into()],
refund_keys: None,
refund_keys: vec![],
num_sigs: None,
sig_flag: SigFlag::SigInputs,
};