Skip to content

Commit

Permalink
Merge fd8ed2a into b313f19
Browse files Browse the repository at this point in the history
  • Loading branch information
toxeus committed Sep 11, 2018
2 parents b313f19 + fd8ed2a commit 64791d4
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 50 deletions.
7 changes: 7 additions & 0 deletions include/bitcoin/bitcoin/chain/chain_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,13 @@ class BC_API chain_state
/// This block height is less than or equal to that of the top checkpoint.
bool is_under_checkpoint() const;

static uint32_t minimum_timespan(uint32_t retargeting_interval_seconds,
uint32_t retargeting_factor);
static uint32_t maximum_timespan(uint32_t retargeting_interval_seconds,
uint32_t retargeting_factor);
static uint32_t retargeting_interval(uint32_t retargeting_interval_seconds,
uint32_t block_spacing_seconds);

protected:
struct activations
{
Expand Down
29 changes: 19 additions & 10 deletions include/bitcoin/bitcoin/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ class BC_API settings
settings();
settings(config::settings context);

void retargeting_factor(uint32_t value);
uint32_t retargeting_interval_seconds() const;
void retargeting_interval_seconds(uint32_t value);
uint32_t block_spacing_seconds() const;
void block_spacing_seconds(uint32_t value);
uint32_t minimum_timespan() const;
uint32_t maximum_timespan() const;
size_t retargeting_interval() const;

// Currency unit helper methods (uint64_t).
//--------------------------------------------------------------------------

Expand All @@ -46,19 +55,9 @@ class BC_API settings
uint64_t subsidy_interval() const;
uint64_t max_money() const;

uint32_t retargeting_factor;
uint32_t block_spacing_seconds;
uint32_t timestamp_limit_seconds;
uint32_t retargeting_interval_seconds;
uint32_t proof_of_work_limit;

// The upper and lower bounds for the retargeting timespan.
uint32_t minimum_timespan;
uint32_t maximum_timespan;

// The target number of blocks for 2 weeks of work (2016 blocks).
size_t retargeting_interval;

config::block genesis_block;

// Fork settings.
Expand Down Expand Up @@ -98,6 +97,16 @@ class BC_API settings
config::checkpoint bip9_bit1_active_checkpoint;

private:
uint32_t retargeting_factor_;
uint32_t block_spacing_seconds_;
uint32_t retargeting_interval_seconds_;

// The upper and lower bounds for the retargeting timespan.
uint32_t minimum_timespan_;
uint32_t maximum_timespan_;

// The target number of blocks for 2 weeks of work (2016 blocks).
size_t retargeting_interval_;

// Currency unit settings (uint64_t).
//--------------------------------------------------------------------------
Expand Down
33 changes: 26 additions & 7 deletions src/chain/chain_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,15 +303,16 @@ uint32_t chain_state::work_required(const data& values, uint32_t forks,
return bits_high(values);

// Mainnet and testnet retarget on interval.
if (is_retarget_height(values.height, settings.retargeting_interval))
if (is_retarget_height(values.height, settings.retargeting_interval()))
return work_required_retarget(values, forks,
settings.proof_of_work_limit, settings.minimum_timespan,
settings.maximum_timespan, settings.retargeting_interval_seconds);
settings.proof_of_work_limit, settings.minimum_timespan(),
settings.maximum_timespan(),
settings.retargeting_interval_seconds());

// Testnet retargets easy on inter-interval.
if (!script::is_enabled(forks, rule_fork::difficult))
return easy_work_required(values, settings.retargeting_interval,
settings.proof_of_work_limit, settings.block_spacing_seconds);
return easy_work_required(values, settings.retargeting_interval(),
settings.proof_of_work_limit, settings.block_spacing_seconds());

// Mainnet not retargeting.
return bits_high(values);
Expand Down Expand Up @@ -517,7 +518,7 @@ chain_state::data chain_state::to_pool(const chain_state& top,

// If bits collection overflows, dequeue oldest member.
if (data.bits.ordered.size() >
bits_count(height, forks, settings.retargeting_interval))
bits_count(height, forks, settings.retargeting_interval()))
data.bits.ordered.pop_front();

// If version collection overflows, dequeue oldest member.
Expand All @@ -532,7 +533,7 @@ chain_state::data chain_state::to_pool(const chain_state& top,
// Regtest does not perform retargeting.
// If promoting from retarget height, move that timestamp into retarget.
if (retarget &&
is_retarget_height(height - 1u, settings.retargeting_interval))
is_retarget_height(height - 1u, settings.retargeting_interval()))
data.timestamp.retarget = (script::is_enabled(forks,
rule_fork::time_warp_patch) && height != 1) ?
*std::next(data.timestamp.ordered.crbegin()) : data.timestamp.self;
Expand Down Expand Up @@ -728,5 +729,23 @@ bool chain_state::is_under_checkpoint() const
return checkpoint::covered(data_.height, checkpoints_);
}

