Add callback for confirmed block in RPC block_confirm (#1898)

* Add callback for confirmed block in RPC block_confirm

* rpc.block_confirm_confirmed test

* Add lock_guard for active.confirmed changes
This commit is contained in:
Sergey Kroshnin 2019-04-13 00:15:57 +03:00 committed by GitHub
commit d2ecede34f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 2 deletions

View file

@ -836,7 +836,38 @@ void nano::rpc_handler::block_confirm ()
auto block_l (node.store.block_get (transaction, hash));
if (block_l != nullptr)
{
node.block_confirm (std::move (block_l));
if (!node.ledger.block_confirmed (transaction, hash))
{
// Start new confirmation for unconfirmed block
node.block_confirm (std::move (block_l));
}
else
{
// Add record in confirmation history for confirmed block
nano::election_status status;
status.winner = block_l;
status.tally = 0;
status.election_end = std::chrono::duration_cast<std::chrono::milliseconds> (std::chrono::system_clock::now ().time_since_epoch ());
status.election_duration = std::chrono::milliseconds::zero ();
{
std::lock_guard<std::mutex> lock (node.active.mutex);
node.active.confirmed.push_back (status);
if (node.active.confirmed.size () > node.active.election_history_size)
{
node.active.confirmed.pop_front ();
}
}
// Trigger callback for confirmed block
node.block_arrival.add (hash);
auto account (node.ledger.account (transaction, hash));
auto amount (node.ledger.amount (transaction, hash));
bool is_state_send (false);
if (auto state = dynamic_cast<nano::state_block *> (block_l.get ()))
{
is_state_send = node.ledger.is_send (transaction, *state);
}
node.observers.blocks.notify (block_l, account, amount, is_state_send);
}
response_l.put ("started", "1");
}
else

View file

@ -4637,7 +4637,6 @@ TEST (rpc, block_confirm)
nano::system system (24000, 1);
system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv);
nano::genesis genesis;
system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv);
auto send1 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::test_genesis_key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, system.nodes[0]->work_generate_blocking (genesis.hash ())));
{
auto transaction (system.nodes[0]->store.tx_begin (true));
@ -4677,6 +4676,54 @@ TEST (rpc, block_confirm_absent)
ASSERT_EQ ("Block not found", response.json.get<std::string> ("error"));
}
TEST (rpc, block_confirm_confirmed)
{
nano::system system (24000, 1);
nano::node_init init;
auto path (nano::unique_path ());
nano::node_config config;
config.peering_port = 24001;
config.callback_address = "localhost";
config.callback_port = 24002;
config.callback_target = "/";
config.logging.init (path);
auto node (std::make_shared<nano::node> (init, system.io_ctx, path, system.alarm, config, system.work));
node->start ();
system.nodes.push_back (node);
nano::genesis genesis;
{
auto transaction (node->store.tx_begin_read ());
ASSERT_TRUE (node->ledger.block_confirmed (transaction, genesis.hash ()));
}
ASSERT_EQ (0, node->stats.count (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out));
nano::rpc rpc (system.io_ctx, *node, nano::rpc_config (true));
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "block_confirm");
request.put ("hash", genesis.hash ().to_string ());
test_response response (request, rpc, system.io_ctx);
system.deadline_set (5s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_EQ (200, response.status);
ASSERT_EQ ("1", response.json.get<std::string> ("started"));
// Check confirmation history
auto confirmed (node->active.list_confirmed ());
ASSERT_EQ (1, confirmed.size ());
ASSERT_EQ (genesis.hash (), confirmed.begin ()->winner->hash ());
// Check callback
system.deadline_set (5s);
while (node->stats.count (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out) == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
// Callback result is error because callback target port isn't listening
ASSERT_EQ (1, node->stats.count (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out));
node->stop ();
}
TEST (rpc, node_id)
{
nano::system system (24000, 1);