From eb5c0b370df522b20237eb8dc0f1a2de96de836c Mon Sep 17 00:00:00 2001 From: kn0sys Date: Thu, 5 Sep 2024 09:31:43 -0400 Subject: [PATCH] serialization fixes --- Cargo.lock | 174 +++++++- neveko-contact/src/controller.rs | 2 +- neveko-core/Cargo.toml | 2 + neveko-core/src/args.rs | 7 - neveko-core/src/auth.rs | 115 ++--- neveko-core/src/contact.rs | 132 +++--- neveko-core/src/db.rs | 291 +++++++------ neveko-core/src/dispute.rs | 62 +-- neveko-core/src/error.rs | 12 + neveko-core/src/i2p.rs | 18 +- neveko-core/src/lib.rs | 10 +- neveko-core/src/message.rs | 151 ++++--- neveko-core/src/models.rs | 360 +--------------- neveko-core/src/monero.rs | 10 +- neveko-core/src/neveko25519.rs | 16 +- neveko-core/src/order.rs | 110 ++--- neveko-core/src/product.rs | 32 +- neveko-core/src/proof.rs | 26 +- neveko-core/src/reqres.rs | 627 ++++------------------------ neveko-core/src/user.rs | 91 ++-- neveko-core/src/utils.rs | 190 +++------ neveko-gui/src/apps/address_book.rs | 64 +-- neveko-gui/src/apps/home.rs | 78 +--- neveko-gui/src/apps/lock_screen.rs | 6 +- neveko-gui/src/apps/mailbox.rs | 4 +- neveko-gui/src/apps/market.rs | 220 +++++----- neveko-gui/src/apps/settings.rs | 13 +- neveko-gui/src/apps/wallet.rs | 8 +- neveko-gui/src/login.rs | 8 +- neveko-gui/src/wrap_app.rs | 12 +- src/controller.rs | 6 +- 31 files changed, 996 insertions(+), 1861 deletions(-) create mode 100644 neveko-core/src/error.rs diff --git a/Cargo.lock b/Cargo.lock index ce60ede..65ce477 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -567,16 +567,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" version = "0.8.3" @@ -1117,7 +1107,7 @@ dependencies = [ "libc 0.2.153", "log", "rustversion", - "windows", + "windows 0.48.0", ] [[package]] @@ -1418,7 +1408,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows 0.48.0", ] [[package]] @@ -1946,6 +1936,8 @@ dependencies = [ "serde", "serde_json", "sha2", + "sysinfo", + "thiserror", "tokio", ] @@ -2035,6 +2027,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2494,9 +2495,9 @@ checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" [[package]] name = "rayon" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -2504,14 +2505,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -3095,6 +3094,20 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sysinfo" +version = "0.31.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be" +dependencies = [ + "core-foundation-sys", + "libc 0.2.153", + "memchr", + "ntapi", + "rayon", + "windows 0.57.0", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -3150,18 +3163,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", @@ -3817,6 +3830,59 @@ dependencies = [ "windows-targets 0.48.0", ] +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.42.0" @@ -3880,6 +3946,22 @@ dependencies = [ "windows_x86_64_msvc 0.48.0", ] +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -3892,6 +3974,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -3904,6 +3992,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -3916,6 +4010,18 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -3928,6 +4034,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -3940,6 +4052,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -3952,6 +4070,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -3964,6 +4088,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "winit" version = "0.28.6" diff --git a/neveko-contact/src/controller.rs b/neveko-contact/src/controller.rs index 632e672..f1e4aab 100644 --- a/neveko-contact/src/controller.rs +++ b/neveko-contact/src/controller.rs @@ -25,7 +25,7 @@ pub async fn add_contact( _token: auth::BearerToken, ) -> Custom> { let res_contact = contact::create(&req_contact).await; - if res_contact.cid == utils::empty_string() { + if res_contact.cid.is_empty() { return Custom(Status::BadRequest, Json(Default::default())); } Custom(Status::Ok, Json(res_contact)) diff --git a/neveko-core/Cargo.toml b/neveko-core/Cargo.toml index 8921767..aaba349 100644 --- a/neveko-core/Cargo.toml +++ b/neveko-core/Cargo.toml @@ -28,4 +28,6 @@ schedule_recv = "0.1.0" sha2 = "0.10.6" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.94" +sysinfo = "0.31.2" +thiserror = "1.0.63" tokio = "1.25.0" diff --git a/neveko-core/src/args.rs b/neveko-core/src/args.rs index 2a083b5..f48b1c8 100644 --- a/neveko-core/src/args.rs +++ b/neveko-core/src/args.rs @@ -34,13 +34,6 @@ pub struct Args { default_value = "/home/user/.bitmonero" )] pub monero_blockchain_dir: String, - /// Absolute path to i2p zero - #[arg( - long, - help = "Absolute path to i2p-zero directroy", - default_value = "/home/user/i2p-zero-linux.v1.21" - )] - pub i2p_zero_dir: String, /// Monero RPC daemon host #[arg( long, diff --git a/neveko-core/src/auth.rs b/neveko-core/src/auth.rs index efd6bad..941abee 100644 --- a/neveko-core/src/auth.rs +++ b/neveko-core/src/auth.rs @@ -10,6 +10,7 @@ use crate::{ utils, }; use clap::Parser; +use kn0sys_lmdb_rs::MdbError; use log::{ debug, error, @@ -32,7 +33,7 @@ use sha2::Sha384; use std::collections::BTreeMap; /// Create authorization data to sign and expiration -pub fn create(address: &String) -> Authorization { +pub fn create(address: &String) -> Result { info!("creating auth"); let aid: String = format!("{}{}", crate::AUTH_DB_KEY, utils::generate_rnd()); let rnd: String = utils::generate_rnd(); @@ -41,32 +42,35 @@ pub fn create(address: &String) -> Authorization { let new_auth = Authorization { aid, created, - uid: utils::empty_string(), + uid: String::new(), rnd, token, xmr_address: String::from(address), }; - let s = db::Interface::open(); + let env = utils::get_release_env(); + let s = db::DatabaseEnvironment::open(&env.value())?; debug!("insert auth: {:?}", &new_auth); - let k = &new_auth.aid; - db::Interface::write(&s.env, &s.handle, k, &Authorization::to_db(&new_auth)); - new_auth + let k = &new_auth.aid.as_bytes(); + let v = bincode::serialize(&new_auth).unwrap_or_default(); + db::write_chunks(&s.env, &s.handle?, k, &v); + Ok(new_auth) } /// Authorization lookup for recurring requests -pub fn find(aid: &String) -> Authorization { +pub fn find(aid: &String) -> Result { info!("searching for auth: {}", aid); - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, &String::from(aid)); - debug!("auth read: {}", r); - if r == utils::empty_string() { - return Default::default(); + let env = utils::get_release_env(); + let s = db::DatabaseEnvironment::open(&env.value())?; + let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &aid.as_bytes().to_vec())?; + if r.is_empty() { + return Err(MdbError::NotFound); } - Authorization::from_db(String::from(aid), r) + let result: Authorization = bincode::deserialize(&r[..]).unwrap_or_default(); + Ok(result) } /// Update new authorization creation time -fn update_expiration(f_auth: &Authorization, address: &String) -> Authorization { +fn update_expiration(f_auth: &Authorization, address: &String) -> Result { info!("modify auth expiration"); let data = utils::generate_rnd(); let time: i64 = chrono::offset::Utc::now().timestamp(); @@ -77,27 +81,26 @@ fn update_expiration(f_auth: &Authorization, address: &String) -> Authorization data, create_token(String::from(address), time), ); - let s = db::Interface::open(); - db::Interface::delete(&s.env, &s.handle, &u_auth.aid); - db::Interface::write( - &s.env, - &s.handle, - &u_auth.aid, - &Authorization::to_db(&u_auth), - ); - u_auth + let env = utils::get_release_env(); + let s = db::DatabaseEnvironment::open(&env.value())?; + db::DatabaseEnvironment::delete(&s.env, &s.handle?, &u_auth.aid.as_bytes().to_vec()); + let k = u_auth.aid.as_bytes(); + let v = bincode::serialize(&u_auth).unwrap_or_default(); + let s = db::DatabaseEnvironment::open(&env.value())?; + db::write_chunks(&s.env, &s.handle?, k, &v); + Ok(u_auth) } /// Performs the signature verfication against stored auth -pub async fn verify_login(aid: String, uid: String, signature: String) -> Authorization { +pub async fn verify_login(aid: String, uid: String, signature: String) -> Result { let wallet_name = String::from(crate::APP_NAME); let wallet_password = std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password")); monero::open_wallet(&wallet_name, &wallet_password).await; let m_address: reqres::XmrRpcAddressResponse = monero::get_address().await; let address = m_address.result.address; - let f_auth: Authorization = find(&aid); - if f_auth.xmr_address == utils::empty_string() { + let f_auth: Authorization = find(&aid)?; + if f_auth.xmr_address.is_empty() { error!("auth not found"); monero::close_wallet(&wallet_name, &wallet_password).await; return create(&address); @@ -113,51 +116,49 @@ pub async fn verify_login(aid: String, uid: String, signature: String) -> Author if sig_address == utils::ApplicationErrors::LoginError.value() { error!("signature validation failed"); monero::close_wallet(&wallet_name, &wallet_password).await; - return f_auth; + return Ok(f_auth); } - let f_user: User = user::find(&uid); - if f_user.xmr_address == utils::empty_string() { + let f_user: User = user::find(&uid)?; + if f_user.xmr_address.is_empty() { info!("creating new user"); - let u: User = user::create(&address); + let u: User = user::create(&address)?; // update auth with uid let u_auth = Authorization::update_uid(f_auth, String::from(&u.uid)); - let s = db::Interface::open(); - db::Interface::delete(&s.env, &s.handle, &u_auth.aid); - db::Interface::write( - &s.env, - &s.handle, - &u_auth.aid, - &Authorization::to_db(&u_auth), - ); + let env = utils::get_release_env(); + let s = db::DatabaseEnvironment::open(&env.value())?; + db::DatabaseEnvironment::delete(&s.env, &s.handle?, &u_auth.aid.as_bytes()); + let v = bincode::serialize(&u_auth).unwrap_or_default(); + let s = db::DatabaseEnvironment::open(&env.value())?; + db::write_chunks(&s.env, &s.handle?, u_auth.aid.as_bytes(), &v); monero::close_wallet(&wallet_name, &wallet_password).await; - u_auth - } else if f_user.xmr_address != utils::empty_string() { + Ok(u_auth) + } else if !f_user.xmr_address.is_empty() { info!("returning user"); - let m_access = verify_access(&address, &signature).await; + let m_access = verify_access(&address, &signature).await?; if !m_access { monero::close_wallet(&wallet_name, &wallet_password).await; - return Default::default(); + return Ok(Default::default()); } monero::close_wallet(&wallet_name, &wallet_password).await; - return f_auth; + return Ok(f_auth); } else { error!("error creating user"); monero::close_wallet(&wallet_name, &wallet_password).await; - return Default::default(); + return Ok(Default::default()); } } /// Called during auth flow to update data to sign and expiration -async fn verify_access(address: &String, signature: &String) -> bool { +async fn verify_access(address: &String, signature: &String) -> Result { // look up auth for address - let f_auth: Authorization = find(address); - if f_auth.xmr_address != utils::empty_string() { + let f_auth: Authorization = find(address)?; + if !f_auth.xmr_address.is_empty() { // check expiration, generate new data to sign if necessary let now: i64 = chrono::offset::Utc::now().timestamp(); let expiration = get_auth_expiration(); if now > f_auth.created + expiration { update_expiration(&f_auth, address); - return false; + return Ok(false); } } // verify signature on the data if not expired @@ -171,10 +172,10 @@ async fn verify_access(address: &String, signature: &String) -> bool { }; if sig_address == utils::ApplicationErrors::LoginError.value() { debug!("signing failed"); - return false; + return Ok(false); } info!("auth verified"); - true + Ok(true) } /// get the auth expiration command line configuration @@ -224,7 +225,7 @@ impl<'r> FromRequest<'r> for BearerToken { let env = utils::get_release_env(); let dev = utils::ReleaseEnvironment::Development; if env == dev { - return Outcome::Success(BearerToken(utils::empty_string())); + return Outcome::Success(BearerToken(String::new())); } let token = request.headers().get_one("token"); let wallet_name = String::from(crate::APP_NAME); @@ -281,17 +282,17 @@ impl<'r> FromRequest<'r> for BearerToken { mod tests { use super::*; - async fn find_test_auth(k: &String) -> Authorization { + async fn find_test_auth(k: &String) -> Result { tokio::time::sleep(std::time::Duration::from_secs(1)).await; - let s: db::Interface = db::Interface::async_open().await; - let v = db::Interface::async_read(&s.env, &s.handle, k).await; + let s: db::Interface = db::DatabaseEnvironment::async_open("test").await; + let v = db::DatabaseEnvironment::read(&s.env, &s.handle, k).await; Authorization::from_db(String::from(k), v) } - async fn cleanup(k: &String) { + async fn cleanup(k: &String) -> Result<(), MdbError>{ tokio::time::sleep(std::time::Duration::from_secs(1)).await; - let s = db::Interface::async_open().await; - db::Interface::async_delete(&s.env, &s.handle, k).await; + let s = db::DatabaseEnvironment::open("test").await?; + db::DatabaseEnvironment::delete(&s.env, &s.handle?, k).await; } #[test] diff --git a/neveko-core/src/contact.rs b/neveko-core/src/contact.rs index 7cc26a6..c2ce722 100644 --- a/neveko-core/src/contact.rs +++ b/neveko-core/src/contact.rs @@ -8,6 +8,7 @@ use crate::{ reqres, utils, }; +use kn0sys_lmdb_rs::MdbError; use log::{ debug, error, @@ -21,22 +22,8 @@ pub const NEVEKO_VENDOR_ENABLED: &str = "NEVEKO_VENDOR_ENABLED"; pub const NEVEKO_VENDOR_MODE_OFF: &str = "0"; pub const NEVEKO_VENDOR_MODE_ON: &str = "1"; -pub enum Prune { - Full, - Pruned, -} - -impl Prune { - pub fn value(&self) -> u32 { - match *self { - Prune::Full => 0, - Prune::Pruned => 1, - } - } -} - /// Create a new contact -pub async fn create(c: &Json) -> Contact { +pub async fn create(c: &Json) -> Result { let f_cid: String = format!("{}{}", crate::CONTACT_DB_KEY, utils::generate_rnd()); info!("creating contact: {}", f_cid); let new_contact = Contact { @@ -48,80 +35,95 @@ pub async fn create(c: &Json) -> Contact { }; let is_valid = validate_contact(c).await; if !is_valid { - return Default::default(); + log::error!("invalid contact"); + return Ok(Default::default()); } debug!("insert contact: {:?}", &new_contact); - let s = db::Interface::open(); + let env = utils::get_release_env(); + let s = db::DatabaseEnvironment::open(&env.value())?; let k = &new_contact.cid; - db::Interface::write(&s.env, &s.handle, k, &Contact::to_db(&new_contact)); + let v = bincode::serialize(&new_contact).unwrap_or_default(); + db::write_chunks(&s.env, &s.handle?, k.as_bytes(), &v); // in order to retrieve all contact, write keys to with cl let list_key = crate::CONTACT_LIST_DB_KEY; - let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key)); - if r == utils::empty_string() { + let str_lk = String::from(list_key); + let s = db::DatabaseEnvironment::open(&env.value())?; + let lk_bytes = str_lk.as_bytes(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &lk_bytes.to_vec())?; + if r.is_empty() { debug!("creating contact index"); } - let contact_list = [r, String::from(&f_cid)].join(","); + let old: String = bincode::deserialize(&r[..]).unwrap_or_default(); + let contact_list = [old, String::from(&f_cid)].join(","); debug!( "writing contact index {} for key {}", contact_list, list_key ); - db::Interface::write(&s.env, &s.handle, &String::from(list_key), &contact_list); - new_contact + let s = db::DatabaseEnvironment::open(&env.value())?; + db::write_chunks(&s.env, &s.handle?, list_key.as_bytes(), &contact_list.as_bytes()); + Ok(new_contact) } /// Contact lookup -pub fn find(cid: &String) -> Contact { - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, &String::from(cid)); - if r == utils::empty_string() { +pub fn find(cid: &String) -> Result { + let env = utils::get_release_env(); + let s = db::DatabaseEnvironment::open(&env.value())?; + let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &cid.as_bytes().to_vec())?; + if r.is_empty() { error!("contact not found"); - return Default::default(); + return Err(MdbError::NotFound); } - Contact::from_db(String::from(cid), r) + let result: Contact = bincode::deserialize(&r[..]).unwrap_or_default(); + Ok(result) } /// Contact lookup -pub fn find_by_i2p_address(i2p_address: &String) -> Contact { - let contacts = find_all(); +pub fn find_by_i2p_address(i2p_address: &String) -> Result { + let contacts = find_all()?; for c in contacts { if c.i2p_address == *i2p_address { - return c; + return Ok(c); } } - Default::default() + Err(MdbError::NotFound) } /// Contact deletion -pub fn delete(cid: &String) { - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, &String::from(cid)); - if r == utils::empty_string() { +pub fn delete(cid: &String) -> Result<(), MdbError> { + let env = utils::get_release_env(); + let s = db::DatabaseEnvironment::open(&env.value())?; + let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &cid.as_bytes().to_vec())?; + if r.is_empty() { error!("contact not found"); - return; + return Err(MdbError::NotFound); } - db::Interface::delete(&s.env, &s.handle, cid); + let s = db::DatabaseEnvironment::open(&env.value())?; + db::DatabaseEnvironment::delete(&s.env, &s.handle?, cid.as_bytes()); + Ok(()) } /// All contact lookup -pub fn find_all() -> Vec { +pub fn find_all() -> Result, MdbError> { info!("looking up all contacts"); - let s = db::Interface::open(); + let env = utils::get_release_env(); + let s = db::DatabaseEnvironment::open(&env.value())?; let list_key = crate::CONTACT_LIST_DB_KEY; - let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key)); - if r == utils::empty_string() { + let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &list_key.as_bytes().to_vec())?; + if r.is_empty() { error!("contact index not found"); - return Default::default(); + return Err(MdbError::NotFound); } - let v_cid = r.split(","); + let str_r: String = bincode::deserialize(&r[..]).unwrap_or_default(); + let v_cid = str_r.split(","); let v: Vec = v_cid.map(String::from).collect(); let mut contacts: Vec = Vec::new(); for id in v { - if id != utils::empty_string() { - let contact: Contact = find(&id); + if !id.is_empty() { + let contact: Contact = find(&id)?; contacts.push(contact); } } - contacts + Ok(contacts) } async fn validate_contact(j: &Json) -> bool { @@ -140,10 +142,12 @@ async fn validate_contact(j: &Json) -> bool { } /// Send our information -pub async fn share() -> Contact { - let s = db::Interface::async_open().await; - let r = db::Interface::async_read(&s.env, &s.handle, NEVEKO_VENDOR_ENABLED).await; - let is_vendor = r == NEVEKO_VENDOR_MODE_ON; +pub async fn share() -> Result { + let env = utils::get_release_env(); + let s = db::DatabaseEnvironment::open(&env.value())?; + let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &NEVEKO_VENDOR_ENABLED.as_bytes().to_vec())?; + let str_r: String = bincode::deserialize(&r[..]).unwrap_or_default(); + let is_vendor = str_r == NEVEKO_VENDOR_MODE_ON; let wallet_name = String::from(crate::APP_NAME); let wallet_password = std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password")); @@ -153,22 +157,22 @@ pub async fn share() -> Contact { let nmpk = utils::get_nmpk(); let i2p_address = i2p::get_destination(None); let xmr_address = m_address.result.address; - Contact { - cid: utils::empty_string(), + Ok(Contact { + cid: String::new(), nmpk, i2p_address, is_vendor, xmr_address, - } + }) } -pub fn exists(from: &String) -> bool { - let all = find_all(); +pub fn exists(from: &String) -> Result { + let all = find_all()?; let mut addresses: Vec = Vec::new(); for c in all { addresses.push(c.i2p_address); } - addresses.contains(from) + Ok(addresses.contains(from)) } /// Get invoice for jwp creation @@ -228,10 +232,10 @@ pub async fn add_contact_request(contact: String) -> Result, } -impl Interface { - /// Instantiation of ```Environment``` and ```DbHandle``` - pub fn open() -> Self { - info!("excecuting lmdb open"); - let release_env = utils::get_release_env(); - let file_path = format!( - "/home/{}/.{}/", - std::env::var("USER").unwrap_or(String::from("user")), - crate::APP_NAME, - ); - let mut env_str: &str = "test-lmdb"; - if release_env != utils::ReleaseEnvironment::Development { - env_str = "lmdb"; - }; - let env = EnvBuilder::new() - // increase map size for writing the multisig txset - .map_size(crate::LMDB_MAPSIZE) - .open(format!("{}/{}", file_path, env_str), 0o777) - .unwrap_or_else(|_| panic!("could not open LMDB at {}", file_path)); - let handle = env.get_default_db(DbFlags::empty()).unwrap(); - Interface { env, handle } - } - pub async fn async_open() -> Self { - info!("excecuting lmdb async open"); - tokio::time::sleep(std::time::Duration::from_micros(1)).await; - self::Interface::open() - } - /// Write a key-value to LMDB. NEVEKO does not currently support +impl DatabaseEnvironment { + /// Opens environment in specified path. The map size defaults to 20 percent /// - /// writing multiple key value pairs. - pub fn write(e: &Environment, h: &DbHandle, k: &str, v: &str) { + /// of available memory and can be set via the `LMDB_MAP_SIZE` environment variable. + /// + /// The path of the user can be set with `LMDB_USER`. + pub fn open(env: &str) -> Result { + let s = System::new_all(); + let default_map_size: u64 = + (s.available_memory() as f32 * MAP_SIZE_MEMORY_RATIO).floor() as u64; + let env_map_size: u64 = match std::env::var("LMDB_MAP_SIZE") { + Err(_) => default_map_size, + Ok(size) => size.parse::().unwrap_or(default_map_size), + }; + info!("setting lmdb map size to: {}", env_map_size); + let user: String = match std::env::var("LMDB_USER") { + Err(_) => std::env::var("USER").unwrap_or(String::from("user")), + Ok(user) => user, + }; + info!("$LMDB_USER={}", user); + info!("excecuting lmdb open"); + let file_path: String = format!("/home/{}/.{}/", user, "valentinus"); + let env: Environment = EnvBuilder::new() + .map_size(env_map_size) + .open(format!("{}/{}", file_path, env), 0o777) + .unwrap_or_else(|_| panic!("could not open LMDB at {}", file_path)); + let default: Result = env.get_default_db(DbFlags::empty()); + if default.is_err() { + panic!("could not set db handle") + } + let handle: DbHandle = default?; + Ok(DatabaseEnvironment { + env, + handle: Ok(handle), + }) + } + /// Write a key/value pair to the database. It is not possible to + /// + /// write with empty keys. + fn write(e: &Environment, h: &DbHandle, k: &Vec, v: &Vec) -> Result<(), MdbError> { info!("excecuting lmdb write"); - // don't try and write empty keys if k.is_empty() { error!("can't write empty key"); - return; + return Err(MdbError::NotFound); } - let txn = e.new_transaction().unwrap(); + let new_txn = e.new_transaction()?; + let txn = new_txn; { - // get a database bound to this transaction - let db = txn.bind(h); - let pair = [(k, v)]; + let db: Database = txn.bind(h); + let pair: Vec<(&Vec, &Vec)> = vec![(k, v)]; for &(key, value) in pair.iter() { - db.set(&key, &value).unwrap(); + db.set(key, value) + .unwrap_or_else(|_| error!("failed to set key: {:?}", k)); } } - if txn.commit().is_err() { error!("failed to commit!") } + txn.commit() } - pub async fn async_write(e: &Environment, h: &DbHandle, k: &str, v: &str) { - info!("excecuting lmdb async write"); - tokio::time::sleep(std::time::Duration::from_micros(1)).await; - self::Interface::write(e, h, k, v) - } - /// Read a value from LMDB by passing the key as a static + /// Read key from the database. If it doesn't exist then /// - /// string. If the value does not exist an empty string is + /// an empty vector will be returned. Treat all empty vectors /// - /// returned. NEVEKO does not currently support duplicate keys. - pub fn read(e: &Environment, h: &DbHandle, k: &str) -> String { + /// from database operations as failures. + pub fn read(e: &Environment, h: &DbHandle, k: &Vec) -> Result, MdbError> { info!("excecuting lmdb read"); // don't try and read empty keys if k.is_empty() { error!("can't read empty key"); - return utils::empty_string(); + return Err(MdbError::NotFound); + } + let get_reader = e.get_reader(); + let reader: ReadonlyTransaction = get_reader?; + let db: Database = reader.bind(h); + let mut result: Vec = Vec::new(); + for num_writes in 0..usize::MAX { + let mut new_key: Vec = k.to_vec(); + let mut key_count: Vec = (num_writes).to_be_bytes().to_vec(); + new_key.append(&mut key_count); + let mut r = db.get::>(&new_key).unwrap_or_default(); + if r.is_empty() { + break; + } + result.append(&mut r); } - let reader = e.get_reader().unwrap(); - let db = reader.bind(h); - let value = db.get::<&str>(&k).unwrap_or(""); - let r = String::from(value); { - if r == utils::empty_string() { - debug!("Failed to read from db.") + if result.is_empty() { + error!("failed to read key {:?} from db", k); } } - r + Ok(result) } - pub async fn async_read(e: &Environment, h: &DbHandle, k: &str) -> String { - info!("excecuting lmdb async read"); - tokio::time::sleep(std::time::Duration::from_micros(1)).await; - self::Interface::read(e, h, k) - } - /// Delete a value from LMDB by passing the key as a - /// - /// static string. If the value does not exist then an - /// - /// error will be logged. - pub fn delete(e: &Environment, h: &DbHandle, k: &str) { + /// Deletes a key/value pair from the database + pub fn delete(e: &Environment, h: &DbHandle, k: &[u8]) -> Result<(), MdbError> { info!("excecuting lmdb delete"); - // don't try and delete empty keys if k.is_empty() { error!("can't delete empty key"); - return; + return Err(MdbError::NotFound); } - let txn = e.new_transaction().unwrap(); + let new_txn = e.new_transaction(); + let txn = new_txn?; + let get_reader = e.get_reader(); + let reader: ReadonlyTransaction = get_reader?; + let db_reader: Database = reader.bind(h); { - // get a database bound to this transaction let db = txn.bind(h); - db.del(&k).unwrap_or_else(|_| error!("failed to delete")); + + for num_writes in 0..usize::MAX { + let mut new_key: Vec = k.to_vec(); + let mut key_count: Vec = num_writes.to_be_bytes().to_vec(); + new_key.append(&mut key_count); + let r = db_reader.get::>(&new_key).unwrap_or_default(); + if r.is_empty() { + break; + } + db.del(&new_key) + .unwrap_or_else(|_| error!("failed to delete")); + } } - if txn.commit().is_err() { error!("failed to commit!") } + txn.commit() } - pub async fn async_delete(e: &Environment, h: &DbHandle, k: &str) { - info!("excecuting lmdb async delete"); - tokio::time::sleep(std::time::Duration::from_micros(1)).await; - self::Interface::delete(e, h, k) +} + +/// Write chunks to the database. This function uses one percent +/// +/// of the map size . Setting the map_size to a low value +/// +/// will cause degraded performance. +pub fn write_chunks(e: &Environment, h: &DbHandle, k: &[u8], v: &[u8]) -> Result<(), MdbError> { + let s = System::new_all(); + let chunk_size = (s.available_memory() as f32 * CHUNK_SIZE_MEMORY_RATIO) as usize; + let mut writes: usize = 1; + let mut index: usize = 0; + let length = v.len(); + loop { + let mut old_key: Vec = k.to_vec(); + let mut append: Vec = (writes - 1).to_be_bytes().to_vec(); + old_key.append(&mut append); + if length > chunk_size && (length - index > chunk_size) { + // write chunks until the last value which is smaller than chunk_size + let _ = DatabaseEnvironment::write( + e, + h, + &old_key, + &v[index..(chunk_size * writes)].to_vec(), + ); + index += chunk_size; + writes += 1; + } else { + DatabaseEnvironment::write(e, h, &old_key, &v[index..length].to_vec())?; + return Ok(()); + } } } // Tests //------------------------------------------------------------------------------- - #[cfg(test)] mod tests { + use super::*; - #[test] - fn async_write_and_read_test() { - // run and async cleanup so the test doesn't fail when deleting test data - use tokio::runtime::Runtime; - let rt = Runtime::new().expect("Unable to create Runtime for test"); - let _enter = rt.enter(); - tokio::spawn(async move { - let s = Interface::async_open().await; - let k = "async-test-key"; - let v = "async-test-value"; - Interface::async_write(&s.env, &s.handle, k, v).await; - let expected = String::from(v); - let actual = Interface::async_read(&s.env, &s.handle, k).await; - assert_eq!(expected, actual); - Interface::async_delete(&s.env, &s.handle, &k).await; - }); - } + use rand::RngCore; #[test] - fn async_write_and_delete_test() { - // run and async cleanup so the test doesn't fail when deleting test data - use tokio::runtime::Runtime; - let rt = Runtime::new().expect("Unable to create Runtime for test"); - let _enter = rt.enter(); - tokio::spawn(async move { - let s = Interface::open(); - let k = "write_and_delete_test_test-key"; - let v = "write_and_delete_test_test-value"; - Interface::async_write(&s.env, &s.handle, k, v).await; - let expected = utils::empty_string(); - Interface::async_delete(&s.env, &s.handle, &k).await; - let actual = Interface::async_read(&s.env, &s.handle, k).await; - assert_eq!(expected, actual); - }); + fn environment_test() -> Result<(), MdbError> { + let db = DatabaseEnvironment::open("10-mb-test")?; + const DATA_SIZE_10MB: usize = 10000000; + let mut data = vec![0u8; DATA_SIZE_10MB]; + rand::thread_rng().fill_bytes(&mut data); + let k = "test-key".as_bytes(); + let expected = &data.to_vec(); + write_chunks(&db.env, &db.handle?, &Vec::from(k), &Vec::from(data))?; + let db = DatabaseEnvironment::open("10-mb-test")?; + let actual = DatabaseEnvironment::read(&db.env, &db.handle?, &Vec::from(k)); + assert_eq!(expected.to_vec(), actual?); + let db = DatabaseEnvironment::open("10-mb-test")?; + let _ = DatabaseEnvironment::delete(&db.env, &db.handle?, &Vec::from(k)); + let db = DatabaseEnvironment::open("100-mb-test")?; + const DATA_SIZE_100MB: usize = 100000000; + let mut data = vec![0u8; DATA_SIZE_100MB]; + rand::thread_rng().fill_bytes(&mut data); + let k = "test-key".as_bytes(); + let expected = &data.to_vec(); + write_chunks(&db.env, &db.handle?, &Vec::from(k), &Vec::from(data))?; + let db = DatabaseEnvironment::open("100-mb-test")?; + let actual = DatabaseEnvironment::read(&db.env, &db.handle?, &Vec::from(k)); + assert_eq!(expected.to_vec(), actual?); + let db = DatabaseEnvironment::open("100-mb-test")?; + let _ = DatabaseEnvironment::delete(&db.env, &db.handle?, &Vec::from(k)); + Ok(()) } } diff --git a/neveko-core/src/dispute.rs b/neveko-core/src/dispute.rs index f7376db..795b615 100644 --- a/neveko-core/src/dispute.rs +++ b/neveko-core/src/dispute.rs @@ -26,13 +26,13 @@ pub fn create(d: Json) -> Dispute { tx_set: String::from(&d.tx_set), }; debug!("insert dispute: {:?}", &d); - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let k = &d.did; - db::Interface::write(&s.env, &s.handle, k, &Dispute::to_db(&new_dispute)); + db::DatabaseEnvironment::write(&s.env, &s.handle, k, &Dispute::to_db(&new_dispute)); // in order to retrieve all orders, write keys to with dl let list_key = crate::DISPUTE_LIST_DB_KEY; - let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key)); - if r == utils::empty_string() { + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key)); + if r.is_empty() { debug!("creating dispute index"); } let dispute_list = [String::from(&r), String::from(&f_did)].join(","); @@ -40,7 +40,7 @@ pub fn create(d: Json) -> Dispute { "writing dispute index {} for id: {}", dispute_list, list_key ); - db::Interface::write(&s.env, &s.handle, &String::from(list_key), &dispute_list); + db::DatabaseEnvironment::write(&s.env, &s.handle, &String::from(list_key), &dispute_list); // restart the dispute aut-settle thread let cleared = is_dispute_clear(r); if !cleared { @@ -52,9 +52,9 @@ pub fn create(d: Json) -> Dispute { /// Dispute lookup pub fn find(did: &String) -> Dispute { - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, &String::from(did)); - if r == utils::empty_string() { + let s = db::DatabaseEnvironment::open(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(did)); + if r.is_empty() { error!("dispute not found"); return Default::default(); } @@ -63,10 +63,10 @@ pub fn find(did: &String) -> Dispute { /// Lookup all disputes pub fn find_all() -> Vec { - let d_s = db::Interface::open(); + let d_s = db::DatabaseEnvironment::open(); let d_list_key = crate::DISPUTE_LIST_DB_KEY; - let d_r = db::Interface::read(&d_s.env, &d_s.handle, &String::from(d_list_key)); - if d_r == utils::empty_string() { + let d_r = db::DatabaseEnvironment::read(&d_s.env, &d_s.handle, &String::from(d_list_key)); + if d_r.is_empty() { error!("dispute index not found"); } let d_v_did = d_r.split(","); @@ -74,7 +74,7 @@ pub fn find_all() -> Vec { let mut disputes: Vec = Vec::new(); for o in d_v { let dispute: Dispute = find(&o); - if dispute.did != utils::empty_string() { + if !dispute.did.is_empty() { disputes.push(dispute); } } @@ -83,13 +83,13 @@ pub fn find_all() -> Vec { /// Dispute deletion pub fn delete(did: &String) { - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, &String::from(did)); - if r == utils::empty_string() { + let s = db::DatabaseEnvironment::open(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(did)); + if r.is_empty() { error!("dispute not found"); return Default::default(); } - db::Interface::delete(&s.env, &s.handle, &String::from(did)) + db::DatabaseEnvironment::delete(&s.env, &s.handle, &String::from(did)) } /// Triggered on DISPUTE_LAST_CHECK_DB_KEY. @@ -105,10 +105,10 @@ pub async fn settle_dispute() { loop { debug!("running dispute auto-settle thread"); tick.recv().unwrap(); - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let list_key = crate::DISPUTE_LIST_DB_KEY; - let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key)); - if r == utils::empty_string() { + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key)); + if r.is_empty() { info!("dispute index not found"); } let v_mid = r.split(","); @@ -118,17 +118,17 @@ pub async fn settle_dispute() { if cleared { // index was created but cleared info!("terminating dispute auto-settle thread"); - db::Interface::delete(&s.env, &s.handle, list_key); + db::DatabaseEnvironment::delete(&s.env, &s.handle, list_key); return; } for d in d_vec { let dispute: Dispute = find(&d); - if dispute.did != utils::empty_string() { + if !dispute.did.is_empty() { let now = chrono::offset::Utc::now().timestamp(); let settle_date = dispute.created + crate::DISPUTE_AUTO_SETTLE as i64; if settle_date > now { let wallet_name = dispute.orid; - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::open_wallet(&wallet_name, &wallet_password).await; let signed = monero::sign_multisig(dispute.tx_set).await; let submit = monero::submit_multisig(signed.result.tx_data_hex).await; @@ -152,8 +152,8 @@ fn is_dispute_clear(r: String) -> bool { let limit = v.len() <= 1; if !limit { v.len() >= 2 - && v[v.len() - 1] == utils::empty_string() - && v[0] == utils::empty_string() + && v[v.len() - 1].is_empty() + && v[0].is_empty() } else { limit } @@ -162,10 +162,10 @@ fn is_dispute_clear(r: String) -> bool { /// clear dispute from index fn remove_from_auto_settle(did: String) { info!("removing id {} from disputes", &did); - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let list_key = crate::DISPUTE_LIST_DB_KEY; - let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key)); - if r == utils::empty_string() { + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key)); + if r.is_empty() { debug!("dispute list index is empty"); } let pre_v_fts = r.split(","); @@ -174,7 +174,7 @@ fn remove_from_auto_settle(did: String) { if s != &did { String::from(s) } else { - utils::empty_string() + String::new() } }) .collect(); @@ -183,7 +183,7 @@ fn remove_from_auto_settle(did: String) { "writing dipsute index {} for id: {}", dispute_list, list_key ); - db::Interface::write(&s.env, &s.handle, &String::from(list_key), &dispute_list); + db::DatabaseEnvironment::write(&s.env, &s.handle, &String::from(list_key), &dispute_list); } /// Executes POST /market/dispute/create @@ -229,9 +229,9 @@ async fn transmit_dispute_request( /// can be executed from the gui. pub async fn trigger_dispute_request(contact: &String, dispute: &Dispute) -> Dispute { info!("executing trigger_dispute_request"); - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact); - let jwp = db::Interface::async_read(&s.env, &s.handle, &k).await; + let jwp = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &k).await; let dispute = transmit_dispute_request(contact, &jwp, dispute).await; // handle a failure to create dispute if dispute.is_err() { diff --git a/neveko-core/src/error.rs b/neveko-core/src/error.rs new file mode 100644 index 0000000..db6edd1 --- /dev/null +++ b/neveko-core/src/error.rs @@ -0,0 +1,12 @@ +use kn0sys_lmdb_rs::MdbError; +use thiserror::Error; + +#[derive(Debug, Error)] +#[error("neveko error. See logs for more info.")] +pub enum NevekoError { + ///J4I2PRS(J4RsError), + Database(MdbError), + MoneroRpc, + MoneroDaemon, + Unknown, +} \ No newline at end of file diff --git a/neveko-core/src/i2p.rs b/neveko-core/src/i2p.rs index 08efd61..33d3b3c 100644 --- a/neveko-core/src/i2p.rs +++ b/neveko-core/src/i2p.rs @@ -65,7 +65,7 @@ async fn find_tunnels() { "/home/{}/.i2p-zero/config/tunnels.json", env::var("USER").unwrap_or(String::from("user")) ); - let contents = fs::read_to_string(file_path).unwrap_or(utils::empty_string()); + let contents = fs::read_to_string(file_path).unwrap_or(String::new()); debug!("i2p tunnels: {}", contents); let has_app_tunnel = contents.contains(&format!("{}", app_port)); let proxy_port = get_i2p_proxy_port(); @@ -209,11 +209,11 @@ pub fn get_destination(port: Option) -> String { ); let args = args::Args::parse(); let is_advanced_mode = - std::env::var(crate::NEVEKO_I2P_ADVANCED_MODE).unwrap_or(utils::empty_string()); + std::env::var(crate::NEVEKO_I2P_ADVANCED_MODE).unwrap_or(String::new()); if args.i2p_advanced || is_advanced_mode == *"1" { let advanced_tunnel = - std::env::var(crate::NEVEKO_I2P_TUNNELS_JSON).unwrap_or(utils::empty_string()); - let manual_tunnel = if advanced_tunnel == utils::empty_string() { + std::env::var(crate::NEVEKO_I2P_TUNNELS_JSON).unwrap_or(String::new()); + let manual_tunnel = if advanced_tunnel.is_empty() { args.i2p_tunnels_json } else { advanced_tunnel @@ -223,21 +223,21 @@ pub fn get_destination(port: Option) -> String { // Don't panic if i2p-zero isn't installed let contents = match fs::read_to_string(file_path) { Ok(file) => file, - _ => utils::empty_string(), + _ => String::new(), }; - if contents != utils::empty_string() { + if !contents.is_empty() { let input = contents.to_string(); let j: Tunnels = serde_json::from_str(&input).unwrap_or(Default::default()); - let mut destination: String = utils::empty_string(); + let mut destination: String = String::new(); let tunnels: Vec = j.tunnels; for tunnel in tunnels { if tunnel.port == format!("{}", port.unwrap_or(utils::get_app_port())) { - destination = tunnel.dest.unwrap_or(utils::empty_string()); + destination = tunnel.dest.unwrap_or(String::new()); } } return destination; } - utils::empty_string() + String::new() } /// Ping the i2p-zero http proxy `tunnel-control http.state ` diff --git a/neveko-core/src/lib.rs b/neveko-core/src/lib.rs index c68b5e4..94d953b 100644 --- a/neveko-core/src/lib.rs +++ b/neveko-core/src/lib.rs @@ -4,6 +4,7 @@ pub mod contact; pub mod neveko25519; pub mod dispute; pub mod db; +pub mod error; pub mod i2p; pub mod message; pub mod models; @@ -60,15 +61,6 @@ pub const MONERO_WALLET_RPC_HOST: &str = "MONERO_WALLET_RPC_HOST"; pub const GUI_REMOTE_NODE: &str = "GUI_REMOTE_NODE"; pub const GUI_SET_REMOTE_NODE: &str = "1"; -/// The latest monero release download -pub const MONERO_RELEASE_VERSION: &str = "monero-linux-x64-v0.18.3.2.tar.bz2"; -pub const MONERO_RELEASE_HASH: &str = - "9dafd70230a7b3a73101b624f3b5f439cc5b84a19b12c17c24e6aab94b678cbb"; -/// The latest i2p-zero release version -pub const I2P_ZERO_RELEASE_VERSION: &str = "v1.21"; -pub const I2P_ZERO_RELEASH_HASH: &str = - "14f34052ad6abb0c24b048816b0ea86b696ae350dd139dd1e90a67ca88e1d07a"; - pub const LMDB_MAPSIZE: u64 = 1024 * 1024 * 1024; pub const I2P_CONNECTIVITY_CHECK_INTERVAL: u32 = 600000; pub const FTS_RETRY_INTERVAL: u32 = 60000; diff --git a/neveko-core/src/message.rs b/neveko-core/src/message.rs index 0b416d7..b9b4c04 100644 --- a/neveko-core/src/message.rs +++ b/neveko-core/src/message.rs @@ -36,22 +36,13 @@ pub enum MessageType { Multisig, } +#[derive(Default)] struct MultisigMessageData { info: String, sub_type: String, orid: String, } -impl Default for MultisigMessageData { - fn default() -> Self { - MultisigMessageData { - info: utils::empty_string(), - sub_type: utils::empty_string(), - orid: utils::empty_string(), - } - } -} - /// Create a new message pub async fn create(m: Json, jwp: String, m_type: MessageType) -> Message { let rnd = utils::generate_rnd(); @@ -76,18 +67,18 @@ pub async fn create(m: Json, jwp: String, m_type: MessageType) -> Messa to: String::from(&m.to), }; debug!("insert message: {:?}", &new_message); - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let k = &new_message.mid; - db::Interface::write(&s.env, &s.handle, k, &Message::to_db(&new_message)); + db::DatabaseEnvironment::write(&s.env, &s.handle, k, &Message::to_db(&new_message)); // in order to retrieve all message, write keys to with ml let list_key = crate::MESSAGE_LIST_DB_KEY; - let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key)); - if r == utils::empty_string() { + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key)); + if r.is_empty() { debug!("creating message index"); } let msg_list = [r, String::from(&f_mid)].join(","); debug!("writing message index {} for id: {}", msg_list, list_key); - db::Interface::write(&s.env, &s.handle, &String::from(list_key), &msg_list); + db::DatabaseEnvironment::write(&s.env, &s.handle, &String::from(list_key), &msg_list); info!("attempting to send message"); let send = send_message(&new_message, &jwp, m_type).await; send.unwrap(); @@ -116,25 +107,25 @@ pub async fn rx(m: Json) { to: String::from(&m.to), }; debug!("insert message: {:?}", &new_message); - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let k = &new_message.mid; - db::Interface::write(&s.env, &s.handle, k, &Message::to_db(&new_message)); + db::DatabaseEnvironment::write(&s.env, &s.handle, k, &Message::to_db(&new_message)); // in order to retrieve all message, write keys to with rx let list_key = crate::RX_MESSAGE_DB_KEY; - let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key)); - if r == utils::empty_string() { + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key)); + if r.is_empty() { debug!("creating message index"); } let msg_list = [r, String::from(&f_mid)].join(","); debug!("writing message index {} for {}", msg_list, list_key); - db::Interface::write(&s.env, &s.handle, &String::from(list_key), &msg_list); + db::DatabaseEnvironment::write(&s.env, &s.handle, &String::from(list_key), &msg_list); } /// Parse the multisig message type and info async fn parse_multisig_message(mid: String) -> MultisigMessageData { let d: reqres::DecipheredMessageBody = decipher_body(mid).await; let mut bytes = hex::decode(d.body.into_bytes()).unwrap_or_default(); - let decoded = String::from_utf8(bytes).unwrap_or(utils::empty_string()); + let decoded = String::from_utf8(bytes).unwrap_or(String::new()); let values = decoded.split(":"); let mut v: Vec = values.map(String::from).collect(); if v.len() != VALID_MSIG_MSG_LENGTH { @@ -176,9 +167,9 @@ async fn parse_multisig_message(mid: String) -> MultisigMessageData { /// ```rust /// // lookup prepare info for vendor /// use neveko_core::db; -/// let s = db::Interface::open(); +/// let s = db::DatabaseEnvironment::open(); /// let key = "prepare-o123-test.b32.i2p"; -/// let info_str = db::Interface::read(&s.env, &s.handle, &key); +/// let info_str = db::DatabaseEnvironment::read(&s.env, &s.handle, &key); /// ``` pub async fn rx_multisig(m: Json) { // make sure the message isn't something strange @@ -200,13 +191,13 @@ pub async fn rx_multisig(m: Json) { created: chrono::offset::Utc::now().timestamp(), to: String::from(&m.to), }; - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; let k = &new_message.mid; - db::Interface::async_write(&s.env, &s.handle, k, &Message::to_db(&new_message)).await; + db::DatabaseEnvironment::async_write(&s.env, &s.handle, k, &Message::to_db(&new_message)).await; // in order to retrieve all msig messages, write keys to with msigl let list_key = crate::MSIG_MESSAGE_LIST_DB_KEY; - let r = db::Interface::async_read(&s.env, &s.handle, &String::from(list_key)).await; - if r == utils::empty_string() { + let r = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &String::from(list_key)).await; + if r.is_empty() { debug!("creating msig message index"); } let msg_list = [r, String::from(&f_mid)].join(","); @@ -214,7 +205,7 @@ pub async fn rx_multisig(m: Json) { "writing msig message index {} for id: {}", msg_list, list_key ); - db::Interface::async_write(&s.env, &s.handle, &String::from(list_key), &msg_list).await; + db::DatabaseEnvironment::async_write(&s.env, &s.handle, &String::from(list_key), &msg_list).await; let data: MultisigMessageData = parse_multisig_message(new_message.mid).await; debug!( "writing multisig message type {} for order {}", @@ -222,16 +213,16 @@ pub async fn rx_multisig(m: Json) { ); // lookup msig message data by {type}-{order id}-{contact .b32.i2p address} // store info as {a_info}:{a_info (optional)} - let s_msig = db::Interface::async_open().await; + let s_msig = db::DatabaseEnvironment::async_open().await; let msig_key = format!("{}-{}-{}", &data.sub_type, &data.orid, &m.from); - db::Interface::async_write(&s_msig.env, &s_msig.handle, &msig_key, &data.info).await; + db::DatabaseEnvironment::async_write(&s_msig.env, &s_msig.handle, &msig_key, &data.info).await; } /// Message lookup pub fn find(mid: &String) -> Message { - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, &String::from(mid)); - if r == utils::empty_string() { + let s = db::DatabaseEnvironment::open(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(mid)); + if r.is_empty() { error!("message not found"); return Default::default(); } @@ -240,10 +231,10 @@ pub fn find(mid: &String) -> Message { /// Message lookup pub fn find_all() -> Vec { - let i_s = db::Interface::open(); + let i_s = db::DatabaseEnvironment::open(); let i_list_key = crate::MESSAGE_LIST_DB_KEY; - let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key)); - if i_r == utils::empty_string() { + let i_r = db::DatabaseEnvironment::read(&i_s.env, &i_s.handle, &String::from(i_list_key)); + if i_r.is_empty() { error!("message index not found"); } let i_v_mid = i_r.split(","); @@ -251,21 +242,21 @@ pub fn find_all() -> Vec { let mut messages: Vec = Vec::new(); for m in i_v { let message: Message = find(&m); - if message.mid != utils::empty_string() { + if !message.mid.is_empty() { messages.push(message); } } let o_list_key = crate::RX_MESSAGE_DB_KEY; - let o_s = db::Interface::open(); - let o_r = db::Interface::read(&o_s.env, &o_s.handle, &String::from(o_list_key)); - if o_r == utils::empty_string() { + let o_s = db::DatabaseEnvironment::open(); + let o_r = db::DatabaseEnvironment::read(&o_s.env, &o_s.handle, &String::from(o_list_key)); + if o_r.is_empty() { error!("message index not found"); } let o_v_mid = o_r.split(","); let o_v: Vec = o_v_mid.map(String::from).collect(); for m in o_v { let message: Message = find(&m); - if message.mid != utils::empty_string() { + if !message.mid.is_empty() { messages.push(message); } } @@ -326,8 +317,8 @@ pub async fn decipher_body(mid: String) -> reqres::DecipheredMessageBody { /// Message deletion pub fn delete(mid: &String) { - let s = db::Interface::open(); - db::Interface::delete(&s.env, &s.handle, &String::from(mid)); + let s = db::DatabaseEnvironment::open(); + db::DatabaseEnvironment::delete(&s.env, &s.handle, &String::from(mid)); } /// ping the contact health check over i2p @@ -365,11 +356,11 @@ async fn is_contact_online(contact: &String, jwp: String) -> Result = v_mid.map(String::from).collect(); debug!("fts contents: {:#?}", v); @@ -397,11 +388,11 @@ async fn send_to_retry(mid: String) { /// clear fts message from index fn remove_from_fts(mid: String) { info!("removing id {} from fts", &mid); - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); // in order to retrieve FTS (failed-to-send), write keys to with fts let list_key = crate::FTS_DB_KEY; - let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key)); - if r == utils::empty_string() { + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key)); + if r.is_empty() { debug!("fts is empty"); } let pre_v_fts = r.split(","); @@ -410,7 +401,7 @@ fn remove_from_fts(mid: String) { if s != &mid { String::from(s) } else { - utils::empty_string() + String::new() } }) .collect(); @@ -419,7 +410,7 @@ fn remove_from_fts(mid: String) { "writing fts message index {} for id: {}", msg_list, list_key ); - db::Interface::write(&s.env, &s.handle, &String::from(list_key), &msg_list); + db::DatabaseEnvironment::write(&s.env, &s.handle, &String::from(list_key), &msg_list); } /// Triggered on app startup, retries to send fts every minute @@ -432,10 +423,10 @@ pub async fn retry_fts() { loop { debug!("running retry failed-to-send thread"); tick.recv().unwrap(); - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let list_key = crate::FTS_DB_KEY; - let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key)); - if r == utils::empty_string() { + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key)); + if r.is_empty() { info!("fts message index not found"); break; // terminate fts if no message to send } @@ -446,17 +437,17 @@ pub async fn retry_fts() { if cleared { // index was created but cleared info!("terminating retry fts thread"); - db::Interface::delete(&s.env, &s.handle, list_key); + db::DatabaseEnvironment::delete(&s.env, &s.handle, list_key); break; } for m in v { let message: Message = find(&m); - if message.mid != utils::empty_string() { - let s = db::Interface::open(); + if !message.mid.is_empty() { + let s = db::DatabaseEnvironment::open(); // get jwp from db let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &message.to); - let jwp = db::Interface::read(&s.env, &s.handle, &k); - if jwp != utils::empty_string() { + let jwp = db::DatabaseEnvironment::read(&s.env, &s.handle, &k); + if !jwp.is_empty() { let m_type = if message.mid.contains("msig") { MessageType::Multisig } else { @@ -487,8 +478,8 @@ fn is_fts_clear(r: String) -> bool { let limit = v.len() <= 1; if !limit { v.len() >= 2 - && v[v.len() - 1] == utils::empty_string() - && v[0] == utils::empty_string() + && v[v.len() - 1].is_empty() + && v[0].is_empty() } else { limit } @@ -498,13 +489,13 @@ fn is_fts_clear(r: String) -> bool { /// /// `prepare_multisig_info` method. pub async fn send_prepare_info(orid: &String, contact: &String) { - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let wallet_name = String::from(orid); - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::open_wallet(&wallet_name, &wallet_password).await; let prepare_info = monero::prepare_wallet().await; let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact); - let jwp = db::Interface::read(&s.env, &s.handle, &k); + let jwp = db::DatabaseEnvironment::read(&s.env, &s.handle, &k); let body_str = format!( "{}:{}:{}", PREPARE_MSIG, orid, &prepare_info.result.multisig_info @@ -524,13 +515,13 @@ pub async fn send_prepare_info(orid: &String, contact: &String) { /// /// `make_multisig_info` method. pub async fn send_make_info(orid: &String, contact: &String, info: Vec) { - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let wallet_name = String::from(orid); - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::open_wallet(&wallet_name, &wallet_password).await; let make_info = monero::make_wallet(info).await; let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact); - let jwp = db::Interface::read(&s.env, &s.handle, &k); + let jwp = db::DatabaseEnvironment::read(&s.env, &s.handle, &k); let body_str = format!("{}:{}:{}", MAKE_MSIG, orid, &make_info.result.multisig_info); let message: Message = Message { body: body_str, @@ -552,13 +543,13 @@ pub async fn send_exchange_info( info: Vec, kex_init: bool, ) { - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let wallet_name = String::from(orid); - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::open_wallet(&wallet_name, &wallet_password).await; let exchange_info = monero::exchange_multisig_keys(false, info, &wallet_password).await; let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact); - let jwp = db::Interface::read(&s.env, &s.handle, &k); + let jwp = db::DatabaseEnvironment::read(&s.env, &s.handle, &k); let mut body_str = format!( "{}:{}:{}", KEX_ONE_MSIG, orid, &exchange_info.result.multisig_info @@ -584,13 +575,13 @@ pub async fn send_exchange_info( /// /// `export_multisig_info` method. pub async fn send_export_info(orid: &String, contact: &String) { - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let wallet_name = String::from(orid); - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::open_wallet(&wallet_name, &wallet_password).await; let exchange_info = monero::export_multisig_info().await; let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact); - let jwp = db::Interface::read(&s.env, &s.handle, &k); + let jwp = db::DatabaseEnvironment::read(&s.env, &s.handle, &k); let body_str = format!("{}:{}:{}", EXPORT_MSIG, orid, &exchange_info.result.info); let message: Message = Message { body: body_str, @@ -610,7 +601,7 @@ pub async fn send_export_info(orid: &String, contact: &String) { /// successfully the order needs to be updated to `MultisigComplete`. pub async fn send_import_info(orid: &String, info: &Vec) { let wallet_name = String::from(orid); - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::open_wallet(&wallet_name, &wallet_password).await; let pre_import = monero::import_multisig_info(info.to_vec()).await; monero::close_wallet(orid, &wallet_password).await; @@ -701,8 +692,8 @@ mod tests { async fn cleanup(k: &String) { tokio::time::sleep(std::time::Duration::from_secs(1)).await; - let s = db::Interface::async_open().await; - db::Interface::async_delete(&s.env, &s.handle, k).await; + let s = db::DatabaseEnvironment::async_open().await; + db::DatabaseEnvironment::async_delete(&s.env, &s.handle, k).await; } #[test] @@ -740,8 +731,8 @@ mod tests { }; let k = "test-key"; tokio::spawn(async move { - let s = db::Interface::async_open().await; - db::Interface::async_write(&s.env, &s.handle, k, &Message::to_db(&expected_message)) + let s = db::DatabaseEnvironment::async_open().await; + db::DatabaseEnvironment::async_write(&s.env, &s.handle, k, &Message::to_db(&expected_message)) .await; let actual_message: Message = find(&String::from(k)); assert_eq!(expected_message.body, actual_message.body); diff --git a/neveko-core/src/models.rs b/neveko-core/src/models.rs index 406327d..e1fe513 100644 --- a/neveko-core/src/models.rs +++ b/neveko-core/src/models.rs @@ -1,13 +1,12 @@ //! Custom object relational mapping (ORM) for structs into LMBD -use crate::utils; use rocket::serde::{ json::Json, Deserialize, Serialize, }; -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Default, Serialize, Deserialize)] #[serde(crate = "rocket::serde")] pub struct Authorization { pub aid: String, @@ -18,47 +17,8 @@ pub struct Authorization { pub xmr_address: String, } -impl Default for Authorization { - fn default() -> Self { - Authorization { - aid: utils::empty_string(), - created: 0, - uid: utils::empty_string(), - rnd: utils::empty_string(), - token: utils::empty_string(), - xmr_address: utils::empty_string(), - } - } -} impl Authorization { - pub fn to_db(a: &Authorization) -> String { - format!( - "{}:{}:{}:{}:{}", - a.created, a.uid, a.rnd, a.token, a.xmr_address - ) - } - pub fn from_db(k: String, v: String) -> Authorization { - let values = v.split(":"); - let mut v: Vec = values.map(String::from).collect(); - let created_str = v.remove(0); - let created = match created_str.parse::() { - Ok(n) => n, - Err(_e) => 0, - }; - let uid = v.remove(0); - let rnd = v.remove(0); - let token = v.remove(0); - let xmr_address = v.remove(0); - Authorization { - aid: k, - created, - uid, - rnd, - token, - xmr_address, - } - } pub fn update_uid(a: Authorization, uid: String) -> Authorization { Authorization { aid: a.aid, @@ -86,7 +46,7 @@ impl Authorization { } } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Default, Serialize, Deserialize)] #[serde(crate = "rocket::serde")] pub struct Contact { pub cid: String, @@ -96,46 +56,7 @@ pub struct Contact { pub nmpk: String, } -impl Default for Contact { - fn default() -> Self { - Contact { - cid: utils::empty_string(), - nmpk: utils::empty_string(), - i2p_address: utils::empty_string(), - is_vendor: false, - xmr_address: utils::empty_string(), - } - } -} - -impl Contact { - pub fn to_db(c: &Contact) -> String { - format!( - "{}!{}!{}!{}", - c.nmpk, c.i2p_address, c.is_vendor, c.xmr_address - ) - } - pub fn from_db(k: String, v: String) -> Contact { - let values = v.split("!"); - let mut v: Vec = values.map(String::from).collect(); - let nmpk = v.remove(0); - let i2p_address = v.remove(0); - let is_vendor = match v.remove(0).parse::() { - Ok(n) => n, - Err(_e) => false, - }; - let xmr_address = v.remove(0); - Contact { - cid: k, - nmpk, - i2p_address, - is_vendor, - xmr_address, - } - } -} - -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Default, Serialize, Deserialize)] #[serde(crate = "rocket::serde")] pub struct Message { pub mid: String, @@ -146,47 +67,7 @@ pub struct Message { pub to: String, } -impl Default for Message { - fn default() -> Self { - Message { - mid: utils::empty_string(), - uid: utils::empty_string(), - body: utils::empty_string(), - created: 0, - from: utils::empty_string(), - to: utils::empty_string(), - } - } -} - -impl Message { - pub fn to_db(m: &Message) -> String { - format!("{}:{}:{}:{}:{}", m.uid, m.body, m.created, m.from, m.to) - } - pub fn from_db(k: String, v: String) -> Message { - let values = v.split(":"); - let mut v: Vec = values.map(String::from).collect(); - let uid = v.remove(0); - let body = v.remove(0); - let created_str = v.remove(0); - let created = match created_str.parse::() { - Ok(n) => n, - Err(_e) => 0, - }; - let from = v.remove(0); - let to = v.remove(0); - Message { - mid: k, - uid, - body, - created, - from, - to, - } - } -} - -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Default, Deserialize, Serialize)] #[serde(crate = "rocket::serde")] pub struct User { pub uid: String, @@ -194,31 +75,7 @@ pub struct User { pub name: String, } -impl Default for User { - fn default() -> Self { - User { - uid: utils::empty_string(), - xmr_address: utils::empty_string(), - name: utils::empty_string(), - } - } -} - impl User { - pub fn to_db(u: &User) -> String { - format!("{}:{}", u.name, u.xmr_address) - } - pub fn from_db(k: String, v: String) -> User { - let values = v.split(":"); - let mut v: Vec = values.map(String::from).collect(); - let name = v.remove(0); - let xmr_address = v.remove(0); - User { - uid: k, - name, - xmr_address, - } - } pub fn update(u: User, name: String) -> User { User { uid: u.uid, @@ -228,7 +85,7 @@ impl User { } } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Default, Deserialize, Serialize)] #[serde(crate = "rocket::serde")] pub struct Product { pub pid: String, @@ -240,47 +97,7 @@ pub struct Product { pub qty: u128, } -impl Default for Product { - fn default() -> Self { - Product { - pid: utils::empty_string(), - description: utils::empty_string(), - image: Vec::new(), - in_stock: false, - name: utils::empty_string(), - price: 0, - qty: 0, - } - } -} - impl Product { - pub fn to_db(p: &Product) -> String { - let image: String = hex::encode(&p.image); - format!( - "{}:{}:{}:{}:{}:{}", - p.description, image, p.in_stock, p.name, p.price, p.qty - ) - } - pub fn from_db(k: String, v: String) -> Product { - let values = v.split(":"); - let mut v: Vec = values.map(String::from).collect(); - let description = v.remove(0); - let image = hex::decode(v.remove(0)).unwrap_or_default(); - let in_stock = v.remove(0).parse::().unwrap_or(false); - let name = v.remove(0); - let price = v.remove(0).parse::().unwrap_or(0); - let qty = v.remove(0).parse::().unwrap_or(0); - Product { - pid: k, - description, - image, - in_stock, - name, - price, - qty, - } - } pub fn update(p: Product, jp: &Json) -> Product { Product { pid: p.pid, @@ -294,7 +111,7 @@ impl Product { } } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Default, Deserialize, Serialize)] #[serde(crate = "rocket::serde")] pub struct Order { pub orid: String, @@ -332,140 +149,7 @@ pub struct Order { pub xmr_address: String, } -impl Default for Order { - fn default() -> Self { - Order { - orid: utils::empty_string(), - cid: utils::empty_string(), - pid: utils::empty_string(), - xmr_address: utils::empty_string(), - cust_kex_1: utils::empty_string(), - cust_kex_2: utils::empty_string(), - cust_kex_3: utils::empty_string(), - cust_msig_make: utils::empty_string(), - cust_msig_prepare: utils::empty_string(), - cust_msig_txset: utils::empty_string(), - date: 0, - deliver_date: 0, - hash: utils::empty_string(), - adjudicator_kex_1: utils::empty_string(), - adjudicator_kex_2: utils::empty_string(), - adjudicator_kex_3: utils::empty_string(), - adjudicator_msig_make: utils::empty_string(), - adjudicator_msig_prepare: utils::empty_string(), - ship_address: utils::empty_string(), - ship_date: 0, - subaddress: utils::empty_string(), - status: utils::empty_string(), - quantity: 0, - vend_kex_1: utils::empty_string(), - vend_kex_2: utils::empty_string(), - vend_kex_3: utils::empty_string(), - vend_msig_make: utils::empty_string(), - vend_msig_prepare: utils::empty_string(), - vend_msig_txset: utils::empty_string(), - } - } -} - impl Order { - pub fn to_db(o: &Order) -> String { - format!( - "{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}", - o.cid, - o.pid, - o.cust_kex_1, - o.cust_kex_2, - o.cust_kex_3, - o.cust_msig_make, - o.cust_msig_prepare, - o.cust_msig_txset, - o.date, - o.deliver_date, - o.hash, - o.adjudicator_msig_make, - o.adjudicator_msig_prepare, - o.adjudicator_kex_1, - o.adjudicator_kex_2, - o.adjudicator_kex_3, - o.ship_address, - o.ship_date, - o.subaddress, - o.status, - o.quantity, - o.vend_kex_1, - o.vend_kex_2, - o.vend_kex_3, - o.vend_msig_make, - o.vend_msig_prepare, - o.vend_msig_txset, - o.xmr_address, - ) - } - pub fn from_db(k: String, v: String) -> Order { - let values = v.split(":"); - let mut v: Vec = values.map(String::from).collect(); - let orid = k; - let cid = v.remove(0); - let pid = v.remove(0); - let cust_kex_1 = v.remove(0); - let cust_kex_2 = v.remove(0); - let cust_kex_3 = v.remove(0); - let cust_msig_make = v.remove(0); - let cust_msig_prepare = v.remove(0); - let cust_msig_txset = v.remove(0); - let date = v.remove(0).parse::().unwrap_or(0); - let deliver_date = v.remove(0).parse::().unwrap_or(0); - let hash = v.remove(0); - let adjudicator_msig_make = v.remove(0); - let adjudicator_msig_prepare = v.remove(0); - let adjudicator_kex_1 = v.remove(0); - let adjudicator_kex_2 = v.remove(0); - let adjudicator_kex_3 = v.remove(0); - let ship_address = v.remove(0); - let ship_date = v.remove(0).parse::().unwrap_or(0); - let subaddress = v.remove(0); - let status = v.remove(0); - let quantity = v.remove(0).parse::().unwrap_or(0); - let vend_kex_1 = v.remove(0); - let vend_kex_2 = v.remove(0); - let vend_kex_3 = v.remove(0); - let vend_msig_make = v.remove(0); - let vend_msig_prepare = v.remove(0); - let vend_msig_txset = v.remove(0); - let xmr_address = v.remove(0); - Order { - orid, - cid, - pid, - cust_kex_1, - cust_kex_2, - cust_kex_3, - cust_msig_make, - cust_msig_prepare, - cust_msig_txset, - date, - deliver_date, - hash, - adjudicator_kex_1, - adjudicator_kex_2, - adjudicator_kex_3, - adjudicator_msig_make, - adjudicator_msig_prepare, - ship_address, - ship_date, - subaddress, - status, - quantity, - vend_kex_1, - vend_kex_2, - vend_kex_3, - vend_msig_make, - vend_msig_prepare, - vend_msig_txset, - xmr_address, - } - } pub fn update(orid: String, o: &Json) -> Order { Order { orid, @@ -501,7 +185,7 @@ impl Order { } } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Default, Deserialize, Serialize)] #[serde(crate = "rocket::serde")] pub struct Dispute { pub did: String, @@ -509,33 +193,3 @@ pub struct Dispute { pub orid: String, pub tx_set: String, } - -impl Default for Dispute { - fn default() -> Self { - Dispute { - did: utils::empty_string(), - created: 0, - orid: utils::empty_string(), - tx_set: utils::empty_string(), - } - } -} - -impl Dispute { - pub fn to_db(d: &Dispute) -> String { - format!("{}:{}:{}", d.created, d.orid, d.tx_set) - } - pub fn from_db(k: String, v: String) -> Dispute { - let values = v.split(":"); - let mut v: Vec = values.map(String::from).collect(); - let created = v.remove(0).parse::().unwrap_or(0); - let orid = v.remove(0); - let tx_set = v.remove(0); - Dispute { - did: k, - created, - orid, - tx_set, - } - } -} diff --git a/neveko-core/src/monero.rs b/neveko-core/src/monero.rs index 79535ba..a1023bb 100644 --- a/neveko-core/src/monero.rs +++ b/neveko-core/src/monero.rs @@ -319,15 +319,15 @@ fn get_blockchain_dir() -> String { /// Get monero download location fn get_monero_location() -> String { let args = args::Args::parse(); - let user = std::env::var("USER").unwrap_or(utils::empty_string()); + let user = std::env::var("USER").unwrap_or(String::new()); format!("/home/{}/{}", &user, &args.monero_location) } /// Get monero rpc host from the `--monero-rpc-host` cli arg fn get_rpc_host() -> String { let args = args::Args::parse(); - let gui_host = std::env::var(crate::MONERO_WALLET_RPC_HOST).unwrap_or(utils::empty_string()); - let rpc = if gui_host == utils::empty_string() { + let gui_host = std::env::var(crate::MONERO_WALLET_RPC_HOST).unwrap_or(String::new()); + let rpc = if gui_host.is_empty() { args.monero_rpc_host } else { gui_host @@ -348,8 +348,8 @@ fn get_rpc_creds() -> RpcLogin { fn get_rpc_daemon() -> String { let args = args::Args::parse(); - let gui_host = std::env::var(crate::MONERO_DAEMON_HOST).unwrap_or(utils::empty_string()); - if gui_host == utils::empty_string() { + let gui_host = std::env::var(crate::MONERO_DAEMON_HOST).unwrap_or(String::new()); + if gui_host.is_empty() { args.monero_rpc_daemon } else { gui_host diff --git a/neveko-core/src/neveko25519.rs b/neveko-core/src/neveko25519.rs index 4f659b6..1df9eaf 100644 --- a/neveko-core/src/neveko25519.rs +++ b/neveko-core/src/neveko25519.rs @@ -15,11 +15,7 @@ use sha2::{ Digest, Sha512, }; - -use crate::{ - monero, - utils, -}; +use crate::monero; #[derive(Debug)] /// Container for the Neveko Message Keys @@ -39,8 +35,8 @@ impl Default for NevekoMessageKeys { NevekoMessageKeys { nmpk: [0u8; 32], nmsk: [0u8; 32], - hex_nmpk: utils::empty_string(), - hex_nmsk: utils::empty_string(), + hex_nmpk: String::new(), + hex_nmsk: String::new(), } } } @@ -96,7 +92,7 @@ fn hash_to_scalar(s: Vec<&str>) -> Scalar { /// Neveko Message Public Key (NMPK). pub async fn generate_neveko_message_keys() -> NevekoMessageKeys { log::info!("generating neveko message keys"); - let password = std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(utils::empty_string()); + let password = std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(String::new()); let filename = String::from(crate::APP_NAME); let m_wallet = monero::open_wallet(&filename, &password).await; if !m_wallet { @@ -130,7 +126,7 @@ pub async fn generate_neveko_message_keys() -> NevekoMessageKeys { /// /// Pass `None` to encipher parameter to perform deciphering. pub async fn cipher(hex_nmpk: &String, message: String, encipher: Option) -> String { - let unwrap_encipher: String = encipher.unwrap_or(utils::empty_string()); + let unwrap_encipher: String = encipher.unwrap_or(String::new()); let keys: NevekoMessageKeys = generate_neveko_message_keys().await; // shared secret = nmpk * nmsk let scalar_nmsk = Scalar::from_bytes_mod_order(keys.nmsk); @@ -162,7 +158,7 @@ mod tests { use super::*; fn test_cipher(message: &String, encipher: Option) -> String { - let unwrap_encipher: String = encipher.unwrap_or(utils::empty_string()); + let unwrap_encipher: String = encipher.unwrap_or(String::new()); let test_nmpk: [u8; 32] = [ 203, 2, 188, 13, 167, 96, 59, 189, 38, 238, 2, 71, 84, 155, 153, 73, 241, 137, 9, 30, 28, 134, 91, 137, 134, 73, 231, 45, 174, 98, 103, 158, diff --git a/neveko-core/src/order.rs b/neveko-core/src/order.rs index 1b812e1..74fd4e3 100644 --- a/neveko-core/src/order.rs +++ b/neveko-core/src/order.rs @@ -65,7 +65,7 @@ pub async fn create(j_order: Json) -> Order { ..Default::default() }; debug!("insert order: {:?}", new_order); - let order_wallet_password = utils::empty_string(); + let order_wallet_password = String::new(); let m_wallet = monero::create_wallet(&orid, &order_wallet_password).await; if !m_wallet { error!("error creating msig wallet for order {}", &orid); @@ -74,35 +74,35 @@ pub async fn create(j_order: Json) -> Order { } monero::close_wallet(&orid, &order_wallet_password).await; debug!("insert order: {:?}", &new_order); - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; // inject adjudicator separately, modifying the order model is mendokusai let adjudicator_k = format!("{}-{}", crate::ADJUDICATOR_DB_KEY, &orid); - db::Interface::async_write(&s.env, &s.handle, &adjudicator_k, &j_order.adjudicator).await; + db::DatabaseEnvironment::async_write(&s.env, &s.handle, &adjudicator_k, &j_order.adjudicator).await; let k = &new_order.orid; - db::Interface::async_write(&s.env, &s.handle, k, &Order::to_db(&new_order)).await; + db::DatabaseEnvironment::async_write(&s.env, &s.handle, k, &Order::to_db(&new_order)).await; // in order to retrieve all orders, write keys to with ol let list_key = crate::ORDER_LIST_DB_KEY; - let r = db::Interface::async_read(&s.env, &s.handle, &String::from(list_key)).await; - if r == utils::empty_string() { + let r = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &String::from(list_key)).await; + if r.is_empty() { debug!("creating order index"); } let order_list = [r, String::from(&orid)].join(","); debug!("writing order index {} for id: {}", order_list, list_key); - db::Interface::async_write(&s.env, &s.handle, &String::from(list_key), &order_list).await; + db::DatabaseEnvironment::async_write(&s.env, &s.handle, &String::from(list_key), &order_list).await; new_order } /// Backup order for customer pub fn backup(order: &Order) { info!("creating backup of order: {}", order.orid); - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let k = &order.orid; - db::Interface::delete(&s.env, &s.handle, k); - db::Interface::write(&s.env, &s.handle, k, &Order::to_db(order)); + db::DatabaseEnvironment::delete(&s.env, &s.handle, k); + db::DatabaseEnvironment::write(&s.env, &s.handle, k, &Order::to_db(order)); // in order to retrieve all orders, write keys to with col let list_key = crate::CUSTOMER_ORDER_LIST_DB_KEY; - let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key)); - if r == utils::empty_string() { + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key)); + if r.is_empty() { debug!("creating customer order index"); } let mut order_list = [String::from(&r), String::from(&order.orid)].join(","); @@ -111,15 +111,15 @@ pub fn backup(order: &Order) { 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); + db::DatabaseEnvironment::write(&s.env, &s.handle, &String::from(list_key), &order_list); } /// Lookup order pub fn find(oid: &String) -> Order { info!("find order: {}", &oid); - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, &String::from(oid)); - if r == utils::empty_string() { + let s = db::DatabaseEnvironment::open(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(oid)); + if r.is_empty() { error!("order not found"); return Default::default(); } @@ -128,10 +128,10 @@ pub fn find(oid: &String) -> Order { /// Lookup all orders from admin server pub fn find_all() -> Vec { - let i_s = db::Interface::open(); + let i_s = db::DatabaseEnvironment::open(); let i_list_key = crate::ORDER_LIST_DB_KEY; - let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key)); - if i_r == utils::empty_string() { + let i_r = db::DatabaseEnvironment::read(&i_s.env, &i_s.handle, &String::from(i_list_key)); + if i_r.is_empty() { error!("order index not found"); } let i_v_oid = i_r.split(","); @@ -139,7 +139,7 @@ pub fn find_all() -> Vec { let mut orders: Vec = Vec::new(); for o in i_v { let order: Order = find(&o); - if order.orid != utils::empty_string() { + if !order.orid.is_empty() { orders.push(order); } } @@ -148,10 +148,10 @@ pub fn find_all() -> Vec { /// Lookup all orders that customer has saved from gui pub fn find_all_backup() -> Vec { - let i_s = db::Interface::open(); + let i_s = db::DatabaseEnvironment::open(); let i_list_key = crate::CUSTOMER_ORDER_LIST_DB_KEY; - let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key)); - if i_r == utils::empty_string() { + let i_r = db::DatabaseEnvironment::read(&i_s.env, &i_s.handle, &String::from(i_list_key)); + if i_r.is_empty() { error!("customer order index not found"); } let i_v_oid = i_r.split(","); @@ -159,7 +159,7 @@ pub fn find_all_backup() -> Vec { let mut orders: Vec = Vec::new(); for o in i_v { let order: Order = find(&o); - let visible = order.orid != utils::empty_string() + let visible = !order.orid.is_empty() && order.status != order::StatusType::Delivered.value() && order.status != order::StatusType::Cancelled.value(); if visible { @@ -172,10 +172,10 @@ pub fn find_all_backup() -> Vec { /// Lookup all orders for customer pub async fn find_all_customer_orders(cid: String) -> Vec { info!("lookup orders for customer: {}", &cid); - let i_s = db::Interface::open(); + let i_s = db::DatabaseEnvironment::open(); let i_list_key = crate::ORDER_LIST_DB_KEY; - let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key)); - if i_r == utils::empty_string() { + let i_r = db::DatabaseEnvironment::read(&i_s.env, &i_s.handle, &String::from(i_list_key)); + if i_r.is_empty() { error!("order index not found"); } let i_v_oid = i_r.split(","); @@ -183,7 +183,7 @@ pub async fn find_all_customer_orders(cid: String) -> Vec { let mut orders: Vec = Vec::new(); for o in i_v { let order: Order = find(&o); - if order.orid != utils::empty_string() && order.cid == cid { + if !order.orid.is_empty() && order.cid == cid { orders.push(order); } } @@ -193,10 +193,10 @@ pub async fn find_all_customer_orders(cid: String) -> Vec { /// Lookup all orders for vendor pub fn find_all_vendor_orders() -> Vec { info!("lookup orders for vendor"); - let i_s = db::Interface::open(); + let i_s = db::DatabaseEnvironment::open(); let i_list_key = crate::ORDER_LIST_DB_KEY; - let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key)); - if i_r == utils::empty_string() { + let i_r = db::DatabaseEnvironment::read(&i_s.env, &i_s.handle, &String::from(i_list_key)); + if i_r.is_empty() { error!("order index not found"); } let i_v_oid = i_r.split(","); @@ -205,7 +205,7 @@ pub fn find_all_vendor_orders() -> Vec { let vendor_b32: String = i2p::get_destination(None); for o in i_v { let order: Order = find(&o); - if order.orid != utils::empty_string() && order.cid != vendor_b32 { + if !order.orid.is_empty() && order.cid != vendor_b32 { // TODO(c2m): separate functionality for archived orders if order.status != order::StatusType::Cancelled.value() && order.status != order::StatusType::Delivered.value() @@ -221,14 +221,14 @@ pub fn find_all_vendor_orders() -> Vec { pub fn modify(o: Json) -> Order { info!("modify order: {}", &o.orid); let f_order: Order = find(&o.orid); - if f_order.orid == utils::empty_string() { + if f_order.orid.is_empty() { error!("order not found"); return Default::default(); } let u_order = Order::update(String::from(&f_order.orid), &o); - let s = db::Interface::open(); - db::Interface::delete(&s.env, &s.handle, &u_order.orid); - db::Interface::write(&s.env, &s.handle, &u_order.orid, &Order::to_db(&u_order)); + let s = db::DatabaseEnvironment::open(); + db::DatabaseEnvironment::delete(&s.env, &s.handle, &u_order.orid); + db::DatabaseEnvironment::write(&s.env, &s.handle, &u_order.orid, &Order::to_db(&u_order)); u_order } @@ -238,7 +238,7 @@ pub async fn sign_and_submit_multisig( tx_data_hex: &String, ) -> reqres::XmrRpcSubmitMultisigResponse { info!("signing and submitting multisig"); - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::open_wallet(orid, &wallet_password).await; let r_sign: reqres::XmrRpcSignMultisigResponse = monero::sign_multisig(String::from(tx_data_hex)).await; @@ -327,14 +327,14 @@ pub async fn validate_order_for_ship(orid: &String) -> reqres::FinalizeOrderResp let m_order: Order = find(orid); let contact: Contact = contact::find(&m_order.cid); let hex_nmpk: String = contact.nmpk; - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::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 delivery_info: String = db::DatabaseEnvironment::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; let total = price * &m_order.quantity; - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::open_wallet(orid, &wallet_password).await; // check balance and unlock_time let r_balance = monero::get_balance().await; @@ -420,7 +420,7 @@ pub async fn upload_delivery_info( error!("unable to encipher delivery info"); } // get draft payment txset - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::open_wallet(orid, &wallet_password).await; monero::refresh().await; let sweep: reqres::XmrRpcSweepAllResponse = @@ -437,17 +437,17 @@ pub async fn upload_delivery_info( m_order.vend_msig_txset = sweep.result.multisig_txset; // delivery info will be stored enciphered and separate from the rest of the // order - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::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; + db::DatabaseEnvironment::async_write(&s.env, &s.handle, &k, &hex::encode(delivery_info)).await; modify(Json(m_order)); // trigger nasr, this will cause the customer's neveko instance to request the // txset let i2p_address = i2p::get_destination(None); - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); // get jwp from db let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &lookup.cid); - let jwp = db::Interface::read(&s.env, &s.handle, &k); + let jwp = db::DatabaseEnvironment::read(&s.env, &s.handle, &k); let nasr_order = trigger_nasr(&lookup.cid, &i2p_address, &jwp, orid).await; if nasr_order.is_err() { return Default::default(); @@ -468,12 +468,12 @@ pub async fn finalize_order(orid: &String) -> reqres::FinalizeOrderResponse { info!("finalizing order: {}", orid); // verify recipient and unlock time let mut m_order: Order = order::find(orid); - if m_order.vend_msig_txset == utils::empty_string() { + if m_order.vend_msig_txset.is_empty() { error!("txset missing"); return Default::default(); } // get draft payment txset - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::open_wallet(orid, &wallet_password).await; monero::refresh().await; let address: String = String::from(&m_order.subaddress); @@ -573,9 +573,9 @@ pub async fn d_trigger_finalize_request( ) -> reqres::FinalizeOrderResponse { // ugh, sorry seems we need to get jwp for vendor from fts cache // get jwp from db - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact); - let jwp = db::Interface::async_read(&s.env, &s.handle, &k).await; + let jwp = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &k).await; info!("executing d_trigger_finalize_request"); // request finalize if the order status is shipped let order: Order = order::find(orid); @@ -738,9 +738,9 @@ pub async fn trigger_cancel_request(contact: &String, jwp: &String, orid: &Strin pub async fn d_trigger_ship_request(contact: &String, orid: &String) -> Order { // ugh, sorry seems we need to get jwp for vendor from fts cache // get jwp from db - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact); - let jwp = db::Interface::async_read(&s.env, &s.handle, &k).await; + let jwp = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &k).await; info!("executing d_trigger_ship_request"); // request shipment if the order status is MultisigComplete let trigger = trigger_ship_request(contact, &jwp, orid).await; @@ -753,7 +753,7 @@ pub async fn d_trigger_ship_request(contact: &String, orid: &String) -> Order { let u_ship_res = ship_res.unwrap_or(Default::default()); let hex_delivery_info: String = hex::encode(u_ship_res.delivery_info); let key = format!("{}-{}", crate::DELIVERY_INFO_DB_KEY, orid); - db::Interface::write(&s.env, &s.handle, &key, &hex_delivery_info); + db::DatabaseEnvironment::write(&s.env, &s.handle, &key, &hex_delivery_info); } trigger } @@ -803,9 +803,9 @@ pub async fn transmit_cancel_request( pub async fn d_trigger_cancel_request(contact: &String, orid: &String) -> Order { // ugh, sorry seems we need to get jwp for vendor from fts cache // get jwp from db - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact); - let jwp = db::Interface::async_read(&s.env, &s.handle, &k).await; + let jwp = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &k).await; info!("executing d_trigger_cancel_request"); // request cancel if the order status is not MultisigComplete let order: Order = order::find(orid); @@ -819,7 +819,7 @@ pub async fn d_trigger_cancel_request(contact: &String, orid: &String) -> Order } pub async fn init_adjudicator_wallet(orid: &String) { - let password = utils::empty_string(); + let password = String::new(); let m_wallet = monero::create_wallet(orid, &password).await; if !m_wallet { log::error!("failed to create adjudicator wallet"); diff --git a/neveko-core/src/product.rs b/neveko-core/src/product.rs index b0428fc..ffe7a74 100644 --- a/neveko-core/src/product.rs +++ b/neveko-core/src/product.rs @@ -30,13 +30,13 @@ pub fn create(d: Json) -> Product { qty: d.qty, }; debug!("insert product: {:?}", &new_product); - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let k = &new_product.pid; - db::Interface::write(&s.env, &s.handle, k, &Product::to_db(&new_product)); + db::DatabaseEnvironment::write(&s.env, &s.handle, k, &Product::to_db(&new_product)); // in order to retrieve all products, write keys to with pl let list_key = crate::PRODUCT_LIST_DB_KEY; - let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key)); - if r == utils::empty_string() { + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key)); + if r.is_empty() { debug!("creating product index"); } let product_list = [r, String::from(&pid)].join(","); @@ -44,15 +44,15 @@ pub fn create(d: Json) -> Product { "writing product index {} for id: {}", product_list, list_key ); - db::Interface::write(&s.env, &s.handle, &String::from(list_key), &product_list); + db::DatabaseEnvironment::write(&s.env, &s.handle, &String::from(list_key), &product_list); new_product } /// Single Product lookup pub fn find(pid: &String) -> Product { - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, &String::from(pid)); - if r == utils::empty_string() { + let s = db::DatabaseEnvironment::open(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(pid)); + if r.is_empty() { error!("product not found"); return Default::default(); } @@ -61,10 +61,10 @@ pub fn find(pid: &String) -> Product { /// Product lookup for all pub fn find_all() -> Vec { - let i_s = db::Interface::open(); + let i_s = db::DatabaseEnvironment::open(); let i_list_key = crate::PRODUCT_LIST_DB_KEY; - let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key)); - if i_r == utils::empty_string() { + let i_r = db::DatabaseEnvironment::read(&i_s.env, &i_s.handle, &String::from(i_list_key)); + if i_r.is_empty() { error!("product index not found"); } let i_v_pid = i_r.split(","); @@ -72,7 +72,7 @@ pub fn find_all() -> Vec { let mut products: Vec = Vec::new(); for p in i_v { let mut product: Product = find(&p); - if product.pid != utils::empty_string() { + if !product.pid.is_empty() { // don't return images product.image = Vec::new(); products.push(product); @@ -86,14 +86,14 @@ pub fn modify(p: Json) -> Product { // TODO(c2m): don't allow modification to products with un-delivered orders info!("modify product: {}", &p.pid); let f_prod: Product = find(&p.pid); - if f_prod.pid == utils::empty_string() { + if f_prod.pid.is_empty() { error!("product not found"); return Default::default(); } let u_prod = Product::update(f_prod, &p); - let s = db::Interface::open(); - db::Interface::delete(&s.env, &s.handle, &u_prod.pid); - db::Interface::write(&s.env, &s.handle, &u_prod.pid, &Product::to_db(&u_prod)); + let s = db::DatabaseEnvironment::open(); + db::DatabaseEnvironment::delete(&s.env, &s.handle, &u_prod.pid); + db::DatabaseEnvironment::write(&s.env, &s.handle, &u_prod.pid, &Product::to_db(&u_prod)); u_prod } diff --git a/neveko-core/src/proof.rs b/neveko-core/src/proof.rs index 8a56f58..c08bae9 100644 --- a/neveko-core/src/proof.rs +++ b/neveko-core/src/proof.rs @@ -31,7 +31,7 @@ use serde::{ use sha2::Sha512; use std::collections::BTreeMap; -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct TxProof { pub subaddress: String, pub confirmations: u64, @@ -40,18 +40,6 @@ pub struct TxProof { pub signature: String, } -impl Default for TxProof { - fn default() -> Self { - TxProof { - subaddress: utils::empty_string(), - confirmations: 0, - hash: utils::empty_string(), - message: utils::empty_string(), - signature: utils::empty_string(), - } - } -} - /// Provide neccessary information for contacts to /// /// provide proof of payment. @@ -89,9 +77,9 @@ pub async fn create_jwp(proof: &TxProof) -> String { info!("creating jwp"); // validate the proof let c_txp: TxProof = validate_proof(proof).await; - if c_txp.hash == utils::empty_string() { + if c_txp.hash.is_empty() { error!("invalid transaction proof"); - return utils::empty_string(); + return String::new(); } let jwp_secret_key = utils::get_jwp_secret_key(); let key: Hmac = Hmac::new_from_slice(jwp_secret_key.as_bytes()).expect("hash"); @@ -134,10 +122,12 @@ pub async fn prove_payment(contact: String, txp: &TxProof) -> Result { // cache the jwp for for fts - let s = db::Interface::open(); + let env = utils::get_release_env(); + let s = db::DatabaseEnvironment::open(&env.value())?; let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact); - db::Interface::delete(&s.env, &s.handle, &k); - db::Interface::write(&s.env, &s.handle, &k, &r.jwp); + db::DatabaseEnvironment::delete(&s.env, &s.handle?, k.as_bytes())?; + let s = db::DatabaseEnvironment::open(&env.value())?; + db::write_chunks(&s.env, &s.handle?, &k.as_bytes(), &r.jwp.as_bytes().to_vec()); Ok(r) } _ => Ok(Default::default()), diff --git a/neveko-core/src/reqres.rs b/neveko-core/src/reqres.rs index 1e0a559..aa7388c 100644 --- a/neveko-core/src/reqres.rs +++ b/neveko-core/src/reqres.rs @@ -1,6 +1,5 @@ //! Structs for all http requests -use crate::utils; use serde::{ Deserialize, Serialize, @@ -113,21 +112,12 @@ pub struct XmrRpcGetTxByIdParams { pub txid: String, } -#[derive(Deserialize, Serialize, Debug, PartialEq)] +#[derive(Default, Deserialize, Serialize, Debug, PartialEq)] pub struct Destination { pub address: String, pub amount: u128, } -impl Default for Destination { - fn default() -> Self { - Destination { - address: utils::empty_string(), - amount: 0, - } - } -} - #[derive(Deserialize, Serialize, Debug)] pub struct XmrRpcTransferParams { pub destinations: Vec, @@ -158,13 +148,13 @@ pub struct XmrDaemonGetBlockParams { pub height: u64, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcChangePasswordParams { pub old_password: String, pub new_password: String, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcQueryKeyParams { pub key_type: String, } @@ -343,7 +333,7 @@ pub struct XmrRpcCreateAddressRequest { pub params: XmrRpcCreateAddressParams, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcChangePasswordRequest { pub jsonrpc: String, pub id: String, @@ -351,7 +341,7 @@ pub struct XmrRpcChangePasswordRequest { pub params: XmrRpcChangePasswordParams, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcQueryKeyRequest { pub jsonrpc: String, pub id: String, @@ -360,7 +350,7 @@ pub struct XmrRpcQueryKeyRequest { } // results -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcValidateAddressResult { pub integrated: bool, pub nettype: String, @@ -369,60 +359,60 @@ pub struct XmrRpcValidateAddressResult { pub valid: bool, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcSignResult { pub signature: String, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcVerifyResult { pub good: bool, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcVersionResult { pub version: u32, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcPrepareResult { pub multisig_info: String, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcMakeResult { pub address: String, pub multisig_info: String, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcExportResult { pub info: String, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcImportResult { pub n_outputs: u8, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcSignMultisigResult { pub tx_data_hex: String, pub tx_hash_list: Vec, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcSubmitMultisigResult { pub tx_hash_list: Vec, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcExchangeMultisigKeysResult { pub address: String, pub multisig_info: String, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct SubAddressInfo { pub account_index: u64, pub address_index: u64, @@ -435,7 +425,7 @@ pub struct SubAddressInfo { pub blocks_to_unlock: u64, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct Address { pub address: String, pub address_index: u64, @@ -443,13 +433,13 @@ pub struct Address { pub used: bool, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcAddressResult { pub address: String, pub addresses: Vec
, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcBalanceResult { pub balance: u128, pub unlocked_balance: u128, @@ -459,7 +449,7 @@ pub struct XmrRpcBalanceResult { pub per_subaddress: Vec, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcCheckTxProofResult { pub confirmations: u64, pub good: bool, @@ -467,20 +457,19 @@ pub struct XmrRpcCheckTxProofResult { pub received: u128, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcGetTxProofResult { pub signature: String, } -#[derive(Deserialize, Serialize, Debug)] -#[derive(Default)] +#[derive(Debug, Default, Deserialize)] pub struct SubAddressIndex { pub major: u64, pub minor: u64, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct Transfer { pub address: String, pub amount: u128, @@ -502,13 +491,13 @@ pub struct Transfer { pub unlock_time: u64, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcGetTxByIdResult { pub transfer: Transfer, pub transfers: Vec, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcTranferResult { pub amount: u128, pub fee: u128, @@ -520,7 +509,7 @@ pub struct XmrRpcTranferResult { pub unsigned_txset: String, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct TransferDescription { pub amount_in: u128, pub amount_out: u128, @@ -534,17 +523,17 @@ pub struct TransferDescription { pub extra: String, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcDescribeTranferResult { pub desc: Vec, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct KeyImageList { key_images: Vec, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcSweepAllResult { pub amount_list: Vec, pub fee_list: Vec, @@ -555,7 +544,7 @@ pub struct XmrRpcSweepAllResult { pub weight_list: Vec, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcCreateAddressResult { pub address: String, pub address_index: u64, @@ -563,13 +552,13 @@ pub struct XmrRpcCreateAddressResult { pub addresses: Vec, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcRefreshResult { pub blocks_fetched: u64, pub received_money: bool, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcIsMultisigResult { pub multisig: bool, pub ready: bool, @@ -577,17 +566,17 @@ pub struct XmrRpcIsMultisigResult { pub total: u16, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcGetHeightResult { pub height: u64, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcQueryKeyResult { pub key: String, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrDaemonGetInfoResult { pub adjusted_time: u64, pub alt_blocks_count: u64, @@ -633,7 +622,7 @@ pub struct XmrDaemonGetInfoResult { pub wide_difficulty: String, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct BlockHeader { pub block_size: u32, pub block_weight: u32, @@ -659,36 +648,7 @@ pub struct BlockHeader { pub wide_difficulty: String, } -impl Default for BlockHeader { - fn default() -> Self { - BlockHeader { - block_size: 0, - block_weight: 0, - cumulative_difficulty: 0, - cumulative_difficulty_top64: 0, - depth: 0, - difficulty: 0, - difficulty_top64: 0, - hash: utils::empty_string(), - height: 0, - long_term_weight: 0, - major_version: 0, - miner_tx_hash: utils::empty_string(), - minor_version: 0, - nonce: 0, - num_txes: 0, - orphan_status: false, - pow_hash: utils::empty_string(), - prev_hash: utils::empty_string(), - reward: 0, - timestamp: 0, - wide_cumulative_difficulty: utils::empty_string(), - wide_difficulty: utils::empty_string(), - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrDaemonGetBlockResult { pub blob: String, pub block_header: BlockHeader, @@ -705,7 +665,7 @@ pub struct XmrDaemonGetBlockResult { } // responses -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrDaemonGetHeightResponse { pub hash: String, pub height: u64, @@ -713,521 +673,154 @@ pub struct XmrDaemonGetHeightResponse { pub untrusted: bool, } -impl Default for XmrDaemonGetHeightResponse { - fn default() -> Self { - XmrDaemonGetHeightResponse { - hash: utils::empty_string(), - height: 0, - status: utils::empty_string(), - untrusted: false, - } - } -} - -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrDaemonGetInfoResponse { pub result: XmrDaemonGetInfoResult, } -impl Default for XmrDaemonGetInfoResponse { - fn default() -> Self { - XmrDaemonGetInfoResponse { - result: XmrDaemonGetInfoResult { - adjusted_time: 0, - alt_blocks_count: 0, - block_size_limit: 0, - block_size_median: 0, - block_weight_median: 0, - bootstrap_daemon_address: utils::empty_string(), - busy_syncing: false, - credits: 0, - cumulative_difficulty: 0, - cumulative_difficulty_top64: 0, - database_size: 0, - difficulty: 0, - difficulty_top64: 0, - free_space: 0, - grey_peerlist_size: 0, - height: 0, - height_without_bootstrap: 0, - incoming_connections_count: 0, - mainnet: false, - nettype: utils::empty_string(), - offline: false, - outgoing_connections_count: 0, - restricted: false, - rpc_connections_count: 0, - stagenet: false, - start_time: 0, - status: utils::empty_string(), - synchronized: false, - target: 0, - target_height: 0, - testnet: false, - top_block_hash: utils::empty_string(), - top_hash: utils::empty_string(), - tx_count: 0, - tx_pool_size: 0, - untrusted: false, - update_available: false, - version: utils::empty_string(), - was_bootstrap_ever_used: false, - white_peerlist_size: 0, - wide_cumulative_difficulty: utils::empty_string(), - wide_difficulty: utils::empty_string(), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrDaemonGetBlockResponse { pub result: XmrDaemonGetBlockResult, } -impl Default for XmrDaemonGetBlockResponse { - fn default() -> Self { - XmrDaemonGetBlockResponse { - result: XmrDaemonGetBlockResult { - blob: utils::empty_string(), - block_header: Default::default(), - credits: 0, - json: utils::empty_string(), - miner_tx_hash: utils::empty_string(), - status: utils::empty_string(), - top_hash: utils::empty_string(), - tx_hashes: Some(Vec::new()), - untrusted: false, - }, - } - } -} - /// Only extract the json string. TODO(c2m): map to a struct -#[derive(Serialize, Deserialize, Debug)] -#[derive(Default)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrDaemonGetTransactionsResponse { pub txs_as_json: Vec, } -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcSignResponse { pub result: XmrRpcSignResult, } -impl Default for XmrRpcSignResponse { - fn default() -> Self { - XmrRpcSignResponse { - result: XmrRpcSignResult { - signature: utils::empty_string(), - }, - } - } -} - #[derive(Deserialize, Debug)] pub struct XmrRpcVerifyResponse { pub result: XmrRpcVerifyResult, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct XmrRpcVersionResponse { pub result: XmrRpcVersionResult, } -impl Default for XmrRpcVersionResponse { - fn default() -> Self { - XmrRpcVersionResponse { - result: XmrRpcVersionResult { version: 0 }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcPrepareResponse { pub result: XmrRpcPrepareResult, } -impl Default for XmrRpcPrepareResponse { - fn default() -> Self { - XmrRpcPrepareResponse { - result: XmrRpcPrepareResult { - multisig_info: String::from(""), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcBalanceResponse { pub result: XmrRpcBalanceResult, } -impl Default for XmrRpcBalanceResponse { - fn default() -> Self { - XmrRpcBalanceResponse { - result: XmrRpcBalanceResult { - balance: 0, - unlocked_balance: 0, - multisig_import_needed: false, - time_to_unlock: 0, - blocks_to_unlock: 0, - per_subaddress: Vec::new(), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcValidateAddressResponse { pub result: XmrRpcValidateAddressResult, } -impl Default for XmrRpcValidateAddressResponse { - fn default() -> Self { - XmrRpcValidateAddressResponse { - result: XmrRpcValidateAddressResult { - integrated: false, - nettype: utils::empty_string(), - openalias_address: utils::empty_string(), - subaddress: false, - valid: false, - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcAddressResponse { pub result: XmrRpcAddressResult, } -impl Default for XmrRpcAddressResponse { - fn default() -> Self { - XmrRpcAddressResponse { - result: XmrRpcAddressResult { - address: utils::empty_string(), - addresses: Vec::new(), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcMakeResponse { pub result: XmrRpcMakeResult, } -impl Default for XmrRpcMakeResponse { - fn default() -> Self { - XmrRpcMakeResponse { - result: XmrRpcMakeResult { - address: utils::empty_string(), - multisig_info: utils::empty_string(), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcExportResponse { pub result: XmrRpcExportResult, } -impl Default for XmrRpcExportResponse { - fn default() -> Self { - XmrRpcExportResponse { - result: XmrRpcExportResult { - info: utils::empty_string(), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcImportResponse { pub result: XmrRpcImportResult, } -impl Default for XmrRpcImportResponse { - fn default() -> Self { - XmrRpcImportResponse { - result: XmrRpcImportResult { n_outputs: 0 }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcSignMultisigResponse { pub result: XmrRpcSignMultisigResult, } -impl Default for XmrRpcSignMultisigResponse { - fn default() -> Self { - XmrRpcSignMultisigResponse { - result: XmrRpcSignMultisigResult { - tx_data_hex: utils::empty_string(), - tx_hash_list: Vec::new(), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcSubmitMultisigResponse { pub result: XmrRpcSubmitMultisigResult, } -impl Default for XmrRpcSubmitMultisigResponse { - fn default() -> Self { - XmrRpcSubmitMultisigResponse { - result: XmrRpcSubmitMultisigResult { - tx_hash_list: Vec::new(), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcExchangeMultisigKeysResponse { pub result: XmrRpcExchangeMultisigKeysResult, } -impl Default for XmrRpcExchangeMultisigKeysResponse { - fn default() -> Self { - XmrRpcExchangeMultisigKeysResponse { - result: XmrRpcExchangeMultisigKeysResult { - address: utils::empty_string(), - multisig_info: utils::empty_string(), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcCheckTxProofResponse { pub result: XmrRpcCheckTxProofResult, } -impl Default for XmrRpcCheckTxProofResponse { - fn default() -> Self { - XmrRpcCheckTxProofResponse { - result: XmrRpcCheckTxProofResult { - confirmations: 0, - good: false, - in_pool: false, - received: 0, - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcGetTxProofResponse { pub result: XmrRpcGetTxProofResult, } -impl Default for XmrRpcGetTxProofResponse { - fn default() -> Self { - XmrRpcGetTxProofResponse { - result: XmrRpcGetTxProofResult { - signature: utils::empty_string(), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcGetTxByIdResponse { pub result: XmrRpcGetTxByIdResult, } -impl Default for XmrRpcGetTxByIdResponse { - fn default() -> Self { - XmrRpcGetTxByIdResponse { - result: XmrRpcGetTxByIdResult { - transfer: Transfer { - address: utils::empty_string(), - amount: 0, - amounts: Vec::new(), - confirmations: None, - double_spend_seen: false, - fee: 0, - height: 0, - locked: false, - note: utils::empty_string(), - payment_id: utils::empty_string(), - subaddr_index: Default::default(), - subaddr_indices: Vec::new(), - suggested_confirmations_threshold: 0, - timestamp: 0, - txid: utils::empty_string(), - r#type: utils::empty_string(), - unlock_time: 0, - }, - transfers: Vec::new(), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcTransferResponse { pub result: XmrRpcTranferResult, } -impl Default for XmrRpcTransferResponse { - fn default() -> Self { - XmrRpcTransferResponse { - result: XmrRpcTranferResult { - amount: 0, - fee: 0, - multisig_txset: utils::empty_string(), - tx_blob: utils::empty_string(), - tx_hash: utils::empty_string(), - tx_key: utils::empty_string(), - tx_metadata: utils::empty_string(), - unsigned_txset: utils::empty_string(), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcDescribeTransferResponse { pub result: XmrRpcDescribeTranferResult, } -impl Default for XmrRpcDescribeTransferResponse { - fn default() -> Self { - XmrRpcDescribeTransferResponse { - result: XmrRpcDescribeTranferResult { desc: Vec::new() }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcSweepAllResponse { pub result: XmrRpcSweepAllResult, } -impl Default for XmrRpcSweepAllResponse { - fn default() -> Self { - XmrRpcSweepAllResponse { - result: XmrRpcSweepAllResult { - amount_list: Vec::new(), - fee_list: Vec::new(), - multisig_txset: utils::empty_string(), - spent_key_images_list: Vec::new(), - tx_hash_list: Some(Vec::new()), - unsigned_txset: utils::empty_string(), - weight_list: Vec::new(), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcCreateAddressResponse { pub result: XmrRpcCreateAddressResult, } -impl Default for XmrRpcCreateAddressResponse { - fn default() -> Self { - XmrRpcCreateAddressResponse { - result: XmrRpcCreateAddressResult { - address: utils::empty_string(), - address_index: 0, - address_indices: Vec::new(), - addresses: Vec::new(), - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcRefreshResponse { pub result: XmrRpcRefreshResult, } -impl Default for XmrRpcRefreshResponse { - fn default() -> Self { - XmrRpcRefreshResponse { - result: XmrRpcRefreshResult { - blocks_fetched: 0, - received_money: false, - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcIsMultisigResponse { pub result: XmrRpcIsMultisigResult, } -impl Default for XmrRpcIsMultisigResponse { - fn default() -> Self { - XmrRpcIsMultisigResponse { - result: XmrRpcIsMultisigResult { - multisig: false, - ready: false, - threshold: 0, - total: 0, - }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcGetHeightResponse { pub result: XmrRpcGetHeightResult, } -impl Default for XmrRpcGetHeightResponse { - fn default() -> Self { - XmrRpcGetHeightResponse { - result: XmrRpcGetHeightResult { height: 0 }, - } - } -} - -#[derive(Deserialize, Debug)] +#[derive(Debug, Default, Deserialize)] pub struct XmrRpcQueryKeyResponse { pub result: XmrRpcQueryKeyResult, } - -impl Default for XmrRpcQueryKeyResponse { - fn default() -> Self { - XmrRpcQueryKeyResponse { - result: XmrRpcQueryKeyResult { - key: utils::empty_string(), - }, - } - } -} // END XMR Structs /// Container for the message decipher -#[derive(Serialize, Deserialize)] +#[derive(Debug, Default, Deserialize)] #[serde(crate = "rocket::serde")] pub struct DecipheredMessageBody { pub mid: String, pub body: String, } -impl Default for DecipheredMessageBody { - fn default() -> Self { - DecipheredMessageBody { - mid: utils::empty_string(), - body: utils::empty_string(), - } - } -} - /// Invoice response for host.b32.i2p/invoice -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] #[serde(crate = "rocket::serde")] pub struct Invoice { pub address: String, @@ -1235,50 +828,24 @@ pub struct Invoice { pub conf_threshold: u64, } -impl Default for Invoice { - fn default() -> Self { - Invoice { - address: utils::empty_string(), - pay_threshold: 0, - conf_threshold: 0, - } - } -} - /// Not to be confused with the PaymentProof guard. /// /// This is the response when proving payment -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] #[serde(crate = "rocket::serde")] pub struct Jwp { pub jwp: String, } -impl Default for Jwp { - fn default() -> Self { - Jwp { - jwp: utils::empty_string(), - } - } -} - /// For handling 402, 404 and 500 error responses -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] #[serde(crate = "rocket::serde")] pub struct ErrorResponse { pub error: String, } -impl Default for ErrorResponse { - fn default() -> Self { - ErrorResponse { - error: utils::empty_string(), - } - } -} - /// Handle intial order information for request -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] #[serde(crate = "rocket::serde")] pub struct OrderRequest { pub cid: String, @@ -1288,20 +855,8 @@ pub struct OrderRequest { pub quantity: u128, } -impl Default for OrderRequest { - fn default() -> Self { - OrderRequest { - cid: utils::empty_string(), - adjudicator: utils::empty_string(), - pid: utils::empty_string(), - ship_address: utils::empty_string(), - quantity: 0, - } - } -} - /// Handle multisig info requests -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] #[serde(crate = "rocket::serde")] pub struct MultisigInfoRequest { pub contact: String, @@ -1316,38 +871,16 @@ pub struct MultisigInfoRequest { pub orid: String, } -impl Default for MultisigInfoRequest { - fn default() -> Self { - MultisigInfoRequest { - contact: utils::empty_string(), - info: Vec::new(), - init_adjudicator: false, - kex_init: false, - msig_type: utils::empty_string(), - orid: utils::empty_string(), - } - } -} - /// Request for signing and submitting the unsigned txset -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] #[serde(crate = "rocket::serde")] pub struct SignAndSubmitRequest { pub orid: String, pub txset: String, } -impl Default for SignAndSubmitRequest { - fn default() -> Self { - SignAndSubmitRequest { - orid: utils::empty_string(), - txset: utils::empty_string(), - } - } -} - /// Response for the order finalization -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] #[serde(crate = "rocket::serde")] pub struct FinalizeOrderResponse { pub orid: String, @@ -1357,21 +890,9 @@ pub struct FinalizeOrderResponse { pub vendor_update_success: bool, } -impl Default for FinalizeOrderResponse { - fn default() -> Self { - FinalizeOrderResponse { - orid: utils::empty_string(), - delivery_info: utils::empty_string(), - vendor_update_success: false, - } - } -} - /// Response for the vendor mode -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Default, Deserialize, Serialize)] #[serde(crate = "rocket::serde")] -#[derive(Default)] pub struct VendorModeResponse { pub mode: bool, } - diff --git a/neveko-core/src/user.rs b/neveko-core/src/user.rs index c7946ca..d2243b4 100644 --- a/neveko-core/src/user.rs +++ b/neveko-core/src/user.rs @@ -6,52 +6,40 @@ use crate::{ models::*, utils, }; +use kn0sys_lmdb_rs::MdbError; use log::{ debug, error, - info, }; -use rocket::serde::json::Json; /// Create a new user -pub fn create(address: &String) -> User { +pub fn create(address: &String) -> Result { let f_uid: String = format!("{}{}", crate::USER_DB_KEY, utils::generate_rnd()); let new_user = User { uid: String::from(&f_uid), xmr_address: String::from(address), - name: utils::empty_string(), + name: String::new(), }; debug!("insert user: {:?}", &new_user); - let s = db::Interface::open(); + let env = utils::get_release_env(); + let s = db::DatabaseEnvironment::open(&env.value())?; let k = &new_user.uid; - db::Interface::write(&s.env, &s.handle, k, &User::to_db(&new_user)); - new_user + let v = bincode::serialize(&new_user).unwrap_or_default(); + db::write_chunks(&s.env, &s.handle?, k.as_bytes(), &v)?; + Ok(new_user) } /// User lookup -pub fn find(uid: &String) -> User { - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, &String::from(uid)); - if r == utils::empty_string() { +pub fn find(uid: &String) -> Result { + let env = utils::get_release_env(); + let s = db::DatabaseEnvironment::open(&env.value())?; + let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &uid.as_bytes().to_vec())?; + if r.is_empty() { error!("user not found"); - return Default::default(); + return Err(MdbError::NotFound); } - User::from_db(String::from(uid), r) -} - -/// Modify user - not implemented -fn _modify(u: Json) -> User { - info!("modify user: {}", u.uid); - let f_cust: User = find(&u.uid); - if f_cust.uid == utils::empty_string() { - error!("user not found"); - return Default::default(); - } - let u_user = User::update(f_cust, String::from(&u.name)); - let s = db::Interface::open(); - db::Interface::delete(&s.env, &s.handle, &u_user.uid); - db::Interface::write(&s.env, &s.handle, &u_user.uid, &User::to_db(&u_user)); - todo!() + let user: User = bincode::deserialize(&r[..]).unwrap_or_default(); + Ok(user) } // Tests @@ -59,42 +47,34 @@ fn _modify(u: Json) -> User { #[cfg(test)] mod tests { + use kn0sys_lmdb_rs::MdbError; + use super::*; - async fn cleanup(k: &String) { - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - let s = db::Interface::async_open().await; - db::Interface::async_delete(&s.env, &s.handle, k).await; + fn cleanup(k: &String) -> Result<(), MdbError> { + let s = db::DatabaseEnvironment::open("test")?; + db::DatabaseEnvironment::delete(&s.env, &s.handle?, k.as_bytes()); + Ok(()) } #[test] fn create_test() { // run and async cleanup so the test doesn't fail when deleting test data - use tokio::runtime::Runtime; - let rt = Runtime::new().expect("Unable to create Runtime for test"); - let _enter = rt.enter(); let address: String = String::from( "73a4nWuvkYoYoksGurDjKZQcZkmaxLaKbbeiKzHnMmqKivrCzq5Q2JtJG1UZNZFqLPbQ3MiXCk2Q5bdwdUNSr7X9QrPubkn" ); let test_user = create(&address); - tokio::spawn(async move { - let s = db::Interface::async_open().await; - let r = db::Interface::async_read(&s.env, &s.handle, &test_user.uid).await; - let id = String::from(&test_user.uid); - let cleanup_id = String::from(&test_user.uid); - let expected_user = User::from_db(id, r); - assert_eq!(test_user.xmr_address, expected_user.xmr_address); - cleanup(&cleanup_id).await; - }); - Runtime::shutdown_background(rt); + let s = db::DatabaseEnvironment::open("test")?; + let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &test_user.uid); + let id = String::from(&test_user.uid); + let cleanup_id = String::from(&test_user.uid); + let expected_user = User::from_db(id, r); + assert_eq!(test_user.xmr_address, expected_user.xmr_address); + cleanup(&cleanup_id); } #[test] fn find_test() { - // run and async cleanup so the test doesn't fail when deleting test data - use tokio::runtime::Runtime; - let rt = Runtime::new().expect("Unable to create Runtime for test"); - let _enter = rt.enter(); let address: String = String::from( "73a4nWuvkYoYoksGurDjKZQcZkmaxLaKbbeiKzHnMmqKivrCzq5Q2JtJG1UZNZFqLPbQ3MiXCk2Q5bdwdUNSr7X9QrPubkn" ); @@ -103,13 +83,10 @@ mod tests { xmr_address: address, ..Default::default() }; - tokio::spawn(async move { - let s = db::Interface::async_open().await; - db::Interface::async_write(&s.env, &s.handle, k, &User::to_db(&expected_user)).await; - let actual_user: User = find(&String::from(k)); - assert_eq!(expected_user.xmr_address, actual_user.xmr_address); - cleanup(&String::from(k)).await; - }); - Runtime::shutdown_background(rt); + let s = db::DatabaseEnvironment::open("test")?; + db::DatabaseEnvironment::write_chunks(&s.env, &s.handle?, k, &User::to_db(&expected_user)); + let actual_user: User = find(&String::from(k)); + assert_eq!(expected_user.xmr_address, actual_user.xmr_address); + cleanup(&String::from(k)); } } diff --git a/neveko-core/src/utils.rs b/neveko-core/src/utils.rs index dbc4109..ab6516d 100644 --- a/neveko-core/src/utils.rs +++ b/neveko-core/src/utils.rs @@ -14,6 +14,7 @@ use crate::{ utils, }; use clap::Parser; +use kn0sys_lmdb_rs::MdbError; use log::{ debug, error, @@ -49,13 +50,13 @@ pub struct ContactStatus { impl Default for ContactStatus { fn default() -> Self { ContactStatus { - exp: utils::empty_string(), - h_exp: utils::empty_string(), - i2p: utils::empty_string(), + exp: String::new(), + h_exp: String::new(), + i2p: String::new(), is_vendor: false, - jwp: utils::empty_string(), + jwp: String::new(), nick: String::from("anon"), - txp: utils::empty_string(), + txp: String::new(), } } } @@ -307,7 +308,7 @@ pub fn message_to_json(m: &models::Message) -> Json { let r_message: models::Message = models::Message { body: String::from(&m.body), mid: String::from(&m.mid), - uid: utils::empty_string(), + uid: String::new(), created: m.created, from: String::from(&m.from), to: String::from(&m.to), @@ -350,11 +351,6 @@ pub fn dispute_to_json(d: &models::Dispute) -> Json { Json(dispute) } -/// Instead of putting `String::from("")` -pub fn empty_string() -> String { - String::from("") -} - // DoS prevention pub const fn string_limit() -> usize { 512 @@ -411,35 +407,40 @@ async fn gen_app_wallet(password: &String) { } /// Secret keys for signing internal/external auth tokens -fn gen_signing_keys() { +fn gen_signing_keys() -> Result<(), MdbError> { info!("generating signing keys"); let jwp = get_jwp_secret_key(); let jwt = get_jwt_secret_key(); // send to db - let s = db::Interface::open(); - if jwp == utils::empty_string() { - let rnd_jwp = generate_rnd(); - db::Interface::write(&s.env, &s.handle, crate::NEVEKO_JWP_SECRET_KEY, &rnd_jwp); + let env = utils::get_release_env(); + if jwp.is_empty() { + let mut data = [0u8; 32]; + rand::thread_rng().fill_bytes(&mut data); + let s = db::DatabaseEnvironment::open(&env.value())?; + db::write_chunks(&s.env, &s.handle?, crate::NEVEKO_JWP_SECRET_KEY.as_bytes(), &data); } - if jwt == utils::empty_string() { - let rnd_jwt = generate_rnd(); - db::Interface::write(&s.env, &s.handle, crate::NEVEKO_JWT_SECRET_KEY, &rnd_jwt); + if jwt.is_empty() { + let mut data = [0u8; 32]; + rand::thread_rng().fill_bytes(&mut data); + let s = db::DatabaseEnvironment::open(&env.value())?; + db::write_chunks(&s.env, &s.handle?, crate::NEVEKO_JWT_SECRET_KEY.as_bytes(), &data); } + Ok(()) } /// TODO(c2m): add a button to gui to call this /// /// dont' forget to generate new keys as well pub fn revoke_signing_keys() { - let s = db::Interface::open(); - db::Interface::delete(&s.env, &s.handle, crate::NEVEKO_JWT_SECRET_KEY); - db::Interface::delete(&s.env, &s.handle, crate::NEVEKO_JWP_SECRET_KEY); + let s = db::DatabaseEnvironment::open(); + db::DatabaseEnvironment::delete(&s.env, &s.handle, crate::NEVEKO_JWT_SECRET_KEY); + db::DatabaseEnvironment::delete(&s.env, &s.handle, crate::NEVEKO_JWP_SECRET_KEY); } pub fn get_jwt_secret_key() -> String { - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, crate::NEVEKO_JWT_SECRET_KEY); - if r == utils::empty_string() { + let s = db::DatabaseEnvironment::open(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, crate::NEVEKO_JWT_SECRET_KEY); + if r.is_empty() { error!("JWT key not found"); return Default::default(); } @@ -447,9 +448,9 @@ pub fn get_jwt_secret_key() -> String { } pub fn get_jwp_secret_key() -> String { - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, crate::NEVEKO_JWP_SECRET_KEY); - if r == utils::empty_string() { + let s = db::DatabaseEnvironment::open(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, crate::NEVEKO_JWP_SECRET_KEY); + if r.is_empty() { error!("JWP key not found"); return Default::default(); } @@ -458,9 +459,9 @@ pub fn get_jwp_secret_key() -> String { /// Returns the hex encoded neveko message public key from LMDB pub fn get_nmpk() -> String { - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, crate::NEVEKO_NMPK); - if r == utils::empty_string() { + let s = db::DatabaseEnvironment::open(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, crate::NEVEKO_NMPK); + if r.is_empty() { error!("neveko message public key not found"); return Default::default(); } @@ -471,10 +472,10 @@ async fn generate_nmpk() { info!("generating neveko message public key"); let nmpk: String = get_nmpk(); // send to db - let s = db::Interface::open(); - if nmpk == utils::empty_string() { + let s = db::DatabaseEnvironment::open(); + if nmpk.is_empty() { let nmk: neveko25519::NevekoMessageKeys = neveko25519::generate_neveko_message_keys().await; - db::Interface::write(&s.env, &s.handle, crate::NEVEKO_NMPK, &nmk.hex_nmpk); + db::DatabaseEnvironment::write(&s.env, &s.handle, crate::NEVEKO_NMPK, &nmk.hex_nmpk); } } @@ -573,106 +574,15 @@ pub fn restart_dispute_auto_settle() { /// Called on app startup if `--clear-fts` flag is passed. fn clear_fts() { info!("clear fts"); - let s = db::Interface::open(); - db::Interface::delete(&s.env, &s.handle, crate::FTS_DB_KEY); + let s = db::DatabaseEnvironment::open(); + db::DatabaseEnvironment::delete(&s.env, &s.handle, crate::FTS_DB_KEY); } /// Called on app startup if `--clear-dispute` flag is passed. fn clear_disputes() { info!("clear_disputes"); - let s = db::Interface::open(); - db::Interface::delete(&s.env, &s.handle, crate::DISPUTE_LIST_DB_KEY); -} - -/// TODO(?): get rid of this after implementing monero bindings -/// -/// Handle the request from user to additional software -/// -/// from gui startup. Power users will most like install -/// -/// software on their own. Note that software pull is over -/// -/// clearnet. TODO(c2m): remove this after monero and i2pd -/// -/// are completed. -pub async fn install_software(installations: Installations) -> bool { - let mut valid_i2p_zero_hash = true; - let mut valid_xmr_hash = true; - if installations.i2p_zero { - info!("installing i2p-zero"); - let i2p_version = crate::I2P_ZERO_RELEASE_VERSION; - let i2p_zero_zip = format!("i2p-zero-linux.{}.zip", i2p_version); - let link = format!( - "https://github.com/creating2morrow/i2p-zero/releases/download/{}-neveko/{}", - i2p_version, i2p_zero_zip - ); - let curl = std::process::Command::new("curl") - .args(["-LO#", &link]) - .status(); - match curl { - Ok(curl_output) => { - debug!("{:?}", curl_output); - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - let unzip_output = std::process::Command::new("unzip") - .arg(&i2p_zero_zip) - .spawn() - .expect("i2p unzip failed"); - debug!("{:?}", unzip_output.stdout); - } - _ => error!("i2p-zero download failed"), - } - valid_i2p_zero_hash = validate_installation_hash(ExternalSoftware::I2PZero, &i2p_zero_zip); - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - } - if installations.xmr { - info!("installing monero"); - let link = format!( - "https://downloads.getmonero.org/cli/{}", - crate::MONERO_RELEASE_VERSION - ); - let curl = std::process::Command::new("curl") - .args(["-O#", &link]) - .status(); - match curl { - Ok(curl_output) => { - debug!("{:?}", curl_output); - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - let tar_output = std::process::Command::new("tar") - .args(["-xvf", crate::MONERO_RELEASE_VERSION]) - .spawn() - .expect("monero tar extraction failed"); - debug!("{:?}", tar_output.stdout); - } - _ => error!("monero download failed"), - } - valid_xmr_hash = validate_installation_hash( - ExternalSoftware::XMR, - &String::from(crate::MONERO_RELEASE_VERSION), - ); - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - } - valid_i2p_zero_hash && valid_xmr_hash -} - -/// Linux specific hash validation using the command `sha256sum` -fn validate_installation_hash(sw: ExternalSoftware, filename: &String) -> bool { - debug!("validating hash"); - let expected_hash = if sw == ExternalSoftware::I2PZero { - String::from(crate::I2P_ZERO_RELEASH_HASH) - } else { - String::from(crate::MONERO_RELEASE_HASH) - }; - let sha_output = std::process::Command::new("sha256sum") - .arg(filename) - .output() - .expect("hash validation failed"); - let str_sha = String::from_utf8(sha_output.stdout).unwrap(); - let split1 = str_sha.split(" "); - let mut v: Vec = split1.map(String::from).collect(); - let actual_hash = v.remove(0); - debug!("actual hash: {}", actual_hash); - debug!("expected hash: {}", expected_hash); - actual_hash == expected_hash + let s = db::DatabaseEnvironment::open(); + db::DatabaseEnvironment::delete(&s.env, &s.handle, crate::DISPUTE_LIST_DB_KEY); } /// ### The highly ineffecient fee estimator. @@ -700,7 +610,7 @@ pub async fn estimate_fee() -> u128 { let mut count: u64 = 1; let mut v_fee: Vec = Vec::new(); let mut r_height: reqres::XmrDaemonGetHeightResponse = Default::default(); - let remote_var = std::env::var(crate::GUI_REMOTE_NODE).unwrap_or(utils::empty_string()); + let remote_var = std::env::var(crate::GUI_REMOTE_NODE).unwrap_or(String::new()); let remote_set = remote_var == *crate::GUI_SET_REMOTE_NODE; if remote_set { let p_height = monero::p_get_height().await; @@ -780,11 +690,11 @@ pub async fn can_transfer(invoice: u128) -> bool { /// Gui toggle for vendor mode pub fn toggle_vendor_enabled() -> bool { // TODO(c2m): Dont toggle vendors with orders status != Delivered - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, contact::NEVEKO_VENDOR_ENABLED); + let s = db::DatabaseEnvironment::open(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, contact::NEVEKO_VENDOR_ENABLED); if r != contact::NEVEKO_VENDOR_MODE_ON { info!("neveko vendor mode enabled"); - db::Interface::write( + db::DatabaseEnvironment::write( &s.env, &s.handle, contact::NEVEKO_VENDOR_ENABLED, @@ -793,7 +703,7 @@ pub fn toggle_vendor_enabled() -> bool { true } else { info!("neveko vendor mode disabled"); - db::Interface::write( + db::DatabaseEnvironment::write( &s.env, &s.handle, contact::NEVEKO_VENDOR_ENABLED, @@ -804,21 +714,21 @@ pub fn toggle_vendor_enabled() -> bool { } pub fn search_gui_db(f: String, data: String) -> String { - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let k = format!("{}-{}", f, data); - db::Interface::read(&s.env, &s.handle, &k) + db::DatabaseEnvironment::read(&s.env, &s.handle, &k) } pub fn write_gui_db(f: String, key: String, data: String) { - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let k = format!("{}-{}", f, key); - db::Interface::write(&s.env, &s.handle, &k, &data); + db::DatabaseEnvironment::write(&s.env, &s.handle, &k, &data); } pub fn clear_gui_db(f: String, key: String) { - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(); let k = format!("{}-{}", f, key); - db::Interface::delete(&s.env, &s.handle, &k); + db::DatabaseEnvironment::delete(&s.env, &s.handle, &k); } // Tests diff --git a/neveko-gui/src/apps/address_book.rs b/neveko-gui/src/apps/address_book.rs index 2687c79..fe40b54 100644 --- a/neveko-gui/src/apps/address_book.rs +++ b/neveko-gui/src/apps/address_book.rs @@ -18,8 +18,8 @@ struct Compose { impl Default for Compose { fn default() -> Self { Compose { - message: utils::empty_string(), - to: utils::empty_string(), + message: String::new(), + to: String::new(), } } } @@ -86,7 +86,7 @@ impl Default for AddressBookApp { let (payment_tx, payment_rx) = std::sync::mpsc::channel(); let (send_message_tx, send_message_rx) = std::sync::mpsc::channel(); AddressBookApp { - add_nick: utils::empty_string(), + add_nick: String::new(), approve_contact: false, approve_payment: false, added: false, @@ -94,7 +94,7 @@ impl Default for AddressBookApp { can_transfer_rx, can_transfer_tx, compose: Default::default(), - contact: utils::empty_string(), + contact: String::new(), contacts: Vec::new(), contacts_init: false, contact_add_tx, @@ -103,7 +103,7 @@ impl Default for AddressBookApp { contact_info_rx, contact_timeout_tx, contact_timeout_rx, - find_contact: utils::empty_string(), + find_contact: String::new(), invoice_tx, invoice_rx, is_adding: false, @@ -134,7 +134,7 @@ impl eframe::App for AddressBookApp { //----------------------------------------------------------------------------------- if let Ok(contact_info) = self.contact_info_rx.try_recv() { self.s_contact = contact_info; - if self.s_contact.xmr_address != utils::empty_string() && !self.showing_status { + if !self.s_contact.xmr_address.is_empty() && !self.showing_status { self.approve_contact = true; } if self.showing_status { @@ -144,7 +144,7 @@ impl eframe::App for AddressBookApp { if let Ok(added_contact) = self.contact_add_rx.try_recv() { self.s_added_contact = added_contact; - if self.s_added_contact.cid != utils::empty_string() { + if !self.s_added_contact.cid.is_empty() { self.added = true; self.is_loading = false; } @@ -156,7 +156,7 @@ impl eframe::App for AddressBookApp { self.is_loading = false; self.is_adding = false; self.approve_contact = false; - self.contact = utils::empty_string(); + self.contact = String::new(); } } @@ -186,7 +186,7 @@ impl eframe::App for AddressBookApp { if self.is_message_sent { self.is_loading = false; self.is_composing = false; - self.compose.message = utils::empty_string(); + self.compose.message = String::new(); } } @@ -222,7 +222,7 @@ impl eframe::App for AddressBookApp { }); if !self.is_loading { self.compose.to = self.status.i2p.clone(); - if self.status.jwp != utils::empty_string() { + if !self.status.jwp.is_empty() { if ui.button("Send").clicked() { self.is_loading = true; send_message_req( @@ -243,7 +243,7 @@ impl eframe::App for AddressBookApp { // Payment approval window //----------------------------------------------------------------------------------- let mut is_approving_payment = - self.approve_payment && self.s_invoice.address != utils::empty_string(); + self.approve_payment && !self.s_invoice.address.is_empty(); let address = self.s_invoice.address.clone(); let amount = self.s_invoice.pay_threshold; let expire = self.s_invoice.conf_threshold; @@ -265,7 +265,7 @@ impl eframe::App for AddressBookApp { ui.label(format!("pay to: {}", address)); ui.label(format!("amount: {} piconero(s)", amount)); ui.label(format!("expiration: {} blocks", expire)); - let show_approve = self.s_invoice.address != utils::empty_string() + let show_approve = !self.s_invoice.address.is_empty() && self.can_transfer && !self.is_estimating_fee; if !self.is_loading { @@ -316,7 +316,7 @@ impl eframe::App for AddressBookApp { ui.add(egui::Spinner::new()); ui.label(spinner_text); } - let status = if self.s_contact.xmr_address != utils::empty_string() { + let status = if !self.s_contact.xmr_address.is_empty() { "online" } else { "offline" @@ -326,10 +326,10 @@ impl eframe::App for AddressBookApp { ui.label(format!("tx proof: {}", self.status.txp)); ui.label(format!("jwp: {}", self.status.jwp)); ui.label(format!("expiration: {}", self.status.h_exp)); - if self.status.jwp == utils::empty_string() + if self.status.jwp.is_empty() && !self.is_pinging && status == "online" - && self.status.txp == utils::empty_string() + && self.status.txp.is_empty() { if ui.button("Create JWP").clicked() { self.s_invoice = Default::default(); @@ -343,9 +343,9 @@ impl eframe::App for AddressBookApp { self.is_approving_jwp = true; } } - let failed_to_prove = self.status.txp != utils::empty_string() - && self.status.jwp == utils::empty_string(); - if self.status.jwp != utils::empty_string() || failed_to_prove { + let failed_to_prove = !self.status.txp.is_empty() + && self.status.jwp.is_empty(); + if !self.status.jwp.is_empty() || failed_to_prove { if ui.button("Clear stale JWP").clicked() { utils::clear_gui_db(String::from("gui-txp"), self.status.i2p.clone()); utils::clear_gui_db(String::from("gui-jwp"), self.status.i2p.clone()); @@ -353,8 +353,8 @@ impl eframe::App for AddressBookApp { self.showing_status = false; } } - if self.status.txp != utils::empty_string() - && self.status.jwp == utils::empty_string() + if !self.status.txp.is_empty() + && self.status.jwp.is_empty() && status == "online" { if ui.button("Prove Retry").clicked() { @@ -376,7 +376,7 @@ impl eframe::App for AddressBookApp { }); if ui.button("Change nick").clicked() { change_nick_req(self.status.i2p.clone(), self.add_nick.clone()); - self.add_nick = utils::empty_string(); + self.add_nick = String::new(); } if ui.button("Exit").clicked() { self.showing_status = false; @@ -419,7 +419,7 @@ impl eframe::App for AddressBookApp { ui.label(format!("i2p address: {}", self.s_added_contact.i2p_address)); if ui.button("Exit").clicked() { self.added = false; - self.contact = utils::empty_string(); + self.contact = String::new(); self.is_adding = false; self.approve_contact = false; self.contacts = contact::find_all(); @@ -541,7 +541,7 @@ impl eframe::App for AddressBookApp { String::from(crate::GUI_NICK_DB_KEY), String::from(&c.i2p_address), ); - let nick = if nick_db == utils::empty_string() { + let nick = if nick_db.is_empty() { String::from("anon") } else { nick_db @@ -587,7 +587,7 @@ impl eframe::App for AddressBookApp { Err(_e) => 0, }; if now < expire - && self.status.jwp != utils::empty_string() + && !self.status.jwp.is_empty() && c.i2p_address == self.status.i2p { if ui.button("Compose").clicked() { @@ -683,14 +683,14 @@ fn send_payment_req( subaddress: ptxp_address, confirmations: 0, hash: ptxp_hash, - message: utils::empty_string(), - signature: utils::empty_string(), + message: String::new(), + signature: String::new(), }; log::debug!("creating transaction proof for: {}", &ptxp.hash); // if we made it this far we can now request a JWP from our friend // wait a bit for the tx to propogate, i2p takes longer let wait = if std::env::var(neveko_core::GUI_REMOTE_NODE) - .unwrap_or(utils::empty_string()) + .unwrap_or(String::new()) == String::from(neveko_core::GUI_SET_REMOTE_NODE) { crate::I2P_PROPAGATION_TIME_IN_SECS_EST @@ -705,7 +705,7 @@ fn send_payment_req( subaddress: ftxp_address, confirmations: 0, hash: ftxp_hash, - message: utils::empty_string(), + message: String::new(), signature: get_txp.result.signature, }; utils::write_gui_db( @@ -765,7 +765,7 @@ fn send_payment_req( subaddress, confirmations: 0, hash: String::from(&hash), - message: utils::empty_string(), + message: String::new(), signature, }; log::debug!( @@ -795,8 +795,8 @@ fn send_message_req(tx: Sender, ctx: egui::Context, body: String, to: Stri let m: models::Message = models::Message { body: body, to, - mid: utils::empty_string(), - uid: utils::empty_string(), + mid: String::new(), + uid: String::new(), created: 0, from: i2p::get_destination(None), }; @@ -804,7 +804,7 @@ fn send_message_req(tx: Sender, ctx: egui::Context, body: String, to: Stri tokio::spawn(async move { let m_type = message::MessageType::Normal; let result = message::create(j_message, jwp, m_type).await; - if result.mid != utils::empty_string() { + if !result.mid.is_empty() { log::info!("sent message: {}", result.mid); let _ = tx.send(true); ctx.request_repaint(); diff --git a/neveko-gui/src/apps/home.rs b/neveko-gui/src/apps/home.rs index 9328e1b..e327edb 100644 --- a/neveko-gui/src/apps/home.rs +++ b/neveko-gui/src/apps/home.rs @@ -24,10 +24,6 @@ pub struct HomeApp { connections: utils::Connections, core_timeout_tx: Sender, core_timeout_rx: Receiver, - has_install_failed: bool, - installations: utils::Installations, - installation_tx: Sender, - installation_rx: Receiver, is_core_running: bool, is_editing_connections: bool, is_init: bool, @@ -111,10 +107,6 @@ impl Default for HomeApp { connections, core_timeout_rx, core_timeout_tx, - has_install_failed, - installations, - installation_rx, - installation_tx, is_core_running, is_editing_connections, is_init, @@ -208,7 +200,7 @@ impl eframe::App for HomeApp { .vscroll(true) .show(ctx, |ui| { let mut i2p_address = i2p::get_destination(None); - if !self.is_qr_set && i2p_address != utils::empty_string() { + if !self.is_qr_set && !i2p_address.is_empty() { let code = QrCode::new(&i2p_address).unwrap(); let image = code.render::>().build(); let file_path = format!( @@ -232,22 +224,6 @@ impl eframe::App for HomeApp { } }); - // Installation Error window - //----------------------------------------------------------------------------------- - let mut has_install_failed = self.has_install_failed; - egui::Window::new("error") - .open(&mut has_install_failed) - .title_bar(false) - .vscroll(false) - .show(&ctx, |ui| { - ui.heading("Installation Failure"); - if ui.button("Exit").clicked() { - self.has_install_failed = false; - self.is_installing = false; - self.is_loading = false; - } - }); - // Connection Manager window //----------------------------------------------------------------------------------- let mut is_editing_connections = self.is_editing_connections; @@ -343,42 +319,6 @@ impl eframe::App for HomeApp { } }); - // Installation Manager window - //----------------------------------------------------------------------------------- - let mut is_installing = self.is_installing; - egui::Window::new("installation") - .open(&mut is_installing) - .title_bar(false) - .vscroll(true) - .show(&ctx, |ui| { - ui.heading("Installation Manager"); - let mut wants_i2p_zero = self.installations.i2p_zero; - let mut wants_xmr = self.installations.xmr; - if ui.checkbox(&mut wants_i2p_zero, "i2p-zero").changed() { - self.installations.i2p_zero = !self.installations.i2p_zero; - } - if ui.checkbox(&mut wants_xmr, "xmr").changed() { - self.installations.xmr = !self.installations.xmr; - } - let install = &self.installations; - if install.i2p_zero || install.xmr { - if !self.is_loading { - if ui.button("Install").clicked() { - self.is_loading = true; - install_software_req( - self.installation_tx.clone(), - ctx.clone(), - &self.installations, - ); - } - } - } - if ui.button("Exit").clicked() { - self.is_installing = false; - self.is_loading = false; - } - }); - //---------------------------------------------------------------------------------------------- egui::CentralPanel::default().show(ctx, |ui| { if !self.is_updated { @@ -561,19 +501,3 @@ fn start_core_timeout(tx: Sender, ctx: egui::Context) { ctx.request_repaint(); }); } - -fn install_software_req( - tx: Sender, - ctx: egui::Context, - installations: &utils::Installations, -) { - let req_install: utils::Installations = utils::Installations { - i2p_zero: installations.i2p_zero, - xmr: installations.xmr, - }; - tokio::spawn(async move { - let did_install = utils::install_software(req_install).await; - let _ = tx.send(did_install); - ctx.request_repaint(); - }); -} diff --git a/neveko-gui/src/apps/lock_screen.rs b/neveko-gui/src/apps/lock_screen.rs index a6b182e..d19bc96 100644 --- a/neveko-gui/src/apps/lock_screen.rs +++ b/neveko-gui/src/apps/lock_screen.rs @@ -15,7 +15,7 @@ struct LockScreen { impl Default for LockScreen { fn default() -> Self { LockScreen { - credential: utils::empty_string(), + credential: String::new(), } } } @@ -62,8 +62,8 @@ impl eframe::App for LockScreenApp { self.lock_screen.credential.clone(), ); // Get the credential hash from lmdb - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, CREDENTIAL_KEY); + let s = db::DatabaseEnvironment::open(&utils::get_release_env().value()).unwrap(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, CREDENTIAL_KEY); // hash the text entered and compare let mut hasher = Sha512::new(); hasher.update(self.lock_screen.credential.clone()); diff --git a/neveko-gui/src/apps/mailbox.rs b/neveko-gui/src/apps/mailbox.rs index 0da0ac4..c1db9cd 100644 --- a/neveko-gui/src/apps/mailbox.rs +++ b/neveko-gui/src/apps/mailbox.rs @@ -23,7 +23,7 @@ impl Default for MailBoxApp { let (refresh_on_delete_tx, refresh_on_delete_rx) = std::sync::mpsc::channel(); let (deciphered_tx, deciphered_rx) = std::sync::mpsc::channel(); MailBoxApp { - deciphered: utils::empty_string(), + deciphered: String::new(), is_showing_decipher: false, messages: Vec::new(), message_init: false, @@ -67,7 +67,7 @@ impl eframe::App for MailBoxApp { ui.label(format!("{}", self.deciphered)); ui.label("\n"); if ui.button("Exit").clicked() { - self.deciphered = utils::empty_string(); + self.deciphered = String::new(); self.is_showing_decipher = false; } }); diff --git a/neveko-gui/src/apps/market.rs b/neveko-gui/src/apps/market.rs index f1c9b2c..8d5535e 100644 --- a/neveko-gui/src/apps/market.rs +++ b/neveko-gui/src/apps/market.rs @@ -39,15 +39,15 @@ impl Default for MultisigManagement { completed_prepare: false, completed_shipping_request: false, completed_make: false, - exchange_multisig_keys: utils::empty_string(), - export_info: utils::empty_string(), + exchange_multisig_keys: String::new(), + export_info: String::new(), has_adjudicator: false, - make_info: utils::empty_string(), - adjudicator: utils::empty_string(), - prepare_info: utils::empty_string(), + make_info: String::new(), + adjudicator: String::new(), + prepare_info: String::new(), query_adjudicator: false, - signed_txset: utils::empty_string(), - vendor: utils::empty_string(), + signed_txset: String::new(), + vendor: String::new(), } } } @@ -140,8 +140,8 @@ impl Default for MarketApp { let (_refresh_on_delete_product_tx, _refresh_on_delete_product_rx) = std::sync::mpsc::channel(); let read_product_image = std::fs::read("./assets/qr.png").unwrap_or(Vec::new()); - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, contact::NEVEKO_VENDOR_ENABLED); + let s = db::DatabaseEnvironment::open(&utils::get_release_env().value()).unwrap(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, contact::NEVEKO_VENDOR_ENABLED); let is_vendor_enabled = r == contact::NEVEKO_VENDOR_MODE_ON; let (contact_info_tx, contact_info_rx) = std::sync::mpsc::channel(); let (get_vendor_products_tx, get_vendor_products_rx) = std::sync::mpsc::channel(); @@ -164,10 +164,10 @@ impl Default for MarketApp { contact_timeout_rx, contact_timeout_tx, customer_orders: Vec::new(), - cipher: utils::empty_string(), + cipher: String::new(), ciphered_tx, ciphered_rx, - find_vendor: utils::empty_string(), + find_vendor: String::new(), get_vendor_products_rx, get_vendor_products_tx, get_vendor_product_rx, @@ -195,7 +195,7 @@ impl Default for MarketApp { is_window_shopping: false, msig: Default::default(), m_order: Default::default(), - order_xmr_address: utils::empty_string(), + order_xmr_address: String::new(), order_xmr_address_rx, order_xmr_address_tx, order_qr: egui_extras::RetainedImage::from_image_bytes("qr.png", &contents).unwrap(), @@ -206,8 +206,8 @@ impl Default for MarketApp { our_prepare_info_tx, new_order: Default::default(), new_order_price: 0, - new_order_shipping_address: utils::empty_string(), - new_order_quantity: utils::empty_string(), + new_order_shipping_address: String::new(), + new_order_quantity: String::new(), orders: Vec::new(), product_from_vendor: Default::default(), product_image: egui_extras::RetainedImage::from_image_bytes( @@ -216,12 +216,12 @@ impl Default for MarketApp { ) .unwrap(), products: Vec::new(), - product_update_pid: utils::empty_string(), - new_product_image: utils::empty_string(), - new_product_name: utils::empty_string(), - new_product_desc: utils::empty_string(), - new_product_price: utils::empty_string(), - new_product_qty: utils::empty_string(), + product_update_pid: String::new(), + new_product_image: String::new(), + new_product_name: String::new(), + new_product_desc: String::new(), + new_product_price: String::new(), + new_product_qty: String::new(), _refresh_on_delete_product_tx, _refresh_on_delete_product_rx, s_contact: Default::default(), @@ -238,7 +238,7 @@ impl Default for MarketApp { submit_txset_tx, vendor_status: Default::default(), vendors: Vec::new(), - upload_dinfo_str: utils::empty_string(), + upload_dinfo_str: String::new(), upload_dinfo_rx, upload_dinfo_tx, } @@ -252,7 +252,7 @@ impl eframe::App for MarketApp { if let Ok(submit_order) = self.submit_order_rx.try_recv() { self.s_order = submit_order; - if self.s_order.orid != utils::empty_string() { + if !self.s_order.orid.is_empty() { self.is_ordering = false; self.is_loading = false; } @@ -260,7 +260,7 @@ impl eframe::App for MarketApp { if let Ok(contact_info) = self.contact_info_rx.try_recv() { self.s_contact = contact_info; - if self.s_contact.xmr_address != utils::empty_string() { + if !self.s_contact.xmr_address.is_empty() { self.is_pinging = false; self.vendor_status.is_vendor = self.s_contact.is_vendor; } @@ -325,7 +325,7 @@ impl eframe::App for MarketApp { if let Ok(a) = self.order_xmr_address_rx.try_recv() { self.order_xmr_address = a.result.address; - if self.order_xmr_address != utils::empty_string() { + if !self.order_xmr_address.is_empty() { self.is_showing_order_qr = true; } } @@ -357,7 +357,7 @@ impl eframe::App for MarketApp { } if let Ok(disputed) = self.dispute_request_rx.try_recv() { - if disputed.tx_set != utils::empty_string() { + if !disputed.tx_set.is_empty() { log::info!("dispute in progress"); } self.is_loading = false; @@ -391,7 +391,7 @@ impl eframe::App for MarketApp { ui.add(egui::Spinner::new()); ui.label("pinging..."); } - let status = if self.s_contact.xmr_address != utils::empty_string() { + let status = if !self.s_contact.xmr_address.is_empty() { "online" } else { "offline" @@ -452,7 +452,7 @@ impl eframe::App for MarketApp { let adjudicator_db = utils::search_gui_db(String::from(&prefix), self.m_order.orid.clone()); log::debug!("adjudicator db: {}", adjudicator_db); - self.msig.has_adjudicator = adjudicator_db != utils::empty_string(); + self.msig.has_adjudicator = !adjudicator_db.is_empty(); self.msig.adjudicator = adjudicator_db; self.msig.query_adjudicator = true; } else if self.msig.query_adjudicator && !self.msig.has_adjudicator { @@ -473,7 +473,7 @@ impl eframe::App for MarketApp { if !self.msig.completed_prepare { if ui.button("Clear Mediator").clicked() { utils::clear_gui_db(prefix, self.m_order.orid.clone()); - self.msig.adjudicator = utils::empty_string(); + self.msig.adjudicator = String::new(); self.msig.has_adjudicator = false; self.msig.query_adjudicator = false; } @@ -695,7 +695,7 @@ impl eframe::App for MarketApp { String::from(crate::GUI_MSIG_EXPORT_DB_KEY), String::from(&self.m_order.orid.clone()), ); - if info != utils::empty_string() { + if !info.is_empty() { self.msig.completed_export = true; } } @@ -779,7 +779,7 @@ impl eframe::App for MarketApp { .title_bar(false) .vscroll(true) .show(ctx, |ui| { - if !self.is_order_qr_set && self.order_xmr_address != utils::empty_string() { + if !self.is_order_qr_set && !self.order_xmr_address.is_empty() { let code = QrCode::new(&self.order_xmr_address.clone()).unwrap(); let image = code.render::>().build(); let file_path = format!( @@ -814,7 +814,7 @@ impl eframe::App for MarketApp { ui.label(format!("{}", self.cipher)); ui.label("\n"); if ui.button("Exit").clicked() { - self.cipher = utils::empty_string(); + self.cipher = String::new(); self.is_showing_deciphered_delivery_info = false; } }); @@ -1026,8 +1026,8 @@ impl eframe::App for MarketApp { ); self.new_order = Default::default(); self.new_order_price = 0; - self.new_order_quantity = utils::empty_string(); - self.new_order_shipping_address = utils::empty_string(); + self.new_order_quantity = String::new(); + self.new_order_shipping_address = String::new(); self.is_showing_products = false; } } @@ -1057,8 +1057,8 @@ impl eframe::App for MarketApp { ui.text_edit_singleline(&mut self.upload_dinfo_str) .labelled_by(delivery_info.id); }); - if self.new_order.orid != utils::empty_string() - && self.upload_dinfo_str != utils::empty_string() + if !self.new_order.orid.is_empty() + && !self.upload_dinfo_str.is_empty() { if ui.button("Trigger NASR").clicked() { // upload delivery info @@ -1146,7 +1146,7 @@ impl eframe::App for MarketApp { String::from(crate::GUI_NICK_DB_KEY), String::from(&v.i2p_address), ); - let nick = if nick_db == utils::empty_string() { + let nick = if nick_db.is_empty() { String::from("anon") } else { nick_db @@ -1199,7 +1199,7 @@ impl eframe::App for MarketApp { Err(_e) => 0, }; if now < expire - && self.vendor_status.jwp != utils::empty_string() + && !self.vendor_status.jwp.is_empty() && v.i2p_address == self.vendor_status.i2p && self.vendor_status.is_vendor { @@ -1239,7 +1239,7 @@ impl eframe::App for MarketApp { ui.add(egui::Spinner::new()); ui.label("pinging..."); } - let status = if self.s_contact.xmr_address != utils::empty_string() { + let status = if !self.s_contact.xmr_address.is_empty() { "online" } else { "offline" @@ -1495,20 +1495,20 @@ impl eframe::App for MarketApp { }; let j_product = utils::product_to_json(&product); product::modify(j_product); - self.new_product_desc = utils::empty_string(); - self.new_product_name = utils::empty_string(); - self.new_product_price = utils::empty_string(); - self.new_product_qty = utils::empty_string(); - self.new_product_image = utils::empty_string(); + self.new_product_desc = String::new(); + self.new_product_name = String::new(); + self.new_product_price = String::new(); + self.new_product_qty = String::new(); + self.new_product_image = String::new(); self.is_showing_product_update = false; self.products = product::find_all(); } if ui.button("Exit").clicked() { - self.new_product_desc = utils::empty_string(); - self.new_product_name = utils::empty_string(); - self.new_product_price = utils::empty_string(); - self.new_product_qty = utils::empty_string(); - self.new_product_image = utils::empty_string(); + self.new_product_desc = String::new(); + self.new_product_name = String::new(); + self.new_product_price = String::new(); + self.new_product_qty = String::new(); + self.new_product_image = String::new(); self.is_showing_product_update = false; } }); @@ -1688,7 +1688,7 @@ impl eframe::App for MarketApp { Err(_) => 0, }; let product: models::Product = models::Product { - pid: utils::empty_string(), + pid: String::new(), description: self.new_product_desc.clone(), image, in_stock: qty > 0, @@ -1698,11 +1698,11 @@ impl eframe::App for MarketApp { }; let j_product = utils::product_to_json(&product); product::create(j_product); - self.new_product_desc = utils::empty_string(); - self.new_product_name = utils::empty_string(); - self.new_product_price = utils::empty_string(); - self.new_product_qty = utils::empty_string(); - self.new_product_image = utils::empty_string(); + self.new_product_desc = String::new(); + self.new_product_name = String::new(); + self.new_product_price = String::new(); + self.new_product_qty = String::new(); + self.new_product_image = String::new(); } ui.label("\n"); if ui.button("View Products").clicked() { @@ -1833,13 +1833,13 @@ fn send_prepare_info_req( ); let v_jwp: String = utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor)); - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::create_wallet(&w_orid, &wallet_password).await; let m_wallet = monero::open_wallet(&w_orid, &wallet_password).await; if !m_wallet { log::error!("failed to open wallet"); monero::close_wallet(&w_orid, &wallet_password).await; - let _ = tx.send(utils::empty_string()); + let _ = tx.send(String::new()); return; } monero::close_wallet(&w_orid, &wallet_password).await; @@ -1853,7 +1853,7 @@ fn send_prepare_info_req( ); // Request adjudicator and vendor while we're at it // Will coordinating send this on make requests next - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; let m_msig_key = format!( "{}-{}-{}", message::PREPARE_MSIG, @@ -1866,9 +1866,9 @@ fn send_prepare_info_req( String::from(&v_orid), vendor ); - let m_prepare = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await; - let v_prepare = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await; - if v_prepare == utils::empty_string() { + let m_prepare = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await; + let v_prepare = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await; + if v_prepare.is_empty() { log::debug!( "constructing vendor {} msig messages", message::PREPARE_MSIG @@ -1883,7 +1883,7 @@ fn send_prepare_info_req( }; let _v_result = message::d_trigger_msig_info(&vendor, &v_jwp, &v_msig_request).await; } - if m_prepare == utils::empty_string() { + if m_prepare.is_empty() { log::debug!( "constructing adjudicator {} msig messages", message::PREPARE_MSIG @@ -1921,12 +1921,12 @@ fn send_make_info_req( ); let v_jwp: String = utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor)); - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); let m_wallet = monero::open_wallet(&w_orid, &wallet_password).await; if !m_wallet { monero::close_wallet(&w_orid, &wallet_password).await; log::error!("failed to open wallet"); - let _ = tx.send(utils::empty_string()); + let _ = tx.send(String::new()); return; } let mut prepare_info_prep = Vec::new(); @@ -1938,7 +1938,7 @@ fn send_make_info_req( String::from(crate::GUI_MSIG_PREPARE_DB_KEY), String::from(&w_orid), ); - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; let m_msig_key = format!( "{}-{}-{}", message::PREPARE_MSIG, @@ -1951,8 +1951,8 @@ fn send_make_info_req( String::from(&v_orid), vendor ); - let m_prepare = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await; - let v_prepare = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await; + let m_prepare = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await; + let v_prepare = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await; prepare_info_prep.push(String::from(&m_prepare)); prepare_info_prep.push(String::from(&v_prepare)); m_prepare_info_send.push(String::from(&c_prepare)); @@ -1963,11 +1963,11 @@ fn send_make_info_req( String::from(crate::GUI_MSIG_MAKE_DB_KEY), String::from(&w_orid), ); - if local_make == utils::empty_string() { + if local_make.is_empty() { let make_info = monero::make_wallet(prepare_info_prep).await; monero::close_wallet(&w_orid, &wallet_password).await; let ref_make_info: &String = &make_info.result.multisig_info; - if String::from(ref_make_info) != utils::empty_string() { + if !String::from(ref_make_info).is_empty() { utils::write_gui_db( String::from(crate::GUI_MSIG_MAKE_DB_KEY), String::from(&w_orid), @@ -1978,7 +1978,7 @@ fn send_make_info_req( // Request adjudicator and vendor while we're at it // Will coordinating send this on make requests next - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; let m_msig_key = format!( "{}-{}-{}", message::MAKE_MSIG, @@ -1991,9 +1991,9 @@ fn send_make_info_req( String::from(&v_orid), vendor ); - let m_make = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await; - let v_make = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await; - if v_make == utils::empty_string() { + let m_make = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await; + let v_make = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await; + if v_make.is_empty() { log::debug!("constructing vendor {} msig messages", message::MAKE_MSIG); let v_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest { contact: i2p::get_destination(None), @@ -2005,7 +2005,7 @@ fn send_make_info_req( }; let _v_result = message::d_trigger_msig_info(&vendor, &v_jwp, &v_msig_request).await; } - if m_make == utils::empty_string() { + if m_make.is_empty() { log::debug!( "constructing adjudicator {} msig messages", message::MAKE_MSIG @@ -2043,12 +2043,12 @@ fn send_kex_initial_req( ); let v_jwp: String = utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor)); - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); let m_wallet = monero::open_wallet(&w_orid, &wallet_password).await; if !m_wallet { monero::close_wallet(&w_orid, &wallet_password).await; log::error!("failed to open wallet"); - let _ = tx.send(utils::empty_string()); + let _ = tx.send(String::new()); return; } let mut kex_init_prep = Vec::new(); @@ -2060,7 +2060,7 @@ fn send_kex_initial_req( String::from(crate::GUI_MSIG_MAKE_DB_KEY), String::from(&w_orid), ); - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; let m_msig_key = format!( "{}-{}-{}", message::MAKE_MSIG, @@ -2073,8 +2073,8 @@ fn send_kex_initial_req( String::from(&v_orid), vendor ); - let m_kex_init = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await; - let v_kex_init = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await; + let m_kex_init = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await; + let v_kex_init = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await; kex_init_prep.push(String::from(&m_kex_init)); kex_init_prep.push(String::from(&v_kex_init)); m_kex_init_send.push(String::from(&c_kex_init)); @@ -2085,12 +2085,12 @@ fn send_kex_initial_req( String::from(crate::GUI_MSIG_KEX_ONE_DB_KEY), String::from(&w_orid), ); - if local_kex_init == utils::empty_string() { + if local_kex_init.is_empty() { let kex_out = monero::exchange_multisig_keys(false, kex_init_prep, &wallet_password).await; monero::close_wallet(&w_orid, &wallet_password).await; let ref_kex_info: &String = &kex_out.result.multisig_info; - if String::from(ref_kex_info) != utils::empty_string() { + if !String::from(ref_kex_info).is_empty() { utils::write_gui_db( String::from(crate::GUI_MSIG_KEX_ONE_DB_KEY), String::from(&w_orid), @@ -2100,7 +2100,7 @@ fn send_kex_initial_req( } // Request adjudicator and vendor while we're at it // Will coordinating send this on kex round two next - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; let m_msig_key = format!( "{}-{}-{}", message::KEX_ONE_MSIG, @@ -2113,9 +2113,9 @@ fn send_kex_initial_req( String::from(&v_orid), vendor ); - let m_kex_init = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await; - let v_kex_init = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await; - if v_kex_init == utils::empty_string() { + let m_kex_init = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await; + let v_kex_init = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await; + if v_kex_init.is_empty() { log::debug!( "constructing vendor {} msig messages", message::KEX_ONE_MSIG @@ -2130,7 +2130,7 @@ fn send_kex_initial_req( }; let _v_result = message::d_trigger_msig_info(&vendor, &v_jwp, &v_msig_request).await; } - if m_kex_init == utils::empty_string() { + if m_kex_init.is_empty() { log::debug!( "constructing adjudicator {} msig messages", message::KEX_ONE_MSIG @@ -2168,12 +2168,12 @@ fn send_kex_final_req( ); let v_jwp: String = utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor)); - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); let m_wallet = monero::open_wallet(&w_orid, &wallet_password).await; if !m_wallet { monero::close_wallet(&w_orid, &wallet_password).await; log::error!("failed to open wallet"); - let _ = tx.send(utils::empty_string()); + let _ = tx.send(String::new()); return; } let mut kex_final_prep = Vec::new(); @@ -2183,7 +2183,7 @@ fn send_kex_final_req( String::from(crate::GUI_MSIG_KEX_ONE_DB_KEY), String::from(&w_orid), ); - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; let m_msig_key = format!( "{}-{}-{}", message::KEX_ONE_MSIG, @@ -2196,8 +2196,8 @@ fn send_kex_final_req( String::from(&v_orid), vendor ); - let m_kex_final = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await; - let v_kex_final = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await; + let m_kex_final = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await; + let v_kex_final = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await; kex_final_prep.push(String::from(&m_kex_final)); kex_final_prep.push(String::from(&v_kex_final)); m_kex_final_send.push(String::from(&c_kex_final)); @@ -2208,12 +2208,12 @@ fn send_kex_final_req( String::from(crate::GUI_MSIG_KEX_TWO_DB_KEY), String::from(&w_orid), ); - if local_kex_final == utils::empty_string() { + if local_kex_final.is_empty() { let kex_out = monero::exchange_multisig_keys(false, kex_final_prep, &wallet_password).await; monero::close_wallet(&w_orid, &wallet_password).await; let ref_kex_info: &String = &kex_out.result.address; - if String::from(ref_kex_info) != utils::empty_string() { + if !String::from(ref_kex_info).is_empty() { utils::write_gui_db( String::from(crate::GUI_MSIG_KEX_TWO_DB_KEY), String::from(&w_orid), @@ -2222,7 +2222,7 @@ fn send_kex_final_req( } } // we can verify all good if the senders all send back the correct wallet address - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; let m_msig_key = format!( "{}-{}-{}", message::KEX_TWO_MSIG, @@ -2235,9 +2235,9 @@ fn send_kex_final_req( String::from(&v_orid), vendor ); - let m_kex_final = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await; - let v_kex_final = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await; - if v_kex_final == utils::empty_string() { + let m_kex_final = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await; + let v_kex_final = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await; + if v_kex_final.is_empty() { log::debug!( "constructing vendor {} msig messages", message::KEX_TWO_MSIG @@ -2252,7 +2252,7 @@ fn send_kex_final_req( }; let _v_result = message::d_trigger_msig_info(&vendor, &v_jwp, &v_msig_request).await; } - if m_kex_final == utils::empty_string() { + if m_kex_final.is_empty() { log::debug!( "constructing adjudicator {} msig messages", message::KEX_TWO_MSIG @@ -2276,7 +2276,7 @@ fn send_kex_final_req( fn set_order_address(orid: &String, tx: Sender, ctx: egui::Context) { let order_id = String::from(orid); tokio::spawn(async move { - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::open_wallet(&order_id, &wallet_password).await; let address: reqres::XmrRpcAddressResponse = monero::get_address().await; monero::close_wallet(&order_id, &wallet_password).await; @@ -2295,7 +2295,7 @@ fn verify_order_wallet_funded( let l_contact = String::from(contact); tokio::spawn(async move { log::info!("executing verify_order_wallet_funded"); - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::open_wallet(&order_id, &wallet_password).await; let _ = monero::refresh().await; let pre_bal = monero::get_balance().await; @@ -2334,12 +2334,12 @@ fn send_import_info_req(tx: Sender, ctx: egui::Context, orid: &String, v tokio::spawn(async move { let v_jwp: String = utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor)); - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); let m_wallet = monero::open_wallet(&w_orid, &wallet_password).await; if !m_wallet { log::error!("failed to open wallet"); monero::close_wallet(&w_orid, &wallet_password).await; - let _ = tx.send(utils::empty_string()); + let _ = tx.send(String::new()); return; } let mut info: Vec = Vec::new(); @@ -2353,15 +2353,15 @@ fn send_import_info_req(tx: Sender, ctx: egui::Context, orid: &String, v ); // Request vendor while we're at it // Will coordinating send this on make requests next - let s = db::Interface::async_open().await; + let s = db::DatabaseEnvironment::async_open().await; let v_msig_key = format!( "{}-{}-{}", message::EXPORT_MSIG, String::from(&v_orid), vendor ); - let v_export = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await; - if v_export == utils::empty_string() { + let v_export = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await; + if v_export.is_empty() { log::debug!("constructing vendor {} msig messages", message::EXPORT_MSIG); let v_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest { contact: i2p::get_destination(None), @@ -2422,14 +2422,14 @@ fn validate_msig_step( vendor: &String, sub_type: &String, ) -> bool { - let s = db::Interface::open(); + let s = db::DatabaseEnvironment::open(&utils::get_release_env().value()).unwrap(); let m_msig_key = format!("{}-{}-{}", sub_type, orid, adjudicator); let v_msig_key = format!("{}-{}-{}", sub_type, orid, vendor); - let m_info = db::Interface::read(&s.env, &s.handle, &m_msig_key); - let v_info = db::Interface::read(&s.env, &s.handle, &v_msig_key); + let m_info = db::DatabaseEnvironment::read(&s.env, &s.handle, &m_msig_key); + let v_info = db::DatabaseEnvironment::read(&s.env, &s.handle, &v_msig_key); log::debug!("{} adjudicator info: {}", sub_type, &m_info); log::debug!("{} vendor info: {}", sub_type, &v_info); - m_info != utils::empty_string() && v_info != utils::empty_string() + !m_info.is_empty() && !v_info.is_empty() } fn release_txset(contact: String, orid: String, ctx: egui::Context, tx: Sender) { @@ -2454,7 +2454,7 @@ fn upload_dinfo_req(dinfo: String, orid: String, ctx: egui::Context, tx: Sender< tokio::spawn(async move { log::info!("async upload_dinfo_req"); let dinfo = order::upload_delivery_info(&orid, &dinfo).await; - let _ = tx.send(dinfo.orid != utils::empty_string()); + let _ = tx.send(!dinfo.orid.is_empty()); ctx.request_repaint(); }); } @@ -2477,7 +2477,7 @@ fn create_dispute_req( let address_res = monero::get_address().await; monero::close_wallet(&wallet_name, &wallet_password).await; // generate a txset for the adjudicator - let wallet_password = utils::empty_string(); + let wallet_password = String::new(); monero::open_wallet(&d_orid, &wallet_password).await; let transfer = monero::sweep_all(String::from(address_res.result.address)).await; monero::close_wallet(&d_orid, &wallet_password).await; diff --git a/neveko-gui/src/apps/settings.rs b/neveko-gui/src/apps/settings.rs index 7ecdc8f..58d5a81 100644 --- a/neveko-gui/src/apps/settings.rs +++ b/neveko-gui/src/apps/settings.rs @@ -22,7 +22,7 @@ impl Default for SettingsApp { fn default() -> Self { let (change_wallet_password_tx, change_wallet_password_rx) = std::sync::mpsc::channel(); SettingsApp { - credential: utils::empty_string(), + credential: String::new(), change_wallet_password_rx, change_wallet_password_tx, is_loading: false, @@ -63,20 +63,23 @@ impl eframe::App for SettingsApp { } if ui.button("Change").clicked() { self.is_loading = true; - let s = db::Interface::open(); + + // TODO: don't open the database in the GUI + + let s = db::DatabaseEnvironment::open(&utils::get_release_env().value()).unwrap(); let k = CREDENTIAL_KEY; - db::Interface::delete(&s.env, &s.handle, &k); + db::DatabaseEnvironment::delete(&s.env, &s.handle, &k); let mut hasher = Sha512::new(); hasher.update(self.credential.clone()); let result = hasher.finalize(); - db::Interface::write(&s.env, &s.handle, &k, &hex::encode(&result[..])); + db::write_chunks(&s.env, &s.handle, &k, &hex::encode(&result[..])); // update wallet rpc change_wallet_password( self.change_wallet_password_tx.clone(), &self.credential, ctx.clone(), ); - self.credential = utils::empty_string(); + self.credential = String::new(); } }); }); diff --git a/neveko-gui/src/apps/wallet.rs b/neveko-gui/src/apps/wallet.rs index bf09b14..4f3904d 100644 --- a/neveko-gui/src/apps/wallet.rs +++ b/neveko-gui/src/apps/wallet.rs @@ -34,12 +34,12 @@ impl Default for WalletApp { is_showing_qr: false, is_showing_sweep_result: false, qr: egui_extras::RetainedImage::from_image_bytes("qr.png", &contents).unwrap(), - sweep_address: utils::empty_string(), + sweep_address: String::new(), xmr_address_rx, xmr_address_tx, xmr_sweep_all_rx, xmr_sweep_all_tx, - s_xmr_address: utils::empty_string(), + s_xmr_address: String::new(), x_xmr_sweep_res: Default::default(), } } @@ -85,7 +85,7 @@ impl eframe::App for WalletApp { .title_bar(false) .vscroll(true) .show(ctx, |ui| { - if !self.is_qr_set && self.s_xmr_address != utils::empty_string() { + if !self.is_qr_set && !self.s_xmr_address.is_empty() { let code = QrCode::new(&self.s_xmr_address.clone()).unwrap(); let image = code.render::>().build(); let file_path = format!( @@ -135,7 +135,7 @@ impl eframe::App for WalletApp { ctx.clone(), self.sweep_address.clone(), ); - self.sweep_address = utils::empty_string(); + self.sweep_address = String::new(); self.is_showing_sweep_result = true; self.is_loading = true; } diff --git a/neveko-gui/src/login.rs b/neveko-gui/src/login.rs index d3660f8..2618a32 100644 --- a/neveko-gui/src/login.rs +++ b/neveko-gui/src/login.rs @@ -14,7 +14,7 @@ pub struct LoginApp { impl Default for LoginApp { fn default() -> Self { - let credential = utils::empty_string(); + let credential = String::new(); let is_cred_generated = false; let is_not_showing_password = true; LoginApp { @@ -54,9 +54,9 @@ impl eframe::App for LoginApp { let mut hasher = Sha512::new(); hasher.update(self.credential.clone()); let result = hasher.finalize(); - let s = db::Interface::open(); - db::Interface::write(&s.env, &s.handle, k, &hex::encode(&result[..])); - self.credential = utils::empty_string(); + let s = db::DatabaseEnvironment::open(); + db::DatabaseEnvironment::write(&s.env, &s.handle, k, &hex::encode(&result[..])); + self.credential = String::new(); } }); } diff --git a/neveko-gui/src/wrap_app.rs b/neveko-gui/src/wrap_app.rs index 99ba246..ab69c73 100644 --- a/neveko-gui/src/wrap_app.rs +++ b/neveko-gui/src/wrap_app.rs @@ -236,9 +236,9 @@ impl WrapApp { ctx.set_pixels_per_point(1.5); // initial cred check, is there a better way to do this? if !self.state.is_cred_set { - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, crate::CREDENTIAL_KEY); - if r != utils::empty_string() { + let s = db::DatabaseEnvironment::open(&utils::get_release_env().value()).unwrap(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, crate::CREDENTIAL_KEY); + if !r.is_empty() { self.state.is_cred_set = true; self.state.is_checking_cred = false; } @@ -308,9 +308,9 @@ impl WrapApp { loop { log::debug!("check for cred"); tokio::time::sleep(std::time::Duration::from_secs(5)).await; - let s = db::Interface::open(); - let r = db::Interface::read(&s.env, &s.handle, crate::CREDENTIAL_KEY); - if r == utils::empty_string() { + let s = db::DatabaseEnvironment::open(&utils::get_release_env().value()).unwrap(); + let r = db::DatabaseEnvironment::read(&s.env, &s.handle, crate::CREDENTIAL_KEY); + if r.is_empty() { log::debug!("credential not found"); let _ = tx.send(false); ctx.request_repaint(); diff --git a/src/controller.rs b/src/controller.rs index d0d6df5..97ebcc0 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -121,7 +121,7 @@ pub async fn retrieve_order( _jwp: proof::PaymentProof, ) -> Custom> { let m_order = order::secure_retrieval(&orid, &signature).await; - if m_order.cid == utils::empty_string() { + if m_order.cid.is_empty() { return Custom(Status::BadRequest, Json(Default::default())); } Custom(Status::Created, Json(m_order)) @@ -205,7 +205,7 @@ pub async fn trigger_nasr( _jwp: proof::PaymentProof, ) -> Custom> { let order: models::Order = order::d_trigger_ship_request(&vendor, &orid).await; - if order.orid == utils::empty_string() { + if order.orid.is_empty() { return Custom(Status::BadRequest, Json(Default::default())); } Custom(Status::Ok, Json(order)) @@ -223,7 +223,7 @@ pub async fn cancel_order( _jwp: proof::PaymentProof, ) -> Custom> { let m_order = order::cancel_order(&orid, &signature).await; - if m_order.cid == utils::empty_string() { + if m_order.cid.is_empty() { return Custom(Status::BadRequest, Json(Default::default())); } Custom(Status::Ok, Json(m_order))