From 2b5cb6ef1f61099f716744e7e09c154cefbc6fa4 Mon Sep 17 00:00:00 2001 From: creating2morrow Date: Sun, 3 Dec 2023 21:28:27 -0500 Subject: [PATCH] patches for secure order retrieval --- neveko-core/src/contact.rs | 1 + neveko-core/src/monero.rs | 5 ++--- neveko-core/src/order.rs | 35 +++++++++++++++++++++++++---------- neveko-gui/LICENSE-APACHE | 2 +- neveko-gui/src/apps/market.rs | 1 - neveko-market/README.md | 12 +++++++----- 6 files changed, 36 insertions(+), 20 deletions(-) diff --git a/neveko-core/src/contact.rs b/neveko-core/src/contact.rs index 7c16e5e..2aef3fc 100644 --- a/neveko-core/src/contact.rs +++ b/neveko-core/src/contact.rs @@ -84,6 +84,7 @@ pub fn find(cid: &String) -> Contact { /// All contact lookup pub fn find_all() -> Vec { + info!("looking up all contacts"); let s = db::Interface::open(); let list_key = crate::CONTACT_LIST_DB_KEY; let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key)); diff --git a/neveko-core/src/monero.rs b/neveko-core/src/monero.rs index 5a7eaa4..41e3cd2 100644 --- a/neveko-core/src/monero.rs +++ b/neveko-core/src/monero.rs @@ -398,7 +398,7 @@ pub async fn check_rpc_connection() -> () { /// Performs the xmr rpc 'sign' method pub async fn sign(data: String) -> reqres::XmrRpcSignResponse { - info!("executing {}", RpcFields::Sign.value()); + info!("executing {} on: {}", RpcFields::Sign.value(), &data); let client = reqwest::Client::new(); let host = get_rpc_host(); let params = reqres::XmrRpcSignParams { data }; @@ -429,7 +429,7 @@ pub async fn sign(data: String) -> reqres::XmrRpcSignResponse { /// Performs the xmr rpc 'verify' method pub async fn verify(address: String, data: String, signature: String) -> bool { - info!("executing {}", RpcFields::Verify.value()); + info!("executing {} for sig: {} on {}", RpcFields::Verify.value(), &signature, &data); let client = reqwest::Client::new(); let host = get_rpc_host(); let params = reqres::XmrRpcVerifyParams { @@ -852,7 +852,6 @@ pub async fn export_multisig_info() -> reqres::XmrRpcExportResponse { { Ok(response) => { let res = response.json::().await; - debug!("{} response: {:?}", RpcFields::Export.value(), res); match res { Ok(res) => res, _ => Default::default(), diff --git a/neveko-core/src/order.rs b/neveko-core/src/order.rs index 3261c2c..5db4361 100644 --- a/neveko-core/src/order.rs +++ b/neveko-core/src/order.rs @@ -21,6 +21,7 @@ use log::{ info, }; use rocket::serde::json::Json; +use serde::de; pub enum StatusType { _Cancelled, @@ -108,7 +109,11 @@ pub fn backup(order: &Order) { if r == utils::empty_string() { debug!("creating customer order index"); } - let order_list = [r, String::from(&order.orid)].join(","); + let mut order_list = [String::from(&r), String::from(&order.orid)].join(","); + // don't duplicate order ids when backing up updates from vendor + if String::from(&r).contains(&String::from(&order.orid)) { + order_list = r; + } debug!("writing order index {} for id: {}", order_list, list_key); db::Interface::write(&s.env, &s.handle, &String::from(list_key), &order_list); } @@ -239,10 +244,12 @@ pub async fn secure_retrieval(orid: &String, signature: &String) -> Order { // send address, orid and signature to verify() let id: String = String::from(&m_order.orid); let sig: String = String::from(signature); - let wallet_password = utils::empty_string(); - monero::open_wallet(&orid, &wallet_password).await; + let wallet_password = + std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password")); + let wallet_name = String::from(crate::APP_NAME); + monero::open_wallet(&wallet_name, &wallet_password).await; let is_valid_signature = monero::verify(xmr_address, id, sig).await; - monero::close_wallet(&orid, &wallet_password).await; + monero::close_wallet(&wallet_name, &wallet_password).await; if !is_valid_signature { return Default::default(); } @@ -255,7 +262,9 @@ pub async fn secure_retrieval(orid: &String, signature: &String) -> Order { pub async fn validate_order_for_ship(orid: &String) -> reqres::FinalizeOrderResponse { info!("validating order for shipment"); let m_order: Order = find(orid); - let delivery_info: Vec = hex::decode(&m_order.ship_address).unwrap(); + let s = db::Interface::async_open().await; + let k = String::from(crate::DELIVERY_INFO_DB_KEY); + let delivery_info: String = db::Interface::async_read(&s.env, &s.handle, &k).await; let mut j_order: Order = find(orid); let m_product: Product = product::find(&m_order.pid); let price = m_product.price; @@ -274,13 +283,15 @@ pub async fn validate_order_for_ship(orid: &String) -> reqres::FinalizeOrderResp } reqres::FinalizeOrderResponse { orid: String::from(orid), - delivery_info, + delivery_info: hex::decode(delivery_info).unwrap_or(Vec::new()), } } /// Write encrypted delivery info to lmdb. Once the customer releases the signed /// txset /// +/// This will also attempt to notify the customer to trigger the NASR (neveko auto-ship request). +/// /// they will have access to this information (tracking number, locker code, /// etc.) pub async fn upload_delivery_info( @@ -294,14 +305,18 @@ pub async fn upload_delivery_info( error!("unable to encrypt delivery info"); } // get draft payment txset - let sweep: reqres::XmrRpcSweepAllResponse = + let mut sweep: reqres::XmrRpcSweepAllResponse = monero::sweep_all(String::from(&lookup.subaddress)).await; // update the order let mut m_order: Order = find(orid); m_order.status = StatusType::Shipped.value(); - m_order.deliver_date = chrono::offset::Utc::now().timestamp(); - m_order.ship_address = delivery_info.to_vec(); + m_order.ship_date = chrono::offset::Utc::now().timestamp(); + m_order.hash = String::from(&sweep.result.tx_hash_list.remove(0)); m_order.vend_msig_txset = sweep.result.multisig_txset; + // delivery info will be stored encrypted and separate from the rest of the order + let s = db::Interface::async_open().await; + let k = String::from(crate::DELIVERY_INFO_DB_KEY); + db::Interface::async_write(&s.env, &s.handle, &k, &hex::encode(&delivery_info)).await; modify(Json(m_order)); FinalizeOrderResponse { delivery_info: delivery_info.to_vec(), @@ -431,7 +446,7 @@ pub async fn transmit_sor_request( let client = reqwest::Client::builder().proxy(proxy).build(); match client? .get(format!( - "http://{}/order/retrieve/{}/{}", + "http://{}/market/order/retrieve/{}/{}", contact, orid, signature )) .header("proof", jwp) diff --git a/neveko-gui/LICENSE-APACHE b/neveko-gui/LICENSE-APACHE index 11069ed..b56c276 100644 --- a/neveko-gui/LICENSE-APACHE +++ b/neveko-gui/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright [yyyy] [name of copyright owner] +Copyright [2023] [creating2morrow] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/neveko-gui/src/apps/market.rs b/neveko-gui/src/apps/market.rs index 5883195..3b135ef 100644 --- a/neveko-gui/src/apps/market.rs +++ b/neveko-gui/src/apps/market.rs @@ -624,7 +624,6 @@ impl eframe::App for MarketApp { } }); } - if self.msig.completed_export && !self.msig.completed_shipping_request { ui.horizontal(|ui| { ui.label("Request Shipping: \t"); diff --git a/neveko-market/README.md b/neveko-market/README.md index a115905..0a7e717 100755 --- a/neveko-market/README.md +++ b/neveko-market/README.md @@ -47,12 +47,14 @@ |cust | X | X | X | |med | X | X | X | -* customer funds wallet and exports info to vendor and mediator -* vendor and mediator import multisig info -* customer signs multisig txset and sends to mediator -* mediator requests tracking number from vendor -* mediator relase signed txset to vendor +* customer funds wallet and exports info to vendor +* vendor imports multisig info +* vendor uploads delivery info and triggers and automate NASR (neveko auto-ship request) from customer +* customer requests shipment +* vendor drafts the multisig txset and sends to customer with tracking/delivery info +* order arrives, customer releases signed txset to vendor * vendor signs and submits signed txset * in case of dispute the mediator can sign multisig txset for customer refund + or if the customer doesn't release payment after delivery Reference: https://resilience365.com/monero-multisig-how-to/