Merge pull request #4656 from pwojcikdev/online-reps-overhaul
Overhaul of `online_reps` class
This commit is contained in:
		
				commit
				
					
						60a44d6c08
					
				
			
		
					 34 changed files with 491 additions and 261 deletions
				
			
		| 
						 | 
					@ -40,6 +40,7 @@ add_executable(
 | 
				
			||||||
  numbers.cpp
 | 
					  numbers.cpp
 | 
				
			||||||
  object_stream.cpp
 | 
					  object_stream.cpp
 | 
				
			||||||
  observer_set.cpp
 | 
					  observer_set.cpp
 | 
				
			||||||
 | 
					  online_reps.cpp
 | 
				
			||||||
  optimistic_scheduler.cpp
 | 
					  optimistic_scheduler.cpp
 | 
				
			||||||
  processing_queue.cpp
 | 
					  processing_queue.cpp
 | 
				
			||||||
  processor_service.cpp
 | 
					  processor_service.cpp
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
#include <nano/node/active_elections.hpp>
 | 
					#include <nano/node/active_elections.hpp>
 | 
				
			||||||
#include <nano/node/confirming_set.hpp>
 | 
					#include <nano/node/confirming_set.hpp>
 | 
				
			||||||
#include <nano/node/election.hpp>
 | 
					#include <nano/node/election.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/component.hpp>
 | 
					#include <nano/node/scheduler/component.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/manual.hpp>
 | 
					#include <nano/node/scheduler/manual.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/priority.hpp>
 | 
					#include <nano/node/scheduler/priority.hpp>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
#include <nano/lib/blocks.hpp>
 | 
					#include <nano/lib/blocks.hpp>
 | 
				
			||||||
#include <nano/node/active_elections.hpp>
 | 
					#include <nano/node/active_elections.hpp>
 | 
				
			||||||
#include <nano/node/election.hpp>
 | 
					#include <nano/node/election.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/component.hpp>
 | 
					#include <nano/node/scheduler/component.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/priority.hpp>
 | 
					#include <nano/node/scheduler/priority.hpp>
 | 
				
			||||||
#include <nano/node/vote_router.hpp>
 | 
					#include <nano/node/vote_router.hpp>
 | 
				
			||||||
| 
						 | 
					@ -259,11 +260,9 @@ TEST (election, quorum_minimum_update_weight_before_quorum_checks)
 | 
				
			||||||
	node1.rep_crawler.force_process (vote2, channel);
 | 
						node1.rep_crawler.force_process (vote2, channel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ASSERT_FALSE (election->confirmed ());
 | 
						ASSERT_FALSE (election->confirmed ());
 | 
				
			||||||
	{
 | 
					
 | 
				
			||||||
		nano::lock_guard<nano::mutex> guard (node1.online_reps.mutex);
 | 
						// Modify online_m for online_reps to more than is available, this checks that voting below updates it to current online reps.
 | 
				
			||||||
		// Modify online_m for online_reps to more than is available, this checks that voting below updates it to current online reps.
 | 
						node1.online_reps.force_online_weight (node_config.online_weight_minimum.number () + 20);
 | 
				
			||||||
		node1.online_reps.online_m = node_config.online_weight_minimum.number () + 20;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::vote_code::vote, node1.vote_router.vote (vote2).at (send1->hash ()));
 | 
						ASSERT_EQ (nano::vote_code::vote, node1.vote_router.vote (vote2).at (send1->hash ()));
 | 
				
			||||||
	ASSERT_TIMELY (5s, election->confirmed ());
 | 
						ASSERT_TIMELY (5s, election->confirmed ());
 | 
				
			||||||
	ASSERT_NE (nullptr, node1.block (send1->hash ()));
 | 
						ASSERT_NE (nullptr, node1.block (send1->hash ()));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
#include <nano/node/active_elections.hpp>
 | 
					#include <nano/node/active_elections.hpp>
 | 
				
			||||||
#include <nano/node/election.hpp>
 | 
					#include <nano/node/election.hpp>
 | 
				
			||||||
#include <nano/node/make_store.hpp>
 | 
					#include <nano/node/make_store.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/secure/ledger.hpp>
 | 
					#include <nano/secure/ledger.hpp>
 | 
				
			||||||
#include <nano/secure/ledger_set_any.hpp>
 | 
					#include <nano/secure/ledger_set_any.hpp>
 | 
				
			||||||
#include <nano/secure/ledger_set_confirmed.hpp>
 | 
					#include <nano/secure/ledger_set_confirmed.hpp>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
#include <nano/node/inactive_node.hpp>
 | 
					#include <nano/node/inactive_node.hpp>
 | 
				
			||||||
#include <nano/node/local_vote_history.hpp>
 | 
					#include <nano/node/local_vote_history.hpp>
 | 
				
			||||||
#include <nano/node/make_store.hpp>
 | 
					#include <nano/node/make_store.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/node/portmapping.hpp>
 | 
					#include <nano/node/portmapping.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/component.hpp>
 | 
					#include <nano/node/scheduler/component.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/manual.hpp>
 | 
					#include <nano/node/scheduler/manual.hpp>
 | 
				
			||||||
| 
						 | 
					@ -1565,71 +1566,6 @@ TEST (node, balance_observer)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (node, online_reps)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::test::system system (1);
 | 
					 | 
				
			||||||
	auto & node1 (*system.nodes[0]);
 | 
					 | 
				
			||||||
	// 1 sample of minimum weight
 | 
					 | 
				
			||||||
	ASSERT_EQ (node1.config.online_weight_minimum, node1.online_reps.trended ());
 | 
					 | 
				
			||||||
	auto vote (std::make_shared<nano::vote> ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (0, node1.online_reps.online ());
 | 
					 | 
				
			||||||
	node1.online_reps.observe (nano::dev::genesis_key.pub);
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::dev::constants.genesis_amount, node1.online_reps.online ());
 | 
					 | 
				
			||||||
	// 1 minimum, 1 maximum
 | 
					 | 
				
			||||||
	ASSERT_EQ (node1.config.online_weight_minimum, node1.online_reps.trended ());
 | 
					 | 
				
			||||||
	node1.online_reps.sample ();
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::dev::constants.genesis_amount, node1.online_reps.trended ());
 | 
					 | 
				
			||||||
	node1.online_reps.clear ();
 | 
					 | 
				
			||||||
	// 2 minimum, 1 maximum
 | 
					 | 
				
			||||||
	node1.online_reps.sample ();
 | 
					 | 
				
			||||||
	ASSERT_EQ (node1.config.online_weight_minimum, node1.online_reps.trended ());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (node, online_reps_rep_crawler)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::test::system system;
 | 
					 | 
				
			||||||
	nano::node_flags flags;
 | 
					 | 
				
			||||||
	flags.disable_rep_crawler = true;
 | 
					 | 
				
			||||||
	auto & node1 = *system.add_node (flags);
 | 
					 | 
				
			||||||
	auto vote = std::make_shared<nano::vote> (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::milliseconds_since_epoch (), 0, std::vector<nano::block_hash>{ nano::dev::genesis->hash () });
 | 
					 | 
				
			||||||
	ASSERT_EQ (0, node1.online_reps.online ());
 | 
					 | 
				
			||||||
	// Without rep crawler
 | 
					 | 
				
			||||||
	node1.vote_processor.vote_blocking (vote, std::make_shared<nano::transport::fake::channel> (node1));
 | 
					 | 
				
			||||||
	ASSERT_EQ (0, node1.online_reps.online ());
 | 
					 | 
				
			||||||
	// After inserting to rep crawler
 | 
					 | 
				
			||||||
	auto channel = std::make_shared<nano::transport::fake::channel> (node1);
 | 
					 | 
				
			||||||
	node1.rep_crawler.force_query (nano::dev::genesis->hash (), channel);
 | 
					 | 
				
			||||||
	node1.vote_processor.vote_blocking (vote, channel);
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::dev::constants.genesis_amount, node1.online_reps.online ());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (node, online_reps_election)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::test::system system;
 | 
					 | 
				
			||||||
	nano::node_flags flags;
 | 
					 | 
				
			||||||
	flags.disable_rep_crawler = true;
 | 
					 | 
				
			||||||
	auto & node1 = *system.add_node (flags);
 | 
					 | 
				
			||||||
	// Start election
 | 
					 | 
				
			||||||
	nano::keypair key;
 | 
					 | 
				
			||||||
	nano::state_block_builder builder;
 | 
					 | 
				
			||||||
	auto send1 = builder.make_block ()
 | 
					 | 
				
			||||||
				 .account (nano::dev::genesis_key.pub)
 | 
					 | 
				
			||||||
				 .previous (nano::dev::genesis->hash ())
 | 
					 | 
				
			||||||
				 .representative (nano::dev::genesis_key.pub)
 | 
					 | 
				
			||||||
				 .balance (nano::dev::constants.genesis_amount - nano::Knano_ratio)
 | 
					 | 
				
			||||||
				 .link (key.pub)
 | 
					 | 
				
			||||||
				 .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
 | 
					 | 
				
			||||||
				 .work (*node1.work_generate_blocking (nano::dev::genesis->hash ()))
 | 
					 | 
				
			||||||
				 .build ();
 | 
					 | 
				
			||||||
	node1.process_active (send1);
 | 
					 | 
				
			||||||
	ASSERT_TIMELY_EQ (5s, 1, node1.active.size ());
 | 
					 | 
				
			||||||
	// Process vote for ongoing election
 | 
					 | 
				
			||||||
	auto vote = std::make_shared<nano::vote> (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::milliseconds_since_epoch (), 0, std::vector<nano::block_hash>{ send1->hash () });
 | 
					 | 
				
			||||||
	ASSERT_EQ (0, node1.online_reps.online ());
 | 
					 | 
				
			||||||
	node1.vote_processor.vote_blocking (vote, std::make_shared<nano::transport::fake::channel> (node1));
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Knano_ratio, node1.online_reps.online ());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (node, block_confirm)
 | 
					TEST (node, block_confirm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto type = nano::transport::transport_type::tcp;
 | 
						auto type = nano::transport::transport_type::tcp;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										72
									
								
								nano/core_test/online_reps.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								nano/core_test/online_reps.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,72 @@
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/transport/fake.hpp>
 | 
				
			||||||
 | 
					#include <nano/secure/vote.hpp>
 | 
				
			||||||
 | 
					#include <nano/test_common/system.hpp>
 | 
				
			||||||
 | 
					#include <nano/test_common/testutil.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gtest/gtest.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST (online_reps, basic)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nano::test::system system (1);
 | 
				
			||||||
 | 
						auto & node1 (*system.nodes[0]);
 | 
				
			||||||
 | 
						// 1 sample of minimum weight
 | 
				
			||||||
 | 
						ASSERT_EQ (node1.config.online_weight_minimum, node1.online_reps.trended ());
 | 
				
			||||||
 | 
						auto vote (std::make_shared<nano::vote> ());
 | 
				
			||||||
 | 
						ASSERT_EQ (0, node1.online_reps.online ());
 | 
				
			||||||
 | 
						node1.online_reps.observe (nano::dev::genesis_key.pub);
 | 
				
			||||||
 | 
						ASSERT_EQ (nano::dev::constants.genesis_amount, node1.online_reps.online ());
 | 
				
			||||||
 | 
						// 1 minimum, 1 maximum
 | 
				
			||||||
 | 
						ASSERT_EQ (node1.config.online_weight_minimum, node1.online_reps.trended ());
 | 
				
			||||||
 | 
						node1.online_reps.force_sample ();
 | 
				
			||||||
 | 
						ASSERT_EQ (nano::dev::constants.genesis_amount, node1.online_reps.trended ());
 | 
				
			||||||
 | 
						node1.online_reps.clear ();
 | 
				
			||||||
 | 
						// 2 minimum, 1 maximum
 | 
				
			||||||
 | 
						node1.online_reps.force_sample ();
 | 
				
			||||||
 | 
						ASSERT_EQ (node1.config.online_weight_minimum, node1.online_reps.trended ());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST (online_reps, rep_crawler)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nano::test::system system;
 | 
				
			||||||
 | 
						nano::node_flags flags;
 | 
				
			||||||
 | 
						flags.disable_rep_crawler = true;
 | 
				
			||||||
 | 
						auto & node1 = *system.add_node (flags);
 | 
				
			||||||
 | 
						auto vote = std::make_shared<nano::vote> (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::milliseconds_since_epoch (), 0, std::vector<nano::block_hash>{ nano::dev::genesis->hash () });
 | 
				
			||||||
 | 
						ASSERT_EQ (0, node1.online_reps.online ());
 | 
				
			||||||
 | 
						// Without rep crawler
 | 
				
			||||||
 | 
						node1.vote_processor.vote_blocking (vote, std::make_shared<nano::transport::fake::channel> (node1));
 | 
				
			||||||
 | 
						ASSERT_EQ (0, node1.online_reps.online ());
 | 
				
			||||||
 | 
						// After inserting to rep crawler
 | 
				
			||||||
 | 
						auto channel = std::make_shared<nano::transport::fake::channel> (node1);
 | 
				
			||||||
 | 
						node1.rep_crawler.force_query (nano::dev::genesis->hash (), channel);
 | 
				
			||||||
 | 
						node1.vote_processor.vote_blocking (vote, channel);
 | 
				
			||||||
 | 
						ASSERT_EQ (nano::dev::constants.genesis_amount, node1.online_reps.online ());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST (online_reps, election)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nano::test::system system;
 | 
				
			||||||
 | 
						nano::node_flags flags;
 | 
				
			||||||
 | 
						flags.disable_rep_crawler = true;
 | 
				
			||||||
 | 
						auto & node1 = *system.add_node (flags);
 | 
				
			||||||
 | 
						// Start election
 | 
				
			||||||
 | 
						nano::keypair key;
 | 
				
			||||||
 | 
						nano::state_block_builder builder;
 | 
				
			||||||
 | 
						auto send1 = builder.make_block ()
 | 
				
			||||||
 | 
									 .account (nano::dev::genesis_key.pub)
 | 
				
			||||||
 | 
									 .previous (nano::dev::genesis->hash ())
 | 
				
			||||||
 | 
									 .representative (nano::dev::genesis_key.pub)
 | 
				
			||||||
 | 
									 .balance (nano::dev::constants.genesis_amount - nano::Knano_ratio)
 | 
				
			||||||
 | 
									 .link (key.pub)
 | 
				
			||||||
 | 
									 .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
 | 
				
			||||||
 | 
									 .work (*node1.work_generate_blocking (nano::dev::genesis->hash ()))
 | 
				
			||||||
 | 
									 .build ();
 | 
				
			||||||
 | 
						node1.process_active (send1);
 | 
				
			||||||
 | 
						ASSERT_TIMELY_EQ (5s, 1, node1.active.size ());
 | 
				
			||||||
 | 
						// Process vote for ongoing election
 | 
				
			||||||
 | 
						auto vote = std::make_shared<nano::vote> (nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::milliseconds_since_epoch (), 0, std::vector<nano::block_hash>{ send1->hash () });
 | 
				
			||||||
 | 
						ASSERT_EQ (0, node1.online_reps.online ());
 | 
				
			||||||
 | 
						node1.vote_processor.vote_blocking (vote, std::make_shared<nano::transport::fake::channel> (node1));
 | 
				
			||||||
 | 
						ASSERT_EQ (nano::dev::constants.genesis_amount - nano::Knano_ratio, node1.online_reps.online ());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -128,53 +128,56 @@ TEST (rep_crawler, rep_remove)
 | 
				
			||||||
	nano::keypair keys_rep2; // Principal representative 2
 | 
						nano::keypair keys_rep2; // Principal representative 2
 | 
				
			||||||
	nano::block_builder builder;
 | 
						nano::block_builder builder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto const rep_weight = nano::test::minimum_principal_weight () * 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Send enough nanos to Rep1 to make it a principal representative
 | 
						// Send enough nanos to Rep1 to make it a principal representative
 | 
				
			||||||
	std::shared_ptr<nano::block> send_to_rep1 = builder
 | 
						auto send_to_rep1 = builder
 | 
				
			||||||
												.state ()
 | 
											.state ()
 | 
				
			||||||
												.account (nano::dev::genesis_key.pub)
 | 
											.account (nano::dev::genesis_key.pub)
 | 
				
			||||||
												.previous (nano::dev::genesis->hash ())
 | 
											.previous (nano::dev::genesis->hash ())
 | 
				
			||||||
												.representative (nano::dev::genesis_key.pub)
 | 
											.representative (nano::dev::genesis_key.pub)
 | 
				
			||||||
												.balance (nano::dev::constants.genesis_amount - searching_node.minimum_principal_weight () * 2)
 | 
											.balance (nano::dev::constants.genesis_amount - rep_weight)
 | 
				
			||||||
												.link (keys_rep1.pub)
 | 
											.link (keys_rep1.pub)
 | 
				
			||||||
												.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
 | 
											.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
 | 
				
			||||||
												.work (*system.work.generate (nano::dev::genesis->hash ()))
 | 
											.work (*system.work.generate (nano::dev::genesis->hash ()))
 | 
				
			||||||
												.build ();
 | 
											.build ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Receive by Rep1
 | 
						// Receive by Rep1
 | 
				
			||||||
	std::shared_ptr<nano::block> receive_rep1 = builder
 | 
						auto receive_rep1 = builder
 | 
				
			||||||
												.state ()
 | 
											.state ()
 | 
				
			||||||
												.account (keys_rep1.pub)
 | 
											.account (keys_rep1.pub)
 | 
				
			||||||
												.previous (0)
 | 
											.previous (0)
 | 
				
			||||||
												.representative (keys_rep1.pub)
 | 
											.representative (keys_rep1.pub)
 | 
				
			||||||
												.balance (searching_node.minimum_principal_weight () * 2)
 | 
											.balance (rep_weight)
 | 
				
			||||||
												.link (send_to_rep1->hash ())
 | 
											.link (send_to_rep1->hash ())
 | 
				
			||||||
												.sign (keys_rep1.prv, keys_rep1.pub)
 | 
											.sign (keys_rep1.prv, keys_rep1.pub)
 | 
				
			||||||
												.work (*system.work.generate (keys_rep1.pub))
 | 
											.work (*system.work.generate (keys_rep1.pub))
 | 
				
			||||||
												.build ();
 | 
											.build ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Send enough nanos to Rep2 to make it a principal representative
 | 
						// Send enough nanos to Rep2 to make it a principal representative
 | 
				
			||||||
	std::shared_ptr<nano::block> send_to_rep2 = builder
 | 
						auto send_to_rep2 = builder
 | 
				
			||||||
												.state ()
 | 
											.state ()
 | 
				
			||||||
												.account (nano::dev::genesis_key.pub)
 | 
											.account (nano::dev::genesis_key.pub)
 | 
				
			||||||
												.previous (send_to_rep1->hash ())
 | 
											.previous (send_to_rep1->hash ())
 | 
				
			||||||
												.representative (nano::dev::genesis_key.pub)
 | 
											.representative (nano::dev::genesis_key.pub)
 | 
				
			||||||
												.balance (nano::dev::constants.genesis_amount - searching_node.minimum_principal_weight () * 4)
 | 
											.balance (nano::dev::constants.genesis_amount - rep_weight * 2)
 | 
				
			||||||
												.link (keys_rep2.pub)
 | 
											.link (keys_rep2.pub)
 | 
				
			||||||
												.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
 | 
											.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
 | 
				
			||||||
												.work (*system.work.generate (send_to_rep1->hash ()))
 | 
											.work (*system.work.generate (send_to_rep1->hash ()))
 | 
				
			||||||
												.build ();
 | 
											.build ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Receive by Rep2
 | 
						// Receive by Rep2
 | 
				
			||||||
	std::shared_ptr<nano::block> receive_rep2 = builder
 | 
						auto receive_rep2 = builder
 | 
				
			||||||
												.state ()
 | 
											.state ()
 | 
				
			||||||
												.account (keys_rep2.pub)
 | 
											.account (keys_rep2.pub)
 | 
				
			||||||
												.previous (0)
 | 
											.previous (0)
 | 
				
			||||||
												.representative (keys_rep2.pub)
 | 
											.representative (keys_rep2.pub)
 | 
				
			||||||
												.balance (searching_node.minimum_principal_weight () * 2)
 | 
											.balance (rep_weight)
 | 
				
			||||||
												.link (send_to_rep2->hash ())
 | 
											.link (send_to_rep2->hash ())
 | 
				
			||||||
												.sign (keys_rep2.prv, keys_rep2.pub)
 | 
											.sign (keys_rep2.prv, keys_rep2.pub)
 | 
				
			||||||
												.work (*system.work.generate (keys_rep2.pub))
 | 
											.work (*system.work.generate (keys_rep2.pub))
 | 
				
			||||||
												.build ();
 | 
											.build ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto transaction = searching_node.ledger.tx_begin_write ();
 | 
							auto transaction = searching_node.ledger.tx_begin_write ();
 | 
				
			||||||
		ASSERT_EQ (nano::block_status::progress, searching_node.ledger.process (transaction, send_to_rep1));
 | 
							ASSERT_EQ (nano::block_status::progress, searching_node.ledger.process (transaction, send_to_rep1));
 | 
				
			||||||
| 
						 | 
					@ -188,11 +191,12 @@ TEST (rep_crawler, rep_remove)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Ensure Rep1 is found by the rep_crawler after receiving a vote from it
 | 
						// Ensure Rep1 is found by the rep_crawler after receiving a vote from it
 | 
				
			||||||
	auto vote_rep1 = std::make_shared<nano::vote> (keys_rep1.pub, keys_rep1.prv, 0, 0, std::vector<nano::block_hash>{ nano::dev::genesis->hash () });
 | 
						auto vote_rep1 = std::make_shared<nano::vote> (keys_rep1.pub, keys_rep1.prv, 0, 0, std::vector<nano::block_hash>{ nano::dev::genesis->hash () });
 | 
				
			||||||
 | 
						ASSERT_LE (searching_node.minimum_principal_weight (), rep_weight);
 | 
				
			||||||
	searching_node.rep_crawler.force_process (vote_rep1, channel_rep1);
 | 
						searching_node.rep_crawler.force_process (vote_rep1, channel_rep1);
 | 
				
			||||||
	ASSERT_TIMELY_EQ (5s, searching_node.rep_crawler.representative_count (), 1);
 | 
						ASSERT_TIMELY_EQ (5s, searching_node.rep_crawler.representative_count (), 1);
 | 
				
			||||||
	auto reps (searching_node.rep_crawler.representatives (1));
 | 
						auto reps (searching_node.rep_crawler.representatives (1));
 | 
				
			||||||
	ASSERT_EQ (1, reps.size ());
 | 
						ASSERT_EQ (1, reps.size ());
 | 
				
			||||||
	ASSERT_EQ (searching_node.minimum_principal_weight () * 2, searching_node.ledger.weight (reps[0].account));
 | 
						ASSERT_LE (searching_node.minimum_principal_weight (), searching_node.ledger.weight (reps[0].account));
 | 
				
			||||||
	ASSERT_EQ (keys_rep1.pub, reps[0].account);
 | 
						ASSERT_EQ (keys_rep1.pub, reps[0].account);
 | 
				
			||||||
	ASSERT_EQ (channel_rep1, reps[0].channel);
 | 
						ASSERT_EQ (channel_rep1, reps[0].channel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,7 +114,6 @@ TEST (vote_processor, weights)
 | 
				
			||||||
	auto & node (*system.nodes[0]);
 | 
						auto & node (*system.nodes[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Create representatives of different weight levels
 | 
						// Create representatives of different weight levels
 | 
				
			||||||
	// FIXME: Using `online_weight_minimum` because calculation of trended and online weight is broken when running tests
 | 
					 | 
				
			||||||
	auto const stake = node.config.online_weight_minimum.number ();
 | 
						auto const stake = node.config.online_weight_minimum.number ();
 | 
				
			||||||
	auto const level0 = stake / 5000; // 0.02%
 | 
						auto const level0 = stake / 5000; // 0.02%
 | 
				
			||||||
	auto const level1 = stake / 500; // 0.2%
 | 
						auto const level1 = stake / 500; // 0.2%
 | 
				
			||||||
| 
						 | 
					@ -142,10 +141,10 @@ TEST (vote_processor, weights)
 | 
				
			||||||
	node.stats.clear ();
 | 
						node.stats.clear ();
 | 
				
			||||||
	ASSERT_TIMELY (5s, node.stats.count (nano::stat::type::rep_tiers, nano::stat::detail::updated) >= 2);
 | 
						ASSERT_TIMELY (5s, node.stats.count (nano::stat::type::rep_tiers, nano::stat::detail::updated) >= 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ASSERT_EQ (node.rep_tiers.tier (key0.pub), nano::rep_tier::none);
 | 
						ASSERT_TIMELY_EQ (5s, node.rep_tiers.tier (key0.pub), nano::rep_tier::none);
 | 
				
			||||||
	ASSERT_EQ (node.rep_tiers.tier (key1.pub), nano::rep_tier::tier_1);
 | 
						ASSERT_TIMELY_EQ (5s, node.rep_tiers.tier (key1.pub), nano::rep_tier::tier_1);
 | 
				
			||||||
	ASSERT_EQ (node.rep_tiers.tier (key2.pub), nano::rep_tier::tier_2);
 | 
						ASSERT_TIMELY_EQ (5s, node.rep_tiers.tier (key2.pub), nano::rep_tier::tier_2);
 | 
				
			||||||
	ASSERT_EQ (node.rep_tiers.tier (nano::dev::genesis_key.pub), nano::rep_tier::tier_3);
 | 
						ASSERT_TIMELY_EQ (5s, node.rep_tiers.tier (nano::dev::genesis_key.pub), nano::rep_tier::tier_3);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Issue that tracks last changes on this test: https://github.com/nanocurrency/nano-node/issues/3485
 | 
					// Issue that tracks last changes on this test: https://github.com/nanocurrency/nano-node/issues/3485
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
#include <nano/lib/jsonconfig.hpp>
 | 
					#include <nano/lib/jsonconfig.hpp>
 | 
				
			||||||
#include <nano/lib/work_version.hpp>
 | 
					#include <nano/lib/work_version.hpp>
 | 
				
			||||||
#include <nano/node/active_elections.hpp>
 | 
					#include <nano/node/active_elections.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/node/telemetry.hpp>
 | 
					#include <nano/node/telemetry.hpp>
 | 
				
			||||||
#include <nano/node/transport/fake.hpp>
 | 
					#include <nano/node/transport/fake.hpp>
 | 
				
			||||||
#include <nano/node/vote_router.hpp>
 | 
					#include <nano/node/vote_router.hpp>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,11 @@ void force_nano_dev_network ()
 | 
				
			||||||
	nano::network_constants::set_active_network (nano::networks::nano_dev_network);
 | 
						nano::network_constants::set_active_network (nano::networks::nano_dev_network);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool is_dev_run ()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nano::network_constants::get_active_network () == nano::networks::nano_dev_network;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool running_within_valgrind ()
 | 
					bool running_within_valgrind ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return (RUNNING_ON_VALGRIND > 0);
 | 
						return (RUNNING_ON_VALGRIND > 0);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ consteval bool is_asan_build ()
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
// GCC builds
 | 
						// GCC builds
 | 
				
			||||||
#elif defined(__SANITIZE_ADDRESS__)
 | 
					#elif defined(__SANITIZE_ADDRESS__)
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ consteval bool is_tsan_build ()
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
// GCC builds
 | 
						// GCC builds
 | 
				
			||||||
#elif defined(__SANITIZE_THREAD__)
 | 
					#elif defined(__SANITIZE_THREAD__)
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
| 
						 | 
					@ -105,6 +105,9 @@ bool slow_instrumentation ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Set the active network to the dev network */
 | 
					/** Set the active network to the dev network */
 | 
				
			||||||
void force_nano_dev_network ();
 | 
					void force_nano_dev_network ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Checks that we are running in test mode */
 | 
				
			||||||
 | 
					bool is_dev_run ();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace nano
 | 
					namespace nano
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -205,6 +205,11 @@ public:
 | 
				
			||||||
		active_network = network_a;
 | 
							active_network = network_a;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static nano::networks get_active_network ()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return active_network;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Optionally called on startup to override the global active network.
 | 
						 * Optionally called on startup to override the global active network.
 | 
				
			||||||
	 * If not called, the compile-time option will be used.
 | 
						 * If not called, the compile-time option will be used.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,6 +81,7 @@ enum class type
 | 
				
			||||||
	signal_manager,
 | 
						signal_manager,
 | 
				
			||||||
	peer_history,
 | 
						peer_history,
 | 
				
			||||||
	message_processor,
 | 
						message_processor,
 | 
				
			||||||
 | 
						online_reps,
 | 
				
			||||||
	local_block_broadcaster,
 | 
						local_block_broadcaster,
 | 
				
			||||||
	monitor,
 | 
						monitor,
 | 
				
			||||||
	confirming_set,
 | 
						confirming_set,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -112,6 +112,7 @@ enum class type
 | 
				
			||||||
	message_processor_overfill,
 | 
						message_processor_overfill,
 | 
				
			||||||
	message_processor_type,
 | 
						message_processor_type,
 | 
				
			||||||
	process_confirmed,
 | 
						process_confirmed,
 | 
				
			||||||
 | 
						online_reps,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_last // Must be the last enum
 | 
						_last // Must be the last enum
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -609,6 +610,15 @@ enum class detail
 | 
				
			||||||
	rollback_skipped,
 | 
						rollback_skipped,
 | 
				
			||||||
	loop_scan,
 | 
						loop_scan,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// online_reps
 | 
				
			||||||
 | 
						trim_trend,
 | 
				
			||||||
 | 
						sanitize_old,
 | 
				
			||||||
 | 
						sanitize_future,
 | 
				
			||||||
 | 
						sample,
 | 
				
			||||||
 | 
						rep_new,
 | 
				
			||||||
 | 
						rep_update,
 | 
				
			||||||
 | 
						update_online,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// error codes
 | 
						// error codes
 | 
				
			||||||
	no_buffer_space,
 | 
						no_buffer_space,
 | 
				
			||||||
	timed_out,
 | 
						timed_out,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -184,6 +184,9 @@ std::string nano::thread_role::get_string (nano::thread_role::name role)
 | 
				
			||||||
		case nano::thread_role::name::vote_router:
 | 
							case nano::thread_role::name::vote_router:
 | 
				
			||||||
			thread_role_name_string = "Vote router";
 | 
								thread_role_name_string = "Vote router";
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case nano::thread_role::name::online_reps:
 | 
				
			||||||
 | 
								thread_role_name_string = "Online reps";
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case nano::thread_role::name::monitor:
 | 
							case nano::thread_role::name::monitor:
 | 
				
			||||||
			thread_role_name_string = "Monitor";
 | 
								thread_role_name_string = "Monitor";
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,6 +66,7 @@ enum class name
 | 
				
			||||||
	port_mapping,
 | 
						port_mapping,
 | 
				
			||||||
	stats,
 | 
						stats,
 | 
				
			||||||
	vote_router,
 | 
						vote_router,
 | 
				
			||||||
 | 
						online_reps,
 | 
				
			||||||
	monitor,
 | 
						monitor,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@
 | 
				
			||||||
#include <nano/node/ipc/ipc_server.hpp>
 | 
					#include <nano/node/ipc/ipc_server.hpp>
 | 
				
			||||||
#include <nano/node/json_handler.hpp>
 | 
					#include <nano/node/json_handler.hpp>
 | 
				
			||||||
#include <nano/node/node.hpp>
 | 
					#include <nano/node/node.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/node/transport/inproc.hpp>
 | 
					#include <nano/node/transport/inproc.hpp>
 | 
				
			||||||
#include <nano/secure/ledger.hpp>
 | 
					#include <nano/secure/ledger.hpp>
 | 
				
			||||||
#include <nano/secure/ledger_set_any.hpp>
 | 
					#include <nano/secure/ledger_set_any.hpp>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
#include <nano/node/confirming_set.hpp>
 | 
					#include <nano/node/confirming_set.hpp>
 | 
				
			||||||
#include <nano/node/election.hpp>
 | 
					#include <nano/node/election.hpp>
 | 
				
			||||||
#include <nano/node/node.hpp>
 | 
					#include <nano/node/node.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/node/repcrawler.hpp>
 | 
					#include <nano/node/repcrawler.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/component.hpp>
 | 
					#include <nano/node/scheduler/component.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/priority.hpp>
 | 
					#include <nano/node/scheduler/priority.hpp>
 | 
				
			||||||
| 
						 | 
					@ -405,6 +406,7 @@ nano::election_insertion_result nano::active_elections::insert (std::shared_ptr<
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			result.inserted = true;
 | 
								result.inserted = true;
 | 
				
			||||||
			auto observe_rep_cb = [&node = node] (auto const & rep_a) {
 | 
								auto observe_rep_cb = [&node = node] (auto const & rep_a) {
 | 
				
			||||||
 | 
									// TODO: Is this neccessary? Move this outside of the election class
 | 
				
			||||||
				// Representative is defined as online if replying to live votes or rep_crawler queries
 | 
									// Representative is defined as online if replying to live votes or rep_crawler queries
 | 
				
			||||||
				node.online_reps.observe (rep_a);
 | 
									node.online_reps.observe (rep_a);
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@
 | 
				
			||||||
#include <nano/node/local_vote_history.hpp>
 | 
					#include <nano/node/local_vote_history.hpp>
 | 
				
			||||||
#include <nano/node/network.hpp>
 | 
					#include <nano/node/network.hpp>
 | 
				
			||||||
#include <nano/node/node.hpp>
 | 
					#include <nano/node/node.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/node/vote_generator.hpp>
 | 
					#include <nano/node/vote_generator.hpp>
 | 
				
			||||||
#include <nano/node/vote_router.hpp>
 | 
					#include <nano/node/vote_router.hpp>
 | 
				
			||||||
#include <nano/secure/ledger.hpp>
 | 
					#include <nano/secure/ledger.hpp>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@
 | 
				
			||||||
#include <nano/node/json_handler.hpp>
 | 
					#include <nano/node/json_handler.hpp>
 | 
				
			||||||
#include <nano/node/node.hpp>
 | 
					#include <nano/node/node.hpp>
 | 
				
			||||||
#include <nano/node/node_rpc_config.hpp>
 | 
					#include <nano/node/node_rpc_config.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/node/telemetry.hpp>
 | 
					#include <nano/node/telemetry.hpp>
 | 
				
			||||||
#include <nano/secure/ledger.hpp>
 | 
					#include <nano/secure/ledger.hpp>
 | 
				
			||||||
#include <nano/secure/ledger_set_any.hpp>
 | 
					#include <nano/secure/ledger_set_any.hpp>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,7 @@
 | 
				
			||||||
#include <nano/node/message_processor.hpp>
 | 
					#include <nano/node/message_processor.hpp>
 | 
				
			||||||
#include <nano/node/monitor.hpp>
 | 
					#include <nano/node/monitor.hpp>
 | 
				
			||||||
#include <nano/node/node.hpp>
 | 
					#include <nano/node/node.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/node/peer_history.hpp>
 | 
					#include <nano/node/peer_history.hpp>
 | 
				
			||||||
#include <nano/node/portmapping.hpp>
 | 
					#include <nano/node/portmapping.hpp>
 | 
				
			||||||
#include <nano/node/request_aggregator.hpp>
 | 
					#include <nano/node/request_aggregator.hpp>
 | 
				
			||||||
| 
						 | 
					@ -138,7 +139,8 @@ nano::node::node (std::shared_ptr<boost::asio::io_context> io_ctx_a, std::filesy
 | 
				
			||||||
	rep_crawler (config.rep_crawler, *this),
 | 
						rep_crawler (config.rep_crawler, *this),
 | 
				
			||||||
	rep_tiers{ ledger, network_params, online_reps, stats, logger },
 | 
						rep_tiers{ ledger, network_params, online_reps, stats, logger },
 | 
				
			||||||
	warmed_up (0),
 | 
						warmed_up (0),
 | 
				
			||||||
	online_reps (ledger, config),
 | 
						online_reps_impl{ std::make_unique<nano::online_reps> (config, ledger, stats, logger) },
 | 
				
			||||||
 | 
						online_reps{ *online_reps_impl },
 | 
				
			||||||
	history_impl{ std::make_unique<nano::local_vote_history> (config.network_params.voting) },
 | 
						history_impl{ std::make_unique<nano::local_vote_history> (config.network_params.voting) },
 | 
				
			||||||
	history{ *history_impl },
 | 
						history{ *history_impl },
 | 
				
			||||||
	vote_uniquer{},
 | 
						vote_uniquer{},
 | 
				
			||||||
| 
						 | 
					@ -333,10 +335,12 @@ nano::node::node (std::shared_ptr<boost::asio::io_context> io_ctx_a, std::filesy
 | 
				
			||||||
		logger.info (nano::log::type::node, "Work peers: {}", config.work_peers.size ());
 | 
							logger.info (nano::log::type::node, "Work peers: {}", config.work_peers.size ());
 | 
				
			||||||
		logger.info (nano::log::type::node, "Node ID: {}", node_id.pub.to_node_id ());
 | 
							logger.info (nano::log::type::node, "Node ID: {}", node_id.pub.to_node_id ());
 | 
				
			||||||
		logger.info (nano::log::type::node, "Number of buckets: {}", bucketing.size ());
 | 
							logger.info (nano::log::type::node, "Number of buckets: {}", bucketing.size ());
 | 
				
			||||||
 | 
							logger.info (nano::log::type::node, "Genesis block: {}", config.network_params.ledger.genesis->hash ().to_string ());
 | 
				
			||||||
 | 
							logger.info (nano::log::type::node, "Genesis account: {}", config.network_params.ledger.genesis->account ().to_account ());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!work_generation_enabled ())
 | 
							if (!work_generation_enabled ())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			logger.info (nano::log::type::node, "Work generation is disabled");
 | 
								logger.warn (nano::log::type::node, "Work generation is disabled");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		logger.info (nano::log::type::node, "Outbound bandwidth limit: {} bytes/s, burst ratio: {}",
 | 
							logger.info (nano::log::type::node, "Outbound bandwidth limit: {} bytes/s, burst ratio: {}",
 | 
				
			||||||
| 
						 | 
					@ -587,8 +591,6 @@ void nano::node::process_local_async (std::shared_ptr<nano::block> const & block
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::node::start ()
 | 
					void nano::node::start ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	long_inactivity_cleanup ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	network.start ();
 | 
						network.start ();
 | 
				
			||||||
	message_processor.start ();
 | 
						message_processor.start ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -604,8 +606,6 @@ void nano::node::start ()
 | 
				
			||||||
		rep_crawler.start ();
 | 
							rep_crawler.start ();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ongoing_online_weight_calculation_queue ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bool tcp_enabled = false;
 | 
						bool tcp_enabled = false;
 | 
				
			||||||
	if (config.tcp_incoming_connections_max > 0 && !(flags.disable_bootstrap_listener && flags.disable_tcp_realtime))
 | 
						if (config.tcp_incoming_connections_max > 0 && !(flags.disable_bootstrap_listener && flags.disable_tcp_realtime))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -659,6 +659,7 @@ void nano::node::start ()
 | 
				
			||||||
	local_block_broadcaster.start ();
 | 
						local_block_broadcaster.start ();
 | 
				
			||||||
	peer_history.start ();
 | 
						peer_history.start ();
 | 
				
			||||||
	vote_router.start ();
 | 
						vote_router.start ();
 | 
				
			||||||
 | 
						online_reps.start ();
 | 
				
			||||||
	monitor.start ();
 | 
						monitor.start ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	add_initial_peers ();
 | 
						add_initial_peers ();
 | 
				
			||||||
| 
						 | 
					@ -675,7 +676,7 @@ void nano::node::stop ()
 | 
				
			||||||
	logger.info (nano::log::type::node, "Node stopping...");
 | 
						logger.info (nano::log::type::node, "Node stopping...");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tcp_listener.stop ();
 | 
						tcp_listener.stop ();
 | 
				
			||||||
 | 
						online_reps.stop ();
 | 
				
			||||||
	vote_router.stop ();
 | 
						vote_router.stop ();
 | 
				
			||||||
	peer_history.stop ();
 | 
						peer_history.stop ();
 | 
				
			||||||
	// Cancels ongoing work generation tasks, which may be blocking other threads
 | 
						// Cancels ongoing work generation tasks, which may be blocking other threads
 | 
				
			||||||
| 
						 | 
					@ -772,26 +773,6 @@ nano::uint128_t nano::node::minimum_principal_weight ()
 | 
				
			||||||
	return online_reps.trended () / network_params.network.principal_weight_factor;
 | 
						return online_reps.trended () / network_params.network.principal_weight_factor;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::node::long_inactivity_cleanup ()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	bool perform_cleanup = false;
 | 
					 | 
				
			||||||
	auto const transaction = store.tx_begin_write ();
 | 
					 | 
				
			||||||
	if (store.online_weight.count (transaction) > 0)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto sample (store.online_weight.rbegin (transaction));
 | 
					 | 
				
			||||||
		auto n (store.online_weight.rend (transaction));
 | 
					 | 
				
			||||||
		debug_assert (sample != n);
 | 
					 | 
				
			||||||
		auto const one_week_ago = static_cast<std::size_t> ((std::chrono::system_clock::now () - std::chrono::hours (7 * 24)).time_since_epoch ().count ());
 | 
					 | 
				
			||||||
		perform_cleanup = sample->first < one_week_ago;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (perform_cleanup)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		store.online_weight.clear (transaction);
 | 
					 | 
				
			||||||
		store.peer.clear (transaction);
 | 
					 | 
				
			||||||
		logger.info (nano::log::type::node, "Removed records of peers and online weight after a long period of inactivity");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::node::backup_wallet ()
 | 
					void nano::node::backup_wallet ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto transaction (wallets.tx_begin_read ());
 | 
						auto transaction (wallets.tx_begin_read ());
 | 
				
			||||||
| 
						 | 
					@ -1061,28 +1042,11 @@ bool nano::node::block_confirmed_or_being_confirmed (nano::block_hash const & ha
 | 
				
			||||||
	return block_confirmed_or_being_confirmed (ledger.tx_begin_read (), hash_a);
 | 
						return block_confirmed_or_being_confirmed (ledger.tx_begin_read (), hash_a);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::node::ongoing_online_weight_calculation_queue ()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	std::weak_ptr<nano::node> node_w (shared_from_this ());
 | 
					 | 
				
			||||||
	workers.post_delayed ((std::chrono::seconds (network_params.node.weight_period)), [node_w] () {
 | 
					 | 
				
			||||||
		if (auto node_l = node_w.lock ())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			node_l->ongoing_online_weight_calculation ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool nano::node::online () const
 | 
					bool nano::node::online () const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return rep_crawler.total_weight () > online_reps.delta ();
 | 
						return rep_crawler.total_weight () > online_reps.delta ();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::node::ongoing_online_weight_calculation ()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	online_reps.sample ();
 | 
					 | 
				
			||||||
	ongoing_online_weight_calculation_queue ();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::shared_ptr<nano::node> nano::node::shared ()
 | 
					std::shared_ptr<nano::node> nano::node::shared ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return shared_from_this ();
 | 
						return shared_from_this ();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@
 | 
				
			||||||
#include <nano/node/node_observers.hpp>
 | 
					#include <nano/node/node_observers.hpp>
 | 
				
			||||||
#include <nano/node/nodeconfig.hpp>
 | 
					#include <nano/node/nodeconfig.hpp>
 | 
				
			||||||
#include <nano/node/online_reps.hpp>
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/portmapping.hpp>
 | 
				
			||||||
#include <nano/node/process_live_dispatcher.hpp>
 | 
					#include <nano/node/process_live_dispatcher.hpp>
 | 
				
			||||||
#include <nano/node/rep_tiers.hpp>
 | 
					#include <nano/node/rep_tiers.hpp>
 | 
				
			||||||
#include <nano/node/repcrawler.hpp>
 | 
					#include <nano/node/repcrawler.hpp>
 | 
				
			||||||
| 
						 | 
					@ -39,6 +40,7 @@ class message_processor;
 | 
				
			||||||
class monitor;
 | 
					class monitor;
 | 
				
			||||||
class node;
 | 
					class node;
 | 
				
			||||||
class telemetry;
 | 
					class telemetry;
 | 
				
			||||||
 | 
					class online_reps;
 | 
				
			||||||
class vote_processor;
 | 
					class vote_processor;
 | 
				
			||||||
class vote_cache_processor;
 | 
					class vote_cache_processor;
 | 
				
			||||||
class vote_router;
 | 
					class vote_router;
 | 
				
			||||||
| 
						 | 
					@ -112,8 +114,6 @@ public:
 | 
				
			||||||
	bool block_confirmed_or_being_confirmed (nano::block_hash const &);
 | 
						bool block_confirmed_or_being_confirmed (nano::block_hash const &);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void do_rpc_callback (boost::asio::ip::tcp::resolver::iterator i_a, std::string const &, uint16_t, std::shared_ptr<std::string> const &, std::shared_ptr<std::string> const &, std::shared_ptr<boost::asio::ip::tcp::resolver> const &);
 | 
						void do_rpc_callback (boost::asio::ip::tcp::resolver::iterator i_a, std::string const &, uint16_t, std::shared_ptr<std::string> const &, std::shared_ptr<std::string> const &, std::shared_ptr<boost::asio::ip::tcp::resolver> const &);
 | 
				
			||||||
	void ongoing_online_weight_calculation ();
 | 
					 | 
				
			||||||
	void ongoing_online_weight_calculation_queue ();
 | 
					 | 
				
			||||||
	bool online () const;
 | 
						bool online () const;
 | 
				
			||||||
	bool init_error () const;
 | 
						bool init_error () const;
 | 
				
			||||||
	std::pair<uint64_t, std::unordered_map<nano::account, nano::uint128_t>> get_bootstrap_weights () const;
 | 
						std::pair<uint64_t, std::unordered_map<nano::account, nano::uint128_t>> get_bootstrap_weights () const;
 | 
				
			||||||
| 
						 | 
					@ -176,7 +176,8 @@ public:
 | 
				
			||||||
	nano::bucketing & bucketing;
 | 
						nano::bucketing & bucketing;
 | 
				
			||||||
	std::unique_ptr<nano::active_elections> active_impl;
 | 
						std::unique_ptr<nano::active_elections> active_impl;
 | 
				
			||||||
	nano::active_elections & active;
 | 
						nano::active_elections & active;
 | 
				
			||||||
	nano::online_reps online_reps;
 | 
						std::unique_ptr<nano::online_reps> online_reps_impl;
 | 
				
			||||||
 | 
						nano::online_reps & online_reps;
 | 
				
			||||||
	nano::rep_crawler rep_crawler;
 | 
						nano::rep_crawler rep_crawler;
 | 
				
			||||||
	nano::rep_tiers rep_tiers;
 | 
						nano::rep_tiers rep_tiers;
 | 
				
			||||||
	unsigned warmed_up;
 | 
						unsigned warmed_up;
 | 
				
			||||||
| 
						 | 
					@ -239,8 +240,6 @@ public: // Testing convenience functions
 | 
				
			||||||
	nano::uint128_t balance (nano::account const &);
 | 
						nano::uint128_t balance (nano::account const &);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	void long_inactivity_cleanup ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	static std::string make_logger_identifier (nano::keypair const & node_id);
 | 
						static std::string make_logger_identifier (nano::keypair const & node_id);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,105 +1,264 @@
 | 
				
			||||||
 | 
					#include <nano/lib/config.hpp>
 | 
				
			||||||
 | 
					#include <nano/lib/thread_roles.hpp>
 | 
				
			||||||
 | 
					#include <nano/lib/timer.hpp>
 | 
				
			||||||
#include <nano/node/nodeconfig.hpp>
 | 
					#include <nano/node/nodeconfig.hpp>
 | 
				
			||||||
#include <nano/node/online_reps.hpp>
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/secure/ledger.hpp>
 | 
					#include <nano/secure/ledger.hpp>
 | 
				
			||||||
#include <nano/store/component.hpp>
 | 
					#include <nano/store/component.hpp>
 | 
				
			||||||
#include <nano/store/online_weight.hpp>
 | 
					#include <nano/store/online_weight.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::online_reps::online_reps (nano::ledger & ledger_a, nano::node_config const & config_a) :
 | 
					nano::online_reps::online_reps (nano::node_config const & config_a, nano::ledger & ledger_a, nano::stats & stats_a, nano::logger & logger_a) :
 | 
				
			||||||
 | 
						config{ config_a },
 | 
				
			||||||
	ledger{ ledger_a },
 | 
						ledger{ ledger_a },
 | 
				
			||||||
	config{ config_a }
 | 
						stats{ stats_a },
 | 
				
			||||||
 | 
						logger{ logger_a }
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!ledger.store.init_error ())
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nano::online_reps::~online_reps ()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						debug_assert (!thread.joinable ());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void nano::online_reps::start ()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						debug_assert (!thread.joinable ());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto transaction (ledger.store.tx_begin_read ());
 | 
							auto transaction = ledger.tx_begin_write (nano::store::writer::online_weight);
 | 
				
			||||||
		trended_m = calculate_trend (transaction);
 | 
							sanitize_trended (transaction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto trended_l = calculate_trended (transaction);
 | 
				
			||||||
 | 
							nano::lock_guard<nano::mutex> lock{ mutex };
 | 
				
			||||||
 | 
							cached_trended = trended_l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							logger.info (nano::log::type::online_reps, "Initial trended weight: {}", fmt::streamed (cached_trended));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						thread = std::thread ([this] () {
 | 
				
			||||||
 | 
							nano::thread_role::set (nano::thread_role::name::online_reps);
 | 
				
			||||||
 | 
							run ();
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void nano::online_reps::stop ()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							nano::lock_guard<nano::mutex> lock{ mutex };
 | 
				
			||||||
 | 
							stopped = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						condition.notify_all ();
 | 
				
			||||||
 | 
						if (thread.joinable ())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							thread.join ();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::online_reps::observe (nano::account const & rep_a)
 | 
					void nano::online_reps::observe (nano::account const & rep)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (ledger.weight (rep_a) > 0)
 | 
						if (ledger.weight (rep) > config.representative_vote_weight_minimum)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		nano::lock_guard<nano::mutex> lock{ mutex };
 | 
							nano::lock_guard<nano::mutex> lock{ mutex };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto now = std::chrono::steady_clock::now ();
 | 
							auto now = std::chrono::steady_clock::now ();
 | 
				
			||||||
		auto new_insert = reps.get<tag_account> ().erase (rep_a) == 0;
 | 
							auto new_insert = reps.get<tag_account> ().erase (rep) == 0;
 | 
				
			||||||
		reps.insert ({ now, rep_a });
 | 
							reps.insert ({ now, rep });
 | 
				
			||||||
		auto cutoff = reps.get<tag_time> ().lower_bound (now - std::chrono::seconds (config.network_params.node.weight_period));
 | 
					
 | 
				
			||||||
		auto trimmed = reps.get<tag_time> ().begin () != cutoff;
 | 
							stats.inc (nano::stat::type::online_reps, new_insert ? nano::stat::detail::rep_new : nano::stat::detail::rep_update);
 | 
				
			||||||
		reps.get<tag_time> ().erase (reps.get<tag_time> ().begin (), cutoff);
 | 
					
 | 
				
			||||||
 | 
							bool trimmed = trim ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Update current online weight if anything changed
 | 
				
			||||||
		if (new_insert || trimmed)
 | 
							if (new_insert || trimmed)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			online_m = calculate_online ();
 | 
								stats.inc (nano::stat::type::online_reps, nano::stat::detail::update_online);
 | 
				
			||||||
 | 
								cached_online = calculate_online ();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool nano::online_reps::trim ()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						debug_assert (!mutex.try_lock ());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto now = std::chrono::steady_clock::now ();
 | 
				
			||||||
 | 
						auto cutoff = reps.get<tag_time> ().lower_bound (now - config.network_params.node.weight_interval);
 | 
				
			||||||
 | 
						auto trimmed = reps.get<tag_time> ().begin () != cutoff;
 | 
				
			||||||
 | 
						reps.get<tag_time> ().erase (reps.get<tag_time> ().begin (), cutoff);
 | 
				
			||||||
 | 
						return trimmed;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void nano::online_reps::run ()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nano::unique_lock<nano::mutex> lock{ mutex };
 | 
				
			||||||
 | 
						while (!stopped)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// Set next time point explicitly to ensure that we don't sample too early
 | 
				
			||||||
 | 
							auto next = std::chrono::steady_clock::now () + config.network_params.node.weight_interval;
 | 
				
			||||||
 | 
							condition.wait_until (lock, next, [this, next] {
 | 
				
			||||||
 | 
								return stopped || std::chrono::steady_clock::now () >= next;
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
							if (!stopped)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								lock.unlock ();
 | 
				
			||||||
 | 
								sample ();
 | 
				
			||||||
 | 
								lock.lock ();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::online_reps::sample ()
 | 
					void nano::online_reps::sample ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::unique_lock<nano::mutex> lock{ mutex };
 | 
						stats.inc (nano::stat::type::online_reps, nano::stat::detail::sample);
 | 
				
			||||||
	nano::uint128_t online_l = online_m;
 | 
					
 | 
				
			||||||
	lock.unlock ();
 | 
						auto transaction = ledger.tx_begin_write (nano::store::writer::online_weight);
 | 
				
			||||||
	nano::uint128_t trend_l;
 | 
					
 | 
				
			||||||
 | 
						// Remove old records from the database
 | 
				
			||||||
 | 
						trim_trended (transaction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Put current online weight sample into the database
 | 
				
			||||||
 | 
						ledger.store.online_weight.put (transaction, nano::seconds_since_epoch (), online ());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Update current trended weight
 | 
				
			||||||
 | 
						auto trended_l = calculate_trended (transaction);
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto transaction = ledger.store.tx_begin_write ();
 | 
							nano::lock_guard<nano::mutex> lock{ mutex };
 | 
				
			||||||
		// Discard oldest entries
 | 
							cached_trended = trended_l;
 | 
				
			||||||
		while (ledger.store.online_weight.count (transaction) >= config.network_params.node.max_weight_samples)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			auto oldest (ledger.store.online_weight.begin (transaction));
 | 
					 | 
				
			||||||
			debug_assert (oldest != ledger.store.online_weight.end (transaction));
 | 
					 | 
				
			||||||
			ledger.store.online_weight.del (transaction, oldest->first);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		ledger.store.online_weight.put (transaction, std::chrono::system_clock::now ().time_since_epoch ().count (), online_l);
 | 
					 | 
				
			||||||
		trend_l = calculate_trend (transaction);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	lock.lock ();
 | 
						logger.info (nano::log::type::online_reps, "Updated trended weight: {}", fmt::streamed (trended_l));
 | 
				
			||||||
	trended_m = trend_l;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::uint128_t nano::online_reps::calculate_online () const
 | 
					nano::uint128_t nano::online_reps::calculate_online () const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::uint128_t current;
 | 
						debug_assert (!mutex.try_lock ());
 | 
				
			||||||
	for (auto & i : reps)
 | 
						return std::accumulate (reps.begin (), reps.end (), nano::uint128_t{ 0 }, [this] (nano::uint128_t current, rep_info const & info) {
 | 
				
			||||||
	{
 | 
							return current + ledger.weight (info.account);
 | 
				
			||||||
		current += ledger.weight (i.account);
 | 
						});
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return current;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::uint128_t nano::online_reps::calculate_trend (store::transaction & transaction_a) const
 | 
					void nano::online_reps::trim_trended (nano::store::write_transaction const & transaction)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto const now = std::chrono::system_clock::now ();
 | 
				
			||||||
 | 
						auto const cutoff = now - config.network_params.node.weight_cutoff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::deque<nano::store::online_weight::iterator::value_type> to_remove;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto it = ledger.store.online_weight.begin (transaction); it != ledger.store.online_weight.end (transaction); ++it)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto tstamp = nano::from_seconds_since_epoch (it->first);
 | 
				
			||||||
 | 
							if (tstamp < cutoff)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								stats.inc (nano::stat::type::online_reps, nano::stat::detail::trim_trend);
 | 
				
			||||||
 | 
								to_remove.push_back (*it);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								break; // Entries are ordered by timestamp, so break early
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Remove entries after iterating to avoid iterator invalidation
 | 
				
			||||||
 | 
						for (auto const & entry : to_remove)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ledger.store.online_weight.del (transaction, entry.first);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Ensure that all remaining entries are within the expected range
 | 
				
			||||||
 | 
						debug_assert (verify_consistency (transaction, now, cutoff));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void nano::online_reps::sanitize_trended (nano::store::write_transaction const & transaction)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto const now = std::chrono::system_clock::now ();
 | 
				
			||||||
 | 
						auto const cutoff = now - config.network_params.node.weight_cutoff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t removed_old = 0, removed_future = 0;
 | 
				
			||||||
 | 
						std::deque<nano::store::online_weight::iterator::value_type> to_remove;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto it = ledger.store.online_weight.begin (transaction); it != ledger.store.online_weight.end (transaction); ++it)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto tstamp = nano::from_seconds_since_epoch (it->first);
 | 
				
			||||||
 | 
							if (tstamp < cutoff)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								stats.inc (nano::stat::type::online_reps, nano::stat::detail::sanitize_old);
 | 
				
			||||||
 | 
								to_remove.push_back (*it);
 | 
				
			||||||
 | 
								++removed_old;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (tstamp > now)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								stats.inc (nano::stat::type::online_reps, nano::stat::detail::sanitize_future);
 | 
				
			||||||
 | 
								to_remove.push_back (*it);
 | 
				
			||||||
 | 
								++removed_future;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Remove entries after iterating to avoid iterator invalidation
 | 
				
			||||||
 | 
						for (auto const & entry : to_remove)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ledger.store.online_weight.del (transaction, entry.first);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logger.debug (nano::log::type::online_reps, "Sanitized online weight trend, remaining entries: {}, removed: {} (old: {}, future: {})",
 | 
				
			||||||
 | 
						ledger.store.online_weight.count (transaction),
 | 
				
			||||||
 | 
						removed_old + removed_future,
 | 
				
			||||||
 | 
						removed_old,
 | 
				
			||||||
 | 
						removed_future);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Ensure that all remaining entries are within the expected range
 | 
				
			||||||
 | 
						debug_assert (verify_consistency (transaction, now, cutoff));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool nano::online_reps::verify_consistency (nano::store::write_transaction const & transaction, std::chrono::system_clock::time_point now, std::chrono::system_clock::time_point cutoff) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						for (auto it = ledger.store.online_weight.begin (transaction); it != ledger.store.online_weight.end (transaction); ++it)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto tstamp = nano::from_seconds_since_epoch (it->first);
 | 
				
			||||||
 | 
							if (tstamp < cutoff || tstamp > now)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nano::uint128_t nano::online_reps::calculate_trended (nano::store::transaction const & transaction) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	std::vector<nano::uint128_t> items;
 | 
						std::vector<nano::uint128_t> items;
 | 
				
			||||||
	items.reserve (config.network_params.node.max_weight_samples + 1);
 | 
						for (auto it = ledger.store.online_weight.begin (transaction); it != ledger.store.online_weight.end (transaction); ++it)
 | 
				
			||||||
	items.push_back (config.online_weight_minimum.number ());
 | 
					 | 
				
			||||||
	for (auto i (ledger.store.online_weight.begin (transaction_a)), n (ledger.store.online_weight.end (transaction_a)); i != n; ++i)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		items.push_back (i->second.number ());
 | 
							items.push_back (it->second.number ());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	nano::uint128_t result;
 | 
						if (!items.empty ())
 | 
				
			||||||
	// Pick median value for our target vote weight
 | 
						{
 | 
				
			||||||
	auto median_idx = items.size () / 2;
 | 
							// Pick median value for our target vote weight
 | 
				
			||||||
	nth_element (items.begin (), items.begin () + median_idx, items.end ());
 | 
							auto median_idx = items.size () / 2;
 | 
				
			||||||
	result = items[median_idx];
 | 
							std::nth_element (items.begin (), items.begin () + median_idx, items.end ());
 | 
				
			||||||
	return result;
 | 
							return items[median_idx];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::uint128_t nano::online_reps::trended () const
 | 
					nano::uint128_t nano::online_reps::trended () const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::lock_guard<nano::mutex> lock{ mutex };
 | 
						nano::lock_guard<nano::mutex> lock{ mutex };
 | 
				
			||||||
	return trended_m;
 | 
						return std::max (cached_trended, config.online_weight_minimum.number ());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::uint128_t nano::online_reps::online () const
 | 
					nano::uint128_t nano::online_reps::online () const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::lock_guard<nano::mutex> lock{ mutex };
 | 
						nano::lock_guard<nano::mutex> lock{ mutex };
 | 
				
			||||||
	return online_m;
 | 
						return cached_online;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::uint128_t nano::online_reps::delta () const
 | 
					nano::uint128_t nano::online_reps::delta () const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::lock_guard<nano::mutex> lock{ mutex };
 | 
						nano::lock_guard<nano::mutex> lock{ mutex };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Using a larger container to ensure maximum precision
 | 
						// Using a larger container to ensure maximum precision
 | 
				
			||||||
	auto weight = static_cast<nano::uint256_t> (std::max ({ online_m, trended_m, config.online_weight_minimum.number () }));
 | 
						auto weight = static_cast<nano::uint256_t> (std::max ({ cached_online, cached_trended, config.online_weight_minimum.number () }));
 | 
				
			||||||
	return ((weight * online_weight_quorum) / 100).convert_to<nano::uint128_t> ();
 | 
						auto delta = ((weight * online_weight_quorum) / 100).convert_to<nano::uint128_t> ();
 | 
				
			||||||
 | 
						release_assert (delta >= config.online_weight_minimum.number () / 100 * online_weight_quorum);
 | 
				
			||||||
 | 
						return delta;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::vector<nano::account> nano::online_reps::list ()
 | 
					std::vector<nano::account> nano::online_reps::list ()
 | 
				
			||||||
| 
						 | 
					@ -114,7 +273,20 @@ void nano::online_reps::clear ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::lock_guard<nano::mutex> lock{ mutex };
 | 
						nano::lock_guard<nano::mutex> lock{ mutex };
 | 
				
			||||||
	reps.clear ();
 | 
						reps.clear ();
 | 
				
			||||||
	online_m = 0;
 | 
						cached_online = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void nano::online_reps::force_online_weight (nano::uint128_t const & online_weight)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						release_assert (nano::is_dev_run ());
 | 
				
			||||||
 | 
						nano::lock_guard<nano::mutex> lock{ mutex };
 | 
				
			||||||
 | 
						cached_online = online_weight;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void nano::online_reps::force_sample ()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						release_assert (nano::is_dev_run ());
 | 
				
			||||||
 | 
						sample ();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::container_info nano::online_reps::container_info () const
 | 
					nano::container_info nano::online_reps::container_info () const
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
#include <nano/lib/numbers.hpp>
 | 
					#include <nano/lib/numbers.hpp>
 | 
				
			||||||
#include <nano/lib/numbers_templ.hpp>
 | 
					#include <nano/lib/numbers_templ.hpp>
 | 
				
			||||||
#include <nano/lib/utility.hpp>
 | 
					#include <nano/lib/utility.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/fwd.hpp>
 | 
				
			||||||
#include <nano/secure/common.hpp>
 | 
					#include <nano/secure/common.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <boost/multi_index/hashed_index.hpp>
 | 
					#include <boost/multi_index/hashed_index.hpp>
 | 
				
			||||||
| 
						 | 
					@ -11,26 +12,26 @@
 | 
				
			||||||
#include <boost/multi_index_container.hpp>
 | 
					#include <boost/multi_index_container.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <thread>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace mi = boost::multi_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace nano
 | 
					namespace nano
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
class ledger;
 | 
					 | 
				
			||||||
class node_config;
 | 
					 | 
				
			||||||
namespace store
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	class transaction;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Track online representatives and trend online weight */
 | 
					/** Track online representatives and trend online weight */
 | 
				
			||||||
class online_reps final
 | 
					class online_reps final
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	online_reps (nano::ledger & ledger_a, nano::node_config const & config_a);
 | 
						online_reps (nano::node_config const &, nano::ledger &, nano::stats &, nano::logger &);
 | 
				
			||||||
 | 
						~online_reps ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void start ();
 | 
				
			||||||
 | 
						void stop ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/** Add voting account \p rep_account to the set of online representatives */
 | 
						/** Add voting account \p rep_account to the set of online representatives */
 | 
				
			||||||
	void observe (nano::account const & rep_account);
 | 
						void observe (nano::account const & rep_account);
 | 
				
			||||||
	/** Called periodically to sample online weight */
 | 
					
 | 
				
			||||||
	void sample ();
 | 
					 | 
				
			||||||
	/** Returns the trended online stake */
 | 
						/** Returns the trended online stake */
 | 
				
			||||||
	nano::uint128_t trended () const;
 | 
						nano::uint128_t trended () const;
 | 
				
			||||||
	/** Returns the current online stake */
 | 
						/** Returns the current online stake */
 | 
				
			||||||
| 
						 | 
					@ -43,37 +44,61 @@ public:
 | 
				
			||||||
	nano::container_info container_info () const;
 | 
						nano::container_info container_info () const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
						// TODO: This should be in the network constants
 | 
				
			||||||
	static unsigned constexpr online_weight_quorum = 67;
 | 
						static unsigned constexpr online_weight_quorum = 67;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private: // Dependencies
 | 
				
			||||||
 | 
						nano::node_config const & config;
 | 
				
			||||||
 | 
						nano::ledger & ledger;
 | 
				
			||||||
 | 
						nano::stats & stats;
 | 
				
			||||||
 | 
						nano::logger & logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	class rep_info
 | 
						void run ();
 | 
				
			||||||
 | 
						/** Called periodically to sample online weight */
 | 
				
			||||||
 | 
						void sample ();
 | 
				
			||||||
 | 
						bool trim ();
 | 
				
			||||||
 | 
						/** Remove old records from the database */
 | 
				
			||||||
 | 
						void trim_trended (nano::store::write_transaction const &);
 | 
				
			||||||
 | 
						/** Iterate over all database samples and remove invalid records. This is meant to clean potential leftovers from previous versions. */
 | 
				
			||||||
 | 
						void sanitize_trended (nano::store::write_transaction const &);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nano::uint128_t calculate_trended (nano::store::transaction const &) const;
 | 
				
			||||||
 | 
						nano::uint128_t calculate_online () const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool verify_consistency (nano::store::write_transaction const &, std::chrono::system_clock::time_point now, std::chrono::system_clock::time_point cutoff) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						struct rep_info
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	public:
 | 
					 | 
				
			||||||
		std::chrono::steady_clock::time_point time;
 | 
							std::chrono::steady_clock::time_point time;
 | 
				
			||||||
		nano::account account;
 | 
							nano::account account;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	class tag_time
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	class tag_account
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	nano::uint128_t calculate_trend (store::transaction &) const;
 | 
					 | 
				
			||||||
	nano::uint128_t calculate_online () const;
 | 
					 | 
				
			||||||
	mutable nano::mutex mutex;
 | 
					 | 
				
			||||||
	nano::ledger & ledger;
 | 
					 | 
				
			||||||
	nano::node_config const & config;
 | 
					 | 
				
			||||||
	boost::multi_index_container<rep_info,
 | 
					 | 
				
			||||||
	boost::multi_index::indexed_by<
 | 
					 | 
				
			||||||
	boost::multi_index::ordered_non_unique<boost::multi_index::tag<tag_time>,
 | 
					 | 
				
			||||||
	boost::multi_index::member<rep_info, std::chrono::steady_clock::time_point, &rep_info::time>>,
 | 
					 | 
				
			||||||
	boost::multi_index::hashed_unique<boost::multi_index::tag<tag_account>,
 | 
					 | 
				
			||||||
	boost::multi_index::member<rep_info, nano::account, &rep_info::account>>>>
 | 
					 | 
				
			||||||
	reps;
 | 
					 | 
				
			||||||
	nano::uint128_t trended_m;
 | 
					 | 
				
			||||||
	nano::uint128_t online_m;
 | 
					 | 
				
			||||||
	nano::uint128_t minimum;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friend class election_quorum_minimum_update_weight_before_quorum_checks_Test;
 | 
						// clang-format off
 | 
				
			||||||
 | 
						class tag_time {};
 | 
				
			||||||
 | 
						class tag_account {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						using ordered_reps = boost::multi_index_container<rep_info,
 | 
				
			||||||
 | 
						mi::indexed_by<
 | 
				
			||||||
 | 
							mi::ordered_non_unique<mi::tag<tag_time>,
 | 
				
			||||||
 | 
								mi::member<rep_info, std::chrono::steady_clock::time_point, &rep_info::time>>,
 | 
				
			||||||
 | 
							mi::hashed_unique<mi::tag<tag_account>,
 | 
				
			||||||
 | 
								mi::member<rep_info, nano::account, &rep_info::account>>
 | 
				
			||||||
 | 
						>>;
 | 
				
			||||||
 | 
						// clang-format off
 | 
				
			||||||
 | 
						ordered_reps reps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nano::uint128_t cached_trended{0};
 | 
				
			||||||
 | 
						nano::uint128_t cached_online{0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool stopped{ false };
 | 
				
			||||||
 | 
						nano::condition_variable condition;
 | 
				
			||||||
 | 
						mutable nano::mutex mutex;
 | 
				
			||||||
 | 
						std::thread thread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public: // Only for tests
 | 
				
			||||||
 | 
						void force_online_weight (nano::uint128_t const & online_weight);
 | 
				
			||||||
 | 
						void force_sample ();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -104,13 +104,15 @@ void nano::peer_history::run_one ()
 | 
				
			||||||
	auto const now = std::chrono::system_clock::now ();
 | 
						auto const now = std::chrono::system_clock::now ();
 | 
				
			||||||
	auto const cutoff = now - config.erase_cutoff;
 | 
						auto const cutoff = now - config.erase_cutoff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::deque<nano::store::peer::iterator::value_type> to_remove;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (auto it = store.peer.begin (transaction); it != store.peer.end (transaction); ++it)
 | 
						for (auto it = store.peer.begin (transaction); it != store.peer.end (transaction); ++it)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto const [endpoint, timestamp_millis] = *it;
 | 
							auto const [endpoint, timestamp_millis] = *it;
 | 
				
			||||||
		auto timestamp = nano::from_milliseconds_since_epoch (timestamp_millis);
 | 
							auto timestamp = nano::from_milliseconds_since_epoch (timestamp_millis);
 | 
				
			||||||
		if (timestamp > now || timestamp < cutoff)
 | 
							if (timestamp > now || timestamp < cutoff)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			store.peer.del (transaction, endpoint);
 | 
								to_remove.push_back (*it);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			stats.inc (nano::stat::type::peer_history, nano::stat::detail::erased);
 | 
								stats.inc (nano::stat::type::peer_history, nano::stat::detail::erased);
 | 
				
			||||||
			logger.debug (nano::log::type::peer_history, "Erased peer: {} (not seen for {}s)",
 | 
								logger.debug (nano::log::type::peer_history, "Erased peer: {} (not seen for {}s)",
 | 
				
			||||||
| 
						 | 
					@ -118,6 +120,12 @@ void nano::peer_history::run_one ()
 | 
				
			||||||
			nano::log::seconds_delta (timestamp));
 | 
								nano::log::seconds_delta (timestamp));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Remove entries after iterating to avoid iterator invalidation
 | 
				
			||||||
 | 
						for (auto const & entry : to_remove)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							store.peer.del (transaction, entry.first);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::vector<nano::endpoint> nano::peer_history::peers () const
 | 
					std::vector<nano::endpoint> nano::peer_history::peers () const
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
#include <nano/node/active_elections.hpp>
 | 
					#include <nano/node/active_elections.hpp>
 | 
				
			||||||
#include <nano/node/node.hpp>
 | 
					#include <nano/node/node.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/node/repcrawler.hpp>
 | 
					#include <nano/node/repcrawler.hpp>
 | 
				
			||||||
#include <nano/secure/ledger.hpp>
 | 
					#include <nano/secure/ledger.hpp>
 | 
				
			||||||
#include <nano/secure/vote.hpp>
 | 
					#include <nano/secure/vote.hpp>
 | 
				
			||||||
| 
						 | 
					@ -82,7 +83,8 @@ void nano::rep_crawler::validate_and_process (nano::unique_lock<nano::mutex> & l
 | 
				
			||||||
		if (channel->get_type () == nano::transport::transport_type::loopback)
 | 
							if (channel->get_type () == nano::transport::transport_type::loopback)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			logger.debug (nano::log::type::rep_crawler, "Ignoring vote from loopback channel: {}", channel->to_string ());
 | 
								logger.debug (nano::log::type::rep_crawler, "Ignoring vote from loopback channel: {}", channel->to_string ());
 | 
				
			||||||
			continue;
 | 
					
 | 
				
			||||||
 | 
								continue; // Skip this vote
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		nano::uint128_t const rep_weight = node.ledger.weight (vote->account);
 | 
							nano::uint128_t const rep_weight = node.ledger.weight (vote->account);
 | 
				
			||||||
| 
						 | 
					@ -90,8 +92,9 @@ void nano::rep_crawler::validate_and_process (nano::unique_lock<nano::mutex> & l
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			logger.debug (nano::log::type::rep_crawler, "Ignoring vote from account: {} with too little voting weight: {}",
 | 
								logger.debug (nano::log::type::rep_crawler, "Ignoring vote from account: {} with too little voting weight: {}",
 | 
				
			||||||
			vote->account.to_account (),
 | 
								vote->account.to_account (),
 | 
				
			||||||
			nano::util::to_str (rep_weight));
 | 
								fmt::streamed (rep_weight));
 | 
				
			||||||
			continue;
 | 
					
 | 
				
			||||||
 | 
								continue; // Skip this vote
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// temporary data used for logging after dropping the lock
 | 
							// temporary data used for logging after dropping the lock
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
#include <nano/node/active_elections.hpp>
 | 
					#include <nano/node/active_elections.hpp>
 | 
				
			||||||
#include <nano/node/election_behavior.hpp>
 | 
					#include <nano/node/election_behavior.hpp>
 | 
				
			||||||
#include <nano/node/node.hpp>
 | 
					#include <nano/node/node.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/hinted.hpp>
 | 
					#include <nano/node/scheduler/hinted.hpp>
 | 
				
			||||||
#include <nano/secure/ledger.hpp>
 | 
					#include <nano/secure/ledger.hpp>
 | 
				
			||||||
#include <nano/secure/ledger_set_any.hpp>
 | 
					#include <nano/secure/ledger_set_any.hpp>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@
 | 
				
			||||||
#include <nano/node/ipc/ipc_server.hpp>
 | 
					#include <nano/node/ipc/ipc_server.hpp>
 | 
				
			||||||
#include <nano/node/json_handler.hpp>
 | 
					#include <nano/node/json_handler.hpp>
 | 
				
			||||||
#include <nano/node/node_rpc_config.hpp>
 | 
					#include <nano/node/node_rpc_config.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/component.hpp>
 | 
					#include <nano/node/scheduler/component.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/manual.hpp>
 | 
					#include <nano/node/scheduler/manual.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/priority.hpp>
 | 
					#include <nano/node/scheduler/priority.hpp>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -255,8 +255,8 @@ nano::node_constants::node_constants (nano::network_constants & network_constant
 | 
				
			||||||
	search_pending_interval = network_constants.is_dev_network () ? std::chrono::seconds (1) : std::chrono::seconds (5 * 60);
 | 
						search_pending_interval = network_constants.is_dev_network () ? std::chrono::seconds (1) : std::chrono::seconds (5 * 60);
 | 
				
			||||||
	unchecked_cleaning_interval = std::chrono::minutes (30);
 | 
						unchecked_cleaning_interval = std::chrono::minutes (30);
 | 
				
			||||||
	process_confirmed_interval = network_constants.is_dev_network () ? std::chrono::milliseconds (50) : std::chrono::milliseconds (500);
 | 
						process_confirmed_interval = network_constants.is_dev_network () ? std::chrono::milliseconds (50) : std::chrono::milliseconds (500);
 | 
				
			||||||
	max_weight_samples = (network_constants.is_live_network () || network_constants.is_test_network ()) ? 4032 : 288;
 | 
						weight_interval = network_constants.is_dev_network () ? std::chrono::seconds (1) : std::chrono::minutes (5);
 | 
				
			||||||
	weight_period = 5 * 60; // 5 minutes
 | 
						weight_cutoff = (network_constants.is_live_network () || network_constants.is_test_network ()) ? std::chrono::weeks (2) : std::chrono::days (1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -211,9 +211,10 @@ public:
 | 
				
			||||||
	std::chrono::minutes unchecked_cleaning_interval;
 | 
						std::chrono::minutes unchecked_cleaning_interval;
 | 
				
			||||||
	std::chrono::milliseconds process_confirmed_interval;
 | 
						std::chrono::milliseconds process_confirmed_interval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/** The maximum amount of samples for a 2 week period on live or 1 day on beta */
 | 
						/** Time between collecting online representative samples */
 | 
				
			||||||
	uint64_t max_weight_samples;
 | 
						std::chrono::seconds weight_interval;
 | 
				
			||||||
	uint64_t weight_period;
 | 
						/** The maximum time to keep online weight samples: 2 weeks on live or 1 day on beta */
 | 
				
			||||||
 | 
						std::chrono::seconds weight_cutoff;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Voting related constants whose value depends on the active network */
 | 
					/** Voting related constants whose value depends on the active network */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@
 | 
				
			||||||
#include <nano/node/confirming_set.hpp>
 | 
					#include <nano/node/confirming_set.hpp>
 | 
				
			||||||
#include <nano/node/election.hpp>
 | 
					#include <nano/node/election.hpp>
 | 
				
			||||||
#include <nano/node/make_store.hpp>
 | 
					#include <nano/node/make_store.hpp>
 | 
				
			||||||
 | 
					#include <nano/node/online_reps.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/component.hpp>
 | 
					#include <nano/node/scheduler/component.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/manual.hpp>
 | 
					#include <nano/node/scheduler/manual.hpp>
 | 
				
			||||||
#include <nano/node/scheduler/priority.hpp>
 | 
					#include <nano/node/scheduler/priority.hpp>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ enum class writer
 | 
				
			||||||
	pruning,
 | 
						pruning,
 | 
				
			||||||
	voting_final,
 | 
						voting_final,
 | 
				
			||||||
	bounded_backlog,
 | 
						bounded_backlog,
 | 
				
			||||||
 | 
						online_weight,
 | 
				
			||||||
	testing // Used in tests to emulate a write lock
 | 
						testing // Used in tests to emulate a write lock
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -387,3 +387,8 @@ std::vector<std::shared_ptr<nano::block>> nano::test::all_blocks (nano::node & n
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nano::uint128_t nano::test::minimum_principal_weight ()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nano::dev::genesis->balance ().number () / nano::dev::network_params.network.principal_weight_factor;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -432,5 +432,7 @@ namespace test
 | 
				
			||||||
	 * Returns all blocks in the ledger
 | 
						 * Returns all blocks in the ledger
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	std::vector<std::shared_ptr<nano::block>> all_blocks (nano::node &);
 | 
						std::vector<std::shared_ptr<nano::block>> all_blocks (nano::node &);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nano::uint128_t minimum_principal_weight ();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue