aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/blockchain_db/blockchain_db.cpp3
-rw-r--r--src/blockchain_db/blockchain_db.h17
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp218
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.h7
-rw-r--r--src/blockchain_db/testdb.h152
-rw-r--r--src/blockchain_utilities/blockchain_import.cpp3
-rw-r--r--src/cryptonote_config.h3
-rw-r--r--src/cryptonote_core/blockchain.cpp133
-rw-r--r--src/cryptonote_core/blockchain.h35
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp3
-rw-r--r--src/cryptonote_core/cryptonote_core.h1
-rw-r--r--src/daemon/rpc_command_executor.cpp1
-rw-r--r--src/rpc/core_rpc_server.cpp1
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h2
14 files changed, 551 insertions, 28 deletions
diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp
index be0ffeac3..682857157 100644
--- a/src/blockchain_db/blockchain_db.cpp
+++ b/src/blockchain_db/blockchain_db.cpp
@@ -197,6 +197,7 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const transacti
uint64_t BlockchainDB::add_block( const block& blk
, size_t block_weight
+ , uint64_t long_term_block_weight
, const difficulty_type& cumulative_difficulty
, const uint64_t& coins_generated
, const std::vector<transaction>& txs
@@ -241,7 +242,7 @@ uint64_t BlockchainDB::add_block( const block& blk
// call out to subclass implementation to add the block & metadata
time1 = epee::misc_utils::get_tick_count();
- add_block(blk, block_weight, cumulative_difficulty, coins_generated, num_rct_outs, blk_hash);
+ add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, num_rct_outs, blk_hash);
TIME_MEASURE_FINISH(time1);
time_add_block1 += time1;
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index 396ae7544..6cd4cf346 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -359,12 +359,14 @@ private:
*
* @param blk the block to be added
* @param block_weight the weight of the block (transactions and all)
+ * @param long_term_block_weight the long term block weight of the block (transactions and all)
* @param cumulative_difficulty the accumulated difficulty after this block
* @param coins_generated the number of coins generated total after this block
* @param blk_hash the hash of the block
*/
virtual void add_block( const block& blk
, size_t block_weight
+ , uint64_t long_term_block_weight
, const difficulty_type& cumulative_difficulty
, const uint64_t& coins_generated
, uint64_t num_rct_outs
@@ -376,7 +378,7 @@ private:
*
* The subclass implementing this will remove the block data from the top
* block in the chain. The data to be removed is that which was added in
- * BlockchainDB::add_block(const block& blk, size_t block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated, const crypto::hash& blk_hash)
+ * BlockchainDB::add_block(const block& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated, const crypto::hash& blk_hash)
*
* If any of this cannot be done, the subclass should throw the corresponding
* subclass of DB_EXCEPTION
@@ -790,6 +792,7 @@ public:
*
* @param blk the block to be added
* @param block_weight the size of the block (transactions and all)
+ * @param long_term_block_weight the long term weight of the block (transactions and all)
* @param cumulative_difficulty the accumulated difficulty after this block
* @param coins_generated the number of coins generated total after this block
* @param txs the transactions in the block
@@ -798,6 +801,7 @@ public:
*/
virtual uint64_t add_block( const block& blk
, size_t block_weight
+ , uint64_t long_term_block_weight
, const difficulty_type& cumulative_difficulty
, const uint64_t& coins_generated
, const std::vector<transaction>& txs
@@ -986,6 +990,17 @@ public:
virtual uint64_t get_block_already_generated_coins(const uint64_t& height) const = 0;
/**
+ * @brief fetch a block's long term weight
+ *
+ * If the block does not exist, the subclass should throw BLOCK_DNE
+ *
+ * @param height the height requested
+ *
+ * @return the long term weight
+ */
+ virtual uint64_t get_block_long_term_weight(const uint64_t& height) const = 0;
+
+ /**
* @brief fetch a block's hash
*
* The subclass should return hash of the block with the
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index bd91f308a..747d30cf8 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -30,6 +30,7 @@
#include <boost/filesystem.hpp>
#include <boost/format.hpp>
#include <boost/current_function.hpp>
+#include <boost/circular_buffer.hpp>
#include <memory> // std::unique_ptr
#include <cstring> // memcpy
#include <random>
@@ -54,7 +55,7 @@ using epee::string_tools::pod_to_hex;
using namespace crypto;
// Increase when the DB structure changes
-#define VERSION 3
+#define VERSION 4
namespace
{
@@ -251,7 +252,7 @@ inline void lmdb_db_open(MDB_txn* txn, const char* name, int flags, MDB_dbi& dbi
namespace cryptonote
{
-typedef struct mdb_block_info_old
+typedef struct mdb_block_info_1
{
uint64_t bi_height;
uint64_t bi_timestamp;
@@ -259,9 +260,9 @@ typedef struct mdb_block_info_old
uint64_t bi_weight; // a size_t really but we need 32-bit compat
difficulty_type bi_diff;
crypto::hash bi_hash;
-} mdb_block_info_old;
+} mdb_block_info_1;
-typedef struct mdb_block_info
+typedef struct mdb_block_info_2
{
uint64_t bi_height;
uint64_t bi_timestamp;
@@ -270,7 +271,21 @@ typedef struct mdb_block_info
difficulty_type bi_diff;
crypto::hash bi_hash;
uint64_t bi_cum_rct;
-} mdb_block_info;
+} mdb_block_info_2;
+
+typedef struct mdb_block_info_3
+{
+ 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
+ difficulty_type 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 blk_height {
crypto::hash bh_hash;
@@ -677,7 +692,7 @@ estim:
return threshold_size;
}
-void BlockchainLMDB::add_block(const block& blk, size_t block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated,
+void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated,
uint64_t num_rct_outs, const crypto::hash& blk_hash)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
@@ -736,6 +751,7 @@ void BlockchainLMDB::add_block(const block& blk, size_t block_weight, const diff
const mdb_block_info *bi_prev = (const mdb_block_info*)h.mv_data;
bi.bi_cum_rct += bi_prev->bi_cum_rct;
}
+ bi.bi_long_term_block_weight = long_term_block_weight;
MDB_val_set(val, bi);
result = mdb_cursor_put(m_cur_block_info, (MDB_val *)&zerokval, &val, MDB_APPENDDUP);
@@ -2105,6 +2121,29 @@ uint64_t BlockchainLMDB::get_block_already_generated_coins(const uint64_t& heigh
return ret;
}
+uint64_t BlockchainLMDB::get_block_long_term_weight(const uint64_t& height) const
+{
+ LOG_PRINT_L3("BlockchainLMDB::" << __func__);
+ check_open();
+
+ TXN_PREFIX_RDONLY();
+ RCURSOR(block_info);
+
+ MDB_val_set(result, height);
+ auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH);
+ if (get_result == MDB_NOTFOUND)
+ {
+ throw0(BLOCK_DNE(std::string("Attempt to get block long term weight from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- block info not in db").c_str()));
+ }
+ else if (get_result)
+ throw0(DB_ERROR("Error attempting to retrieve a long term block weight from the db"));
+
+ mdb_block_info *bi = (mdb_block_info *)result.mv_data;
+ uint64_t ret = bi->bi_long_term_block_weight;
+ TXN_POSTFIX_RDONLY();
+ return ret;
+}
+
crypto::hash BlockchainLMDB::get_block_hash_from_height(const uint64_t& height) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
@@ -3098,7 +3137,7 @@ void BlockchainLMDB::block_txn_abort()
}
}
-uint64_t BlockchainLMDB::add_block(const block& blk, size_t block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated,
+uint64_t BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated,
const std::vector<transaction>& txs)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
@@ -3117,7 +3156,7 @@ uint64_t BlockchainLMDB::add_block(const block& blk, size_t block_weight, const
try
{
- BlockchainDB::add_block(blk, block_weight, cumulative_difficulty, coins_generated, txs);
+ BlockchainDB::add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs);
}
catch (const DB_ERROR_TXN_START& e)
{
@@ -3655,7 +3694,7 @@ void BlockchainLMDB::migrate_0_1()
break;
}
MDB_dbi diffs, hashes, sizes, timestamps;
- mdb_block_info_old bi;
+ mdb_block_info_1 bi;
MDB_val_set(nv, bi);
lmdb_db_open(txn, "block_diffs", 0, diffs, "Failed to open db handle for block_diffs");
@@ -4282,8 +4321,8 @@ void BlockchainLMDB::migrate_2_3()
}
else if (result)
throw0(DB_ERROR(lmdb_error("Failed to get a record from block_info: ", result).c_str()));
- const mdb_block_info_old *bi_old = (const mdb_block_info_old*)v.mv_data;
- mdb_block_info bi;
+ const mdb_block_info_1 *bi_old = (const mdb_block_info_1*)v.mv_data;
+ mdb_block_info_2 bi;
bi.bi_height = bi_old->bi_height;
bi.bi_timestamp = bi_old->bi_timestamp;
bi.bi_coins = bi_old->bi_coins;
@@ -4336,6 +4375,161 @@ void BlockchainLMDB::migrate_2_3()
txn.commit();
}
+void BlockchainLMDB::migrate_3_4()
+{
+ LOG_PRINT_L3("BlockchainLMDB::" << __func__);
+ uint64_t i;
+ int result;
+ mdb_txn_safe txn(false);
+ MDB_val k, v;
+ char *ptr;
+ bool past_long_term_weight = false;
+
+ MGINFO_YELLOW("Migrating blockchain from DB version 3 to 4 - 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;
+
+ boost::circular_buffer<uint64_t> long_term_block_weights(CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE);
+
+ /* 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_2 *bi_old = (const mdb_block_info_2*)v.mv_data;
+ mdb_block_info_3 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 = bi_old->bi_diff;
+ bi.bi_hash = bi_old->bi_hash;
+ bi.bi_cum_rct = bi_old->bi_cum_rct;
+
+ // get block major version to determine which rule is in place
+ if (!past_long_term_weight)
+ {
+ MDB_val kb, vb;
+ result = mdb_cursor_get(c_blocks, &k, &v, MDB_NEXT);
+ if (result)
+ throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str()));
+ if (vb.mv_size == 0)
+ throw0(DB_ERROR("Invalid data from m_blocks"));
+ const uint8_t block_major_version = *((const uint8_t*)vb.mv_data);
+ if (block_major_version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT)
+ past_long_term_weight = true;
+ }
+
+ uint64_t long_term_block_weight;
+ if (past_long_term_weight)
+ {
+ std::vector<uint64_t> weights(long_term_block_weights.begin(), long_term_block_weights.end());
+ uint64_t long_term_effective_block_median_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, epee::misc_utils::median(weights));
+ long_term_block_weight = std::min<uint64_t>(bi.bi_weight, long_term_effective_block_median_weight + long_term_effective_block_median_weight * 2 / 5);
+ }
+ else
+ {
+ long_term_block_weight = bi.bi_weight;
+ }
+ long_term_block_weights.push_back(long_term_block_weight);
+ bi.bi_long_term_block_weight = 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");
+
+ 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 = 4;
+ v.mv_data = (void *)&version;
+ v.mv_size = sizeof(version);
+ MDB_val_copy<const char *> 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)
{
switch(oldversion) {
@@ -4345,6 +4539,8 @@ void BlockchainLMDB::migrate(const uint32_t oldversion)
migrate_1_2(); /* FALLTHRU */
case 2:
migrate_2_3(); /* FALLTHRU */
+ case 3:
+ migrate_3_4(); /* FALLTHRU */
default:
;
}
diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h
index e1f748ed8..923507d06 100644
--- a/src/blockchain_db/lmdb/db_lmdb.h
+++ b/src/blockchain_db/lmdb/db_lmdb.h
@@ -213,6 +213,8 @@ public:
virtual uint64_t get_block_already_generated_coins(const uint64_t& height) const;
+ virtual uint64_t get_block_long_term_weight(const uint64_t& height) const;
+
virtual crypto::hash get_block_hash_from_height(const uint64_t& height) const;
virtual std::vector<block> get_blocks_range(const uint64_t& h1, const uint64_t& h2) const;
@@ -274,6 +276,7 @@ public:
virtual uint64_t add_block( const block& blk
, size_t block_weight
+ , uint64_t long_term_block_weight
, const difficulty_type& cumulative_difficulty
, const uint64_t& coins_generated
, const std::vector<transaction>& txs
@@ -318,6 +321,7 @@ private:
virtual void add_block( const block& blk
, size_t block_weight
+ , uint64_t long_term_block_weight
, const difficulty_type& cumulative_difficulty
, const uint64_t& coins_generated
, uint64_t num_rct_outs
@@ -396,6 +400,9 @@ private:
// migrate from DB version 2 to 3
void migrate_2_3();
+ // migrate from DB version 3 to 4
+ void migrate_3_4();
+
void cleanup_batch();
private:
diff --git a/src/blockchain_db/testdb.h b/src/blockchain_db/testdb.h
new file mode 100644
index 000000000..0476e5e1b
--- /dev/null
+++ b/src/blockchain_db/testdb.h
@@ -0,0 +1,152 @@
+// Copyright (c) 2014-2018, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#pragma once
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "blockchain_db.h"
+
+namespace cryptonote
+{
+
+class BaseTestDB: public cryptonote::BlockchainDB {
+public:
+ BaseTestDB() {}
+ virtual void open(const std::string& filename, const int db_flags = 0) { }
+ virtual void close() {}
+ virtual void sync() {}
+ virtual void safesyncmode(const bool onoff) {}
+ virtual void reset() {}
+ virtual std::vector<std::string> get_filenames() const { return std::vector<std::string>(); }
+ virtual bool remove_data_file(const std::string& folder) const { return true; }
+ virtual std::string get_db_name() const { return std::string(); }
+ virtual bool lock() { return true; }
+ virtual void unlock() { }
+ virtual bool batch_start(uint64_t batch_num_blocks=0, uint64_t batch_bytes=0) { return true; }
+ virtual void batch_stop() {}
+ virtual void set_batch_transactions(bool) {}
+ virtual void block_txn_start(bool readonly=false) {}
+ virtual void block_txn_stop() {}
+ virtual void block_txn_abort() {}
+ virtual void drop_hard_fork_info() {}
+ virtual bool block_exists(const crypto::hash& h, uint64_t *height) const { return false; }
+ virtual cryptonote::blobdata get_block_blob_from_height(const uint64_t& height) const { return cryptonote::t_serializable_object_to_blob(get_block_from_height(height)); }
+ virtual cryptonote::blobdata get_block_blob(const crypto::hash& h) const { return cryptonote::blobdata(); }
+ virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const { return false; }
+ virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const { return false; }
+ virtual bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const { return false; }
+ virtual bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const { return false; }
+ virtual uint64_t get_block_height(const crypto::hash& h) const { return 0; }
+ virtual cryptonote::block_header get_block_header(const crypto::hash& h) const { return cryptonote::block_header(); }
+ virtual uint64_t get_block_timestamp(const uint64_t& height) const { return 0; }
+ virtual std::vector<uint64_t> get_block_cumulative_rct_outputs(const std::vector<uint64_t> &heights) const { return {}; }
+ virtual uint64_t get_top_block_timestamp() const { return 0; }
+ virtual size_t get_block_weight(const uint64_t& height) const { return 128; }
+ virtual cryptonote::difficulty_type get_block_cumulative_difficulty(const uint64_t& height) const { return 10; }
+ virtual cryptonote::difficulty_type get_block_difficulty(const uint64_t& height) const { return 0; }
+ virtual uint64_t get_block_already_generated_coins(const uint64_t& height) const { return 10000000000; }
+ virtual uint64_t get_block_long_term_weight(const uint64_t& height) const { return 128; }
+ virtual crypto::hash get_block_hash_from_height(const uint64_t& height) const { return crypto::hash(); }
+ virtual std::vector<cryptonote::block> get_blocks_range(const uint64_t& h1, const uint64_t& h2) const { return std::vector<cryptonote::block>(); }
+ virtual std::vector<crypto::hash> get_hashes_range(const uint64_t& h1, const uint64_t& h2) const { return std::vector<crypto::hash>(); }
+ virtual crypto::hash top_block_hash() const { return crypto::hash(); }
+ virtual cryptonote::block get_top_block() const { return cryptonote::block(); }
+ virtual uint64_t height() const { return 1; }
+ virtual bool tx_exists(const crypto::hash& h) const { return false; }
+ virtual bool tx_exists(const crypto::hash& h, uint64_t& tx_index) const { return false; }
+ virtual uint64_t get_tx_unlock_time(const crypto::hash& h) const { return 0; }
+ virtual cryptonote::transaction get_tx(const crypto::hash& h) const { return cryptonote::transaction(); }
+ virtual bool get_tx(const crypto::hash& h, cryptonote::transaction &tx) const { return false; }
+ virtual uint64_t get_tx_count() const { return 0; }
+ virtual std::vector<cryptonote::transaction> get_tx_list(const std::vector<crypto::hash>& hlist) const { return std::vector<cryptonote::transaction>(); }
+ virtual uint64_t get_tx_block_height(const crypto::hash& h) const { return 0; }
+ virtual uint64_t get_num_outputs(const uint64_t& amount) const { return 1; }
+ virtual uint64_t get_indexing_base() const { return 0; }
+ virtual cryptonote::output_data_t get_output_key(const uint64_t& amount, const uint64_t& index) { return cryptonote::output_data_t(); }
+ virtual cryptonote::tx_out_index get_output_tx_and_index_from_global(const uint64_t& index) const { return cryptonote::tx_out_index(); }
+ virtual cryptonote::tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) const { return cryptonote::tx_out_index(); }
+ virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<cryptonote::tx_out_index> &indices) const {}
+ virtual void get_output_key(const uint64_t &amount, const std::vector<uint64_t> &offsets, std::vector<cryptonote::output_data_t> &outputs, bool allow_partial = false) {}
+ virtual bool can_thread_bulk_indices() const { return false; }
+ virtual std::vector<uint64_t> get_tx_output_indices(const crypto::hash& h) const { return std::vector<uint64_t>(); }
+ virtual std::vector<uint64_t> get_tx_amount_output_indices(const uint64_t tx_index) const { return std::vector<uint64_t>(); }
+ virtual bool has_key_image(const crypto::key_image& img) const { return false; }
+ virtual void remove_block() { }
+ virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const cryptonote::transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) {return 0;}
+ virtual void remove_transaction_data(const crypto::hash& tx_hash, const cryptonote::transaction& tx) {}
+ virtual uint64_t add_output(const crypto::hash& tx_hash, const cryptonote::tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) {return 0;}
+ virtual void add_tx_amount_output_indices(const uint64_t tx_index, const std::vector<uint64_t>& amount_output_indices) {}
+ virtual void add_spent_key(const crypto::key_image& k_image) {}
+ virtual void remove_spent_key(const crypto::key_image& k_image) {}
+
+ virtual bool for_all_key_images(std::function<bool(const crypto::key_image&)>) const { return true; }
+ virtual bool for_blocks_range(const uint64_t&, const uint64_t&, std::function<bool(uint64_t, const crypto::hash&, const cryptonote::block&)>) const { return true; }
+ virtual bool for_all_transactions(std::function<bool(const crypto::hash&, const cryptonote::transaction&)>, bool pruned) const { return true; }
+ virtual bool for_all_outputs(std::function<bool(uint64_t amount, const crypto::hash &tx_hash, uint64_t height, size_t tx_idx)> f) const { return true; }
+ virtual bool for_all_outputs(uint64_t amount, const std::function<bool(uint64_t height)> &f) const { return true; }
+ virtual bool is_read_only() const { return false; }
+ virtual std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const { return std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>>(); }
+ virtual bool get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, std::vector<uint64_t> &distribution, uint64_t &base) const { return false; }
+
+ virtual void add_txpool_tx(const cryptonote::transaction &tx, const cryptonote::txpool_tx_meta_t& details) {}
+ virtual void update_txpool_tx(const crypto::hash &txid, const cryptonote::txpool_tx_meta_t& details) {}
+ virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const { return 0; }
+ virtual bool txpool_has_tx(const crypto::hash &txid) const { return false; }
+ virtual void remove_txpool_tx(const crypto::hash& txid) {}
+ virtual bool get_txpool_tx_meta(const crypto::hash& txid, cryptonote::txpool_tx_meta_t &meta) const { return false; }
+ virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const { return false; }
+ virtual uint64_t get_database_size() const { return 0; }
+ virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const { return ""; }
+ virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const cryptonote::txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, bool include_unrelayed_txes = false) const { return false; }
+
+ virtual void add_block( const cryptonote::block& blk
+ , size_t block_weight
+ , uint64_t long_term_block_weight
+ , const cryptonote::difficulty_type& cumulative_difficulty
+ , const uint64_t& coins_generated
+ , uint64_t num_rct_outs
+ , const crypto::hash& blk_hash
+ ) { }
+ virtual cryptonote::block get_block_from_height(const uint64_t& height) const { return cryptonote::block(); }
+ virtual void set_hard_fork_version(uint64_t height, uint8_t version) {}
+ virtual uint8_t get_hard_fork_version(uint64_t height) const { return 0; }
+ virtual void check_hard_fork_info() {}
+
+ virtual uint32_t get_blockchain_pruning_seed() const { return 0; }
+ virtual bool prune_blockchain(uint32_t pruning_seed = 0) { return true; }
+ virtual bool update_pruning() { return true; }
+ virtual bool check_pruning() { return true; }
+ virtual void prune_outputs(uint64_t amount) {}
+};
+
+}
diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp
index 9ec768d26..b78b8b5c9 100644
--- a/src/blockchain_utilities/blockchain_import.cpp
+++ b/src/blockchain_utilities/blockchain_import.cpp
@@ -484,7 +484,8 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path
try
{
- core.get_blockchain_storage().get_db().add_block(b, block_weight, cumulative_difficulty, coins_generated, txs);
+ uint64_t long_term_block_weight = core.get_blockchain_storage().get_next_long_term_block_weight(block_weight);
+ core.get_blockchain_storage().get_db().add_block(b, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs);
}
catch (const std::exception& e)
{
diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h
index a6858ce7c..021c8562c 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
@@ -58,6 +58,8 @@
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 60000 //size of block (bytes) after which reward for block calculated using block size
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 20000 //size of block (bytes) after which reward for block calculated using block size - before first fork
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 300000 //size of block (bytes) after which reward for block calculated using block size - second change, from v5
+#define CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE 100000 // size in blocks of the long term block weight median window
+#define CRYPTONOTE_SHORT_TERM_BLOCK_WEIGHT_SURGE_FACTOR 50
#define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE 600
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT 12
// COIN - number of smallest units in one coin
@@ -138,6 +140,7 @@
#define HF_VERSION_MIN_MIXIN_10 8
#define HF_VERSION_ENFORCE_RCT 6
#define HF_VERSION_PER_BYTE_FEE 8
+#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT 10
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index fa23b6bd2..9c6153212 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -167,6 +167,8 @@ static const struct {
Blockchain::Blockchain(tx_memory_pool& tx_pool) :
m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_current_block_cumul_weight_limit(0), m_current_block_cumul_weight_median(0),
m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_sync_on_blocks(true), m_db_sync_threshold(1), m_db_sync_mode(db_async), m_db_default_sync(false), m_fast_sync(true), m_show_time_stats(false), m_sync_counter(0), m_bytes_to_sync(0), m_cancel(false),
+ m_long_term_block_weights(CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE),
+ m_long_term_block_weights_height(0),
m_difficulty_for_next_block_top_hash(crypto::null_hash),
m_difficulty_for_next_block(1),
m_btc_valid(false)
@@ -492,6 +494,17 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
m_tx_pool.on_blockchain_dec(m_db->height()-1, get_tail_id());
}
+ if (test_options && test_options->long_term_block_weight_window)
+ m_long_term_block_weights.set_capacity(test_options->long_term_block_weight_window);
+
+ // fill up the long term block weights to reach the required amount
+ const uint64_t db_height = m_db->height();
+ const uint64_t nblocks = std::min<uint64_t>(m_long_term_block_weights.capacity(), db_height);
+ while (m_long_term_block_weights.size() < nblocks)
+ {
+ m_long_term_block_weights.push_front(db_height - 1 - m_long_term_block_weights.size());
+ }
+
update_next_cumulative_weight_limit();
return true;
}
@@ -606,6 +619,8 @@ block Blockchain::pop_block_from_blockchain()
throw;
}
+ pop_from_long_term_block_weights();
+
// return transactions from popped block to the tx_pool
for (transaction& tx : popped_txs)
{
@@ -655,6 +670,8 @@ bool Blockchain::reset_and_set_genesis_block(const block& b)
m_timestamps_and_difficulties_height = 0;
m_alternative_chains.clear();
invalidate_block_template_cache();
+ m_long_term_block_weights.clear();
+ m_long_term_block_weights_height = 0;
m_db->reset();
m_hardfork->init();
@@ -2947,7 +2964,8 @@ bool Blockchain::check_fee(size_t tx_weight, uint64_t fee) const
uint64_t needed_fee;
if (version >= HF_VERSION_PER_BYTE_FEE)
{
- uint64_t fee_per_byte = get_dynamic_base_fee(base_reward, median, version);
+ const bool use_long_term_median_in_fee = version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT;
+ uint64_t fee_per_byte = get_dynamic_base_fee(base_reward, use_long_term_median_in_fee ? m_long_term_block_weights.back() : median, version);
MDEBUG("Using " << print_money(fee_per_byte) << "/byte fee");
needed_fee = tx_weight * fee_per_byte;
// quantize fee up to 8 decimals
@@ -3010,7 +3028,8 @@ uint64_t Blockchain::get_dynamic_base_fee_estimate(uint64_t grace_blocks) const
base_reward = BLOCK_REWARD_OVERESTIMATE;
}
- uint64_t fee = get_dynamic_base_fee(base_reward, median, version);
+ const bool use_long_term_median_in_fee = version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT;
+ uint64_t fee = get_dynamic_base_fee(base_reward, use_long_term_median_in_fee ? m_long_term_block_weights.back() : median, version);
const bool per_byte = version < HF_VERSION_PER_BYTE_FEE;
MDEBUG("Estimating " << grace_blocks << "-block fee at " << print_money(fee) << "/" << (per_byte ? "byte" : "kB"));
return fee;
@@ -3507,7 +3526,8 @@ leave:
{
try
{
- new_height = m_db->add_block(bl, block_weight, cumulative_difficulty, already_generated_coins, txs);
+ uint64_t long_term_block_weight = get_next_long_term_block_weight(block_weight);
+ new_height = m_db->add_block(bl, block_weight, long_term_block_weight, cumulative_difficulty, already_generated_coins, txs);
}
catch (const KEY_IMAGE_EXISTS& e)
{
@@ -3560,20 +3580,109 @@ leave:
return true;
}
//------------------------------------------------------------------
-bool Blockchain::update_next_cumulative_weight_limit()
+void Blockchain::pop_from_long_term_block_weights()
+{
+ m_long_term_block_weights.pop_back();
+ --m_long_term_block_weights_height;
+ if (m_long_term_block_weights_height + 1 > m_long_term_block_weights.capacity())
+ {
+ uint64_t block_height = m_long_term_block_weights_height - m_long_term_block_weights.capacity() + 1;
+ m_long_term_block_weights.push_front(block_height);
+ }
+}
+//------------------------------------------------------------------
+uint64_t Blockchain::get_next_long_term_block_weight(uint64_t block_weight) const
{
- uint64_t full_reward_zone = get_min_block_weight(get_current_hard_fork_version());
+ PERF_TIMER(get_next_long_term_block_weight);
+
+ const uint64_t nblocks = std::min<uint64_t>(m_long_term_block_weights.capacity(), m_db->height());
+ CHECK_AND_ASSERT_MES(m_long_term_block_weights.size() == nblocks, 0,
+ "m_long_term_block_weights is not the expected size");
+
+ const uint8_t hf_version = get_current_hard_fork_version();
+ if (hf_version < HF_VERSION_LONG_TERM_BLOCK_WEIGHT)
+ return block_weight;
+
+ std::vector<uint64_t> weights(m_long_term_block_weights.begin(), m_long_term_block_weights.end());
+ uint64_t long_term_median = epee::misc_utils::median(weights);
+ uint64_t long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median);
+
+ uint64_t short_term_constraint = long_term_effective_median_block_weight + long_term_effective_median_block_weight * 2 / 5;
+ uint64_t long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint);
+
+ return long_term_block_weight;
+}
+//------------------------------------------------------------------
+bool Blockchain::update_next_cumulative_weight_limit(uint64_t *long_term_effective_median_block_weight)
+{
+ PERF_TIMER(update_next_cumulative_weight_limit);
LOG_PRINT_L3("Blockchain::" << __func__);
- std::vector<size_t> weights;
- get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
- uint64_t median = epee::misc_utils::median(weights);
- m_current_block_cumul_weight_median = median;
- if(median <= full_reward_zone)
- median = full_reward_zone;
+ uint64_t local_long_term_effective_median_block_weight;
+ if (!long_term_effective_median_block_weight)
+ long_term_effective_median_block_weight = &local_long_term_effective_median_block_weight;
+
+ // when we reach this, the last hf version is not yet written to the db
+ const uint64_t db_height = m_db->height();
+ const uint8_t hf_version = (m_long_term_block_weights_height + 1 < m_db->height()) ? m_db->get_hard_fork_version(db_height - 1) : get_current_hard_fork_version();
+ uint64_t full_reward_zone = get_min_block_weight(hf_version);
+ uint64_t long_term_block_weight;
+
+ // recalc, or reorg ? pop the last one(s) and recompute
+ uint64_t pop = 0;
+ if (db_height && db_height <= m_long_term_block_weights_height)
+ {
+ pop = m_long_term_block_weights_height - db_height + 1;
+ while (pop--)
+ pop_from_long_term_block_weights();
+ }
+
+ if (hf_version < HF_VERSION_LONG_TERM_BLOCK_WEIGHT)
+ {
+ std::vector<size_t> weights;
+ get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
+ m_current_block_cumul_weight_median = epee::misc_utils::median(weights);
+ long_term_block_weight = weights.back();
+ }
+ else
+ {
+ const uint64_t block_weight = m_db->get_block_weight(db_height - 1);
+
+ std::vector<uint64_t> weights(m_long_term_block_weights.begin(), m_long_term_block_weights.end());
+ uint64_t long_term_median = epee::misc_utils::median(weights);
+ *long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median);
+
+ uint64_t short_term_constraint = *long_term_effective_median_block_weight + *long_term_effective_median_block_weight * 2 / 5;
+ long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint);
+
+ weights = std::vector<uint64_t>(m_long_term_block_weights.begin(), m_long_term_block_weights.end());
+ if (weights.empty())
+ weights.resize(1);
+ weights[0] = long_term_block_weight;
+ long_term_median = epee::misc_utils::median(weights);
+ *long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median);
+ short_term_constraint = *long_term_effective_median_block_weight + *long_term_effective_median_block_weight * 2 / 5;
+
+ weights.clear();
+ get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
+
+ uint64_t short_term_median = epee::misc_utils::median(weights);
+ uint64_t effective_median_block_weight = std::min<uint64_t>(std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, short_term_median), CRYPTONOTE_SHORT_TERM_BLOCK_WEIGHT_SURGE_FACTOR * *long_term_effective_median_block_weight);
+
+ m_current_block_cumul_weight_median = effective_median_block_weight;
+ }
+
+ m_long_term_block_weights.push_back(long_term_block_weight);
+ m_long_term_block_weights_height = db_height;
+ const uint64_t nblocks = std::min<uint64_t>(m_long_term_block_weights.capacity(), db_height);
+ CHECK_AND_ASSERT_MES(m_long_term_block_weights.size() == nblocks, false, "Bad m_long_term_block_weights size");
+
+ if (m_current_block_cumul_weight_median <= full_reward_zone)
+ m_current_block_cumul_weight_median = full_reward_zone;
+
+ m_current_block_cumul_weight_limit = m_current_block_cumul_weight_median * 2;
- m_current_block_cumul_weight_limit = median*2;
return true;
}
//------------------------------------------------------------------
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index ab66fac8b..463a37b64 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -37,6 +37,7 @@
#include <boost/multi_index/global_fun.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
+#include <boost/circular_buffer.hpp>
#include <atomic>
#include <unordered_map>
#include <unordered_set>
@@ -612,6 +613,13 @@ namespace cryptonote
uint64_t get_current_cumulative_block_weight_limit() const;
/**
+ * @brief gets the long term block weight for a new block
+ *
+ * @return the long term block weight
+ */
+ uint64_t get_next_long_term_block_weight(uint64_t block_weight) const;
+
+ /**
* @brief gets the block weight median based on recent blocks (same window as for the limit)
*
* @return the median
@@ -952,7 +960,21 @@ namespace cryptonote
*/
void on_new_tx_from_block(const cryptonote::transaction &tx);
+ /**
+ * @brief returns the timestamps of the last N blocks
+ */
+ std::vector<time_t> get_last_block_timestamps(unsigned int blocks) const;
+
+ /**
+ * @brief removes blocks from the top of the blockchain
+ *
+ * @param nblocks number of blocks to be removed
+ */
+ void pop_blocks(uint64_t nblocks);
+
+#ifndef IN_UNIT_TESTS
private:
+#endif
// TODO: evaluate whether or not each of these typedefs are left over from blockchain_storage
typedef std::unordered_map<crypto::hash, size_t> blocks_by_id_index;
@@ -1005,6 +1027,8 @@ namespace cryptonote
std::vector<uint64_t> m_timestamps;
std::vector<difficulty_type> m_difficulties;
uint64_t m_timestamps_and_difficulties_height;
+ boost::circular_buffer<uint64_t> m_long_term_block_weights;
+ uint64_t m_long_term_block_weights_height;
epee::critical_section m_difficulty_lock;
crypto::hash m_difficulty_for_next_block_top_hash;
@@ -1336,9 +1360,11 @@ namespace cryptonote
/**
* @brief calculate the block weight limit for the next block to be added
*
+ * @param long_term_effective_median_block_weight optionally return that value
+ *
* @return true
*/
- bool update_next_cumulative_weight_limit();
+ bool update_next_cumulative_weight_limit(uint64_t *long_term_effective_median_block_weight = NULL);
void return_tx_to_pool(std::vector<transaction> &txs);
/**
@@ -1392,5 +1418,12 @@ namespace cryptonote
* At some point, may be used to push an update to miners
*/
void cache_block_template(const block &b, const cryptonote::account_public_address &address, const blobdata &nonce, const difficulty_type &diff, uint64_t expected_reward, uint64_t pool_cookie);
+
+ /**
+ * @brief pops an entry from long term block weights
+ *
+ * another is added at the other end if necessary
+ */
+ void pop_from_long_term_block_weights();
};
} // namespace cryptonote
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 2fec6b613..40541ba8c 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -564,7 +564,8 @@ namespace cryptonote
const std::pair<uint8_t, uint64_t> regtest_hard_forks[3] = {std::make_pair(1, 0), std::make_pair(Blockchain::get_hard_fork_heights(MAINNET).back().version, 1), std::make_pair(0, 0)};
const cryptonote::test_options regtest_test_options = {
- regtest_hard_forks
+ regtest_hard_forks,
+ 0
};
const difficulty_type fixed_difficulty = command_line::get_arg(vm, arg_fixed_difficulty);
r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? &regtest_test_options : test_options, fixed_difficulty);
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 58fe5b7b5..c74c244b0 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -55,6 +55,7 @@ namespace cryptonote
{
struct test_options {
const std::pair<uint8_t, uint64_t> *hard_forks;
+ const size_t long_term_block_weight_window;
};
extern const command_line::arg_descriptor<std::string, false, true, 2> arg_data_dir;
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 6464d372f..3348989f2 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -77,6 +77,7 @@ namespace {
<< "POW hash: " << header.pow_hash << std::endl
<< "block size: " << header.block_size << std::endl
<< "block weight: " << header.block_weight << std::endl
+ << "long term weight: " << header.long_term_weight << std::endl
<< "num txes: " << header.num_txes << std::endl
<< "reward: " << cryptonote::print_money(header.reward);
}
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index bc33dc77f..8098b62ad 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -1264,6 +1264,7 @@ namespace cryptonote
response.block_size = response.block_weight = m_core.get_blockchain_storage().get_db().get_block_weight(height);
response.num_txes = blk.tx_hashes.size();
response.pow_hash = fill_pow_hash ? string_tools::pod_to_hex(get_block_longhash(blk, height)) : "";
+ response.long_term_weight = m_core.get_blockchain_storage().get_db().get_block_long_term_weight(height);
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 3b654d4cb..8ac1279a2 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -1128,6 +1128,7 @@ namespace cryptonote
uint64_t block_weight;
uint64_t num_txes;
std::string pow_hash;
+ uint64_t long_term_weight;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(major_version)
@@ -1146,6 +1147,7 @@ namespace cryptonote
KV_SERIALIZE_OPT(block_weight, (uint64_t)0)
KV_SERIALIZE(num_txes)
KV_SERIALIZE(pow_hash)
+ KV_SERIALIZE_OPT(long_term_weight, (uint64_t)0)
END_KV_SERIALIZE_MAP()
};