Skip to content
Permalink
Browse files

Make difficulty 128 bit instead of 64 bit

Based on Boolberry work by:
  jahrsg <jahr@jahr.me>
  cr.zoidberg <crypto.zoidberg@gmail.com>
  • Loading branch information...
moneromooo-monero committed Jan 31, 2019
1 parent 1d1a02e commit 0e28c462f233f2b9d086f662d408a418578d22fa
10 LICENSE
@@ -29,3 +29,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Parts of the project are originally copyright (c) 2012-2013 The Cryptonote
developers

Parts of the project are originally copyright (c) 2014 The Boolberry
developers, distributed under the MIT licence:

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@@ -54,7 +54,7 @@ using epee::string_tools::pod_to_hex;
using namespace crypto;

// Increase when the DB structure changes
#define VERSION 4
#define VERSION 5

namespace
{
@@ -274,7 +274,7 @@ typedef struct mdb_block_info_1
uint64_t bi_timestamp;
uint64_t bi_coins;
uint64_t bi_weight; // a size_t really but we need 32-bit compat
difficulty_type bi_diff;
uint64_t bi_diff;
crypto::hash bi_hash;
} mdb_block_info_1;

@@ -284,7 +284,7 @@ typedef struct mdb_block_info_2
uint64_t bi_timestamp;
uint64_t bi_coins;
uint64_t bi_weight; // a size_t really but we need 32-bit compat
difficulty_type bi_diff;
uint64_t bi_diff;
crypto::hash bi_hash;
uint64_t bi_cum_rct;
} mdb_block_info_2;
@@ -295,13 +295,26 @@ typedef struct mdb_block_info_3
uint64_t bi_timestamp;
uint64_t bi_coins;
uint64_t bi_weight; // a size_t really but we need 32-bit compat
difficulty_type bi_diff;
uint64_t bi_diff;
crypto::hash bi_hash;
uint64_t bi_cum_rct;
uint64_t bi_long_term_block_weight;
} mdb_block_info_3;

typedef mdb_block_info_3 mdb_block_info;
typedef struct mdb_block_info_4
{
uint64_t bi_height;
uint64_t bi_timestamp;
uint64_t bi_coins;
uint64_t bi_weight; // a size_t really but we need 32-bit compat
uint64_t bi_diff_lo;
uint64_t bi_diff_hi;
crypto::hash bi_hash;
uint64_t bi_cum_rct;
uint64_t bi_long_term_block_weight;
} mdb_block_info_4;

typedef mdb_block_info_4 mdb_block_info;

typedef struct blk_height {
crypto::hash bh_hash;
@@ -757,7 +770,8 @@ void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t l
bi.bi_timestamp = blk.timestamp;
bi.bi_coins = coins_generated;
bi.bi_weight = block_weight;
bi.bi_diff = cumulative_difficulty;
bi.bi_diff_hi = (cumulative_difficulty >> 64).convert_to<uint64_t>();
bi.bi_diff_lo = (cumulative_difficulty << 64 >> 64).convert_to<uint64_t>();
bi.bi_hash = blk_hash;
bi.bi_cum_rct = num_rct_outs;
if (blk.major_version >= 4)
@@ -2463,7 +2477,9 @@ difficulty_type BlockchainLMDB::get_block_cumulative_difficulty(const uint64_t&
throw0(DB_ERROR("Error attempting to retrieve a cumulative difficulty from the db"));

mdb_block_info *bi = (mdb_block_info *)result.mv_data;
difficulty_type ret = bi->bi_diff;
difficulty_type ret = bi->bi_diff_hi;
ret <<= 64;
ret |= bi->bi_diff_lo;
TXN_POSTFIX_RDONLY();
return ret;
}
@@ -4976,6 +4992,133 @@ void BlockchainLMDB::migrate_3_4()
txn.commit();
}

void BlockchainLMDB::migrate_4_5()
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
uint64_t i;
int result;
mdb_txn_safe txn(false);
MDB_val k, v;
char *ptr;

MGINFO_YELLOW("Migrating blockchain from DB version 4 to 5 - this may take a while:");

do {
LOG_PRINT_L1("migrating block info:");

result = mdb_txn_begin(m_env, NULL, 0, txn);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", result).c_str()));

MDB_stat db_stats;
if ((result = mdb_stat(txn, m_blocks, &db_stats)))
throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str()));
const uint64_t blockchain_height = db_stats.ms_entries;

/* the block_info table name is the same but the old version and new version
* have incompatible data. Create a new table. We want the name to be similar
* to the old name so that it will occupy the same location in the DB.
*/
MDB_dbi o_block_info = m_block_info;
lmdb_db_open(txn, "block_infn", MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_block_info, "Failed to open db handle for block_infn");
mdb_set_dupsort(txn, m_block_info, compare_uint64);


MDB_cursor *c_blocks;
result = mdb_cursor_open(txn, m_blocks, &c_blocks);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to open a cursor for blocks: ", result).c_str()));

MDB_cursor *c_old, *c_cur;
i = 0;
while(1) {
if (!(i % 1000)) {
if (i) {
LOGIF(el::Level::Info) {
std::cout << i << " / " << blockchain_height << " \r" << std::flush;
}
txn.commit();
result = mdb_txn_begin(m_env, NULL, 0, txn);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", result).c_str()));
}
result = mdb_cursor_open(txn, m_block_info, &c_cur);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to open a cursor for block_infn: ", result).c_str()));
result = mdb_cursor_open(txn, o_block_info, &c_old);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to open a cursor for block_info: ", result).c_str()));
if (!i) {
MDB_stat db_stat;
result = mdb_stat(txn, m_block_info, &db_stats);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to query m_block_info: ", result).c_str()));
i = db_stats.ms_entries;
}
}
result = mdb_cursor_get(c_old, &k, &v, MDB_NEXT);
if (result == MDB_NOTFOUND) {
txn.commit();
break;
}
else if (result)
throw0(DB_ERROR(lmdb_error("Failed to get a record from block_info: ", result).c_str()));
const mdb_block_info_3 *bi_old = (const mdb_block_info_3*)v.mv_data;
mdb_block_info_4 bi;
bi.bi_height = bi_old->bi_height;
bi.bi_timestamp = bi_old->bi_timestamp;
bi.bi_coins = bi_old->bi_coins;
bi.bi_weight = bi_old->bi_weight;
bi.bi_diff_lo = bi_old->bi_diff;
bi.bi_diff_hi = 0;
bi.bi_hash = bi_old->bi_hash;
bi.bi_cum_rct = bi_old->bi_cum_rct;
bi.bi_long_term_block_weight = bi_old->bi_long_term_block_weight;

MDB_val_set(nv, bi);
result = mdb_cursor_put(c_cur, (MDB_val *)&zerokval, &nv, MDB_APPENDDUP);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to put a record into block_infn: ", result).c_str()));
/* we delete the old records immediately, so the overall DB and mapsize should not grow.
* This is a little slower than just letting mdb_drop() delete it all at the end, but
* it saves a significant amount of disk space.
*/
result = mdb_cursor_del(c_old, 0);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to delete a record from block_info: ", result).c_str()));
i++;
}

result = mdb_txn_begin(m_env, NULL, 0, txn);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", result).c_str()));
/* Delete the old table */
result = mdb_drop(txn, o_block_info, 1);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to delete old block_info table: ", result).c_str()));

RENAME_DB("block_infn");
mdb_dbi_close(m_env, m_block_info);

lmdb_db_open(txn, "block_info", MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_block_info, "Failed to open db handle for block_infn");
mdb_set_dupsort(txn, m_block_info, compare_uint64);

txn.commit();
} while(0);

uint32_t version = 5;
v.mv_data = (void *)&version;
v.mv_size = sizeof(version);
MDB_val_str(vk, "version");
result = mdb_txn_begin(m_env, NULL, 0, txn);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", result).c_str()));
result = mdb_put(txn, m_properties, &vk, &v, 0);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to update version for the db: ", result).c_str()));
txn.commit();
}

void BlockchainLMDB::migrate(const uint32_t oldversion)
{
if (oldversion < 1)
@@ -4986,6 +5129,8 @@ void BlockchainLMDB::migrate(const uint32_t oldversion)
migrate_2_3();
if (oldversion < 4)
migrate_3_4();
if (oldversion < 5)
migrate_4_5();
}

} // namespace cryptonote
@@ -412,6 +412,9 @@ class BlockchainLMDB : public BlockchainDB
// migrate from DB version 3 to 4
void migrate_3_4();

// migrate from DB version 4 to 5
void migrate_4_5();

void cleanup_batch();

private:
@@ -294,7 +294,8 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path
}

// 4 byte magic + (currently) 1024 byte header structures
bootstrap.seek_to_first_chunk(import_file);
uint8_t major_version, minor_version;
bootstrap.seek_to_first_chunk(import_file, major_version, minor_version);

std::string str1;
char buffer1[1024];
@@ -415,7 +416,23 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path
{
str1.assign(buffer_block, chunk_size);
bootstrap::block_package bp;
if (! ::serialization::parse_binary(str1, bp))
bool res;
if (major_version == 0)
{
bootstrap::block_package_1 bp1;
res = ::serialization::parse_binary(str1, bp1);
if (res)
{
bp.block = std::move(bp1.block);
bp.txs = std::move(bp1.txs);
bp.block_weight = bp1.block_weight;
bp.cumulative_difficulty = bp1.cumulative_difficulty;
bp.coins_generated = bp1.coins_generated;
}
}
else
res = ::serialization::parse_binary(str1, bp);
if (!res)
throw std::runtime_error("Error in deserialization of chunk");

int display_interval = 1000;
@@ -124,8 +124,8 @@ bool BootstrapFile::initialize_file()
*m_raw_data_file << blob;

bootstrap::file_info bfi;
bfi.major_version = 0;
bfi.minor_version = 1;
bfi.major_version = 1;
bfi.minor_version = 0;
bfi.header_size = header_size;

bootstrap::blocks_info bbi;
@@ -323,7 +323,7 @@ bool BootstrapFile::store_blockchain_raw(Blockchain* _blockchain_storage, tx_mem
return BootstrapFile::close();
}

uint64_t BootstrapFile::seek_to_first_chunk(std::ifstream& import_file)
uint64_t BootstrapFile::seek_to_first_chunk(std::ifstream& import_file, uint8_t &major_version, uint8_t &minor_version)
{
uint32_t file_magic;

@@ -371,6 +371,8 @@ uint64_t BootstrapFile::seek_to_first_chunk(std::ifstream& import_file)
uint64_t full_header_size = sizeof(file_magic) + bfi.header_size;
import_file.seekg(full_header_size);

major_version = bfi.major_version;
minor_version = bfi.minor_version;
return full_header_size;
}

@@ -461,7 +463,8 @@ uint64_t BootstrapFile::count_blocks(const std::string& import_file_path, std::s
}

uint64_t full_header_size; // 4 byte magic + length of header structures
full_header_size = seek_to_first_chunk(import_file);
uint8_t major_version, minor_version;
full_header_size = seek_to_first_chunk(import_file, major_version, minor_version);

MINFO("Scanning blockchain from bootstrap file...");
bool quit = false;
@@ -60,7 +60,7 @@ class BootstrapFile
uint64_t count_bytes(std::ifstream& import_file, uint64_t blocks, uint64_t& h, bool& quit);
uint64_t count_blocks(const std::string& dir_path, std::streampos& start_pos, uint64_t& seek_height);
uint64_t count_blocks(const std::string& dir_path);
uint64_t seek_to_first_chunk(std::ifstream& import_file);
uint64_t seek_to_first_chunk(std::ifstream& import_file, uint8_t &major_version, uint8_t &minor_version);

bool store_blockchain_raw(cryptonote::Blockchain* cs, cryptonote::tx_memory_pool* txp,
boost::filesystem::path& output_file, uint64_t use_block_height=0);
@@ -29,7 +29,7 @@
#pragma once

#include "cryptonote_basic/cryptonote_boost_serialization.h"
#include "cryptonote_basic/difficulty.h"
#include "serialization/difficulty_type.h"


namespace cryptonote
@@ -66,6 +66,23 @@ namespace cryptonote
END_SERIALIZE()
};

struct block_package_1
{
cryptonote::block block;
std::vector<transaction> txs;
size_t block_weight;
uint64_t cumulative_difficulty;
uint64_t coins_generated;

BEGIN_SERIALIZE()
FIELD(block)
FIELD(txs)
VARINT_FIELD(block_weight)
VARINT_FIELD(cumulative_difficulty)
VARINT_FIELD(coins_generated)
END_SERIALIZE()
};

struct block_package
{
cryptonote::block block;
@@ -78,7 +95,7 @@ namespace cryptonote
FIELD(block)
FIELD(txs)
VARINT_FIELD(block_weight)
VARINT_FIELD(cumulative_difficulty)
FIELD(cumulative_difficulty)
VARINT_FIELD(coins_generated)
END_SERIALIZE()
};
Oops, something went wrong.

0 comments on commit 0e28c46

Please sign in to comment.
You can’t perform that action at this time.