forked from lthn/blockchain
core: HF4 coinage rule is not checked while adding a tx to the pool, letting it being confirmed later
This commit is contained in:
parent
2a13a63eb7
commit
2bb1113b43
5 changed files with 67 additions and 38 deletions
|
|
@ -5118,10 +5118,13 @@ bool blockchain_storage::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::
|
|||
bool blockchain_storage::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
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
bool res = check_tx_inputs(tx, tx_prefix_hash, max_used_block_height);
|
||||
if(!res) return false;
|
||||
CHECK_AND_ASSERT_MES(max_used_block_height < m_db_blocks.size(), false, "internal error: max used block index=" << max_used_block_height << " is not less than blockchain size = " << m_db_blocks.size());
|
||||
get_block_hash(m_db_blocks[max_used_block_height]->bl, max_used_block_id);
|
||||
check_tx_inputs_context ctic{};
|
||||
ctic.calculate_max_used_block_id = true;
|
||||
bool res = check_tx_inputs(tx, tx_prefix_hash, ctic);
|
||||
if (!res)
|
||||
return false;
|
||||
max_used_block_height = ctic.max_used_block_height;
|
||||
max_used_block_id = ctic.max_used_block_id;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
@ -5397,15 +5400,16 @@ bool blockchain_storage::have_tx_keyimges_as_spent(const transaction &tx) const
|
|||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash) const
|
||||
{
|
||||
uint64_t stub = 0;
|
||||
return check_tx_inputs(tx, tx_prefix_hash, stub);
|
||||
check_tx_inputs_context ctic{};
|
||||
return check_tx_inputs(tx, tx_prefix_hash, ctic);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height) const
|
||||
bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, check_tx_inputs_context& ctic) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
size_t sig_index = 0;
|
||||
max_used_block_height = 0;
|
||||
bool all_tx_ins_have_explicit_native_asset_ids = true;
|
||||
ctic.max_used_block_height = 0;
|
||||
|
||||
auto local_check_key_image = [&](const crypto::key_image& ki) -> bool
|
||||
{
|
||||
|
|
@ -5430,7 +5434,7 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
|
|||
return false;
|
||||
|
||||
uint64_t max_unlock_time = 0;
|
||||
if (!check_tx_input(tx, sig_index, in_to_key, tx_prefix_hash, max_used_block_height, max_unlock_time))
|
||||
if (!check_tx_input(tx, sig_index, in_to_key, tx_prefix_hash, ctic.max_used_block_height, max_unlock_time))
|
||||
{
|
||||
LOG_ERROR("Failed to validate input #" << sig_index << " tx: " << tx_prefix_hash);
|
||||
return false;
|
||||
|
|
@ -5438,7 +5442,7 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
|
|||
}
|
||||
VARIANT_CASE_CONST(txin_multisig, in_ms)
|
||||
{
|
||||
if (!check_tx_input(tx, sig_index, in_ms, tx_prefix_hash, max_used_block_height))
|
||||
if (!check_tx_input(tx, sig_index, in_ms, tx_prefix_hash, ctic.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;
|
||||
|
|
@ -5450,7 +5454,7 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
|
|||
if (!local_check_key_image(in_htlc.k_image))
|
||||
return false;
|
||||
|
||||
if (!check_tx_input(tx, sig_index, in_htlc, tx_prefix_hash, max_used_block_height))
|
||||
if (!check_tx_input(tx, sig_index, in_htlc, tx_prefix_hash, ctic.max_used_block_height))
|
||||
{
|
||||
LOG_ERROR("Failed to validate htlc input #" << sig_index << " in tx: " << tx_prefix_hash << ", htlc json: " << ENDL << obj_to_json_str(in_htlc));
|
||||
return false;
|
||||
|
|
@ -5461,7 +5465,7 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
|
|||
if (!local_check_key_image(in_zc.k_image))
|
||||
return false;
|
||||
|
||||
if (!check_tx_input(tx, sig_index, in_zc, tx_prefix_hash, max_used_block_height, all_tx_ins_have_explicit_native_asset_ids))
|
||||
if (!check_tx_input(tx, sig_index, in_zc, tx_prefix_hash, ctic))
|
||||
{
|
||||
LOG_ERROR("Failed to validate zc input #" << sig_index << " in tx: " << tx_prefix_hash);
|
||||
return false;
|
||||
|
|
@ -5484,9 +5488,16 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
|
|||
CHECK_AND_ASSERT_MES(r, false, "Failed to validate attachments in tx " << tx_prefix_hash << ": incorrect extra_attachment_info in tx.extra");
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(check_tx_explicit_asset_id_rules(tx, all_tx_ins_have_explicit_native_asset_ids), false, "tx does not comply with explicit asset id rules");
|
||||
CHECK_AND_ASSERT_MES(check_tx_explicit_asset_id_rules(tx, ctic.all_tx_ins_have_explicit_native_asset_ids), false, "tx does not comply with explicit asset id rules");
|
||||
}
|
||||
TIME_MEASURE_FINISH_PD(tx_check_inputs_attachment_check);
|
||||
|
||||
if (ctic.calculate_max_used_block_id)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(ctic.max_used_block_height < m_db_blocks.size(), false, "internal error: max used block index=" << ctic.max_used_block_height << " is not less than blockchain size = " << m_db_blocks.size());
|
||||
get_block_hash(m_db_blocks[ctic.max_used_block_height]->bl, ctic.max_used_block_id);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
@ -5620,7 +5631,7 @@ struct outputs_visitor
|
|||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Checks each referenced output for:
|
||||
// Checks each referenced output against the current blockchain state for:
|
||||
// 1) source tx unlock time validity
|
||||
// 2) mixin restrictions
|
||||
// 3) general gindex/ref_by_id corectness
|
||||
|
|
@ -5908,8 +5919,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
|
|||
return check_input_signature(tx, in_index, txin.amount, txin.k_image, txin.etc_details, tx_prefix_hash, output_keys_ptrs);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_zc_input& zc_in, const crypto::hash& tx_prefix_hash,
|
||||
uint64_t& max_related_block_height, bool& all_tx_ins_have_explicit_native_asset_ids) const
|
||||
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_zc_input& zc_in, const crypto::hash& tx_prefix_hash, check_tx_inputs_context& ctic) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
|
|
@ -5919,9 +5929,10 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
|
|||
//
|
||||
std::vector<crypto::public_key> dummy_output_keys; // won't be used
|
||||
uint64_t dummy_source_max_unlock_time_for_pos_coinbase_dummy = 0; // won't be used
|
||||
scan_for_keys_context scan_contex = AUTO_VAL_INIT(scan_contex);
|
||||
scan_for_keys_context scan_contex{};
|
||||
scan_contex.check_hf4_coinage_rule = ctic.check_hf4_coinage_rule;
|
||||
|
||||
if (!get_output_keys_for_input_with_checks(tx, zc_in, dummy_output_keys, max_related_block_height, dummy_source_max_unlock_time_for_pos_coinbase_dummy, scan_contex))
|
||||
if (!get_output_keys_for_input_with_checks(tx, zc_in, dummy_output_keys, ctic.max_used_block_height, dummy_source_max_unlock_time_for_pos_coinbase_dummy, scan_contex))
|
||||
{
|
||||
LOG_PRINT_L0("get_output_keys_for_input_with_checks failed for input #" << in_index << ", key_offset.size = " << zc_in.key_offsets.size() << ")");
|
||||
return false;
|
||||
|
|
@ -5942,8 +5953,8 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
|
|||
for(auto& zc_out : scan_contex.zc_outs)
|
||||
{
|
||||
ring.emplace_back(zc_out.stealth_address, zc_out.amount_commitment, zc_out.blinded_asset_id);
|
||||
if (all_tx_ins_have_explicit_native_asset_ids && crypto::point_t(zc_out.blinded_asset_id).modify_mul8().to_public_key() != native_coin_asset_id)
|
||||
all_tx_ins_have_explicit_native_asset_ids = false;
|
||||
if (ctic.all_tx_ins_have_explicit_native_asset_ids && crypto::point_t(zc_out.blinded_asset_id).modify_mul8().to_public_key() != native_coin_asset_id)
|
||||
ctic.all_tx_ins_have_explicit_native_asset_ids = false;
|
||||
}
|
||||
|
||||
// calculate corresponding tx prefix hash
|
||||
|
|
|
|||
|
|
@ -150,9 +150,19 @@ namespace currency
|
|||
|
||||
struct scan_for_keys_context
|
||||
{
|
||||
bool htlc_is_expired;
|
||||
std::list<txout_htlc> htlc_outs;
|
||||
std::list<tx_out_zarcanum> zc_outs;
|
||||
bool check_hf4_coinage_rule = true; // input
|
||||
bool htlc_is_expired; // output
|
||||
std::list<txout_htlc> htlc_outs; // output, legacy
|
||||
std::list<tx_out_zarcanum> zc_outs; // output
|
||||
};
|
||||
|
||||
struct check_tx_inputs_context
|
||||
{
|
||||
bool check_hf4_coinage_rule = true; // input
|
||||
bool calculate_max_used_block_id = false; // input
|
||||
crypto::hash max_used_block_id{}; // output
|
||||
uint64_t max_used_block_height = 0; // output
|
||||
bool all_tx_ins_have_explicit_native_asset_ids = true; // output
|
||||
};
|
||||
|
||||
// == Output indexes local lookup table conception ==
|
||||
|
|
@ -316,8 +326,8 @@ namespace currency
|
|||
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_input(const transaction& tx, size_t in_index, const txin_zc_input& zc_in, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, bool& all_tx_ins_have_explicit_native_asset_ids) const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_zc_input& zc_in, const crypto::hash& tx_prefix_hash, check_tx_inputs_context& ctic) const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, check_tx_inputs_context& ctic)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 transaction& source_tx, size_t out_n) const;
|
||||
|
|
@ -927,7 +937,7 @@ namespace currency
|
|||
++output_index;
|
||||
}
|
||||
|
||||
if (m_core_runtime_config.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, this->get_current_blockchain_size()))
|
||||
if (scan_context.check_hf4_coinage_rule && m_core_runtime_config.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, this->get_current_blockchain_size()))
|
||||
{
|
||||
//with hard fork 4 make it network rule to have at least 10 confirmations
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::check_tx_fee(const transaction &tx, uint64_t amount_fee)
|
||||
bool tx_memory_pool::check_tx_fee(const transaction &tx, uint64_t amount_fee) const
|
||||
{
|
||||
if (amount_fee < m_blockchain.get_core_runtime_config().tx_pool_min_fee)
|
||||
return false;
|
||||
|
|
@ -227,9 +227,10 @@ namespace currency
|
|||
TIME_MEASURE_FINISH_PD(check_keyimages_ws_ms_time);
|
||||
|
||||
TIME_MEASURE_START_PD(check_inputs_time);
|
||||
crypto::hash max_used_block_id = null_hash;
|
||||
uint64_t max_used_block_height = 0;
|
||||
bool ch_inp_res = m_blockchain.check_tx_inputs(tx, id, max_used_block_height, max_used_block_id);
|
||||
blockchain_storage::check_tx_inputs_context ctic{};
|
||||
ctic.calculate_max_used_block_id = true;
|
||||
ctic.check_hf4_coinage_rule = false;
|
||||
bool ch_inp_res = m_blockchain.check_tx_inputs(tx, id, ctic);
|
||||
if (!ch_inp_res && !kept_by_block && !from_core)
|
||||
{
|
||||
LOG_PRINT_L0("check_tx_inputs failed, tx rejected");
|
||||
|
|
@ -255,7 +256,7 @@ namespace currency
|
|||
}
|
||||
}
|
||||
|
||||
do_insert_transaction(tx, id, blob_size, kept_by_block, tx_fee, ch_inp_res ? max_used_block_id : null_hash, ch_inp_res ? max_used_block_height : 0);
|
||||
do_insert_transaction(tx, id, blob_size, kept_by_block, tx_fee, ch_inp_res ? ctic.max_used_block_id : null_hash, ch_inp_res ? ctic.max_used_block_height : 0);
|
||||
|
||||
TIME_MEASURE_FINISH_PD(tx_processing_time);
|
||||
tvc.m_added_to_pool = true;
|
||||
|
|
@ -935,12 +936,16 @@ namespace currency
|
|||
if(txd.last_failed_id != null_hash && m_blockchain.get_current_blockchain_size() > txd.last_failed_height && txd.last_failed_id == m_blockchain.get_block_id_by_height(txd.last_failed_height))
|
||||
return false;//we already sure that this tx is broken for this height
|
||||
|
||||
if(!m_blockchain.check_tx_inputs(txd.tx, id, txd.max_used_block_height, txd.max_used_block_id))
|
||||
blockchain_storage::check_tx_inputs_context ctic{};
|
||||
ctic.check_hf4_coinage_rule = false;
|
||||
if(!m_blockchain.check_tx_inputs(txd.tx, id, ctic))
|
||||
{
|
||||
txd.last_failed_height = m_blockchain.get_top_block_height();
|
||||
txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height);
|
||||
return false;
|
||||
}
|
||||
txd.max_used_block_height = ctic.max_used_block_height;
|
||||
txd.max_used_block_id = ctic.max_used_block_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -952,12 +957,16 @@ namespace currency
|
|||
if(txd.last_failed_id == m_blockchain.get_block_id_by_height(txd.last_failed_height))
|
||||
return false;
|
||||
//check ring signature again, it is possible (with very small chance) that this transaction become again valid
|
||||
if(!m_blockchain.check_tx_inputs(txd.tx, id, txd.max_used_block_height, txd.max_used_block_id))
|
||||
blockchain_storage::check_tx_inputs_context ctic{};
|
||||
ctic.check_hf4_coinage_rule = false;
|
||||
if(!m_blockchain.check_tx_inputs(txd.tx, id, ctic))
|
||||
{
|
||||
txd.last_failed_height = m_blockchain.get_top_block_height();
|
||||
txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height);
|
||||
return false;
|
||||
}
|
||||
txd.max_used_block_height = ctic.max_used_block_height;
|
||||
txd.max_used_block_id = ctic.max_used_block_id;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ namespace currency
|
|||
bool remove_key_images(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block);
|
||||
bool insert_alias_info(const transaction& tx);
|
||||
bool remove_alias_info(const transaction& tx);
|
||||
bool check_tx_fee(const transaction &tx, uint64_t amount_fee);
|
||||
bool check_tx_fee(const transaction &tx, uint64_t amount_fee) const;
|
||||
std::string get_blacklisted_txs_string() const;
|
||||
|
||||
bool is_valid_contract_finalization_tx(const transaction &tx)const;
|
||||
|
|
|
|||
|
|
@ -2568,10 +2568,9 @@ bool input_refers_to_incompatible_by_type_output::assert_zc_input_refers_bare_ou
|
|||
|
||||
{
|
||||
bool all_inputs_have_explicit_native_asset_id{};
|
||||
uint64_t max_related_block_height{};
|
||||
blockchain_storage::check_tx_inputs_context ctic{};
|
||||
|
||||
CHECK_AND_ASSERT_EQ(c.get_blockchain_storage().check_tx_input(tx, 0, boost::get<const txin_zc_input>(tx.vin.front()), get_transaction_hash(tx), max_related_block_height,
|
||||
all_inputs_have_explicit_native_asset_id), false);
|
||||
CHECK_AND_ASSERT_EQ(c.get_blockchain_storage().check_tx_input(tx, 0, boost::get<const txin_zc_input>(tx.vin.front()), get_transaction_hash(tx), ctic), false);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue