Просмотр исходного кода

drk: unused sql tables removed

skoupidi 1 год назад
Родитель
Сommit
7622f58a9e
10 измененных файлов с 103 добавлено и 352 удалено
  1. 0 6
      bin/drk/dao.sql
  2. 0 11
      bin/drk/money.sql
  3. 10 3
      bin/drk/src/cache.rs
  4. 16 84
      bin/drk/src/dao.rs
  5. 1 52
      bin/drk/src/lib.rs
  6. 4 4
      bin/drk/src/main.rs
  7. 28 110
      bin/drk/src/money.rs
  8. 1 4
      bin/drk/src/rpc.rs
  9. 43 71
      bin/drk/src/scanned_blocks.rs
  10. 0 7
      bin/drk/wallet.sql

+ 0 - 6
bin/drk/dao.sql

@@ -142,12 +142,6 @@ CREATE TABLE IF NOT EXISTS Fd8kfCuqU8BoFFp6GcXv5pC8XXRkBK7gUPQX5XDz7iXj_dao_daos
     call_index INTEGER
 );
 
--- The merkle tree containing DAO bullas
-CREATE TABLE IF NOT EXISTS Fd8kfCuqU8BoFFp6GcXv5pC8XXRkBK7gUPQX5XDz7iXj_dao_trees (
-	daos_tree BLOB NOT NULL,
-	proposals_tree BLOB NOT NULL
-);
-
 CREATE TABLE IF NOT EXISTS Fd8kfCuqU8BoFFp6GcXv5pC8XXRkBK7gUPQX5XDz7iXj_dao_proposals (
     -- Bulla identifier of the proposal
     bulla BLOB PRIMARY KEY NOT NULL,

+ 0 - 11
bin/drk/money.sql

@@ -1,17 +1,6 @@
 -- Wallet definitions for this contract.
 -- We store data that is needed to be able to receive and send tokens.
 
--- The Merkle tree containing coins
-CREATE TABLE IF NOT EXISTS BZHKGQ26bzmBithTQYTJtjo2QdCqpkR9tjSBopT4yf4o_money_tree (
-	tree BLOB NOT NULL
-);
-
--- The Sparse Merkle tree containing coins nullifiers
-CREATE TABLE IF NOT EXISTS BZHKGQ26bzmBithTQYTJtjo2QdCqpkR9tjSBopT4yf4o_money_smt (
-	smt_key BLOB PRIMARY KEY NOT NULL,
-	smt_value BLOB NOT NULL
-);
-
 -- The keypairs in our wallet
 CREATE TABLE IF NOT EXISTS BZHKGQ26bzmBithTQYTJtjo2QdCqpkR9tjSBopT4yf4o_money_keys (
 	key_id INTEGER PRIMARY KEY NOT NULL,

+ 10 - 3
bin/drk/src/cache.rs

@@ -57,7 +57,10 @@ pub struct Cache {
     pub merkle_trees: sled::Tree,
     /// The `sled` tree storing the Sparse Merkle Tree of the Money
     /// contract.
+    // TODO: this could be a map of trees so more contracts can open
+    // SMTs if needed
     pub money_smt: sled::Tree,
+    // TODO: Perhaps we should also move transactions history here
 }
 
 impl Cache {
@@ -103,10 +106,14 @@ impl CacheOverlay {
     }
 
     /// Insert a `u32` and a block hash into overlay's scanned blocks
-    /// tree. The block height is used as the key, and the blockhash is
-    /// used as value.
+    /// tree. The block height is used as the key, and the serialized
+    /// blockhash string is used as value.
     pub fn insert_scanned_block(&mut self, height: &u32, hash: &HeaderHash) -> Result<()> {
-        self.0.insert(SLED_SCANNED_BLOCKS_TREE, &height.to_be_bytes(), hash.inner())?;
+        self.0.insert(
+            SLED_SCANNED_BLOCKS_TREE,
+            &height.to_be_bytes(),
+            &serialize(&hash.to_string()),
+        )?;
         Ok(())
     }
 

+ 16 - 84
bin/drk/src/dao.rs

@@ -88,7 +88,6 @@ pub const SLED_MERKLE_TREES_DAO_PROPOSALS: &[u8] = b"_dao_proposals";
 // SQL schema. Table names are prefixed with the contract ID to avoid collisions.
 lazy_static! {
     pub static ref DAO_DAOS_TABLE: String = format!("{}_dao_daos", DAO_CONTRACT_ID.to_string());
-    pub static ref DAO_TREES_TABLE: String = format!("{}_dao_trees", DAO_CONTRACT_ID.to_string());
     pub static ref DAO_COINS_TABLE: String = format!("{}_dao_coins", DAO_CONTRACT_ID.to_string());
     pub static ref DAO_PROPOSALS_TABLE: String =
         format!("{}_dao_proposals", DAO_CONTRACT_ID.to_string());
@@ -103,10 +102,6 @@ pub const DAO_DAOS_COL_LEAF_POSITION: &str = "leaf_position";
 pub const DAO_DAOS_COL_TX_HASH: &str = "tx_hash";
 pub const DAO_DAOS_COL_CALL_INDEX: &str = "call_index";
 
-// DAO_TREES_TABLE
-pub const DAO_TREES_COL_DAOS_TREE: &str = "daos_tree";
-pub const DAO_TREES_COL_PROPOSALS_TREE: &str = "proposals_tree";
-
 // DAO_PROPOSALS_TABLE
 pub const DAO_PROPOSALS_COL_BULLA: &str = "bulla";
 pub const DAO_PROPOSALS_COL_DAO_BULLA: &str = "dao_bulla";
@@ -899,92 +894,23 @@ impl Drk {
         let wallet_schema = include_str!("../dao.sql");
         self.wallet.exec_batch_sql(wallet_schema)?;
 
-        // Check if we have to initialize the Merkle trees.
-        // We check if one exists, but we actually create two. This should be written
-        // a bit better and safer.
-        // For now, on success, we don't care what's returned, but in the future
-        // we should actually check it.
-        if self.get_dao_trees().await.is_err() {
-            println!("Initializing DAO Merkle trees");
-            let tree = serialize_async(&MerkleTree::new(1)).await;
-            let query = format!(
-                "INSERT INTO {} ({}, {}) VALUES (?1, ?2);",
-                *DAO_TREES_TABLE, DAO_TREES_COL_DAOS_TREE, DAO_TREES_COL_PROPOSALS_TREE
-            );
-            self.wallet.exec_sql(&query, rusqlite::params![tree, tree])?;
-            println!("Successfully initialized Merkle trees for the DAO contract");
-        }
-
         Ok(())
     }
 
-    /// Replace the DAO Merkle trees in the wallet.
-    pub async fn put_dao_trees(
-        &self,
-        daos_tree: &MerkleTree,
-        proposals_tree: &MerkleTree,
-    ) -> WalletDbResult<()> {
-        let query = format!(
-            "UPDATE {} SET {} = ?1, {} = ?2;",
-            *DAO_TREES_TABLE, DAO_TREES_COL_DAOS_TREE, DAO_TREES_COL_PROPOSALS_TREE
-        );
-        self.wallet.exec_sql(
-            &query,
-            rusqlite::params![
-                serialize_async(daos_tree).await,
-                serialize_async(proposals_tree).await
-            ],
-        )
-    }
-
     /// Fetch DAO Merkle trees from the wallet.
+    /// If a tree doesn't exists a new Merkle Tree is returned.
     pub async fn get_dao_trees(&self) -> Result<(MerkleTree, MerkleTree)> {
-        let row = match self.wallet.query_single(&DAO_TREES_TABLE, &[], &[]) {
-            Ok(r) => r,
-            Err(e) => {
-                return Err(Error::DatabaseError(format!(
-                    "[get_dao_trees] Trees retrieval failed: {e:?}"
-                )))
-            }
+        let daos_tree = match self.cache.merkle_trees.get(SLED_MERKLE_TREES_DAO_DAOS)? {
+            Some(tree_bytes) => deserialize_async(&tree_bytes).await?,
+            None => MerkleTree::new(1),
         };
-
-        let Value::Blob(ref daos_tree_bytes) = row[0] else {
-            return Err(Error::ParseFailed("[get_dao_trees] DAO tree bytes parsing failed"))
-        };
-        let daos_tree = deserialize_async(daos_tree_bytes).await?;
-
-        let Value::Blob(ref proposals_tree_bytes) = row[1] else {
-            return Err(Error::ParseFailed("[get_dao_trees] Proposals tree bytes parsing failed"))
+        let proposals_tree = match self.cache.merkle_trees.get(SLED_MERKLE_TREES_DAO_PROPOSALS)? {
+            Some(tree_bytes) => deserialize_async(&tree_bytes).await?,
+            None => MerkleTree::new(1),
         };
-        let proposals_tree = deserialize_async(proposals_tree_bytes).await?;
-
         Ok((daos_tree, proposals_tree))
     }
 
-    /// Auxiliary function to fetch the current DAO Merkle trees state,
-    /// as an update query.
-    pub async fn get_dao_trees_state_query(&self) -> Result<String> {
-        // Grab current DAO trees
-        let (daos_tree, proposals_tree) = self.get_dao_trees().await?;
-
-        // Create the update query
-        match self.wallet.create_prepared_statement(
-            &format!(
-                "UPDATE {} SET {} = ?1, {} = ?2;",
-                *DAO_TREES_TABLE, DAO_TREES_COL_DAOS_TREE, DAO_TREES_COL_PROPOSALS_TREE
-            ),
-            rusqlite::params![
-                serialize_async(&daos_tree).await,
-                serialize_async(&proposals_tree).await
-            ],
-        ) {
-            Ok(q) => Ok(q),
-            Err(e) => Err(Error::DatabaseError(format!(
-                "[get_dao_trees_state_query] Creating query for DAO trees failed: {e:?}"
-            ))),
-        }
-    }
-
     /// Auxiliary function to parse a `DAO_DAOS_TABLE` record.
     async fn parse_dao_record(&self, row: &[Value]) -> Result<DaoRecord> {
         let Value::Text(ref name) = row[1] else {
@@ -1706,11 +1632,17 @@ impl Drk {
         Ok(())
     }
 
-    /// Reset the DAO Merkle trees in the wallet.
+    /// Reset the DAO Merkle trees in the cache.
     pub async fn reset_dao_trees(&self) -> WalletDbResult<()> {
         println!("Resetting DAO Merkle trees");
-        let tree = MerkleTree::new(1);
-        self.put_dao_trees(&tree, &tree).await?;
+        if let Err(e) = self.cache.merkle_trees.remove(SLED_MERKLE_TREES_DAO_DAOS) {
+            println!("[reset_dao_trees] Resetting DAO DAOs Merkle tree failed: {e:?}");
+            return Err(WalletDbError::GenericError)
+        }
+        if let Err(e) = self.cache.merkle_trees.remove(SLED_MERKLE_TREES_DAO_PROPOSALS) {
+            println!("[reset_dao_trees] Resetting DAO Proposals Merkle tree failed: {e:?}");
+            return Err(WalletDbError::GenericError)
+        }
         println!("Successfully reset DAO Merkle trees");
 
         Ok(())

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

@@ -125,7 +125,7 @@ impl Drk {
     pub async fn reset(&self) -> WalletDbResult<()> {
         println!("Resetting full wallet state");
         self.reset_scanned_blocks()?;
-        self.reset_money_tree().await?;
+        self.reset_money_tree()?;
         self.reset_money_smt()?;
         self.reset_money_coins()?;
         self.reset_mint_authorities()?;
@@ -139,10 +139,6 @@ impl Drk {
     }
 
     /// Auxiliary function to reset `walletdb` inverse cache state.
-    /// Additionally, set current trees state inverse queries.
-    /// We keep the entire trees state as two distinct inverse queries,
-    /// since we execute per transaction call, so we don't have to update
-    /// them on each iteration.
     pub async fn reset_inverse_cache(&self) -> Result<()> {
         // Reset `walletdb` inverse cache
         if let Err(e) = self.wallet.clear_inverse_cache() {
@@ -151,53 +147,6 @@ impl Drk {
             )))
         }
 
-        // Grab current money tree state query and insert it into inverse cache
-        let query = self.get_money_tree_state_query().await?;
-        if let Err(e) = self.wallet.cache_inverse(query) {
-            return Err(Error::DatabaseError(format!(
-                "[reset_inverse_cache] Inserting money query into inverse cache failed: {e:?}"
-            )))
-        }
-
-        // Grab current DAO trees state query and insert it into inverse cache
-        let query = self.get_dao_trees_state_query().await?;
-        if let Err(e) = self.wallet.cache_inverse(query) {
-            return Err(Error::DatabaseError(format!(
-                "[reset_inverse_cache] Inserting DAO query into inverse cache failed: {e:?}"
-            )))
-        }
-
-        Ok(())
-    }
-
-    /// Auxiliary function to store current `walletdb` inverse cache
-    /// in scanned blocks information for provided block height and hash.
-    /// Additionally, clear `walletdb` inverse cache state.
-    pub fn store_inverse_cache(&self, height: u32, hash: &str) -> Result<()> {
-        // Grab current inverse state rollback query
-        let rollback_query = match self.wallet.grab_inverse_cache_block() {
-            Ok(q) => q,
-            Err(e) => {
-                return Err(Error::DatabaseError(format!(
-                    "[store_inverse_cache] Creating rollback query failed: {e:?}"
-                )))
-            }
-        };
-
-        // Store it as a scanned blocks information record
-        if let Err(e) = self.put_scanned_block_record(height, hash, &rollback_query) {
-            return Err(Error::DatabaseError(format!(
-                "[store_inverse_cache] Inserting scanned blocks information record failed: {e:?}"
-            )))
-        };
-
-        // Reset `walletdb` inverse cache
-        if let Err(e) = self.wallet.clear_inverse_cache() {
-            return Err(Error::DatabaseError(format!(
-                "[store_inverse_cache] Clearing wallet inverse cache failed: {e:?}"
-            )))
-        };
-
         Ok(())
     }
 }

+ 4 - 4
bin/drk/src/main.rs

@@ -2189,9 +2189,9 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 )
                 .await;
 
-                if let Some(h) = height {
-                    let (height, hash, _) = match drk.get_scanned_block_record(h) {
-                        Ok(ret) => ret,
+                if let Some(height) = height {
+                    let hash = match drk.get_scanned_block_hash(&height) {
+                        Ok(h) => h,
                         Err(e) => {
                             eprintln!("Failed to retrieve scanned block record: {e:?}");
                             exit(2);
@@ -2216,7 +2216,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 let mut table = Table::new();
                 table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
                 table.set_titles(row!["Height", "Hash"]);
-                for (height, hash, _) in map.iter() {
+                for (height, hash) in map.iter() {
                     table.add_row(row![height, hash]);
                 }
 

+ 28 - 110
bin/drk/src/money.rs

@@ -22,7 +22,6 @@ use std::{
 };
 
 use lazy_static::lazy_static;
-use num_bigint::BigUint;
 use rand::rngs::OsRng;
 use rusqlite::types::Value;
 
@@ -49,8 +48,8 @@ use darkfi_money_contract::{
 use darkfi_sdk::{
     bridgetree,
     crypto::{
-        note::AeadEncryptedNote, pasta_prelude::PrimeField, BaseBlind, FuncId, Keypair, MerkleNode,
-        MerkleTree, PublicKey, ScalarBlind, SecretKey, MONEY_CONTRACT_ID,
+        note::AeadEncryptedNote, BaseBlind, FuncId, Keypair, MerkleNode, MerkleTree, PublicKey,
+        ScalarBlind, SecretKey, MONEY_CONTRACT_ID,
     },
     dark_tree::DarkLeaf,
     pasta::pallas,
@@ -59,8 +58,12 @@ use darkfi_sdk::{
 use darkfi_serial::{deserialize_async, serialize_async, AsyncEncodable};
 
 use crate::{
-    cache::CacheSmt, cli_util::kaching, convert_named_params, error::WalletDbResult,
-    rpc::ScanCache, Drk,
+    cache::CacheSmt,
+    cli_util::kaching,
+    convert_named_params,
+    error::{WalletDbError, WalletDbResult},
+    rpc::ScanCache,
+    Drk,
 };
 
 // Money Merkle tree Sled key
@@ -69,9 +72,6 @@ pub const SLED_MERKLE_TREES_MONEY: &[u8] = b"_money_tree";
 // Wallet SQL table constant names. These have to represent the `money.sql`
 // SQL schema. Table names are prefixed with the contract ID to avoid collisions.
 lazy_static! {
-    pub static ref MONEY_TREE_TABLE: String =
-        format!("{}_money_tree", MONEY_CONTRACT_ID.to_string());
-    pub static ref MONEY_SMT_TABLE: String = format!("{}_money_smt", MONEY_CONTRACT_ID.to_string());
     pub static ref MONEY_KEYS_TABLE: String =
         format!("{}_money_keys", MONEY_CONTRACT_ID.to_string());
     pub static ref MONEY_COINS_TABLE: String =
@@ -82,13 +82,6 @@ lazy_static! {
         format!("{}_money_aliases", MONEY_CONTRACT_ID.to_string());
 }
 
-// MONEY_TREE_TABLE
-pub const MONEY_TREE_COL_TREE: &str = "tree";
-
-// MONEY_SMT_TABLE
-pub const MONEY_SMT_COL_KEY: &str = "smt_key";
-pub const MONEY_SMT_COL_VALUE: &str = "smt_value";
-
 // MONEY_KEYS_TABLE
 pub const MONEY_KEYS_COL_KEY_ID: &str = "key_id";
 pub const MONEY_KEYS_COL_IS_DEFAULT: &str = "is_default";
@@ -129,22 +122,6 @@ impl Drk {
         let wallet_schema = include_str!("../money.sql");
         self.wallet.exec_batch_sql(wallet_schema)?;
 
-        // Check if we have to initialize the Merkle tree.
-        // We check if we find a row in the tree table, and if not, we create a
-        // new tree and push it into the table.
-        // For now, on success, we don't care what's returned, but in the future
-        // we should actually check it.
-        if self.get_money_tree().await.is_err() {
-            println!("Initializing Money Merkle tree");
-            let mut tree = MerkleTree::new(1);
-            tree.append(MerkleNode::from(pallas::Base::ZERO));
-            let _ = tree.mark().unwrap();
-            let query =
-                format!("INSERT INTO {} ({}) VALUES (?1);", *MONEY_TREE_TABLE, MONEY_TREE_COL_TREE);
-            self.wallet.exec_sql(&query, rusqlite::params![serialize_async(&tree).await])?;
-            println!("Successfully initialized Merkle tree for the Money contract");
-        }
-
         // Insert DRK alias
         self.add_alias("DRK".to_string(), *DARK_TOKEN_ID).await?;
 
@@ -642,81 +619,20 @@ impl Drk {
         )
     }
 
-    /// Replace the Money Merkle tree in the wallet.
-    pub async fn put_money_tree(&self, tree: &MerkleTree) -> WalletDbResult<()> {
-        let query = format!("UPDATE {} SET {} = ?1;", *MONEY_TREE_TABLE, MONEY_TREE_COL_TREE);
-        self.wallet.exec_sql(&query, rusqlite::params![serialize_async(tree).await])
-    }
-
-    /// Fetch the Money Merkle tree from the wallet.
+    /// Fetch the Money Merkle tree from the cache.
+    /// If it doesn't exists a new Merkle Tree is returned.
     pub async fn get_money_tree(&self) -> Result<MerkleTree> {
-        let row = match self.wallet.query_single(&MONEY_TREE_TABLE, &[MONEY_TREE_COL_TREE], &[]) {
-            Ok(r) => r,
-            Err(e) => {
-                return Err(Error::DatabaseError(format!(
-                    "[get_money_tree] Tree retrieval failed: {e:?}"
-                )))
+        match self.cache.merkle_trees.get(SLED_MERKLE_TREES_MONEY)? {
+            Some(tree_bytes) => Ok(deserialize_async(&tree_bytes).await?),
+            None => {
+                let mut tree = MerkleTree::new(1);
+                tree.append(MerkleNode::from(pallas::Base::ZERO));
+                let _ = tree.mark().unwrap();
+                Ok(tree)
             }
-        };
-
-        let Value::Blob(ref tree_bytes) = row[0] else {
-            return Err(Error::ParseFailed("[get_money_tree] Tree bytes parsing failed"))
-        };
-        let tree = deserialize_async(tree_bytes).await?;
-        Ok(tree)
-    }
-
-    /// Auxiliary function to fetch the current Money Merkle tree state,
-    /// as an update query.
-    pub async fn get_money_tree_state_query(&self) -> Result<String> {
-        // Grab current money tree
-        let tree = self.get_money_tree().await?;
-
-        // Create the update query
-        match self.wallet.create_prepared_statement(
-            &format!("UPDATE {} SET {} = ?1;", *MONEY_TREE_TABLE, MONEY_TREE_COL_TREE),
-            rusqlite::params![serialize_async(&tree).await],
-        ) {
-            Ok(q) => Ok(q),
-            Err(e) => Err(Error::DatabaseError(format!(
-                "[get_money_tree_state_query] Creating query for money tree failed: {e:?}"
-            ))),
         }
     }
 
-    /// Fetch the Money nullifiers SMT from the wallet, as a map.
-    pub async fn get_nullifiers_smt(&self) -> Result<HashMap<BigUint, pallas::Base>> {
-        let rows = match self.wallet.query_multiple(&MONEY_SMT_TABLE, &[], &[]) {
-            Ok(r) => r,
-            Err(e) => {
-                return Err(Error::DatabaseError(format!(
-                    "[get_nullifiers_smt] SMT records retrieval failed: {e:?}"
-                )))
-            }
-        };
-
-        let mut smt = HashMap::new();
-        for row in rows {
-            let Value::Blob(ref key_bytes) = row[0] else {
-                return Err(Error::ParseFailed("[get_nullifiers_smt] Key bytes parsing failed"))
-            };
-            let key = BigUint::from_bytes_le(key_bytes);
-
-            let Value::Blob(ref value_bytes) = row[1] else {
-                return Err(Error::ParseFailed("[get_nullifiers_smt] Value bytes parsing failed"))
-            };
-            let mut repr = [0; 32];
-            repr.copy_from_slice(value_bytes);
-            let Some(value) = pallas::Base::from_repr(repr).into() else {
-                return Err(Error::ParseFailed("[get_nullifiers_smt] Value conversion failed"))
-            };
-
-            smt.insert(key, value);
-        }
-
-        Ok(smt)
-    }
-
     /// Auxiliary function to grab all the nullifiers, coins with their
     /// notes and freezes from a transaction money call.
     async fn parse_money_call(
@@ -1155,23 +1071,25 @@ impl Drk {
         Ok(smt.insert_batch(leaves)?)
     }
 
-    /// Reset the Money Merkle tree in the wallet.
-    pub async fn reset_money_tree(&self) -> WalletDbResult<()> {
+    /// Reset the Money Merkle tree in the cache.
+    pub fn reset_money_tree(&self) -> WalletDbResult<()> {
         println!("Resetting Money Merkle tree");
-        let mut tree = MerkleTree::new(1);
-        tree.append(MerkleNode::from(pallas::Base::ZERO));
-        let _ = tree.mark().unwrap();
-        self.put_money_tree(&tree).await?;
+        if let Err(e) = self.cache.merkle_trees.remove(SLED_MERKLE_TREES_MONEY) {
+            println!("[reset_money_tree] Resetting Money Merkle tree failed: {e:?}");
+            return Err(WalletDbError::GenericError)
+        }
         println!("Successfully reset Money Merkle tree");
 
         Ok(())
     }
 
-    /// Reset the Money nullifiers Sparse Merkle Tree in the wallet.
+    /// Reset the Money nullifiers Sparse Merkle Tree in the cache.
     pub fn reset_money_smt(&self) -> WalletDbResult<()> {
         println!("Resetting Money Sparse Merkle tree");
-        let query = format!("DELETE FROM {};", *MONEY_SMT_TABLE);
-        self.wallet.exec_sql(&query, &[])?;
+        if let Err(e) = self.cache.money_smt.clear() {
+            println!("[reset_money_smt] Resetting Money Sparse Merkle tree failed: {e:?}");
+            return Err(WalletDbError::GenericError)
+        }
         println!("Successfully reset Money Sparse Merkle tree");
 
         Ok(())

+ 1 - 4
bin/drk/src/rpc.rs

@@ -415,9 +415,6 @@ impl Drk {
             )))
         }
 
-        // Store this block rollback query
-        self.store_inverse_cache(block.header.height, &block.hash().to_string())?;
-
         Ok(())
     }
 
@@ -446,7 +443,7 @@ impl Drk {
             height = height.saturating_sub(1);
             while height != 0 {
                 // Grab our scanned block hash for that height
-                let (_, scanned_block_hash, _) = self.get_scanned_block_record(height)?;
+                let scanned_block_hash = self.get_scanned_block_hash(&height)?;
 
                 // Grab the block from darkfid for that height
                 let block = match self.get_block_by_height(height).await {

+ 43 - 71
bin/drk/src/scanned_blocks.rs

@@ -16,100 +16,71 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use rusqlite::types::Value;
+use darkfi_serial::deserialize;
 
 use crate::{
-    convert_named_params,
     error::{WalletDbError, WalletDbResult},
     Drk,
 };
 
-// Wallet SQL table constant names. These have to represent the `wallet.sql`
-// SQL schema.
-const WALLET_SCANNED_BLOCKS_TABLE: &str = "scanned_blocks";
-const WALLET_SCANNED_BLOCKS_COL_HEIGH: &str = "height";
-const WALLET_SCANNED_BLOCKS_COL_HASH: &str = "hash";
-const WALLET_SCANNED_BLOCKS_COL_ROLLBACK_QUERY: &str = "rollback_query";
-
 impl Drk {
-    /// Insert a scanned block information record into the wallet.
-    pub fn put_scanned_block_record(
-        &self,
-        height: u32,
-        hash: &str,
-        rollback_query: &str,
-    ) -> WalletDbResult<()> {
-        let query = format!(
-            "INSERT INTO {WALLET_SCANNED_BLOCKS_TABLE} ({WALLET_SCANNED_BLOCKS_COL_HEIGH}, {WALLET_SCANNED_BLOCKS_COL_HASH}, {WALLET_SCANNED_BLOCKS_COL_ROLLBACK_QUERY}) VALUES (?1, ?2, ?3);"
-        );
-        self.wallet.exec_sql(&query, rusqlite::params![height, hash, rollback_query])
-    }
-
-    /// Auxiliary function to parse a `WALLET_SCANNED_BLOCKS_TABLE` records.
-    fn parse_scanned_block_record(&self, row: &[Value]) -> WalletDbResult<(u32, String, String)> {
-        let Value::Integer(height) = row[0] else {
-            return Err(WalletDbError::ParseColumnValueError);
-        };
-        let Ok(height) = u32::try_from(height) else {
-            return Err(WalletDbError::ParseColumnValueError);
+    /// Get a scanned block information record.
+    pub fn get_scanned_block_hash(&self, height: &u32) -> WalletDbResult<String> {
+        let Ok(query_result) = self.cache.scanned_blocks.get(height.to_be_bytes()) else {
+            return Err(WalletDbError::QueryExecutionFailed);
         };
-
-        let Value::Text(ref hash) = row[1] else {
-            return Err(WalletDbError::ParseColumnValueError);
+        let Some(hash_bytes) = query_result else {
+            return Err(WalletDbError::RowNotFound);
         };
-
-        let Value::Text(ref rollback_query) = row[2] else {
+        let Ok(hash) = deserialize(&hash_bytes) else {
             return Err(WalletDbError::ParseColumnValueError);
         };
-
-        Ok((height, hash.clone(), rollback_query.clone()))
-    }
-
-    /// Get a scanned block information record.
-    pub fn get_scanned_block_record(&self, height: u32) -> WalletDbResult<(u32, String, String)> {
-        let row = self.wallet.query_single(
-            WALLET_SCANNED_BLOCKS_TABLE,
-            &[],
-            convert_named_params! {(WALLET_SCANNED_BLOCKS_COL_HEIGH, height)},
-        )?;
-
-        self.parse_scanned_block_record(&row)
+        Ok(hash)
     }
 
-    /// Fetch all scanned block information record.
-    pub fn get_scanned_block_records(&self) -> WalletDbResult<Vec<(u32, String, String)>> {
-        let rows = self.wallet.query_multiple(WALLET_SCANNED_BLOCKS_TABLE, &[], &[])?;
-
-        let mut ret = Vec::with_capacity(rows.len());
-        for row in rows {
-            ret.push(self.parse_scanned_block_record(&row)?);
+    /// Fetch all scanned block information records.
+    pub fn get_scanned_block_records(&self) -> WalletDbResult<Vec<(u32, String)>> {
+        let mut scanned_blocks = vec![];
+
+        for record in self.cache.scanned_blocks.iter() {
+            let Ok((key, value)) = record else {
+                return Err(WalletDbError::QueryExecutionFailed);
+            };
+            let Ok(key) = deserialize(&key) else {
+                return Err(WalletDbError::ParseColumnValueError);
+            };
+            let Ok(value) = deserialize(&value) else {
+                return Err(WalletDbError::ParseColumnValueError);
+            };
+            scanned_blocks.push((key, value));
         }
 
-        Ok(ret)
+        Ok(scanned_blocks)
     }
 
     /// Get the last scanned block height and hash from the wallet.
     /// If database is empty default (0, '-') is returned.
     pub fn get_last_scanned_block(&self) -> WalletDbResult<(u32, String)> {
-        let query = format!(
-            "SELECT * FROM {WALLET_SCANNED_BLOCKS_TABLE} ORDER BY {WALLET_SCANNED_BLOCKS_COL_HEIGH} DESC LIMIT 1;"
-        );
-        let ret = self.wallet.query_custom(&query, &[])?;
-
-        if ret.is_empty() {
-            return Ok((0, String::from("-")))
-        }
-
-        let (height, hash, _) = self.parse_scanned_block_record(&ret[0])?;
-
-        Ok((height, hash))
+        let Ok(query_result) = self.cache.scanned_blocks.last() else {
+            return Err(WalletDbError::QueryExecutionFailed);
+        };
+        let Some((key, value)) = query_result else { return Ok((0, String::from("-"))) };
+        let Ok(key) = deserialize(&key) else {
+            return Err(WalletDbError::ParseColumnValueError);
+        };
+        let Ok(value) = deserialize(&value) else {
+            return Err(WalletDbError::ParseColumnValueError);
+        };
+        Ok((key, value))
     }
 
     /// Reset the scanned blocks information records in the wallet.
     pub fn reset_scanned_blocks(&self) -> WalletDbResult<()> {
         println!("Resetting scanned blocks");
-        let query = format!("DELETE FROM {WALLET_SCANNED_BLOCKS_TABLE};");
-        self.wallet.exec_sql(&query, &[])?;
+        if let Err(e) = self.cache.scanned_blocks.clear() {
+            println!("[reset_scanned_blocks] Resetting scanned blocks tree failed: {e:?}");
+            return Err(WalletDbError::GenericError)
+        }
         println!("Successfully reset scanned blocks");
 
         Ok(())
@@ -125,7 +96,8 @@ impl Drk {
         if height == 0 {
             return self.reset().await
         }
-
+        // TODO
+        /*
         // Grab last scanned block height
         let (last, _) = self.get_last_scanned_block()?;
 
@@ -143,7 +115,7 @@ impl Drk {
             let query = format!("DELETE FROM {WALLET_SCANNED_BLOCKS_TABLE} WHERE {WALLET_SCANNED_BLOCKS_COL_HEIGH} = {height};");
             self.wallet.exec_batch_sql(&query)?;
         }
-
+        */
         println!("Successfully reset wallet state");
         Ok(())
     }

+ 0 - 7
bin/drk/wallet.sql

@@ -3,13 +3,6 @@
 
 PRAGMA foreign_keys = ON;
 
--- Scanned blocks information
-CREATE TABLE IF NOT EXISTS scanned_blocks (
-	height INTEGER PRIMARY KEY NOT NULL,
-	hash TEXT NOT NULL,
-	rollback_query TEXT NOT NULL
-);
-
 -- Transactions history
 CREATE TABLE IF NOT EXISTS transactions_history (
     transaction_hash TEXT PRIMARY KEY NOT NULL,