Skip to content

Commit

Permalink
v2.0.4
Browse files Browse the repository at this point in the history
  • Loading branch information
pmitchev committed May 28, 2017
1 parent 72048a9 commit cea10e4
Show file tree
Hide file tree
Showing 45 changed files with 872 additions and 128 deletions.
17 changes: 17 additions & 0 deletions ReleaseNotes.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
Release notes 2.0.4

- Fixed an issue where some users experienced daemon hanging
- Fixed block difficulty calculation issue

Release notes 2.0.3

- Stability enhancement
- Various improvements

Release notes 2.0.2

- Security algorithm enhancement
- Daemon synchronization issue fix
- Wallet minor bug fixes
- Bytecoin RPC Wallet log optimization

Release notes 2.0.1

- Bytecoin RPC Wallet API improvements
Expand Down
4 changes: 4 additions & 0 deletions src/Common/ScopeExit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,8 @@ void ScopeExit::cancel() {
m_cancelled = true;
}

void ScopeExit::resume() {
m_cancelled = false;
}

}
1 change: 1 addition & 0 deletions src/Common/ScopeExit.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ScopeExit {
ScopeExit& operator=(ScopeExit&&) = delete;

void cancel();
void resume();

private:
std::function<void()> m_handler;
Expand Down
1 change: 1 addition & 0 deletions src/CryptoNoteConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const size_t FUSION_TX_MAX_SIZE = CRYPTONOTE_BLOCK_
const size_t FUSION_TX_MIN_INPUT_COUNT = 12;
const size_t FUSION_TX_MIN_IN_OUT_COUNT_RATIO = 4;

const uint32_t KEY_IMAGE_CHECKING_BLOCK_INDEX = 0;
const uint32_t UPGRADE_HEIGHT_V2 = 91452;
const uint32_t UPGRADE_HEIGHT_V3 = static_cast<uint32_t>(-1);
const unsigned UPGRADE_VOTING_THRESHOLD = 90; // percent
Expand Down
3 changes: 2 additions & 1 deletion src/CryptoNoteCore/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1246,7 +1246,8 @@ std::error_code Core::validateTransaction(const CachedTransaction& cachedTransac
outputKeyPointers.reserve(outputKeys.size());
std::for_each(outputKeys.begin(), outputKeys.end(), [&outputKeyPointers] (const Crypto::PublicKey& key) { outputKeyPointers.push_back(&key); });
if (!Crypto::check_ring_signature(cachedTransaction.getTransactionPrefixHash(), in.keyImage, outputKeyPointers.data(),
outputKeyPointers.size(), transaction.signatures[inputIndex].data())) {
outputKeyPointers.size(), transaction.signatures[inputIndex].data(),
blockIndex > parameters::KEY_IMAGE_CHECKING_BLOCK_INDEX)) {
return error::TransactionValidationError::INPUT_INVALID_SIGNATURES;
}
}
Expand Down
56 changes: 44 additions & 12 deletions src/CryptoNoteCore/DatabaseBlockchainCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ class DatabaseVersionWriteBatch: public IWriteBatch {
uint32_t schemeVersion;
};

const uint32_t CURRENT_DB_SCHEME_VERSION = 1;
const uint32_t CURRENT_DB_SCHEME_VERSION = 2;

}

Expand Down Expand Up @@ -487,6 +487,30 @@ DatabaseBlockchainCache::DatabaseBlockchainCache(const Currency& curr, IDataBase
}
}

bool DatabaseBlockchainCache::checkDBSchemeVersion(IDataBase& database, Logging::ILogger& _logger) {
Logging::LoggerRef logger(_logger, "DatabaseBlockchainCache");

DatabaseVersionReadBatch readBatch;
auto ec = database.read(readBatch);
if (ec) {
throw std::system_error(ec);
}

auto version = readBatch.getDbSchemeVersion();
if (!version) {
//DB scheme version not found. Looks like it was just created.
return true;
} else if (*version < CURRENT_DB_SCHEME_VERSION) {
logger(Logging::WARNING) << "DB scheme version is less than expected. Expected version " << CURRENT_DB_SCHEME_VERSION << ". Actual version " << *version << ". DB will be destroyed and recreated from blocks.bin file.";
return false;
} else if (*version > CURRENT_DB_SCHEME_VERSION) {
logger(Logging::ERROR) << "DB scheme version is greater than expected. Expected version " << CURRENT_DB_SCHEME_VERSION << ". Actual version " << *version << ". Please update your software.";
throw std::runtime_error("DB scheme version is greater than expected");
} else {
return true;
}
}

void DatabaseBlockchainCache::deleteClosestTimestampBlockIndex(BlockchainWriteBatch& writeBatch, uint32_t splitBlockIndex) {
auto batch = BlockchainReadBatch().requestCachedBlock(splitBlockIndex);
auto blockResult = readDatabase(batch);
Expand Down Expand Up @@ -1345,23 +1369,31 @@ std::vector<CachedBlockInfo> DatabaseBlockchainCache::getLastCachedUnits(uint32_
assert(blockIndex <= getTopBlockIndex());

std::vector<CachedBlockInfo> cachedResult;
uint32_t cacheStart = (getTopBlockIndex() + 1) - static_cast<uint32_t>(unitsCache.size());
if (cacheStart == 0 && !useGenesis) {
count = std::min(static_cast<size_t>(getTopBlockIndex()), count);
cacheStart = 0;
}
const uint32_t cacheStartIndex = (getTopBlockIndex() + 1) - static_cast<uint32_t>(unitsCache.size());

count = std::min(unitsCache.size(), count);

if (cacheStart > blockIndex || count == 0) {
if (cacheStartIndex > blockIndex || count == 0) {
return cachedResult;
}

count = std::min(blockIndex + 1, static_cast<uint32_t>(count));
uint32_t offset = std::max(static_cast<uint32_t>(blockIndex + 1 - count), cacheStart) - cacheStart;
count = std::min(blockIndex - cacheStartIndex + 1, static_cast<uint32_t>(count));
uint32_t offset = static_cast<uint32_t>(blockIndex + 1 - count) - cacheStartIndex;

assert(offset < unitsCache.size());

cachedResult.reserve(unitsCache.size() - offset - (getTopBlockIndex() - blockIndex));
for (size_t i = offset; (i + cacheStart) <= blockIndex; ++i) {
cachedResult.push_back(unitsCache[i]);
if (!useGenesis && cacheStartIndex == 0 && offset == 0) {
++offset;
--count;
}

if (offset >= unitsCache.size() || count == 0) {
return cachedResult;
}

cachedResult.reserve(count);
for (size_t i = 0; i < count; ++i) {
cachedResult.push_back(unitsCache[offset + i]);
}

return cachedResult;
Expand Down
2 changes: 2 additions & 0 deletions src/CryptoNoteCore/DatabaseBlockchainCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class DatabaseBlockchainCache : public IBlockchainCache {
DatabaseBlockchainCache(const Currency& currency, IDataBase& dataBase,
IBlockchainCacheFactory& blockchainCacheFactory, Logging::ILogger& logger);

static bool checkDBSchemeVersion(IDataBase& dataBase, Logging::ILogger& logger);

/*
* This methods splits cache, upper part (ie blocks with indexes larger than splitBlockIndex)
* is copied to new BlockchainCache. Unfortunately, implementation requires return value to be of
Expand Down
122 changes: 75 additions & 47 deletions src/CryptoNoteCore/RocksDBWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,63 +45,20 @@ void RocksDBWrapper::init(const DataBaseConfig& config) {
throw std::system_error(make_error_code(CryptoNote::error::DataBaseErrorCodes::ALREADY_INITIALIZED));
}

std::string dataDir;
if (config.getTestnet()) {
dataDir = config.getDataDir() + '/' + TESTNET_DB_NAME;
} else {
dataDir = config.getDataDir() + '/' + DB_NAME;
}
std::string dataDir = getDataDir(config);

logger(INFO) << "Opening DB in " << dataDir;

rocksdb::DB* dbPtr;

rocksdb::DBOptions dbOptions;
dbOptions.IncreaseParallelism(config.getBackgroundThreadsCount());
dbOptions.info_log_level = rocksdb::InfoLogLevel::WARN_LEVEL;
dbOptions.max_open_files = config.getMaxOpenFiles();

rocksdb::ColumnFamilyOptions fOptions;
fOptions.write_buffer_size = static_cast<size_t>(config.getWriteBufferSize());
// merge two memtables when flushing to L0
fOptions.min_write_buffer_number_to_merge = 2;
// this means we'll use 50% extra memory in the worst case, but will reduce
// write stalls.
fOptions.max_write_buffer_number = 6;
// start flushing L0->L1 as soon as possible. each file on level0 is
// (memtable_memory_budget / 2). This will flush level 0 when it's bigger than
// memtable_memory_budget.
fOptions.level0_file_num_compaction_trigger = 20;

fOptions.level0_slowdown_writes_trigger = 30;
fOptions.level0_stop_writes_trigger = 40;

// doesn't really matter much, but we don't want to create too many files
fOptions.target_file_size_base = config.getWriteBufferSize() / 10;
// make Level1 size equal to Level0 size, so that L0->L1 compactions are fast
fOptions.max_bytes_for_level_base = config.getWriteBufferSize();
fOptions.num_levels = 10;
fOptions.target_file_size_multiplier = 2;
// level style compaction
fOptions.compaction_style = rocksdb::kCompactionStyleLevel;

fOptions.compression_per_level.resize(fOptions.num_levels);
for (int i = 0; i < fOptions.num_levels; ++i) {
fOptions.compression_per_level[i] = rocksdb::kNoCompression;
}

rocksdb::BlockBasedTableOptions tableOptions;
tableOptions.block_cache = rocksdb::NewLRUCache(config.getReadCacheSize());
std::shared_ptr<rocksdb::TableFactory> tfp(NewBlockBasedTableFactory(tableOptions));
fOptions.table_factory = tfp;

rocksdb::Status status = rocksdb::DB::Open(rocksdb::Options(dbOptions, fOptions), dataDir, &dbPtr);
rocksdb::Options dbOptions = getDBOptions(config);
rocksdb::Status status = rocksdb::DB::Open(dbOptions, dataDir, &dbPtr);
if (status.ok()) {
logger(INFO) << "DB opened in " << dataDir;
} else if (!status.ok() || status.IsNotFound()) {
logger(INFO) << "DB not found in " << dataDir << ". Creating new DB...";
dbOptions.create_if_missing = true;
rocksdb::Status status = rocksdb::DB::Open(rocksdb::Options(dbOptions, fOptions), dataDir, &dbPtr);
rocksdb::Status status = rocksdb::DB::Open(dbOptions, dataDir, &dbPtr);
if (!status.ok()) {
logger(ERROR) << "DB Error. DB can't be created in " << dataDir << ". Error: " << status.ToString();
throw std::system_error(make_error_code(CryptoNote::error::DataBaseErrorCodes::INTERNAL_ERROR));
Expand All @@ -127,6 +84,26 @@ void RocksDBWrapper::shutdown() {
state.store(NOT_INITIALIZED);
}

void RocksDBWrapper::destoy(const DataBaseConfig& config) {
if (state.load() != NOT_INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::DataBaseErrorCodes::ALREADY_INITIALIZED));
}

std::string dataDir = getDataDir(config);

logger(WARNING) << "Destroying DB in " << dataDir;

rocksdb::Options dbOptions = getDBOptions(config);
rocksdb::Status status = rocksdb::DestroyDB(dataDir, dbOptions);

if (status.ok()) {
logger(WARNING) << "DB destroyed in " << dataDir;
} else {
logger(ERROR) << "DB Error. DB can't be destroyed in " << dataDir << ". Error: " << status.ToString();
throw std::system_error(make_error_code(CryptoNote::error::DataBaseErrorCodes::INTERNAL_ERROR));
}
}

std::error_code RocksDBWrapper::write(IWriteBatch& batch) {
if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::DataBaseErrorCodes::NOT_INITIALIZED));
Expand Down Expand Up @@ -198,3 +175,54 @@ std::error_code RocksDBWrapper::read(IReadBatch& batch) {
batch.submitRawResult(values, resultStates);
return std::error_code();
}

rocksdb::Options RocksDBWrapper::getDBOptions(const DataBaseConfig& config) {
rocksdb::DBOptions dbOptions;
dbOptions.IncreaseParallelism(config.getBackgroundThreadsCount());
dbOptions.info_log_level = rocksdb::InfoLogLevel::WARN_LEVEL;
dbOptions.max_open_files = config.getMaxOpenFiles();

rocksdb::ColumnFamilyOptions fOptions;
fOptions.write_buffer_size = static_cast<size_t>(config.getWriteBufferSize());
// merge two memtables when flushing to L0
fOptions.min_write_buffer_number_to_merge = 2;
// this means we'll use 50% extra memory in the worst case, but will reduce
// write stalls.
fOptions.max_write_buffer_number = 6;
// start flushing L0->L1 as soon as possible. each file on level0 is
// (memtable_memory_budget / 2). This will flush level 0 when it's bigger than
// memtable_memory_budget.
fOptions.level0_file_num_compaction_trigger = 20;

fOptions.level0_slowdown_writes_trigger = 30;
fOptions.level0_stop_writes_trigger = 40;

// doesn't really matter much, but we don't want to create too many files
fOptions.target_file_size_base = config.getWriteBufferSize() / 10;
// make Level1 size equal to Level0 size, so that L0->L1 compactions are fast
fOptions.max_bytes_for_level_base = config.getWriteBufferSize();
fOptions.num_levels = 10;
fOptions.target_file_size_multiplier = 2;
// level style compaction
fOptions.compaction_style = rocksdb::kCompactionStyleLevel;

fOptions.compression_per_level.resize(fOptions.num_levels);
for (int i = 0; i < fOptions.num_levels; ++i) {
fOptions.compression_per_level[i] = rocksdb::kNoCompression;
}

rocksdb::BlockBasedTableOptions tableOptions;
tableOptions.block_cache = rocksdb::NewLRUCache(config.getReadCacheSize());
std::shared_ptr<rocksdb::TableFactory> tfp(NewBlockBasedTableFactory(tableOptions));
fOptions.table_factory = tfp;

return rocksdb::Options(dbOptions, fOptions);
}

std::string RocksDBWrapper::getDataDir(const DataBaseConfig& config) {
if (config.getTestnet()) {
return config.getDataDir() + '/' + TESTNET_DB_NAME;
} else {
return config.getDataDir() + '/' + DB_NAME;
}
}
4 changes: 4 additions & 0 deletions src/CryptoNoteCore/RocksDBWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class RocksDBWrapper : public IDataBase {

void init(const DataBaseConfig& config);
void shutdown();
void destoy(const DataBaseConfig& config); //Be careful with this method!

std::error_code write(IWriteBatch& batch) override;
std::error_code writeSync(IWriteBatch& batch) override;
Expand All @@ -51,6 +52,9 @@ class RocksDBWrapper : public IDataBase {
private:
std::error_code write(IWriteBatch& batch, bool sync);

rocksdb::Options getDBOptions(const DataBaseConfig& config);
std::string getDataDir(const DataBaseConfig& config);

enum State {
NOT_INITIALIZED,
INITIALIZED
Expand Down
12 changes: 12 additions & 0 deletions src/Daemon/Daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "crypto/hash.h"
#include "CryptoNoteCore/Core.h"
#include "CryptoNoteCore/Currency.h"
#include "CryptoNoteCore/DatabaseBlockchainCache.h"
#include "CryptoNoteCore/DatabaseBlockchainCacheFactory.h"
#include "CryptoNoteCore/MainChainStorage.h"
#include "CryptoNoteCore/MinerConfig.h"
Expand Down Expand Up @@ -219,6 +220,17 @@ int main(int argc, char* argv[])
database.init(dbConfig);
Tools::ScopeExit dbShutdownOnExit([&database] () { database.shutdown(); });

if (!DatabaseBlockchainCache::checkDBSchemeVersion(database, logManager))
{
dbShutdownOnExit.cancel();
database.shutdown();

database.destoy(dbConfig);

database.init(dbConfig);
dbShutdownOnExit.resume();
}

System::Dispatcher dispatcher;
logger(INFO) << "Initializing core...";
CryptoNote::Core ccore(
Expand Down
Loading

0 comments on commit cea10e4

Please sign in to comment.