1
0
Fork 0
forked from lthn/blockchain

pos_block_builder & zarcanum adaptation: WIP

This commit is contained in:
sowle 2022-10-24 21:01:45 +02:00
parent 078a7bf8b5
commit b570ca81ef
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
7 changed files with 107 additions and 69 deletions

View file

@ -46,7 +46,7 @@ namespace crypto
if (!(cond)) { LOG_PRINT_RED("zarcanum_generate_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
if (p_err) { *p_err = err_code; } return false; }
bool zarcanum_generate_proof(const hash& m, const hash& kernel_hash, const std::vector<CLSAG_GGXG_input_ref_t>& ring, const point_t& pseudo_out_amount_commitment,
bool zarcanum_generate_proof(const hash& m, const hash& kernel_hash, const std::vector<CLSAG_GGXG_input_ref_t>& ring,
const scalar_t& last_pow_block_id_hashed, const key_image& stake_ki,
const scalar_t& secret_x, const scalar_t& secret_q, uint64_t secret_index, const scalar_t& pseudo_out_blinding_mask, uint64_t stake_amount, const scalar_t& stake_blinding_mask,
zarcanum_proof& result, uint8_t* p_err /* = nullptr */)
@ -144,6 +144,7 @@ namespace crypto
// layer 3 secret (with respect to G)
// secret_q
point_t pseudo_out_amount_commitment = a * crypto::c_point_H + pseudo_out_blinding_mask * crypto::c_point_G;
result.pseudo_out_amount_commitment = (crypto::c_scalar_1div8 * pseudo_out_amount_commitment).to_public_key();
TRY_ENTRY()

View file

@ -44,7 +44,7 @@ namespace crypto
CLSAG_GGXG_signature clsag_ggxg;
};
bool zarcanum_generate_proof(const hash& m, const hash& kernel_hash, const std::vector<crypto::CLSAG_GGXG_input_ref_t>& ring, const point_t& pseudo_out_amount_commitment,
bool zarcanum_generate_proof(const hash& m, const hash& kernel_hash, const std::vector<crypto::CLSAG_GGXG_input_ref_t>& ring,
const scalar_t& last_pow_block_id_hashed, const key_image& stake_ki,
const scalar_t& secret_x, const scalar_t& secret_q, uint64_t secret_index, const scalar_t& pseudo_out_blinding_mask, uint64_t stake_amount, const scalar_t& stake_blinding_mask,
zarcanum_proof& result, uint8_t* p_err = nullptr);

View file

@ -2114,37 +2114,13 @@ namespace currency
}
LOG_PRINT2("construct_tx.log", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL << ss_ring_s.str(), LOG_LEVEL_3);
//input_index++;
//in_context_index++;
}
/*
for(const tx_source_entry& source_entry : sources)
{
crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, input_index, tx_prefix_hash);
CHECK_AND_ASSERT_MES(tx_hash_for_signature != null_hash, false, "prepare_prefix_hash_for_sign failed");
std::stringstream ss_ring_s;
if (source_entry.is_zarcanum())
{
// ZC
// blinding_masks_sum is supposed to be sum(mask of all tx output) - sum(masks of all pseudo out commitments)
r = generate_ZC_sig(tx_hash_for_signature, input_index, source_entry, in_contexts[in_context_index], sender_account_keys, blinding_masks_sum, flags, local_blinding_masks_sum, tx);
CHECK_AND_ASSERT_MES(r, false, "generate_ZC_sigs failed");
}
else
{
// NLSAG
r = generate_NLSAG_sig(tx_hash_for_signature, tx_prefix_hash, input_index, source_entry, sender_account_keys, in_contexts[in_context_index], txkey, flags, tx, &ss_ring_s);
CHECK_AND_ASSERT_MES(r, false, "generate_NLSAG_sig failed");
}
//size_t prefix_size = get_object_blobsize(static_cast<const transaction_prefix&>(tx));
//size_t full_blob_size = t_serializable_object_to_blob(tx).size();
//size_t estimated_blob_size = get_object_blobsize(tx);
//CHECK_AND_ASSERT_MES(full_blob_size == estimated_blob_size, false, "!");
LOG_PRINT2("construct_tx.log", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL << ss_ring_s.str(), LOG_LEVEL_3);
input_index++;
in_context_index++;
}
*/
return true;
}

View file

