1
0
Fork 0
forked from lthn/blockchain

coretests: pos_block_builder now supports Zarcanum

This commit is contained in:
sowle 2022-11-11 19:10:50 +01:00
parent d0862e7be8
commit e02d15a170
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC

View file

@ -198,7 +198,7 @@ void pos_block_builder::step4_generate_coinbase_tx(size_t median_size,
m_step = 4;
}
// supports Zarcanum and mixins
void pos_block_builder::step5_sign(const currency::tx_source_entry& se, const currency::account_keys& stakeholder_keys)
{
bool r = false;
@ -219,22 +219,20 @@ void pos_block_builder::step5_sign(const currency::tx_source_entry& se, const cu
stake_input.k_image = m_context.sk.kimage;
for(const auto& oe : se.outputs)
std::vector<crypto::CLSAG_GGXG_input_ref_t> ring;
for(const auto& el : se.outputs)
{
//oe.
stake_input.key_offsets.push_back(el.out_reference);
ring.emplace_back(el.stealth_address, el.amount_commitment, el.concealing_point);
}
stake_input.key_offsets.push_back(m_pos_stake_output_gindex); // TODO: support decoys
r = absolute_sorted_output_offsets_to_relative_in_place(stake_input.key_offsets);
CHECK_AND_ASSERT_THROW_MES(r, "absolute_sorted_output_offsets_to_relative_in_place failed");
crypto::hash tx_hash_for_sig = get_transaction_hash(m_block.miner_tx); // TODO @#@# change to block hash after the corresponding test is made
std::vector<crypto::CLSAG_GGXG_input_ref_t> ring;
uint64_t secret_index = 0; // index of the real stake output
uint8_t err = 0;
r = crypto::zarcanum_generate_proof(tx_hash_for_sig, m_context.kernel_hash, ring, m_context.last_pow_block_id_hashed, m_context.sk.kimage,
secret_x, m_context.secret_q, secret_index, m_blinding_masks_sum, m_context.stake_amount, m_context.stake_out_blinding_mask,
secret_x, m_context.secret_q, se.real_output, m_blinding_masks_sum, m_context.stake_amount, m_context.stake_out_blinding_mask,
static_cast<crypto::zarcanum_proof&>(sig), &err);
CHECK_AND_ASSERT_THROW_MES(r, "zarcanum_generate_proof failed, err: " << (int)err);
}
@ -261,201 +259,17 @@ void pos_block_builder::step5_sign(const currency::tx_source_entry& se, const cu
void pos_block_builder::step5_sign(const crypto::public_key& stake_tx_pub_key, size_t stake_tx_out_index, const crypto::public_key& stake_tx_out_pub_key,
const currency::account_base& stakeholder_account)
{
bool r = false;
CHECK_AND_ASSERT_THROW_MES(m_step == 4, "pos_block_builder: incorrect step sequence");
CHECK_AND_ASSERT_THROW_MES(!m_context.zarcanum, "for zarcanum use another overloading");
// calculate stake_out_derivation and secret_x (derived ephemeral secret key)
crypto::key_derivation stake_out_derivation = AUTO_VAL_INIT(stake_out_derivation);
r = crypto::generate_key_derivation(stake_tx_pub_key, stakeholder_account.get_keys().view_secret_key, stake_out_derivation); // d = 8 * v * R
CHECK_AND_ASSERT_THROW_MES(r, "generate_key_derivation failed");
crypto::secret_key secret_x = AUTO_VAL_INIT(secret_x);
crypto::derive_secret_key(stake_out_derivation, stake_tx_out_index, stakeholder_account.get_keys().spend_secret_key, secret_x); // x = Hs(8 * v * R, i) + s
tx_source_entry se{};
if (m_context.zarcanum)
{
// Zarcanum
zarcanum_sig& sig = boost::get<zarcanum_sig>(m_block.miner_tx.signatures[0]);
txin_zc_input& stake_input = boost::get<txin_zc_input>(m_block.miner_tx.vin[1]);
se.real_out_tx_key = stake_tx_pub_key;
se.real_output_in_tx_index = stake_tx_out_index;
se.outputs.emplace_back(m_pos_stake_output_gindex, stake_tx_out_pub_key);
stake_input.k_image = m_context.sk.kimage;
stake_input.key_offsets.push_back(m_pos_stake_output_gindex); // TODO: support decoys
crypto::hash tx_hash_for_sig = get_transaction_hash(m_block.miner_tx); // TODO @#@# change to block hash after the corresponding test is made
std::vector<crypto::CLSAG_GGXG_input_ref_t> ring;
uint64_t secret_index = 0; // index of the real stake output
uint8_t err = 0;
r = crypto::zarcanum_generate_proof(tx_hash_for_sig, m_context.kernel_hash, ring, m_context.last_pow_block_id_hashed, m_context.sk.kimage,
secret_x, m_context.secret_q, secret_index, m_blinding_masks_sum, m_context.stake_amount, m_context.stake_out_blinding_mask,
static_cast<crypto::zarcanum_proof&>(sig), &err);
CHECK_AND_ASSERT_THROW_MES(r, "zarcanum_generate_proof failed, err: " << (int)err);
}
else
{
// old PoS with non-hidden amounts
NLSAG_sig& sig = boost::get<NLSAG_sig>(m_block.miner_tx.signatures[0]);
txin_to_key& stake_input = boost::get<txin_to_key>(m_block.miner_tx.vin[1]);
stake_input.k_image = m_context.sk.kimage;
stake_input.amount = m_context.stake_amount;
stake_input.key_offsets.push_back(m_pos_stake_output_gindex);
crypto::hash block_hash = currency::get_block_hash(m_block);
std::vector<const crypto::public_key*> keys_ptrs(1, &stake_tx_out_pub_key);
sig.s.resize(1);
crypto::generate_ring_signature(block_hash, m_context.sk.kimage, keys_ptrs, secret_x, 0, sig.s.data());
}
m_step = 5;
step5_sign(se, stakeholder_account.get_keys());
}
/*
void pos_block_builder::step5_sign_zarcanum(const crypto::public_key& stake_tx_pub_key, size_t stake_tx_out_index, const currency::account_base& stakeholder_account)
{
CHECK_AND_ASSERT_THROW_MES(m_step == 4, "pos_block_builder: incorrect step sequence");
CHECK_AND_ASSERT_THROW_MES(m_block.miner_tx.signatures.size() == 1, "pos_block_builder: incorrect size of miner_tx signatures: " << m_block.miner_tx.signatures.size());
zarcanum_sig& sig = boost::get<zarcanum_sig>(m_block.miner_tx.signatures[0]);
crypto::key_derivation pos_coin_derivation{};
bool r = crypto::generate_key_derivation(stake_tx_pub_key, stakeholder_account.get_keys().view_secret_key, pos_coin_derivation); // v * 8 * R
CHECK_AND_ASSERT_THROW_MES(r, "generate_key_derivation failed");
crypto::secret_key secret_x{};
crypto::derive_secret_key(pos_coin_derivation, stake_tx_out_index, stakeholder_account.get_keys().spend_secret_key, secret_x); // x = s + Hs(v * 8 * R, i)
std::vector<crypto::CLSAG_GGXG_input_ref_t> ring;
uint64_t secret_index = 0;
crypto::scalar_t blinding_masks_sum;
crypto::hash tx_hash_for_sig = get_transaction_hash(m_block.miner_tx); // TODO @#@# change to currency::get_block_hash(m_block);
uint8_t err = 0;
r = crypto::zarcanum_generate_proof(tx_hash_for_sig, m_context.kernel_hash, ring, m_context.last_pow_block_id_hashed, m_context.sk.kimage,
secret_x, m_context.secret_q, secret_index, blinding_masks_sum, m_context.stake_amount, m_context.stake_out_blinding_mask,
static_cast<crypto::zarcanum_proof&>(sig), &err);
CHECK_AND_ASSERT_THROW_MES(r, "zarcanum_generate_proof failed, err: " << (int)err);
m_step = 5;
}
*/
/*
bool construct_homemade_pos_miner_tx(bool zarcanum, size_t height, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins,
size_t current_block_size,
uint64_t fee,
uint64_t pos_stake_amount,
crypto::key_image pos_stake_keyimage,
size_t pos_stake_gindex,
const account_public_address &reward_receiving_address,
const account_public_address &stakeholder_address,
transaction& tx,
const blobdata& extra_nonce, //= blobdata(),
size_t max_outs, //= CURRENCY_MINER_TX_MAX_OUTS,
keypair tx_one_time_key, //= keypair::generate())
{
tx = transaction{};
tx.version = zarcanum ? TRANSACTION_VERSION_POST_HF4 : TRANSACTION_VERSION_PRE_HF4;
set_tx_unlock_time(tx, height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
// calculate block reward
uint64_t block_reward;
bool r = get_block_reward(true, median_size, current_block_size, already_generated_coins, block_reward, height);
CHECK_AND_ASSERT_MES(r, false, "get_block_reward failed");
block_reward += fee;
//
// prepare destinations
//
// 1. split block_reward into out_amounts
std::vector<size_t> out_amounts;
if (tx.version > TRANSACTION_VERSION_PRE_HF4)
{
// randomly split into CURRENCY_TX_MIN_ALLOWED_OUTS outputs
decompose_amount_randomly(block_reward, [&](uint64_t a){ out_amounts.push_back(a); }, CURRENCY_TX_MIN_ALLOWED_OUTS);
}
else
{
// non-hidden outs: split into digits
decompose_amount_into_digits(block_reward, DEFAULT_DUST_THRESHOLD,
[&out_amounts](uint64_t a_chunk) { out_amounts.push_back(a_chunk); },
[&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); });
CHECK_AND_ASSERT_MES(1 <= max_outs, false, "max_out must be non-zero");
while (max_outs < out_amounts.size())
{
out_amounts[out_amounts.size() - 2] += out_amounts.back();
out_amounts.resize(out_amounts.size() - 1);
}
}
// reward
bool burn_money = reward_receiving_address.spend_public_key == null_pkey && reward_receiving_address.view_public_key == null_pkey; // if true, burn reward, so no one on Earth can spend them
for (size_t output_index = 0; output_index < out_amounts.size(); ++output_index)
{
txout_to_key tk;
tk.key = null_pkey; // null means burn money
tk.mix_attr = 0;
if (!burn_money)
{
r = currency::derive_public_key_from_target_address(reward_receiving_address, tx_one_time_key.sec, output_index, tk.key); // derivation(view_pub; tx_sec).derive(output_index, spend_pub) => output pub key
CHECK_AND_ASSERT_MES(r, false, "failed to derive_public_key_from_target_address");
}
tx_out_bare out;
out.amount = out_amounts[output_index];
out.target = tk;
tx.vout.push_back(out);
}
// stake
burn_money = stakeholder_address.spend_public_key == null_pkey && stakeholder_address.view_public_key == null_pkey; // if true, burn stake
{
txout_to_key tk;
tk.key = null_pkey; // null means burn money
tk.mix_attr = 0;
if (!burn_money)
{
r = currency::derive_public_key_from_target_address(stakeholder_address, tx_one_time_key.sec, tx.vout.size(), tk.key);
CHECK_AND_ASSERT_MES(r, false, "failed to derive_public_key_from_target_address");
}
tx_out_bare out;
out.amount = pos_stake_amount;
out.target = tk;
tx.vout.push_back(out);
}
// take care about extra
add_tx_pub_key_to_extra(tx, tx_one_time_key.pub);
if (extra_nonce.size())
if (!add_tx_extra_userdata(tx, extra_nonce))
return false;
// populate ins with 1) money-generating and 2) PoS
txin_gen in;
in.height = height;
tx.vin.push_back(in);
txin_to_key posin;
posin.amount = pos_stake_amount;
posin.key_offsets.push_back(pos_stake_gindex);
posin.k_image = pos_stake_keyimage;
tx.vin.push_back(posin);
//reserve place for ring signature
tx.signatures.resize(1);
boost::get<currency::NLSAG_sig>(tx.signatures[0]).s.resize(posin.key_offsets.size());
return true;
}
*/
bool mine_next_pos_block_in_playtime_sign_cb(currency::core& c, const currency::block& prev_block, const currency::block& coinstake_scr_block, const currency::account_base& acc,
std::function<bool(currency::block&)> before_sign_cb, currency::block& output)