uint32_t chain_state::minimum_timespan(uint32_t retargeting_interval_seconds,
uint32_t retargeting_factor)
{
return retargeting_interval_seconds / retargeting_factor;
}

uint32_t chain_state::maximum_timespan(uint32_t retargeting_interval_seconds,
uint32_t retargeting_factor)
{
return retargeting_interval_seconds * retargeting_factor;
}

uint32_t chain_state::retargeting_interval(
uint32_t retargeting_interval_seconds, uint32_t block_spacing_seconds)
{
return retargeting_interval_seconds / block_spacing_seconds;
}

} // namespace chain
} // namespace libbitcoin
72 changes: 65 additions & 7 deletions src/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,31 @@
#include <cstdint>
#include <bitcoin/bitcoin/settings.hpp>
#include <bitcoin/bitcoin/chain/block.hpp>
#include <bitcoin/bitcoin/chain/chain_state.hpp>

namespace libbitcoin {

using namespace chain;

// Common default values (no settings context).
settings::settings()
: retargeting_factor(4),
block_spacing_seconds(10 * 60),
timestamp_limit_seconds(2 * 60 * 60),
retargeting_interval_seconds(2 * 7 * 24 * 60 * 60),
minimum_timespan(retargeting_interval_seconds / retargeting_factor),
maximum_timespan(retargeting_interval_seconds * retargeting_factor),
retargeting_interval(retargeting_interval_seconds / block_spacing_seconds),
: timestamp_limit_seconds(2 * 60 * 60),
first_version(1),
bip34_version(2),
bip66_version(3),
bip65_version(4),
bip9_version_bit0(1u << 0),
bip9_version_bit1(1u << 1),
bip9_version_base(0x20000000),
retargeting_factor_(4),
block_spacing_seconds_(10 * 60),
retargeting_interval_seconds_(2 * 7 * 24 * 60 * 60),
minimum_timespan_(chain_state::minimum_timespan(
retargeting_interval_seconds_, retargeting_factor_)),
maximum_timespan_(chain_state::maximum_timespan(
retargeting_interval_seconds_, retargeting_factor_)),
retargeting_interval_(chain_state::retargeting_interval(
retargeting_interval_seconds_, block_spacing_seconds_)),
initial_block_subsidy_bitcoin_(50),
recursive_money_(9999999989u)
{
Expand Down Expand Up @@ -238,6 +244,58 @@ settings::settings(config::settings context)
max_money_ = recursive_money_ * subsidy_interval_;
}

void settings::retargeting_factor(uint32_t value)
{
retargeting_factor_ = value;
minimum_timespan_ = chain_state::minimum_timespan(
retargeting_interval_seconds_, retargeting_factor_);
maximum_timespan_ = chain_state::maximum_timespan(
retargeting_interval_seconds_, retargeting_factor_);
}

uint32_t settings::retargeting_interval_seconds() const
{
return retargeting_interval_seconds_;
}

void settings::retargeting_interval_seconds(uint32_t value)
{
retargeting_interval_seconds_ = value;
minimum_timespan_ = chain_state::minimum_timespan(
retargeting_interval_seconds_, retargeting_factor_);
maximum_timespan_ = chain_state::maximum_timespan(
retargeting_interval_seconds_, retargeting_factor_);
retargeting_interval_ = chain_state::retargeting_interval(
retargeting_interval_seconds_, block_spacing_seconds_);
}

uint32_t settings::block_spacing_seconds() const
{
return block_spacing_seconds_;
}

void settings::block_spacing_seconds(uint32_t value)
{
block_spacing_seconds_ = value;
retargeting_interval_ = chain_state::retargeting_interval(
retargeting_interval_seconds_, block_spacing_seconds_);
}

uint32_t settings::minimum_timespan() const
{
return minimum_timespan_;
}

uint32_t settings::maximum_timespan() const
{
return maximum_timespan_;
}

size_t settings::retargeting_interval() const
{
return retargeting_interval_;
}

uint64_t settings::bitcoin_to_satoshi(uint64_t value) const
{
static const uint64_t satoshi_per_bitcoin = 100000000;
Expand Down
4 changes: 2 additions & 2 deletions test/chain/chain_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ BOOST_AUTO_TEST_CASE(chain_state__work_required_retarget__overflow_patch_disable
{
settings settings(config::settings::mainnet);
settings.proof_of_work_limit = 0x1e0fffff;
const auto values = get_values(settings.retargeting_interval);
const auto values = get_values(settings.retargeting_interval());
const auto forks = machine::rule_fork::retarget;
const auto work = test_chain_state::work_required(values, forks, settings);
BOOST_REQUIRE_EQUAL(work, 0x1e0884d1);
Expand All @@ -52,7 +52,7 @@ BOOST_AUTO_TEST_CASE(chain_state__work_required_retarget__overflow_patch_enabled
{
settings settings(config::settings::mainnet);
settings.proof_of_work_limit = 0x1e0fffff;
const auto values = get_values(settings.retargeting_interval);
const auto values = get_values(settings.retargeting_interval());
const auto forks = machine::rule_fork::retarget | machine::rule_fork::retarget_overflow_patch;
const auto work = test_chain_state::work_required(values, forks, settings);
BOOST_REQUIRE_EQUAL(work, settings.proof_of_work_limit);
Expand Down
78 changes: 54 additions & 24 deletions test/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,12 @@ BOOST_AUTO_TEST_SUITE(settings_tests)
BOOST_AUTO_TEST_CASE(settings__construct__default_context__expected)
{
settings configuration;
BOOST_REQUIRE_EQUAL(configuration.retargeting_factor, 4);
BOOST_REQUIRE_EQUAL(configuration.block_spacing_seconds, 600);
BOOST_REQUIRE_EQUAL(configuration.block_spacing_seconds(), 600);
BOOST_REQUIRE_EQUAL(configuration.timestamp_limit_seconds, 7200);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval_seconds, 1209600);
BOOST_REQUIRE_EQUAL(configuration.minimum_timespan, 302400);
BOOST_REQUIRE_EQUAL(configuration.maximum_timespan, 4838400);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval, 2016);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval_seconds(), 1209600);
BOOST_REQUIRE_EQUAL(configuration.minimum_timespan(), 302400);
BOOST_REQUIRE_EQUAL(configuration.maximum_timespan(), 4838400);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval(), 2016);
BOOST_REQUIRE_EQUAL(configuration.first_version, 1);
BOOST_REQUIRE_EQUAL(configuration.bip34_version, 2);
BOOST_REQUIRE_EQUAL(configuration.bip66_version, 3);
Expand All @@ -50,14 +49,13 @@ BOOST_AUTO_TEST_CASE(settings__construct__default_context__expected)
BOOST_AUTO_TEST_CASE(settings__construct__mainnet_context__expected)
{
settings configuration(config::settings::mainnet);
BOOST_REQUIRE_EQUAL(configuration.retargeting_factor, 4);
BOOST_REQUIRE_EQUAL(configuration.block_spacing_seconds, 600);
BOOST_REQUIRE_EQUAL(configuration.block_spacing_seconds(), 600);
BOOST_REQUIRE_EQUAL(configuration.timestamp_limit_seconds, 7200);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval_seconds, 1209600);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval_seconds(), 1209600);
BOOST_REQUIRE_EQUAL(configuration.proof_of_work_limit, 0x1d00ffff);
BOOST_REQUIRE_EQUAL(configuration.minimum_timespan, 302400);
BOOST_REQUIRE_EQUAL(configuration.maximum_timespan, 4838400);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval, 2016);
BOOST_REQUIRE_EQUAL(configuration.minimum_timespan(), 302400);
BOOST_REQUIRE_EQUAL(configuration.maximum_timespan(), 4838400);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval(), 2016);
const chain::block genesis_block = configuration.genesis_block;
BOOST_REQUIRE_EQUAL(genesis_block.to_data(), data_chunk({
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Expand Down Expand Up @@ -131,14 +129,13 @@ BOOST_AUTO_TEST_CASE(settings__construct__mainnet_context__expected)
BOOST_AUTO_TEST_CASE(settings__construct__testnet_context__expected)
{
settings configuration(config::settings::testnet);
BOOST_REQUIRE_EQUAL(configuration.retargeting_factor, 4);
BOOST_REQUIRE_EQUAL(configuration.block_spacing_seconds, 600);
BOOST_REQUIRE_EQUAL(configuration.block_spacing_seconds(), 600);
BOOST_REQUIRE_EQUAL(configuration.timestamp_limit_seconds, 7200);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval_seconds, 1209600);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval_seconds(), 1209600);
BOOST_REQUIRE_EQUAL(configuration.proof_of_work_limit, 0x1d00ffff);
BOOST_REQUIRE_EQUAL(configuration.minimum_timespan, 302400);
BOOST_REQUIRE_EQUAL(configuration.maximum_timespan, 4838400);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval, 2016);
BOOST_REQUIRE_EQUAL(configuration.minimum_timespan(), 302400);
BOOST_REQUIRE_EQUAL(configuration.maximum_timespan(), 4838400);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval(), 2016);
const chain::block genesis_block = configuration.genesis_block;
BOOST_REQUIRE_EQUAL(genesis_block.to_data(), data_chunk({
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Expand Down Expand Up @@ -212,14 +209,13 @@ BOOST_AUTO_TEST_CASE(settings__construct__testnet_context__expected)
BOOST_AUTO_TEST_CASE(settings__construct__regtest_context__expected)
{
settings configuration(config::settings::regtest);
BOOST_REQUIRE_EQUAL(configuration.retargeting_factor, 4);
BOOST_REQUIRE_EQUAL(configuration.block_spacing_seconds, 600);
BOOST_REQUIRE_EQUAL(configuration.block_spacing_seconds(), 600);
BOOST_REQUIRE_EQUAL(configuration.timestamp_limit_seconds, 7200);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval_seconds, 1209600);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval_seconds(), 1209600);
BOOST_REQUIRE_EQUAL(configuration.proof_of_work_limit, 0x207fffff);
BOOST_REQUIRE_EQUAL(configuration.minimum_timespan, 302400);
BOOST_REQUIRE_EQUAL(configuration.maximum_timespan, 4838400);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval, 2016);
BOOST_REQUIRE_EQUAL(configuration.minimum_timespan(), 302400);
BOOST_REQUIRE_EQUAL(configuration.maximum_timespan(), 4838400);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval(), 2016);
const chain::block genesis_block = configuration.genesis_block;
BOOST_REQUIRE_EQUAL(genesis_block.to_data(), data_chunk({
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Expand Down Expand Up @@ -303,4 +299,38 @@ BOOST_AUTO_TEST_CASE(settings__subsidy_interval__set_double_value__max_money_dou
BOOST_REQUIRE_EQUAL(configuration.max_money(), double_max_money);
}

BOOST_AUTO_TEST_CASE(settings__retargeting_factor__set_double_value__timespan_limits_scaled)
{
settings configuration(config::settings::mainnet);
const auto double_maximum_timespan = configuration.maximum_timespan() * 2;
const auto half_minimum_timespan = configuration.minimum_timespan() / 2;
configuration.retargeting_factor(8);
BOOST_REQUIRE_EQUAL(configuration.maximum_timespan(), double_maximum_timespan);
BOOST_REQUIRE_EQUAL(configuration.minimum_timespan(), half_minimum_timespan);
}

BOOST_AUTO_TEST_CASE(settings__retargeting_interval_seconds__set_double_value__timespan_limits_scaled)
{
settings configuration(config::settings::mainnet);
const auto double_interval_seconds = configuration.retargeting_interval_seconds() * 2;
const auto double_maximum_timespan = configuration.maximum_timespan() * 2;
const auto double_minimum_timespan = configuration.minimum_timespan() * 2;
const auto double_retargeting_interval = configuration.retargeting_interval() * 2;
configuration.retargeting_interval_seconds(double_interval_seconds);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval_seconds(), double_interval_seconds);
BOOST_REQUIRE_EQUAL(configuration.maximum_timespan(), double_maximum_timespan);
BOOST_REQUIRE_EQUAL(configuration.minimum_timespan(), double_minimum_timespan);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval(), double_retargeting_interval);
}

BOOST_AUTO_TEST_CASE(settings__block_spacing_seconds__set_double_value__retargeting_interval_halved)
{
settings configuration(config::settings::mainnet);
const auto double_block_spacing_seconds = configuration.block_spacing_seconds() * 2;
const auto half_retargeting_interval = configuration.retargeting_interval() / 2;
configuration.block_spacing_seconds(double_block_spacing_seconds);
BOOST_REQUIRE_EQUAL(configuration.block_spacing_seconds(), double_block_spacing_seconds);
BOOST_REQUIRE_EQUAL(configuration.retargeting_interval(), half_retargeting_interval);
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 64791d4

Please sign in to comment.