forked from lthn/blockchain
Merge branch 'multiassets' into cryptoassets
This commit is contained in:
commit
86e9667773
38 changed files with 2068 additions and 515 deletions
|
|
@ -1 +1 @@
|
|||
Subproject commit 486a46e927449a5827cf3cb69731bc0e3811b46a
|
||||
Subproject commit b589edb1906dccb387cfeded6ed12286c5f0405f
|
||||
|
|
@ -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"
|
||||
|
|
@ -5150,6 +5150,88 @@ std::shared_ptr<const transaction_chain_entry> blockchain_storage::find_key_imag
|
|||
|
||||
return std::shared_ptr<const transaction_chain_entry>();
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool blockchain_storage::fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short) const
|
||||
{
|
||||
//tei.blob = tx_ptr->tx
|
||||
tei.id = epee::string_tools::pod_to_hex(h);
|
||||
if (!tei.blob_size)
|
||||
tei.blob_size = get_object_blobsize(tx);
|
||||
|
||||
tei.fee = get_tx_fee(tx);
|
||||
tei.pub_key = epee::string_tools::pod_to_hex(get_tx_pub_key_from_extra(tx));
|
||||
tei.timestamp = timestamp;
|
||||
tei.amount = get_outs_money_amount(tx);
|
||||
|
||||
if (is_short)
|
||||
return true;
|
||||
|
||||
fill_tx_rpc_inputs(tei, tx);
|
||||
fill_tx_rpc_outputs(tei, tx, ptce);
|
||||
fill_tx_rpc_payload_items(tei.extra, tx.extra);
|
||||
fill_tx_rpc_payload_items(tei.attachments, tx.attachment);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::fill_tx_rpc_inputs(tx_rpc_extended_info& tei, const transaction& tx) const
|
||||
{
|
||||
|
||||
//handle inputs
|
||||
for (auto in : tx.vin)
|
||||
{
|
||||
tei.ins.push_back(tx_in_rpc_entry());
|
||||
tx_in_rpc_entry& entry_to_fill = tei.ins.back();
|
||||
if (in.type() == typeid(txin_gen))
|
||||
{
|
||||
entry_to_fill.amount = 0;
|
||||
}
|
||||
else if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc) || in.type() == typeid(txin_zc_input))
|
||||
{
|
||||
//TODO: add htlc info
|
||||
entry_to_fill.amount = get_amount_from_variant(in);
|
||||
entry_to_fill.kimage_or_ms_id = epee::string_tools::pod_to_hex(get_key_image_from_txin_v(in));
|
||||
const std::vector<txout_ref_v>& key_offsets = get_key_offsets_from_txin_v(in);
|
||||
std::vector<txout_ref_v> absolute_offsets = relative_output_offsets_to_absolute(key_offsets);
|
||||
for (auto& ao : absolute_offsets)
|
||||
{
|
||||
entry_to_fill.global_indexes.push_back(0);
|
||||
if (ao.type() == typeid(uint64_t))
|
||||
{
|
||||
entry_to_fill.global_indexes.back() = boost::get<uint64_t>(ao);
|
||||
}
|
||||
else if (ao.type() == typeid(ref_by_id))
|
||||
{
|
||||
//disable for the reset at the moment
|
||||
auto tx_ptr = get_tx_chain_entry(boost::get<ref_by_id>(ao).tx_id);
|
||||
if (!tx_ptr || tx_ptr->m_global_output_indexes.size() <= boost::get<ref_by_id>(ao).n)
|
||||
{
|
||||
tei.ins.back().global_indexes.back() = std::numeric_limits<uint64_t>::max();
|
||||
return false;
|
||||
}
|
||||
tei.ins.back().global_indexes.back() = tx_ptr->m_global_output_indexes[boost::get<ref_by_id>(ao).n];
|
||||
}
|
||||
}
|
||||
if (in.type() == typeid(txin_htlc))
|
||||
{
|
||||
entry_to_fill.htlc_origin = epee::string_tools::buff_to_hex_nodelimer(boost::get<txin_htlc>(in).hltc_origin);
|
||||
}
|
||||
//tk.etc_details -> visualize it may be later
|
||||
}
|
||||
else if (in.type() == typeid(txin_multisig))
|
||||
{
|
||||
txin_multisig& tms = boost::get<txin_multisig>(in);
|
||||
entry_to_fill.amount = tms.amount;
|
||||
entry_to_fill.kimage_or_ms_id = epee::string_tools::pod_to_hex(tms.multisig_out_id);
|
||||
if (tx.signatures.size() >= tei.ins.size() &&
|
||||
tx.signatures[tei.ins.size() - 1].type() == typeid(NLSAG_sig))
|
||||
{
|
||||
entry_to_fill.multisig_count = boost::get<NLSAG_sig>(tx.signatures[tei.ins.size() - 1]).s.size();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::prune_aged_alt_blocks()
|
||||
{
|
||||
|
|
@ -6327,15 +6409,7 @@ bool blockchain_storage::prevalidate_block(const block& bl)
|
|||
return true;
|
||||
}
|
||||
|
||||
// HF3
|
||||
if ( m_core_runtime_config.is_hardfork_active_for_height(3, block_height) &&
|
||||
!m_core_runtime_config.is_hardfork_active_for_height(4, block_height))
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(bl.major_version == HF3_BLOCK_MAJOR_VERSION, false, "HF3, incorrect block major version: " << (int)bl.major_version);
|
||||
}
|
||||
|
||||
|
||||
//after hard_fork3
|
||||
// >= HF3
|
||||
if (bl.major_version > CURRENT_BLOCK_MAJOR_VERSION)
|
||||
{
|
||||
LOG_ERROR("prevalidation failed for block " << get_block_hash(bl) << ": major block version " << static_cast<size_t>(bl.major_version) << " is incorrect, " << CURRENT_BLOCK_MAJOR_VERSION << " is expected" << ENDL
|
||||
|
|
|
|||
|
|
@ -334,6 +334,8 @@ namespace currency
|
|||
|
||||
// returns true as soon as the hardfork is active for the NEXT upcoming block (not for the top block in the blockchain storage)
|
||||
bool is_hardfork_active(size_t hardfork_id) const;
|
||||
bool fill_tx_rpc_inputs(tx_rpc_extended_info& tei, const transaction& tx) const;
|
||||
bool fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short = false) const;
|
||||
|
||||
wide_difficulty_type block_difficulty(size_t i)const;
|
||||
bool forecast_difficulty(std::vector<std::pair<uint64_t, wide_difficulty_type>> &out_height_2_diff_vector, bool pos) const;
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ namespace currency
|
|||
const static crypto::key_derivation null_derivation = AUTO_VAL_INIT(null_derivation);
|
||||
|
||||
const static crypto::hash gdefault_genesis = epee::string_tools::hex_to_pod<crypto::hash>("CC608F59F8080E2FBFE3C8C80EB6E6A953D47CF2D6AEBD345BADA3A1CAB99852");
|
||||
const static crypto::hash ffff_hash = epee::string_tools::hex_to_pod<crypto::hash>("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
const static crypto::public_key ffff_pkey = epee::string_tools::hex_to_pod<crypto::public_key>("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // TODO @#@# consider getting rid of this
|
||||
//const static crypto::hash ffff_hash = epee::string_tools::hex_to_pod<crypto::hash>("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
//const static crypto::public_key ffff_pkey = epee::string_tools::hex_to_pod<crypto::public_key>("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // TODO @#@# consider getting rid of this
|
||||
|
||||
// TODO: rewtire the following to a normal aggregate initialization once we move to C++17 -- sowle
|
||||
const static crypto::public_key native_coin_asset_id = reinterpret_cast<const crypto::public_key&>(static_cast<const crypto::ec_scalar&>(crypto::ec_scalar{'\xd6', '\x32', '\x9b', '\x5b', '\x1f', '\x7c', '\x08', '\x05', '\xb5', '\xc3', '\x45', '\xf4', '\x95', '\x75', '\x54', '\x00', '\x2a', '\x2f', '\x55', '\x78', '\x45', '\xf6', '\x4d', '\x76', '\x45', '\xda', '\xe0', '\xe0', '\x51', '\xa6', '\x49', '\x8a'})); // == crypto::c_point_H, checked in crypto_constants
|
||||
|
|
|
|||
|
|
@ -406,7 +406,7 @@ namespace currency
|
|||
tx_destination_entry de = AUTO_VAL_INIT(de);
|
||||
de.addr.push_back(miner_address);
|
||||
de.amount = a;
|
||||
de.explicit_native_asset_id = true; // don't use asset id blinding as it's obvious which asset it is
|
||||
de.flags |= tx_destination_entry_flags::tdef_explicit_native_asset_id; // don't use asset id blinding as it's obvious which asset it is
|
||||
if (pe.stake_unlock_time && pe.stake_unlock_time > height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW)
|
||||
{
|
||||
//this means that block is creating after hardfork_1 and unlock_time is needed to set for every destination separately
|
||||
|
|
@ -421,7 +421,7 @@ namespace currency
|
|||
if (pe.stake_unlock_time && pe.stake_unlock_time > height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW)
|
||||
stake_lock_time = pe.stake_unlock_time;
|
||||
destinations.push_back(tx_destination_entry(pe.amount, stakeholder_address, stake_lock_time));
|
||||
destinations.back().explicit_native_asset_id = true; // don't use asset id blinding as it's obvious which asset it is
|
||||
destinations.back().flags |= tx_destination_entry_flags::tdef_explicit_native_asset_id; // don't use asset id blinding as it's obvious which asset it is
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(destinations.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS || height == 0, false, "Too many outs (" << destinations.size() << ")! Miner tx can't be constructed.");
|
||||
|
|
@ -1143,8 +1143,8 @@ namespace currency
|
|||
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)
|
||||
|
||||
CHECK_AND_ASSERT_MES(!de.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.explicit_native_asset_id ? 0 : crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_ASSET_BLINDING_MASK, h); // f = Hs(domain_sep, d, i)
|
||||
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)
|
||||
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
|
||||
|
||||
|
|
@ -1163,8 +1163,8 @@ namespace currency
|
|||
crypto::scalar_t amount_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_MASK, h);
|
||||
out.encrypted_amount = de.amount ^ amount_mask.m_u64[0];
|
||||
|
||||
CHECK_AND_ASSERT_MES(!de.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.explicit_native_asset_id ? 0 : crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_ASSET_BLINDING_MASK, h); // f = Hs(domain_sep, d, i)
|
||||
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)
|
||||
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)
|
||||
|
||||
|
|
@ -1549,13 +1549,6 @@ namespace currency
|
|||
crypto::key_derivation get_encryption_key_derivation(bool is_income, const transaction& tx, const account_keys& acc_keys)
|
||||
{
|
||||
crypto::key_derivation derivation = null_derivation;
|
||||
tx_crypto_checksum crypto_info = AUTO_VAL_INIT(crypto_info);
|
||||
if (!get_type_in_variant_container(tx.extra, crypto_info) && !get_type_in_variant_container(tx.attachment, crypto_info))
|
||||
{
|
||||
//no crypt info in tx
|
||||
return null_derivation;
|
||||
}
|
||||
|
||||
if (is_income)
|
||||
{
|
||||
crypto::public_key tx_pub_key = currency::get_tx_pub_key_from_extra(tx);
|
||||
|
|
@ -1563,18 +1556,25 @@ namespace currency
|
|||
bool r = crypto::generate_key_derivation(tx_pub_key, acc_keys.view_secret_key, derivation);
|
||||
CHECK_AND_ASSERT_MES(r, null_derivation, "failed to generate_key_derivation");
|
||||
LOG_PRINT_GREEN("DECRYPTING ON KEY: " << epee::string_tools::pod_to_hex(derivation) << ", key derived from destination addr: " << currency::get_account_address_as_str(acc_keys.account_address), LOG_LEVEL_0);
|
||||
return derivation;
|
||||
}
|
||||
else
|
||||
{
|
||||
tx_crypto_checksum crypto_info = AUTO_VAL_INIT(crypto_info);
|
||||
if (!get_type_in_variant_container(tx.extra, crypto_info) && !get_type_in_variant_container(tx.attachment, crypto_info))
|
||||
{
|
||||
//no crypt info in tx
|
||||
return null_derivation;
|
||||
}
|
||||
|
||||
derivation = crypto_info.encrypted_key_derivation;
|
||||
crypto::chacha_crypt(derivation, acc_keys.spend_secret_key);
|
||||
LOG_PRINT_GREEN("DECRYPTING ON KEY: " << epee::string_tools::pod_to_hex(derivation) << ", key decrypted from sender address: " << currency::get_account_address_as_str(acc_keys.account_address), LOG_LEVEL_0);
|
||||
//validate derivation we here. Yoda style
|
||||
crypto::hash hash_for_check_sum = crypto::cn_fast_hash(&derivation, sizeof(derivation));
|
||||
CHECK_AND_ASSERT_MES(*(uint32_t*)&hash_for_check_sum == crypto_info.derivation_hash, null_derivation, "Derivation hash missmatched in tx id " << currency::get_transaction_hash(tx));
|
||||
return derivation;
|
||||
}
|
||||
|
||||
//validate derivation we here. Yoda style
|
||||
crypto::hash hash_for_check_sum = crypto::cn_fast_hash(&derivation, sizeof(derivation));
|
||||
CHECK_AND_ASSERT_MES(*(uint32_t*)&hash_for_check_sum == crypto_info.derivation_hash, null_derivation, "Derivation hash missmatched in tx id " << currency::get_transaction_hash(tx));
|
||||
return derivation;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<class total_t_container>
|
||||
|
|
@ -1612,9 +1612,8 @@ namespace currency
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
void encrypt_attachments(transaction& tx, const account_keys& sender_keys, const account_public_address& destination_addr, const keypair& tx_random_key)
|
||||
void encrypt_attachments(transaction& tx, const account_keys& sender_keys, const account_public_address& destination_addr, const keypair& tx_random_key, crypto::key_derivation& derivation)
|
||||
{
|
||||
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
|
||||
bool r = crypto::generate_key_derivation(destination_addr.view_public_key, tx_random_key.sec, derivation);
|
||||
CHECK_AND_ASSERT_MES(r, void(), "failed to generate_key_derivation");
|
||||
bool was_attachment_crypted_entries = false;
|
||||
|
|
@ -1645,6 +1644,12 @@ namespace currency
|
|||
}
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
void encrypt_attachments(transaction& tx, const account_keys& sender_keys, const account_public_address& destination_addr, const keypair& tx_random_key)
|
||||
{
|
||||
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
|
||||
return encrypt_attachments(tx, sender_keys, destination_addr, tx_random_key, derivation);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
void load_wallet_transfer_info_flags(tools::wallet_public::wallet_transfer_info& x)
|
||||
{
|
||||
x.is_service = currency::is_service_tx(x.tx);
|
||||
|
|
@ -2022,7 +2027,8 @@ namespace currency
|
|||
append_mode = true;
|
||||
|
||||
keypair txkey = AUTO_VAL_INIT(txkey);
|
||||
|
||||
size_t zc_inputs_count = 0;
|
||||
bool has_non_zc_inputs = false;
|
||||
|
||||
if (!append_mode)
|
||||
{
|
||||
|
|
@ -2052,7 +2058,7 @@ namespace currency
|
|||
|
||||
//include offers if need
|
||||
tx.attachment = attachments;
|
||||
encrypt_attachments(tx, sender_account_keys, crypt_destination_addr, txkey);
|
||||
encrypt_attachments(tx, sender_account_keys, crypt_destination_addr, txkey, result.derivation);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2061,7 +2067,8 @@ namespace currency
|
|||
CHECK_AND_ASSERT_MES(txkey.pub != null_pkey && txkey.sec != null_skey, false, "In append mode both public and secret keys must be provided");
|
||||
|
||||
//separately encrypt attachments without putting extra
|
||||
crypto::key_derivation derivation = get_encryption_key_derivation(true, tx, sender_account_keys);
|
||||
result.derivation = get_encryption_key_derivation(true, tx, sender_account_keys);
|
||||
crypto::key_derivation& derivation = result.derivation;
|
||||
CHECK_AND_ASSERT_MES(derivation != null_derivation, false, "failed to generate_key_derivation");
|
||||
bool was_attachment_crypted_entries = false;
|
||||
std::vector<extra_v> extra_local = extra;
|
||||
|
|
@ -2076,9 +2083,20 @@ namespace currency
|
|||
|
||||
tx.attachment.insert(tx.attachment.end(), attachments_local.begin(), attachments_local.end());
|
||||
tx.extra.insert(tx.extra.end(), extra_local.begin(), extra_local.end());
|
||||
|
||||
for (const auto in : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_zc_input))
|
||||
{
|
||||
zc_inputs_count++;
|
||||
}
|
||||
else {
|
||||
has_non_zc_inputs = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t thirdparty_zc_inputs_count = zc_inputs_count;
|
||||
//
|
||||
// INs
|
||||
//
|
||||
|
|
@ -2088,7 +2106,6 @@ namespace currency
|
|||
size_t current_index = 0;
|
||||
inputs_mapping.resize(sources.size());
|
||||
size_t input_starter_index = tx.vin.size();
|
||||
size_t zc_inputs_count = 0;
|
||||
bool all_inputs_are_obviously_native_coins = true;
|
||||
for (const tx_source_entry& src_entr : sources)
|
||||
{
|
||||
|
|
@ -2107,6 +2124,7 @@ namespace currency
|
|||
input_multisig.multisig_out_id = src_entr.multisig_id;
|
||||
input_multisig.sigs_count = src_entr.ms_sigs_count;
|
||||
tx.vin.push_back(input_multisig);
|
||||
has_non_zc_inputs = true;
|
||||
}
|
||||
else if (src_entr.htlc_origin.size())
|
||||
{
|
||||
|
|
@ -2141,6 +2159,7 @@ namespace currency
|
|||
input_to_key.key_offsets.push_back(src_entr.outputs.front().out_reference);
|
||||
|
||||
tx.vin.push_back(input_to_key);
|
||||
has_non_zc_inputs = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2183,6 +2202,7 @@ namespace currency
|
|||
input_to_key.k_image = img;
|
||||
input_to_key.key_offsets = std::move(key_offsets);
|
||||
tx.vin.push_back(input_to_key);
|
||||
has_non_zc_inputs = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2203,15 +2223,15 @@ namespace currency
|
|||
}
|
||||
}
|
||||
}
|
||||
bool has_non_zc_inputs = zc_inputs_count != sources.size(); // TODO @#@# reconsider this for consilidated txs
|
||||
|
||||
|
||||
//
|
||||
// OUTs
|
||||
//
|
||||
std::vector<tx_destination_entry> shuffled_dsts(destinations);
|
||||
size_t outputs_to_be_constructed = shuffled_dsts.size();
|
||||
//size_t outputs_to_be_constructed = shuffled_dsts.size();
|
||||
tx_generation_context& gen_context = result.ftp.gen_context;
|
||||
gen_context.resize(zc_inputs_count, outputs_to_be_constructed);
|
||||
gen_context.resize(zc_inputs_count, tx.vout.size() + shuffled_dsts.size());
|
||||
|
||||
// ASSET oprations handling
|
||||
if (tx.version > TRANSACTION_VERSION_PRE_HF4)
|
||||
|
|
@ -2235,7 +2255,7 @@ namespace currency
|
|||
uint64_t amount_of_emitted_asset = 0;
|
||||
for (auto& item : shuffled_dsts)
|
||||
{
|
||||
if (item.asset_id == currency::ffff_pkey)
|
||||
if (item.asset_id == currency::null_pkey)
|
||||
{
|
||||
item.asset_id = gen_context.ao_asset_id; // set calculated asset_id to the asset's outputs, if this asset is being emitted within this tx
|
||||
amount_of_emitted_asset += item.amount;
|
||||
|
|
@ -2259,24 +2279,24 @@ namespace currency
|
|||
// construct outputs
|
||||
uint64_t native_coins_output_sum = 0;
|
||||
size_t output_index = tx.vout.size(); // in case of append mode we need to start output indexing from the last one + 1
|
||||
uint64_t range_proof_start_index = output_index;
|
||||
uint64_t range_proof_start_index = 0;
|
||||
std::set<uint16_t> deriv_cache;
|
||||
for(size_t j = 0; j < outputs_to_be_constructed; ++j, ++output_index)
|
||||
for(size_t destination_index = 0; destination_index < shuffled_dsts.size(); ++destination_index, ++output_index)
|
||||
{
|
||||
tx_destination_entry& dst_entr = shuffled_dsts[j];
|
||||
if (all_inputs_are_obviously_native_coins && gen_context.ao_asset_id == currency::null_pkey)
|
||||
dst_entr.explicit_native_asset_id = true; // all inputs are obviously native coins -- all outputs must have explicit asset ids (unless there's an asset emission)
|
||||
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)
|
||||
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
|
||||
r = construct_tx_out(dst_entr, txkey.sec, output_index, tx, deriv_cache, sender_account_keys,
|
||||
gen_context.asset_id_blinding_masks[j], gen_context.amount_blinding_masks[j],
|
||||
gen_context.blinded_asset_ids[j], gen_context.amount_commitments[j], result, tx_outs_attr);
|
||||
gen_context.asset_id_blinding_masks[output_index], gen_context.amount_blinding_masks[output_index],
|
||||
gen_context.blinded_asset_ids[output_index], gen_context.amount_commitments[output_index], result, tx_outs_attr);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construct tx out");
|
||||
gen_context.amounts[j] = dst_entr.amount;
|
||||
gen_context.asset_ids[j] = crypto::point_t(dst_entr.asset_id);
|
||||
gen_context.asset_id_blinding_mask_x_amount_sum += gen_context.asset_id_blinding_masks[j] * dst_entr.amount;
|
||||
gen_context.amount_blinding_masks_sum += gen_context.amount_blinding_masks[j];
|
||||
gen_context.amount_commitments_sum += gen_context.amount_commitments[j];
|
||||
gen_context.amounts[output_index] = dst_entr.amount;
|
||||
gen_context.asset_ids[output_index] = crypto::point_t(dst_entr.asset_id);
|
||||
gen_context.asset_id_blinding_mask_x_amount_sum += gen_context.asset_id_blinding_masks[output_index] * dst_entr.amount;
|
||||
gen_context.amount_blinding_masks_sum += gen_context.amount_blinding_masks[output_index];
|
||||
gen_context.amount_commitments_sum += gen_context.amount_commitments[output_index];
|
||||
if (dst_entr.is_native_coin())
|
||||
native_coins_output_sum += dst_entr.amount;
|
||||
}
|
||||
|
|
@ -2311,8 +2331,16 @@ namespace currency
|
|||
std::sort(tx.vin.begin() + input_starter_index, tx.vin.end(), less_txin_v);
|
||||
|
||||
// add explicit fee info
|
||||
r = add_tx_fee_amount_to_extra(tx, native_coins_input_sum - native_coins_output_sum);
|
||||
CHECK_AND_ASSERT_MES(r, false, "add_tx_fee_amount_to_extra failed");
|
||||
uint64_t fee_to_declare = native_coins_input_sum - native_coins_output_sum;
|
||||
if (flags & TX_FLAG_SIGNATURE_MODE_SEPARATE)
|
||||
{
|
||||
fee_to_declare = ftp.mode_separate_fee;
|
||||
}
|
||||
if (fee_to_declare)
|
||||
{
|
||||
r = add_tx_fee_amount_to_extra(tx, fee_to_declare);
|
||||
CHECK_AND_ASSERT_MES(r, false, "add_tx_fee_amount_to_extra failed");
|
||||
}
|
||||
}
|
||||
|
||||
// attachments container should be sealed by now
|
||||
|
|
@ -2348,13 +2376,13 @@ 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_];
|
||||
|
||||
const tx_source_entry& source_entry = sources[i_mapped];
|
||||
crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, i_ + input_starter_index, tx_prefix_hash);
|
||||
CHECK_AND_ASSERT_MES(tx_hash_for_signature != null_hash, false, "prepare_prefix_hash_for_sign failed");
|
||||
CHECK_AND_ASSERT_MES(tx_hash_for_signature != null_hash, false, "prepare_prefix_hash_for_sign failed");
|
||||
std::stringstream ss_ring_s;
|
||||
|
||||
if (source_entry.is_zc())
|
||||
|
|
@ -2363,6 +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.zc_input_amounts[curren_zc_index] = source_entry.amount;
|
||||
curren_zc_index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2377,7 +2407,8 @@ namespace currency
|
|||
//
|
||||
// proofs (transaction-wise, not pre-input)
|
||||
//
|
||||
if (tx.version > TRANSACTION_VERSION_PRE_HF4)
|
||||
if (tx.version > TRANSACTION_VERSION_PRE_HF4 &&
|
||||
(append_mode || (flags & TX_FLAG_SIGNATURE_MODE_SEPARATE) == 0))
|
||||
{
|
||||
// asset surjection proof
|
||||
currency::zc_asset_surjection_proof asp{};
|
||||
|
|
@ -3502,7 +3533,7 @@ namespace currency
|
|||
}
|
||||
if (p_amount_burnt)
|
||||
*p_amount_burnt = sum_of_bare_outs_burnt;
|
||||
return sum_of_bare_outs_burnt == amount;
|
||||
return sum_of_bare_outs_burnt >= amount;
|
||||
}
|
||||
|
||||
// post HF-4 txs
|
||||
|
|
@ -3564,235 +3595,7 @@ namespace currency
|
|||
return cnt;
|
||||
}
|
||||
|
||||
struct rpc_tx_payload_handler : public boost::static_visitor<bool>
|
||||
{
|
||||
tx_extra_rpc_entry& tv;
|
||||
rpc_tx_payload_handler(tx_extra_rpc_entry& t) : tv(t)
|
||||
{}
|
||||
|
||||
bool operator()(const tx_service_attachment& ee)
|
||||
{
|
||||
tv.type = "service";
|
||||
tv.short_view = ee.service_id + ":" + ee.instruction;
|
||||
if (ee.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY)
|
||||
tv.short_view += "(encrypted)";
|
||||
else
|
||||
{
|
||||
std::string deflated_buff;
|
||||
const std::string* pfinalbuff = &ee.body;
|
||||
if (ee.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY)
|
||||
{
|
||||
bool r = epee::zlib_helper::unpack(ee.body, deflated_buff);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to unpack");
|
||||
pfinalbuff = &deflated_buff;
|
||||
}
|
||||
if (ee.service_id == BC_PAYMENT_ID_SERVICE_ID || ee.service_id == BC_OFFERS_SERVICE_ID)
|
||||
tv.details_view = *pfinalbuff;
|
||||
else
|
||||
tv.details_view = "BINARY DATA";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_crypto_checksum& ee)
|
||||
{
|
||||
tv.type = "crypto_checksum";
|
||||
tv.short_view = std::string("derivation_hash: ") + epee::string_tools::pod_to_hex(ee.derivation_hash);
|
||||
tv.details_view = std::string("derivation_hash: ") + epee::string_tools::pod_to_hex(ee.derivation_hash) + "\n"
|
||||
+ "encrypted_key_derivation: " + epee::string_tools::pod_to_hex(ee.encrypted_key_derivation);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_time& ee)
|
||||
{
|
||||
tv.type = "pos_time";
|
||||
tv.short_view = std::string("timestamp: ") + std::to_string(ee.v) + " " + epee::misc_utils::get_internet_time_str(ee.v);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_details_unlock_time& ee)
|
||||
{
|
||||
tv.type = "unlock_time";
|
||||
if (ee.v < CURRENCY_MAX_BLOCK_NUMBER)
|
||||
tv.short_view = std::string("height: ") + std::to_string(ee.v);
|
||||
else
|
||||
tv.short_view = std::string("timestamp: ") + std::to_string(ee.v) + " " + epee::misc_utils::get_internet_time_str(ee.v);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_details_unlock_time2& ee)
|
||||
{
|
||||
tv.type = "unlock_time";
|
||||
std::stringstream ss;
|
||||
ss << "[";
|
||||
for (auto v : ee.unlock_time_array)
|
||||
{
|
||||
ss << " " << v;
|
||||
}
|
||||
ss << "]";
|
||||
tv.short_view = ss.str();
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_details_expiration_time& ee)
|
||||
{
|
||||
tv.type = "expiration_time";
|
||||
if (ee.v < CURRENCY_MAX_BLOCK_NUMBER)
|
||||
tv.short_view = std::string("height: ") + std::to_string(ee.v);
|
||||
else
|
||||
tv.short_view = std::string("timestamp: ") + std::to_string(ee.v) + " " + epee::misc_utils::get_internet_time_str(ee.v);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_details_flags& ee)
|
||||
{
|
||||
tv.type = "details_flags";
|
||||
tv.short_view = epee::string_tools::pod_to_hex(ee.v);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const crypto::public_key& ee)
|
||||
{
|
||||
tv.type = "pub_key";
|
||||
tv.short_view = epee::string_tools::pod_to_hex(ee);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const extra_attachment_info& ee)
|
||||
{
|
||||
tv.type = "attachment_info";
|
||||
tv.short_view = std::to_string(ee.sz) + " bytes";
|
||||
tv.details_view = currency::obj_to_json_str(ee);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const extra_alias_entry& ee)
|
||||
{
|
||||
tv.type = "alias_info";
|
||||
tv.short_view = ee.m_alias + "-->" + get_account_address_as_str(ee.m_address);
|
||||
tv.details_view = currency::obj_to_json_str(ee);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const extra_alias_entry_old& ee)
|
||||
{
|
||||
return operator()(static_cast<const extra_alias_entry&>(ee));
|
||||
}
|
||||
bool operator()(const extra_user_data& ee)
|
||||
{
|
||||
tv.type = "user_data";
|
||||
tv.short_view = std::to_string(ee.buff.size()) + " bytes";
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee.buff);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const extra_padding& ee)
|
||||
{
|
||||
tv.type = "extra_padding";
|
||||
tv.short_view = std::to_string(ee.buff.size()) + " bytes";
|
||||
if (!ee.buff.empty())
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(&ee.buff[0]), ee.buff.size()));
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_comment& ee)
|
||||
{
|
||||
tv.type = "comment";
|
||||
tv.short_view = std::to_string(ee.comment.size()) + " bytes(encrypted)";
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee.comment);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_payer& ee)
|
||||
{
|
||||
//const tx_payer& ee = boost::get<tx_payer>(extra);
|
||||
tv.type = "payer";
|
||||
tv.short_view = "(encrypted)";
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_payer_old&)
|
||||
{
|
||||
tv.type = "payer_old";
|
||||
tv.short_view = "(encrypted)";
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_receiver& ee)
|
||||
{
|
||||
//const tx_payer& ee = boost::get<tx_payer>(extra);
|
||||
tv.type = "receiver";
|
||||
tv.short_view = "(encrypted)";
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_receiver_old& ee)
|
||||
{
|
||||
tv.type = "receiver_old";
|
||||
tv.short_view = "(encrypted)";
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_derivation_hint& ee)
|
||||
{
|
||||
tv.type = "derivation_hint";
|
||||
tv.short_view = std::to_string(ee.msg.size()) + " bytes";
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee.msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const std::string& ee)
|
||||
{
|
||||
tv.type = "string";
|
||||
tv.short_view = std::to_string(ee.size()) + " bytes";
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_flags16_t& dh)
|
||||
{
|
||||
tv.type = "FLAGS16";
|
||||
tv.short_view = epee::string_tools::pod_to_hex(dh);
|
||||
tv.details_view = epee::string_tools::pod_to_hex(dh);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const zarcanum_tx_data_v1& ztxd)
|
||||
{
|
||||
tv.type = "zarcanum_tx_data_v1";
|
||||
tv.short_view = "fee = " + print_money_brief(ztxd.fee);
|
||||
tv.details_view = tv.short_view;
|
||||
return true;
|
||||
}
|
||||
bool operator()(const zc_outs_range_proof& rp)
|
||||
{
|
||||
tv.type = "zc_outs_range_proof";
|
||||
// TODO @#@#
|
||||
//tv.short_view = "outputs_count = " + std::to_string(rp.outputs_count);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const zc_balance_proof& bp)
|
||||
{
|
||||
tv.type = "zc_balance_proof";
|
||||
return true;
|
||||
}
|
||||
template<typename t_type>
|
||||
bool operator()(const t_type& t_t)
|
||||
{
|
||||
tv.type = typeid(t_t).name();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
//------------------------------------------------------------------
|
||||
template<class t_container>
|
||||
bool fill_tx_rpc_payload_items(std::vector<tx_extra_rpc_entry>& target_vector, const t_container& tc)
|
||||
{
|
||||
//handle extra
|
||||
for (auto& extra : tc)
|
||||
{
|
||||
target_vector.push_back(tx_extra_rpc_entry());
|
||||
tx_extra_rpc_entry& tv = target_vector.back();
|
||||
|
||||
rpc_tx_payload_handler vstr(tv);
|
||||
boost::apply_visitor(vstr, extra);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool fill_tx_rpc_outputs(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce)
|
||||
{
|
||||
|
|
@ -3913,28 +3716,7 @@ namespace currency
|
|||
pei_rpc.penalty = (pei_rpc.base_reward + pei_rpc.total_fee) - pei_rpc.summary_reward;
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short)
|
||||
{
|
||||
//tei.blob = tx_ptr->tx
|
||||
tei.id = epee::string_tools::pod_to_hex(h);
|
||||
if(!tei.blob_size)
|
||||
tei.blob_size = get_object_blobsize(tx);
|
||||
|
||||
tei.fee = get_tx_fee(tx);
|
||||
tei.pub_key = epee::string_tools::pod_to_hex(get_tx_pub_key_from_extra(tx));
|
||||
tei.timestamp = timestamp;
|
||||
tei.amount = get_outs_money_amount(tx);
|
||||
|
||||
if (is_short)
|
||||
return true;
|
||||
|
||||
fill_tx_rpc_inputs(tei, tx);
|
||||
fill_tx_rpc_outputs(tei, tx, ptce);
|
||||
fill_tx_rpc_payload_items(tei.extra, tx.extra);
|
||||
fill_tx_rpc_payload_items(tei.attachments, tx.attachment);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void append_per_block_increments_for_tx(const transaction& tx, std::unordered_map<uint64_t, uint32_t>& gindices)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@
|
|||
#include "currency_format_utils_transactions.h"
|
||||
#include "core_runtime_config.h"
|
||||
#include "wallet/wallet_public_structs_defs.h"
|
||||
#include "bc_attachments_helpers.h"
|
||||
#include "bc_payments_id_service.h"
|
||||
#include "bc_offers_service_basic.h"
|
||||
|
||||
|
||||
// ------ get_tx_type_definition -------------
|
||||
|
|
@ -139,6 +142,7 @@ namespace currency
|
|||
|
||||
struct finalize_tx_param
|
||||
{
|
||||
|
||||
uint64_t unlock_time;
|
||||
std::vector<currency::extra_v> extra;
|
||||
std::vector<currency::attachment_v> attachments;
|
||||
|
|
@ -153,6 +157,7 @@ namespace currency
|
|||
uint64_t expiration_time;
|
||||
crypto::public_key spend_pub_key; // only for validations
|
||||
uint64_t tx_version;
|
||||
uint64_t mode_separate_fee = 0;
|
||||
|
||||
tx_generation_context gen_context{}; // solely for consolidated txs
|
||||
|
||||
|
|
@ -171,6 +176,7 @@ namespace currency
|
|||
FIELD(expiration_time)
|
||||
FIELD(spend_pub_key)
|
||||
FIELD(tx_version)
|
||||
FIELD(mode_separate_fee)
|
||||
if (flags & TX_FLAG_SIGNATURE_MODE_SEPARATE)
|
||||
FIELD(gen_context);
|
||||
END_SERIALIZE()
|
||||
|
|
@ -183,6 +189,7 @@ namespace currency
|
|||
finalize_tx_param ftp;
|
||||
std::string htlc_origin;
|
||||
std::vector<serializable_pair<uint64_t, crypto::key_image>> outs_key_images; // pairs (out_index, key_image) for each change output
|
||||
crypto::key_derivation derivation;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(tx)
|
||||
|
|
@ -190,6 +197,7 @@ namespace currency
|
|||
FIELD(ftp)
|
||||
FIELD(htlc_origin)
|
||||
FIELD(outs_key_images)
|
||||
FIELD(derivation)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
|
|
@ -339,6 +347,7 @@ namespace currency
|
|||
bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t current_blockchain_size, uint64_t current_time);
|
||||
crypto::key_derivation get_encryption_key_derivation(bool is_income, const transaction& tx, const account_keys& acc_keys);
|
||||
bool decrypt_payload_items(bool is_income, const transaction& tx, const account_keys& acc_keys, std::vector<payload_items_v>& decrypted_items);
|
||||
void encrypt_attachments(transaction& tx, const account_keys& sender_keys, const account_public_address& destination_addr, const keypair& tx_random_key, crypto::key_derivation& derivation);
|
||||
void encrypt_attachments(transaction& tx, const account_keys& sender_keys, const account_public_address& destination_addr, const keypair& tx_random_key);
|
||||
bool is_derivation_used_to_encrypt(const transaction& tx, const crypto::key_derivation& derivation);
|
||||
bool is_address_like_wrapped(const std::string& addr);
|
||||
|
|
@ -414,8 +423,7 @@ namespace currency
|
|||
update_alias_rpc_details alias_info_to_rpc_update_alias_info(const currency::extra_alias_entry& ai, const std::string& old_address);
|
||||
size_t get_service_attachments_count_in_tx(const transaction& tx);
|
||||
bool fill_tx_rpc_outputs(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce);
|
||||
bool fill_tx_rpc_inputs(tx_rpc_extended_info& tei, const transaction& tx);
|
||||
bool fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short = false);
|
||||
|
||||
bool fill_block_rpc_details(block_rpc_extended_info& pei_rpc, const block_extended_info& bei_chain, const crypto::hash& h);
|
||||
void append_per_block_increments_for_tx(const transaction& tx, std::unordered_map<uint64_t, uint32_t>& gindices);
|
||||
std::string get_word_from_timstamp(uint64_t timestamp, bool use_password);
|
||||
|
|
@ -891,5 +899,236 @@ namespace currency
|
|||
const difficulties& b_diff
|
||||
);
|
||||
|
||||
struct rpc_tx_payload_handler : public boost::static_visitor<bool>
|
||||
{
|
||||
tx_extra_rpc_entry& tv;
|
||||
rpc_tx_payload_handler(tx_extra_rpc_entry& t) : tv(t)
|
||||
{}
|
||||
|
||||
bool operator()(const tx_service_attachment& ee)
|
||||
{
|
||||
tv.type = "service";
|
||||
tv.short_view = ee.service_id + ":" + ee.instruction;
|
||||
if (ee.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY)
|
||||
tv.short_view += "(encrypted)";
|
||||
else
|
||||
{
|
||||
std::string deflated_buff;
|
||||
const std::string* pfinalbuff = &ee.body;
|
||||
if (ee.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY)
|
||||
{
|
||||
bool r = epee::zlib_helper::unpack(ee.body, deflated_buff);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to unpack");
|
||||
pfinalbuff = &deflated_buff;
|
||||
}
|
||||
if (ee.service_id == BC_PAYMENT_ID_SERVICE_ID || ee.service_id == BC_OFFERS_SERVICE_ID)
|
||||
tv.details_view = *pfinalbuff;
|
||||
else
|
||||
tv.details_view = "BINARY DATA";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_crypto_checksum& ee)
|
||||
{
|
||||
tv.type = "crypto_checksum";
|
||||
tv.short_view = std::string("derivation_hash: ") + epee::string_tools::pod_to_hex(ee.derivation_hash);
|
||||
tv.details_view = std::string("derivation_hash: ") + epee::string_tools::pod_to_hex(ee.derivation_hash) + "\n"
|
||||
+ "encrypted_key_derivation: " + epee::string_tools::pod_to_hex(ee.encrypted_key_derivation);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_time& ee)
|
||||
{
|
||||
tv.type = "pos_time";
|
||||
tv.short_view = std::string("timestamp: ") + std::to_string(ee.v) + " " + epee::misc_utils::get_internet_time_str(ee.v);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_details_unlock_time& ee)
|
||||
{
|
||||
tv.type = "unlock_time";
|
||||
if (ee.v < CURRENCY_MAX_BLOCK_NUMBER)
|
||||
tv.short_view = std::string("height: ") + std::to_string(ee.v);
|
||||
else
|
||||
tv.short_view = std::string("timestamp: ") + std::to_string(ee.v) + " " + epee::misc_utils::get_internet_time_str(ee.v);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_details_unlock_time2& ee)
|
||||
{
|
||||
tv.type = "unlock_time";
|
||||
std::stringstream ss;
|
||||
ss << "[";
|
||||
for (auto v : ee.unlock_time_array)
|
||||
{
|
||||
ss << " " << v;
|
||||
}
|
||||
ss << "]";
|
||||
tv.short_view = ss.str();
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_details_expiration_time& ee)
|
||||
{
|
||||
tv.type = "expiration_time";
|
||||
if (ee.v < CURRENCY_MAX_BLOCK_NUMBER)
|
||||
tv.short_view = std::string("height: ") + std::to_string(ee.v);
|
||||
else
|
||||
tv.short_view = std::string("timestamp: ") + std::to_string(ee.v) + " " + epee::misc_utils::get_internet_time_str(ee.v);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_details_flags& ee)
|
||||
{
|
||||
tv.type = "details_flags";
|
||||
tv.short_view = epee::string_tools::pod_to_hex(ee.v);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const crypto::public_key& ee)
|
||||
{
|
||||
tv.type = "pub_key";
|
||||
tv.short_view = epee::string_tools::pod_to_hex(ee);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const extra_attachment_info& ee)
|
||||
{
|
||||
tv.type = "attachment_info";
|
||||
tv.short_view = std::to_string(ee.sz) + " bytes";
|
||||
tv.details_view = currency::obj_to_json_str(ee);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const extra_alias_entry& ee)
|
||||
{
|
||||
tv.type = "alias_info";
|
||||
tv.short_view = ee.m_alias + "-->" + get_account_address_as_str(ee.m_address);
|
||||
tv.details_view = currency::obj_to_json_str(ee);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const extra_alias_entry_old& ee)
|
||||
{
|
||||
return operator()(static_cast<const extra_alias_entry&>(ee));
|
||||
}
|
||||
bool operator()(const extra_user_data& ee)
|
||||
{
|
||||
tv.type = "user_data";
|
||||
tv.short_view = std::to_string(ee.buff.size()) + " bytes";
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee.buff);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const extra_padding& ee)
|
||||
{
|
||||
tv.type = "extra_padding";
|
||||
tv.short_view = std::to_string(ee.buff.size()) + " bytes";
|
||||
if (!ee.buff.empty())
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(&ee.buff[0]), ee.buff.size()));
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_comment& ee)
|
||||
{
|
||||
tv.type = "comment";
|
||||
tv.short_view = std::to_string(ee.comment.size()) + " bytes(encrypted)";
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee.comment);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_payer& ee)
|
||||
{
|
||||
//const tx_payer& ee = boost::get<tx_payer>(extra);
|
||||
tv.type = "payer";
|
||||
tv.short_view = "(encrypted)";
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_payer_old&)
|
||||
{
|
||||
tv.type = "payer_old";
|
||||
tv.short_view = "(encrypted)";
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_receiver& ee)
|
||||
{
|
||||
//const tx_payer& ee = boost::get<tx_payer>(extra);
|
||||
tv.type = "receiver";
|
||||
tv.short_view = "(encrypted)";
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_receiver_old& ee)
|
||||
{
|
||||
tv.type = "receiver_old";
|
||||
tv.short_view = "(encrypted)";
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_derivation_hint& ee)
|
||||
{
|
||||
tv.type = "derivation_hint";
|
||||
tv.short_view = std::to_string(ee.msg.size()) + " bytes";
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee.msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const std::string& ee)
|
||||
{
|
||||
tv.type = "string";
|
||||
tv.short_view = std::to_string(ee.size()) + " bytes";
|
||||
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_flags16_t& dh)
|
||||
{
|
||||
tv.type = "FLAGS16";
|
||||
tv.short_view = epee::string_tools::pod_to_hex(dh);
|
||||
tv.details_view = epee::string_tools::pod_to_hex(dh);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const zarcanum_tx_data_v1& ztxd)
|
||||
{
|
||||
tv.type = "zarcanum_tx_data_v1";
|
||||
tv.short_view = "fee = " + print_money_brief(ztxd.fee);
|
||||
tv.details_view = tv.short_view;
|
||||
return true;
|
||||
}
|
||||
bool operator()(const zc_outs_range_proof& rp)
|
||||
{
|
||||
tv.type = "zc_outs_range_proof";
|
||||
// TODO @#@#
|
||||
//tv.short_view = "outputs_count = " + std::to_string(rp.outputs_count);
|
||||
return true;
|
||||
}
|
||||
bool operator()(const zc_balance_proof& bp)
|
||||
{
|
||||
tv.type = "zc_balance_proof";
|
||||
return true;
|
||||
}
|
||||
template<typename t_type>
|
||||
bool operator()(const t_type& t_t)
|
||||
{
|
||||
tv.type = typeid(t_t).name();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
//------------------------------------------------------------------
|
||||
|
||||
|
||||
template<class t_container>
|
||||
bool fill_tx_rpc_payload_items(std::vector<tx_extra_rpc_entry>& target_vector, const t_container& tc)
|
||||
{
|
||||
//handle extra
|
||||
for (auto& extra : tc)
|
||||
{
|
||||
target_vector.push_back(tx_extra_rpc_entry());
|
||||
tx_extra_rpc_entry& tv = target_vector.back();
|
||||
|
||||
rpc_tx_payload_handler vstr(tv);
|
||||
boost::apply_visitor(vstr, extra);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace currency
|
||||
|
|
|
|||
|
|
@ -397,5 +397,14 @@ namespace currency
|
|||
CATCH_ENTRY2(std::vector<tx_source_entry::output_entry>{});
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool validate_tx_output_details_againt_tx_generation_context(const transaction& tx, const tx_generation_context& gen_context, const crypto::secret_key& onet_time_key)
|
||||
{
|
||||
//TODO: Implement this function before mainnet
|
||||
#ifdef TESTNET
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -94,6 +94,13 @@ namespace currency
|
|||
};
|
||||
|
||||
|
||||
enum tx_destination_entry_flags
|
||||
{
|
||||
tdef_none = 0,
|
||||
tdef_explicit_native_asset_id = 0x0001,
|
||||
tdef_explicit_amount_to_provide = 0x0002
|
||||
};
|
||||
|
||||
struct tx_destination_entry
|
||||
{
|
||||
uint64_t amount = 0; // money
|
||||
|
|
@ -103,7 +110,7 @@ namespace currency
|
|||
uint64_t unlock_time = 0;
|
||||
destination_option_htlc_out htlc_options; // htlc options
|
||||
crypto::public_key asset_id = currency::native_coin_asset_id; // not blinded, not premultiplied
|
||||
bool explicit_native_asset_id = false;
|
||||
uint64_t flags = 0; // set of flags (see tx_destination_entry_flags)
|
||||
|
||||
tx_destination_entry() = default;
|
||||
tx_destination_entry(uint64_t a, const account_public_address& ad) : amount(a), addr(1, ad) {}
|
||||
|
|
@ -123,7 +130,7 @@ namespace currency
|
|||
FIELD(unlock_time)
|
||||
FIELD(htlc_options)
|
||||
FIELD(asset_id)
|
||||
FIELD(explicit_native_asset_id)
|
||||
FIELD(flags)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
//---------------------------------------------------------------
|
||||
|
|
@ -201,7 +208,7 @@ namespace currency
|
|||
bool tx_to_blob(const transaction& b, blobdata& b_blob);
|
||||
bool read_keyimages_from_tx(const transaction& tx, std::list<crypto::key_image>& kil);
|
||||
bool validate_inputs_sorting(const transaction& tx);
|
||||
bool is_asset_emitting_transaction(const transaction& tx, asset_descriptor_operation* p_ado = nullptr);
|
||||
bool is_asset_emitting_transaction(const transaction& tx, asset_descriptor_operation* p_ado = nullptr);
|
||||
|
||||
std::vector<tx_source_entry::output_entry> prepare_outputs_entries_for_key_offsets(const std::vector<tx_source_entry::output_entry>& outputs, size_t old_real_index, size_t& new_real_index) noexcept;
|
||||
|
||||
|
|
@ -218,6 +225,7 @@ namespace currency
|
|||
asset_id_blinding_masks.resize(outs_count);
|
||||
amounts.resize(outs_count);
|
||||
amount_blinding_masks.resize(outs_count);
|
||||
zc_input_amounts.resize(zc_ins_count);
|
||||
}
|
||||
|
||||
// TODO @#@# reconsider this check -- sowle
|
||||
|
|
@ -245,6 +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> 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
|
||||
|
|
@ -264,44 +273,48 @@ namespace currency
|
|||
|
||||
// consider redesign, some data may possibly be excluded from kv serialization -- sowle
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(asset_ids);
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(blinded_asset_ids);
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(amount_commitments);
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(asset_id_blinding_masks);
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(amounts);
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(amount_blinding_masks);
|
||||
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_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);
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(amount_commitments_sum);
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(amount_blinding_masks_sum);
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id_blinding_mask_x_amount_sum);
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_asset_id);
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_asset_id_pt);
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_amount_commitment);
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_amount_blinding_mask);
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(asset_ids)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(blinded_asset_ids)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(amount_commitments)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(asset_id_blinding_masks)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(amounts)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(amount_blinding_masks)
|
||||
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(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)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(amount_commitments_sum)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(amount_blinding_masks_sum)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id_blinding_mask_x_amount_sum)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_asset_id)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_asset_id_pt)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_amount_commitment)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_amount_blinding_mask)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
// solely for consolidated txs, asset opration fields are not serialized
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(asset_ids);
|
||||
FIELD(blinded_asset_ids);
|
||||
FIELD(amount_commitments);
|
||||
FIELD((std::vector<crypto::scalar_t>&)(asset_id_blinding_masks));
|
||||
FIELD((std::vector<crypto::scalar_t>&)(amounts));
|
||||
FIELD((std::vector<crypto::scalar_t>&)(amount_blinding_masks));
|
||||
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(pseudo_out_amount_commitments_sum);
|
||||
FIELD(pseudo_out_amount_blinding_masks_sum);
|
||||
FIELD(real_in_asset_id_blinding_mask_x_amount_sum);
|
||||
FIELD(amount_commitments_sum);
|
||||
FIELD(amount_blinding_masks_sum);
|
||||
FIELD(asset_id_blinding_mask_x_amount_sum);
|
||||
VERSION()
|
||||
CURRENT_VERSION(0)
|
||||
FIELD(asset_ids)
|
||||
FIELD(blinded_asset_ids)
|
||||
FIELD(amount_commitments)
|
||||
FIELD((std::vector<crypto::scalar_t>&)(asset_id_blinding_masks))
|
||||
FIELD((std::vector<crypto::scalar_t>&)(amounts))
|
||||
FIELD((std::vector<crypto::scalar_t>&)(amount_blinding_masks))
|
||||
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(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)
|
||||
FIELD(amount_commitments_sum)
|
||||
FIELD(amount_blinding_masks_sum)
|
||||
FIELD(asset_id_blinding_mask_x_amount_sum)
|
||||
|
||||
// no asset operation fields here
|
||||
//ao_asset_id
|
||||
|
|
@ -311,4 +324,6 @@ namespace currency
|
|||
END_SERIALIZE()
|
||||
}; // struct tx_generation_context
|
||||
|
||||
bool validate_tx_output_details_againt_tx_generation_context(const transaction& tx, const tx_generation_context& gen_context, const crypto::secret_key& onet_time_key);
|
||||
|
||||
} // namespace currency
|
||||
|
|
|
|||
|
|
@ -516,7 +516,7 @@ namespace currency
|
|||
txs.push_back(tx_rpc_extended_info());
|
||||
tx_rpc_extended_info& trei = txs.back();
|
||||
trei.blob_size = tx_entry.blob_size;
|
||||
fill_tx_rpc_details(trei, tx_entry.tx, nullptr, h, tx_entry.receive_time, true);
|
||||
m_blockchain.fill_tx_rpc_details(trei, tx_entry.tx, nullptr, h, tx_entry.receive_time, true);
|
||||
return true;
|
||||
});
|
||||
|
||||
|
|
@ -568,7 +568,7 @@ namespace currency
|
|||
txs.push_back(tx_rpc_extended_info());
|
||||
tx_rpc_extended_info& trei = txs.back();
|
||||
trei.blob_size = ptei->blob_size;
|
||||
fill_tx_rpc_details(trei, ptei->tx, nullptr, id, ptei->receive_time, false);
|
||||
m_blockchain.fill_tx_rpc_details(trei, ptei->tx, nullptr, id, ptei->receive_time, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -605,7 +605,7 @@ namespace currency
|
|||
if (!ptei)
|
||||
return false;
|
||||
|
||||
fill_tx_rpc_details(trei, ptei->tx, nullptr, id, ptei->receive_time, false);
|
||||
m_blockchain.fill_tx_rpc_details(trei, ptei->tx, nullptr, id, ptei->receive_time, false);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#define PREPARE_ARG_FROM_JSON(arg_type, var_name) \
|
||||
arg_type var_name = AUTO_VAL_INIT(var_name); \
|
||||
view::api_response default_ar = AUTO_VAL_INIT(default_ar); \
|
||||
LOG_PRINT_BLUE("[REQUEST]: " << param.toStdString(), LOG_LEVEL_3); \
|
||||
if (!epee::serialization::load_t_from_json(var_name, param.toStdString())) \
|
||||
{ \
|
||||
default_ar.error_code = API_RETURN_CODE_BAD_ARG; \
|
||||
|
|
@ -28,6 +29,7 @@ template<typename T>
|
|||
QString make_response(const T& r)
|
||||
{
|
||||
std::string str = epee::serialization::store_t_to_json(r);
|
||||
LOG_PRINT_BLUE("[RESPONSE]: " << str, LOG_LEVEL_3);
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
|
|
@ -549,6 +551,14 @@ void MainWindow::store_pos(bool consider_showed)
|
|||
void MainWindow::restore_pos(bool consider_showed)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
if (consider_showed)
|
||||
{
|
||||
if (m_config.is_showed)
|
||||
this->showNormal();
|
||||
else
|
||||
this->showMinimized();
|
||||
}
|
||||
|
||||
if (m_config.is_maximazed)
|
||||
{
|
||||
this->setWindowState(windowState() | Qt::WindowMaximized);
|
||||
|
|
@ -580,14 +590,6 @@ void MainWindow::restore_pos(bool consider_showed)
|
|||
}
|
||||
}
|
||||
|
||||
if (consider_showed)
|
||||
{
|
||||
if (m_config.is_showed)
|
||||
this->showNormal();
|
||||
else
|
||||
this->showMinimized();
|
||||
}
|
||||
|
||||
CATCH_ENTRY2(void());
|
||||
}
|
||||
void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
|
||||
|
|
@ -2160,7 +2162,39 @@ QString MainWindow::get_wallet_info(const QString& param)
|
|||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::create_ionic_swap_proposal(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
PREPARE_ARG_FROM_JSON(view::create_ionic_swap_proposal_request, cispr);
|
||||
PREPARE_RESPONSE(std::string, ar);
|
||||
ar.error_code = m_backend.create_ionic_swap_proposal(cispr.wallet_id, cispr, ar.response_data);
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::get_ionic_swap_proposal_info(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
PREPARE_ARG_FROM_JSON(view::api_request_t<std::string>, tx_raw_hex);
|
||||
PREPARE_RESPONSE(tools::wallet_public::ionic_swap_proposal_info, ar);
|
||||
ar.error_code = m_backend.get_ionic_swap_proposal_info(tx_raw_hex.wallet_id, tx_raw_hex.req_data, ar.response_data);
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
|
||||
}
|
||||
|
||||
QString MainWindow::accept_ionic_swap_proposal(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
LOG_API_TIMING();
|
||||
PREPARE_ARG_FROM_JSON(view::api_request_t<std::string>, tx_raw_hex);
|
||||
PREPARE_RESPONSE(std::string, ar);
|
||||
ar.error_code = m_backend.accept_ionic_swap_proposal(tx_raw_hex.wallet_id, tx_raw_hex.req_data, ar.response_data);
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
QString MainWindow::backup_wallet_keys(const QString& param)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
|
|||
|
|
@ -172,6 +172,9 @@ public:
|
|||
QString remove_custom_asset_id(const QString& param);
|
||||
QString get_wallet_info(const QString& param);
|
||||
|
||||
QString create_ionic_swap_proposal(const QString& param);
|
||||
QString get_ionic_swap_proposal_info(const QString& param);
|
||||
QString accept_ionic_swap_proposal(const QString& param);
|
||||
|
||||
bool get_is_disabled_notifications();
|
||||
bool set_is_disabled_notifications(const bool& param);
|
||||
|
|
|
|||
|
|
@ -63,8 +63,8 @@ inline bool do_serialize(Archive &ar, T &v)
|
|||
#define BEGIN_SERIALIZE() \
|
||||
template <bool W, template <bool> class Archive> bool do_serialize(Archive<W> &_ser_ar) {uint8_t s_current_version ATTRIBUTE_UNUSED = 0; uint8_t s_version ATTRIBUTE_UNUSED = 0;
|
||||
#define BEGIN_SERIALIZE_OBJECT() \
|
||||
template <bool W, template <bool> class Archive> bool do_serialize(Archive<W> &_ser_ar) { _ser_ar.begin_object(); bool _ser_res = do_serialize_object(_ser_ar); _ser_ar.end_object(); return _ser_res; } \
|
||||
template <bool W, template <bool> class Archive> bool do_serialize_object(Archive<W> &_ser_ar){
|
||||
template <bool W, template <bool> class Archive> bool do_serialize(Archive<W> &_ser_ar) {_ser_ar.begin_object(); bool _ser_res = do_serialize_object(_ser_ar); _ser_ar.end_object(); return _ser_res; } \
|
||||
template <bool W, template <bool> class Archive> bool do_serialize_object(Archive<W> &_ser_ar){ uint8_t s_current_version ATTRIBUTE_UNUSED = 0; uint8_t s_version ATTRIBUTE_UNUSED = 0;
|
||||
#define PREPARE_CUSTOM_VECTOR_SERIALIZATION(size, vec) ::serialization::detail::prepare_custom_vector_serialization(size, vec, typename Archive<W>::is_saving())
|
||||
|
||||
#define END_SERIALIZE() return true;}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <cstdlib>
|
||||
#if defined(WIN32)
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
#include <thread>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
|
@ -22,11 +26,10 @@
|
|||
#include "string_coding.h"
|
||||
#include "wallet/wrap_service.h"
|
||||
#include "common/general_purpose_commands_defs.h"
|
||||
#include <cstdlib>
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
#include "wallet/wallet_helpers.h"
|
||||
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace epee;
|
||||
|
|
@ -229,6 +232,10 @@ simple_wallet::simple_wallet()
|
|||
m_cmd_binder.set_handler("add_custom_asset_id", boost::bind(&simple_wallet::add_custom_asset_id, this, ph::_1), "Approve asset id to be recognized in the wallet and returned in balances");
|
||||
m_cmd_binder.set_handler("remove_custom_asset_id", boost::bind(&simple_wallet::remove_custom_asset_id, this, ph::_1), "Cancel previously made approval for asset id");
|
||||
|
||||
m_cmd_binder.set_handler("generate_ionic_swap_proposal", boost::bind(&simple_wallet::generate_ionic_swap_proposal, this, _1), "generate_ionic_swap_proposal <proposal_config.json> <destination_addr>- Generates ionic_swap proposal with given conditions");
|
||||
m_cmd_binder.set_handler("get_ionic_swap_proposal_info", boost::bind(&simple_wallet::get_ionic_swap_proposal_info, this, _1), "get_ionic_swap_proposal_info <hex_encoded_raw_proposal> - Extracts and display information from ionic_swap proposal raw data");
|
||||
m_cmd_binder.set_handler("accept_ionic_swap_proposal", boost::bind(&simple_wallet::accept_ionic_swap_proposal, this, _1), "accept_ionic_swap_proposal <hex_encoded_raw_proposal> - Accept ionic_swap proposal and generates exchange transaction");
|
||||
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
simple_wallet::~simple_wallet()
|
||||
|
|
@ -691,6 +698,17 @@ void simple_wallet::on_tor_status_change(const std::string& state)
|
|||
message_writer(epee::log_space::console_color_yellow, true, std::string("[TOR]: ")) << human_message;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void simple_wallet::on_mw_get_wallets(std::vector<tools::wallet_public::wallet_entry_info>& wallets)
|
||||
{
|
||||
wallets.resize(1);
|
||||
tools::get_wallet_info(*m_wallet, wallets[0].wi);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::on_mw_select_wallet(uint64_t wallet_id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::refresh(const std::vector<std::string>& args)
|
||||
{
|
||||
if (m_offline_mode)
|
||||
|
|
@ -1801,7 +1819,7 @@ bool simple_wallet::deploy_new_asset(const std::vector<std::string> &args)
|
|||
tx_destination_entry td = AUTO_VAL_INIT(td);
|
||||
td.addr.push_back(m_wallet->get_account().get_public_address());
|
||||
td.amount = adb.current_supply;
|
||||
td.asset_id = currency::ffff_pkey;
|
||||
td.asset_id = currency::null_pkey;
|
||||
std::vector<currency::tx_destination_entry> destinations;
|
||||
destinations.push_back(td);
|
||||
currency::transaction result_tx = AUTO_VAL_INIT(result_tx);
|
||||
|
|
@ -1849,6 +1867,104 @@ bool simple_wallet::add_custom_asset_id(const std::vector<std::string> &args)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::generate_ionic_swap_proposal(const std::vector<std::string> &args)
|
||||
{
|
||||
|
||||
if (args.size() != 2)
|
||||
{
|
||||
fail_msg_writer() << "invalid arguments count: " << args.size() << ", expected 1";
|
||||
}
|
||||
|
||||
view::ionic_swap_proposal_info proposal = AUTO_VAL_INIT(proposal);
|
||||
bool r = epee::serialization::load_t_from_json_file(proposal, args[0]);
|
||||
if (!r)
|
||||
{
|
||||
fail_msg_writer() << "Failed to load json file with asset specification: " << args[0];
|
||||
}
|
||||
currency::account_public_address destination_addr = AUTO_VAL_INIT(destination_addr);
|
||||
currency::payment_id_t integrated_payment_id;
|
||||
if (!m_wallet->get_transfer_address(args[1], destination_addr, integrated_payment_id))
|
||||
{
|
||||
fail_msg_writer() << "wrong address: " << args[1];
|
||||
return true;
|
||||
}
|
||||
if (integrated_payment_id.size())
|
||||
{
|
||||
fail_msg_writer() << "Integrated addresses not supported yet";
|
||||
return true;
|
||||
}
|
||||
|
||||
transaction tx_template = AUTO_VAL_INIT(tx_template);
|
||||
r = m_wallet->create_ionic_swap_proposal(proposal, destination_addr, tx_template);
|
||||
if (!r)
|
||||
{
|
||||
fail_msg_writer() << "Failed to create ionic_swap proposal";
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
success_msg_writer() << "Generated proposal: " << ENDL << epee::string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(tx_template));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::get_ionic_swap_proposal_info(const std::vector<std::string> &args)
|
||||
{
|
||||
if (args.size() != 1)
|
||||
{
|
||||
fail_msg_writer() << "invalid arguments count: " << args.size() << ", expected 1";
|
||||
}
|
||||
|
||||
std::string raw_tx_template;
|
||||
bool r = epee::string_tools::parse_hexstr_to_binbuff(args[0], raw_tx_template);
|
||||
if (!r)
|
||||
{
|
||||
fail_msg_writer() << "Failed to parse proposal hex to raw data";
|
||||
return true;
|
||||
}
|
||||
|
||||
view::ionic_swap_proposal_info proposal = AUTO_VAL_INIT(proposal);
|
||||
if (!m_wallet->get_ionic_swap_proposal_info(raw_tx_template, proposal))
|
||||
{
|
||||
fail_msg_writer() << "Failed to decode proposal info";
|
||||
return true;
|
||||
}
|
||||
std::string json_proposal = epee::serialization::store_t_to_json(proposal);
|
||||
|
||||
|
||||
success_msg_writer() << "Proposal details: " << ENDL << json_proposal;
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::accept_ionic_swap_proposal(const std::vector<std::string> &args)
|
||||
{
|
||||
if (args.size() != 1)
|
||||
{
|
||||
fail_msg_writer() << "invalid arguments count: " << args.size() << ", expected 1";
|
||||
}
|
||||
|
||||
std::string raw_tx_template;
|
||||
bool r = epee::string_tools::parse_hexstr_to_binbuff(args[0], raw_tx_template);
|
||||
if (!r)
|
||||
{
|
||||
fail_msg_writer() << "Failed to parse proposal hex to raw data";
|
||||
return true;
|
||||
}
|
||||
|
||||
currency::transaction result_tx = AUTO_VAL_INIT(result_tx);
|
||||
if (!m_wallet->accept_ionic_swap_proposal(raw_tx_template, result_tx))
|
||||
{
|
||||
fail_msg_writer() << "Failed accept ionic_swap proposal";
|
||||
return true;
|
||||
}
|
||||
|
||||
success_msg_writer() << "Proposal accepted and executed, tx_id : " << currency::get_transaction_hash(result_tx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::remove_custom_asset_id(const std::vector<std::string> &args)
|
||||
{
|
||||
|
|
@ -2239,7 +2355,8 @@ int main(int argc, char* argv[])
|
|||
if (daemon_address.empty())
|
||||
daemon_address = std::string("http://") + daemon_host + ":" + std::to_string(daemon_port);
|
||||
|
||||
tools::wallet2 wal;
|
||||
std::shared_ptr<tools::wallet2> wallet_ptr(new tools::wallet2());
|
||||
tools::wallet2& wal = *wallet_ptr;
|
||||
//try to open it
|
||||
while (true)
|
||||
{
|
||||
|
|
@ -2295,7 +2412,7 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
tools::wallet_rpc_server wrpc(wal);
|
||||
tools::wallet_rpc_server wrpc(wallet_ptr);
|
||||
bool r = wrpc.init(vm);
|
||||
CHECK_AND_ASSERT_MES(r, EXIT_FAILURE, "Failed to initialize wallet rpc server");
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,11 @@ namespace currency
|
|||
bool add_custom_asset_id(const std::vector<std::string> &args);
|
||||
bool remove_custom_asset_id(const std::vector<std::string> &args);
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool generate_ionic_swap_proposal(const std::vector<std::string> &args);
|
||||
bool get_ionic_swap_proposal_info(const std::vector<std::string> &args);
|
||||
bool accept_ionic_swap_proposal(const std::vector<std::string> &args);
|
||||
|
||||
bool validate_wrap_status(uint64_t amount);
|
||||
|
||||
bool get_alias_from_daemon(const std::string& alias_name, currency::extra_alias_entry_base& ai);
|
||||
|
|
@ -106,6 +111,8 @@ namespace currency
|
|||
virtual void on_message(i_wallet2_callback::message_severity severity, const std::string& m) override;
|
||||
virtual void on_tor_status_change(const std::string& state) override;
|
||||
|
||||
virtual void on_mw_get_wallets(std::vector<tools::wallet_public::wallet_entry_info>& wallets) override;
|
||||
virtual bool on_mw_select_wallet(uint64_t wallet_id) override;
|
||||
//----------------------------------------------------------
|
||||
|
||||
friend class refresh_progress_reporter_t;
|
||||
|
|
@ -178,7 +185,7 @@ namespace currency
|
|||
|
||||
epee::console_handlers_binder m_cmd_binder;
|
||||
|
||||
std::unique_ptr<tools::wallet2> m_wallet;
|
||||
std::shared_ptr<tools::wallet2> m_wallet;
|
||||
net_utils::http::http_simple_client m_http_client;
|
||||
refresh_progress_reporter_t m_refresh_progress_reporter;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -209,40 +209,9 @@ public:
|
|||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct wallet_info
|
||||
{
|
||||
std::list<tools::wallet_public::asset_balance_entry> balances;
|
||||
uint64_t mined_total;
|
||||
std::string address;
|
||||
std::string view_sec_key;
|
||||
std::string path;
|
||||
bool is_auditable;
|
||||
bool is_watch_only;
|
||||
typedef tools::wallet_public::wallet_info wallet_info;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(balances)
|
||||
KV_SERIALIZE(mined_total)
|
||||
KV_SERIALIZE(address)
|
||||
KV_SERIALIZE(view_sec_key)
|
||||
KV_SERIALIZE(path)
|
||||
KV_SERIALIZE(is_auditable);
|
||||
KV_SERIALIZE(is_watch_only);
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct wallet_entry_info
|
||||
{
|
||||
wallet_info wi;
|
||||
uint64_t wallet_id;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(wi)
|
||||
KV_SERIALIZE(wallet_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
};
|
||||
typedef tools::wallet_public::wallet_entry_info wallet_entry_info;
|
||||
|
||||
|
||||
|
||||
|
|
@ -440,7 +409,7 @@ public:
|
|||
struct wallet_and_asset_id
|
||||
{
|
||||
uint64_t wallet_id = 0;
|
||||
crypto::hash asset_id = currency::null_hash;
|
||||
crypto::public_key asset_id = currency::null_pkey;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(wallet_id)
|
||||
|
|
@ -686,14 +655,11 @@ public:
|
|||
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct wallet_and_contract_id_param
|
||||
{
|
||||
uint64_t wallet_id;
|
||||
crypto::hash contract_id;
|
||||
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(wallet_id)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(contract_id)
|
||||
|
|
@ -742,6 +708,11 @@ public:
|
|||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
typedef tools::wallet_public::asset_funds asset_funds;
|
||||
typedef tools::wallet_public::ionic_swap_proposal_info ionic_swap_proposal_info;
|
||||
typedef tools::wallet_public::create_ionic_swap_proposal_request create_ionic_swap_proposal_request;
|
||||
|
||||
struct address_validation_response
|
||||
{
|
||||
std::string error_code;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -934,7 +936,9 @@ void wallet2::accept_proposal(const crypto::hash& contract_id, uint64_t b_accept
|
|||
|
||||
construct_tx_param construct_param = AUTO_VAL_INIT(construct_param);
|
||||
construct_param.fee = b_acceptance_fee;
|
||||
currency::transaction tx = contr_it->second.proposal.tx_template;
|
||||
mode_separate_context msc = AUTO_VAL_INIT(msc);
|
||||
msc.tx_for_mode_separate = contr_it->second.proposal.tx_template;
|
||||
currency::transaction& tx = msc.tx_for_mode_separate;
|
||||
crypto::secret_key one_time_key = contr_it->second.proposal.tx_onetime_secret_key;
|
||||
construct_param.crypt_address = m_account.get_public_address();
|
||||
construct_param.flags = TX_FLAG_SIGNATURE_MODE_SEPARATE;
|
||||
|
|
@ -992,7 +996,7 @@ void wallet2::accept_proposal(const crypto::hash& contract_id, uint64_t b_accept
|
|||
//build transaction
|
||||
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
|
||||
ftp.tx_version = this->get_current_tx_version();
|
||||
prepare_transaction(construct_param, ftp, tx);
|
||||
prepare_transaction(construct_param, ftp, msc);
|
||||
mark_transfers_as_spent(ftp.selected_transfers, std::string("contract <") + epee::string_tools::pod_to_hex(contract_id) + "> has been accepted with tx <" + epee::string_tools::pod_to_hex(get_transaction_hash(tx)) + ">");
|
||||
|
||||
try
|
||||
|
|
@ -4739,7 +4743,7 @@ void wallet2::build_escrow_template(const bc_services::contract_private_details&
|
|||
|
||||
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
|
||||
ftp.tx_version = this->get_current_tx_version();
|
||||
prepare_transaction(ctp, ftp, tx);
|
||||
prepare_transaction(ctp, ftp);
|
||||
|
||||
selected_transfers = ftp.selected_transfers;
|
||||
|
||||
|
|
@ -4991,6 +4995,337 @@ bool wallet2::check_htlc_redeemed(const crypto::hash& htlc_tx_id, std::string& o
|
|||
return false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::create_ionic_swap_proposal(const wallet_public::ionic_swap_proposal_info& proposal_details, const currency::account_public_address& destination_addr, wallet_public::ionic_swap_proposal& proposal)
|
||||
{
|
||||
std::vector<uint64_t> selected_transfers_for_template;
|
||||
|
||||
build_ionic_swap_template(proposal_details, destination_addr, proposal, selected_transfers_for_template);
|
||||
|
||||
const uint32_t mask_to_mark_escrow_template_locked_transfers = WALLET_TRANSFER_DETAIL_FLAG_BLOCKED | WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION;
|
||||
mark_transfers_with_flag(selected_transfers_for_template, mask_to_mark_escrow_template_locked_transfers, "preparing ionic_swap");
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::build_ionic_swap_template(const wallet_public::ionic_swap_proposal_info& proposal_detais, const currency::account_public_address& destination_addr,
|
||||
wallet_public::ionic_swap_proposal& proposal,
|
||||
std::vector<uint64_t>& selected_transfers)
|
||||
{
|
||||
construct_tx_param ctp = get_default_construct_tx_param();
|
||||
|
||||
ctp.fake_outputs_count = proposal_detais.mixins;
|
||||
ctp.fee = proposal_detais.fee_paid_by_a;
|
||||
ctp.flags = TX_FLAG_SIGNATURE_MODE_SEPARATE;
|
||||
ctp.mark_tx_as_complete = false;
|
||||
ctp.crypt_address = destination_addr;
|
||||
|
||||
etc_tx_details_expiration_time t = AUTO_VAL_INIT(t);
|
||||
t.v = proposal_detais.expiration_time;
|
||||
ctp.extra.push_back(t);
|
||||
|
||||
ctp.dsts.resize(proposal_detais.to_bob.size() + proposal_detais.to_alice.size());
|
||||
size_t i = 0;
|
||||
// Here is an proposed for exchange funds
|
||||
for (; i != proposal_detais.to_bob.size(); i++)
|
||||
{
|
||||
ctp.dsts[i].amount = proposal_detais.to_bob[i].amount;
|
||||
ctp.dsts[i].amount_to_provide = proposal_detais.to_bob[i].amount;
|
||||
ctp.dsts[i].flags |= tx_destination_entry_flags::tdef_explicit_amount_to_provide;
|
||||
ctp.dsts[i].addr.push_back(destination_addr);
|
||||
ctp.dsts[i].asset_id = proposal_detais.to_bob[i].asset_id;
|
||||
}
|
||||
// Here is an expected in return funds
|
||||
for (size_t j = 0; j != proposal_detais.to_alice.size(); j++, i++)
|
||||
{
|
||||
ctp.dsts[i].amount = proposal_detais.to_alice[j].amount;
|
||||
ctp.dsts[i].amount_to_provide = 0;
|
||||
ctp.dsts[i].flags |= tx_destination_entry_flags::tdef_explicit_amount_to_provide;
|
||||
ctp.dsts[i].addr.push_back(m_account.get_public_address());
|
||||
ctp.dsts[i].asset_id = proposal_detais.to_alice[j].asset_id;
|
||||
}
|
||||
|
||||
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
|
||||
ftp.mode_separate_fee = ctp.fee;
|
||||
ftp.tx_version = this->get_current_tx_version();
|
||||
prepare_transaction(ctp, ftp);
|
||||
|
||||
selected_transfers = ftp.selected_transfers;
|
||||
currency::finalized_tx finalize_result = AUTO_VAL_INIT(finalize_result);
|
||||
finalize_transaction(ftp, finalize_result, false);
|
||||
add_transfers_to_expiration_list(selected_transfers, proposal_detais.expiration_time, 0, currency::null_hash);
|
||||
|
||||
//wrap it all
|
||||
proposal.tx_template = finalize_result.tx;
|
||||
wallet_public::ionic_swap_proposal_context ispc = AUTO_VAL_INIT(ispc);
|
||||
ispc.gen_context = finalize_result.ftp.gen_context;
|
||||
ispc.one_time_skey = finalize_result.one_time_key;
|
||||
std::string proposal_context_blob = t_serializable_object_to_blob(ispc);
|
||||
proposal.encrypted_context = crypto::chacha_crypt(static_cast<const std::string&>(proposal_context_blob), finalize_result.derivation);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::get_ionic_swap_proposal_info(const std::string&raw_proposal, wallet_public::ionic_swap_proposal_info& proposal_info)
|
||||
{
|
||||
wallet_public::ionic_swap_proposal proposal = AUTO_VAL_INIT(proposal);
|
||||
bool r = t_unserializable_object_from_blob(proposal, raw_proposal);
|
||||
THROW_IF_TRUE_WALLET_EX(!r, error::wallet_internal_error, "Failed to parse proposal");
|
||||
return get_ionic_swap_proposal_info(proposal, proposal_info);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::get_ionic_swap_proposal_info(const wallet_public::ionic_swap_proposal& proposal, wallet_public::ionic_swap_proposal_info& proposal_info)
|
||||
{
|
||||
wallet_public::ionic_swap_proposal_context ionic_context = AUTO_VAL_INIT(ionic_context);
|
||||
return get_ionic_swap_proposal_info(proposal, proposal_info, ionic_context);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::get_ionic_swap_proposal_info(const wallet_public::ionic_swap_proposal& proposal, wallet_public::ionic_swap_proposal_info& proposal_info, wallet_public::ionic_swap_proposal_context& ionic_context)
|
||||
{
|
||||
const transaction& tx = proposal.tx_template;
|
||||
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
|
||||
std::vector<wallet_out_info> outs;
|
||||
uint64_t tx_money_got_in_outs = 0;
|
||||
bool r = lookup_acc_outs(m_account.get_keys(), tx, outs, tx_money_got_in_outs, derivation);
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(r, "Failed to lookup_acc_outs for tx: " << get_transaction_hash(tx));
|
||||
|
||||
if (!outs.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//decrypt context
|
||||
std::string decrypted_raw_context = crypto::chacha_crypt(proposal.encrypted_context, derivation);
|
||||
r = t_unserializable_object_from_blob(ionic_context, decrypted_raw_context);
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(r, "Failed to unserialize decrypted ionic_context");
|
||||
|
||||
r = validate_tx_output_details_againt_tx_generation_context(tx, ionic_context.gen_context, ionic_context.one_time_skey);
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(r, "Failed to validate decrypted ionic_context");
|
||||
|
||||
std::unordered_map<crypto::public_key, uint64_t> amounts_provided_by_a;
|
||||
|
||||
std::unordered_map<crypto::public_key, uint64_t> ammounts_to_a; //amounts to Alice (the one who created proposal), should be NOT funded
|
||||
std::unordered_map<crypto::public_key, uint64_t> ammounts_to_b; //amounts to Bob (the one who received proposal), should BE funded
|
||||
std::vector<bool> bob_outs;
|
||||
bob_outs.resize(proposal.tx_template.vout.size());
|
||||
|
||||
for (const auto& o : outs)
|
||||
{
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(ionic_context.gen_context.asset_ids.size() > o.index, "Tx gen context has mismatch with tx(asset_ids) ");
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(ionic_context.gen_context.asset_ids[o.index].to_public_key() == o.asset_id, "Tx gen context has mismatch with tx(asset_id != asset_id) ");
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(ionic_context.gen_context.amounts[o.index].m_u64[0] == o.amount, "Tx gen context has mismatch with tx(amount != amount)");
|
||||
|
||||
ammounts_to_b[o.asset_id] += o.amount;
|
||||
bob_outs[o.index] = true;
|
||||
}
|
||||
size_t i = 0;
|
||||
//validate outputs against decrypted tx generation context
|
||||
for (i = 0; i != tx.vout.size(); i++)
|
||||
{
|
||||
|
||||
if (bob_outs[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
crypto::public_key asset_id = ionic_context.gen_context.asset_ids[i].to_public_key();
|
||||
uint64_t amount = ionic_context.gen_context.amounts[i].m_u64[0];
|
||||
ammounts_to_a[asset_id] += amount;
|
||||
}
|
||||
|
||||
//read amounts already provided by third party
|
||||
size_t zc_current_index = 0; //some inputs might be old ones, so it's asset id assumed as native and there is no entry for it in real_zc_ins_asset_ids
|
||||
//THROW_IF_FALSE_WALLET_INT_ERR_EX(ionic_context.gen_context.input_amounts.size() == tx.vin.size(), "Tx gen context has mismatch with tx(amount != amount)");
|
||||
for (i = 0; i != tx.vin.size(); i++)
|
||||
{
|
||||
size_t mx = 0;
|
||||
uint64_t amount = 0;
|
||||
crypto::public_key in_asset_id = currency::native_coin_asset_id;
|
||||
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.zc_input_amounts[zc_current_index];
|
||||
zc_current_index++;
|
||||
mx = boost::get<currency::txin_zc_input>(tx.vin[i]).key_offsets.size() - 1;
|
||||
}
|
||||
else if (tx.vin[i].type() == typeid(txin_to_key))
|
||||
{
|
||||
amount = boost::get<txin_to_key>(tx.vin[i]).amount;
|
||||
mx = boost::get<currency::txin_to_key>(tx.vin[i]).key_offsets.size() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLT_LOG_RED("Unexpected type of input in ionic_swap tx: " << tx.vin[i].type().name(), LOG_LEVEL_0);
|
||||
return false;
|
||||
}
|
||||
amounts_provided_by_a[in_asset_id] += amount;
|
||||
|
||||
if (proposal_info.mixins == 0 || proposal_info.mixins > mx)
|
||||
{
|
||||
proposal_info.mixins = mx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//this might be 0, if Alice don't want to pay fee herself
|
||||
proposal_info.fee_paid_by_a = currency::get_tx_fee(tx);
|
||||
if (proposal_info.fee_paid_by_a)
|
||||
{
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(amounts_provided_by_a[currency::native_coin_asset_id] >= proposal_info.fee_paid_by_a, "Fee mentioned as specified but not provided by A");
|
||||
amounts_provided_by_a[currency::native_coin_asset_id] -= proposal_info.fee_paid_by_a;
|
||||
}
|
||||
|
||||
//proposal_info.fee = currency::get_tx_fee(tx);
|
||||
//need to make sure that funds for Bob properly funded
|
||||
for (const auto& a : ammounts_to_b)
|
||||
{
|
||||
uint64_t amount_sent_back_to_alice = ammounts_to_a[a.first];
|
||||
|
||||
if (amounts_provided_by_a[a.first] < (a.second + amount_sent_back_to_alice) )
|
||||
{
|
||||
WLT_LOG_RED("Amount[" << a.first << "] provided by Alice(" << amounts_provided_by_a[a.first] << ") is less then transfered to Bob(" << a.second <<")", LOG_LEVEL_0);
|
||||
return false;
|
||||
}
|
||||
amounts_provided_by_a[a.first] -= (amount_sent_back_to_alice + a.second);
|
||||
proposal_info.to_bob.push_back(view::asset_funds{ a.first, a.second });
|
||||
//clean accounted assets
|
||||
ammounts_to_a.erase(ammounts_to_a.find(a.first));
|
||||
if (amounts_provided_by_a[a.first] > 0)
|
||||
{
|
||||
WLT_LOG_RED("Amount[" << a.first << "] provided by Alice has unused leftovers: " << amounts_provided_by_a[a.first], LOG_LEVEL_0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//need to see what Alice actually expect in return
|
||||
for (const auto& a : ammounts_to_a)
|
||||
{
|
||||
//now amount provided by A should be less or equal to what we have in a.second
|
||||
if (amounts_provided_by_a[a.first] > a.second)
|
||||
{
|
||||
//could be fee
|
||||
WLT_LOG_RED("Amount[" << a.first << "] provided by Alice has unused leftovers: " << amounts_provided_by_a[a.first], LOG_LEVEL_0);
|
||||
return false;
|
||||
}
|
||||
|
||||
proposal_info.to_alice.push_back(view::asset_funds{ a.first, a.second - amounts_provided_by_a[a.first] });
|
||||
}
|
||||
|
||||
etc_tx_details_expiration_time t = AUTO_VAL_INIT(t);
|
||||
if (!get_type_in_variant_container(tx.extra, t))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
proposal_info.expiration_time = t.v;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::accept_ionic_swap_proposal(const std::string& raw_proposal, currency::transaction& result_tx)
|
||||
{
|
||||
wallet_public::ionic_swap_proposal proposal = AUTO_VAL_INIT(proposal);
|
||||
bool r = t_unserializable_object_from_blob(proposal, raw_proposal);
|
||||
THROW_IF_TRUE_WALLET_EX(!r, error::wallet_internal_error, "Failed to parse proposal info");
|
||||
|
||||
return accept_ionic_swap_proposal(proposal, result_tx);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::accept_ionic_swap_proposal(const wallet_public::ionic_swap_proposal& proposal, currency::transaction& result_tx)
|
||||
{
|
||||
mode_separate_context msc = AUTO_VAL_INIT(msc);
|
||||
msc.tx_for_mode_separate = proposal.tx_template;
|
||||
result_tx = msc.tx_for_mode_separate;
|
||||
|
||||
wallet_public::ionic_swap_proposal_context ionic_context = AUTO_VAL_INIT(ionic_context);
|
||||
bool r = get_ionic_swap_proposal_info(proposal, msc.proposal_info, ionic_context);
|
||||
THROW_IF_TRUE_WALLET_EX(!r, error::wallet_internal_error, "Failed to get info from proposal");
|
||||
|
||||
std::unordered_map<crypto::public_key, wallet_public::asset_balance_entry_base> balances;
|
||||
uint64_t mined = 0;
|
||||
this->balance(balances, mined);
|
||||
//validate balances needed
|
||||
uint64_t native_amount_required = 0;
|
||||
for (const auto& item : msc.proposal_info.to_alice)
|
||||
{
|
||||
if (balances[item.asset_id].unlocked < item.amount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (item.asset_id == currency::native_coin_asset_id)
|
||||
{
|
||||
native_amount_required = item.amount;
|
||||
}
|
||||
}
|
||||
|
||||
// balances is ok, check if fee is added to tx
|
||||
uint64_t additional_fee = 0;
|
||||
if (msc.proposal_info.fee_paid_by_a < m_core_runtime_config.tx_default_fee)
|
||||
{
|
||||
additional_fee = m_core_runtime_config.tx_default_fee - msc.proposal_info.fee_paid_by_a;
|
||||
if (balances[currency::native_coin_asset_id].unlocked < additional_fee + native_amount_required)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//everything is seemed to be ok
|
||||
|
||||
construct_tx_param construct_param = get_default_construct_tx_param();
|
||||
construct_param.fee = additional_fee;
|
||||
|
||||
crypto::secret_key one_time_key = ionic_context.one_time_skey;
|
||||
construct_param.crypt_address = m_account.get_public_address();
|
||||
construct_param.flags = TX_FLAG_SIGNATURE_MODE_SEPARATE;
|
||||
construct_param.mark_tx_as_complete = true;
|
||||
|
||||
//build transaction
|
||||
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
|
||||
ftp.tx_version = this->get_current_tx_version();
|
||||
ftp.gen_context = ionic_context.gen_context;
|
||||
prepare_transaction(construct_param, ftp, msc);
|
||||
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
finalize_transaction(ftp, result_tx, one_time_key, true);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
clear_transfers_from_flag(ftp.selected_transfers, WALLET_TRANSFER_DETAIL_FLAG_SPENT, std::string("exception in finalize_transaction, tx: ") + epee::string_tools::pod_to_hex(get_transaction_hash(result_tx)));
|
||||
throw;
|
||||
}
|
||||
mark_transfers_as_spent(ftp.selected_transfers, std::string("Proposal has been accepted with tx <" + epee::string_tools::pod_to_hex(get_transaction_hash(result_tx))) + ">");
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
// Signing and auth
|
||||
bool wallet2::sign_buffer(const std::string& buff, crypto::signature& sig)
|
||||
{
|
||||
crypto::hash h = crypto::cn_fast_hash(buff.data(), buff.size());
|
||||
crypto::generate_signature(h, m_account.get_public_address().spend_public_key, m_account.get_keys().spend_secret_key, sig);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::validate_sign(const std::string& buff, const crypto::signature& sig, const crypto::public_key& pkey)
|
||||
{
|
||||
crypto::hash h = crypto::cn_fast_hash(buff.data(), buff.size());
|
||||
return crypto::check_signature(h, pkey, sig);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::encrypt_buffer(const std::string& buff, std::string& res_buff)
|
||||
{
|
||||
res_buff = buff;
|
||||
crypto::chacha_crypt(res_buff, m_account.get_keys().view_secret_key);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::decrypt_buffer(const std::string& buff, std::string& res_buff)
|
||||
{
|
||||
res_buff = buff;
|
||||
crypto::chacha_crypt(res_buff, m_account.get_keys().view_secret_key);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_tx_sources_for_packing(uint64_t items_to_pack, size_t fake_outputs_count, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies, uint64_t& found_money)
|
||||
{
|
||||
prepare_free_transfers_cache(fake_outputs_count);
|
||||
|
|
@ -5271,16 +5606,21 @@ assets_selection_context wallet2::get_needed_money(uint64_t fee, const std::vect
|
|||
amounts_map[currency::native_coin_asset_id].needed_amount = fee;
|
||||
for(auto& dt : dsts)
|
||||
{
|
||||
if(dt.asset_id == currency::ffff_pkey)
|
||||
if(dt.asset_id == currency::null_pkey)
|
||||
continue; //this destination for emmition only
|
||||
|
||||
THROW_IF_TRUE_WALLET_EX(0 == dt.amount, error::zero_destination);
|
||||
uint64_t money_to_add = dt.amount;
|
||||
if (dt.amount_to_provide)
|
||||
if (dt.amount_to_provide || dt.flags & tx_destination_entry_flags::tdef_explicit_amount_to_provide)
|
||||
money_to_add = dt.amount_to_provide;
|
||||
|
||||
amounts_map[dt.asset_id].needed_amount += money_to_add;
|
||||
THROW_IF_TRUE_WALLET_EX(amounts_map[dt.asset_id].needed_amount < money_to_add, error::tx_sum_overflow, dsts, fee);
|
||||
//clean up empty entries
|
||||
if (amounts_map[dt.asset_id].needed_amount == 0)
|
||||
{
|
||||
amounts_map.erase(amounts_map.find(dt.asset_id));
|
||||
}
|
||||
}
|
||||
return std::move(amounts_map);
|
||||
}
|
||||
|
|
@ -5559,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;
|
||||
|
|
@ -5570,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;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
@ -5577,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())
|
||||
{
|
||||
|
|
@ -5598,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;
|
||||
}
|
||||
|
|
@ -5721,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;
|
||||
|
|
@ -5917,7 +6314,7 @@ void wallet2::prepare_tx_destinations(const assets_selection_context& needed_mon
|
|||
{
|
||||
// special case for asset minting destinations
|
||||
for (auto& dst : dsts)
|
||||
if (dst.asset_id == currency::ffff_pkey)
|
||||
if (dst.asset_id == currency::null_pkey)
|
||||
final_destinations.emplace_back(dst.amount, dst.addr, dst.asset_id);
|
||||
|
||||
// if there's not ehough destinations items (i.e. outputs), split the last one
|
||||
|
|
@ -5976,20 +6373,29 @@ void wallet2::prepare_tx_destinations(uint64_t needed_money,
|
|||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx_param& ftp, const currency::transaction& tx_for_mode_separate /* = currency::transaction() */)
|
||||
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");
|
||||
needed_money_map[currency::null_pkey].needed_amount += (currency::get_outs_money_amount(tx_for_mode_separate) - get_inputs_money_amount(tx_for_mode_separate));
|
||||
for (const auto& el : mode_separatemode_separate.proposal_info.to_alice)
|
||||
{
|
||||
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);
|
||||
|
||||
|
|
@ -6004,15 +6410,15 @@ void wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx
|
|||
{
|
||||
//htlc
|
||||
//@#@ need to do refactoring over this part to support hidden amounts and asset_id
|
||||
prepare_tx_sources_htlc(ctp.htlc_tx_id, ctp.htlc_origin, ftp.sources, needed_money_map[currency::null_pkey].found_amount);
|
||||
prepare_tx_sources_htlc(ctp.htlc_tx_id, ctp.htlc_origin, ftp.sources, needed_money_map[currency::native_coin_asset_id].found_amount);
|
||||
WLT_THROW_IF_FALSE_WITH_CODE(ctp.dsts.size() == 1,
|
||||
"htlc: unexpected ctp.dsts.size() =" << ctp.dsts.size(), API_RETURN_CODE_INTERNAL_ERROR);
|
||||
|
||||
WLT_THROW_IF_FALSE_WITH_CODE(needed_money_map[currency::null_pkey].found_amount > ctp.fee,
|
||||
WLT_THROW_IF_FALSE_WITH_CODE(needed_money_map[currency::native_coin_asset_id].found_amount > ctp.fee,
|
||||
"htlc: found money less then fee", API_RETURN_CODE_INTERNAL_ERROR);
|
||||
|
||||
//fill amount
|
||||
ctp.dsts.begin()->amount = needed_money_map[currency::null_pkey].found_amount - ctp.fee;
|
||||
ctp.dsts.begin()->amount = needed_money_map[currency::native_coin_asset_id].found_amount - ctp.fee;
|
||||
|
||||
}
|
||||
else if (ctp.multisig_id != currency::null_hash)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "wallet_chain_shortener.h"
|
||||
#include "tor-connect/torlib/tor_lib_iface.h"
|
||||
#include "currency_core/pos_mining.h"
|
||||
#include "view_iface.h"
|
||||
|
||||
|
||||
#define WALLET_DEFAULT_TX_SPENDABLE_AGE 10
|
||||
|
|
@ -126,6 +127,10 @@ namespace tools
|
|||
virtual void on_transfer_canceled(const wallet_public::wallet_transfer_info& wti) {}
|
||||
virtual void on_message(message_severity /*severity*/, const std::string& /*m*/) {}
|
||||
virtual void on_tor_status_change(const std::string& state) {}
|
||||
|
||||
//mw api
|
||||
virtual void on_mw_get_wallets(std::vector<wallet_public::wallet_entry_info>& wallets) {}
|
||||
virtual bool on_mw_select_wallet(uint64_t wallet_id) { return true; }
|
||||
};
|
||||
|
||||
struct tx_dust_policy
|
||||
|
|
@ -295,8 +300,15 @@ 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
|
||||
{
|
||||
currency::transaction tx_for_mode_separate;
|
||||
view::ionic_swap_proposal_info proposal_info;
|
||||
};
|
||||
|
||||
|
||||
struct selection_for_amount
|
||||
{
|
||||
|
|
@ -458,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;
|
||||
|
|
@ -559,6 +586,7 @@ namespace tools
|
|||
//i_wallet2_callback* callback() const { return m_wcallback; }
|
||||
//void callback(i_wallet2_callback* callback) { m_callback = callback; }
|
||||
void callback(std::shared_ptr<i_wallet2_callback> callback) { m_wcallback = callback; m_do_rise_transfer = (callback != nullptr); }
|
||||
i_wallet2_callback* get_callback() { return m_wcallback.get(); }
|
||||
void set_do_rise_transfer(bool do_rise) { m_do_rise_transfer = do_rise; }
|
||||
|
||||
bool has_related_alias_entry_unconfirmed(const currency::transaction& tx);
|
||||
|
|
@ -903,7 +931,7 @@ namespace tools
|
|||
const std::list<expiration_entry_info>& get_expiration_entries() const { return m_money_expirations; };
|
||||
bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) const;
|
||||
|
||||
void prepare_transaction(construct_tx_param& ctp, currency::finalize_tx_param& ftp, const currency::transaction& tx_for_mode_separate = currency::transaction());
|
||||
void prepare_transaction(construct_tx_param& ctp, currency::finalize_tx_param& ftp, const mode_separate_context& emode_separate = mode_separate_context());
|
||||
|
||||
void finalize_transaction(const currency::finalize_tx_param& ftp, currency::transaction& tx, crypto::secret_key& tx_key, bool broadcast_tx, bool store_tx_secret_key = true);
|
||||
void finalize_transaction(const currency::finalize_tx_param& ftp, currency::finalized_tx& result, bool broadcast_tx, bool store_tx_secret_key = true );
|
||||
|
|
@ -934,13 +962,29 @@ namespace tools
|
|||
void redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& origin, currency::transaction& result_tx);
|
||||
void redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& origin);
|
||||
bool check_htlc_redeemed(const crypto::hash& htlc_tx_id, std::string& origin, crypto::hash& redeem_tx_id);
|
||||
|
||||
// ionic swaps:
|
||||
bool create_ionic_swap_proposal(const wallet_public::ionic_swap_proposal_info& proposal_details, const currency::account_public_address& destination_addr, wallet_public::ionic_swap_proposal& proposal);
|
||||
bool build_ionic_swap_template(const wallet_public::ionic_swap_proposal_info& proposal_detais, const currency::account_public_address& destination_addr,
|
||||
wallet_public::ionic_swap_proposal& proposal,
|
||||
std::vector<uint64_t>& selected_transfers_for_template);
|
||||
bool get_ionic_swap_proposal_info(const std::string&raw_proposal, wallet_public::ionic_swap_proposal_info& proposal_info);
|
||||
bool get_ionic_swap_proposal_info(const wallet_public::ionic_swap_proposal& proposal, wallet_public::ionic_swap_proposal_info& proposal_info);
|
||||
bool get_ionic_swap_proposal_info(const wallet_public::ionic_swap_proposal& proposal, wallet_public::ionic_swap_proposal_info& proposal_info, wallet_public::ionic_swap_proposal_context& ionic_context);
|
||||
bool accept_ionic_swap_proposal(const std::string& raw_proposal, currency::transaction& result_tx);
|
||||
bool accept_ionic_swap_proposal(const wallet_public::ionic_swap_proposal& proposal, currency::transaction& result_tx);
|
||||
|
||||
// Signing and auth
|
||||
bool sign_buffer(const std::string& buff, crypto::signature& sig);
|
||||
bool validate_sign(const std::string& buff, const crypto::signature& sig, const crypto::public_key& pkey);
|
||||
bool encrypt_buffer(const std::string& buff, std::string& res_buff);
|
||||
bool decrypt_buffer(const std::string& buff, std::string& res_buff);
|
||||
|
||||
private:
|
||||
|
||||
// -------- t_transport_state_notifier ------------------------------------------------
|
||||
virtual void notify_state_change(const std::string& state_code, const std::string& details = std::string());
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
void add_transfers_to_expiration_list(const std::vector<uint64_t>& selected_transfers, uint64_t expiration, uint64_t change_amount, const crypto::hash& related_tx_id);
|
||||
void remove_transfer_from_expiration_list(uint64_t transfer_index);
|
||||
void load_keys(const std::string& keys_file_name, const std::string& password, uint64_t file_signature, keys_file_data& kf_data);
|
||||
|
|
@ -1081,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);
|
||||
|
|
@ -1146,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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@ public:
|
|||
virtual void on_sync_progress(size_t wallet_id, const uint64_t& /*percents*/) {}
|
||||
virtual void on_transfer_canceled(size_t wallet_id, const tools::wallet_public::wallet_transfer_info& wti) {}
|
||||
virtual void on_tor_status_change(size_t wallet_id, const std::string& state) {}
|
||||
|
||||
virtual void on_mw_get_wallets(std::vector<tools::wallet_public::wallet_entry_info>& wallets) {}
|
||||
virtual bool on_mw_select_wallet(uint64_t wallet_id) { return true; }
|
||||
|
||||
};
|
||||
|
||||
struct i_wallet_to_i_backend_adapter: public tools::i_wallet2_callback
|
||||
|
|
@ -45,6 +49,16 @@ struct i_wallet_to_i_backend_adapter: public tools::i_wallet2_callback
|
|||
m_pbackend->on_tor_status_change(m_wallet_id, state);
|
||||
}
|
||||
|
||||
virtual void on_mw_get_wallets(std::vector<tools::wallet_public::wallet_entry_info>& wallets)
|
||||
{
|
||||
m_pbackend->on_mw_get_wallets(wallets);
|
||||
}
|
||||
virtual bool on_mw_select_wallet(uint64_t wallet_id)
|
||||
{
|
||||
return m_pbackend->on_mw_select_wallet(wallet_id);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
i_backend_wallet_callback* m_pbackend;
|
||||
size_t m_wallet_id;
|
||||
|
|
|
|||
|
|
@ -1179,6 +1179,310 @@ namespace wallet_public
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct asset_funds
|
||||
{
|
||||
crypto::public_key asset_id;
|
||||
uint64_t amount;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id)
|
||||
KV_SERIALIZE(amount)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct ionic_swap_proposal_info
|
||||
{
|
||||
std::vector<asset_funds> to_bob; //assets that funded by side that making proposal(Alice) and addressed to receiver of proposal (Bob)
|
||||
std::vector<asset_funds> to_alice; //assets expected to be funded by the side that receiving proposal (Bob) and addressed to Alice
|
||||
uint64_t mixins;
|
||||
uint64_t fee_paid_by_a;
|
||||
uint64_t expiration_time;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
|
||||
KV_SERIALIZE(to_bob)
|
||||
KV_SERIALIZE(to_alice)
|
||||
KV_SERIALIZE(mixins)
|
||||
KV_SERIALIZE(fee_paid_by_a)
|
||||
KV_SERIALIZE(expiration_time)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct ionic_swap_proposal_context
|
||||
{
|
||||
currency::tx_generation_context gen_context;
|
||||
crypto::secret_key one_time_skey;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
VERSION()
|
||||
CURRENT_VERSION(0)
|
||||
FIELD(gen_context)
|
||||
FIELD(one_time_skey)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct ionic_swap_proposal
|
||||
{
|
||||
currency::transaction tx_template;
|
||||
std::string encrypted_context; //ionic_swap_proposal_context encrypted with derivation
|
||||
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
VERSION()
|
||||
CURRENT_VERSION(0)
|
||||
FIELD(tx_template)
|
||||
FIELD(encrypted_context)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct create_ionic_swap_proposal_request
|
||||
{
|
||||
uint64_t wallet_id;
|
||||
ionic_swap_proposal_info proposal_info;
|
||||
std::string destination_add;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(wallet_id)
|
||||
KV_SERIALIZE(proposal_info)
|
||||
KV_SERIALIZE(destination_add)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct COMMAND_IONIC_SWAP_GENERATE_PROPOSAL
|
||||
{
|
||||
struct request
|
||||
{
|
||||
ionic_swap_proposal_info proposal;
|
||||
std::string destination_address;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(proposal)
|
||||
KV_SERIALIZE(destination_address)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string hex_raw_proposal;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(hex_raw_proposal)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_IONIC_SWAP_GET_PROPOSAL_INFO
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string hex_raw_proposal;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(hex_raw_proposal)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct response
|
||||
{
|
||||
ionic_swap_proposal_info proposal;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(proposal)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_IONIC_SWAP_ACCEPT_PROPOSAL
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string hex_raw_proposal;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(hex_raw_proposal)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct response
|
||||
{
|
||||
crypto::hash result_tx_id;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(result_tx_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct wallet_info
|
||||
{
|
||||
std::list<tools::wallet_public::asset_balance_entry> balances;
|
||||
uint64_t mined_total;
|
||||
std::string address;
|
||||
std::string view_sec_key;
|
||||
std::string path;
|
||||
bool is_auditable;
|
||||
bool is_watch_only;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(balances)
|
||||
KV_SERIALIZE(mined_total)
|
||||
KV_SERIALIZE(address)
|
||||
KV_SERIALIZE(view_sec_key)
|
||||
KV_SERIALIZE(path)
|
||||
KV_SERIALIZE(is_auditable);
|
||||
KV_SERIALIZE(is_watch_only);
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct wallet_entry_info
|
||||
{
|
||||
wallet_info wi;
|
||||
uint64_t wallet_id;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(wi)
|
||||
KV_SERIALIZE(wallet_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
};
|
||||
|
||||
struct COMMAND_MW_GET_WALLETS
|
||||
{
|
||||
struct request
|
||||
{
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::vector<wallet_entry_info> wallets;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(wallets)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_MW_SELECT_WALLET
|
||||
{
|
||||
struct request
|
||||
{
|
||||
uint64_t wallet_id;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(wallet_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct response
|
||||
{
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_SIGN_MESSAGE
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string buff; //base64 encoded data
|
||||
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(buff)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct response
|
||||
{
|
||||
crypto::signature sig;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(sig)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_VALIDATE_SIGNATURE
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string buff; //base64 encoded data
|
||||
crypto::signature sig;
|
||||
crypto::public_key pkey;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(buff)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(sig)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(pkey)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct response
|
||||
{
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_ENCRYPT_DATA
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string buff; //base64 encoded data
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(buff)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string res_buff; //base64 encoded encrypted data
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(res_buff)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_DECRYPT_DATA
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string buff; //base64 encoded encrypted data
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(buff)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string res_buff; //base64 encoded data
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(res_buff)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct assets_whitelist
|
||||
{
|
||||
std::vector<currency::asset_descriptor_with_id> assets;
|
||||
|
|
@ -1212,6 +1516,10 @@ namespace wallet_public
|
|||
}
|
||||
}
|
||||
|
||||
inline bool operator==(const asset_funds& lhs, const asset_funds& rhs)
|
||||
{
|
||||
return lhs.amount == rhs.amount && lhs.asset_id == rhs.asset_id;
|
||||
}
|
||||
|
||||
} // namespace wallet_rpc
|
||||
} // namespace tools
|
||||
|
|
|
|||
|
|
@ -56,13 +56,18 @@ namespace tools
|
|||
command_line::add_arg(desc, arg_deaf_mode);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
wallet_rpc_server::wallet_rpc_server(wallet2& w)
|
||||
: m_wallet(w)
|
||||
wallet_rpc_server::wallet_rpc_server(std::shared_ptr<wallet2> wptr)
|
||||
: m_pwallet(wptr)
|
||||
, m_do_mint(false)
|
||||
, m_deaf(false)
|
||||
, m_last_wallet_store_height(0)
|
||||
{}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
std::shared_ptr<wallet2> wallet_rpc_server::get_wallet()
|
||||
{
|
||||
return std::shared_ptr<wallet2>(m_pwallet);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::run(bool do_mint, bool offline_mode, const currency::account_public_address& miner_address)
|
||||
{
|
||||
static const uint64_t wallet_rpc_idle_work_period_ms = 2000;
|
||||
|
|
@ -79,7 +84,7 @@ namespace tools
|
|||
bool received_money = false, ok = false;
|
||||
std::atomic<bool> stop(false);
|
||||
LOG_PRINT_L2("wallet RPC idle: refreshing...");
|
||||
m_wallet.refresh(blocks_fetched, received_money, ok, stop);
|
||||
get_wallet()->refresh(blocks_fetched, received_money, ok, stop);
|
||||
if (stop)
|
||||
{
|
||||
LOG_PRINT_L1("wallet RPC idle: refresh failed");
|
||||
|
|
@ -88,24 +93,24 @@ namespace tools
|
|||
|
||||
bool has_related_alias_in_unconfirmed = false;
|
||||
LOG_PRINT_L2("wallet RPC idle: scanning tx pool...");
|
||||
m_wallet.scan_tx_pool(has_related_alias_in_unconfirmed);
|
||||
get_wallet()->scan_tx_pool(has_related_alias_in_unconfirmed);
|
||||
|
||||
if (m_do_mint)
|
||||
{
|
||||
LOG_PRINT_L2("wallet RPC idle: trying to do PoS iteration...");
|
||||
m_wallet.try_mint_pos(miner_address);
|
||||
get_wallet()->try_mint_pos(miner_address);
|
||||
}
|
||||
|
||||
//auto-store wallet in server mode, let's do it every 24-hour
|
||||
if (m_wallet.get_top_block_height() < m_last_wallet_store_height)
|
||||
if (get_wallet()->get_top_block_height() < m_last_wallet_store_height)
|
||||
{
|
||||
LOG_ERROR("Unexpected m_last_wallet_store_height = " << m_last_wallet_store_height << " or " << m_wallet.get_top_block_height());
|
||||
LOG_ERROR("Unexpected m_last_wallet_store_height = " << m_last_wallet_store_height << " or " << get_wallet()->get_top_block_height());
|
||||
}
|
||||
else if (m_wallet.get_top_block_height() - m_last_wallet_store_height > CURRENCY_BLOCKS_PER_DAY)
|
||||
else if (get_wallet()->get_top_block_height() - m_last_wallet_store_height > CURRENCY_BLOCKS_PER_DAY)
|
||||
{
|
||||
//store wallet
|
||||
m_wallet.store();
|
||||
m_last_wallet_store_height = m_wallet.get_top_block_height();
|
||||
get_wallet()->store();
|
||||
m_last_wallet_store_height = get_wallet()->get_top_block_height();
|
||||
}
|
||||
}
|
||||
catch (error::no_connection_to_daemon&)
|
||||
|
|
@ -141,14 +146,14 @@ namespace tools
|
|||
|
||||
if (command_line::has_arg(vm, arg_miner_text_info))
|
||||
{
|
||||
m_wallet.set_miner_text_info(command_line::get_arg(vm, arg_miner_text_info));
|
||||
get_wallet()->set_miner_text_info(command_line::get_arg(vm, arg_miner_text_info));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::init(const boost::program_options::variables_map& vm)
|
||||
{
|
||||
m_last_wallet_store_height = m_wallet.get_top_block_height();
|
||||
m_last_wallet_store_height = get_wallet()->get_top_block_height();
|
||||
m_net_server.set_threads_prefix("RPC");
|
||||
bool r = handle_command_line(vm);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to process command line in core_rpc_server");
|
||||
|
|
@ -187,7 +192,7 @@ namespace tools
|
|||
try
|
||||
{
|
||||
uint64_t stub_mined = 0; // unused
|
||||
bool r = m_wallet.balance(res.balances, stub_mined);
|
||||
bool r = get_wallet()->balance(res.balances, stub_mined);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "m_wallet.balance failed");
|
||||
for (auto it = res.balances.begin(); it != res.balances.end(); ++it)
|
||||
{
|
||||
|
|
@ -212,7 +217,7 @@ namespace tools
|
|||
{
|
||||
try
|
||||
{
|
||||
res.address = m_wallet.get_account().get_public_address_str();
|
||||
res.address = get_wallet()->get_account().get_public_address_str();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
|
@ -226,17 +231,17 @@ namespace tools
|
|||
{
|
||||
try
|
||||
{
|
||||
res.address = m_wallet.get_account().get_public_address_str();
|
||||
res.is_whatch_only = m_wallet.is_watch_only();
|
||||
res.path = epee::string_encoding::convert_to_ansii(m_wallet.get_wallet_path());
|
||||
res.transfers_count = m_wallet.get_recent_transfers_total_count();
|
||||
res.transfer_entries_count = m_wallet.get_transfer_entries_count();
|
||||
res.address = get_wallet()->get_account().get_public_address_str();
|
||||
res.is_whatch_only = get_wallet()->is_watch_only();
|
||||
res.path = epee::string_encoding::convert_to_ansii(get_wallet()->get_wallet_path());
|
||||
res.transfers_count = get_wallet()->get_recent_transfers_total_count();
|
||||
res.transfer_entries_count = get_wallet()->get_transfer_entries_count();
|
||||
std::map<uint64_t, uint64_t> distribution;
|
||||
m_wallet.get_utxo_distribution(distribution);
|
||||
get_wallet()->get_utxo_distribution(distribution);
|
||||
for (const auto& ent : distribution)
|
||||
res.utxo_distribution.push_back(currency::print_money_brief(ent.first) + ":" + std::to_string(ent.second));
|
||||
|
||||
res.current_height = m_wallet.get_top_block_height();
|
||||
res.current_height = get_wallet()->get_top_block_height();
|
||||
return true;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
|
|
@ -250,7 +255,7 @@ namespace tools
|
|||
{
|
||||
try
|
||||
{
|
||||
res.seed_phrase = m_wallet.get_account().get_seed_phrase(req.seed_password);
|
||||
res.seed_phrase = get_wallet()->get_account().get_seed_phrase(req.seed_password);
|
||||
return true;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
|
|
@ -271,21 +276,21 @@ namespace tools
|
|||
{
|
||||
if (req.update_provision_info)
|
||||
{
|
||||
res.pi.balance = m_wallet.balance(res.pi.unlocked_balance);
|
||||
res.pi.transfer_entries_count = m_wallet.get_transfer_entries_count();
|
||||
res.pi.transfers_count = m_wallet.get_recent_transfers_total_count();
|
||||
res.pi.curent_height = m_wallet.get_top_block_height();
|
||||
res.pi.balance = get_wallet()->balance(res.pi.unlocked_balance);
|
||||
res.pi.transfer_entries_count = get_wallet()->get_transfer_entries_count();
|
||||
res.pi.transfers_count = get_wallet()->get_recent_transfers_total_count();
|
||||
res.pi.curent_height = get_wallet()->get_top_block_height();
|
||||
}
|
||||
|
||||
if (req.offset == 0 && !req.exclude_unconfirmed)
|
||||
m_wallet.get_unconfirmed_transfers(res.transfers, req.exclude_mining_txs);
|
||||
get_wallet()->get_unconfirmed_transfers(res.transfers, req.exclude_mining_txs);
|
||||
|
||||
bool start_from_end = true;
|
||||
if (req.order == ORDER_FROM_BEGIN_TO_END)
|
||||
{
|
||||
start_from_end = false;
|
||||
}
|
||||
m_wallet.get_recent_transfers_history(res.transfers, req.offset, req.count, res.total_transfers, res.last_item_index, req.exclude_mining_txs, start_from_end);
|
||||
get_wallet()->get_recent_transfers_history(res.transfers, req.offset, req.count, res.total_transfers, res.last_item_index, req.exclude_mining_txs, start_from_end);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -299,10 +304,10 @@ namespace tools
|
|||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_transfer(const wallet_public::COMMAND_RPC_TRANSFER::request& req, wallet_public::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
if (req.fee < m_wallet.get_core_runtime_config().tx_pool_min_fee)
|
||||
if (req.fee < get_wallet()->get_core_runtime_config().tx_pool_min_fee)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT;
|
||||
er.message = std::string("Given fee is too low: ") + epee::string_tools::num_to_string_fast(req.fee) + ", minimum is: " + epee::string_tools::num_to_string_fast(m_wallet.get_core_runtime_config().tx_pool_min_fee);
|
||||
er.message = std::string("Given fee is too low: ") + epee::string_tools::num_to_string_fast(req.fee) + ", minimum is: " + epee::string_tools::num_to_string_fast(get_wallet()->get_core_runtime_config().tx_pool_min_fee);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -314,7 +319,7 @@ namespace tools
|
|||
return false;
|
||||
}
|
||||
|
||||
construct_tx_param ctp = m_wallet.get_default_construct_tx_param_inital();
|
||||
construct_tx_param ctp = get_wallet()->get_default_construct_tx_param_inital();
|
||||
if (req.service_entries_permanent)
|
||||
{
|
||||
//put it to extra
|
||||
|
|
@ -357,7 +362,7 @@ namespace tools
|
|||
wrap = true;
|
||||
//encrypt body with a special way
|
||||
}
|
||||
else if(!m_wallet.get_transfer_address(it->address, de.addr.back(), embedded_payment_id))
|
||||
else if(!get_wallet()->get_transfer_address(it->address, de.addr.back(), embedded_payment_id))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
|
||||
er.message = std::string("WALLET_RPC_ERROR_CODE_WRONG_ADDRESS: ") + it->address;
|
||||
|
|
@ -396,7 +401,7 @@ namespace tools
|
|||
|
||||
if (req.push_payer && !wrap)
|
||||
{
|
||||
currency::create_and_add_tx_payer_to_container_from_address(extra, m_wallet.get_account().get_keys().account_address, m_wallet.get_top_block_height(), m_wallet.get_core_runtime_config());
|
||||
currency::create_and_add_tx_payer_to_container_from_address(extra, get_wallet()->get_account().get_keys().account_address, get_wallet()->get_top_block_height(), get_wallet()->get_core_runtime_config());
|
||||
}
|
||||
|
||||
if (!req.hide_receiver)
|
||||
|
|
@ -404,7 +409,7 @@ namespace tools
|
|||
for (auto& d : dsts)
|
||||
{
|
||||
for (auto& a : d.addr)
|
||||
currency::create_and_add_tx_receiver_to_container_from_address(extra, a, m_wallet.get_top_block_height(), m_wallet.get_core_runtime_config());
|
||||
currency::create_and_add_tx_receiver_to_container_from_address(extra, a, get_wallet()->get_top_block_height(), get_wallet()->get_core_runtime_config());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -412,8 +417,8 @@ namespace tools
|
|||
std::string unsigned_tx_blob_str;
|
||||
ctp.fee = req.fee;
|
||||
ctp.fake_outputs_count = req.mixin;
|
||||
m_wallet.transfer(ctp, result, true, &unsigned_tx_blob_str);
|
||||
if (m_wallet.is_watch_only())
|
||||
get_wallet()->transfer(ctp, result, true, &unsigned_tx_blob_str);
|
||||
if (get_wallet()->is_watch_only())
|
||||
{
|
||||
res.tx_unsigned_hex = epee::string_tools::buff_to_hex_nodelimer(unsigned_tx_blob_str); // watch-only wallets could not sign and relay transactions
|
||||
// leave res.tx_hash empty, because tx hash will change after signing
|
||||
|
|
@ -449,9 +454,9 @@ namespace tools
|
|||
bool wallet_rpc_server::on_store(const wallet_public::COMMAND_RPC_STORE::request& req, wallet_public::COMMAND_RPC_STORE::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
m_wallet.store();
|
||||
get_wallet()->store();
|
||||
boost::system::error_code ec = AUTO_VAL_INIT(ec);
|
||||
res.wallet_file_size = m_wallet.get_wallet_file_size();
|
||||
res.wallet_file_size = get_wallet()->get_wallet_file_size();
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -468,7 +473,7 @@ namespace tools
|
|||
|
||||
res.payments.clear();
|
||||
std::list<wallet2::payment_details> payment_list;
|
||||
m_wallet.get_payments(payment_id, payment_list);
|
||||
get_wallet()->get_payments(payment_id, payment_list);
|
||||
for (auto payment : payment_list)
|
||||
{
|
||||
if (payment.m_unlock_time && !req.allow_locked_transactions)
|
||||
|
|
@ -505,7 +510,7 @@ namespace tools
|
|||
}
|
||||
|
||||
std::list<wallet2::payment_details> payment_list;
|
||||
m_wallet.get_payments(payment_id, payment_list, req.min_block_height);
|
||||
get_wallet()->get_payments(payment_id, payment_list, req.min_block_height);
|
||||
|
||||
for (auto & payment : payment_list)
|
||||
{
|
||||
|
|
@ -553,7 +558,7 @@ namespace tools
|
|||
crypto::generate_random_bytes(payment_id.size(), &payment_id.front());
|
||||
}
|
||||
|
||||
res.integrated_address = currency::get_account_address_and_payment_id_as_str(m_wallet.get_account().get_public_address(), payment_id);
|
||||
res.integrated_address = currency::get_account_address_and_payment_id_as_str(get_wallet()->get_account().get_public_address(), payment_id);
|
||||
res.payment_id = epee::string_tools::buff_to_hex_nodelimer(payment_id);
|
||||
|
||||
return !res.integrated_address.empty();
|
||||
|
|
@ -587,7 +592,7 @@ namespace tools
|
|||
|
||||
currency::account_public_address addr;
|
||||
currency::payment_id_t integrated_payment_id;
|
||||
if (!m_wallet.get_transfer_address(req.address, addr, integrated_payment_id))
|
||||
if (!get_wallet()->get_transfer_address(req.address, addr, integrated_payment_id))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
|
||||
er.message = std::string("Invalid address: ") + req.address;
|
||||
|
|
@ -606,10 +611,10 @@ namespace tools
|
|||
payment_id = integrated_payment_id;
|
||||
}
|
||||
|
||||
if (req.fee < m_wallet.get_core_runtime_config().tx_pool_min_fee)
|
||||
if (req.fee < get_wallet()->get_core_runtime_config().tx_pool_min_fee)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT;
|
||||
er.message = std::string("Given fee is too low: ") + epee::string_tools::num_to_string_fast(req.fee) + ", minimum is: " + epee::string_tools::num_to_string_fast(m_wallet.get_core_runtime_config().tx_pool_min_fee);
|
||||
er.message = std::string("Given fee is too low: ") + epee::string_tools::num_to_string_fast(req.fee) + ", minimum is: " + epee::string_tools::num_to_string_fast(get_wallet()->get_core_runtime_config().tx_pool_min_fee);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -620,14 +625,14 @@ namespace tools
|
|||
uint64_t amount_total = 0, amount_swept = 0;
|
||||
|
||||
std::string unsigned_tx_blob_str;
|
||||
m_wallet.sweep_below(req.mixin, addr, req.amount, payment_id, req.fee, outs_total, amount_total, outs_swept, amount_swept, &tx, &unsigned_tx_blob_str);
|
||||
get_wallet()->sweep_below(req.mixin, addr, req.amount, payment_id, req.fee, outs_total, amount_total, outs_swept, amount_swept, &tx, &unsigned_tx_blob_str);
|
||||
|
||||
res.amount_swept = amount_swept;
|
||||
res.amount_total = amount_total;
|
||||
res.outs_swept = outs_swept;
|
||||
res.outs_total = outs_total;
|
||||
|
||||
if (m_wallet.is_watch_only())
|
||||
if (get_wallet()->is_watch_only())
|
||||
{
|
||||
res.tx_unsigned_hex = epee::string_tools::buff_to_hex_nodelimer(unsigned_tx_blob_str); // watch-only wallets can't sign and relay transactions
|
||||
// leave res.tx_hash empty, because tx has will change after signing
|
||||
|
|
@ -673,7 +678,7 @@ namespace tools
|
|||
return false;
|
||||
}
|
||||
std::string tx_signed_blob;
|
||||
m_wallet.sign_transfer(tx_unsigned_blob, tx_signed_blob, tx);
|
||||
get_wallet()->sign_transfer(tx_unsigned_blob, tx_signed_blob, tx);
|
||||
|
||||
res.tx_signed_hex = epee::string_tools::buff_to_hex_nodelimer(tx_signed_blob);
|
||||
res.tx_hash = epee::string_tools::pod_to_hex(currency::get_transaction_hash(tx));
|
||||
|
|
@ -693,7 +698,7 @@ namespace tools
|
|||
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
currency::transaction tx = AUTO_VAL_INIT(tx);
|
||||
m_wallet.submit_transfer(tx_signed_blob, tx);
|
||||
get_wallet()->submit_transfer(tx_signed_blob, tx);
|
||||
res.tx_hash = epee::string_tools::pod_to_hex(currency::get_transaction_hash(tx));
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
|
||||
|
|
@ -705,7 +710,7 @@ namespace tools
|
|||
bool tx_id_specified = req.tx_id != currency::null_hash;
|
||||
|
||||
// process confirmed txs
|
||||
m_wallet.enumerate_transfers_history([&](const wallet_public::wallet_transfer_info& wti) -> bool {
|
||||
get_wallet()->enumerate_transfers_history([&](const wallet_public::wallet_transfer_info& wti) -> bool {
|
||||
|
||||
if (tx_id_specified)
|
||||
{
|
||||
|
|
@ -741,7 +746,7 @@ namespace tools
|
|||
// process unconfirmed txs
|
||||
if (req.pool)
|
||||
{
|
||||
m_wallet.enumerate_unconfirmed_transfers([&](const wallet_public::wallet_transfer_info& wti) -> bool {
|
||||
get_wallet()->enumerate_unconfirmed_transfers([&](const wallet_public::wallet_transfer_info& wti) -> bool {
|
||||
if ((wti.is_income && req.in) || (!wti.is_income && req.out))
|
||||
res.pool.push_back(wti);
|
||||
return true; // continue
|
||||
|
|
@ -752,7 +757,7 @@ namespace tools
|
|||
}
|
||||
bool wallet_rpc_server::on_get_mining_history(const wallet_public::COMMAND_RPC_GET_MINING_HISTORY::request& req, wallet_public::COMMAND_RPC_GET_MINING_HISTORY::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
m_wallet.get_mining_history(res, req.v);
|
||||
get_wallet()->get_mining_history(res, req.v);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
@ -775,7 +780,7 @@ namespace tools
|
|||
}
|
||||
|
||||
currency::transaction tx = AUTO_VAL_INIT(tx);
|
||||
m_wallet.request_alias_registration(ai, tx, m_wallet.get_default_fee(), 0, req.authority_key);
|
||||
get_wallet()->request_alias_registration(ai, tx, get_wallet()->get_default_fee(), 0, req.authority_key);
|
||||
res.tx_id = get_transaction_hash(tx);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
|
|
@ -786,7 +791,7 @@ namespace tools
|
|||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
currency::transaction tx = AUTO_VAL_INIT(tx);
|
||||
currency::transaction template_tx = AUTO_VAL_INIT(template_tx);
|
||||
m_wallet.send_escrow_proposal(req, tx, template_tx);
|
||||
get_wallet()->send_escrow_proposal(req, tx, template_tx);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
|
|
@ -794,7 +799,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_contracts_accept_proposal(const wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
m_wallet.accept_proposal(req.contract_id, req.acceptance_fee);
|
||||
get_wallet()->accept_proposal(req.contract_id, req.acceptance_fee);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
|
|
@ -803,7 +808,7 @@ namespace tools
|
|||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
tools::wallet2::escrow_contracts_container ecc;
|
||||
m_wallet.get_contracts(ecc);
|
||||
get_wallet()->get_contracts(ecc);
|
||||
res.contracts.resize(ecc.size());
|
||||
size_t i = 0;
|
||||
for (auto& c : ecc)
|
||||
|
|
@ -819,7 +824,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_contracts_release(const wallet_public::COMMAND_CONTRACTS_RELEASE::request& req, wallet_public::COMMAND_CONTRACTS_RELEASE::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
m_wallet.finish_contract(req.contract_id, req.release_type);
|
||||
get_wallet()->finish_contract(req.contract_id, req.release_type);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
|
|
@ -827,7 +832,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_contracts_request_cancel(const wallet_public::COMMAND_CONTRACTS_REQUEST_CANCEL::request& req, wallet_public::COMMAND_CONTRACTS_REQUEST_CANCEL::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
m_wallet.request_cancel_contract(req.contract_id, req.fee, req.expiration_period);
|
||||
get_wallet()->request_cancel_contract(req.contract_id, req.fee, req.expiration_period);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
|
|
@ -835,7 +840,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_contracts_accept_cancel(const wallet_public::COMMAND_CONTRACTS_ACCEPT_CANCEL::request& req, wallet_public::COMMAND_CONTRACTS_ACCEPT_CANCEL::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
m_wallet.accept_cancel_contract(req.contract_id);
|
||||
get_wallet()->accept_cancel_contract(req.contract_id);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
|
|
@ -843,9 +848,9 @@ namespace tools
|
|||
bool wallet_rpc_server::on_marketplace_get_my_offers(const wallet_public::COMMAND_MARKETPLACE_GET_MY_OFFERS::request& req, wallet_public::COMMAND_MARKETPLACE_GET_MY_OFFERS::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
m_wallet.get_actual_offers(res.offers);
|
||||
get_wallet()->get_actual_offers(res.offers);
|
||||
size_t offers_count_before_filtering = res.offers.size();
|
||||
bc_services::filter_offers_list(res.offers, req.filter, m_wallet.get_core_runtime_config().get_core_time());
|
||||
bc_services::filter_offers_list(res.offers, req.filter, get_wallet()->get_core_runtime_config().get_core_time());
|
||||
LOG_PRINT("get_my_offers(): " << res.offers.size() << " offers returned (" << offers_count_before_filtering << " was before filter)", LOG_LEVEL_1);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
|
|
@ -855,7 +860,7 @@ namespace tools
|
|||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
currency::transaction res_tx = AUTO_VAL_INIT(res_tx);
|
||||
m_wallet.push_offer(req.od, res_tx);
|
||||
get_wallet()->push_offer(req.od, res_tx);
|
||||
|
||||
res.tx_hash = string_tools::pod_to_hex(currency::get_transaction_hash(res_tx));
|
||||
res.tx_blob_size = currency::get_object_blobsize(res_tx);
|
||||
|
|
@ -868,7 +873,7 @@ namespace tools
|
|||
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
currency::transaction res_tx = AUTO_VAL_INIT(res_tx);
|
||||
m_wallet.update_offer_by_id(req.tx_id, req.no, req.od, res_tx);
|
||||
get_wallet()->update_offer_by_id(req.tx_id, req.no, req.od, res_tx);
|
||||
|
||||
res.tx_hash = string_tools::pod_to_hex(currency::get_transaction_hash(res_tx));
|
||||
res.tx_blob_size = currency::get_object_blobsize(res_tx);
|
||||
|
|
@ -880,7 +885,7 @@ namespace tools
|
|||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
currency::transaction res_tx = AUTO_VAL_INIT(res_tx);
|
||||
m_wallet.cancel_offer_by_id(req.tx_id, req.no, req.fee, res_tx);
|
||||
get_wallet()->cancel_offer_by_id(req.tx_id, req.no, req.fee, res_tx);
|
||||
|
||||
res.tx_hash = string_tools::pod_to_hex(currency::get_transaction_hash(res_tx));
|
||||
res.tx_blob_size = currency::get_object_blobsize(res_tx);
|
||||
|
|
@ -892,7 +897,7 @@ namespace tools
|
|||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
currency::transaction tx = AUTO_VAL_INIT(tx);
|
||||
m_wallet.create_htlc_proposal(req.amount, req.counterparty_address, req.lock_blocks_count, tx, req.htlc_hash, res.derived_origin_secret);
|
||||
get_wallet()->create_htlc_proposal(req.amount, req.counterparty_address, req.lock_blocks_count, tx, req.htlc_hash, res.derived_origin_secret);
|
||||
res.result_tx_blob = currency::tx_to_blob(tx);
|
||||
res.result_tx_id = get_transaction_hash(tx);
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
|
|
@ -902,7 +907,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_get_list_of_active_htlc(const wallet_public::COMMAND_GET_LIST_OF_ACTIVE_HTLC::request& req, wallet_public::COMMAND_GET_LIST_OF_ACTIVE_HTLC::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
m_wallet.get_list_of_active_htlc(res.htlcs, req.income_redeem_only);
|
||||
get_wallet()->get_list_of_active_htlc(res.htlcs, req.income_redeem_only);
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -911,7 +916,7 @@ namespace tools
|
|||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
currency::transaction tx = AUTO_VAL_INIT(tx);
|
||||
m_wallet.redeem_htlc(req.tx_id, req.origin_secret, tx);
|
||||
get_wallet()->redeem_htlc(req.tx_id, req.origin_secret, tx);
|
||||
res.result_tx_blob = currency::tx_to_blob(tx);
|
||||
res.result_tx_id = get_transaction_hash(tx);
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
|
|
@ -921,11 +926,150 @@ namespace tools
|
|||
bool wallet_rpc_server::on_check_htlc_redeemed(const wallet_public::COMMAND_CHECK_HTLC_REDEEMED::request& req, wallet_public::COMMAND_CHECK_HTLC_REDEEMED::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
m_wallet.check_htlc_redeemed(req.htlc_tx_id, res.origin_secrete, res.redeem_tx_id);
|
||||
get_wallet()->check_htlc_redeemed(req.htlc_tx_id, res.origin_secrete, res.redeem_tx_id);
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_ionic_swap_generate_proposal(const wallet_public::COMMAND_IONIC_SWAP_GENERATE_PROPOSAL::request& req, wallet_public::COMMAND_IONIC_SWAP_GENERATE_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
currency::account_public_address destination_addr = AUTO_VAL_INIT(destination_addr);
|
||||
currency::payment_id_t integrated_payment_id;
|
||||
if (!get_wallet()->get_transfer_address(req.destination_address, destination_addr, integrated_payment_id))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
|
||||
er.message = "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS";
|
||||
return false;
|
||||
}
|
||||
if (integrated_payment_id.size())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
|
||||
er.message = "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS - integrated address is noit supported yet";
|
||||
return false;
|
||||
}
|
||||
|
||||
wallet_public::ionic_swap_proposal proposal = AUTO_VAL_INIT(proposal);
|
||||
bool r = get_wallet()->create_ionic_swap_proposal(req.proposal, destination_addr, proposal);
|
||||
if (!r)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT;
|
||||
er.message = "WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT - Error creating proposal";
|
||||
return false;
|
||||
}
|
||||
res.hex_raw_proposal = epee::string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(proposal));
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_ionic_swap_get_proposal_info(const wallet_public::COMMAND_IONIC_SWAP_GET_PROPOSAL_INFO::request& req, wallet_public::COMMAND_IONIC_SWAP_GET_PROPOSAL_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
std::string raw_tx_template;
|
||||
bool r = epee::string_tools::parse_hexstr_to_binbuff(req.hex_raw_proposal, raw_tx_template);
|
||||
if (!r)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT;
|
||||
er.message = "WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT - failed to parse template from hex";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!get_wallet()->get_ionic_swap_proposal_info(raw_tx_template, res.proposal))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT;
|
||||
er.message = "WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT - get_ionic_swap_proposal_info";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_ionic_swap_accept_proposal(const wallet_public::COMMAND_IONIC_SWAP_ACCEPT_PROPOSAL::request& req, wallet_public::COMMAND_IONIC_SWAP_ACCEPT_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
|
||||
std::string raw_tx_template;
|
||||
bool r = epee::string_tools::parse_hexstr_to_binbuff(req.hex_raw_proposal, raw_tx_template);
|
||||
if (!r)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT;
|
||||
er.message = "WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT - failed to parse template from hex";
|
||||
return false;
|
||||
}
|
||||
|
||||
currency::transaction result_tx = AUTO_VAL_INIT(result_tx);
|
||||
if (!get_wallet()->accept_ionic_swap_proposal(raw_tx_template, result_tx))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT;
|
||||
er.message = "WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT - failed to accept_ionic_swap_proposal()";
|
||||
return false;
|
||||
}
|
||||
|
||||
res.result_tx_id = currency::get_transaction_hash(result_tx);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_mw_get_wallets(const wallet_public::COMMAND_MW_GET_WALLETS::request& req, wallet_public::COMMAND_MW_GET_WALLETS::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
i_wallet2_callback* pcallback = get_wallet()->get_callback();
|
||||
if (!pcallback)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR";
|
||||
return false;
|
||||
}
|
||||
pcallback->on_mw_get_wallets(res.wallets);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_mw_select_wallet(const wallet_public::COMMAND_MW_SELECT_WALLET::request& req, wallet_public::COMMAND_MW_SELECT_WALLET::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
i_wallet2_callback* pcallback = get_wallet()->get_callback();
|
||||
if (!pcallback)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR";
|
||||
return false;
|
||||
}
|
||||
pcallback->on_mw_select_wallet(req.wallet_id);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_sign_message(const wallet_public::COMMAND_SIGN_MESSAGE::request& req, wallet_public::COMMAND_SIGN_MESSAGE::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
std::string buff = epee::string_encoding::base64_decode(req.buff);
|
||||
get_wallet()->sign_buffer(buff, res.sig);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_validate_signature(const wallet_public::COMMAND_VALIDATE_SIGNATURE::request& req, wallet_public::COMMAND_VALIDATE_SIGNATURE::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
std::string buff = epee::string_encoding::base64_decode(req.buff);
|
||||
bool r = get_wallet()->validate_sign(buff, req.sig, req.pkey);
|
||||
if (!r)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT;
|
||||
er.message = "WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_encrypt_data(const wallet_public::COMMAND_ENCRYPT_DATA::request& req, wallet_public::COMMAND_ENCRYPT_DATA::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
std::string buff = epee::string_encoding::base64_decode(req.buff);
|
||||
bool r = get_wallet()->encrypt_buffer(buff, res.res_buff);
|
||||
res.res_buff = epee::string_encoding::base64_encode(res.res_buff);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_decrypt_data(const wallet_public::COMMAND_DECRYPT_DATA::request& req, wallet_public::COMMAND_DECRYPT_DATA::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
std::string buff = epee::string_encoding::base64_decode(req.buff);
|
||||
bool r = get_wallet()->encrypt_buffer(buff, res.res_buff);
|
||||
res.res_buff = epee::string_encoding::base64_encode(res.res_buff);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::reset_active_wallet(std::shared_ptr<wallet2> w)
|
||||
{
|
||||
m_pwallet = w;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
} // namespace tools
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace tools
|
|||
public:
|
||||
typedef epee::net_utils::connection_context_base connection_context;
|
||||
|
||||
wallet_rpc_server(wallet2& cr);
|
||||
wallet_rpc_server(std::shared_ptr<wallet2> wptr);
|
||||
|
||||
const static command_line::arg_descriptor<std::string> arg_rpc_bind_port;
|
||||
const static command_line::arg_descriptor<std::string> arg_rpc_bind_ip;
|
||||
|
|
@ -73,6 +73,20 @@ namespace tools
|
|||
MAP_JON_RPC_WE("atomics_redeem_htlc", on_redeem_htlc, wallet_public::COMMAND_REDEEM_HTLC)
|
||||
MAP_JON_RPC_WE("atomics_check_htlc_redeemed", on_check_htlc_redeemed, wallet_public::COMMAND_CHECK_HTLC_REDEEMED)
|
||||
|
||||
//IONIC_SWAPS API
|
||||
MAP_JON_RPC_WE("ionic_swap_generate_proposal", on_ionic_swap_generate_proposal, wallet_public::COMMAND_IONIC_SWAP_GENERATE_PROPOSAL)
|
||||
MAP_JON_RPC_WE("ionic_swap_get_proposal_info", on_ionic_swap_get_proposal_info, wallet_public::COMMAND_IONIC_SWAP_GET_PROPOSAL_INFO)
|
||||
MAP_JON_RPC_WE("ionic_swap_accept_proposal", on_ionic_swap_accept_proposal, wallet_public::COMMAND_IONIC_SWAP_ACCEPT_PROPOSAL)
|
||||
|
||||
//MULTIWALLET APIs
|
||||
MAP_JON_RPC_WE("mw_get_wallets", on_mw_get_wallets, wallet_public::COMMAND_MW_GET_WALLETS)
|
||||
MAP_JON_RPC_WE("mw_select_wallet", on_mw_select_wallet, wallet_public::COMMAND_MW_SELECT_WALLET)
|
||||
|
||||
//basic crypto operations
|
||||
MAP_JON_RPC_WE("sign_message", on_sign_message, wallet_public::COMMAND_SIGN_MESSAGE)
|
||||
MAP_JON_RPC_WE("validate_signature", on_validate_signature, wallet_public::COMMAND_VALIDATE_SIGNATURE)
|
||||
MAP_JON_RPC_WE("encrypt_data", on_encrypt_data, wallet_public::COMMAND_ENCRYPT_DATA)
|
||||
MAP_JON_RPC_WE("decrypt_data", on_decrypt_data, wallet_public::COMMAND_DECRYPT_DATA)
|
||||
END_JSON_RPC_MAP()
|
||||
END_URI_MAP2()
|
||||
|
||||
|
|
@ -114,11 +128,28 @@ namespace tools
|
|||
bool on_redeem_htlc(const wallet_public::COMMAND_REDEEM_HTLC::request& req, wallet_public::COMMAND_REDEEM_HTLC::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_check_htlc_redeemed(const wallet_public::COMMAND_CHECK_HTLC_REDEEMED::request& req, wallet_public::COMMAND_CHECK_HTLC_REDEEMED::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
||||
bool on_ionic_swap_generate_proposal(const wallet_public::COMMAND_IONIC_SWAP_GENERATE_PROPOSAL::request& req, wallet_public::COMMAND_IONIC_SWAP_GENERATE_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_ionic_swap_get_proposal_info(const wallet_public::COMMAND_IONIC_SWAP_GET_PROPOSAL_INFO::request& req, wallet_public::COMMAND_IONIC_SWAP_GET_PROPOSAL_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_ionic_swap_accept_proposal(const wallet_public::COMMAND_IONIC_SWAP_ACCEPT_PROPOSAL::request& req, wallet_public::COMMAND_IONIC_SWAP_ACCEPT_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
||||
bool on_mw_get_wallets(const wallet_public::COMMAND_MW_GET_WALLETS::request& req, wallet_public::COMMAND_MW_GET_WALLETS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_mw_select_wallet(const wallet_public::COMMAND_MW_SELECT_WALLET::request& req, wallet_public::COMMAND_MW_SELECT_WALLET::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
||||
bool on_sign_message(const wallet_public::COMMAND_SIGN_MESSAGE::request& req, wallet_public::COMMAND_SIGN_MESSAGE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_validate_signature(const wallet_public::COMMAND_VALIDATE_SIGNATURE::request& req, wallet_public::COMMAND_VALIDATE_SIGNATURE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_encrypt_data(const wallet_public::COMMAND_ENCRYPT_DATA::request& req, wallet_public::COMMAND_ENCRYPT_DATA::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_decrypt_data(const wallet_public::COMMAND_DECRYPT_DATA::request& req, wallet_public::COMMAND_DECRYPT_DATA::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
||||
|
||||
|
||||
std::shared_ptr<wallet2> get_wallet();
|
||||
|
||||
bool reset_active_wallet(std::shared_ptr<wallet2> w);
|
||||
|
||||
bool handle_command_line(const boost::program_options::variables_map& vm);
|
||||
|
||||
private:
|
||||
wallet2& m_wallet;
|
||||
std::weak_ptr<wallet2> m_pwallet;
|
||||
std::string m_port;
|
||||
std::string m_bind_ip;
|
||||
bool m_do_mint;
|
||||
|
|
|
|||
|
|
@ -802,7 +802,7 @@ void wallets_manager::init_wallet_entry(wallet_vs_options& wo, uint64_t id)
|
|||
wo.m_pproxy_diagnostig_info = m_rpc_proxy->get_proxy_diagnostic_info();
|
||||
wo.pview = m_pview;
|
||||
wo.has_related_alias_in_unconfirmed = false;
|
||||
wo.rpc_wrapper.reset(new tools::wallet_rpc_server(*wo.w.unlocked_get().get()));
|
||||
wo.rpc_wrapper.reset(new tools::wallet_rpc_server(wo.w.unlocked_get()));
|
||||
if (m_remote_node_mode)
|
||||
wo.core_conf = currency::get_default_core_runtime_config();
|
||||
else
|
||||
|
|
@ -876,6 +876,80 @@ std::string wallets_manager::get_fav_offers(const std::list<bc_services::offer_i
|
|||
#endif
|
||||
}
|
||||
|
||||
std::string wallets_manager::create_ionic_swap_proposal(uint64_t wallet_id, const tools::wallet_public::create_ionic_swap_proposal_request& proposal_req, std::string& result_proposal_hex)
|
||||
{
|
||||
GET_WALLET_OPT_BY_ID(wallet_id, wo);
|
||||
try {
|
||||
currency::account_public_address dest_account = AUTO_VAL_INIT(dest_account);
|
||||
if (!currency::get_account_address_from_str(dest_account, proposal_req.destination_add))
|
||||
{
|
||||
return API_RETURN_CODE_BAD_ARG;
|
||||
}
|
||||
tools::wallet_public::ionic_swap_proposal proposal = AUTO_VAL_INIT(proposal);
|
||||
bool r = wo.w->get()->create_ionic_swap_proposal(proposal_req.proposal_info, dest_account, proposal);
|
||||
if (!r)
|
||||
{
|
||||
return API_RETURN_CODE_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_proposal_hex = epee::string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(proposal));
|
||||
return API_RETURN_CODE_OK;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return API_RETURN_CODE_FAIL;
|
||||
}
|
||||
return API_RETURN_CODE_OK;
|
||||
}
|
||||
|
||||
std::string wallets_manager::get_ionic_swap_proposal_info(uint64_t wallet_id, std::string&raw_tx_template_hex, tools::wallet_public::ionic_swap_proposal_info& proposal)
|
||||
{
|
||||
GET_WALLET_OPT_BY_ID(wallet_id, wo);
|
||||
try {
|
||||
std::string raw_tx_template;
|
||||
bool r = epee::string_tools::parse_hexstr_to_binbuff(raw_tx_template_hex, raw_tx_template);
|
||||
if (!r)
|
||||
{
|
||||
return API_RETURN_CODE_BAD_ARG;
|
||||
}
|
||||
|
||||
if (!wo.w->get()->get_ionic_swap_proposal_info(raw_tx_template, proposal))
|
||||
{
|
||||
return API_RETURN_CODE_FAIL;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return API_RETURN_CODE_FAIL;
|
||||
}
|
||||
return API_RETURN_CODE_OK;
|
||||
}
|
||||
|
||||
std::string wallets_manager::accept_ionic_swap_proposal(uint64_t wallet_id, std::string&raw_tx_template_hex, std::string& result_raw_tx_hex)
|
||||
{
|
||||
GET_WALLET_OPT_BY_ID(wallet_id, wo);
|
||||
try {
|
||||
std::string raw_tx_template;
|
||||
bool r = epee::string_tools::parse_hexstr_to_binbuff(raw_tx_template_hex, raw_tx_template);
|
||||
if (!r)
|
||||
{
|
||||
return API_RETURN_CODE_BAD_ARG;
|
||||
}
|
||||
currency::transaction result_tx = AUTO_VAL_INIT(result_tx);
|
||||
if (!wo.w->get()->accept_ionic_swap_proposal(raw_tx_template, result_tx))
|
||||
{
|
||||
return API_RETURN_CODE_FAIL;
|
||||
}
|
||||
result_raw_tx_hex = epee::string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(result_tx));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return API_RETURN_CODE_FAIL;
|
||||
}
|
||||
return API_RETURN_CODE_OK;
|
||||
}
|
||||
std::string wallets_manager::get_my_offers(const bc_services::core_offers_filter& filter, std::list<bc_services::offer_details_ex>& offers)
|
||||
{
|
||||
if (m_remote_node_mode)
|
||||
|
|
@ -1297,6 +1371,8 @@ std::string wallets_manager::get_alias_info_by_name(const std::string& name, cur
|
|||
if (!r)
|
||||
return API_RETURN_CODE_FAIL;
|
||||
|
||||
if (res.status == API_RETURN_CODE_NOT_FOUND)
|
||||
return API_RETURN_CODE_NOT_FOUND;
|
||||
|
||||
res_details.alias = name;
|
||||
res_details.details = res.alias_details;
|
||||
|
|
@ -1923,7 +1999,13 @@ void wallets_manager::on_transfer_canceled(size_t wallet_id, const tools::wallet
|
|||
tei.ti = wti;
|
||||
|
||||
SHARED_CRITICAL_REGION_LOCAL(m_wallets_lock);
|
||||
auto& w = m_wallets[wallet_id].w;
|
||||
auto it = m_wallets.find(wallet_id);
|
||||
if (it == m_wallets.end())
|
||||
{
|
||||
LOG_ERROR(get_wallet_log_prefix(wallet_id) + "on_transfer_canceled() wallet with id = " << wallet_id << " not found");
|
||||
return;
|
||||
}
|
||||
auto& w = it->second.w;
|
||||
if (w->get() != nullptr)
|
||||
{
|
||||
w->get()->balance(tei.balances, tei.total_mined);
|
||||
|
|
@ -1931,7 +2013,7 @@ void wallets_manager::on_transfer_canceled(size_t wallet_id, const tools::wallet
|
|||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(get_wallet_log_prefix(wallet_id) + "on_transfer() wallet with id = " << wallet_id << " not found");
|
||||
LOG_ERROR(get_wallet_log_prefix(wallet_id) + "on_transfer_canceled() wallet with id = " << wallet_id << " has nullptr");
|
||||
}
|
||||
m_pview->money_transfer_cancel(tei);
|
||||
}
|
||||
|
|
@ -1942,6 +2024,31 @@ void wallets_manager::on_tor_status_change(size_t wallet_id, const std::string&
|
|||
m_pview->update_tor_status(tsu);
|
||||
}
|
||||
|
||||
void wallets_manager::on_mw_get_wallets(std::vector<tools::wallet_public::wallet_entry_info>& wallets)
|
||||
{
|
||||
std::list<view::open_wallet_response> opened_wallets;
|
||||
this->get_opened_wallets(opened_wallets);
|
||||
wallets.resize(opened_wallets.size());
|
||||
size_t i = 0;
|
||||
for (const auto& item : opened_wallets)
|
||||
{
|
||||
wallets[i].wi = item.wi;
|
||||
wallets[i].wallet_id = item.wallet_id;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
bool wallets_manager::on_mw_select_wallet(uint64_t wallet_id)
|
||||
{
|
||||
SHARED_CRITICAL_REGION_LOCAL(m_wallets_lock);
|
||||
auto it = m_wallets.find(wallet_id);
|
||||
if (it == m_wallets.end())
|
||||
return false;
|
||||
auto& wo = it->second;
|
||||
//m_wallet_rpc_server.reset_active_wallet(wo.w);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void wallets_manager::wallet_vs_options::worker_func()
|
||||
{
|
||||
LOG_PRINT_GREEN("[WALLET_HANDLER] Wallet handler thread started, addr: " << w->get()->get_account().get_public_address_str(), LOG_LEVEL_0);
|
||||
|
|
|
|||
|
|
@ -136,6 +136,9 @@ public:
|
|||
std::string backup_wallet(uint64_t wallet_id, const std::wstring& path);
|
||||
std::string reset_wallet_password(uint64_t wallet_id, const std::string& pass);
|
||||
std::string is_wallet_password_valid(uint64_t wallet_id, const std::string& pass);
|
||||
std::string create_ionic_swap_proposal(uint64_t wallet_id, const tools::wallet_public::create_ionic_swap_proposal_request& proposal, std::string& result_proposal_hex);
|
||||
std::string get_ionic_swap_proposal_info(uint64_t wallet_id, std::string&raw_tx_template_hex, tools::wallet_public::ionic_swap_proposal_info& proposal);
|
||||
std::string accept_ionic_swap_proposal(uint64_t wallet_id, std::string&raw_tx_template_hex, std::string& result_raw_tx);
|
||||
std::string get_my_offers(const bc_services::core_offers_filter& filter, std::list<bc_services::offer_details_ex>& offers);
|
||||
std::string get_fav_offers(const std::list<bc_services::offer_id>& hashes, const bc_services::core_offers_filter& filter, std::list<bc_services::offer_details_ex>& offers);
|
||||
std::string get_tx_pool_info(currency::COMMAND_RPC_GET_POOL_INFO::response& res);
|
||||
|
|
@ -190,6 +193,10 @@ private:
|
|||
virtual void on_transfer_canceled(size_t wallet_id, const tools::wallet_public::wallet_transfer_info& wti);
|
||||
virtual void on_tor_status_change(size_t wallet_id, const std::string& state);
|
||||
|
||||
virtual void on_mw_get_wallets(std::vector<tools::wallet_public::wallet_entry_info>& wallets) override;
|
||||
virtual bool on_mw_select_wallet(uint64_t wallet_id) override;
|
||||
|
||||
//--------
|
||||
|
||||
std::thread m_main_worker_thread;
|
||||
|
||||
|
|
|
|||
|
|
@ -2229,7 +2229,10 @@ bool shuffle_source_entries(std::vector<tx_source_entry>& sources)
|
|||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
test_chain_unit_base::test_chain_unit_base()
|
||||
{
|
||||
m_hardforks = get_default_core_runtime_config().hard_forks; // set default hardforks for tests (will be overriden by test if necessary)
|
||||
}
|
||||
void test_chain_unit_base::register_callback(const std::string& cb_name, verify_callback cb)
|
||||
{
|
||||
m_callbacks[cb_name] = cb;
|
||||
|
|
@ -2287,8 +2290,6 @@ test_chain_unit_enchanced::test_chain_unit_enchanced()
|
|||
REGISTER_CALLBACK_METHOD(test_chain_unit_enchanced, check_offers_count);
|
||||
REGISTER_CALLBACK_METHOD(test_chain_unit_enchanced, check_hardfork_active);
|
||||
REGISTER_CALLBACK_METHOD(test_chain_unit_enchanced, check_hardfork_inactive);
|
||||
|
||||
m_hardforks = get_default_core_runtime_config().hard_forks; // set default hardforks for tests (will be overriden by test if necessary)
|
||||
}
|
||||
|
||||
bool test_chain_unit_enchanced::configure_core(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
|
|
|
|||
|
|
@ -230,6 +230,8 @@ class test_generator;
|
|||
class test_chain_unit_base
|
||||
{
|
||||
public:
|
||||
test_chain_unit_base();
|
||||
|
||||
typedef boost::function<bool(currency::core& c, size_t ev_index, const std::vector<test_event_entry> &events)> verify_callback;
|
||||
typedef std::map<std::string, verify_callback> callbacks_map;
|
||||
|
||||
|
|
|
|||
|
|
@ -1085,6 +1085,7 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(zarcanum_basic_test);
|
||||
|
||||
GENERATE_AND_PLAY(multiassets_basic_test);
|
||||
GENERATE_AND_PLAY(ionic_swap_basic_test);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -42,3 +42,4 @@
|
|||
#include "isolate_auditable_and_proof.h"
|
||||
#include "zarcanum_test.h"
|
||||
#include "multiassets_test.h"
|
||||
#include "ionic_swap_tests.h"
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ bool hard_fork_2_tx_payer_in_wallet::c1(currency::core& c, size_t ev_index, cons
|
|||
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt, MK_TEST_COINS(12)), false, "");
|
||||
|
||||
// wallet RPC server
|
||||
tools::wallet_rpc_server miner_wlt_rpc(*miner_wlt);
|
||||
tools::wallet_rpc_server miner_wlt_rpc(miner_wlt);
|
||||
epee::json_rpc::error je;
|
||||
tools::wallet_rpc_server::connection_context ctx;
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ bool hard_fork_2_tx_payer_in_wallet::c1(currency::core& c, size_t ev_index, cons
|
|||
bob_wlt->callback(std::make_shared<tools::i_wallet2_callback>()); // clear callback
|
||||
|
||||
// Before HF2: Bob (auditable address) -> Alice with payer info requested (should NOT put tx_payer or tx_payer_old)
|
||||
tools::wallet_rpc_server bob_wlt_rpc(*bob_wlt);
|
||||
tools::wallet_rpc_server bob_wlt_rpc(bob_wlt);
|
||||
tools::wallet_public::COMMAND_RPC_TRANSFER::request req_c = AUTO_VAL_INIT(req_c);
|
||||
req_c.destinations.push_back(tools::wallet_public::transfer_destination{ MK_TEST_COINS(1), m_accounts[ALICE_ACC_IDX].get_public_address_str() });
|
||||
req_c.fee = TESTS_DEFAULT_FEE;
|
||||
|
|
@ -328,7 +328,7 @@ bool hard_fork_2_tx_receiver_in_wallet::c1(currency::core& c, size_t ev_index, c
|
|||
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt, 0), false, "");
|
||||
|
||||
// wallet RPC server
|
||||
tools::wallet_rpc_server alice_wlt_rpc(*alice_wlt);
|
||||
tools::wallet_rpc_server alice_wlt_rpc(alice_wlt);
|
||||
epee::json_rpc::error je;
|
||||
tools::wallet_rpc_server::connection_context ctx;
|
||||
|
||||
|
|
|
|||
203
tests/core_tests/ionic_swap_tests.cpp
Normal file
203
tests/core_tests/ionic_swap_tests.cpp
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
// Copyright (c) 2014-2022 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "chaingen.h"
|
||||
#include "ionic_swap_tests.h"
|
||||
#include "wallet_test_core_proxy.h"
|
||||
|
||||
#include "random_helper.h"
|
||||
#include "tx_builder.h"
|
||||
|
||||
#define AMOUNT_TO_TRANSFER_MULTIASSETS_BASIC (TESTS_DEFAULT_FEE)
|
||||
|
||||
#define AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC 500000000000000000
|
||||
|
||||
|
||||
|
||||
ionic_swap_basic_test::ionic_swap_basic_test()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(ionic_swap_basic_test, configure_core);
|
||||
REGISTER_CALLBACK_METHOD(ionic_swap_basic_test, c1);
|
||||
|
||||
m_hardforks.set_hardfork_height(1, 1);
|
||||
m_hardforks.set_hardfork_height(2, 1);
|
||||
m_hardforks.set_hardfork_height(3, 1);
|
||||
m_hardforks.set_hardfork_height(4, 2);
|
||||
}
|
||||
|
||||
bool ionic_swap_basic_test::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
// NOTE: This test is made deterministic to be able to correctly set up checkpoint.
|
||||
random_state_test_restorer::reset_random(); // random generator's state was previously stored, will be restore on dtor (see also m_random_state_test_restorer)
|
||||
uint64_t ts = 1450000000;
|
||||
test_core_time::adjust(ts);
|
||||
|
||||
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);
|
||||
//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);
|
||||
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 + 3);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ionic_swap_basic_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->get_account().set_createtime(0);
|
||||
|
||||
//std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX);
|
||||
//std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, BOB_ACC_IDX);
|
||||
|
||||
// check passing over the hardfork
|
||||
CHECK_AND_ASSERT_MES(c.get_blockchain_storage().is_hardfork_active(ZANO_HARDFORK_04_ZARCANUM), false, "ZANO_HARDFORK_04_ZARCANUM is active");
|
||||
|
||||
|
||||
currency::account_base alice_acc;
|
||||
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);
|
||||
adb.total_max_supply = 1000000000000000000; //1M coins
|
||||
adb.full_name = "Test coins";
|
||||
adb.ticker = "TCT";
|
||||
adb.decimal_point = 12;
|
||||
|
||||
std::vector<currency::tx_destination_entry> destinations(2);
|
||||
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());
|
||||
destinations[1].amount = AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC;
|
||||
destinations[1].asset_id = currency::null_pkey;
|
||||
|
||||
LOG_PRINT_MAGENTA("destinations[0].asset_id:" << destinations[0].asset_id, LOG_LEVEL_0);
|
||||
LOG_PRINT_MAGENTA("destinations[1].asset_id:" << destinations[1].asset_id, LOG_LEVEL_0);
|
||||
LOG_PRINT_MAGENTA("currency::null_pkey:" << currency::null_pkey, LOG_LEVEL_0);
|
||||
|
||||
currency::transaction tx = AUTO_VAL_INIT(tx);
|
||||
crypto::public_key asset_id = currency::null_pkey;
|
||||
miner_wlt->publish_new_asset(adb, destinations, tx, asset_id);
|
||||
LOG_PRINT_L0("Published new asset: " << asset_id << ", tx_id: " << currency::get_transaction_hash(tx));
|
||||
|
||||
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");
|
||||
|
||||
|
||||
bob_wlt->refresh();
|
||||
alice_wlt->refresh();
|
||||
uint64_t mined = 0;
|
||||
std::unordered_map<crypto::public_key, tools::wallet_public::asset_balance_entry_base> balances;
|
||||
bob_wlt->balance(balances, mined);
|
||||
|
||||
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 == COIN, false, "Failed to find needed asset in result balances");
|
||||
|
||||
uint64_t mined_balance = it_native->second.total;
|
||||
|
||||
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() && it_native != balances.end(), 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");
|
||||
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 = COIN/2;
|
||||
|
||||
//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;
|
||||
proposal_details.mixins = 10;
|
||||
proposal_details.to_bob.push_back(view::asset_funds{ asset_id , assets_to_exchange });
|
||||
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, bob_wlt->get_account().get_public_address(), proposal);
|
||||
|
||||
view::ionic_swap_proposal_info proposal_decoded_info = AUTO_VAL_INIT(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
|
||||
|| proposal_decoded_info.to_alice != proposal_details.to_alice
|
||||
|| proposal_decoded_info.fee_paid_by_a != proposal_details.fee_paid_by_a
|
||||
|| proposal_decoded_info.mixins != proposal_details.mixins
|
||||
)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(false, false, "proposal actual and proposals decoded mismatch");
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
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");
|
||||
|
||||
bob_wlt->refresh();
|
||||
alice_wlt->refresh();
|
||||
|
||||
|
||||
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->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();
|
||||
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 == 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");
|
||||
|
||||
|
||||
//TODO:
|
||||
// add fee paid by bob scenario
|
||||
// add transfer of tokens without native coins
|
||||
// different fail combination
|
||||
return true;
|
||||
}
|
||||
|
||||
18
tests/core_tests/ionic_swap_tests.h
Normal file
18
tests/core_tests/ionic_swap_tests.h
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) 2014-2022 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#pragma once
|
||||
#include "chaingen.h"
|
||||
#include "wallet_tests_basic.h"
|
||||
#include "random_helper.h"
|
||||
|
||||
struct ionic_swap_basic_test : public wallet_test
|
||||
{
|
||||
ionic_swap_basic_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);
|
||||
|
||||
private:
|
||||
random_state_test_restorer m_random_state_test_restorer;
|
||||
};
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ bool isolate_auditable_and_proof::c1(currency::core& c, size_t ev_index, const s
|
|||
|
||||
epee::json_rpc::error je;
|
||||
tools::wallet_rpc_server::connection_context ctx;
|
||||
tools::wallet_rpc_server miner_wlt_rpc(*auditable_test_instance);
|
||||
tools::wallet_rpc_server miner_wlt_rpc(auditable_test_instance);
|
||||
tools::wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::request req = AUTO_VAL_INIT(req);
|
||||
tools::wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::response res = AUTO_VAL_INIT(res);
|
||||
req.count = 100;
|
||||
|
|
|
|||
|
|
@ -70,14 +70,14 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
std::vector<currency::tx_destination_entry> destinations(2);
|
||||
destinations[0].addr.push_back(miner_wlt->get_account().get_public_address());
|
||||
destinations[0].amount = AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC;
|
||||
destinations[0].asset_id = currency::ffff_pkey;
|
||||
destinations[0].asset_id = currency::null_pkey;
|
||||
destinations[1].addr.push_back(alice_wlt->get_account().get_public_address());
|
||||
destinations[1].amount = AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC;
|
||||
destinations[1].asset_id = currency::ffff_pkey;
|
||||
destinations[1].asset_id = currency::null_pkey;
|
||||
|
||||
LOG_PRINT_MAGENTA("destinations[0].asset_id:" << destinations[0].asset_id, LOG_LEVEL_0);
|
||||
LOG_PRINT_MAGENTA("destinations[1].asset_id:" << destinations[1].asset_id, LOG_LEVEL_0);
|
||||
LOG_PRINT_MAGENTA("currency::ffff_pkey: " << currency::ffff_pkey, LOG_LEVEL_0);
|
||||
LOG_PRINT_MAGENTA("currency::null_pkey: " << currency::null_pkey, LOG_LEVEL_0);
|
||||
|
||||
currency::transaction tx = AUTO_VAL_INIT(tx);
|
||||
crypto::public_key asset_id = currency::null_pkey;
|
||||
|
|
|
|||
|
|
@ -66,8 +66,9 @@ void transfer_multisig(tools::wallet2& w,
|
|||
|
||||
|
||||
ftp.tx_version = tx_version;
|
||||
|
||||
w.prepare_transaction(ctp, ftp, tx);
|
||||
tools::mode_separate_context emode_separate = AUTO_VAL_INIT(emode_separate);
|
||||
emode_separate.tx_for_mode_separate = tx;
|
||||
w.prepare_transaction(ctp, ftp, emode_separate);
|
||||
crypto::secret_key sk = AUTO_VAL_INIT(sk);
|
||||
w.finalize_transaction(ftp, tx, sk, false);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ bool wallet_rpc_integrated_address::generate(std::vector<test_event_entry>& even
|
|||
CREATE_TEST_WALLET(miner_wlt, miner_acc, blk_0);
|
||||
|
||||
// wallet RPC server
|
||||
tools::wallet_rpc_server miner_wlt_rpc(*miner_wlt);
|
||||
tools::wallet_rpc_server miner_wlt_rpc(miner_wlt);
|
||||
epee::json_rpc::error je;
|
||||
tools::wallet_rpc_server::connection_context ctx;
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ bool wallet_rpc_integrated_address_transfer::c1(currency::core& c, size_t ev_ind
|
|||
std::string alice_integrated_address = get_account_address_and_payment_id_as_str(m_accounts[ALICE_ACC_IDX].get_public_address(), payment_id);
|
||||
|
||||
// wallet RPC server
|
||||
tools::wallet_rpc_server miner_wlt_rpc(*miner_wlt);
|
||||
tools::wallet_rpc_server miner_wlt_rpc(miner_wlt);
|
||||
epee::json_rpc::error je;
|
||||
tools::wallet_rpc_server::connection_context ctx;
|
||||
|
||||
|
|
@ -226,7 +226,7 @@ bool wallet_rpc_transfer::c1(currency::core& c, size_t ev_index, const std::vect
|
|||
miner_wlt->refresh();
|
||||
|
||||
// wallet RPC server
|
||||
tools::wallet_rpc_server miner_wlt_rpc(*miner_wlt);
|
||||
tools::wallet_rpc_server miner_wlt_rpc(miner_wlt);
|
||||
epee::json_rpc::error je;
|
||||
tools::wallet_rpc_server::connection_context ctx;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
// Copyright (c) 2014-2022 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
// Copyright (c) 2014-2022 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#pragma once
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue