1
0
Fork 0
forked from lthn/blockchain

payment_id improved

This commit is contained in:
cryptozoidberg 2024-02-17 20:34:35 +04:00
parent 93b3ca4b66
commit fa606c1665
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
9 changed files with 107 additions and 52 deletions

View file

@ -8,14 +8,54 @@
namespace bc_services
{
template<typename T>
struct is_boost_variant : std::false_type {};
template<typename... Args>
struct is_boost_variant<boost::variant<Args...>> : std::true_type {};
template<bool is_variant>
struct type_selector;
template<>
struct type_selector<true>
{
template<typename t_type>
static const std::type_info& get_type(const t_type& t)
{
return t.type();
}
template<typename t_type, typename t_return_type>
static const t_return_type& get(const t_type& t)
{
return boost::get<t_return_type>(t);
}
};
template<>
struct type_selector<false>
{
template<typename t_type>
static const std::type_info& get_type(const t_type& t)
{
return typeid(t);
}
template<typename t_type, typename t_return_type>
static const t_return_type& get(const t_type& t)
{
return t;
}
};
template<class t_attachment_type_container_t>
bool get_first_service_attachment_by_id(const t_attachment_type_container_t& tx_items, const std::string& id, const std::string& instruction, currency::tx_service_attachment& res)
{
for (const auto& item : tx_items)
{
if (item.type() == typeid(currency::tx_service_attachment))
if (/*item.type()*/ type_selector<is_boost_variant<t_attachment_type_container_t::value_type>::value>::get_type(item) == typeid(currency::tx_service_attachment))
{
const currency::tx_service_attachment& tsa = boost::get<currency::tx_service_attachment>(item);
const currency::tx_service_attachment& tsa = type_selector<is_boost_variant<t_attachment_type_container_t::value_type>::value>::get<t_attachment_type_container_t::value_type, currency::tx_service_attachment>(item);
//const currency::tx_service_attachment& tsa = boost::get<currency::tx_service_attachment>(item);
if (tsa.service_id == id && tsa.instruction == instruction)
{
res = tsa;

View file

@ -3361,7 +3361,7 @@ namespace currency
return true;
}
//---------------------------------------------------------------
bool set_payment_id_to_tx(std::vector<attachment_v>& att, const std::string& payment_id)
bool set_payment_id_to_tx(std::vector<attachment_v>& att, const std::string& payment_id, bool is_in_hardfork4)
{
if (!is_payment_id_size_ok(payment_id))
return false;
@ -3369,6 +3369,10 @@ namespace currency
tx_service_attachment tsa = AUTO_VAL_INIT(tsa);
tsa.service_id = BC_PAYMENT_ID_SERVICE_ID;
tsa.body = payment_id;
if (is_in_hardfork4)
{
tsa.flags = TX_SERVICE_ATTACHMENT_ENCRYPT_BODY;
}
att.push_back(tsa);
return true;
}

View file

@ -431,7 +431,7 @@ namespace currency
bool addendum_to_hexstr(const std::vector<crypto::hash>& add, std::string& hex_buff);
bool hexstr_to_addendum(const std::string& hex_buff, std::vector<crypto::hash>& add);
bool set_payment_id_to_tx(std::vector<attachment_v>& att, const std::string& payment_id);
bool set_payment_id_to_tx(std::vector<attachment_v>& att, const std::string& payment_id, bool is_in_hardfork4 = false);
bool add_padding_to_tx(transaction& tx, size_t count);
bool is_service_tx(const transaction& tx);
bool does_tx_have_only_mixin_inputs(const transaction& tx);
@ -672,7 +672,7 @@ namespace currency
}
//---------------------------------------------------------------
template<typename t_container>
bool get_payment_id_from_tx(const t_container& att, std::string& payment_id)
bool get_payment_id_from_decrypted_container(const t_container& att, std::string& payment_id)
{
tx_service_attachment sa = AUTO_VAL_INIT(sa);
if (bc_services::get_first_service_attachment_by_id(att, BC_PAYMENT_ID_SERVICE_ID, "", sa))

View file

@ -1681,7 +1681,7 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
std::vector<currency::attachment_v> attachments;
if (!payment_id.empty() && !set_payment_id_to_tx(attachments, payment_id))
if (!payment_id.empty() && !set_payment_id_to_tx(attachments, payment_id, m_wallet->is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM)))
{
fail_msg_writer() << "provided (or embedded) payment id can't be set: \"" << payment_id << "\"";
return true;

View file

@ -589,7 +589,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
all values m_payments entry, use this strict policy is required to protect exchanges from being feeded with
useless outputs
*/
uint64_t max_out_unlock_time = 0;
ptc.max_out_unlock_time = 0;
std::vector<wallet_out_info> outs;
//uint64_t sum_of_native_outs = 0; // TODO: @#@# correctly calculate tx_money_got_in_outs for post-HF4
@ -833,8 +833,8 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
m_amount_gindex_to_transfer_id[amount_gindex_pair] = transfer_index;
}
if (max_out_unlock_time < get_tx_unlock_time(tx, o))
max_out_unlock_time = get_tx_unlock_time(tx, o);
if (ptc.max_out_unlock_time < get_tx_unlock_time(tx, o))
ptc.max_out_unlock_time = get_tx_unlock_time(tx, o);
if (out_type_to_key || out_type_zc)
{
@ -888,32 +888,6 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
}
}
std::string payment_id;
if (has_in_transfers && get_payment_id_from_tx(tx.attachment, payment_id) && payment_id.size())
{
payment_details payment;
payment.m_tx_hash = ptc.tx_hash();
payment.m_amount = 0;
payment.m_block_height = height;
payment.m_unlock_time = max_out_unlock_time;
for (const auto& bce : ptc.total_balance_change)
{
if (bce.second > 0)
{
if (bce.first == currency::native_coin_asset_id)
{
payment.m_amount = static_cast<uint64_t>(bce.second);
}else
{
payment.subtransfers.push_back(payment_details_subtransfer{ bce.first, static_cast<uint64_t>(bce.second)});
}
}
}
m_payments.emplace(payment_id, payment);
WLT_LOG_L2("Payment found, id (hex): " << epee::string_tools::buff_to_hex_nodelimer(payment_id) << ", tx: " << payment.m_tx_hash << ", amount: " << print_money_brief(payment.m_amount) << "subtransfers = " << payment.subtransfers.size());
}
//check if there are asset_registration that belong to this wallet
const asset_descriptor_operation* pado = get_type_in_variant_container<const asset_descriptor_operation>(tx.extra);
if (pado && (ptc.employed_entries.receive.size() || ptc.employed_entries.spent.size() || pado->descriptor.owner == m_account.get_public_address().spend_public_key))
@ -971,7 +945,7 @@ void wallet2::prepare_wti_decrypted_attachments(wallet_public::wallet_transfer_i
{
LOG_ERROR("wti.payment_id is expected to be empty. Go ahead.");
}
get_payment_id_from_tx(decrypted_att, wti.payment_id);
get_payment_id_from_decrypted_container(decrypted_att, wti.payment_id);
for (const auto& item : decrypted_att)
{
@ -1315,7 +1289,7 @@ bool wallet2::handle_proposal(wallet_public::wallet_transfer_info& wti, const bc
ed.is_a = cpd.a_addr.spend_public_key == m_account.get_keys().account_address.spend_public_key;
change_contract_state(ed, wallet_public::escrow_contract_details_basic::proposal_sent, ms_id, wti);
ed.private_detailes = cpd;
currency::get_payment_id_from_tx(decrypted_items, ed.payment_id);
currency::get_payment_id_from_decrypted_container(decrypted_items, ed.payment_id);
ed.proposal = prop;
ed.height = wti.height;
wti.contract.resize(1);
@ -1584,8 +1558,42 @@ void wallet2::prepare_wti(wallet_public::wallet_transfer_info& wti, const proces
}
prepare_wti_decrypted_attachments(wti, decrypted_att);
process_contract_info(wti, decrypted_att);
process_payment_id_for_wti(wti, tx_process_context);
}
//----------------------------------------------------------------------------------------------------
bool wallet2::process_payment_id_for_wti(wallet_public::wallet_transfer_info& wti, const process_transaction_context& ptc)
{
//if(this->is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM))
{
if (wti.get_native_is_income() && wti.payment_id.size())
{
payment_details payment;
payment.m_tx_hash = wti.tx_hash;
payment.m_amount = 0;
payment.m_block_height = wti.height;
payment.m_unlock_time = ptc.max_out_unlock_time;
for (const auto& bce : ptc.total_balance_change)
{
if (bce.second > 0)
{
if (bce.first == currency::native_coin_asset_id)
{
payment.m_amount = static_cast<uint64_t>(bce.second);
}
else
{
payment.subtransfers.push_back(payment_details_subtransfer{ bce.first, static_cast<uint64_t>(bce.second) });
}
}
}
m_payments.emplace(wti.payment_id, payment);
WLT_LOG_L2("Payment found, id (hex): " << epee::string_tools::buff_to_hex_nodelimer(wti.payment_id) << ", tx: " << payment.m_tx_hash << ", amount: " << print_money_brief(payment.m_amount) << "subtransfers = " << payment.subtransfers.size());
}
}
return true;
}
void wallet2::rise_on_transfer2(const wallet_public::wallet_transfer_info& wti)
{
PROFILE_FUNC("wallet2::rise_on_transfer2");
@ -3864,7 +3872,7 @@ void wallet2::submit_transfer(const std::string& signed_tx_blob, currency::trans
throw;
}
add_sent_tx_detailed_info(tx, ft.ftp.prepared_destinations, ft.ftp.selected_transfers);
add_sent_tx_detailed_info(tx, ft.ftp.attachments, ft.ftp.prepared_destinations, ft.ftp.selected_transfers);
m_tx_keys.insert(std::make_pair(tx_hash, ft.one_time_key));
if (m_watch_only)
@ -5467,7 +5475,7 @@ void wallet2::send_escrow_proposal(const bc_services::contract_private_details&
send_transaction_to_network(tx);
mark_transfers_as_spent(ftp.selected_transfers, std::string("escrow proposal sent, tx <") + epee::string_tools::pod_to_hex(get_transaction_hash(tx)) + ">, contract: " + epee::string_tools::pod_to_hex(ms_id));
add_sent_tx_detailed_info(tx, ftp.prepared_destinations, ftp.selected_transfers);
add_sent_tx_detailed_info(tx, ftp.attachments, ftp.prepared_destinations, ftp.selected_transfers);
print_tx_sent_message(tx, "(from multisig)", fee);
}
@ -6337,12 +6345,12 @@ void wallet2::send_transaction_to_network(const transaction& tx)
}
//----------------------------------------------------------------------------------------------------------------
void wallet2::add_sent_tx_detailed_info(const transaction& tx,
void wallet2::add_sent_tx_detailed_info(const transaction& tx, const std::vector<currency::attachment_v>& decrypted_att,
const std::vector<currency::tx_destination_entry>& destinations,
const std::vector<uint64_t>& selected_transfers)
{
payment_id_t payment_id;
get_payment_id_from_tx(tx.attachment, payment_id);
get_payment_id_from_decrypted_container(decrypted_att, payment_id);
std::vector<std::string> recipients;
std::unordered_set<account_public_address> used_addresses;
@ -7145,7 +7153,7 @@ void wallet2::finalize_transaction(currency::finalize_tx_param& ftp, currency::f
//TIME_MEASURE_START(add_sent_tx_detailed_info_time);
if (broadcast_tx)
add_sent_tx_detailed_info(result.tx, ftp.prepared_destinations, ftp.selected_transfers);
add_sent_tx_detailed_info(result.tx, ftp.attachments, ftp.prepared_destinations, ftp.selected_transfers);
//TIME_MEASURE_FINISH(add_sent_tx_detailed_info_time);
/* TODO
@ -7269,7 +7277,7 @@ void wallet2::check_and_throw_if_self_directed_tx_with_payment_id_requested(cons
// it's self-directed tx
payment_id_t pid;
bool has_payment_id = get_payment_id_from_tx(ctp.attachments, pid) && !pid.empty();
bool has_payment_id = get_payment_id_from_decrypted_container(ctp.attachments, pid) && !pid.empty();
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(!has_payment_id, "sending funds to yourself with payment id is not allowed");
}
//----------------------------------------------------------------------------------------------------
@ -7419,8 +7427,9 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
ftp.tx_version = this->get_current_tx_version();
bool is_hf4 = this->is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM);
if (!payment_id.empty())
set_payment_id_to_tx(ftp.attachments, payment_id);
set_payment_id_to_tx(ftp.attachments, payment_id, is_hf4);
// put encrypted payer info into the extra
ftp.crypt_address = destination_addr;

View file

@ -323,6 +323,7 @@ namespace tools
multisig_entries_map* pmultisig_entries = nullptr;
crypto::public_key tx_pub_key = currency::null_pkey;
uint64_t tx_expiration_ts_median = 0;
uint64_t max_out_unlock_time = 0;
const crypto::hash& tx_hash() const
{
@ -690,6 +691,7 @@ namespace tools
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);
bool is_in_hardfork_zone(uint64_t hardfork_index) const;
construct_tx_param get_default_construct_tx_param();
@ -741,6 +743,7 @@ private:
void prepare_wti_decrypted_attachments(wallet_public::wallet_transfer_info& wti, const std::vector<currency::payload_items_v>& decrypted_att);
void handle_money(const currency::block& b, const process_transaction_context& tx_process_context);
void load_wti_from_process_transaction_context(wallet_public::wallet_transfer_info& wti, const process_transaction_context& tx_process_context);
bool process_payment_id_for_wti(wallet_public::wallet_transfer_info& wti, const process_transaction_context& tx_process_context);
void handle_pulled_blocks(size_t& blocks_added, std::atomic<bool>& stop,
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& blocks);
@ -817,7 +820,8 @@ private:
void load_keys2ki(bool create_if_not_exist, bool& need_to_resync);
void send_transaction_to_network(const currency::transaction& tx);
void add_sent_tx_detailed_info(const currency::transaction& tx,
void add_sent_tx_detailed_info(const currency::transaction& tx,
const std::vector<currency::attachment_v>& decrypted_att,
const std::vector<currency::tx_destination_entry>& destinations,
const std::vector<uint64_t>& selected_indicies);
void mark_transfers_as_spent(const std::vector<uint64_t>& selected_transfers, const std::string& reason = std::string());
@ -838,7 +842,6 @@ private:
uint64_t get_directly_spent_transfer_index_by_input_in_tracking_wallet(uint64_t amount, const std::vector<currency::txout_ref_v> & key_offsets);
uint64_t get_directly_spent_transfer_index_by_input_in_tracking_wallet(const currency::txin_to_key& intk);
uint64_t get_directly_spent_transfer_index_by_input_in_tracking_wallet(const currency::txin_zc_input& inzc);
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);

View file

@ -410,7 +410,7 @@ namespace tools
std::vector<currency::attachment_v>& attachments = ctp.attachments;
std::vector<currency::extra_v>& extra = ctp.extra;
if (!payment_id.empty() && !currency::set_payment_id_to_tx(attachments, payment_id))
if (!payment_id.empty() && !currency::set_payment_id_to_tx(attachments, payment_id, w.get_wallet()->is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM)))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
er.message = std::string("payment id ") + payment_id + " is invalid and can't be set";

View file

@ -1533,18 +1533,17 @@ std::string wallets_manager::transfer(uint64_t wallet_id, const view::transfer_p
dsts.back().asset_id = d.asset_id;
}
GET_WALLET_BY_ID(wallet_id, w);
if (payment_id.size())
{
if (!currency::is_payment_id_size_ok(payment_id))
return API_RETURN_CODE_BAD_ARG_WRONG_PAYMENT_ID; // payment id is too big
if (!currency::set_payment_id_to_tx(attachments, payment_id))
if (!currency::set_payment_id_to_tx(attachments, payment_id, w->get()->is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM)))
return API_RETURN_CODE_INTERNAL_ERROR;
}
GET_WALLET_BY_ID(wallet_id, w);
//set transaction unlock time if it was specified by user
uint64_t unlock_time = 0;

View file

@ -58,7 +58,7 @@ TEST(parse_and_validate_tx_extra, test_payment_ids)
ASSERT_TRUE(r);
std::string h2;
r = currency::get_payment_id_from_tx(tx.attachment, h2);
r = currency::get_payment_id_from_decrypted_container(tx.attachment, h2);
ASSERT_TRUE(r);
ASSERT_EQ(h, h2);