diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 741a26db..1da3cf01 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -1599,7 +1599,7 @@ namespace currency }; //-------------------------------------------------------------------------------- bool generate_ZC_sig(const crypto::hash& tx_hash_for_signature, size_t input_index, const tx_source_entry& se, const input_generation_context_data& in_context, - const account_keys& sender_account_keys, const crypto::scalar_t& blinding_masks_sum, const uint64_t tx_flags, crypto::scalar_t& local_blinding_masks_sum, transaction& tx) + const account_keys& sender_account_keys, const crypto::scalar_t& blinding_masks_sum, const uint64_t tx_flags, crypto::scalar_t& local_blinding_masks_sum, transaction& tx, bool last_output) { bool watch_only_mode = sender_account_keys.spend_secret_key == null_skey; CHECK_AND_ASSERT_MES(se.is_zarcanum(), false, "sources contains a non-zarcanum input"); @@ -1621,7 +1621,7 @@ namespace currency #endif crypto::scalar_t blinding_mask = 0; - if ((tx_flags & TX_FLAG_SIGNATURE_MODE_SEPARATE) == 0 || se.separately_signed_tx_complete) + if ((last_output && (tx_flags & TX_FLAG_SIGNATURE_MODE_SEPARATE) == 0) || se.separately_signed_tx_complete) { // either normal tx or the last signature of consolidated tx -- in both cases we need to calculate non-random blinding mask for pseudo output commitment blinding_mask = blinding_masks_sum + local_blinding_masks_sum; @@ -1946,11 +1946,10 @@ namespace currency { tx.vin.push_back(ins_zc); }*/ - + uint64_t amount_of_assets = 0; std::vector shuffled_dsts(destinations); if (asset_id_for_destinations != currency::null_hash) { - uint64_t amount_of_assets = 0; //must be asset publication for (auto& item : shuffled_dsts) { @@ -2048,7 +2047,7 @@ namespace currency if (!has_zc_inputs) { - r = generate_tx_balance_proof(tx, blinding_masks_sum); + r = generate_tx_balance_proof(tx, blinding_masks_sum, amount_of_assets); CHECK_AND_ASSERT_MES(r, false, "generate_tx_balance_proof failed"); } } @@ -2094,7 +2093,8 @@ namespace currency { // ZC // blinding_masks_sum is supposed to be sum(mask of all tx output) - sum(masks of all pseudo out commitments) - r = generate_ZC_sig(tx_hash_for_signature, i + input_starter_index, source_entry, in_contexts[i], sender_account_keys, blinding_masks_sum, flags, local_blinding_masks_sum, tx); + r = generate_ZC_sig(tx_hash_for_signature, i + input_starter_index, source_entry, in_contexts[i], sender_account_keys, blinding_masks_sum, flags, + local_blinding_masks_sum, tx, i + 1 == sources.size()); CHECK_AND_ASSERT_MES(r, false, "generate_ZC_sigs failed"); } else diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 014ed1ff..41f620a2 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1877,7 +1877,7 @@ detail::split_strategy_id_t wallet2::get_current_split_strategy() return tools::detail::ssi_void; } // -void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx) +void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx, const crypto::hash& asset_id) { std::vector extra; std::vector attachments; @@ -1886,13 +1886,14 @@ void wallet2::transfer(uint64_t amount, const currency::account_public_address& dst.resize(1); dst.back().addr.push_back(acc); dst.back().amount = amount; + dst.back().asset_id = asset_id; this->transfer(dst, 0, 0, TX_DEFAULT_FEE, extra, attachments, get_current_split_strategy(), tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD), result_tx); } //---------------------------------------------------------------------------------------------------- -void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc) +void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::hash& asset_id) { transaction result_tx = AUTO_VAL_INIT(result_tx); - this->transfer(amount, acc, result_tx); + this->transfer(amount, acc, result_tx, asset_id); } //---------------------------------------------------------------------------------------------------- void wallet2::reset_creation_time(uint64_t timestamp) @@ -5664,7 +5665,14 @@ void wallet2::prepare_tx_destinations(uint64_t needed_money, change_dts.asset_id = asset_id; } WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(found_money >= needed_money, "needed_money==" << needed_money << " < found_money==" << found_money); - + if (asset_id != currency::null_hash) + { + if (change_dts.amount) + { + final_detinations.push_back(change_dts); + } + return; + } uint64_t dust = 0; bool r = detail::apply_split_strategy_by_id(destination_split_strategy_id, dsts, change_dts, dust_policy.dust_threshold, final_detinations, dust, WALLET_MAX_ALLOWED_OUTPUT_AMOUNT); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 83da27e9..1435df27 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -241,7 +241,7 @@ namespace tools const currency::tx_destination_entry& change_dst, uint64_t dust_threshold, std::vector& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed) { - splitted_dsts = dsts; + splitted_dsts.insert(splitted_dsts.end(), dsts.begin(), dsts.end()); if (change_dst.amount > 0) splitted_dsts.push_back(change_dst); } @@ -578,8 +578,8 @@ namespace tools uint64_t unlocked_balance() const; - void transfer(uint64_t amount, const currency::account_public_address& acc); - void transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx); + void transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::hash& asset_id = currency::null_hash); + void transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx, const crypto::hash& asset_id = currency::null_hash); void transfer(const std::vector& dsts, size_t fake_outputs_count, diff --git a/tests/core_tests/multiassets_test.cpp b/tests/core_tests/multiassets_test.cpp index 3f65b4c0..d9d300b7 100644 --- a/tests/core_tests/multiassets_test.cpp +++ b/tests/core_tests/multiassets_test.cpp @@ -20,6 +20,10 @@ using namespace currency; //------------------------------------------------------------------------------ multiassets_basic_test::multiassets_basic_test() { + // TODO: remove the following line + static uint64_t ts = 1; + random_state_test_restorer::reset_random(ts); + REGISTER_CALLBACK_METHOD(multiassets_basic_test, configure_core); REGISTER_CALLBACK_METHOD(multiassets_basic_test, c1); @@ -35,12 +39,13 @@ bool multiassets_basic_test::generate(std::vector& events) con account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); - MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time()); + uint64_t ts = 145000000; + MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts); DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks set_hard_fork_heights_to_generator(generator); //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(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3); + REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3); DO_CALLBACK(events, "c1"); @@ -51,10 +56,11 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v { bool r = false; std::shared_ptr miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX); + miner_wlt->get_account().set_createtime(0); account_base alice_acc; alice_acc.generate(); std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, alice_acc); - + alice_wlt->get_account().set_createtime(0); miner_wlt->refresh(); asset_descriptor_base adb = AUTO_VAL_INIT(adb); @@ -106,7 +112,32 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v 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"); - //TODO: add transfer of tokens + miner_wlt->transfer(AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC/2, alice_wlt->get_account().get_public_address(), asset_id); + //pass over hardfork + 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"); + + alice_wlt->refresh(); + balances.clear(); + alice_wlt->balance(balances, mined); + + it_asset = balances.find(asset_id); + + CHECK_AND_ASSERT_MES(it_asset != 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 + AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC/2, false, "Failed to find needed asset in result balances"); + + try { + + miner_wlt->transfer(AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC / 2, alice_wlt->get_account().get_public_address(), asset_id); + //pass over hardfork + CHECK_AND_ASSERT_MES(false, false, "Transfer with 0 Zano worked(fail)"); + } + catch (...) + { + + } + + return true; }