1
0
Fork 0
forked from lthn/blockchain

blockchain_storage.cpp compilation fixed

This commit is contained in:
cryptozoidberg 2022-05-24 00:46:44 +02:00
parent 7070cecaf2
commit 7162a23dd3
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
5 changed files with 141 additions and 131 deletions

View file

@ -4,7 +4,8 @@
#pragma once
#define VARIANT_SWITCH_BEGIN(v_type_obj) {decltype(v_type_obj)& local_reference_eokcmeokmeokcm = v_type_obj; if(false) {;
#define VARIANT_SWITCH_BEGIN(v_type_obj) {auto & local_reference_eokcmeokmeokcm = v_type_obj; if(false) {;
#define VARIANT_CASE_CONST(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { const v_type& typed_name = boost::get<v_type>(local_reference_eokcmeokmeokcm);
#define VARIANT_CASE(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { v_type& typed_name = boost::get<v_type>(local_reference_eokcmeokmeokcm);
#define VARIANT_CASE_TV(v_type) VARIANT_CASE(v_type, tv)
#define VARIANT_CASE_OTHER() } else {
@ -26,9 +27,10 @@ usage:
VARIANT_SWITCH_END();
VARIANT_SWITCH_BEGIN(o);
VARIANT_CASE(txout_to_key, o);
VARIANT_CASE_TV(txout_multisig);
VARIANT_CASE_TV(txout_htlc);
VARIANT_CASE_CONST(txout_to_key, o);
VARIANT_CASE_CONST(txout_multisig, ms);
VARIANT_CASE_CONST(txout_htlc, htlc);
VARIANT_CASE_THROW_ON_OTHER();
VARIANT_SWITCH_END();

View file

@ -38,6 +38,7 @@
#include "crypto/RIPEMD160_helper.h"
#include "crypto/bitcoin/sha256_helper.h"
#undef LOG_DEFAULT_CHANNEL
#define LOG_DEFAULT_CHANNEL "core"
ENABLE_CHANNEL_BY_DEFAULT("core");
@ -610,13 +611,13 @@ bool blockchain_storage::prune_ring_signatures_and_attachments(uint64_t height,
transaction_chain_entry lolcal_chain_entry = *it;
VARIANT_SWITCH_BEGIN(lolcal_chain_entry.tx.signature);
VARIANT_CASE(void_sig, v);
VARIANT_CASE_CONST(void_sig, v);
VARIANT_CASE(NLSAG_sig, signatures)
{
signatures_pruned += signatures.s.size();
signatures.s.clear();
}
VARIANT_CASE(zarcanum_sig, s);
VARIANT_CASE_CONST(zarcanum_sig, s);
//@#@
VARIANT_SWITCH_END();
@ -2488,7 +2489,7 @@ bool blockchain_storage::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPU
const transaction& tx = tx_ptr->tx;
VARIANT_SWITCH_BEGIN(tx.vout[out_ptr->out_no]);
VARIANT_CASE(tx_out_bare, o)
VARIANT_CASE_CONST(tx_out_bare, o)
{
if (o.target.type() == typeid(txout_htlc))
{
@ -2527,7 +2528,7 @@ bool blockchain_storage::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPU
oen.global_amount_index = i;
oen.out_key = otk.key;
}
VARIANT_CASE_TV(tx_out_zarcanum)
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
//@#@
VARIANT_SWITCH_END();
@ -3034,10 +3035,10 @@ void blockchain_storage::print_blockchain_outs_stats() const
if (!spent)// && p_tx->tx.vout[output_entry.out_no].target.type() == typeid(txout_to_key))
{
VARIANT_SWITCH_BEGIN(p_tx->tx.vout[output_entry.out_no]);
VARIANT_CASE(tx_out_bare, o)
VARIANT_CASE_CONST(tx_out_bare, o)
if (boost::get<txout_to_key>(o.target).mix_attr != CURRENCY_TO_KEY_OUT_FORCED_NO_MIX)
++stat.mixable;
VARIANT_CASE_TV(tx_out_zarcanum)
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
//@#@
VARIANT_SWITCH_END();
}
@ -3354,7 +3355,7 @@ bool blockchain_storage::push_transaction_to_global_outs_index(const transaction
BOOST_FOREACH(const auto& otv, tx.vout)
{
VARIANT_SWITCH_BEGIN(otv);
VARIANT_CASE(tx_out_bare, ot)
VARIANT_CASE_CONST(tx_out_bare, ot)
if (ot.target.type() == typeid(txout_to_key) || ot.target.type() == typeid(txout_htlc))
{
m_db_outputs.push_back_item(ot.amount, global_output_entry::construct(tx_id, i));
@ -3374,7 +3375,7 @@ bool blockchain_storage::push_transaction_to_global_outs_index(const transaction
m_db_multisig_outs.set(multisig_out_id, ms_output_entry::construct(tx_id, i));
global_indexes.push_back(0); // just stub to make other code easier
}
VARIANT_CASE_TV(tx_out_zarcanum)
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
//@#@
VARIANT_CASE_THROW_ON_OTHER();
VARIANT_SWITCH_END();
@ -3406,7 +3407,7 @@ bool blockchain_storage::get_outs(uint64_t amount, std::list<crypto::public_key>
CHECK_AND_ASSERT_MES(tx_ptr->tx.vout.size() > out_entry_ptr->out_no, false, "transactions outs global index consistency broken: index in tx_outx == " << out_entry_ptr->out_no << " is greather than tx.vout size == " << tx_ptr->tx.vout.size() << ", for amount: " << amount << ", gindex: " << i);
//CHECK_AND_ASSERT_MES(tx_ptr->tx.vout[out_entry_ptr->out_no].target.type() == typeid(txout_to_key), false, "transactions outs global index consistency broken: out #" << out_entry_ptr->out_no << " in tx " << out_entry_ptr->tx_id << " has wrong type, for amount: " << amount << ", gindex: " << i);
VARIANT_SWITCH_BEGIN(tx_ptr->tx.vout[out_entry_ptr->out_no]);
VARIANT_CASE(tx_out_bare, o)
VARIANT_CASE_CONST(tx_out_bare, o)
if (o.target.type() == typeid(txout_to_key))
{
pkeys.push_back(boost::get<txout_to_key>(o.target).key);
@ -3415,7 +3416,7 @@ bool blockchain_storage::get_outs(uint64_t amount, std::list<crypto::public_key>
{
pkeys.push_back(boost::get<txout_htlc>(o.target).pkey_redeem);
}
VARIANT_CASE_TV(tx_out_zarcanum)
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
//@#@
VARIANT_CASE_THROW_ON_OTHER();
VARIANT_SWITCH_END();
@ -3431,7 +3432,7 @@ bool blockchain_storage::pop_transaction_from_global_index(const transaction& tx
BOOST_REVERSE_FOREACH(const auto& otv, tx.vout)
{
VARIANT_SWITCH_BEGIN(otv);
VARIANT_CASE(tx_out_bare, ot)
VARIANT_CASE_CONST(tx_out_bare, ot)
if (ot.target.type() == typeid(txout_to_key) || ot.target.type() == typeid(txout_htlc))
{
uint64_t sz = m_db_outputs.get_item_size(ot.amount);
@ -3450,7 +3451,7 @@ bool blockchain_storage::pop_transaction_from_global_index(const transaction& tx
bool res = m_db_multisig_outs.erase_validate(multisig_out_id);
CHECK_AND_ASSERT_MES(res, false, "Internal error: multisig out not found, multisig_out_id " << multisig_out_id << "in multisig outs index");
}
VARIANT_CASE_TV(tx_out_zarcanum)
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
//@#@
VARIANT_CASE_THROW_ON_OTHER();
VARIANT_SWITCH_END();
@ -4188,12 +4189,12 @@ bool blockchain_storage::print_tx_outputs_lookup(const crypto::hash& tx_id)const
for (uint64_t i = 0; i!= tx_ptr->tx.vout.size();i++)
{
VARIANT_SWITCH_BEGIN(tx_ptr->tx.vout[i]);
VARIANT_CASE(tx_out_bare, o)
VARIANT_CASE_CONST(tx_out_bare, o)
strm_tx << "[" << i << "]: " << print_money(o.amount) << ENDL;
if (o.target.type() != typeid(currency::txout_to_key))
continue;
usage_stat[o.amount][tx_ptr->m_global_output_indexes[i]];
VARIANT_CASE_TV(tx_out_zarcanum)
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
//@#@
VARIANT_SWITCH_END();
}
@ -4296,22 +4297,21 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
if (!m_is_in_checkpoint_zone)
{
VARIANT_SWITCH_BEGIN(tx.signature);
VARIANT_CASE(void_sig, v);
VARIANT_CASE(NLSAG_sig, signatures);
VARIANT_CASE_CONST(void_sig, v);
VARIANT_CASE_CONST(NLSAG_sig, signatures);
{
CHECK_AND_ASSERT_MES(sig_index < signatures.s.size(), false, "Wrong transaction: missing signature entry for input #" << sig_index << " tx: " << tx_prefix_hash);
psig = &signatures.s[sig_index];
}
VARIANT_CASE(zarcanum_sig, s);
VARIANT_CASE_CONST(zarcanum_sig, s);
//@#@
VARIANT_SWITCH_END();
}
if (txin.type() == typeid(txin_to_key))
VARIANT_SWITCH_BEGIN(txin);
VARIANT_CASE_CONST(txin_to_key, in_to_key)
{
const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
CHECK_AND_ASSERT_MES(in_to_key.key_offsets.size(), false, "Empty in_to_key.key_offsets for input #" << sig_index << " tx: " << tx_prefix_hash);
TIME_MEASURE_START_PD(tx_check_inputs_loop_kimage_check);
if (have_tx_keyimg_as_spent(in_to_key.k_image))
@ -4321,22 +4321,21 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
}
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_kimage_check);
uint64_t max_unlock_time = 0;
if (!check_tx_input(tx, sig_index, in_to_key, tx_prefix_hash, *psig, max_used_block_height, max_unlock_time))
if (!check_tx_input(tx, sig_index, in_to_key, tx_prefix_hash, max_used_block_height, max_unlock_time))
{
LOG_ERROR("Failed to validate input #" << sig_index << " tx: " << tx_prefix_hash);
return false;
}
}
else if (txin.type() == typeid(txin_multisig))
VARIANT_CASE_CONST(txin_multisig, in_ms)
{
const txin_multisig& in_ms = boost::get<txin_multisig>(txin);
if (!check_tx_input(tx, sig_index, in_ms, tx_prefix_hash, *psig, max_used_block_height))
if (!check_tx_input(tx, sig_index, in_ms, tx_prefix_hash, max_used_block_height))
{
LOG_ERROR("Failed to validate multisig input #" << sig_index << " (ms out id: " << in_ms.multisig_out_id << ") in tx: " << tx_prefix_hash);
return false;
}
}
else if (txin.type() == typeid(txin_htlc))
VARIANT_CASE_CONST(txin_htlc, in_htlc)
{
if (!is_after_hardfork_3_zone())
{
@ -4344,7 +4343,6 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
return false;
}
const txin_htlc& in_htlc = boost::get<txin_htlc>(txin);
CHECK_AND_ASSERT_MES(in_htlc.key_offsets.size(), false, "Empty in_to_key.key_offsets for input #" << sig_index << " tx: " << tx_prefix_hash);
TIME_MEASURE_START_PD(tx_check_inputs_loop_kimage_check);
if (have_tx_keyimg_as_spent(in_htlc.k_image))
@ -4353,12 +4351,15 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
return false;
}
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_kimage_check);
if (!check_tx_input(tx, sig_index, in_htlc, tx_prefix_hash, *psig, max_used_block_height))
if (!check_tx_input(tx, sig_index, in_htlc, tx_prefix_hash, max_used_block_height))
{
LOG_ERROR("Failed to validate multisig input #" << sig_index << " (ms out id: " << obj_to_json_str(in_htlc) << ") in tx: " << tx_prefix_hash);
return false;
}
}
VARIANT_CASE_THROW_ON_OTHER();
VARIANT_SWITCH_END();
sig_index++;
}
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop);
@ -4367,11 +4368,11 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
if (!m_is_in_checkpoint_zone)
{
VARIANT_SWITCH_BEGIN(tx.signature);
VARIANT_CASE(NLSAG_sig, signatures)
VARIANT_CASE_CONST(NLSAG_sig, signatures)
{
CHECK_AND_ASSERT_MES(signatures.size() == sig_index, false, "tx signatures count differs from inputs");
CHECK_AND_ASSERT_MES(signatures.s.size() == sig_index, false, "tx signatures count differs from inputs");
}
VARIANT_CASE(zarcanum_sig, s);
VARIANT_CASE_CONST(zarcanum_sig, s);
//@#@
VARIANT_CASE_THROW_ON_OTHER();
VARIANT_SWITCH_END();
@ -4390,7 +4391,7 @@ bool blockchain_storage::is_tx_spendtime_unlocked(uint64_t unlock_time) const
return currency::is_tx_spendtime_unlocked(unlock_time, get_current_blockchain_size(), m_core_runtime_config.get_core_time());
}
//------------------------------------------------------------------
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const
{
CRITICAL_REGION_LOCAL(m_read_lock);
@ -4410,7 +4411,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
for (auto& ptr : output_keys)
output_keys_ptrs.push_back(&ptr);
return check_input_signature(tx, in_index, txin, tx_prefix_hash, sig, output_keys_ptrs);
return check_input_signature(tx, in_index, txin, tx_prefix_hash, output_keys_ptrs);
}
//----------------------------------------------------------------
struct outputs_visitor
@ -4497,7 +4498,7 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction
//------------------------------------------------------------------
// Note: this function can be used for checking to_key inputs against either main chain or alt chain, that's why it has output_keys_ptrs parameter
// Doesn't check spent flags, the caller must check it.
bool blockchain_storage::check_input_signature(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, const std::vector<const crypto::public_key*>& output_keys_ptrs) const
bool blockchain_storage::check_input_signature(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<const crypto::public_key*>& output_keys_ptrs) const
{
if (txin.key_offsets.size() != output_keys_ptrs.size())
{
@ -4505,7 +4506,7 @@ bool blockchain_storage::check_input_signature(const transaction& tx, size_t in_
return false;
}
return check_input_signature(tx, in_index, /*txin.key_offsets,*/ txin.amount, txin.k_image, txin.etc_details, tx_prefix_hash, sig, output_keys_ptrs);
return check_input_signature(tx, in_index, /*txin.key_offsets,*/ txin.amount, txin.k_image, txin.etc_details, tx_prefix_hash, output_keys_ptrs);
}
//------------------------------------------------------------------
bool blockchain_storage::check_input_signature(const transaction& tx,
@ -4514,7 +4515,6 @@ bool blockchain_storage::check_input_signature(const transaction& tx,
const crypto::key_image& in_k_image,
const std::vector<txin_etc_details_v>& in_etc_details,
const crypto::hash& tx_prefix_hash,
const std::vector<crypto::signature>& sig,
const std::vector<const crypto::public_key*>& output_keys_ptrs) const
{
CRITICAL_REGION_LOCAL(m_read_lock);
@ -4524,6 +4524,10 @@ bool blockchain_storage::check_input_signature(const transaction& tx,
if(m_is_in_checkpoint_zone)
return true;
CHECK_AND_ASSERT_MES(tx.signature.type() == typeid(NLSAG_sig), false, "Unexpected type of sig in check_input_signature: " << tx.signature.type().name());
auto s = boost::get<NLSAG_sig>(tx.signature).s;
CHECK_AND_ASSERT_MES(s.size() > in_index, false, "Failed to check s.size(){" << s.size() << "} > in_index {" << in_index << "}" );
const std::vector<crypto::signature>& sig = s[in_index];
if (get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE)
{
// check attachments, mentioned directly in this input
@ -4572,7 +4576,7 @@ bool blockchain_storage::check_input_signature(const transaction& tx,
//------------------------------------------------------------------
// Note: this function doesn't check spent flags by design (to be able to use either for main chain and alt chains).
// The caller MUST check spent flags.
bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, const transaction& source_tx, size_t out_n) const
bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const transaction& source_tx, size_t out_n) const
{
#define LOC_CHK(cond, msg) CHECK_AND_ASSERT_MES(cond, false, "ms input check failed: ms_id: " << txin.multisig_out_id << ", input #" << in_index << " in tx " << tx_prefix_hash << ", refers to ms output #" << out_n << " in source tx " << get_transaction_hash(source_tx) << ENDL << msg)
CRITICAL_REGION_LOCAL(m_read_lock);
@ -4581,7 +4585,7 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index,
LOC_CHK(is_tx_spendtime_unlocked(unlock_time), "Source transaction is LOCKED! unlock_time: " << unlock_time << ", now is " << m_core_runtime_config.get_core_time() << ", blockchain size is " << get_current_blockchain_size());
LOC_CHK(source_tx.vout.size() > out_n, "internal error: out_n==" << out_n << " is out-of-bounds of source_tx.vout, size=" << source_tx.vout.size());
LOC_CHK(source_tx.vout[out_n].type() !== typeid(tx_out_bare), "internal error: out_n==" << out_n << " has unexpected type: " << source_tx.vout[out_n].type().name());
LOC_CHK(source_tx.vout[out_n].type() != typeid(tx_out_bare), "internal error: out_n==" << out_n << " has unexpected type: " << source_tx.vout[out_n].type().name());
const tx_out_bare& source_tx_out = boost::get<tx_out_bare>(source_tx.vout[out_n]);
const txout_multisig& source_ms_out_target = boost::get<txout_multisig>(source_tx_out.target);
@ -4610,16 +4614,15 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index,
// make sure normal tx does not have extra_attachment_info in etc_details
LOC_CHK(!have_type_in_variant_container<extra_attachment_info>(txin.etc_details), "Incorrect using of extra_attachment_info in etc_details in input #" << in_index << " for tx " << tx_prefix_hash);
}
bool need_to_check_extra_sign = false;
VARIANT_SWITCH_BEGIN(tx.signature);
VARIANT_CASE(void_sig, v);
VARIANT_CASE(NLSAG_sig, signatures)
VARIANT_CASE_CONST(void_sig, v);
VARIANT_CASE_CONST(NLSAG_sig, signatures)
{
LOC_CHK(signatures.size() > in_index, "ms input index is out of signatures container bounds, signatures.size() = " << signatures.size());
LOC_CHK(signatures.s.size() > in_index, "ms input index is out of signatures container bounds, signatures.size() = " << signatures.s.size());
const std::vector<crypto::signature>& input_signatures = signatures.s[in_index];
size_t expected_signatures_count = txin.sigs_count;
bool need_to_check_extra_sign = false;
if (get_tx_flags(tx)&TX_FLAG_SIGNATURE_MODE_SEPARATE && in_index == tx.vin.size() - 1) // last input in TX_FLAG_SIGNATURE_MODE_SEPARATE must contain one more signature to ensure that tx was completed by an authorized subject
{
expected_signatures_count++;
@ -4652,21 +4655,21 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index,
}
}
}
VARIANT_CASE(zarcanum_sig, s);
VARIANT_CASE_CONST(zarcanum_sig, s);
//@#@
VARIANT_SWITCH_END();
if (need_to_check_extra_sign)
{
VARIANT_SWITCH_BEGIN(tx.signature);
VARIANT_CASE(void_sig, v);
VARIANT_CASE(NLSAG_sig, signatures)
VARIANT_CASE_CONST(void_sig, v);
VARIANT_CASE_CONST(NLSAG_sig, signatures)
{
//here we check extra signature to validate that transaction was finilized by authorized subject
bool r = crypto::check_signature(tx_prefix_hash, get_tx_pub_key_from_extra(tx), signatures.s[in_index].back());
LOC_CHK(r, "failed to check extra signature for last out with TX_FLAG_SIGNATURE_MODE_SEPARATE");
}
VARIANT_CASE(zarcanum_sig, s);
VARIANT_CASE_CONST(zarcanum_sig, s);
//@#@
VARIANT_SWITCH_END();
@ -4677,7 +4680,7 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index,
}
//------------------------------------------------------------------
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height) const
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height) const
{
CRITICAL_REGION_LOCAL(m_read_lock);
@ -4694,12 +4697,12 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
auto source_tx_ptr = m_db_transactions.find(source_tx_id);
LOC_CHK(source_tx_ptr, "Can't find source transaction");
LOC_CHK(source_tx_ptr->tx.vout.size() > n, "ms output index is incorrect, source tx's vout size is " << source_tx_ptr->tx.vout.size());
LOC_CHK(source_tx_ptr->tx.vout[n].type() != = typeid(tx_out_bare), "internal error: out_n==" << n << " has unexpected type: " << source_tx_ptr->tx.vout[n].type().name());
LOC_CHK(source_tx_ptr->tx.vout[n].type() != typeid(tx_out_bare), "internal error: out_n==" << n << " has unexpected type: " << source_tx_ptr->tx.vout[n].type().name());
LOC_CHK(boost::get<tx_out_bare>(source_tx_ptr->tx.vout[n]).target.type() == typeid(txout_multisig), "ms output has wrong type, txout_multisig expected");
LOC_CHK(source_tx_ptr->m_spent_flags.size() > n, "Internal error, m_spent_flags size (" << source_tx_ptr->m_spent_flags.size() << ") less then expected, n: " << n);
LOC_CHK(source_tx_ptr->m_spent_flags[n] == false, "Internal error, ms output is already spent"); // should never happen as multisig_ptr->spent_height is checked above
if (!check_ms_input(tx, in_index, txin, tx_prefix_hash, sig, source_tx_ptr->tx, n))
if (!check_ms_input(tx, in_index, txin, tx_prefix_hash, source_tx_ptr->tx, n))
return false;
max_related_block_height = source_tx_ptr->m_keeper_block_height;
@ -4708,7 +4711,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
#undef LOC_CHK
}
//------------------------------------------------------------------
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height)const
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const
{
CRITICAL_REGION_LOCAL(m_read_lock);
@ -4753,8 +4756,19 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
output_keys_ptrs.push_back(&ptr);
CHECK_AND_ASSERT_THROW_MES(output_keys_ptrs.size() == 1, "Internal error: output_keys_ptrs.size() is not equal 1 for HTLC");
return check_input_signature(tx, in_index, txin.amount, txin.k_image, txin.etc_details, tx_prefix_hash, sig, output_keys_ptrs);
VARIANT_SWITCH_BEGIN(tx.signature);
VARIANT_CASE_CONST(NLSAG_sig, signatures);
{
CHECK_AND_ASSERT_MES(signatures.s.size() > in_index, false, "Unexpeted number of singatures in NLSAG_sig: " << signatures.s.size() << ", expected at least: " << in_index);
return check_input_signature(tx, in_index, txin.amount, txin.k_image, txin.etc_details, tx_prefix_hash, output_keys_ptrs);
}
VARIANT_CASE_CONST(zarcanum_sig, s);
//@#@ TODO
return false;
VARIANT_CASE_THROW_ON_OTHER();
VARIANT_SWITCH_END();
return false;
}
//------------------------------------------------------------------
uint64_t blockchain_storage::get_adjusted_time() const
@ -5054,13 +5068,13 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti
for (const auto out : tx.vout)
{
VARIANT_SWITCH_BEGIN(out);
VARIANT_CASE(tx_out_bare, o)
VARIANT_CASE_CONST(tx_out_bare, o)
if (o.target.type() == typeid(txout_htlc))
{
if (!var_is_after_hardfork_3_zone)
return false;
}
VARIANT_CASE_TV(tx_out_zarcanum)
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
if (!var_is_after_hardfork_4_zone)
return false;
VARIANT_SWITCH_END();
@ -5115,9 +5129,9 @@ bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transactio
if (unlock_value >= source_max_unlock_time)
{
VARIANT_SWITCH_BEGIN(miner_tx.vout[i]);
VARIANT_CASE(tx_out_bare, o)
VARIANT_CASE_CONST(tx_out_bare, o)
amount_of_coins_in_unlock_in_range += o.amount;
VARIANT_CASE_TV(tx_out_zarcanum)
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
//@#@
VARIANT_SWITCH_END();
}
@ -5205,37 +5219,30 @@ bool blockchain_storage::validate_pos_block(const block& b,
uint64_t max_related_block_height = 0;
const txin_to_key& coinstake_in = boost::get<txin_to_key>(b.miner_tx.vin[1]);
VARIANT_SWITCH_BEGIN(b.miner_tx.signature);
VARIANT_CASE(void_sig, v);
VARIANT_CASE(NLSAG_sig, signatures)
if (!for_altchain)
{
CHECK_AND_ASSERT_MES(signatures.s.size() == 1, false, "PoS block's miner_tx has incorrect signatures size = " << signatures.s.size() << ", block_id = " << get_block_hash(b));
if (!for_altchain)
{
// Do coinstake input validation for main chain only.
// Txs in alternative PoS blocks (including miner_tx) are validated by validate_alt_block_txs()
uint64_t source_max_unlock_time_for_pos_coinbase = 0;
r = check_tx_input(b.miner_tx, 1, coinstake_in, id, signatures.s[0], max_related_block_height, source_max_unlock_time_for_pos_coinbase);
CHECK_AND_ASSERT_MES(r, false, "Failed to validate coinstake input in miner tx, block_id = " << get_block_hash(b));
// Do coinstake input validation for main chain only.
// Txs in alternative PoS blocks (including miner_tx) are validated by validate_alt_block_txs()
uint64_t source_max_unlock_time_for_pos_coinbase = 0;
r = check_tx_input(b.miner_tx, 1, coinstake_in, id, max_related_block_height, source_max_unlock_time_for_pos_coinbase);
CHECK_AND_ASSERT_MES(r, false, "Failed to validate coinstake input in miner tx, block_id = " << get_block_hash(b));
if (get_block_height(b) > m_core_runtime_config.hard_forks.hard_fork_01_starts_after_height)
{
uint64_t last_pow_h = get_last_x_block_height(false);
CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_h, false, "Failed to validate coinbase in PoS block, condition failed: max_related_block_height(" << max_related_block_height << ") <= last_pow_h(" << last_pow_h << ")");
//let's check that coinbase amount and unlock time
r = validate_pos_coinbase_outs_unlock_time(b.miner_tx, coinstake_in.amount, source_max_unlock_time_for_pos_coinbase);
CHECK_AND_ASSERT_MES(r, false, "Failed to validate_pos_coinbase_outs_unlock_time() in miner tx, block_id = " << get_block_hash(b)
<< "source_max_unlock_time_for_pos_coinbase=" << source_max_unlock_time_for_pos_coinbase);
}
else
{
CHECK_AND_ASSERT_MES(is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase), false, "Failed to validate coinbase in PoS block, condition failed: is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase)(" << source_max_unlock_time_for_pos_coinbase << ")");
}
if (get_block_height(b) > m_core_runtime_config.hard_forks.hard_fork_01_starts_after_height)
{
uint64_t last_pow_h = get_last_x_block_height(false);
CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_h, false, "Failed to validate coinbase in PoS block, condition failed: max_related_block_height(" << max_related_block_height << ") <= last_pow_h(" << last_pow_h << ")");
//let's check that coinbase amount and unlock time
r = validate_pos_coinbase_outs_unlock_time(b.miner_tx, coinstake_in.amount, source_max_unlock_time_for_pos_coinbase);
CHECK_AND_ASSERT_MES(r, false, "Failed to validate_pos_coinbase_outs_unlock_time() in miner tx, block_id = " << get_block_hash(b)
<< "source_max_unlock_time_for_pos_coinbase=" << source_max_unlock_time_for_pos_coinbase);
}
else
{
CHECK_AND_ASSERT_MES(is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase), false, "Failed to validate coinbase in PoS block, condition failed: is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase)(" << source_max_unlock_time_for_pos_coinbase << ")");
}
}
VARIANT_CASE(zarcanum_sig, s);
//@#@
VARIANT_SWITCH_END();
uint64_t block_height = for_altchain ? split_height + alt_chain.size() : m_db_blocks.size();
uint64_t coinstake_age = block_height - max_related_block_height - 1;
@ -5540,7 +5547,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
VARIANT_SWITCH_BEGIN(tx.signature);
VARIANT_CASE(NLSAG_sig, signatures)
signatures.s.clear();
VARIANT_CASE(zarcanum_sig, s);
VARIANT_CASE_CONST(zarcanum_sig, s);
//@#@
VARIANT_SWITCH_END();
@ -6360,7 +6367,6 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
const crypto::hash& bl_id,
const crypto::hash& input_tx_hash,
size_t input_index,
const signature_v& input_sigs,
uint64_t split_height,
const alt_chain_type& alt_chain,
const std::unordered_set<crypto::hash>& alt_chain_block_ids,
@ -6569,7 +6575,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
CHECK_AND_ASSERT_MES(it->second.first.vout.size() > out_n, false, "Internal error: out_n(" << out_n << ") >= it->second.vout.size()(" << it->second.first.vout.size() << ")");
VARIANT_SWITCH_BEGIN(it->second.first.vout[out_n]);
VARIANT_CASE(tx_out_bare, o)
VARIANT_CASE_CONST(tx_out_bare, o)
{
/*
here we do validation against compatibility of input and output type
@ -6606,7 +6612,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
ASSERT_MES_AND_THROW("Unexpected out type for tx_in in altblock: " << out_target_v.type().name());
}
}
VARIANT_CASE_TV(tx_out_zarcanum)
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
//@#@
VARIANT_SWITCH_END();
}
@ -6617,7 +6623,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
CHECK_AND_ASSERT_MES(p != nullptr && out_n < p->tx.vout.size(), false, "can't find output #" << out_n << " for tx " << tx_id << " referred by offset #" << pk_n);
VARIANT_SWITCH_BEGIN(p->tx.vout[out_n]);
VARIANT_CASE(tx_out_bare, o)
VARIANT_CASE_CONST(tx_out_bare, o)
{
auto &t = o.target;
@ -6666,22 +6672,16 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
//CHECK_AND_ASSERT_MES(pk != null_pkey, false, "Can't determine output public key for offset " << pk_n << " in related tx: " << tx_id << ", out_n = " << out_n);
pub_key_pointers.push_back(&pk);
}
VARIANT_CASE_TV(tx_out_zarcanum)
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
//@#@
VARIANT_SWITCH_END();
}
VARIANT_SWITCH_BEGIN(input_sigs);
VARIANT_CASE(void_sig, v);
VARIANT_CASE(NLSAG_sig, signatures)
{
// do input checks (attachment_info, ring signature and extra signature, etc.)
r = check_input_signature(input_tx, input_index, input_to_key, input_tx_hash, signatures.s[input_index], pub_key_pointers);
CHECK_AND_ASSERT_MES(r, false, "to_key input validation failed");
}
VARIANT_CASE(zarcanum_sig, s);
//@#@
VARIANT_SWITCH_END();
// do input checks (attachment_info, ring signature and extra signature, etc.)
r = check_input_signature(input_tx, input_index, input_to_key, input_tx_hash, pub_key_pointers);
CHECK_AND_ASSERT_MES(r, false, "to_key input validation failed");
// TODO: consider checking input_tx for valid extra attachment info as it's checked in check_tx_inputs()
return true;
@ -6788,7 +6788,7 @@ bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx
&& input_tx.signature.type() == typeid(NLSAG_sig), false, "invalid ms input index: " << input_index << " or type");
const txin_multisig& input = boost::get<txin_multisig>(input_tx.vin[input_index]);
const std::vector<crypto::signature>& input_sigs = boost::get<NLSAG_sig>(input_tx.signature).s[input_index];
//const std::vector<crypto::signature>& input_sigs = boost::get<NLSAG_sig>(input_tx.signature).s[input_index];
// check corresponding ms out in the main chain
auto p = m_db_multisig_outs.get(input.multisig_out_id);
if (p != nullptr)
@ -6803,7 +6803,7 @@ bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx
if (p_source_tx->m_keeper_block_height < split_height)
{
// cases g1, g2
return check_ms_input(input_tx, input_index, input, input_tx_hash, input_sigs, p_source_tx->tx, p->out_no);
return check_ms_input(input_tx, input_index, input, input_tx_hash, p_source_tx->tx, p->out_no);
}
// p_source_tx is above split_height in main chain B, so it can't be a source for this input
@ -6838,7 +6838,7 @@ bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx
for (size_t out_n = 0; out_n < tx.vout.size(); ++out_n)
{
VARIANT_SWITCH_BEGIN(tx.vout[out_n]);
VARIANT_CASE(tx_out_bare, o)
VARIANT_CASE_CONST(tx_out_bare, o)
const tx_out_bare& out = o;
if (out.target.type() == typeid(txout_multisig))
{
@ -6847,10 +6847,10 @@ bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx
{
// cases g3, g4, g5
output_found = true;
return check_ms_input(input_tx, input_index, input, input_tx_hash, input_sigs, tx, out_n);
return check_ms_input(input_tx, input_index, input, input_tx_hash, tx, out_n);
}
}
VARIANT_CASE_TV(tx_out_zarcanum)
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
//@#@
VARIANT_SWITCH_END();
}
@ -6903,7 +6903,7 @@ bool blockchain_storage::update_alt_out_indexes_for_tx_in_block(const transactio
for (auto ov : tx.vout)
{
VARIANT_SWITCH_BEGIN(ov);
VARIANT_CASE(tx_out_bare, o)
VARIANT_CASE_CONST(tx_out_bare, o)
if (o.target.type() == typeid(txout_to_key) || o.target.type() == typeid(txout_htlc))
{
//LOG_PRINT_MAGENTA("ALT_OUT KEY ON H[" << abei.height << "] AMOUNT: " << o.amount, LOG_LEVEL_0);
@ -6925,7 +6925,7 @@ bool blockchain_storage::update_alt_out_indexes_for_tx_in_block(const transactio
//TODO: At the moment we ignore check of mix_attr again mixing to simplify alt chain check, but in future consider it for stronger validation
}
VARIANT_CASE_TV(tx_out_zarcanum)
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
//@#@
VARIANT_SWITCH_END();
}
@ -6981,14 +6981,14 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha
// check PoS block miner tx in a special way
VARIANT_SWITCH_BEGIN(b.miner_tx.signature);
VARIANT_CASE(void_sig, v);
VARIANT_CASE(NLSAG_sig, signatures);
VARIANT_CASE_CONST(void_sig, v);
VARIANT_CASE_CONST(NLSAG_sig, signatures);
{
CHECK_AND_ASSERT_MES(signatures.s.size() == 1 && b.miner_tx.vin.size() == 2, false, "invalid PoS block's miner_tx, signatures size = " << signatures.s.size() << ", miner_tx.vin.size() = " << b.miner_tx.vin.size());
r = validate_alt_block_input(b.miner_tx, collected_keyimages, alt_chain_tx_ids, id, get_block_hash(b), 1, signatures.s[0], split_height, alt_chain, alt_chain_block_ids, ki_lookup, &max_related_block_height);
r = validate_alt_block_input(b.miner_tx, collected_keyimages, alt_chain_tx_ids, id, get_block_hash(b), 1, split_height, alt_chain, alt_chain_block_ids, ki_lookup, &max_related_block_height);
CHECK_AND_ASSERT_MES(r, false, "miner tx " << get_transaction_hash(b.miner_tx) << ": validation failed");
}
VARIANT_CASE(zarcanum_sig, s);
VARIANT_CASE_CONST(zarcanum_sig, s);
//@#@
VARIANT_SWITCH_END();
@ -7020,7 +7020,7 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha
if (tx.vin[n].type() == typeid(txin_to_key) || tx.vin[n].type() == typeid(txin_htlc))
{
uint64_t ki_lookup = 0;
r = validate_alt_block_input(tx, collected_keyimages, alt_chain_tx_ids, id, tx_id, n, tx.signature, split_height, alt_chain, alt_chain_block_ids, ki_lookup);
r = validate_alt_block_input(tx, collected_keyimages, alt_chain_tx_ids, id, tx_id, n, split_height, alt_chain, alt_chain_block_ids, ki_lookup);
CHECK_AND_ASSERT_MES(r, false, "tx " << tx_id << ", input #" << n << ": validation failed");
ki_lookup_time_total += ki_lookup;
}

View file

@ -39,7 +39,7 @@
#include "dispatch_core_events.h"
#include "bc_attachments_service_manager.h"
#include "common/median_db_cache.h"
#include "common/variant_helper.h"
MARK_AS_POD_C11(crypto::key_image);
@ -286,25 +286,24 @@ namespace currency
uint64_t get_aliases_count()const;
uint64_t get_block_h_older_then(uint64_t timestamp) const;
bool validate_tx_service_attachmens_in_services(const tx_service_attachment& a, size_t i, const transaction& tx)const;
bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const signature_v& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const;
bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const signature_v& sig, uint64_t& max_related_block_height)const;
bool check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, const signature_v& sig, uint64_t& max_related_block_height)const;
bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const;
bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const;
bool check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const;
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height)const;
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash) const;
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height, crypto::hash& max_used_block_id)const;
bool check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const signature_v& sig, const transaction& source_tx, size_t out_n) const;
bool check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const transaction& source_tx, size_t out_n) const;
bool validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id, uint64_t block_height) const;
bool validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id) const;
bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_v& verified_input, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase, scan_for_keys_context& scan_context) const;
bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_v& verified_input, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const;
bool check_input_signature(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, const std::vector<const crypto::public_key*>& output_keys_ptrs) const;
bool check_input_signature(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<const crypto::public_key*>& output_keys_ptrs) const;
bool check_input_signature(const transaction& tx,
size_t in_index,
uint64_t in_amount,
const crypto::key_image& k_image,
const std::vector<txin_etc_details_v>& in_etc_details,
const crypto::hash& tx_prefix_hash,
const std::vector<crypto::signature>& sig,
const std::vector<const crypto::public_key*>& output_keys_ptrs) const;
uint64_t get_current_comulative_blocksize_limit()const;
@ -597,7 +596,6 @@ namespace currency
const crypto::hash& bl_id,
const crypto::hash& input_tx_hash,
size_t input_index,
const signature_v& input_sigs, //const std::vector<crypto::signature>& input_sigs,
uint64_t split_height,
const alt_chain_type& alt_chain,
const std::unordered_set<crypto::hash>& alt_chain_block_ids,
@ -782,7 +780,7 @@ namespace currency
*/
VARIANT_SWITCH_BEGIN(tx_ptr->tx.vout[n]);
VARIANT_CASE(tx_out_bare, o)
VARIANT_CASE_CONST(tx_out_bare, o)
{
bool r = is_output_allowed_for_input(o.target, verified_input, get_current_blockchain_size() - tx_ptr->m_keeper_block_height);
CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type");
@ -821,21 +819,22 @@ namespace currency
return false;
}
TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output);
if (!vis.handle_output(tx_ptr->tx, validated_tx, tx_ptr->tx.vout[n], n))
if (!vis.handle_output(tx_ptr->tx, validated_tx, o, n))
{
LOG_PRINT_L0("Failed to handle_output for output id = " << tx_id << ", no " << n);
return false;
}
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output);
}
VARIANT_CASE_TV(tx_out_zarcanum)
VARIANT_CASE_CONST(tx_out_zarcanum, oz)
//@#@
return false;
VARIANT_CASE_THROW_ON_OTHER();
VARIANT_SWITCH_END();
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output);
if (max_related_block_height < tx_ptr->m_keeper_block_height)
max_related_block_height = tx_ptr->m_keeper_block_height;

View file

@ -659,16 +659,24 @@ namespace currency
struct NLSAG_sig
{
std::vector<std::vector<crypto::signature> > s;
BEGIN_SERIALIZE_OBJECT()
FIELD(s)
END_SERIALIZE()
};
struct zarcanum_sig
{
//TODO:
BEGIN_SERIALIZE_OBJECT()
END_SERIALIZE()
};
struct void_sig
{
//TODO:
BEGIN_SERIALIZE_OBJECT()
END_SERIALIZE()
};
typedef boost::variant<void_sig, NLSAG_sig, zarcanum_sig> signature_v;
@ -740,7 +748,7 @@ namespace currency
vin.clear();
vout.clear();
extra.clear();
signatures.clear();
signature = void_sig();
attachment.clear();
}

View file

@ -75,7 +75,8 @@ bool transition_convert(const transaction_prefix_v1& from, transaction_prefix_cu
}
class transaction_v1:
class transaction_v1
{
public:
std::vector<std::vector<crypto::signature> > signatures; //count signatures always the same as inputs count