From 42bee0eee8230a484da88432c6b1db64ba1f0a22 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Tue, 13 Feb 2024 22:36:47 +0400 Subject: [PATCH] transfer asset ownership - implemented first test --- src/currency_core/currency_format_utils.cpp | 17 ++- src/wallet/wallet2.cpp | 43 ++++-- src/wallet/wallet2.h | 6 +- src/wallet/wallet_debug_events_definitions.h | 6 + tests/core_tests/multiassets_test.cpp | 134 ++++++------------- 5 files changed, 97 insertions(+), 109 deletions(-) diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index e44fb693..71312151 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -1137,16 +1137,16 @@ namespace currency return origin_blob; } //--------------------------------------------------------------- - bool validate_ado_update_allowed(const asset_descriptor_base& a, const asset_descriptor_base& b) + bool validate_ado_update_allowed(const asset_descriptor_base& new_ado, const asset_descriptor_base& prev_ado) { - if (a.total_max_supply != b.total_max_supply) return false; - //if (a.current_supply != b.current_supply) return false; - if (a.decimal_point != b.decimal_point) return false; - if (a.ticker != b.ticker) return false; - if (a.full_name != b.full_name) return false; + if (new_ado.total_max_supply != prev_ado.total_max_supply) return false; + if (new_ado.current_supply > prev_ado.total_max_supply) return false; + if (new_ado.decimal_point != prev_ado.decimal_point) return false; + if (new_ado.ticker != prev_ado.ticker) return false; + if (new_ado.full_name != prev_ado.full_name) return false; //a.meta_info; //if (a.owner != b.owner) return false; - if (a.hidden_supply != b.hidden_supply) return false; + if (new_ado.hidden_supply != prev_ado.hidden_supply) return false; return true; } @@ -2213,6 +2213,9 @@ namespace currency gen_context.ao_amount_commitment = amount_of_burned_assets * gen_context.ao_asset_id_pt + gen_context.ao_amount_blinding_mask * crypto::c_point_G; ado.amount_commitment = (crypto::c_scalar_1div8 * gen_context.ao_amount_commitment).to_public_key(); + + if (ftp.pevents_dispatcher) ftp.pevents_dispatcher->RAISE_DEBUG_EVENT(wde_construct_tx_handle_asset_descriptor_operation_before_burn{ &ado }); + } else { diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 305a3a57..c35db921 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -913,15 +913,13 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t m_payments.emplace(payment_id, payment); WLT_LOG_L2("Payment found, id (hex): " << epee::string_tools::buff_to_hex_nodelimer(payment_id) << ", tx: " << payment.m_tx_hash << ", amount: " << print_money_brief(payment.m_amount) << "subtransfers = " << payment.subtransfers.size()); } - - if (ptc.employed_entries.receive.size() || ptc.employed_entries.spent.size()) + + //check if there are asset_registration that belong to this wallet + const asset_descriptor_operation* pado = get_type_in_variant_container(tx.extra); + if (ptc.employed_entries.receive.size() || ptc.employed_entries.spent.size() || (pado && pado->descriptor.owner == m_account.get_public_address().spend_public_key)) { //check if there are asset_registration that belong to this wallet - asset_descriptor_operation ado = AUTO_VAL_INIT(ado); - if (get_type_in_variant_container(tx.extra, ado)) - { - process_ado_in_new_transaction(ado, ptc); - } + process_ado_in_new_transaction(*pado, ptc); } if (has_in_transfers || has_out_transfers || is_derivation_used_to_encrypt(tx, derivation) || ptc.employed_entries.spent.size()) @@ -3378,7 +3376,7 @@ uint64_t wallet2::balance(uint64_t& unlocked, uint64_t& awaiting_in, uint64_t& a return total; } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::balance(crypto::public_key asset_id, uint64_t& unlocked) const +uint64_t wallet2::balance(const crypto::public_key& asset_id, uint64_t& unlocked) const { std::unordered_map balances; uint64_t dummy; @@ -3392,6 +3390,12 @@ uint64_t wallet2::balance(crypto::public_key asset_id, uint64_t& unlocked) const return it->second.total; } //---------------------------------------------------------------------------------------------------- +uint64_t wallet2::balance(const crypto::public_key& asset_id) const +{ + uint64_t dummy = 0; + return balance(asset_id, dummy); +} +//---------------------------------------------------------------------------------------------------- bool wallet2::balance(std::unordered_map& balances, uint64_t& mined) const { mined = 0; @@ -4957,6 +4961,29 @@ void wallet2::update_asset(const crypto::public_key asset_id, const currency::as result_tx = ft.tx; } //---------------------------------------------------------------------------------------------------- +void wallet2::transfer_asset_ownership(const crypto::public_key asset_id, const crypto::public_key& new_owner, currency::transaction& result_tx) +{ + auto own_asset_entry_it = m_own_asset_descriptors.find(asset_id); + CHECK_AND_ASSERT_THROW_MES(own_asset_entry_it != m_own_asset_descriptors.end(), "Failed find asset_id " << asset_id << " in own assets list"); + + currency::asset_descriptor_base adb = AUTO_VAL_INIT(adb); + bool r = this->daemon_get_asset_info(asset_id, adb); + CHECK_AND_ASSERT_THROW_MES(r, "Failed to get asset info from daemon"); + + asset_descriptor_operation asset_update_info = AUTO_VAL_INIT(asset_update_info); + asset_update_info.descriptor = adb; + asset_update_info.operation_type = ASSET_DESCRIPTOR_OPERATION_UPDATE; + asset_update_info.opt_asset_id = asset_id; + asset_update_info.descriptor.owner = new_owner; + construct_tx_param ctp = get_default_construct_tx_param(); + ctp.ado_current_asset_owner = adb.owner; + ctp.extra.push_back(asset_update_info); + + finalized_tx ft = AUTO_VAL_INIT(ft); + this->transfer(ctp, ft, true, nullptr); + result_tx = ft.tx; +} +//---------------------------------------------------------------------------------------------------- void wallet2::burn_asset(const crypto::public_key asset_id, uint64_t amount_to_burn, currency::transaction& result_tx) { //auto own_asset_entry_it = m_own_asset_descriptors.find(asset_id); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 0caefca0..f83cecee 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -391,9 +391,10 @@ namespace tools void emmit_asset(const crypto::public_key asset_id, std::vector& destinations, currency::transaction& result_tx); void update_asset(const crypto::public_key asset_id, const currency::asset_descriptor_base new_descriptor, currency::transaction& result_tx); void burn_asset(const crypto::public_key asset_id, uint64_t amount_to_burn, currency::transaction& result_tx); + void transfer_asset_ownership(const crypto::public_key asset_id, const crypto::public_key& new_owner, currency::transaction& result_tx); bool daemon_get_asset_info(const crypto::public_key& asset_id, currency::asset_descriptor_base& adb); - + const std::unordered_map& get_own_assets() const { return m_own_asset_descriptors; } bool set_core_proxy(const std::shared_ptr& proxy); void set_pos_utxo_count_limits_for_defragmentation_tx(uint64_t min_outs, uint64_t max_outs); // don't create UTXO defrag. tx if there are less than 'min_outs' outs; don't put more than 'max_outs' outs void set_pos_decoys_count_for_defragmentation_tx(size_t decoys_count); @@ -404,7 +405,8 @@ namespace tools uint64_t balance(uint64_t& unloked, uint64_t& awaiting_in, uint64_t& awaiting_out, uint64_t& mined, const crypto::public_key& asset_id = currency::native_coin_asset_id) const; bool balance(std::unordered_map& balances, uint64_t& mined) const; bool balance(std::list& balances, uint64_t& mined) const; - uint64_t balance(crypto::public_key asset_id, uint64_t& unloked) const; + uint64_t balance(const crypto::public_key& asset_id, uint64_t& unlocked) const; + uint64_t balance(const crypto::public_key& asset_id) const; uint64_t balance(uint64_t& unloked) const; diff --git a/src/wallet/wallet_debug_events_definitions.h b/src/wallet/wallet_debug_events_definitions.h index 8a351469..30d7885c 100644 --- a/src/wallet/wallet_debug_events_definitions.h +++ b/src/wallet/wallet_debug_events_definitions.h @@ -18,6 +18,12 @@ struct wde_construct_tx_handle_asset_descriptor_operation_before_seal currency::asset_descriptor_operation* pado; }; +struct wde_construct_tx_handle_asset_descriptor_operation_before_burn +{ + currency::asset_descriptor_operation* pado; +}; + + struct wde_construct_tx_after_asset_ownership_proof_generated { diff --git a/tests/core_tests/multiassets_test.cpp b/tests/core_tests/multiassets_test.cpp index cc5191fa..1f5bbe5a 100644 --- a/tests/core_tests/multiassets_test.cpp +++ b/tests/core_tests/multiassets_test.cpp @@ -11,65 +11,6 @@ #include "wallet/wallet_debug_events_definitions.h" using namespace currency; - - - - - -/* - - -struct debug_context_event_1 -{ - int& i; - std::string& s; -}; - - - -//#define RAISE_DEBUG_EVENT dw.handle_type - - -void test_test() -{ - epee::misc_utils::events_dispatcher ed; - - //-------------------------------------------------------------------------------- - //-------------------------------------------------------------------------------- - //-------------------------------------------------------------------------------- - //thus code will be called in the tests - ed.SUBSCIRBE_DEBUG_EVENT([&](debug_context_event_1& d) - { - //here some operations - LOG_PRINT_L0("lala: " << d.i << d.s); - // - d.i = 10; - d.s = "33333"; - - }); - - - //-------------------------------------------------------------------------------- - //-------------------------------------------------------------------------------- - //-------------------------------------------------------------------------------- - //this code will be in the wallet and helper functions - - int i = 22; - std::string sss = "11111"; - - ed.RAISE_DEBUG_EVENT(debug_context_event_1{i, sss }); - - - LOG_PRINT_L0("lala: " << i << sss); -} -*/ - - - - - - - //------------------------------------------------------------------------------ #define AMOUNT_TO_TRANSFER_MULTIASSETS_BASIC (TESTS_DEFAULT_FEE) @@ -97,7 +38,8 @@ bool multiassets_basic_test::generate(std::vector& events) con DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks //TODO: Need to make sure REWIND_BLOCKS_N and other coretests codebase are capable of following hardfork4 rules //in this test hardfork4 moment moved to runtime section - REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3); + REWIND_BLOCKS_N_WITH_TIME(events, blk_2_inital, blk_0, alice_acc, 2); + REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_2_inital, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3); DO_CALLBACK(events, "c1"); @@ -115,7 +57,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v alice_wlt->get_account().set_createtime(0); asset_descriptor_base adb = AUTO_VAL_INIT(adb); - adb.total_max_supply = 1000000000000000000; //1M coins + adb.total_max_supply = 10000000000000000000; //1M coins adb.full_name = "Test coins"; adb.ticker = "TCT"; adb.decimal_point = 12; @@ -141,31 +83,13 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed"); - miner_wlt->refresh(); alice_wlt->refresh(); - uint64_t mined = 0; - std::unordered_map balances; - miner_wlt->balance(balances, mined); + CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id) == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances"); + CHECK_AND_ASSERT_MES(miner_wlt->balance() == uint64_t(17517225990000000000), false, "Failed to find needed asset in result balances"); - auto it_asset = balances.find(asset_id); - auto it_native = balances.find(currency::native_coin_asset_id); - - - CHECK_AND_ASSERT_MES(it_asset != balances.end() && it_native != balances.end(), false, "Failed to find needed asset in result balances"); - CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances"); - CHECK_AND_ASSERT_MES(it_native->second.total == uint64_t(17517225990000000000), false, "Failed to find needed asset in result balances"); - - - balances.clear(); - alice_wlt->balance(balances, mined); - - it_asset = balances.find(asset_id); - it_native = balances.find(currency::native_coin_asset_id); - - CHECK_AND_ASSERT_MES(it_asset != balances.end(), false, "Failed to find needed asset in result balances"); - CHECK_AND_ASSERT_MES(it_native == balances.end(), false, "Failed to find needed asset in result balances"); - CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances"); + CHECK_AND_ASSERT_MES(alice_wlt->balance() == 0, false, "Failed to find needed asset in result balances"); + CHECK_AND_ASSERT_MES(alice_wlt->balance(asset_id) == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances"); miner_wlt->transfer(AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC/2, alice_wlt->get_account().get_public_address(), asset_id); //pass over hardfork @@ -173,11 +97,9 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed"); alice_wlt->refresh(); - uint64_t last_alice_balances = alice_wlt->balance(asset_id, mined); + uint64_t last_alice_balances = alice_wlt->balance(asset_id); CHECK_AND_ASSERT_MES(last_alice_balances == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC + AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC/2, false, "Failed to find needed asset in result balances"); - - { try { @@ -193,7 +115,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v } miner_wlt->refresh(); - uint64_t last_miner_balance = miner_wlt->balance(asset_id, mined); + uint64_t last_miner_balance = miner_wlt->balance(asset_id); asset_descriptor_base asset_info = AUTO_VAL_INIT(asset_info); @@ -228,8 +150,8 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v miner_wlt->refresh(); alice_wlt->refresh(); - CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id, mined) == last_miner_balance + destinations[0].amount, false, "Miner balance wrong"); - CHECK_AND_ASSERT_MES(alice_wlt->balance(asset_id, mined) == last_alice_balances + destinations[1].amount, false, "Alice balance wrong"); + CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id) == last_miner_balance + destinations[0].amount, false, "Miner balance wrong"); + CHECK_AND_ASSERT_MES(alice_wlt->balance(asset_id) == last_alice_balances + destinations[1].amount, false, "Alice balance wrong"); asset_descriptor_base asset_info3 = AUTO_VAL_INIT(asset_info3); r = c.get_blockchain_storage().get_asset_info(asset_id, asset_info3); @@ -242,7 +164,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 1); miner_wlt->refresh(); - CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id, mined) == destinations[0].amount, false, "Miner balance wrong"); + CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id) == destinations[0].amount, false, "Miner balance wrong"); asset_descriptor_base asset_info4 = AUTO_VAL_INIT(asset_info4); r = c.get_blockchain_storage().get_asset_info(asset_id, asset_info4); @@ -348,7 +270,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v //test burn that burns more than tx has miner_wlt->get_debug_events_dispatcher().UNSUBSCRIBE_DEBUG_EVENT(); - miner_wlt->get_debug_events_dispatcher().SUBSCIRBE_DEBUG_EVENT([&](const wde_construct_tx_handle_asset_descriptor_operation_before_seal& o) + miner_wlt->get_debug_events_dispatcher().SUBSCIRBE_DEBUG_EVENT([&](const wde_construct_tx_handle_asset_descriptor_operation_before_burn& o) { o.pado->descriptor.current_supply -= 1000000; }); @@ -362,6 +284,34 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v miner_wlt->refresh(); // + miner_wlt->transfer_asset_ownership(asset_id, alice_wlt->get_account().get_public_address().spend_public_key, tx); + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); + r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c); + CHECK_AND_ASSERT_MES(r, false, "block with a bad tx was unexpectedly mined"); + CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not confirmed + + miner_wlt->refresh(); + alice_wlt->refresh(); + + auto miner_own_assets = miner_wlt->get_own_assets(); + auto alice_own_assets = alice_wlt->get_own_assets(); + CHECK_AND_ASSERT_MES(miner_own_assets.size() == 0, false, "Miner wlt still think he own asset"); + CHECK_AND_ASSERT_MES(alice_own_assets.size() == 1, false, "Alice still don't know she own asset"); + + uint64_t balance_alice_native = alice_wlt->balance(); + uint64_t balance_miner_native = miner_wlt->balance(); + uint64_t balance_alice_asset = alice_wlt->balance(asset_id); + uint64_t balance_miner_asset = miner_wlt->balance(asset_id); + + alice_wlt->emmit_asset(asset_id, destinations, tx); + r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed"); + + miner_wlt->refresh(); + alice_wlt->refresh(); + + CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id) == balance_miner_asset + destinations[0].amount, false, "Miner balance wrong"); + CHECK_AND_ASSERT_MES(alice_wlt->balance(asset_id) == balance_alice_asset + destinations[1].amount, false, "Alice balance wrong"); return true; } @@ -432,7 +382,7 @@ bool assets_and_explicit_native_coins_in_outs::generate(std::vector