mirror of
https://github.com/aljazceru/cdk.git
synced 2026-02-20 20:45:54 +01:00
fix split
This commit is contained in:
@@ -78,7 +78,7 @@ pub fn construct_proofs(
|
||||
for (i, promise) in promises.into_iter().enumerate() {
|
||||
let blinded_c = promise.c;
|
||||
let a: PublicKey = keys
|
||||
.amount_key(&promise.amount.to_sat())
|
||||
.amount_key(promise.amount)
|
||||
.ok_or(Error::CustomError("Could not get proofs".to_string()))?
|
||||
.to_owned();
|
||||
|
||||
@@ -107,8 +107,7 @@ pub fn sign_message(
|
||||
blinded_message
|
||||
.as_affine()
|
||||
.mul(Scalar::from(a.as_scalar_primitive())),
|
||||
)
|
||||
.unwrap())
|
||||
)?)
|
||||
}
|
||||
|
||||
/// Verify Message
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
pub mod amount;
|
||||
pub mod cashu_wallet;
|
||||
pub mod client;
|
||||
pub mod dhke;
|
||||
pub mod error;
|
||||
@@ -8,6 +7,7 @@ pub mod nuts;
|
||||
pub mod serde_utils;
|
||||
pub mod types;
|
||||
pub mod utils;
|
||||
pub mod wallet;
|
||||
|
||||
pub use amount::Amount;
|
||||
pub use bitcoin::hashes::sha256::Hash as Sha256;
|
||||
|
||||
@@ -98,6 +98,8 @@ impl Mint {
|
||||
amount: Amount,
|
||||
outputs: &[BlindedMessage],
|
||||
) -> Result<SplitResponse, Error> {
|
||||
let mut outputs = outputs.to_vec();
|
||||
outputs.reverse();
|
||||
let mut target_total = Amount::ZERO;
|
||||
let mut change_total = Amount::ZERO;
|
||||
let mut target = Vec::with_capacity(outputs.len());
|
||||
@@ -107,7 +109,7 @@ impl Mint {
|
||||
// in the outputs (blind messages). As we loop, take from those sets,
|
||||
// target amount first.
|
||||
for output in outputs {
|
||||
let signed = self.blind_sign(output)?;
|
||||
let signed = self.blind_sign(&output)?;
|
||||
|
||||
// Accumulate outputs into the target (send) list
|
||||
if target_total + signed.amount <= amount {
|
||||
@@ -119,6 +121,9 @@ impl Mint {
|
||||
}
|
||||
}
|
||||
|
||||
println!("change: {:?}", serde_json::to_string(&change));
|
||||
println!("send: {:?}", serde_json::to_string(&target));
|
||||
|
||||
Ok(SplitResponse {
|
||||
fst: change,
|
||||
snd: target,
|
||||
@@ -168,7 +173,7 @@ impl Mint {
|
||||
Ok(split_response)
|
||||
}
|
||||
|
||||
fn verify_proof(&self, proof: &Proof) -> Result<String, Error> {
|
||||
pub fn verify_proof(&self, proof: &Proof) -> Result<String, Error> {
|
||||
if self.spent_secrets.contains(&proof.secret) {
|
||||
return Err(Error::TokenSpent);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::Amount;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct PublicKey(#[serde(with = "crate::serde_utils::serde_public_key")] k256::PublicKey);
|
||||
@@ -57,8 +59,8 @@ impl Keys {
|
||||
self.0.clone()
|
||||
}
|
||||
|
||||
pub fn amount_key(&self, amount: &u64) -> Option<PublicKey> {
|
||||
self.0.get(amount).cloned()
|
||||
pub fn amount_key(&self, amount: Amount) -> Option<PublicKey> {
|
||||
self.0.get(&amount.to_sat()).cloned()
|
||||
}
|
||||
|
||||
pub fn as_hashmap(&self) -> HashMap<u64, String> {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
//! Cashu Wallet
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::nuts::nut00::{mint, BlindedMessages, Proofs, Token};
|
||||
use crate::dhke::unblind_message;
|
||||
use crate::nuts::nut00::{mint, BlindedMessages, BlindedSignature, Proof, Proofs, Token};
|
||||
use crate::nuts::nut01::Keys;
|
||||
use crate::nuts::nut03::RequestMintResponse;
|
||||
use crate::nuts::nut06::{SplitPayload, SplitRequest};
|
||||
@@ -12,13 +13,13 @@ use crate::{client::Client, dhke::construct_proofs, error::Error};
|
||||
use crate::amount::Amount;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CashuWallet {
|
||||
pub struct Wallet {
|
||||
pub client: Client,
|
||||
pub mint_keys: Keys,
|
||||
pub balance: Amount,
|
||||
}
|
||||
|
||||
impl CashuWallet {
|
||||
impl Wallet {
|
||||
pub fn new(client: Client, mint_keys: Keys) -> Self {
|
||||
Self {
|
||||
client,
|
||||
@@ -151,6 +152,15 @@ impl CashuWallet {
|
||||
outputs,
|
||||
};
|
||||
|
||||
println!(
|
||||
"Keep blinded: {:?}",
|
||||
serde_json::to_string(&keep_blinded_messages)
|
||||
);
|
||||
println!(
|
||||
"Send blinded: {:?}",
|
||||
serde_json::to_string(&send_blinded_messages)
|
||||
);
|
||||
|
||||
Ok(SplitPayload {
|
||||
keep_blinded_messages,
|
||||
send_blinded_messages,
|
||||
@@ -158,6 +168,54 @@ impl CashuWallet {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn process_split_response(
|
||||
&self,
|
||||
blinded_messages: BlindedMessages,
|
||||
promisses: Vec<BlindedSignature>,
|
||||
) -> Result<Proofs, Error> {
|
||||
let BlindedMessages {
|
||||
blinded_messages,
|
||||
secrets,
|
||||
rs,
|
||||
amounts,
|
||||
} = blinded_messages;
|
||||
|
||||
println!(
|
||||
"b: {:?}",
|
||||
blinded_messages
|
||||
.iter()
|
||||
.map(|b| b.amount)
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
println!("a: {:?}", amounts);
|
||||
let secrets: Vec<_> = secrets.iter().collect();
|
||||
let mut proofs = vec![];
|
||||
|
||||
for (i, promise) in promisses.iter().enumerate() {
|
||||
let a = self
|
||||
.mint_keys
|
||||
.amount_key(promise.amount)
|
||||
.unwrap()
|
||||
.to_owned();
|
||||
|
||||
let blinded_c = promise.c.clone();
|
||||
|
||||
let unblinded_sig = unblind_message(blinded_c, rs[i].clone().into(), a).unwrap();
|
||||
let proof = Proof {
|
||||
id: Some(promise.id.clone()),
|
||||
amount: promise.amount,
|
||||
secret: secrets[i].clone(),
|
||||
c: unblinded_sig,
|
||||
script: None,
|
||||
};
|
||||
|
||||
proofs.push(proof);
|
||||
}
|
||||
|
||||
Ok(proofs)
|
||||
}
|
||||
|
||||
/// Send
|
||||
pub async fn send(&self, amount: Amount, proofs: Proofs) -> Result<SendProofs, Error> {
|
||||
let mut amount_available = Amount::ZERO;
|
||||
@@ -251,3 +309,89 @@ impl CashuWallet {
|
||||
Token::new(self.client.mint_url.clone(), proofs, memo).convert_to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use super::*;
|
||||
|
||||
use crate::client::Client;
|
||||
use crate::mint::Mint;
|
||||
use crate::nuts::nut04;
|
||||
|
||||
#[test]
|
||||
fn test_wallet() {
|
||||
let mut mint = Mint::new(
|
||||
"supersecretsecret",
|
||||
"0/0/0/0",
|
||||
HashMap::new(),
|
||||
HashSet::new(),
|
||||
32,
|
||||
);
|
||||
|
||||
let keys = mint.active_keyset_pubkeys();
|
||||
|
||||
let client = Client::new("https://cashu-rs.thesimplekid.space/").unwrap();
|
||||
|
||||
let wallet = Wallet::new(client, keys.keys);
|
||||
|
||||
let blinded_messages = BlindedMessages::random(Amount::from_sat(100)).unwrap();
|
||||
|
||||
let mint_request = nut04::MintRequest {
|
||||
outputs: blinded_messages.blinded_messages.clone(),
|
||||
};
|
||||
|
||||
let res = mint.process_mint_request(mint_request).unwrap();
|
||||
/*
|
||||
let proofs = construct_proofs(
|
||||
res.promises,
|
||||
blinded_messages.rs,
|
||||
blinded_messages.secrets,
|
||||
&mint.active_keyset_pubkeys().keys,
|
||||
)
|
||||
.unwrap();
|
||||
*/
|
||||
|
||||
let proofs = wallet
|
||||
.process_split_response(blinded_messages, res.promises)
|
||||
.unwrap();
|
||||
for proof in &proofs {
|
||||
mint.verify_proof(proof).unwrap();
|
||||
}
|
||||
|
||||
let split = wallet
|
||||
.create_split(Amount::from_sat(33), Amount::from_sat(67), proofs.clone())
|
||||
.unwrap();
|
||||
|
||||
let split_request = split.split_payload;
|
||||
let split_response = mint.process_split_request(split_request).unwrap();
|
||||
let mut p = split_response.snd;
|
||||
p.reverse();
|
||||
|
||||
let snd_proofs = wallet
|
||||
.process_split_response(split.send_blinded_messages, p)
|
||||
.unwrap();
|
||||
/*
|
||||
let snd_proofs = construct_proofs(
|
||||
split_response.snd,
|
||||
split.send_blinded_messages.rs,
|
||||
split.send_blinded_messages.secrets,
|
||||
&mint.active_keyset_pubkeys().keys,
|
||||
)
|
||||
.unwrap();
|
||||
*/
|
||||
let mut error = false;
|
||||
for proof in &snd_proofs {
|
||||
if let Err(err) = mint.verify_proof(proof) {
|
||||
println!("{err}{:?}", serde_json::to_string(proof));
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if error {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user