From 6b6511b73f4158bac7f2cdcf87f514953c546597 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 19 May 2022 21:22:44 +0200 Subject: [PATCH] tx stracture changes: in progress --- src/common/variant_helper.h | 9 +- src/currency_core/currency_format_utils.cpp | 80 +++++++++-------- src/currency_core/currency_format_utils.h | 8 +- src/rpc/core_rpc_server.cpp | 9 +- src/wallet/wallet2.h | 6 +- src/wallet/wallet2_escrow.cpp | 95 +++++++++++++-------- 6 files changed, 128 insertions(+), 79 deletions(-) diff --git a/src/common/variant_helper.h b/src/common/variant_helper.h index ae4f8d02..c730bf3c 100644 --- a/src/common/variant_helper.h +++ b/src/common/variant_helper.h @@ -19,13 +19,18 @@ usage: VARIANT_SWITCH_BEGIN(o); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE(tx_out_bare, o); - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_TV(tx_out_zarcanum); //@#@ VARIANT_SWITCH_END(); + VARIANT_SWITCH_BEGIN(o); + VARIANT_CASE(txout_to_key, o) + VARIANT_CASE_TV(txout_multisig) + VARIANT_CASE_TV(txout_htlc) + VARIANT_SWITCH_END(); VARIANT_SWITCH_BEGIN(o); diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index a1ffe112..ebe8db6f 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -2536,12 +2536,18 @@ namespace currency uint64_t found_alias_reward = 0; for (const auto& out : tx.vout) { - if (out.target.type() != typeid(txout_to_key)) - continue; + VARIANT_SWITCH_BEGIN(out); + VARIANT_CASE(tx_out_bare, out) + if (out.target.type() != typeid(txout_to_key)) + continue; + + const txout_to_key& o = boost::get(out.target); + if (o.key == null_pkey) + found_alias_reward += out.amount; + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); - const txout_to_key& o = boost::get(out.target); - if (o.key == null_pkey) - found_alias_reward += out.amount; } return found_alias_reward; } @@ -2776,35 +2782,34 @@ namespace currency for (auto& out : tx.vout) { tei.outs.push_back(tx_out_rpc_entry()); - tei.outs.back().amount = out.amount; tei.outs.back().is_spent = ptce ? ptce->m_spent_flags[i] : false; tei.outs.back().global_index = ptce ? ptce->m_global_output_indexes[i] : 0; + VARIANT_SWITCH_BEGIN(out); + VARIANT_CASE(tx_out_bare, out) + { + tei.outs.back().amount = out.amount; - if (out.target.type() == typeid(txout_to_key)) - { - const txout_to_key& otk = boost::get(out.target); - tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.key)); - if (otk.mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) - tei.outs.back().pub_keys.back() += "(FORCED_NO_MIX)"; - if (otk.mix_attr >= CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND) - tei.outs.back().pub_keys.back() += std::string("(FORCED_MIX_LOWER_BOUND: ") + std::to_string(otk.mix_attr) + ")"; + VARIANT_SWITCH_BEGIN(out.target); + VARIANT_CASE(txout_to_key, otk) + tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.key)); + if (otk.mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) + tei.outs.back().pub_keys.back() += "(FORCED_NO_MIX)"; + if (otk.mix_attr >= CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND) + tei.outs.back().pub_keys.back() += std::string("(FORCED_MIX_LOWER_BOUND: ") + std::to_string(otk.mix_attr) + ")"; + VARIANT_CASE(txout_multisig, otm) + for (auto& k : otm.keys) + { + tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(k)); + } + tei.outs.back().minimum_sigs = otm.minimum_sigs; + VARIANT_CASE(txout_htlc, otk) + tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.pkey_redeem) + "(htlc_pkey_redeem)"); + tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.pkey_refund) + "(htlc_pkey_refund)"); + VARIANT_SWITCH_END(); } - else if (out.target.type() == typeid(txout_multisig)) - { - const txout_multisig& otm = boost::get(out.target); - for (auto& k : otm.keys) - { - tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(k)); - } - tei.outs.back().minimum_sigs = otm.minimum_sigs; - } - else if (out.target.type() == typeid(txout_htlc)) - { - const txout_htlc& otk = boost::get(out.target); - tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.pkey_redeem) + "(htlc_pkey_redeem)"); - tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.pkey_refund) + "(htlc_pkey_refund)"); - } - + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); ++i; } return true; @@ -2912,11 +2917,16 @@ namespace currency { for (size_t n = 0; n < tx.vout.size(); ++n) { - if (tx.vout[n].target.type() == typeid(txout_to_key) || tx.vout[n].target.type() == typeid(txout_htlc)) - { - uint64_t amount = tx.vout[n].amount; - gindices[amount] += 1; - } + VARIANT_SWITCH_BEGIN(tx.vout[n]); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(txout_to_key) || o.target.type() == typeid(txout_htlc)) + { + uint64_t amount = o.amount; + gindices[amount] += 1; + } + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } } //--------------------------------------------------------------- diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index ee86735d..eb94538d 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -698,7 +698,13 @@ namespace currency uint64_t operator()(const t_input& i) const{return i.amount;} uint64_t operator()(const txin_gen& i) const {return 0;} }; - + //--------------------------------------------------------------- + const tx_out_bare& get_tx_out_bare_from_out_v(const tx_out_v& o) + { + //this function will throw if type is not matching + return boost::get(o); + } + //--------------------------------------------------------------- inline uint64_t get_amount_from_variant(const txin_v& v) { return boost::apply_visitor(input_amount_getter(), v); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 375e14de..159349b4 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -970,9 +970,14 @@ namespace currency uint64_t core_rpc_server::get_block_reward(const block& blk) { uint64_t reward = 0; - BOOST_FOREACH(const tx_out_bare& out, blk.miner_tx.vout) + BOOST_FOREACH(const auto& out, blk.miner_tx.vout) { - reward += out.amount; + VARIANT_SWITCH_BEGIN(out); + VARIANT_CASE(tx_out_bare, out) + reward += out.amount; + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } return reward; } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 57e8695a..0a1d7e70 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -379,8 +379,10 @@ namespace tools uint64_t m_spent_height; uint32_t m_flags; - uint64_t amount() const { return m_ptx_wallet_info->m_tx.vout[m_internal_output_index].amount; } - const currency::tx_out_bare& output() const { return m_ptx_wallet_info->m_tx.vout[m_internal_output_index]; } + // @#@ will throw if type is not tx_out_bare, TODO: change according to new model, + // need to replace all get_tx_out_bare_from_out_v() to proper code + uint64_t amount() const { return currency::get_tx_out_bare_from_out_v(m_ptx_wallet_info->m_tx.vout[m_internal_output_index]).amount; } + const currency::tx_out_bare& output() const { return currency::get_tx_out_bare_from_out_v(m_ptx_wallet_info->m_tx.vout[m_internal_output_index]); } uint8_t mix_attr() const { return output().target.type() == typeid(currency::txout_to_key) ? boost::get(output().target).mix_attr : UINT8_MAX; } crypto::hash tx_hash() const { return get_transaction_hash(m_ptx_wallet_info->m_tx); } bool is_spent() const { return m_flags & WALLET_TRANSFER_DETAIL_FLAG_SPENT; } diff --git a/src/wallet/wallet2_escrow.cpp b/src/wallet/wallet2_escrow.cpp index 4c5f1d65..bbf2b533 100644 --- a/src/wallet/wallet2_escrow.cpp +++ b/src/wallet/wallet2_escrow.cpp @@ -74,20 +74,28 @@ bool wallet2::validate_escrow_proposal(const wallet_public::wallet_transfer_info size_t ms_out_index = SIZE_MAX; for (size_t i = 0; i != prop.tx_template.vout.size(); ++i) { - if (prop.tx_template.vout[i].target.type() == typeid(txout_multisig)) + VARIANT_SWITCH_BEGIN(prop.tx_template.vout[i]); + VARIANT_CASE(tx_out_bare, o) { - LOC_CHK(ms_out_index == SIZE_MAX, "template has more than one multisig output"); - ms_out_index = i; + if (o.target.type() == typeid(txout_multisig)) + { + LOC_CHK(ms_out_index == SIZE_MAX, "template has more than one multisig output"); + ms_out_index = i; + } + else if (o.target.type() == typeid(txout_to_key)) + to_key_outputs_amount += o.amount; + else + LOC_CHK(false, "Invalid output type: " << o.target.type().name()); } - else if (prop.tx_template.vout[i].target.type() == typeid(txout_to_key)) - to_key_outputs_amount += prop.tx_template.vout[i].amount; - else - LOC_CHK(false, "Invalid output type: " << prop.tx_template.vout[i].target.type().name()); + VARIANT_CASE_TV(tx_out_zarcanum); + //@#@ + VARIANT_SWITCH_END(); } LOC_CHK(ms_out_index != SIZE_MAX, "template has no multisig outputs"); ms_id = currency::get_multisig_out_id(prop.tx_template, ms_out_index); - uint64_t ms_amount = prop.tx_template.vout[ms_out_index].amount; - const txout_multisig& ms = boost::get(prop.tx_template.vout[ms_out_index].target); + // @#@ using of get_tx_out_bare_from_out_v might be not safe, TODO: review this code + uint64_t ms_amount = currency::get_tx_out_bare_from_out_v(prop.tx_template.vout[ms_out_index]).amount; + const txout_multisig& ms = boost::get(currency::get_tx_out_bare_from_out_v(prop.tx_template.vout[ms_out_index]).target); LOC_CHK(ms.minimum_sigs == 2, "template has multisig output with wrong minimum_sigs==" << ms.minimum_sigs); LOC_CHK(ms.keys.size() == 2, "template has multisig output with wrong keys size: " << ms.keys.size()); @@ -138,7 +146,8 @@ bool wallet2::validate_escrow_release(const transaction& tx, bool release_type_n LOC_CHK(ms.multisig_out_id == ms_id, "multisig input references to wrong ms output: " << ms.multisig_out_id << ", expected: " << ms_id); LOC_CHK(source_ms_out.minimum_sigs == 2, "multisig output has wrong minimim_sigs: " <= min_ms_amount, "multisig input amount " << ms.amount << " is less than contract expected value: " << min_ms_amount << ", a_pledge=" << cpd.amount_a_pledge << ", b_pledge=" << cpd.amount_b_pledge << ", amount_to_pay=" << cpd.amount_to_pay); @@ -181,20 +190,27 @@ bool wallet2::validate_escrow_release(const transaction& tx, bool release_type_n uint64_t total_outputs_amount = 0, outputs_to_A_amount = 0, outputs_to_null_addr_amount = 0; for (size_t i = 0; i != tx.vout.size(); ++i) { - if (tx.vout[i].target.type() == typeid(txout_to_key)) + VARIANT_SWITCH_BEGIN(tx.vout[i]); + VARIANT_CASE(tx_out_bare, o); { - total_outputs_amount += tx.vout[i].amount; - const txout_to_key& otk = boost::get(tx.vout[i].target); - crypto::public_key ephemeral_pub_key = AUTO_VAL_INIT(ephemeral_pub_key); - r = crypto::derive_public_key(der, i, cpd.a_addr.spend_public_key, ephemeral_pub_key); - LOC_CHK(r, "derive_public_key failed for output #" << i); - if (otk.key == ephemeral_pub_key) - outputs_to_A_amount += tx.vout[i].amount; - else if (otk.key == null_pkey) - outputs_to_null_addr_amount += tx.vout[i].amount; + if (o.target.type() == typeid(txout_to_key)) + { + total_outputs_amount += o.amount; + const txout_to_key& otk = boost::get(o.target); + crypto::public_key ephemeral_pub_key = AUTO_VAL_INIT(ephemeral_pub_key); + r = crypto::derive_public_key(der, i, cpd.a_addr.spend_public_key, ephemeral_pub_key); + LOC_CHK(r, "derive_public_key failed for output #" << i); + if (otk.key == ephemeral_pub_key) + outputs_to_A_amount += o.amount; + else if (otk.key == null_pkey) + outputs_to_null_addr_amount += o.amount; + } + else + LOC_CHK(false, "Invalid output type: " << o.target.type().name()); } - else - LOC_CHK(false, "Invalid output type: " << tx.vout[i].target.type().name()); + VARIANT_CASE(tx_out_zarcanum, o) + LOC_CHK(false, "Invalid output type: " << o.type().name()); + VARIANT_SWITCH_END(); } if (release_type_normal) @@ -258,7 +274,7 @@ bool wallet2::validate_escrow_contract(const wallet_public::wallet_transfer_info LOC_CHK(n < wti.tx.vout.size(), "multisig output was not found"); ms_id = currency::get_multisig_out_id(wti.tx, n); LOC_CHK(ms_id != null_hash, "failed to obtain ms output id"); - const txout_multisig& ms = boost::get(wti.tx.vout[n].target); + const txout_multisig& ms = boost::get( boost::get(wti.tx.vout[n]).target); tx_service_attachment tsa = AUTO_VAL_INIT(tsa); r = bc_services::get_first_service_attachment_by_id(decrypted_items, BC_ESCROW_SERVICE_ID, BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_TEMPLATES, tsa); @@ -318,11 +334,11 @@ bool wallet2::validate_escrow_cancel_release(const currency::transaction& tx, co LOC_CHK(tx.vin.back().type() == typeid(txin_multisig), "input 0 is not txin_multisig"); const txin_multisig& ms = boost::get(tx.vin.back()); LOC_CHK(source_ms_out_index < source_tx.vout.size(), "internal invariant failed: source_ms_out_index is out of bounds: " << source_ms_out_index); - const txout_multisig& source_ms_out = boost::get(source_tx.vout[source_ms_out_index].target); + const txout_multisig& source_ms_out = boost::get(currency::get_tx_out_bare_from_out_v(source_tx.vout[source_ms_out_index]).target); LOC_CHK(ms.multisig_out_id == ms_id, "multisig input references to wrong ms output: " << ms.multisig_out_id << ", expected: " << ms_id); LOC_CHK(source_ms_out.minimum_sigs == 2, "source multisig output has wrong minimim_sigs: " <(tx.vout[i].target); - crypto::public_key ephemeral_pub_key = AUTO_VAL_INIT(ephemeral_pub_key); - r = crypto::derive_public_key(der, i, cpd.b_addr.spend_public_key, ephemeral_pub_key); - LOC_CHK(r, "derive_public_key failed for output #" << i); - if (otk.key == ephemeral_pub_key) - outputs_to_B_amount += tx.vout[i].amount; - } - else - LOC_CHK(false, "Invalid output type: " << tx.vout[i].target.type().name()); + VARIANT_SWITCH_BEGIN(tx.vout[i]); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(txout_to_key)) + { + total_outputs_amount += o.amount; + const txout_to_key& otk = boost::get(o.target); + crypto::public_key ephemeral_pub_key = AUTO_VAL_INIT(ephemeral_pub_key); + r = crypto::derive_public_key(der, i, cpd.b_addr.spend_public_key, ephemeral_pub_key); + LOC_CHK(r, "derive_public_key failed for output #" << i); + if (otk.key == ephemeral_pub_key) + outputs_to_B_amount += o.amount; + } + else + LOC_CHK(false, "Invalid output type: " << o.target.type().name()); + VARIANT_CASE_TV(tx_out_zarcanum) + LOC_CHK(false, "Invalid output type: " << tv.type().name()); + VARIANT_SWITCH_END(); } LOC_CHK(outputs_to_B_amount >= cpd.amount_b_pledge, "B-addressed outs total amount: " << print_money(outputs_to_B_amount) << " is less than b_pledge: " << print_money(cpd.amount_b_pledge));