Fix qt wallet hitting a debug_assert when creating blocks (#3018)
This changes the block creation path of the Qt wallet to use the appropriate difficulty for work generation. By doing so, it fixes the assert reported in #3017. The normal sending process (clicking Send in the wallet) and receive process (automatically) use the node wallet and thus the appropriate difficulty. A test is added to make some epoch_2 validation where difficulty is different across block types. There is a similar test for the node internal wallet.
This commit is contained in:
parent
583cd4834d
commit
d3ac57d0fc
2 changed files with 103 additions and 6 deletions
|
@ -2265,7 +2265,11 @@ void nano_qt::block_creation::create_send ()
|
|||
(void)error;
|
||||
debug_assert (!error);
|
||||
nano::state_block send (account_l, info.head, info.representative, balance - amount_l.number (), destination_l, key, account_l, 0);
|
||||
if (wallet.node.work_generate_blocking (send).is_initialized ())
|
||||
nano::block_details details;
|
||||
details.is_send = true;
|
||||
details.epoch = info.epoch ();
|
||||
auto const required_difficulty{ nano::work_threshold (send.work_version (), details) };
|
||||
if (wallet.node.work_generate_blocking (send, required_difficulty).is_initialized ())
|
||||
{
|
||||
std::string block_l;
|
||||
send.serialize_json (block_l);
|
||||
|
@ -2275,6 +2279,7 @@ void nano_qt::block_creation::create_send ()
|
|||
}
|
||||
else
|
||||
{
|
||||
debug_assert (required_difficulty <= wallet.node.max_work_generate_difficulty (send.work_version ()));
|
||||
show_label_error (*status);
|
||||
if (wallet.node.work_generation_enabled ())
|
||||
{
|
||||
|
@ -2328,7 +2333,7 @@ void nano_qt::block_creation::create_receive ()
|
|||
auto block_l (wallet.node.store.block_get (block_transaction, source_l));
|
||||
if (block_l != nullptr)
|
||||
{
|
||||
auto destination (wallet.node.ledger.block_destination (block_transaction, *block_l));
|
||||
auto const & destination (wallet.node.ledger.block_destination (block_transaction, *block_l));
|
||||
if (!destination.is_zero ())
|
||||
{
|
||||
nano::pending_key pending_key (destination, source_l);
|
||||
|
@ -2344,7 +2349,11 @@ void nano_qt::block_creation::create_receive ()
|
|||
if (!error)
|
||||
{
|
||||
nano::state_block receive (pending_key.account, info.head, info.representative, info.balance.number () + pending.amount.number (), source_l, key, pending_key.account, 0);
|
||||
if (wallet.node.work_generate_blocking (receive).is_initialized ())
|
||||
nano::block_details details;
|
||||
details.is_receive = true;
|
||||
details.epoch = std::max (info.epoch (), pending.epoch);
|
||||
auto required_difficulty{ nano::work_threshold (receive.work_version (), details) };
|
||||
if (wallet.node.work_generate_blocking (receive, required_difficulty).is_initialized ())
|
||||
{
|
||||
std::string block_l;
|
||||
receive.serialize_json (block_l);
|
||||
|
@ -2354,6 +2363,7 @@ void nano_qt::block_creation::create_receive ()
|
|||
}
|
||||
else
|
||||
{
|
||||
debug_assert (required_difficulty <= wallet.node.max_work_generate_difficulty (receive.work_version ()));
|
||||
show_label_error (*status);
|
||||
if (wallet.node.work_generation_enabled ())
|
||||
{
|
||||
|
@ -2423,7 +2433,10 @@ void nano_qt::block_creation::create_change ()
|
|||
if (!error)
|
||||
{
|
||||
nano::state_block change (account_l, info.head, representative_l, info.balance, 0, key, account_l, 0);
|
||||
if (wallet.node.work_generate_blocking (change).is_initialized ())
|
||||
nano::block_details details;
|
||||
details.epoch = info.epoch ();
|
||||
auto const required_difficulty{ nano::work_threshold (change.work_version (), details) };
|
||||
if (wallet.node.work_generate_blocking (change, required_difficulty).is_initialized ())
|
||||
{
|
||||
std::string block_l;
|
||||
change.serialize_json (block_l);
|
||||
|
@ -2433,6 +2446,7 @@ void nano_qt::block_creation::create_change ()
|
|||
}
|
||||
else
|
||||
{
|
||||
debug_assert (required_difficulty <= wallet.node.max_work_generate_difficulty (change.work_version ()));
|
||||
show_label_error (*status);
|
||||
if (wallet.node.work_generation_enabled ())
|
||||
{
|
||||
|
@ -2484,7 +2498,7 @@ void nano_qt::block_creation::create_open ()
|
|||
auto block_l (wallet.node.store.block_get (block_transaction, source_l));
|
||||
if (block_l != nullptr)
|
||||
{
|
||||
auto destination (wallet.node.ledger.block_destination (block_transaction, *block_l));
|
||||
auto const & destination (wallet.node.ledger.block_destination (block_transaction, *block_l));
|
||||
if (!destination.is_zero ())
|
||||
{
|
||||
nano::pending_key pending_key (destination, source_l);
|
||||
|
@ -2500,7 +2514,11 @@ void nano_qt::block_creation::create_open ()
|
|||
if (!error)
|
||||
{
|
||||
nano::state_block open (pending_key.account, 0, representative_l, pending.amount, source_l, key, pending_key.account, 0);
|
||||
if (wallet.node.work_generate_blocking (open).is_initialized ())
|
||||
nano::block_details details;
|
||||
details.is_receive = true;
|
||||
details.epoch = pending.epoch;
|
||||
auto const required_difficulty{ nano::work_threshold (open.work_version (), details) };
|
||||
if (wallet.node.work_generate_blocking (open, required_difficulty).is_initialized ())
|
||||
{
|
||||
std::string block_l;
|
||||
open.serialize_json (block_l);
|
||||
|
@ -2510,6 +2528,7 @@ void nano_qt::block_creation::create_open ()
|
|||
}
|
||||
else
|
||||
{
|
||||
debug_assert (required_difficulty <= wallet.node.max_work_generate_difficulty (open.work_version ()));
|
||||
show_label_error (*status);
|
||||
if (wallet.node.work_generation_enabled ())
|
||||
{
|
||||
|
|
|
@ -894,3 +894,81 @@ TEST (wallet, DISABLED_synchronizing)
|
|||
test_application->processEvents ();
|
||||
}
|
||||
}
|
||||
|
||||
TEST (wallet, epoch_2_validation)
|
||||
{
|
||||
nano_qt::eventloop_processor processor;
|
||||
nano::system system (1);
|
||||
auto & node = system.nodes[0];
|
||||
|
||||
// Upgrade the genesis account to epoch 2
|
||||
ASSERT_NE (nullptr, system.upgrade_genesis_epoch (*node, nano::epoch::epoch_1));
|
||||
ASSERT_NE (nullptr, system.upgrade_genesis_epoch (*node, nano::epoch::epoch_2));
|
||||
|
||||
system.wallet (0)->insert_adhoc (nano::dev_genesis_key.prv);
|
||||
|
||||
auto account (nano::dev_genesis_key.pub);
|
||||
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *node, system.wallet (0), account));
|
||||
wallet->start ();
|
||||
wallet->client_window->show ();
|
||||
|
||||
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
|
||||
QTest::mouseClick (wallet->advanced.create_block, Qt::LeftButton);
|
||||
|
||||
auto create_and_process = [&]() -> nano::block_hash {
|
||||
wallet->block_creation.create->click ();
|
||||
std::string json (wallet->block_creation.block->toPlainText ().toStdString ());
|
||||
EXPECT_FALSE (json.empty ());
|
||||
boost::property_tree::ptree tree1;
|
||||
std::stringstream istream (json);
|
||||
boost::property_tree::read_json (istream, tree1);
|
||||
bool error (false);
|
||||
nano::state_block block (error, tree1);
|
||||
EXPECT_FALSE (error);
|
||||
EXPECT_EQ (nano::process_result::progress, node->process (block).code);
|
||||
return block.hash ();
|
||||
};
|
||||
|
||||
auto do_send = [&](nano::public_key const & destination) -> nano::block_hash {
|
||||
wallet->block_creation.send->click ();
|
||||
wallet->block_creation.account->setText (nano::dev_genesis_key.pub.to_account ().c_str ());
|
||||
wallet->block_creation.amount->setText ("1");
|
||||
wallet->block_creation.destination->setText (destination.to_account ().c_str ());
|
||||
return create_and_process ();
|
||||
};
|
||||
|
||||
auto do_open = [&](nano::block_hash const & source, nano::public_key const & account) -> nano::block_hash {
|
||||
wallet->block_creation.open->click ();
|
||||
wallet->block_creation.source->setText (source.to_string ().c_str ());
|
||||
wallet->block_creation.representative->setText (account.to_account ().c_str ());
|
||||
return create_and_process ();
|
||||
};
|
||||
|
||||
auto do_receive = [&](nano::block_hash const & source) -> nano::block_hash {
|
||||
wallet->block_creation.receive->click ();
|
||||
wallet->block_creation.source->setText (source.to_string ().c_str ());
|
||||
return create_and_process ();
|
||||
};
|
||||
|
||||
auto do_change = [&](nano::public_key const & account, nano::public_key const & representative) -> nano::block_hash {
|
||||
wallet->block_creation.change->click ();
|
||||
wallet->block_creation.account->setText (account.to_account ().c_str ());
|
||||
wallet->block_creation.representative->setText (representative.to_account ().c_str ());
|
||||
return create_and_process ();
|
||||
};
|
||||
|
||||
// An epoch 2 receive (open) block should be generated with lower difficulty with high probability
|
||||
auto tries = 0;
|
||||
auto max_tries = 20;
|
||||
|
||||
while (++tries < max_tries)
|
||||
{
|
||||
nano::keypair key;
|
||||
system.wallet (0)->insert_adhoc (key.prv);
|
||||
auto send1 = do_send (key.pub);
|
||||
do_open (send1, key.pub);
|
||||
auto send2 = do_send (key.pub);
|
||||
do_receive (send2);
|
||||
do_change (key.pub, nano::dev_genesis_key.pub);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue