forked from lthn/blockchain
fix for PoS locking issue + enhanced naming
This commit is contained in:
parent
d111e014bb
commit
6f93fbd7a0
3 changed files with 29 additions and 23 deletions
|
|
@ -3910,14 +3910,14 @@ bool blockchain_storage::is_tx_spendtime_unlocked(uint64_t unlock_time) 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, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height, uint64_t& max_unlock_time) 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, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
//TIME_MEASURE_START_PD(tx_check_inputs_loop_ch_in_get_keys_loop);
|
||||
|
||||
std::vector<crypto::public_key> output_keys;
|
||||
if(!get_output_keys_for_input_with_checks(tx, txin, output_keys, max_related_block_height, max_unlock_time))
|
||||
if(!get_output_keys_for_input_with_checks(tx, txin, output_keys, max_related_block_height, source_max_unlock_time_for_pos_coinbase))
|
||||
{
|
||||
LOG_PRINT_L0("Failed to get output keys for input #" << in_index << " (amount = " << print_money(txin.amount) << ", key_offset.size = " << txin.key_offsets.size() << ")");
|
||||
return false;
|
||||
|
|
@ -3936,7 +3936,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
|
|||
// 1) source tx unlock time validity
|
||||
// 2) mixin restrictions
|
||||
// 3) general gindex/ref_by_id corectness
|
||||
bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction& tx, const txin_to_key& txin, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& max_unlock_time) const
|
||||
bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction& tx, const txin_to_key& txin, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
|
|
@ -3944,10 +3944,13 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction
|
|||
{
|
||||
std::vector<crypto::public_key >& m_results_collector;
|
||||
const blockchain_storage& m_bch;
|
||||
uint64_t& m_max_unlock_time;
|
||||
uint64_t& m_source_max_unlock_time_for_pos_coinbase;
|
||||
outputs_visitor(std::vector<crypto::public_key>& results_collector,
|
||||
const blockchain_storage& bch,
|
||||
uint64_t& max_unlock_time) :m_results_collector(results_collector), m_bch(bch), m_max_unlock_time(max_unlock_time)
|
||||
uint64_t& source_max_unlock_time_for_pos_coinbase)
|
||||
: m_results_collector(results_collector)
|
||||
, m_bch(bch)
|
||||
, m_source_max_unlock_time_for_pos_coinbase(source_max_unlock_time_for_pos_coinbase)
|
||||
{}
|
||||
bool handle_output(const transaction& source_tx, const transaction& validated_tx, const tx_out& out, uint64_t out_i)
|
||||
{
|
||||
|
|
@ -3956,8 +3959,9 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction
|
|||
//let coinbase sources for PoS block to have locked inputs, the outputs supposed to be locked same way, except the reward
|
||||
if (is_coinbase(validated_tx) && is_pos_block(validated_tx))
|
||||
{
|
||||
if (source_out_unlock_time > m_max_unlock_time)
|
||||
m_max_unlock_time = source_out_unlock_time;
|
||||
CHECK_AND_ASSERT_MES(should_unlock_value_be_treated_as_block_height(source_out_unlock_time), false, "source output #" << out_i << " is locked by time, not by height, which is not allowed for PoS coinbase");
|
||||
if (source_out_unlock_time > m_source_max_unlock_time_for_pos_coinbase)
|
||||
m_source_max_unlock_time_for_pos_coinbase = source_out_unlock_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3968,7 +3972,6 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if(out.target.type() != typeid(txout_to_key))
|
||||
{
|
||||
LOG_PRINT_L0("Output have wrong type id, which=" << out.target.which());
|
||||
|
|
@ -3980,7 +3983,7 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction
|
|||
}
|
||||
};
|
||||
|
||||
outputs_visitor vi(output_keys, *this, max_unlock_time);
|
||||
outputs_visitor vi(output_keys, *this, source_max_unlock_time_for_pos_coinbase);
|
||||
return scan_outputkeys_for_indexes(tx, txin, vi, max_related_block_height);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
@ -4438,13 +4441,13 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t max_unlock_time)const
|
||||
bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const
|
||||
{
|
||||
uint64_t major_unlock_time = get_tx_x_detail<etc_tx_details_unlock_time>(miner_tx);
|
||||
if (major_unlock_time)
|
||||
{
|
||||
//if there was etc_tx_details_unlock_time present in tx, then ignore etc_tx_details_unlock_time2
|
||||
if (major_unlock_time < max_unlock_time)
|
||||
if (major_unlock_time < source_max_unlock_time)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
|
|
@ -4458,11 +4461,13 @@ bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transactio
|
|||
CHECK_AND_ASSERT_MES(ut2.unlock_time_array.size() == miner_tx.vout.size(), false, "ut2.unlock_time_array.size()<" << ut2.unlock_time_array.size()
|
||||
<< "> != miner_tx.vout.size()<" << miner_tx.vout.size() << ">");
|
||||
|
||||
uint64_t amount_of_coins_in_unlock_in_range = 0;
|
||||
uint64_t amount_of_coins_in_unlock_in_range = 0; // amount of outputs locked for at least the same time
|
||||
|
||||
for (uint64_t i = 0; i != miner_tx.vout.size(); i++)
|
||||
{
|
||||
if (ut2.unlock_time_array[i] >= max_unlock_time)
|
||||
uint64_t unlock_value = ut2.unlock_time_array[i];
|
||||
CHECK_AND_ASSERT_MES(should_unlock_value_be_treated_as_block_height(unlock_value), false, "output #" << i << " is locked by time, not buy height, which is not allowed for PoS coinbase");
|
||||
if (unlock_value >= source_max_unlock_time)
|
||||
amount_of_coins_in_unlock_in_range += miner_tx.vout[i].amount;
|
||||
}
|
||||
|
||||
|
|
@ -4549,22 +4554,22 @@ bool blockchain_storage::validate_pos_block(const block& 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 max_unlock_time = 0;
|
||||
r = check_tx_input(b.miner_tx, 1, coinstake_in, id, b.miner_tx.signatures[0], max_related_block_height, max_unlock_time);
|
||||
uint64_t source_max_unlock_time_for_pos_coinbase = 0;
|
||||
r = check_tx_input(b.miner_tx, 1, coinstake_in, id, b.miner_tx.signatures[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));
|
||||
|
||||
if (get_block_height(b) > m_core_runtime_config.hard_fork1_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 failed to validate coinbase in pos block, condition failed: max_related_block_height(" << max_related_block_height << ") < last_pow_h(" << last_pow_h << ")");
|
||||
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, max_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)
|
||||
<< "max_unlock_time=" << max_unlock_time);
|
||||
<< "source_max_unlock_time_for_pos_coinbase=" << source_max_unlock_time_for_pos_coinbase);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(is_tx_spendtime_unlocked(max_unlock_time), false, "Failed to failed to validate coinbase in pos block, condition failed: is_tx_spendtime_unlocked(max_unlock_time)(" << max_unlock_time << ")");
|
||||
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 << ")");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -267,14 +267,14 @@ 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 std::vector<crypto::signature>& sig, uint64_t& max_related_block_height, uint64_t& max_unlock_time)const;
|
||||
bool 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 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 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 std::vector<crypto::signature>& sig, 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 get_output_keys_for_input_with_checks(const transaction& tx, const txin_to_key& txin, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& max_unlock_time) const;
|
||||
bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_to_key& txin, 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_tokey_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, const std::vector<const crypto::public_key*>& output_keys_ptrs) const;
|
||||
uint64_t get_current_comulative_blocksize_limit()const;
|
||||
uint64_t get_current_hashrate(size_t aprox_count)const;
|
||||
|
|
@ -312,7 +312,7 @@ namespace currency
|
|||
bool build_stake_modifier(stake_modifier_type& sm, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0, crypto::hash *p_last_block_hash = nullptr) const;
|
||||
|
||||
bool scan_pos(const COMMAND_RPC_SCAN_POS::request& sp, COMMAND_RPC_SCAN_POS::response& rsp)const;
|
||||
bool validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t max_unlock_time)const;
|
||||
bool validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const;
|
||||
bool validate_pos_block(const block& b, const crypto::hash& id, bool for_altchain)const;
|
||||
bool validate_pos_block(const block& b, wide_difficulty_type basic_diff, const crypto::hash& id, bool for_altchain)const;
|
||||
bool validate_pos_block(const block& b,
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ namespace currency
|
|||
uint64_t get_tx_unlock_time(const transaction& tx, uint64_t o_i);
|
||||
uint64_t get_tx_max_unlock_time(const transaction& tx);
|
||||
bool get_tx_max_min_unlock_time(const transaction& tx, uint64_t& max_unlock_time, uint64_t& min_unlock_time);
|
||||
inline bool should_unlock_value_be_treated_as_block_height(uint64_t v) { return v < CURRENCY_MAX_BLOCK_NUMBER; }
|
||||
inline uint64_t get_tx_flags(const transaction& tx) { return get_tx_x_detail<etc_tx_details_flags>(tx); }
|
||||
inline uint64_t get_tx_expiration_time(const transaction& tx) {return get_tx_x_detail<etc_tx_details_expiration_time>(tx); }
|
||||
inline void set_tx_unlock_time(transaction& tx, uint64_t v) { set_tx_x_detail<etc_tx_details_unlock_time>(tx, v); }
|
||||
|
|
@ -106,4 +107,4 @@ namespace currency
|
|||
size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size);
|
||||
blobdata tx_to_blob(const transaction& b);
|
||||
bool tx_to_blob(const transaction& b, blobdata& b_blob);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue