diff --git a/rai/lib/errors.cpp b/rai/lib/errors.cpp index 3539167d..87caeeef 100644 --- a/rai/lib/errors.cpp +++ b/rai/lib/errors.cpp @@ -114,6 +114,8 @@ std::string nano::error_rpc_messages::message (int ev) const return "Representative account and previous hash required"; case nano::error_rpc::block_create_requirements_send: return "Destination account, previous hash, current balance and amount required"; + case nano::error_rpc::confirmation_not_found: + return "Active confirmation not found"; case nano::error_rpc::invalid_balance: return "Invalid balance number"; case nano::error_rpc::invalid_destinations: @@ -122,6 +124,8 @@ std::string nano::error_rpc_messages::message (int ev) const return "Invalid offset"; case nano::error_rpc::invalid_missing_type: return "Invalid or missing type argument"; + case nano::error_rpc::invalid_root: + return "Invalid root hash"; case nano::error_rpc::invalid_sources: return "Invalid sources number"; case nano::error_rpc::payment_account_balance: diff --git a/rai/lib/errors.hpp b/rai/lib/errors.hpp index 22a2c2c7..ec3d883a 100644 --- a/rai/lib/errors.hpp +++ b/rai/lib/errors.hpp @@ -83,10 +83,12 @@ enum class error_rpc block_create_requirements_receive, block_create_requirements_change, block_create_requirements_send, + confirmation_not_found, invalid_balance, invalid_destinations, invalid_offset, invalid_missing_type, + invalid_root, invalid_sources, payment_account_balance, payment_unable_create_account, diff --git a/rai/node/node.hpp b/rai/node/node.hpp index b6551cd9..8d96aa4a 100644 --- a/rai/node/node.hpp +++ b/rai/node/node.hpp @@ -375,6 +375,7 @@ public: void vote (std::shared_ptr const &); void recalculate_stake (); rai::uint128_t online_stake (); + rai::uint128_t online_stake_total; std::deque list (); boost::multi_index_container< rai::rep_last_heard_info, @@ -384,7 +385,6 @@ public: reps; private: - rai::uint128_t online_stake_total; std::mutex mutex; rai::node & node; }; diff --git a/rai/node/rpc.cpp b/rai/node/rpc.cpp index 2f4806e5..b13fbbff 100644 --- a/rai/node/rpc.cpp +++ b/rai/node/rpc.cpp @@ -1369,6 +1369,31 @@ void rai::rpc_handler::chain (bool successors) response_errors (); } +void rai::rpc_handler::confirmation_active () +{ + uint64_t announcements (0); + boost::optional announcements_text (request.get_optional ("announcements")); + if (announcements_text.is_initialized ()) + { + announcements = strtoul (announcements_text.get ().c_str (), NULL, 10); + } + boost::property_tree::ptree elections; + { + std::lock_guard lock (node.active.mutex); + for (auto i (node.active.roots.begin ()), n (node.active.roots.end ()); i != n; ++i) + { + if (i->announcements >= announcements) + { + boost::property_tree::ptree entry; + entry.put ("", i->root.to_string ()); + elections.push_back (std::make_pair ("", entry)); + } + } + } + response_l.add_child ("confirmations", elections); + response_errors (); +} + void rai::rpc_handler::confirmation_history () { boost::property_tree::ptree elections; @@ -1386,6 +1411,83 @@ void rai::rpc_handler::confirmation_history () response_errors (); } +void rai::rpc_handler::confirmation_info () +{ + const bool representatives = request.get ("representatives", false); + const bool contents = request.get ("contents", true); + std::string root_text (request.get ("root")); + rai::block_hash root; + if (!root.decode_hex (root_text)) + { + std::lock_guard lock (node.active.mutex); + auto conflict_info (node.active.roots.find (root)); + if (conflict_info != node.active.roots.end ()) + { + response_l.put ("announcements", std::to_string (conflict_info->announcements)); + auto election (conflict_info->election); + rai::uint128_t total (0); + response_l.put ("last_winner", election->status.winner->hash ().to_string ()); + auto transaction (node.store.tx_begin_read ()); + auto tally_l (election->tally (transaction)); + boost::property_tree::ptree blocks; + for (auto i (tally_l.begin ()), n (tally_l.end ()); i != n; ++i) + { + boost::property_tree::ptree entry; + auto tally (i->first); + entry.put ("tally", tally.convert_to ()); + total += tally; + if (contents) + { + std::string contents; + i->second->serialize_json (contents); + entry.put ("contents", contents); + } + if (representatives) + { + std::multimap> representatives; + for (auto ii (election->last_votes.begin ()), nn (election->last_votes.end ()); ii != nn; ++ii) + { + if (i->second->hash () == ii->second.hash) + { + rai::account representative (ii->first); + auto amount (node.store.representation_get (transaction, representative)); + representatives.insert (std::make_pair (amount, representative)); + } + } + boost::property_tree::ptree representatives_list; + for (auto ii (representatives.begin ()), nn (representatives.end ()); ii != nn; ++ii) + { + representatives_list.put (ii->second.to_account (), ii->first.convert_to ()); + } + entry.add_child ("representatives", representatives_list); + } + blocks.add_child ((i->second->hash ()).to_string (), entry); + } + response_l.put ("total_tally", total.convert_to ()); + response_l.add_child ("blocks", blocks); + } + else + { + ec = nano::error_rpc::confirmation_not_found; + } + } + else + { + ec = nano::error_rpc::invalid_root; + } + response_errors (); +} + +void rai::rpc_handler::confirmation_quorum () +{ + response_l.put ("quorum_delta", node.delta ().convert_to ()); + response_l.put ("online_weight_quorum_percent", std::to_string (node.config.online_weight_quorum)); + response_l.put ("online_weight_minimum", node.config.online_weight_minimum.to_string_dec ()); + response_l.put ("online_stake_total", node.online_reps.online_stake_total.convert_to ()); + response_l.put ("peers_stake_total", node.peers.total_weight ().convert_to ()); + response_errors (); +} + void rai::rpc_handler::delegators () { auto account (account_impl ()); @@ -3712,10 +3814,22 @@ void rai::rpc_handler::process_request () { deterministic_key (); } + else if (action == "confirmation_active") + { + confirmation_active (); + } else if (action == "confirmation_history") { confirmation_history (); } + else if (action == "confirmation_info") + { + confirmation_info (); + } + else if (action == "confirmation_quorum") + { + confirmation_quorum (); + } else if (action == "frontiers") { frontiers (); diff --git a/rai/node/rpc.hpp b/rai/node/rpc.hpp index 5b2bfe86..07ef879e 100644 --- a/rai/node/rpc.hpp +++ b/rai/node/rpc.hpp @@ -146,7 +146,10 @@ public: void bootstrap (); void bootstrap_any (); void chain (bool = false); + void confirmation_active (); void confirmation_history (); + void confirmation_info (); + void confirmation_quorum (); void delegators (); void delegators_count (); void deterministic_key ();