1
0
Fork 0
forked from lthn/blockchain

Final fixes for ionic_swap_basic_test - first time test worked!!!!!

This commit is contained in:
cryptozoidberg 2023-04-25 00:16:13 +02:00
parent 09215f8923
commit 9f6436ea08
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
7 changed files with 139 additions and 28 deletions

View file

@ -40,4 +40,5 @@
#define API_RETURN_CODE_TX_IS_TOO_BIG "TX_IS_TOO_BIG"
#define API_RETURN_CODE_TX_REJECTED "TX_REJECTED"
#define API_RETURN_CODE_HTLC_ORIGIN_HASH_MISSMATCHED "HTLC_ORIGIN_HASH_MISSMATCHED"
#define API_RETURN_CODE_WRAP "WRAP"
#define API_RETURN_CODE_WRAP "WRAP"
#define API_RETURN_CODE_MISSING_ZC_INPUTS "MISSING_ZC_INPUTS"

View file

@ -2096,7 +2096,7 @@ namespace currency
}
}
size_t thirdparty_zc_inputs_count = zc_inputs_count;
//
// INs
//
@ -2284,7 +2284,7 @@ namespace currency
for(size_t destination_index = 0; destination_index < shuffled_dsts.size(); ++destination_index, ++output_index)
{
tx_destination_entry& dst_entr = shuffled_dsts[destination_index];
if (all_inputs_are_obviously_native_coins && gen_context.ao_asset_id == currency::null_pkey)
if (!append_mode && all_inputs_are_obviously_native_coins && gen_context.ao_asset_id == currency::null_pkey)
dst_entr.flags |= tx_destination_entry_flags::tdef_explicit_native_asset_id; // all inputs are obviously native coins -- all outputs must have explicit asset ids (unless there's an asset emission)
CHECK_AND_ASSERT_MES(dst_entr.amount > 0, false, "Destination with wrong amount: " << dst_entr.amount); // <<-- TODO @#@# consider removing this check
@ -2376,6 +2376,7 @@ namespace currency
// ring signatures (per-input proofs)
r = false;
size_t curren_zc_index = thirdparty_zc_inputs_count;
for (size_t i_ = 0; i_ != sources.size(); i_++)
{
size_t i_mapped = inputs_mapping[i_];
@ -2390,7 +2391,8 @@ namespace currency
// 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_mapped], sender_account_keys, flags, gen_context, tx, i_ + 1 == sources.size());
CHECK_AND_ASSERT_MES(r, false, "generate_ZC_sigs failed");
gen_context.input_amounts[i_ + input_starter_index] = source_entry.amount;
gen_context.zc_input_amounts[curren_zc_index] = source_entry.amount;
curren_zc_index++;
}
else
{

View file

@ -225,7 +225,7 @@ namespace currency
asset_id_blinding_masks.resize(outs_count);
amounts.resize(outs_count);
amount_blinding_masks.resize(outs_count);
input_amounts.resize(zc_ins_count);
zc_input_amounts.resize(zc_ins_count);
}
// TODO @#@# reconsider this check -- sowle
@ -253,7 +253,7 @@ namespace currency
std::vector<crypto::point_t> pseudo_outs_blinded_asset_ids; // generate_asset_surjection_proof
crypto::scalar_vec_t pseudo_outs_plus_real_out_blinding_masks; // r_pi + r'_j // generate_asset_surjection_proof
std::vector<crypto::point_t> real_zc_ins_asset_ids; // H_i // generate_asset_surjection_proof
std::vector<uint64_t> input_amounts; // all inputs, including non ZC
std::vector<uint64_t> zc_input_amounts; // ZC only input amounts
// common data: inputs
crypto::point_t pseudo_out_amount_commitments_sum = crypto::c_point_0; // generate_tx_balance_proof generate_ZC_sig
@ -282,7 +282,7 @@ namespace currency
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(pseudo_outs_blinded_asset_ids)
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(pseudo_outs_plus_real_out_blinding_masks)
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(real_zc_ins_asset_ids)
KV_SERIALIZE(input_amounts)
KV_SERIALIZE(zc_input_amounts)
KV_SERIALIZE_POD_AS_HEX_STRING(pseudo_out_amount_commitments_sum)
KV_SERIALIZE_POD_AS_HEX_STRING(pseudo_out_amount_blinding_masks_sum)
KV_SERIALIZE_POD_AS_HEX_STRING(real_in_asset_id_blinding_mask_x_amount_sum)
@ -308,7 +308,7 @@ namespace currency
FIELD(pseudo_outs_blinded_asset_ids)
FIELD((std::vector<crypto::scalar_t>&)(pseudo_outs_plus_real_out_blinding_masks))
FIELD(real_zc_ins_asset_ids)
FIELD(input_amounts)
FIELD(zc_input_amounts)
FIELD(pseudo_out_amount_commitments_sum)
FIELD(pseudo_out_amount_blinding_masks_sum)
FIELD(real_in_asset_id_blinding_mask_x_amount_sum)

View file

@ -42,6 +42,8 @@ using namespace epee;
using namespace currency;
#define SET_CONTEXT_OBJ_FOR_SCOPE(name, obj) m_current_context.name = &obj; \
auto COMBINE(auto_scope_var_, __LINE__) = epee::misc_utils::create_scope_leave_handler([&]() { m_current_context.name = nullptr; });
#define MINIMUM_REQUIRED_WALLET_FREE_SPACE_BYTES (100*1024*1024) // 100 MB
@ -5139,7 +5141,7 @@ bool wallet2::get_ionic_swap_proposal_info(const wallet_public::ionic_swap_propo
if (tx.vin[i].type() == typeid(txin_zc_input))
{
in_asset_id = ionic_context.gen_context.real_zc_ins_asset_ids[zc_current_index].to_public_key();
amount = ionic_context.gen_context.input_amounts[zc_current_index];
amount = ionic_context.gen_context.zc_input_amounts[zc_current_index];
zc_current_index++;
mx = boost::get<currency::txin_zc_input>(tx.vin[i]).key_offsets.size() - 1;
}
@ -5280,6 +5282,8 @@ bool wallet2::accept_ionic_swap_proposal(const wallet_public::ionic_swap_proposa
ftp.gen_context = ionic_context.gen_context;
prepare_transaction(construct_param, ftp, msc);
try
{
finalize_transaction(ftp, result_tx, one_time_key, true);
@ -5895,6 +5899,38 @@ bool wallet2::get_actual_offers(std::list<bc_services::offer_details_ex>& offers
return true;
}
//----------------------------------------------------------------------------------------------------
bool wallet2::expand_selection_with_zc_input(assets_selection_context& needed_money_map, uint64_t fake_outputs_count, std::vector<uint64_t>& selected_indexes)
{
free_amounts_cache_type& found_free_amounts = m_found_free_amounts[currency::native_coin_asset_id];
auto& asset_needed_money_item = needed_money_map[currency::native_coin_asset_id];
//need to add ZC input
for (auto it = found_free_amounts.begin(); it != found_free_amounts.end(); it++)
{
for (auto it_in_amount = it->second.begin(); it_in_amount != it->second.end(); it_in_amount++)
{
if (!m_transfers[*it_in_amount].is_zc())
{
continue;
}
if (is_transfer_ready_to_go(m_transfers[*it->second.begin()], fake_outputs_count))
{
asset_needed_money_item.found_amount += it->first;
selected_indexes.push_back(*it_in_amount);
it->second.erase(it_in_amount);
if (!it->second.size())
{
found_free_amounts.erase(it);
}
return true;
}
}
}
WLT_THROW_IF_FALSE_WALLET_EX_MES(false , error::no_zc_inputs, "Missing ZC inputs for TX_FLAG_SIGNATURE_MODE_SEPARATE operation");
return true;
}
//----------------------------------------------------------------------------------------------------
bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money_map, uint64_t fake_outputs_count, std::vector<uint64_t>& selected_indexes)
{
bool res = true;
@ -5906,6 +5942,24 @@ bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money
item.second.found_amount = select_indices_for_transfer(selected_indexes, asset_cashe_it->second, item.second.needed_amount, fake_outputs_count);
WLT_THROW_IF_FALSE_WALLET_EX_MES(item.second.found_amount >= item.second.needed_amount, error::not_enough_money, "", item.second.found_amount, item.second.needed_amount, 0, item.first);
}
if (m_current_context.pconstruct_tx_param && m_current_context.pconstruct_tx_param->need_at_least_1_zc)
{
bool found_zc_input = false;
for (auto i : selected_indexes)
{
if (m_transfers[i].is_zc())
{
found_zc_input = true;
break;
}
}
if (!found_zc_input)
{
expand_selection_with_zc_input(needed_money_map, fake_outputs_count, selected_indexes);
}
}
return res;
}
//----------------------------------------------------------------------------------------------------
@ -5913,6 +5967,7 @@ uint64_t wallet2::select_indices_for_transfer(std::vector<uint64_t>& selected_in
{
WLT_LOG_GREEN("Selecting indices for transfer of " << print_money_brief(needed_money) << " with " << fake_outputs_count << " fake outs, found_free_amounts.size()=" << found_free_amounts.size() << "...", LOG_LEVEL_0);
uint64_t found_money = 0;
//uint64_t found_zc_input = false;
std::string selected_amounts_str;
while (found_money < needed_money && found_free_amounts.size())
{
@ -5934,6 +5989,7 @@ uint64_t wallet2::select_indices_for_transfer(std::vector<uint64_t>& selected_in
found_free_amounts.erase(it);
}
WLT_LOG_GREEN("Found " << print_money_brief(found_money) << " as " << selected_indexes.size() << " out(s): " << selected_amounts_str << ", found_free_amounts.size()=" << found_free_amounts.size(), LOG_LEVEL_0);
return found_money;
}
@ -6057,11 +6113,16 @@ bool wallet2::read_money_transfer2_details_from_tx(const transaction& tx, const
else if (i.type() == typeid(currency::txin_zc_input))
{
const currency::txin_zc_input& in_zc = boost::get<currency::txin_zc_input>(i);
auto it = m_key_images.find(in_zc.k_image);
//should we panic if image not found?
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it != m_key_images.end(), "[read_money_transfer2_details_from_tx]Unknown key image in tx: " << get_transaction_hash(tx));
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->second < m_transfers.size(), "[read_money_transfer2_details_from_tx]Index out of range for key image in tx: " << get_transaction_hash(tx));
wtd.spn.push_back(m_transfers[it->second].amount());
//@zoidberg: nope!
if (m_key_images.count(in_zc.k_image))
{
auto it = m_key_images.find(in_zc.k_image);
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it != m_key_images.end(), "[read_money_transfer2_details_from_tx]Unknown key image in tx: " << get_transaction_hash(tx));
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->second < m_transfers.size(), "[read_money_transfer2_details_from_tx]Index out of range for key image in tx: " << get_transaction_hash(tx));
wtd.spn.push_back(m_transfers[it->second].amount());
}
}
}
return true;
@ -6314,14 +6375,19 @@ void wallet2::prepare_tx_destinations(uint64_t needed_money,
//----------------------------------------------------------------------------------------------------
void wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx_param& ftp, const mode_separate_context& mode_separatemode_separate)
{
SET_CONTEXT_OBJ_FOR_SCOPE(pconstruct_tx_param, ctp);
SET_CONTEXT_OBJ_FOR_SCOPE(pfinalize_tx_param, ftp);
SET_CONTEXT_OBJ_FOR_SCOPE(pmode_separate_context, mode_separatemode_separate);
TIME_MEASURE_START_MS(get_needed_money_time);
const currency::transaction& tx_for_mode_separate = mode_separatemode_separate.tx_for_mode_separate;
assets_selection_context needed_money_map = get_needed_money(ctp.fee, ctp.dsts);
//
// TODO @#@# need to do refactoring over this part to support hidden amounts and asset_id
//
if (ctp.flags & TX_FLAG_SIGNATURE_MODE_SEPARATE && tx_for_mode_separate.vout.size() )
{
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(get_tx_flags(tx_for_mode_separate) & TX_FLAG_SIGNATURE_MODE_SEPARATE, "tx_param.flags differs from tx.flags");
@ -6329,6 +6395,7 @@ void wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx
{
needed_money_map[el.asset_id].needed_amount += el.amount;
}
ctp.need_at_least_1_zc = true;
}
TIME_MEASURE_FINISH_MS(get_needed_money_time);

View file

@ -300,6 +300,7 @@ namespace tools
uint8_t tx_outs_attr = 0;
bool shuffle = false;
bool perform_packing = false;
bool need_at_least_1_zc = false;
};
struct mode_separate_context
@ -469,6 +470,21 @@ namespace tools
crypto::hash related_tx_id = currency::null_hash; // tx id which caused money lock, if any (ex: escrow proposal transport tx)
};
/*
This might be not the best solution so far, but after discussion with @sowle we came up to conclusion
that passing great variety of arguments through the long call stack of different member functions of the wallet will
only complicate codebase and make it harder to understand.
current_operation_context will keep pointers to some useful data, and every function that use it, should
make sure(!!!) that pointer got nulled before pointed object got destroyed, likely by using SET_CONTEXT_OBJ_FOR_SCOPE macro
*/
struct current_operation_context
{
construct_tx_param* pconstruct_tx_param = nullptr;
currency::finalize_tx_param* pfinalize_tx_param = nullptr;
const mode_separate_context* pmode_separate_context = nullptr;
};
typedef std::unordered_multimap<std::string, payment_details> payment_container;
@ -1109,7 +1125,7 @@ private:
bool is_in_hardfork_zone(uint64_t hardfork_index) const;
uint8_t out_get_mixin_attr(const currency::tx_out_v& out_t);
const crypto::public_key& out_get_pub_key(const currency::tx_out_v& out_t, std::list<currency::htlc_info>& htlc_info_list);
bool expand_selection_with_zc_input(assets_selection_context& needed_money_map, uint64_t fake_outputs_count, std::vector<uint64_t>& selected_indexes);
void push_alias_info_to_extra_according_to_hf_status(const currency::extra_alias_entry& ai, std::vector<currency::extra_v>& extra);
void remove_transfer_from_amount_gindex_map(uint64_t tid);
@ -1174,6 +1190,8 @@ private:
mutable uint64_t m_current_wallet_file_size;
bool m_use_deffered_global_outputs;
bool m_disable_tor_relay;
mutable current_operation_context m_current_context;
//this needed to access wallets state in coretests, for creating abnormal blocks and tranmsactions
friend class test_generator;

