Parcourir la source

drk: introduced sled cache

skoupidi il y a 1 an
Parent
commit
4eca3e248d

+ 1 - 0
Cargo.lock

@@ -2478,6 +2478,7 @@ dependencies = [
  "signal-hook",
  "signal-hook-async-std",
  "simplelog",
+ "sled-overlay",
  "smol",
  "structopt",
  "structopt-toml",

+ 1 - 0
bin/drk/Cargo.toml

@@ -27,6 +27,7 @@ prettytable-rs = "0.10.0"
 rand = "0.8.5"
 rodio = {version = "0.20.1", default-features = false, features = ["minimp3"]}
 rusqlite = {version = "0.36.0", features = ["sqlcipher"]}
+sled-overlay = "0.1.8"
 toml = "0.9.5"
 url = "2.5.4"
 

+ 9 - 0
bin/drk/drk_config.toml

@@ -14,6 +14,9 @@ fun = true
 
 # Localnet blockchain network configuration
 [network_config."localnet"]
+# Path to blockchain cache database
+cache_path = "~/.local/share/darkfi/drk/localnet/cache"
+
 # Path to wallet database
 wallet_path = "~/.local/share/darkfi/drk/localnet/wallet.db"
 
@@ -25,6 +28,9 @@ endpoint = "tcp://127.0.0.1:8240"
 
 # Testnet blockchain network configuration
 [network_config."testnet"]
+# Path to blockchain cache database
+cache_path = "~/.local/share/darkfi/drk/testnet/cache"
+
 # Path to wallet database
 wallet_path = "~/.local/share/darkfi/drk/testnet/wallet.db"
 
@@ -36,6 +42,9 @@ endpoint = "tcp://127.0.0.1:8340"
 
 # Mainnet blockchain network configuration
 [network_config."mainnet"]
+# Path to blockchain cache database
+cache_path = "~/.local/share/darkfi/drk/mainnet/cache"
+
 # Path to wallet database
 wallet_path = "~/.local/share/darkfi/drk/mainnet/wallet.db"
 

+ 59 - 0
bin/drk/src/cache.rs

@@ -0,0 +1,59 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2025 Dyne.org foundation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+use darkfi::Result;
+use sled_overlay::sled;
+
+pub const SLED_ORDER_TREE: &[u8] = b"_order";
+pub const SLED_STATE_INVERSE_DIFF_TREE: &[u8] = b"_state_inverse_diff";
+pub const SLED_MERKLE_TREES_TREE: &[u8] = b"_merkle_trees";
+pub const SLED_MONEY_SMT_TREE: &[u8] = b"_money_smt";
+
+/// Structure holding all sled trees that define the Blockchain cache.
+#[derive(Clone)]
+pub struct Cache {
+    /// Main pointer to the sled db connection
+    pub sled_db: sled::Db,
+    /// The `sled` tree storing the order of the blockchain's blocks,
+    /// where the key is the height number, and the value is the blocks'
+    /// hash.
+    pub order: sled::Tree,
+    /// The `sled` tree storing each blocks' full database state inverse
+    /// changes, where the key is the block height number, and the value
+    /// is the serialized database inverse diff.
+    pub state_inverse_diff: sled::Tree,
+    /// The `sled` tree storing the merkle trees of the blockchain,
+    /// where the key is the tree name, and the value is the serialized
+    /// merkle tree itself.
+    pub merkle_trees: sled::Tree,
+    /// The `sled` tree storing the Sparse Merkle Tree of the money
+    /// contract.
+    pub money_smt: sled::Tree,
+}
+
+impl Cache {
+    /// Instantiate a new `Cache` with the given `sled` database.
+    pub fn new(db: &sled::Db) -> Result<Self> {
+        let order = db.open_tree(SLED_ORDER_TREE)?;
+        let state_inverse_diff = db.open_tree(SLED_STATE_INVERSE_DIFF_TREE)?;
+        let merkle_trees = db.open_tree(SLED_MERKLE_TREES_TREE)?;
+        let money_smt = db.open_tree(SLED_MONEY_SMT_TREE)?;
+
+        Ok(Self { sled_db: db.clone(), order, state_inverse_diff, merkle_trees, money_smt })
+    }
+}

+ 15 - 1
bin/drk/src/lib.rs

@@ -60,8 +60,14 @@ pub mod scanned_blocks;
 pub mod walletdb;
 use walletdb::{WalletDb, WalletPtr};
 
+/// Blockchain cache database operations handler
+pub mod cache;
+use cache::Cache;
+
 /// CLI-util structure
 pub struct Drk {
+    /// Blockchain cache database operations handler
+    pub cache: Cache,
     /// Wallet database operations handler
     pub wallet: WalletPtr,
     /// JSON-RPC client to execute requests to darkfid daemon
@@ -72,12 +78,20 @@ pub struct Drk {
 
 impl Drk {
     pub async fn new(
+        cache_path: String,
         wallet_path: String,
         wallet_pass: String,
         endpoint: Option<Url>,
         ex: Arc<smol::Executor<'static>>,
         fun: bool,
     ) -> Result<Self> {
+        // Initialize blockchain cache database
+        let db_path = expand_path(&cache_path)?;
+        let sled_db = sled_overlay::sled::open(&db_path)?;
+        let Ok(cache) = Cache::new(&sled_db) else {
+            return Err(Error::DatabaseError(format!("{}", WalletDbError::InitializationFailed)));
+        };
+
         // Initialize wallet
         let wallet_path = expand_path(&wallet_path)?;
         if !wallet_path.exists() {
@@ -96,7 +110,7 @@ impl Drk {
             None
         };
 
-        Ok(Self { wallet, rpc_client, fun })
+        Ok(Self { cache, wallet, rpc_client, fun })
     }
 
     /// Initialize wallet with tables for `Drk`.

+ 49 - 1
bin/drk/src/main.rs

@@ -550,6 +550,10 @@ enum ContractSubcmd {
 #[derive(Clone, Debug, serde::Deserialize, structopt::StructOpt, structopt_toml::StructOptToml)]
 #[structopt()]
 struct BlockchainNetwork {
+    #[structopt(long, default_value = "~/.local/share/darkfi/drk/localnet/cache")]
+    /// Path to blockchain cache database
+    cache_path: String,
+
     #[structopt(long, default_value = "~/.local/share/darkfi/drk/localnet/wallet.db")]
     /// Path to wallet database
     wallet_path: String,
@@ -608,6 +612,7 @@ async fn parse_blockchain_config(
 
 /// Auxiliary function to create a `Drk` wallet for provided configuration.
 async fn new_wallet(
+    cache_path: String,
     wallet_path: String,
     wallet_pass: String,
     endpoint: Option<Url>,
@@ -620,7 +625,7 @@ async fn new_wallet(
         exit(2);
     }
 
-    match Drk::new(wallet_path, wallet_pass, endpoint, ex, fun).await {
+    match Drk::new(cache_path, wallet_path, wallet_pass, endpoint, ex, fun).await {
         Ok(wallet) => wallet,
         Err(e) => {
             eprintln!("Error initializing wallet: {e:?}");
@@ -654,6 +659,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
         Subcmd::Ping => {
             let drk = new_wallet(
+                blockchain_config.cache_path,
                 blockchain_config.wallet_path,
                 blockchain_config.wallet_pass,
                 Some(blockchain_config.endpoint),
@@ -696,6 +702,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
             }
 
             let drk = new_wallet(
+                blockchain_config.cache_path,
                 blockchain_config.wallet_path,
                 blockchain_config.wallet_pass,
                 None,
@@ -927,6 +934,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
             let tx = parse_tx_from_stdin().await?;
 
             let drk = new_wallet(
+                blockchain_config.cache_path,
                 blockchain_config.wallet_path,
                 blockchain_config.wallet_pass,
                 None,
@@ -962,6 +970,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             let coin = Coin::from(elem);
             let drk = new_wallet(
+                blockchain_config.cache_path,
                 blockchain_config.wallet_path,
                 blockchain_config.wallet_pass,
                 None,
@@ -979,6 +988,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
         Subcmd::Transfer { amount, token, recipient, spend_hook, user_data, half_split } => {
             let drk = new_wallet(
+                blockchain_config.cache_path,
                 blockchain_config.wallet_path,
                 blockchain_config.wallet_pass,
                 Some(blockchain_config.endpoint),
@@ -1059,6 +1069,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
         Subcmd::Otc { command } => match command {
             OtcSubcmd::Init { value_pair, token_pair } => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),
@@ -1092,6 +1103,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 let partial: PartialSwapData = deserialize_async(&bytes).await?;
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),
@@ -1120,6 +1132,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 };
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -1139,6 +1152,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 let mut tx = parse_tx_from_stdin().await?;
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -1191,6 +1205,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 let approval_ratio_quot = (approval_ratio * approval_ratio_base as f64) as u64;
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -1256,6 +1271,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 let params = DaoParams::from_toml_str(&buf)?;
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -1277,6 +1293,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 let params = DaoParams::from_toml_str(&buf)?;
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -1294,6 +1311,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             DaoSubcmd::List { name } => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -1311,6 +1329,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             DaoSubcmd::Balance { name } => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -1362,6 +1381,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             DaoSubcmd::Mint { name } => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),
@@ -1391,6 +1411,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 user_data,
             } => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),
@@ -1472,6 +1493,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             DaoSubcmd::ProposeGeneric { name, duration, user_data } => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),
@@ -1516,6 +1538,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             DaoSubcmd::Proposals { name } => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -1542,6 +1565,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 };
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),
@@ -1749,6 +1773,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 let encrypted_proposal: AeadEncryptedNote = deserialize_async(&bytes).await?;
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -1815,6 +1840,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 };
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),
@@ -1844,6 +1870,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 };
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),
@@ -1903,6 +1930,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
             let mut tx = parse_tx_from_stdin().await?;
 
             let drk = new_wallet(
+                blockchain_config.cache_path,
                 blockchain_config.wallet_path,
                 blockchain_config.wallet_pass,
                 Some(blockchain_config.endpoint),
@@ -1932,6 +1960,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
             let tx = parse_tx_from_stdin().await?;
 
             let drk = new_wallet(
+                blockchain_config.cache_path,
                 blockchain_config.wallet_path,
                 blockchain_config.wallet_pass,
                 Some(blockchain_config.endpoint),
@@ -1965,6 +1994,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
         Subcmd::Subscribe => {
             let drk = new_wallet(
+                blockchain_config.cache_path,
                 blockchain_config.wallet_path,
                 blockchain_config.wallet_pass,
                 Some(blockchain_config.endpoint.clone()),
@@ -1983,6 +2013,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
         Subcmd::Scan { reset } => {
             let drk = new_wallet(
+                blockchain_config.cache_path,
                 blockchain_config.wallet_path,
                 blockchain_config.wallet_pass,
                 Some(blockchain_config.endpoint),
@@ -2012,6 +2043,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 let tx_hash = TransactionHash(*blake3::Hash::from_hex(&tx_hash)?.as_bytes());
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),
@@ -2053,6 +2085,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 let tx = parse_tx_from_stdin().await?;
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),
@@ -2077,6 +2110,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             ExplorerSubcmd::TxsHistory { tx_hash, encode } => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -2127,6 +2161,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             ExplorerSubcmd::ClearReverted => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -2145,6 +2180,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             ExplorerSubcmd::ScannedBlocks { height } => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -2210,6 +2246,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 };
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -2238,6 +2275,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 };
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -2266,6 +2304,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             AliasSubcmd::Remove { alias } => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -2301,6 +2340,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 };
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -2316,6 +2356,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             TokenSubcmd::GenerateMint => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -2333,6 +2374,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             TokenSubcmd::List => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -2379,6 +2421,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             TokenSubcmd::Mint { token, amount, recipient, spend_hook, user_data } => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),
@@ -2456,6 +2499,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             TokenSubcmd::Freeze { token } => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),
@@ -2488,6 +2532,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
         Subcmd::Contract { command } => match command {
             ContractSubcmd::GenerateDeploy => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -2506,6 +2551,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             ContractSubcmd::List => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     None,
@@ -2538,6 +2584,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 let deploy_ix = smol::fs::read(expand_path(&deploy_ix)?).await?;
 
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),
@@ -2566,6 +2613,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
 
             ContractSubcmd::Lock { deploy_auth } => {
                 let drk = new_wallet(
+                    blockchain_config.cache_path,
                     blockchain_config.wallet_path,
                     blockchain_config.wallet_pass,
                     Some(blockchain_config.endpoint),

+ 3 - 0
contrib/localnet/darkfid-single-node/drk.toml

@@ -11,6 +11,9 @@ network = "localnet"
 
 # Localnet blockchain network configuration
 [network_config."localnet"]
+# Path to blockchain cache database
+cache_path = "drk/cache"
+
 # Path to wallet database
 wallet_path = "drk/wallet.db"