Skip to content

Commit

Permalink
Add the batch of release v3.0.3 commits
Browse files Browse the repository at this point in the history
  • Loading branch information
developer-at-bcn committed May 9, 2018
1 parent 3fe90e3 commit 8d7795e
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 50 deletions.
4 changes: 4 additions & 0 deletions ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## Release Notes

### v3.0.3

- Fix consensus bug.

### v3.0.2

- __API change:__ In `create_transaction`, `spend_address` parameter of type `string` is changed to `spend_addresses` of type `[]string`. This change is likely to affect only Web wallets developers.
Expand Down
85 changes: 58 additions & 27 deletions src/Core/BlockChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,9 @@ BlockChain::BlockChain(const Hash &genesis_bid, const std::string &coin_folder)
}

void BlockChain::db_commit() {
std::cout << "BlockChain::db_commit started... tip_height=" << m_tip_height << std::endl;
std::cout << "BlockChain::db_commit started... tip_height=" << m_tip_height << " header_cache.size=" << header_cache.size() << std::endl;

This comment has been minimized.

Copy link
@SoraKohaku

SoraKohaku May 9, 2018

agreed for tim segment for cache header for size need

m_db.commit_db_txn();
header_cache.clear(); // Most simple cache policy ever
std::cout << "BlockChain::db_commit finished..." << std::endl;
}

Expand Down Expand Up @@ -465,15 +466,14 @@ bool BlockChain::redo_block(const Hash &bhash, const RawBlock &, const Block &bl
m_db.put(bkey, std::string(), true);
}

m_tip_segment.push_back(info);
if (m_tip_segment.size() > 2048) // TODO - should be enough for all block windows we use
m_tip_segment.pop_front();

// m_tip_segment.push_back(info);
// if (m_tip_segment.size() > 2048) // TODO - should be enough for all block windows we use
// m_tip_segment.pop_front();
return true;
}
void BlockChain::undo_block(const Hash &bhash, const RawBlock &, const Block &block, Height height) {
if (!m_tip_segment.empty())
m_tip_segment.pop_back();
// if (!m_tip_segment.empty())
// m_tip_segment.pop_back();
undo_block(bhash, block, height);

auto tikey = TIMESTAMP_BLOCK_PREFIX + common::write_varint_sqlite4(block.header.timestamp) +
Expand Down Expand Up @@ -521,15 +521,22 @@ void BlockChain::store_header(const Hash &bid, const api::BlockHeader &header) {
}

bool BlockChain::read_header(const Hash &bid, api::BlockHeader &header) const {
if (bid == m_tip_bid && !m_tip_segment.empty()) {
header = m_tip_segment.back();
auto cit = header_cache.find(bid);
if( cit != header_cache.end() ){
header = cit->second;
return true;
}
// if (bid == m_tip_bid && !m_tip_segment.empty()) {
// header = m_tip_segment.back();
// return true;
// }
BinaryArray rb;
auto key = HEADER_PREFIX + DB::to_binary_key(bid.data, sizeof(bid.data)) + HEADER_SUFFIX;
if (!m_db.get(key, rb))
return false;
Hash bbid = bid;
seria::from_binary(header, rb);
header_cache.insert(std::make_pair(bbid, header));
return true;
}

Expand All @@ -541,25 +548,49 @@ api::BlockHeader BlockChain::read_header(const Hash &bid) const {
}

const api::BlockHeader &BlockChain::get_tip() const {
if (m_tip_segment.empty())
m_tip_segment.push_back(read_header(get_tip_bid()));
return m_tip_segment.back();
}

std::pair<std::deque<api::BlockHeader>::const_iterator, std::deque<api::BlockHeader>::const_iterator>
BlockChain::get_tip_segment(Height height_delta, Height window, bool add_genesis) const {
if (get_tip_height() == (Height)-1 || height_delta > get_tip_height())
return std::make_pair(m_tip_segment.end(), m_tip_segment.end());
while (m_tip_segment.size() < height_delta + window && m_tip_segment.size() < m_tip_height + 1) {
Hash ha = read_chain(static_cast<uint32_t>(m_tip_height - m_tip_segment.size()));
m_tip_segment.push_front(read_header(ha));
auto cit = header_cache.find(get_tip_bid());
if( cit != header_cache.end() ){
return cit->second;
}
if (m_tip_height + 1 <= height_delta + window) {
// if( m_tip_segment.size() == m_tip_height + 1 ) {
// if (height_delta + window >= m_tip_segment.size()) {
return std::make_pair(m_tip_segment.begin() + (add_genesis ? 0 : 1), m_tip_segment.end() - height_delta);
read_header(get_tip_bid());
cit = header_cache.find(get_tip_bid());
if( cit == header_cache.end() )
throw std::logic_error("After read_header, header should be in header_cache");
return cit->second;
// if (m_tip_segment.empty())
// m_tip_segment.push_back(read_header(get_tip_bid()));
// return m_tip_segment.back();
}

std::vector<api::BlockHeader>
BlockChain::get_tip_segment(const api::BlockHeader & prev_info, Height window, bool add_genesis) const {
std::vector<api::BlockHeader> result;
if( prev_info.height == Height(-1))
return result;
api::BlockHeader pi = prev_info;
while(result.size() < window && pi.height != 0){
result.push_back(pi);
if( !read_header(pi.previous_block_hash, pi) )
throw std::logic_error("Invariant dead - previous block header not found in get_tip_segment");
}
if( result.size() < window && add_genesis){
if( pi.height != 0)
throw std::logic_error("Invariant dead - window size not reached, but genesis not found in get_tip_segment");
result.push_back(pi);
}
return std::make_pair(m_tip_segment.end() - window - height_delta, m_tip_segment.end() - height_delta);
// if (get_tip_height() == (Height)-1 || height_delta > get_tip_height())
// return std::make_pair(m_tip_segment.end(), m_tip_segment.end());
// while (m_tip_segment.size() < height_delta + window && m_tip_segment.size() < m_tip_height + 1) {
// Hash ha = read_chain(static_cast<uint32_t>(m_tip_height - m_tip_segment.size()));
// m_tip_segment.push_front(read_header(ha));
// }
// if (m_tip_height + 1 <= height_delta + window) {
// if( m_tip_segment.size() == m_tip_height + 1 ) {
// if (height_delta + window >= m_tip_segment.size()) {
// return std::make_pair(m_tip_segment.begin() + (add_genesis ? 0 : 1), m_tip_segment.end() - height_delta);
// }
std::reverse(result.begin(), result.end());
return result;// std::make_pair(m_tip_segment.end() - window - height_delta, m_tip_segment.end() - height_delta);
}

void BlockChain::read_tip() {
Expand Down Expand Up @@ -759,7 +790,7 @@ void BlockChain::test_undo_everything() {
api::BlockHeader info = get_tip();
m_tip_bid = block.header.previous_block_hash;
m_tip_cumulative_difficulty -= info.cumulative_difficulty;
if (get_tip_height() % 50000 == 1)
if (get_tip_height() % 50000 == 1 )
db_commit();
}
std::cout << "---- After undo everything ---- " << std::endl;
Expand Down
7 changes: 4 additions & 3 deletions src/Core/BlockChain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#pragma once

#include <deque>
#include <unordered_map>
#include "CryptoNote.hpp"
#include "Currency.hpp"
#include "platform/DB.hpp"
Expand Down Expand Up @@ -43,8 +44,8 @@ class BlockChain {
Height get_tip_height() const { return m_tip_height; }
const api::BlockHeader &get_tip() const;

std::pair<std::deque<api::BlockHeader>::const_iterator, std::deque<api::BlockHeader>::const_iterator>
get_tip_segment(Height height_delta, Height window, bool add_genesis) const;
std::vector<api::BlockHeader>
get_tip_segment(const api::BlockHeader & prev_info, Height window, bool add_genesis) const;

bool read_chain(Height height, Hash &bid) const;
bool read_block(const Hash &bid, RawBlock &rb) const;
Expand Down Expand Up @@ -102,7 +103,7 @@ class BlockChain {
void read_tip();
void push_chain(Hash bid, Difficulty cumulative_difficulty);
void pop_chain();
mutable std::deque<api::BlockHeader> m_tip_segment;
mutable std::unordered_map<Hash, api::BlockHeader> header_cache;
// We cache recent headers for quick calculation in block windows

void store_block(const Hash &bid, const BinaryArray &block_data);
Expand Down
29 changes: 14 additions & 15 deletions src/Core/BlockChainState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,8 @@ std::string BlockChainState::get_standalone_consensus_error(
info.timestamp_median = m_next_median_timestamp;
info.timestamp_unlock = m_next_unlock_timestamp;

if (get_tip_height() != prev_info.height) // Optimization for most common case
calculate_consensus_values(
get_tip_height() - prev_info.height, info.size_median, info.timestamp_median, info.timestamp_unlock);
if (get_tip_bid() != prev_info.hash) // Optimization for most common case
calculate_consensus_values(prev_info, info.size_median, info.timestamp_median, info.timestamp_unlock);

auto next_block_granted_full_reward_zone = m_currency.block_granted_full_reward_zone_by_block_version(
block.header.major_version); // We will check version later in this fun
Expand Down Expand Up @@ -229,12 +228,12 @@ std::string BlockChainState::get_standalone_consensus_error(
std::vector<Timestamp> timestamps;
std::vector<Difficulty> difficulties;
Height blocks_count = std::min(prev_info.height, m_currency.difficulty_blocks_count());
auto timestamps_window = get_tip_segment(get_tip_height() - prev_info.height, blocks_count, false);
size_t actual_count = timestamps_window.second - timestamps_window.first;
auto timestamps_window = get_tip_segment(prev_info, blocks_count, false);
size_t actual_count = timestamps_window.size();
timestamps.resize(actual_count);
difficulties.resize(actual_count);
size_t pos = 0;
for (auto it = timestamps_window.first; it != timestamps_window.second; ++it, ++pos) {
for (auto it = timestamps_window.begin(); it != timestamps_window.end(); ++it, ++pos) {
timestamps.at(pos) = it->timestamp;
difficulties.at(pos) = it->cumulative_difficulty;
}
Expand Down Expand Up @@ -287,20 +286,20 @@ std::string BlockChainState::get_standalone_consensus_error(
return std::string();
}

void BlockChainState::calculate_consensus_values(Height height_delta, uint32_t &next_median_size,
void BlockChainState::calculate_consensus_values(const api::BlockHeader & prev_info, uint32_t &next_median_size,
Timestamp &next_median_timestamp, Timestamp &next_unlock_timestamp) const {
std::vector<uint32_t> last_blocks_sizes;
auto window = get_tip_segment(height_delta, m_currency.reward_blocks_window, true);
auto window = get_tip_segment(prev_info, m_currency.reward_blocks_window, true);
last_blocks_sizes.reserve(m_currency.reward_blocks_window);
for (auto it = window.first; it != window.second; ++it)
for (auto it = window.begin(); it != window.end(); ++it)
last_blocks_sizes.push_back(it->block_size);
next_median_size = common::median_value(last_blocks_sizes);

window = get_tip_segment(height_delta, m_currency.timestamp_check_window, false);
if (window.second - window.first >= static_cast<ptrdiff_t>(m_currency.timestamp_check_window)) {
window = get_tip_segment(prev_info, m_currency.timestamp_check_window, false);
if (window.size() >= m_currency.timestamp_check_window) {
std::vector<Timestamp> timestamps;
timestamps.reserve(m_currency.timestamp_check_window);
for (auto it = window.first; it != window.second; ++it)
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];
Expand All @@ -318,7 +317,7 @@ void BlockChainState::calculate_consensus_values(Height height_delta, uint32_t &
}

void BlockChainState::tip_changed() {
calculate_consensus_values(0, m_next_median_size, m_next_median_timestamp, m_next_unlock_timestamp);
calculate_consensus_values(read_header(get_tip_bid()), m_next_median_size, m_next_median_timestamp, m_next_unlock_timestamp);
}

bool BlockChainState::create_mining_block_template(BlockTemplate &b, const AccountPublicAddress &adr,
Expand All @@ -331,8 +330,8 @@ bool BlockChainState::create_mining_block_template(BlockTemplate &b, const Accou
Height blocks_count = std::min(get_tip_height(), m_currency.difficulty_blocks_count());
timestamps.reserve(blocks_count);
difficulties.reserve(blocks_count);
auto timestamps_window = get_tip_segment(0, blocks_count, false);
for (auto it = timestamps_window.first; it != timestamps_window.second; ++it) {
auto timestamps_window = get_tip_segment(read_header(get_tip_bid()), blocks_count, false);
for (auto it = timestamps_window.begin(); it != timestamps_window.end(); ++it) {
timestamps.push_back(it->timestamp);
difficulties.push_back(it->cumulative_difficulty);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Core/BlockChainState.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class BlockChainState : public BlockChain, private IBlockChainState {
Timestamp m_next_unlock_timestamp = 0;
uint32_t m_next_median_size = 0;
virtual void tip_changed() override; // Updates values above
void calculate_consensus_values(Height height_delta, uint32_t &next_median_size, Timestamp &next_median_timestamp,
void calculate_consensus_values(const api::BlockHeader & prev_info, uint32_t &next_median_size, Timestamp &next_median_timestamp,
Timestamp &next_unlock_timestamp) const;

RingCheckerMulticore ring_checker;
Expand Down
3 changes: 2 additions & 1 deletion src/main_bytecoind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ static const char USAGE[] =
--testnet Configure for testnet.
--p2p-bind-address=<ip:port> Interface and port for P2P network protocol [default: 0.0.0.0:8080].
--p2p-external-port=<port> External port for P2P network protocol, if port forwarding used with NAT [default: 8080].
--bytecoind-bind-address=<ip:port> Interface and port for bytecoind RPC [default: 0.0.0.0:8081].
--bytecoind-bind-address=<ip:port> Interface and port for bytecoind RPC [default: 127.0.0.1:8081].
--seed-node-address=<ip:port> Specify list (one or more) of nodes to start connecting to.
--priority-node-address=<ip:port> Specify list (one or more) of nodes to connect to and attempt to keep the connection open.
--exclusive-node-address=<ip:port> Specify list (one or more) of nodes to connect to only. All other nodes including seed nodes will be ignored.
Expand Down Expand Up @@ -72,6 +72,7 @@ int main(int argc, const char *argv[]) try {
logManager.configure_default(config.get_data_folder("logs"), "bytecoind-");

BlockChainState block_chain(logManager, config, currency);
// block_chain.test_undo_everything();

if (!export_blocks.empty()) {
if (!LegacyBlockChainWriter::export_blockchain2(export_blocks, block_chain))
Expand Down
2 changes: 1 addition & 1 deletion src/main_walletd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Options for built-in bytecoind (run when no --bytecoind-remote-address specified
--allow-local-ip Allow local ip add to peer list, mostly in debug purposes.
--p2p-bind-address=<ip:port> Interface and port for P2P network protocol [default: 0.0.0.0:8080].
--p2p-external-port=<port> External port for P2P network protocol, if port forwarding used with NAT [default: 8080].
--bytecoind-bind-address=<ip:port> Interface and port for bytecoind RPC [default: 0.0.0.0:8081].
--bytecoind-bind-address=<ip:port> Interface and port for bytecoind RPC [default: 127.0.0.1:8081].
--seed-node-address=<ip:port> Specify list (one or more) of nodes to start connecting to.
--priority-node-address=<ip:port> Specify list (one or more) of nodes to connect to and attempt to keep the connection open.
--exclusive-node-address=<ip:port> Specify list (one or more) of nodes to connect to only. All other nodes including seed nodes will be ignored.)";
Expand Down
4 changes: 2 additions & 2 deletions src/version.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
#pragma once

// defines are for Windows resource compiler
#define bytecoin_VERSION_WINDOWS_COMMA 3, 18, 4, 16
#define bytecoin_VERSION_STRING "3.0.2"
#define bytecoin_VERSION_WINDOWS_COMMA 3, 18, 5, 9
#define bytecoin_VERSION_STRING "3.0.3"

#ifndef RC_INVOKED // Windows resource compiler

Expand Down

1 comment on commit 8d7795e

@SoraKohaku
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice updates!

Please sign in to comment.