Skip to content

Commit

Permalink
check for last used address before reducing lookahead size
Browse files Browse the repository at this point in the history
  • Loading branch information
OBorce committed Jan 10, 2024
1 parent 4697182 commit 6545b31
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 14 deletions.
5 changes: 3 additions & 2 deletions test/functional/test_framework/wallet_cli_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,9 @@ async def create_new_account(self, name: Optional[str] = '') -> str:
async def select_account(self, account_index: int) -> str:
return await self._write_command(f"selectaccount {account_index}\n")

async def set_lookahead_size(self, size: int) -> str:
return await self._write_command(f"setlookaheadsize {size}\n")
async def set_lookahead_size(self, size: int, force_reduce: bool) -> str:
i_know_what_i_am_doing = "i-know-what-i-am-doing" if force_reduce else ""
return await self._write_command(f"setlookaheadsize {size} {i_know_what_i_am_doing}\n")

async def new_public_key(self) -> bytes:
public_key = await self._write_command("newpublickey\n")
Expand Down
8 changes: 5 additions & 3 deletions test/functional/wallet_set_lookahead_size.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,18 +131,20 @@ async def async_test(self):
assert_in(f"Coins amount: {coins_to_send}", await wallet.get_balance())

lower_size = random.randint(1, 2)
assert_in("Success. Lookahead size has been updated, will rescan the blockchain.", await wallet.set_lookahead_size(lower_size))
assert_in(f"Cannot reduce lookahead size to {lower_size} as it is below the last known used key {num_addresses-1}", await wallet.set_lookahead_size(lower_size, False))

assert_in("Success. Lookahead size has been updated, will rescan the blockchain.", await wallet.set_lookahead_size(lower_size, True))

assert_in("Success", await wallet.sync())
assert_in(f"Coins amount: 0", await wallet.get_balance())

higher_size = random.randint(num_addresses, num_addresses * 2)
assert_in("Success. Lookahead size has been updated, will rescan the blockchain.", await wallet.set_lookahead_size(higher_size))
assert_in("Success. Lookahead size has been updated, will rescan the blockchain.", await wallet.set_lookahead_size(higher_size, False))

assert_in("Success", await wallet.sync())
assert_in(f"Coins amount: {coins_to_send}", await wallet.get_balance())

assert_in("Lookahead size cannot be 0", await wallet.set_lookahead_size(0))
assert_in("Lookahead size cannot be 0", await wallet.set_lookahead_size(0, False))



Expand Down
20 changes: 19 additions & 1 deletion wallet/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ pub enum WalletError {
DataDepositToBig(usize, usize),
#[error("Cannot deposit empty data")]
EmptyDataDeposit,
#[error("Cannot reduce lookahead size to {0} as it is below the last known used key {1}")]
ReducedLookaheadSize(u32, u32),
}

/// Result type used for the wallet
Expand Down Expand Up @@ -550,7 +552,23 @@ impl<B: storage::Backend> Wallet<B> {
self.db.unlock_private_keys(password).map_err(WalletError::from)
}

