From 303c3cdcaa3c830aafa7b82c50cb7cf1cb7741ed Mon Sep 17 00:00:00 2001 From: clemahieu Date: Wed, 25 Apr 2018 20:17:21 +0200 Subject: [PATCH 1/3] Adding manual block confirmation function. --- rai/core_test/node.cpp | 22 ++++++++++++++++++++++ rai/node/node.cpp | 7 +++++++ rai/node/node.hpp | 1 + 3 files changed, 30 insertions(+) diff --git a/rai/core_test/node.cpp b/rai/core_test/node.cpp index e689d220..0106a383 100644 --- a/rai/core_test/node.cpp +++ b/rai/core_test/node.cpp @@ -1475,3 +1475,25 @@ TEST (node, online_reps) ASSERT_LT (iterations, 200); } } + +TEST (node, block_confirm) +{ + rai::system system (24000, 1); + rai::genesis genesis; + system.nodes [0]->ledger.state_block_parse_canary = genesis.hash (); + system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv); + auto send1 (std::make_shared (rai::test_genesis_key.pub, genesis.hash (), rai::test_genesis_key.pub, rai::genesis_amount - rai::Gxrb_ratio, rai::test_genesis_key.pub, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.nodes [0]->generate_work (genesis.hash ()))); + { + rai::transaction transaction (system.nodes [0]->store.environment, nullptr, true); + ASSERT_EQ (rai::process_result::progress, system.nodes [0]->ledger.process (transaction, *send1).code); + } + system.nodes [0]->block_confirm (send1); + ASSERT_TRUE (system.nodes [0]->active.confirmed.empty ()); + auto iterations (0); + while (system.nodes [0]->active.confirmed.empty ()) + { + system.poll (); + ++iterations; + ASSERT_LT (iterations, 200); + } +} diff --git a/rai/node/node.cpp b/rai/node/node.cpp index 45d02058..51b28926 100644 --- a/rai/node/node.cpp +++ b/rai/node/node.cpp @@ -2394,6 +2394,13 @@ void rai::node::add_initial_peers () { } +void rai::node::block_confirm (std::shared_ptr block_a) +{ + rai::transaction transaction (store.environment, nullptr, false); + active.start (transaction, block_a); + network.broadcast_confirm_req (block_a); +} + namespace { class confirmed_visitor : public rai::block_visitor diff --git a/rai/node/node.hpp b/rai/node/node.hpp index d459b1f5..d0192995 100644 --- a/rai/node/node.hpp +++ b/rai/node/node.hpp @@ -549,6 +549,7 @@ public: uint64_t generate_work (rai::uint256_union const &); void generate_work (rai::uint256_union const &, std::function); void add_initial_peers (); + void block_confirm (std::shared_ptr ); boost::asio::io_service & service; rai::node_config config; rai::alarm & alarm; From ded0ca58a42e8fb981a43a38897c8af620735d9b Mon Sep 17 00:00:00 2001 From: clemahieu Date: Wed, 25 Apr 2018 20:27:04 +0200 Subject: [PATCH 2/3] Adding block_confirm RPC. --- rai/core_test/rpc.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ rai/node/rpc.cpp | 30 ++++++++++++++++++++++++++++++ rai/node/rpc.hpp | 1 + 3 files changed, 74 insertions(+) diff --git a/rai/core_test/rpc.cpp b/rai/core_test/rpc.cpp index 1372f5f0..ba09bcee 100644 --- a/rai/core_test/rpc.cpp +++ b/rai/core_test/rpc.cpp @@ -3509,3 +3509,46 @@ TEST (rpc, confirmation_history) ASSERT_EQ ((rai::genesis_amount - rai::Gxrb_ratio).convert_to (), tally); system.stop (); } + +TEST (rpc, block_confirm) +{ + rai::system system (24000, 1); + system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv); + rai::genesis genesis; + system.nodes [0]->ledger.state_block_parse_canary = genesis.hash (); + system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv); + auto send1 (std::make_shared (rai::test_genesis_key.pub, genesis.hash (), rai::test_genesis_key.pub, rai::genesis_amount - rai::Gxrb_ratio, rai::test_genesis_key.pub, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.nodes [0]->generate_work (genesis.hash ()))); + { + rai::transaction transaction (system.nodes [0]->store.environment, nullptr, true); + ASSERT_EQ (rai::process_result::progress, system.nodes [0]->ledger.process (transaction, *send1).code); + } + rai::rpc rpc (system.service, *system.nodes[0], rai::rpc_config (true)); + rpc.start (); + boost::property_tree::ptree request; + request.put ("action", "block_confirm"); + request.put ("hash", send1->hash ().to_string ()); + test_response response (request, rpc, system.service); + while (response.status == 0) + { + system.poll (); + } + ASSERT_EQ (200, response.status); + ASSERT_EQ ("1", response.json.get ("started")); +} + +TEST (rpc, block_confirm_absent) +{ + rai::system system (24000, 1); + system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv); rai::rpc rpc (system.service, *system.nodes[0], rai::rpc_config (true)); + rpc.start (); + boost::property_tree::ptree request; + request.put ("action", "block_confirm"); + request.put ("hash", "0"); + test_response response (request, rpc, system.service); + while (response.status == 0) + { + system.poll (); + } + ASSERT_EQ (200, response.status); + ASSERT_EQ ("Block not found", response.json.get ("error")); +} diff --git a/rai/node/rpc.cpp b/rai/node/rpc.cpp index 4961777c..dc1e24f7 100644 --- a/rai/node/rpc.cpp +++ b/rai/node/rpc.cpp @@ -899,6 +899,32 @@ void rai::rpc_handler::block () } } +void rai::rpc_handler::block_confirm () +{ + std::string hash_text (request.get ("hash")); + rai::block_hash hash_l; + if (!hash_l.decode_hex (hash_text)) + { + rai::transaction transaction (node.store.environment, nullptr, false); + auto block_l (node.store.block_get (transaction, hash_l)); + if (block_l != nullptr) + { + node.block_confirm (std::move (block_l)); + boost::property_tree::ptree response_l; + response_l.put ("started", "1"); + response (response_l); + } + else + { + error_response (response, "Block not found"); + } + } + else + { + error_response (response, "Invalid block hash"); + } +} + void rai::rpc_handler::blocks () { std::vector hashes; @@ -4597,6 +4623,10 @@ void rai::rpc_handler::process_request () { block (); } + else if (action == "block_confirm") + { + block_confirm (); + } else if (action == "blocks") { blocks (); diff --git a/rai/node/rpc.hpp b/rai/node/rpc.hpp index 71ff02a8..d63955cd 100644 --- a/rai/node/rpc.hpp +++ b/rai/node/rpc.hpp @@ -133,6 +133,7 @@ public: void accounts_pending (); void available_supply (); void block (); + void block_confirm (); void blocks (); void blocks_info (); void block_account (); From 8131a608f9cead9353a007d60aaaf603d2d7bb1e Mon Sep 17 00:00:00 2001 From: clemahieu Date: Thu, 26 Apr 2018 01:49:54 +0200 Subject: [PATCH 3/3] Moving block callback post-confirmation. --- rai/core_test/node.cpp | 2 +- rai/node/node.cpp | 79 ++++++++++++++++++++++++------------------ rai/node/node.hpp | 2 +- rai/node/rpc.cpp | 15 ++++++-- rai/qt/qt.cpp | 9 +++-- 5 files changed, 64 insertions(+), 43 deletions(-) diff --git a/rai/core_test/node.cpp b/rai/core_test/node.cpp index 0106a383..cd284ac2 100644 --- a/rai/core_test/node.cpp +++ b/rai/core_test/node.cpp @@ -1012,7 +1012,7 @@ TEST (node, coherent_observer) { rai::system system (24000, 1); auto & node1 (*system.nodes[0]); - node1.observers.blocks.add ([&node1](std::shared_ptr block_a, rai::process_return const &) { + node1.observers.blocks.add ([&node1](std::shared_ptr block_a, rai::account const &, rai::uint128_t const &, bool) { rai::transaction transaction (node1.store.environment, nullptr, false); ASSERT_TRUE (node1.store.block_exists (transaction, block_a->hash ())); }); diff --git a/rai/node/node.cpp b/rai/node/node.cpp index 51b28926..24cb993c 100644 --- a/rai/node/node.cpp +++ b/rai/node/node.cpp @@ -1273,7 +1273,10 @@ void rai::block_processor::process_receive_many (std::unique_lock & { case rai::process_result::progress: { - progress.push_back (std::make_pair (block, process_result)); + if (node.block_arrival.recent (hash)) + { + node.active.start (transaction, block); + } } case rai::process_result::old: { @@ -1294,18 +1297,6 @@ void rai::block_processor::process_receive_many (std::unique_lock & } } lock_a.unlock (); - for (auto & i : progress) - { - node.observers.blocks (i.first, i.second); - if (i.second.amount > 0) - { - node.observers.account_balance (i.second.account, false); - if (!i.second.pending_account.is_zero ()) - { - node.observers.account_balance (i.second.pending_account, true); - } - } - } } rai::process_return rai::block_processor::process_receive_one (MDB_txn * transaction_a, std::shared_ptr block_a) @@ -1476,30 +1467,23 @@ online_reps (*this) peers.disconnect_observer = [this]() { observers.disconnect (); }; - observers.blocks.add ([this](std::shared_ptr block_a, rai::process_return const & result_a) { - if (this->block_arrival.recent (block_a->hash ())) - { - rai::transaction transaction (store.environment, nullptr, false); - active.start (transaction, block_a); - } - }); - observers.blocks.add ([this](std::shared_ptr block_a, rai::process_return const & result_a) { + observers.blocks.add ([this](std::shared_ptr block_a, rai::account const & account_a, rai::amount const & amount_a, bool is_state_send_a) { if (this->block_arrival.recent (block_a->hash ())) { auto node_l (shared_from_this ()); - background ([node_l, block_a, result_a]() { + background ([node_l, block_a, account_a, amount_a, is_state_send_a]() { if (!node_l->config.callback_address.empty ()) { boost::property_tree::ptree event; - event.add ("account", result_a.account.to_account ()); + event.add ("account", account_a.to_account ()); event.add ("hash", block_a->hash ().to_string ()); std::string block_text; block_a->serialize_json (block_text); event.add ("block", block_text); - event.add ("amount", result_a.amount.to_string_dec ()); - if (result_a.state_is_send) + event.add ("amount", amount_a.to_string_dec ()); + if (is_state_send_a) { - event.add ("is_send", *result_a.state_is_send); + event.add ("is_send", is_state_send_a); } std::stringstream ostream; boost::property_tree::write_json (ostream, event); @@ -2406,10 +2390,11 @@ namespace class confirmed_visitor : public rai::block_visitor { public: - confirmed_visitor (MDB_txn * transaction_a, rai::node & node_a, std::shared_ptr block_a) : + confirmed_visitor (MDB_txn * transaction_a, rai::node & node_a, std::shared_ptr block_a, rai::block_hash const & hash_a) : transaction (transaction_a), node (node_a), - block (block_a) + block (block_a), + hash (hash_a) { } virtual ~confirmed_visitor () = default; @@ -2423,7 +2408,7 @@ public: rai::account representative; rai::pending_info pending; representative = wallet->store.representative (transaction); - auto error (node.store.pending_get (transaction, rai::pending_key (account_a, block->hash ()), pending)); + auto error (node.store.pending_get (transaction, rai::pending_key (account_a, hash), pending)); if (!error) { auto node_l (node.shared ()); @@ -2432,9 +2417,9 @@ public: } else { - if (!node.store.block_exists (transaction, block->hash ())) + if (!node.store.block_exists (transaction, hash)) { - BOOST_LOG (node.log) << boost::str (boost::format ("Block %1% has already been received") % block->hash ().to_string ()); + BOOST_LOG (node.log) << boost::str (boost::format ("Block %1% has already been received") % hash.to_string ()); } else { @@ -2464,14 +2449,42 @@ public: MDB_txn * transaction; rai::node & node; std::shared_ptr block; + rai::block_hash const &hash; }; } void rai::node::process_confirmed (std::shared_ptr block_a) { rai::transaction transaction (store.environment, nullptr, false); - confirmed_visitor visitor (transaction, *this, block_a); - block_a->visit (visitor); + auto hash (block_a->hash ()); + if (store.block_exists (transaction, hash)) + { + confirmed_visitor visitor (transaction, *this, block_a, hash); + block_a->visit (visitor); + auto account (ledger.account (transaction, hash)); + auto amount (ledger.amount (transaction, hash)); + bool is_state_send (false); + rai::account pending_account (0); + if (auto state = dynamic_cast (block_a.get ())) + { + rai::transaction transaction (store.environment, nullptr, false); + is_state_send = ledger.is_send (transaction, *state); + pending_account = state->hashables.link; + } + if (auto send = dynamic_cast (block_a.get ())) + { + pending_account = send->hashables.destination; + } + observers.blocks (block_a, account, amount, is_state_send); + if (amount > 0) + { + observers.account_balance (account, false); + if (!pending_account.is_zero ()) + { + observers.account_balance (pending_account, true); + } + } + } } void rai::node::process_message (rai::message & message_a, rai::endpoint const & sender_a) diff --git a/rai/node/node.hpp b/rai/node/node.hpp index d0192995..a0c62172 100644 --- a/rai/node/node.hpp +++ b/rai/node/node.hpp @@ -458,7 +458,7 @@ public: class node_observers { public: - rai::observer_set, rai::process_return const &> blocks; + rai::observer_set, rai::account const &, rai::uint128_t const &, bool> blocks; rai::observer_set wallet; rai::observer_set, rai::endpoint const &> vote; rai::observer_set account_balance; diff --git a/rai/node/rpc.cpp b/rai/node/rpc.cpp index dc1e24f7..a83e390f 100644 --- a/rai/node/rpc.cpp +++ b/rai/node/rpc.cpp @@ -141,8 +141,8 @@ void rai::rpc::start () } acceptor.listen (); - node.observers.blocks.add ([this](std::shared_ptr block_a, rai::process_return const & result_a) { - observer_action (result_a.account); + node.observers.blocks.add ([this](std::shared_ptr block_a, rai::account const & account_a, rai::uint128_t const &, bool) { + observer_action (account_a); }); accept (); @@ -2584,7 +2584,16 @@ void rai::rpc_handler::process () { case rai::process_result::progress: { - node.observers.blocks (block_a, result); + rai::transaction transaction (node.store.environment, nullptr, false); + auto account (node.ledger.account (transaction, hash)); + auto amount (node.ledger.amount (transaction, hash)); + bool is_state_send (false); + if (auto state = dynamic_cast (block_a.get ())) + { + rai::transaction transaction (node.store.environment, nullptr, false); + is_state_send = node.ledger.is_send (transaction, *state); + } + node.observers.blocks (block_a, account, amount, is_state_send); boost::property_tree::ptree response_l; response_l.put ("hash", hash.to_string ()); response (response_l); diff --git a/rai/qt/qt.cpp b/rai/qt/qt.cpp index 57e77b01..0871a572 100644 --- a/rai/qt/qt.cpp +++ b/rai/qt/qt.cpp @@ -1099,18 +1099,17 @@ void rai_qt::wallet::start () this_l->push_main_stack (this_l->send_blocks_window); } }); - node.observers.blocks.add ([this_w](std::shared_ptr block_a, rai::process_return const & result_a) { + node.observers.blocks.add ([this_w](std::shared_ptr block_a, rai::account const & account_a, rai::uint128_t const & amount_a, bool) { if (auto this_l = this_w.lock ()) { - auto account (result_a.account); - this_l->application.postEvent (&this_l->processor, new eventloop_event ([this_w, block_a, account]() { + this_l->application.postEvent (&this_l->processor, new eventloop_event ([this_w, block_a, account_a]() { if (auto this_l = this_w.lock ()) { - if (this_l->wallet_m->exists (account)) + if (this_l->wallet_m->exists (account_a)) { this_l->accounts.refresh (); } - if (account == this_l->account) + if (account_a == this_l->account) { this_l->history.refresh (); }