dncurrency/nano/qt_test/qt.cpp
Dani (Sergey) K b3722ca73d
QT wallet: proper display of state open block in GUI history (#4744)
* QT wallet: properly display state open block in history

State open block should be marked as "Receive"

* Update pruned blocks detection in QT GUI history

* Update conditions

* QT GUI pruning test update

* Update QT GUI account history

* Update pruned blocks QT GUI test

* Update with developer branch changes
2025-03-23 18:36:08 +01:00

1112 lines
50 KiB
C++

#include <nano/lib/blocks.hpp>
#include <nano/lib/work_version.hpp>
#include <nano/node/make_store.hpp>
#include <nano/qt/qt.hpp>
#include <nano/secure/ledger.hpp>
#include <nano/secure/ledger_set_any.hpp>
#include <nano/test_common/network.hpp>
#include <nano/test_common/system.hpp>
#include <nano/test_common/testutil.hpp>
#include <gtest/gtest.h>
#include <boost/property_tree/json_parser.hpp>
#include <algorithm>
#include <nano/qt_test/QTest>
#include <thread>
using namespace std::chrono_literals;
extern QApplication * test_application;
TEST (wallet, construction)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
auto wallet_l (system.nodes[0]->wallets.create (nano::random_wallet_id ()));
auto key (wallet_l->deterministic_insert ());
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], wallet_l, key));
wallet->start ();
std::string account (key.to_account ());
ASSERT_EQ (account, wallet->self.account_text->text ().toStdString ());
ASSERT_EQ (1, wallet->accounts.model->rowCount ());
auto item1 (wallet->accounts.model->item (0, 1));
ASSERT_EQ (key.to_account (), item1->text ().toStdString ());
}
// Disabled because it does not work and it is not clearly defined what its behaviour should be:
// https://github.com/nanocurrency/nano-node/issues/3235
TEST (wallet, DISABLED_status)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
auto wallet_l (system.nodes[0]->wallets.create (nano::random_wallet_id ()));
nano::keypair key;
wallet_l->insert_adhoc (key.prv);
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], wallet_l, key.pub));
wallet->start ();
auto wallet_has = [wallet] (nano_qt::status_types status_ty) {
return wallet->active_status.active.find (status_ty) != wallet->active_status.active.end ();
};
ASSERT_EQ ("Status: Disconnected, Blocks: 1", wallet->status->text ().toStdString ());
auto outer_node = nano::test::add_outer_node (system);
nano::test::establish_tcp (system, *system.nodes[0], outer_node->network.endpoint ());
// Because of the wallet "vulnerable" message, this won't be the message displayed.
// However, it will still be part of the status set.
ASSERT_FALSE (wallet_has (nano_qt::status_types::synchronizing));
system.deadline_set (25s);
while (!wallet_has (nano_qt::status_types::synchronizing))
{
test_application->processEvents ();
ASSERT_NO_ERROR (system.poll ());
}
system.nodes[0]->network.cleanup (std::chrono::steady_clock::now () + std::chrono::seconds (5));
while (wallet_has (nano_qt::status_types::synchronizing))
{
test_application->processEvents ();
}
ASSERT_TRUE (wallet_has (nano_qt::status_types::disconnected));
}
// this test is modelled on wallet.status but it introduces another node on the network
TEST (wallet, status_with_peer)
{
nano_qt::eventloop_processor processor;
nano::test::system system (2);
auto wallet_l = system.nodes[0]->wallets.create (nano::random_wallet_id ());
nano::keypair key;
wallet_l->insert_adhoc (key.prv);
auto wallet = std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], wallet_l, key.pub);
wallet->start ();
auto wallet_has = [wallet] (nano_qt::status_types status_ty) {
return wallet->active_status.active.find (status_ty) != wallet->active_status.active.end ();
};
// Because of the wallet "vulnerable" message, this won't be the message displayed.
// However, it will still be part of the status set.
system.deadline_set (25s);
system.nodes[0]->network.cleanup (std::chrono::steady_clock::now () + std::chrono::seconds (5));
while (wallet_has (nano_qt::status_types::synchronizing))
{
test_application->processEvents ();
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_TRUE (wallet_has (nano_qt::status_types::nominal));
}
TEST (wallet, startup_balance)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
auto wallet_l (system.nodes[0]->wallets.create (nano::random_wallet_id ()));
nano::keypair key;
wallet_l->insert_adhoc (key.prv);
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], wallet_l, key.pub));
wallet->needs_balance_refresh = true;
wallet->start ();
wallet->application.processEvents (QEventLoop::AllEvents);
ASSERT_EQ ("Balance: 0 nano", wallet->self.balance_label->text ().toStdString ());
}
TEST (wallet, select_account)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
auto wallet_l (system.nodes[0]->wallets.create (nano::random_wallet_id ()));
nano::public_key key1 (wallet_l->deterministic_insert ());
nano::public_key key2 (wallet_l->deterministic_insert ());
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], wallet_l, key1));
wallet->start ();
ASSERT_EQ (key1, wallet->account);
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
QTest::mouseClick (wallet->accounts_button, Qt::LeftButton);
wallet->accounts.view->selectionModel ()->setCurrentIndex (wallet->accounts.model->index (0, 0), QItemSelectionModel::SelectionFlag::Select);
QTest::mouseClick (wallet->accounts.use_account, Qt::LeftButton);
auto key3 (wallet->account);
wallet->accounts.view->selectionModel ()->setCurrentIndex (wallet->accounts.model->index (1, 0), QItemSelectionModel::SelectionFlag::Select);
QTest::mouseClick (wallet->accounts.use_account, Qt::LeftButton);
auto key4 (wallet->account);
ASSERT_NE (key3, key4);
// The list is populated in sorted order as it's read from store in lexical order. This may
// be different from the insertion order.
if (key1 < key2)
{
ASSERT_EQ (key2, key4);
}
else
{
ASSERT_EQ (key1, key4);
}
}
TEST (wallet, main)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
auto wallet_l (system.nodes[0]->wallets.create (nano::random_wallet_id ()));
nano::keypair key;
wallet_l->insert_adhoc (key.prv);
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], wallet_l, key.pub));
wallet->start ();
ASSERT_EQ (wallet->entry_window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->send_blocks, Qt::LeftButton);
ASSERT_EQ (wallet->send_blocks_window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->send_blocks_back, Qt::LeftButton);
QTest::mouseClick (wallet->settings_button, Qt::LeftButton);
ASSERT_EQ (wallet->settings.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->settings.back, Qt::LeftButton);
ASSERT_EQ (wallet->entry_window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->advanced.show_ledger, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.ledger_window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->advanced.ledger_back, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->advanced.show_peers, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.peers_window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->advanced.peers_back, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->advanced.back, Qt::LeftButton);
ASSERT_EQ (wallet->entry_window, wallet->main_stack->currentWidget ());
}
TEST (wallet, password_change)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
nano::account account;
system.wallet (0)->insert_adhoc (nano::keypair ().prv);
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
account = system.account (transaction, 0);
}
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), account));
wallet->start ();
QTest::mouseClick (wallet->settings_button, Qt::LeftButton);
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
nano::raw_key password1;
nano::raw_key password2;
system.wallet (0)->store.derive_key (password1, transaction, "1");
system.wallet (0)->store.password.value (password2);
ASSERT_NE (password1, password2);
}
QTest::keyClicks (wallet->settings.new_password, "1");
QTest::keyClicks (wallet->settings.retype_password, "1");
QTest::mouseClick (wallet->settings.change, Qt::LeftButton);
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
nano::raw_key password1;
nano::raw_key password2;
system.wallet (0)->store.derive_key (password1, transaction, "1");
system.wallet (0)->store.password.value (password2);
ASSERT_EQ (password1, password2);
}
ASSERT_EQ ("", wallet->settings.new_password->text ());
ASSERT_EQ ("", wallet->settings.retype_password->text ());
}
TEST (client, password_nochange)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
nano::account account;
system.wallet (0)->insert_adhoc (nano::keypair ().prv);
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
account = system.account (transaction, 0);
}
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), account));
wallet->start ();
QTest::mouseClick (wallet->settings_button, Qt::LeftButton);
nano::raw_key password;
password.clear ();
system.deadline_set (10s);
while (password == 0)
{
ASSERT_NO_ERROR (system.poll ());
system.wallet (0)->store.password.value (password);
}
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
nano::raw_key password1;
system.wallet (0)->store.derive_key (password1, transaction, "");
nano::raw_key password2;
system.wallet (0)->store.password.value (password2);
ASSERT_EQ (password1, password2);
}
QTest::keyClicks (wallet->settings.new_password, "1");
QTest::keyClicks (wallet->settings.retype_password, "2");
QTest::mouseClick (wallet->settings.change, Qt::LeftButton);
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
nano::raw_key password1;
system.wallet (0)->store.derive_key (password1, transaction, "");
nano::raw_key password2;
system.wallet (0)->store.password.value (password2);
ASSERT_EQ (password1, password2);
}
ASSERT_EQ ("1", wallet->settings.new_password->text ());
ASSERT_EQ ("", wallet->settings.retype_password->text ());
}
TEST (wallet, enter_password)
{
nano_qt::eventloop_processor processor;
nano::test::system system (2);
nano::account account;
system.wallet (0)->insert_adhoc (nano::keypair ().prv);
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
account = system.account (transaction, 0);
}
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), account));
wallet->start ();
ASSERT_NE (-1, wallet->settings.layout->indexOf (wallet->settings.password));
ASSERT_NE (-1, wallet->settings.layout->indexOf (wallet->settings.lock_toggle));
ASSERT_NE (-1, wallet->settings.layout->indexOf (wallet->settings.back));
// The wallet UI always starts as locked, so we lock it then unlock it again to update the UI.
// This should never be a problem in actual use, as in reality, the wallet does start locked.
QTest::mouseClick (wallet->settings.lock_toggle, Qt::LeftButton);
QTest::mouseClick (wallet->settings.lock_toggle, Qt::LeftButton);
test_application->processEvents ();
ASSERT_NE (wallet->status->text ().toStdString ().rfind ("Status: Wallet password empty", 0), std::string::npos);
{
auto transaction (system.nodes[0]->wallets.tx_begin_write ());
ASSERT_FALSE (system.wallet (0)->store.rekey (transaction, "abc"));
}
QTest::mouseClick (wallet->settings_button, Qt::LeftButton);
QTest::mouseClick (wallet->settings.lock_toggle, Qt::LeftButton);
test_application->processEvents ();
ASSERT_NE (wallet->status->text ().toStdString ().rfind ("Status: Wallet locked", 0), std::string::npos);
wallet->settings.new_password->setText ("");
QTest::keyClicks (wallet->settings.password, "abc");
QTest::mouseClick (wallet->settings.lock_toggle, Qt::LeftButton);
auto is_running_status = [&wallet] () -> bool {
test_application->processEvents ();
return wallet->status->text ().toStdString ().rfind ("Status: Running", 0) != std::string::npos;
};
ASSERT_TIMELY (5s, is_running_status ());
ASSERT_EQ ("", wallet->settings.password->text ());
}
TEST (wallet, send)
{
nano_qt::eventloop_processor processor;
nano::test::system system (2);
system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv);
nano::public_key key1 (system.wallet (1)->insert_adhoc (nano::keypair ().prv));
auto account (nano::dev::genesis_key.pub);
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), account));
wallet->start ();
ASSERT_NE (wallet->rendering_ratio, nano::raw_ratio);
QTest::mouseClick (wallet->send_blocks, Qt::LeftButton);
QTest::keyClicks (wallet->send_account, key1.to_account ().c_str ());
QTest::keyClicks (wallet->send_count, "2.03");
QTest::mouseClick (wallet->send_blocks_send, Qt::LeftButton);
system.deadline_set (10s);
while (wallet->node.balance (key1).is_zero ())
{
ASSERT_NO_ERROR (system.poll ());
}
nano::uint128_t amount (wallet->node.balance (key1));
ASSERT_EQ (2 * wallet->rendering_ratio + (3 * wallet->rendering_ratio / 100), amount);
QTest::mouseClick (wallet->send_blocks_back, Qt::LeftButton);
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
QTest::mouseClick (wallet->advanced.show_ledger, Qt::LeftButton);
QTest::mouseClick (wallet->advanced.ledger_refresh, Qt::LeftButton);
ASSERT_EQ (2, wallet->advanced.ledger_model->rowCount ());
ASSERT_EQ (3, wallet->advanced.ledger_model->columnCount ());
auto item (wallet->advanced.ledger_model->itemFromIndex (wallet->advanced.ledger_model->index (0, 1)));
auto other_item (wallet->advanced.ledger_model->itemFromIndex (wallet->advanced.ledger_model->index (1, 1)));
// this seems somewhat random
ASSERT_TRUE (("2" == item->text ()) || ("2" == other_item->text ()));
}
TEST (wallet, send_locked)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv);
nano::keypair key1;
{
auto transaction (system.wallet (0)->wallets.tx_begin_write ());
system.wallet (0)->enter_password (transaction, "0");
}
auto account (nano::dev::genesis_key.pub);
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), account));
wallet->start ();
QTest::mouseClick (wallet->send_blocks, Qt::LeftButton);
QTest::keyClicks (wallet->send_account, key1.pub.to_account ().c_str ());
QTest::keyClicks (wallet->send_count, "2");
QTest::mouseClick (wallet->send_blocks_send, Qt::LeftButton);
system.deadline_set (10s);
while (!wallet->send_blocks_send->isEnabled ())
{
test_application->processEvents ();
ASSERT_NO_ERROR (system.poll ());
}
}
// Test disabled because it's failing intermittently.
// PR in which it got disabled: https://github.com/nanocurrency/nano-node/pull/3629
// Issue for investigating it: https://github.com/nanocurrency/nano-node/issues/3642
TEST (wallet, DISABLED_process_block)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
nano::account account;
nano::block_hash latest (system.nodes[0]->latest (nano::dev::genesis_key.pub));
system.wallet (0)->insert_adhoc (nano::keypair ().prv);
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
account = system.account (transaction, 0);
}
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), account));
wallet->start ();
ASSERT_EQ ("Process", wallet->block_entry.process->text ());
ASSERT_EQ ("Back", wallet->block_entry.back->text ());
nano::keypair key1;
ASSERT_EQ (wallet->entry_window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
QTest::mouseClick (wallet->advanced.enter_block, Qt::LeftButton);
ASSERT_EQ (wallet->block_entry.window, wallet->main_stack->currentWidget ());
nano::send_block send (latest, key1.pub, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest));
std::string previous = send.hashables.previous.to_string ();
std::string balance = send.hashables.balance.to_string ();
std::string signature = send.signature.to_string ();
std::string block_json;
send.serialize_json (block_json);
block_json.erase (std::remove (block_json.begin (), block_json.end (), '\n'), block_json.end ());
QTest::keyClicks (wallet->block_entry.block, QString::fromStdString (block_json));
QTest::mouseClick (wallet->block_entry.process, Qt::LeftButton);
{
auto transaction (system.nodes[0]->ledger.tx_begin_read ());
system.deadline_set (10s);
while (system.nodes[0]->ledger.any.block_exists (transaction, send.hash ()))
{
ASSERT_NO_ERROR (system.poll ());
}
}
QTest::mouseClick (wallet->block_entry.back, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.window, wallet->main_stack->currentWidget ());
}
TEST (wallet, create_send)
{
nano_qt::eventloop_processor processor;
nano::keypair key;
nano::test::system system (1);
system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv);
system.wallet (0)->insert_adhoc (key.prv);
auto account (nano::dev::genesis_key.pub);
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], 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);
QTest::mouseClick (wallet->block_creation.send, Qt::LeftButton);
QTest::keyClicks (wallet->block_creation.account, nano::dev::genesis_key.pub.to_account ().c_str ());
QTest::keyClicks (wallet->block_creation.amount, "100000000000000000000");
QTest::keyClicks (wallet->block_creation.destination, key.pub.to_account ().c_str ());
QTest::mouseClick (wallet->block_creation.create, Qt::LeftButton);
std::string json (wallet->block_creation.block->toPlainText ().toStdString ());
ASSERT_FALSE (json.empty ());
boost::property_tree::ptree tree1;
std::stringstream istream (json);
boost::property_tree::read_json (istream, tree1);
bool error (false);
auto send = std::make_shared<nano::state_block> (error, tree1);
ASSERT_FALSE (error);
ASSERT_EQ (nano::block_status::progress, system.nodes[0]->process (send));
ASSERT_EQ (nano::block_status::old, system.nodes[0]->process (send));
}
TEST (wallet, create_open_receive)
{
nano_qt::eventloop_processor processor;
nano::keypair key;
nano::test::system system (1);
system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv);
system.wallet (0)->send_action (nano::dev::genesis_key.pub, key.pub, 100);
nano::block_hash latest1 (system.nodes[0]->latest (nano::dev::genesis_key.pub));
system.wallet (0)->send_action (nano::dev::genesis_key.pub, key.pub, 100);
nano::block_hash latest2 (system.nodes[0]->latest (nano::dev::genesis_key.pub));
ASSERT_NE (latest1, latest2);
system.wallet (0)->insert_adhoc (key.prv);
auto account (nano::dev::genesis_key.pub);
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], 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);
wallet->block_creation.open->click ();
QTest::keyClicks (wallet->block_creation.source, latest1.to_string ().c_str ());
QTest::keyClicks (wallet->block_creation.representative, nano::dev::genesis_key.pub.to_account ().c_str ());
QTest::mouseClick (wallet->block_creation.create, Qt::LeftButton);
std::string json1 (wallet->block_creation.block->toPlainText ().toStdString ());
ASSERT_FALSE (json1.empty ());
boost::property_tree::ptree tree1;
std::stringstream istream1 (json1);
boost::property_tree::read_json (istream1, tree1);
bool error (false);
auto open = std::make_shared<nano::state_block> (error, tree1);
ASSERT_FALSE (error);
ASSERT_EQ (nano::block_status::progress, system.nodes[0]->process (open));
ASSERT_EQ (nano::block_status::old, system.nodes[0]->process (open));
wallet->block_creation.block->clear ();
wallet->block_creation.source->clear ();
wallet->block_creation.receive->click ();
QTest::keyClicks (wallet->block_creation.source, latest2.to_string ().c_str ());
QTest::mouseClick (wallet->block_creation.create, Qt::LeftButton);
std::string json2 (wallet->block_creation.block->toPlainText ().toStdString ());
ASSERT_FALSE (json2.empty ());
boost::property_tree::ptree tree2;
std::stringstream istream2 (json2);
boost::property_tree::read_json (istream2, tree2);
bool error2 (false);
auto receive = std::make_shared<nano::state_block> (error2, tree2);
ASSERT_FALSE (error2);
ASSERT_EQ (nano::block_status::progress, system.nodes[0]->process (receive));
ASSERT_EQ (nano::block_status::old, system.nodes[0]->process (receive));
}
TEST (wallet, create_change)
{
nano_qt::eventloop_processor processor;
nano::keypair key;
nano::test::system system (1);
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, *system.nodes[0], 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);
wallet->block_creation.change->click ();
QTest::keyClicks (wallet->block_creation.account, nano::dev::genesis_key.pub.to_account ().c_str ());
QTest::keyClicks (wallet->block_creation.representative, key.pub.to_account ().c_str ());
wallet->block_creation.create->click ();
std::string json (wallet->block_creation.block->toPlainText ().toStdString ());
ASSERT_FALSE (json.empty ());
boost::property_tree::ptree tree1;
std::stringstream istream (json);
boost::property_tree::read_json (istream, tree1);
bool error (false);
auto change = std::make_shared<nano::state_block> (error, tree1);
ASSERT_FALSE (error);
ASSERT_EQ (nano::block_status::progress, system.nodes[0]->process (change));
ASSERT_EQ (nano::block_status::old, system.nodes[0]->process (change));
}
TEST (history, short_text)
{
if (nano::rocksdb_config::using_rocksdb_in_tests ())
{
// Don't test this in rocksdb mode
return;
}
nano_qt::eventloop_processor processor;
nano::keypair key;
nano::test::system system (1);
system.wallet (0)->insert_adhoc (key.prv);
nano::account account;
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
account = system.account (transaction, 0);
}
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), account));
nano::logger logger;
nano::stats stats{ logger };
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
{
auto transaction (ledger.tx_begin_write ());
store->initialize (transaction, ledger.cache, ledger.constants);
nano::keypair key;
auto latest (ledger.any.account_head (transaction, nano::dev::genesis_key.pub));
auto send = std::make_shared<nano::send_block> (latest, nano::dev::genesis_key.pub, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest));
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send));
auto receive = std::make_shared<nano::receive_block> (send->hash (), send->hash (), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (send->hash ()));
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive));
auto change = std::make_shared<nano::change_block> (receive->hash (), key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (receive->hash ()));
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, change));
}
nano_qt::history history (ledger, nano::dev::genesis_key.pub, *wallet);
history.refresh ();
ASSERT_EQ (4, history.model->rowCount ());
}
TEST (history, pruned_source)
{
if (nano::rocksdb_config::using_rocksdb_in_tests ())
{
// Don't test this in rocksdb mode
return;
}
nano_qt::eventloop_processor processor;
nano::keypair key;
nano::test::system system (1);
system.wallet (0)->insert_adhoc (key.prv);
nano::account account;
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
account = system.account (transaction, 0);
}
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), account));
nano::logger logger;
nano::stats stats{ logger };
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ());
nano::ledger ledger (*store, nano::dev::constants, stats, logger);
ledger.pruning = true;
nano::block_hash next_pruning;
// Basic pruning for legacy blocks. Previous block is pruned, source is pruned
{
auto transaction = ledger.tx_begin_write ();
store->initialize (transaction, ledger.cache, nano::dev::constants);
auto latest (ledger.any.account_head (transaction, nano::dev::genesis_key.pub));
auto send1 = std::make_shared<nano::send_block> (latest, nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - 100, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest));
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1));
auto send2 = std::make_shared<nano::send_block> (send1->hash (), key.pub, nano::dev::constants.genesis_amount - 200, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (send1->hash ()));
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send2));
auto receive1 = std::make_shared<nano::receive_block> (send2->hash (), send1->hash (), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (send2->hash ()));
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive1));
auto open = std::make_shared<nano::open_block> (send2->hash (), key.pub, key.pub, key.prv, key.pub, *system.work.generate (key.pub));
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open));
ledger.confirm (transaction, send1->hash ());
ASSERT_EQ (1, ledger.pruning_action (transaction, send1->hash (), 2));
next_pruning = send2->hash ();
}
// Set rendering ration to raw units
ASSERT_NE (wallet->rendering_ratio, nano::raw_ratio);
wallet->rendering_ratio = nano::raw_ratio;
// Genesis account pruned values
nano_qt::history history1 (ledger, nano::dev::genesis_key.pub, *wallet);
history1.refresh ();
ASSERT_EQ (2, history1.model->rowCount ());
// Source block send1 is removed
auto type1 (history1.model->item (0, 0));
ASSERT_EQ ("Receive (pruned source)", type1->text ().toStdString ());
// Source block account is unknown
auto account1 (history1.model->item (0, 1));
ASSERT_EQ (nano::account (0).to_account (), account1->text ().toStdString ());
// Amount is known because previous block (send2) isn't removed
auto amount1 (history1.model->item (0, 2));
ASSERT_EQ ("100 raw", amount1->text ().toStdString ());
// Last not pruned block in chain (send2)
auto type2 (history1.model->item (1, 0));
ASSERT_EQ ("Send (pruned)", type2->text ().toStdString ());
auto account2 (history1.model->item (1, 1));
// Amount is unknown because previous block (send1) is removed
ASSERT_EQ (key.pub.to_account (), account2->text ().toStdString ());
auto amount2 (history1.model->item (1, 2));
ASSERT_EQ ("0 raw", amount2->text ().toStdString ());
// New account pruned values
nano_qt::history history2 (ledger, key.pub, *wallet);
history2.refresh ();
ASSERT_EQ (1, history2.model->rowCount ());
auto type3 (history2.model->item (0, 0));
ASSERT_EQ ("Receive", type3->text ().toStdString ());
// Source block (send2) account is known
auto account3 (history2.model->item (0, 1));
ASSERT_EQ (nano::dev::genesis_key.pub.to_account (), account3->text ().toStdString ());
auto amount3 (history2.model->item (0, 2));
ASSERT_EQ ("100 raw", amount3->text ().toStdString ());
// Additional legacy test
{
auto transaction = ledger.tx_begin_write ();
ledger.confirm (transaction, next_pruning);
ASSERT_EQ (1, ledger.pruning_action (transaction, next_pruning, 2));
}
// Genesis account pruned values
history1.refresh ();
ASSERT_EQ (1, history1.model->rowCount ());
auto type4 (history1.model->item (0, 0));
ASSERT_EQ ("Receive (pruned)", type4->text ().toStdString ());
auto account4 (history1.model->item (0, 1));
ASSERT_EQ (nano::account (0).to_account (), account4->text ().toStdString ());
// Amount is unknown because previous block (send2) is removed
auto amount4 (history1.model->item (0, 2));
ASSERT_EQ ("0 raw", amount4->text ().toStdString ());
// New account pruned values
history2.refresh ();
ASSERT_EQ (1, history2.model->rowCount ());
auto type5 (history2.model->item (0, 0));
ASSERT_EQ ("Receive (pruned source)", type5->text ().toStdString ());
// Source block (send2) account is unknown
auto account5 (history2.model->item (0, 1));
ASSERT_EQ (nano::account (0).to_account (), account5->text ().toStdString ());
auto amount5 (history2.model->item (0, 2));
ASSERT_EQ ("100 raw", amount5->text ().toStdString ());
// Pruning for state blocks. Previous block is pruned, source is pruned
{
auto transaction = ledger.tx_begin_write ();
auto latest (ledger.any.account_head (transaction, nano::dev::genesis_key.pub));
auto send3 = std::make_shared<nano::state_block> (nano::dev::genesis_key.pub, latest, nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - 200, key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest));
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send3));
auto latest_key (ledger.any.account_head (transaction, key.pub));
auto receive2 = std::make_shared<nano::state_block> (key.pub, latest_key, key.pub, 200, send3->hash (), key.prv, key.pub, *system.work.generate (latest_key));
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, receive2));
ledger.confirm (transaction, latest);
ASSERT_EQ (1, ledger.pruning_action (transaction, latest, 2));
ledger.confirm (transaction, latest_key);
ASSERT_EQ (1, ledger.pruning_action (transaction, latest_key, 2));
}
// Genesis account pruned values
history1.refresh ();
ASSERT_EQ (1, history1.model->rowCount ());
auto type6 (history1.model->item (0, 0));
ASSERT_EQ ("Send (pruned)", type6->text ().toStdString ());
auto account6 (history1.model->item (0, 1));
ASSERT_EQ (key.pub.to_account (), account6->text ().toStdString ());
// Amount is unknown because previous block (receive1) is removed
auto amount6 (history1.model->item (0, 2));
ASSERT_EQ ("0 raw", amount6->text ().toStdString ());
// New account pruned values
history2.refresh ();
ASSERT_EQ (1, history2.model->rowCount ());
auto type7 (history2.model->item (0, 0));
ASSERT_EQ ("Receive (pruned)", type7->text ().toStdString ());
// Source block (send3) account is known
auto account7 (history2.model->item (0, 1));
ASSERT_EQ (nano::dev::genesis_key.pub.to_account (), account7->text ().toStdString ());
// Amount is unknown because previous block (receive1) is removed
auto amount7 (history2.model->item (0, 2));
ASSERT_EQ ("0 raw", amount7->text ().toStdString ());
// Pruning for state blocks. Change state block
{
auto transaction = ledger.tx_begin_write ();
auto latest (ledger.any.account_head (transaction, nano::dev::genesis_key.pub));
auto change = std::make_shared<nano::state_block> (nano::dev::genesis_key.pub, latest, key.pub, nano::dev::constants.genesis_amount - 200, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest));
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, change));
ledger.confirm (transaction, latest);
ASSERT_EQ (1, ledger.pruning_action (transaction, latest, 2));
}
// Genesis account pruned values
history1.refresh ();
ASSERT_EQ (1, history1.model->rowCount ());
auto type8 (history1.model->item (0, 0));
ASSERT_EQ ("Change (pruned)", type8->text ().toStdString ());
auto account8 (history1.model->item (0, 1));
ASSERT_EQ (key.pub.to_account (), account8->text ().toStdString ());
// Amount is 0 for change blocks
auto amount8 (history1.model->item (0, 2));
ASSERT_EQ ("0 raw", amount8->text ().toStdString ());
// New account pruned values
history2.refresh ();
ASSERT_EQ (1, history2.model->rowCount ());
auto type9 (history2.model->item (0, 0));
ASSERT_EQ ("Receive (pruned)", type9->text ().toStdString ());
// Source block (send3) account is unknown
auto account9 (history2.model->item (0, 1));
ASSERT_EQ (nano::account (0).to_account (), account9->text ().toStdString ());
// Amount is unknown because previous block (receive1) is removed
auto amount9 (history2.model->item (0, 2));
ASSERT_EQ ("0 raw", amount9->text ().toStdString ());
// Pruning for state blocks. Open state block
nano::keypair key2;
system.wallet (0)->insert_adhoc (key2.prv);
{
auto transaction = ledger.tx_begin_write ();
auto latest_key (ledger.any.account_head (transaction, key.pub));
auto send4 = std::make_shared<nano::state_block> (key.pub, latest_key, key.pub, 100, key2.pub, key.prv, key.pub, *system.work.generate (latest_key));
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send4));
auto open2 = std::make_shared<nano::state_block> (key2.pub, 0, key2.pub, 100, send4->hash (), key2.prv, key2.pub, *system.work.generate (key2.pub));
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open2));
ledger.confirm (transaction, latest_key);
ASSERT_EQ (1, ledger.pruning_action (transaction, latest_key, 2));
}
// New account (key) pruned values
history2.refresh ();
ASSERT_EQ (1, history2.model->rowCount ());
auto type10 (history2.model->item (0, 0));
ASSERT_EQ ("Send (pruned)", type10->text ().toStdString ());
auto account10 (history2.model->item (0, 1));
ASSERT_EQ (key2.pub.to_account (), account10->text ().toStdString ());
// Amount is unknown because previous block (receive2) is removed
auto amount10 (history2.model->item (0, 2));
ASSERT_EQ ("0 raw", amount10->text ().toStdString ());
// Account (key2) pruned values
nano_qt::history history3 (ledger, key2.pub, *wallet);
history3.refresh ();
ASSERT_EQ (1, history3.model->rowCount ());
// Type is "Recieve" for open block because source block (send4) isn't removed
auto type11 (history3.model->item (0, 0));
ASSERT_EQ ("Receive", type11->text ().toStdString ());
auto account11 (history3.model->item (0, 1));
ASSERT_EQ (key.pub.to_account (), account11->text ().toStdString ());
// Amount is known for open blocks
auto amount11 (history3.model->item (0, 2));
ASSERT_EQ ("100 raw", amount11->text ().toStdString ());
}
TEST (wallet, startup_work)
{
nano_qt::eventloop_processor processor;
nano::keypair key;
nano::test::system system (1);
system.wallet (0)->insert_adhoc (key.prv);
nano::account account;
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
account = system.account (transaction, 0);
}
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), account));
wallet->start ();
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
uint64_t work1;
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
ASSERT_TRUE (wallet->wallet_m->store.work_get (transaction, nano::dev::genesis_key.pub, work1));
}
QTest::mouseClick (wallet->accounts_button, Qt::LeftButton);
QTest::keyClicks (wallet->accounts.account_key_line, "34F0A37AAD20F4A260F0A5B3CB3D7FB50673212263E58A380BC10474BB039CE4");
QTest::mouseClick (wallet->accounts.account_key_button, Qt::LeftButton);
system.deadline_set (10s);
auto again (true);
while (again)
{
ASSERT_NO_ERROR (system.poll ());
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
again = wallet->wallet_m->store.work_get (transaction, nano::dev::genesis_key.pub, work1);
}
}
TEST (wallet, block_viewer)
{
nano_qt::eventloop_processor processor;
nano::keypair key;
nano::test::system system (1);
system.wallet (0)->insert_adhoc (key.prv);
nano::account account;
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
account = system.account (transaction, 0);
}
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), account));
wallet->start ();
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
ASSERT_NE (-1, wallet->advanced.layout->indexOf (wallet->advanced.block_viewer));
QTest::mouseClick (wallet->advanced.block_viewer, Qt::LeftButton);
ASSERT_EQ (wallet->block_viewer.window, wallet->main_stack->currentWidget ());
nano::block_hash latest (system.nodes[0]->latest (nano::dev::genesis_key.pub));
QTest::keyClicks (wallet->block_viewer.hash, latest.to_string ().c_str ());
QTest::mouseClick (wallet->block_viewer.retrieve, Qt::LeftButton);
ASSERT_FALSE (wallet->block_viewer.block->toPlainText ().toStdString ().empty ());
QTest::mouseClick (wallet->block_viewer.back, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.window, wallet->main_stack->currentWidget ());
}
TEST (wallet, import)
{
nano_qt::eventloop_processor processor;
nano::test::system system (2);
std::string json;
nano::keypair key1;
nano::keypair key2;
system.wallet (0)->insert_adhoc (key1.prv);
{
auto transaction (system.nodes[0]->wallets.tx_begin_read ());
system.wallet (0)->store.serialize_json (transaction, json);
}
system.wallet (1)->insert_adhoc (key2.prv);
auto path{ nano::unique_path () / "wallet.json" };
{
std::ofstream stream;
stream.open (path.string ().c_str ());
stream << json;
}
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[1], system.wallet (1), key2.pub));
wallet->start ();
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->accounts_button, Qt::LeftButton);
ASSERT_EQ (wallet->accounts.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->accounts.import_wallet, Qt::LeftButton);
ASSERT_EQ (wallet->import.window, wallet->main_stack->currentWidget ());
QTest::keyClicks (wallet->import.filename, path.string ().c_str ());
QTest::keyClicks (wallet->import.password, "");
ASSERT_FALSE (system.wallet (1)->exists (key1.pub));
QTest::mouseClick (wallet->import.perform, Qt::LeftButton);
ASSERT_TRUE (system.wallet (1)->exists (key1.pub));
}
TEST (wallet, republish)
{
nano_qt::eventloop_processor processor;
nano::test::system system (2);
system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv);
nano::keypair key;
nano::block_hash hash;
{
auto transaction = system.nodes[0]->ledger.tx_begin_write ();
auto latest (system.nodes[0]->ledger.any.account_head (transaction, nano::dev::genesis_key.pub));
auto block = std::make_shared<nano::send_block> (latest, key.pub, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *system.work.generate (latest));
hash = block->hash ();
ASSERT_EQ (nano::block_status::progress, system.nodes[0]->ledger.process (transaction, block));
}
auto account (nano::dev::genesis_key.pub);
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), account));
wallet->start ();
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->advanced.block_viewer, Qt::LeftButton);
ASSERT_EQ (wallet->block_viewer.window, wallet->main_stack->currentWidget ());
QTest::keyClicks (wallet->block_viewer.hash, hash.to_string ().c_str ());
QTest::mouseClick (wallet->block_viewer.rebroadcast, Qt::LeftButton);
ASSERT_FALSE (system.nodes[1]->balance (nano::dev::genesis_key.pub).is_zero ());
system.deadline_set (10s);
while (system.nodes[1]->balance (nano::dev::genesis_key.pub).is_zero ())
{
ASSERT_NO_ERROR (system.poll ());
}
}
TEST (wallet, ignore_empty_adhoc)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
nano::keypair key1;
system.wallet (0)->insert_adhoc (key1.prv);
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), key1.pub));
wallet->start ();
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->accounts_button, Qt::LeftButton);
ASSERT_EQ (wallet->accounts.window, wallet->main_stack->currentWidget ());
QTest::keyClicks (wallet->accounts.account_key_line, nano::dev::genesis_key.prv.to_string ().c_str ());
QTest::mouseClick (wallet->accounts.account_key_button, Qt::LeftButton);
ASSERT_EQ (1, wallet->accounts.model->rowCount ());
ASSERT_EQ (0, wallet->accounts.account_key_line->text ().length ());
nano::keypair key;
QTest::keyClicks (wallet->accounts.account_key_line, key.prv.to_string ().c_str ());
QTest::mouseClick (wallet->accounts.account_key_button, Qt::LeftButton);
ASSERT_EQ (1, wallet->accounts.model->rowCount ());
ASSERT_EQ (0, wallet->accounts.account_key_line->text ().length ());
QTest::mouseClick (wallet->accounts.create_account, Qt::LeftButton);
test_application->processEvents ();
test_application->processEvents ();
ASSERT_EQ (2, wallet->accounts.model->rowCount ());
}
TEST (wallet, change_seed)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
auto key1 (system.wallet (0)->deterministic_insert ());
system.wallet (0)->deterministic_insert ();
nano::raw_key seed3;
{
auto transaction (system.wallet (0)->wallets.tx_begin_read ());
system.wallet (0)->store.seed (seed3, transaction);
}
auto wallet_key (key1);
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), wallet_key));
wallet->start ();
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->accounts_button, Qt::LeftButton);
ASSERT_EQ (wallet->accounts.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->accounts.import_wallet, Qt::LeftButton);
ASSERT_EQ (wallet->import.window, wallet->main_stack->currentWidget ());
nano::raw_key seed;
seed.clear ();
QTest::keyClicks (wallet->import.seed, seed.to_string ().c_str ());
nano::raw_key seed1;
{
auto transaction (system.wallet (0)->wallets.tx_begin_read ());
system.wallet (0)->store.seed (seed1, transaction);
}
ASSERT_NE (seed, seed1);
ASSERT_TRUE (system.wallet (0)->exists (key1));
ASSERT_EQ (2, wallet->accounts.model->rowCount ());
QTest::mouseClick (wallet->import.import_seed, Qt::LeftButton);
ASSERT_EQ (2, wallet->accounts.model->rowCount ());
QTest::keyClicks (wallet->import.clear_line, "clear keys");
QTest::mouseClick (wallet->import.import_seed, Qt::LeftButton);
ASSERT_EQ (1, wallet->accounts.model->rowCount ());
ASSERT_TRUE (wallet->import.clear_line->text ().toStdString ().empty ());
nano::raw_key seed2;
auto transaction (system.wallet (0)->wallets.tx_begin_read ());
system.wallet (0)->store.seed (seed2, transaction);
ASSERT_EQ (seed, seed2);
ASSERT_FALSE (system.wallet (0)->exists (key1));
ASSERT_NE (key1, wallet->account);
auto key2 (wallet->account);
ASSERT_TRUE (system.wallet (0)->exists (key2));
QTest::keyClicks (wallet->import.seed, seed3.to_string ().c_str ());
QTest::keyClicks (wallet->import.clear_line, "clear keys");
QTest::mouseClick (wallet->import.import_seed, Qt::LeftButton);
ASSERT_EQ (key1, wallet->account);
ASSERT_FALSE (system.wallet (0)->exists (key2));
ASSERT_TRUE (system.wallet (0)->exists (key1));
}
TEST (wallet, seed_work_generation)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
auto key1 (system.wallet (0)->deterministic_insert ());
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), key1));
wallet->start ();
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->accounts_button, Qt::LeftButton);
ASSERT_EQ (wallet->accounts.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->accounts.import_wallet, Qt::LeftButton);
ASSERT_EQ (wallet->import.window, wallet->main_stack->currentWidget ());
nano::raw_key seed;
auto prv = nano::deterministic_key (seed, 0);
auto pub (nano::pub_key (prv));
QTest::keyClicks (wallet->import.seed, seed.to_string ().c_str ());
QTest::keyClicks (wallet->import.clear_line, "clear keys");
uint64_t work (0);
QTest::mouseClick (wallet->import.import_seed, Qt::LeftButton);
system.deadline_set (10s);
while (work == 0)
{
auto ec = system.poll ();
auto transaction (system.wallet (0)->wallets.tx_begin_read ());
system.wallet (0)->store.work_get (transaction, pub, work);
ASSERT_NO_ERROR (ec);
}
auto transaction = system.nodes[0]->ledger.tx_begin_read ();
ASSERT_GE (nano::dev::network_params.work.difficulty (nano::work_version::work_1, system.nodes[0]->ledger.latest_root (transaction, pub), work), system.nodes[0]->default_difficulty (nano::work_version::work_1));
}
TEST (wallet, backup_seed)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
auto key1 (system.wallet (0)->deterministic_insert ());
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), key1));
wallet->start ();
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->accounts_button, Qt::LeftButton);
ASSERT_EQ (wallet->accounts.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->accounts.backup_seed, Qt::LeftButton);
nano::raw_key seed;
auto transaction (system.wallet (0)->wallets.tx_begin_read ());
system.wallet (0)->store.seed (seed, transaction);
ASSERT_EQ (seed.to_string (), test_application->clipboard ()->text ().toStdString ());
}
TEST (wallet, import_locked)
{
nano_qt::eventloop_processor processor;
nano::test::system system (1);
auto key1 (system.wallet (0)->deterministic_insert ());
{
auto transaction (system.wallet (0)->wallets.tx_begin_write ());
system.wallet (0)->store.rekey (transaction, "1");
}
auto wallet (std::make_shared<nano_qt::wallet> (*test_application, processor, *system.nodes[0], system.wallet (0), key1));
wallet->start ();
QTest::mouseClick (wallet->show_advanced, Qt::LeftButton);
ASSERT_EQ (wallet->advanced.window, wallet->main_stack->currentWidget ());
QTest::mouseClick (wallet->accounts_button, Qt::LeftButton);
ASSERT_EQ (wallet->accounts.window, wallet->main_stack->currentWidget ());
nano::raw_key seed1;
seed1.clear ();
QTest::keyClicks (wallet->import.seed, seed1.to_string ().c_str ());
QTest::keyClicks (wallet->import.clear_line, "clear keys");
{
auto transaction (system.wallet (0)->wallets.tx_begin_write ());
system.wallet (0)->enter_password (transaction, "");
}
QTest::mouseClick (wallet->import.import_seed, Qt::LeftButton);
nano::raw_key seed2;
{
auto transaction (system.wallet (0)->wallets.tx_begin_write ());
system.wallet (0)->store.seed (seed2, transaction);
ASSERT_NE (seed1, seed2);
system.wallet (0)->enter_password (transaction, "1");
}
QTest::mouseClick (wallet->import.import_seed, Qt::LeftButton);
nano::raw_key seed3;
auto transaction (system.wallet (0)->wallets.tx_begin_read ());
system.wallet (0)->store.seed (seed3, transaction);
ASSERT_EQ (seed1, seed3);
}
TEST (wallet, epoch_2_validation)
{
nano_qt::eventloop_processor processor;
nano::test::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);
auto block = std::make_shared<nano::state_block> (error, tree1);
EXPECT_FALSE (error);
EXPECT_EQ (nano::block_status::progress, node->process (block));
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);
}
}