pub fn set_lookahead_size(&mut self, lookahead_size: u32) -> WalletResult<()> {
pub fn set_lookahead_size(
&mut self,
lookahead_size: u32,
force_reduce: bool,
) -> WalletResult<()> {
let last_used = self.accounts.values().fold(None, |last, acc| {
let usage = acc.get_addresses_usage();
std::cmp::max(last, usage.last_used().map(U31::into_u32))
});

if let Some(last_used) = last_used {
ensure!(
last_used < lookahead_size || force_reduce,
WalletError::ReducedLookaheadSize(lookahead_size, last_used)
);
}

let mut db_tx = self.db.transaction_rw(None)?;
db_tx.set_lookahead_size(lookahead_size)?;
let mut accounts = Self::reset_wallet_transactions(self.chain_config.clone(), &mut db_tx)?;
Expand Down
10 changes: 8 additions & 2 deletions wallet/src/wallet/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3529,7 +3529,13 @@ fn wallet_set_lookahead_size(#[case] seed: Seed) {
assert_eq!(coins, block1_amount);

let less_than_last_used = rng.gen_range(1..=last_used);
wallet.set_lookahead_size(less_than_last_used).unwrap();
let err = wallet.set_lookahead_size(less_than_last_used, false).unwrap_err();
assert_eq!(
err,
WalletError::ReducedLookaheadSize(less_than_last_used, last_used)
);

wallet.set_lookahead_size(less_than_last_used, true).unwrap();

scan_wallet(&mut wallet, BlockHeight::new(0), vec![block1.clone()]);
let coins = get_coin_balance_for_acc(&wallet, DEFAULT_ACCOUNT_INDEX);
Expand All @@ -3539,7 +3545,7 @@ fn wallet_set_lookahead_size(#[case] seed: Seed) {
assert_eq!(usage.last_issued(), None);

let more_than_last_used = rng.gen_range(last_used + 1..100);
wallet.set_lookahead_size(more_than_last_used).unwrap();
wallet.set_lookahead_size(more_than_last_used, false).unwrap();

scan_wallet(&mut wallet, BlockHeight::new(0), vec![block1.clone()]);
let coins = get_coin_balance_for_acc(&wallet, DEFAULT_ACCOUNT_INDEX);
Expand Down
5 changes: 5 additions & 0 deletions wallet/wallet-cli-lib/src/commands/helper_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,3 +358,8 @@ impl CliIsUnfreezable {
}
}
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum CliForceReduce {
IKnowWhatIAmDoing,
}
21 changes: 17 additions & 4 deletions wallet/wallet-cli-lib/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ use crate::{

use self::helper_types::{
format_delegation_info, format_pool_info, parse_coin_amount, parse_pool_id, parse_token_amount,
parse_token_id, parse_utxo_outpoint, print_coin_amount, to_per_thousand, CliIsFreezable,
CliIsUnfreezable, CliStoreSeedPhrase, CliUtxoState, CliUtxoTypes, CliWithLocked,
parse_token_id, parse_utxo_outpoint, print_coin_amount, to_per_thousand, CliForceReduce,
CliIsFreezable, CliIsUnfreezable, CliStoreSeedPhrase, CliUtxoState, CliUtxoTypes,
CliWithLocked,
};

#[derive(Debug, Parser)]
Expand Down Expand Up @@ -102,6 +103,10 @@ pub enum WalletCommand {
SetLookaheadSize {
// The new lookahead size
lookahead_size: u32,

// Forces the reduction of lookahead size even below the known last used address
// the new wallet can lose track of known addresses and balance
i_know_what_i_am_doing: Option<CliForceReduce>,
},

/// Returns the node chainstate
Expand Down Expand Up @@ -686,9 +691,17 @@ impl CommandHandler {
))
}

WalletCommand::SetLookaheadSize { lookahead_size } => {
WalletCommand::SetLookaheadSize {
lookahead_size,
i_know_what_i_am_doing,
} => {
let force_reduce = match i_know_what_i_am_doing {
Some(CliForceReduce::IKnowWhatIAmDoing) => true,
None => false,
};

self.controller()?
.set_lookahead_size(lookahead_size)
.set_lookahead_size(lookahead_size, force_reduce)
.map_err(WalletCliError::Controller)?;

Ok(ConsoleCommand::Print(
Expand Down
8 changes: 6 additions & 2 deletions wallet/wallet-controller/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,11 +353,15 @@ impl<T: NodeInterface + Clone + Send + Sync + 'static, W: WalletEvents> Controll
/// # Returns
///
/// This method returns an error if you try to set lookahead size to 0
pub fn set_lookahead_size(&mut self, lookahead_size: u32) -> Result<(), ControllerError<T>> {
pub fn set_lookahead_size(
&mut self,
lookahead_size: u32,
force_reduce: bool,
) -> Result<(), ControllerError<T>> {
utils::ensure!(lookahead_size > 0, ControllerError::InvalidLookaheadSize);

self.wallet
.set_lookahead_size(lookahead_size)
.set_lookahead_size(lookahead_size, force_reduce)
.map_err(ControllerError::WalletError)
}

Expand Down

0 comments on commit 6545b31

Please sign in to comment.