aboutsummaryrefslogtreecommitdiff
path: root/tests/unit_tests
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/blockchain_db/testdb.h (renamed from tests/unit_tests/testdb.h)9
-rw-r--r--tests/unit_tests/CMakeLists.txt1
-rw-r--r--tests/unit_tests/blockchain_db.cpp12
-rw-r--r--tests/unit_tests/hardfork.cpp41
-rw-r--r--tests/unit_tests/long_term_block_weight.cpp384
-rw-r--r--tests/unit_tests/output_distribution.cpp4
6 files changed, 421 insertions, 30 deletions
diff --git a/tests/unit_tests/testdb.h b/src/blockchain_db/testdb.h
index 8f5cf70e8..35dfbe673 100644
--- a/tests/unit_tests/testdb.h
+++ b/src/blockchain_db/testdb.h
@@ -33,9 +33,11 @@
#include <string>
#include <vector>
#include <map>
-#include "gtest/gtest.h"
-#include "blockchain_db/blockchain_db.h"
+#include "blockchain_db.h"
+
+namespace cryptonote
+{
class BaseTestDB: public cryptonote::BlockchainDB {
public:
@@ -73,6 +75,7 @@ public:
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>(); }
@@ -128,6 +131,7 @@ public:
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
@@ -145,3 +149,4 @@ public:
virtual void prune_outputs(uint64_t amount) {}
};
+}
diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt
index cb421c847..aea82ede2 100644
--- a/tests/unit_tests/CMakeLists.txt
+++ b/tests/unit_tests/CMakeLists.txt
@@ -55,6 +55,7 @@ set(unit_tests_sources
http.cpp
keccak.cpp
logging.cpp
+ long_term_block_weight.cpp
main.cpp
memwipe.cpp
mlocker.cpp
diff --git a/tests/unit_tests/blockchain_db.cpp b/tests/unit_tests/blockchain_db.cpp
index 7e7ce9bf7..9cf8c5fbe 100644
--- a/tests/unit_tests/blockchain_db.cpp
+++ b/tests/unit_tests/blockchain_db.cpp
@@ -277,10 +277,10 @@ TYPED_TEST(BlockchainDBTest, AddBlock)
// TODO: need at least one more block to make this reasonable, as the
// BlockchainDB implementation should not check for parent if
// no blocks have been added yet (because genesis has no parent).
- //ASSERT_THROW(this->m_db->add_block(this->m_blocks[1], t_sizes[1], t_diffs[1], t_coins[1], this->m_txs[1]), BLOCK_PARENT_DNE);
+ //ASSERT_THROW(this->m_db->add_block(this->m_blocks[1], t_sizes[1], t_sizes[1], t_diffs[1], t_coins[1], this->m_txs[1]), BLOCK_PARENT_DNE);
- ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[0], t_sizes[0], t_diffs[0], t_coins[0], this->m_txs[0]));
- ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[1], t_sizes[1], t_diffs[1], t_coins[1], this->m_txs[1]));
+ ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[0], t_sizes[0], t_sizes[0], t_diffs[0], t_coins[0], this->m_txs[0]));
+ ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[1], t_sizes[1], t_sizes[1], t_diffs[1], t_coins[1], this->m_txs[1]));
block b;
ASSERT_TRUE(this->m_db->block_exists(get_block_hash(this->m_blocks[0])));
@@ -293,7 +293,7 @@ TYPED_TEST(BlockchainDBTest, AddBlock)
ASSERT_TRUE(compare_blocks(this->m_blocks[0], b));
// assert that we can't add the same block twice
- ASSERT_THROW(this->m_db->add_block(this->m_blocks[0], t_sizes[0], t_diffs[0], t_coins[0], this->m_txs[0]), TX_EXISTS);
+ ASSERT_THROW(this->m_db->add_block(this->m_blocks[0], t_sizes[0], t_sizes[0], t_diffs[0], t_coins[0], this->m_txs[0]), TX_EXISTS);
for (auto& h : this->m_blocks[0].tx_hashes)
{
@@ -317,14 +317,14 @@ TYPED_TEST(BlockchainDBTest, RetrieveBlockData)
this->get_filenames();
this->init_hard_fork();
- ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[0], t_sizes[0], t_diffs[0], t_coins[0], this->m_txs[0]));
+ ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[0], t_sizes[0], t_sizes[0], t_diffs[0], t_coins[0], this->m_txs[0]));
ASSERT_EQ(t_sizes[0], this->m_db->get_block_weight(0));
ASSERT_EQ(t_diffs[0], this->m_db->get_block_cumulative_difficulty(0));
ASSERT_EQ(t_diffs[0], this->m_db->get_block_difficulty(0));
ASSERT_EQ(t_coins[0], this->m_db->get_block_already_generated_coins(0));
- ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[1], t_sizes[1], t_diffs[1], t_coins[1], this->m_txs[1]));
+ ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[1], t_sizes[1], t_sizes[1], t_diffs[1], t_coins[1], this->m_txs[1]));
ASSERT_EQ(t_diffs[1] - t_diffs[0], this->m_db->get_block_difficulty(1));
ASSERT_HASH_EQ(get_block_hash(this->m_blocks[0]), this->m_db->get_block_hash_from_height(0));
diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp
index ec8d1d202..12dfde1bc 100644
--- a/tests/unit_tests/hardfork.cpp
+++ b/tests/unit_tests/hardfork.cpp
@@ -34,7 +34,7 @@
#include "blockchain_db/blockchain_db.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_basic/hardfork.h"
-#include "testdb.h"
+#include "blockchain_db/testdb.h"
using namespace cryptonote;
@@ -44,11 +44,12 @@ using namespace cryptonote;
namespace
{
-class TestDB: public BaseTestDB {
+class TestDB: public cryptonote::BaseTestDB {
public:
virtual uint64_t height() const { return blocks.size(); }
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
@@ -106,20 +107,20 @@ TEST(major, Only)
ASSERT_FALSE(hf.add(mkblock(0, 2), 0));
ASSERT_FALSE(hf.add(mkblock(2, 2), 0));
ASSERT_TRUE(hf.add(mkblock(1, 2), 0));
- db.add_block(mkblock(1, 1), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(1, 1), 0, 0, 0, 0, 0, crypto::hash());
// block height 1, only version 1 is accepted
ASSERT_FALSE(hf.add(mkblock(0, 2), 1));
ASSERT_FALSE(hf.add(mkblock(2, 2), 1));
ASSERT_TRUE(hf.add(mkblock(1, 2), 1));
- db.add_block(mkblock(1, 1), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(1, 1), 0, 0, 0, 0, 0, crypto::hash());
// block height 2, only version 2 is accepted
ASSERT_FALSE(hf.add(mkblock(0, 2), 2));
ASSERT_FALSE(hf.add(mkblock(1, 2), 2));
ASSERT_FALSE(hf.add(mkblock(3, 2), 2));
ASSERT_TRUE(hf.add(mkblock(2, 2), 2));
- db.add_block(mkblock(2, 1), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(2, 1), 0, 0, 0, 0, 0, crypto::hash());
}
TEST(empty_hardforks, Success)
@@ -133,7 +134,7 @@ TEST(empty_hardforks, Success)
ASSERT_TRUE(hf.get_state(time(NULL) + 3600*24*400) == HardFork::Ready);
for (uint64_t h = 0; h <= 10; ++h) {
- db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, 0, crypto::hash());
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
}
ASSERT_EQ(hf.get(0), 1);
@@ -167,14 +168,14 @@ TEST(check_for_height, Success)
for (uint64_t h = 0; h <= 4; ++h) {
ASSERT_TRUE(hf.check_for_height(mkblock(1, 1), h));
ASSERT_FALSE(hf.check_for_height(mkblock(2, 2), h)); // block version is too high
- db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, 0, crypto::hash());
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
}
for (uint64_t h = 5; h <= 10; ++h) {
ASSERT_FALSE(hf.check_for_height(mkblock(1, 1), h)); // block version is too low
ASSERT_TRUE(hf.check_for_height(mkblock(2, 2), h));
- db.add_block(mkblock(hf, h, 2), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, 2), 0, 0, 0, 0, 0, crypto::hash());
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
}
}
@@ -191,19 +192,19 @@ TEST(get, next_version)
for (uint64_t h = 0; h <= 4; ++h) {
ASSERT_EQ(2, hf.get_next_version());
- db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, 1), 0, 0, 0, 0, 0, crypto::hash());
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
}
for (uint64_t h = 5; h <= 9; ++h) {
ASSERT_EQ(4, hf.get_next_version());
- db.add_block(mkblock(hf, h, 2), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, 2), 0, 0, 0, 0, 0, crypto::hash());
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
}
for (uint64_t h = 10; h <= 15; ++h) {
ASSERT_EQ(4, hf.get_next_version());
- db.add_block(mkblock(hf, h, 4), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, 4), 0, 0, 0, 0, 0, crypto::hash());
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
}
}
@@ -244,7 +245,7 @@ TEST(steps_asap, Success)
hf.init();
for (uint64_t h = 0; h < 10; ++h) {
- db.add_block(mkblock(hf, h, 9), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, 9), 0, 0, 0, 0, 0, crypto::hash());
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
}
@@ -271,7 +272,7 @@ TEST(steps_1, Success)
hf.init();
for (uint64_t h = 0 ; h < 10; ++h) {
- db.add_block(mkblock(hf, h, h+1), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, h+1), 0, 0, 0, 0, 0, crypto::hash());
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
}
@@ -296,7 +297,7 @@ TEST(reorganize, Same)
// index 0 1 2 3 4 5 6 7 8 9
static const uint8_t block_versions[] = { 1, 1, 4, 4, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
for (uint64_t h = 0; h < 20; ++h) {
- db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, crypto::hash());
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
}
@@ -327,7 +328,7 @@ TEST(reorganize, Changed)
static const uint8_t block_versions[] = { 1, 1, 4, 4, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
static const uint8_t expected_versions[] = { 1, 1, 1, 1, 1, 1, 4, 4, 7, 7, 9, 9, 9, 9, 9, 9 };
for (uint64_t h = 0; h < 16; ++h) {
- db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, crypto::hash());
ASSERT_TRUE (hf.add(db.get_block_from_height(h), h));
}
@@ -347,7 +348,7 @@ TEST(reorganize, Changed)
ASSERT_EQ(db.height(), 3);
hf.reorganize_from_block_height(2);
for (uint64_t h = 3; h < 16; ++h) {
- db.add_block(mkblock(hf, h, block_versions_new[h]), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, block_versions_new[h]), 0, 0, 0, 0, 0, crypto::hash());
bool ret = hf.add(db.get_block_from_height(h), h);
ASSERT_EQ (ret, h < 15);
}
@@ -371,7 +372,7 @@ TEST(voting, threshold)
for (uint64_t h = 0; h <= 8; ++h) {
uint8_t v = 1 + !!(h % 8);
- db.add_block(mkblock(hf, h, v), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, v), 0, 0, 0, 0, 0, crypto::hash());
bool ret = hf.add(db.get_block_from_height(h), h);
if (h >= 8 && threshold == 87) {
// for threshold 87, we reach the treshold at height 7, so from height 8, hard fork to version 2, but 8 tries to add 1
@@ -405,7 +406,7 @@ TEST(voting, different_thresholds)
static const uint8_t expected_versions[] = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };
for (uint64_t h = 0; h < sizeof(block_versions) / sizeof(block_versions[0]); ++h) {
- db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, crypto::hash());
bool ret = hf.add(db.get_block_from_height(h), h);
ASSERT_EQ(ret, true);
}
@@ -459,7 +460,7 @@ TEST(voting, info)
ASSERT_EQ(expected_thresholds[h], threshold);
ASSERT_EQ(4, voting);
- db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, crypto::hash());
+ db.add_block(mkblock(hf, h, block_versions[h]), 0, 0, 0, 0, 0, crypto::hash());
ASSERT_TRUE(hf.add(db.get_block_from_height(h), h));
}
}
@@ -522,7 +523,7 @@ TEST(reorganize, changed)
#define ADD(v, h, a) \
do { \
cryptonote::block b = mkblock(hf, h, v); \
- db.add_block(b, 0, 0, 0, 0, crypto::hash()); \
+ db.add_block(b, 0, 0, 0, 0, 0, crypto::hash()); \
ASSERT_##a(hf.add(b, h)); \
} while(0)
#define ADD_TRUE(v, h) ADD(v, h, TRUE)
diff --git a/tests/unit_tests/long_term_block_weight.cpp b/tests/unit_tests/long_term_block_weight.cpp
new file mode 100644
index 000000000..0ee6c5c2b
--- /dev/null
+++ b/tests/unit_tests/long_term_block_weight.cpp
@@ -0,0 +1,384 @@
+// Copyright (c) 2019, 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.
+
+#define IN_UNIT_TESTS
+
+#include "gtest/gtest.h"
+#include "cryptonote_core/blockchain.h"
+#include "cryptonote_core/tx_pool.h"
+#include "cryptonote_core/cryptonote_core.h"
+#include "blockchain_db/testdb.h"
+
+#define TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW 5000
+
+namespace
+{
+
+class TestDB: public cryptonote::BaseTestDB
+{
+private:
+ struct block_t
+ {
+ size_t weight;
+ uint64_t long_term_weight;
+ };
+
+public:
+ TestDB() { m_open = true; }
+
+ 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
+ ) override {
+ blocks.push_back({block_weight, long_term_block_weight});
+ }
+ virtual uint64_t height() const override { return blocks.size(); }
+ virtual size_t get_block_weight(const uint64_t &h) const override { return blocks[h].weight; }
+ virtual uint64_t get_block_long_term_weight(const uint64_t &h) const override { return blocks[h].long_term_weight; }
+ virtual crypto::hash top_block_hash() const override {
+ uint64_t h = height();
+ crypto::hash top = crypto::null_hash;
+ if (h)
+ *(uint64_t*)&top = h - 1;
+ return top;
+ }
+ virtual void pop_block(cryptonote::block &blk, std::vector<cryptonote::transaction> &txs) override { blocks.pop_back(); }
+
+private:
+ std::vector<block_t> blocks;
+};
+
+static uint32_t lcg_seed = 0;
+
+static uint32_t lcg()
+{
+ lcg_seed = (lcg_seed * 0x100000001b3 + 0xcbf29ce484222325) & 0xffffffff;
+ return lcg_seed;
+}
+
+}
+
+#define PREFIX_WINDOW(hf_version,window) \
+ std::unique_ptr<cryptonote::Blockchain> bc; \
+ cryptonote::tx_memory_pool txpool(*bc); \
+ bc.reset(new cryptonote::Blockchain(txpool)); \
+ struct get_test_options { \
+ const std::pair<uint8_t, uint64_t> hard_forks[3]; \
+ const cryptonote::test_options test_options = { \
+ hard_forks, \
+ window, \
+ }; \
+ get_test_options(): hard_forks{std::make_pair(1, (uint64_t)0), std::make_pair((uint8_t)hf_version, (uint64_t)1), std::make_pair((uint8_t)0, (uint64_t)0)} {} \
+ } opts; \
+ cryptonote::Blockchain *blockchain = bc.get(); \
+ bool r = blockchain->init(new TestDB(), cryptonote::FAKECHAIN, true, &opts.test_options, 0, NULL); \
+ ASSERT_TRUE(r)
+
+#define PREFIX(hf_version) PREFIX_WINDOW(hf_version, TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW)
+
+TEST(long_term_block_weight, empty_short)
+{
+ PREFIX(9);
+
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+
+ ASSERT_EQ(bc->get_current_cumulative_block_weight_median(), CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5);
+ ASSERT_EQ(bc->get_current_cumulative_block_weight_limit(), CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 * 2);
+}
+
+TEST(long_term_block_weight, identical_before_fork)
+{
+ PREFIX(9);
+
+ for (uint64_t h = 1; h < 10 * TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW; ++h)
+ {
+ size_t w = h < CRYPTONOTE_REWARD_BLOCKS_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, h, h, {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ }
+ for (uint64_t h = 0; h < 10 * TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW; ++h)
+ {
+ ASSERT_EQ(bc->get_db().get_block_long_term_weight(h), bc->get_db().get_block_weight(h));
+ }
+}
+
+TEST(long_term_block_weight, identical_after_fork_before_long_term_window)
+{
+ PREFIX(10);
+
+ for (uint64_t h = 1; h <= TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW; ++h)
+ {
+ size_t w = h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, h, h, {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ }
+ for (uint64_t h = 0; h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW; ++h)
+ {
+ ASSERT_EQ(bc->get_db().get_block_long_term_weight(h), bc->get_db().get_block_weight(h));
+ }
+}
+
+TEST(long_term_block_weight, ceiling_at_30000000)
+{
+ PREFIX(10);
+
+ for (uint64_t h = 0; h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW + TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW / 2 - 1; ++h)
+ {
+ size_t w = h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, h, h, {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ }
+ ASSERT_EQ(bc->get_current_cumulative_block_weight_median(), 15000000);
+ ASSERT_EQ(bc->get_current_cumulative_block_weight_limit(), 30000000);
+}
+
+TEST(long_term_block_weight, multi_pop)
+{
+ PREFIX(10);
+
+ for (uint64_t h = 1; h <= TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW + 20; ++h)
+ {
+ size_t w = h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, h, h, {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ }
+
+ const uint64_t effective_median = bc->get_current_cumulative_block_weight_median();
+ const uint64_t effective_limit = bc->get_current_cumulative_block_weight_limit();
+
+ for (uint64_t h = 0; h < 4; ++h)
+ {
+ size_t w = h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, h, h, {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ }
+
+ cryptonote::block b;
+ std::vector<cryptonote::transaction> txs;
+ bc->get_db().pop_block(b, txs);
+ bc->get_db().pop_block(b, txs);
+ bc->get_db().pop_block(b, txs);
+ bc->get_db().pop_block(b, txs);
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+
+ ASSERT_EQ(effective_median, bc->get_current_cumulative_block_weight_median());
+ ASSERT_EQ(effective_limit, bc->get_current_cumulative_block_weight_limit());
+}
+
+TEST(long_term_block_weight, multiple_updates)
+{
+ PREFIX(10);
+
+ for (uint64_t h = 1; h <= 3 * TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW; ++h)
+ {
+ size_t w = h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, h, h, {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ const uint64_t effective_median = bc->get_current_cumulative_block_weight_median();
+ const uint64_t effective_limit = bc->get_current_cumulative_block_weight_limit();
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ ASSERT_EQ(effective_median, bc->get_current_cumulative_block_weight_median());
+ ASSERT_EQ(effective_limit, bc->get_current_cumulative_block_weight_limit());
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ ASSERT_EQ(effective_median, bc->get_current_cumulative_block_weight_median());
+ ASSERT_EQ(effective_limit, bc->get_current_cumulative_block_weight_limit());
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ ASSERT_EQ(effective_median, bc->get_current_cumulative_block_weight_median());
+ ASSERT_EQ(effective_limit, bc->get_current_cumulative_block_weight_limit());
+ }
+}
+
+TEST(long_term_block_weight, pop_invariant_max)
+{
+ PREFIX(10);
+
+ for (uint64_t h = 1; h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW - 10; ++h)
+ {
+ size_t w = bc->get_db().height() < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, h, h, {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ }
+
+ for (int n = 0; n < 1000; ++n)
+ {
+ // pop some blocks, then add some more
+ int remove = 1 + (n * 17) % 8;
+ int add = (n * 23) % 12;
+
+ // save long term block weights we're about to remove
+ uint64_t old_ltbw[16], h0 = bc->get_db().height() - remove - 1;
+ for (int i = -2; i < remove; ++i)
+ {
+ old_ltbw[i + 2] = bc->get_db().get_block_long_term_weight(h0 + i);
+ }
+
+ for (int i = 0; i < remove; ++i)
+ {
+ cryptonote::block b;
+ std::vector<cryptonote::transaction> txs;
+ bc->get_db().pop_block(b, txs);
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ }
+ for (int i = 0; i < add; ++i)
+ {
+ size_t w = bc->get_db().height() < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, bc->get_db().height(), bc->get_db().height(), {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ }
+
+ // check the new values are the same as the old ones
+ for (int i = -2; i < std::min(add, remove); ++i)
+ {
+ ASSERT_EQ(bc->get_db().get_block_long_term_weight(h0 + i), old_ltbw[i + 2]);
+ }
+ }
+}
+
+TEST(long_term_block_weight, pop_invariant_random)
+{
+ PREFIX(10);
+
+ for (uint64_t h = 1; h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW - 10; ++h)
+ {
+ size_t w = bc->get_db().height() < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit();
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, h, h, {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ }
+
+ for (int n = 0; n < 1000; ++n)
+ {
+ // pop some blocks, then add some more
+ int remove = 1 + (n * 17) % 8;
+ int add = (n * 23) % 123;
+
+ // save long term block weights we're about to remove
+ uint64_t old_ltbw[16], h0 = bc->get_db().height() - remove - 1;
+ for (int i = -2; i < remove; ++i)
+ {
+ old_ltbw[i + 2] = bc->get_db().get_block_long_term_weight(h0 + i);
+ }
+
+ for (int i = 0; i < remove; ++i)
+ {
+ cryptonote::block b;
+ std::vector<cryptonote::transaction> txs;
+ bc->get_db().pop_block(b, txs);
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ const uint64_t effective_median = bc->get_current_cumulative_block_weight_median();
+ const uint64_t effective_limit = bc->get_current_cumulative_block_weight_limit();
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ ASSERT_EQ(effective_median, bc->get_current_cumulative_block_weight_median());
+ ASSERT_EQ(effective_limit, bc->get_current_cumulative_block_weight_limit());
+ }
+ for (int i = 0; i < add; ++i)
+ {
+ lcg_seed = bc->get_db().height();
+ uint32_t r = lcg();
+ size_t w = bc->get_db().height() < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : (r % bc->get_current_cumulative_block_weight_limit());
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, bc->get_db().height(), bc->get_db().height(), {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ const uint64_t effective_median = bc->get_current_cumulative_block_weight_median();
+ const uint64_t effective_limit = bc->get_current_cumulative_block_weight_limit();
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit());
+ ASSERT_EQ(effective_median, bc->get_current_cumulative_block_weight_median());
+ ASSERT_EQ(effective_limit, bc->get_current_cumulative_block_weight_limit());
+ }
+
+ // check the new values are the same as the old ones
+ for (int i = -2; i < std::min(add, remove); ++i)
+ {
+ ASSERT_EQ(bc->get_db().get_block_long_term_weight(h0 + i), old_ltbw[i + 2]);
+ }
+ }
+}
+
+TEST(long_term_block_weight, long_growth_spike_and_drop)
+{
+ PREFIX(10);
+
+ uint64_t long_term_effective_median_block_weight;
+
+ // constant init
+ for (uint64_t h = 0; h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW; ++h)
+ {
+ size_t w = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5;
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, h, h, {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit(&long_term_effective_median_block_weight));
+ }
+ ASSERT_EQ(long_term_effective_median_block_weight, 300000);
+
+ // slow 10% yearly for a year (scaled down by 100000 / TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW) -> 8% change
+ for (uint64_t h = 0; h < 365 * 720 * TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW / 100000; ++h)
+ {
+ //size_t w = bc->get_current_cumulative_block_weight_median() * rate;
+ float t = h / float(365 * 720 * TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW / 100000);
+ size_t w = 300000 + t * 30000;
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, h, h, {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit(&long_term_effective_median_block_weight));
+ }
+ ASSERT_GT(long_term_effective_median_block_weight, 300000 * 1.07);
+ ASSERT_LT(long_term_effective_median_block_weight, 300000 * 1.09);
+
+ // spike over three weeks - does not move much
+ for (uint64_t h = 0; h < 21 * 720 * TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW / 100000; ++h)
+ {
+ size_t w = bc->get_current_cumulative_block_weight_limit();
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, h, h, {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit(&long_term_effective_median_block_weight));
+ }
+ ASSERT_GT(long_term_effective_median_block_weight, 300000 * 1.07);
+ ASSERT_LT(long_term_effective_median_block_weight, 300000 * 1.09);
+
+ // drop - does not move much
+ for (uint64_t h = 0; h < 21 * 720 * TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW / 100000; ++h)
+ {
+ size_t w = bc->get_current_cumulative_block_weight_median() * .25;
+ uint64_t ltw = bc->get_next_long_term_block_weight(w);
+ bc->get_db().add_block(cryptonote::block(), w, ltw, h, h, {});
+ ASSERT_TRUE(bc->update_next_cumulative_weight_limit(&long_term_effective_median_block_weight));
+ }
+ ASSERT_GT(long_term_effective_median_block_weight, 300000 * 1.07);
+ ASSERT_LT(long_term_effective_median_block_weight, 300000 * 1.09);
+}
diff --git a/tests/unit_tests/output_distribution.cpp b/tests/unit_tests/output_distribution.cpp
index 649752ac7..45f2c135b 100644
--- a/tests/unit_tests/output_distribution.cpp
+++ b/tests/unit_tests/output_distribution.cpp
@@ -33,7 +33,7 @@
#include "cryptonote_core/cryptonote_core.h"
#include "cryptonote_core/tx_pool.h"
#include "cryptonote_core/blockchain.h"
-#include "testdb.h"
+#include "blockchain_db/testdb.h"
static const uint64_t test_distribution[32] = {
0, 0, 0, 0, 0, 1, 5, 1, 4, 0, 0, 1, 0, 1, 2, 3, 1, 0, 2, 0, 1, 3, 8, 1, 3, 5, 7, 1, 5, 0, 2, 3
@@ -43,7 +43,7 @@ static const size_t test_distribution_size = sizeof(test_distribution) / sizeof(
namespace
{
-class TestDB: public BaseTestDB
+class TestDB: public cryptonote::BaseTestDB
{
public:
TestDB(size_t bc_height = test_distribution_size): blockchain_height(bc_height) { m_open = true; }