mirror of
https://github.com/aljazceru/cdk.git
synced 2026-01-09 07:55:53 +01:00
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:
@@ -98,7 +98,7 @@ interface Token {
|
||||
|
||||
};
|
||||
|
||||
interface BlindedMessages {
|
||||
interface PreMintSecrets {
|
||||
[Throws=CashuError, Name=random]
|
||||
constructor(Id keyset_id, Amount amount);
|
||||
[Throws=CashuError, Name=blank]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
78
bindings/cashu-ffi/src/nuts/nut00/premint_secrets.rs
Normal file
78
bindings/cashu-ffi/src/nuts/nut00/premint_secrets.rs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user