mirror of
https://github.com/aljazceru/cdk.git
synced 2026-02-05 05:06:14 +01:00
refactor: add keyset_id to blinded_message
stop mint from signing if keyset in blinded_message is not the active keyset
This commit is contained in:
@@ -50,7 +50,7 @@ interface SecretKey {
|
||||
};
|
||||
|
||||
interface BlindedMessage {
|
||||
constructor(Amount amount, PublicKey b);
|
||||
constructor(Id keyset_id, Amount amount, PublicKey b);
|
||||
Amount amount();
|
||||
PublicKey b();
|
||||
};
|
||||
@@ -100,9 +100,9 @@ interface Token {
|
||||
|
||||
interface BlindedMessages {
|
||||
[Throws=CashuError, Name=random]
|
||||
constructor(Amount amount);
|
||||
constructor(Id keyset_id, Amount amount);
|
||||
[Throws=CashuError, Name=blank]
|
||||
constructor(Amount fee_reserve);
|
||||
constructor(Id keyset_id, Amount amount);
|
||||
sequence<BlindedMessage> blinded_messages();
|
||||
sequence<Secret> secrets();
|
||||
sequence<SecretKey> rs();
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::sync::Arc;
|
||||
use cashu::nuts::BlindedMessage as BlindedMessageSdk;
|
||||
|
||||
use crate::nuts::nut01::public_key::PublicKey;
|
||||
use crate::Amount;
|
||||
use crate::{Amount, Id};
|
||||
|
||||
pub struct BlindedMessage {
|
||||
inner: BlindedMessageSdk,
|
||||
@@ -18,9 +18,10 @@ impl Deref for BlindedMessage {
|
||||
}
|
||||
|
||||
impl BlindedMessage {
|
||||
pub fn new(amount: Arc<Amount>, b: Arc<PublicKey>) -> Self {
|
||||
pub fn new(keyset_id: Arc<Id>, amount: Arc<Amount>, b: Arc<PublicKey>) -> Self {
|
||||
Self {
|
||||
inner: BlindedMessageSdk {
|
||||
keyset_id: *keyset_id.as_ref().deref(),
|
||||
amount: *amount.as_ref().deref(),
|
||||
b: b.as_ref().into(),
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::sync::Arc;
|
||||
use cashu::nuts::nut00::wallet::BlindedMessages as BlindedMessagesSdk;
|
||||
|
||||
use crate::error::Result;
|
||||
use crate::{Amount, BlindedMessage, Secret, SecretKey};
|
||||
use crate::{Amount, BlindedMessage, Id, Secret, SecretKey};
|
||||
|
||||
pub struct BlindedMessages {
|
||||
inner: BlindedMessagesSdk,
|
||||
@@ -18,15 +18,21 @@ impl Deref for BlindedMessages {
|
||||
}
|
||||
|
||||
impl BlindedMessages {
|
||||
pub fn random(amount: Arc<Amount>) -> Result<Self> {
|
||||
pub fn random(keyset_id: Arc<Id>, amount: Arc<Amount>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
inner: BlindedMessagesSdk::random(*amount.as_ref().deref())?,
|
||||
inner: BlindedMessagesSdk::random(
|
||||
*keyset_id.as_ref().deref(),
|
||||
*amount.as_ref().deref(),
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn blank(fee_reserve: Arc<Amount>) -> Result<Self> {
|
||||
pub fn blank(keyset_id: Arc<Id>, fee_reserve: Arc<Amount>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
inner: BlindedMessagesSdk::blank(*fee_reserve.as_ref().deref())?,
|
||||
inner: BlindedMessagesSdk::blank(
|
||||
*keyset_id.as_ref().deref(),
|
||||
*fee_reserve.as_ref().deref(),
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ use cashu::nuts::nut00::BlindedMessage;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::nuts::nut01::JsPublicKey;
|
||||
use crate::nuts::nut02::JsId;
|
||||
use crate::types::amount::JsAmount;
|
||||
|
||||
#[wasm_bindgen(js_name = BlindedMessage)]
|
||||
@@ -28,9 +29,10 @@ impl From<BlindedMessage> for JsBlindedMessage {
|
||||
impl JsBlindedMessage {
|
||||
#[allow(clippy::new_without_default)]
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new(amount: JsAmount, b: JsPublicKey) -> Self {
|
||||
pub fn new(keyset_id: JsId, amount: JsAmount, b: JsPublicKey) -> Self {
|
||||
Self {
|
||||
inner: BlindedMessage {
|
||||
keyset_id: *keyset_id.deref(),
|
||||
amount: *amount.deref(),
|
||||
b: b.deref().clone(),
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@ use cashu::nuts::nut00::wallet::BlindedMessages;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::error::{into_err, Result};
|
||||
use crate::nuts::nut02::JsId;
|
||||
use crate::types::JsAmount;
|
||||
|
||||
#[wasm_bindgen(js_name = BlindedMessages)]
|
||||
@@ -21,16 +22,18 @@ impl Deref for JsBlindedMessages {
|
||||
#[wasm_bindgen(js_class = BlindedMessages)]
|
||||
impl JsBlindedMessages {
|
||||
#[wasm_bindgen(js_name = random)]
|
||||
pub fn random(amount: JsAmount) -> Result<JsBlindedMessages> {
|
||||
pub fn random(keyset_id: JsId, amount: JsAmount) -> Result<JsBlindedMessages> {
|
||||
Ok(JsBlindedMessages {
|
||||
inner: BlindedMessages::random(*amount.deref()).map_err(into_err)?,
|
||||
inner: BlindedMessages::random(*keyset_id.deref(), *amount.deref())
|
||||
.map_err(into_err)?,
|
||||
})
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = blank)]
|
||||
pub fn blank(fee_reserve: JsAmount) -> Result<JsBlindedMessages> {
|
||||
pub fn blank(keyset_id: JsId, fee_reserve: JsAmount) -> Result<JsBlindedMessages> {
|
||||
Ok(JsBlindedMessages {
|
||||
inner: BlindedMessages::blank(*fee_reserve.deref()).map_err(into_err)?,
|
||||
inner: BlindedMessages::blank(*keyset_id.deref(), *fee_reserve.deref())
|
||||
.map_err(into_err)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ interface SecretKey {
|
||||
};
|
||||
|
||||
interface BlindedMessage {
|
||||
constructor(Amount amount, PublicKey b);
|
||||
constructor(Id keyset_id, Amount amount, PublicKey b);
|
||||
Amount amount();
|
||||
PublicKey b();
|
||||
};
|
||||
@@ -103,9 +103,9 @@ interface Token {
|
||||
|
||||
interface BlindedMessages {
|
||||
[Throws=CashuError, Name=random]
|
||||
constructor(Amount amount);
|
||||
constructor(Id keyset_id, Amount amount);
|
||||
[Throws=CashuError, Name=blank]
|
||||
constructor(Amount fee_reserve);
|
||||
constructor(Id keyset_id, Amount amount);
|
||||
sequence<BlindedMessage> blinded_messages();
|
||||
sequence<Secret> secrets();
|
||||
sequence<SecretKey> rs();
|
||||
|
||||
@@ -119,7 +119,15 @@ impl Mint {
|
||||
}
|
||||
|
||||
fn blind_sign(&self, blinded_message: &BlindedMessage) -> Result<BlindedSignature, Error> {
|
||||
let BlindedMessage { amount, b } = blinded_message;
|
||||
let BlindedMessage {
|
||||
amount,
|
||||
b,
|
||||
keyset_id,
|
||||
} = blinded_message;
|
||||
|
||||
if self.active_keyset.id.ne(keyset_id) {
|
||||
return Err(Error::InactiveKeyset);
|
||||
}
|
||||
|
||||
let Some(key_pair) = self.active_keyset.keys.0.get(amount) else {
|
||||
// No key for amount
|
||||
|
||||
@@ -98,7 +98,7 @@ impl<C: Client> Wallet<C> {
|
||||
|
||||
/// Mint Proofs
|
||||
pub async fn mint(&self, amount: Amount, hash: &str) -> Result<Proofs, Error> {
|
||||
let blinded_messages = BlindedMessages::random(amount)?;
|
||||
let blinded_messages = BlindedMessages::random((&self.mint_keys).into(), amount)?;
|
||||
|
||||
let mint_res = self
|
||||
.client
|
||||
@@ -181,17 +181,17 @@ impl<C: Client> Wallet<C> {
|
||||
// amount first blinded messages are created for the amount
|
||||
|
||||
let blinded_messages = if let Some(amount) = amount {
|
||||
let mut desired_messages = BlindedMessages::random(amount)?;
|
||||
let mut desired_messages = BlindedMessages::random((&self.mint_keys).into(), amount)?;
|
||||
|
||||
let change_amount = proofs.iter().map(|p| p.amount).sum::<Amount>() - amount;
|
||||
|
||||
let change_messages = BlindedMessages::random(change_amount)?;
|
||||
let change_messages = BlindedMessages::random((&self.mint_keys).into(), change_amount)?;
|
||||
desired_messages.combine(change_messages);
|
||||
desired_messages
|
||||
} else {
|
||||
let value = proofs.iter().map(|p| p.amount).sum();
|
||||
|
||||
BlindedMessages::random(value)?
|
||||
BlindedMessages::random((&self.mint_keys).into(), value)?
|
||||
};
|
||||
|
||||
let split_payload = SplitRequest::new(proofs, blinded_messages.blinded_messages.clone());
|
||||
@@ -308,7 +308,7 @@ impl<C: Client> Wallet<C> {
|
||||
proofs: Proofs,
|
||||
fee_reserve: Amount,
|
||||
) -> Result<Melted, Error> {
|
||||
let blinded = BlindedMessages::blank(fee_reserve)?;
|
||||
let blinded = BlindedMessages::blank((&self.mint_keys).into(), fee_reserve)?;
|
||||
let melt_response = self
|
||||
.client
|
||||
.post_melt(
|
||||
|
||||
@@ -101,6 +101,9 @@ pub mod mint {
|
||||
/// Duplicate Proofs sent in request
|
||||
#[error("Duplicate proofs")]
|
||||
DuplicateProofs,
|
||||
/// Keyset id not active
|
||||
#[error("Keyset id is not active")]
|
||||
InactiveKeyset,
|
||||
#[error("`{0}`")]
|
||||
CustomError(String),
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ pub struct BlindedMessage {
|
||||
/// encrypted secret message (B_)
|
||||
#[serde(rename = "B_")]
|
||||
pub b: PublicKey,
|
||||
#[serde(rename = "id")]
|
||||
pub keyset_id: Id,
|
||||
}
|
||||
|
||||
#[cfg(feature = "wallet")]
|
||||
@@ -30,7 +32,7 @@ pub mod wallet {
|
||||
use super::MintProofs;
|
||||
use crate::dhke::blind_message;
|
||||
use crate::error::wallet;
|
||||
use crate::nuts::{BlindedMessage, Proofs, SecretKey};
|
||||
use crate::nuts::{BlindedMessage, Id, Proofs, SecretKey};
|
||||
use crate::secret::Secret;
|
||||
use crate::url::UncheckedUrl;
|
||||
use crate::{error, Amount};
|
||||
@@ -50,14 +52,18 @@ pub mod wallet {
|
||||
|
||||
impl BlindedMessages {
|
||||
/// Outputs for speceifed amount with random secret
|
||||
pub fn random(amount: Amount) -> Result<Self, wallet::Error> {
|
||||
pub fn random(keyset_id: Id, amount: Amount) -> Result<Self, wallet::Error> {
|
||||
let mut blinded_messages = BlindedMessages::default();
|
||||
|
||||
for amount in amount.split() {
|
||||
let secret = Secret::new();
|
||||
let (blinded, r) = blind_message(secret.as_bytes(), None)?;
|
||||
|
||||
let blinded_message = BlindedMessage { amount, b: blinded };
|
||||
let blinded_message = BlindedMessage {
|
||||
amount,
|
||||
b: blinded,
|
||||
keyset_id,
|
||||
};
|
||||
|
||||
blinded_messages.secrets.push(secret);
|
||||
blinded_messages.blinded_messages.push(blinded_message);
|
||||
@@ -69,7 +75,7 @@ pub mod wallet {
|
||||
}
|
||||
|
||||
/// Blank Outputs used for NUT-08 change
|
||||
pub fn blank(fee_reserve: Amount) -> Result<Self, wallet::Error> {
|
||||
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());
|
||||
@@ -87,6 +93,7 @@ pub mod wallet {
|
||||
let blinded_message = BlindedMessage {
|
||||
amount: Amount::ZERO,
|
||||
b: blinded,
|
||||
keyset_id,
|
||||
};
|
||||
|
||||
blinded_messages.secrets.push(secret);
|
||||
@@ -322,10 +329,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_blank_blinded_messages() {
|
||||
let b = BlindedMessages::blank(Amount::from_sat(1000)).unwrap();
|
||||
// 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 = BlindedMessages::blank(Amount::from_sat(1)).unwrap();
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ impl std::fmt::Display for Id {
|
||||
f.write_str(&format!(
|
||||
"{}{}",
|
||||
self.version,
|
||||
String::from_utf8(self.id.to_vec()).map_err(|_| fmt::Error::default())?
|
||||
String::from_utf8(self.id.to_vec()).map_err(|_| fmt::Error)?
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user