1
0
Fork 0
forked from lthn/blockchain

explicit tx fee for zarcanum txs: get_tx_fee, add_tx_fee_amount_to_extra, process_type_in_variant_container

This commit is contained in:
sowle 2022-08-25 04:22:38 +02:00
parent 458f347e1e
commit 636fb820ea
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
3 changed files with 61 additions and 9 deletions

View file

@ -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<zarcanum_tx_data_v1>(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<zarcanum_tx_data_v1>(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

View file

@ -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);

View file

@ -94,7 +94,7 @@ namespace currency
}
//---------------------------------------------------------------
template<typename specific_type_t, typename variant_t_container>
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<typename specific_type_t, typename variant_container_t, typename callback_t>
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<specific_type_t>(ai)))
return false;
}
}
if (found)
return true;
return return_value_if_none_found;
}
//---------------------------------------------------------------
// callback should return true to continue iterating through the container
template <typename A, typename B, typename container_t, typename callback_t>
bool handle_2_alternative_types_in_variant_container(const container_t& container, callback_t cb)