refactor: rename 'BlindedMessages' to 'PreMintSecrets'

In the nuts 'BlindedMessages' is a Vec<BlindedMessage>
using it another way is confusing this avoids that.
This commit is contained in:
thesimplekid
2023-11-27 22:47:18 +00:00
parent 78f35eda8e
commit b92be032ee
18 changed files with 260 additions and 197 deletions

View File

@@ -98,7 +98,7 @@ interface Token {
};
interface BlindedMessages {
interface PreMintSecrets {
[Throws=CashuError, Name=random]
constructor(Id keyset_id, Amount amount);
[Throws=CashuError, Name=blank]

View File

@@ -7,9 +7,9 @@ mod ffi {
pub use crate::error::CashuError;
pub use crate::nuts::nut00::blinded_message::BlindedMessage;
pub use crate::nuts::nut00::blinded_messages::BlindedMessages;
pub use crate::nuts::nut00::blinded_signature::BlindedSignature;
pub use crate::nuts::nut00::mint_proofs::MintProofs;
pub use crate::nuts::nut00::premint_secrets::PreMintSecrets;
pub use crate::nuts::nut00::proof::mint::Proof as MintProof;
pub use crate::nuts::nut00::proof::Proof;
pub use crate::nuts::nut00::token::Token;

View File

@@ -1,86 +0,0 @@
use std::ops::Deref;
use std::sync::Arc;
use cashu::nuts::nut00::wallet::BlindedMessages as BlindedMessagesSdk;
use crate::error::Result;
use crate::{Amount, BlindedMessage, Id, Secret, SecretKey};
pub struct BlindedMessages {
inner: BlindedMessagesSdk,
}
impl Deref for BlindedMessages {
type Target = BlindedMessagesSdk;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl BlindedMessages {
pub fn random(keyset_id: Arc<Id>, amount: Arc<Amount>) -> Result<Self> {
Ok(Self {
inner: BlindedMessagesSdk::random(
*keyset_id.as_ref().deref(),
*amount.as_ref().deref(),
)?,
})
}
pub fn blank(keyset_id: Arc<Id>, fee_reserve: Arc<Amount>) -> Result<Self> {
Ok(Self {
inner: BlindedMessagesSdk::blank(
*keyset_id.as_ref().deref(),
*fee_reserve.as_ref().deref(),
)?,
})
}
pub fn blinded_messages(&self) -> Vec<Arc<BlindedMessage>> {
self.inner
.blinded_messages
.clone()
.into_iter()
.map(|b| Arc::new(b.into()))
.collect()
}
pub fn secrets(&self) -> Vec<Arc<Secret>> {
self.inner
.secrets
.clone()
.into_iter()
.map(|s| Arc::new(s.into()))
.collect()
}
pub fn rs(&self) -> Vec<Arc<SecretKey>> {
self.inner
.rs
.clone()
.into_iter()
.map(|s| Arc::new(s.into()))
.collect()
}
pub fn amounts(&self) -> Vec<Arc<Amount>> {
self.inner
.amounts
.clone()
.into_iter()
.map(|a| Arc::new(a.into()))
.collect()
}
}
impl From<cashu::nuts::nut00::wallet::BlindedMessages> for BlindedMessages {
fn from(inner: cashu::nuts::nut00::wallet::BlindedMessages) -> BlindedMessages {
BlindedMessages { inner }
}
}
impl From<BlindedMessages> for cashu::nuts::nut00::wallet::BlindedMessages {
fn from(blinded_messages: BlindedMessages) -> cashu::nuts::nut00::wallet::BlindedMessages {
blinded_messages.inner
}
}

View File

@@ -1,6 +1,6 @@
pub mod blinded_message;
pub mod blinded_messages;
pub mod blinded_signature;
pub mod mint_proofs;
pub mod premint_secrets;
pub mod proof;
pub mod token;

View File

@@ -0,0 +1,78 @@
use std::ops::Deref;
use std::sync::Arc;
use cashu::nuts::nut00::wallet::PreMintSecrets as PreMintSecretsSdk;
use crate::error::Result;
use crate::{Amount, BlindedMessage, Id, Secret, SecretKey};
pub struct PreMintSecrets {
inner: PreMintSecretsSdk,
}
impl Deref for PreMintSecrets {
type Target = PreMintSecretsSdk;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl PreMintSecrets {
pub fn random(keyset_id: Arc<Id>, amount: Arc<Amount>) -> Result<Self> {
Ok(Self {
inner: PreMintSecretsSdk::random(
*keyset_id.as_ref().deref(),
*amount.as_ref().deref(),
)?,
})
}
pub fn blank(keyset_id: Arc<Id>, fee_reserve: Arc<Amount>) -> Result<Self> {
Ok(Self {
inner: PreMintSecretsSdk::blank(
*keyset_id.as_ref().deref(),
*fee_reserve.as_ref().deref(),
)?,
})
}
pub fn blinded_messages(&self) -> Vec<Arc<BlindedMessage>> {
self.inner
.iter()
.map(|premint| Arc::new(premint.blinded_message.clone().into()))
.collect()
}
pub fn secrets(&self) -> Vec<Arc<Secret>> {
self.inner
.iter()
.map(|premint| Arc::new(premint.secret.clone().into()))
.collect()
}
pub fn rs(&self) -> Vec<Arc<SecretKey>> {
self.inner
.iter()
.map(|premint| Arc::new(premint.r.clone().into()))
.collect()
}
pub fn amounts(&self) -> Vec<Arc<Amount>> {
self.inner
.iter()
.map(|premint| Arc::new(premint.amount.into()))
.collect()
}
}
impl From<cashu::nuts::nut00::wallet::PreMintSecrets> for PreMintSecrets {
fn from(inner: cashu::nuts::nut00::wallet::PreMintSecrets) -> PreMintSecrets {
PreMintSecrets { inner }
}
}
impl From<PreMintSecrets> for cashu::nuts::nut00::wallet::PreMintSecrets {
fn from(blinded_messages: PreMintSecrets) -> cashu::nuts::nut00::wallet::PreMintSecrets {
blinded_messages.inner
}
}

View File

@@ -1,6 +1,6 @@
use std::ops::Deref;
use cashu::nuts::nut00::wallet::BlindedMessages;
use cashu::nuts::nut00::wallet::PreMintSecrets;
use wasm_bindgen::prelude::*;
use crate::error::{into_err, Result};
@@ -9,11 +9,11 @@ use crate::types::JsAmount;
#[wasm_bindgen(js_name = BlindedMessages)]
pub struct JsBlindedMessages {
inner: BlindedMessages,
inner: PreMintSecrets,
}
impl Deref for JsBlindedMessages {
type Target = BlindedMessages;
type Target = PreMintSecrets;
fn deref(&self) -> &Self::Target {
&self.inner
}
@@ -24,15 +24,14 @@ impl JsBlindedMessages {
#[wasm_bindgen(js_name = random)]
pub fn random(keyset_id: JsId, amount: JsAmount) -> Result<JsBlindedMessages> {
Ok(JsBlindedMessages {
inner: BlindedMessages::random(*keyset_id.deref(), *amount.deref())
.map_err(into_err)?,
inner: PreMintSecrets::random(*keyset_id.deref(), *amount.deref()).map_err(into_err)?,
})
}
#[wasm_bindgen(js_name = blank)]
pub fn blank(keyset_id: JsId, fee_reserve: JsAmount) -> Result<JsBlindedMessages> {
Ok(JsBlindedMessages {
inner: BlindedMessages::blank(*keyset_id.deref(), *fee_reserve.deref())
inner: PreMintSecrets::blank(*keyset_id.deref(), *fee_reserve.deref())
.map_err(into_err)?,
})
}
@@ -40,24 +39,24 @@ impl JsBlindedMessages {
/// Blinded Messages
#[wasm_bindgen(getter)]
pub fn blinded_messages(&self) -> Result<JsValue> {
serde_wasm_bindgen::to_value(&self.inner.blinded_messages).map_err(into_err)
serde_wasm_bindgen::to_value(&self.inner.blinded_messages()).map_err(into_err)
}
/// Secrets
#[wasm_bindgen(getter)]
pub fn secrets(&self) -> Result<JsValue> {
serde_wasm_bindgen::to_value(&self.inner.secrets).map_err(into_err)
serde_wasm_bindgen::to_value(&self.inner.secrets()).map_err(into_err)
}
/// rs
#[wasm_bindgen(getter)]
pub fn rs(&self) -> Result<JsValue> {
serde_wasm_bindgen::to_value(&self.inner.rs).map_err(into_err)
serde_wasm_bindgen::to_value(&self.inner.rs()).map_err(into_err)
}
/// Amounts
#[wasm_bindgen(getter)]
pub fn amounts(&self) -> Result<JsValue> {
serde_wasm_bindgen::to_value(&self.inner.amounts).map_err(into_err)
serde_wasm_bindgen::to_value(&self.inner.amounts()).map_err(into_err)
}
}

View File

@@ -101,7 +101,7 @@ interface Token {
};
interface BlindedMessages {
interface PreMintSecrets {
[Throws=CashuError, Name=random]
constructor(Id keyset_id, Amount amount);
[Throws=CashuError, Name=blank]
@@ -307,7 +307,7 @@ interface Wallet {
[Throws=CashuSdkError]
sequence<Proof> receive(string encoded_token);
[Throws=CashuSdkError]
sequence<Proof> process_split_response(BlindedMessages blinded_messages, sequence<BlindedSignature> promises);
sequence<Proof> process_split_response(PreMintSecrets blinded_messages, sequence<BlindedSignature> promises);
[Throws=CashuSdkError]
SendProofs send(Amount amount, sequence<Proof> proofs);
[Throws=CashuSdkError]

View File

@@ -5,12 +5,12 @@ mod wallet;
mod ffi {
pub use cashu_ffi::{
Amount, BlindedMessage, BlindedMessages, BlindedSignature, Bolt11Invoice, CashuError,
CheckFeesRequest, CheckFeesResponse, CheckSpendableRequest, CheckSpendableResponse, Id,
InvoiceStatus, KeyPair, KeySet, KeySetInfo, KeySetResponse, Keys, KeysResponse,
MeltRequest, MeltResponse, MintInfo, MintKeySet, MintProof, MintProofs, MintRequest,
MintVersion, Nut05MeltRequest, Nut05MeltResponse, PostMintResponse, Proof, PublicKey,
RequestMintResponse, Secret, SecretKey, SplitRequest, SplitResponse, Token,
Amount, BlindedMessage, BlindedSignature, Bolt11Invoice, CashuError, CheckFeesRequest,
CheckFeesResponse, CheckSpendableRequest, CheckSpendableResponse, Id, InvoiceStatus,
KeyPair, KeySet, KeySetInfo, KeySetResponse, Keys, KeysResponse, MeltRequest, MeltResponse,
MintInfo, MintKeySet, MintProof, MintProofs, MintRequest, MintVersion, Nut05MeltRequest,
Nut05MeltResponse, PostMintResponse, PreMintSecrets, Proof, PublicKey, RequestMintResponse,
Secret, SecretKey, SplitRequest, SplitResponse, Token,
};
pub use crate::error::CashuSdkError;

View File

@@ -2,7 +2,7 @@ use std::ops::Deref;
use std::sync::Arc;
use cashu_ffi::{
BlindedMessages, BlindedSignature, Bolt11Invoice, Proof, RequestMintResponse, Token,
BlindedSignature, Bolt11Invoice, PreMintSecrets, Proof, RequestMintResponse, Token,
};
use cashu_sdk::client::minreq_client::HttpClient;
use cashu_sdk::types::ProofsStatus;
@@ -88,7 +88,7 @@ impl Wallet {
pub fn process_split_response(
&self,
blinded_messages: Arc<BlindedMessages>,
blinded_messages: Arc<PreMintSecrets>,
promises: Vec<Arc<BlindedSignature>>,
) -> Result<Vec<Arc<Proof>>> {
Ok(self

View File

@@ -4,8 +4,8 @@ use async_trait::async_trait;
#[cfg(feature = "nut09")]
use cashu::nuts::MintInfo;
use cashu::nuts::{
BlindedMessage, BlindedMessages, CheckFeesRequest, CheckFeesResponse, Keys, MeltRequest,
MeltResponse, MintRequest, PostMintResponse, Proof, RequestMintResponse, SplitRequest,
BlindedMessage, CheckFeesRequest, CheckFeesResponse, Keys, MeltRequest, MeltResponse,
MintRequest, PostMintResponse, PreMintSecrets, Proof, RequestMintResponse, SplitRequest,
SplitResponse, *,
};
#[cfg(feature = "nut07")]
@@ -89,14 +89,14 @@ impl Client for HttpClient {
async fn post_mint(
&self,
mint_url: Url,
blinded_messages: BlindedMessages,
premint_secrets: PreMintSecrets,
hash: &str,
) -> Result<PostMintResponse, Error> {
let mut url = join_url(mint_url, "mint")?;
url.query_pairs_mut().append_pair("hash", hash);
let request = MintRequest {
outputs: blinded_messages.blinded_messages,
outputs: premint_secrets.blinded_messages(),
};
let res = Request::post(url.as_str())

View File

@@ -6,8 +6,8 @@ use async_trait::async_trait;
#[cfg(feature = "nut09")]
use cashu::nuts::MintInfo;
use cashu::nuts::{
BlindedMessage, BlindedMessages, CheckFeesRequest, CheckFeesResponse, Keys, MeltRequest,
MeltResponse, MintRequest, PostMintResponse, Proof, RequestMintResponse, SplitRequest,
BlindedMessage, CheckFeesRequest, CheckFeesResponse, Keys, MeltRequest, MeltResponse,
MintRequest, PostMintResponse, PreMintSecrets, Proof, RequestMintResponse, SplitRequest,
SplitResponse, *,
};
#[cfg(feature = "nut07")]
@@ -72,14 +72,14 @@ impl Client for HttpClient {
async fn post_mint(
&self,
mint_url: Url,
blinded_messages: BlindedMessages,
premint_secrets: PreMintSecrets,
hash: &str,
) -> Result<PostMintResponse, Error> {
let mut url = join_url(mint_url, "mint")?;
url.query_pairs_mut().append_pair("hash", hash);
let request = MintRequest {
outputs: blinded_messages.blinded_messages,
outputs: premint_secrets.blinded_messages(),
};
let res = minreq::post(url)

View File

@@ -8,8 +8,8 @@ use cashu::nuts::CheckSpendableResponse;
#[cfg(feature = "nut09")]
use cashu::nuts::MintInfo;
use cashu::nuts::{
BlindedMessage, BlindedMessages, CheckFeesResponse, Keys, KeysetResponse, MeltResponse,
PostMintResponse, Proof, RequestMintResponse, SplitRequest, SplitResponse,
BlindedMessage, CheckFeesResponse, Keys, KeysetResponse, MeltResponse, PostMintResponse,
PreMintSecrets, Proof, RequestMintResponse, SplitRequest, SplitResponse,
};
use cashu::{utils, Amount};
use serde::{Deserialize, Serialize};
@@ -99,7 +99,7 @@ pub trait Client {
async fn post_mint(
&self,
mint_url: Url,
blinded_messages: BlindedMessages,
premint_secrets: PreMintSecrets,
hash: &str,
) -> Result<PostMintResponse, Error>;

View File

@@ -38,11 +38,9 @@ impl Mint {
// Check that there is only one active keyset per unit
for keyset_info in keysets_info {
if keyset_info.active {
if !active_units.insert(keyset_info.unit.clone()) {
// TODO: Handle Error
todo!()
}
if keyset_info.active && !active_units.insert(keyset_info.unit.clone()) {
// TODO: Handle Error
todo!()
}
let keyset = nut02::mint::KeySet::generate(
@@ -88,7 +86,6 @@ impl Mint {
let keysets = self
.keysets_info
.values()
.into_iter()
.map(|k| k.clone().into())
.collect();

View File

@@ -5,7 +5,7 @@ use cashu::dhke::{construct_proofs, unblind_message};
#[cfg(feature = "nut07")]
use cashu::nuts::nut00::mint;
use cashu::nuts::{
BlindedMessages, BlindedSignature, Keys, Proof, Proofs, RequestMintResponse, SplitPayload,
BlindedSignature, Keys, PreMintSecrets, Proof, Proofs, RequestMintResponse, SplitPayload,
SplitRequest, Token,
};
#[cfg(feature = "nut07")]
@@ -106,21 +106,21 @@ impl<C: Client> Wallet<C> {
/// Mint Proofs
pub async fn mint(&self, amount: Amount, hash: &str) -> Result<Proofs, Error> {
let blinded_messages = BlindedMessages::random((&self.mint_keys).into(), amount)?;
let premint_secrets = PreMintSecrets::random((&self.mint_keys).into(), amount)?;
let mint_res = self
.client
.post_mint(
self.mint_url.clone().try_into()?,
blinded_messages.clone(),
premint_secrets.clone(),
hash,
)
.await?;
let proofs = construct_proofs(
mint_res.promises,
blinded_messages.rs,
blinded_messages.secrets,
premint_secrets.rs(),
premint_secrets.secrets(),
&self.mint_keys,
)?;
@@ -169,8 +169,8 @@ impl<C: Client> Wallet<C> {
// Proof to keep
let p = construct_proofs(
promises.to_owned(),
split_payload.blinded_messages.rs,
split_payload.blinded_messages.secrets,
split_payload.pre_mint_secrets.rs(),
split_payload.pre_mint_secrets.secrets(),
&keys,
)?;
proofs.push(p);
@@ -183,49 +183,43 @@ impl<C: Client> Wallet<C> {
}
/// Create Split Payload
/// TODO: This needs to sort to avoid finer printing
fn create_split(&self, amount: Option<Amount>, proofs: Proofs) -> Result<SplitPayload, Error> {
// Since split is used to get the needed combination of tokens for a specific
// amount first blinded messages are created for the amount
let blinded_messages = if let Some(amount) = amount {
let mut desired_messages = BlindedMessages::random((&self.mint_keys).into(), amount)?;
let pre_mint_secrets = if let Some(amount) = amount {
let mut desired_messages = PreMintSecrets::random((&self.mint_keys).into(), amount)?;
let change_amount = proofs.iter().map(|p| p.amount).sum::<Amount>() - amount;
let change_messages = BlindedMessages::random((&self.mint_keys).into(), change_amount)?;
let change_messages = PreMintSecrets::random((&self.mint_keys).into(), change_amount)?;
// Combine the BlindedMessages totoalling the desired amount with change
desired_messages.combine(change_messages);
// Sort the premint secrets to avoid finger printing
desired_messages.sort_secrets();
desired_messages
} else {
let value = proofs.iter().map(|p| p.amount).sum();
BlindedMessages::random((&self.mint_keys).into(), value)?
PreMintSecrets::random((&self.mint_keys).into(), value)?
};
let split_payload = SplitRequest::new(proofs, blinded_messages.blinded_messages.clone());
let split_payload = SplitRequest::new(proofs, pre_mint_secrets.blinded_messages());
Ok(SplitPayload {
blinded_messages,
pre_mint_secrets,
split_payload,
})
}
pub fn process_split_response(
&self,
blinded_messages: BlindedMessages,
blinded_messages: PreMintSecrets,
promises: Vec<BlindedSignature>,
) -> Result<Proofs, Error> {
let BlindedMessages {
blinded_messages: _,
secrets,
rs,
amounts: _,
} = blinded_messages;
let secrets: Vec<_> = secrets.iter().collect();
let mut proofs = vec![];
for (i, promise) in promises.iter().enumerate() {
for (promise, premint) in promises.iter().zip(blinded_messages) {
let a = self
.mint_keys
.amount_key(promise.amount)
@@ -234,11 +228,11 @@ impl<C: Client> Wallet<C> {
let blinded_c = promise.c.clone();
let unblinded_sig = unblind_message(blinded_c, rs[i].clone().into(), a).unwrap();
let unblinded_sig = unblind_message(blinded_c, premint.r.into(), a).unwrap();
let proof = Proof {
id: promise.id,
amount: promise.amount,
secret: secrets[i].clone(),
secret: premint.secret,
c: unblinded_sig,
};
@@ -273,8 +267,8 @@ impl<C: Client> Wallet<C> {
if let Some(promises) = split_response.promises {
let mut proofs = construct_proofs(
promises,
split_payload.blinded_messages.rs,
split_payload.blinded_messages.secrets,
split_payload.pre_mint_secrets.rs(),
split_payload.pre_mint_secrets.secrets(),
&self.mint_keys,
)?;
@@ -316,22 +310,22 @@ impl<C: Client> Wallet<C> {
proofs: Proofs,
fee_reserve: Amount,
) -> Result<Melted, Error> {
let blinded = BlindedMessages::blank((&self.mint_keys).into(), fee_reserve)?;
let blinded = PreMintSecrets::blank((&self.mint_keys).into(), fee_reserve)?;
let melt_response = self
.client
.post_melt(
self.mint_url.clone().try_into()?,
proofs,
invoice,
Some(blinded.blinded_messages),
Some(blinded.blinded_messages()),
)
.await?;
let change_proofs = match melt_response.change {
Some(change) => Some(construct_proofs(
change,
blinded.rs,
blinded.secrets,
blinded.rs(),
blinded.secrets(),
&self.mint_keys,
)?),
None => None,

View File

@@ -13,7 +13,7 @@ pub mod nut08;
pub mod nut09;
#[cfg(feature = "wallet")]
pub use nut00::wallet::{BlindedMessages, Token};
pub use nut00::wallet::{PreMint, PreMintSecrets, Token};
pub use nut00::{BlindedMessage, BlindedSignature, Proof};
pub use nut01::{Keys, KeysResponse, PublicKey, SecretKey};
pub use nut02::mint::KeySet as MintKeySet;

View File

@@ -22,6 +22,7 @@ pub struct BlindedMessage {
#[cfg(feature = "wallet")]
pub mod wallet {
use std::cmp::Ordering;
use std::str::FromStr;
use base64::engine::{general_purpose, GeneralPurpose};
@@ -37,25 +38,65 @@ pub mod wallet {
use crate::url::UncheckedUrl;
use crate::{error, Amount};
/// Blinded Messages [NUT-00]
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize)]
pub struct BlindedMessages {
/// Blinded messages
pub blinded_messages: Vec<BlindedMessage>,
/// Secrets
pub secrets: Vec<Secret>,
/// Rs
pub rs: Vec<SecretKey>,
/// Amounts
pub amounts: Vec<Amount>,
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct PreMint {
/// Blinded message
pub blinded_message: BlindedMessage,
/// Secret
pub secret: Secret,
/// R
pub r: SecretKey,
/// Amount
pub amount: Amount,
}
impl BlindedMessages {
impl Ord for PreMint {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.amount.cmp(&other.amount)
}
}
impl PartialOrd for PreMint {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize)]
pub struct PreMintSecrets {
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> {
let mut blinded_messages = BlindedMessages::default();
let amount_split = amount.split();
for amount in amount.split() {
let mut output = Vec::with_capacity(amount_split.len());
for amount in amount_split {
let secret = Secret::new();
let (blinded, r) = blind_message(secret.as_bytes(), None)?;
@@ -65,19 +106,19 @@ pub mod wallet {
keyset_id,
};
blinded_messages.secrets.push(secret);
blinded_messages.blinded_messages.push(blinded_message);
blinded_messages.rs.push(r.into());
blinded_messages.amounts.push(amount);
output.push(PreMint {
secret,
blinded_message,
r: r.into(),
amount,
});
}
Ok(blinded_messages)
Ok(PreMintSecrets { secrets: output })
}
/// Blank Outputs used for NUT-08 change
pub fn blank(keyset_id: Id, fee_reserve: Amount) -> Result<Self, wallet::Error> {
let mut blinded_messages = BlindedMessages::default();
let fee_reserve = bitcoin::Amount::from_sat(fee_reserve.to_sat());
let count = (fee_reserve
@@ -86,6 +127,8 @@ pub mod wallet {
.ceil() as u64)
.max(1);
let mut output = Vec::with_capacity(count as usize);
for _i in 0..count {
let secret = Secret::new();
let (blinded, r) = blind_message(secret.as_bytes(), None)?;
@@ -96,20 +139,58 @@ pub mod wallet {
keyset_id,
};
blinded_messages.secrets.push(secret);
blinded_messages.blinded_messages.push(blinded_message);
blinded_messages.rs.push(r.into());
blinded_messages.amounts.push(Amount::ZERO);
output.push(PreMint {
secret,
blinded_message,
r: r.into(),
amount: Amount::ZERO,
})
}
Ok(blinded_messages)
Ok(PreMintSecrets { secrets: output })
}
pub fn iter(&self) -> impl Iterator<Item = &PreMint> {
self.secrets.iter()
}
pub fn len(&self) -> usize {
self.secrets.len()
}
pub fn is_empty(&self) -> bool {
self.secrets.is_empty()
}
pub fn total_amount(&self) -> Amount {
self.secrets
.iter()
.map(|PreMint { amount, .. }| *amount)
.sum()
}
pub fn blinded_messages(&self) -> Vec<BlindedMessage> {
self.iter().map(|pm| pm.blinded_message.clone()).collect()
}
pub fn secrets(&self) -> Vec<Secret> {
self.iter().map(|pm| pm.secret.clone()).collect()
}
pub fn rs(&self) -> Vec<SecretKey> {
self.iter().map(|pm| pm.r.clone()).collect()
}
pub fn amounts(&self) -> Vec<Amount> {
self.iter().map(|pm| pm.amount).collect()
}
pub fn combine(&mut self, mut other: Self) {
self.blinded_messages.append(&mut other.blinded_messages);
self.secrets.append(&mut other.secrets);
self.rs.append(&mut other.rs);
self.amounts.append(&mut other.amounts);
self.secrets.append(&mut other.secrets)
}
pub fn sort_secrets(&mut self) {
self.secrets.sort();
}
}
@@ -335,11 +416,11 @@ mod tests {
#[test]
fn test_blank_blinded_messages() {
// TODO: Need to update id to new type in proof
let b = BlindedMessages::blank(Id::from_str("").unwrap(), Amount::from_sat(1000)).unwrap();
assert_eq!(b.blinded_messages.len(), 10);
let b = PreMintSecrets::blank(Id::from_str("").unwrap(), Amount::from_sat(1000)).unwrap();
assert_eq!(b.len(), 10);
// TODO: Need to update id to new type in proof
let b = BlindedMessages::blank(Id::from_str("").unwrap(), Amount::from_sat(1)).unwrap();
assert_eq!(b.blinded_messages.len(), 1);
let b = PreMintSecrets::blank(Id::from_str("").unwrap(), Amount::from_sat(1)).unwrap();
assert_eq!(b.len(), 1);
}
}

View File

@@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
use super::nut00::BlindedSignature;
#[cfg(feature = "wallet")]
use crate::nuts::BlindedMessages;
use crate::nuts::PreMintSecrets;
use crate::nuts::{BlindedMessage, Proofs};
use crate::Amount;
pub use crate::Bolt11Invoice;
@@ -22,7 +22,7 @@ pub struct RequestMintResponse {
#[cfg(feature = "wallet")]
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct SplitPayload {
pub blinded_messages: BlindedMessages,
pub pre_mint_secrets: PreMintSecrets,
pub split_payload: SplitRequest,
}

View File

@@ -4,14 +4,14 @@ use serde::{Deserialize, Serialize};
use super::nut00::BlindedSignature;
#[cfg(feature = "wallet")]
use crate::nuts::BlindedMessages;
use crate::nuts::PreMintSecrets;
use crate::nuts::{BlindedMessage, Proofs};
use crate::Amount;
#[cfg(feature = "wallet")]
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct SplitPayload {
pub blinded_messages: BlindedMessages,
pub pre_mint_secrets: PreMintSecrets,
pub split_payload: SplitRequest,
}