1
0
Fork 0
forked from lthn/blockchain

htlc in work: refactoring of txin_htlc structure, work on altchain handling witb htlc

This commit is contained in:
cryptozoidberg 2021-01-06 23:16:49 +01:00
parent 93aacf3bec
commit 0bb579769c
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
5 changed files with 54 additions and 60 deletions

View file

@ -4263,7 +4263,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
std::vector<crypto::public_key> output_keys;
scan_for_keys_context scan_context = AUTO_VAL_INIT(scan_context);
if(!get_output_keys_for_input_with_checks(tx, txin.amount, txin.key_offsets, output_keys, max_related_block_height, source_max_unlock_time_for_pos_coinbase))
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;
@ -4559,12 +4559,11 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
//TIME_MEASURE_START_PD(tx_check_inputs_loop_ch_in_get_keys_loop);
std::vector<crypto::public_key> output_keys;
std::vector<txout_ref_v> key_offsets(1, txin.key_offset);
scan_for_keys_context scan_contex = AUTO_VAL_INIT(scan_contex);
uint64_t source_max_unlock_time_for_pos_coinbase_dummy = AUTO_VAL_INIT(source_max_unlock_time_for_pos_coinbase_dummy);
if (!get_output_keys_for_input_with_checks(tx, txin, output_keys, max_related_block_height, source_max_unlock_time_for_pos_coinbase_dummy, scan_contex))
{
LOG_PRINT_L0("Failed to get output keys for input #" << in_index << " (amount = " << print_money(txin.amount) << ", key_offset.size = " << key_offsets.size() << ")");
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;
}
@ -4599,7 +4598,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
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, 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.amount, txin.k_image, txin.etc_details, tx_prefix_hash, sig, output_keys_ptrs);
}
//------------------------------------------------------------------
uint64_t blockchain_storage::get_adjusted_time() const
@ -6100,23 +6099,24 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, s
if (p_max_related_block_height != nullptr)
*p_max_related_block_height = 0;
CHECK_AND_ASSERT_MES(input_index < input_tx.vin.size() && input_tx.vin[input_index].type() == typeid(txin_to_key), false, "invalid input index: " << input_index);
const txin_to_key& input = boost::get<txin_to_key>(input_tx.vin[input_index]);
CHECK_AND_ASSERT_MES(input_index < input_tx.vin.size(), false, "invalid input index: " << input_index);
const txin_v& input_v = input_tx.vin[input_index];
const txin_to_key& input_to_key = get_to_key_input_from_txin_v(input_v);
// check case b1: key_image spent status in main chain, should be either non-spent or has spent height >= split_height
auto p = m_db_spent_keys.get(input.k_image);
CHECK_AND_ASSERT_MES(p == nullptr || *p >= split_height, false, "key image " << input.k_image << " has been already spent in main chain at height " << *p << ", split height: " << split_height);
auto p = m_db_spent_keys.get(input_to_key.k_image);
CHECK_AND_ASSERT_MES(p == nullptr || *p >= split_height, false, "key image " << input_to_key.k_image << " has been already spent in main chain at height " << *p << ", split height: " << split_height);
TIME_MEASURE_START(ki_lookup_time);
//check key_image in altchain
//check among this alt block already collected key images first
if (collected_keyimages.find(input.k_image) != collected_keyimages.end())
if (collected_keyimages.find(input_to_key.k_image) != collected_keyimages.end())
{
// cases b2, b3
LOG_ERROR("key image " << input.k_image << " already spent in this alt block");
LOG_ERROR("key image " << input_to_key.k_image << " already spent in this alt block");
return false;
}
auto ki_it = m_altblocks_keyimages.find(input.k_image);
auto ki_it = m_altblocks_keyimages.find(input_to_key.k_image);
if (ki_it != m_altblocks_keyimages.end())
{
//have some entry for this key image. Check if this key image belongs to this alt chain
@ -6126,18 +6126,18 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, s
if (alt_chain_block_ids.find(h) != alt_chain_block_ids.end())
{
// cases b2, b3
LOG_ERROR("key image " << input.k_image << " already spent in altchain");
LOG_ERROR("key image " << input_to_key.k_image << " already spent in altchain");
return false;
}
}
}
//update altchain with key image
collected_keyimages.insert(input.k_image);
collected_keyimages.insert(input_to_key.k_image);
TIME_MEASURE_FINISH(ki_lookup_time);
ki_lookuptime = ki_lookup_time;
std::vector<txout_ref_v> abs_key_offsets = relative_output_offsets_to_absolute(input.key_offsets);
CHECK_AND_ASSERT_MES(abs_key_offsets.size() > 0 && abs_key_offsets.size() == input.key_offsets.size(), false, "internal error: abs_key_offsets.size()==" << abs_key_offsets.size() << ", input.key_offsets.size()==" << input.key_offsets.size());
std::vector<txout_ref_v> abs_key_offsets = relative_output_offsets_to_absolute(input_to_key.key_offsets);
CHECK_AND_ASSERT_MES(abs_key_offsets.size() > 0 && abs_key_offsets.size() == input_to_key.key_offsets.size(), false, "internal error: abs_key_offsets.size()==" << abs_key_offsets.size() << ", input_to_key.key_offsets.size()==" << input_to_key.key_offsets.size());
// eventually we should found all public keys for all outputs this input refers to, for checking ring signature
std::vector<crypto::public_key> pub_keys(abs_key_offsets.size(), null_pkey);
@ -6147,12 +6147,12 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, s
uint64_t global_outs_for_amount = 0;
//figure out if this amount touched alt_chain amount's index and if it is, get
bool amount_touched_altchain = false;
//auto abg_it = abei.gindex_lookup_table.find(input.amount);
//auto abg_it = abei.gindex_lookup_table.find(input_to_key.amount);
//if (abg_it == abei.gindex_lookup_table.end())
if (!alt_chain.empty())
{
auto abg_it = alt_chain.back()->second.gindex_lookup_table.find(input.amount);
auto abg_it = alt_chain.back()->second.gindex_lookup_table.find(input_to_key.amount);
if (abg_it != alt_chain.back()->second.gindex_lookup_table.end())
{
amount_touched_altchain = true;
@ -6163,13 +6163,13 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, s
else
{
//quite easy,
global_outs_for_amount = m_db_outputs.get_item_size(input.amount);
global_outs_for_amount = m_db_outputs.get_item_size(input_to_key.amount);
}
}
else
{
//quite easy,
global_outs_for_amount = m_db_outputs.get_item_size(input.amount);
global_outs_for_amount = m_db_outputs.get_item_size(input_to_key.amount);
}
CHECK_AND_ASSERT_MES(pub_keys.size() == abs_key_offsets.size(), false, "pub_keys.size()==" << pub_keys.size() << " != abs_key_offsets.size()==" << abs_key_offsets.size()); // just a little bit of paranoia
@ -6184,7 +6184,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, s
{
uint64_t offset_gindex = boost::get<uint64_t>(off);
CHECK_AND_ASSERT_MES(offset_gindex < global_outs_for_amount, false,
"invalid global output index " << offset_gindex << " for amount=" << input.amount <<
"invalid global output index " << offset_gindex << " for amount=" << input_to_key.amount <<
", max is " << global_outs_for_amount <<
", referred to by offset #" << pk_n <<
", amount_touched_altchain = " << amount_touched_altchain);
@ -6193,7 +6193,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, s
bool found_the_key = false;
for (auto alt_it = alt_chain.rbegin(); alt_it != alt_chain.rend(); alt_it++)
{
auto it_aag = (*alt_it)->second.gindex_lookup_table.find(input.amount);
auto it_aag = (*alt_it)->second.gindex_lookup_table.find(input_to_key.amount);
if (it_aag == (*alt_it)->second.gindex_lookup_table.end())
{
CHECK_AND_ASSERT_MES(alt_it != alt_chain.rbegin(), false, "internal error: was marked as amount_touched_altchain but unable to find on first entry");
@ -6203,11 +6203,11 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, s
if (offset_gindex >= it_aag->second)
{
//GOT IT!!
//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
//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;
auto& alt_keys = (*alt_it)->second.outputs_pub_keys;
CHECK_AND_ASSERT_MES(local_offset < alt_keys[input.amount].size(), false, "Internal error: local_offset=" << local_offset << " while alt_keys[" << input.amount << " ].size()=" << alt_keys.size());
pk = alt_keys[input.amount][local_offset];
CHECK_AND_ASSERT_MES(local_offset < alt_keys[input_to_key.amount].size(), false, "Internal error: local_offset=" << local_offset << " while alt_keys[" << input_to_key.amount << " ].size()=" << alt_keys.size());
pk = alt_keys[input_to_key.amount][local_offset];
pub_key_pointers.push_back(&pk);
found_the_key = true;
break;
@ -6217,8 +6217,8 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, s
break;
//otherwise lookup in main chain index
}
auto p = m_db_outputs.get_subitem(input.amount, offset_gindex);
CHECK_AND_ASSERT_MES(p != nullptr, false, "global output was not found, amount: " << input.amount << ", gindex: " << offset_gindex << ", referred to by offset #" << pk_n);
auto p = m_db_outputs.get_subitem(input_to_key.amount, offset_gindex);
CHECK_AND_ASSERT_MES(p != nullptr, false, "global output was not found, amount: " << input_to_key.amount << ", gindex: " << offset_gindex << ", referred to by offset #" << pk_n);
tx_id = p->tx_id;
out_n = p->out_no;
}
@ -6254,7 +6254,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, s
}
// do input checks (attachment_info, ring signature and extra signature, etc.)
r = check_input_signature(input_tx, input_index, input, input_tx_hash, input_sigs, pub_key_pointers);
r = check_input_signature(input_tx, input_index, input_to_key, input_tx_hash, input_sigs, 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()
@ -6485,7 +6485,7 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha
CHECK_AND_ASSERT_MES(tx.signatures.size() == tx.vin.size(), false, "invalid tx: tx.signatures.size() == " << tx.signatures.size() << ", tx.vin.size() == " << tx.vin.size());
for (size_t n = 0; n < tx.vin.size(); ++n)
{
if (tx.vin[n].type() == typeid(txin_to_key))
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);

View file

@ -686,26 +686,10 @@ namespace currency
template<class visitor_t>
bool blockchain_storage::scan_outputkeys_for_indexes(const transaction &validated_tx, const txin_v& verified_input, visitor_t& vis, uint64_t& max_related_block_height, scan_for_keys_context& scan_context) const
{
std::vector<txout_ref_v> key_offsets_dummy;
uint64_t amount = 0;
const std::vector<txout_ref_v>& key_offsets = [&] -> const std::vector<txout_ref_v>&
{
if (verified_input.type() == typeid(txin_htlc))
{
//hltc
const txin_htlc& htlc = boost::get<txin_htlc>(verified_input);
key_offsets_dummy.push_back(htlc.key_offset);
amount = htlc.amount;
return key_offsets_dummy;
}
else if (verified_input.type() == typeid(txin_to_key))
{
//regular to key output
const txin_to_key& to_key = boost::get<txin_to_key>(verified_input);
amount = to_key.amount;
return to_key.key_offsets;
}
};
const txin_to_key& input_to_key = get_to_key_input_from_txin_v(verified_input);
uint64_t amount = input_to_key.amount;
const std::vector<txout_ref_v>& key_offsets = input_to_key.key_offsets;
CRITICAL_REGION_LOCAL(m_read_lock);
TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_get_item_size);
@ -757,6 +741,8 @@ namespace currency
{
//HTLC input CAN'T refer to regular to_key output
CHECK_AND_ASSERT_MES(verified_input.type() != typeid(txin_htlc), false, "[TXOUT_TO_KEY]: Unexpected output type of HTLC input");
CHECKED_GET_SPECIFIC_VARIANT(tx_ptr->tx.vout[n].target, const txout_to_key, outtk, false);
//fix for burned money
patch_out_if_needed(const_cast<txout_to_key&>(outtk), tx_id, n);

View file

@ -223,21 +223,13 @@ namespace currency
END_SERIALIZE()
};
struct txin_htlc
struct txin_htlc: public txin_to_key
{
uint64_t amount;
std::string hltc_origin;
txout_ref_v key_offset;
crypto::key_image k_image; // double spending protection
std::vector<txin_etc_details_v> etc_details; //this flag used when TX_FLAG_SIGNATURE_MODE_SEPARATE flag is set, point to which amount of outputs(starting from zero) used in signature
BEGIN_SERIALIZE_OBJECT()
VARINT_FIELD(amount)
FIELD(hltc_origin)
FIELD(key_offset)
FIELD(k_image)
FIELD(etc_details)
END_SERIALIZE()
FIELDS(*static_cast<txin_to_key*>(this))
END_SERIALIZE()
};
struct txin_multisig

View file

@ -100,7 +100,7 @@ namespace boost
a & x.etc_details;
a & x.hltc_origin;
a & x.k_image;
a & x.key_offset;
a & x.key_offsets;
}
template <class Archive>

View file

@ -129,6 +129,22 @@ namespace currency
}
return found;
}
const txin_to_key& get_to_key_input_from_txin_v(const txin_v& in_v)
{
if (in_v.type() == typeid(txin_to_key))
{
return boost::get<txin_to_key>(in_v);
}
else if (in_v.type() == typeid(txin_htlc))
{
const txin_htlc& in = boost::get<txin_htlc>(in_v);
return static_cast<const txin_to_key&>(in);
}
else {
ASSERT_MES_AND_THROW("[get_to_key_input_from_txin_v] Wrong type " << in_v.type().name());
}
}
//---------------------------------------------------------------
template<typename variant_container_t>
bool check_allowed_types_in_variant_container(const variant_container_t& container, const std::unordered_set<std::type_index>& allowed_types, bool elements_must_be_unique = true)