mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 14:48:08 -05:00
drk: use block references to reset stuff
This commit is contained in:
@@ -28,7 +28,7 @@ use darkfi_sdk::{
|
||||
error::{ContractError, ContractResult},
|
||||
pasta::pallas,
|
||||
};
|
||||
use darkfi_serial::serialize;
|
||||
use darkfi_serial::{deserialize, serialize};
|
||||
use log::error;
|
||||
use num_bigint::BigUint;
|
||||
use sled_overlay::{sled, SledDbOverlay, SledDbOverlayStateDiff};
|
||||
@@ -79,6 +79,21 @@ impl Cache {
|
||||
money_smt,
|
||||
})
|
||||
}
|
||||
|
||||
/// Fetch given block height numbers from the store's state inverse
|
||||
/// diffs tree. The function will fail if a block height number was
|
||||
/// not found.
|
||||
pub fn get_state_inverse_diff(&self, heights: &[u32]) -> Result<Vec<SledDbOverlayStateDiff>> {
|
||||
let mut ret = Vec::with_capacity(heights.len());
|
||||
for height in heights {
|
||||
match self.state_inverse_diff.get(height.to_be_bytes())? {
|
||||
Some(found) => ret.push(deserialize(&found)?),
|
||||
None => return Err(Error::BlockStateInverseDiffNotFound(*height)),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
/// Overlay structure over a [`Cache`] instance.
|
||||
|
||||
@@ -1628,7 +1628,7 @@ impl Drk {
|
||||
}
|
||||
|
||||
/// Reset the DAO Merkle trees in the cache.
|
||||
pub async fn reset_dao_trees(&self) -> WalletDbResult<()> {
|
||||
pub fn reset_dao_trees(&self) -> WalletDbResult<()> {
|
||||
println!("Resetting DAO Merkle trees");
|
||||
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:?}");
|
||||
@@ -1644,7 +1644,7 @@ impl Drk {
|
||||
}
|
||||
|
||||
/// Reset confirmed DAOs in the wallet.
|
||||
pub async fn reset_daos(&self) -> WalletDbResult<()> {
|
||||
pub fn reset_daos(&self) -> WalletDbResult<()> {
|
||||
println!("Resetting DAO confirmations");
|
||||
let query = format!(
|
||||
"UPDATE {} SET {} = NULL, {} = NULL, {} = NULL, {} = NULL;",
|
||||
@@ -1660,8 +1660,27 @@ impl Drk {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reset confirmed DAOs in the wallet that were minted after
|
||||
/// provided height.
|
||||
pub fn unconfirm_daos_after(&self, height: &u32) -> WalletDbResult<()> {
|
||||
println!("Resetting DAO confirmations after: {height}");
|
||||
let query = format!(
|
||||
"UPDATE {} SET {} = NULL, {} = NULL, {} = NULL, {} = NULL WHERE {} > ?1;",
|
||||
*DAO_DAOS_TABLE,
|
||||
DAO_DAOS_COL_LEAF_POSITION,
|
||||
DAO_DAOS_COL_MINT_HEIGHT,
|
||||
DAO_DAOS_COL_TX_HASH,
|
||||
DAO_DAOS_COL_CALL_INDEX,
|
||||
DAO_DAOS_COL_MINT_HEIGHT,
|
||||
);
|
||||
self.wallet.exec_sql(&query, rusqlite::params![Some(*height)])?;
|
||||
println!("Successfully unconfirmed DAOs");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reset all DAO proposals in the wallet.
|
||||
pub async fn reset_dao_proposals(&self) -> WalletDbResult<()> {
|
||||
pub fn reset_dao_proposals(&self) -> WalletDbResult<()> {
|
||||
println!("Resetting DAO proposals confirmations");
|
||||
let query = format!(
|
||||
"UPDATE {} SET {} = NULL, {} = NULL, {} = NULL, {} = NULL, {} = NULL, {} = NULL, {} = NULL, {} = NULL;",
|
||||
@@ -1681,11 +1700,66 @@ impl Drk {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reset DAO proposals in the wallet that were minted after
|
||||
/// provided height.
|
||||
pub fn unconfirm_dao_proposals_after(&self, height: &u32) -> WalletDbResult<()> {
|
||||
println!("Resetting DAO proposals confirmations after: {height}");
|
||||
let query = format!(
|
||||
"UPDATE {} SET {} = NULL, {} = NULL, {} = NULL, {} = NULL, {} = NULL, {} = NULL, {} = NULL, {} = NULL WHERE {} > ?1;",
|
||||
*DAO_PROPOSALS_TABLE,
|
||||
DAO_PROPOSALS_COL_LEAF_POSITION,
|
||||
DAO_PROPOSALS_COL_MONEY_SNAPSHOT_TREE,
|
||||
DAO_PROPOSALS_COL_NULLIFIERS_SMT_SNAPSHOT,
|
||||
DAO_PROPOSALS_COL_MINT_HEIGHT,
|
||||
DAO_PROPOSALS_COL_TX_HASH,
|
||||
DAO_PROPOSALS_COL_CALL_INDEX,
|
||||
DAO_PROPOSALS_COL_EXEC_HEIGHT,
|
||||
DAO_PROPOSALS_COL_EXEC_TX_HASH,
|
||||
DAO_PROPOSALS_COL_MINT_HEIGHT,
|
||||
);
|
||||
self.wallet.exec_sql(&query, rusqlite::params![Some(*height)])?;
|
||||
println!("Successfully unconfirmed DAO proposals");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reset execution information in the wallet for DAO proposals
|
||||
/// that were executed after provided height.
|
||||
pub fn unexec_dao_proposals_after(&self, height: &u32) -> WalletDbResult<()> {
|
||||
println!("Resetting DAO proposals execution information after: {height}");
|
||||
let query = format!(
|
||||
"UPDATE {} SET {} = NULL, {} = NULL WHERE {} > ?1;",
|
||||
*DAO_PROPOSALS_TABLE,
|
||||
DAO_PROPOSALS_COL_EXEC_HEIGHT,
|
||||
DAO_PROPOSALS_COL_EXEC_TX_HASH,
|
||||
DAO_PROPOSALS_COL_EXEC_HEIGHT,
|
||||
);
|
||||
self.wallet.exec_sql(&query, rusqlite::params![Some(*height)])?;
|
||||
println!("Successfully reset DAO proposals execution information");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reset all DAO votes in the wallet.
|
||||
pub fn reset_dao_votes(&self) -> WalletDbResult<()> {
|
||||
println!("Resetting DAO votes");
|
||||
let query = format!("DELETE FROM {};", *DAO_VOTES_TABLE);
|
||||
self.wallet.exec_sql(&query, &[])
|
||||
self.wallet.exec_sql(&query, &[])?;
|
||||
println!("Successfully reset DAO votes");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove the DAO votes in the wallet that were created after
|
||||
/// provided height.
|
||||
pub fn remove_dao_votes_after(&self, height: &u32) -> WalletDbResult<()> {
|
||||
println!("Removing DAO votes after: {height}");
|
||||
let query =
|
||||
format!("DELETE FROM {} WHERE {} > ?1;", *DAO_VOTES_TABLE, DAO_VOTES_COL_BLOCK_HEIGHT);
|
||||
self.wallet.exec_sql(&query, rusqlite::params![height])?;
|
||||
println!("Successfully removed DAO votes");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Import given DAO params into the wallet with a given name.
|
||||
|
||||
@@ -84,6 +84,36 @@ impl Drk {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reset all token deploy authorities frozen status in the wallet.
|
||||
pub fn reset_deploy_authorities(&self) -> WalletDbResult<()> {
|
||||
println!("Resetting deploy authorities frozen status");
|
||||
let query = format!(
|
||||
"UPDATE {} SET {} = 0, {} = NULL;",
|
||||
*DEPLOY_AUTH_TABLE, DEPLOY_AUTH_COL_IS_FROZEN, DEPLOY_AUTH_COL_FREEZE_HEIGHT
|
||||
);
|
||||
self.wallet.exec_sql(&query, &[])?;
|
||||
println!("Successfully reset deploy authorities frozen status");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove deploy authorities frozen status in the wallet that
|
||||
/// where frozen after provided height.
|
||||
pub fn unfreeze_deploy_authorities_after(&self, height: &u32) -> WalletDbResult<()> {
|
||||
println!("Resetting deploy authorities frozen status after: {height}");
|
||||
let query = format!(
|
||||
"UPDATE {} SET {} = 0, {} = NULL WHERE {} > ?1;",
|
||||
*DEPLOY_AUTH_TABLE,
|
||||
DEPLOY_AUTH_COL_IS_FROZEN,
|
||||
DEPLOY_AUTH_COL_FREEZE_HEIGHT,
|
||||
DEPLOY_AUTH_COL_FREEZE_HEIGHT
|
||||
);
|
||||
self.wallet.exec_sql(&query, rusqlite::params![Some(*height)])?;
|
||||
println!("Successfully reset deploy authorities frozen status");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// List contract deploy authorities from the wallet
|
||||
pub async fn list_deploy_auth(&self) -> Result<Vec<(i64, ContractId, bool, Option<u32>)>> {
|
||||
let rows = match self.wallet.query_multiple(&DEPLOY_AUTH_TABLE, &[], &[]) {
|
||||
|
||||
@@ -122,17 +122,18 @@ impl Drk {
|
||||
}
|
||||
|
||||
/// Auxiliary function to completely reset wallet state.
|
||||
pub async fn reset(&self) -> WalletDbResult<()> {
|
||||
pub fn reset(&self) -> WalletDbResult<()> {
|
||||
println!("Resetting full wallet state");
|
||||
self.reset_scanned_blocks()?;
|
||||
self.reset_money_tree()?;
|
||||
self.reset_money_smt()?;
|
||||
self.reset_money_coins()?;
|
||||
self.reset_mint_authorities()?;
|
||||
self.reset_dao_trees().await?;
|
||||
self.reset_daos().await?;
|
||||
self.reset_dao_proposals().await?;
|
||||
self.reset_dao_trees()?;
|
||||
self.reset_daos()?;
|
||||
self.reset_dao_proposals()?;
|
||||
self.reset_dao_votes()?;
|
||||
self.reset_deploy_authorities()?;
|
||||
self.reset_tx_history()?;
|
||||
println!("Successfully reset full wallet state");
|
||||
Ok(())
|
||||
|
||||
@@ -2032,7 +2032,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
|
||||
.await;
|
||||
|
||||
if let Some(height) = reset {
|
||||
if let Err(e) = drk.reset_to_height(height).await {
|
||||
if let Err(e) = drk.reset_to_height(height) {
|
||||
eprintln!("Failed during wallet reset: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@@ -651,20 +651,15 @@ impl Drk {
|
||||
|
||||
/// Mark a given coin in the wallet as unspent.
|
||||
pub async fn unspend_coin(&self, coin: &Coin) -> WalletDbResult<()> {
|
||||
let is_spend = 0;
|
||||
let spent_height: Option<u32> = None;
|
||||
let query = format!(
|
||||
"UPDATE {} SET {} = ?1, {} = ?2, {} = ?3 WHERE {} = ?4;",
|
||||
"UPDATE {} SET {} = 0, {} = NULL, {} = '-' WHERE {} = ?1;",
|
||||
*MONEY_COINS_TABLE,
|
||||
MONEY_COINS_COL_IS_SPENT,
|
||||
MONEY_COINS_COL_SPENT_HEIGHT,
|
||||
MONEY_COINS_COL_SPENT_TX_HASH,
|
||||
MONEY_COINS_COL_COIN
|
||||
);
|
||||
self.wallet.exec_sql(
|
||||
&query,
|
||||
rusqlite::params![is_spend, spent_height, "-", serialize_async(&coin.inner()).await],
|
||||
)
|
||||
self.wallet.exec_sql(&query, rusqlite::params![serialize_async(&coin.inner()).await])
|
||||
}
|
||||
|
||||
/// Fetch the Money Merkle tree from the cache.
|
||||
@@ -1120,6 +1115,38 @@ impl Drk {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove the Money coins in the wallet that were created after
|
||||
/// provided height.
|
||||
pub fn remove_money_coins_after(&self, height: &u32) -> WalletDbResult<()> {
|
||||
println!("Removing coins after: {height}");
|
||||
let query = format!(
|
||||
"DELETE FROM {} WHERE {} > ?1;",
|
||||
*MONEY_COINS_TABLE, MONEY_COINS_COL_CREATION_HEIGHT
|
||||
);
|
||||
self.wallet.exec_sql(&query, rusqlite::params![height])?;
|
||||
println!("Successfully removed coins");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Mark the Money coins in the wallet that were spent after
|
||||
/// provided height as unspent.
|
||||
pub fn unspent_money_coins_after(&self, height: &u32) -> WalletDbResult<()> {
|
||||
println!("Unspenting coins after: {height}");
|
||||
let query = format!(
|
||||
"UPDATE {} SET {} = 0, {} = NULL, {} = '=' WHERE {} > ?1;",
|
||||
*MONEY_COINS_TABLE,
|
||||
MONEY_COINS_COL_IS_SPENT,
|
||||
MONEY_COINS_COL_SPENT_HEIGHT,
|
||||
MONEY_COINS_COL_SPENT_TX_HASH,
|
||||
MONEY_COINS_COL_SPENT_HEIGHT
|
||||
);
|
||||
self.wallet.exec_sql(&query, rusqlite::params![Some(*height)])?;
|
||||
println!("Successfully unspent coins");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Retrieve token by provided string.
|
||||
/// Input string represents either an alias or a token id.
|
||||
pub async fn get_token(&self, input: String) -> Result<TokenId> {
|
||||
|
||||
@@ -239,7 +239,7 @@ impl Drk {
|
||||
// Check if a reorg block was received, to reset to its previous
|
||||
if block.header.height <= last_scanned_height {
|
||||
let reset_height = block.header.height.saturating_sub(1);
|
||||
if let Err(e) = self.reset_to_height(reset_height).await {
|
||||
if let Err(e) = self.reset_to_height(reset_height) {
|
||||
return Err(Error::DatabaseError(format!(
|
||||
"[subscribe_blocks] Wallet state reset failed: {e:?}"
|
||||
)))
|
||||
@@ -483,7 +483,7 @@ impl Drk {
|
||||
|
||||
// Reset to its height
|
||||
println!("Last common block found: {height} - {scanned_block_hash}");
|
||||
self.reset_to_height(height).await?;
|
||||
self.reset_to_height(height)?;
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -491,7 +491,7 @@ impl Drk {
|
||||
// If last scanned block is genesis(0) we reset,
|
||||
// otherwise continue with the next block height.
|
||||
if height == 0 {
|
||||
self.reset().await?;
|
||||
self.reset()?;
|
||||
} else {
|
||||
height += 1;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
use darkfi_serial::deserialize;
|
||||
|
||||
use crate::{
|
||||
cache::CacheOverlay,
|
||||
error::{WalletDbError, WalletDbResult},
|
||||
Drk,
|
||||
};
|
||||
@@ -88,16 +89,15 @@ impl Drk {
|
||||
|
||||
/// Reset state to provided block height.
|
||||
/// If genesis block height(0) was provided, perform a full reset.
|
||||
pub async fn reset_to_height(&self, height: u32) -> WalletDbResult<()> {
|
||||
pub fn reset_to_height(&self, height: u32) -> WalletDbResult<()> {
|
||||
println!("Resetting wallet state to block: {height}");
|
||||
|
||||
// If genesis block height(0) was provided,
|
||||
// perform a full reset.
|
||||
if height == 0 {
|
||||
return self.reset().await
|
||||
return self.reset()
|
||||
}
|
||||
// TODO
|
||||
/*
|
||||
|
||||
// Grab last scanned block height
|
||||
let (last, _) = self.get_last_scanned_block()?;
|
||||
|
||||
@@ -107,15 +107,75 @@ impl Drk {
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
// Iterate the range (height, last] in reverse to grab the corresponding blocks
|
||||
for height in (height + 1..=last).rev() {
|
||||
let (height, hash, query) = self.get_scanned_block_record(height)?;
|
||||
println!("Reverting block: {height} - {hash}");
|
||||
self.wallet.exec_batch_sql(&query)?;
|
||||
let query = format!("DELETE FROM {WALLET_SCANNED_BLOCKS_TABLE} WHERE {WALLET_SCANNED_BLOCKS_COL_HEIGH} = {height};");
|
||||
self.wallet.exec_batch_sql(&query)?;
|
||||
// Grab all state inverse diffs until requested height,
|
||||
// going backwards.
|
||||
let heights: Vec<u32> = (height + 1..=last).rev().collect();
|
||||
let inverse_diffs = match self.cache.get_state_inverse_diff(&heights) {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
println!(
|
||||
"[reset_to_height] Retrieving state inverse diffs from cache failed: {e:?}"
|
||||
);
|
||||
return Err(WalletDbError::GenericError)
|
||||
}
|
||||
};
|
||||
|
||||
// Create an overlay to apply the reverse diffs
|
||||
let mut overlay = match CacheOverlay::new(&self.cache) {
|
||||
Ok(o) => o,
|
||||
Err(e) => {
|
||||
println!("[reset_to_height] Creating cache overlay failed: {e:?}");
|
||||
return Err(WalletDbError::GenericError)
|
||||
}
|
||||
};
|
||||
|
||||
// Apply the inverse diffs sequence
|
||||
for inverse_diff in inverse_diffs {
|
||||
if let Err(e) = overlay.0.add_diff(&inverse_diff) {
|
||||
println!("[reset_to_height] Adding state inverse diff to the cache overlay failed: {e:?}");
|
||||
return Err(WalletDbError::GenericError)
|
||||
}
|
||||
if let Err(e) = overlay.0.apply_diff(&inverse_diff) {
|
||||
println!("[reset_to_height] Applying state inverse diff to the cache overlay failed: {e:?}");
|
||||
return Err(WalletDbError::GenericError)
|
||||
}
|
||||
if let Err(e) = self.cache.sled_db.flush() {
|
||||
println!("[reset_to_height] Flushing cache sled database failed: {e:?}");
|
||||
return Err(WalletDbError::GenericError)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Remove all wallet coins created after the reset height
|
||||
self.remove_money_coins_after(&height)?;
|
||||
|
||||
// Unspent all wallet coins spent after the reset height
|
||||
self.unspent_money_coins_after(&height)?;
|
||||
|
||||
// Unfreeze tokens mint authorities frozen after the reset
|
||||
// height.
|
||||
self.unfreeze_mint_authorities_after(&height)?;
|
||||
|
||||
// Unconfirm DAOs minted after the reset height
|
||||
self.unconfirm_daos_after(&height)?;
|
||||
|
||||
// Unconfirm DAOs proposals minted after the reset height
|
||||
self.unconfirm_dao_proposals_after(&height)?;
|
||||
|
||||
// Reset execution information for DAOs proposals executed
|
||||
// after the reset height.
|
||||
self.unexec_dao_proposals_after(&height)?;
|
||||
|
||||
// Remove all DAOs proposals votes created after the reset
|
||||
// height.
|
||||
self.remove_dao_votes_after(&height)?;
|
||||
|
||||
// Unfreeze all contracts frozen after the reset height
|
||||
self.unfreeze_deploy_authorities_after(&height)?;
|
||||
|
||||
// Set reverted status to all transactions executed after reset
|
||||
// height.
|
||||
self.revert_transactions_after(&height)?;
|
||||
|
||||
println!("Successfully reset wallet state");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -177,13 +177,29 @@ impl Drk {
|
||||
/// Reset all token mint authorities frozen status in the wallet.
|
||||
pub fn reset_mint_authorities(&self) -> WalletDbResult<()> {
|
||||
println!("Resetting mint authorities frozen status");
|
||||
let freeze_height: Option<u32> = None;
|
||||
let query = format!(
|
||||
"UPDATE {} SET {} = 0, {} = ?1",
|
||||
"UPDATE {} SET {} = 0, {} = NULL;",
|
||||
*MONEY_TOKENS_TABLE, MONEY_TOKENS_COL_IS_FROZEN, MONEY_TOKENS_COL_FREEZE_HEIGHT
|
||||
);
|
||||
self.wallet.exec_sql(&query, rusqlite::params![freeze_height])?;
|
||||
println!("Successfully mint authorities frozen status");
|
||||
self.wallet.exec_sql(&query, &[])?;
|
||||
println!("Successfully reset mint authorities frozen status");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove token mint authorities frozen status in the wallet that
|
||||
/// where frozen after provided height.
|
||||
pub fn unfreeze_mint_authorities_after(&self, height: &u32) -> WalletDbResult<()> {
|
||||
println!("Resetting mint authorities frozen status after: {height}");
|
||||
let query = format!(
|
||||
"UPDATE {} SET {} = 0, {} = NULL WHERE {} > ?1;",
|
||||
*MONEY_TOKENS_TABLE,
|
||||
MONEY_TOKENS_COL_IS_FROZEN,
|
||||
MONEY_TOKENS_COL_FREEZE_HEIGHT,
|
||||
MONEY_TOKENS_COL_FREEZE_HEIGHT
|
||||
);
|
||||
self.wallet.exec_sql(&query, rusqlite::params![Some(*height)])?;
|
||||
println!("Successfully reset mint authorities frozen status");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -183,6 +183,23 @@ impl Drk {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set reverted status to the transaction history records in the
|
||||
/// wallet that where executed after provided height.
|
||||
pub fn revert_transactions_after(&self, height: &u32) -> WalletDbResult<()> {
|
||||
println!("Reverting transactions history after: {height}");
|
||||
let query = format!(
|
||||
"UPDATE {} SET {} = 'Reverted', {} = NULL WHERE {} > ?1;",
|
||||
WALLET_TXS_HISTORY_TABLE,
|
||||
WALLET_TXS_HISTORY_COL_STATUS,
|
||||
WALLET_TXS_HISTORY_BLOCK_HEIGHT,
|
||||
WALLET_TXS_HISTORY_BLOCK_HEIGHT
|
||||
);
|
||||
self.wallet.exec_sql(&query, rusqlite::params![Some(*height)])?;
|
||||
println!("Successfully reverted transactions history");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove the transaction history records in the wallet
|
||||
/// that have been reverted.
|
||||
pub fn remove_reverted_txs(&self) -> WalletDbResult<()> {
|
||||
|
||||
Reference in New Issue
Block a user