forked from lthn/blockchain
htlc in work: altblock tx handling refactoring in work
This commit is contained in:
parent
902d4ffd43
commit
29e291bcc1
3 changed files with 85 additions and 15 deletions
|
|
@ -6,6 +6,8 @@
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <boost/archive/binary_oarchive.hpp>
|
||||
|
|
@ -1577,7 +1579,7 @@ std::string blockchain_storage::print_alt_chain(alt_chain_type alt_chain)
|
|||
return ss.str();
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::append_altblock_keyimages_to_big_heap(const crypto::hash& block_id, const std::set<crypto::key_image>& alt_block_keyimages)
|
||||
bool blockchain_storage::append_altblock_keyimages_to_big_heap(const crypto::hash& block_id, const std::unordered_set<crypto::key_image>& alt_block_keyimages)
|
||||
{
|
||||
for (auto& ki : alt_block_keyimages)
|
||||
m_altblocks_keyimages[ki].push_back(block_id);
|
||||
|
|
@ -1781,7 +1783,7 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
|
|||
bvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
std::set<crypto::key_image> alt_block_keyimages;
|
||||
std::unordered_set<crypto::key_image> alt_block_keyimages;
|
||||
uint64_t ki_lookup_total = 0;
|
||||
if (!validate_alt_block_txs(b, id, alt_block_keyimages, abei, alt_chain, connection_height, ki_lookup_total))
|
||||
{
|
||||
|
|
@ -6064,8 +6066,17 @@ void blockchain_storage::calculate_local_gindex_lookup_table_for_height(uint64_t
|
|||
}
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, std::set<crypto::key_image>& collected_keyimages, const crypto::hash& bl_id, const crypto::hash& input_tx_hash, size_t input_index,
|
||||
const std::vector<crypto::signature>& input_sigs, uint64_t split_height, const alt_chain_type& alt_chain, const std::set<crypto::hash>& alt_chain_block_ids, uint64_t& ki_lookuptime,
|
||||
bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
||||
const std::unordered_set<crypto::key_image>& collected_keyimages,
|
||||
const txs_by_id_and_height_altchain& alt_chain_tx_ids,
|
||||
const crypto::hash& bl_id,
|
||||
const crypto::hash& input_tx_hash,
|
||||
size_t input_index,
|
||||
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,
|
||||
uint64_t& ki_lookuptime,
|
||||
uint64_t* p_max_related_block_height /* = nullptr */) const
|
||||
{
|
||||
// Main and alt chain outline:
|
||||
|
|
@ -6202,6 +6213,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, s
|
|||
}
|
||||
if (offset_gindex >= it_aag->second)
|
||||
{
|
||||
//source tx found in altchain
|
||||
//GOT IT!!
|
||||
//TODO: At the moment we ignore check of mix_attr against mixing to simplify alt chain check, but in future consider it for stronger validation
|
||||
uint64_t local_offset = offset_gindex - it_aag->second;
|
||||
|
|
@ -6227,6 +6239,57 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, s
|
|||
auto &rbi = boost::get<ref_by_id>(off);
|
||||
tx_id = rbi.tx_id;
|
||||
out_n = rbi.n;
|
||||
//look up in alt-chain transactions fist
|
||||
auto it = alt_chain_tx_ids.find(tx_id);
|
||||
if (it != alt_chain_tx_ids.end())
|
||||
{
|
||||
//source tx found in altchain
|
||||
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() << ")");
|
||||
txout_target_v out_target_v = it->second.first.vout[out_n].target;
|
||||
if (out_target_v.type() == typeid(txout_htlc))
|
||||
{
|
||||
//source is hltc out
|
||||
const txout_htlc& htlc = boost::get<txout_to_key>(out_target_v);
|
||||
uint64_t height_of_source_block = it->second.second;
|
||||
uint64_t height_of_current_alt_block = alt_chain.size() ? alt_chain.back()->second.height + 1 : split_height + 1;
|
||||
CHECK_AND_ASSERT_MES(height_of_current_alt_block > height_of_source_block, false, "Intenral error: height_of_current_alt_block > height_of_source_block failed");
|
||||
if (htlc.expiration > height_of_current_alt_block - height_of_source_block)
|
||||
{
|
||||
//HTLC IS NOT expired, can be used ONLY by pkey_before_expiration and ONLY by HTLC input
|
||||
CHECK_AND_ASSERT_MES(input_v.type() == typeid(txin_htlc), false, "[TXOUT_HTLC]: Unexpected output type of non-HTLC input");
|
||||
pk = htlc.pkey_before_expiration;
|
||||
}
|
||||
else
|
||||
{
|
||||
//HTLC IS expired, can be used ONLY by pkey_after_expiration and ONLY by to_key input
|
||||
CHECK_AND_ASSERT_MES(input_v.type() == typeid(txin_to_key), false, "[TXOUT_HTLC]: Unexpected output type of HTLC input");
|
||||
pk = htlc.pkey_after_expiration;
|
||||
}
|
||||
pub_key_pointers.push_back(&pk);
|
||||
continue;
|
||||
}
|
||||
else if (out_target_v.type() == typeid(txout_to_key))
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(input_v.type() != typeid(txin_htlc), false, "Forbidden output type referenced by in tx ( input txin_htlc refered to txout_to_key )");
|
||||
//source is to_key out
|
||||
pk = boost::get<txout_to_key>(out_target_v).key;
|
||||
pub_key_pointers.push_back(&pk);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_MES_AND_THROW("Unexpected out type for tx_in in altblock: " << out_target_v.type().name());
|
||||
}
|
||||
|
||||
|
||||
//let's validate against htlc&to_key
|
||||
pk = alt_keys[input_to_key.amount][local_offset];
|
||||
pub_key_pointers.push_back(&pk);
|
||||
found_the_key = true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
auto p = m_db_transactions.get(tx_id);
|
||||
|
|
@ -6420,11 +6483,12 @@ bool blockchain_storage::update_alt_out_indexes_for_tx_in_block(const transactio
|
|||
return true;
|
||||
}
|
||||
|
||||
bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::hash& id, std::set<crypto::key_image>& collected_keyimages, alt_block_extended_info& abei, const alt_chain_type& alt_chain, uint64_t split_height, uint64_t& ki_lookup_time_total) const
|
||||
bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::hash& id, std::unordered_set<crypto::key_image>& collected_keyimages, alt_block_extended_info& abei, const alt_chain_type& alt_chain, uint64_t split_height, uint64_t& ki_lookup_time_total) const
|
||||
{
|
||||
uint64_t height = abei.height;
|
||||
bool r = false;
|
||||
std::set<crypto::hash> alt_chain_block_ids;
|
||||
std::unordered_set<crypto::hash> alt_chain_block_ids;
|
||||
txs_by_id_and_height_altchain alt_chain_tx_ids;
|
||||
|
||||
|
||||
alt_chain_block_ids.insert(id);
|
||||
|
|
@ -6447,8 +6511,13 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha
|
|||
for (auto& ch : alt_chain)
|
||||
{
|
||||
alt_chain_block_ids.insert(get_block_hash(ch->second.bl));
|
||||
for (auto & on_board_tx : ch->second.onboard_transactions)
|
||||
{
|
||||
alt_chain_tx_ids.insert(txs_by_id_and_height_altchain::value_type(on_board_tx.first, txs_by_id_and_height_altchain::value_type::second_type(on_board_tx.second, ch->second.height)));
|
||||
}
|
||||
//TODO: consider performance optimization (get_transaction_hash might slow down deep reorganizations )
|
||||
alt_chain_tx_ids.insert(txs_by_id_and_height_altchain::value_type(get_transaction_hash(ch->second.bl.miner_tx), txs_by_id_and_height_altchain::value_type::second_type(ch->second.bl.miner_tx, ch->second.height)));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -6462,7 +6531,7 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha
|
|||
CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1 && b.miner_tx.vin.size() == 2, false, "invalid PoS block's miner_tx, signatures size = " << b.miner_tx.signatures.size() << ", miner_tx.vin.size() = " << b.miner_tx.vin.size());
|
||||
uint64_t max_related_block_height = 0;
|
||||
uint64_t ki_lookup = 0;
|
||||
r = validate_alt_block_input(b.miner_tx, collected_keyimages, id, get_block_hash(b), 1, b.miner_tx.signatures[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, b.miner_tx.signatures[0], 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");
|
||||
ki_lookup_time_total += ki_lookup;
|
||||
// check stake age
|
||||
|
|
@ -6489,7 +6558,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, id, tx_id, n, tx.signatures[n], 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, tx.signatures[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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,8 +167,7 @@ namespace currency
|
|||
transactions_map onboard_transactions;
|
||||
};
|
||||
typedef std::unordered_map<crypto::hash, alt_block_extended_info> alt_chain_container;
|
||||
//typedef std::list<alt_chain_container::iterator> alt_chain_type;
|
||||
typedef std::vector<alt_chain_container::iterator> alt_chain_type;
|
||||
typedef std::vector<alt_chain_container::iterator> alt_chain_type; // alternative subchain, front -> mainchain(split point), back -> alternative head
|
||||
|
||||
typedef std::unordered_map<crypto::hash, block_extended_info> blocks_ext_by_hash;
|
||||
|
||||
|
|
@ -484,6 +483,8 @@ namespace currency
|
|||
typedef tools::db::basic_key_value_accessor<uint32_t, block_gindex_increments, true> per_block_gindex_increments_container; // height => [(amount, gindex_increment), ...]
|
||||
|
||||
//-----------------------------------------
|
||||
|
||||
typedef std::unordered_map<crypto::hash, std::pair<const transaction&, uint64_t> > txs_by_id_and_height_altchain;
|
||||
|
||||
tx_memory_pool& m_tx_pool;
|
||||
mutable bc_attachment_services_manager m_services_mgr;
|
||||
|
|
@ -584,10 +585,10 @@ namespace currency
|
|||
wide_difficulty_type get_x_difficulty_after_height(uint64_t height, bool is_pos);
|
||||
bool purge_keyimage_from_big_heap(const crypto::key_image& ki, const crypto::hash& id);
|
||||
bool purge_altblock_keyimages_from_big_heap(const block& b, const crypto::hash& id);
|
||||
bool append_altblock_keyimages_to_big_heap(const crypto::hash& block_id, const std::set<crypto::key_image>& alt_block_keyimages);
|
||||
bool validate_alt_block_input(const transaction& input_tx, std::set<crypto::key_image>& collected_keyimages, const crypto::hash& bl_id, const crypto::hash& input_tx_hash, size_t input_index, const std::vector<crypto::signature>& input_sigs, uint64_t split_height, const alt_chain_type& alt_chain, const std::set<crypto::hash>& alt_chain_block_ids, uint64_t& ki_lookuptime, uint64_t* p_max_related_block_height = nullptr) const;
|
||||
bool append_altblock_keyimages_to_big_heap(const crypto::hash& block_id, const std::unordered_set<crypto::key_image>& alt_block_keyimages);
|
||||
bool validate_alt_block_input(const transaction& input_tx, std::unordered_set<crypto::key_image>& collected_keyimages, const txs_by_id_and_height_altchain& alt_chain_tx_ids, const crypto::hash& bl_id, const crypto::hash& input_tx_hash, size_t input_index, 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, uint64_t& ki_lookuptime, uint64_t* p_max_related_block_height = nullptr) const;
|
||||
bool validate_alt_block_ms_input(const transaction& input_tx, const crypto::hash& input_tx_hash, size_t input_index, const std::vector<crypto::signature>& input_sigs, uint64_t split_height, const alt_chain_type& alt_chain) const;
|
||||
bool validate_alt_block_txs(const block& b, const crypto::hash& id, std::set<crypto::key_image>& collected_keyimages, alt_block_extended_info& abei, const alt_chain_type& alt_chain, uint64_t split_height, uint64_t& ki_lookup_time_total) const;
|
||||
bool validate_alt_block_txs(const block& b, const crypto::hash& id, std::unordered_set<crypto::key_image>& collected_keyimages, alt_block_extended_info& abei, const alt_chain_type& alt_chain, uint64_t split_height, uint64_t& ki_lookup_time_total) const;
|
||||
bool update_alt_out_indexes_for_tx_in_block(const transaction& tx, alt_block_extended_info& abei)const;
|
||||
bool get_transaction_from_pool_or_db(const crypto::hash& tx_id, std::shared_ptr<transaction>& tx_ptr, uint64_t min_allowed_block_height = 0) const;
|
||||
void get_last_n_x_blocks(uint64_t n, bool pos_blocks, std::list<std::shared_ptr<const block_extended_info>>& blocks) const;
|
||||
|
|
|
|||
|
|
@ -559,7 +559,7 @@ namespace currency
|
|||
{
|
||||
public:
|
||||
// tx version information
|
||||
size_t version{};
|
||||
uint64_t version{};
|
||||
//extra
|
||||
std::vector<extra_v> extra;
|
||||
std::vector<txin_v> vin;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue