Using a quorum derived from votes observed on the network instead of configured in the node.
online_weight_minimum sets a minimum expected online vote weight to be observed, underwhich we're assumed to be disconnected. online_weight_quorum is a percentage delta of the online vote weight that needs to exist between the winning block and the next highest voted block before it's accepted as confirmed. Receiving blocks by the internal wallets will no longer be done always after time expirery and will only be done if the quorum threshold is reached.
This commit is contained in:
commit
ac1bb737f0
9 changed files with 161 additions and 222 deletions
|
@ -1494,54 +1494,6 @@ TEST (ledger, latest_root)
|
|||
ASSERT_EQ (send.hash (), ledger.latest_root (transaction, rai::test_genesis_key.pub));
|
||||
}
|
||||
|
||||
TEST (ledger, supply_cache)
|
||||
{
|
||||
bool init (false);
|
||||
rai::block_store store (init, rai::unique_path ());
|
||||
ASSERT_TRUE (!init);
|
||||
rai::stat stats;
|
||||
rai::ledger ledger (store, stats, 40);
|
||||
{
|
||||
rai::transaction transaction (store.environment, nullptr, true);
|
||||
rai::genesis genesis;
|
||||
genesis.initialize (transaction, store);
|
||||
rai::keypair key2;
|
||||
rai::account_info info1;
|
||||
ASSERT_FALSE (store.account_get (transaction, rai::test_genesis_key.pub, info1));
|
||||
rai::send_block send (info1.head, key2.pub, std::numeric_limits<rai::uint128_t>::max () - 50, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
|
||||
ledger.process (transaction, send);
|
||||
}
|
||||
|
||||
// Cached (default)
|
||||
ASSERT_NE (10, ledger.supply.circulating_get ());
|
||||
// Uncached
|
||||
ASSERT_EQ (10, ledger.supply.circulating_get (true));
|
||||
}
|
||||
|
||||
TEST (ledger, inactive_supply)
|
||||
{
|
||||
bool init (false);
|
||||
rai::block_store store (init, rai::unique_path ());
|
||||
ASSERT_TRUE (!init);
|
||||
rai::stat stats;
|
||||
rai::ledger ledger (store, stats, 40);
|
||||
{
|
||||
rai::transaction transaction (store.environment, nullptr, true);
|
||||
rai::genesis genesis;
|
||||
genesis.initialize (transaction, store);
|
||||
rai::keypair key2;
|
||||
rai::account_info info1;
|
||||
ASSERT_FALSE (store.account_get (transaction, rai::test_genesis_key.pub, info1));
|
||||
rai::send_block send (info1.head, key2.pub, std::numeric_limits<rai::uint128_t>::max () - 50, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
|
||||
ledger.process (transaction, send);
|
||||
}
|
||||
ASSERT_EQ (10, ledger.supply.circulating_get (true));
|
||||
ledger.supply.inactive_set (60);
|
||||
ASSERT_EQ (0, ledger.supply.circulating_get (true));
|
||||
ledger.supply.inactive_set (0);
|
||||
ASSERT_EQ (50, ledger.supply.circulating_get (true));
|
||||
}
|
||||
|
||||
TEST (ledger, change_representative_move_representation)
|
||||
{
|
||||
bool init (false);
|
||||
|
@ -2354,8 +2306,7 @@ TEST (ledger, state_canary_blocks)
|
|||
rai::genesis genesis;
|
||||
rai::send_block parse_canary (genesis.hash (), rai::test_genesis_key.pub, rai::genesis_amount, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
|
||||
rai::send_block generate_canary (parse_canary.hash (), rai::test_genesis_key.pub, rai::genesis_amount, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
|
||||
rai::stat stats;
|
||||
rai::ledger ledger (store, stats, 0, parse_canary.hash (), generate_canary.hash ());
|
||||
rai::ledger ledger (store, stats, parse_canary.hash (), generate_canary.hash ());
|
||||
rai::transaction transaction (store.environment, nullptr, true);
|
||||
genesis.initialize (transaction, store);
|
||||
rai::state_block state (rai::test_genesis_key.pub, genesis.hash (), rai::test_genesis_key.pub, rai::genesis_amount - rai::Gxrb_ratio, rai::test_genesis_key.pub, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
|
||||
|
|
|
@ -27,21 +27,6 @@ TEST (node, block_store_path_failure)
|
|||
node->stop ();
|
||||
}
|
||||
|
||||
TEST (node, inactive_supply)
|
||||
{
|
||||
rai::node_init init;
|
||||
auto service (boost::make_shared<boost::asio::io_service> ());
|
||||
rai::alarm alarm (*service);
|
||||
auto path (rai::unique_path ());
|
||||
rai::node_config config;
|
||||
config.logging.init (path);
|
||||
rai::work_pool work (std::numeric_limits<unsigned>::max (), nullptr);
|
||||
config.inactive_supply = 10;
|
||||
auto node (std::make_shared<rai::node> (init, *service, path, alarm, config, work));
|
||||
ASSERT_EQ (10, node->ledger.supply.inactive_get ());
|
||||
node->stop ();
|
||||
}
|
||||
|
||||
TEST (node, state_canaries)
|
||||
{
|
||||
rai::node_init init;
|
||||
|
@ -199,7 +184,8 @@ TEST (node, quick_confirm)
|
|||
rai::keypair key;
|
||||
rai::block_hash previous (system.nodes[0]->latest (rai::test_genesis_key.pub));
|
||||
system.wallet (0)->insert_adhoc (key.prv);
|
||||
auto send (std::make_shared<rai::send_block> (previous, key.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (previous)));
|
||||
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
|
||||
auto send (std::make_shared<rai::send_block> (previous, key.pub, system.nodes[0]->delta () + 1, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (previous)));
|
||||
system.nodes[0]->process_active (send);
|
||||
auto iterations (0);
|
||||
while (system.nodes[0]->balance (key.pub).is_zero ())
|
||||
|
@ -210,6 +196,38 @@ TEST (node, quick_confirm)
|
|||
}
|
||||
}
|
||||
|
||||
TEST (node, node_receive_quorum)
|
||||
{
|
||||
rai::system system (24000, 1);
|
||||
rai::keypair key;
|
||||
rai::block_hash previous (system.nodes[0]->latest (rai::test_genesis_key.pub));
|
||||
system.wallet (0)->insert_adhoc (key.prv);
|
||||
auto send (std::make_shared<rai::send_block> (previous, key.pub, rai::genesis_amount - rai::Gxrb_ratio, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (previous)));
|
||||
system.nodes[0]->process_active (send);
|
||||
auto iterations (0);
|
||||
while (!system.nodes[0]->ledger.block_exists (send->hash ()))
|
||||
{
|
||||
system.poll ();
|
||||
++iterations;
|
||||
ASSERT_LT (iterations, 200);
|
||||
}
|
||||
while (!system.nodes[0]->active.roots.empty ())
|
||||
{
|
||||
system.poll ();
|
||||
++iterations;
|
||||
ASSERT_LT (iterations, 200);
|
||||
}
|
||||
ASSERT_TRUE (system.nodes[0]->balance (key.pub).is_zero ());
|
||||
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
|
||||
system.nodes[0]->block_confirm (send);
|
||||
while (system.nodes[0]->balance (key.pub).is_zero ())
|
||||
{
|
||||
system.poll ();
|
||||
++iterations;
|
||||
ASSERT_LT (iterations, 200);
|
||||
}
|
||||
}
|
||||
|
||||
TEST (node, auto_bootstrap)
|
||||
{
|
||||
rai::system system (24000, 1);
|
||||
|
@ -506,7 +524,8 @@ TEST (node_config, serialization)
|
|||
rai::node_config config1 (100, logging1);
|
||||
config1.bootstrap_fraction_numerator = 10;
|
||||
config1.receive_minimum = 10;
|
||||
config1.inactive_supply = 10;
|
||||
config1.online_weight_minimum = 10;
|
||||
config1.online_weight_quorom = 10;
|
||||
config1.password_fanout = 10;
|
||||
config1.enable_voting = false;
|
||||
config1.callback_address = "test";
|
||||
|
@ -524,7 +543,8 @@ TEST (node_config, serialization)
|
|||
ASSERT_NE (config2.bootstrap_fraction_numerator, config1.bootstrap_fraction_numerator);
|
||||
ASSERT_NE (config2.peering_port, config1.peering_port);
|
||||
ASSERT_NE (config2.logging.node_lifetime_tracing_value, config1.logging.node_lifetime_tracing_value);
|
||||
ASSERT_NE (config2.inactive_supply, config1.inactive_supply);
|
||||
ASSERT_NE (config2.online_weight_minimum, config1.online_weight_minimum);
|
||||
ASSERT_NE (config2.online_weight_quorom, config1.online_weight_quorom);
|
||||
ASSERT_NE (config2.password_fanout, config1.password_fanout);
|
||||
ASSERT_NE (config2.enable_voting, config1.enable_voting);
|
||||
ASSERT_NE (config2.callback_address, config1.callback_address);
|
||||
|
@ -540,7 +560,8 @@ TEST (node_config, serialization)
|
|||
ASSERT_EQ (config2.bootstrap_fraction_numerator, config1.bootstrap_fraction_numerator);
|
||||
ASSERT_EQ (config2.peering_port, config1.peering_port);
|
||||
ASSERT_EQ (config2.logging.node_lifetime_tracing_value, config1.logging.node_lifetime_tracing_value);
|
||||
ASSERT_EQ (config2.inactive_supply, config1.inactive_supply);
|
||||
ASSERT_EQ (config2.online_weight_minimum, config1.online_weight_minimum);
|
||||
ASSERT_EQ (config2.online_weight_quorom, config1.online_weight_quorom);
|
||||
ASSERT_EQ (config2.password_fanout, config1.password_fanout);
|
||||
ASSERT_EQ (config2.enable_voting, config1.enable_voting);
|
||||
ASSERT_EQ (config2.callback_address, config1.callback_address);
|
||||
|
@ -651,7 +672,7 @@ TEST (node_config, v2_v3_upgrade)
|
|||
ASSERT_FALSE (tree.get_optional<std::string> ("io_threads"));
|
||||
ASSERT_FALSE (tree.get_optional<std::string> ("work_threads"));
|
||||
config1.deserialize_json (upgraded, tree);
|
||||
ASSERT_EQ (rai::uint128_union (0).to_string_dec (), tree.get<std::string> ("inactive_supply"));
|
||||
//ASSERT_EQ (rai::uint128_union (0).to_string_dec (), tree.get<std::string> ("inactive_supply"));
|
||||
ASSERT_EQ ("1024", tree.get<std::string> ("password_fanout"));
|
||||
ASSERT_NE (0, std::stoul (tree.get<std::string> ("password_fanout")));
|
||||
ASSERT_NE (0, std::stoul (tree.get<std::string> ("password_fanout")));
|
||||
|
@ -1167,7 +1188,7 @@ TEST (node, rep_self_vote)
|
|||
auto & active (node0->active);
|
||||
{
|
||||
rai::transaction transaction (node0->store.environment, nullptr, true);
|
||||
active.start (transaction, block0, [](std::shared_ptr<rai::block>, bool) {});
|
||||
active.start (transaction, block0);
|
||||
}
|
||||
auto existing (active.roots.find (block0->root ()));
|
||||
ASSERT_NE (active.roots.end (), existing);
|
||||
|
@ -1330,7 +1351,7 @@ TEST (node, no_voting)
|
|||
// Broadcast a confirm so others should know this is a rep node
|
||||
wallet0->send_action (rai::test_genesis_key.pub, key1.pub, rai::Mxrb_ratio);
|
||||
auto iterations (0);
|
||||
while (node1.balance (key1.pub).is_zero ())
|
||||
while (!node1.active.roots.empty ())
|
||||
{
|
||||
system.poll ();
|
||||
++iterations;
|
||||
|
@ -1449,6 +1470,7 @@ TEST (node, bootstrap_connection_scaling)
|
|||
auto & node1 (*system.nodes[0]);
|
||||
node1.bootstrap_initiator.bootstrap ();
|
||||
auto attempt (node1.bootstrap_initiator.current_attempt ());
|
||||
ASSERT_NE (nullptr, attempt);
|
||||
ASSERT_EQ (34, attempt->target_connections (25000));
|
||||
ASSERT_EQ (4, attempt->target_connections (0));
|
||||
ASSERT_EQ (64, attempt->target_connections (50000));
|
||||
|
@ -1484,10 +1506,10 @@ TEST (node, online_reps)
|
|||
{
|
||||
rai::system system (24000, 2);
|
||||
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
|
||||
ASSERT_TRUE (system.nodes[1]->online_reps.online_stake ().is_zero ());
|
||||
ASSERT_EQ (system.nodes[1]->config.online_weight_minimum.number (), system.nodes[1]->online_reps.online_stake ());
|
||||
system.wallet (0)->send_action (rai::test_genesis_key.pub, rai::test_genesis_key.pub, rai::Gxrb_ratio);
|
||||
auto iterations (0);
|
||||
while (system.nodes[1]->online_reps.online_stake ().is_zero ())
|
||||
while (system.nodes[1]->online_reps.online_stake () == system.nodes[1]->config.online_weight_minimum.number ())
|
||||
{
|
||||
system.poll ();
|
||||
++iterations;
|
||||
|
@ -1563,3 +1585,34 @@ TEST (node, block_arrival_time)
|
|||
node.block_arrival.recent (0);
|
||||
ASSERT_EQ (rai::block_arrival::arrival_size_min * 2, node.block_arrival.arrival.size ());
|
||||
}
|
||||
|
||||
TEST (node, confirm_quorom)
|
||||
{
|
||||
rai::system system (24000, 1);
|
||||
rai::genesis genesis;
|
||||
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
|
||||
system.nodes[0]->ledger.state_block_parse_canary = genesis.hash ();
|
||||
// Put greater than online_weight_minimum in pending so quorom can't be reached
|
||||
auto send1 (std::make_shared<rai::state_block> (rai::test_genesis_key.pub, genesis.hash (), rai::test_genesis_key.pub, rai::Gxrb_ratio, rai::test_genesis_key.pub, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.nodes[0]->generate_work (genesis.hash ())));
|
||||
{
|
||||
rai::transaction transaction (system.nodes[0]->store.environment, nullptr, true);
|
||||
ASSERT_EQ (rai::process_result::progress, system.nodes[0]->ledger.process (transaction, *send1).code);
|
||||
}
|
||||
system.wallet (0)->send_action (rai::test_genesis_key.pub, rai::test_genesis_key.pub, rai::Gxrb_ratio);
|
||||
auto iterations (0);
|
||||
while (system.nodes[0]->active.roots.empty ())
|
||||
{
|
||||
system.poll ();
|
||||
++iterations;
|
||||
ASSERT_LT (iterations, 200);
|
||||
}
|
||||
ASSERT_FALSE (system.nodes[0]->active.roots.empty ());
|
||||
while (!system.nodes[0]->active.roots.empty ())
|
||||
{
|
||||
system.poll ();
|
||||
++iterations;
|
||||
ASSERT_LT (iterations, 200);
|
||||
}
|
||||
ASSERT_TRUE (system.nodes[0]->active.roots.empty ());
|
||||
ASSERT_EQ (0, system.nodes[0]->balance (rai::test_genesis_key.pub));
|
||||
}
|
||||
|
|
|
@ -3516,10 +3516,10 @@ TEST (rpc, online_reps)
|
|||
{
|
||||
rai::system system (24000, 2);
|
||||
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
|
||||
ASSERT_TRUE (system.nodes[1]->online_reps.online_stake ().is_zero ());
|
||||
ASSERT_TRUE (system.nodes[1]->online_reps.online_stake () == system.nodes[1]->config.online_weight_minimum.number ());
|
||||
system.wallet (0)->send_action (rai::test_genesis_key.pub, rai::test_genesis_key.pub, rai::Gxrb_ratio);
|
||||
auto iterations (0);
|
||||
while (system.nodes[1]->online_reps.online_stake ().is_zero ())
|
||||
while (system.nodes[1]->online_reps.online_stake () == system.nodes[1]->config.online_weight_minimum.number ())
|
||||
{
|
||||
system.poll ();
|
||||
++iterations;
|
||||
|
|
|
@ -505,53 +505,12 @@ bool rai::shared_ptr_block_hash::operator() (std::shared_ptr<rai::block> const &
|
|||
return *lhs == *rhs;
|
||||
}
|
||||
|
||||
rai::supply::supply (rai::ledger & ledger_a, rai::uint128_t const & inactive_supply_a) :
|
||||
ledger (ledger_a),
|
||||
inactive_supply (inactive_supply_a)
|
||||
{
|
||||
circulating_update ();
|
||||
}
|
||||
|
||||
rai::uint128_t rai::supply::circulating_get (bool force_update)
|
||||
{
|
||||
rai::uint128_t supply;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock (mutex);
|
||||
if (force_update)
|
||||
{
|
||||
update_cache ();
|
||||
}
|
||||
supply = cached_supply;
|
||||
}
|
||||
return supply;
|
||||
}
|
||||
|
||||
void rai::supply::circulating_update ()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock (mutex);
|
||||
update_cache ();
|
||||
}
|
||||
|
||||
void rai::supply::update_cache ()
|
||||
{
|
||||
if (ledger.store.environment)
|
||||
{
|
||||
rai::transaction transaction (ledger.store.environment, nullptr, false);
|
||||
auto unallocated (ledger.account_balance (transaction, rai::genesis_account));
|
||||
auto burned (ledger.account_pending (transaction, 0));
|
||||
auto absolute_supply (rai::genesis_amount - unallocated - burned);
|
||||
auto adjusted_supply (absolute_supply - inactive_supply);
|
||||
cached_supply = adjusted_supply <= absolute_supply ? adjusted_supply : 0;
|
||||
}
|
||||
}
|
||||
|
||||
rai::ledger::ledger (rai::block_store & store_a, rai::stat & stat_a, rai::uint128_t const & inactive_supply_a, rai::block_hash const & state_block_parse_canary_a, rai::block_hash const & state_block_generate_canary_a) :
|
||||
rai::ledger::ledger (rai::block_store & store_a, rai::stat & stat_a, rai::block_hash const & state_block_parse_canary_a, rai::block_hash const & state_block_generate_canary_a) :
|
||||
store (store_a),
|
||||
stats (stat_a),
|
||||
check_bootstrap_weights (true),
|
||||
state_block_parse_canary (state_block_parse_canary_a),
|
||||
state_block_generate_canary (state_block_generate_canary_a),
|
||||
supply (*this, inactive_supply_a)
|
||||
state_block_generate_canary (state_block_generate_canary_a)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -13,36 +13,14 @@ public:
|
|||
size_t operator() (std::shared_ptr<rai::block> const &) const;
|
||||
bool operator() (std::shared_ptr<rai::block> const &, std::shared_ptr<rai::block> const &) const;
|
||||
};
|
||||
class ledger;
|
||||
class supply
|
||||
{
|
||||
public:
|
||||
supply (rai::ledger & ledger_a, rai::uint128_t const & inactive_supply_a);
|
||||
rai::uint128_t circulating_get (bool force_update = false);
|
||||
void circulating_update ();
|
||||
inline rai::uint128_t inactive_get () const
|
||||
{
|
||||
return inactive_supply;
|
||||
};
|
||||
inline void inactive_set (rai::uint128_t const & inactive_supply_a)
|
||||
{
|
||||
inactive_supply = inactive_supply_a;
|
||||
};
|
||||
|
||||
private:
|
||||
void update_cache ();
|
||||
rai::ledger & ledger;
|
||||
rai::uint128_t inactive_supply;
|
||||
rai::uint128_t cached_supply;
|
||||
std::mutex mutex;
|
||||
};
|
||||
using tally_t = std::map<rai::uint128_t, std::shared_ptr<rai::block>, std::greater<rai::uint128_t>>;
|
||||
class ledger
|
||||
{
|
||||
public:
|
||||
ledger (rai::block_store &, rai::stat &, rai::uint128_t const & = 0, rai::block_hash const & = 0, rai::block_hash const & = 0);
|
||||
ledger (rai::block_store &, rai::stat &, rai::block_hash const & = 0, rai::block_hash const & = 0);
|
||||
std::pair<rai::uint128_t, std::shared_ptr<rai::block>> winner (MDB_txn *, rai::votes const & votes_a);
|
||||
// Map of weight -> associated block, ordered greatest to least
|
||||
std::map<rai::uint128_t, std::shared_ptr<rai::block>, std::greater<rai::uint128_t>> tally (MDB_txn *, rai::votes const &);
|
||||
rai::tally_t tally (MDB_txn *, rai::votes const &);
|
||||
rai::account account (MDB_txn *, rai::block_hash const &);
|
||||
rai::uint128_t amount (MDB_txn *, rai::block_hash const &);
|
||||
rai::uint128_t balance (MDB_txn *, rai::block_hash const &);
|
||||
|
@ -77,6 +55,5 @@ public:
|
|||
std::atomic<bool> check_bootstrap_weights;
|
||||
rai::block_hash state_block_parse_canary;
|
||||
rai::block_hash state_block_generate_canary;
|
||||
rai::supply supply;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1043,22 +1043,19 @@ void rai::bootstrap_attempt::process_fork (MDB_txn * transaction_a, std::shared_
|
|||
if (ledger_block)
|
||||
{
|
||||
std::weak_ptr<rai::bootstrap_attempt> this_w (shared_from_this ());
|
||||
if (!node->active.start (transaction_a, std::make_pair (ledger_block, block_a), [this_w, root](std::shared_ptr<rai::block>, bool resolved) {
|
||||
if (!node->active.start (transaction_a, std::make_pair (ledger_block, block_a), [this_w, root](std::shared_ptr<rai::block>) {
|
||||
if (auto this_l = this_w.lock ())
|
||||
{
|
||||
if (resolved)
|
||||
{
|
||||
rai::transaction transaction (this_l->node->store.environment, nullptr, false);
|
||||
auto account (this_l->node->ledger.store.frontier_get (transaction, root));
|
||||
if (!account.is_zero ())
|
||||
{
|
||||
this_l->requeue_pull (rai::pull_info (account, root, root));
|
||||
}
|
||||
else if (this_l->node->ledger.store.account_exists (transaction, root))
|
||||
{
|
||||
this_l->requeue_pull (rai::pull_info (root, rai::block_hash (0), rai::block_hash (0)));
|
||||
}
|
||||
}
|
||||
rai::transaction transaction (this_l->node->store.environment, nullptr, false);
|
||||
auto account (this_l->node->ledger.store.frontier_get (transaction, root));
|
||||
if (!account.is_zero ())
|
||||
{
|
||||
this_l->requeue_pull (rai::pull_info (account, root, root));
|
||||
}
|
||||
else if (this_l->node->ledger.store.account_exists (transaction, root))
|
||||
{
|
||||
this_l->requeue_pull (rai::pull_info (root, rai::block_hash (0), rai::block_hash (0)));
|
||||
}
|
||||
}
|
||||
}))
|
||||
{
|
||||
|
|
|
@ -797,7 +797,8 @@ peering_port (peering_port_a),
|
|||
logging (logging_a),
|
||||
bootstrap_fraction_numerator (1),
|
||||
receive_minimum (rai::xrb_ratio),
|
||||
inactive_supply (0),
|
||||
online_weight_minimum (60000 * rai::Gxrb_ratio),
|
||||
online_weight_quorom (50),
|
||||
password_fanout (1024),
|
||||
io_threads (std::max<unsigned> (4, std::thread::hardware_concurrency ())),
|
||||
work_threads (std::max<unsigned> (4, std::thread::hardware_concurrency ())),
|
||||
|
@ -841,7 +842,7 @@ state_block_generate_canary (0)
|
|||
|
||||
void rai::node_config::serialize_json (boost::property_tree::ptree & tree_a) const
|
||||
{
|
||||
tree_a.put ("version", "10");
|
||||
tree_a.put ("version", "11");
|
||||
tree_a.put ("peering_port", std::to_string (peering_port));
|
||||
tree_a.put ("bootstrap_fraction_numerator", std::to_string (bootstrap_fraction_numerator));
|
||||
tree_a.put ("receive_minimum", receive_minimum.to_string_dec ());
|
||||
|
@ -872,7 +873,8 @@ void rai::node_config::serialize_json (boost::property_tree::ptree & tree_a) con
|
|||
preconfigured_representatives_l.push_back (std::make_pair ("", entry));
|
||||
}
|
||||
tree_a.add_child ("preconfigured_representatives", preconfigured_representatives_l);
|
||||
tree_a.put ("inactive_supply", inactive_supply.to_string_dec ());
|
||||
tree_a.put ("online_weight_minimum", online_weight_minimum.to_string_dec ());
|
||||
tree_a.put ("online_weight_quorom", std::to_string (online_weight_quorom));
|
||||
tree_a.put ("password_fanout", std::to_string (password_fanout));
|
||||
tree_a.put ("io_threads", std::to_string (io_threads));
|
||||
tree_a.put ("work_threads", std::to_string (work_threads));
|
||||
|
@ -965,6 +967,13 @@ bool rai::node_config::upgrade_json (unsigned version, boost::property_tree::ptr
|
|||
tree_a.put ("version", "10");
|
||||
result = true;
|
||||
case 10:
|
||||
tree_a.put ("online_weight_minimum", online_weight_minimum.to_string_dec ());
|
||||
tree_a.put ("online_weight_quorom", std::to_string (online_weight_quorom));
|
||||
tree_a.erase ("inactive_supply");
|
||||
tree_a.erase ("version");
|
||||
tree_a.put ("version", "11");
|
||||
result = true;
|
||||
case 11:
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error ("Unknown node_config version");
|
||||
|
@ -1031,7 +1040,8 @@ bool rai::node_config::deserialize_json (bool & upgraded_a, boost::property_tree
|
|||
{
|
||||
result |= stat_config.deserialize_json (stat_config_l.get ());
|
||||
}
|
||||
auto inactive_supply_l (tree_a.get<std::string> ("inactive_supply"));
|
||||
auto online_weight_minimum_l (tree_a.get<std::string> ("online_weight_minimum"));
|
||||
auto online_weight_quorom_l (tree_a.get<std::string> ("online_weight_quorom"));
|
||||
auto password_fanout_l (tree_a.get<std::string> ("password_fanout"));
|
||||
auto io_threads_l (tree_a.get<std::string> ("io_threads"));
|
||||
auto work_threads_l (tree_a.get<std::string> ("work_threads"));
|
||||
|
@ -1055,10 +1065,12 @@ bool rai::node_config::deserialize_json (bool & upgraded_a, boost::property_tree
|
|||
bootstrap_connections = std::stoul (bootstrap_connections_l);
|
||||
bootstrap_connections_max = std::stoul (bootstrap_connections_max_l);
|
||||
lmdb_max_dbs = std::stoi (lmdb_max_dbs_l);
|
||||
online_weight_quorom = std::stoul (online_weight_quorom_l);
|
||||
result |= peering_port > std::numeric_limits<uint16_t>::max ();
|
||||
result |= logging.deserialize_json (upgraded_a, logging_l);
|
||||
result |= receive_minimum.decode_dec (receive_minimum_l);
|
||||
result |= inactive_supply.decode_dec (inactive_supply_l);
|
||||
result |= online_weight_minimum.decode_dec (online_weight_minimum_l);
|
||||
result |= online_weight_quorom > 100;
|
||||
result |= password_fanout < 16;
|
||||
result |= password_fanout > 1024 * 1024;
|
||||
result |= io_threads == 0;
|
||||
|
@ -1251,7 +1263,6 @@ bool rai::block_processor::have_blocks ()
|
|||
|
||||
void rai::block_processor::process_receive_many (std::unique_lock<std::mutex> & lock_a)
|
||||
{
|
||||
std::deque<std::pair<std::shared_ptr<rai::block>, rai::process_return>> progress;
|
||||
{
|
||||
rai::transaction transaction (node.store.environment, nullptr, true);
|
||||
auto cutoff (std::chrono::steady_clock::now () + rai::transaction_timeout);
|
||||
|
@ -1462,7 +1473,7 @@ alarm (alarm_a),
|
|||
work (work_a),
|
||||
store (init_a.block_store_init, application_path_a / "data.ldb", config_a.lmdb_max_dbs),
|
||||
gap_cache (*this),
|
||||
ledger (store, stats, config_a.inactive_supply.number (), config.state_block_parse_canary, config.state_block_generate_canary),
|
||||
ledger (store, stats, config.state_block_parse_canary, config.state_block_generate_canary),
|
||||
active (*this),
|
||||
network (*this, config.peering_port),
|
||||
bootstrap_initiator (*this),
|
||||
|
@ -1607,7 +1618,7 @@ stats (config.stat_config)
|
|||
{
|
||||
rai::transaction transaction (store.environment, nullptr, false);
|
||||
rep_weight = ledger.weight (transaction, vote_a->account);
|
||||
min_rep_weight = ledger.supply.circulating_get () / 1000;
|
||||
min_rep_weight = online_reps.online_stake () / 1000;
|
||||
}
|
||||
if (rep_weight > min_rep_weight)
|
||||
{
|
||||
|
@ -1762,7 +1773,7 @@ void rai::gap_cache::vote (std::shared_ptr<rai::vote> vote_a)
|
|||
|
||||
rai::uint128_t rai::gap_cache::bootstrap_threshold (MDB_txn * transaction_a)
|
||||
{
|
||||
auto result ((node.ledger.supply.circulating_get () / 256) * node.config.bootstrap_fraction_numerator);
|
||||
auto result ((node.online_reps.online_stake () / 256) * node.config.bootstrap_fraction_numerator);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1962,7 +1973,6 @@ void rai::node::start ()
|
|||
ongoing_bootstrap ();
|
||||
ongoing_store_flush ();
|
||||
ongoing_rep_crawl ();
|
||||
ongoing_supply_update ();
|
||||
bootstrap.start ();
|
||||
backup_wallet ();
|
||||
active.announce_votes ();
|
||||
|
@ -2058,18 +2068,6 @@ void rai::node::ongoing_keepalive ()
|
|||
});
|
||||
}
|
||||
|
||||
void rai::node::ongoing_supply_update ()
|
||||
{
|
||||
ledger.supply.circulating_update ();
|
||||
std::weak_ptr<rai::node> node_w (shared_from_this ());
|
||||
alarm.add (std::chrono::steady_clock::now () + std::chrono::minutes (5), [node_w]() {
|
||||
if (auto node_l = node_w.lock ())
|
||||
{
|
||||
node_l->ongoing_supply_update ();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void rai::node::ongoing_rep_crawl ()
|
||||
{
|
||||
auto now (std::chrono::steady_clock::now ());
|
||||
|
@ -2421,6 +2419,12 @@ void rai::node::block_confirm (std::shared_ptr<rai::block> block_a)
|
|||
network.broadcast_confirm_req (block_a);
|
||||
}
|
||||
|
||||
rai::uint128_t rai::node::delta ()
|
||||
{
|
||||
auto result ((online_reps.online_stake () / 100) * config.online_weight_quorom);
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class confirmed_visitor : public rai::block_visitor
|
||||
|
@ -2623,7 +2627,7 @@ void rai::online_reps::recalculate_stake ()
|
|||
rai::uint128_t rai::online_reps::online_stake ()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock (mutex);
|
||||
return online_stake_total;
|
||||
return std::max (online_stake_total, node.config.online_weight_minimum.number ());
|
||||
}
|
||||
|
||||
std::deque<rai::account> rai::online_reps::list ()
|
||||
|
@ -2997,7 +3001,7 @@ std::shared_ptr<rai::node> rai::node::shared ()
|
|||
return shared_from_this ();
|
||||
}
|
||||
|
||||
rai::election::election (MDB_txn * transaction_a, rai::node & node_a, std::shared_ptr<rai::block> block_a, std::function<void(std::shared_ptr<rai::block>, bool)> const & confirmation_action_a) :
|
||||
rai::election::election (MDB_txn * transaction_a, rai::node & node_a, std::shared_ptr<rai::block> block_a, std::function<void(std::shared_ptr<rai::block>)> const & confirmation_action_a) :
|
||||
confirmation_action (confirmation_action_a),
|
||||
votes (block_a),
|
||||
node (node_a),
|
||||
|
@ -3023,27 +3027,15 @@ void rai::election::broadcast_winner ()
|
|||
node.network.republish_block (transaction, status.winner);
|
||||
}
|
||||
|
||||
rai::uint128_t rai::election::quorum_threshold (MDB_txn * transaction_a, rai::ledger & ledger_a)
|
||||
{
|
||||
// Threshold over which unanimous voting implies confirmation
|
||||
return ledger_a.supply.circulating_get () / 2;
|
||||
}
|
||||
|
||||
rai::uint128_t rai::election::minimum_threshold (MDB_txn * transaction_a, rai::ledger & ledger_a)
|
||||
{
|
||||
// Minimum number of votes needed to change our ledger, under which we're probably disconnected
|
||||
return ledger_a.supply.circulating_get () / 16;
|
||||
}
|
||||
|
||||
void rai::election::confirm_once (MDB_txn * transaction_a)
|
||||
{
|
||||
if (!confirmed.exchange (true))
|
||||
{
|
||||
auto tally_l (node.ledger.tally (transaction_a, votes));
|
||||
assert (tally_l.size () > 0);
|
||||
auto have_quorum_l = have_quorum (tally_l);
|
||||
auto winner (tally_l.begin ());
|
||||
auto block_l (winner->second);
|
||||
auto exceeded_min_threshold = winner->first > minimum_threshold (transaction_a, node.ledger);
|
||||
if (node.config.logging.vote_logging () || !votes.uncontested ())
|
||||
{
|
||||
BOOST_LOG (node.log) << boost::str (boost::format ("Vote tally for root %1%") % status.winner->root ().to_string ());
|
||||
|
@ -3058,7 +3050,7 @@ void rai::election::confirm_once (MDB_txn * transaction_a)
|
|||
}
|
||||
if (!(*block_l == *status.winner))
|
||||
{
|
||||
if (exceeded_min_threshold)
|
||||
if (have_quorum_l)
|
||||
{
|
||||
auto node_l (node.shared ());
|
||||
node_l->block_processor.force (block_l);
|
||||
|
@ -3070,27 +3062,38 @@ void rai::election::confirm_once (MDB_txn * transaction_a)
|
|||
}
|
||||
}
|
||||
status.tally = winner->first;
|
||||
auto winner_l (status.winner);
|
||||
auto node_l (node.shared ());
|
||||
auto confirmation_action_l (confirmation_action);
|
||||
node.background ([winner_l, confirmation_action_l, node_l, exceeded_min_threshold]() {
|
||||
node_l->process_confirmed (winner_l);
|
||||
confirmation_action_l (winner_l, exceeded_min_threshold);
|
||||
});
|
||||
if (have_quorum_l)
|
||||
{
|
||||
auto winner_l (status.winner);
|
||||
auto node_l (node.shared ());
|
||||
auto confirmation_action_l (confirmation_action);
|
||||
node.background ([node_l, winner_l, confirmation_action_l]() {
|
||||
node_l->process_confirmed (winner_l);
|
||||
confirmation_action_l (winner_l);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_LOG (node.log) << boost::str (boost::format ("Insufficient quorum for block %1% %2%") % status.winner->hash ().to_string () % status.tally.number ().convert_to<std::string> ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool rai::election::have_quorum (MDB_txn * transaction_a)
|
||||
bool rai::election::have_quorum (rai::tally_t const & tally_a)
|
||||
{
|
||||
auto tally_l (node.ledger.tally (transaction_a, votes));
|
||||
assert (tally_l.size () > 0);
|
||||
auto result (tally_l.begin ()->first > quorum_threshold (transaction_a, node.ledger));
|
||||
auto i (tally_a.begin ());
|
||||
auto first (i->first);
|
||||
++i;
|
||||
auto second (i != tally_a.end () ? i->first : 0);
|
||||
auto delta_l (node.delta ());
|
||||
auto result (tally_a.begin ()->first > (second + delta_l));
|
||||
return result;
|
||||
}
|
||||
|
||||
void rai::election::confirm_if_quorum (MDB_txn * transaction_a)
|
||||
{
|
||||
auto quorum (have_quorum (transaction_a));
|
||||
auto tally_l (node.ledger.tally (transaction_a, votes));
|
||||
auto quorum (have_quorum (tally_l));
|
||||
if (quorum)
|
||||
{
|
||||
confirm_once (transaction_a);
|
||||
|
@ -3108,7 +3111,7 @@ bool rai::election::vote (std::shared_ptr<rai::vote> vote_a)
|
|||
// see republish_vote documentation for an explanation of these rules
|
||||
rai::transaction transaction (node.store.environment, nullptr, false);
|
||||
auto replay (false);
|
||||
auto supply (node.ledger.supply.circulating_get ());
|
||||
auto supply (node.online_reps.online_stake ());
|
||||
auto weight (node.ledger.weight (transaction, vote_a->account));
|
||||
if (rai::rai_network == rai::rai_networks::rai_test_network || weight > supply / 1000) // 0.1% or above
|
||||
{
|
||||
|
@ -3259,12 +3262,12 @@ void rai::active_transactions::stop ()
|
|||
roots.clear ();
|
||||
}
|
||||
|
||||
bool rai::active_transactions::start (MDB_txn * transaction_a, std::shared_ptr<rai::block> block_a, std::function<void(std::shared_ptr<rai::block>, bool)> const & confirmation_action_a)
|
||||
bool rai::active_transactions::start (MDB_txn * transaction_a, std::shared_ptr<rai::block> block_a, std::function<void(std::shared_ptr<rai::block>)> const & confirmation_action_a)
|
||||
{
|
||||
return start (transaction_a, std::make_pair (block_a, nullptr), confirmation_action_a);
|
||||
}
|
||||
|
||||
bool rai::active_transactions::start (MDB_txn * transaction_a, std::pair<std::shared_ptr<rai::block>, std::shared_ptr<rai::block>> blocks_a, std::function<void(std::shared_ptr<rai::block>, bool)> const & confirmation_action_a)
|
||||
bool rai::active_transactions::start (MDB_txn * transaction_a, std::pair<std::shared_ptr<rai::block>, std::shared_ptr<rai::block>> blocks_a, std::function<void(std::shared_ptr<rai::block>)> const & confirmation_action_a)
|
||||
{
|
||||
assert (blocks_a.first != nullptr);
|
||||
std::lock_guard<std::mutex> lock (mutex);
|
||||
|
|
|
@ -44,14 +44,14 @@ public:
|
|||
};
|
||||
class election : public std::enable_shared_from_this<rai::election>
|
||||
{
|
||||
std::function<void(std::shared_ptr<rai::block>, bool)> confirmation_action;
|
||||
std::function<void(std::shared_ptr<rai::block>)> confirmation_action;
|
||||
void confirm_once (MDB_txn *);
|
||||
|
||||
public:
|
||||
election (MDB_txn *, rai::node &, std::shared_ptr<rai::block>, std::function<void(std::shared_ptr<rai::block>, bool)> const &);
|
||||
election (MDB_txn *, rai::node &, std::shared_ptr<rai::block>, std::function<void(std::shared_ptr<rai::block>)> const &);
|
||||
bool vote (std::shared_ptr<rai::vote>);
|
||||
// Check if we have vote quorum
|
||||
bool have_quorum (MDB_txn *);
|
||||
bool have_quorum (rai::tally_t const &);
|
||||
// Tell the network our view of the winner
|
||||
void broadcast_winner ();
|
||||
// Change our winner to agree with the network
|
||||
|
@ -60,8 +60,6 @@ public:
|
|||
void confirm_if_quorum (MDB_txn *);
|
||||
// Confirmation method 2, settling time
|
||||
void confirm_cutoff (MDB_txn *);
|
||||
rai::uint128_t quorum_threshold (MDB_txn *, rai::ledger &);
|
||||
rai::uint128_t minimum_threshold (MDB_txn *, rai::ledger &);
|
||||
rai::votes votes;
|
||||
rai::node & node;
|
||||
std::unordered_map<rai::account, std::pair<std::chrono::steady_clock::time_point, uint64_t>> last_votes;
|
||||
|
@ -85,11 +83,11 @@ public:
|
|||
active_transactions (rai::node &);
|
||||
// Start an election for a block
|
||||
// Call action with confirmed block, may be different than what we started with
|
||||
bool start (MDB_txn *, std::shared_ptr<rai::block>, std::function<void(std::shared_ptr<rai::block>, bool)> const & = [](std::shared_ptr<rai::block>, bool) {});
|
||||
bool start (MDB_txn *, std::shared_ptr<rai::block>, std::function<void(std::shared_ptr<rai::block>)> const & = [](std::shared_ptr<rai::block>) {});
|
||||
// Also supply alternatives to block, to confirm_req reps with if the boolean argument is true
|
||||
// Should only be used for old elections
|
||||
// The first block should be the one in the ledger
|
||||
bool start (MDB_txn *, std::pair<std::shared_ptr<rai::block>, std::shared_ptr<rai::block>>, std::function<void(std::shared_ptr<rai::block>, bool)> const & = [](std::shared_ptr<rai::block>, bool) {});
|
||||
bool start (MDB_txn *, std::pair<std::shared_ptr<rai::block>, std::shared_ptr<rai::block>>, std::function<void(std::shared_ptr<rai::block>)> const & = [](std::shared_ptr<rai::block>) {});
|
||||
// If this returns true, the vote is a replay
|
||||
// If this returns false, the vote may or may not be a replay
|
||||
bool vote (std::shared_ptr<rai::vote>);
|
||||
|
@ -426,7 +424,8 @@ public:
|
|||
std::vector<rai::account> preconfigured_representatives;
|
||||
unsigned bootstrap_fraction_numerator;
|
||||
rai::amount receive_minimum;
|
||||
rai::amount inactive_supply;
|
||||
rai::amount online_weight_minimum;
|
||||
unsigned online_weight_quorom;
|
||||
unsigned password_fanout;
|
||||
unsigned io_threads;
|
||||
unsigned work_threads;
|
||||
|
@ -532,7 +531,6 @@ public:
|
|||
void ongoing_rep_crawl ();
|
||||
void ongoing_bootstrap ();
|
||||
void ongoing_store_flush ();
|
||||
void ongoing_supply_update ();
|
||||
void backup_wallet ();
|
||||
int price (rai::uint128_t const &, int);
|
||||
void generate_work (rai::block &);
|
||||
|
@ -540,6 +538,7 @@ public:
|
|||
void generate_work (rai::uint256_union const &, std::function<void(uint64_t)>);
|
||||
void add_initial_peers ();
|
||||
void block_confirm (std::shared_ptr<rai::block>);
|
||||
rai::uint128_t delta ();
|
||||
boost::asio::io_service & service;
|
||||
rai::node_config config;
|
||||
rai::alarm & alarm;
|
||||
|
|
|
@ -1229,7 +1229,7 @@ public:
|
|||
std::shared_ptr<rai::block> block_l (wallet->node.store.block_get (transaction, info.head));
|
||||
wallet->node.background ([this_l, account, block_l] {
|
||||
rai::transaction transaction (this_l->wallet->node.store.environment, nullptr, true);
|
||||
this_l->wallet->node.active.start (transaction, block_l, [this_l, account](std::shared_ptr<rai::block>, bool) {
|
||||
this_l->wallet->node.active.start (transaction, block_l, [this_l, account](std::shared_ptr<rai::block>) {
|
||||
// If there were any forks for this account they've been rolled back and we can receive anything remaining from this account
|
||||
this_l->receive_all (account);
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue