Confirm delta (#2884)
* Rewrite tests in terms of state blocks. * online_weight_minimum is already considered in the calculation of node::delta. Using online_weight_minimum directly can cause quorum requirements to be unnecessarily high as the online_weight_minimum is approached. Replacing references to online_weight_minimum with node:delta and adding tests to ensure rollbacks and confirmation is done precisely on the correct conditions. * online_weight_minimum is already considered in the calculation of node::delta. Using online_weight_minimum directly can cause quorum requirements to be unnecessarily high as actual online vote weight approaches online_weight_minimum. Replacing references to online_weight_minimum with node:delta and adding tests to ensure rollbacks and confirmation is done precisely on the correct conditions. * Replace additional direct references to online_weight_minimum with references to delta (), which already considers the online_weight_minimum. * Changing vote_processor to reference nano::node instead of all of its components directly. * Moving online_stake calculation on to node. * Tracking trended weight separately from currently online weight. Moving delta on to online_reps class so all network weight calculations are done in one place. * Cleaning up tests and removing unrelated vote_processor changes. * Avoiding extra memory allocations on vector. Generating timestamp within mutex to avoid issues of delays. Removing reference to unused header.
This commit is contained in:
parent
abfe2b05b6
commit
932ee97318
22 changed files with 343 additions and 156 deletions
|
@ -463,7 +463,7 @@ TEST (bootstrap_processor, frontiers_unconfirmed_threshold)
|
|||
nano::keypair key1, key2;
|
||||
// Generating invalid chain
|
||||
auto threshold (node1->gap_cache.bootstrap_threshold () + 1);
|
||||
ASSERT_LT (threshold, node1->config.online_weight_minimum.number ());
|
||||
ASSERT_LT (threshold, node1->online_reps.delta ());
|
||||
auto send1 (std::make_shared<nano::state_block> (nano::dev_genesis_key.pub, genesis.hash (), nano::dev_genesis_key.pub, nano::genesis_amount - threshold, key1.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (genesis.hash ())));
|
||||
ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code);
|
||||
auto send2 (std::make_shared<nano::state_block> (nano::dev_genesis_key.pub, send1->hash (), nano::dev_genesis_key.pub, nano::genesis_amount - threshold - nano::Gxrb_ratio, key2.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (send1->hash ())));
|
||||
|
|
|
@ -93,9 +93,9 @@ TEST (confirmation_height, multiple_accounts)
|
|||
nano::block_hash latest1 (system.nodes[0]->latest (nano::dev_genesis_key.pub));
|
||||
|
||||
// Send to all accounts
|
||||
nano::send_block send1 (latest1, key1.pub, system.nodes.front ()->config.online_weight_minimum.number () + 300, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (latest1));
|
||||
nano::send_block send2 (send1.hash (), key2.pub, system.nodes.front ()->config.online_weight_minimum.number () + 200, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (send1.hash ()));
|
||||
nano::send_block send3 (send2.hash (), key3.pub, system.nodes.front ()->config.online_weight_minimum.number () + 100, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (send2.hash ()));
|
||||
nano::send_block send1 (latest1, key1.pub, node->online_reps.delta () + 300, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (latest1));
|
||||
nano::send_block send2 (send1.hash (), key2.pub, node->online_reps.delta () + 200, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (send1.hash ()));
|
||||
nano::send_block send3 (send2.hash (), key3.pub, node->online_reps.delta () + 100, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (send2.hash ()));
|
||||
|
||||
// Open all accounts
|
||||
nano::open_block open1 (send1.hash (), nano::genesis_account, key1.pub, key1.prv, key1.pub, *system.work.generate (key1.pub));
|
||||
|
@ -393,7 +393,7 @@ TEST (confirmation_height, send_receive_between_2_accounts)
|
|||
nano::keypair key1;
|
||||
nano::block_hash latest (node->latest (nano::dev_genesis_key.pub));
|
||||
|
||||
nano::send_block send1 (latest, key1.pub, node->config.online_weight_minimum.number () + 2, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (latest));
|
||||
nano::send_block send1 (latest, key1.pub, node->online_reps.delta () + 2, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (latest));
|
||||
|
||||
nano::open_block open1 (send1.hash (), nano::genesis_account, key1.pub, key1.prv, key1.pub, *system.work.generate (key1.pub));
|
||||
nano::send_block send2 (open1.hash (), nano::genesis_account, 1000, key1.prv, key1.pub, *system.work.generate (open1.hash ()));
|
||||
|
@ -404,11 +404,11 @@ TEST (confirmation_height, send_receive_between_2_accounts)
|
|||
nano::receive_block receive2 (receive1.hash (), send3.hash (), nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (receive1.hash ()));
|
||||
nano::receive_block receive3 (receive2.hash (), send4.hash (), nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (receive2.hash ()));
|
||||
|
||||
nano::send_block send5 (receive3.hash (), key1.pub, node->config.online_weight_minimum.number () + 1, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (receive3.hash ()));
|
||||
nano::send_block send5 (receive3.hash (), key1.pub, node->online_reps.delta () + 1, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (receive3.hash ()));
|
||||
auto receive4 = std::make_shared<nano::receive_block> (send4.hash (), send5.hash (), key1.prv, key1.pub, *system.work.generate (send4.hash ()));
|
||||
// Unpocketed send
|
||||
nano::keypair key2;
|
||||
nano::send_block send6 (send5.hash (), key2.pub, node->config.online_weight_minimum.number (), nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (send5.hash ()));
|
||||
nano::send_block send6 (send5.hash (), key2.pub, node->online_reps.delta (), nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (send5.hash ()));
|
||||
{
|
||||
auto transaction = node->store.tx_begin_write ();
|
||||
ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, send1).code);
|
||||
|
@ -487,7 +487,7 @@ TEST (confirmation_height, send_receive_self)
|
|||
|
||||
// Send to another account to prevent automatic receiving on the genesis account
|
||||
nano::keypair key1;
|
||||
nano::send_block send4 (receive3->hash (), key1.pub, node->config.online_weight_minimum.number (), nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (receive3->hash ()));
|
||||
nano::send_block send4 (receive3->hash (), key1.pub, node->online_reps.delta (), nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (receive3->hash ()));
|
||||
{
|
||||
auto transaction = node->store.tx_begin_write ();
|
||||
ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, send1).code);
|
||||
|
|
|
@ -13,3 +13,155 @@ TEST (election, construction)
|
|||
auto election = node.active.insert (genesis.open).election;
|
||||
election->transition_active ();
|
||||
}
|
||||
|
||||
TEST (election, quorum_minimum_flip_success)
|
||||
{
|
||||
nano::system system;
|
||||
nano::node_config node_config (nano::get_available_port (), system.logging);
|
||||
node_config.online_weight_minimum = nano::genesis_amount;
|
||||
node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
|
||||
auto & node1 = *system.add_node (node_config);
|
||||
nano::keypair key1;
|
||||
nano::block_builder builder;
|
||||
auto send1 = builder.state ()
|
||||
.account (nano::dev_genesis_key.pub)
|
||||
.previous (nano::genesis_hash)
|
||||
.representative (nano::dev_genesis_key.pub)
|
||||
.balance (node1.online_reps.delta ())
|
||||
.link (key1.pub)
|
||||
.work (0)
|
||||
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
|
||||
.build_shared ();
|
||||
node1.work_generate_blocking (*send1);
|
||||
nano::keypair key2;
|
||||
auto send2 = builder.state ()
|
||||
.account (nano::dev_genesis_key.pub)
|
||||
.previous (nano::genesis_hash)
|
||||
.representative (nano::dev_genesis_key.pub)
|
||||
.balance (node1.online_reps.delta ())
|
||||
.link (key2.pub)
|
||||
.work (0)
|
||||
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
|
||||
.build_shared ();
|
||||
node1.work_generate_blocking (*send2);
|
||||
node1.process_active (send1);
|
||||
node1.process_active (send2);
|
||||
node1.block_processor.flush ();
|
||||
auto election{ node1.active.insert (send1) };
|
||||
ASSERT_FALSE (election.inserted);
|
||||
ASSERT_NE (nullptr, election.election);
|
||||
ASSERT_EQ (2, election.election->blocks ().size ());
|
||||
auto vote1 (std::make_shared<nano::vote> (nano::dev_genesis_key.pub, nano::dev_genesis_key.prv, 1, send2));
|
||||
ASSERT_EQ (nano::vote_code::vote, node1.active.vote (vote1));
|
||||
node1.block_processor.flush ();
|
||||
ASSERT_NE (nullptr, node1.block (send2->hash ()));
|
||||
ASSERT_TRUE (election.election->confirmed ());
|
||||
}
|
||||
|
||||
TEST (election, quorum_minimum_flip_fail)
|
||||
{
|
||||
nano::system system;
|
||||
nano::node_config node_config (nano::get_available_port (), system.logging);
|
||||
node_config.online_weight_minimum = nano::genesis_amount;
|
||||
node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
|
||||
auto & node1 = *system.add_node (node_config);
|
||||
nano::keypair key1;
|
||||
nano::block_builder builder;
|
||||
auto send1 = builder.state ()
|
||||
.account (nano::dev_genesis_key.pub)
|
||||
.previous (nano::genesis_hash)
|
||||
.representative (nano::dev_genesis_key.pub)
|
||||
.balance (node1.online_reps.delta () - 1)
|
||||
.link (key1.pub)
|
||||
.work (0)
|
||||
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
|
||||
.build_shared ();
|
||||
node1.work_generate_blocking (*send1);
|
||||
nano::keypair key2;
|
||||
auto send2 = builder.state ()
|
||||
.account (nano::dev_genesis_key.pub)
|
||||
.previous (nano::genesis_hash)
|
||||
.representative (nano::dev_genesis_key.pub)
|
||||
.balance (node1.online_reps.delta () - 1)
|
||||
.link (key2.pub)
|
||||
.work (0)
|
||||
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
|
||||
.build_shared ();
|
||||
node1.work_generate_blocking (*send2);
|
||||
node1.process_active (send1);
|
||||
node1.process_active (send2);
|
||||
node1.block_processor.flush ();
|
||||
auto election{ node1.active.insert (send1) };
|
||||
ASSERT_FALSE (election.inserted);
|
||||
ASSERT_NE (nullptr, election.election);
|
||||
ASSERT_EQ (2, election.election->blocks ().size ());
|
||||
auto vote1 (std::make_shared<nano::vote> (nano::dev_genesis_key.pub, nano::dev_genesis_key.prv, 1, send2));
|
||||
ASSERT_EQ (nano::vote_code::vote, node1.active.vote (vote1));
|
||||
node1.block_processor.flush ();
|
||||
ASSERT_NE (nullptr, node1.block (send1->hash ()));
|
||||
ASSERT_FALSE (election.election->confirmed ());
|
||||
}
|
||||
|
||||
TEST (election, quorum_minimum_confirm_success)
|
||||
{
|
||||
nano::system system;
|
||||
nano::node_config node_config (nano::get_available_port (), system.logging);
|
||||
node_config.online_weight_minimum = nano::genesis_amount;
|
||||
node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
|
||||
auto & node1 = *system.add_node (node_config);
|
||||
nano::keypair key1;
|
||||
nano::block_builder builder;
|
||||
auto send1 = builder.state ()
|
||||
.account (nano::dev_genesis_key.pub)
|
||||
.previous (nano::genesis_hash)
|
||||
.representative (nano::dev_genesis_key.pub)
|
||||
.balance (node1.online_reps.delta ())
|
||||
.link (key1.pub)
|
||||
.work (0)
|
||||
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
|
||||
.build_shared ();
|
||||
node1.work_generate_blocking (*send1);
|
||||
node1.process_active (send1);
|
||||
node1.block_processor.flush ();
|
||||
auto election{ node1.active.insert (send1) };
|
||||
ASSERT_FALSE (election.inserted);
|
||||
ASSERT_NE (nullptr, election.election);
|
||||
ASSERT_EQ (1, election.election->blocks ().size ());
|
||||
auto vote1 (std::make_shared<nano::vote> (nano::dev_genesis_key.pub, nano::dev_genesis_key.prv, 1, send1));
|
||||
ASSERT_EQ (nano::vote_code::vote, node1.active.vote (vote1));
|
||||
node1.block_processor.flush ();
|
||||
ASSERT_NE (nullptr, node1.block (send1->hash ()));
|
||||
ASSERT_TRUE (election.election->confirmed ());
|
||||
}
|
||||
|
||||
TEST (election, quorum_minimum_confirm_fail)
|
||||
{
|
||||
nano::system system;
|
||||
nano::node_config node_config (nano::get_available_port (), system.logging);
|
||||
node_config.online_weight_minimum = nano::genesis_amount;
|
||||
node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
|
||||
auto & node1 = *system.add_node (node_config);
|
||||
nano::keypair key1;
|
||||
nano::block_builder builder;
|
||||
auto send1 = builder.state ()
|
||||
.account (nano::dev_genesis_key.pub)
|
||||
.previous (nano::genesis_hash)
|
||||
.representative (nano::dev_genesis_key.pub)
|
||||
.balance (node1.online_reps.delta () - 1)
|
||||
.link (key1.pub)
|
||||
.work (0)
|
||||
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
|
||||
.build_shared ();
|
||||
node1.work_generate_blocking (*send1);
|
||||
node1.process_active (send1);
|
||||
node1.block_processor.flush ();
|
||||
auto election{ node1.active.insert (send1) };
|
||||
ASSERT_FALSE (election.inserted);
|
||||
ASSERT_NE (nullptr, election.election);
|
||||
ASSERT_EQ (1, election.election->blocks ().size ());
|
||||
auto vote1 (std::make_shared<nano::vote> (nano::dev_genesis_key.pub, nano::dev_genesis_key.prv, 1, send1));
|
||||
ASSERT_EQ (nano::vote_code::vote, node1.active.vote (vote1));
|
||||
node1.block_processor.flush ();
|
||||
ASSERT_NE (nullptr, node1.block (send1->hash ()));
|
||||
ASSERT_FALSE (election.election->confirmed ());
|
||||
}
|
||||
|
|
|
@ -837,17 +837,22 @@ TEST (votes, add_existing)
|
|||
{
|
||||
nano::system system;
|
||||
nano::node_config node_config (nano::get_available_port (), system.logging);
|
||||
node_config.online_weight_minimum = std::numeric_limits<nano::uint128_t>::max ();
|
||||
node_config.online_weight_minimum = nano::genesis_amount;
|
||||
node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
|
||||
auto & node1 = *system.add_node (node_config);
|
||||
nano::genesis genesis;
|
||||
nano::keypair key1;
|
||||
auto send1 (std::make_shared<nano::send_block> (genesis.hash (), key1.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, 0));
|
||||
nano::block_builder builder;
|
||||
std::shared_ptr<nano::block> send1 = builder.state ()
|
||||
.account (nano::dev_genesis_key.pub)
|
||||
.previous (nano::genesis_hash)
|
||||
.representative (nano::dev_genesis_key.pub) // No representative, blocks can't confirm
|
||||
.balance (nano::genesis_amount / 2 - nano::Gxrb_ratio)
|
||||
.link (key1.pub)
|
||||
.work (0)
|
||||
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
|
||||
.build ();
|
||||
node1.work_generate_blocking (*send1);
|
||||
{
|
||||
auto transaction (node1.store.tx_begin_write ());
|
||||
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code);
|
||||
}
|
||||
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (node1.store.tx_begin_write (), *send1).code);
|
||||
auto election1 = node1.active.insert (send1);
|
||||
auto vote1 (std::make_shared<nano::vote> (nano::dev_genesis_key.pub, nano::dev_genesis_key.prv, 1, send1));
|
||||
ASSERT_EQ (nano::vote_code::vote, node1.active.vote (vote1));
|
||||
|
@ -855,7 +860,15 @@ TEST (votes, add_existing)
|
|||
ASSERT_TRUE (node1.active.publish (send1));
|
||||
ASSERT_EQ (1, election1.election->last_votes[nano::dev_genesis_key.pub].timestamp);
|
||||
nano::keypair key2;
|
||||
auto send2 (std::make_shared<nano::send_block> (genesis.hash (), key2.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, 0));
|
||||
std::shared_ptr<nano::block> send2 = builder.state ()
|
||||
.account (nano::dev_genesis_key.pub)
|
||||
.previous (nano::genesis_hash)
|
||||
.representative (nano::dev_genesis_key.pub) // No representative, blocks can't confirm
|
||||
.balance (nano::genesis_amount / 2 - nano::Gxrb_ratio)
|
||||
.link (key2.pub)
|
||||
.work (0)
|
||||
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
|
||||
.build ();
|
||||
node1.work_generate_blocking (*send2);
|
||||
auto vote2 (std::make_shared<nano::vote> (nano::dev_genesis_key.pub, nano::dev_genesis_key.prv, 2, send2));
|
||||
// Pretend we've waited the timeout
|
||||
|
|
|
@ -229,14 +229,14 @@ TEST (node, quick_confirm)
|
|||
auto send = nano::send_block_builder ()
|
||||
.previous (previous)
|
||||
.destination (key.pub)
|
||||
.balance (node1.config.online_weight_minimum.number () + 1)
|
||||
.balance (node1.online_reps.delta () + 1)
|
||||
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
|
||||
.work (*system.work.generate (previous))
|
||||
.build_shared ();
|
||||
node1.process_active (send);
|
||||
ASSERT_TIMELY (10s, !node1.balance (key.pub).is_zero ());
|
||||
ASSERT_EQ (node1.balance (nano::dev_genesis_key.pub), node1.config.online_weight_minimum.number () + 1);
|
||||
ASSERT_EQ (node1.balance (key.pub), genesis_start_balance - (node1.config.online_weight_minimum.number () + 1));
|
||||
ASSERT_EQ (node1.balance (nano::dev_genesis_key.pub), node1.online_reps.delta () + 1);
|
||||
ASSERT_EQ (node1.balance (key.pub), genesis_start_balance - (node1.online_reps.delta () + 1));
|
||||
}
|
||||
|
||||
TEST (node, node_receive_quorum)
|
||||
|
@ -2415,15 +2415,19 @@ TEST (node, online_reps)
|
|||
nano::system system (1);
|
||||
auto & node1 (*system.nodes[0]);
|
||||
// 1 sample of minimum weight
|
||||
ASSERT_EQ (node1.config.online_weight_minimum, node1.online_reps.online_stake ());
|
||||
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::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::genesis_amount, node1.online_reps.online_stake ());
|
||||
ASSERT_EQ (nano::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.online_stake ());
|
||||
ASSERT_EQ (node1.config.online_weight_minimum, node1.online_reps.trended ());
|
||||
}
|
||||
|
||||
TEST (node, block_confirm)
|
||||
|
@ -2537,8 +2541,8 @@ TEST (node, confirm_quorum)
|
|||
auto & node1 (*system.nodes[0]);
|
||||
nano::genesis genesis;
|
||||
system.wallet (0)->insert_adhoc (nano::dev_genesis_key.prv);
|
||||
// Put greater than online_weight_minimum in pending so quorum can't be reached
|
||||
nano::amount new_balance (node1.config.online_weight_minimum.number () - nano::Gxrb_ratio);
|
||||
// Put greater than node.delta () in pending so quorum can't be reached
|
||||
nano::amount new_balance (node1.online_reps.delta () - nano::Gxrb_ratio);
|
||||
auto send1 = nano::state_block_builder ()
|
||||
.account (nano::dev_genesis_key.pub)
|
||||
.previous (genesis.hash ())
|
||||
|
@ -3855,7 +3859,7 @@ TEST (node, rollback_vote_self)
|
|||
auto & node = *system.add_node (flags);
|
||||
nano::state_block_builder builder;
|
||||
nano::keypair key;
|
||||
auto weight = node.config.online_weight_minimum.number ();
|
||||
auto weight = node.online_reps.delta ();
|
||||
auto send1 = builder.make_block ()
|
||||
.account (nano::dev_genesis_key.pub)
|
||||
.previous (nano::genesis_hash)
|
||||
|
@ -4490,33 +4494,6 @@ TEST (rep_crawler, local)
|
|||
}
|
||||
}
|
||||
|
||||
TEST (online_reps, backup)
|
||||
{
|
||||
nano::logger_mt logger;
|
||||
auto store = nano::make_store (logger, nano::unique_path ());
|
||||
ASSERT_TRUE (!store->init_error ());
|
||||
nano::stat stats;
|
||||
nano::ledger ledger (*store, stats);
|
||||
{
|
||||
nano::genesis genesis;
|
||||
auto transaction (store->tx_begin_write ());
|
||||
store->initialize (transaction, genesis, ledger.cache);
|
||||
}
|
||||
nano::network_params params;
|
||||
nano::online_reps online_reps (ledger, params, 0);
|
||||
ASSERT_EQ (0, online_reps.list ().size ());
|
||||
online_reps.observe (nano::dev_genesis_key.pub);
|
||||
// The reported list of online reps is the union of the current list and the backup list, which changes when sampling
|
||||
ASSERT_EQ (1, online_reps.list ().size ());
|
||||
ASSERT_TRUE (online_reps.online_stake ().is_zero ());
|
||||
online_reps.sample ();
|
||||
ASSERT_EQ (1, online_reps.list ().size ());
|
||||
// The trend is also correctly updated
|
||||
ASSERT_EQ (nano::genesis_amount, online_reps.online_stake ());
|
||||
online_reps.sample ();
|
||||
ASSERT_EQ (0, online_reps.list ().size ());
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
void add_required_children_node_config_tree (nano::jsonconfig & tree)
|
||||
|
|
|
@ -156,7 +156,7 @@ TEST (websocket, confirmation)
|
|||
nano::keypair key;
|
||||
system.wallet (0)->insert_adhoc (nano::dev_genesis_key.prv);
|
||||
auto balance = nano::genesis_amount;
|
||||
auto send_amount = node1->config.online_weight_minimum.number () + 1;
|
||||
auto send_amount = node1->online_reps.delta () + 1;
|
||||
// Quick-confirm a block, legacy blocks should work without filtering
|
||||
{
|
||||
nano::block_hash previous (node1->latest (nano::dev_genesis_key.pub));
|
||||
|
@ -248,7 +248,7 @@ TEST (websocket, confirmation_options)
|
|||
system.wallet (0)->insert_adhoc (nano::dev_genesis_key.prv);
|
||||
nano::keypair key;
|
||||
auto balance = nano::genesis_amount;
|
||||
auto send_amount = node1->config.online_weight_minimum.number () + 1;
|
||||
auto send_amount = node1->online_reps.delta () + 1;
|
||||
nano::block_hash previous (node1->latest (nano::dev_genesis_key.pub));
|
||||
{
|
||||
balance -= send_amount;
|
||||
|
@ -416,7 +416,7 @@ TEST (websocket, vote)
|
|||
nano::keypair key;
|
||||
system.wallet (0)->insert_adhoc (nano::dev_genesis_key.prv);
|
||||
nano::block_hash previous (node1->latest (nano::dev_genesis_key.pub));
|
||||
auto send (std::make_shared<nano::state_block> (nano::dev_genesis_key.pub, previous, nano::dev_genesis_key.pub, nano::genesis_amount - (node1->config.online_weight_minimum.number () + 1), key.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (previous)));
|
||||
auto send (std::make_shared<nano::state_block> (nano::dev_genesis_key.pub, previous, nano::dev_genesis_key.pub, nano::genesis_amount - (node1->online_reps.delta () + 1), key.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (previous)));
|
||||
node1->process_active (send);
|
||||
|
||||
ASSERT_TIMELY (5s, future.wait_for (0s) == std::future_status::ready);
|
||||
|
@ -505,7 +505,7 @@ TEST (websocket, vote_options_representatives)
|
|||
nano::keypair key;
|
||||
auto balance = nano::genesis_amount;
|
||||
system.wallet (0)->insert_adhoc (nano::dev_genesis_key.prv);
|
||||
auto send_amount = node1->config.online_weight_minimum.number () + 1;
|
||||
auto send_amount = node1->online_reps.delta () + 1;
|
||||
auto confirm_block = [&]() {
|
||||
nano::block_hash previous (node1->latest (nano::dev_genesis_key.pub));
|
||||
balance -= send_amount;
|
||||
|
|
|
@ -77,7 +77,7 @@ int main (int argc, char * const * argv)
|
|||
("debug_block_count", "Display the number of blocks")
|
||||
("debug_bootstrap_generate", "Generate bootstrap sequence of blocks")
|
||||
("debug_dump_frontier_unchecked_dependents", "Dump frontiers which have matching unchecked keys")
|
||||
("debug_dump_online_weight", "Dump online_weights table")
|
||||
("debug_dump_trended_weight", "Dump trended weights table")
|
||||
("debug_dump_representatives", "List representatives and weights")
|
||||
("debug_account_count", "Display the number of accounts")
|
||||
("debug_profile_generate", "Profile work generation")
|
||||
|
@ -382,12 +382,12 @@ int main (int argc, char * const * argv)
|
|||
result = -1;
|
||||
}
|
||||
}
|
||||
else if (vm.count ("debug_dump_online_weight"))
|
||||
else if (vm.count ("debug_dump_trended_weight"))
|
||||
{
|
||||
auto inactive_node = nano::default_inactive_node (data_path, vm);
|
||||
auto node = inactive_node->node;
|
||||
auto current (node->online_reps.online_stake ());
|
||||
std::cout << boost::str (boost::format ("Online Weight %1%\n") % current);
|
||||
auto current (node->online_reps.trended ());
|
||||
std::cout << boost::str (boost::format ("Trended Weight %1%\n") % current);
|
||||
auto transaction (node->store.tx_begin_read ());
|
||||
for (auto i (node->store.online_weight_begin (transaction)), n (node->store.online_weight_end ()); i != n; ++i)
|
||||
{
|
||||
|
|
|
@ -1462,7 +1462,7 @@ nano::inactive_cache_status nano::active_transactions::inactive_votes_bootstrap_
|
|||
tally += node.ledger.weight (voter);
|
||||
}
|
||||
|
||||
if (!previously_a.confirmed && tally >= node.config.online_weight_minimum.number ())
|
||||
if (!previously_a.confirmed && tally >= node.online_reps.delta ())
|
||||
{
|
||||
status.bootstrap_started = true;
|
||||
status.confirmed = true;
|
||||
|
@ -1471,7 +1471,7 @@ nano::inactive_cache_status nano::active_transactions::inactive_votes_bootstrap_
|
|||
{
|
||||
status.bootstrap_started = true;
|
||||
}
|
||||
if (!previously_a.election_started && voters_a.size () >= election_start_voters_min && tally >= (node.online_reps.online_stake () / 100) * node.config.election_hint_weight_percent)
|
||||
if (!previously_a.election_started && voters_a.size () >= election_start_voters_min && tally >= (node.online_reps.trended () / 100) * node.config.election_hint_weight_percent)
|
||||
{
|
||||
status.election_started = true;
|
||||
}
|
||||
|
|
|
@ -229,17 +229,13 @@ bool nano::election::transition_time (nano::confirmation_solicitor & solicitor_a
|
|||
return result;
|
||||
}
|
||||
|
||||
bool nano::election::have_quorum (nano::tally_t const & tally_a, nano::uint128_t tally_sum) const
|
||||
bool nano::election::have_quorum (nano::tally_t const & tally_a) const
|
||||
{
|
||||
bool result = false;
|
||||
if (tally_sum >= node.config.online_weight_minimum.number ())
|
||||
{
|
||||
auto i (tally_a.begin ());
|
||||
++i;
|
||||
auto second (i != tally_a.end () ? i->first : 0);
|
||||
auto delta_l (node.delta ());
|
||||
result = tally_a.begin ()->first > (second + delta_l);
|
||||
}
|
||||
auto i (tally_a.begin ());
|
||||
++i;
|
||||
auto second (i != tally_a.end () ? i->first : 0);
|
||||
auto delta_l (node.online_reps.delta ());
|
||||
bool result{ tally_a.begin ()->first >= (second + delta_l) };
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -284,13 +280,13 @@ void nano::election::confirm_if_quorum (nano::unique_lock<std::mutex> & lock_a)
|
|||
{
|
||||
sum += i.first;
|
||||
}
|
||||
if (sum >= node.config.online_weight_minimum.number () && winner_hash_l != status_winner_hash_l)
|
||||
if (sum >= node.online_reps.delta () && winner_hash_l != status_winner_hash_l)
|
||||
{
|
||||
status.winner = block_l;
|
||||
remove_votes (status_winner_hash_l);
|
||||
node.block_processor.force (block_l);
|
||||
}
|
||||
if (have_quorum (tally_l, sum))
|
||||
if (have_quorum (tally_l))
|
||||
{
|
||||
if (node.config.logging.vote_logging () || (node.config.logging.election_fork_tally_logging () && last_blocks.size () > 1))
|
||||
{
|
||||
|
@ -334,7 +330,7 @@ nano::election_vote_result nano::election::vote (nano::account const & rep, uint
|
|||
{
|
||||
// see republish_vote documentation for an explanation of these rules
|
||||
auto replay (false);
|
||||
auto online_stake (node.online_reps.online_stake ());
|
||||
auto online_stake (node.online_reps.trended ());
|
||||
auto weight (node.ledger.weight (rep));
|
||||
auto should_process (false);
|
||||
if (node.network_params.network.is_dev_network () || weight > node.minimum_principal_weight (online_stake))
|
||||
|
@ -396,7 +392,7 @@ bool nano::election::publish (std::shared_ptr<nano::block> const & block_a)
|
|||
auto result (confirmed ());
|
||||
if (!result && last_blocks.size () >= 10)
|
||||
{
|
||||
if (last_tally[block_a->hash ()] < node.online_reps.online_stake () / 10)
|
||||
if (last_tally[block_a->hash ()] < node.online_reps.trended () / 10)
|
||||
{
|
||||
result = true;
|
||||
node.network.publish_filter.clear (block_a);
|
||||
|
|
|
@ -96,7 +96,7 @@ public: // Status
|
|||
|
||||
void log_votes (nano::tally_t const &, std::string const & = "") const;
|
||||
nano::tally_t tally () const;
|
||||
bool have_quorum (nano::tally_t const &, nano::uint128_t) const;
|
||||
bool have_quorum (nano::tally_t const &) const;
|
||||
|
||||
// Guarded by mutex
|
||||
nano::election_status status;
|
||||
|
|
|
@ -77,7 +77,7 @@ bool nano::gap_cache::bootstrap_check (std::vector<nano::account> const & voters
|
|||
bool start_bootstrap (false);
|
||||
if (!node.flags.disable_lazy_bootstrap)
|
||||
{
|
||||
if (tally >= node.config.online_weight_minimum.number ())
|
||||
if (tally >= node.online_reps.delta ())
|
||||
{
|
||||
start_bootstrap = true;
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ void nano::gap_cache::bootstrap_start (nano::block_hash const & hash_a)
|
|||
|
||||
nano::uint128_t nano::gap_cache::bootstrap_threshold ()
|
||||
{
|
||||
auto result ((node.online_reps.online_stake () / 256) * node.config.bootstrap_fraction_numerator);
|
||||
auto result ((node.online_reps.trended () / 256) * node.config.bootstrap_fraction_numerator);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1994,12 +1994,12 @@ void nano::json_handler::confirmation_info ()
|
|||
|
||||
void nano::json_handler::confirmation_quorum ()
|
||||
{
|
||||
response_l.put ("quorum_delta", node.delta ().convert_to<std::string> ());
|
||||
response_l.put ("quorum_delta", node.online_reps.delta ().convert_to<std::string> ());
|
||||
response_l.put ("online_weight_quorum_percent", std::to_string (node.config.online_weight_quorum));
|
||||
response_l.put ("online_weight_minimum", node.config.online_weight_minimum.to_string_dec ());
|
||||
response_l.put ("online_stake_total", node.online_reps.online_stake ().convert_to<std::string> ());
|
||||
response_l.put ("online_stake_total", node.online_reps.online ().convert_to<std::string> ());
|
||||
response_l.put ("trended_stake_total", node.online_reps.trended ().convert_to<std::string> ());
|
||||
response_l.put ("peers_stake_total", node.rep_crawler.total_weight ().convert_to<std::string> ());
|
||||
response_l.put ("peers_stake_required", std::max (node.config.online_weight_minimum.number (), node.delta ()).convert_to<std::string> ());
|
||||
if (request.get<bool> ("peer_details", false))
|
||||
{
|
||||
boost::property_tree::ptree peers;
|
||||
|
|
|
@ -248,7 +248,7 @@ void nano::network::send_confirm_req (std::shared_ptr<nano::transport::channel>
|
|||
void nano::network::broadcast_confirm_req (std::shared_ptr<nano::block> block_a)
|
||||
{
|
||||
auto list (std::make_shared<std::vector<std::shared_ptr<nano::transport::channel>>> (node.rep_crawler.representative_endpoints (std::numeric_limits<size_t>::max ())));
|
||||
if (list->empty () || node.rep_crawler.total_weight () < node.config.online_weight_minimum.number ())
|
||||
if (list->empty () || node.rep_crawler.total_weight () < node.online_reps.delta ())
|
||||
{
|
||||
// broadcast request to all peers (with max limit 2 * sqrt (peers count))
|
||||
auto peers (node.network.list (std::min<size_t> (100, node.network.fanout (2.0))));
|
||||
|
|
|
@ -118,7 +118,7 @@ block_processor_thread ([this]() {
|
|||
this->block_processor.process_blocks ();
|
||||
}),
|
||||
// clang-format on
|
||||
online_reps (ledger, network_params, config.online_weight_minimum.number ()),
|
||||
online_reps (ledger, config),
|
||||
vote_uniquer (block_uniquer),
|
||||
confirmation_height_processor (ledger, write_database_queue, config.conf_height_processor_batch_min_time, config.logging, logger, node_initialized_latch, flags.confirmation_height_processor_mode),
|
||||
active (*this, confirmation_height_processor),
|
||||
|
@ -779,7 +779,7 @@ nano::block_hash nano::node::rep_block (nano::account const & account_a)
|
|||
|
||||
nano::uint128_t nano::node::minimum_principal_weight ()
|
||||
{
|
||||
return minimum_principal_weight (online_reps.online_stake ());
|
||||
return minimum_principal_weight (online_reps.trended ());
|
||||
}
|
||||
|
||||
nano::uint128_t nano::node::minimum_principal_weight (nano::uint128_t const & online_stake)
|
||||
|
@ -1130,12 +1130,6 @@ bool nano::node::block_confirmed_or_being_confirmed (nano::transaction const & t
|
|||
return confirmation_height_processor.is_processing_block (hash_a) || ledger.block_confirmed (transaction_a, hash_a);
|
||||
}
|
||||
|
||||
nano::uint128_t nano::node::delta () const
|
||||
{
|
||||
auto result ((online_reps.online_stake () / 100) * config.online_weight_quorum);
|
||||
return result;
|
||||
}
|
||||
|
||||
void nano::node::ongoing_online_weight_calculation_queue ()
|
||||
{
|
||||
std::weak_ptr<nano::node> node_w (shared_from_this ());
|
||||
|
@ -1151,7 +1145,7 @@ void nano::node::ongoing_online_weight_calculation_queue ()
|
|||
|
||||
bool nano::node::online () const
|
||||
{
|
||||
return rep_crawler.total_weight () > (std::max (config.online_weight_minimum.number (), delta ()));
|
||||
return rep_crawler.total_weight () > online_reps.delta ();
|
||||
}
|
||||
|
||||
void nano::node::ongoing_online_weight_calculation ()
|
||||
|
|
|
@ -149,7 +149,6 @@ public:
|
|||
bool block_confirmed_or_being_confirmed (nano::transaction const &, nano::block_hash const &);
|
||||
void process_fork (nano::transaction const &, std::shared_ptr<nano::block> const &, uint64_t);
|
||||
void do_rpc_callback (boost::asio::ip::tcp::resolver::iterator i_a, std::string const &, uint16_t, std::shared_ptr<std::string>, std::shared_ptr<std::string>, std::shared_ptr<boost::asio::ip::tcp::resolver>);
|
||||
nano::uint128_t delta () const;
|
||||
void ongoing_online_weight_calculation ();
|
||||
void ongoing_online_weight_calculation_queue ();
|
||||
bool online () const;
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
#include <nano/node/nodeconfig.hpp>
|
||||
#include <nano/node/online_reps.hpp>
|
||||
#include <nano/secure/blockstore.hpp>
|
||||
#include <nano/secure/common.hpp>
|
||||
#include <nano/secure/ledger.hpp>
|
||||
|
||||
nano::online_reps::online_reps (nano::ledger & ledger_a, nano::network_params & network_params_a, nano::uint128_t minimum_a) :
|
||||
ledger (ledger_a),
|
||||
network_params (network_params_a),
|
||||
minimum (minimum_a)
|
||||
nano::online_reps::online_reps (nano::ledger & ledger_a, nano::node_config const & config_a) :
|
||||
ledger{ ledger_a },
|
||||
config{ config_a }
|
||||
{
|
||||
if (!ledger.store.init_error ())
|
||||
{
|
||||
auto transaction (ledger.store.tx_begin_read ());
|
||||
online = trend (transaction);
|
||||
trended_m = calculate_trend (transaction);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,82 +19,112 @@ void nano::online_reps::observe (nano::account const & rep_a)
|
|||
if (ledger.weight (rep_a) > 0)
|
||||
{
|
||||
nano::lock_guard<std::mutex> lock (mutex);
|
||||
reps.insert (rep_a);
|
||||
auto now = std::chrono::steady_clock::now ();
|
||||
auto new_insert = reps.get<tag_account> ().erase (rep_a) == 0;
|
||||
reps.insert ({ now, rep_a });
|
||||
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;
|
||||
reps.get<tag_time> ().erase (reps.get<tag_time> ().begin (), cutoff);
|
||||
if (new_insert || trimmed)
|
||||
{
|
||||
online_m = calculate_online ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nano::online_reps::sample ()
|
||||
{
|
||||
auto transaction (ledger.store.tx_begin_write ({ tables::online_weight }));
|
||||
// Discard oldest entries
|
||||
while (ledger.store.online_weight_count (transaction) >= network_params.node.max_weight_samples)
|
||||
nano::unique_lock<std::mutex> lock (mutex);
|
||||
nano::uint128_t online_l = online_m;
|
||||
lock.unlock ();
|
||||
nano::uint128_t trend_l;
|
||||
{
|
||||
auto oldest (ledger.store.online_weight_begin (transaction));
|
||||
debug_assert (oldest != ledger.store.online_weight_end ());
|
||||
ledger.store.online_weight_del (transaction, oldest->first);
|
||||
auto transaction (ledger.store.tx_begin_write ({ tables::online_weight }));
|
||||
// Discard oldest entries
|
||||
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 ());
|
||||
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);
|
||||
}
|
||||
// Calculate current active rep weight
|
||||
nano::uint128_t current;
|
||||
std::unordered_set<nano::account> reps_copy;
|
||||
{
|
||||
nano::lock_guard<std::mutex> lock (mutex);
|
||||
last_reps = reps;
|
||||
reps_copy.swap (reps);
|
||||
}
|
||||
for (auto & i : reps_copy)
|
||||
{
|
||||
current += ledger.weight (i);
|
||||
}
|
||||
ledger.store.online_weight_put (transaction, std::chrono::system_clock::now ().time_since_epoch ().count (), current);
|
||||
auto trend_l (trend (transaction));
|
||||
nano::lock_guard<std::mutex> lock (mutex);
|
||||
online = trend_l;
|
||||
lock.lock ();
|
||||
trended_m = trend_l;
|
||||
}
|
||||
|
||||
nano::uint128_t nano::online_reps::trend (nano::transaction & transaction_a)
|
||||
nano::uint128_t nano::online_reps::calculate_online () const
|
||||
{
|
||||
nano::uint128_t current;
|
||||
for (auto & i : reps)
|
||||
{
|
||||
current += ledger.weight (i.account);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
nano::uint128_t nano::online_reps::calculate_trend (nano::transaction & transaction_a) const
|
||||
{
|
||||
std::vector<nano::uint128_t> items;
|
||||
items.reserve (network_params.node.max_weight_samples + 1);
|
||||
items.push_back (minimum);
|
||||
items.reserve (config.network_params.node.max_weight_samples + 1);
|
||||
items.push_back (config.online_weight_minimum.number ());
|
||||
for (auto i (ledger.store.online_weight_begin (transaction_a)), n (ledger.store.online_weight_end ()); i != n; ++i)
|
||||
{
|
||||
items.push_back (i->second.number ());
|
||||
}
|
||||
|
||||
nano::uint128_t result;
|
||||
// Pick median value for our target vote weight
|
||||
auto median_idx = items.size () / 2;
|
||||
nth_element (items.begin (), items.begin () + median_idx, items.end ());
|
||||
return nano::uint128_t{ items[median_idx] };
|
||||
result = items[median_idx];
|
||||
return result;
|
||||
}
|
||||
|
||||
nano::uint128_t nano::online_reps::online_stake () const
|
||||
nano::uint128_t nano::online_reps::trended () const
|
||||
{
|
||||
nano::lock_guard<std::mutex> lock (mutex);
|
||||
return std::max (online, minimum);
|
||||
return trended_m;
|
||||
}
|
||||
|
||||
nano::uint128_t nano::online_reps::online () const
|
||||
{
|
||||
nano::lock_guard<std::mutex> lock (mutex);
|
||||
return online_m;
|
||||
}
|
||||
|
||||
nano::uint128_t nano::online_reps::delta () const
|
||||
{
|
||||
nano::lock_guard<std::mutex> lock (mutex);
|
||||
auto weight = std::max ({ online_m, trended_m, config.online_weight_minimum.number () });
|
||||
auto result ((weight / 100) * config.online_weight_quorum);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<nano::account> nano::online_reps::list ()
|
||||
{
|
||||
std::vector<nano::account> result;
|
||||
decltype (reps) all_reps;
|
||||
{
|
||||
nano::lock_guard<std::mutex> lock (mutex);
|
||||
all_reps.insert (last_reps.begin (), last_reps.end ());
|
||||
all_reps.insert (reps.begin (), reps.end ());
|
||||
}
|
||||
result.insert (result.end (), all_reps.begin (), all_reps.end ());
|
||||
nano::lock_guard<std::mutex> lock (mutex);
|
||||
std::for_each (reps.begin (), reps.end (), [&result](rep_info const & info_a) { result.push_back (info_a.account); });
|
||||
return result;
|
||||
}
|
||||
|
||||
void nano::online_reps::clear ()
|
||||
{
|
||||
nano::lock_guard<std::mutex> lock (mutex);
|
||||
reps.clear ();
|
||||
online_m = 0;
|
||||
}
|
||||
|
||||
std::unique_ptr<nano::container_info_component> nano::collect_container_info (online_reps & online_reps, const std::string & name)
|
||||
{
|
||||
size_t count;
|
||||
{
|
||||
nano::lock_guard<std::mutex> guard (online_reps.mutex);
|
||||
count = online_reps.last_reps.size ();
|
||||
count = online_reps.reps.size ();
|
||||
}
|
||||
|
||||
auto sizeof_element = sizeof (decltype (online_reps.last_reps)::value_type);
|
||||
auto sizeof_element = sizeof (decltype (online_reps.reps)::value_type);
|
||||
auto composite = std::make_unique<container_info_composite> (name);
|
||||
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "reps", count, sizeof_element }));
|
||||
return composite;
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
#include <nano/lib/numbers.hpp>
|
||||
#include <nano/lib/utility.hpp>
|
||||
#include <nano/secure/common.hpp>
|
||||
|
||||
#include <boost/multi_index/hashed_index.hpp>
|
||||
#include <boost/multi_index/member.hpp>
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
#include <boost/multi_index_container.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
|
@ -10,31 +16,55 @@
|
|||
namespace nano
|
||||
{
|
||||
class ledger;
|
||||
class network_params;
|
||||
class node_config;
|
||||
class transaction;
|
||||
|
||||
/** Track online representatives and trend online weight */
|
||||
class online_reps final
|
||||
{
|
||||
public:
|
||||
online_reps (nano::ledger & ledger_a, nano::network_params & network_params_a, nano::uint128_t minimum_a);
|
||||
online_reps (nano::ledger & ledger_a, nano::node_config const & config_a);
|
||||
/** Add voting account \p rep_account to the set of online representatives */
|
||||
void observe (nano::account const & rep_account);
|
||||
/** Called periodically to sample online weight */
|
||||
void sample ();
|
||||
/** Returns the trended online stake, but never less than configured minimum */
|
||||
nano::uint128_t online_stake () const;
|
||||
/** Returns the trended online stake */
|
||||
nano::uint128_t trended () const;
|
||||
/** Returns the current online stake */
|
||||
nano::uint128_t online () const;
|
||||
/** Returns the quorum required for confirmation*/
|
||||
nano::uint128_t delta () const;
|
||||
/** List of online representatives, both the currently sampling ones and the ones observed in the previous sampling period */
|
||||
std::vector<nano::account> list ();
|
||||
void clear ();
|
||||
|
||||
private:
|
||||
nano::uint128_t trend (nano::transaction &);
|
||||
class rep_info
|
||||
{
|
||||
public:
|
||||
std::chrono::steady_clock::time_point time;
|
||||
nano::account account;
|
||||
};
|
||||
class tag_time
|
||||
{
|
||||
};
|
||||
class tag_account
|
||||
{
|
||||
};
|
||||
nano::uint128_t calculate_trend (nano::transaction &) const;
|
||||
nano::uint128_t calculate_online () const;
|
||||
mutable std::mutex mutex;
|
||||
nano::ledger & ledger;
|
||||
nano::network_params & network_params;
|
||||
std::unordered_set<nano::account> reps;
|
||||
std::unordered_set<nano::account> last_reps;
|
||||
nano::uint128_t online;
|
||||
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 std::unique_ptr<container_info_component> collect_container_info (online_reps & online_reps, const std::string & name);
|
||||
|
|
|
@ -84,7 +84,7 @@ void nano::rep_crawler::ongoing_crawl ()
|
|||
update_weights ();
|
||||
validate ();
|
||||
query (get_crawl_targets (total_weight_l));
|
||||
auto sufficient_weight (total_weight_l > node.config.online_weight_minimum.number ());
|
||||
auto sufficient_weight (total_weight_l > node.online_reps.delta ());
|
||||
// If online weight drops below minimum, reach out to preconfigured peers
|
||||
if (!sufficient_weight)
|
||||
{
|
||||
|
@ -107,7 +107,7 @@ std::vector<std::shared_ptr<nano::transport::channel>> nano::rep_crawler::get_cr
|
|||
constexpr size_t aggressive_count = 40;
|
||||
|
||||
// Crawl more aggressively if we lack sufficient total peer weight.
|
||||
bool sufficient_weight (total_weight_a > node.config.online_weight_minimum.number ());
|
||||
bool sufficient_weight (total_weight_a > node.online_reps.delta ());
|
||||
uint16_t required_peer_count = sufficient_weight ? conservative_count : aggressive_count;
|
||||
|
||||
// Add random peers. We do this even if we have enough weight, in order to pick up reps
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include <nano/lib/threading.hpp>
|
||||
#include <nano/lib/timer.hpp>
|
||||
#include <nano/node/active_transactions.hpp>
|
||||
#include <nano/node/node.hpp>
|
||||
#include <nano/node/node_observers.hpp>
|
||||
#include <nano/node/nodeconfig.hpp>
|
||||
#include <nano/node/online_reps.hpp>
|
||||
|
@ -257,7 +256,7 @@ void nano::vote_processor::calculate_weights ()
|
|||
representatives_1.clear ();
|
||||
representatives_2.clear ();
|
||||
representatives_3.clear ();
|
||||
auto supply (online_reps.online_stake ());
|
||||
auto supply (online_reps.trended ());
|
||||
auto rep_amounts = ledger.cache.rep_weights.get_rep_amounts ();
|
||||
for (auto const & rep_amount : rep_amounts)
|
||||
{
|
||||
|
|
|
@ -60,9 +60,7 @@ private:
|
|||
nano::online_reps & online_reps;
|
||||
nano::ledger & ledger;
|
||||
nano::network_params & network_params;
|
||||
|
||||
size_t max_votes;
|
||||
|
||||
std::deque<std::pair<std::shared_ptr<nano::vote>, std::shared_ptr<nano::transport::channel>>> votes;
|
||||
/** Representatives levels for random early detection */
|
||||
std::unordered_set<nano::account> representatives_1;
|
||||
|
|
|
@ -5983,7 +5983,7 @@ TEST (rpc, online_reps)
|
|||
auto node2 = add_ipc_enabled_node (system);
|
||||
nano::keypair key;
|
||||
system.wallet (0)->insert_adhoc (nano::dev_genesis_key.prv);
|
||||
ASSERT_TRUE (node2->online_reps.online_stake () == node2->config.online_weight_minimum.number ());
|
||||
ASSERT_TRUE (node2->online_reps.online () == node2->config.online_weight_minimum.number ());
|
||||
auto send_block (system.wallet (0)->send_action (nano::dev_genesis_key.pub, key.pub, nano::Gxrb_ratio));
|
||||
ASSERT_NE (nullptr, send_block);
|
||||
scoped_io_thread_name_change scoped_thread_name_io;
|
||||
|
|
|
@ -522,7 +522,7 @@ TEST (confirmation_height, many_accounts_single_confirmation)
|
|||
nano::keypair key;
|
||||
system.wallet (0)->insert_adhoc (key.prv);
|
||||
|
||||
nano::send_block send (last_open_hash, key.pub, node->config.online_weight_minimum.number (), last_keypair.prv, last_keypair.pub, *system.work.generate (last_open_hash));
|
||||
nano::send_block send (last_open_hash, key.pub, node->online_reps.delta (), last_keypair.prv, last_keypair.pub, *system.work.generate (last_open_hash));
|
||||
ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, send).code);
|
||||
nano::open_block open (send.hash (), last_keypair.pub, key.pub, key.prv, key.pub, *system.work.generate (key.pub));
|
||||
ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, open).code);
|
||||
|
@ -591,7 +591,7 @@ TEST (confirmation_height, many_accounts_many_confirmations)
|
|||
nano::keypair key;
|
||||
system.wallet (0)->insert_adhoc (key.prv);
|
||||
|
||||
nano::send_block send (ladev_genesis, key.pub, node->config.online_weight_minimum.number (), nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (ladev_genesis));
|
||||
nano::send_block send (ladev_genesis, key.pub, node->online_reps.delta (), nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *system.work.generate (ladev_genesis));
|
||||
ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, send).code);
|
||||
auto open = std::make_shared<nano::open_block> (send.hash (), nano::dev_genesis_key.pub, key.pub, key.prv, key.pub, *system.work.generate (key.pub));
|
||||
ASSERT_EQ (nano::process_result::progress, node->ledger.process (transaction, *open).code);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue