Add support for election info in websocket confirmations (#2195)

This commit is contained in:
cryptocode 2019-08-05 18:41:56 +02:00 committed by GitHub
commit 80854af4ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 10 deletions

View file

@ -463,7 +463,7 @@ TEST (websocket, confirmation_options)
std::thread client_thread_2 ([&client_thread_2_finished]() {
// Re-subscribe with options for all local wallet accounts
auto response = websocket_test_call ("::1", "24078",
R"json({"action": "subscribe", "topic": "confirmation", "ack": "true", "options": {"confirmation_type": "active_quorum", "all_local_accounts": "true"}})json", true, true);
R"json({"action": "subscribe", "topic": "confirmation", "ack": "true", "options": {"confirmation_type": "active_quorum", "all_local_accounts": "true", "include_election_info": "true"}})json", true, true);
ASSERT_TRUE (response);
boost::property_tree::ptree event;
@ -471,6 +471,20 @@ TEST (websocket, confirmation_options)
stream << response.get ();
boost::property_tree::read_json (stream, event);
ASSERT_EQ (event.get<std::string> ("topic"), "confirmation");
try
{
boost::property_tree::ptree election_info = event.get_child ("message.election_info");
auto tally (election_info.get<std::string> ("tally"));
auto time (election_info.get<std::string> ("time"));
election_info.get<std::string> ("duration");
// Make sure tally and time are non-zero. Duration may be zero on testnet, so we only check that it's present (exception thrown otherwise)
ASSERT_NE ("0", tally);
ASSERT_NE ("0", time);
}
catch (std::runtime_error const & ex)
{
FAIL () << ex.what ();
}
client_thread_2_finished = true;
});

View file

@ -260,7 +260,7 @@ startup_time (std::chrono::steady_clock::now ())
}
}
this->websocket_server->broadcast_confirmation (block_a, account_a, amount_a, subtype, status_a.type);
this->websocket_server->broadcast_confirmation (block_a, account_a, amount_a, subtype, status_a);
}
});

View file

@ -7,11 +7,17 @@
#include <algorithm>
#include <chrono>
nano::websocket::confirmation_options::confirmation_options (nano::node & node_a) :
node (node_a)
{
}
nano::websocket::confirmation_options::confirmation_options (boost::property_tree::ptree const & options_a, nano::node & node_a) :
node (node_a)
{
// Non-account filtering options
include_block = options_a.get<bool> ("include_block", true);
include_election_info = options_a.get<bool> ("include_election_info", false);
confirmation_types = 0;
auto type_l (options_a.get<std::string> ("confirmation_type", "all"));
@ -497,7 +503,7 @@ void nano::websocket::listener::on_accept (boost::system::error_code ec)
}
}
void nano::websocket::listener::broadcast_confirmation (std::shared_ptr<nano::block> block_a, nano::account const & account_a, nano::amount const & amount_a, std::string subtype, nano::election_status_type election_status_type_a)
void nano::websocket::listener::broadcast_confirmation (std::shared_ptr<nano::block> block_a, nano::account const & account_a, nano::amount const & amount_a, std::string subtype, nano::election_status const & election_status_a)
{
nano::websocket::message_builder builder;
@ -512,16 +518,21 @@ void nano::websocket::listener::broadcast_confirmation (std::shared_ptr<nano::bl
auto subscription (session_ptr->subscriptions.find (nano::websocket::topic::confirmation));
if (subscription != session_ptr->subscriptions.end ())
{
nano::websocket::confirmation_options default_options (node);
auto conf_options (dynamic_cast<nano::websocket::confirmation_options *> (subscription->second.get ()));
if (conf_options == nullptr)
{
conf_options = &default_options;
}
auto include_block (conf_options == nullptr ? true : conf_options->get_include_block ());
if (include_block && !msg_with_block)
{
msg_with_block = builder.block_confirmed (block_a, account_a, amount_a, subtype, include_block, election_status_type_a);
msg_with_block = builder.block_confirmed (block_a, account_a, amount_a, subtype, include_block, election_status_a, *conf_options);
}
else if (!include_block && !msg_without_block)
{
msg_without_block = builder.block_confirmed (block_a, account_a, amount_a, subtype, include_block, election_status_type_a);
msg_without_block = builder.block_confirmed (block_a, account_a, amount_a, subtype, include_block, election_status_a, *conf_options);
}
else
{
@ -571,7 +582,7 @@ nano::websocket::message nano::websocket::message_builder::stopped_election (nan
return message_l;
}
nano::websocket::message nano::websocket::message_builder::block_confirmed (std::shared_ptr<nano::block> block_a, nano::account const & account_a, nano::amount const & amount_a, std::string subtype, bool include_block_a, nano::election_status_type election_status_type_a)
nano::websocket::message nano::websocket::message_builder::block_confirmed (std::shared_ptr<nano::block> block_a, nano::account const & account_a, nano::amount const & amount_a, std::string subtype, bool include_block_a, nano::election_status const & election_status_a, nano::websocket::confirmation_options const & options_a)
{
nano::websocket::message message_l (nano::websocket::topic::confirmation);
set_common_fields (message_l);
@ -583,7 +594,7 @@ nano::websocket::message nano::websocket::message_builder::block_confirmed (std:
message_node_l.add ("hash", block_a->hash ().to_string ());
std::string confirmation_type = "unknown";
switch (election_status_type_a)
switch (election_status_a.type)
{
case nano::election_status_type::active_confirmed_quorum:
confirmation_type = "active_quorum";
@ -599,6 +610,15 @@ nano::websocket::message nano::websocket::message_builder::block_confirmed (std:
};
message_node_l.add ("confirmation_type", confirmation_type);
if (options_a.get_include_election_info ())
{
boost::property_tree::ptree election_node_l;
election_node_l.add ("duration", election_status_a.election_duration.count ());
election_node_l.add ("time", election_status_a.election_end.count ());
election_node_l.add ("tally", election_status_a.tally.to_string_dec ());
message_node_l.add_child ("election_info", election_node_l);
}
if (include_block_a)
{
boost::property_tree::ptree block_node_l;

View file

@ -36,6 +36,7 @@ enum class election_status_type : uint8_t;
namespace websocket
{
class listener;
class confirmation_options;
/** Supported topics */
enum class topic
@ -78,7 +79,7 @@ namespace websocket
class message_builder final
{
public:
message block_confirmed (std::shared_ptr<nano::block> block_a, nano::account const & account_a, nano::amount const & amount_a, std::string subtype, bool include_block, nano::election_status_type election_status_type_a);
message block_confirmed (std::shared_ptr<nano::block> block_a, nano::account const & account_a, nano::amount const & amount_a, std::string subtype, bool include_block, nano::election_status const & election_status_a, nano::websocket::confirmation_options const & options_a);
message stopped_election (nano::block_hash const & hash_a);
message vote_received (std::shared_ptr<nano::vote> vote_a);
message difficulty_changed (uint64_t publish_threshold, uint64_t difficulty_active);
@ -117,7 +118,7 @@ namespace websocket
class confirmation_options final : public options
{
public:
confirmation_options ();
confirmation_options (nano::node & node_a);
confirmation_options (boost::property_tree::ptree const & options_a, nano::node & node_a);
/**
@ -133,6 +134,12 @@ namespace websocket
return include_block;
}
/** Returns whether or not to include election info, such as tally and duration */
bool get_include_election_info () const
{
return include_election_info;
}
static constexpr const uint8_t type_active_quorum = 1;
static constexpr const uint8_t type_active_confirmation_height = 2;
static constexpr const uint8_t type_inactive = 4;
@ -141,6 +148,7 @@ namespace websocket
private:
nano::node & node;
bool include_election_info{ false };
bool include_block{ true };
bool has_account_filtering_options{ false };
bool all_local_accounts{ false };
@ -241,7 +249,7 @@ namespace websocket
void stop ();
/** Broadcast block confirmation. The content of the message depends on subscription options (such as "include_block") */
void broadcast_confirmation (std::shared_ptr<nano::block> block_a, nano::account const & account_a, nano::amount const & amount_a, std::string subtype, nano::election_status_type election_status_type_a);
void broadcast_confirmation (std::shared_ptr<nano::block> block_a, nano::account const & account_a, nano::amount const & amount_a, std::string subtype, nano::election_status const & election_status_a);
/** Broadcast \p message to all session subscribing to the message topic. */
void broadcast (nano::websocket::message message_a);