diff --git a/Cargo.lock b/Cargo.lock index 9e633f6..d7fb3ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -269,18 +269,21 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9ff0bbfd639f15c74af777d81383cf53efb7c93613f6cab67c6c11e05bbf8b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bit-vec" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" - [[package]] name = "bitflags" version = "1.3.2" @@ -289,9 +292,12 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +dependencies = [ + "serde_core", +] [[package]] name = "blake2-rfc" @@ -593,6 +599,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.20" @@ -830,6 +845,15 @@ dependencies = [ "syn 2.0.86", ] +[[package]] +name = "doxygen-rs" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415b6ec780d34dcf624666747194393603d0373b7141eef01d12ee58881507d9" +dependencies = [ + "phf", +] + [[package]] name = "easy-jsonrpc-mw" version = "0.5.4" @@ -1146,12 +1170,6 @@ dependencies = [ "slab", ] -[[package]] -name = "gcc" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" - [[package]] name = "generic-array" version = "0.12.4" @@ -1205,7 +1223,7 @@ version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b88256088d75a56f8ecfa070513a775dd9107f6530ef14919dac831af9cfe2b" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.11.1", "libc", "libgit2-sys", "log", @@ -1373,8 +1391,8 @@ dependencies = [ "croaring", "grin_core", "grin_util", + "heed", "libc", - "lmdb-zero", "log", "memmap", "serde", @@ -1670,6 +1688,44 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heed" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad82d6598ccf1dac15c8b758a1bd282b755b6776be600429176757190a1b0202" +dependencies = [ + "bitflags 2.11.1", + "byteorder", + "heed-traits", + "heed-types", + "libc", + "lmdb-master-sys", + "once_cell", + "page_size", + "serde", + "synchronoise", + "url", +] + +[[package]] +name = "heed-traits" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3130048d404c57ce5a1ac61a903696e8fcde7e8c2991e9fcfc1f27c3ef74ff" + +[[package]] +name = "heed-types" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c255bdf46e07fb840d120a36dcc81f385140d7191c76a7391672675c01a55d" +dependencies = [ + "bincode", + "byteorder", + "heed-traits", + "serde", + "serde_json", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -2209,9 +2265,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libgit2-sys" @@ -2225,23 +2281,13 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "liblmdb-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feed38a3a580f60bf61aaa067b0ff4123395966839adeaf67258a9e50c4d2e49" -dependencies = [ - "gcc", - "libc", -] - [[package]] name = "libredox" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.11.1", "libc", ] @@ -2287,15 +2333,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] -name = "lmdb-zero" -version = "0.4.4" +name = "lmdb-master-sys" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13416eee745b087c22934f35f1f24da22da41ba2a5ce197143d168ce055cc58d" +checksum = "aaeb9bd22e73bd1babffff614994b341e9b2008de7bb73bf1f7e9154f1978f8b" dependencies = [ - "bitflags 0.9.1", + "cc", + "doxygen-rs", "libc", - "liblmdb-sys", - "supercow", ] [[package]] @@ -2497,7 +2542,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c624fa1b7aab6bd2aff6e9b18565cc0363b6d45cbcd7465c9ed5e3740ebf097" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.11.1", "libc", "nix 0.26.4", "smallstr", @@ -2689,9 +2734,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.2" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "opaque-debug" @@ -2711,7 +2756,7 @@ version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.11.1", "cfg-if 1.0.0", "foreign-types", "libc", @@ -2767,6 +2812,16 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "parking_lot" version = "0.10.2" @@ -2859,6 +2914,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros", "phf_shared", ] @@ -2882,6 +2938,19 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.86", +] + [[package]] name = "phf_shared" version = "0.11.2" @@ -3287,7 +3356,7 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.11.1", ] [[package]] @@ -3508,7 +3577,7 @@ version = "0.38.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.11.1", "errno", "libc", "linux-raw-sys", @@ -3687,7 +3756,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.11.1", "core-foundation", "core-foundation-sys", "libc", @@ -3736,10 +3805,11 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] @@ -3754,10 +3824,19 @@ dependencies = [ ] [[package]] -name = "serde_derive" -version = "1.0.214" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2 1.0.89", "quote 1.0.37", @@ -3766,14 +3845,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa 1.0.11", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] @@ -3958,12 +4038,6 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" -[[package]] -name = "supercow" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171758edb47aa306a78dfa4ab9aeb5167405bd4e3dc2b64e88f6a84bbe98bd63" - [[package]] name = "syn" version = "0.15.44" @@ -3997,6 +4071,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synchronoise" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dbc01390fc626ce8d1cffe3376ded2b72a11bb70e1c75f404a210e4daa4def2" +dependencies = [ + "crossbeam-queue", +] + [[package]] name = "synstructure" version = "0.13.2" @@ -4990,3 +5073,9 @@ dependencies = [ "crc32fast", "thiserror", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/impls/src/backends/lmdb.rs b/impls/src/backends/lmdb.rs index e0df269..c7e6808 100644 --- a/impls/src/backends/lmdb.rs +++ b/impls/src/backends/lmdb.rs @@ -16,17 +16,17 @@ use std::cell::RefCell; use std::{fs, path}; // for writing stored transaction files +use byteorder::BigEndian; use std::fs::File; use std::io::{Read, Write}; use std::marker::PhantomData; use std::path::Path; - use uuid::Uuid; use crate::blake2::blake2b::{Blake2b, Blake2bResult}; use crate::keychain::{ChildNumber, ExtKeychain, Identifier, Keychain, SwitchCommitmentType}; -use crate::store::{self, option_to_not_found, to_key, to_key_u64}; +use crate::store::{self, option_to_not_found}; use crate::core::core::Transaction; use crate::core::ser; @@ -40,6 +40,7 @@ use crate::util::{self, secp, ToHex}; use rand::rngs::mock::StepRng; use rand::thread_rng; +use tokio::io::AsyncWriteExt; pub const DB_DIR: &str = "db"; pub const TX_SAVE_DIR: &str = "saved_txs"; @@ -56,10 +57,22 @@ const LAST_SCANNED_KEY: &str = "LAST_SCANNED_KEY"; const WALLET_INIT_STATUS: u8 = b'w'; const WALLET_INIT_STATUS_KEY: &str = "WALLET_INIT_STATUS"; +const DB_PREFIXES: [u8; 9] = [ + OUTPUT_PREFIX, + DERIV_PREFIX, + CONFIRMED_HEIGHT_PREFIX, + PRIVATE_TX_CONTEXT_PREFIX, + TX_LOG_ENTRY_PREFIX, + TX_LOG_ID_PREFIX, + ACCOUNT_PATH_MAPPING_PREFIX, + LAST_SCANNED_BLOCK, + WALLET_INIT_STATUS, +]; + /// test to see if database files exist in the current directory. If so, /// use a DB backend for all operations pub fn wallet_db_exists(data_file_dir: &str) -> bool { - let db_path = path::Path::new(data_file_dir).join(DB_DIR); + let db_path = Path::new(data_file_dir).join(DB_DIR); db_path.exists() } @@ -121,14 +134,20 @@ where K: Keychain + 'ck, { pub fn new(data_file_dir: &str, n_client: C) -> Result { - let db_path = path::Path::new(data_file_dir).join(DB_DIR); + let db_path = Path::new(data_file_dir).join(DB_DIR); fs::create_dir_all(&db_path).expect("Couldn't create wallet backend directory!"); - let stored_tx_path = path::Path::new(data_file_dir).join(TX_SAVE_DIR); + let stored_tx_path = Path::new(data_file_dir).join(TX_SAVE_DIR); fs::create_dir_all(&stored_tx_path) .expect("Couldn't create wallet backend tx storage directory!"); - let store = store::Store::new(db_path.to_str().unwrap(), None, Some(DB_DIR), None)?; + let store = store::Store::new( + db_path.to_str().unwrap(), + None, + Some(DB_DIR), + DB_PREFIXES.to_vec(), + None, + )?; // Make sure default wallet derivation path always exists // as well as path (so it can be retrieved by batches to know where to store @@ -137,14 +156,14 @@ where label: "default".to_owned(), path: LMDBBackend::::default_path(), }; - let acct_key = to_key( - ACCOUNT_PATH_MAPPING_PREFIX, - &mut default_account.label.as_bytes().to_vec(), - ); { - let batch = store.batch()?; - batch.put_ser(&acct_key, &default_account)?; + let mut batch = store.batch()?; + batch.put_ser( + Some(ACCOUNT_PATH_MAPPING_PREFIX), + default_account.label.as_bytes(), + &default_account, + )?; batch.commit()?; } @@ -201,9 +220,9 @@ where let mask_value = match use_test_rng { true => { let mut test_rng = StepRng::new(1_234_567_890_u64, 1); - secp::key::SecretKey::new(&k.secp(), &mut test_rng) + SecretKey::new(&k.secp(), &mut test_rng) } - false => secp::key::SecretKey::new(&k.secp(), &mut thread_rng()), + false => SecretKey::new(&k.secp(), &mut thread_rng()), }; k.mask_master_key(&mask_value)?; Some(mask_value) @@ -296,17 +315,19 @@ where fn get(&self, id: &Identifier, mmr_index: &Option) -> Result { let key = match mmr_index { - Some(i) => to_key_u64(OUTPUT_PREFIX, &mut id.to_bytes().to_vec(), *i), - None => to_key(OUTPUT_PREFIX, &mut id.to_bytes().to_vec()), + Some(i) => to_key_u64(id.to_bytes(), *i), + None => id.to_bytes().to_vec(), }; - option_to_not_found(self.db.get_ser(&key, None), || format!("Key Id: {}", id)) - .map_err(|e| e.into()) + option_to_not_found(self.db.get_ser(Some(OUTPUT_PREFIX), &key, None), || { + format!("Key Id: {}", id) + }) + .map_err(|e| e.into()) } // TODO - fix this awkward conversion between PrefixIterator and our Box fn iter<'a>(&'a self) -> Box + 'a> { let protocol_version = self.db.protocol_version(); - let prefix_iter = self.db.iter(&[OUTPUT_PREFIX], move |_, mut v| { + let prefix_iter = self.db.iter(Some(OUTPUT_PREFIX), move |_, mut v| { ser::deserialize( &mut v, protocol_version, @@ -319,14 +340,15 @@ where } fn get_tx_log_entry(&self, u: &Uuid) -> Result, Error> { - let key = to_key(TX_LOG_ENTRY_PREFIX, &mut u.as_bytes().to_vec()); - self.db.get_ser(&key, None).map_err(|e| e.into()) + self.db + .get_ser(Some(TX_LOG_ENTRY_PREFIX), u.as_bytes(), None) + .map_err(|e| e.into()) } // TODO - fix this awkward conversion between PrefixIterator and our Box fn tx_log_iter<'a>(&'a self) -> Box + 'a> { let protocol_version = self.db.protocol_version(); - let prefix_iter = self.db.iter(&[TX_LOG_ENTRY_PREFIX], move |_, mut v| { + let prefix_iter = self.db.iter(Some(TX_LOG_ENTRY_PREFIX), move |_, mut v| { ser::deserialize( &mut v, protocol_version, @@ -343,13 +365,15 @@ where keychain_mask: Option<&SecretKey>, slate_id: &[u8], ) -> Result { - let ctx_key = to_key_u64(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec(), 0); + let ctx_key = to_key_u64(slate_id, 0); let (blind_xor_key, nonce_xor_key) = private_ctx_xor_keys(&self.keychain(keychain_mask)?, slate_id)?; - let mut ctx: Context = option_to_not_found(self.db.get_ser(&ctx_key, None), || { - format!("Slate id: {:x?}", slate_id.to_vec()) - })?; + let mut ctx: Context = option_to_not_found( + self.db + .get_ser(Some(PRIVATE_TX_CONTEXT_PREFIX), &ctx_key, None), + || format!("Slate id: {:x?}", slate_id.to_vec()), + )?; for i in 0..SECRET_KEY_SIZE { ctx.sec_key.0[i] ^= blind_xor_key[i]; @@ -364,7 +388,7 @@ where let protocol_version = self.db.protocol_version(); let prefix_iter = self .db - .iter(&[ACCOUNT_PATH_MAPPING_PREFIX], move |_, mut v| { + .iter(Some(ACCOUNT_PATH_MAPPING_PREFIX), move |_, mut v| { ser::deserialize( &mut v, protocol_version, @@ -377,13 +401,14 @@ where } fn get_acct_path(&self, label: String) -> Result, Error> { - let acct_key = to_key(ACCOUNT_PATH_MAPPING_PREFIX, &mut label.as_bytes().to_vec()); - self.db.get_ser(&acct_key, None).map_err(|e| e.into()) + self.db + .get_ser(Some(ACCOUNT_PATH_MAPPING_PREFIX), label.as_bytes(), None) + .map_err(|e| e.into()) } fn store_tx(&self, uuid: &str, tx: &Transaction) -> Result<(), Error> { let filename = format!("{}.grintx", uuid); - let path = path::Path::new(&self.data_file_dir) + let path = Path::new(&self.data_file_dir) .join(TX_SAVE_DIR) .join(filename); let path_buf = Path::new(&path).to_path_buf(); @@ -396,7 +421,7 @@ where fn get_stored_tx(&self, uuid: &str) -> Result, Error> { let filename = format!("{}.grintx", uuid); - let path = path::Path::new(&self.data_file_dir) + let path = Path::new(&self.data_file_dir) .join(TX_SAVE_DIR) .join(filename); let tx_file = Path::new(&path).to_path_buf(); @@ -436,11 +461,9 @@ where fn current_child_index<'a>(&mut self, parent_key_id: &Identifier) -> Result { let index = { let batch = self.db.batch()?; - let deriv_key = to_key(DERIV_PREFIX, &mut parent_key_id.to_bytes().to_vec()); - match batch.get_ser(&deriv_key, None)? { - Some(idx) => idx, - None => 0, - } + batch + .get_ser(Some(DERIV_PREFIX), &parent_key_id.to_bytes(), None)? + .unwrap_or_else(|| 0) }; Ok(index) } @@ -449,11 +472,9 @@ where let parent_key_id = self.parent_key_id.clone(); let mut deriv_idx = { let batch = self.db.batch()?; - let deriv_key = to_key(DERIV_PREFIX, &mut self.parent_key_id.to_bytes().to_vec()); - match batch.get_ser(&deriv_key, None)? { - Some(idx) => idx, - None => 0, - } + batch + .get_ser(Some(DERIV_PREFIX), &self.parent_key_id.to_bytes(), None)? + .unwrap_or_else(|| 0) }; let mut return_path = self.parent_key_id.to_path(); return_path.depth += 1; @@ -467,45 +488,38 @@ where fn last_confirmed_height<'a>(&mut self) -> Result { let batch = self.db.batch()?; - let height_key = to_key( - CONFIRMED_HEIGHT_PREFIX, - &mut self.parent_key_id.to_bytes().to_vec(), - ); - let last_confirmed_height = match batch.get_ser(&height_key, None)? { - Some(h) => h, - None => 0, - }; + let last_confirmed_height = batch + .get_ser( + Some(CONFIRMED_HEIGHT_PREFIX), + &self.parent_key_id.to_bytes(), + None, + )? + .unwrap_or_else(|| 0); Ok(last_confirmed_height) } fn last_scanned_block<'a>(&mut self) -> Result { let batch = self.db.batch()?; - let scanned_block_key = to_key( - LAST_SCANNED_BLOCK, - &mut LAST_SCANNED_KEY.as_bytes().to_vec(), - ); - let last_scanned_block = match batch.get_ser(&scanned_block_key, None)? { - Some(b) => b, - None => ScannedBlockInfo { + let last_scanned_block = batch + .get_ser(Some(LAST_SCANNED_BLOCK), LAST_SCANNED_KEY.as_bytes(), None)? + .unwrap_or_else(|| ScannedBlockInfo { height: 0, hash: "".to_owned(), start_pmmr_index: 0, last_pmmr_index: 0, - }, - }; + }); Ok(last_scanned_block) } fn init_status<'a>(&mut self) -> Result { let batch = self.db.batch()?; - let init_status_key = to_key( - WALLET_INIT_STATUS, - &mut WALLET_INIT_STATUS_KEY.as_bytes().to_vec(), - ); - let status = match batch.get_ser(&init_status_key, None)? { - Some(s) => s, - None => WalletInitStatus::InitComplete, - }; + let status = batch + .get_ser( + Some(WALLET_INIT_STATUS), + WALLET_INIT_STATUS_KEY.as_bytes(), + None, + )? + .unwrap_or_else(|| WalletInitStatus::InitComplete); Ok(status) } } @@ -535,24 +549,30 @@ where fn save(&mut self, out: OutputData) -> Result<(), Error> { // Save the output data to the db. - { - let key = match out.mmr_index { - Some(i) => to_key_u64(OUTPUT_PREFIX, &mut out.key_id.to_bytes().to_vec(), i), - None => to_key(OUTPUT_PREFIX, &mut out.key_id.to_bytes().to_vec()), - }; - self.db.borrow().as_ref().unwrap().put_ser(&key, &out)?; - } + let key = match out.mmr_index { + Some(i) => to_key_u64(out.key_id.to_bytes(), i), + None => out.key_id.to_bytes().to_vec(), + }; + self.db + .borrow_mut() + .as_mut() + .unwrap() + .put_ser(Some(OUTPUT_PREFIX), &key, &out)?; Ok(()) } fn get(&self, id: &Identifier, mmr_index: &Option) -> Result { let key = match mmr_index { - Some(i) => to_key_u64(OUTPUT_PREFIX, &mut id.to_bytes().to_vec(), *i), - None => to_key(OUTPUT_PREFIX, &mut id.to_bytes().to_vec()), + Some(i) => to_key_u64(id.to_bytes(), *i), + None => id.to_bytes().to_vec(), }; option_to_not_found( - self.db.borrow().as_ref().unwrap().get_ser(&key, None), + self.db + .borrow() + .as_ref() + .unwrap() + .get_ser(Some(OUTPUT_PREFIX), &key, None), || format!("Key ID: {}", id), ) .map_err(|e| e.into()) @@ -563,7 +583,7 @@ where let db = self.db.borrow(); let db = db.as_ref().unwrap(); let protocol_version = db.protocol_version(); - let prefix_iter = db.iter(&[OUTPUT_PREFIX], move |_, mut v| { + let prefix_iter = db.iter(Some(OUTPUT_PREFIX), move |_, mut v| { ser::deserialize( &mut v, protocol_version, @@ -577,34 +597,31 @@ where fn delete(&mut self, id: &Identifier, mmr_index: &Option) -> Result<(), Error> { // Delete the output data. - { - let key = match mmr_index { - Some(i) => to_key_u64(OUTPUT_PREFIX, &mut id.to_bytes().to_vec(), *i), - None => to_key(OUTPUT_PREFIX, &mut id.to_bytes().to_vec()), - }; - let _ = self.db.borrow().as_ref().unwrap().delete(&key); - } - + let key = match mmr_index { + Some(i) => to_key_u64(id.to_bytes(), *i), + None => id.to_bytes().to_vec(), + }; + self.db + .borrow_mut() + .as_mut() + .unwrap() + .delete(Some(OUTPUT_PREFIX), &key)?; Ok(()) } fn next_tx_log_id(&mut self, parent_key_id: &Identifier) -> Result { - let tx_id_key = to_key(TX_LOG_ID_PREFIX, &mut parent_key_id.to_bytes().to_vec()); - let last_tx_log_id = match self + let last_tx_log_id = self .db - .borrow() - .as_ref() + .borrow_mut() + .as_mut() .unwrap() - .get_ser(&tx_id_key, None)? - { - Some(t) => t, - None => 0, - }; - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&tx_id_key, &(last_tx_log_id + 1))?; + .get_ser(Some(TX_LOG_ID_PREFIX), &parent_key_id.to_bytes(), None)? + .unwrap_or_else(|| 0); + self.db.borrow_mut().as_mut().unwrap().put_ser( + Some(TX_LOG_ID_PREFIX), + &parent_key_id.to_bytes(), + &(last_tx_log_id + 1), + )?; Ok(last_tx_log_id) } @@ -613,7 +630,7 @@ where let db = self.db.borrow(); let db = db.as_ref().unwrap(); let protocol_version = db.protocol_version(); - let prefix_iter = db.iter(&[TX_LOG_ENTRY_PREFIX], move |_, mut v| { + let prefix_iter = db.iter(Some(TX_LOG_ENTRY_PREFIX), move |_, mut v| { ser::deserialize( &mut v, protocol_version, @@ -630,51 +647,38 @@ where parent_key_id: &Identifier, height: u64, ) -> Result<(), Error> { - let height_key = to_key( - CONFIRMED_HEIGHT_PREFIX, - &mut parent_key_id.to_bytes().to_vec(), - ); - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&height_key, &height)?; + self.db.borrow_mut().as_mut().unwrap().put_ser( + Some(CONFIRMED_HEIGHT_PREFIX), + &parent_key_id.to_bytes(), + &height, + )?; Ok(()) } fn save_last_scanned_block(&mut self, block_info: ScannedBlockInfo) -> Result<(), Error> { - let pmmr_index_key = to_key( - LAST_SCANNED_BLOCK, - &mut LAST_SCANNED_KEY.as_bytes().to_vec(), - ); - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&pmmr_index_key, &block_info)?; + self.db.borrow_mut().as_mut().unwrap().put_ser( + Some(LAST_SCANNED_BLOCK), + LAST_SCANNED_KEY.as_bytes(), + &block_info, + )?; Ok(()) } fn save_init_status(&mut self, value: WalletInitStatus) -> Result<(), Error> { - let init_status_key = to_key( - WALLET_INIT_STATUS, - &mut WALLET_INIT_STATUS_KEY.as_bytes().to_vec(), - ); - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&init_status_key, &value)?; + self.db.borrow_mut().as_mut().unwrap().put_ser( + Some(WALLET_INIT_STATUS), + WALLET_INIT_STATUS_KEY.as_bytes(), + &value, + )?; Ok(()) } fn save_child_index(&mut self, parent_id: &Identifier, child_n: u32) -> Result<(), Error> { - let deriv_key = to_key(DERIV_PREFIX, &mut parent_id.to_bytes().to_vec()); - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&deriv_key, &child_n)?; + self.db.borrow_mut().as_mut().unwrap().put_ser( + Some(DERIV_PREFIX), + &parent_id.to_bytes(), + &child_n, + )?; Ok(()) } @@ -683,39 +687,31 @@ where tx_in: TxLogEntry, parent_id: &Identifier, ) -> Result<(), Error> { - let tx_log_key = to_key_u64( - TX_LOG_ENTRY_PREFIX, - &mut parent_id.to_bytes().to_vec(), - tx_in.id as u64, - ); - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&tx_log_key, &tx_in)?; + let tx_log_key = to_key_u64(parent_id.to_bytes(), tx_in.id as u64); + self.db.borrow_mut().as_mut().unwrap().put_ser( + Some(TX_LOG_ENTRY_PREFIX), + &tx_log_key, + &tx_in, + )?; Ok(()) } fn delete_tx_log_entry(&mut self, tx_id: u32, parent_id: &Identifier) -> Result<(), Error> { - let tx_log_key = to_key_u64( - TX_LOG_ENTRY_PREFIX, - &mut parent_id.to_bytes().to_vec(), - tx_id as u64, - ); - self.db.borrow().as_ref().unwrap().delete(&tx_log_key)?; + let tx_log_key = to_key_u64(parent_id.to_bytes(), tx_id as u64); + self.db + .borrow_mut() + .as_mut() + .unwrap() + .delete(Some(TX_LOG_ENTRY_PREFIX), &tx_log_key)?; Ok(()) } fn save_acct_path(&mut self, mapping: AcctPathMapping) -> Result<(), Error> { - let acct_key = to_key( - ACCOUNT_PATH_MAPPING_PREFIX, - &mut mapping.label.as_bytes().to_vec(), - ); - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&acct_key, &mapping)?; + self.db.borrow_mut().as_mut().unwrap().put_ser( + Some(ACCOUNT_PATH_MAPPING_PREFIX), + mapping.label.as_bytes(), + &mapping, + )?; Ok(()) } @@ -724,7 +720,7 @@ where let db = self.db.borrow(); let db = db.as_ref().unwrap(); let protocol_version = db.protocol_version(); - let prefix_iter = db.iter(&[ACCOUNT_PATH_MAPPING_PREFIX], move |_, mut v| { + let prefix_iter = db.iter(Some(ACCOUNT_PATH_MAPPING_PREFIX), move |_, mut v| { ser::deserialize( &mut v, protocol_version, @@ -742,7 +738,7 @@ where } fn save_private_context(&mut self, slate_id: &[u8], ctx: &Context) -> Result<(), Error> { - let ctx_key = to_key_u64(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec(), 0); + let ctx_key = to_key_u64(slate_id, 0); let (blind_xor_key, nonce_xor_key) = private_ctx_xor_keys(self.keychain(), slate_id)?; let mut s_ctx = ctx.clone(); @@ -751,21 +747,21 @@ where s_ctx.sec_nonce.0[i] ^= nonce_xor_key[i]; } - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&ctx_key, &s_ctx)?; + self.db.borrow_mut().as_mut().unwrap().put_ser( + Some(PRIVATE_TX_CONTEXT_PREFIX), + &ctx_key, + &s_ctx, + )?; Ok(()) } fn delete_private_context(&mut self, slate_id: &[u8]) -> Result<(), Error> { - let ctx_key = to_key_u64(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec(), 0); + let ctx_key = to_key_u64(slate_id, 0); self.db - .borrow() - .as_ref() + .borrow_mut() + .as_mut() .unwrap() - .delete(&ctx_key) + .delete(Some(PRIVATE_TX_CONTEXT_PREFIX), &ctx_key) .map_err(|e| e.into()) } @@ -775,3 +771,10 @@ where Ok(()) } } + +/// Build a db key from a byte vector identifier and numeric identifier +fn to_key_u64>(k: K, val: u64) -> Vec { + let mut res = k.as_ref().to_vec(); + res.write_u64(val); + res +}