1
0
Fork 0
forked from lthn/blockchain

verify_asset_surjection_proof() : first PoC implementation

This commit is contained in:
sowle 2023-04-04 23:22:11 +02:00
parent 4d6977b301
commit 6915213eb1
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
3 changed files with 81 additions and 3 deletions

View file

@ -1354,10 +1354,12 @@ bool blockchain_storage::validate_miner_transaction(const block& b,
return false;
}
crypto::hash tx_id_for_balance_check = b.miner_tx.version > TRANSACTION_VERSION_PRE_HF4 ? get_transaction_hash(b.miner_tx) : null_hash;
if (!check_tx_balance(b.miner_tx, tx_id_for_balance_check, base_reward + fee))
uint64_t block_reward = base_reward + fee;
crypto::hash tx_id_for_post_hf4_era = b.miner_tx.version > TRANSACTION_VERSION_PRE_HF4 ? get_transaction_hash(b.miner_tx) : null_hash;
if (!check_tx_balance(b.miner_tx, tx_id_for_post_hf4_era, block_reward))
{
LOG_ERROR("coinbase transaction balance check failed. Block reward is " << print_money_brief(base_reward + fee) << "(" << print_money(base_reward) << "+" << print_money(fee)
LOG_ERROR("coinbase transaction balance check failed. Block reward is " << print_money_brief(block_reward) << "(" << print_money(base_reward) << "+" << print_money(fee)
<< ", blocks_size_median = " << blocks_size_median
<< ", cumulative_block_size = " << cumulative_block_size
<< ", fee = " << fee
@ -1367,6 +1369,15 @@ bool blockchain_storage::validate_miner_transaction(const block& b,
return false;
}
if (b.miner_tx.version > TRANSACTION_VERSION_PRE_HF4)
{
if (!verify_asset_surjection_proof(b.miner_tx, tx_id_for_post_hf4_era))
{
LOG_ERROR("asset surjection proof verification failed for miner tx");
return false;
}
}
LOG_PRINT_MAGENTA("Mining tx verification ok, blocks_size_median = " << blocks_size_median, LOG_LEVEL_2);
return true;
}
@ -5914,6 +5925,9 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
CHECK_AND_ASSERT_MES_CUSTOM(check_tx_balance(tx, tx_id), false, cleanup(),
"block " << id << ", tx " << tx_id << ": check_tx_balance failed");
CHECK_AND_ASSERT_MES_CUSTOM(verify_asset_surjection_proof(tx, tx_id), false, cleanup(),
"block " << id << ", tx " << tx_id << ": verify_asset_surjection_proof failed");
}
TIME_MEASURE_START_PD(tx_add_one_tx_time);

View file

@ -107,6 +107,69 @@ namespace currency
return true;
}
//--------------------------------------------------------------------------------
bool verify_asset_surjection_proof(const transaction& tx, const crypto::hash& tx_id)
{
bool r = false;
if (tx.version <= TRANSACTION_VERSION_PRE_HF4)
return true;
size_t outs_count = tx.vout.size();
bool has_ZC_inputs = false;
bool has_non_ZC_inputs = false;
for(const auto& in : tx.vin)
{
if (in.type() == typeid(txin_zc_input))
has_ZC_inputs = true;
else
has_non_ZC_inputs = true;
}
if (!has_ZC_inputs)
{
// no ZC ins -- just make sure there's only native outputs with explicit asset ids
for(size_t j = 0; j < outs_count; ++j)
{
CHECK_AND_ASSERT_MES(boost::get<tx_out_zarcanum>(tx.vout[j]).blinded_asset_id == native_coin_asset_id_1div8, false, "output #" << j << " has a non explicitly native asset id");
}
return true;
}
// tx has ZC inputs
const zc_asset_surjection_proof& sig = get_type_in_variant_container_by_ref<const zc_asset_surjection_proof>(tx.proofs); // order of proofs and uniqueness of zc_asset_surjection_proof should be check before on prevalidation
CHECK_AND_ASSERT_MES(sig.bge_proofs.size() == outs_count, false, "ASP count: " << sig.bge_proofs.size() << ", outputs: " << outs_count << " => missmatch");
// make a ring
std::vector<crypto::point_t> pseudo_outs_blinded_asset_ids;
for(const auto& sig : tx.signatures)
{
if (sig.type() == typeid(ZC_sig))
pseudo_outs_blinded_asset_ids.emplace_back(crypto::point_t(boost::get<ZC_sig>(sig).pseudo_out_blinded_asset_id).modify_mul8());
}
if (has_non_ZC_inputs)
pseudo_outs_blinded_asset_ids.emplace_back(currency::native_coin_asset_id_pt); // additional ring member for txs with non-zc inputs
for(size_t j = 0; j < outs_count; ++j)
{
crypto::point_t blinded_asset_id(boost::get<tx_out_zarcanum>(tx.vout[j]).blinded_asset_id);
blinded_asset_id.modify_mul8();
// TODO @#@# remove this redundant conversion to pubkey and back
std::vector<crypto::public_key> ring(pseudo_outs_blinded_asset_ids.size());
std::vector<const crypto::public_key*> ring_pointers(pseudo_outs_blinded_asset_ids.size());
for(size_t i = 0, n = pseudo_outs_blinded_asset_ids.size(); i < n; ++i)
{
ring[i] = ((crypto::c_scalar_1div8 * (pseudo_outs_blinded_asset_ids[i] - blinded_asset_id)).to_public_key());
ring_pointers[i] = &ring[i];
}
uint8_t err = 0;
CHECK_AND_ASSERT_MES(crypto::verify_BGE_proof(tx_id, ring_pointers, sig.bge_proofs[j], &err), false, "verify_BGE_proof failed, err = " << (int)err);
}
return true;
}
//--------------------------------------------------------------------------------
bool generate_zc_outs_range_proof(const crypto::hash& context_hash, size_t out_index_start, const outputs_generation_context& outs_gen_context,
const std::vector<tx_out_v>& vouts, zc_outs_range_proof& result)
{

View file

@ -230,6 +230,7 @@ namespace currency
bool verify_multiple_zc_outs_range_proofs(const std::vector<zc_outs_range_proofs_with_commitments>& range_proofs);
bool generate_asset_surjection_proof(const crypto::hash& context_hash, bool has_non_zc_inputs, outputs_generation_context& ogc, zc_asset_surjection_proof& result);
bool verify_asset_surjection_proof(const transaction& tx, const crypto::hash& tx_id);
bool generate_tx_balance_proof(const transaction &tx, const crypto::hash& tx_id, const outputs_generation_context& ogc, uint64_t block_reward_for_miner_tx, zc_balance_proof& proof);
bool generate_zc_outs_range_proof(const crypto::hash& context_hash, size_t out_index_start, const outputs_generation_context& outs_gen_context,
const std::vector<tx_out_v>& vouts, zc_outs_range_proof& result);