Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/bitcoin/node/chasers/chaser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class BCN_API chaser
public:
DELETE_COPY_MOVE_DESTRUCT(chaser);

/// Should be called from node strand.
/// Must be called from node strand.
virtual code start() NOEXCEPT = 0;

/// Override to capture non-blocking stopping.
Expand Down
25 changes: 25 additions & 0 deletions include/bitcoin/node/chasers/chaser_estimate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
#ifndef LIBBITCOIN_NODE_CHASERS_CHASER_ESTIMATE_HPP
#define LIBBITCOIN_NODE_CHASERS_CHASER_ESTIMATE_HPP

#include <atomic>
#include <bitcoin/node/chasers/chaser.hpp>
#include <bitcoin/node/define.hpp>
#include <bitcoin/node/estimator.hpp>

namespace libbitcoin {
namespace node {
Expand All @@ -37,13 +39,36 @@ class BCN_API chaser_estimate
chaser_estimate(full_node& node) NOEXCEPT;

code start() NOEXCEPT override;
void stopping(const code& ec) NOEXCEPT override;

/// Returns max_uint64 when disabled.
void estimate(size_t target, estimator::mode mode,
estimate_handler&& handler) NOEXCEPT;

/// Returns zero when disabled (thread safe).
size_t top_height() const NOEXCEPT;

/// Initialization is complete and successful.
bool initialized() const NOEXCEPT;

protected:
virtual bool handle_chase(const code& ec, chase event_,
event_value value) NOEXCEPT;

virtual void do_organized(header_t value) NOEXCEPT;
virtual void do_reorganized(header_t value) NOEXCEPT;

private:
bool initialize() NOEXCEPT;
void do_estimate(size_t target, estimator::mode mode,
const estimate_handler& handler) NOEXCEPT;

// These are thread safe.
std::atomic_bool stopping_{};
std::atomic_bool initialized_{};

// This is protected by strand.
estimator::ptr estimator_{};
};

} // namespace node
Expand Down
13 changes: 8 additions & 5 deletions include/bitcoin/node/define.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ namespace node {
/// Alias system code.
typedef std::error_code code;

/// Estimate types.
typedef std::function<void(const code&, uint64_t)> estimate_handler;

/// Organization types.
typedef std::function<void(const code&, size_t)> organize_handler;
typedef database::store<database::map> store;
Expand Down Expand Up @@ -120,10 +123,10 @@ using type_id = network::messages::peer::inventory_item::type_id;
// settings : define
// configuration : define settings
// parser : define configuration
// /chasers : define configuration [forward: full_node]
// /chasers : define configuration estimator [forward: full_node]
// /channels : define configuration
// full_node : define /chasers
// session : define [forward: full_node]
// full_node : define estimator /chasers
// session : define estimator [forward: full_node]
// /messages : define
// /protocols : define /channels [session.hpp]
// /sessions : define /protocols [forward: full_node]
// /protocols : define estimator /channels [session.hpp]
// /sessions : define /protocols [forward: full_node]
5 changes: 4 additions & 1 deletion include/bitcoin/node/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,10 @@ enum error_t : uint8_t
confirm9,
confirm10,
confirm11,
confirm12
confirm12,
estimates_failed,
estimates_disabled,
estimates_premature
};

// No current need for error_code equivalence mapping.
Expand Down
16 changes: 9 additions & 7 deletions include/bitcoin/node/estimator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#ifndef LIBBITCOIN_NODE_ESTIMATOR_HPP
#define LIBBITCOIN_NODE_ESTIMATOR_HPP

#include <atomic>
#include <memory>
#include <bitcoin/node/define.hpp>

Expand All @@ -34,7 +35,7 @@ namespace node {
class BCN_API estimator
{
public:
typedef std::shared_ptr<estimator> ptr;
typedef std::unique_ptr<estimator> ptr;
static constexpr size_t maximum_horizon = 1008;

DELETE_COPY_MOVE_DESTRUCT(estimator);
Expand All @@ -45,25 +46,26 @@ class BCN_API estimator
basic,
geometric,
economical,
conservative
conservative,
unknown
};

/// Construct (use heap allocation).
estimator() NOEXCEPT {};

/// Fee estimation in satoshis / transaction virtual size.
/// Fee estimation in satoshis/transaction virtual size (not thread safe).
/// Pass zero to target next block for confirmation, range:0..1007.
uint64_t estimate(size_t target, mode mode) const NOEXCEPT;

/// Populate accumulator with count blocks up to the top confirmed block.
bool initialize(std::atomic_bool& cancel, const query& query,
bool initialize(const std::atomic_bool& cancel, const query& query,
size_t count=maximum_horizon) NOEXCEPT;

/// Update accumulator.
/// Update accumulator (not thread safe).
bool push(const query& query) NOEXCEPT;
bool pop(const query& query) NOEXCEPT;

/// Top height of accumulator.
/// Top height of accumulator (thread safe).
size_t top_height() const NOEXCEPT;

protected:
Expand Down Expand Up @@ -116,7 +118,7 @@ class BCN_API estimator
};

/// Current block height of accumulated state.
size_t top_height{};
std::atomic<size_t> top_height{};

/// Accumulated scaled fee in decayed buckets by horizon.
/// Array count is the half life of the decay it implies.
Expand Down
5 changes: 5 additions & 0 deletions include/bitcoin/node/full_node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <bitcoin/node/chasers/chasers.hpp>
#include <bitcoin/node/configuration.hpp>
#include <bitcoin/node/define.hpp>
#include <bitcoin/node/estimator.hpp>
#include <bitcoin/node/sessions/sessions.hpp>

namespace libbitcoin {
Expand Down Expand Up @@ -151,6 +152,10 @@ class BCN_API full_node
/// Methods.
/// -----------------------------------------------------------------------

/// Get current fee estimate.
void estimate(size_t target, estimator::mode mode,
estimate_handler&& handler) NOEXCEPT;

/// Handle performance, base returns false (implied terminate).
virtual void performance(object_key channel, uint64_t speed,
result_handler&& handler) NOEXCEPT;
Expand Down
8 changes: 8 additions & 0 deletions include/bitcoin/node/protocols/protocol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <bitcoin/node/channels/channels.hpp>
#include <bitcoin/node/configuration.hpp>
#include <bitcoin/node/define.hpp>
#include <bitcoin/node/estimator.hpp>

// Only session.hpp.
#include <bitcoin/node/sessions/session.hpp>
Expand Down Expand Up @@ -67,6 +68,13 @@ class BCN_API protocol
/// The candidate|confirmed chain is current.
virtual bool is_current(bool confirmed) const NOEXCEPT;

/// Methods.
/// -----------------------------------------------------------------------

/// Get current fee estimate.
void estimate(size_t target, estimator::mode mode,
estimate_handler&& handler) NOEXCEPT;

/// Events subscription.
/// -----------------------------------------------------------------------

Expand Down
5 changes: 5 additions & 0 deletions include/bitcoin/node/sessions/session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <bitcoin/node/configuration.hpp>
#include <bitcoin/node/define.hpp>
#include <bitcoin/node/estimator.hpp>

namespace libbitcoin {
namespace node {
Expand Down Expand Up @@ -75,6 +76,10 @@ class BCN_API session
/// Methods.
/// -----------------------------------------------------------------------

/// Get current fee estimate.
void estimate(size_t target, estimator::mode mode,
estimate_handler&& handler) NOEXCEPT;

/// Handle performance, base returns false (implied terminate).
virtual void performance(object_key channel, uint64_t speed,
network::result_handler&& handler) NOEXCEPT;
Expand Down
3 changes: 3 additions & 0 deletions include/bitcoin/node/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class BCN_API settings
float minimum_bump_rate;
uint16_t announcement_cache;
uint16_t allocation_multiple;
uint16_t fee_estimate_horizon;
////uint64_t snapshot_bytes;
////uint32_t snapshot_valid;
////uint32_t snapshot_confirm;
Expand All @@ -59,6 +60,8 @@ class BCN_API settings
virtual size_t threads_() const NOEXCEPT;
virtual size_t maximum_height_() const NOEXCEPT;
virtual size_t maximum_concurrency_() const NOEXCEPT;
virtual size_t fee_estimate_horizon_() const NOEXCEPT;
virtual bool fee_estimate_enabled() const NOEXCEPT;
virtual network::steady_clock::duration sample_period() const NOEXCEPT;
virtual network::wall_clock::duration currency_window() const NOEXCEPT;
virtual network::processing_priority thread_priority_() const NOEXCEPT;
Expand Down
1 change: 1 addition & 0 deletions src/chasers/chaser_check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ map_ptr chaser_check::split(const map_ptr& map) NOEXCEPT

code chaser_check::start() NOEXCEPT
{
BC_ASSERT(stranded());
start_tracking();
set_position(archive().get_fork());
requested_ = advanced_ = position();
Expand Down
1 change: 1 addition & 0 deletions src/chasers/chaser_confirm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ chaser_confirm::chaser_confirm(full_node& node) NOEXCEPT

code chaser_confirm::start() NOEXCEPT
{
BC_ASSERT(stranded());
const auto& query = archive();
set_position(query.get_fork());

Expand Down
96 changes: 94 additions & 2 deletions src/chasers/chaser_estimate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
*/
#include <bitcoin/node/chasers/chaser_estimate.hpp>

#include <atomic>
#include <bitcoin/node/chasers/chaser.hpp>
#include <bitcoin/node/define.hpp>
#include <bitcoin/node/estimator.hpp>
#include <bitcoin/node/full_node.hpp>

namespace libbitcoin {
Expand All @@ -37,17 +39,69 @@ chaser_estimate::chaser_estimate(full_node& node) NOEXCEPT
{
}

// start
// start/stop
// ----------------------------------------------------------------------------

code chaser_estimate::start() NOEXCEPT
{
SUBSCRIBE_CHASE(handle_chase, _1, _2, _3);
BC_ASSERT(stranded());

if (is_zero(node_settings().fee_estimate_enabled()))
{
SUBSCRIBE_CHASE(handle_chase, _1, _2, _3);
}

return error::success;
}

void chaser_estimate::stopping(const code& ec) NOEXCEPT
{
stopping_.store(true);
chaser::stopping(ec);
}

// methods
// ----------------------------------------------------------------------------

void chaser_estimate::estimate(size_t target, estimator::mode mode,
estimate_handler&& handler) NOEXCEPT
{
if (!node_settings().fee_estimate_enabled())
{
handler(error::estimates_disabled, {});
return;
}

if (!initialized())
{
handler(error::estimates_premature, {});
return;
}

POST(do_estimate, target, mode, std::move(handler));
}

// private
void chaser_estimate::do_estimate(size_t target, estimator::mode mode,
const estimate_handler& handler) NOEXCEPT
{
BC_ASSERT(stranded());
handler(error::success, estimator_->estimate(target, mode));
}

size_t chaser_estimate::top_height() const NOEXCEPT
{
return initialized() ? estimator_->top_height() : zero;
}

bool chaser_estimate::initialized() const NOEXCEPT
{
return initialized_.load(std::memory_order_relaxed);
}

// event handlers
// ----------------------------------------------------------------------------
// protected

bool chaser_estimate::handle_chase(const code&, chase event_,
event_value value) NOEXCEPT
Expand All @@ -59,6 +113,9 @@ bool chaser_estimate::handle_chase(const code&, chase event_,
////if (suspended())
//// return true;

if (!is_current(true))
return true;

switch (event_)
{
case chase::organized:
Expand Down Expand Up @@ -89,11 +146,46 @@ bool chaser_estimate::handle_chase(const code&, chase event_,
void chaser_estimate::do_organized(header_t) NOEXCEPT
{
BC_ASSERT(stranded());

if (initialize())
estimator_->push(archive());
}

void chaser_estimate::do_reorganized(header_t) NOEXCEPT
{
BC_ASSERT(stranded());

if (initialize())
estimator_->pop(archive());
}

// utility
// ----------------------------------------------------------------------------
// private

bool chaser_estimate::initialize() NOEXCEPT
{
BC_ASSERT(stranded());

if (initialized())
return true;

// Preempt initialize fault when horizon exceeds chain length.
const auto horizon = node_settings().fee_estimate_horizon_();
if (horizon > add1(archive().get_top_confirmed()))
return false;

// Heap-allocate the estimator due to size.
estimator_ = std::make_unique<estimator>();
if (!estimator_->initialize(stopping_, archive(), horizon))
{
fault(error::estimates_failed);
estimator_.release();
return false;
}

initialized_.store(true, std::memory_order_relaxed);
return true;
}

BC_POP_WARNING()
Expand Down
1 change: 1 addition & 0 deletions src/chasers/chaser_header.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ chaser_header::chaser_header(full_node& node) NOEXCEPT

code chaser_header::start() NOEXCEPT
{
BC_ASSERT(stranded());
if (!initialize_milestone())
return fault(error::header1);

Expand Down
Loading
Loading