Safe ascending bootstrap
This commit is contained in:
parent
0941d7d364
commit
ce0956a8a4
5 changed files with 44 additions and 12 deletions
|
|
@ -64,6 +64,7 @@ enum class type
|
|||
bootstrap_ascending_verify_frontiers,
|
||||
bootstrap_ascending_process,
|
||||
bootstrap_ascending_request,
|
||||
bootstrap_ascending_request_blocks,
|
||||
bootstrap_ascending_reply,
|
||||
bootstrap_ascending_next,
|
||||
bootstrap_ascending_frontiers,
|
||||
|
|
@ -454,7 +455,6 @@ enum class detail
|
|||
process_frontiers,
|
||||
dropped_frontiers,
|
||||
|
||||
// bootstrap_ascending_accounts
|
||||
prioritize,
|
||||
prioritize_failed,
|
||||
block,
|
||||
|
|
@ -491,6 +491,9 @@ enum class detail
|
|||
request_blocks,
|
||||
request_account_info,
|
||||
|
||||
safe,
|
||||
base,
|
||||
|
||||
// active
|
||||
started_hinted,
|
||||
started_optimistic,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ nano::error nano::bootstrap_ascending_config::deserialize (nano::tomlconfig & to
|
|||
toml.get_duration ("throttle_wait", throttle_wait);
|
||||
toml.get ("block_processor_threshold", block_processor_threshold);
|
||||
toml.get ("max_requests", max_requests);
|
||||
toml.get ("optimistic_request_percentage", optimistic_request_percentage);
|
||||
|
||||
if (toml.has_key ("account_sets"))
|
||||
{
|
||||
|
|
@ -71,6 +72,7 @@ nano::error nano::bootstrap_ascending_config::serialize (nano::tomlconfig & toml
|
|||
toml.put ("throttle_wait", throttle_wait.count (), "Length of time to wait between requests when throttled.\ntype:milliseconds");
|
||||
toml.put ("block_processor_threshold", block_processor_threshold, "Ascending bootstrap will wait while block processor has more than this many blocks queued.\ntype:uint64");
|
||||
toml.put ("max_requests", max_requests, "Maximum total number of in flight requests.\ntype:uint64");
|
||||
toml.put ("optimistic_request_percentage", optimistic_request_percentage, "Percentage of requests that will be optimistic. Optimistic requests start from the (possibly unconfirmed) account frontier and are vulnerable to bootstrap poisoning. Safe requests start from the confirmed frontier and given enough time will eventually resolve forks.\ntype:uint64");
|
||||
|
||||
nano::tomlconfig account_sets_l;
|
||||
account_sets.serialize (account_sets_l);
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ public:
|
|||
std::chrono::milliseconds throttle_wait{ 100 };
|
||||
std::size_t block_processor_threshold{ 1000 };
|
||||
std::size_t max_requests{ 1024 };
|
||||
unsigned optimistic_request_percentage{ 75 };
|
||||
|
||||
account_sets_config account_sets;
|
||||
frontier_scan_config frontier_scan;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <nano/secure/ledger_set_any.hpp>
|
||||
#include <nano/store/account.hpp>
|
||||
#include <nano/store/component.hpp>
|
||||
#include <nano/store/confirmation_height.hpp>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
|
|
@ -263,6 +264,7 @@ void nano::bootstrap_ascending::service::inspect (secure::transaction const & tx
|
|||
break;
|
||||
case nano::block_status::gap_source:
|
||||
{
|
||||
// Prevent malicious live traffic from filling up the blocked set
|
||||
if (source == nano::block_source::bootstrap)
|
||||
{
|
||||
const auto account = block.previous ().is_zero () ? block.account_field ().value () : ledger.any.block_account (tx, block.previous ()).value_or (0);
|
||||
|
|
@ -491,18 +493,40 @@ bool nano::bootstrap_ascending::service::request (nano::account account, size_t
|
|||
tag.account = account;
|
||||
tag.count = count;
|
||||
|
||||
// Check if the account picked has blocks, if it does, start the pull from the highest block
|
||||
auto info = ledger.store.account.get (ledger.store.tx_begin_read (), account);
|
||||
if (info)
|
||||
{
|
||||
tag.type = query_type::blocks_by_hash;
|
||||
tag.start = info->head;
|
||||
tag.hash = info->head;
|
||||
}
|
||||
else
|
||||
{
|
||||
tag.type = query_type::blocks_by_account;
|
||||
tag.start = account;
|
||||
auto transaction = ledger.store.tx_begin_read ();
|
||||
|
||||
// Check if the account picked has blocks, if it does, start the pull from the highest block
|
||||
if (auto info = ledger.store.account.get (transaction, account))
|
||||
{
|
||||
tag.type = query_type::blocks_by_hash;
|
||||
|
||||
// Probabilistically choose between requesting blocks from account frontier or confirmed frontier
|
||||
// Optimistic requests start from the (possibly unconfirmed) account frontier and are vulnerable to bootstrap poisoning
|
||||
// Safe requests start from the confirmed frontier and given enough time will eventually resolve forks
|
||||
bool optimistic_reuest = rng.random (100) < config.optimistic_request_percentage;
|
||||
if (!optimistic_reuest)
|
||||
{
|
||||
if (auto conf_info = ledger.store.confirmation_height.get (transaction, account))
|
||||
{
|
||||
stats.inc (nano::stat::type::bootstrap_ascending_request_blocks, nano::stat::detail::safe);
|
||||
tag.start = conf_info->frontier;
|
||||
tag.hash = conf_info->height;
|
||||
}
|
||||
}
|
||||
if (tag.start.is_zero ())
|
||||
{
|
||||
stats.inc (nano::stat::type::bootstrap_ascending_request_blocks, nano::stat::detail::optimistic);
|
||||
tag.start = info->head;
|
||||
tag.hash = info->head;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stats.inc (nano::stat::type::bootstrap_ascending_request_blocks, nano::stat::detail::base);
|
||||
tag.type = query_type::blocks_by_account;
|
||||
tag.start = account;
|
||||
}
|
||||
}
|
||||
|
||||
return send (channel, tag);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <nano/lib/locks.hpp>
|
||||
#include <nano/lib/numbers.hpp>
|
||||
#include <nano/lib/observer_set.hpp>
|
||||
#include <nano/lib/random.hpp>
|
||||
#include <nano/lib/rate_limiting.hpp>
|
||||
#include <nano/lib/thread_pool.hpp>
|
||||
#include <nano/lib/timer.hpp>
|
||||
|
|
@ -211,6 +212,7 @@ namespace bootstrap_ascending
|
|||
std::thread timeout_thread;
|
||||
|
||||
nano::thread_pool workers;
|
||||
nano::random_generator_mt rng;
|
||||
};
|
||||
|
||||
nano::stat::detail to_stat_detail (service::query_type);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue