Merge pull request #4508 from clemahieu/block_cemented_callback_simplify
Block cemented callback simplify
This commit is contained in:
		
				commit
				
					
						0e6b7fa635
					
				
			
		
					 6 changed files with 61 additions and 153 deletions
				
			
		| 
						 | 
				
			
			@ -1444,8 +1444,9 @@ TEST (confirmation_height, pending_observer_callbacks)
 | 
			
		|||
 | 
			
		||||
		node->confirmation_height_processor.add (send1);
 | 
			
		||||
 | 
			
		||||
		// Confirm the callback is not called under this circumstance because there is no election information
 | 
			
		||||
		ASSERT_TIMELY (10s, node->stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out) == 1 && node->ledger.stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::all, nano::stat::dir::out) == 1);
 | 
			
		||||
		// Callback is performed for all blocks that are confirmed
 | 
			
		||||
		ASSERT_TIMELY_EQ (5s, 2, node->stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out))
 | 
			
		||||
		ASSERT_TIMELY_EQ (5s, 2, node->ledger.stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::all, nano::stat::dir::out));
 | 
			
		||||
 | 
			
		||||
		ASSERT_EQ (2, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in));
 | 
			
		||||
		ASSERT_EQ (2, node->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in));
 | 
			
		||||
| 
						 | 
				
			
			@ -1528,7 +1529,8 @@ TEST (confirmation_height, callback_confirmed_history)
 | 
			
		|||
		ASSERT_TIMELY_EQ (10s, node->active.size (), 0);
 | 
			
		||||
		ASSERT_TIMELY_EQ (10s, node->stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::active_quorum, nano::stat::dir::out), 1);
 | 
			
		||||
 | 
			
		||||
		ASSERT_EQ (1, node->active.recently_cemented.list ().size ());
 | 
			
		||||
		// Each block that's confirmed is in the recently_cemented history
 | 
			
		||||
		ASSERT_EQ (2, node->active.recently_cemented.list ().size ());
 | 
			
		||||
		ASSERT_TRUE (node->active.empty ());
 | 
			
		||||
 | 
			
		||||
		// Confirm the callback is not called under this circumstance
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,75 +80,44 @@ void nano::active_transactions::stop ()
 | 
			
		|||
	clear ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::active_transactions::block_cemented_callback (std::shared_ptr<nano::block> const & block_a)
 | 
			
		||||
void nano::active_transactions::block_cemented_callback (std::shared_ptr<nano::block> const & block)
 | 
			
		||||
{
 | 
			
		||||
	auto status_type = election_status (block_a);
 | 
			
		||||
 | 
			
		||||
	if (!status_type)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	auto transaction = node.store.tx_begin_read ();
 | 
			
		||||
	switch (*status_type)
 | 
			
		||||
	if (auto election_l = election (block->qualified_root ()))
 | 
			
		||||
	{
 | 
			
		||||
		case nano::election_status_type::inactive_confirmation_height:
 | 
			
		||||
			process_inactive_confirmation (transaction, block_a);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			process_active_confirmation (transaction, block_a, *status_type);
 | 
			
		||||
			break;
 | 
			
		||||
		election_l->try_confirm (block->hash ());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	handle_final_votes_confirmation (block_a, transaction, *status_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
boost::optional<nano::election_status_type> nano::active_transactions::election_status (std::shared_ptr<nano::block> const & block)
 | 
			
		||||
{
 | 
			
		||||
	boost::optional<nano::election_status_type> status_type;
 | 
			
		||||
 | 
			
		||||
	if (!confirmation_height_processor.is_processing_added_block (block->hash ()))
 | 
			
		||||
	auto election = remove_election_winner_details (block->hash ());
 | 
			
		||||
	nano::election_status status;
 | 
			
		||||
	std::vector<nano::vote_with_weight_info> votes;
 | 
			
		||||
	status.winner = block;
 | 
			
		||||
	if (election)
 | 
			
		||||
	{
 | 
			
		||||
		status_type = confirm_block (block);
 | 
			
		||||
		status = election->get_status ();
 | 
			
		||||
		votes = election->votes_with_weight ();
 | 
			
		||||
	}
 | 
			
		||||
	if (confirmation_height_processor.is_processing_added_block (block->hash ()))
 | 
			
		||||
	{
 | 
			
		||||
		status.type = nano::election_status_type::active_confirmed_quorum;
 | 
			
		||||
	}
 | 
			
		||||
	else if (election)
 | 
			
		||||
	{
 | 
			
		||||
		status.type = nano::election_status_type::active_confirmation_height;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		status_type = nano::election_status_type::active_confirmed_quorum;
 | 
			
		||||
		status.type = nano::election_status_type::inactive_confirmation_height;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return status_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::active_transactions::process_inactive_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block)
 | 
			
		||||
{
 | 
			
		||||
	nano::election_status status{ block, 0, 0, std::chrono::duration_cast<std::chrono::milliseconds> (std::chrono::system_clock::now ().time_since_epoch ()), std::chrono::duration_values<std::chrono::milliseconds>::zero (), 0, 1, 0, nano::election_status_type::inactive_confirmation_height };
 | 
			
		||||
	notify_observers (transaction, status, {});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::active_transactions::process_active_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block, nano::election_status_type status_type)
 | 
			
		||||
{
 | 
			
		||||
	auto hash (block->hash ());
 | 
			
		||||
	nano::unique_lock<nano::mutex> election_winners_lk{ election_winner_details_mutex };
 | 
			
		||||
	auto existing = election_winner_details.find (hash);
 | 
			
		||||
	if (existing != election_winner_details.end ())
 | 
			
		||||
	{
 | 
			
		||||
		auto election = existing->second;
 | 
			
		||||
		election_winner_details.erase (hash);
 | 
			
		||||
		election_winners_lk.unlock ();
 | 
			
		||||
		if (election->confirmed () && election->winner ()->hash () == hash)
 | 
			
		||||
		{
 | 
			
		||||
			handle_confirmation (transaction, block, election, status_type);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::active_transactions::handle_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block, std::shared_ptr<nano::election> election, nano::election_status_type status_type)
 | 
			
		||||
{
 | 
			
		||||
	nano::block_hash hash = block->hash ();
 | 
			
		||||
	recently_cemented.put (election->get_status ());
 | 
			
		||||
 | 
			
		||||
	auto status = election->set_status_type (status_type);
 | 
			
		||||
	auto votes = election->votes_with_weight ();
 | 
			
		||||
	recently_cemented.put (status);
 | 
			
		||||
	auto transaction = node.store.tx_begin_read ();
 | 
			
		||||
	notify_observers (transaction, status, votes);
 | 
			
		||||
	bool cemented_bootstrap_count_reached = node.ledger.cache.cemented_count >= node.ledger.bootstrap_weight_max_blocks;
 | 
			
		||||
	bool was_active = status.type == nano::election_status_type::active_confirmed_quorum || status.type == nano::election_status_type::active_confirmation_height;
 | 
			
		||||
 | 
			
		||||
	// Next-block activations are only done for blocks with previously active elections
 | 
			
		||||
	if (cemented_bootstrap_count_reached && was_active)
 | 
			
		||||
	{
 | 
			
		||||
		activate_successors (transaction, block);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::active_transactions::notify_observers (nano::store::read_transaction const & transaction, nano::election_status const & status, std::vector<nano::vote_with_weight_info> const & votes)
 | 
			
		||||
| 
						 | 
				
			
			@ -170,19 +139,6 @@ void nano::active_transactions::notify_observers (nano::store::read_transaction
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::active_transactions::handle_final_votes_confirmation (std::shared_ptr<nano::block> const & block, nano::store::read_transaction const & transaction, nano::election_status_type status)
 | 
			
		||||
{
 | 
			
		||||
	auto account = block->account ();
 | 
			
		||||
	bool cemented_bootstrap_count_reached = node.ledger.cache.cemented_count >= node.ledger.bootstrap_weight_max_blocks;
 | 
			
		||||
	bool was_active = status == nano::election_status_type::active_confirmed_quorum || status == nano::election_status_type::active_confirmation_height;
 | 
			
		||||
 | 
			
		||||
	// Next-block activations are only done for blocks with previously active elections
 | 
			
		||||
	if (cemented_bootstrap_count_reached && was_active)
 | 
			
		||||
	{
 | 
			
		||||
		activate_successors (transaction, block);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::active_transactions::activate_successors (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block)
 | 
			
		||||
{
 | 
			
		||||
	node.scheduler.priority.activate (block->account (), transaction);
 | 
			
		||||
| 
						 | 
				
			
			@ -200,10 +156,17 @@ void nano::active_transactions::add_election_winner_details (nano::block_hash co
 | 
			
		|||
	election_winner_details.emplace (hash_a, election_a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::active_transactions::remove_election_winner_details (nano::block_hash const & hash_a)
 | 
			
		||||
std::shared_ptr<nano::election> nano::active_transactions::remove_election_winner_details (nano::block_hash const & hash_a)
 | 
			
		||||
{
 | 
			
		||||
	nano::lock_guard<nano::mutex> guard{ election_winner_details_mutex };
 | 
			
		||||
	election_winner_details.erase (hash_a);
 | 
			
		||||
	std::shared_ptr<nano::election> result;
 | 
			
		||||
	auto existing = election_winner_details.find (hash_a);
 | 
			
		||||
	if (existing != election_winner_details.end ())
 | 
			
		||||
	{
 | 
			
		||||
		result = existing->second;
 | 
			
		||||
		election_winner_details.erase (existing);
 | 
			
		||||
	}
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::active_transactions::block_already_cemented_callback (nano::block_hash const & hash_a)
 | 
			
		||||
| 
						 | 
				
			
			@ -653,33 +616,6 @@ bool nano::active_transactions::publish (std::shared_ptr<nano::block> const & bl
 | 
			
		|||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns the type of election status requiring callbacks calling later
 | 
			
		||||
boost::optional<nano::election_status_type> nano::active_transactions::confirm_block (std::shared_ptr<nano::block> const & block_a)
 | 
			
		||||
{
 | 
			
		||||
	auto const hash = block_a->hash ();
 | 
			
		||||
	std::shared_ptr<nano::election> election = nullptr;
 | 
			
		||||
	{
 | 
			
		||||
		nano::lock_guard<nano::mutex> guard{ mutex };
 | 
			
		||||
		auto existing = blocks.find (hash);
 | 
			
		||||
		if (existing != blocks.end ())
 | 
			
		||||
		{
 | 
			
		||||
			election = existing->second;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	boost::optional<nano::election_status_type> status_type;
 | 
			
		||||
	if (election)
 | 
			
		||||
	{
 | 
			
		||||
		status_type = election->try_confirm (hash);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		status_type = nano::election_status_type::inactive_confirmation_height;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return status_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::active_transactions::add_vote_cache (nano::block_hash const & hash, std::shared_ptr<nano::vote> const vote)
 | 
			
		||||
{
 | 
			
		||||
	if (node.ledger.weight (vote->account) > node.minimum_principal_weight ())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -160,7 +160,6 @@ public:
 | 
			
		|||
	bool empty () const;
 | 
			
		||||
	std::size_t size () const;
 | 
			
		||||
	bool publish (std::shared_ptr<nano::block> const &);
 | 
			
		||||
	boost::optional<nano::election_status_type> confirm_block (std::shared_ptr<nano::block> const &);
 | 
			
		||||
	void block_cemented_callback (std::shared_ptr<nano::block> const &);
 | 
			
		||||
	void block_already_cemented_callback (nano::block_hash const &);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -177,7 +176,7 @@ public:
 | 
			
		|||
 | 
			
		||||
	std::size_t election_winner_details_size ();
 | 
			
		||||
	void add_election_winner_details (nano::block_hash const &, std::shared_ptr<nano::election> const &);
 | 
			
		||||
	void remove_election_winner_details (nano::block_hash const &);
 | 
			
		||||
	std::shared_ptr<nano::election> remove_election_winner_details (nano::block_hash const &);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	// Erase elections if we're over capacity
 | 
			
		||||
| 
						 | 
				
			
			@ -195,11 +194,6 @@ private:
 | 
			
		|||
	 * TODO: Should be moved to `vote_cache` class
 | 
			
		||||
	 */
 | 
			
		||||
	void add_vote_cache (nano::block_hash const & hash, std::shared_ptr<nano::vote> vote);
 | 
			
		||||
	boost::optional<nano::election_status_type> election_status (std::shared_ptr<nano::block> const & block);
 | 
			
		||||
	void process_inactive_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block);
 | 
			
		||||
	void process_active_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block, nano::election_status_type status);
 | 
			
		||||
	void handle_final_votes_confirmation (std::shared_ptr<nano::block> const & block, nano::store::read_transaction const & transaction, nano::election_status_type status);
 | 
			
		||||
	void handle_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block, std::shared_ptr<nano::election> election, nano::election_status_type status);
 | 
			
		||||
	void activate_successors (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block);
 | 
			
		||||
	void notify_observers (nano::store::read_transaction const & transaction, nano::election_status const & status, std::vector<nano::vote_with_weight_info> const & votes);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,7 +34,7 @@ nano::election::election (nano::node & node_a, std::shared_ptr<nano::block> cons
 | 
			
		|||
	last_blocks.emplace (block_a->hash (), block_a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::election::confirm_once (nano::unique_lock<nano::mutex> & lock_a, nano::election_status_type type_a)
 | 
			
		||||
void nano::election::confirm_once (nano::unique_lock<nano::mutex> & lock_a)
 | 
			
		||||
{
 | 
			
		||||
	debug_assert (lock_a.owns_lock ());
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +51,6 @@ void nano::election::confirm_once (nano::unique_lock<nano::mutex> & lock_a, nano
 | 
			
		|||
		status.confirmation_request_count = confirmation_request_count;
 | 
			
		||||
		status.block_count = nano::narrow_cast<decltype (status.block_count)> (last_blocks.size ());
 | 
			
		||||
		status.voter_count = nano::narrow_cast<decltype (status.voter_count)> (last_votes.size ());
 | 
			
		||||
		status.type = type_a;
 | 
			
		||||
		auto const status_l = status;
 | 
			
		||||
 | 
			
		||||
		node.active.recently_confirmed.put (qualified_root, status_l.winner->hash ());
 | 
			
		||||
| 
						 | 
				
			
			@ -403,44 +402,22 @@ void nano::election::confirm_if_quorum (nano::unique_lock<nano::mutex> & lock_a)
 | 
			
		|||
		}
 | 
			
		||||
		if (final_weight >= node.online_reps.delta ())
 | 
			
		||||
		{
 | 
			
		||||
			confirm_once (lock_a, nano::election_status_type::active_confirmed_quorum);
 | 
			
		||||
			confirm_once (lock_a);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
boost::optional<nano::election_status_type> nano::election::try_confirm (nano::block_hash const & hash)
 | 
			
		||||
void nano::election::try_confirm (nano::block_hash const & hash)
 | 
			
		||||
{
 | 
			
		||||
	boost::optional<nano::election_status_type> status_type;
 | 
			
		||||
	nano::unique_lock<nano::mutex> election_lock{ mutex };
 | 
			
		||||
	auto winner = status.winner;
 | 
			
		||||
	if (winner && winner->hash () == hash)
 | 
			
		||||
	{
 | 
			
		||||
		// Determine if the block was confirmed explicitly via election confirmation or implicitly via confirmation height
 | 
			
		||||
		if (!confirmed_locked ())
 | 
			
		||||
		{
 | 
			
		||||
			confirm_once (election_lock, nano::election_status_type::active_confirmation_height);
 | 
			
		||||
			status_type = nano::election_status_type::active_confirmation_height;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			status_type = nano::election_status_type::active_confirmed_quorum;
 | 
			
		||||
			confirm_once (election_lock);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		status_type = boost::optional<nano::election_status_type>{};
 | 
			
		||||
	}
 | 
			
		||||
	return status_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nano::election_status nano::election::set_status_type (nano::election_status_type status_type)
 | 
			
		||||
{
 | 
			
		||||
	nano::unique_lock<nano::mutex> election_lk{ mutex };
 | 
			
		||||
	status.type = status_type;
 | 
			
		||||
	status.confirmation_request_count = confirmation_request_count;
 | 
			
		||||
	nano::election_status status_l{ status };
 | 
			
		||||
	election_lk.unlock ();
 | 
			
		||||
	return status_l;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<nano::block> nano::election::find (nano::block_hash const & hash_a) const
 | 
			
		||||
| 
						 | 
				
			
			@ -709,11 +686,11 @@ bool nano::election::replace_by_weight (nano::unique_lock<nano::mutex> & lock_a,
 | 
			
		|||
	return replaced;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::election::force_confirm (nano::election_status_type type_a)
 | 
			
		||||
void nano::election::force_confirm ()
 | 
			
		||||
{
 | 
			
		||||
	release_assert (node.network_params.network.is_dev_network ());
 | 
			
		||||
	nano::unique_lock<nano::mutex> lock{ mutex };
 | 
			
		||||
	confirm_once (lock, type_a);
 | 
			
		||||
	confirm_once (lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unordered_map<nano::block_hash, std::shared_ptr<nano::block>> nano::election::blocks () const
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -146,8 +146,7 @@ public: // Interface
 | 
			
		|||
	bool publish (std::shared_ptr<nano::block> const & block_a);
 | 
			
		||||
	// Confirm this block if quorum is met
 | 
			
		||||
	void confirm_if_quorum (nano::unique_lock<nano::mutex> &);
 | 
			
		||||
	boost::optional<nano::election_status_type> try_confirm (nano::block_hash const & hash);
 | 
			
		||||
	nano::election_status set_status_type (nano::election_status_type status_type);
 | 
			
		||||
	void try_confirm (nano::block_hash const & hash);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Broadcasts vote for the current winner of this election
 | 
			
		||||
| 
						 | 
				
			
			@ -173,7 +172,7 @@ private:
 | 
			
		|||
	bool confirmed_locked () const;
 | 
			
		||||
	nano::election_extended_status current_status_locked () const;
 | 
			
		||||
	// lock_a does not own the mutex on return
 | 
			
		||||
	void confirm_once (nano::unique_lock<nano::mutex> & lock_a, nano::election_status_type = nano::election_status_type::active_confirmed_quorum);
 | 
			
		||||
	void confirm_once (nano::unique_lock<nano::mutex> & lock_a);
 | 
			
		||||
	bool broadcast_block_predicate () const;
 | 
			
		||||
	void broadcast_block (nano::confirmation_solicitor &);
 | 
			
		||||
	void send_confirm_req (nano::confirmation_solicitor &);
 | 
			
		||||
| 
						 | 
				
			
			@ -217,7 +216,7 @@ private: // Constants
 | 
			
		|||
	friend class confirmation_solicitor;
 | 
			
		||||
 | 
			
		||||
public: // Only used in tests
 | 
			
		||||
	void force_confirm (nano::election_status_type = nano::election_status_type::active_confirmed_quorum);
 | 
			
		||||
	void force_confirm ();
 | 
			
		||||
	std::unordered_map<nano::account, nano::vote_info> votes () const;
 | 
			
		||||
	std::unordered_map<nano::block_hash, std::shared_ptr<nano::block>> blocks () const;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -360,14 +360,14 @@ class election_status final
 | 
			
		|||
{
 | 
			
		||||
public:
 | 
			
		||||
	std::shared_ptr<nano::block> winner;
 | 
			
		||||
	nano::amount tally;
 | 
			
		||||
	nano::amount final_tally;
 | 
			
		||||
	std::chrono::milliseconds election_end;
 | 
			
		||||
	std::chrono::milliseconds election_duration;
 | 
			
		||||
	unsigned confirmation_request_count;
 | 
			
		||||
	unsigned block_count;
 | 
			
		||||
	unsigned voter_count;
 | 
			
		||||
	election_status_type type;
 | 
			
		||||
	nano::amount tally{ 0 };
 | 
			
		||||
	nano::amount final_tally{ 0 };
 | 
			
		||||
	std::chrono::milliseconds election_end{ std::chrono::duration_cast<std::chrono::milliseconds> (std::chrono::system_clock::now ().time_since_epoch ()) };
 | 
			
		||||
	std::chrono::milliseconds election_duration{ std::chrono::duration_values<std::chrono::milliseconds>::zero () };
 | 
			
		||||
	unsigned confirmation_request_count{ 0 };
 | 
			
		||||
	unsigned block_count{ 0 };
 | 
			
		||||
	unsigned voter_count{ 0 };
 | 
			
		||||
	election_status_type type{ nano::election_status_type::inactive_confirmation_height };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
nano::wallet_id random_wallet_id ();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue