aboutsummaryrefslogtreecommitdiff
path: root/tests/unit_tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit_tests')
-rw-r--r--tests/unit_tests/CMakeLists.txt4
-rw-r--r--tests/unit_tests/ban.cpp2
-rw-r--r--tests/unit_tests/blockchain_db.cpp12
-rw-r--r--tests/unit_tests/bulletproofs.cpp3
-rw-r--r--tests/unit_tests/device.cpp9
-rw-r--r--tests/unit_tests/epee_utils.cpp22
-rw-r--r--tests/unit_tests/hardfork.cpp41
-rw-r--r--tests/unit_tests/json_serialization.cpp2
-rw-r--r--tests/unit_tests/long_term_block_weight.cpp384
-rw-r--r--tests/unit_tests/mnemonics.cpp36
-rw-r--r--tests/unit_tests/net.cpp745
-rw-r--r--tests/unit_tests/notify.cpp2
-rw-r--r--tests/unit_tests/output_distribution.cpp4
-rw-r--r--tests/unit_tests/pruning.cpp240
-rw-r--r--tests/unit_tests/ringct.cpp42
-rw-r--r--tests/unit_tests/serialization.cpp5
-rw-r--r--tests/unit_tests/test_peerlist.cpp175
-rw-r--r--tests/unit_tests/testdb.h147
18 files changed, 1653 insertions, 222 deletions
diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt
index f7012746d..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
@@ -62,9 +63,11 @@ set(unit_tests_sources
mul_div.cpp
multiexp.cpp
multisig.cpp
+ net.cpp
notify.cpp
output_distribution.cpp
parse_amount.cpp
+ pruning.cpp
random.cpp
serialization.cpp
sha256.cpp
@@ -99,6 +102,7 @@ target_link_libraries(unit_tests
cryptonote_core
blockchain_db
rpc
+ net
serialization
wallet
p2p
diff --git a/tests/unit_tests/ban.cpp b/tests/unit_tests/ban.cpp
index 12625a949..1e764c83e 100644
--- a/tests/unit_tests/ban.cpp
+++ b/tests/unit_tests/ban.cpp
@@ -84,6 +84,8 @@ public:
bool fluffy_blocks_enabled() const { return false; }
uint64_t prevalidate_block_hashes(uint64_t height, const std::vector<crypto::hash> &hashes) { return 0; }
bool pad_transactions() { return false; }
+ uint32_t get_blockchain_pruning_seed() const { return 0; }
+ bool prune_blockchain(uint32_t pruning_seed = 0) { return true; }
void stop() {}
};
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/bulletproofs.cpp b/tests/unit_tests/bulletproofs.cpp
index ac6eaca0b..4f07415b0 100644
--- a/tests/unit_tests/bulletproofs.cpp
+++ b/tests/unit_tests/bulletproofs.cpp
@@ -131,7 +131,8 @@ TEST(bulletproofs, multi_splitting)
}
rct::ctkeyV outSk;
- rct::rctSig s = rct::genRctSimple(rct::zero(), sc, destinations, inamounts, outamounts, available, mixRing, amount_keys, NULL, NULL, index, outSk, rct::RangeProofPaddedBulletproof, hw::get_device("default"));
+ rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 0 };
+ rct::rctSig s = rct::genRctSimple(rct::zero(), sc, destinations, inamounts, outamounts, available, mixRing, amount_keys, NULL, NULL, index, outSk, rct_config, hw::get_device("default"));
ASSERT_TRUE(rct::verRctSimple(s));
for (size_t i = 0; i < n_outputs; ++i)
{
diff --git a/tests/unit_tests/device.cpp b/tests/unit_tests/device.cpp
index 50ccec9fa..c0e8fecc1 100644
--- a/tests/unit_tests/device.cpp
+++ b/tests/unit_tests/device.cpp
@@ -114,18 +114,17 @@ TEST(device, ops)
ASSERT_EQ(ki0, ki1);
}
-TEST(device, ecdh)
+TEST(device, ecdh32)
{
hw::core::device_default dev;
rct::ecdhTuple tuple, tuple2;
rct::key key = rct::skGen();
tuple.mask = rct::skGen();
tuple.amount = rct::skGen();
- tuple.senderPk = rct::pkGen();
tuple2 = tuple;
- dev.ecdhEncode(tuple, key);
- dev.ecdhDecode(tuple, key);
+ dev.ecdhEncode(tuple, key, false);
+ dev.ecdhDecode(tuple, key, false);
ASSERT_EQ(tuple2.mask, tuple.mask);
ASSERT_EQ(tuple2.amount, tuple.amount);
- ASSERT_EQ(tuple2.senderPk, tuple.senderPk);
}
+
diff --git a/tests/unit_tests/epee_utils.cpp b/tests/unit_tests/epee_utils.cpp
index 3d5882d7d..18fb262c2 100644
--- a/tests/unit_tests/epee_utils.cpp
+++ b/tests/unit_tests/epee_utils.cpp
@@ -545,6 +545,8 @@ TEST(StringTools, GetIpInt32)
TEST(NetUtils, IPv4NetworkAddress)
{
+ static_assert(epee::net_utils::ipv4_network_address::get_type_id() == epee::net_utils::address_type::ipv4, "bad ipv4 type id");
+
const auto ip1 = boost::endian::native_to_big(0x330012FFu);
const auto ip_loopback = boost::endian::native_to_big(0x7F000001u);
const auto ip_local = boost::endian::native_to_big(0x0A000000u);
@@ -555,7 +557,7 @@ TEST(NetUtils, IPv4NetworkAddress)
EXPECT_STREQ("51.0.18.255", address1.host_str().c_str());
EXPECT_FALSE(address1.is_loopback());
EXPECT_FALSE(address1.is_local());
- EXPECT_EQ(epee::net_utils::ipv4_network_address::ID, address1.get_type_id());
+ EXPECT_EQ(epee::net_utils::ipv4_network_address::get_type_id(), address1.get_type_id());
EXPECT_EQ(ip1, address1.ip());
EXPECT_EQ(65535, address1.port());
EXPECT_TRUE(epee::net_utils::ipv4_network_address{std::move(address1)} == address1);
@@ -568,7 +570,7 @@ TEST(NetUtils, IPv4NetworkAddress)
EXPECT_STREQ("127.0.0.1", loopback.host_str().c_str());
EXPECT_TRUE(loopback.is_loopback());
EXPECT_FALSE(loopback.is_local());
- EXPECT_EQ(epee::net_utils::ipv4_network_address::ID, address1.get_type_id());
+ EXPECT_EQ(epee::net_utils::ipv4_network_address::get_type_id(), address1.get_type_id());
EXPECT_EQ(ip_loopback, loopback.ip());
EXPECT_EQ(0, loopback.port());
@@ -624,7 +626,9 @@ TEST(NetUtils, NetworkAddress)
constexpr static bool is_local() noexcept { return false; }
static std::string str() { return {}; }
static std::string host_str() { return {}; }
- constexpr static uint8_t get_type_id() noexcept { return uint8_t(-1); }
+ constexpr static epee::net_utils::address_type get_type_id() noexcept { return epee::net_utils::address_type(-1); }
+ constexpr static epee::net_utils::zone get_zone() noexcept { return epee::net_utils::zone::invalid; }
+ constexpr static bool is_blockable() noexcept { return false; }
};
const epee::net_utils::network_address empty;
@@ -634,7 +638,9 @@ TEST(NetUtils, NetworkAddress)
EXPECT_STREQ("<none>", empty.host_str().c_str());
EXPECT_FALSE(empty.is_loopback());
EXPECT_FALSE(empty.is_local());
- EXPECT_EQ(0, empty.get_type_id());
+ EXPECT_EQ(epee::net_utils::address_type::invalid, empty.get_type_id());
+ EXPECT_EQ(epee::net_utils::zone::invalid, empty.get_zone());
+ EXPECT_FALSE(empty.is_blockable());
EXPECT_THROW(empty.as<custom_address>(), std::bad_cast);
epee::net_utils::network_address address1{
@@ -650,7 +656,9 @@ TEST(NetUtils, NetworkAddress)
EXPECT_STREQ("51.0.18.255", address1.host_str().c_str());
EXPECT_FALSE(address1.is_loopback());
EXPECT_FALSE(address1.is_local());
- EXPECT_EQ(epee::net_utils::ipv4_network_address::ID, address1.get_type_id());
+ EXPECT_EQ(epee::net_utils::ipv4_network_address::get_type_id(), address1.get_type_id());
+ EXPECT_EQ(epee::net_utils::zone::public_, address1.get_zone());
+ EXPECT_TRUE(address1.is_blockable());
EXPECT_NO_THROW(address1.as<epee::net_utils::ipv4_network_address>());
EXPECT_THROW(address1.as<custom_address>(), std::bad_cast);
@@ -667,7 +675,9 @@ TEST(NetUtils, NetworkAddress)
EXPECT_STREQ("127.0.0.1", loopback.host_str().c_str());
EXPECT_TRUE(loopback.is_loopback());
EXPECT_FALSE(loopback.is_local());
- EXPECT_EQ(epee::net_utils::ipv4_network_address::ID, address1.get_type_id());
+ EXPECT_EQ(epee::net_utils::ipv4_network_address::get_type_id(), address1.get_type_id());
+ EXPECT_EQ(epee::net_utils::zone::public_, address1.get_zone());
+ EXPECT_EQ(epee::net_utils::ipv4_network_address::get_type_id(), address1.get_type_id());
const epee::net_utils::network_address local{
epee::net_utils::ipv4_network_address{ip_local, 8080}
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/json_serialization.cpp b/tests/unit_tests/json_serialization.cpp
index 234cb2c33..53d9f84c7 100644
--- a/tests/unit_tests/json_serialization.cpp
+++ b/tests/unit_tests/json_serialization.cpp
@@ -75,7 +75,7 @@ namespace
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
subaddresses[from.m_account_address.m_spend_public_key] = {0,0};
- if (!cryptonote::construct_tx_and_get_tx_key(from, subaddresses, actual_sources, to, boost::none, {}, tx, 0, tx_key, extra_keys, rct, bulletproof ? rct::RangeProofBulletproof : rct::RangeProofBorromean))
+ if (!cryptonote::construct_tx_and_get_tx_key(from, subaddresses, actual_sources, to, boost::none, {}, tx, 0, tx_key, extra_keys, rct, { bulletproof ? rct::RangeProofBulletproof : rct::RangeProofBorromean, bulletproof ? 2 : 0 }))
throw std::runtime_error{"transaction construction error"};
return tx;
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/mnemonics.cpp b/tests/unit_tests/mnemonics.cpp
index 4dc2d931e..59642828d 100644
--- a/tests/unit_tests/mnemonics.cpp
+++ b/tests/unit_tests/mnemonics.cpp
@@ -51,6 +51,7 @@
#include "mnemonics/english_old.h"
#include "mnemonics/language_base.h"
#include "mnemonics/singleton.h"
+#include <boost/algorithm/string.hpp>
namespace
{
@@ -221,3 +222,38 @@ TEST(mnemonics, utf8prefix)
ASSERT_TRUE(Language::utf8prefix(epee::wipeable_string("æon"), 3) == "æon");
ASSERT_TRUE(Language::utf8prefix(epee::wipeable_string("æon"), 4) == "æon");
}
+
+TEST(mnemonics, case_tolerance)
+{
+ bool res;
+ //
+ crypto::secret_key key_1;
+ std::string language_name_1;
+ const std::string seed_1 = "Neubau umarmen Abart umarmen Turban feilen Brett Bargeld Episode Milchkuh Substanz Jahr Armband Maibaum Tand Grünalge Tabak erziehen Federboa Lobrede Tenor Leuchter Curry Diskurs Tenor";
+ res = crypto::ElectrumWords::words_to_bytes(seed_1, key_1, language_name_1);
+ ASSERT_EQ(true, res);
+ ASSERT_STREQ(language_name_1.c_str(), "Deutsch");
+ //
+ crypto::secret_key key_2;
+ std::string language_name_2;
+ // neubau is capitalized in the word list, but the language detection code should be able to detect it as Deutsch
+ std::string seed_2 = "neubau umarmen Abart umarmen Turban feilen Brett Bargeld Episode Milchkuh Substanz Jahr Armband Maibaum Tand Grünalge Tabak erziehen Federboa Lobrede Tenor Leuchter Curry Diskurs tenor";
+ boost::algorithm::to_lower(seed_2);
+ res = crypto::ElectrumWords::words_to_bytes(seed_2, key_2, language_name_2);
+ ASSERT_EQ(true, res);
+ ASSERT_STREQ(language_name_2.c_str(), "Deutsch");
+ //
+ ASSERT_TRUE(key_1 == key_2);
+}
+
+TEST(mnemonics, partial_word_tolerance)
+{
+ bool res;
+ //
+ crypto::secret_key key_1;
+ std::string language_name_1;
+ const std::string seed_1 = "crim bam scamp gna limi woma wron tuit birth mundane donuts square cohesive dolphin titans narrate fue saved wrap aloof magic mirr toget upda wra";
+ res = crypto::ElectrumWords::words_to_bytes(seed_1, key_1, language_name_1);
+ ASSERT_EQ(true, res);
+ ASSERT_STREQ(language_name_1.c_str(), "English");
+} \ No newline at end of file
diff --git a/tests/unit_tests/net.cpp b/tests/unit_tests/net.cpp
new file mode 100644
index 000000000..a38ecfe81
--- /dev/null
+++ b/tests/unit_tests/net.cpp
@@ -0,0 +1,745 @@
+// Copyright (c) 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.
+
+#include <atomic>
+#include <boost/archive/portable_binary_oarchive.hpp>
+#include <boost/archive/portable_binary_iarchive.hpp>
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/read.hpp>
+#include <boost/asio/write.hpp>
+#include <boost/endian/conversion.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/thread/thread.hpp>
+#include <cstring>
+#include <functional>
+#include <gtest/gtest.h>
+#include <memory>
+
+#include "net/error.h"
+#include "net/net_utils_base.h"
+#include "net/socks.h"
+#include "net/parse.h"
+#include "net/tor_address.h"
+#include "p2p/net_peerlist_boost_serialization.h"
+#include "serialization/keyvalue_serialization.h"
+#include "storages/portable_storage.h"
+
+namespace
+{
+ static constexpr const char v2_onion[] =
+ "xmrto2bturnore26.onion";
+ static constexpr const char v3_onion[] =
+ "vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd.onion";
+}
+
+TEST(tor_address, constants)
+{
+ static_assert(!net::tor_address::is_local(), "bad is_local() response");
+ static_assert(!net::tor_address::is_loopback(), "bad is_loopback() response");
+ static_assert(net::tor_address::get_type_id() == epee::net_utils::address_type::tor, "bad get_type_id() response");
+
+ EXPECT_FALSE(net::tor_address::is_local());
+ EXPECT_FALSE(net::tor_address::is_loopback());
+ EXPECT_EQ(epee::net_utils::address_type::tor, net::tor_address::get_type_id());
+ EXPECT_EQ(epee::net_utils::address_type::tor, net::tor_address::get_type_id());
+}
+
+TEST(tor_address, invalid)
+{
+ EXPECT_TRUE(net::tor_address::make("").has_error());
+ EXPECT_TRUE(net::tor_address::make(":").has_error());
+ EXPECT_TRUE(net::tor_address::make(".onion").has_error());
+ EXPECT_TRUE(net::tor_address::make(".onion:").has_error());
+ EXPECT_TRUE(net::tor_address::make(v2_onion + 1).has_error());
+ EXPECT_TRUE(net::tor_address::make(v3_onion + 1).has_error());
+ EXPECT_TRUE(net::tor_address::make(boost::string_ref{v2_onion, sizeof(v2_onion) - 2}).has_error());
+ EXPECT_TRUE(net::tor_address::make(boost::string_ref{v3_onion, sizeof(v3_onion) - 2}).has_error());
+ EXPECT_TRUE(net::tor_address::make(std::string{v2_onion} + ":-").has_error());
+ EXPECT_TRUE(net::tor_address::make(std::string{v2_onion} + ":900a").has_error());
+ EXPECT_TRUE(net::tor_address::make(std::string{v3_onion} + ":65536").has_error());
+ EXPECT_TRUE(net::tor_address::make(std::string{v3_onion} + ":-1").has_error());
+
+ std::string onion{v3_onion};
+ onion.at(10) = 1;
+ EXPECT_TRUE(net::tor_address::make(onion).has_error());
+}
+
+TEST(tor_address, unblockable_types)
+{
+ net::tor_address tor{};
+
+ ASSERT_NE(nullptr, tor.host_str());
+ EXPECT_STREQ("<unknown tor host>", tor.host_str());
+ EXPECT_STREQ("<unknown tor host>", tor.str().c_str());
+ EXPECT_EQ(0u, tor.port());
+ EXPECT_TRUE(tor.is_unknown());
+ EXPECT_FALSE(tor.is_local());
+ EXPECT_FALSE(tor.is_loopback());
+ EXPECT_EQ(epee::net_utils::address_type::tor, tor.get_type_id());
+ EXPECT_EQ(epee::net_utils::zone::tor, tor.get_zone());
+
+ tor = net::tor_address::unknown();
+ ASSERT_NE(nullptr, tor.host_str());
+ EXPECT_STREQ("<unknown tor host>", tor.host_str());
+ EXPECT_STREQ("<unknown tor host>", tor.str().c_str());
+ EXPECT_EQ(0u, tor.port());
+ EXPECT_TRUE(tor.is_unknown());
+ EXPECT_FALSE(tor.is_local());
+ EXPECT_FALSE(tor.is_loopback());
+ EXPECT_EQ(epee::net_utils::address_type::tor, tor.get_type_id());
+ EXPECT_EQ(epee::net_utils::zone::tor, tor.get_zone());
+
+ EXPECT_EQ(net::tor_address{}, net::tor_address::unknown());
+}
+
+TEST(tor_address, valid)
+{
+ const auto address1 = net::tor_address::make(v3_onion);
+
+ ASSERT_TRUE(address1.has_value());
+ EXPECT_EQ(0u, address1->port());
+ EXPECT_STREQ(v3_onion, address1->host_str());
+ EXPECT_STREQ(v3_onion, address1->str().c_str());
+ EXPECT_TRUE(address1->is_blockable());
+
+ net::tor_address address2{*address1};
+
+ EXPECT_EQ(0u, address2.port());
+ EXPECT_STREQ(v3_onion, address2.host_str());
+ EXPECT_STREQ(v3_onion, address2.str().c_str());
+ EXPECT_TRUE(address2.is_blockable());
+ EXPECT_TRUE(address2.equal(*address1));
+ EXPECT_TRUE(address1->equal(address2));
+ EXPECT_TRUE(address2 == *address1);
+ EXPECT_TRUE(*address1 == address2);
+ EXPECT_FALSE(address2 != *address1);
+ EXPECT_FALSE(*address1 != address2);
+ EXPECT_TRUE(address2.is_same_host(*address1));
+ EXPECT_TRUE(address1->is_same_host(address2));
+ EXPECT_FALSE(address2.less(*address1));
+ EXPECT_FALSE(address1->less(address2));
+
+ address2 = MONERO_UNWRAP(net::tor_address::make(std::string{v2_onion} + ":6545"));
+
+ EXPECT_EQ(6545, address2.port());
+ EXPECT_STREQ(v2_onion, address2.host_str());
+ EXPECT_EQ(std::string{v2_onion} + ":6545", address2.str().c_str());
+ EXPECT_TRUE(address2.is_blockable());
+ EXPECT_FALSE(address2.equal(*address1));
+ EXPECT_FALSE(address1->equal(address2));
+ EXPECT_FALSE(address2 == *address1);
+ EXPECT_FALSE(*address1 == address2);
+ EXPECT_TRUE(address2 != *address1);
+ EXPECT_TRUE(*address1 != address2);
+ EXPECT_FALSE(address2.is_same_host(*address1));
+ EXPECT_FALSE(address1->is_same_host(address2));
+ EXPECT_FALSE(address2.less(*address1));
+ EXPECT_TRUE(address1->less(address2));
+
+ address2 = MONERO_UNWRAP(net::tor_address::make(std::string{v3_onion} + ":", 65535));
+
+ EXPECT_EQ(65535, address2.port());
+ EXPECT_STREQ(v3_onion, address2.host_str());
+ EXPECT_EQ(std::string{v3_onion} + ":65535", address2.str().c_str());
+ EXPECT_TRUE(address2.is_blockable());
+ EXPECT_FALSE(address2.equal(*address1));
+ EXPECT_FALSE(address1->equal(address2));
+ EXPECT_FALSE(address2 == *address1);
+ EXPECT_FALSE(*address1 == address2);
+ EXPECT_TRUE(address2 != *address1);
+ EXPECT_TRUE(*address1 != address2);
+ EXPECT_TRUE(address2.is_same_host(*address1));
+ EXPECT_TRUE(address1->is_same_host(address2));
+ EXPECT_FALSE(address2.less(*address1));
+ EXPECT_TRUE(address1->less(address2));
+}
+
+TEST(tor_address, generic_network_address)
+{
+ const epee::net_utils::network_address tor1{MONERO_UNWRAP(net::tor_address::make(v3_onion, 8080))};
+ const epee::net_utils::network_address tor2{MONERO_UNWRAP(net::tor_address::make(v3_onion, 8080))};
+ const epee::net_utils::network_address ip{epee::net_utils::ipv4_network_address{100, 200}};
+
+ EXPECT_EQ(tor1, tor2);
+ EXPECT_NE(ip, tor1);
+ EXPECT_LT(ip, tor1);
+
+ EXPECT_STREQ(v3_onion, tor1.host_str().c_str());
+ EXPECT_EQ(std::string{v3_onion} + ":8080", tor1.str());
+ EXPECT_EQ(epee::net_utils::address_type::tor, tor1.get_type_id());
+ EXPECT_EQ(epee::net_utils::address_type::tor, tor2.get_type_id());
+ EXPECT_EQ(epee::net_utils::address_type::ipv4, ip.get_type_id());
+ EXPECT_EQ(epee::net_utils::zone::tor, tor1.get_zone());
+ EXPECT_EQ(epee::net_utils::zone::tor, tor2.get_zone());
+ EXPECT_EQ(epee::net_utils::zone::public_, ip.get_zone());
+ EXPECT_TRUE(tor1.is_blockable());
+ EXPECT_TRUE(tor2.is_blockable());
+ EXPECT_TRUE(ip.is_blockable());
+}
+
+namespace
+{
+ struct test_command
+ {
+ net::tor_address tor;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(tor);
+ END_KV_SERIALIZE_MAP()
+ };
+}
+
+TEST(tor_address, epee_serializev_v2)
+{
+ std::string buffer{};
+ {
+ test_command command{MONERO_UNWRAP(net::tor_address::make(v2_onion, 10))};
+ EXPECT_FALSE(command.tor.is_unknown());
+ EXPECT_NE(net::tor_address{}, command.tor);
+ EXPECT_STREQ(v2_onion, command.tor.host_str());
+ EXPECT_EQ(10u, command.tor.port());
+
+ epee::serialization::portable_storage stg{};
+ EXPECT_TRUE(command.store(stg));
+ EXPECT_TRUE(stg.store_to_binary(buffer));
+ }
+
+ test_command command{};
+ {
+ EXPECT_TRUE(command.tor.is_unknown());
+ EXPECT_EQ(net::tor_address{}, command.tor);
+ EXPECT_STREQ(net::tor_address::unknown_str(), command.tor.host_str());
+ EXPECT_EQ(0u, command.tor.port());
+
+ epee::serialization::portable_storage stg{};
+ EXPECT_TRUE(stg.load_from_binary(buffer));
+ EXPECT_TRUE(command.load(stg));
+ }
+ EXPECT_FALSE(command.tor.is_unknown());
+ EXPECT_NE(net::tor_address{}, command.tor);
+ EXPECT_STREQ(v2_onion, command.tor.host_str());
+ EXPECT_EQ(10u, command.tor.port());
+
+ // make sure that exceeding max buffer doesn't destroy tor_address::_load
+ {
+ epee::serialization::portable_storage stg{};
+ stg.load_from_binary(buffer);
+
+ std::string host{};
+ ASSERT_TRUE(stg.get_value("host", host, stg.open_section("tor", nullptr, false)));
+ EXPECT_EQ(std::strlen(v2_onion), host.size());
+
+ host.push_back('k');
+ EXPECT_TRUE(stg.set_value("host", host, stg.open_section("tor", nullptr, false)));
+ EXPECT_TRUE(command.load(stg)); // poor error reporting from `KV_SERIALIZE`
+ }
+
+ EXPECT_TRUE(command.tor.is_unknown());
+ EXPECT_EQ(net::tor_address{}, command.tor);
+ EXPECT_STREQ(net::tor_address::unknown_str(), command.tor.host_str());
+ EXPECT_EQ(0u, command.tor.port());
+}
+
+TEST(tor_address, epee_serializev_v3)
+{
+ std::string buffer{};
+ {
+ test_command command{MONERO_UNWRAP(net::tor_address::make(v3_onion, 10))};
+ EXPECT_FALSE(command.tor.is_unknown());
+ EXPECT_NE(net::tor_address{}, command.tor);
+ EXPECT_STREQ(v3_onion, command.tor.host_str());
+ EXPECT_EQ(10u, command.tor.port());
+
+ epee::serialization::portable_storage stg{};
+ EXPECT_TRUE(command.store(stg));
+ EXPECT_TRUE(stg.store_to_binary(buffer));
+ }
+
+ test_command command{};
+ {
+ EXPECT_TRUE(command.tor.is_unknown());
+ EXPECT_EQ(net::tor_address{}, command.tor);
+ EXPECT_STREQ(net::tor_address::unknown_str(), command.tor.host_str());
+ EXPECT_EQ(0u, command.tor.port());
+
+ epee::serialization::portable_storage stg{};
+ EXPECT_TRUE(stg.load_from_binary(buffer));
+ EXPECT_TRUE(command.load(stg));
+ }
+ EXPECT_FALSE(command.tor.is_unknown());
+ EXPECT_NE(net::tor_address{}, command.tor);
+ EXPECT_STREQ(v3_onion, command.tor.host_str());
+ EXPECT_EQ(10u, command.tor.port());
+
+ // make sure that exceeding max buffer doesn't destroy tor_address::_load
+ {
+ epee::serialization::portable_storage stg{};
+ stg.load_from_binary(buffer);
+
+ std::string host{};
+ ASSERT_TRUE(stg.get_value("host", host, stg.open_section("tor", nullptr, false)));
+ EXPECT_EQ(std::strlen(v3_onion), host.size());
+
+ host.push_back('k');
+ EXPECT_TRUE(stg.set_value("host", host, stg.open_section("tor", nullptr, false)));
+ EXPECT_TRUE(command.load(stg)); // poor error reporting from `KV_SERIALIZE`
+ }
+
+ EXPECT_TRUE(command.tor.is_unknown());
+ EXPECT_EQ(net::tor_address{}, command.tor);
+ EXPECT_STRNE(v3_onion, command.tor.host_str());
+ EXPECT_EQ(0u, command.tor.port());
+}
+
+TEST(tor_address, epee_serialize_unknown)
+{
+ std::string buffer{};
+ {
+ test_command command{net::tor_address::unknown()};
+ EXPECT_TRUE(command.tor.is_unknown());
+ EXPECT_EQ(net::tor_address{}, command.tor);
+ EXPECT_STREQ(net::tor_address::unknown_str(), command.tor.host_str());
+ EXPECT_EQ(0u, command.tor.port());
+
+ epee::serialization::portable_storage stg{};
+ EXPECT_TRUE(command.store(stg));
+ EXPECT_TRUE(stg.store_to_binary(buffer));
+ }
+
+ test_command command{};
+ {
+ EXPECT_TRUE(command.tor.is_unknown());
+ EXPECT_EQ(net::tor_address{}, command.tor);
+ EXPECT_STRNE(v3_onion, command.tor.host_str());
+ EXPECT_EQ(0u, command.tor.port());
+
+ epee::serialization::portable_storage stg{};
+ EXPECT_TRUE(stg.load_from_binary(buffer));
+ EXPECT_TRUE(command.load(stg));
+ }
+ EXPECT_TRUE(command.tor.is_unknown());
+ EXPECT_EQ(net::tor_address{}, command.tor);
+ EXPECT_STREQ(net::tor_address::unknown_str(), command.tor.host_str());
+ EXPECT_EQ(0u, command.tor.port());
+
+ // make sure that exceeding max buffer doesn't destroy tor_address::_load
+ {
+ epee::serialization::portable_storage stg{};
+ stg.load_from_binary(buffer);
+
+ std::string host{};
+ ASSERT_TRUE(stg.get_value("host", host, stg.open_section("tor", nullptr, false)));
+ EXPECT_EQ(std::strlen(net::tor_address::unknown_str()), host.size());
+
+ host.push_back('k');
+ EXPECT_TRUE(stg.set_value("host", host, stg.open_section("tor", nullptr, false)));
+ EXPECT_TRUE(command.load(stg)); // poor error reporting from `KV_SERIALIZE`
+ }
+
+ EXPECT_TRUE(command.tor.is_unknown());
+ EXPECT_EQ(net::tor_address{}, command.tor);
+ EXPECT_STRNE(v3_onion, command.tor.host_str());
+ EXPECT_EQ(0u, command.tor.port());
+}
+
+TEST(tor_address, boost_serialize_v2)
+{
+ std::string buffer{};
+ {
+ const net::tor_address tor = MONERO_UNWRAP(net::tor_address::make(v2_onion, 10));
+ EXPECT_FALSE(tor.is_unknown());
+ EXPECT_NE(net::tor_address{}, tor);
+ EXPECT_STREQ(v2_onion, tor.host_str());
+ EXPECT_EQ(10u, tor.port());
+
+ std::ostringstream stream{};
+ {
+ boost::archive::portable_binary_oarchive archive{stream};
+ archive << tor;
+ }
+ buffer = stream.str();
+ }
+
+ net::tor_address tor{};
+ {
+ EXPECT_TRUE(tor.is_unknown());
+ EXPECT_EQ(net::tor_address{}, tor);
+ EXPECT_STREQ(net::tor_address::unknown_str(), tor.host_str());
+ EXPECT_EQ(0u, tor.port());
+
+ std::istringstream stream{buffer};
+ boost::archive::portable_binary_iarchive archive{stream};
+ archive >> tor;
+ }
+ EXPECT_FALSE(tor.is_unknown());
+ EXPECT_NE(net::tor_address{}, tor);
+ EXPECT_STREQ(v2_onion, tor.host_str());
+ EXPECT_EQ(10u, tor.port());
+}
+
+TEST(tor_address, boost_serialize_v3)
+{
+ std::string buffer{};
+ {
+ const net::tor_address tor = MONERO_UNWRAP(net::tor_address::make(v3_onion, 10));
+ EXPECT_FALSE(tor.is_unknown());
+ EXPECT_NE(net::tor_address{}, tor);
+ EXPECT_STREQ(v3_onion, tor.host_str());
+ EXPECT_EQ(10u, tor.port());
+
+ std::ostringstream stream{};
+ {
+ boost::archive::portable_binary_oarchive archive{stream};
+ archive << tor;
+ }
+ buffer = stream.str();
+ }
+
+ net::tor_address tor{};
+ {
+ EXPECT_TRUE(tor.is_unknown());
+ EXPECT_EQ(net::tor_address{}, tor);
+ EXPECT_STREQ(net::tor_address::unknown_str(), tor.host_str());
+ EXPECT_EQ(0u, tor.port());
+
+ std::istringstream stream{buffer};
+ boost::archive::portable_binary_iarchive archive{stream};
+ archive >> tor;
+ }
+ EXPECT_FALSE(tor.is_unknown());
+ EXPECT_NE(net::tor_address{}, tor);
+ EXPECT_STREQ(v3_onion, tor.host_str());
+ EXPECT_EQ(10u, tor.port());
+}
+
+TEST(tor_address, boost_serialize_unknown)
+{
+ std::string buffer{};
+ {
+ const net::tor_address tor{};
+ EXPECT_TRUE(tor.is_unknown());
+ EXPECT_EQ(net::tor_address::unknown(), tor);
+ EXPECT_STREQ(net::tor_address::unknown_str(), tor.host_str());
+ EXPECT_EQ(0u, tor.port());
+
+ std::ostringstream stream{};
+ {
+ boost::archive::portable_binary_oarchive archive{stream};
+ archive << tor;
+ }
+ buffer = stream.str();
+ }
+
+ net::tor_address tor{};
+ {
+ EXPECT_TRUE(tor.is_unknown());
+ EXPECT_EQ(net::tor_address{}, tor);
+ EXPECT_STREQ(net::tor_address::unknown_str(), tor.host_str());
+ EXPECT_EQ(0u, tor.port());
+
+ std::istringstream stream{buffer};
+ boost::archive::portable_binary_iarchive archive{stream};
+ archive >> tor;
+ }
+ EXPECT_TRUE(tor.is_unknown());
+ EXPECT_EQ(net::tor_address::unknown(), tor);
+ EXPECT_STREQ(net::tor_address::unknown_str(), tor.host_str());
+ EXPECT_EQ(0u, tor.port());
+}
+
+TEST(get_network_address, onion)
+{
+ expect<epee::net_utils::network_address> address =
+ net::get_network_address("onion", 0);
+ EXPECT_EQ(net::error::unsupported_address, address);
+
+ address = net::get_network_address(".onion", 0);
+ EXPECT_EQ(net::error::invalid_tor_address, address);
+
+ address = net::get_network_address(v3_onion, 1000);
+ ASSERT_TRUE(bool(address));
+ EXPECT_EQ(epee::net_utils::address_type::tor, address->get_type_id());
+ EXPECT_STREQ(v3_onion, address->host_str().c_str());
+ EXPECT_EQ(std::string{v3_onion} + ":1000", address->str());
+
+ address = net::get_network_address(std::string{v3_onion} + ":2000", 1000);
+ ASSERT_TRUE(bool(address));
+ EXPECT_EQ(epee::net_utils::address_type::tor, address->get_type_id());
+ EXPECT_STREQ(v3_onion, address->host_str().c_str());
+ EXPECT_EQ(std::string{v3_onion} + ":2000", address->str());
+
+ address = net::get_network_address(std::string{v3_onion} + ":65536", 1000);
+ EXPECT_EQ(net::error::invalid_port, address);
+}
+
+
+TEST(get_network_address, ipv4)
+{
+ expect<epee::net_utils::network_address> address =
+ net::get_network_address("0.0.0.", 0);
+ EXPECT_EQ(net::error::unsupported_address, address);
+
+ address = net::get_network_address("0.0.0.257", 0);
+ EXPECT_EQ(net::error::unsupported_address, address);
+
+ address = net::get_network_address("0.0.0.254", 1000);
+ ASSERT_TRUE(bool(address));
+ EXPECT_EQ(epee::net_utils::address_type::ipv4, address->get_type_id());
+ EXPECT_STREQ("0.0.0.254", address->host_str().c_str());
+ EXPECT_STREQ("0.0.0.254:1000", address->str().c_str());
+
+ address = net::get_network_address("23.0.0.254:2000", 1000);
+ ASSERT_TRUE(bool(address));
+ EXPECT_EQ(epee::net_utils::address_type::ipv4, address->get_type_id());
+ EXPECT_STREQ("23.0.0.254", address->host_str().c_str());
+ EXPECT_STREQ("23.0.0.254:2000", address->str().c_str());
+}
+
+namespace
+{
+ using stream_type = boost::asio::ip::tcp;
+
+ struct io_thread
+ {
+ boost::asio::io_service io_service;
+ boost::asio::io_service::work work;
+ stream_type::socket server;
+ stream_type::acceptor acceptor;
+ boost::thread io;
+ std::atomic<bool> connected;
+
+ io_thread()
+ : io_service(),
+ work(io_service),
+ server(io_service),
+ acceptor(io_service),
+ io([this] () { try { this->io_service.run(); } catch (const std::exception& e) { MERROR(e.what()); }}),
+ connected(false)
+ {
+ acceptor.open(boost::asio::ip::tcp::v4());
+ acceptor.bind(stream_type::endpoint{boost::asio::ip::tcp::v4(), 0});
+ acceptor.listen();
+ acceptor.async_accept(server, [this] (boost::system::error_code error) {
+ this->connected = true;
+ if (error)
+ throw boost::system::system_error{error};
+ });
+ }
+
+ ~io_thread() noexcept
+ {
+ io_service.stop();
+ if (io.joinable())
+ io.join();
+ }
+ };
+
+ struct checked_client
+ {
+ std::atomic<bool>* called_;
+ bool expected_;
+
+ void operator()(boost::system::error_code error, net::socks::client::stream_type::socket&&) const
+ {
+ EXPECT_EQ(expected_, bool(error)) << "Socks server: " << error.message();
+ ASSERT_TRUE(called_ != nullptr);
+ (*called_) = true;
+ }
+ };
+}
+
+TEST(socks_client, unsupported_command)
+{
+ boost::asio::io_service io_service{};
+ stream_type::socket client{io_service};
+
+ auto test_client = net::socks::make_connect_client(
+ std::move(client), net::socks::version::v4, std::bind( [] {} )
+ );
+ ASSERT_TRUE(bool(test_client));
+ EXPECT_TRUE(test_client->buffer().empty());
+
+ EXPECT_FALSE(test_client->set_connect_command("example.com", 8080));
+ EXPECT_TRUE(test_client->buffer().empty());
+
+ EXPECT_FALSE(test_client->set_resolve_command("example.com"));
+ EXPECT_TRUE(test_client->buffer().empty());
+}
+
+TEST(socks_client, no_command)
+{
+ boost::asio::io_service io_service{};
+ stream_type::socket client{io_service};
+
+ auto test_client = net::socks::make_connect_client(
+ std::move(client), net::socks::version::v4a, std::bind( [] {} )
+ );
+ ASSERT_TRUE(bool(test_client));
+ EXPECT_FALSE(net::socks::client::send(std::move(test_client)));
+}
+
+TEST(socks_client, connect_command)
+{
+ io_thread io{};
+ stream_type::socket client{io.io_service};
+
+ std::atomic<bool> called{false};
+ auto test_client = net::socks::make_connect_client(
+ std::move(client), net::socks::version::v4a, checked_client{std::addressof(called), false}
+ );
+ ASSERT_TRUE(bool(test_client));
+
+ ASSERT_TRUE(test_client->set_connect_command("example.com", 8080));
+ EXPECT_FALSE(test_client->buffer().empty());
+ ASSERT_TRUE(net::socks::client::connect_and_send(std::move(test_client), io.acceptor.local_endpoint()));
+ while (!io.connected);
+
+ const std::uint8_t expected_bytes[] = {
+ 4, 1, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', 0x00
+ };
+
+ std::uint8_t actual_bytes[sizeof(expected_bytes)];
+ boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
+ EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
+
+ const std::uint8_t reply_bytes[] = {0, 90, 0, 0, 0, 0, 0, 0};
+ boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
+
+ // yikes!
+ while (!called);
+}
+
+TEST(socks_client, connect_command_failed)
+{
+ io_thread io{};
+ stream_type::socket client{io.io_service};
+
+ std::atomic<bool> called{false};
+ auto test_client = net::socks::make_connect_client(
+ std::move(client), net::socks::version::v4, checked_client{std::addressof(called), true}
+ );
+ ASSERT_TRUE(bool(test_client));
+
+ ASSERT_TRUE(
+ test_client->set_connect_command(
+ epee::net_utils::ipv4_network_address{boost::endian::native_to_big(std::uint32_t(5000)), 3000}
+ )
+ );
+ EXPECT_FALSE(test_client->buffer().empty());
+ ASSERT_TRUE(net::socks::client::connect_and_send(std::move(test_client), io.acceptor.local_endpoint()));
+ while (!io.connected);
+
+ const std::uint8_t expected_bytes[] = {
+ 4, 1, 0x0b, 0xb8, 0x00, 0x00, 0x13, 0x88, 0x00
+ };
+
+ std::uint8_t actual_bytes[sizeof(expected_bytes)];
+ boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
+ EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
+
+ const std::uint8_t reply_bytes[] = {0, 91, 0, 0, 0, 0, 0, 0};
+ boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
+
+ // yikes!
+ while (!called);
+}
+
+TEST(socks_client, resolve_command)
+{
+ static std::uint8_t reply_bytes[] = {0, 90, 0, 0, 0xff, 0, 0xad, 0};
+
+ struct resolve_client : net::socks::client
+ {
+ std::atomic<unsigned> called_;
+ bool expected_;
+
+ resolve_client(stream_type::socket&& proxy)
+ : net::socks::client(std::move(proxy), net::socks::version::v4a_tor)
+ , called_(0)
+ , expected_(false)
+ {};
+
+ virtual void done(boost::system::error_code error, std::shared_ptr<client> self) override
+ {
+ EXPECT_EQ(this, self.get());
+ EXPECT_EQ(expected_, bool(error)) << "Resolve failure: " << error.message();
+
+ if (!error)
+ {
+ ASSERT_EQ(sizeof(reply_bytes), buffer().size());
+ EXPECT_EQ(0u, std::memcmp(buffer().data(), reply_bytes, sizeof(reply_bytes)));
+ }
+
+ ++called_;
+ }
+ };
+
+ io_thread io{};
+ stream_type::socket client{io.io_service};
+
+ auto test_client = std::make_shared<resolve_client>(std::move(client));
+ ASSERT_TRUE(bool(test_client));
+
+ ASSERT_TRUE(test_client->set_resolve_command("example.com"));
+ EXPECT_FALSE(test_client->buffer().empty());
+ ASSERT_TRUE(net::socks::client::connect_and_send(test_client, io.acceptor.local_endpoint()));
+ while (!io.connected);
+
+ const std::uint8_t expected_bytes[] = {
+ 4, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', 0x00
+ };
+
+ std::uint8_t actual_bytes[sizeof(expected_bytes)];
+ boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
+ EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
+
+ boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
+
+ // yikes!
+ while (test_client->called_ == 0);
+
+ test_client->expected_ = true;
+ ASSERT_TRUE(test_client->set_resolve_command("example.com"));
+ EXPECT_FALSE(test_client->buffer().empty());
+ ASSERT_TRUE(net::socks::client::send(test_client));
+
+ boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
+ EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
+
+ reply_bytes[1] = 91;
+ boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
+
+ // yikes!
+ while (test_client->called_ == 1);
+}
+
+
diff --git a/tests/unit_tests/notify.cpp b/tests/unit_tests/notify.cpp
index cd70b7739..ceeba8649 100644
--- a/tests/unit_tests/notify.cpp
+++ b/tests/unit_tests/notify.cpp
@@ -67,7 +67,7 @@ TEST(notify, works)
+ " " + name_template + " %s";
tools::Notify notify(spec.c_str());
- notify.notify("1111111111111111111111111111111111111111111111111111111111111111");
+ notify.notify("%s", "1111111111111111111111111111111111111111111111111111111111111111", NULL);
bool ok = false;
for (int i = 0; i < 10; ++i)
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; }
diff --git a/tests/unit_tests/pruning.cpp b/tests/unit_tests/pruning.cpp
new file mode 100644
index 000000000..83c35df68
--- /dev/null
+++ b/tests/unit_tests/pruning.cpp
@@ -0,0 +1,240 @@
+// Copyright (c) 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.
+
+#include "gtest/gtest.h"
+
+#include "misc_log_ex.h"
+#include "cryptonote_config.h"
+#include "common/pruning.h"
+
+#define ASSERT_EX(x) do { bool ex = false; try { x; } catch(...) { ex = true; } ASSERT_TRUE(ex); } while(0)
+
+TEST(pruning, parts)
+{
+ ASSERT_EQ(tools::get_pruning_stripe(tools::make_pruning_seed(3, 2)), 3);
+ ASSERT_EQ(tools::get_pruning_stripe(tools::make_pruning_seed(1, 2)), 1);
+ ASSERT_EQ(tools::get_pruning_stripe(tools::make_pruning_seed(7, 7)), 7);
+
+ ASSERT_EQ(tools::get_pruning_log_stripes(tools::make_pruning_seed(1, 2)), 2);
+ ASSERT_EQ(tools::get_pruning_log_stripes(tools::make_pruning_seed(1, 0)), 0);
+ ASSERT_EQ(tools::get_pruning_log_stripes(tools::make_pruning_seed(1, 7)), 7);
+ ASSERT_EQ(tools::get_pruning_log_stripes(tools::make_pruning_seed(7, 7)), 7);
+
+ for (uint32_t log_stripes = 1; log_stripes <= tools::PRUNING_SEED_LOG_STRIPES_MASK; ++log_stripes)
+ {
+ for (uint32_t stripe = 1; stripe <= (1 << log_stripes); ++stripe)
+ {
+ ASSERT_EQ(tools::get_pruning_log_stripes(tools::make_pruning_seed(stripe, log_stripes)), log_stripes);
+ ASSERT_EQ(tools::get_pruning_stripe(tools::make_pruning_seed(stripe, log_stripes)), stripe);
+ }
+ }
+}
+
+TEST(pruning, out_of_range)
+{
+ ASSERT_EX(tools::make_pruning_seed(5, 2));
+ ASSERT_EX(tools::make_pruning_seed(0, 2));
+}
+
+TEST(pruning, fits)
+{
+ const uint32_t log_stripes = 3;
+ const uint32_t num_stripes = 1 << log_stripes;
+ for (uint32_t stripe = 1; stripe <= num_stripes; ++stripe)
+ {
+ const uint32_t seed = tools::make_pruning_seed(stripe, log_stripes);
+ ASSERT_NE(seed, 0);
+ ASSERT_EQ(tools::get_pruning_log_stripes(seed), log_stripes);
+ ASSERT_EQ(tools::get_pruning_stripe(seed), stripe);
+ }
+}
+
+TEST(pruning, tip)
+{
+ static constexpr uint64_t H = CRYPTONOTE_PRUNING_TIP_BLOCKS + 1000;
+ static_assert(H >= CRYPTONOTE_PRUNING_TIP_BLOCKS, "H must be >= CRYPTONOTE_PRUNING_TIP_BLOCKS");
+ for (uint64_t h = H - CRYPTONOTE_PRUNING_TIP_BLOCKS; h < H; ++h)
+ {
+ uint32_t pruning_seed = tools::get_pruning_seed(h, H, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ ASSERT_EQ(pruning_seed, 0);
+ for (pruning_seed = 0; pruning_seed <= (1 << CRYPTONOTE_PRUNING_LOG_STRIPES); ++pruning_seed)
+ ASSERT_TRUE(tools::has_unpruned_block(h, H, pruning_seed));
+ }
+}
+
+TEST(pruning, seed)
+{
+ const uint64_t SS = CRYPTONOTE_PRUNING_STRIPE_SIZE;
+ const uint64_t NS = 1 << CRYPTONOTE_PRUNING_LOG_STRIPES;
+ const uint64_t TB = NS * SS;
+
+ for (uint64_t cycle = 0; cycle < 10; ++cycle)
+ {
+ const uint64_t O = TB * cycle;
+ ASSERT_EQ(tools::get_pruning_stripe(O + 0, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 1);
+ ASSERT_EQ(tools::get_pruning_stripe(O + 1, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 1);
+ ASSERT_EQ(tools::get_pruning_stripe(O + SS-1, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 1);
+ ASSERT_EQ(tools::get_pruning_stripe(O + SS, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 2);
+ ASSERT_EQ(tools::get_pruning_stripe(O + SS*2-1, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 2);
+ ASSERT_EQ(tools::get_pruning_stripe(O + SS*2, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 3);
+ ASSERT_EQ(tools::get_pruning_stripe(O + SS*NS-1, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), NS);
+ ASSERT_EQ(tools::get_pruning_stripe(O + SS*NS, 10000000, CRYPTONOTE_PRUNING_LOG_STRIPES), 1);
+ }
+}
+
+TEST(pruning, match)
+{
+ static constexpr uint64_t H = CRYPTONOTE_PRUNING_TIP_BLOCKS + 1000;
+ static_assert(H >= CRYPTONOTE_PRUNING_TIP_BLOCKS, "H must be >= CRYPTONOTE_PRUNING_TIP_BLOCKS");
+ for (uint64_t h = 0; h < H - CRYPTONOTE_PRUNING_TIP_BLOCKS; ++h)
+ {
+ uint32_t pruning_seed = tools::get_pruning_seed(h, H, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ uint32_t pruning_stripe = tools::get_pruning_stripe(pruning_seed);
+ ASSERT_TRUE(pruning_stripe > 0 && pruning_stripe <= (1 << CRYPTONOTE_PRUNING_LOG_STRIPES));
+ for (uint32_t other_pruning_stripe = 1; other_pruning_stripe <= (1 << CRYPTONOTE_PRUNING_LOG_STRIPES); ++other_pruning_stripe)
+ {
+ uint32_t other_pruning_seed = tools::make_pruning_seed(other_pruning_stripe, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ ASSERT_TRUE(tools::has_unpruned_block(h, H, other_pruning_seed) == (other_pruning_seed == pruning_seed));
+ }
+ }
+}
+
+TEST(pruning, stripe_size)
+{
+ static constexpr uint64_t H = CRYPTONOTE_PRUNING_TIP_BLOCKS + CRYPTONOTE_PRUNING_STRIPE_SIZE * (1 << CRYPTONOTE_PRUNING_LOG_STRIPES) + 1000;
+ static_assert(H >= CRYPTONOTE_PRUNING_TIP_BLOCKS + CRYPTONOTE_PRUNING_STRIPE_SIZE * (1 << CRYPTONOTE_PRUNING_LOG_STRIPES), "H must be >= that stuff in front");
+ for (uint32_t pruning_stripe = 1; pruning_stripe <= (1 << CRYPTONOTE_PRUNING_LOG_STRIPES); ++pruning_stripe)
+ {
+ uint32_t pruning_seed = tools::make_pruning_seed(pruning_stripe, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ unsigned int current_run = 0, best_run = 0;
+ for (uint64_t h = 0; h < H - CRYPTONOTE_PRUNING_TIP_BLOCKS; ++h)
+ {
+ if (tools::has_unpruned_block(h, H, pruning_seed))
+ {
+ ++current_run;
+ }
+ else if (current_run)
+ {
+ ASSERT_EQ(current_run, CRYPTONOTE_PRUNING_STRIPE_SIZE);
+ best_run = std::max(best_run, current_run);
+ current_run = 0;
+ }
+ }
+ ASSERT_EQ(best_run, CRYPTONOTE_PRUNING_STRIPE_SIZE);
+ }
+}
+
+TEST(pruning, next_unpruned)
+{
+ static_assert((1 << CRYPTONOTE_PRUNING_LOG_STRIPES) >= 4, "CRYPTONOTE_PRUNING_LOG_STRIPES too low");
+
+ const uint64_t SS = CRYPTONOTE_PRUNING_STRIPE_SIZE;
+ const uint64_t NS = 1 << CRYPTONOTE_PRUNING_LOG_STRIPES;
+ const uint64_t TB = NS * SS;
+
+ for (uint64_t h = 0; h < 100; ++h)
+ ASSERT_EQ(tools::get_next_unpruned_block_height(h, 10000000, 0), h);
+
+ const uint32_t seed1 = tools::make_pruning_seed(1, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seed2 = tools::make_pruning_seed(2, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seed3 = tools::make_pruning_seed(3, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seed4 = tools::make_pruning_seed(4, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seedNS = tools::make_pruning_seed(NS, CRYPTONOTE_PRUNING_LOG_STRIPES);
+
+ ASSERT_EQ(tools::get_next_unpruned_block_height(0, 10000000, seed1), 0);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(1, 10000000, seed1), 1);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS-1, 10000000, seed1), SS-1);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS, 10000000, seed1), TB);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(TB, 10000000, seed1), TB);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(TB-1, 10000000, seed1), TB);
+
+ ASSERT_EQ(tools::get_next_unpruned_block_height(0, 10000000, seed2), SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(1, 10000000, seed2), SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS-1, 10000000, seed2), SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS, 10000000, seed2), SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(2*SS-1, 10000000, seed2), 2*SS-1);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(2*SS, 10000000, seed2), TB+SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(TB+2*SS,10000000, seed2), TB*2+SS);
+
+ ASSERT_EQ(tools::get_next_unpruned_block_height(0, 10000000, seed3), SS*2);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS, 10000000, seed3), SS*2);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(2*SS, 10000000, seed3), SS*2);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(3*SS-1, 10000000, seed3), SS*3-1);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(3*SS, 10000000, seed3), TB+SS*2);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(TB+3*SS,10000000, seed3), TB*2+SS*2);
+
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS, 10000000, seed4), 3*SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(4*SS-1, 10000000, seed4), 4*SS-1);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(4*SS, 10000000, seed4), TB+3*SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(TB+4*SS,10000000, seed4), TB*2+3*SS);
+
+ ASSERT_EQ(tools::get_next_unpruned_block_height(SS, 10000000, seedNS), (NS-1)*SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(NS*SS-1,10000000, seedNS), NS*SS-1);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(NS*SS, 10000000, seedNS), TB+(NS-1)*SS);
+ ASSERT_EQ(tools::get_next_unpruned_block_height(TB+NS*SS, 10000000, seedNS), TB*2+(NS-1)*SS);
+}
+
+TEST(pruning, next_pruned)
+{
+ static_assert((1 << CRYPTONOTE_PRUNING_LOG_STRIPES) >= 4, "CRYPTONOTE_PRUNING_LOG_STRIPES too low");
+
+ const uint64_t SS = CRYPTONOTE_PRUNING_STRIPE_SIZE;
+ const uint64_t NS = 1 << CRYPTONOTE_PRUNING_LOG_STRIPES;
+ const uint64_t TB = NS * SS;
+
+ const uint32_t seed1 = tools::make_pruning_seed(1, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seed2 = tools::make_pruning_seed(2, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seedNS_1 = tools::make_pruning_seed(NS-1, CRYPTONOTE_PRUNING_LOG_STRIPES);
+ const uint32_t seedNS = tools::make_pruning_seed(NS, CRYPTONOTE_PRUNING_LOG_STRIPES);
+
+ for (uint64_t h = 0; h < 100; ++h)
+ ASSERT_EQ(tools::get_next_pruned_block_height(h, 10000000, 0), 10000000);
+ for (uint64_t h = 10000000 - 1 - CRYPTONOTE_PRUNING_TIP_BLOCKS; h < 10000000; ++h)
+ ASSERT_EQ(tools::get_next_pruned_block_height(h, 10000000, 0), 10000000);
+
+ ASSERT_EQ(tools::get_next_pruned_block_height(1, 10000000, seed1), SS);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS-1, 10000000, seed1), SS);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS, 10000000, seed1), SS);
+ ASSERT_EQ(tools::get_next_pruned_block_height(TB-1, 10000000, seed1), TB-1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(TB, 10000000, seed1), TB+SS);
+
+ ASSERT_EQ(tools::get_next_pruned_block_height(1, 10000000, seed2), 1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS-1, 10000000, seed2), SS-1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS, 10000000, seed2), 2*SS);
+ ASSERT_EQ(tools::get_next_pruned_block_height(TB-1, 10000000, seed2), TB-1);
+
+ ASSERT_EQ(tools::get_next_pruned_block_height(1, 10000000, seedNS_1), 1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS-1, 10000000, seedNS_1), SS-1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS, 10000000, seedNS_1), SS);
+ ASSERT_EQ(tools::get_next_pruned_block_height(TB-1, 10000000, seedNS_1), TB-1);
+
+ ASSERT_EQ(tools::get_next_pruned_block_height(1, 10000000, seedNS), 1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS-1, 10000000, seedNS), SS-1);
+ ASSERT_EQ(tools::get_next_pruned_block_height(SS, 10000000, seedNS), SS);
+ ASSERT_EQ(tools::get_next_pruned_block_height(TB-1, 10000000, seedNS), TB);
+}
diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp
index ccef5f3e7..3f302cb83 100644
--- a/tests/unit_tests/ringct.cpp
+++ b/tests/unit_tests/ringct.cpp
@@ -171,8 +171,10 @@ TEST(ringct, range_proofs)
skpkGen(Sk, Pk);
destinations.push_back(Pk);
+ const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
+
//compute rct data with mixin 500
- rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, hw::get_device("default"));
+ rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default"));
//verify rct data
ASSERT_TRUE(verRct(s));
@@ -189,7 +191,7 @@ TEST(ringct, range_proofs)
//compute rct data with mixin 500
- s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, hw::get_device("default"));
+ s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default"));
//verify rct data
ASSERT_FALSE(verRct(s));
@@ -235,8 +237,10 @@ TEST(ringct, range_proofs_with_fee)
skpkGen(Sk, Pk);
destinations.push_back(Pk);
+ const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
+
//compute rct data with mixin 500
- rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, hw::get_device("default"));
+ rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default"));
//verify rct data
ASSERT_TRUE(verRct(s));
@@ -253,7 +257,7 @@ TEST(ringct, range_proofs_with_fee)
//compute rct data with mixin 500
- s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, hw::get_device("default"));
+ s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default"));
//verify rct data
ASSERT_FALSE(verRct(s));
@@ -311,7 +315,8 @@ TEST(ringct, simple)
//compute sig with mixin 2
xmr_amount txnfee = 1;
- rctSig s = genRctSimple(message, sc, pc, destinations,inamounts, outamounts, amount_keys, NULL, NULL, txnfee, 2, hw::get_device("default"));
+ const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
+ rctSig s = genRctSimple(message, sc, pc, destinations,inamounts, outamounts, amount_keys, NULL, NULL, txnfee, 2, rct_config, hw::get_device("default"));
//verify ring ct signature
ASSERT_TRUE(verRctSimple(s));
@@ -345,7 +350,8 @@ static rct::rctSig make_sample_rct_sig(int n_inputs, const uint64_t input_amount
}
}
- return genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, hw::get_device("default"));
+ const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
+ return genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default"));
}
static rct::rctSig make_sample_simple_rct_sig(int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[], uint64_t fee)
@@ -371,7 +377,8 @@ static rct::rctSig make_sample_simple_rct_sig(int n_inputs, const uint64_t input
destinations.push_back(Pk);
}
- return genRctSimple(rct::zero(), sc, pc, destinations, inamounts, outamounts, amount_keys, NULL, NULL, fee, 3, hw::get_device("default"));
+ const rct::RCTConfig rct_config { RangeProofBorromean, 0 };
+ return genRctSimple(rct::zero(), sc, pc, destinations, inamounts, outamounts, amount_keys, NULL, NULL, fee, 3, rct_config, hw::get_device("default"));
}
static bool range_proof_test(bool expected_valid,
@@ -824,27 +831,6 @@ TEST(ringct, HPow2)
static const xmr_amount test_amounts[]={0, 1, 2, 3, 4, 5, 10000, 10000000000000000000ull, 10203040506070809000ull, 123456789123456789};
-TEST(ringct, ecdh_roundtrip)
-{
- key k;
- ecdhTuple t0, t1;
-
- for (auto amount: test_amounts) {
- skGen(k);
-
- t0.mask = skGen();
- t0.amount = d2h(amount);
-
- t1 = t0;
- ecdhEncode(t1, k);
- ecdhDecode(t1, k);
- ASSERT_TRUE(t0.mask == t1.mask);
- ASSERT_TRUE(equalKeys(t0.mask, t1.mask));
- ASSERT_TRUE(t0.amount == t1.amount);
- ASSERT_TRUE(equalKeys(t0.amount, t1.amount));
- }
-}
-
TEST(ringct, d2h)
{
key k, P1;
diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp
index b4517af2f..343a11c37 100644
--- a/tests/unit_tests/serialization.cpp
+++ b/tests/unit_tests/serialization.cpp
@@ -550,12 +550,10 @@ TEST(Serialization, serializes_ringct_types)
ecdh0.mask = rct::skGen();
ecdh0.amount = rct::skGen();
- ecdh0.senderPk = rct::skGen();
ASSERT_TRUE(serialization::dump_binary(ecdh0, blob));
ASSERT_TRUE(serialization::parse_binary(blob, ecdh1));
ASSERT_TRUE(!memcmp(&ecdh0.mask, &ecdh1.mask, sizeof(ecdh0.mask)));
ASSERT_TRUE(!memcmp(&ecdh0.amount, &ecdh1.amount, sizeof(ecdh0.amount)));
- // senderPk is not serialized
for (size_t n = 0; n < 64; ++n)
{
@@ -591,7 +589,8 @@ TEST(Serialization, serializes_ringct_types)
rct::skpkGen(Sk, Pk);
destinations.push_back(Pk);
//compute rct data with mixin 500
- s0 = rct::genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, hw::get_device("default"));
+ const rct::RCTConfig rct_config{ rct::RangeProofPaddedBulletproof, 0 };
+ s0 = rct::genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default"));
mg0 = s0.p.MGs[0];
ASSERT_TRUE(serialization::dump_binary(mg0, blob));
diff --git a/tests/unit_tests/test_peerlist.cpp b/tests/unit_tests/test_peerlist.cpp
index f638c6251..03aa48ea0 100644
--- a/tests/unit_tests/test_peerlist.cpp
+++ b/tests/unit_tests/test_peerlist.cpp
@@ -37,7 +37,7 @@
TEST(peer_list, peer_list_general)
{
nodetool::peerlist_manager plm;
- plm.init(false);
+ plm.init(nodetool::peerlist_types{}, false);
#define MAKE_IPV4_ADDRESS(a,b,c,d,e) epee::net_utils::ipv4_network_address{MAKE_IP(a,b,c,d),e}
#define ADD_GRAY_NODE(addr_, id_, last_seen_) { nodetool::peerlist_entry ple; ple.last_seen=last_seen_;ple.adr = addr_; ple.id = id_;plm.append_with_peer_gray(ple);}
#define ADD_WHITE_NODE(addr_, id_, last_seen_) { nodetool::peerlist_entry ple;ple.last_seen=last_seen_; ple.adr = addr_; ple.id = id_;plm.append_with_peer_white(ple);}
@@ -77,9 +77,180 @@ TEST(peer_list, merge_peer_lists)
//([^ \t]*)\t([^ \t]*):([^ \t]*) \tlast_seen: d(\d+)\.h(\d+)\.m(\d+)\.s(\d+)\n
//ADD_NODE_TO_PL("\2", \3, 0x\1, (1353346618 -(\4*60*60*24+\5*60*60+\6*60+\7 )));\n
nodetool::peerlist_manager plm;
- plm.init(false);
+ plm.init(nodetool::peerlist_types{}, false);
std::vector<nodetool::peerlist_entry> outer_bs;
#define ADD_NODE_TO_PL(ip_, port_, id_, timestamp_) { nodetool::peerlist_entry ple; epee::string_tools::get_ip_int32_from_string(ple.adr.ip, ip_); ple.last_seen = timestamp_; ple.adr.port = port_; ple.id = id_;outer_bs.push_back(ple);}
+}
+
+namespace
+{
+ bool check_empty(nodetool::peerlist_storage& peers, std::initializer_list<epee::net_utils::zone> zones)
+ {
+ bool pass = false;
+ for (const epee::net_utils::zone zone : zones)
+ {
+ const nodetool::peerlist_types types{peers.take_zone(zone)};
+ EXPECT_TRUE(types.white.empty());
+ EXPECT_TRUE(types.gray.empty());
+ EXPECT_TRUE(types.anchor.empty());
+ pass = (types.white.empty() && types.gray.empty() && types.anchor.empty());
+ }
+ return pass;
+ }
+}
+
+TEST(peerlist_storage, store)
+{
+
+ using address_type = epee::net_utils::address_type;
+ using zone = epee::net_utils::zone;
+
+ nodetool::peerlist_storage peers{};
+ EXPECT_TRUE(check_empty(peers, {zone::invalid, zone::public_, zone::tor, zone::i2p}));
+
+ std::string buffer{};
+ {
+ nodetool::peerlist_types types{};
+ types.white.push_back({epee::net_utils::ipv4_network_address{1000, 10}, 44, 55});
+ types.white.push_back({net::tor_address::unknown(), 64, 75});
+ types.gray.push_back({net::tor_address::unknown(), 99, 88});
+ types.gray.push_back({epee::net_utils::ipv4_network_address{2000, 20}, 84, 45});
+ types.anchor.push_back({epee::net_utils::ipv4_network_address{999, 654}, 444, 555});
+ types.anchor.push_back({net::tor_address::unknown(), 14, 33});
+ types.anchor.push_back({net::tor_address::unknown(), 24, 22});
+
+ std::ostringstream stream{};
+ EXPECT_TRUE(peers.store(stream, types));
+ buffer = stream.str();
+ }
+ EXPECT_TRUE(check_empty(peers, {zone::invalid, zone::public_, zone::tor, zone::i2p}));
+ {
+ std::istringstream stream{buffer};
+ boost::optional<nodetool::peerlist_storage> read_peers =
+ nodetool::peerlist_storage::open(stream, true);
+ ASSERT_TRUE(bool(read_peers));
+ peers = std::move(*read_peers);
+ }
+ EXPECT_TRUE(check_empty(peers, {zone::invalid, zone::i2p}));
+
+ nodetool::peerlist_types types = peers.take_zone(zone::public_);
+ EXPECT_TRUE(check_empty(peers, {zone::invalid, zone::public_, zone::i2p}));
+
+ ASSERT_EQ(1u, types.white.size());
+ ASSERT_EQ(address_type::ipv4, types.white[0].adr.get_type_id());
+ EXPECT_EQ(1000u, types.white[0].adr.template as<epee::net_utils::ipv4_network_address>().ip());
+ EXPECT_EQ(10u, types.white[0].adr.template as<epee::net_utils::ipv4_network_address>().port());
+ EXPECT_EQ(44u, types.white[0].id);
+ EXPECT_EQ(55u, types.white[0].last_seen);
+
+ ASSERT_EQ(1u, types.gray.size());
+ ASSERT_EQ(address_type::ipv4, types.gray[0].adr.get_type_id());
+ EXPECT_EQ(2000u, types.gray[0].adr.template as<epee::net_utils::ipv4_network_address>().ip());
+ EXPECT_EQ(20u, types.gray[0].adr.template as<epee::net_utils::ipv4_network_address>().port());
+ EXPECT_EQ(84u, types.gray[0].id);
+ EXPECT_EQ(45u, types.gray[0].last_seen);
+
+ ASSERT_EQ(1u, types.anchor.size());
+ ASSERT_EQ(address_type::ipv4, types.anchor[0].adr.get_type_id());
+ EXPECT_EQ(999u, types.anchor[0].adr.template as<epee::net_utils::ipv4_network_address>().ip());
+ EXPECT_EQ(654u, types.anchor[0].adr.template as<epee::net_utils::ipv4_network_address>().port());
+ EXPECT_EQ(444u, types.anchor[0].id);
+ EXPECT_EQ(555u, types.anchor[0].first_seen);
+ {
+ std::ostringstream stream{};
+ EXPECT_TRUE(peers.store(stream, types));
+ buffer = stream.str();
+ }
+ EXPECT_TRUE(check_empty(peers, {zone::invalid, zone::public_, zone::i2p}));
+
+ types = peers.take_zone(zone::tor);
+ EXPECT_TRUE(check_empty(peers, {zone::invalid, zone::public_, zone::i2p, zone::tor}));
+
+ ASSERT_EQ(1u, types.white.size());
+ ASSERT_EQ(address_type::tor, types.white[0].adr.get_type_id());
+ EXPECT_STREQ(net::tor_address::unknown_str(), types.white[0].adr.template as<net::tor_address>().host_str());
+ EXPECT_EQ(0u, types.white[0].adr.template as<net::tor_address>().port());
+ EXPECT_EQ(64u, types.white[0].id);
+ EXPECT_EQ(75u, types.white[0].last_seen);
+
+ ASSERT_EQ(1u, types.gray.size());
+ ASSERT_EQ(address_type::tor, types.gray[0].adr.get_type_id());
+ EXPECT_STREQ(net::tor_address::unknown_str(), types.gray[0].adr.template as<net::tor_address>().host_str());
+ EXPECT_EQ(0u, types.gray[0].adr.template as<net::tor_address>().port());
+ EXPECT_EQ(99u, types.gray[0].id);
+ EXPECT_EQ(88u, types.gray[0].last_seen);
+
+ ASSERT_EQ(2u, types.anchor.size());
+ ASSERT_EQ(address_type::tor, types.anchor[0].adr.get_type_id());
+ EXPECT_STREQ(net::tor_address::unknown_str(), types.anchor[0].adr.template as<net::tor_address>().host_str());
+ EXPECT_EQ(0u, types.anchor[0].adr.template as<net::tor_address>().port());
+ EXPECT_EQ(14u, types.anchor[0].id);
+ EXPECT_EQ(33u, types.anchor[0].first_seen);
+ ASSERT_EQ(address_type::tor, types.anchor[1].adr.get_type_id());
+ EXPECT_STREQ(net::tor_address::unknown_str(), types.anchor[1].adr.template as<net::tor_address>().host_str());
+ EXPECT_EQ(0u, types.anchor[1].adr.template as<net::tor_address>().port());
+ EXPECT_EQ(24u, types.anchor[1].id);
+ EXPECT_EQ(22u, types.anchor[1].first_seen);
+
+ {
+ std::istringstream stream{buffer};
+ boost::optional<nodetool::peerlist_storage> read_peers =
+ nodetool::peerlist_storage::open(stream, true);
+ ASSERT_TRUE(bool(read_peers));
+ peers = std::move(*read_peers);
+ }
+ EXPECT_TRUE(check_empty(peers, {zone::invalid, zone::i2p}));
+
+ types = peers.take_zone(zone::public_);
+ EXPECT_TRUE(check_empty(peers, {zone::invalid, zone::public_, zone::i2p}));
+
+ ASSERT_EQ(1u, types.white.size());
+ ASSERT_EQ(address_type::ipv4, types.white[0].adr.get_type_id());
+ EXPECT_EQ(1000u, types.white[0].adr.template as<epee::net_utils::ipv4_network_address>().ip());
+ EXPECT_EQ(10u, types.white[0].adr.template as<epee::net_utils::ipv4_network_address>().port());
+ EXPECT_EQ(44u, types.white[0].id);
+ EXPECT_EQ(55u, types.white[0].last_seen);
+
+ ASSERT_EQ(1u, types.gray.size());
+ ASSERT_EQ(address_type::ipv4, types.gray[0].adr.get_type_id());
+ EXPECT_EQ(2000u, types.gray[0].adr.template as<epee::net_utils::ipv4_network_address>().ip());
+ EXPECT_EQ(20u, types.gray[0].adr.template as<epee::net_utils::ipv4_network_address>().port());
+ EXPECT_EQ(84u, types.gray[0].id);
+ EXPECT_EQ(45u, types.gray[0].last_seen);
+
+ ASSERT_EQ(1u, types.anchor.size());
+ ASSERT_EQ(address_type::ipv4, types.anchor[0].adr.get_type_id());
+ EXPECT_EQ(999u, types.anchor[0].adr.template as<epee::net_utils::ipv4_network_address>().ip());
+ EXPECT_EQ(654u, types.anchor[0].adr.template as<epee::net_utils::ipv4_network_address>().port());
+ EXPECT_EQ(444u, types.anchor[0].id);
+ EXPECT_EQ(555u, types.anchor[0].first_seen);
+
+ types = peers.take_zone(zone::tor);
+ EXPECT_TRUE(check_empty(peers, {zone::invalid, zone::public_, zone::i2p, zone::tor}));
+
+ ASSERT_EQ(1u, types.white.size());
+ ASSERT_EQ(address_type::tor, types.white[0].adr.get_type_id());
+ EXPECT_STREQ(net::tor_address::unknown_str(), types.white[0].adr.template as<net::tor_address>().host_str());
+ EXPECT_EQ(0u, types.white[0].adr.template as<net::tor_address>().port());
+ EXPECT_EQ(64u, types.white[0].id);
+ EXPECT_EQ(75u, types.white[0].last_seen);
+ ASSERT_EQ(1u, types.gray.size());
+ ASSERT_EQ(address_type::tor, types.gray[0].adr.get_type_id());
+ EXPECT_STREQ(net::tor_address::unknown_str(), types.gray[0].adr.template as<net::tor_address>().host_str());
+ EXPECT_EQ(0u, types.gray[0].adr.template as<net::tor_address>().port());
+ EXPECT_EQ(99u, types.gray[0].id);
+ EXPECT_EQ(88u, types.gray[0].last_seen);
+ ASSERT_EQ(2u, types.anchor.size());
+ ASSERT_EQ(address_type::tor, types.anchor[0].adr.get_type_id());
+ EXPECT_STREQ(net::tor_address::unknown_str(), types.anchor[0].adr.template as<net::tor_address>().host_str());
+ EXPECT_EQ(0u, types.anchor[0].adr.template as<net::tor_address>().port());
+ EXPECT_EQ(14u, types.anchor[0].id);
+ EXPECT_EQ(33u, types.anchor[0].first_seen);
+ ASSERT_EQ(address_type::tor, types.anchor[1].adr.get_type_id());
+ EXPECT_STREQ(net::tor_address::unknown_str(), types.anchor[1].adr.template as<net::tor_address>().host_str());
+ EXPECT_EQ(0u, types.anchor[1].adr.template as<net::tor_address>().port());
+ EXPECT_EQ(24u, types.anchor[1].id);
+ EXPECT_EQ(22u, types.anchor[1].first_seen);
}
diff --git a/tests/unit_tests/testdb.h b/tests/unit_tests/testdb.h
deleted file mode 100644
index 8f5cf70e8..000000000
--- a/tests/unit_tests/testdb.h
+++ /dev/null
@@ -1,147 +0,0 @@
-// 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 "gtest/gtest.h"
-
-#include "blockchain_db/blockchain_db.h"
-
-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 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, bool include_commitmemt) const { 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 epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<cryptonote::output_data_t> &outputs, bool allow_partial = false) const {}
- 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<std::vector<uint64_t>> get_tx_amount_output_indices(const uint64_t tx_index, size_t n_txes) const { return std::vector<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 crypto::hash &txid, const cryptonote::blobdata &blob, 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
- , 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) {}
-};
-