forked from lthn/blockchain
coretests: pos_block_builder now supports Zarcanum
This commit is contained in:
parent
d0862e7be8
commit
e02d15a170
1 changed files with 14 additions and 200 deletions
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue