From fe7db04b84a102cba0c2ce8689efdc734a21d255 Mon Sep 17 00:00:00 2001 From: sowle Date: Fri, 12 Jan 2024 03:14:59 +0100 Subject: [PATCH] coretests: hard_fork_4_consolidated_txs WIP --- tests/core_tests/chaingen_tests_list.h | 5 +- tests/core_tests/hard_fork_4.cpp | 216 +++++++++++++++++++++++++ tests/core_tests/hard_fork_4.h | 26 +++ 3 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 tests/core_tests/hard_fork_4.cpp create mode 100644 tests/core_tests/hard_fork_4.h diff --git a/tests/core_tests/chaingen_tests_list.h b/tests/core_tests/chaingen_tests_list.h index 2dccb4e3..c6a952f6 100644 --- a/tests/core_tests/chaingen_tests_list.h +++ b/tests/core_tests/chaingen_tests_list.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2024 Zano Project // Copyright (c) 2014-2018 The Louisdor Project // Copyright (c) 2012-2013 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying @@ -38,9 +38,10 @@ #include "hard_fork_1_bad_pos_source.h" #include "hard_fork_1.h" #include "hard_fork_2.h" +#include "hard_fork_4.h" #include "atomic_tests.h" #include "isolate_auditable_and_proof.h" #include "zarcanum_test.h" #include "multiassets_test.h" #include "ionic_swap_tests.h" -#include "attachment_isolation_encryption_test.h" \ No newline at end of file +#include "attachment_isolation_encryption_test.h" diff --git a/tests/core_tests/hard_fork_4.cpp b/tests/core_tests/hard_fork_4.cpp new file mode 100644 index 00000000..0ce910ad --- /dev/null +++ b/tests/core_tests/hard_fork_4.cpp @@ -0,0 +1,216 @@ +// Copyright (c) 2023-2024 Zano Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "chaingen.h" +#include "hard_fork_4.h" +#include "random_helper.h" + +using namespace currency; + +namespace currency +{ + bool construct_tx(const account_keys& sender_account_keys, const std::vector& sources, + const std::vector& destinations, + const std::vector& extra, + const std::vector& attachments, + transaction& tx, + uint64_t tx_version, + crypto::secret_key& one_time_secret_key, + uint64_t unlock_time, + uint64_t expiration_time, + uint8_t tx_outs_attr, + bool shuffle, + uint64_t flags, + uint64_t explicit_consolidated_tx_fee, + tx_generation_context& gen_context) + { + //extra copy operation, but creating transaction is not sensitive to this + finalize_tx_param ftp{}; + ftp.tx_version = tx_version; + ftp.sources = sources; + ftp.prepared_destinations = destinations; + ftp.extra = extra; + ftp.attachments = attachments; + ftp.unlock_time = unlock_time; + // ftp.crypt_address = crypt_destination_addr; + ftp.expiration_time = expiration_time; + ftp.tx_outs_attr = tx_outs_attr; + ftp.shuffle = shuffle; + ftp.flags = flags; + ftp.mode_separate_fee = explicit_consolidated_tx_fee; + + finalized_tx ft = AUTO_VAL_INIT(ft); + ft.tx = tx; + ft.one_time_key = one_time_secret_key; + ftp.gen_context = gen_context; // ftp, not ft here, this is UGLY -- sowle + bool r = construct_tx(sender_account_keys, ftp, ft); + tx = ft.tx; + one_time_secret_key = ft.one_time_key; + gen_context = ft.ftp.gen_context; + return r; + } +} // namespace currency + + +//------------------------------- + + +hard_fork_4_consolidated_txs::hard_fork_4_consolidated_txs() +{ + REGISTER_CALLBACK_METHOD(hard_fork_4_consolidated_txs, c1); +} + +bool hard_fork_4_consolidated_txs::generate(std::vector& events) const +{ + bool r = false; + + uint64_t ts = test_core_time::get_time(); + m_accounts.resize(TOTAL_ACCS_COUNT); + account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts); + account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts); + account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc.generate(); bob_acc.set_createtime(ts); + MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts); + DO_CALLBACK(events, "configure_core"); // necessary for the test to be run by GENERATE_AND_PLAY_HF + + REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + + m_post_hf4_zarcanum = get_hardforks().get_the_most_recent_hardfork_id_for_height(CURRENCY_MINED_MONEY_UNLOCK_WINDOW) >= ZANO_HARDFORK_04_ZARCANUM; + + uint64_t alice_amount = MK_TEST_COINS(50); + MAKE_TX(events, tx_0a, miner_acc, alice_acc, alice_amount, blk_0r); + // tx_0b is only needed for decoy outputs with amount = alice_amount (important only for pre-HF4) + transaction tx_0b{}; + construct_tx_with_many_outputs(m_hardforks, events, blk_0r, miner_acc.get_keys(), miner_acc.get_public_address(), alice_amount * 10, 10, TESTS_DEFAULT_FEE, tx_0b); + ADD_CUSTOM_EVENT(events, tx_0b); + MAKE_NEXT_BLOCK_TX_LIST(events, blk_1, blk_0r, miner_acc, std::list({tx_0a, tx_0b})); + + REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + + // check Alice's balance + std::shared_ptr alice_wlt; + r = generator.init_test_wallet(alice_acc, get_block_hash(blk_0), alice_wlt); + CHECK_AND_ASSERT_MES(r, false, "init_test_wallet failed"); + r = generator.refresh_test_wallet(events, alice_wlt.get(), get_block_hash(blk_1r), 2 * CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1); + CHECK_AND_ASSERT_MES(r, false, "refresh_test_wallet failed"); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice", alice_amount, 0, alice_amount, 0, 0), false, ""); + + uint64_t miner_amount = MK_TEST_COINS(60); + uint64_t bob_amount = miner_amount + alice_amount - TX_DEFAULT_FEE; + + // Consolidated tx (TX_FLAG_SIGNATURE_MODE_SEPARATE). + + // this data will be transferred between stage 1 and 2 + transaction tx_1{}; + crypto::secret_key one_time_secret_key{}; + tx_generation_context gen_context{}; + + // Part 1/2, miner's inputs + { + std::vector sources; + r = fill_tx_sources(sources, events, blk_1r, miner_acc.get_keys(), miner_amount, 10); + CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources failed"); + uint64_t miner_change = get_sources_total_amount(sources) - miner_amount; + + std::vector destinations; + if (miner_change != 0) + destinations.push_back(tx_destination_entry(miner_change, miner_acc.get_public_address())); + destinations.push_back(tx_destination_entry(bob_amount, bob_acc.get_public_address())); + + r = construct_tx(miner_acc.get_keys(), sources, destinations, empty_extra, empty_attachment, tx_1, get_tx_version_from_events(events), one_time_secret_key, + 0, 0, 0, true, TX_FLAG_SIGNATURE_MODE_SEPARATE, TX_DEFAULT_FEE, gen_context); + CHECK_AND_ASSERT_MES(r, false, "construct_tx failed"); + + // partially completed tx_1 shouldn't be accepted + DO_CALLBACK(events, "mark_invalid_tx"); + ADD_CUSTOM_EVENT(events, tx_1); + } + + + // Part 2/2, Alice's inputs + { + std::vector sources; + r = fill_tx_sources(sources, events, blk_1r, alice_acc.get_keys(), alice_amount, 10); + CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources failed"); + CHECK_AND_ASSERT_MES(get_sources_total_amount(sources) == alice_amount, false, "no change for Alice is expected"); + sources.back().separately_signed_tx_complete = true; + + std::vector destinations; + + r = construct_tx(alice_acc.get_keys(), sources, destinations, empty_extra, empty_attachment, tx_1, get_tx_version_from_events(events), one_time_secret_key, + 0, 0, 0, true, TX_FLAG_SIGNATURE_MODE_SEPARATE, 0 /* note zero fee here */, gen_context); + CHECK_AND_ASSERT_MES(r, false, "construct_tx failed"); + + ADD_CUSTOM_EVENT(events, tx_1); + } + MAKE_NEXT_BLOCK_TX1(events, blk_2, blk_1r, miner_acc, tx_1); + + std::shared_ptr bob_wlt; + r = generator.init_test_wallet(bob_acc, get_block_hash(blk_0), bob_wlt); + CHECK_AND_ASSERT_MES(r, false, "init_test_wallet failed"); + r = generator.refresh_test_wallet(events, bob_wlt.get(), get_block_hash(blk_2), 2 * CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 2); + CHECK_AND_ASSERT_MES(r, false, "refresh_test_wallet failed"); + CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", bob_amount, 0, 0, 0, 0), false, ""); + + + return true; +} + +bool hard_fork_4_consolidated_txs::c1(currency::core& c, size_t ev_index, const std::vector& events) +{ + return true; +} + + + +/* +hardfork_4_explicit_native_ids_in_outs::hardfork_4_explicit_native_ids_in_outs() +{ + REGISTER_CALLBACK_METHOD(hardfork_4_explicit_native_ids_in_outs, c1); + + m_hardforks.clear(); + m_hardforks.set_hardfork_height(ZANO_HARDFORK_04_ZARCANUM, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1); +} + +bool hardfork_4_explicit_native_ids_in_outs::generate(std::vector& events) const +{ + bool r = false; + + uint64_t ts = test_core_time::get_time(); + m_accounts.resize(TOTAL_ACCS_COUNT); + account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts); + account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts); + MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts); + DO_CALLBACK(events, "configure_core"); // necessary to set m_hardforks + + REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + + DO_CALLBACK_PARAMS(events, "check_hardfork_inactive", static_cast(ZANO_HARDFORK_04_ZARCANUM)); + + // tx_0: miner -> Alice + // make tx_0 before HF4, so Alice will have only bare outs + m_alice_initial_balance = MK_TEST_COINS(1000); + MAKE_TX(events, tx_0, miner_acc, alice_acc, m_alice_initial_balance, blk_0r); + MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0); + + // make sure HF4 has been activated + DO_CALLBACK_PARAMS(events, "check_hardfork_active", static_cast(ZANO_HARDFORK_04_ZARCANUM)); + + // rewind blocks + REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + + // check Alice's balance and make sure she cannot deploy an asset + DO_CALLBACK(events, "c1_alice_cannot_deploy_asset"); + + // tx_1: Alice -> Alice (all coins) : this will convert all Alice outputs to ZC outs + MAKE_TX(events, tx_1, alice_acc, alice_acc, m_alice_initial_balance - TESTS_DEFAULT_FEE, blk_1r); + + + + return true; +} + +bool hardfork_4_explicit_native_ids_in_outs::c1(currency::core& c, size_t ev_index, const std::vector& events) +{ + return true; +} +*/ \ No newline at end of file diff --git a/tests/core_tests/hard_fork_4.h b/tests/core_tests/hard_fork_4.h new file mode 100644 index 00000000..bf12419f --- /dev/null +++ b/tests/core_tests/hard_fork_4.h @@ -0,0 +1,26 @@ +// Copyright (c) 2023-2024 Zano Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#pragma once +#include "chaingen.h" +#include "wallet_tests_basic.h" + + +struct hard_fork_4_consolidated_txs : public wallet_test +{ + hard_fork_4_consolidated_txs(); + bool generate(std::vector& events) const; + bool c1(currency::core& c, size_t ev_index, const std::vector& events); + + mutable bool m_post_hf4_zarcanum = false; +}; + + +struct hardfork_4_explicit_native_ids_in_outs : public wallet_test +{ + hardfork_4_explicit_native_ids_in_outs(); + bool generate(std::vector& events) const; + bool c1(currency::core& c, size_t ev_index, const std::vector& events); + + mutable uint64_t m_alice_initial_balance = 0; +};