Skip to content

Commit ff227b6

Browse files
authored
Merge pull request hyperledger-indy#952 from KitHat/master
Add utxo already spent error to libnullpay
2 parents b8ce9d3 + 36c5f5d commit ff227b6

File tree

5 files changed

+130
-2
lines changed

5 files changed

+130
-2
lines changed

libnullpay/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,4 +203,7 @@ pub enum ErrorCode
203203

204204
// Insufficient funds on inputs
205205
PaymentInsufficientFundsError = 702,
206+
207+
// No such source on a ledger
208+
PaymentSourceDoesNotExistError = 703,
206209
}

libnullpay/src/payment_method.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,23 @@ pub mod add_request_fees {
6868

6969
trace!("FEE: {}", fee);
7070

71+
let ec = _check_inputs_existance(&inputs_json);
72+
if ec != ErrorCode::Success {
73+
ledger::build_get_txn_request(
74+
submitter_did.as_str(),
75+
None,
76+
1,
77+
Box::new(move |ec, res| {
78+
let ec = if ec == ErrorCode::Success {
79+
_add_response(&res, "NO_UTXO")
80+
} else { ec };
81+
trace!("libnullpay::add_request_fees::handle >>");
82+
_process_callback(cmd_handle, ec, res, cb);
83+
}),
84+
);
85+
return ErrorCode::Success;
86+
}
87+
7188
let total_amount = _count_total_inputs(&inputs_json);
7289
let total_payments = _count_total_payments(&outputs_json);
7390

@@ -188,6 +205,7 @@ pub mod build_payment_req {
188205

189206
let total_balance = _count_total_inputs(&inputs_json);
190207
let total_payments = _count_total_payments(&outputs_json);
208+
let ec_existance = _check_inputs_existance(&inputs_json);
191209

192210
let seq_no = payment_ledger::add_txn(inputs_json.clone(), outputs_json.clone());
193211

@@ -202,7 +220,9 @@ pub mod build_payment_req {
202220
1,
203221
Box::new(move |ec, res| {
204222
if ec == ErrorCode::Success {
205-
if total_balance >= total_payments {
223+
if ec_existance != ErrorCode::Success {
224+
_add_response(&res, "NO_UTXO");
225+
} else if total_balance >= total_payments {
206226
_process_inputs(&inputs_json);
207227
let infos = _process_outputs(&outputs_json, seq_no);
208228

@@ -362,6 +382,16 @@ fn _check_inputs(inputs: &Vec<String>, payment_addresses: &Vec<String>) -> bool
362382
})
363383
}
364384

385+
fn _check_inputs_existance(inputs: &Vec<String>) -> ErrorCode {
386+
for input in inputs {
387+
match utxo_cache::get_balanse_of_utxo(input) {
388+
None => return ErrorCode::PaymentSourceDoesNotExistError,
389+
_ => ()
390+
}
391+
}
392+
ErrorCode::Success
393+
}
394+
365395
fn _process_inputs(inputs: &Vec<String>) {
366396
inputs.into_iter().for_each(|s| {
367397
utxo_cache::remove_utxo(s);

libnullpay/src/services/response_storage.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub fn get_response(response: &str) -> Result<String, ErrorCode> {
3535
let mut responses = RESPONSES.lock().unwrap();
3636
match responses.remove(req_id.to_string().as_str()) {
3737
Some(ref resp) if resp == "INSUFFICIENT_FUNDS" => Err(ErrorCode::PaymentInsufficientFundsError),
38+
Some(ref resp) if resp == "NO_UTXO" => Err(ErrorCode::PaymentSourceDoesNotExistError),
3839
Some(resp) => Ok(resp),
3940
None => Err(ErrorCode::CommonInvalidState)
4041
}

libnullpay/tests/payments.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,57 @@ mod high_cases {
285285
test_utils::cleanup_storage();
286286
}
287287

288+
#[test]
289+
pub fn add_request_works_for_spent_utxo() {
290+
test_utils::cleanup_storage();
291+
plugin::init_plugin();
292+
let wallet_handle = wallet::create_and_open_wallet().unwrap();
293+
let pool_handle = pool::create_and_open_pool_ledger(POOL_NAME).unwrap();
294+
295+
let (trustee_did, _) = did::create_and_store_my_did(wallet_handle, Some(TRUSTEE_SEED)).unwrap();
296+
let (my_did, my_vk) = did::create_and_store_my_did(wallet_handle, None).unwrap();
297+
let (my_did_2, my_vk_2) = did::create_and_store_my_did(wallet_handle, None).unwrap();
298+
let nym_req = ledger::build_nym_request(&trustee_did, &my_did, &my_vk, "aaa", "TRUSTEE").unwrap();
299+
let nym_req_2 = ledger::build_nym_request(&trustee_did, &my_did_2, &my_vk_2, "aaa", "TRUSTEE").unwrap();
300+
301+
let addresses = payments_utils::create_addresses(vec!["{}", "{}"], wallet_handle, PAYMENT_METHOD_NAME);
302+
303+
let mint: Vec<(String, i32, Option<&str>)> = addresses.clone().into_iter().enumerate().map(|(i, addr)| (addr, ((i+3)*10) as i32, None)).collect();
304+
payments_utils::mint_tokens(mint, wallet_handle, pool_handle, my_did.as_str());
305+
306+
payments_utils::set_request_fees(wallet_handle, pool_handle, SUBMITTER_DID, PAYMENT_METHOD_NAME, r#"{"1": 10, "101": 10}"#);
307+
308+
let utxos = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle, SUBMITTER_DID);
309+
310+
let addr_1 = addresses.get(0).unwrap();
311+
let utxos_1: Vec<String> = utxos.get(addr_1.as_str()).unwrap().into_iter().map(|info| info.txo.clone()).collect();
312+
let inputs = serde_json::to_string(&utxos_1).unwrap();
313+
314+
let outputs = vec![UTXOOutput {
315+
payment_address: addresses.get(1).unwrap().to_string(),
316+
amount: 19,
317+
extra: None
318+
}, UTXOOutput {
319+
payment_address: addresses.get(0).unwrap().to_string(),
320+
amount: 1,
321+
extra: None
322+
}];
323+
let outputs = serde_json::to_string(&outputs).unwrap();
324+
325+
let (nym_req_with_fees, payment_method) = payments::add_request_fees(wallet_handle, SUBMITTER_DID, nym_req.as_str(), inputs.as_str(), outputs.as_str()).unwrap();
326+
let nym_resp = ledger::sign_and_submit_request(pool_handle, wallet_handle, trustee_did.as_str(), nym_req_with_fees.as_str()).unwrap();
327+
payments::parse_response_with_fees(payment_method.as_str(), nym_resp.as_str()).unwrap();
328+
329+
let (nym_req_with_fees_2, payment_method) = payments::add_request_fees(wallet_handle, SUBMITTER_DID, nym_req_2.as_str(), inputs.as_str(), outputs.as_str()).unwrap();
330+
let nym_resp_2 = ledger::sign_and_submit_request(pool_handle, wallet_handle, trustee_did.as_str(), nym_req_with_fees_2.as_str()).unwrap();
331+
let ec = payments::parse_response_with_fees(payment_method.as_str(), nym_resp_2.as_str()).unwrap_err();
332+
assert_eq!(ec, ErrorCode::PaymentSourceDoesNotExistError);
333+
334+
pool::close(pool_handle).unwrap();
335+
wallet::close_wallet(wallet_handle).unwrap();
336+
test_utils::cleanup_storage();
337+
}
338+
288339
#[test]
289340
pub fn add_request_fees_works_for_utxo_not_correspond_to_wallet() {
290341
test_utils::cleanup_storage();
@@ -450,6 +501,50 @@ mod high_cases {
450501
test_utils::cleanup_storage();
451502
}
452503

504+
#[test]
505+
pub fn payments_work_for_spent_utxo() {
506+
test_utils::cleanup_storage();
507+
plugin::init_plugin();
508+
let wallet_handle = wallet::create_and_open_wallet().unwrap();
509+
let pool_handle = pool::create_and_open_pool_ledger(POOL_NAME).unwrap();
510+
511+
let addresses = payments_utils::create_addresses(vec!["{}", "{}"], wallet_handle, PAYMENT_METHOD_NAME);
512+
513+
let mint: Vec<(String, i32, Option<&str>)> = addresses.clone().into_iter().enumerate().map(|(i, addr)| (addr, ((i + 2) * 10) as i32, None)).collect();
514+
payments_utils::mint_tokens(mint, wallet_handle, pool_handle, SUBMITTER_DID);
515+
516+
let utxos = payments_utils::get_utxos_with_balance(addresses.clone(), wallet_handle, pool_handle, SUBMITTER_DID);
517+
518+
let addr_1 = addresses.get(0).unwrap();
519+
let utxos_1: Vec<String> = utxos.get(addr_1.as_str()).unwrap().into_iter().map(|info| info.txo.clone()).collect();
520+
let inputs = serde_json::to_string(&utxos_1).unwrap();
521+
522+
let outputs = vec![UTXOOutput {
523+
payment_address: addresses.get(1).unwrap().to_string(),
524+
amount: 19,
525+
extra: None
526+
}, UTXOOutput {
527+
payment_address: addresses.get(0).unwrap().to_string(),
528+
amount: 1,
529+
extra: None
530+
}];
531+
let outputs = serde_json::to_string(&outputs).unwrap();
532+
533+
let (payment_req, payment_method) = payments::build_payment_req(wallet_handle, SUBMITTER_DID, inputs.as_str(), outputs.as_str()).unwrap();
534+
let payment_resp = ledger::submit_request(pool_handle, payment_req.as_str()).unwrap();
535+
payments::parse_payment_response(payment_method.as_str(), payment_resp.as_str()).unwrap();
536+
537+
let (payment_req, payment_method) = payments::build_payment_req(wallet_handle, SUBMITTER_DID, inputs.as_str(), outputs.as_str()).unwrap();
538+
let payment_resp = ledger::submit_request(pool_handle, payment_req.as_str()).unwrap();
539+
let ec = payments::parse_payment_response(payment_method.as_str(), payment_resp.as_str()).unwrap_err();
540+
541+
assert_eq!(ec, ErrorCode::PaymentSourceDoesNotExistError);
542+
543+
pool::close(pool_handle).unwrap();
544+
wallet::close_wallet(wallet_handle).unwrap();
545+
test_utils::cleanup_storage();
546+
}
547+
453548
#[test]
454549
pub fn payment_request_works_for_utxo_not_correspond_to_wallet() {
455550
test_utils::cleanup_storage();

libnullpay/tests/utils/wallet.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use nullpay::ErrorCode;
22

33
use std::ffi::CString;
4-
use std::ptr::null;
54
use std::os::raw::c_char;
65

76
pub const DEFAULT_WALLET_CREDENTIALS: &'static str = r#"{"key":"key"}"#;

0 commit comments

Comments
 (0)