[QT] Automatic full check after leaving the synchronisation state (#1589)

if after an importing seed.
Completing https://github.com/nanocurrency/nano-node/issues/70
This commit is contained in:
Sergey Kroshnin 2019-01-28 00:14:22 +03:00 committed by Zach Hyatt
commit 09bff5a298
5 changed files with 120 additions and 29 deletions

View file

@ -969,3 +969,62 @@ TEST (wallet, password_race_corrupt_seed)
}
}
}
TEST (wallet, change_seed)
{
nano::system system (24000, 1);
auto wallet (system.wallet (0));
wallet->enter_initial_password ();
nano::raw_key seed1;
seed1.data = 1;
nano::public_key pub;
uint32_t index (4);
nano::raw_key prv;
nano::deterministic_key (seed1.data, index, prv.data);
pub = nano::pub_key (prv.data);
wallet->insert_adhoc (nano::test_genesis_key.prv, false);
auto block (wallet->send_action (nano::test_genesis_key.pub, pub, 100));
ASSERT_NE (nullptr, block);
system.nodes[0]->block_processor.flush ();
{
auto transaction (wallet->wallets.tx_begin_write ());
wallet->change_seed (transaction, seed1);
nano::raw_key seed2;
wallet->store.seed (seed2, transaction);
ASSERT_EQ (seed1, seed2);
ASSERT_EQ (index + 1, wallet->store.deterministic_index_get (transaction));
}
ASSERT_TRUE (wallet->exists (pub));
}
TEST (wallet, deterministic_restore)
{
nano::system system (24000, 1);
auto wallet (system.wallet (0));
wallet->enter_initial_password ();
nano::raw_key seed1;
seed1.data = 1;
nano::public_key pub;
uint32_t index (4);
{
auto transaction (wallet->wallets.tx_begin_write ());
wallet->change_seed (transaction, seed1);
nano::raw_key seed2;
wallet->store.seed (seed2, transaction);
ASSERT_EQ (seed1, seed2);
ASSERT_EQ (1, wallet->store.deterministic_index_get (transaction));
nano::raw_key prv;
nano::deterministic_key (seed1.data, index, prv.data);
pub = nano::pub_key (prv.data);
}
wallet->insert_adhoc (nano::test_genesis_key.prv, false);
auto block (wallet->send_action (nano::test_genesis_key.pub, pub, 100));
ASSERT_NE (nullptr, block);
system.nodes[0]->block_processor.flush ();
{
auto transaction (wallet->wallets.tx_begin_write ());
wallet->deterministic_restore (transaction);
ASSERT_EQ (index + 1, wallet->store.deterministic_index_get (transaction));
}
ASSERT_TRUE (wallet->exists (pub));
}

View file

@ -1221,48 +1221,64 @@ void nano::wallet::init_free_accounts (nano::transaction const & transaction_a)
}
}
uint32_t nano::wallet::deterministic_check (nano::transaction const & transaction_a, uint32_t index)
{
auto block_transaction (wallets.node.store.tx_begin_read ());
for (uint32_t i (index + 1), n (index + 64); i < n; ++i)
{
nano::raw_key prv;
store.deterministic_key (prv, transaction_a, i);
nano::keypair pair (prv.data.to_string ());
// Check if account received at least 1 block
auto latest (wallets.node.ledger.latest (block_transaction, pair.pub));
if (!latest.is_zero ())
{
index = i;
// i + 64 - Check additional 64 accounts
// i/64 - Check additional accounts for large wallets. I.e. 64000/64 = 1000 accounts to check
n = i + 64 + (i / 64);
}
else
{
// Check if there are pending blocks for account
for (auto ii (wallets.node.store.pending_begin (block_transaction, nano::pending_key (pair.pub, 0))); nano::pending_key (ii->first).account == pair.pub; ++ii)
{
index = i;
n = i + 64 + (i / 64);
break;
}
}
}
return index;
}
nano::public_key nano::wallet::change_seed (nano::transaction const & transaction_a, nano::raw_key const & prv_a, uint32_t count)
{
store.seed_set (transaction_a, prv_a);
auto account = deterministic_insert (transaction_a);
if (count == 0)
{
for (uint32_t i (1), n (64); i < n; ++i)
{
nano::raw_key prv;
store.deterministic_key (prv, transaction_a, i);
nano::keypair pair (prv.data.to_string ());
// Check if account received at least 1 block
auto block_transaction (wallets.node.store.tx_begin_read ());
auto latest (wallets.node.ledger.latest (block_transaction, pair.pub));
if (!latest.is_zero ())
{
count = i;
// i + 64 - Check additional 64 accounts
// i/64 - Check additional accounts for large wallets. I.e. 64000/64 = 1000 accounts to check
n = i + 64 + (i / 64);
}
else
{
// Check if there are pending blocks for account
for (auto ii (wallets.node.store.pending_begin (block_transaction, nano::pending_key (pair.pub, 0))); nano::pending_key (ii->first).account == pair.pub; ++ii)
{
count = i;
n = i + 64 + (i / 64);
break;
}
}
}
count = deterministic_check (transaction_a, 0);
}
for (uint32_t i (0); i < count; ++i)
{
// Disable work generation to prevent weak CPU nodes stuck
account = deterministic_insert (transaction_a, false);
}
return account;
}
void nano::wallet::deterministic_restore (nano::transaction const & transaction_a)
{
auto index (store.deterministic_index_get (transaction_a));
auto new_index (deterministic_check (transaction_a, index));
for (uint32_t i (index); i <= new_index && index != new_index; ++i)
{
// Disable work generation to prevent weak CPU nodes stuck
deterministic_insert (transaction_a, false);
}
}
bool nano::wallet::live ()
{
return store.handle != 0;

View file

@ -147,8 +147,10 @@ public:
void work_ensure (nano::account const &, nano::block_hash const &);
bool search_pending ();
void init_free_accounts (nano::transaction const &);
uint32_t deterministic_check (nano::transaction const & transaction_a, uint32_t index);
/** Changes the wallet seed and returns the first account */
nano::public_key change_seed (nano::transaction const & transaction_a, nano::raw_key const & prv_a, uint32_t = 0);
nano::public_key change_seed (nano::transaction const & transaction_a, nano::raw_key const & prv_a, uint32_t count = 0);
void deterministic_restore (nano::transaction const & transaction_a);
bool live ();
std::unordered_set<nano::account> free_accounts;
std::function<void(bool, bool)> lock_observer;

View file

@ -396,6 +396,11 @@ wallet (wallet_a)
{
this->wallet.account = this->wallet.wallet_m->change_seed (transaction, seed_l);
successful = true;
// Pending check for accounts to restore if bootstrap is in progress
if (this->wallet.node.bootstrap_initiator.in_progress ())
{
this->wallet.needs_deterministic_restore = true;
}
}
else
{
@ -999,7 +1004,8 @@ send_count_label (new QLabel ("Amount:")),
send_count (new QLineEdit),
send_blocks_send (new QPushButton ("Send")),
send_blocks_back (new QPushButton ("Back")),
active_status (*this)
active_status (*this),
needs_deterministic_restore (false)
{
update_connected ();
empty_password ();
@ -1353,6 +1359,13 @@ void nano_qt::wallet::start ()
else
{
this_l->active_status.erase (nano_qt::status_types::synchronizing);
// Check for accounts to restore
if (this_l->needs_deterministic_restore)
{
this_l->needs_deterministic_restore = false;
auto transaction (this_l->wallet_m->wallets.tx_begin_write ());
this_l->wallet_m->deterministic_restore (transaction);
}
}
}
}));

View file

@ -353,5 +353,6 @@ public:
void push_main_stack (QWidget *);
void ongoing_refresh ();
std::atomic<bool> needs_balance_refresh;
std::atomic<bool> needs_deterministic_restore;
};
}