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:
thesimplekid
2023-11-25 21:06:32 +00:00
parent 614ae73e70
commit 989035e12e
11 changed files with 63 additions and 31 deletions

View File

@@ -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();

View File

@@ -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(),
},

View File

@@ -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(),
)?,
})
}

View File

@@ -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(),
},

View File

@@ -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)?,
})
}

View File

@@ -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();

View File

@@ -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

View File

@@ -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(

View File

@@ -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),
}

View File

@@ -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);
}
}

View File

@@ -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)?
))
}
}