ledger::supply is a hotspot, so we memoize and update periodically. (#824)
This commit is contained in:
parent
06d0c0d000
commit
c942010228
6 changed files with 113 additions and 26 deletions
|
@ -1447,6 +1447,29 @@ 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::ledger ledger (store, 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);
|
||||
|
@ -1463,12 +1486,11 @@ TEST (ledger, inactive_supply)
|
|||
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);
|
||||
}
|
||||
rai::transaction transaction (store.environment, nullptr, false);
|
||||
ASSERT_EQ (10, ledger.supply (transaction));
|
||||
ledger.inactive_supply = 60;
|
||||
ASSERT_EQ (0, ledger.supply (transaction));
|
||||
ledger.inactive_supply = 0;
|
||||
ASSERT_EQ (50, ledger.supply (transaction));
|
||||
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)
|
||||
|
|
|
@ -38,7 +38,7 @@ TEST (node, inactive_supply)
|
|||
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.inactive_supply);
|
||||
ASSERT_EQ (10, node->ledger.supply.inactive_get ());
|
||||
node->stop ();
|
||||
}
|
||||
|
||||
|
|
|
@ -495,12 +495,52 @@ 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::uint128_t const & inactive_supply_a, rai::block_hash const & state_block_parse_canary_a, rai::block_hash const & state_block_generate_canary_a) :
|
||||
store (store_a),
|
||||
inactive_supply (inactive_supply_a),
|
||||
check_bootstrap_weights (true),
|
||||
state_block_parse_canary (state_block_parse_canary_a),
|
||||
state_block_generate_canary (state_block_generate_canary_a)
|
||||
state_block_generate_canary (state_block_generate_canary_a),
|
||||
supply (*this, inactive_supply_a)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -577,16 +617,6 @@ rai::process_return rai::ledger::process (MDB_txn * transaction_a, rai::block co
|
|||
return processor.result;
|
||||
}
|
||||
|
||||
// Money supply for heuristically calculating vote percentages
|
||||
rai::uint128_t rai::ledger::supply (MDB_txn * transaction_a)
|
||||
{
|
||||
auto unallocated (account_balance (transaction_a, rai::genesis_account));
|
||||
auto burned (account_pending (transaction_a, 0));
|
||||
auto absolute_supply (rai::genesis_amount - unallocated - burned);
|
||||
auto adjusted_supply (absolute_supply - inactive_supply);
|
||||
return adjusted_supply <= absolute_supply ? adjusted_supply : 0;
|
||||
}
|
||||
|
||||
rai::block_hash rai::ledger::representative (MDB_txn * transaction_a, rai::block_hash const & hash_a)
|
||||
{
|
||||
auto result (representative_calculated (transaction_a, hash_a));
|
||||
|
|
|
@ -12,7 +12,29 @@ 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;
|
||||
};
|
||||
class ledger
|
||||
{
|
||||
public:
|
||||
|
@ -38,7 +60,6 @@ public:
|
|||
bool is_send (MDB_txn *, rai::state_block const &);
|
||||
rai::block_hash block_destination (MDB_txn *, rai::block const &);
|
||||
rai::block_hash block_source (MDB_txn *, rai::block const &);
|
||||
rai::uint128_t supply (MDB_txn *);
|
||||
rai::process_return process (MDB_txn *, rai::block const &);
|
||||
void rollback (MDB_txn *, rai::block_hash const &);
|
||||
void change_latest (MDB_txn *, rai::account const &, rai::block_hash const &, rai::account const &, rai::uint128_union const &, uint64_t, bool = false);
|
||||
|
@ -49,11 +70,11 @@ public:
|
|||
bool state_block_generation_enabled (MDB_txn *);
|
||||
static rai::uint128_t const unit;
|
||||
rai::block_store & store;
|
||||
rai::uint128_t inactive_supply;
|
||||
std::unordered_map<rai::account, rai::uint128_t> bootstrap_weights;
|
||||
uint64_t bootstrap_weight_max_blocks;
|
||||
std::atomic<bool> check_bootstrap_weights;
|
||||
rai::block_hash state_block_parse_canary;
|
||||
rai::block_hash state_block_generate_canary;
|
||||
rai::supply supply;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1603,7 +1603,7 @@ online_reps (*this)
|
|||
{
|
||||
rai::transaction transaction (store.environment, nullptr, false);
|
||||
rep_weight = ledger.weight (transaction, vote_a->account);
|
||||
min_rep_weight = ledger.supply (transaction) / 1000;
|
||||
min_rep_weight = ledger.supply.circulating_get () / 1000;
|
||||
}
|
||||
if (rep_weight > min_rep_weight)
|
||||
{
|
||||
|
@ -1758,7 +1758,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 (transaction_a) / 256) * node.config.bootstrap_fraction_numerator);
|
||||
auto result ((node.ledger.supply.circulating_get () / 256) * node.config.bootstrap_fraction_numerator);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1955,6 +1955,7 @@ void rai::node::start ()
|
|||
ongoing_bootstrap ();
|
||||
ongoing_store_flush ();
|
||||
ongoing_rep_crawl ();
|
||||
ongoing_supply_update ();
|
||||
bootstrap.start ();
|
||||
backup_wallet ();
|
||||
active.announce_votes ();
|
||||
|
@ -2050,6 +2051,18 @@ 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 ());
|
||||
|
@ -2968,13 +2981,13 @@ void rai::election::broadcast_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 (transaction_a) / 2;
|
||||
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 (transaction_a) / 16;
|
||||
return ledger_a.supply.circulating_get () / 16;
|
||||
}
|
||||
|
||||
void rai::election::confirm_once (MDB_txn * transaction_a)
|
||||
|
@ -3050,7 +3063,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 (transaction));
|
||||
auto supply (node.ledger.supply.circulating_get ());
|
||||
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
|
||||
{
|
||||
|
|
|
@ -543,6 +543,7 @@ 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 &);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue