diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index 270b5399e..68bef3892 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -139,7 +139,7 @@ uint64_t BlockchainDB::add_block( const block& blk return prev_height; } -void BlockchainDB::set_hard_fork(HardFork*& hf) +void BlockchainDB::set_hard_fork(HardFork* hf) { m_hardfork = hf; } diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 5926f34a5..bb4602061 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -377,7 +377,7 @@ public: virtual void block_txn_stop() = 0; virtual void block_txn_abort() = 0; - virtual void set_hard_fork(HardFork*& hf); + virtual void set_hard_fork(HardFork* hf); // adds a block with the given metadata to the top of the blockchain, returns the new height // NOTE: subclass implementations of this (or the functions it calls) need diff --git a/src/blockchain_utilities/blocksdat_file.cpp b/src/blockchain_utilities/blocksdat_file.cpp index aba618034..81b56d55e 100644 --- a/src/blockchain_utilities/blocksdat_file.cpp +++ b/src/blockchain_utilities/blocksdat_file.cpp @@ -66,8 +66,6 @@ bool BlocksdatFile::open_writer(const boost::filesystem::path& file_path, uint64 m_raw_data_file = new std::ofstream(); - uint64_t num_blocks = 0; - LOG_PRINT_L0("creating file"); m_raw_data_file->open(file_path.string(), std::ios_base::binary | std::ios_base::out | std::ios::trunc); diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp index b643f5135..98ff73bc5 100644 --- a/src/common/command_line.cpp +++ b/src/common/command_line.cpp @@ -91,9 +91,4 @@ namespace command_line , "Show time-stats when processing blocks/txs and disk synchronization." , 0 }; - const command_line::arg_descriptor arg_fakechain = { - "fakechain" - , "Use a fake chain for testing purposes." - , false - }; } diff --git a/src/common/command_line.h b/src/common/command_line.h index 2fa213a21..75dc4b9fd 100644 --- a/src/common/command_line.h +++ b/src/common/command_line.h @@ -215,5 +215,4 @@ namespace command_line extern const arg_descriptor arg_prep_blocks_threads; extern const arg_descriptor arg_db_auto_remove_logs; extern const arg_descriptor arg_show_time_stats; - extern const arg_descriptor arg_fakechain; } diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index f9247ae27..a3eb21187 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -50,6 +50,7 @@ #include "warnings.h" #include "crypto/hash.h" #include "cryptonote_core/checkpoints_create.h" +#include "cryptonote_core/cryptonote_core.h" #if defined(PER_BLOCK_CHECKPOINT) #include "blocks/blocks.h" #endif @@ -99,7 +100,7 @@ static const uint64_t testnet_hard_fork_version_1_till = 624633; //------------------------------------------------------------------ Blockchain::Blockchain(tx_memory_pool& tx_pool) : - m_db(), m_tx_pool(tx_pool), m_hardfork(), m_timestamps_and_difficulties_height(0), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false), + m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false), m_is_blockchain_storing(false), m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_blocks_per_sync(1), m_db_sync_mode(db_async), m_fast_sync(true), m_sync_counter(0) { LOG_PRINT_L3("Blockchain::" << __func__); @@ -252,11 +253,13 @@ uint64_t Blockchain::get_current_blockchain_height() const //------------------------------------------------------------------ //FIXME: possibly move this into the constructor, to avoid accidentally // dereferencing a null BlockchainDB pointer -bool Blockchain::init(BlockchainDB* db, const bool testnet, const bool fakechain) +bool Blockchain::init(BlockchainDB* db, const bool testnet, const cryptonote::test_options *test_options) { LOG_PRINT_L3("Blockchain::" << __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); + bool fakechain = test_options != NULL; + if (db == nullptr) { LOG_ERROR("Attempted to init Blockchain with null DB"); @@ -273,12 +276,19 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, const bool fakechain m_testnet = testnet; if (m_hardfork == nullptr) { - if (m_testnet) + if (fakechain) + m_hardfork = new HardFork(*db, 1, 0); + else if (m_testnet) m_hardfork = new HardFork(*db, 1, testnet_hard_fork_version_1_till); else m_hardfork = new HardFork(*db, 1, mainnet_hard_fork_version_1_till); } - if (m_testnet) + if (fakechain) + { + for (size_t n = 0; test_options->hard_forks[n].first; ++n) + m_hardfork->add_fork(test_options->hard_forks[n].first, test_options->hard_forks[n].second, 0, n + 1); + } + else if (m_testnet) { for (size_t n = 0; n < sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]); ++n) m_hardfork->add_fork(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].threshold, testnet_hard_forks[n].time); @@ -348,11 +358,11 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, const bool fakechain return true; } //------------------------------------------------------------------ -bool Blockchain::init(BlockchainDB* db, HardFork*& hf, const bool testnet, const bool fakechain) +bool Blockchain::init(BlockchainDB* db, HardFork*& hf, const bool testnet) { if (hf != nullptr) m_hardfork = hf; - bool res = init(db, testnet, fakechain); + bool res = init(db, testnet, NULL); if (hf == nullptr) hf = m_hardfork; return res; @@ -494,6 +504,7 @@ bool Blockchain::reset_and_set_genesis_block(const block& b) CRITICAL_REGION_LOCAL(m_blockchain_lock); m_alternative_chains.clear(); m_db->reset(); + m_hardfork->init(); block_verification_context bvc = boost::value_initialized(); add_new_block(b, bvc); diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 5299fed99..ab2c8f9e8 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -58,6 +58,7 @@ namespace cryptonote { class tx_memory_pool; + struct test_options; enum blockchain_db_sync_mode { @@ -91,8 +92,8 @@ namespace cryptonote Blockchain(tx_memory_pool& tx_pool); - bool init(BlockchainDB* db, const bool testnet = false, const bool fakechain = false); - bool init(BlockchainDB* db, HardFork*& hf, const bool testnet = false, const bool fakechain = false); + bool init(BlockchainDB* db, const bool testnet = false, const cryptonote::test_options *test_options = NULL); + bool init(BlockchainDB* db, HardFork*& hf, const bool testnet = false); bool deinit(); void set_checkpoints(checkpoints&& chk_pts) { m_checkpoints = chk_pts; } diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 2479931be..2c485d791 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -145,13 +145,11 @@ namespace cryptonote command_line::add_arg(desc, command_line::arg_db_sync_mode); command_line::add_arg(desc, command_line::arg_show_time_stats); command_line::add_arg(desc, command_line::arg_db_auto_remove_logs); - command_line::add_arg(desc, command_line::arg_fakechain); } //----------------------------------------------------------------------------------------------- bool core::handle_command_line(const boost::program_options::variables_map& vm) { m_testnet = command_line::get_arg(vm, command_line::arg_testnet_on); - m_fakechain = command_line::get_arg(vm, command_line::arg_fakechain); auto data_dir_arg = m_testnet ? command_line::arg_testnet_data_dir : command_line::arg_data_dir; m_config_folder = command_line::get_arg(vm, data_dir_arg); @@ -251,8 +249,9 @@ namespace cryptonote return true; } //----------------------------------------------------------------------------------------------- - bool core::init(const boost::program_options::variables_map& vm) + bool core::init(const boost::program_options::variables_map& vm, const cryptonote::test_options *test_options) { + m_fakechain = test_options != NULL; bool r = handle_command_line(vm); r = m_mempool.init(m_fakechain ? std::string() : m_config_folder); @@ -398,7 +397,7 @@ namespace cryptonote m_blockchain_storage.set_user_options(blocks_threads, blocks_per_sync, sync_mode, fast_sync); - r = m_blockchain_storage.init(db, m_testnet, m_fakechain); + r = m_blockchain_storage.init(db, m_testnet, test_options); // now that we have a valid m_blockchain_storage, we can clean out any // transactions in the pool that do not conform to the current fork diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 90fdfefca..3c6f56749 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -56,6 +56,10 @@ DISABLE_VS_WARNINGS(4355) namespace cryptonote { + struct test_options { + const std::pair *hard_forks; + }; + /************************************************************************/ /* */ /************************************************************************/ @@ -81,7 +85,7 @@ namespace cryptonote miner& get_miner(){return m_miner;} const miner& get_miner()const{return m_miner;} static void init_options(boost::program_options::options_description& desc); - bool init(const boost::program_options::variables_map& vm); + bool init(const boost::program_options::variables_map& vm, const test_options *test_options = NULL); bool set_genesis_block(const block& b); bool deinit(); static void set_fast_exit(); diff --git a/src/cryptonote_core/hardfork.cpp b/src/cryptonote_core/hardfork.cpp index 9fe731ad1..e99736ff4 100644 --- a/src/cryptonote_core/hardfork.cpp +++ b/src/cryptonote_core/hardfork.cpp @@ -155,6 +155,11 @@ bool HardFork::add(const cryptonote::block &block, uint64_t height) void HardFork::init() { CRITICAL_REGION_LOCAL(lock); + + // add a placeholder for the default version, to avoid special cases + if (heights.empty()) + heights.push_back(Params(original_version, 0, 0, 0)); + versions.clear(); for (size_t n = 0; n < 256; ++n) last_versions[n] = 0; diff --git a/tests/core_tests/CMakeLists.txt b/tests/core_tests/CMakeLists.txt index 5f34bdc10..c34039c17 100644 --- a/tests/core_tests/CMakeLists.txt +++ b/tests/core_tests/CMakeLists.txt @@ -38,7 +38,8 @@ set(core_tests_sources integer_overflow.cpp ring_signature_1.cpp transaction_tests.cpp - tx_validation.cpp) + tx_validation.cpp + v2_tests.cpp) set(core_tests_headers block_reward.h @@ -52,7 +53,8 @@ set(core_tests_headers integer_overflow.h ring_signature_1.h transaction_tests.h - tx_validation.h) + tx_validation.h + v2_tests.h) add_executable(coretests ${core_tests_sources} diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 8f413c09c..4fdd0a600 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -215,13 +215,14 @@ bool test_generator::construct_block_manually(block& blk, const block& prev_bloc const crypto::hash& prev_id/* = crypto::hash()*/, const difficulty_type& diffic/* = 1*/, const transaction& miner_tx/* = transaction()*/, const std::vector& tx_hashes/* = std::vector()*/, - size_t txs_sizes/* = 0*/) + size_t txs_sizes/* = 0*/, size_t max_outs/* = 0*/) { blk.major_version = actual_params & bf_major_ver ? major_ver : CURRENT_BLOCK_MAJOR_VERSION; blk.minor_version = actual_params & bf_minor_ver ? minor_ver : CURRENT_BLOCK_MINOR_VERSION; blk.timestamp = actual_params & bf_timestamp ? timestamp : prev_block.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN; // Keep difficulty unchanged blk.prev_id = actual_params & bf_prev_id ? prev_id : get_block_hash(prev_block); blk.tx_hashes = actual_params & bf_tx_hashes ? tx_hashes : std::vector(); + max_outs = actual_params & bf_max_outs ? max_outs : 1; size_t height = get_block_height(prev_block) + 1; uint64_t already_generated_coins = get_already_generated_coins(prev_block); @@ -235,7 +236,7 @@ bool test_generator::construct_block_manually(block& blk, const block& prev_bloc { size_t current_block_size = txs_sizes + get_object_blobsize(blk.miner_tx); // TODO: This will work, until size of constructed block is less then CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE - if (!construct_miner_tx(height, misc_utils::median(block_sizes), already_generated_coins, current_block_size, 0, miner_acc.get_keys().m_account_address, blk.miner_tx, blobdata(), 1)) + if (!construct_miner_tx(height, misc_utils::median(block_sizes), already_generated_coins, current_block_size, 0, miner_acc.get_keys().m_account_address, blk.miner_tx, blobdata(), max_outs)) return false; } diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index fa12601a4..f2bbb7346 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -220,7 +220,8 @@ public: bf_prev_id = 1 << 3, bf_miner_tx = 1 << 4, bf_tx_hashes = 1 << 5, - bf_diffic = 1 << 6 + bf_diffic = 1 << 6, + bf_max_outs = 1 << 7 }; void get_block_chain(std::vector& blockchain, const crypto::hash& head, size_t n) const; @@ -240,7 +241,7 @@ public: const cryptonote::account_base& miner_acc, int actual_params = bf_none, uint8_t major_ver = 0, uint8_t minor_ver = 0, uint64_t timestamp = 0, const crypto::hash& prev_id = crypto::hash(), const cryptonote::difficulty_type& diffic = 1, const cryptonote::transaction& miner_tx = cryptonote::transaction(), - const std::vector& tx_hashes = std::vector(), size_t txs_sizes = 0); + const std::vector& tx_hashes = std::vector(), size_t txs_sizes = 0, size_t max_outs = 0); bool construct_block_manually_tx(cryptonote::block& blk, const cryptonote::block& prev_block, const cryptonote::account_base& miner_acc, const std::vector& tx_hashes, size_t txs_size); @@ -470,6 +471,14 @@ inline bool replay_events_through_core(cryptonote::core& cr, const std::vector +struct get_test_options { + const std::pair hard_forks[1] = {std::make_pair(1, 0)}; + const cryptonote::test_options test_options = { + hard_forks + }; +}; +//-------------------------------------------------------------------------- +template inline bool do_replay_events(std::vector& events) { boost::program_options::options_description desc("Allowed options"); @@ -484,15 +493,12 @@ inline bool do_replay_events(std::vector& events) if (!r) return false; - // hardcode a --fakechain option for tests - static const char * const fakechain[] = {"", "--fakechain"}; - boost::program_options::store(boost::program_options::parse_command_line(2, fakechain, desc), vm); - cryptonote::cryptonote_protocol_stub pr; //TODO: stub only for this kind of test, make real validation of relayed objects cryptonote::core c(&pr); // FIXME: make sure that vm has arg_testnet_on set to true or false if // this test needs for it to be so. - if (!c.init(vm)) + const get_test_options gto; + if (!c.init(vm, >o.test_options)) { std::cout << concolor::magenta << "Failed to init core" << concolor::normal << std::endl; return false; diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 99ae496e3..40bce1e4e 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -168,6 +168,13 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_block_reward); + GENERATE_AND_PLAY(gen_v2_tx_mixable_0_mixin); + GENERATE_AND_PLAY(gen_v2_tx_mixable_low_mixin); + GENERATE_AND_PLAY(gen_v2_tx_unmixable_only); + GENERATE_AND_PLAY(gen_v2_tx_unmixable_one); + GENERATE_AND_PLAY(gen_v2_tx_unmixable_two); + GENERATE_AND_PLAY(gen_v2_tx_dust); + std::cout << (failed_tests.empty() ? concolor::green : concolor::magenta); std::cout << "\nREPORT:\n"; std::cout << " Test run: " << tests_count << '\n'; diff --git a/tests/core_tests/chaingen_tests_list.h b/tests/core_tests/chaingen_tests_list.h index e18e00f74..4da87a973 100644 --- a/tests/core_tests/chaingen_tests_list.h +++ b/tests/core_tests/chaingen_tests_list.h @@ -39,6 +39,7 @@ #include "integer_overflow.h" #include "ring_signature_1.h" #include "tx_validation.h" +#include "v2_tests.h" /************************************************************************/ /* */ /************************************************************************/ diff --git a/tests/unit_tests/blockchain_db.cpp b/tests/unit_tests/blockchain_db.cpp index bda8c167e..127a15b44 100644 --- a/tests/unit_tests/blockchain_db.cpp +++ b/tests/unit_tests/blockchain_db.cpp @@ -155,7 +155,7 @@ template class BlockchainDBTest : public testing::Test { protected: - BlockchainDBTest() : m_db(new T()) + BlockchainDBTest() : m_db(new T()), m_hardfork(*m_db, 1, 0) { for (auto& i : t_blocks) { @@ -184,11 +184,18 @@ protected: } BlockchainDB* m_db; + HardFork m_hardfork; std::string m_prefix; std::vector m_blocks; std::vector > m_txs; std::vector m_filenames; + void init_hard_fork() + { + m_hardfork.init(); + m_db->set_hard_fork(&m_hardfork); + } + void get_filenames() { m_filenames = m_db->get_filenames(); @@ -257,6 +264,7 @@ TYPED_TEST(BlockchainDBTest, AddBlock) // make sure open does not throw ASSERT_NO_THROW(this->m_db->open(fname)); this->get_filenames(); + this->init_hard_fork(); // adding a block with no parent in the blockchain should throw. // note: this shouldn't be possible, but is a good (and cheap) failsafe. @@ -300,6 +308,7 @@ TYPED_TEST(BlockchainDBTest, RetrieveBlockData) // make sure open does not throw ASSERT_NO_THROW(this->m_db->open(fname)); 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])); diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp index e20f58a5d..7432c03ec 100644 --- a/tests/unit_tests/hardfork.cpp +++ b/tests/unit_tests/hardfork.cpp @@ -57,6 +57,10 @@ public: virtual void batch_start(uint64_t batch_num_blocks=0) {} virtual void batch_stop() {} virtual void set_batch_transactions(bool) {} + virtual void block_txn_start() {} + virtual void block_txn_stop() {} + virtual void block_txn_abort() {} + virtual void drop_hard_fork_info() {} virtual bool block_exists(const crypto::hash& h) const { return false; } virtual block get_block(const crypto::hash& h) const { return block(); } virtual uint64_t get_block_height(const crypto::hash& h) const { return 0; }