Skip to content

Commit

Permalink
Merge pull request #543 from evoskuil/master
Browse files Browse the repository at this point in the history
Add bitcoin.checkpoint to parser, clear trees on stop.
  • Loading branch information
evoskuil authored Feb 24, 2024
2 parents e30e5ff + dcc34be commit 0ed942b
Show file tree
Hide file tree
Showing 16 changed files with 142 additions and 145 deletions.
13 changes: 1 addition & 12 deletions include/bitcoin/node/chasers/chaser_block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,6 @@ class BCN_API chaser_block
virtual bool get_is_strong(bool& strong, const uint256_t& work,
size_t point) const NOEXCEPT;

/// Header timestamp is within configured span from current time.
virtual bool is_current(const system::chain::header& header,
size_t height) const NOEXCEPT;

/// Save block to tree with validation context.
virtual void save(const system::chain::block::cptr& block,
const system::chain::context& context) NOEXCEPT;
Expand All @@ -98,19 +94,12 @@ class BCN_API chaser_block
virtual void do_organize(const system::chain::block::cptr& block,
const network::result_handler& handler) NOEXCEPT;

/// Properties.
/// Given non-current blocks cached in memory, should always be zero/false.
virtual const network::wall_clock::duration& currency_window() const NOEXCEPT;
virtual bool use_currency_window() const NOEXCEPT;

private:
void set_prevout(const system::chain::input& input) const NOEXCEPT;
void do_handle_event(const code& ec, chase event_, link value) NOEXCEPT;

// These are thread safe.
// This is thread safe.
const system::chain::checkpoints& checkpoints_;
const network::wall_clock::duration currency_window_;
const bool use_currency_window_;
};

} // namespace node
Expand Down
7 changes: 4 additions & 3 deletions include/bitcoin/node/chasers/chaser_header.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class BCN_API chaser_header
system::chain::chain_state::ptr state_{};
std::unordered_map<system::hash_digest, proposed_header> tree_{};

/// Handlers.
/// Handle chaser events.
virtual void handle_event(const code& ec, chase event_,
link value) NOEXCEPT;

Expand All @@ -76,7 +76,8 @@ class BCN_API chaser_header
virtual bool get_is_strong(bool& strong, const uint256_t& work,
size_t point) const NOEXCEPT;

/// Header timestamp is within configured span from current time.
/// Header timestamp is within configured span from current time,
/// or current header is a checkpoint or milestone.
virtual bool is_current(const system::chain::header& header,
size_t height) const NOEXCEPT;

Expand All @@ -96,7 +97,7 @@ class BCN_API chaser_header
virtual void do_organize(const system::chain::header::cptr& header,
const network::result_handler& handler) NOEXCEPT;

/// Properties.
/// A strong header branch is committed to store when current.
virtual const network::wall_clock::duration& currency_window() const NOEXCEPT;
virtual bool use_currency_window() const NOEXCEPT;

Expand Down
5 changes: 2 additions & 3 deletions include/bitcoin/node/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@ enum error_t : uint8_t

// blockchain
orphan_block,
orphan_header,
insufficient_work,
duplicate_block
duplicate_block,
insufficient_work
};

// No current need for error_code equivalence mapping.
Expand Down
2 changes: 1 addition & 1 deletion include/bitcoin/node/protocols/protocol_block_in.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class BCN_API protocol_block_in
virtual void complete() NOEXCEPT;

/// Handle organize result.
virtual void handle_organize(const code& ec,
virtual void handle_organize(const code& ec, size_t height,
const system::chain::block::cptr& block_ptr) NOEXCEPT;

private:
Expand Down
2 changes: 1 addition & 1 deletion include/bitcoin/node/protocols/protocol_block_in_31800.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class BCN_API protocol_block_in_31800
virtual void complete() NOEXCEPT;

/// Handle organize result.
virtual void handle_organize(const code& ec,
virtual void handle_organize(const code& ec, size_t height,
const system::chain::block::cptr& block_ptr) NOEXCEPT;

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class BCN_API protocol_header_in_31800
virtual void complete() NOEXCEPT;

/// Handle organize result.
virtual void handle_organize(const code& ec,
virtual void handle_organize(const code& ec, size_t height,
const system::chain::header::cptr& header_ptr) NOEXCEPT;

private:
Expand Down
32 changes: 16 additions & 16 deletions include/bitcoin/node/sessions/attach.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,28 +58,28 @@ class attach
const network::channel::ptr& channel) NOEXCEPT override
{
auto& self = *this;
////const auto version = channel->negotiated_version();
const auto version = channel->negotiated_version();
////constexpr auto performance = false;

// Attach appropriate alert, reject, ping, and/or address protocols.
Session::attach_protocols(channel);

// Very hard to find < 31800 peer to connect with.
////if (version >= network::messages::level::bip130)
////{
//// // Headers-first synchronization (parallel block download).
//// channel->attach<protocol_header_in_70012>(self)->start();
//// channel->attach<protocol_header_out_70012>(self)->start();
//// ////channel->attach<protocol_block_in_31800>(self, performance)->start();
////}
////else if (version >= network::messages::level::headers_protocol)
////{
//// // Headers-first synchronization (parallel block download).
//// channel->attach<protocol_header_in_31800>(self)->start();
//// channel->attach<protocol_header_out_31800>(self)->start();
//// ////channel->attach<protocol_block_in_31800>(self, performance)->start();
////}
////else
if (version >= network::messages::level::bip130)
{
// Headers-first synchronization (parallel block download).
channel->attach<protocol_header_in_70012>(self)->start();
channel->attach<protocol_header_out_70012>(self)->start();
////channel->attach<protocol_block_in_31800>(self, performance)->start();
}
else if (version >= network::messages::level::headers_protocol)
{
// Headers-first synchronization (parallel block download).
channel->attach<protocol_header_in_31800>(self)->start();
channel->attach<protocol_header_out_31800>(self)->start();
////channel->attach<protocol_block_in_31800>(self, performance)->start();
}
else
{
// Blocks-first synchronization (no header protocol).
channel->attach<protocol_block_in>(self)->start();
Expand Down
54 changes: 10 additions & 44 deletions src/chasers/chaser_block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,29 +39,14 @@ BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)

chaser_block::chaser_block(full_node& node) NOEXCEPT
: chaser(node),
checkpoints_(node.config().bitcoin.checkpoints),
currency_window_(node.node_settings().currency_window()),
use_currency_window_(to_bool(node.node_settings().currency_window_minutes))
checkpoints_(node.config().bitcoin.checkpoints)
{
}

chaser_block::~chaser_block() NOEXCEPT
{
}

// protected
const network::wall_clock::duration&
chaser_block::currency_window() const NOEXCEPT
{
return currency_window_;
}

// protected
bool chaser_block::use_currency_window() const NOEXCEPT
{
return use_currency_window_;
}

// protected
code chaser_block::start() NOEXCEPT
{
Expand All @@ -84,9 +69,12 @@ void chaser_block::handle_event(const code& ec, chase event_,
}

// private
void chaser_block::do_handle_event(const code&, chase, link) NOEXCEPT
void chaser_block::do_handle_event(const code&, chase event_, link) NOEXCEPT
{
BC_ASSERT_MSG(stranded(), "chaser_block");

if (event_ == chase::stop)
tree_.clear();
}

void chaser_block::organize(const block::cptr& block,
Expand Down Expand Up @@ -125,15 +113,14 @@ void chaser_block::do_organize(const block::cptr& block_ptr,
// Block (header and txs) already exists.
if (tree_.contains(hash) || query.is_block(hash))
{
handler(error::success);
handler(error::duplicate_block);
return;
}

// Peer processing should have precluded orphan submission.
// Results from running headers-first and then restarting to blocks-first.
if (!tree_.contains(previous) && !query.is_block(previous))
{
LOGR("Orphan header [" << encode_hash(hash) << "].");
handler(error::orphan_block);
return;
}
Expand All @@ -150,20 +137,22 @@ void chaser_block::do_organize(const block::cptr& block_ptr,
// Checkpoints are considered chain not block/header validation.
if (checkpoint::is_conflict(coin.checkpoints, hash, height))
{
handler(network::error::protocol_violation);
handler(system::error::checkpoint_conflict);
return;
};

// Block validations are bypassed when under checkpoint/milestone.
if (!checkpoint::is_under(coin.checkpoints, height))
{
// Requires no population.
auto error = block.check();
if (error)
{
handler(network::error::protocol_violation);
return;
}

// Requires no population.
error = block.check(context);
if (error)
{
Expand Down Expand Up @@ -204,14 +193,7 @@ void chaser_block::do_organize(const block::cptr& block_ptr,

// Compute relative work.
// ------------------------------------------------------------------------

// Block is new top of stale branch (strength not computed).
if (!is_current(header, context.height))
{
save(block_ptr, context);
handler(error::success);
return;
}
// Currency is not used for blocks due to excessive cache requirement.

size_t point{};
uint256_t work{};
Expand Down Expand Up @@ -303,22 +285,6 @@ void chaser_block::do_organize(const block::cptr& block_ptr,
handler(error::success);
}

bool chaser_block::is_current(const header& header,
size_t height) const NOEXCEPT
{
if (!use_currency_window())
return true;

// Checkpoints are already validated. Current if at a checkpoint height.
if (checkpoint::is_at(checkpoints_, height))
return true;

// en.wikipedia.org/wiki/Time_formatting_and_storage_bugs#Year_2106
const auto time = wall_clock::from_time_t(header.timestamp());
const auto current = wall_clock::now() - currency_window();
return time >= current;
}

bool chaser_block::get_branch_work(uint256_t& work, size_t& point,
hashes& tree_branch, header_links& store_branch,
const header& header) const NOEXCEPT
Expand Down
19 changes: 11 additions & 8 deletions src/chasers/chaser_header.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,12 @@ void chaser_header::handle_event(const code& ec, chase event_,
}

// private
void chaser_header::do_handle_event(const code&, chase, link) NOEXCEPT
void chaser_header::do_handle_event(const code&, chase event_, link) NOEXCEPT
{
BC_ASSERT_MSG(stranded(), "chaser_header");

if (event_ == chase::stop)
tree_.clear();
}

void chaser_header::organize(const header::cptr& header,
Expand Down Expand Up @@ -123,14 +126,14 @@ void chaser_header::do_organize(const header::cptr& header_ptr,
// Header already exists.
if (tree_.contains(hash) || query.is_header(hash))
{
handler(error::success);
handler(error::duplicate_block);
return;
}

// Peer processing should have precluded orphan submission.
if (!tree_.contains(previous) && !query.is_header(previous))
{
handler(error::orphan_header);
handler(error::orphan_block);
return;
}

Expand All @@ -140,12 +143,12 @@ void chaser_header::do_organize(const header::cptr& header_ptr,
// Rolling forward chain_state eliminates requery cost.
state_.reset(new chain_state(*state_, header, coin));
const auto context = state_->context();
const auto height = state_->height();

// Checkpoints are considered chain not block/header validation.
if (checkpoint::is_conflict(coin.checkpoints, hash,
state_->height()))
if (checkpoint::is_conflict(coin.checkpoints, hash, height))
{
handler(network::error::protocol_violation);
handler(system::error::checkpoint_conflict);
return;
}

Expand All @@ -155,14 +158,14 @@ void chaser_header::do_organize(const header::cptr& header_ptr,
coin.proof_of_work_limit, coin.scrypt_proof_of_work);
if (error)
{
handler(network::error::protocol_violation);
handler(error);
return;
}

error = header.accept(context);
if (error)
{
handler(network::error::protocol_violation);
handler(error);
}

// Compute relative work.
Expand Down
5 changes: 2 additions & 3 deletions src/error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@ DEFINE_ERROR_T_MESSAGE_MAP(error)

// blockchain
{ orphan_block, "orphan block" },
{ orphan_header, "orphan header" },
{ insufficient_work, "insufficient work" },
{ duplicate_block, "duplicate block" }
{ duplicate_block, "duplicate block" },
{ insufficient_work, "insufficient work" }
};

DEFINE_ERROR_T_CATEGORY(error, "node", "node code")
Expand Down
6 changes: 6 additions & 0 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,12 @@ options_metadata parser::load_settings() THROWS
value<config::block>(&configured.bitcoin.genesis_block),
"The genesis block, defaults to mainnet."
)
// TODO: checkpoint/checkpoints fail to parse.
(
"bitcoin.checkpoint",
value<chain::checkpoints>(&configured.bitcoin.checkpoints),
"The blockchain checkpoints, defaults to the consensus set."
)
// [version properties excluded here]
(
"bitcoin.bip34_activation_threshold",
Expand Down
Loading

0 comments on commit 0ed942b

Please sign in to comment.