Skip to content

Commit

Permalink
deprecate amount field
Browse files Browse the repository at this point in the history
  • Loading branch information
thesimplekid committed Jun 25, 2023
1 parent ca44218 commit e8303fc
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 76 deletions.
59 changes: 34 additions & 25 deletions src/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,46 +99,55 @@ impl Mint {
) -> Result<SplitResponse, Error> {
let proofs_total = split_request.proofs_amount();

if proofs_total < split_request.amount {
return Err(Error::Amount);
}

let output_total = split_request.output_amount();
if output_total < split_request.amount {
return Err(Error::Amount);
}

if proofs_total != output_total {
return Err(Error::Amount);
}

let mut secrets = Vec::with_capacity(split_request.proofs.len());
for proof in &split_request.proofs {
secrets.push(self.verify_proof(proof)?);
secrets.push(self.verify_proof(&proof)?);
self.spent_secrets.insert(proof.secret.clone());
}

let outs_fst = (proofs_total - split_request.amount).split();
match &split_request.amount {
None => {
let promises: Vec<BlindedSignature> = split_request
.outputs
.iter()
.map(|b| self.blind_sign(b).unwrap())
.collect();

Ok(SplitResponse::new(promises))
}
Some(amount) => {
if proofs_total.le(amount) {
return Err(Error::Amount);
}

// Blinded change messages
let b_fst = split_request.outputs[0..outs_fst.len()].to_vec();
let b_snd = split_request.outputs[outs_fst.len()..].to_vec();
if output_total.gt(amount) {
return Err(Error::Amount);
}

let fst: Vec<BlindedSignature> =
b_fst.iter().map(|b| self.blind_sign(b).unwrap()).collect();
let snd: Vec<BlindedSignature> =
b_snd.iter().map(|b| self.blind_sign(b).unwrap()).collect();
let outs_fst = (proofs_total.to_owned() - amount.to_owned()).split();

let split_response = SplitResponse { snd, fst };
// Blinded change messages
let b_fst = split_request.outputs[0..outs_fst.len()].to_vec();
let b_snd = split_request.outputs[outs_fst.len()..].to_vec();
let fst: Vec<BlindedSignature> =
b_fst.iter().map(|b| self.blind_sign(b).unwrap()).collect();
let snd: Vec<BlindedSignature> =
b_snd.iter().map(|b| self.blind_sign(b).unwrap()).collect();

if split_response.target_amount() != split_request.amount {
return Err(Error::OutputOrdering);
}
let split_response = SplitResponse::new_from_amount(snd, fst);

for proof in split_request.proofs {
self.spent_secrets.insert(proof.secret);
}
if split_response.target_amount() != split_request.amount {
return Err(Error::OutputOrdering);
}

Ok(split_response)
Ok(split_response)
}
}
}

pub fn verify_proof(&self, proof: &Proof) -> Result<String, Error> {
Expand Down
91 changes: 78 additions & 13 deletions src/nuts/nut06.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ pub struct SplitPayload {
/// Split Request [NUT-06]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SplitRequest {
pub amount: Amount,
#[deprecated(since = "0.1.1", note = "mint does not need amount")]
#[serde(skip_serializing_if = "Option::is_none")]
pub amount: Option<Amount>,
pub proofs: Proofs,
pub outputs: Vec<BlindedMessage>,
}
Expand All @@ -35,23 +37,86 @@ impl SplitRequest {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SplitResponse {
/// Promises to keep
pub fst: Vec<BlindedSignature>,
#[deprecated(
since = "0.1.1",
note = "mint only response with one list of all promises"
)]
#[serde(skip_serializing_if = "Option::is_none")]
pub fst: Option<Vec<BlindedSignature>>,
/// Promises to send
pub snd: Vec<BlindedSignature>,
#[deprecated(
since = "0.1.1",
note = "mint only response with one list of all promises"
)]
#[serde(skip_serializing_if = "Option::is_none")]
pub snd: Option<Vec<BlindedSignature>>,
/// Promises
pub promises: Option<Vec<BlindedSignature>>,
}

impl SplitResponse {
pub fn change_amount(&self) -> Amount {
self.fst
.iter()
.map(|BlindedSignature { amount, .. }| *amount)
.sum()
pub fn new(promises: Vec<BlindedSignature>) -> SplitResponse {
SplitResponse {
fst: None,
snd: None,
promises: Some(promises),
}
}

pub fn target_amount(&self) -> Amount {
self.snd
.iter()
.map(|BlindedSignature { amount, .. }| *amount)
.sum()
#[deprecated(
since = "0.1.1",
note = "mint only response with one list of all promises"
)]
pub fn new_from_amount(
fst: Vec<BlindedSignature>,
snd: Vec<BlindedSignature>,
) -> SplitResponse {
Self {
fst: Some(fst),
snd: Some(snd),
promises: None,
}
}

#[deprecated(
since = "0.1.1",
note = "mint only response with one list of all promises"
)]
pub fn change_amount(&self) -> Option<Amount> {
match &self.fst {
Some(fst) => Some(
fst.iter()
.map(|BlindedSignature { amount, .. }| *amount)
.sum(),
),
None => None,
}
}

#[deprecated(
since = "0.1.1",
note = "mint only response with one list of all promises"
)]
pub fn target_amount(&self) -> Option<Amount> {
match &self.snd {
Some(snd) => Some(
snd.iter()
.map(|BlindedSignature { amount, .. }| *amount)
.sum(),
),
None => None,
}
}

pub fn promises_amount(&self) -> Option<Amount> {
match &self.promises {
Some(promises) => Some(
promises
.iter()
.map(|BlindedSignature { amount, .. }| *amount)
.sum(),
),
None => None,
}
}
}
108 changes: 70 additions & 38 deletions src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl Wallet {
pub async fn receive(&self, encoded_token: &str) -> Result<Proofs, Error> {
let token_data = Token::from_str(encoded_token)?;

let mut proofs = vec![];
let mut proofs: Vec<Proofs> = vec![vec![]];
for token in token_data.token {
if token.proofs.is_empty() {
continue;
Expand All @@ -106,26 +106,36 @@ impl Wallet {

let split_response = self.client.split(split_payload.split_payload).await?;

// Proof to keep
let keep_proofs = construct_proofs(
split_response.fst,
split_payload.keep_blinded_messages.rs,
split_payload.keep_blinded_messages.secrets,
&keys,
)?;

// Proofs to send
let send_proofs = construct_proofs(
split_response.snd,
split_payload.send_blinded_messages.rs,
split_payload.send_blinded_messages.secrets,
&keys,
)?;

proofs.push(keep_proofs);
proofs.push(send_proofs);
if let Some(promises) = &split_response.promises {
// Proof to keep
let p = construct_proofs(
split_response.promises.unwrap(),
split_payload.keep_blinded_messages.rs,
split_payload.keep_blinded_messages.secrets,
&keys,
)?;
proofs.push(p);
} else {
// Proof to keep
let keep_proofs = construct_proofs(
split_response.fst.unwrap(),
split_payload.keep_blinded_messages.rs,
split_payload.keep_blinded_messages.secrets,
&keys,
)?;

// Proofs to send
let send_proofs = construct_proofs(
split_response.snd.unwrap(),
split_payload.send_blinded_messages.rs,
split_payload.send_blinded_messages.secrets,
&keys,
)?;

proofs.push(send_proofs);
proofs.push(keep_proofs);
}
}

Ok(proofs.iter().flatten().cloned().collect())
}

Expand All @@ -146,7 +156,7 @@ impl Wallet {
};

let split_payload = SplitRequest {
amount: send_amount,
amount: Some(send_amount),
proofs,
outputs,
};
Expand All @@ -161,7 +171,7 @@ impl Wallet {
pub fn process_split_response(
&self,
blinded_messages: BlindedMessages,
promisses: Vec<BlindedSignature>,
promises: Vec<BlindedSignature>,
) -> Result<Proofs, Error> {
let BlindedMessages {
blinded_messages: _,
Expand All @@ -173,7 +183,7 @@ impl Wallet {
let secrets: Vec<_> = secrets.iter().collect();
let mut proofs = vec![];

for (i, promise) in promisses.iter().enumerate() {
for (i, promise) in promises.iter().enumerate() {
let a = self
.mint_keys
.amount_key(promise.amount)
Expand Down Expand Up @@ -225,26 +235,48 @@ impl Wallet {
let amount_to_keep = amount_available - amount;
let amount_to_send = amount;

// TODO: Will need to change https://github.com/cashubtc/cashu/pull/263/files
let split_payload =
self.create_split(amount_to_keep, amount_to_send, send_proofs.send_proofs)?;

let split_response = self.client.split(split_payload.split_payload).await?;

// Proof to keep
let keep_proofs = construct_proofs(
split_response.fst,
split_payload.keep_blinded_messages.rs,
split_payload.keep_blinded_messages.secrets,
&self.mint_keys,
)?;
// If only prmises assemble proofs needed for amount

// Proofs to send
let send_proofs = construct_proofs(
split_response.snd,
split_payload.send_blinded_messages.rs,
split_payload.send_blinded_messages.secrets,
&self.mint_keys,
)?;
let keep_proofs;
let send_proofs;

if let Some(promises) = split_response.promises {
let proofs = construct_proofs(
promises,
split_payload.keep_blinded_messages.rs,
split_payload.keep_blinded_messages.secrets,
&self.mint_keys,
)?;

let split = amount_to_send.split();

keep_proofs = proofs[0..split.len()].to_vec();
send_proofs = proofs[split.len()..].to_vec();
} else if let (Some(fst), Some(snd)) = (split_response.fst, split_response.snd) {
// Proof to keep
keep_proofs = construct_proofs(
fst,
split_payload.keep_blinded_messages.rs,
split_payload.keep_blinded_messages.secrets,
&self.mint_keys,
)?;

// Proofs to send
send_proofs = construct_proofs(
snd,
split_payload.send_blinded_messages.rs,
split_payload.send_blinded_messages.secrets,
&self.mint_keys,
)?;
} else {
return Err(Error::CustomError("Invalid split response".to_string()));
}

// println!("Send Proofs: {:#?}", send_proofs);
// println!("Keep Proofs: {:#?}", keep_proofs);
Expand Down Expand Up @@ -343,7 +375,7 @@ mod tests {
let p = split_response.snd;

let snd_proofs = wallet
.process_split_response(split.send_blinded_messages, p)
.process_split_response(split.send_blinded_messages, p.unwrap())
.unwrap();

let mut error = false;
Expand Down

0 comments on commit e8303fc

Please sign in to comment.