@ -9,18 +9,17 @@ namespace currency
struct pos_mining_context
{
wide_difficulty_type basic_diff;
// Zarcanum notation:
wide_difficulty_type basic_diff; // D
stake_kernel sk;
crypto::scalar_t last_pow_block_id_hashed; // f'
crypto::scalar_t secret_q; // q
boost::multiprecision::uint256_t z_l_div_z_D; // z * floor( l / (z * D) ) (max possible value (assuming z=2^64) : z * 2^252 / (z * 1) ~= 2^252)
crypto::hash kernel_hash; // h
crypto::scalar_t stake_out_blinding_mask; // f
uint64_t stake_amount; // a
crypto::scalar_t last_pow_block_id_hashed; // Zarcanum notation: f'
crypto::scalar_t secret_q; // Zarcanum notation: q
boost::multiprecision::uint256_t z_l_div_z_D; // Zarcanum notation: z * floor( l / (z * D) ) (max possible value (assuming z=2^64) : z * 2^252 / (z * 1) ~= 2^252)
crypto::hash kernel_hash; // Zarcanum notation: h
crypto::scalar_t stake_out_blinding_mask; // Zarcanum notation: f
uint64_t stake_amount;
bool zarcanum;
bool zarcanum; // false for pre-HF4 classic PoS with explicit amounts
void init(const wide_difficulty_type& pos_diff, const stake_modifier_type& sm, bool is_zarcanum);

View file

@ -3799,21 +3799,17 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, currency::bl
}
#endif
crypto::scalar_t pseudo_out_blinding_mask = blinding_masks_sum;
//process_type_in_variant_container<tx_out_zarcanum>(b.miner_tx.vout, [&](tx_out_zarcanum& o){ pseudo_out_blinding_mask += o. });
crypto::point_t pseudo_out_amount_commitment = td.m_amount * crypto::c_point_H + pseudo_out_blinding_mask * crypto::c_point_G;
crypto::hash tx_hash_for_sig = get_transaction_hash(b.miner_tx);
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
r = crypto::generate_key_derivation(source_tx_pub_key, m_account.get_keys().view_secret_key, derivation);
WLT_CHECK_AND_ASSERT_MES(r, false, "generate_key_derivation failed, tid: " << pe.wallet_index << ", pe.tx_id: " << pe.tx_id);
crypto::secret_key secret_x = AUTO_VAL_INIT(secret_x);
crypto::derive_secret_key(derivation, pe.tx_out_index, m_account.get_keys().spend_secret_key, secret_x);
crypto::hash tx_hash_for_sig = get_transaction_hash(b.miner_tx); // TODO @#@# consider adding more input data to this hash
uint8_t err = 0;
r = crypto::zarcanum_generate_proof(tx_hash_for_sig, cxt.kernel_hash, ring, pseudo_out_amount_commitment, cxt.last_pow_block_id_hashed,
pe.keyimage, secret_x, cxt.secret_q, secret_index, pseudo_out_blinding_mask, td.m_amount, *td.m_opt_blinding_mask,
r = crypto::zarcanum_generate_proof(tx_hash_for_sig, cxt.kernel_hash, ring, cxt.last_pow_block_id_hashed, pe.keyimage,
secret_x, cxt.secret_q, secret_index, blinding_masks_sum, td.m_amount, *td.m_opt_blinding_mask,
static_cast<crypto::zarcanum_proof&>(sig), &err);
WLT_CHECK_AND_ASSERT_MES(r, false, "zarcanum_generate_proof failed, err: " << (int)err);

View file

@ -14,6 +14,7 @@ void pos_block_builder::clear()
*this = pos_block_builder{};
}
void pos_block_builder::step1_init_header(const hard_forks_descriptor& hardforks, size_t block_height, crypto::hash& prev_block_hash)
{
CHECK_AND_ASSERT_THROW_MES(m_step == 0, "pos_block_builder: incorrect step sequence");
@ -26,9 +27,12 @@ void pos_block_builder::step1_init_header(const hard_forks_descriptor& hardforks
m_height = block_height;
m_context.zarcanum = hardforks.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, m_height);
m_step = 1;
}
void pos_block_builder::step2_set_txs(const std::vector<currency::transaction>& txs)
{
CHECK_AND_ASSERT_THROW_MES(m_step == 1, "pos_block_builder: incorrect step sequence");
@ -50,6 +54,7 @@ void pos_block_builder::step2_set_txs(const std::vector<currency::transaction>&
m_step = 2;
}
void pos_block_builder::step3_build_stake_kernel(
uint64_t stake_output_amount,
size_t stake_output_gindex,
@ -61,44 +66,81 @@ void pos_block_builder::step3_build_stake_kernel(
uint64_t timestamp_window,
uint64_t timestamp_step)
{
CHECK_AND_ASSERT_THROW_MES(m_step == 2, "pos_block_builder: incorrect step sequence");
m_pos_stake_amount = stake_output_amount;
m_pos_stake_output_gindex = stake_output_gindex;
step3a(difficulty, last_pow_block_hash, last_pos_block_kernel_hash);
m_stake_kernel.kimage = stake_output_key_image;
m_stake_kernel.block_timestamp = 0;
m_stake_kernel.stake_modifier.last_pow_id = last_pow_block_hash;
m_stake_kernel.stake_modifier.last_pos_kernel_id = last_pos_block_kernel_hash;
crypto::public_key stake_source_tx_pub_key {};
uint64_t stake_out_in_tx_index = UINT64_MAX;
crypto::scalar_t stake_out_blinding_mask {};
crypto::secret_key view_secret {};
step3b(stake_output_amount, stake_output_key_image, stake_source_tx_pub_key, stake_out_in_tx_index, stake_out_blinding_mask, view_secret, stake_output_gindex,
timestamp_lower_bound, timestamp_window, timestamp_step);
}
void pos_block_builder::step3a(
currency::wide_difficulty_type difficulty,
const crypto::hash& last_pow_block_hash,
const crypto::hash& last_pos_block_kernel_hash
)
{
CHECK_AND_ASSERT_THROW_MES(m_step == 2, "pos_block_builder: incorrect step sequence");
stake_modifier_type sm{};
sm.last_pow_id = last_pow_block_hash;
sm.last_pos_kernel_id = last_pos_block_kernel_hash;
if (last_pos_block_kernel_hash == null_hash)
{
bool r = string_tools::parse_tpod_from_hex_string(POS_STARTER_KERNEL_HASH, m_stake_kernel.stake_modifier.last_pos_kernel_id);
bool r = string_tools::parse_tpod_from_hex_string(POS_STARTER_KERNEL_HASH, sm.last_pos_kernel_id);
CHECK_AND_ASSERT_THROW_MES(r, "Failed to parse POS_STARTER_KERNEL_HASH");
}
wide_difficulty_type stake_difficulty = difficulty / stake_output_amount;
m_context.init(difficulty, sm, m_context.zarcanum);
m_step = 31;
}
void pos_block_builder::step3b(
uint64_t stake_output_amount,
const crypto::key_image& stake_output_key_image,
const crypto::public_key& stake_source_tx_pub_key, // zarcanum only
uint64_t stake_out_in_tx_index, // zarcanum only
const crypto::scalar_t& stake_out_blinding_mask, // zarcanum only
const crypto::secret_key& view_secret, // zarcanum only
size_t stake_output_gindex,
uint64_t timestamp_lower_bound,
uint64_t timestamp_window,
uint64_t timestamp_step)
{
CHECK_AND_ASSERT_THROW_MES(m_step == 31, "pos_block_builder: incorrect step sequence");
m_pos_stake_output_gindex = stake_output_gindex;
m_context.prepare_entry(stake_output_amount, stake_output_key_image, stake_source_tx_pub_key, stake_out_in_tx_index, stake_out_blinding_mask, view_secret);
// align timestamp_lower_bound up to timestamp_step boundary if needed
if (timestamp_lower_bound % timestamp_step != 0)
timestamp_lower_bound = timestamp_lower_bound - (timestamp_lower_bound % timestamp_step) + timestamp_step;
bool sk_found = false;
for (uint64_t ts = timestamp_lower_bound; !sk_found && ts < timestamp_lower_bound + timestamp_window; ts += timestamp_step)
{
m_stake_kernel.block_timestamp = ts;
crypto::hash sk_hash = crypto::cn_fast_hash(&m_stake_kernel, sizeof(m_stake_kernel));
if (check_hash(sk_hash, stake_difficulty))
{
if (m_context.do_iteration(ts))
sk_found = true;
}
}
if (!sk_found)
ASSERT_MES_AND_THROW("Could't build stake kernel");
// update block header with found timestamp
m_block.timestamp = m_stake_kernel.block_timestamp;
m_block.timestamp = m_context.sk.block_timestamp;
m_step = 3;
}
void pos_block_builder::step4_generate_coinbase_tx(size_t median_size,
const boost::multiprecision::uint128_t& already_generated_coins,
const account_public_address &reward_and_stake_receiver_address,
@ -110,6 +152,7 @@ void pos_block_builder::step4_generate_coinbase_tx(size_t median_size,
step4_generate_coinbase_tx(median_size, already_generated_coins, reward_and_stake_receiver_address, reward_and_stake_receiver_address, extra_nonce, max_outs, alias, tx_one_time_key);
}
void pos_block_builder::step4_generate_coinbase_tx(size_t median_size,
const boost::multiprecision::uint128_t& already_generated_coins,
const account_public_address &reward_receiver_address,
@ -123,7 +166,7 @@ void pos_block_builder::step4_generate_coinbase_tx(size_t median_size,
// generate miner tx using incorrect current_block_size only for size estimation
size_t estimated_block_size = m_txs_total_size;
bool r = construct_homemade_pos_miner_tx(m_height, median_size, already_generated_coins, estimated_block_size, m_total_fee, m_pos_stake_amount, m_stake_kernel.kimage,
bool r = construct_homemade_pos_miner_tx(m_height, median_size, already_generated_coins, estimated_block_size, m_total_fee, m_context.stake_amount, m_context.sk.kimage,
m_pos_stake_output_gindex, reward_receiver_address, stakeholder_address, m_block.miner_tx, extra_nonce, max_outs, tx_one_time_key);
CHECK_AND_ASSERT_THROW_MES(r, "construct_homemade_pos_miner_tx failed");
@ -131,7 +174,7 @@ void pos_block_builder::step4_generate_coinbase_tx(size_t median_size,
size_t cumulative_size = 0;
for (size_t try_count = 0; try_count != 10; ++try_count)
{
r = construct_homemade_pos_miner_tx(m_height, median_size, already_generated_coins, estimated_block_size, m_total_fee, m_pos_stake_amount, m_stake_kernel.kimage,
r = construct_homemade_pos_miner_tx(m_height, median_size, already_generated_coins, estimated_block_size, m_total_fee, m_context.stake_amount, m_context.sk.kimage,
m_pos_stake_output_gindex, reward_receiver_address, stakeholder_address, m_block.miner_tx, extra_nonce, max_outs, tx_one_time_key);
CHECK_AND_ASSERT_THROW_MES(r, "construct_homemade_pos_miner_tx failed");
@ -152,6 +195,7 @@ void pos_block_builder::step4_generate_coinbase_tx(size_t median_size,
m_step = 4;
}
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)
{
CHECK_AND_ASSERT_THROW_MES(m_step == 4, "pos_block_builder: incorrect step sequence");
@ -166,11 +210,12 @@ void pos_block_builder::step5_sign(const crypto::public_key& stake_tx_pub_key, s
// sign block actually in coinbase transaction
crypto::hash block_hash = currency::get_block_hash(m_block);
std::vector<const crypto::public_key*> keys_ptrs(1, &stake_tx_out_pub_key);
crypto::generate_ring_signature(block_hash, m_stake_kernel.kimage, keys_ptrs, derived_secret_ephemeral_key, 0, &boost::get<currency::NLSAG_sig>(m_block.miner_tx.signatures[0]).s[0]);
crypto::generate_ring_signature(block_hash, m_context.sk.kimage, keys_ptrs, derived_secret_ephemeral_key, 0, &boost::get<currency::NLSAG_sig>(m_block.miner_tx.signatures[0]).s[0]);
m_step = 5;
}
bool construct_homemade_pos_miner_tx(size_t height, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins,
size_t current_block_size,
uint64_t fee,
@ -271,6 +316,7 @@ bool construct_homemade_pos_miner_tx(size_t height, size_t median_size, const bo
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)
{

View file

@ -27,6 +27,26 @@ struct pos_block_builder
uint64_t timestamp_lower_bound,
uint64_t timestamp_window = POS_SCAN_WINDOW,
uint64_t timestamp_step = POS_SCAN_STEP);
void pos_block_builder::step3a(
currency::wide_difficulty_type difficulty,
const crypto::hash& last_pow_block_hash,
const crypto::hash& last_pos_block_kernel_hash
);
void pos_block_builder::step3b(
uint64_t stake_output_amount,
const crypto::key_image& stake_output_key_image,
const crypto::public_key& stake_source_tx_pub_key,
uint64_t stake_out_in_tx_index,
const crypto::scalar_t& stake_out_blinding_mask,
const crypto::secret_key& view_secret,
size_t stake_output_gindex,
uint64_t timestamp_lower_bound,
uint64_t timestamp_window,
uint64_t timestamp_step);
void step4_generate_coinbase_tx(size_t median_size,
const boost::multiprecision::uint128_t& already_generated_coins,
@ -51,12 +71,12 @@ struct pos_block_builder
size_t m_step = 0;
size_t m_txs_total_size = 0;
uint64_t m_total_fee = 0;
currency::stake_kernel m_stake_kernel {};
//currency::stake_kernel m_stake_kernel {};
size_t m_height = 0;
size_t m_pos_stake_output_gindex = 0;
uint64_t m_pos_stake_amount = 0;
//uint64_t m_pos_stake_amount = 0;
bool m_zarcanum = false;
currency::pos_mining_context m_context {};
};
bool construct_homemade_pos_miner_tx(size_t height, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins,