diff --git a/flutter/native/src/wasm_client.rs b/flutter/native/src/wasm_client.rs index 47ced4b7..0fff8ebb 100644 --- a/flutter/native/src/wasm_client.rs +++ b/flutter/native/src/wasm_client.rs @@ -27,15 +27,10 @@ impl Client for WasmClient { async fn post_split_tokens( &self, mint_url: &Url, - amount: u64, proofs: Proofs, outputs: Vec, ) -> Result { - let body = &PostSplitRequest { - amount: Some(amount), - proofs, - outputs, - }; + let body = &PostSplitRequest { proofs, outputs }; let resp = Request::post(mint_url.join("split")?.as_str()) .header("content-type", "application/json") diff --git a/moksha-core/src/model.rs b/moksha-core/src/model.rs index 673afc2d..2a276b66 100644 --- a/moksha-core/src/model.rs +++ b/moksha-core/src/model.rs @@ -106,6 +106,13 @@ impl TokenV3 { } } + pub fn empty() -> Self { + Self { + tokens: vec![], + memo: None, + } + } + pub fn total_amount(&self) -> u64 { self.tokens .iter() @@ -357,31 +364,16 @@ pub struct PostMeltResponse { pub struct PostSplitRequest { pub proofs: Proofs, pub outputs: Vec, - pub amount: Option, } -#[skip_serializing_none] #[derive(Clone, Debug, Serialize, Deserialize, Default)] pub struct PostSplitResponse { - pub fst: Option>, - pub snd: Option>, - pub promises: Option>, + pub promises: Vec, } impl PostSplitResponse { pub fn with_promises(promises: Vec) -> Self { - Self { - promises: Some(promises), - ..Default::default() - } - } - - pub fn with_fst_and_snd(fst: Vec, snd: Vec) -> Self { - Self { - fst: Some(fst), - snd: Some(snd), - ..Default::default() - } + Self { promises } } } @@ -460,7 +452,7 @@ mod tests { fn test_serialize_empty_split_response() -> anyhow::Result<()> { let response = PostSplitResponse::default(); let serialized = serde_json::to_string(&response)?; - assert_eq!(serialized, "{}"); + assert_eq!(serialized, "{\"promises\":[]}"); Ok(()) } diff --git a/moksha-mint/src/fixtures/post_split_request_64_20.json b/moksha-mint/src/fixtures/post_split_request_64_20.json index 8fa72432..b9cf87e4 100644 --- a/moksha-mint/src/fixtures/post_split_request_64_20.json +++ b/moksha-mint/src/fixtures/post_split_request_64_20.json @@ -28,6 +28,5 @@ "amount": 16, "B_": "02364fe16667a049eb6dbdf4a8db23c250822fb8bc9806f4b82cc100ab00872959" } - ], - "amount": 20 + ] } diff --git a/moksha-mint/src/fixtures/post_split_request_64_20_no_amount.json b/moksha-mint/src/fixtures/post_split_request_64_20_no_amount.json deleted file mode 100644 index b9cf87e4..00000000 --- a/moksha-mint/src/fixtures/post_split_request_64_20_no_amount.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "proofs": [ - { - "amount": 64, - "secret": "sYYrrhUD3IwJzGFCGsUqqXXa", - "C": "0359760ad29ae24cd8535d83d9dcf09b585d36e0649235354aa7001e60206b3a66", - "id": "paFbO142_sui" - } - ], - "outputs": [ - { - "amount": 4, - "B_": "021b20f742d4735760e8dc9e89c99dbd9be9b6ec3edb4b8424c5b5a2c08063f96c" - }, - { - "amount": 8, - "B_": "031a392b384f8e2184ff77d0560e416b07f0cfe45c6e15273ddcbe84e6f87c4727" - }, - { - "amount": 32, - "B_": "03d763081ef9afdf11fe9d6114f4c494d53c28a78e9471faa1814ad336a6c234de" - }, - { - "amount": 4, - "B_": "03e997c205b170ed2f88c26f61559733144a55da6e66334b0f4a030b708a49e5ab" - }, - { - "amount": 16, - "B_": "02364fe16667a049eb6dbdf4a8db23c250822fb8bc9806f4b82cc100ab00872959" - } - ] -} diff --git a/moksha-mint/src/fixtures/post_split_request_duplicate_key.json b/moksha-mint/src/fixtures/post_split_request_duplicate_key.json index 293e2573..68c3ddd0 100644 --- a/moksha-mint/src/fixtures/post_split_request_duplicate_key.json +++ b/moksha-mint/src/fixtures/post_split_request_duplicate_key.json @@ -28,6 +28,5 @@ "amount": 16, "B_": "03e997c205b170ed2f88c26f61559733144a55da6e66334b0f4a030b708a49e5ab" } - ], - "amount": 20 + ] } diff --git a/moksha-mint/src/mint.rs b/moksha-mint/src/mint.rs index 0f818d4c..c5b6c08f 100644 --- a/moksha-mint/src/mint.rs +++ b/moksha-mint/src/mint.rs @@ -3,10 +3,7 @@ use std::{collections::HashSet, sync::Arc}; use moksha_core::{ crypto, dhke::Dhke, - model::{ - split_amount, BlindedMessage, BlindedSignature, MintKeyset, PostSplitResponse, Proofs, - TotalAmount, - }, + model::{BlindedMessage, BlindedSignature, MintKeyset, PostSplitResponse, Proofs, TotalAmount}, }; use crate::{ @@ -138,7 +135,6 @@ impl Mint { pub async fn split( &self, - amount: Option, proofs: &Proofs, blinded_messages: &[BlindedMessage], ) -> Result { @@ -150,42 +146,16 @@ impl Mint { let sum_proofs = proofs.total_amount(); - match amount { - Some(amount) => { - if amount > sum_proofs { - return Err(MokshaMintError::SplitAmountTooHigh); - } - let sum_first = split_amount(sum_proofs - amount).len(); - let first_slice = blinded_messages[0..sum_first].to_vec(); - let first_sigs = self.create_blinded_signatures(&first_slice)?; - let second_slice = blinded_messages[sum_first..blinded_messages.len()].to_vec(); - let second_sigs = self.create_blinded_signatures(&second_slice)?; - - let amount_first = first_sigs.total_amount(); - let amount_second = second_sigs.total_amount(); - - if sum_proofs != (amount_first + amount_second) { - return Err(MokshaMintError::SplitAmountMismatch(format!( - "Split amount mismatch: {sum_proofs} != {amount_first} + {amount_second}" - ))); - } - - self.db.add_used_proofs(proofs)?; - Ok(PostSplitResponse::with_fst_and_snd(first_sigs, second_sigs)) - } - None => { - let promises = self.create_blinded_signatures(blinded_messages)?; - let amount_promises = promises.total_amount(); - if sum_proofs != amount_promises { - return Err(MokshaMintError::SplitAmountMismatch(format!( - "Split amount mismatch: {sum_proofs} != {amount_promises}" - ))); - } - - self.db.add_used_proofs(proofs)?; - Ok(PostSplitResponse::with_promises(promises)) - } + let promises = self.create_blinded_signatures(blinded_messages)?; + let amount_promises = promises.total_amount(); + if sum_proofs != amount_promises { + return Err(MokshaMintError::SplitAmountMismatch(format!( + "Split amount mismatch: {sum_proofs} != {amount_promises}" + ))); } + + self.db.add_used_proofs(proofs)?; + Ok(PostSplitResponse::with_promises(promises)) } pub async fn melt( @@ -405,11 +375,9 @@ mod tests { let mint = create_mint_from_mocks(Some(create_mock_db_get_used_proofs()), None); let proofs = Proofs::empty(); - let result = mint.split(Some(0), &proofs, &blinded_messages).await?; + let result = mint.split(&proofs, &blinded_messages).await?; - assert!(result.promises.is_none()); - assert_eq!(result.fst.unwrap().len(), 0); - assert_eq!(result.snd.unwrap().len(), 0); + assert!(result.promises.is_empty()); Ok(()) } @@ -418,56 +386,20 @@ mod tests { let mint = create_mint_from_mocks(Some(create_mock_db_get_used_proofs()), None); let request = create_request_from_fixture("post_split_request_64_20.json".to_string())?; - let result = mint - .split(Some(20), &request.proofs, &request.outputs) - .await?; - - assert!(result.promises.is_none()); - assert_eq!(result.fst.unwrap().total_amount(), 44); - assert_eq!(result.snd.unwrap().total_amount(), 20); - Ok(()) - } - - #[tokio::test] - async fn test_split_64_in_20_no_amount() -> anyhow::Result<()> { - let mint = create_mint_from_mocks(Some(create_mock_db_get_used_proofs()), None); - let request = - create_request_from_fixture("post_split_request_64_20_no_amount.json".to_string())?; + let result = mint.split(&request.proofs, &request.outputs).await?; + assert_eq!(result.promises.total_amount(), 64); - let result = mint.split(None, &request.proofs, &request.outputs).await?; + let prv_lst = result + .promises + .get((result.promises.len() - 2) as usize) + .unwrap(); + let lst = result + .promises + .get((result.promises.len() - 1) as usize) + .unwrap(); - assert_eq!(result.promises.unwrap().total_amount(), 64); - assert!(result.fst.is_none()); - assert!(result.snd.is_none()); - Ok(()) - } - - #[tokio::test] - async fn test_split_64_in_64() -> anyhow::Result<()> { - let mint = create_mint_from_mocks(Some(create_mock_db_get_used_proofs()), None); - let request = create_request_from_fixture("post_split_request_64_20.json".to_string())?; - - let result = mint - .split(Some(64), &request.proofs, &request.outputs) - .await?; - - assert!(result.promises.is_none()); - assert_eq!(result.fst.unwrap().total_amount(), 0); - assert_eq!(result.snd.unwrap().total_amount(), 64); - Ok(()) - } - - #[tokio::test] - async fn test_split_amount_is_too_high() -> anyhow::Result<()> { - let mint = create_mint_from_mocks(Some(create_mock_db_get_used_proofs()), None); - let request = create_request_from_fixture("post_split_request_64_20.json".to_string())?; - - let result = mint - .split(Some(65), &request.proofs, &request.outputs) - .await; - assert!(result.is_err()); - let _err = result.unwrap_err(); - assert!(matches!(MokshaMintError::SplitAmountTooHigh, _err)); + assert_eq!(prv_lst.amount, 4); + assert_eq!(lst.amount, 16); Ok(()) } @@ -477,9 +409,7 @@ mod tests { let request = create_request_from_fixture("post_split_request_duplicate_key.json".to_string())?; - let result = mint - .split(Some(20), &request.proofs, &request.outputs) - .await; + let result = mint.split(&request.proofs, &request.outputs).await; assert!(result.is_err()); Ok(()) } diff --git a/moksha-mint/src/server.rs b/moksha-mint/src/server.rs index 1d0b0146..4fed807e 100644 --- a/moksha-mint/src/server.rs +++ b/moksha-mint/src/server.rs @@ -104,11 +104,7 @@ async fn post_split( Json(split_request): Json, ) -> Result, MokshaMintError> { let response = mint - .split( - split_request.amount, - &split_request.proofs, - &split_request.outputs, - ) + .split(&split_request.proofs, &split_request.outputs) .await?; Ok(Json(response)) diff --git a/moksha-wallet/src/client/mod.rs b/moksha-wallet/src/client/mod.rs index 17a0cdf4..11d92a2d 100644 --- a/moksha-wallet/src/client/mod.rs +++ b/moksha-wallet/src/client/mod.rs @@ -18,7 +18,6 @@ pub trait Client { async fn post_split_tokens( &self, mint_url: &Url, - amount: u64, proofs: Proofs, output: Vec, ) -> Result; diff --git a/moksha-wallet/src/client/reqwest.rs b/moksha-wallet/src/client/reqwest.rs index a55e373f..77c23e10 100644 --- a/moksha-wallet/src/client/reqwest.rs +++ b/moksha-wallet/src/client/reqwest.rs @@ -38,15 +38,10 @@ impl Client for HttpClient { async fn post_split_tokens( &self, mint_url: &Url, - amount: u64, proofs: Proofs, outputs: Vec, ) -> Result { - let body = serde_json::to_string(&PostSplitRequest { - amount: Some(amount), - proofs, - outputs, - })?; + let body = serde_json::to_string(&PostSplitRequest { proofs, outputs })?; let resp = self .request_client diff --git a/moksha-wallet/src/fixtures/post_split_response_24_40.json b/moksha-wallet/src/fixtures/post_split_response_24_40.json index df58d964..0b5490a8 100644 --- a/moksha-wallet/src/fixtures/post_split_response_24_40.json +++ b/moksha-wallet/src/fixtures/post_split_response_24_40.json @@ -1,5 +1,5 @@ { - "fst": [ + "promises": [ { "amount": 4, "C_": "03b2e736e1280f1e64eedf3fc53eeb5fc74e6f1d1664e3b2b7b8e2934afd908673", @@ -14,9 +14,7 @@ "amount": 4, "C_": "036614b4844efe234e0ec2293938a84a42b6e803126b365074943dd338f813421f", "id": "mR9PJ3MzjL1y" - } - ], - "snd": [ + }, { "amount": 8, "C_": "03859164602a27319bcd5c377bec90eda6f9d5d9e9c7987fce5bff4b69151a122f", diff --git a/moksha-wallet/src/wallet.rs b/moksha-wallet/src/wallet.rs index f8185b46..709b8dd5 100644 --- a/moksha-wallet/src/wallet.rs +++ b/moksha-wallet/src/wallet.rs @@ -4,7 +4,7 @@ use moksha_core::{ dhke::Dhke, model::{ split_amount, Amount, BlindedMessage, BlindedSignature, Keysets, PaymentRequest, - PostMeltResponse, PostSplitResponse, Proof, Proofs, TokenV3, TotalAmount, + PostMeltResponse, Proof, Proofs, TokenV3, TotalAmount, }, }; @@ -232,66 +232,33 @@ impl Wallet { let split_result = self .client - .post_split_tokens( - &self.mint_url, - splt_amount.0, - tokens.proofs(), - total_outputs, - ) + .post_split_tokens(&self.mint_url, tokens.proofs(), total_outputs) .await?; - match split_result { - PostSplitResponse { - promises: None, - fst: Some(fst), - snd: Some(snd), - } => { - let first_tokens = ( - self.mint_url.to_owned(), - self.create_proofs_from_blinded_signatures(fst, first_secrets, first_outputs)?, - ) - .into(); - - let second_tokens = ( - self.mint_url.to_owned(), - self.create_proofs_from_blinded_signatures( - snd, - second_secrets, - second_outputs, - )?, - ) - .into(); - - Ok((first_tokens, second_tokens)) - } - PostSplitResponse { - fst: None, - snd: None, - promises: Some(promises), - } => { - let len_first = first_secrets.len(); - let secrets = [first_secrets, second_secrets].concat(); - let outputs = [first_outputs, second_outputs].concat(); - - let proofs = self - .create_proofs_from_blinded_signatures(promises, secrets, outputs)? - .proofs(); - - let first_tokens = ( - self.mint_url.to_owned(), - proofs[0..len_first].to_vec().into(), - ) - .into(); - let second_tokens = ( - self.mint_url.to_owned(), - proofs[len_first..proofs.len()].to_vec().into(), - ) - .into(); - - Ok((first_tokens, second_tokens)) - } - _ => Err(MokshaWalletError::InvalidProofs), + if split_result.promises.is_empty() { + return Ok((TokenV3::empty(), TokenV3::empty())); } + + let len_first = first_secrets.len(); + let secrets = [first_secrets, second_secrets].concat(); + let outputs = [first_outputs, second_outputs].concat(); + + let proofs = self + .create_proofs_from_blinded_signatures(split_result.promises, secrets, outputs)? + .proofs(); + + let first_tokens = ( + self.mint_url.to_owned(), + proofs[0..len_first].to_vec().into(), + ) + .into(); + let second_tokens = ( + self.mint_url.to_owned(), + proofs[len_first..proofs.len()].to_vec().into(), + ) + .into(); + + Ok((first_tokens, second_tokens)) } async fn melt_token( @@ -551,7 +518,7 @@ mod tests { fn with_melt_response(post_melt_response: PostMeltResponse) -> Self { Self { post_melt_response, - split_response: PostSplitResponse::with_fst_and_snd(vec![], vec![]), + split_response: PostSplitResponse::with_promises(vec![]), ..Default::default() } } @@ -562,7 +529,6 @@ mod tests { async fn post_split_tokens( &self, _mint_url: &Url, - _amount: u64, _proofs: Proofs, _output: Vec, ) -> Result { diff --git a/moksha-wallet/tests/tests.rs b/moksha-wallet/tests/tests.rs index e38ec9f0..f5dbc183 100644 --- a/moksha-wallet/tests/tests.rs +++ b/moksha-wallet/tests/tests.rs @@ -44,7 +44,6 @@ impl Client for MockClient { async fn post_split_tokens( &self, _mint_url: &Url, - _amount: u64, _proofs: Proofs, _output: Vec, ) -> Result {