From 636fb820ea3a80df8ff46d7c476b2cf8caae962b Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 25 Aug 2022 04:22:38 +0200 Subject: [PATCH] explicit tx fee for zarcanum txs: get_tx_fee, add_tx_fee_amount_to_extra, process_type_in_variant_container --- src/currency_core/currency_format_utils.cpp | 48 +++++++++++++++---- src/currency_core/currency_format_utils.h | 1 + .../currency_format_utils_abstract.h | 21 +++++++- 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 97c0412f..b22683b3 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -418,18 +418,34 @@ namespace currency fee = 0; if (is_coinbase(tx)) return true; - uint64_t amount_in = 0; - uint64_t amount_out = get_outs_money_amount(tx); - - BOOST_FOREACH(auto& in, tx.vin) + + if (tx.version <= TRANSACTION_VERSION_PRE_HF4) { - amount_in += get_amount_from_variant(in); + // all amounts are open: fee = sum(outputs) - sum(inputs) + + uint64_t amount_in = 0; + uint64_t amount_out = get_outs_money_amount(tx); + + for(auto& in : tx.vin) + amount_in += get_amount_from_variant(in); + + CHECK_AND_ASSERT_MES(amount_in >= amount_out, false, "transaction spends (" << print_money_brief(amount_in) << ") more than it has (" << print_money_brief(amount_out) << ")"); + fee = amount_in - amount_out; + return true; } + // tx.version > TRANSACTION_VERSION_PRE_HF4 + // all amounts are hidden with Pedersen commitments + // therefore fee should be explicitly stated in the extra + if (!process_type_in_variant_container(tx.extra, [&](const zarcanum_tx_data_v1& ztd) -> bool { + fee += ztd.fee; + return true; // continue + }, false)) + { + fee = 0; + return false; + } - - CHECK_AND_ASSERT_MES(amount_in >= amount_out, false, "transaction spend (" << amount_in << ") more than it has (" << amount_out << ")"); - fee = amount_in - amount_out; return true; } //--------------------------------------------------------------- @@ -555,6 +571,22 @@ namespace currency return true; } //--------------------------------------------------------------- + // puts explicit fee amount to tx extra, should be used only for tx.verson > TRANSACTION_VERSION_PRE_HF4 + bool add_tx_fee_amount_to_extra(transaction& tx, uint64_t fee, bool make_sure_its_unique /* = true */) + { + if (make_sure_its_unique) + { + if (count_type_in_variant_container(tx.extra) != 0) + return false; + } + + zarcanum_tx_data_v1 ztd = AUTO_VAL_INIT(ztd); + ztd.fee = fee; + + tx.extra.push_back(ztd); + return true; + } + //--------------------------------------------------------------- //--------------------------------------------------------------- struct multisig_id_generator diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index d60f68d2..7084be7e 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -305,6 +305,7 @@ namespace currency bool parse_and_validate_tx_extra(const transaction& tx, crypto::public_key& tx_pub_key); crypto::public_key get_tx_pub_key_from_extra(const transaction& tx); bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key); + bool add_tx_fee_amount_to_extra(transaction& tx, uint64_t fee, bool make_sure_its_unique = true); bool add_tx_extra_userdata(transaction& tx, const blobdata& extra_nonce); crypto::hash get_multisig_out_id(const transaction& tx, size_t n); diff --git a/src/currency_core/currency_format_utils_abstract.h b/src/currency_core/currency_format_utils_abstract.h index 5f3c6ed4..adddd8e5 100644 --- a/src/currency_core/currency_format_utils_abstract.h +++ b/src/currency_core/currency_format_utils_abstract.h @@ -94,7 +94,7 @@ namespace currency } //--------------------------------------------------------------- template - bool get_type_in_variant_container(const variant_t_container& av, specific_type_t& a) + bool get_type_in_variant_container(variant_t_container& av, specific_type_t& a) { for (auto& ai : av) { @@ -107,6 +107,25 @@ namespace currency return false; } //--------------------------------------------------------------- + // if cb returns true, it means "continue", false -- means "stop" + template + bool process_type_in_variant_container(variant_container_t& av, callback_t& cb, bool return_value_if_none_found = true) + { + bool found = false; + for (auto& ai : av) + { + if (ai.type() == typeid(specific_type_t)) + { + found = true; + if (!cb(boost::get(ai))) + return false; + } + } + if (found) + return true; + return return_value_if_none_found; + } + //--------------------------------------------------------------- // callback should return true to continue iterating through the container template bool handle_2_alternative_types_in_variant_container(const container_t& container, callback_t cb)