forked from lthn/blockchain
bcs: range proofs collection, aggragation and balance checking refactored & improved
This commit is contained in:
parent
7efe48f522
commit
5fbb7a7fbb
4 changed files with 58 additions and 50 deletions
|
|
@ -1324,19 +1324,20 @@ bool blockchain_storage::prevalidate_miner_transaction(const block& b, uint64_t
|
|||
{
|
||||
if (pos)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.attachment.size() == 1, false, "coinbase transaction has incorrect number of attachments (" << b.miner_tx.attachment.size() << "), expected 2");
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.attachment[0].type() == typeid(zc_outs_range_proof), false, "coinbase transaction wrong attachment #0 type (expected: zc_outs_range_proof)");
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.proofs.size() == 1, false, "coinbase transaction has incorrect number of proofs (" << b.miner_tx.proofs.size() << "), expected 2");
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.proofs[0].type() == typeid(zc_outs_range_proof), false, "coinbase transaction has incorrect type of proof #0 (expected: zc_outs_range_proof)");
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.attachment.size() == 2, false, "coinbase transaction has incorrect number of attachments (" << b.miner_tx.attachment.size() << "), expected 2");
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.attachment[0].type() == typeid(zc_outs_range_proof), false, "coinbase transaction wrong attachment #0 type (expected: zc_outs_range_proof)");
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.attachment[1].type() == typeid(zc_balance_proof), false, "coinbase transaction wrong attachmenttype #1 (expected: zc_balance_proof)");
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.proofs.size() == 2, false, "coinbase transaction has incorrect number of proofs (" << b.miner_tx.proofs.size() << "), expected 2");
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.proofs[0].type() == typeid(zc_outs_range_proof), false, "coinbase transaction has incorrect type of proof #0 (expected: zc_outs_range_proof)");
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.proofs[1].type() == typeid(zc_balance_proof), false, "coinbase transaction has incorrect type of proof #1 (expected: zc_balance_proof)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.attachment.empty(), false, "coinbase transaction has attachments; attachments are not allowed for coinbase transactions.");
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.proofs.size() == 0, false, "pre-HF4 coinbase shoudn't have non-empty proofs containter");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -5706,21 +5707,32 @@ bool get_tx_from_cache(const crypto::hash& tx_id, transactions_map& tx_cache, tr
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::collect_rangeproofs_data_from_tx(std::vector<zc_outs_range_proofs_with_commitments>& agregated_proofs, const transaction& tx)
|
||||
bool blockchain_storage::collect_rangeproofs_data_from_tx(const transaction& tx, const crypto::hash& tx_id, std::vector<zc_outs_range_proofs_with_commitments>& agregated_proofs)
|
||||
{
|
||||
if (tx.version <= TRANSACTION_VERSION_PRE_HF4)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO @#@# Verify somewhere(maybe here) that all outputs are covered with associated rangeproofs
|
||||
size_t proofs_count = 0;
|
||||
size_t current_output_start = 0; //for Consolidated Transactions we'll have multiple zc_outs_range_proof entries
|
||||
size_t range_proofs_count = 0;
|
||||
size_t out_index_offset = 0; //Consolidated Transactions have multiple zc_outs_range_proof entries
|
||||
for (const auto& a : tx.proofs)
|
||||
{
|
||||
if (a.type() == typeid(zc_outs_range_proof))
|
||||
{
|
||||
const zc_outs_range_proof& zcrp = boost::get<zc_outs_range_proof>(a);
|
||||
|
||||
// validate aggregation proof
|
||||
std::vector<const crypto::public_key*> amount_commitment_ptrs_1div8, blinded_asset_id_ptrs_1div8;
|
||||
for(size_t j = out_index_offset; j < tx.vout.size(); ++j)
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(tx.vout[j], const tx_out_zarcanum, zcout, false);
|
||||
amount_commitment_ptrs_1div8.push_back(&zcout.amount_commitment);
|
||||
blinded_asset_id_ptrs_1div8.push_back(&zcout.blinded_asset_id);
|
||||
}
|
||||
uint8_t err = 0;
|
||||
bool r = crypto::verify_vector_UG_aggregation_proof(tx_id, amount_commitment_ptrs_1div8, blinded_asset_id_ptrs_1div8, zcrp.aggregation_proof, &err);
|
||||
CHECK_AND_ASSERT_MES(r, false, "verify_vector_UG_aggregation_proof failed with err code " << (int)err);
|
||||
|
||||
|
||||
agregated_proofs.emplace_back(zcrp);
|
||||
|
||||
// convert amount commitments for aggregation from public_key to point_t form
|
||||
|
|
@ -5728,13 +5740,14 @@ bool blockchain_storage::collect_rangeproofs_data_from_tx(std::vector<zc_outs_ra
|
|||
for (uint8_t i = 0; i != zcrp.aggregation_proof.amount_commitments_for_rp_aggregation.size(); i++)
|
||||
agregated_proofs.back().amount_commitments.emplace_back(zcrp.aggregation_proof.amount_commitments_for_rp_aggregation[i]);
|
||||
|
||||
current_output_start += zcrp.aggregation_proof.amount_commitments_for_rp_aggregation.size();
|
||||
proofs_count++;
|
||||
out_index_offset += zcrp.aggregation_proof.amount_commitments_for_rp_aggregation.size();
|
||||
range_proofs_count++;
|
||||
}
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(proofs_count > 0, false, "transaction " << get_transaction_hash(tx) << " don't have range_proofs");
|
||||
CHECK_AND_ASSERT_MES(proofs_count == 1 || (get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE), false, "transaction " << get_transaction_hash(tx)
|
||||
<< " has TX_FLAG_SIGNATURE_MODE_SEPARATE but proofs_count = " << proofs_count);
|
||||
CHECK_AND_ASSERT_MES(out_index_offset == tx.vout.size(), false, "range proof elements count doesn't match with outputs count: " << out_index_offset << " != " << tx.vout.size());
|
||||
CHECK_AND_ASSERT_MES(range_proofs_count > 0, false, "transaction " << get_transaction_hash(tx) << " doesn't have range proofs");
|
||||
CHECK_AND_ASSERT_MES(range_proofs_count == 1 || (get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE), false, "transaction " << get_transaction_hash(tx)
|
||||
<< " doesn't have TX_FLAG_SIGNATURE_MODE_SEPARATE but has range_proofs_count = " << range_proofs_count);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -5901,7 +5914,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
{
|
||||
auto cleanup = [&](){ purge_block_data_from_blockchain(bl, tx_processed_count); bvc.m_verification_failed = true; };
|
||||
|
||||
CHECK_AND_ASSERT_MES_CUSTOM(collect_rangeproofs_data_from_tx(range_proofs_agregated, tx/*, tx_outs_commitments*/), false, cleanup(),
|
||||
CHECK_AND_ASSERT_MES_CUSTOM(collect_rangeproofs_data_from_tx(tx, tx_id, range_proofs_agregated), false, cleanup(),
|
||||
"block " << id << ", tx " << tx_id << ": collect_rangeproofs_data_from_tx failed");
|
||||
|
||||
CHECK_AND_ASSERT_MES_CUSTOM(check_tx_balance(tx, tx_id), false, cleanup(),
|
||||
|
|
@ -5986,7 +5999,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!collect_rangeproofs_data_from_tx(range_proofs_agregated, bl.miner_tx))
|
||||
if (!collect_rangeproofs_data_from_tx(bl.miner_tx, get_transaction_hash(bl.miner_tx), range_proofs_agregated))
|
||||
{
|
||||
LOG_PRINT_L0("Block with id: " << id
|
||||
<< " have wrong miner tx, failed to collect_rangeproofs_data_from_tx()");
|
||||
|
|
|
|||
|
|
@ -593,7 +593,7 @@ namespace currency
|
|||
wide_difficulty_type get_next_difficulty_for_alternative_chain(const alt_chain_type& alt_chain, block_extended_info& bei, bool pos) const;
|
||||
bool handle_block_to_main_chain(const block& bl, block_verification_context& bvc);
|
||||
bool handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc);
|
||||
bool collect_rangeproofs_data_from_tx(std::vector<zc_outs_range_proofs_with_commitments>& agregated_proofs, const transaction& tx);
|
||||
bool collect_rangeproofs_data_from_tx(const transaction& tx, const crypto::hash& tx_id, std::vector<zc_outs_range_proofs_with_commitments>& agregated_proofs);
|
||||
std::string print_alt_chain(alt_chain_type alt_chain);
|
||||
bool handle_alternative_block(const block& b, const crypto::hash& id, block_verification_context& bvc);
|
||||
bool is_reorganize_required(const block_extended_info& main_chain_bei, const alt_chain_type& alt_chain, const crypto::hash& proof_alt);
|
||||
|
|
|
|||
|
|
@ -154,8 +154,24 @@ namespace currency
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
bool verify_multiple_zc_outs_range_proofs(const std::vector<zc_outs_range_proofs_with_commitments>& range_proofs)
|
||||
{
|
||||
if (range_proofs.empty())
|
||||
return true;
|
||||
|
||||
std::vector<crypto::bpp_sig_commit_ref_t> sigs;
|
||||
sigs.reserve(range_proofs.size());
|
||||
for(auto& el : range_proofs)
|
||||
sigs.emplace_back(el.range_proof.bpp, el.amount_commitments);
|
||||
|
||||
uint8_t err = 0;
|
||||
bool r = crypto::bpp_verify<>(sigs, &err);
|
||||
CHECK_AND_ASSERT_MES(r, false, "bpp_verify failed with error " << (int)err);
|
||||
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
wide_difficulty_type correct_difficulty_with_sequence_factor(size_t sequence_factor, wide_difficulty_type diff)
|
||||
{
|
||||
//delta=delta*(0.75^n)
|
||||
|
|
@ -171,6 +187,7 @@ namespace currency
|
|||
{
|
||||
CHECK_AND_ASSERT_MES(tx.version > TRANSACTION_VERSION_PRE_HF4, false, "unsupported tx.version: " << tx.version);
|
||||
CHECK_AND_ASSERT_MES(count_type_in_variant_container<ZC_sig>(tx.signatures) == 0, false, "ZC_sig is unexpected");
|
||||
CHECK_AND_ASSERT_MES(outs_gen_context.asset_id_blinding_masks_sum.is_zero(), false, "it's expected that all asset ids for this tx are non-blinded"); // because this tx has no ZC inputs => all outs clearly have native asset id
|
||||
|
||||
uint64_t bare_inputs_sum = block_reward_for_miner_tx;
|
||||
// TODO: condider remove the followin cycle
|
||||
|
|
@ -200,18 +217,18 @@ namespace currency
|
|||
uint64_t fee = 0;
|
||||
CHECK_AND_ASSERT_MES(get_tx_fee(tx, fee), false, "unable to get tx fee");
|
||||
|
||||
// sum(bare inputs' amounts) * H + sum(pseudo outs commitments for ZC inputs) + residual * G = sum(outputs' commitments) + fee * H
|
||||
// <=>
|
||||
// (fee - sum(bare inputs' amounts)) * H - sum(pseudo outs commitments for ZC inputs) + sum(outputs' commitments) = residual * G
|
||||
// (sum(bare inputs' amounts) - fee) * H + sum(pseudo outs commitments for ZC inputs) - sum(outputs' commitments) = lin(G)
|
||||
|
||||
// tx doesn't have any zc inputs --> add Schnorr proof for commitment to zero
|
||||
// tx doesn't already have any zc inputs --> add Schnorr proof for commitment to zero
|
||||
CHECK_AND_ASSERT_MES(count_type_in_variant_container<zc_balance_proof>(tx.proofs) == 0, false, "");
|
||||
zc_balance_proof balance_proof = AUTO_VAL_INIT(balance_proof);
|
||||
|
||||
crypto::point_t commitment_to_zero = outs_commitments_sum + (crypto::scalar_t(fee) - crypto::scalar_t(bare_inputs_sum)) * crypto::c_point_H;
|
||||
//crypto::scalar_t witness = outputs_blinding_masks_sum;
|
||||
|
||||
crypto::generate_signature(tx_id, commitment_to_zero.to_public_key(), outs_gen_context.amount_blinding_masks_sum.as_secret_key(), balance_proof.s);
|
||||
crypto::point_t commitment_to_zero = (crypto::scalar_t(bare_inputs_sum) - crypto::scalar_t(fee)) * crypto::c_point_H - outs_commitments_sum;
|
||||
crypto::scalar_t secret_x = -outs_gen_context.amount_blinding_masks_sum;
|
||||
#ifndef NDEBUG
|
||||
CHECK_AND_ASSERT_MES(commitment_to_zero == secret_x * crypto::c_point_G, false, "internal error: commitment_to_zero is malformed");
|
||||
#endif
|
||||
crypto::generate_signature(tx_id, commitment_to_zero.to_public_key(), secret_x.as_secret_key(), balance_proof.s);
|
||||
tx.proofs.emplace_back(std::move(balance_proof));
|
||||
|
||||
return true;
|
||||
|
|
@ -4134,23 +4151,6 @@ namespace currency
|
|||
return a.n == b.n && a.tx_id == b.tx_id;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
bool verify_multiple_zc_outs_range_proofs(const std::vector<zc_outs_range_proofs_with_commitments>& range_proofs)
|
||||
{
|
||||
if (range_proofs.empty())
|
||||
return true;
|
||||
|
||||
std::vector<crypto::bpp_sig_commit_ref_t> sigs;
|
||||
sigs.reserve(range_proofs.size());
|
||||
for(auto& el : range_proofs)
|
||||
sigs.emplace_back(el.range_proof.bpp, el.amount_commitments);
|
||||
|
||||
uint8_t err = 0;
|
||||
bool r = crypto::bpp_verify<>(sigs, &err);
|
||||
CHECK_AND_ASSERT_MES(r, false, "bpp_verify failed with error " << (int)err);
|
||||
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
boost::multiprecision::uint1024_t get_a_to_b_relative_cumulative_difficulty(const wide_difficulty_type& difficulty_pos_at_split_point,
|
||||
|
|
|
|||
|
|
@ -33,11 +33,6 @@ namespace currency
|
|||
return expiration_time <= expiration_ts_median + TX_EXPIRATION_MEDIAN_SHIFT;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uint64_t get_burned_amount(const transaction& tx)
|
||||
{
|
||||
uint64_t res = 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue