forked from lthn/blockchain
Merge branch 'cryptoassets' into cake
This commit is contained in:
commit
65b9619762
11 changed files with 319 additions and 91 deletions
|
|
@ -954,21 +954,6 @@ namespace currency
|
|||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
//TODO: @val, should we call it something like schnorr_sig ?
|
||||
struct simple_sig
|
||||
{
|
||||
crypto::signature s;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(s)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(s)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
|
||||
struct void_sig
|
||||
{
|
||||
//TODO:
|
||||
|
|
|
|||
|
|
@ -246,8 +246,8 @@
|
|||
#define WALLET_FILE_SERIALIZATION_VERSION 160
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION 160
|
||||
#else
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION (CURRENCY_FORMATION_VERSION+73)
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+73)
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION (CURRENCY_FORMATION_VERSION+74)
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+74)
|
||||
#endif
|
||||
|
||||
#define CURRENT_MEMPOOL_ARCHIVE_VER (CURRENCY_FORMATION_VERSION+31)
|
||||
|
|
|
|||
|
|
@ -277,10 +277,10 @@ namespace currency
|
|||
bare_inputs_sum += tk.amount;
|
||||
VARIANT_CASE_CONST(txin_htlc, foo);
|
||||
CHECK_AND_ASSERT_MES(false, false, "unexpected txin_htlc input");
|
||||
VARIANT_CASE_CONST(txin_multisig, ms);
|
||||
VARIANT_CASE_CONST(txin_multisig, ms);
|
||||
//bare_inputs_sum += ms.amount;
|
||||
CHECK_AND_ASSERT_MES(false, false, "unexpected txin_multisig input"); // TODO @#@# check support for multisig inputs
|
||||
VARIANT_CASE_CONST(txin_zc_input, foo);
|
||||
VARIANT_CASE_CONST(txin_zc_input, foo);
|
||||
++zc_inputs_count;
|
||||
VARIANT_SWITCH_END();
|
||||
}
|
||||
|
|
@ -1179,11 +1179,11 @@ namespace currency
|
|||
out.encrypted_amount = de.amount ^ amount_mask.m_u64[0];
|
||||
|
||||
CHECK_AND_ASSERT_MES(~de.flags & tx_destination_entry_flags::tdef_explicit_native_asset_id || de.asset_id == currency::native_coin_asset_id, false, "explicit_native_asset_id may be used only with native asset id");
|
||||
asset_blinding_mask = de.flags & tx_destination_entry_flags::tdef_explicit_native_asset_id ? 0 : crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_ASSET_BLINDING_MASK, h); // f = Hs(domain_sep, d, i)
|
||||
asset_blinding_mask = de.flags & tx_destination_entry_flags::tdef_explicit_native_asset_id ? 0 : crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_ASSET_BLINDING_MASK, h); // s = Hs(domain_sep, Hs(8 * r * V, i))
|
||||
blinded_asset_id = crypto::point_t(de.asset_id) + asset_blinding_mask * crypto::c_point_X;
|
||||
out.blinded_asset_id = (crypto::c_scalar_1div8 * blinded_asset_id).to_public_key(); // T = 1/8 * (H_asset + s * X)
|
||||
|
||||
amount_blinding_mask = de.flags & tx_destination_entry_flags::tdef_zero_amount_blinding_mask ? 0 : crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_BLINDING_MASK, h); // f = Hs(domain_sep, d, i)
|
||||
amount_blinding_mask = de.flags & tx_destination_entry_flags::tdef_zero_amount_blinding_mask ? 0 : crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_BLINDING_MASK, h); // y = Hs(domain_sep, Hs(8 * r * V, i))
|
||||
amount_commitment = de.amount * blinded_asset_id + amount_blinding_mask * crypto::c_point_G;
|
||||
out.amount_commitment = (crypto::c_scalar_1div8 * amount_commitment).to_public_key(); // E = 1/8 * e * T + 1/8 * y * G
|
||||
|
||||
|
|
@ -1203,19 +1203,24 @@ namespace currency
|
|||
out.encrypted_amount = de.amount ^ amount_mask.m_u64[0];
|
||||
|
||||
CHECK_AND_ASSERT_MES(~de.flags & tx_destination_entry_flags::tdef_explicit_native_asset_id || de.asset_id == currency::native_coin_asset_id, false, "explicit_native_asset_id may be used only with native asset id");
|
||||
asset_blinding_mask = de.flags & tx_destination_entry_flags::tdef_explicit_native_asset_id ? 0 : crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_ASSET_BLINDING_MASK, h); // f = Hs(domain_sep, d, i)
|
||||
asset_blinding_mask = de.flags & tx_destination_entry_flags::tdef_explicit_native_asset_id ? 0 : crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_ASSET_BLINDING_MASK, h); // s = Hs(domain_sep, Hs(8 * r * V, i))
|
||||
blinded_asset_id = crypto::point_t(de.asset_id) + asset_blinding_mask * crypto::c_point_X;
|
||||
out.blinded_asset_id = (crypto::c_scalar_1div8 * blinded_asset_id).to_public_key(); // T = 1/8 * (H_asset + s * X)
|
||||
|
||||
amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_BLINDING_MASK, h); // f = Hs(domain_sep, d, i)
|
||||
amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_BLINDING_MASK, h); // y = Hs(domain_sep, Hs(8 * r * V, i))
|
||||
amount_commitment = de.amount * blinded_asset_id + amount_blinding_mask * crypto::c_point_G;
|
||||
out.amount_commitment = (crypto::c_scalar_1div8 * amount_commitment).to_public_key(); // E = 1/8 * e * T + 1/8 * y * G
|
||||
|
||||
//LOG_PRINT_CYAN("OUT " << std::setw(2) << output_index << ": " << de.asset_id << " + " << asset_blinding_mask << " x X", LOG_LEVEL_0);
|
||||
//LOG_PRINT_CYAN(" == " << blinded_asset_id, LOG_LEVEL_0);
|
||||
//LOG_PRINT_CYAN("OUT " << std::setw(2) << output_index << ": " << crypto::scalar_t(de.amount) << " x " << blinded_asset_id << " + " << amount_blinding_mask << " x G", LOG_LEVEL_0);
|
||||
//LOG_PRINT_CYAN(" == " << amount_commitment << ", x 1/8 == " << out.amount_commitment, LOG_LEVEL_0);
|
||||
|
||||
DBG_VAL_PRINT(output_index);
|
||||
DBG_VAL_PRINT(de.amount);
|
||||
DBG_VAL_PRINT(de.asset_id);
|
||||
DBG_VAL_PRINT(amount_mask);
|
||||
DBG_VAL_PRINT(asset_blinding_mask);
|
||||
DBG_VAL_PRINT(blinded_asset_id);
|
||||
DBG_VAL_PRINT(amount_blinding_mask);
|
||||
DBG_VAL_PRINT(amount_mask);
|
||||
DBG_VAL_PRINT(amount_commitment);
|
||||
|
||||
if (de.addr.front().is_auditable())
|
||||
out.mix_attr = CURRENCY_TO_KEY_OUT_FORCED_NO_MIX; // override mix_attr to 1 for auditable target addresses
|
||||
else
|
||||
|
|
@ -1942,7 +1947,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 uint64_t tx_flags, tx_generation_context& ogc, transaction& tx, bool last_output)
|
||||
const account_keys& sender_account_keys, const uint64_t tx_flags, tx_generation_context& ogc, transaction& tx, bool last_output, bool separately_signed_tx_complete)
|
||||
{
|
||||
bool watch_only_mode = sender_account_keys.spend_secret_key == null_skey;
|
||||
CHECK_AND_ASSERT_MES(se.is_zc(), false, "sources contains a non-zc input");
|
||||
|
|
@ -1970,10 +1975,10 @@ namespace currency
|
|||
|
||||
crypto::scalar_t pseudo_out_amount_blinding_mask = 0;
|
||||
crypto::scalar_t pseudo_out_asset_id_blinding_mask = crypto::scalar_t::random();
|
||||
if ((last_output && (tx_flags & TX_FLAG_SIGNATURE_MODE_SEPARATE) == 0) || se.separately_signed_tx_complete)
|
||||
if (last_output && ((tx_flags & TX_FLAG_SIGNATURE_MODE_SEPARATE) == 0 || 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
|
||||
pseudo_out_amount_blinding_mask = ogc.amount_blinding_masks_sum - ogc.pseudo_out_amount_blinding_masks_sum + (ogc.ao_commitment_in_outputs ? ogc.ao_amount_blinding_mask : -ogc.ao_amount_blinding_mask); // A_1 - A^p_0 = (f_1 - f'_1) * G => f'_{i-1} = sum{y_j} - sum{f'_i}
|
||||
pseudo_out_amount_blinding_mask = ogc.amount_blinding_masks_sum - ogc.pseudo_out_amount_blinding_masks_sum + (ogc.ao_commitment_in_outputs ? ogc.ao_amount_blinding_mask : -ogc.ao_amount_blinding_mask); // A_1 - A^p_0 = (f_1 - f'_1) * G => f'_{i-1} = sum{y_j} - sum{f'_i}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1981,6 +1986,16 @@ namespace currency
|
|||
ogc.pseudo_out_amount_blinding_masks_sum += pseudo_out_amount_blinding_mask;
|
||||
}
|
||||
|
||||
DBG_VAL_PRINT("ZC sig generation");
|
||||
DBG_VAL_PRINT(input_index);
|
||||
DBG_VAL_PRINT(source_blinded_asset_id);
|
||||
DBG_VAL_PRINT(pseudo_out_asset_id_blinding_mask);
|
||||
DBG_VAL_PRINT(se.real_out_amount_blinding_mask);
|
||||
DBG_VAL_PRINT(se.real_out_asset_id_blinding_mask);
|
||||
DBG_VAL_PRINT(se.asset_id);
|
||||
DBG_VAL_PRINT(se.amount);
|
||||
DBG_VAL_PRINT(pseudo_out_amount_blinding_mask);
|
||||
|
||||
crypto::point_t pseudo_out_blinded_asset_id = source_blinded_asset_id + pseudo_out_asset_id_blinding_mask * crypto::c_point_X; // T^p_i = T_i + r'_i * X
|
||||
sig.pseudo_out_blinded_asset_id = (crypto::c_scalar_1div8 * pseudo_out_blinded_asset_id).to_public_key();
|
||||
ogc.real_in_asset_id_blinding_mask_x_amount_sum += se.real_out_asset_id_blinding_mask * se.amount; // += r_i * a_i
|
||||
|
|
@ -1991,11 +2006,6 @@ namespace currency
|
|||
sig.pseudo_out_amount_commitment = (crypto::c_scalar_1div8 * pseudo_out_amount_commitment).to_public_key();
|
||||
ogc.pseudo_out_amount_commitments_sum += pseudo_out_amount_commitment;
|
||||
|
||||
//LOG_PRINT_CYAN("SBAID " << ": " << asset_id_pt << " + " << se.real_out_asset_id_blinding_mask << " x X", LOG_LEVEL_0);
|
||||
//LOG_PRINT_CYAN(" == " << source_blinded_asset_id, LOG_LEVEL_0);
|
||||
//LOG_PRINT_CYAN("POAM " << ": " << crypto::scalar_t(se.amount) << " x " << source_blinded_asset_id << " + " << pseudo_out_amount_blinding_mask << " x G", LOG_LEVEL_0);
|
||||
//LOG_PRINT_CYAN(" == " << pseudo_out_amount_commitment << ", x 1/8 == " << sig.pseudo_out_amount_commitment, LOG_LEVEL_0);
|
||||
|
||||
// = three-layers ring signature data outline =
|
||||
// (j in [0, ring_size-1])
|
||||
// layer 0 ring
|
||||
|
|
@ -2095,6 +2105,25 @@ namespace currency
|
|||
p_result_point->to_public_key(*p_result_pub_key);
|
||||
}
|
||||
|
||||
const asset_descriptor_base& get_native_coin_asset_descriptor()
|
||||
{
|
||||
static asset_descriptor_base native_coin_asset_descriptor = [](){
|
||||
asset_descriptor_base adb{};
|
||||
adb.total_max_supply = UINT64_MAX;
|
||||
adb.current_supply = 0;
|
||||
adb.decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT;
|
||||
adb.ticker = CURRENCY_NAME_ABR;
|
||||
adb.full_name = CURRENCY_NAME_BASE;
|
||||
adb.meta_info = "";
|
||||
adb.owner = currency::null_pkey;
|
||||
adb.hidden_supply = false;
|
||||
adb.version = 0;
|
||||
return adb;
|
||||
}();
|
||||
|
||||
return native_coin_asset_descriptor;
|
||||
}
|
||||
|
||||
bool construct_tx_handle_ado(const account_keys& sender_account_keys,
|
||||
const finalize_tx_param& ftp,
|
||||
asset_descriptor_operation& ado,
|
||||
|
|
@ -2262,7 +2291,6 @@ namespace currency
|
|||
bool has_non_zc_inputs = false;
|
||||
|
||||
std::list<crypto::key_image> key_images_total;
|
||||
size_t thirdparty_zc_inputs_count = zc_inputs_count;
|
||||
//
|
||||
// INs
|
||||
//
|
||||
|
|
@ -2489,7 +2517,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 (!append_mode && all_inputs_are_obviously_native_coins && gen_context.ao_asset_id == currency::null_pkey)
|
||||
if (!(flags & TX_FLAG_SIGNATURE_MODE_SEPARATE) && 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)
|
||||
|
||||
r = construct_tx_out(dst_entr, txkey.sec, output_index, tx, deriv_cache, sender_account_keys,
|
||||
|
|
@ -2580,7 +2608,8 @@ namespace currency
|
|||
|
||||
// ring signatures (per-input proofs)
|
||||
r = false;
|
||||
size_t curren_zc_index = thirdparty_zc_inputs_count;
|
||||
bool separately_signed_tx_complete = !sources.empty() ? sources.back().separately_signed_tx_complete : false;
|
||||
size_t zc_input_index = 0;
|
||||
for (size_t i_ = 0; i_ != sources.size(); i_++)
|
||||
{
|
||||
size_t i_mapped = inputs_mapping[i_];
|
||||
|
|
@ -2592,11 +2621,10 @@ namespace currency
|
|||
if (source_entry.is_zc())
|
||||
{
|
||||
// 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_mapped], sender_account_keys, flags, gen_context, tx, i_ + 1 == sources.size());
|
||||
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(), separately_signed_tx_complete);
|
||||
CHECK_AND_ASSERT_MES(r, false, "generate_ZC_sigs failed");
|
||||
gen_context.zc_input_amounts[curren_zc_index] = source_entry.amount;
|
||||
curren_zc_index++;
|
||||
gen_context.zc_input_amounts[zc_input_index] = source_entry.amount;
|
||||
zc_input_index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -329,8 +329,7 @@ namespace currency
|
|||
uint64_t get_tx_version(uint64_t tx_expected_block_height, const hard_forks_descriptor& hfd); // returns tx version based on the height of the block where the transaction is expected to be
|
||||
bool construct_tx(const account_keys& sender_account_keys, const finalize_tx_param& param, finalized_tx& result);
|
||||
void calculate_asset_id(const crypto::public_key& asset_owner, crypto::point_t* p_result_point, crypto::public_key* p_result_pub_key);
|
||||
|
||||
|
||||
const asset_descriptor_base& get_native_coin_asset_descriptor();
|
||||
|
||||
bool sign_multisig_input_in_tx(currency::transaction& tx, size_t ms_input_index, const currency::account_keys& keys, const currency::transaction& source_tx, bool *p_is_input_fully_signed = nullptr);
|
||||
|
||||
|
|
|
|||
|
|
@ -269,7 +269,8 @@ simple_wallet::simple_wallet()
|
|||
m_cmd_binder.set_handler("incoming_counts", boost::bind(&simple_wallet::show_incoming_transfers_counts, this, ph::_1), "incoming_transfers counts");
|
||||
m_cmd_binder.set_handler("list_recent_transfers", boost::bind(&simple_wallet::list_recent_transfers, this, ph::_1), "list_recent_transfers [offset] [count] - Show recent maximum 1000 transfers, offset default = 0, count default = 100 ");
|
||||
m_cmd_binder.set_handler("export_recent_transfers", boost::bind(&simple_wallet::export_recent_transfers, this, ph::_1), "list_recent_transfers_tx - Write recent transfer in json to wallet_recent_transfers.txt");
|
||||
m_cmd_binder.set_handler("list_outputs", boost::bind(&simple_wallet::list_outputs, this, ph::_1), "list_outputs [spent|unspent] - Lists all the outputs that have ever been sent to this wallet if called without arguments, otherwise it lists only the spent or unspent outputs");
|
||||
m_cmd_binder.set_handler("list_outputs", boost::bind(&simple_wallet::list_outputs, this, ph::_1), "list_outputs [spent|unspent] [ticker=ZANO] [unknown] - Lists all the outputs. The result may be filtered by spent status, asset ticker or unknown asset ids.");
|
||||
m_cmd_binder.set_handler("lo", boost::bind(&simple_wallet::list_outputs, this, ph::_1), "alias for list_outputs");
|
||||
m_cmd_binder.set_handler("dump_transfers", boost::bind(&simple_wallet::dump_trunsfers, this, ph::_1), "dump_transfers - Write transfers in json to dump_transfers.txt");
|
||||
m_cmd_binder.set_handler("dump_keyimages", boost::bind(&simple_wallet::dump_key_images, this, ph::_1), "dump_keyimages - Write key_images in json to dump_key_images.txt");
|
||||
m_cmd_binder.set_handler("payments", boost::bind(&simple_wallet::show_payments, this, ph::_1), "payments <payment_id_1> [<payment_id_2> ... <payment_id_N>] - Show payments <payment_id_1>, ... <payment_id_N>");
|
||||
|
|
@ -1775,28 +1776,36 @@ bool simple_wallet::save_watch_only(const std::vector<std::string> &args)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::list_outputs(const std::vector<std::string> &args)
|
||||
{
|
||||
if (args.size() > 1)
|
||||
{
|
||||
fail_msg_writer() << "invalid syntax: one or none parameters are expected, " << args.size() << " was given";
|
||||
return true;
|
||||
}
|
||||
bool include_spent = true, include_unspent = true, show_only_unknown = false;
|
||||
std::string filter_asset_ticker{};
|
||||
|
||||
bool include_spent = true, include_unspent = true;
|
||||
if (args.size() == 1)
|
||||
{
|
||||
if (args[0] == "unspent" || args[0] == "available")
|
||||
include_spent = false;
|
||||
else if (args[0] == "spent" || args[0] == "unavailable")
|
||||
include_unspent = false;
|
||||
bool arg_spent_flags = false, arg_unknown_assets = false, arg_ticker_filer = false;
|
||||
|
||||
auto process_arg = [&](const std::string& arg) -> bool {
|
||||
if (!arg_spent_flags && (arg == "u" || arg == "unspent" || arg == "available"))
|
||||
arg_spent_flags = true, include_spent = false;
|
||||
else if (!arg_spent_flags && (arg == "s" || arg == "spent" || arg == "unavailable"))
|
||||
arg_spent_flags = true, include_unspent = false;
|
||||
else if (!arg_unknown_assets && (arg == "unknown"))
|
||||
arg_unknown_assets = true, show_only_unknown = true;
|
||||
else if (!arg_ticker_filer && (arg.find("ticker=") == 0 || arg.find("t=") == 0))
|
||||
arg_ticker_filer = true, filter_asset_ticker = boost::erase_all_copy(boost::erase_all_copy(arg, "ticker="), "t=");
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
for(auto& arg : args)
|
||||
{
|
||||
if (!process_arg(arg))
|
||||
{
|
||||
fail_msg_writer() << "invalid parameter: " << args[0];
|
||||
fail_msg_writer() << "invalid parameter: " << arg;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
success_msg_writer() << "list of all the outputs that have ever been sent to this wallet:" << ENDL <<
|
||||
m_wallet->get_transfers_str(include_spent, include_unspent);
|
||||
success_msg_writer() << m_wallet->get_transfers_str(include_spent, include_unspent, show_only_unknown, filter_asset_ticker);
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@
|
|||
#define PROJECT_REVISION "0"
|
||||
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
|
||||
|
||||
#define PROJECT_VERSION_BUILD_NO 235
|
||||
#define PROJECT_VERSION_BUILD_NO 237
|
||||
#define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO)
|
||||
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]"
|
||||
|
|
|
|||
|
|
@ -2842,6 +2842,7 @@ bool wallet2::reset_all()
|
|||
m_last_pow_block_h = 0;
|
||||
m_current_wallet_file_size = 0;
|
||||
m_custom_assets.clear();
|
||||
m_own_asset_descriptors.clear();
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
@ -3478,7 +3479,9 @@ bool wallet2::get_asset_id_info(const crypto::public_key& asset_id, currency::as
|
|||
{
|
||||
if (asset_id == currency::native_coin_asset_id)
|
||||
{
|
||||
return CURRENCY_NAME_ABR;
|
||||
asset_info = currency::get_native_coin_asset_descriptor();
|
||||
whitelist_ = true;
|
||||
return true;
|
||||
}
|
||||
//check if asset is whitelisted or customly added
|
||||
whitelist_ = false;
|
||||
|
|
@ -3588,12 +3591,13 @@ bool wallet2::generate_utxo_defragmentation_transaction_if_needed(currency::tran
|
|||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool include_unspent /*= true*/) const
|
||||
std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool include_unspent /*= true*/, bool show_only_unknown /*= false*/, const std::string& filter_asset_ticker /*= std::string{}*/) const
|
||||
{
|
||||
static const char* header = "index amount g_index flags block tx out# key image";
|
||||
static const char* header = "index amount ticker g_index flags block tx out# asset id";
|
||||
std::stringstream ss;
|
||||
ss << header << ENDL;
|
||||
size_t count = 0;
|
||||
size_t unknown_assets_outs_count = 0;
|
||||
for (size_t i = 0; i != m_transfers.size(); ++i)
|
||||
{
|
||||
const transfer_details& td = m_transfers[i];
|
||||
|
|
@ -3601,21 +3605,44 @@ std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool inclu
|
|||
if ((td.is_spent() && !include_spent) || (!td.is_spent() && !include_unspent))
|
||||
continue;
|
||||
|
||||
bool native_coin = td.is_native_coin();
|
||||
asset_descriptor_base adb{};
|
||||
bool whitelisted = false;
|
||||
if (get_asset_id_info(td.get_asset_id(), adb, whitelisted) == show_only_unknown)
|
||||
{
|
||||
if (!show_only_unknown)
|
||||
++unknown_assets_outs_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!filter_asset_ticker.empty() && adb.ticker != filter_asset_ticker)
|
||||
continue;
|
||||
|
||||
ss << std::right <<
|
||||
std::setw(5) << i << " " <<
|
||||
std::setw(21) << print_money(td.amount()) << " " <<
|
||||
std::setw(21) << print_asset_money(td.m_amount, adb.decimal_point) << " " <<
|
||||
std::setw(6) << std::left << (native_coin ? std::string(" ") : adb.ticker) << " " << std::right <<
|
||||
std::setw(7) << td.m_global_output_index << " " <<
|
||||
std::setw(2) << std::setfill('0') << td.m_flags << std::setfill(' ') << ":" <<
|
||||
std::setw(5) << transfer_flags_to_str(td.m_flags) << " " <<
|
||||
std::setw(7) << td.m_ptx_wallet_info->m_block_height << " " <<
|
||||
get_transaction_hash(td.m_ptx_wallet_info->m_tx) << " " <<
|
||||
std::setw(4) << td.m_internal_output_index << " " <<
|
||||
td.m_key_image << ENDL;
|
||||
std::setw(4) << td.m_internal_output_index << " ";
|
||||
if (native_coin)
|
||||
ss << " ";
|
||||
else
|
||||
ss << td.get_asset_id();
|
||||
|
||||
ss << ENDL;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
ss << "printed " << count << " outputs of " << m_transfers.size() << " total" << ENDL;
|
||||
if (unknown_assets_outs_count == 1)
|
||||
ss << "(" << unknown_assets_outs_count << " output with unrecognized asset id is not shown, use 'list_outputs unknown' to see it)" << ENDL;
|
||||
else if (unknown_assets_outs_count > 1)
|
||||
ss << "(" << unknown_assets_outs_count << " outputs with unrecognized asset ids are not shown, use 'list_outputs unknown' to see them)" << ENDL;
|
||||
return ss.str();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
@ -6600,6 +6627,7 @@ void wallet2::prepare_tx_destinations(const assets_selection_context& needed_mon
|
|||
detail::split_strategy_id_t destination_split_strategy_id,
|
||||
const tx_dust_policy& dust_policy,
|
||||
const std::vector<currency::tx_destination_entry>& dsts,
|
||||
uint8_t tx_flags,
|
||||
std::vector<currency::tx_destination_entry>& final_destinations)
|
||||
{
|
||||
|
||||
|
|
@ -6611,7 +6639,7 @@ void wallet2::prepare_tx_destinations(const assets_selection_context& needed_mon
|
|||
std::unordered_set<crypto::public_key> processed_assets;
|
||||
for (auto& el: needed_money_map)
|
||||
{
|
||||
prepare_tx_destinations(el.second.needed_amount, el.second.found_amount, destination_split_strategy_id, dust_policy, dsts, final_destinations, el.first);
|
||||
prepare_tx_destinations(el.second.needed_amount, el.second.found_amount, destination_split_strategy_id, dust_policy, dsts, el.first, final_destinations);
|
||||
processed_assets.insert(el.first);
|
||||
}
|
||||
|
||||
|
|
@ -6635,23 +6663,26 @@ void wallet2::prepare_tx_destinations(const assets_selection_context& needed_mon
|
|||
}
|
||||
}
|
||||
|
||||
if (final_destinations.empty())
|
||||
if (!(tx_flags & TX_FLAG_SIGNATURE_MODE_SEPARATE))
|
||||
{
|
||||
// if there's no destinations -- make CURRENCY_TX_MIN_ALLOWED_OUTS empty destinations
|
||||
for(size_t i = 0; i < CURRENCY_TX_MIN_ALLOWED_OUTS; ++i)
|
||||
final_destinations.emplace_back(0, m_account.get_public_address());
|
||||
}
|
||||
else if (final_destinations.size() < CURRENCY_TX_MIN_ALLOWED_OUTS)
|
||||
{
|
||||
// if there's not ehough destinations items (i.e. outputs), split the last one
|
||||
tx_destination_entry de = final_destinations.back();
|
||||
final_destinations.pop_back();
|
||||
size_t items_to_be_added = CURRENCY_TX_MIN_ALLOWED_OUTS - final_destinations.size();
|
||||
// TODO: consider allowing to set them somewhere
|
||||
size_t num_digits_to_keep = CURRENCY_TX_OUTS_RND_SPLIT_DIGITS_TO_KEEP;
|
||||
decompose_amount_randomly(de.amount, [&](uint64_t amount){ de.amount = amount; final_destinations.push_back(de); }, items_to_be_added, num_digits_to_keep);
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(final_destinations.size() == CURRENCY_TX_MIN_ALLOWED_OUTS,
|
||||
"can't get necessary number of outputs using decompose_amount_randomly(), got " << final_destinations.size() << " while mininum is " << CURRENCY_TX_MIN_ALLOWED_OUTS);
|
||||
if (final_destinations.empty())
|
||||
{
|
||||
// if there's no destinations -- make CURRENCY_TX_MIN_ALLOWED_OUTS empty destinations
|
||||
for(size_t i = 0; i < CURRENCY_TX_MIN_ALLOWED_OUTS; ++i)
|
||||
final_destinations.emplace_back(0, m_account.get_public_address());
|
||||
}
|
||||
else if (final_destinations.size() < CURRENCY_TX_MIN_ALLOWED_OUTS)
|
||||
{
|
||||
// if there's not ehough destinations items (i.e. outputs), split the last one
|
||||
tx_destination_entry de = final_destinations.back();
|
||||
final_destinations.pop_back();
|
||||
size_t items_to_be_added = CURRENCY_TX_MIN_ALLOWED_OUTS - final_destinations.size();
|
||||
// TODO: consider allowing to set them somewhere
|
||||
size_t num_digits_to_keep = CURRENCY_TX_OUTS_RND_SPLIT_DIGITS_TO_KEEP;
|
||||
decompose_amount_randomly(de.amount, [&](uint64_t amount){ de.amount = amount; final_destinations.push_back(de); }, items_to_be_added, num_digits_to_keep);
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(final_destinations.size() == CURRENCY_TX_MIN_ALLOWED_OUTS,
|
||||
"can't get necessary number of outputs using decompose_amount_randomly(), got " << final_destinations.size() << " while mininum is " << CURRENCY_TX_MIN_ALLOWED_OUTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6661,7 +6692,8 @@ void wallet2::prepare_tx_destinations(uint64_t needed_money,
|
|||
detail::split_strategy_id_t destination_split_strategy_id,
|
||||
const tx_dust_policy& dust_policy,
|
||||
const std::vector<currency::tx_destination_entry>& dsts,
|
||||
std::vector<currency::tx_destination_entry>& final_destinations, const crypto::public_key& asset_id)
|
||||
const crypto::public_key& asset_id,
|
||||
std::vector<currency::tx_destination_entry>& final_destinations)
|
||||
{
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(found_money >= needed_money, "needed_money==" << needed_money << " < found_money==" << found_money);
|
||||
|
||||
|
|
@ -6767,7 +6799,7 @@ bool wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx
|
|||
TIME_MEASURE_FINISH_MS(prepare_tx_sources_time);
|
||||
|
||||
TIME_MEASURE_START_MS(prepare_tx_destinations_time);
|
||||
prepare_tx_destinations(needed_money_map, static_cast<detail::split_strategy_id_t>(ctp.split_strategy_id), ctp.dust_policy, ctp.dsts, ftp.prepared_destinations);
|
||||
prepare_tx_destinations(needed_money_map, static_cast<detail::split_strategy_id_t>(ctp.split_strategy_id), ctp.dust_policy, ctp.dsts, ctp.flags, ftp.prepared_destinations);
|
||||
TIME_MEASURE_FINISH_MS(prepare_tx_destinations_time);
|
||||
|
||||
|
||||
|
|
@ -7219,7 +7251,7 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public
|
|||
assets_selection_context needed_money_map;
|
||||
needed_money_map[currency::native_coin_asset_id] = {};
|
||||
std::vector<currency::tx_destination_entry> dsts({ tx_destination_entry(amount_swept - fee, destination_addr) });
|
||||
prepare_tx_destinations(needed_money_map, get_current_split_strategy(), tools::tx_dust_policy(), dsts, ftp.prepared_destinations);
|
||||
prepare_tx_destinations(needed_money_map, get_current_split_strategy(), tools::tx_dust_policy(), ftp.prepared_destinations, ftp.flags, dsts);
|
||||
|
||||
currency::transaction tx = AUTO_VAL_INIT(tx);
|
||||
crypto::secret_key tx_key = AUTO_VAL_INIT(tx_key);
|
||||
|
|
|
|||
|
|
@ -833,7 +833,7 @@ namespace tools
|
|||
bool fill_mining_context(mining_context& ctx);
|
||||
|
||||
void get_transfers(wallet2::transfer_container& incoming_transfers) const;
|
||||
std::string get_transfers_str(bool include_spent = true, bool include_unspent = true) const;
|
||||
std::string get_transfers_str(bool include_spent = true, bool include_unspent = true, bool show_only_unknown = false, const std::string& filter_asset_ticker = std::string{}) const;
|
||||
std::string get_balance_str() const;
|
||||
|
||||
// Returns all payments by given id in unspecified order
|
||||
|
|
@ -1110,13 +1110,15 @@ private:
|
|||
detail::split_strategy_id_t destination_split_strategy_id,
|
||||
const tx_dust_policy& dust_policy,
|
||||
const std::vector<currency::tx_destination_entry>& dsts,
|
||||
uint8_t tx_flags,
|
||||
std::vector<currency::tx_destination_entry>& final_destinations);
|
||||
void prepare_tx_destinations(uint64_t needed_money,
|
||||
uint64_t found_money,
|
||||
detail::split_strategy_id_t destination_split_strategy_id,
|
||||
const tx_dust_policy& dust_policy,
|
||||
const std::vector<currency::tx_destination_entry>& dsts,
|
||||
std::vector<currency::tx_destination_entry>& final_detinations, const crypto::public_key& asset_id);
|
||||
const crypto::public_key& asset_id,
|
||||
std::vector<currency::tx_destination_entry>& final_detinations);
|
||||
bool handle_contract(wallet_public::wallet_transfer_info& wti, const bc_services::contract_private_details& cntr, const std::vector<currency::payload_items_v>& decrypted_attach);
|
||||
bool handle_release_contract(wallet_public::wallet_transfer_info& wti, const std::string& release_instruction);
|
||||
bool handle_cancel_proposal(wallet_public::wallet_transfer_info& wti, const bc_services::escrow_cancel_templates_body& ectb, const std::vector<currency::payload_items_v>& decrypted_attach);
|
||||
|
|
|
|||
|
|
@ -1250,7 +1250,8 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(zarcanum_basic_test);
|
||||
|
||||
GENERATE_AND_PLAY_HF(multiassets_basic_test, "4-*");
|
||||
GENERATE_AND_PLAY(ionic_swap_basic_test);
|
||||
GENERATE_AND_PLAY(ionic_swap_basic_test);
|
||||
GENERATE_AND_PLAY_HF(ionic_swap_exact_amounts_test, "4-*");
|
||||
GENERATE_AND_PLAY(zarcanum_test_n_inputs_validation);
|
||||
GENERATE_AND_PLAY(zarcanum_gen_time_balance);
|
||||
GENERATE_AND_PLAY(zarcanum_txs_with_big_shuffled_decoy_set_shuffled);
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@ 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 = bob_wlt->accept_ionic_swap_proposal(proposal, res_tx2);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to accept ionic proposal");
|
||||
CHECK_AND_ASSERT_MES(check_ionic_swap_tx_outs(m_accounts, res_tx2, bob_wlt, proposal), false, "");
|
||||
}
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
|
@ -293,3 +294,167 @@ bool ionic_swap_basic_test::c1(currency::core& c, size_t ev_index, const std::ve
|
|||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
ionic_swap_exact_amounts_test::ionic_swap_exact_amounts_test()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(ionic_swap_exact_amounts_test, c1);
|
||||
}
|
||||
|
||||
bool ionic_swap_exact_amounts_test::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
currency::account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
currency::account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
|
||||
currency::account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc.generate(); bob_acc.set_createtime(ts);
|
||||
currency::account_base& carol_acc = m_accounts[CAROL_ACC_IDX]; carol_acc.generate(); carol_acc.set_createtime(ts);
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
|
||||
|
||||
// rebuild genesis miner tx
|
||||
std::vector<tx_destination_entry> destinations;
|
||||
destinations.emplace_back(MK_TEST_COINS(21), alice_acc.get_public_address());
|
||||
destinations.emplace_back(MK_TEST_COINS(21), miner_acc.get_public_address()); // decoy (later Alice will spend her output using mixins)
|
||||
destinations.emplace_back(MK_TEST_COINS(21), miner_acc.get_public_address()); // decoy
|
||||
destinations.emplace_back(COIN, miner_acc.get_public_address());
|
||||
// leftover amount will be also send to miner
|
||||
CHECK_AND_ASSERT_MES(replace_coinbase_in_genesis_block(destinations, generator, events, blk_0), false, "");
|
||||
|
||||
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
|
||||
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1);
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_hardfork_active", static_cast<size_t>(ZANO_HARDFORK_04_ZARCANUM));
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ionic_swap_exact_amounts_test::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
bool r = false;
|
||||
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX);
|
||||
miner_wlt->refresh();
|
||||
|
||||
asset_descriptor_base adb{};
|
||||
adb.total_max_supply = 10000000000;
|
||||
adb.full_name = "test";
|
||||
adb.ticker = "TEST";
|
||||
|
||||
std::vector<currency::tx_destination_entry> destinations;
|
||||
destinations.emplace_back(7070000000, m_accounts[BOB_ACC_IDX].get_public_address(), null_pkey);
|
||||
destinations.emplace_back(2930000000, m_accounts[BOB_ACC_IDX].get_public_address(), null_pkey);
|
||||
destinations.emplace_back(MK_TEST_COINS(21), m_accounts[CAROL_ACC_IDX].get_public_address()); // Carol will get coins with non-explicit asset id
|
||||
|
||||
currency::transaction tx{};
|
||||
crypto::public_key asset_id = currency::null_pkey;
|
||||
miner_wlt->deploy_new_asset(adb, destinations, tx, asset_id);
|
||||
LOG_PRINT_L0("Deployed new asset: " << asset_id << ", tx_id: " << currency::get_transaction_hash(tx));
|
||||
|
||||
CHECK_AND_ASSERT_MES(tx.vout.size() >= 2, false, "Unexpected vout size: " << tx.vout.size());
|
||||
for(auto& out : tx.vout)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(out.type() == typeid(tx_out_zarcanum), false, "invalid out type");
|
||||
CHECK_AND_ASSERT_MES(boost::get<tx_out_zarcanum>(out).blinded_asset_id != native_coin_asset_id_1div8, false, "One of outputs has explicit native asset id, which is unexpected");
|
||||
}
|
||||
|
||||
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_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX);
|
||||
alice_wlt->refresh();
|
||||
std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, BOB_ACC_IDX);
|
||||
bob_wlt->refresh();
|
||||
std::shared_ptr<tools::wallet2> carol_wlt = init_playtime_test_wallet(events, c, CAROL_ACC_IDX);
|
||||
carol_wlt->refresh();
|
||||
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", MK_TEST_COINS(21), MK_TEST_COINS(21), MK_TEST_COINS(21), 0, 0), false, "");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt, "Bob", adb.total_max_supply, 0, adb.total_max_supply, 0, 0, asset_id), false, "");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*carol_wlt, "Carol", MK_TEST_COINS(21), 0, MK_TEST_COINS(21), 0, 0), false, "");
|
||||
|
||||
size_t current_blockchain_size = c.get_current_blockchain_size();
|
||||
|
||||
// Normal ionic swap between Alice and Bob: (Alice has only coins with explicit asset id)
|
||||
// before:
|
||||
// Alice (initiator): 0.21 ZANO < - > Bob (finalizer): 0.01 TEST
|
||||
// after:
|
||||
// Alice (initiator): 0.01 TEST Bob (finalizer): 0.20 ZANO
|
||||
|
||||
view::ionic_swap_proposal_info proposal_details{};
|
||||
proposal_details.to_initiator.push_back(view::asset_funds{ asset_id, adb.total_max_supply });
|
||||
proposal_details.to_finalizer.push_back(view::asset_funds{ native_coin_asset_id, MK_TEST_COINS(20) });
|
||||
proposal_details.fee_paid_by_a = MK_TEST_COINS(1);
|
||||
proposal_details.mixins = 2;
|
||||
|
||||
tools::wallet_public::ionic_swap_proposal proposal{};
|
||||
alice_wlt->create_ionic_swap_proposal(proposal_details, m_accounts[BOB_ACC_IDX].get_public_address(), proposal);
|
||||
|
||||
view::ionic_swap_proposal_info proposal_decoded_info{};
|
||||
bob_wlt->get_ionic_swap_proposal_info(proposal, proposal_decoded_info);
|
||||
CHECK_AND_ASSERT_MES(
|
||||
proposal_decoded_info.to_finalizer == proposal_details.to_finalizer &&
|
||||
proposal_decoded_info.to_initiator == proposal_details.to_initiator &&
|
||||
proposal_decoded_info.fee_paid_by_a == proposal_details.fee_paid_by_a &&
|
||||
proposal_decoded_info.mixins == proposal_details.mixins,
|
||||
false, "actual and decoded proposal mismatch");
|
||||
|
||||
currency::transaction tx_is{};
|
||||
r = bob_wlt->accept_ionic_swap_proposal(proposal, tx_is);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to accept ionic proposal");
|
||||
CHECK_AND_ASSERT_MES(check_ionic_swap_tx_outs(m_accounts, tx_is, bob_wlt, proposal), false, "");
|
||||
|
||||
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_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
alice_wlt->refresh();
|
||||
bob_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", adb.total_max_supply, 0, adb.total_max_supply, 0, 0, asset_id), false, "");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt, "Bob", MK_TEST_COINS(20), 0, MK_TEST_COINS(20), 0, 0), false, "");
|
||||
|
||||
|
||||
// Normal ionic swap between Carol and Alice: (Carol has only coins with non-explicit asset id)
|
||||
// before:
|
||||
// Carol (initiator): 0.21 Zano Alice (finalizer): 0.01 TEST
|
||||
// after:
|
||||
// Carol (initiator): 0.01 TEST Alice (finalizer): 0.2 ZANO
|
||||
|
||||
proposal_details = view::ionic_swap_proposal_info{};
|
||||
proposal_details.to_initiator.push_back(view::asset_funds{ asset_id, adb.total_max_supply });
|
||||
proposal_details.to_finalizer.push_back(view::asset_funds{ native_coin_asset_id, MK_TEST_COINS(20) });
|
||||
proposal_details.fee_paid_by_a = MK_TEST_COINS(1);
|
||||
proposal_details.mixins = 2;
|
||||
|
||||
proposal = tools::wallet_public::ionic_swap_proposal{};
|
||||
carol_wlt->create_ionic_swap_proposal(proposal_details, m_accounts[ALICE_ACC_IDX].get_public_address(), proposal);
|
||||
|
||||
proposal_decoded_info = view::ionic_swap_proposal_info{};
|
||||
alice_wlt->get_ionic_swap_proposal_info(proposal, proposal_decoded_info);
|
||||
CHECK_AND_ASSERT_MES(
|
||||
proposal_decoded_info.to_finalizer == proposal_details.to_finalizer &&
|
||||
proposal_decoded_info.to_initiator == proposal_details.to_initiator &&
|
||||
proposal_decoded_info.fee_paid_by_a == proposal_details.fee_paid_by_a &&
|
||||
proposal_decoded_info.mixins == proposal_details.mixins,
|
||||
false, "actual and decoded proposal mismatch");
|
||||
|
||||
currency::transaction tx_is2{};
|
||||
r = alice_wlt->accept_ionic_swap_proposal(proposal, tx_is2);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to accept ionic proposal");
|
||||
CHECK_AND_ASSERT_MES(check_ionic_swap_tx_outs(m_accounts, tx_is2, alice_wlt, proposal), false, "");
|
||||
|
||||
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_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
carol_wlt->refresh();
|
||||
alice_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*carol_wlt, "Carol", adb.total_max_supply, 0, adb.total_max_supply, 0, 0, asset_id), false, "");
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", MK_TEST_COINS(20), 0, MK_TEST_COINS(20), 0, 0), false, "");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#pragma once
|
||||
#include "chaingen.h"
|
||||
#include "wallet_tests_basic.h"
|
||||
#include "random_helper.h"
|
||||
|
||||
struct ionic_swap_basic_test : public wallet_test
|
||||
{
|
||||
|
|
@ -12,3 +13,9 @@ struct ionic_swap_basic_test : public wallet_test
|
|||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
};
|
||||
|
||||
struct ionic_swap_exact_amounts_test : public wallet_test
|
||||
{
|
||||
ionic_swap_exact_amounts_test();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue