forked from lthn/blockchain
coretests: asset_operation_in_consolidated_tx test added (#459)
* coretests: Implement "asset_operation_in_consolidated_tx" test * Define "construct_tx" overload with a generation context argument --------- Co-authored-by: crypto.sowle <crypto.sowle@gmail.com>
This commit is contained in:
parent
77d6939411
commit
9d10050325
6 changed files with 193 additions and 46 deletions
|
|
@ -1814,6 +1814,48 @@ bool construct_tx_with_many_outputs(const currency::hard_forks_descriptor& hf, s
|
|||
return construct_tx(keys_from, sources, destinations, empty_attachment, tx, tx_version, 0);
|
||||
}
|
||||
|
||||
bool construct_tx(const account_keys& sender_account_keys,
|
||||
const std::vector<tx_source_entry>& sources,
|
||||
const std::vector<tx_destination_entry>& destinations,
|
||||
const std::vector<extra_v>& extra,
|
||||
const std::vector<attachment_v>& 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;
|
||||
}
|
||||
|
||||
uint64_t get_balance(const currency::account_keys& addr, const std::vector<currency::block>& blockchain, const map_hash2tx_t& mtx, bool dbg_log)
|
||||
{
|
||||
uint64_t res = 0;
|
||||
|
|
|
|||
|
|
@ -673,6 +673,22 @@ bool construct_tx_with_many_outputs(const currency::hard_forks_descriptor& hf, s
|
|||
const currency::account_keys& keys_from, const currency::account_public_address& addr_to,
|
||||
uint64_t total_amount, size_t outputs_count, uint64_t fee, currency::transaction& tx, bool use_ref_by_id = false);
|
||||
|
||||
bool construct_tx(const currency::account_keys& sender_account_keys,
|
||||
const std::vector<currency::tx_source_entry>& sources,
|
||||
const std::vector<currency::tx_destination_entry>& destinations,
|
||||
const std::vector<currency::extra_v>& extra,
|
||||
const std::vector<currency::attachment_v>& attachments,
|
||||
currency::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,
|
||||
currency::tx_generation_context& gen_context);
|
||||
|
||||
void get_confirmed_txs(const std::vector<currency::block>& blockchain, const map_hash2tx_t& mtx, map_hash2tx_t& confirmed_txs);
|
||||
bool find_block_chain(const std::vector<test_event_entry>& events, std::vector<currency::block>& blockchain, map_hash2tx_t& mtx, const crypto::hash& head);
|
||||
bool fill_tx_sources(std::vector<currency::tx_source_entry>& sources, const std::vector<test_event_entry>& events,
|
||||
|
|
|
|||
|
|
@ -1291,13 +1291,14 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(asset_depoyment_and_few_zc_utxos);
|
||||
GENERATE_AND_PLAY_HF(assets_and_pos_mining, "4-*");
|
||||
GENERATE_AND_PLAY_HF(asset_emission_and_unconfirmed_balance, "4-*");
|
||||
GENERATE_AND_PLAY_HF(asset_operation_in_consolidated_tx, "4-*");
|
||||
GENERATE_AND_PLAY_HF(asset_operation_and_hardfork_checks, "4-*");
|
||||
|
||||
GENERATE_AND_PLAY_HF(pos_fuse_test, "4-*");
|
||||
|
||||
|
||||
|
||||
GENERATE_AND_PLAY_HF(attachment_isolation_test, "4-*");
|
||||
GENERATE_AND_PLAY_HF(asset_operation_and_hardfork_checks, "4-*");
|
||||
|
||||
// GENERATE_AND_PLAY(gen_block_reward);
|
||||
// END OF TESTS */
|
||||
|
|
|
|||
|
|
@ -7,51 +7,7 @@
|
|||
|
||||
using namespace currency;
|
||||
|
||||
namespace currency
|
||||
{
|
||||
bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources,
|
||||
const std::vector<tx_destination_entry>& destinations,
|
||||
const std::vector<extra_v>& extra,
|
||||
const std::vector<attachment_v>& 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
|
||||
|
||||
void add_flags_to_all_destination_entries(const uint64_t flags, std::vector<currency::tx_destination_entry>& destinations)
|
||||
static void add_flags_to_all_destination_entries(const uint64_t flags, std::vector<currency::tx_destination_entry>& destinations)
|
||||
{
|
||||
for(auto& de : destinations)
|
||||
de.flags |= flags;
|
||||
|
|
|
|||
|
|
@ -1207,3 +1207,122 @@ bool asset_operation_and_hardfork_checks::c2(
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
asset_operation_in_consolidated_tx::asset_operation_in_consolidated_tx()
|
||||
{
|
||||
m_adb_alice_currency.total_max_supply = 1'000'000'000'000'000'000;
|
||||
m_adb_alice_currency.current_supply = 1'000'000'000'000'000'000;
|
||||
m_adb_alice_currency.ticker = "ALC";
|
||||
m_adb_alice_currency.full_name = "ALICE";
|
||||
m_adb_alice_currency.meta_info = "Currency created by Alice";
|
||||
m_adb_alice_currency.hidden_supply = false;
|
||||
|
||||
m_ado_alice_currency.operation_type = ASSET_DESCRIPTOR_OPERATION_REGISTER;
|
||||
m_ado_alice_currency.opt_asset_id = currency::null_pkey;
|
||||
|
||||
REGISTER_CALLBACK_METHOD(asset_operation_in_consolidated_tx, assert_balances);
|
||||
REGISTER_CALLBACK_METHOD(asset_operation_in_consolidated_tx, assert_alice_currency_not_registered);
|
||||
}
|
||||
|
||||
bool asset_operation_in_consolidated_tx::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
// Test idea: make sure that the core rule prohibiting operations with assets in TX_FLAG_SIGNATURE_MODE_SEPARATE transactions works.
|
||||
bool success {};
|
||||
transaction tx_2 {};
|
||||
uint64_t tx_version {};
|
||||
crypto::secret_key one_time {};
|
||||
tx_generation_context context_tx_2 {};
|
||||
GENERATE_ACCOUNT(miner);
|
||||
GENERATE_ACCOUNT(alice);
|
||||
GENERATE_ACCOUNT(bob);
|
||||
|
||||
m_accounts.push_back(miner);
|
||||
m_accounts.push_back(alice);
|
||||
m_accounts.push_back(bob);
|
||||
m_adb_alice_currency.owner = m_accounts.at(ALICE_ACC_IDX).get_public_address().spend_public_key;
|
||||
m_ado_alice_currency.descriptor = m_adb_alice_currency;
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner, test_core_time::get_time());
|
||||
DO_CALLBACK(events, "configure_core");
|
||||
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
MAKE_TX(events, tx_0, miner, bob, MK_TEST_COINS(10), blk_0r);
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner, tx_0);
|
||||
REWIND_BLOCKS_N(events, blk_1r, blk_1, miner, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
MAKE_TX(events, tx_1, miner, alice, MK_TEST_COINS(10), blk_1r);
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_2, blk_1r, miner, tx_1);
|
||||
REWIND_BLOCKS_N(events, blk_2r, blk_2, miner, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
// Miner sent 10 coins to Alice, 10 coins to Bob.
|
||||
DO_CALLBACK(events, "assert_balances");
|
||||
|
||||
{
|
||||
std::vector<tx_source_entry> sources {};
|
||||
std::vector<tx_destination_entry> destinations {};
|
||||
|
||||
success = fill_tx_sources(sources, events, blk_2r, alice.get_keys(), MK_TEST_COINS(5), 1);
|
||||
CHECK_AND_ASSERT_MES(success, false, "failed to fill transaction sources on step 1");
|
||||
destinations.emplace_back(MK_TEST_COINS(5), bob.get_public_address());
|
||||
destinations.emplace_back(MK_TEST_COINS(/* 10 - 5 - 1 = */ 4), alice.get_public_address());
|
||||
tx_version = get_tx_version(get_block_height(blk_2r), m_hardforks);
|
||||
success = construct_tx(alice.get_keys(), sources, destinations, empty_extra, empty_attachment, tx_2, tx_version, one_time, 0, 0, 0, true, TX_FLAG_SIGNATURE_MODE_SEPARATE, TESTS_DEFAULT_FEE,
|
||||
context_tx_2);
|
||||
CHECK_AND_ASSERT_MES(success, false, "failed to construct transaction tx_2 on step 1");
|
||||
}
|
||||
|
||||
// Transaction tx_2 hasn't been constructed completely yet. Core rejects tx_2.
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx_2);
|
||||
|
||||
{
|
||||
std::vector<tx_source_entry> sources {};
|
||||
std::vector<tx_destination_entry> destinations {};
|
||||
|
||||
success = fill_tx_sources(sources, events, blk_2r, bob.get_keys(), MK_TEST_COINS(5), 0);
|
||||
CHECK_AND_ASSERT_MES(success, false, "failed to fill transaction sources on step 2");
|
||||
for(tx_source_entry& source : sources)
|
||||
{
|
||||
source.separately_signed_tx_complete = true;
|
||||
}
|
||||
destinations.emplace_back(MK_TEST_COINS(5), alice.get_public_address());
|
||||
destinations.emplace_back(MK_TEST_COINS(/* 10 - 5 - 0 = */ 5), bob.get_public_address());
|
||||
destinations.emplace_back(m_adb_alice_currency.current_supply, alice.get_public_address(), null_pkey);
|
||||
tx_version = get_tx_version(get_block_height(blk_2r), m_hardforks);
|
||||
success = construct_tx(bob.get_keys(), sources, destinations, { m_ado_alice_currency }, empty_attachment, tx_2, tx_version, one_time, 0, 0, 0, true, TX_FLAG_SIGNATURE_MODE_SEPARATE,
|
||||
/* fee = */ 0, context_tx_2);
|
||||
CHECK_AND_ASSERT_MES(success, false, "failed to construct transaction tx_2 on step 2");
|
||||
}
|
||||
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx_2);
|
||||
// Core rejects transaction tx_2. The balances of Alice, Bob haven't changed: Alice has 10 coins, Bob has 10 coins.
|
||||
DO_CALLBACK(events, "assert_balances");
|
||||
// Alice's asset hasn't registered, because transaction tx_2 was rejected.
|
||||
DO_CALLBACK(events, "assert_alice_currency_not_registered");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool asset_operation_in_consolidated_tx::assert_balances(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
std::shared_ptr<tools::wallet2> alice_wallet{init_playtime_test_wallet(events, c, ALICE_ACC_IDX)};
|
||||
std::shared_ptr<tools::wallet2> bob_wallet{init_playtime_test_wallet(events, c, BOB_ACC_IDX)};
|
||||
|
||||
alice_wallet->refresh();
|
||||
bob_wallet->refresh();
|
||||
|
||||
CHECK_AND_ASSERT_EQ(alice_wallet->balance(currency::native_coin_asset_id), MK_TEST_COINS(10));
|
||||
CHECK_AND_ASSERT_EQ(bob_wallet->balance(currency::native_coin_asset_id), MK_TEST_COINS(10));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool asset_operation_in_consolidated_tx::assert_alice_currency_not_registered(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
crypto::point_t asset_id_point{};
|
||||
crypto::public_key asset_id{};
|
||||
currency::asset_descriptor_base stub{};
|
||||
|
||||
CHECK_AND_ASSERT_MES(get_or_calculate_asset_id(m_ado_alice_currency, &asset_id_point, &asset_id), false, "fail to calculate asset id");
|
||||
CHECK_AND_ASSERT_MES(!c.get_blockchain_storage().get_asset_info(asset_id, stub), false, "unregistered asset has info");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,3 +68,16 @@ struct asset_operation_and_hardfork_checks : public wallet_test
|
|||
mutable currency::asset_descriptor_base m_adb_bye{};
|
||||
mutable currency::asset_descriptor_operation m_ado_bye{};
|
||||
};
|
||||
|
||||
struct asset_operation_in_consolidated_tx : public wallet_test
|
||||
{
|
||||
public:
|
||||
asset_operation_in_consolidated_tx();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
bool assert_balances(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
bool assert_alice_currency_not_registered(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
|
||||
private:
|
||||
mutable currency::asset_descriptor_base m_adb_alice_currency{};
|
||||
mutable currency::asset_descriptor_operation m_ado_alice_currency{};
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue