add wallet mutex lock

This commit is contained in:
creating2morrow 2023-06-06 10:18:06 -04:00
parent 2128a0d152
commit 6abb0551cd
7 changed files with 54 additions and 3 deletions

1
Cargo.lock generated
View file

@ -1971,6 +1971,7 @@ dependencies = [
"hex",
"hmac",
"jwt",
"lazy_static 1.4.0",
"lmdb-rs",
"log 0.4.17",
"rand",

View file

@ -14,6 +14,7 @@ gpgme = "0.11.0"
hex = "0.4.3"
hmac = "0.12.1"
jwt = "0.16.0"
lazy_static = "1.4.0"
lmdb-rs = "0.7.6"
log = "0.4"
rand = "0.8.5"

View file

@ -14,6 +14,15 @@ use log::{
};
use std::process::Command;
use lazy_static::lazy_static;
use std::sync::Mutex;
// global variable
lazy_static! {
/// used to avoid multisig wallet collision
static ref IS_WALLET_BUSY: Mutex<bool> = Mutex::new(false);
}
/// Current xmr ring size updated here.
const RING_SIZE: u32 = 0x10;
@ -384,8 +393,35 @@ pub async fn create_wallet(filename: &String, password: &String) -> bool {
}
}
/// Set the wallet lock to true during operations to avoid collisons
///
/// on different types of wallet (e.g. order versus NEVEKO instance).
///
/// The open functionality will break on `false` if busy.
fn update_wallet_lock(filename: &String, closing: bool) -> bool {
let is_busy: bool = match IS_WALLET_BUSY.lock() {
Ok(m) => *m,
Err(_) => false,
};
if is_busy && !closing {
debug!("wallet {} is busy", filename);
return false;
}
if !closing {
*IS_WALLET_BUSY.lock().unwrap() = true;
return true;
} else {
*IS_WALLET_BUSY.lock().unwrap() = false;
return true;
}
}
/// Performs the xmr rpc 'open_wallet' method
pub async fn open_wallet(filename: &String, password: &String) -> bool {
let updated = update_wallet_lock(filename, false);
if !updated {
return updated;
}
info!("executing {}", RpcFields::Open.value());
let client = reqwest::Client::new();
let host = get_rpc_host();
@ -399,7 +435,6 @@ pub async fn open_wallet(filename: &String, password: &String) -> bool {
method: RpcFields::Open.value(),
params,
};
debug!("open request: {:?}", req);
let login: RpcLogin = get_rpc_creds();
match client
.post(host)
@ -427,6 +462,10 @@ pub async fn open_wallet(filename: &String, password: &String) -> bool {
/// Performs the xmr rpc 'close_wallet' method
pub async fn close_wallet(filename: &String, password: &String) -> bool {
let updated = update_wallet_lock(filename, true);
if !updated {
return updated;
}
info!("executing {}", RpcFields::Close.value());
let client = reqwest::Client::new();
let host = get_rpc_host();

View file

@ -41,7 +41,7 @@ pub async fn create(j_order: Json<reqres::OrderRequest>) -> Order {
let wallet_name = String::from(crate::APP_NAME);
let wallet_password =
std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password"));
monero::close_wallet(&wallet_name, &wallet_password).await;
monero::open_wallet(&wallet_name, &wallet_password).await;
let ts = chrono::offset::Utc::now().timestamp();
let orid: String = format!("O{}", utils::generate_rnd());
let r_subaddress = monero::create_address().await;
@ -186,7 +186,10 @@ 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 is_valid_signature = monero::verify(xmr_address, id, sig).await;
monero::close_wallet(&orid, &wallet_password).await;
if !is_valid_signature {
return Default::default();
}
@ -213,6 +216,7 @@ pub async fn validate_order_for_ship(orid: &String) -> bool {
let r_import = monero::import_multisig_info(v_info).await;
// check balance and unlock_time
let r_balance = monero::get_balance().await;
monero::close_wallet(&orid, &wallet_password).await;
// update the order status to multisig complete
let ready_to_ship: bool = r_import.result.n_outputs > 0
&& r_balance.result.balance >= total as u128
@ -259,6 +263,8 @@ pub async fn finalize_order(orid: &String) -> reqres::FinalizeOrderResponse {
let key = format!("{}-{}-{}", message::TXSET_MSIG, orid, &m_order.cid);
let txset = db::Interface::async_read(&s.env, &s.handle, &key).await;
// describe transer to check amount, address and unlock_time
let wallet_password = utils::empty_string();
monero::open_wallet(&orid, &wallet_password).await;
let r_describe: reqres::XmrRpcDescribeTransferResponse =
monero::describe_transfer(&txset).await;
let m_product: Product = product::find(&m_order.pid);
@ -271,6 +277,7 @@ pub async fn finalize_order(orid: &String) -> reqres::FinalizeOrderResponse {
}
let r_submit: reqres::XmrRpcSubmitMultisigResponse =
sign_and_submit_multisig(orid, &txset).await;
monero::close_wallet(&orid, &wallet_password).await;
if r_submit.result.tx_hash_list.is_empty() {
return Default::default();
}

View file

@ -300,6 +300,7 @@ async fn gen_app_wallet(password: &String) {
}
}
}
monero::close_wallet(&filename, password).await;
}
/// Secret keys for signing internal/external auth tokens

1
neveko-gui/Cargo.lock generated
View file

@ -2419,6 +2419,7 @@ dependencies = [
"hex",
"hmac",
"jwt",
"lazy_static 1.4.0",
"lmdb-rs",
"log 0.4.17",
"rand",

View file

@ -366,7 +366,8 @@ fn send_ver_req(tx: Sender<reqres::XmrRpcVersionResponse>, ctx: egui::Context) {
fn send_wallet_req(
address_tx: Sender<reqres::XmrRpcAddressResponse>,
balance_tx: Sender<reqres::XmrRpcBalanceResponse>,
ctx: egui::Context) {
ctx: egui::Context,
) {
tokio::spawn(async move {
let wallet_name = String::from(neveko_core::APP_NAME);
let wallet_password =