From: Steve Myers Date: Fri, 18 Feb 2022 20:57:14 +0000 (-0800) Subject: Add key-value-db and sqlite-db features, separate wallet directories X-Git-Tag: v0.5.0~3^2~3 X-Git-Url: http://internal-gitweb-vhost/script/%22https:/database/struct.WScriptHash.html?a=commitdiff_plain;h=d7471f69b3affc2ddbb0b24e3c28bc4fe01354f8;p=bdk-cli Add key-value-db and sqlite-db features, separate wallet directories --- diff --git a/Cargo.lock b/Cargo.lock index 6616d69..1c5573b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" +dependencies = [ + "getrandom 0.2.6", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.18" @@ -96,6 +107,7 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00fa2bcfe9debe57f32285ef56cb218b2e0dbf91e476ad22f61a745d4c032a18" dependencies = [ + "ahash", "async-trait", "bdk-macros", "bip39", @@ -112,6 +124,7 @@ dependencies = [ "rand", "reqwest", "rocksdb", + "rusqlite", "serde", "serde_json", "sled", @@ -568,6 +581,18 @@ dependencies = [ "str-buf", ] +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + [[package]] name = "fastrand" version = "1.7.0" @@ -790,6 +815,18 @@ name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashlink" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" +dependencies = [ + "hashbrown", +] [[package]] name = "heck" @@ -997,6 +1034,16 @@ dependencies = [ "libc", ] +[[package]] +name = "libsqlite3-sys" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290b64917f8b0cb885d9de0f9959fe1f775d7fa12f1da2db9001c1c8ab60f89d" +dependencies = [ + "pkg-config", + "vcpkg", +] + [[package]] name = "lock_api" version = "0.4.7" @@ -1442,6 +1489,21 @@ dependencies = [ "librocksdb-sys", ] +[[package]] +name = "rusqlite" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4b1eaf239b47034fb450ee9cdedd7d0226571689d8823030c4b6c2cb407152" +dependencies = [ + "bitflags", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "memchr", + "smallvec 1.8.0", +] + [[package]] name = "rustc-hash" version = "1.1.0" @@ -2077,6 +2139,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "vec_map" version = "0.8.2" diff --git a/Cargo.toml b/Cargo.toml index af87bad..87133d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,9 +31,11 @@ bdk-reserves = { version = "0.17", optional = true} electrsd = { version= "0.12", features = ["trigger", "bitcoind_22_0"], optional = true} [features] -default = ["cli", "repl"] -cli = ["bdk/key-value-db", "clap", "dirs-next", "env_logger"] +default = ["cli", "repl", "key-value-db"] +cli = ["clap", "dirs-next", "env_logger"] repl = ["regex", "rustyline", "fd-lock"] +key-value-db = ["bdk/key-value-db"] +sqlite-db = ["bdk/sqlite"] electrum = ["bdk/electrum"] esplora = [] esplora-ureq = ["esplora", "bdk/use-esplora-ureq"] diff --git a/src/bdk_cli.rs b/src/bdk_cli.rs index 24ee81b..1e0ee1a 100644 --- a/src/bdk_cli.rs +++ b/src/bdk_cli.rs @@ -43,9 +43,11 @@ use bdk::blockchain::{AnyBlockchain, AnyBlockchainConfig, ConfigurableBlockchain #[cfg(feature = "rpc")] use bdk::blockchain::rpc::{Auth, RpcConfig}; -use bdk::database::BatchDatabase; -use bdk::sled; -use bdk::sled::Tree; +#[cfg(feature = "key-value-db")] +use bdk::database::any::SledDbConfiguration; +#[cfg(feature = "sqlite-db")] +use bdk::database::any::SqliteDbConfiguration; +use bdk::database::{AnyDatabase, AnyDatabaseConfig, BatchDatabase, ConfigurableDatabase}; use bdk::wallet::wallet_name_from_descriptor; use bdk::Wallet; use bdk::{bitcoin, Error}; @@ -88,7 +90,8 @@ enum ReplSubCommand { Exit, } -fn prepare_home_dir() -> Result { +/// prepare bdk_cli home and wallet directory +fn prepare_home_wallet_dir(wallet_name: &String) -> Result { let mut dir = PathBuf::new(); dir.push( &dirs_next::home_dir().ok_or_else(|| Error::Generic("home dir not found".to_string()))?, @@ -100,25 +103,75 @@ fn prepare_home_dir() -> Result { fs::create_dir(&dir).map_err(|e| Error::Generic(e.to_string()))?; } - #[cfg(not(feature = "compact_filters"))] - dir.push("database.sled"); + dir.push(wallet_name); + + if !dir.exists() { + info!("Creating wallet directory {}", dir.as_path().display()); + fs::create_dir(&dir).map_err(|e| Error::Generic(e.to_string()))?; + } - #[cfg(feature = "compact_filters")] - dir.push("compact_filters"); Ok(dir) } -fn open_database(wallet_opts: &WalletOpts) -> Result { - let mut database_path = prepare_home_dir()?; - let wallet_name = wallet_opts - .wallet - .as_deref() - .expect("We should always have a wallet name at this point"); - database_path.push(wallet_name); - let database = sled::open(database_path)?; - let tree = database.open_tree(&wallet_name)?; +/// Prepare wallet database directory +fn prepare_wallet_db_dir(wallet_name: &String) -> Result { + let mut db_dir = prepare_home_wallet_dir(wallet_name)?; + + #[cfg(feature = "key-value-db")] + db_dir.push("wallet.sled"); + + #[cfg(feature = "sqlite-db")] + db_dir.push("wallet.sqlite"); + + #[cfg(not(feature = "sqlite-db"))] + if !db_dir.exists() { + info!("Creating database directory {}", db_dir.as_path().display()); + fs::create_dir(&db_dir).map_err(|e| Error::Generic(e.to_string()))?; + } + + Ok(db_dir) +} + +/// Prepare blockchain data directory (for compact filters) +#[cfg(feature = "compact_filters")] +fn prepare_bc_dir(wallet_name: &String) -> Result { + let mut bc_dir = prepare_home_wallet_dir(wallet_name)?; + + bc_dir.push("compact_filters"); + + if !bc_dir.exists() { + info!( + "Creating blockchain directory {}", + bc_dir.as_path().display() + ); + fs::create_dir(&bc_dir).map_err(|e| Error::Generic(e.to_string()))?; + } + + Ok(bc_dir) +} + +fn open_database(wallet_opts: &WalletOpts) -> Result { + let wallet_name = wallet_opts.wallet.as_ref().expect("wallet name"); + let database_path = prepare_wallet_db_dir(wallet_name)?; + + #[cfg(feature = "key-value-db")] + let config = AnyDatabaseConfig::Sled(SledDbConfiguration { + path: database_path + .into_os_string() + .into_string() + .expect("path string"), + tree_name: wallet_name.to_string(), + }); + #[cfg(feature = "sqlite-db")] + let config = AnyDatabaseConfig::Sqlite(SqliteDbConfiguration { + path: database_path + .into_os_string() + .into_string() + .expect("path string"), + }); + let database = AnyDatabase::from_config(&config)?; debug!("database opened successfully"); - Ok(tree) + Ok(database) } #[allow(dead_code)] @@ -180,10 +233,11 @@ fn new_blockchain( } } + let wallet_name = wallet_opts.wallet.as_ref().expect("wallet name"); AnyBlockchainConfig::CompactFilters(CompactFiltersBlockchainConfig { peers, network: _network, - storage_dir: prepare_home_dir()? + storage_dir: prepare_bc_dir(wallet_name)? .into_os_string() .into_string() .map_err(|_| Error::Generic("Internal OS_String conversion error".to_string()))?,