Skip to content

Commit

Permalink
Change POW algo (CryptoNight Lite, Variation 1)
Browse files Browse the repository at this point in the history
Change Difficulty algo (LWMA-2)
Improvements for CXX 7
  • Loading branch information
4egod committed Jun 22, 2018
1 parent b6c3702 commit ebea96c
Show file tree
Hide file tree
Showing 22 changed files with 393 additions and 105 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ To go futher you have to have a number of packages and utilities. You need at le
* Boost (1.62 or newer):
You need boost in `bcndev` folder. We do not configure to use boost installed by `apt-get`, because it is sometimes updated without your control by installing some unrelated packages. Also some users reported crashes after `find_package` finds headers from one version of boost and libraries from different version, or if installed boost uses dynamic linking.
```
$bitsum> wget -c 'https://dl.bintray.com/boostorg/release/1.67.0/source/boost_1_67_0.tar.gz'
$bitsum> tar xf boost_1_67_0.tar.gz
$bitsum> mv boost_1_67_0 boost
$bitsum> wget -c 'https://dl.bintray.com/boostorg/release/1.65.1/source/boost_1_65_1.tar.gz'
$bitsum> tar xf boost_1_65_1.tar.gz
$bitsum> mv boost_1_65_1 boost
$bitsum> cd boost
$bitsum/boost> ./bootstrap.sh
$bitsum/boost> ./b2 link=static cxxflags="-fPIC" linkflags="-pie" -j 8 --build-dir=build64 --stagedir=stage
Expand Down Expand Up @@ -139,7 +139,7 @@ Then build and install Boost:
```
$~> cd ~/Downloads/boost_1_67_0/
$~/Downloads/boost_1_67_0> ./bootstrap.sh
$~/Downloads/boost_1_67_0> ./b2 -a -j 4 cxxflags="-stdlib=libc++ -std=c++14 -mmacosx-version-min=10.11 -isysroot/Users/user/Downloads/MacOSX10.11.sdk" install`
$~/Downloads/boost_1_67_0> ./b2 -a -j 4 cxxflags="-stdlib=libc++ -std=c++14 -mmacosx-version-min=10.11 -isysroot/Users/user/Downloads/MacOSX10.11.sdk -fPIC" linkflags="-pie" install`
```
Install OpenSSL to `bitsum/openssl` folder:
Expand Down
5 changes: 5 additions & 0 deletions ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
## Release Notes

### v1.18.6.22
- Change POW algo (CryptoNight Lite, Variation 1)
- Change Difficulty algo (LWMA-2)
- Improvements for CXX 7

### v1.18.6.1
- Merge code with bytecoin v3.1.1
- Fix importing keys
Expand Down
16 changes: 8 additions & 8 deletions src/Core/BlockChainState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ std::string BlockChainState::check_standalone_consensus(
return "PARENT_BLOCK_SIZE_TOO_BIG";
}
const uint64_t now = time(nullptr); // It would be better to pass now through Node
if (block.header.timestamp > now + m_currency.block_future_time_limit)
if (block.header.timestamp > now + m_currency.get_block_future_time_limit(get_tip_height() + 1))
return "TIMESTAMP_TOO_FAR_IN_FUTURE";
if (block.header.timestamp < info->timestamp_median)
return "TIMESTAMP_TOO_FAR_IN_PAST";
Expand Down Expand Up @@ -291,7 +291,7 @@ std::string BlockChainState::check_standalone_consensus(
{
std::vector<Timestamp> timestamps;
std::vector<Difficulty> difficulties;
Height blocks_count = std::min(prev_info.height, m_currency.difficulty_blocks_count());
Height blocks_count = std::min(prev_info.height, m_currency.get_difficulty_blocks_count(get_tip_height() + 1));
auto timestamps_window = get_tip_segment(prev_info, blocks_count, false);
size_t actual_count = timestamps_window.size();
timestamps.resize(actual_count);
Expand Down Expand Up @@ -367,21 +367,21 @@ void BlockChainState::calculate_consensus_values(const api::BlockHeader &prev_in
last_blocks_sizes.push_back(it->block_size);
*next_median_size = common::median_value(&last_blocks_sizes);

window = get_tip_segment(prev_info, m_currency.timestamp_check_window, false);
if (window.size() >= m_currency.timestamp_check_window) {
window = get_tip_segment(prev_info, m_currency.get_timestamp_check_window(get_tip_height() + 1), false);
if (window.size() >= m_currency.get_timestamp_check_window(get_tip_height() + 1)) {
std::vector<Timestamp> timestamps;
timestamps.reserve(m_currency.timestamp_check_window);
timestamps.reserve(m_currency.get_timestamp_check_window(get_tip_height() + 1));
for (auto it = window.begin(); it != window.end(); ++it)
timestamps.push_back(it->timestamp);
*next_median_timestamp = common::median_value(&timestamps); // sorts timestamps
*next_unlock_timestamp = timestamps[timestamps.size() / 2];
// unlike median_value, here we select lesser of 2 middle values for
// even-sized array, so
// that m_next_unlock_timestamp will never decrease with block number
if (*next_unlock_timestamp < m_currency.block_future_time_limit)
if (*next_unlock_timestamp < m_currency.get_block_future_time_limit(get_tip_height() + 1))
*next_unlock_timestamp = 0;
else
*next_unlock_timestamp -= m_currency.block_future_time_limit;
*next_unlock_timestamp -= m_currency.get_block_future_time_limit(get_tip_height() + 1);
} else {
*next_median_timestamp = 0;
*next_unlock_timestamp = 0;
Expand All @@ -400,7 +400,7 @@ bool BlockChainState::create_mining_block_template(BlockTemplate *b, const Accou
{
std::vector<Timestamp> timestamps;
std::vector<Difficulty> difficulties;
Height blocks_count = std::min(get_tip_height(), m_currency.difficulty_blocks_count());
Height blocks_count = std::min(get_tip_height(), m_currency.get_difficulty_blocks_count(get_tip_height() + 1));
timestamps.reserve(blocks_count);
difficulties.reserve(blocks_count);
auto timestamps_window = get_tip_segment(read_header(get_tip_bid()), blocks_count, false);
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ static void parse_peer_and_add_to_container(const std::string &str, std::vector<
using namespace common;
using namespace bytecoin;

const static UUID BYTECOIN_NETWORK = { { 0x4C, 0x7E, 0x03, 0x32, 0x6A, 0x3F, 0x75, 0x16, 0x0B, 0x4C, 0xA1, 0xE3, 0x61, 0xD1, 0xDD, 0x17 } }; // Bender's nightmare
const static UUID BYTECOIN_NETWORK = { { 0x4C, 0x7E, 0x03, 0x32, 0x6A, 0x3F, 0x75, 0x16, 0x0B, 0x4C, 0xA1, 0xE3, 0x61, 0xD1, 0xDD, 0x20 } }; // Bender's nightmare

Config::Config(common::CommandLine &cmd)
: is_testnet(cmd.get_bool("--testnet"))
Expand Down
94 changes: 89 additions & 5 deletions src/Core/Currency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,15 @@ Currency::Currency(bool is_testnet)
, locked_tx_allowed_delta_blocks(parameters::CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS)
, upgrade_height_v2(parameters::UPGRADE_HEIGHT_V2)
, upgrade_height_v3(parameters::UPGRADE_HEIGHT_V3)
, current_transaction_version(CURRENT_TRANSACTION_VERSION) {
, upgrade_height_v4(parameters::UPGRADE_HEIGHT_V4)
, current_transaction_version(CURRENT_TRANSACTION_VERSION)
, hardfork_v1_height(parameters::HARDFORK_V1_HEIGHT)
, hardfork_v2_height(parameters::HARDFORK_V2_HEIGHT)
, hardfork_v3_height(parameters::HARDFORK_V3_HEIGHT)
, timestamp_check_window_v2(parameters::BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2)
, block_future_time_limit_v2(parameters::CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2)
, difficulty_window_v2(parameters::DIFFICULTY_WINDOW_V2)
, difficulty_blocks_count_v2(parameters::DIFFICULTY_BLOCKS_COUNT_V2) {
if (is_testnet) {
upgrade_height_v2 = 0;
upgrade_height_v3 = static_cast<Height>(-1);
Expand Down Expand Up @@ -142,7 +150,9 @@ uint8_t Currency::get_block_major_version_for_height(Height height) const {
return 1;
if (height > upgrade_height_v2 && height <= upgrade_height_v3)
return 2;
return 3; // info.height > currency.upgrade_height_v3
if (height > upgrade_height_v3 && height <= upgrade_height_v4)
return 3;
return 4;
}

uint32_t Currency::block_granted_full_reward_zone_by_block_version(uint8_t block_major_version) const {
Expand Down Expand Up @@ -386,6 +396,16 @@ bool Currency::parse_amount(size_t number_of_decimal_places, const std::string &

Difficulty Currency::next_difficulty(Height block_index,
std::vector<Timestamp> timestamps, std::vector<Difficulty> cumulative_difficulties) const {
if (block_index <= hardfork_v2_height)
{
return next_difficulty_v1(block_index, timestamps, cumulative_difficulties);
}

return next_difficulty_v2(timestamps, cumulative_difficulties);
}

Difficulty Currency::next_difficulty_v1(Height block_index, std::vector<Timestamp> timestamps, std::vector<Difficulty> cumulative_difficulties) const
{
std::vector<Timestamp> timestamps_o(timestamps);
std::vector<Difficulty> cumulativeDifficulties_o(cumulative_difficulties);
size_t c_difficultyWindow = difficulty_window;
Expand Down Expand Up @@ -431,8 +451,7 @@ Difficulty Currency::next_difficulty(Height block_index,
return 0;
}

//auto c = (low + timeSpan - 1) / timeSpan;
if (block_index >= 106195) {
if (block_index >= hardfork_v1_height) {
if (high != 0) {
return 0;
}
Expand Down Expand Up @@ -490,6 +509,44 @@ Difficulty Currency::next_difficulty(Height block_index,
return (low + timeSpan - 1) / timeSpan;
}

// LWMA-2 difficulty algorithm
// Copyright (c) 2017-2018 Zawy, MIT License
// https://github.com/zawy12/difficulty-algorithms/issues/3
Difficulty Currency::next_difficulty_v2(std::vector<Timestamp> timestamps, std::vector<Difficulty> cumulative_difficulties) const
{
int64_t T = difficulty_target;
int64_t N = difficulty_window_v2;
int64_t FTL = block_future_time_limit_v2;
int64_t L(0), ST, sum_3_ST(0), next_D, prev_D;

if (timestamps.size() <= static_cast<uint64_t>(N))
{
return 1000;
}

for (int64_t i = 1; i <= N; i++)
{
ST = std::max(-FTL, std::min(static_cast<int64_t>(timestamps[i]) - static_cast<int64_t>(timestamps[i - 1]), 6 * T));

L += ST * i;

if (i > N - 3)
{
sum_3_ST += ST;
}
}

next_D = (cumulative_difficulties[N] - cumulative_difficulties[0]) * T * (N + 1) * 99 / (100 * 2 * L);
prev_D = cumulative_difficulties[N] - cumulative_difficulties[N - 1];

if (sum_3_ST < (8 * T) / 10)
{
next_D = (prev_D * 110) / 100;
}

return static_cast<Difficulty>(next_D);
}

bool Currency::check_proof_of_work_v1(const Hash &long_block_hash,
const BlockTemplate &block,
Difficulty current_difficulty) const {
Expand Down Expand Up @@ -536,6 +593,7 @@ bool Currency::check_proof_of_work(const Hash &long_block_hash,
return check_proof_of_work_v1(long_block_hash, block, current_difficulty);
case 2:
case 3:
case 4:
return check_proof_of_work_v2(long_block_hash, block, current_difficulty);
}
// logger(ERROR, BrightRed) << "Unknown block major version: " <<
Expand Down Expand Up @@ -610,10 +668,36 @@ Hash bytecoin::get_block_long_hash(const BlockTemplate &bh, crypto::CryptoNightC
auto raw_hashing_block = get_block_hashing_binary_array(bh);
return crypto_ctx.cn_slow_hash(raw_hashing_block.data(), raw_hashing_block.size());
}
if (bh.major_version >= 2) {
if (bh.major_version >= 2 && bh.major_version < 4) {
auto serializer = make_parent_block_serializer(bh, true, true);
BinaryArray raw_hashing_block = seria::to_binary(serializer);
return crypto_ctx.cn_slow_hash(raw_hashing_block.data(), raw_hashing_block.size());
}
if (bh.major_version >= 4) {
auto serializer = make_parent_block_serializer(bh, true, true);
BinaryArray raw_hashing_block = seria::to_binary(serializer);
return crypto_ctx.cn_lite_slow_hash_v1(raw_hashing_block.data(), raw_hashing_block.size());
}

throw std::runtime_error("Unknown block major version.");
}

Height Currency::get_timestamp_check_window(Height height) const
{
return height >= hardfork_v2_height ? timestamp_check_window_v2 : timestamp_check_window;
}

Timestamp Currency::get_block_future_time_limit(Height height) const
{
return height >= hardfork_v2_height ? block_future_time_limit_v2 : block_future_time_limit;
}

Height bytecoin::Currency::get_difficulty_blocks_count(Height height) const
{
if (height <= hardfork_v2_height)
{
return difficulty_blocks_count();
}

return difficulty_blocks_count_v2;
}
17 changes: 17 additions & 0 deletions src/Core/Currency.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class Currency { // Consensus calcs depend on those parameters
Height difficulty_lag;
size_t difficulty_cut;
Height difficulty_blocks_count() const { return difficulty_window + difficulty_lag; }
Height get_difficulty_blocks_count(Height height) const;

uint64_t max_block_size_initial;
uint64_t max_block_size_growth_speed_numerator;
Expand All @@ -59,10 +60,20 @@ class Currency { // Consensus calcs depend on those parameters

Height upgrade_height_v2;
Height upgrade_height_v3;
Height upgrade_height_v4;
uint8_t get_block_major_version_for_height(Height) const;

uint8_t current_transaction_version;

Height hardfork_v1_height;
Height hardfork_v2_height;
Height hardfork_v3_height;

Height timestamp_check_window_v2;
Timestamp block_future_time_limit_v2;
Height difficulty_window_v2;
Height difficulty_blocks_count_v2;

size_t checkpoint_count() const;
bool is_in_checkpoint_zone(Height index) const;
bool check_block_checkpoint(Height index, const crypto::Hash &h, bool &is_checkpoint) const;
Expand All @@ -89,6 +100,10 @@ class Currency { // Consensus calcs depend on those parameters

Difficulty next_difficulty(Height block_index,
std::vector<Timestamp> timestamps, std::vector<Difficulty> cumulative_difficulties) const;

Difficulty next_difficulty_v1(Height block_index, std::vector<Timestamp> timestamps, std::vector<Difficulty> cumulative_difficulties) const;

Difficulty next_difficulty_v2(std::vector<Timestamp> timestamps, std::vector<Difficulty> cumulative_difficulties) const;

bool check_proof_of_work_v1(
const Hash &long_block_hash, const BlockTemplate &block, Difficulty current_difficulty) const;
Expand All @@ -106,6 +121,8 @@ class Currency { // Consensus calcs depend on those parameters
return block_time + locked_tx_allowed_delta_seconds >= unlock_time;
}
static bool is_dust(Amount am);
Height get_timestamp_check_window(Height height) const;
Timestamp get_block_future_time_limit(Height height) const;
static uint64_t get_penalized_amount(uint64_t amount, size_t median_size, size_t current_block_size);
static std::string get_account_address_as_str(uint64_t prefix, const AccountPublicAddress &adr);
static bool parse_account_address_string(uint64_t *prefix, AccountPublicAddress *adr, const std::string &str);
Expand Down
6 changes: 3 additions & 3 deletions src/Core/Node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ void Node::advance_long_poll() {
if (!prevent_sleep && m_block_chain.get_tip().timestamp < now - 86400)
prevent_sleep = std::make_unique<platform::PreventSleep>("Downloading blockchain");
if (prevent_sleep &&
m_block_chain.get_tip().timestamp > now - m_block_chain.get_currency().block_future_time_limit * 2)
m_block_chain.get_tip().timestamp > now - m_block_chain.get_currency().get_block_future_time_limit(m_block_chain.get_tip_height() + 1) * 2)
prevent_sleep = nullptr;
if (m_long_poll_http_clients.empty())
return;
Expand Down Expand Up @@ -537,9 +537,9 @@ bool Node::on_wallet_sync3(http::Client *, http::RequestData &&, json_rpc::Reque
if (req.max_count > api::bytecoind::SyncBlocks::Request::MAX_COUNT)
throw std::runtime_error(
"Too big max_count - must be < " + std::to_string(api::bytecoind::SyncBlocks::Request::MAX_COUNT));
auto first_block_timestamp = req.first_block_timestamp < m_block_chain.get_currency().block_future_time_limit
auto first_block_timestamp = req.first_block_timestamp < m_block_chain.get_currency().get_block_future_time_limit(m_block_chain.get_tip_height() + 1)
? 0
: req.first_block_timestamp - m_block_chain.get_currency().block_future_time_limit;
: req.first_block_timestamp - m_block_chain.get_currency().get_block_future_time_limit(m_block_chain.get_tip_height() + 1);
Height full_offset = m_block_chain.get_timestamp_lower_bound_block_index(first_block_timestamp);
Height start_block_index;
std::vector<crypto::Hash> supplement =
Expand Down
6 changes: 3 additions & 3 deletions src/Core/WalletState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ void WalletState::wallet_addresses_updated() {
// case of ctrl-c
}
while (m_tip_height + 1 > m_tail_height &&
get_tip().timestamp + m_currency.block_future_time_limit >=
get_tip().timestamp + m_currency.get_block_future_time_limit(get_tip_height() + 1) >=
undo_timestamp) { // Undo excess blocks in case timestamps are out of
// order
undo_block(m_tip_height);
Expand Down Expand Up @@ -335,7 +335,7 @@ std::vector<WalletRecord> WalletState::generate_new_addresses(const std::vector<
return result;
}
while (m_tip_height + 1 > m_tail_height &&
get_tip().timestamp + m_currency.block_future_time_limit >=
get_tip().timestamp + m_currency.get_block_future_time_limit(get_tip_height() + 1) >=
undo_timestamp) { // Undo excess blocks in case timestamps are out of
// order
undo_block(m_tip_height);
Expand Down Expand Up @@ -383,7 +383,7 @@ bool WalletState::sync_with_blockchain(api::bytecoind::SyncBlocks::Response &res
const api::BlockHeader &header = resp.blocks.at(bin).header;
if (m_tip_height + 1 != m_tail_height && header.previous_block_hash != m_tip.hash)
return false;
if (header.timestamp + m_currency.block_future_time_limit >= m_wallet.get_oldest_timestamp()) {
if (header.timestamp + m_currency.get_block_future_time_limit(get_tip_height() + 1) >= m_wallet.get_oldest_timestamp()) {
const auto &block_gi = resp.blocks.at(bin).global_indices;
PreparedWalletBlock pb = preparator.get_ready_work(m_tip_height + 1);
// PreparedWalletBlock pb(std::move(resp.blocks.at(bin).block), m_wallet.get_view_secret_key());
Expand Down
2 changes: 1 addition & 1 deletion src/Core/WalletSync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ void WalletSync::advance_sync() {
if (!prevent_sleep && m_wallet_state.get_tip().timestamp < now - 86400)
prevent_sleep = std::make_unique<platform::PreventSleep>("Synchronizing wallet");
if (prevent_sleep &&
m_wallet_state.get_tip().timestamp > now - m_wallet_state.get_currency().block_future_time_limit * 2)
m_wallet_state.get_tip().timestamp > now - m_wallet_state.get_currency().get_block_future_time_limit(m_wallet_state.get_tip_height() + 1) * 2)
prevent_sleep = nullptr;
if (m_sync_request)
return;
Expand Down
14 changes: 13 additions & 1 deletion src/CryptoNoteConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@
namespace bytecoin {
namespace parameters {

const uint32_t HARDFORK_V1_HEIGHT = 106195;
const uint32_t HARDFORK_V2_HEIGHT = 162000;
const uint32_t HARDFORK_V3_HEIGHT = 4294967294;

const uint32_t DIFFICULTY_TARGET = 120; // seconds
const uint32_t CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2 = DIFFICULTY_TARGET * 3;
const uint32_t BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 = 11;
const uint64_t DIFFICULTY_WINDOW_V2 = 60;
const uint64_t DIFFICULTY_BLOCKS_COUNT_V2 = DIFFICULTY_WINDOW_V2 + 1;

const uint32_t CRYPTONOTE_MAX_BLOCK_NUMBER = 500000000;
const uint32_t CRYPTONOTE_MAX_BLOCK_BLOB_SIZE = 500000000;
const uint32_t CRYPTONOTE_MAX_TX_SIZE = 1000000000;
Expand All @@ -38,7 +48,6 @@ const size_t CRYPTONOTE_DISPLAY_DECIMAL_POINT = 10;
const uint64_t MINIMUM_FEE = 1000000; // pow(10, 6)
const uint64_t DEFAULT_DUST_THRESHOLD = 1000000; // pow(10, 6)

const uint32_t DIFFICULTY_TARGET = 120; // seconds
constexpr uint32_t EXPECTED_NUMBER_OF_BLOCKS_PER_DAY(uint32_t difficulty_target) {
return 24 * 60 * 60 / difficulty_target;
}
Expand Down Expand Up @@ -73,6 +82,7 @@ const uint32_t CRYPTONOTE_MEMPOOL_TX_LIVETIME = 60 * 60 * 24; // seconds, one d

const uint32_t UPGRADE_HEIGHT_V2 = 1;
const uint32_t UPGRADE_HEIGHT_V3 = 2;
const uint32_t UPGRADE_HEIGHT_V4 = HARDFORK_V2_HEIGHT;

const char CRYPTONOTE_BLOCKS_FILENAME[] = "blocks.bin";
const char CRYPTONOTE_BLOCKINDEXES_FILENAME[] = "blockindexes.bin";
Expand Down Expand Up @@ -134,5 +144,7 @@ constexpr const CheckpointData CHECKPOINTS[] = {
{ 130000, "80add5a415bf8c325497923e039db00de2a086a9dda95e142b03f267e7b7d0c0" },
{ 140000, "efab6c622247beaa832a9f14c0a4844055c442baa089c5586ff34cd23db69107" },
{ 150000, "9e1582b1d8b2539947299655f1b12d9a65d379d1f5cae650e8049ff083c0b39a" },
{ 160000, "a1d285e1faffe828bc2a16ed94e9da284a9ee1960748fe88dc7261871ec14a1c" },
{ 162000, "645a8e5bf0f8a10ee5f950f7abf7113b1f7b0e5cc50261234fd5d79acf3b1164" },
};
} // CryptoNote
Loading

0 comments on commit ebea96c

Please sign in to comment.