Skip to content

Commit

Permalink
Initial functional implementation of competitive header sync.
Browse files Browse the repository at this point in the history
  • Loading branch information
evoskuil committed Feb 16, 2024
1 parent 472b333 commit f9af5ee
Show file tree
Hide file tree
Showing 19 changed files with 393 additions and 101 deletions.
2 changes: 1 addition & 1 deletion include/bitcoin/node/chasers/chaser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class BCN_API chaser
void notify(const code& ec, chase event_, link value) NOEXCEPT;

/// Close the node.
void close(const code& ec) NOEXCEPT;
void stop(const code& ec) NOEXCEPT;

private:
void do_notify(const code& ec, chase event_, link value) NOEXCEPT;
Expand Down
59 changes: 52 additions & 7 deletions include/bitcoin/node/chasers/chaser_header.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#ifndef LIBBITCOIN_NODE_CHASERS_CHASER_HEADER_HPP
#define LIBBITCOIN_NODE_CHASERS_CHASER_HEADER_HPP

#include <unordered_map>
#include <bitcoin/database.hpp>
#include <bitcoin/network.hpp>
#include <bitcoin/node/define.hpp>
#include <bitcoin/node/chasers/chaser.hpp>
Expand All @@ -29,6 +31,8 @@ namespace node {
class full_node;

/// Chase down stronger header branches for the candidate chain.
/// Weak branches are retained in a hash table unless already store populated.
/// Strong branches reorganize the candidate chain and fire the 'header' event.
class BCN_API chaser_header
: public chaser, protected network::tracker<chaser_header>
{
Expand All @@ -37,20 +41,61 @@ class BCN_API chaser_header

chaser_header(full_node& node) NOEXCEPT;

void store(const system::chain::header::cptr& header) NOEXCEPT;
/// Organize the next header in sequence, relative to caller's peer.
/// Causes a fault/stop if preceding headers have not been stored.
/// Caller must validate the header and provide context.
void organize(const system::chain::header::cptr& header,
system::chain::context&& context) NOEXCEPT;

protected:
typedef std::vector<database::header_link> header_links;

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

/// Sum of work from header to branch point (excluded).
virtual bool get_branch_work(uint256_t& work, size_t& point,
system::hashes& tree_branch, header_links& store_branch,
const system::chain::header& header) const NOEXCEPT;

/// Strong if new branch work exceeds candidate work.
/// Also obtains branch point for work summation termination.
/// Also obtains ordered branch identifiers for subsequent reorg.
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) const NOEXCEPT;

/// Save header to tree with validation context.
virtual void save(const system::chain::header::cptr& header,
const system::chain::context& context) NOEXCEPT;

/// Store header to database and push to top of candidate chain.
virtual database::header_link push(
const system::chain::header::cptr& header,
const system::chain::context& context) const NOEXCEPT;

/// Move tree header to database and push to top of candidate chain.
virtual bool push(const system::hash_digest& key) NOEXCEPT;

private:
bool is_current(const system::chain::header& header) const NOEXCEPT;
bool is_strong(const system::chain::header& header) const NOEXCEPT;
struct proposed_header
{
database::context context;
system::chain::header::cptr header;
};

void handle_start() NOEXCEPT;
void handle_event(const code& ec, chase event_, link value) NOEXCEPT;
void do_handle_event(const code& ec, chase event_, link value) NOEXCEPT;
void do_store(const system::chain::header::cptr& header) NOEXCEPT;
void do_organize(const system::chain::header::cptr& header,
const system::chain::context& context) NOEXCEPT;

// These are protected by strand.
std::unordered_map<system::hash_digest, proposed_header> tree_{};
const network::wall_clock::duration currency_window_;
std::vector<system::chain::header::cptr> chain_{};
const bool use_currency_window_;
};

} // namespace node
Expand Down
3 changes: 2 additions & 1 deletion include/bitcoin/node/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,15 @@ enum error_t : uint8_t
unexpected_event,

// database
store_integrity,
store_uninitialized,

// network
slow_channel,
stalled_channel,

// blockchain
orphan_block,
orphan_header,
insufficient_work,
duplicate_block
};
Expand Down
7 changes: 7 additions & 0 deletions include/bitcoin/node/full_node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ class BCN_API full_node
/// Close the node.
void close() NOEXCEPT override;

/// Chasers.
/// -----------------------------------------------------------------------

/// Organize a validated header, failures stop the node.
virtual void organize(const system::chain::header::cptr& header,
system::chain::context&& context) NOEXCEPT;

/// Properties.
/// -----------------------------------------------------------------------

Expand Down
6 changes: 5 additions & 1 deletion include/bitcoin/node/protocols/protocol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,14 @@ class BCN_API protocol

virtual ~protocol() NOEXCEPT;

/// Report performance, false directs self-terminate.
/// Report performance, handler may direct self-terminate.
virtual void performance(uint64_t channel, uint64_t speed,
network::result_handler&& handler) const NOEXCEPT;

/// Organize a validated header, failures stop the node.
virtual void organize(const system::chain::header::cptr& header,
system::chain::context&& context) NOEXCEPT;

/// Configuration settings for all libraries.
const configuration& config() const NOEXCEPT;

Expand Down
28 changes: 14 additions & 14 deletions include/bitcoin/node/sessions/attach.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,21 @@ class attach
Session::attach_protocols(channel);

auto& self = *this;
////const auto version = channel->negotiated_version();
////
////if (version >= network::messages::level::bip130)
////{
//// channel->attach<protocol_header_in_70012>(self)->start();
//// channel->attach<protocol_header_out_70012>(self)->start();
////}
////else if (version >= network::messages::level::headers_protocol)
////{
//// channel->attach<protocol_header_in_31800>(self)->start();
//// channel->attach<protocol_header_out_31800>(self)->start();
////}
const auto version = channel->negotiated_version();

if (version >= network::messages::level::bip130)
{
channel->attach<protocol_header_in_70012>(self)->start();
channel->attach<protocol_header_out_70012>(self)->start();
}
else if (version >= network::messages::level::headers_protocol)
{
channel->attach<protocol_header_in_31800>(self)->start();
channel->attach<protocol_header_out_31800>(self)->start();
}

constexpr auto performance = false;
channel->attach<protocol_block_in>(self, performance)->start();
////constexpr auto performance = false;
////channel->attach<protocol_block_in>(self, performance)->start();
////channel->attach<protocol_block_out>(self)->start();
////channel->attach<protocol_transaction_in>(self)->start();
////channel->attach<protocol_transaction_out>(self)->start();
Expand Down
4 changes: 4 additions & 0 deletions include/bitcoin/node/sessions/session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ class BCN_API session
virtual void performance(uint64_t channel, uint64_t speed,
network::result_handler&& handler) NOEXCEPT;

/// Organize a validated header, failures stop the node.
virtual void organize(const system::chain::header::cptr& header,
system::chain::context&& context) NOEXCEPT;

/// Configuration settings for all libraries.
const configuration& config() const NOEXCEPT;

Expand Down
4 changes: 2 additions & 2 deletions src/chasers/chaser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ void chaser::do_notify(const code& ec, chase event_, link value) NOEXCEPT
subscriber_.notify(ec, event_, value);
}

void chaser::close(const code& ec) NOEXCEPT
void chaser::stop(const code&) NOEXCEPT
{
LOGF("Chaser fault, " << ec.message());
////LOGF("Chaser fault, " << ec.message());
node_.close();
}

Expand Down
Loading

0 comments on commit f9af5ee

Please sign in to comment.