diff --git a/src/currency_core/bc_attachments_helpers_basic.h b/src/currency_core/bc_attachments_helpers_basic.h index 18a8e558..3be62628 100644 --- a/src/currency_core/bc_attachments_helpers_basic.h +++ b/src/currency_core/bc_attachments_helpers_basic.h @@ -8,14 +8,54 @@ namespace bc_services { + template + struct is_boost_variant : std::false_type {}; + + template + struct is_boost_variant> : std::true_type {}; + + template + struct type_selector; + + template<> + struct type_selector + { + template + static const std::type_info& get_type(const t_type& t) + { + return t.type(); + } + template + static const t_return_type& get(const t_type& t) + { + return boost::get(t); + } + }; + + template<> + struct type_selector + { + template + static const std::type_info& get_type(const t_type& t) + { + return typeid(t); + } + template + static const t_return_type& get(const t_type& t) + { + return t; + } + }; + template 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::value>::get_type(item) == typeid(currency::tx_service_attachment)) { - const currency::tx_service_attachment& tsa = boost::get(item); + const currency::tx_service_attachment& tsa = type_selector::value>::get(item); + //const currency::tx_service_attachment& tsa = boost::get(item); if (tsa.service_id == id && tsa.instruction == instruction) { res = tsa; diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 6585c049..554080f4 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -3361,7 +3361,7 @@ namespace currency return true; } //--------------------------------------------------------------- - bool set_payment_id_to_tx(std::vector& att, const std::string& payment_id) + bool set_payment_id_to_tx(std::vector& 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; } diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 620bc91c..ba5d3d7e 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -431,7 +431,7 @@ namespace currency bool addendum_to_hexstr(const std::vector& add, std::string& hex_buff); bool hexstr_to_addendum(const std::string& hex_buff, std::vector& add); - bool set_payment_id_to_tx(std::vector& att, const std::string& payment_id); + bool set_payment_id_to_tx(std::vector& 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 - 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)) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index f0dd80dd..1a1f1e8e 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1681,7 +1681,7 @@ bool simple_wallet::transfer(const std::vector &args_) std::vector 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; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 54ee3934..cb498fca 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -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 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(bce.second); - }else - { - payment.subtransfers.push_back(payment_details_subtransfer{ bce.first, static_cast(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(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(bce.second); + } + else + { + payment.subtransfers.push_back(payment_details_subtransfer{ bce.first, static_cast(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& decrypted_att, const std::vector& destinations, const std::vector& 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 recipients; std::unordered_set 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; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index f83cecee..3097a9c5 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -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& 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& 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& decrypted_att, const std::vector& destinations, const std::vector& selected_indicies); void mark_transfers_as_spent(const std::vector& 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 & 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& htlc_info_list); bool expand_selection_with_zc_input(assets_selection_context& needed_money_map, uint64_t fake_outputs_count, std::vector& selected_indexes); diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 96b65215..a602ecba 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -410,7 +410,7 @@ namespace tools std::vector& attachments = ctp.attachments; std::vector& 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"; diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index e9a95b88..9ef767bf 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -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; diff --git a/tests/unit_tests/test_format_utils.cpp b/tests/unit_tests/test_format_utils.cpp index 9304268f..0e277222 100644 --- a/tests/unit_tests/test_format_utils.cpp +++ b/tests/unit_tests/test_format_utils.cpp @@ -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);