View file

@ -380,6 +380,17 @@ namespace tools
uint64_t m_fee;
crypto::public_key m_asset_id;
};
struct no_zc_inputs : public transfer_error
{
no_zc_inputs(const std::string& /*v*/): transfer_error(std::string(""), API_RETURN_CODE_MISSING_ZC_INPUTS)
{}
virtual const char* what() const noexcept
{
return API_RETURN_CODE_MISSING_ZC_INPUTS;
}
};
//----------------------------------------------------------------------------------------------------
struct not_enough_outs_to_mix : public transfer_error
{

View file

@ -67,6 +67,14 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
alice_acc.generate();
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, alice_acc);
alice_wlt->get_account().set_createtime(0);
currency::account_base bob_acc;
bob_acc.generate();
std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, bob_acc);
bob_wlt->get_account().set_createtime(0);
miner_wlt->refresh();
currency::asset_descriptor_base adb = AUTO_VAL_INIT(adb);
@ -76,7 +84,7 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
adb.decimal_point = 12;
std::vector<currency::tx_destination_entry> destinations(2);
destinations[0].addr.push_back(miner_wlt->get_account().get_public_address());
destinations[0].addr.push_back(bob_wlt->get_account().get_public_address());
destinations[0].amount = AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC;
destinations[0].asset_id = currency::null_pkey;
destinations[1].addr.push_back(alice_wlt->get_account().get_public_address());
@ -94,16 +102,17 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
currency::transaction res_tx = AUTO_VAL_INIT(res_tx);
miner_wlt->transfer(COIN, alice_wlt->get_account().get_public_address(), res_tx);
miner_wlt->transfer(COIN, bob_wlt->get_account().get_public_address(), res_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();
bob_wlt->refresh();
alice_wlt->refresh();
uint64_t mined = 0;
std::unordered_map<crypto::public_key, tools::wallet_public::asset_balance_entry_base> balances;
miner_wlt->balance(balances, mined);
bob_wlt->balance(balances, mined);
auto it_asset = balances.find(asset_id);
auto it_native = balances.find(currency::native_coin_asset_id);
@ -111,7 +120,7 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
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(17517226)*COIN - COIN, false, "Failed to find needed asset in result balances");
CHECK_AND_ASSERT_MES(it_native->second.total == COIN, false, "Failed to find needed asset in result balances");
uint64_t mined_balance = it_native->second.total;
@ -126,9 +135,9 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances");
const uint64_t assets_to_exchange = 10 * COIN;
const uint64_t native_tokens_to_exchange = 1 * COIN;
const uint64_t native_tokens_to_exchange = COIN/2;
//alice_wlt want to trade with miner_wlt, to exchange 10.0 TCT to 1.0 ZANO
//alice_wlt want to trade with bob_wlt, to exchange 10.0 TCT to 1.0 ZANO
view::ionic_swap_proposal_info proposal_details = AUTO_VAL_INIT(proposal_details);
proposal_details.expiration_time = alice_wlt->get_core_runtime_config().get_core_time() + 10 * 60;
proposal_details.fee_paid_by_a = TESTS_DEFAULT_FEE;
@ -137,10 +146,10 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
proposal_details.to_alice.push_back(view::asset_funds{ currency::native_coin_asset_id , native_tokens_to_exchange });
tools::wallet_public::ionic_swap_proposal proposal = AUTO_VAL_INIT(proposal);
alice_wlt->create_ionic_swap_proposal(proposal_details, miner_wlt->get_account().get_public_address(), proposal);
alice_wlt->create_ionic_swap_proposal(proposal_details, bob_wlt->get_account().get_public_address(), proposal);
view::ionic_swap_proposal_info proposal_decoded_info = AUTO_VAL_INIT(proposal_decoded_info);
miner_wlt->get_ionic_swap_proposal_info(proposal, proposal_decoded_info);
bob_wlt->get_ionic_swap_proposal_info(proposal, proposal_decoded_info);
//Validate proposal
if (proposal_decoded_info.to_bob != proposal_details.to_bob
@ -153,13 +162,13 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
}
currency::transaction res_tx2 = AUTO_VAL_INIT(res_tx2);
r = miner_wlt->accept_ionic_swap_proposal(proposal, res_tx2);
r = bob_wlt->accept_ionic_swap_proposal(proposal, res_tx2);
CHECK_AND_ASSERT_MES(r, false, "Failed to accept ionic proposal");
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();
bob_wlt->refresh();
alice_wlt->refresh();
@ -170,15 +179,18 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
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->second.total == native_tokens_to_exchange, false, "Failed to find needed asset in result balances");
CHECK_AND_ASSERT_MES(it_native->second.total == native_tokens_to_exchange + COIN - TESTS_DEFAULT_FEE, false, "Failed to find needed asset in result balances");
CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC - assets_to_exchange, false, "Failed to find needed asset in result balances");
balances.clear();
miner_wlt->balance(balances, mined);
bob_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->second.total == mined_balance - native_tokens_to_exchange, false, "Failed to find needed asset in result balances");
CHECK_AND_ASSERT_MES(it_native->second.total == COIN - native_tokens_to_exchange, false, "Failed to find needed asset in result balances");
CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC + assets_to_exchange, false, "Failed to find needed asset in result balances");