Merge branch 'zarcanum' into multiassets
This commit is contained in:
commit
b6fd8314ca
16 changed files with 443 additions and 208 deletions
|
|
@ -27,7 +27,7 @@ namespace crypto
|
|||
#define DBG_PRINT(x) (void(0)) //*/ std::cout << x << ENDL
|
||||
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("bpp_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
|
||||
if (!(cond)) { LOG_PRINT_RED("bpp_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
|
||||
|
|
@ -355,7 +355,7 @@ namespace crypto
|
|||
bool bpp_verify(const std::vector<bpp_sig_commit_ref_t>& sigs, uint8_t* p_err = nullptr)
|
||||
{
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("bpp_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
|
||||
if (!(cond)) { LOG_PRINT_RED("bpp_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
DBG_PRINT(ENDL << " . . . . bpp_verify() . . . . ");
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace crypto
|
|||
#define DBG_PRINT(x) (void(0)) // std::cout << x << ENDL
|
||||
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("bppe_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
|
||||
if (!(cond)) { LOG_PRINT_RED("bppe_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
|
||||
|
|
@ -366,7 +366,7 @@ namespace crypto
|
|||
bool bppe_verify(const std::vector<bppe_sig_commit_ref_t>& sigs, uint8_t* p_err = nullptr)
|
||||
{
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("bppe_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
|
||||
if (!(cond)) { LOG_PRINT_RED("bppe_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
DBG_PRINT(ENDL << " . . . . bppe_verify() . . . . ");
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ namespace crypto
|
|||
const scalar_t c_zarcanum_z_coeff_s = { 0, 1, 0, 0 }; // c_scalar_2p64
|
||||
const mp::uint256_t c_zarcanum_z_coeff_mp = c_zarcanum_z_coeff_s.as_boost_mp_type<mp::uint256_t>();
|
||||
|
||||
#define DBG_VAL_PRINT(x) (void(0)) // std::cout << #x ": " << x << std::endl
|
||||
#define DBG_PRINT(x) (void(0)) // std::cout << x << std::endl
|
||||
|
||||
|
||||
mp::uint256_t zarcanum_precalculate_l_div_z_D(const mp::uint128_t& pos_difficulty)
|
||||
{
|
||||
//LOG_PRINT_GREEN_L0(ENDL << "floor( l / (z * D) ) = " << c_scalar_L.as_boost_mp_type<mp::uint256_t>() / (c_zarcanum_z_coeff_mp * pos_difficulty));
|
||||
|
|
@ -43,7 +47,7 @@ namespace crypto
|
|||
}
|
||||
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("zarcanum_generate_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
|
||||
if (!(cond)) { LOG_PRINT_RED("zarcanum_generate_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)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,
|
||||
|
|
@ -51,6 +55,7 @@ namespace crypto
|
|||
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 */)
|
||||
{
|
||||
DBG_PRINT("zarcanum_generate_proof");
|
||||
const scalar_t a = stake_amount;
|
||||
const scalar_t h = scalar_t(kernel_hash);
|
||||
const scalar_t f_plus_q = stake_blinding_mask + secret_q;
|
||||
|
|
@ -84,6 +89,9 @@ namespace crypto
|
|||
|
||||
point_t F = h * C_prime - dz * C + E + last_pow_block_id_hashed * h * c_point_H;
|
||||
|
||||
DBG_VAL_PRINT(h); DBG_VAL_PRINT(last_pow_block_id_hashed); DBG_VAL_PRINT(dz);
|
||||
DBG_VAL_PRINT(C); DBG_VAL_PRINT(C_prime); DBG_VAL_PRINT(E); DBG_VAL_PRINT(F);
|
||||
|
||||
scalar_t r0 = scalar_t::random();
|
||||
scalar_t r1 = scalar_t::random();
|
||||
scalar_t r2 = scalar_t::random();
|
||||
|
|
@ -92,9 +100,9 @@ namespace crypto
|
|||
|
||||
point_t R_01 = r0 * c_point_X + r1 * c_point_H_plus_G;
|
||||
point_t R_23 = r2 * c_point_X + r3 * c_point_H_minus_G;
|
||||
point_t R_4 = r4 * c_point_G;
|
||||
point_t R_4 = r4 * c_point_X;
|
||||
|
||||
hash_helper_t::hs_t hash_calc(3);
|
||||
hash_helper_t::hs_t hash_calc(7);
|
||||
hash_calc.add_32_chars(CRYPTO_HDS_ZARCANUM_PROOF_HASH);
|
||||
hash_calc.add_point(R_01);
|
||||
hash_calc.add_point(R_23);
|
||||
|
|
@ -160,26 +168,65 @@ namespace crypto
|
|||
|
||||
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("zarcanum_verify_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
|
||||
if (!(cond)) { LOG_PRINT_RED("zarcanum_verify_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
bool zarcanum_verify_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 mp::uint128_t& pos_difficulty,
|
||||
const zarcanum_proof& sig, uint8_t* p_err /* = nullptr */)
|
||||
{
|
||||
DBG_PRINT("zarcanum_verify_proof");
|
||||
bool r = false;
|
||||
|
||||
// TODO @#@#
|
||||
// make sure 0 < d <= l / floor(z * D)
|
||||
const mp::uint256_t l_div_z_D_mp = crypto::zarcanum_precalculate_l_div_z_D(pos_difficulty);
|
||||
const scalar_t l_div_z_D(l_div_z_D_mp);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(!sig.d.is_zero() && sig.d < l_div_z_D, 2);
|
||||
const scalar_t dz = sig.d * c_zarcanum_z_coeff_s;
|
||||
|
||||
std::vector<point_t> E_for_range_proof = { point_t(sig.E) };
|
||||
// calculate h
|
||||
const scalar_t h = scalar_t(kernel_hash);
|
||||
|
||||
// calculate F
|
||||
point_t C_prime = point_t(sig.C_prime);
|
||||
C_prime.modify_mul8();
|
||||
point_t C = point_t(sig.C);
|
||||
C.modify_mul8();
|
||||
point_t E = point_t(sig.E);
|
||||
E.modify_mul8();
|
||||
point_t F = h * C_prime - dz * C + E + last_pow_block_id_hashed * h * c_point_H;
|
||||
|
||||
DBG_VAL_PRINT(h); DBG_VAL_PRINT(last_pow_block_id_hashed); DBG_VAL_PRINT(dz);
|
||||
DBG_VAL_PRINT(C); DBG_VAL_PRINT(C_prime); DBG_VAL_PRINT(E); DBG_VAL_PRINT(F);
|
||||
|
||||
// check three proofs with a shared Fiat-Shamir challenge c
|
||||
point_t C_plus_C_prime = C + C_prime;
|
||||
point_t C_minus_C_prime = C - C_prime;
|
||||
hash_helper_t::hs_t hash_calc(7);
|
||||
hash_calc.add_32_chars(CRYPTO_HDS_ZARCANUM_PROOF_HASH);
|
||||
hash_calc.add_point(sig.y0 * c_point_X + sig.y1 * c_point_H_plus_G - sig.c * C_plus_C_prime); // y_0 * X + y1 (H + G) - c (C + C')
|
||||
hash_calc.add_point(sig.y2 * c_point_X + sig.y3 * c_point_H_minus_G - sig.c * C_minus_C_prime); // y_2 * X + y3 (H - G) - c (C - C')
|
||||
hash_calc.add_point(sig.y4 * c_point_X - sig.c * F); // y_4 * X - c * F
|
||||
hash_calc.add_point(C_plus_C_prime);
|
||||
hash_calc.add_point(C_minus_C_prime);
|
||||
hash_calc.add_point(F);
|
||||
scalar_t c_prime = hash_calc.calc_hash();
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.c == c_prime, 3);
|
||||
|
||||
// check extended range proof for E
|
||||
std::vector<point_t> E_for_range_proof = { point_t(sig.E) }; // consider changing to 8*sig.E to avoid additional conversion
|
||||
std::vector<bppe_sig_commit_ref_t> range_proofs = { bppe_sig_commit_ref_t(sig.E_range_proof, E_for_range_proof) };
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bppe_verify<bpp_crypto_trait_zano<128>>(range_proofs), 10);
|
||||
|
||||
// check extended CLSAG-GGXG ring signature
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(verify_CLSAG_GGXG(m, ring, sig.pseudo_out_amount_commitment, sig.C, stake_ki, sig.clsag_ggxg), 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ namespace crypto
|
|||
|
||||
bool zarcanum_verify_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 mp::uint128_t& pos_difficulty,
|
||||
const zarcanum_proof& sig, uint8_t* p_err = nullptr);
|
||||
|
||||
} // namespace crypto
|
||||
|
|
|
|||
|
|
@ -2562,10 +2562,10 @@ bool blockchain_storage::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPU
|
|||
VARIANT_CASE_CONST(tx_out_zarcanum, toz)
|
||||
{
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry& oen = *result_outs.outs.insert(result_outs.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry());
|
||||
oen.amount_commitment = toz.amount_commitment;
|
||||
oen.concealing_point = toz.concealing_point;
|
||||
oen.global_amount_index = g_index;
|
||||
oen.stealth_address = toz.stealth_address;
|
||||
oen.amount_commitment = toz.amount_commitment;
|
||||
oen.concealing_point = toz.concealing_point;
|
||||
}
|
||||
VARIANT_SWITCH_END();
|
||||
|
||||
|
|
@ -5428,7 +5428,8 @@ bool blockchain_storage::validate_pos_block(const block& b,
|
|||
// build kernel and calculate hash
|
||||
stake_kernel sk = AUTO_VAL_INIT(sk);
|
||||
stake_modifier_type sm = AUTO_VAL_INIT(sm);
|
||||
bool r = build_stake_modifier(sm, alt_chain, split_height);
|
||||
uint64_t last_pow_block_height = 0;
|
||||
bool r = build_stake_modifier(sm, alt_chain, split_height, nullptr, &last_pow_block_height);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to build_stake_modifier");
|
||||
r = build_kernel(stake_key_image, sk, sm, b.timestamp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to build kernel_stake");
|
||||
|
|
@ -5442,7 +5443,6 @@ bool blockchain_storage::validate_pos_block(const block& b,
|
|||
CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1, false, "incorrect number of stake input signatures: " << b.miner_tx.signatures.size());
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.signatures[0].type() == typeid(zarcanum_sig), false, "incorrect sig 0 type: " << b.miner_tx.signatures[0].type().name());
|
||||
const zarcanum_sig& sig = boost::get<zarcanum_sig>(b.miner_tx.signatures[0]);
|
||||
const crypto::hash miner_tx_hash = get_transaction_hash(b.miner_tx);
|
||||
|
||||
// TODO @#@# do general input check for main chain blocks only?
|
||||
uint64_t max_related_block_height = 0;
|
||||
|
|
@ -5452,6 +5452,9 @@ bool blockchain_storage::validate_pos_block(const block& b,
|
|||
r = get_output_keys_for_input_with_checks(b.miner_tx, stake_input, dummy_output_keys, max_related_block_height, dummy_source_max_unlock_time_for_pos_coinbase_dummy, scan_contex);
|
||||
CHECK_AND_ASSERT_MES(r, false, "get_output_keys_for_input_with_checks failed for stake input");
|
||||
CHECK_AND_ASSERT_MES(scan_contex.zc_outs.size() == stake_input.key_offsets.size(), false, "incorrect number of referenced outputs found: " << scan_contex.zc_outs.size() << ", while " << stake_input.key_offsets.size() << " is expected.");
|
||||
// make sure that all referring inputs are either older then, or the same age as, the most resent PoW block.
|
||||
CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_block_height, false, "stake input refs' max related block height is " << max_related_block_height << " while last PoW block height is " << last_pow_block_height);
|
||||
|
||||
// build a ring of references
|
||||
vector<crypto::CLSAG_GGXG_input_ref_t> ring;
|
||||
ring.reserve(scan_contex.zc_outs.size());
|
||||
|
|
@ -5461,10 +5464,8 @@ bool blockchain_storage::validate_pos_block(const block& b,
|
|||
crypto::scalar_t last_pow_block_id_hashed = crypto::hash_helper_t::hs(CRYPTO_HDS_ZARCANUM_LAST_POW_HASH, sm.last_pow_id);
|
||||
|
||||
uint8_t err = 0;
|
||||
r = crypto::zarcanum_verify_proof(miner_tx_hash, kernel_hash, ring, last_pow_block_id_hashed, stake_input.k_image, sig, &err);
|
||||
CHECK_AND_ASSERT_MES(r, false, "zarcanum_verify_proof failed with code " << err);
|
||||
|
||||
final_diff = basic_diff; // just for logs
|
||||
r = crypto::zarcanum_verify_proof(id, kernel_hash, ring, last_pow_block_id_hashed, stake_input.k_image, basic_diff, sig, &err);
|
||||
CHECK_AND_ASSERT_MES(r, false, "zarcanum_verify_proof failed with code " << (int)err);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
@ -6098,10 +6099,12 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
int64_t ts_diff = actual_ts - m_core_runtime_config.get_core_time();
|
||||
powpos_str_entry << "PoS:\t" << proof_hash << ", stake amount: ";
|
||||
if (pos_coinstake_amount != UINT64_MAX)
|
||||
{
|
||||
powpos_str_entry << print_money_brief(pos_coinstake_amount);
|
||||
powpos_str_entry << ", final_difficulty: " << this_coin_diff;
|
||||
}
|
||||
else
|
||||
powpos_str_entry << "hidden";
|
||||
powpos_str_entry << ", final_difficulty: " << this_coin_diff;
|
||||
timestamp_str_entry << ", actual ts: " << actual_ts << " (diff: " << std::showpos << ts_diff << "s) block ts: " << std::noshowpos << bei.bl.timestamp << " (shift: " << std::showpos << static_cast<int64_t>(bei.bl.timestamp) - actual_ts << ")";
|
||||
}
|
||||
else
|
||||
|
|
@ -6452,7 +6455,9 @@ bool blockchain_storage::build_kernel(const block& bl, stake_kernel& kernel, uin
|
|||
return build_kernel(txin.k_image, kernel, stake_modifier, bl.timestamp);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::build_stake_modifier(stake_modifier_type& sm, const alt_chain_type& alt_chain, uint64_t split_height, crypto::hash *p_last_block_hash /* = nullptr */) const
|
||||
bool blockchain_storage::build_stake_modifier(stake_modifier_type& sm, const alt_chain_type& alt_chain, uint64_t split_height,
|
||||
crypto::hash* p_last_block_hash /* = nullptr */,
|
||||
uint64_t* p_last_pow_block_height /* = nullptr */ ) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
sm = stake_modifier_type();
|
||||
|
|
@ -6474,6 +6479,9 @@ bool blockchain_storage::build_stake_modifier(stake_modifier_type& sm, const alt
|
|||
if (p_last_block_hash != nullptr)
|
||||
*p_last_block_hash = get_block_hash(m_db_blocks.back()->bl);
|
||||
|
||||
if (p_last_pow_block_height != nullptr)
|
||||
*p_last_pow_block_height = pbei_last_pow->height;
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
@ -6688,22 +6696,24 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
|
||||
|
||||
const txin_v& input_v = input_tx.vin[input_index];
|
||||
const txin_to_key& input_to_key = get_to_key_input_from_txin_v(input_v);
|
||||
const crypto::key_image& input_key_image = get_key_image_from_txin_v(input_v);
|
||||
const std::vector<txout_ref_v>& input_key_offsets = get_key_offsets_from_txin_v(input_v);
|
||||
const uint64_t input_amount = get_amount_from_variant(input_v);
|
||||
|
||||
// check case b1: key_image spent status in main chain, should be either non-spent or has spent height >= split_height
|
||||
auto p = m_db_spent_keys.get(input_to_key.k_image);
|
||||
CHECK_AND_ASSERT_MES(p == nullptr || *p >= split_height, false, "key image " << input_to_key.k_image << " has been already spent in main chain at height " << *p << ", split height: " << split_height);
|
||||
auto p = m_db_spent_keys.get(input_key_image);
|
||||
CHECK_AND_ASSERT_MES(p == nullptr || *p >= split_height, false, "key image " << input_key_image << " has been already spent in main chain at height " << *p << ", split height: " << split_height);
|
||||
|
||||
TIME_MEASURE_START(ki_lookup_time);
|
||||
//check key_image in altchain
|
||||
//check among this alt block already collected key images first
|
||||
if (collected_keyimages.find(input_to_key.k_image) != collected_keyimages.end())
|
||||
if (collected_keyimages.find(input_key_image) != collected_keyimages.end())
|
||||
{
|
||||
// cases b2, b3
|
||||
LOG_ERROR("key image " << input_to_key.k_image << " already spent in this alt block");
|
||||
LOG_ERROR("key image " << input_key_image << " already spent in this alt block");
|
||||
return false;
|
||||
}
|
||||
auto ki_it = m_altblocks_keyimages.find(input_to_key.k_image);
|
||||
auto ki_it = m_altblocks_keyimages.find(input_key_image);
|
||||
if (ki_it != m_altblocks_keyimages.end())
|
||||
{
|
||||
//have some entry for this key image. Check if this key image belongs to this alt chain
|
||||
|
|
@ -6713,18 +6723,18 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
if (alt_chain_block_ids.find(h) != alt_chain_block_ids.end())
|
||||
{
|
||||
// cases b2, b3
|
||||
LOG_ERROR("key image " << input_to_key.k_image << " already spent in altchain");
|
||||
LOG_ERROR("key image " << input_key_image << " already spent in altchain");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
//update altchain with key image
|
||||
collected_keyimages.insert(input_to_key.k_image);
|
||||
collected_keyimages.insert(input_key_image);
|
||||
TIME_MEASURE_FINISH(ki_lookup_time);
|
||||
ki_lookuptime = ki_lookup_time;
|
||||
|
||||
std::vector<txout_ref_v> abs_key_offsets = relative_output_offsets_to_absolute(input_to_key.key_offsets);
|
||||
CHECK_AND_ASSERT_MES(abs_key_offsets.size() > 0 && abs_key_offsets.size() == input_to_key.key_offsets.size(), false, "internal error: abs_key_offsets.size()==" << abs_key_offsets.size() << ", input_to_key.key_offsets.size()==" << input_to_key.key_offsets.size());
|
||||
std::vector<txout_ref_v> abs_key_offsets = relative_output_offsets_to_absolute(input_key_offsets);
|
||||
CHECK_AND_ASSERT_MES(abs_key_offsets.size() > 0 && abs_key_offsets.size() == input_key_offsets.size(), false, "internal error: abs_key_offsets.size()==" << abs_key_offsets.size() << ", input_key_offsets.size()==" << input_key_offsets.size());
|
||||
// eventually we should found all public keys for all outputs this input refers to, for checking ring signature
|
||||
std::vector<crypto::public_key> pub_keys(abs_key_offsets.size(), null_pkey);
|
||||
|
||||
|
|
@ -6739,7 +6749,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
|
||||
if (!alt_chain.empty())
|
||||
{
|
||||
auto abg_it = alt_chain.back()->second.gindex_lookup_table.find(input_to_key.amount);
|
||||
auto abg_it = alt_chain.back()->second.gindex_lookup_table.find(input_amount);
|
||||
if (abg_it != alt_chain.back()->second.gindex_lookup_table.end())
|
||||
{
|
||||
amount_touched_altchain = true;
|
||||
|
|
@ -6749,13 +6759,13 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
else
|
||||
{
|
||||
//quite easy,
|
||||
global_outs_for_amount = m_db_outputs.get_item_size(input_to_key.amount);
|
||||
global_outs_for_amount = m_db_outputs.get_item_size(input_amount);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//quite easy,
|
||||
global_outs_for_amount = m_db_outputs.get_item_size(input_to_key.amount);
|
||||
global_outs_for_amount = m_db_outputs.get_item_size(input_amount);
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(pub_keys.size() == abs_key_offsets.size(), false, "pub_keys.size()==" << pub_keys.size() << " != abs_key_offsets.size()==" << abs_key_offsets.size()); // just a little bit of paranoia
|
||||
|
|
@ -6773,7 +6783,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
{
|
||||
uint64_t offset_gindex = boost::get<uint64_t>(off);
|
||||
CHECK_AND_ASSERT_MES(amount_touched_altchain || (offset_gindex < global_outs_for_amount), false,
|
||||
"invalid global output index " << offset_gindex << " for amount=" << input_to_key.amount <<
|
||||
"invalid global output index " << offset_gindex << " for amount=" << input_amount <<
|
||||
", max is " << global_outs_for_amount <<
|
||||
", referred to by offset #" << pk_n <<
|
||||
", amount_touched_altchain = " << amount_touched_altchain);
|
||||
|
|
@ -6782,7 +6792,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
bool found_the_key = false;
|
||||
for (auto alt_it = alt_chain.rbegin(); alt_it != alt_chain.rend(); alt_it++)
|
||||
{
|
||||
auto it_aag = (*alt_it)->second.gindex_lookup_table.find(input_to_key.amount);
|
||||
auto it_aag = (*alt_it)->second.gindex_lookup_table.find(input_amount);
|
||||
if (it_aag == (*alt_it)->second.gindex_lookup_table.end())
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(alt_it != alt_chain.rbegin(), false, "internal error: was marked as amount_touched_altchain but unable to find on first entry");
|
||||
|
|
@ -6796,8 +6806,8 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
//TODO: At the moment we ignore check of mix_attr against mixing to simplify alt chain check, but in future consider it for stronger validation
|
||||
uint64_t local_offset = offset_gindex - it_aag->second;
|
||||
auto& alt_keys = (*alt_it)->second.outputs_pub_keys;
|
||||
CHECK_AND_ASSERT_MES(local_offset < alt_keys[input_to_key.amount].size(), false, "Internal error: local_offset=" << local_offset << " while alt_keys[" << input_to_key.amount << " ].size()=" << alt_keys.size());
|
||||
const output_key_or_htlc_v& out_in_alt = alt_keys[input_to_key.amount][local_offset];
|
||||
CHECK_AND_ASSERT_MES(local_offset < alt_keys[input_amount].size(), false, "Internal error: local_offset=" << local_offset << " while alt_keys[" << input_amount << " ].size()=" << alt_keys.size());
|
||||
const output_key_or_htlc_v& out_in_alt = alt_keys[input_amount][local_offset];
|
||||
|
||||
/*
|
||||
here we do validation against compatibility of input and output type
|
||||
|
|
@ -6834,8 +6844,8 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
continue;
|
||||
//otherwise lookup in main chain index
|
||||
}
|
||||
auto p = m_db_outputs.get_subitem(input_to_key.amount, offset_gindex);
|
||||
CHECK_AND_ASSERT_MES(p != nullptr, false, "global output was not found, amount: " << input_to_key.amount << ", gindex: " << offset_gindex << ", referred to by offset #" << pk_n);
|
||||
auto p = m_db_outputs.get_subitem(input_amount, offset_gindex);
|
||||
CHECK_AND_ASSERT_MES(p != nullptr, false, "global output was not found, amount: " << input_amount << ", gindex: " << offset_gindex << ", referred to by offset #" << pk_n);
|
||||
tx_id = p->tx_id;
|
||||
out_n = p->out_no;
|
||||
}
|
||||
|
|
@ -6957,10 +6967,21 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx,
|
|||
VARIANT_SWITCH_END();
|
||||
}
|
||||
|
||||
// @#@# TODO review the following checks!
|
||||
|
||||
// do input checks (attachment_info, ring signature and extra signature, etc.)
|
||||
r = check_input_signature(input_tx, input_index, input_to_key, input_tx_hash, pub_key_pointers);
|
||||
CHECK_AND_ASSERT_MES(r, false, "to_key input validation failed");
|
||||
VARIANT_SWITCH_BEGIN(input_v);
|
||||
VARIANT_CASE_CONST(txin_to_key, input_to_key)
|
||||
r = check_input_signature(input_tx, input_index, input_to_key, input_tx_hash, pub_key_pointers);
|
||||
CHECK_AND_ASSERT_MES(r, false, "to_key input validation failed");
|
||||
VARIANT_CASE_CONST(txin_zc_input, input_zc);
|
||||
uint64_t max_related_block_height = 0;
|
||||
r = check_tx_input(input_tx, input_index, input_zc, input_tx_hash, max_related_block_height);
|
||||
CHECK_AND_ASSERT_MES(r, false, "check_tx_input failed");
|
||||
VARIANT_CASE_OTHER()
|
||||
LOG_ERROR("unexpected input type: " << input_v.type().name());
|
||||
return false;
|
||||
VARIANT_SWITCH_END();
|
||||
|
||||
|
||||
// TODO: consider checking input_tx for valid extra attachment info as it's checked in check_tx_inputs()
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ namespace currency
|
|||
stake_kernel& kernel,
|
||||
const stake_modifier_type& stake_modifier,
|
||||
uint64_t timestamp) const;
|
||||
bool build_stake_modifier(stake_modifier_type& sm, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0, crypto::hash *p_last_block_hash = nullptr) const;
|
||||
bool build_stake_modifier(stake_modifier_type& sm, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0, crypto::hash* p_last_block_hash = nullptr, uint64_t* p_last_pow_block_height = nullptr) const;
|
||||
|
||||
bool validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const;
|
||||
bool validate_pos_block(const block& b, const crypto::hash& id, bool for_altchain)const;
|
||||
|
|
@ -660,7 +660,7 @@ namespace currency
|
|||
//bool resync_spent_tx_flags();
|
||||
bool prune_ring_signatures_and_attachments_if_need();
|
||||
bool prune_ring_signatures_and_attachments(uint64_t height, uint64_t& transactions_pruned, uint64_t& signatures_pruned, uint64_t& attachments_pruned);
|
||||
// bool build_stake_modifier_for_alt(const alt_chain_type& alt_chain, stake_modifier_type& sm);
|
||||
|
||||
template<class visitor_t>
|
||||
bool enum_blockchain(visitor_t& v, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0) const;
|
||||
bool update_spent_tx_flags_for_input(uint64_t amount, const txout_ref_v& o, bool spent);
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ namespace currency
|
|||
result.outputs_count = outs_count;
|
||||
uint8_t err = 0;
|
||||
bool r = crypto::bpp_gen<>(amounts, blinding_masks, commitments_1div8, result.bpp, &err);
|
||||
CHECK_AND_ASSERT_MES(r, false, "bpp_gen failed with error " << err);
|
||||
CHECK_AND_ASSERT_MES(r, false, "bpp_gen failed with error " << (int)err);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ namespace currency
|
|||
{
|
||||
std::list<uint64_t> amounts;
|
||||
uint64_t decoys_count; // how many decoy outputs needed (per amount)
|
||||
uint64_t height_upper_limit; // all the decoy outputs must be either older than, or the same age as this height
|
||||
uint64_t height_upper_limit; // if nonzero, all the decoy outputs must be either older than, or the same age as this height
|
||||
bool use_forced_mix_outs;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amounts)
|
||||
|
|
@ -359,6 +359,9 @@ namespace currency
|
|||
out_entry(uint64_t global_amount_index, const crypto::public_key& stealth_address, const crypto::public_key& amount_commitment, const crypto::public_key& concealing_point)
|
||||
: global_amount_index(global_amount_index), stealth_address(stealth_address), amount_commitment(amount_commitment), concealing_point(concealing_point)
|
||||
{}
|
||||
out_entry(uint64_t global_amount_index, const crypto::public_key& stealth_address)
|
||||
: global_amount_index(global_amount_index), stealth_address(stealth_address), amount_commitment{}, concealing_point{}
|
||||
{}
|
||||
uint64_t global_amount_index;
|
||||
crypto::public_key stealth_address;
|
||||
crypto::public_key concealing_point;
|
||||
|
|
|
|||
|
|
@ -3774,12 +3774,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, currency::bl
|
|||
|
||||
// generate sring signature
|
||||
sig.s.resize(1);
|
||||
crypto::generate_ring_signature(block_hash,
|
||||
stake_input.k_image,
|
||||
keys_ptrs,
|
||||
secret_x,
|
||||
0,
|
||||
&sig.s[0]);
|
||||
crypto::generate_ring_signature(block_hash, stake_input.k_image, keys_ptrs, secret_x, 0, sig.s.data());
|
||||
|
||||
WLT_LOG_L4("GENERATED RING SIGNATURE for PoS block coinbase: block_id " << block_hash
|
||||
<< "txin.k_image" << stake_input.k_image
|
||||
|
|
@ -3877,7 +3872,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, currency::bl
|
|||
}
|
||||
#endif
|
||||
|
||||
crypto::hash tx_hash_for_sig = get_transaction_hash(b.miner_tx); // TODO @#@# change to block hash after the corresponding test is made
|
||||
crypto::hash tx_hash_for_sig = get_block_hash(b);
|
||||
|
||||
uint8_t err = 0;
|
||||
r = crypto::zarcanum_generate_proof(tx_hash_for_sig, cxt.kernel_hash, ring, cxt.last_pow_block_id_hashed, cxt.sk.kimage,
|
||||
|
|
|
|||
|
|
@ -154,22 +154,20 @@ void test_generator::add_block(const currency::block& blk,
|
|||
uint64_t block_reward;
|
||||
get_block_reward(is_pos_block(blk), misc_utils::median(block_sizes), block_size, already_generated_coins, block_reward, currency::get_block_height(blk));
|
||||
|
||||
crypto::hash block_hash = get_block_hash(blk);
|
||||
m_blocks_info[block_hash] = block_info(blk, already_generated_coins + block_reward, block_size, cum_diff, tx_list, ks_hash);
|
||||
|
||||
|
||||
std::stringstream ss_tx_hashes;
|
||||
for (auto& h : blk.tx_hashes)
|
||||
{
|
||||
ss_tx_hashes << " [tx]: " << h << ENDL;
|
||||
}
|
||||
|
||||
LOG_PRINT_MAGENTA("ADDED_BLOCK[" << block_hash << "][" << (is_pos_block(blk)? "PoS":"PoW") <<"][" << get_block_height(blk) << "][cumul_diff:" << cum_diff << "]" << ENDL << ss_tx_hashes.str(), LOG_LEVEL_0);
|
||||
add_block_info(block_info(blk, already_generated_coins + block_reward, block_size, cum_diff, tx_list, ks_hash));
|
||||
}
|
||||
|
||||
void test_generator::add_block_info(const block_info& bi)
|
||||
{
|
||||
m_blocks_info[get_block_hash(bi.b)] = bi;
|
||||
crypto::hash block_hash = get_block_hash(bi.b);
|
||||
m_blocks_info[block_hash] = bi;
|
||||
|
||||
std::stringstream ss_tx_hashes;
|
||||
for (auto& h : bi.b.tx_hashes)
|
||||
{
|
||||
ss_tx_hashes << " [tx]: " << h << ENDL;
|
||||
}
|
||||
LOG_PRINT_MAGENTA("ADDED_BLOCK[" << block_hash << "][" << (is_pos_block(bi.b)? "PoS":"PoW") <<"][" << get_block_height(bi.b) << "][cumul_diff:" << bi.cumul_difficulty << "]" << ENDL << ss_tx_hashes.str(), LOG_LEVEL_0);
|
||||
}
|
||||
|
||||
bool test_generator::add_block_info(const currency::block& b, const std::list<currency::transaction>& tx_list)
|
||||
|
|
@ -179,7 +177,8 @@ bool test_generator::add_block_info(const currency::block& b, const std::list<cu
|
|||
txs_total_size += get_object_blobsize(tx);
|
||||
uint64_t mined_money = get_reward_from_miner_tx(b.miner_tx);
|
||||
crypto::hash sk_hash = null_hash;
|
||||
if (is_pos_block(b))
|
||||
bool pos = is_pos_block(b);
|
||||
if (pos)
|
||||
{
|
||||
stake_kernel sk = AUTO_VAL_INIT(sk);
|
||||
std::vector<const block_info*> chain;
|
||||
|
|
@ -193,15 +192,29 @@ bool test_generator::add_block_info(const currency::block& b, const std::list<cu
|
|||
}
|
||||
uint64_t pow_idx = get_last_block_of_type(false, chain);
|
||||
sk.stake_modifier.last_pow_id = get_block_hash(chain[pow_idx]->b);
|
||||
sk.kimage = boost::get<txin_to_key>(b.miner_tx.vin[1]).k_image;
|
||||
sk.kimage = get_key_image_from_txin_v(b.miner_tx.vin[1]);
|
||||
sk.block_timestamp = b.timestamp;
|
||||
sk_hash = crypto::cn_fast_hash(&sk, sizeof(sk));
|
||||
}
|
||||
add_block_info(block_info(b, get_already_generated_coins(b.prev_id) + mined_money,
|
||||
txs_total_size + get_object_blobsize(b.miner_tx), get_cumul_difficulty_for_next_block(b.prev_id), tx_list, sk_hash));
|
||||
txs_total_size + get_object_blobsize(b.miner_tx), get_cumul_difficulty_for_next_block(b.prev_id, !pos), tx_list, sk_hash));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_generator::remove_block_info(const crypto::hash& block_id)
|
||||
{
|
||||
if (m_blocks_info.erase(block_id) == 1)
|
||||
{
|
||||
LOG_PRINT_MAGENTA("REMOVED BLOCK[" << block_id << "]", LOG_LEVEL_0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool test_generator::remove_block_info(const currency::block& blk)
|
||||
{
|
||||
return remove_block_info(get_block_hash(blk));
|
||||
}
|
||||
|
||||
|
||||
bool test_generator::construct_block(currency::block& blk,
|
||||
|
|
@ -259,10 +272,9 @@ bool test_generator::construct_block(currency::block& blk,
|
|||
build_outputs_indext_for_chain(blocks, oi, txs_outs);
|
||||
|
||||
//build wallets
|
||||
build_wallets(blocks, coin_stake_sources, txs_outs, wallets);
|
||||
build_wallets(blocks, coin_stake_sources, txs_outs, oi, wallets);
|
||||
r = find_kernel(coin_stake_sources,
|
||||
blocks,
|
||||
oi,
|
||||
wallets,
|
||||
pe,
|
||||
won_walled_index,
|
||||
|
|
@ -361,6 +373,7 @@ bool test_generator::sign_block(const tools::wallet2::mining_context& mining_con
|
|||
bool test_generator::build_wallets(const blockchain_vector& blockchain,
|
||||
const std::list<currency::account_base>& accs,
|
||||
const tx_global_indexes& txs_outs,
|
||||
const outputs_index& oi,
|
||||
wallets_vector& wallets,
|
||||
const core_runtime_config& cc)
|
||||
{
|
||||
|
|
@ -369,10 +382,12 @@ bool test_generator::build_wallets(const blockchain_vector& blockchain,
|
|||
const tx_global_indexes& m_txs_outs;
|
||||
const blockchain_vector& m_blockchain;
|
||||
const core_runtime_config& m_core_runtime_config;
|
||||
const outputs_index& m_outputs_index;
|
||||
|
||||
stub_core_proxy(const blockchain_vector& blockchain, const tx_global_indexes& txs_outs, const core_runtime_config& crc)
|
||||
stub_core_proxy(const blockchain_vector& blockchain, const tx_global_indexes& txs_outs, const outputs_index& oi, const core_runtime_config& crc)
|
||||
: m_blockchain(blockchain)
|
||||
, m_txs_outs(txs_outs)
|
||||
, m_outputs_index(oi)
|
||||
, m_core_runtime_config(crc)
|
||||
{}
|
||||
|
||||
|
|
@ -412,9 +427,68 @@ bool test_generator::build_wallets(const blockchain_vector& blockchain,
|
|||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& rqt, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& rsp) override
|
||||
{
|
||||
for (uint64_t amount : rqt.amounts)
|
||||
{
|
||||
rsp.outs.resize(rsp.outs.size() + 1);
|
||||
auto& rsp_entry = rsp.outs.back();
|
||||
rsp_entry.amount = amount;
|
||||
auto it = m_outputs_index.find(amount);
|
||||
if (it == m_outputs_index.end())
|
||||
continue;
|
||||
|
||||
std::shared_ptr<tools::i_core_proxy> tmp_proxy(new stub_core_proxy(blockchain, txs_outs, cc));
|
||||
std::vector<size_t> random_mapping(it->second.size());
|
||||
for(size_t i = 0; i < random_mapping.size(); ++i)
|
||||
random_mapping[i] = i;
|
||||
std::shuffle(random_mapping.begin(), random_mapping.end(), crypto::uniform_random_bit_generator());
|
||||
|
||||
for (size_t gindex : random_mapping)
|
||||
{
|
||||
const out_index_info& oii = it->second[gindex];
|
||||
if (rqt.height_upper_limit != 0 && oii.block_height > rqt.height_upper_limit)
|
||||
continue;
|
||||
const transaction& tx = oii.in_block_tx_index == 0 ? m_blockchain[oii.block_height]->b.miner_tx : m_blockchain[oii.block_height]->m_transactions[oii.in_block_tx_index];
|
||||
auto& out_v = tx.vout[oii.in_tx_out_index];
|
||||
uint8_t mix_attr = 0;
|
||||
if (!get_mix_attr_from_tx_out_v(out_v, mix_attr))
|
||||
continue;
|
||||
if (mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX)
|
||||
continue;
|
||||
if (rqt.use_forced_mix_outs && mix_attr == CURRENCY_TO_KEY_OUT_RELAXED)
|
||||
continue;
|
||||
if (mix_attr != CURRENCY_TO_KEY_OUT_RELAXED && mix_attr > rqt.decoys_count)
|
||||
continue;
|
||||
|
||||
if (amount == 0 && out_v.type() == typeid(tx_out_zarcanum))
|
||||
{
|
||||
const tx_out_zarcanum& out_zc = boost::get<tx_out_zarcanum>(out_v);
|
||||
rsp_entry.outs.emplace_back(gindex, out_zc.stealth_address, out_zc.amount_commitment, out_zc.concealing_point);
|
||||
}
|
||||
else if (amount != 0 && out_v.type() == typeid(tx_out_bare))
|
||||
{
|
||||
txout_target_v out_tv = boost::get<tx_out_bare>(out_v).target;
|
||||
if (out_tv.type() != typeid(txout_to_key))
|
||||
continue;
|
||||
rsp_entry.outs.emplace_back(gindex, boost::get<txout_to_key>(out_tv).key);
|
||||
}
|
||||
if (rsp_entry.outs.size() >= rqt.decoys_count)
|
||||
break;
|
||||
}
|
||||
if (rsp_entry.outs.size() < rqt.decoys_count)
|
||||
{
|
||||
rsp.status = API_RETURN_CODE_NOT_ENOUGH_OUTPUTS_FOR_MIXING;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
rsp.status = API_RETURN_CODE_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
}; // struct stub_core_proxy
|
||||
|
||||
std::shared_ptr<tools::i_core_proxy> tmp_proxy(new stub_core_proxy(blockchain, txs_outs, oi, cc));
|
||||
|
||||
//build wallets
|
||||
wallets.clear();
|
||||
|
|
@ -471,7 +545,7 @@ bool test_generator::build_wallets(const crypto::hash& blockchain_head, const st
|
|||
|
||||
get_block_chain(blocks, blockchain_head, std::numeric_limits<size_t>::max());
|
||||
build_outputs_indext_for_chain(blocks, oi, txs_outs);
|
||||
return build_wallets(blocks, accounts, txs_outs, wallets, cc);
|
||||
return build_wallets(blocks, accounts, txs_outs, oi, wallets, cc);
|
||||
}
|
||||
|
||||
size_t test_generator::get_tx_out_gindex(const crypto::hash& blockchain_head, const crypto::hash& tx_hash, const size_t output_index) const
|
||||
|
|
@ -509,7 +583,6 @@ uint64_t test_generator::get_timestamps_median(const crypto::hash& blockchain_he
|
|||
|
||||
bool test_generator::find_kernel(const std::list<currency::account_base>& accs,
|
||||
const blockchain_vector& blck_chain,
|
||||
const outputs_index& indexes,
|
||||
wallets_vector& wallets,
|
||||
currency::pos_entry& pe,
|
||||
size_t& found_wallet_index,
|
||||
|
|
@ -577,7 +650,7 @@ bool test_generator::build_outputs_indext_for_chain(const blockchain_vector& blo
|
|||
{
|
||||
uint64_t amount = get_amount_from_variant(blocks[h]->b.miner_tx.vout[out_i]);
|
||||
coinbase_outs.push_back(index[amount].size());
|
||||
index[amount].push_back(std::tuple<size_t, size_t, size_t>(h, 0, out_i));
|
||||
index[amount].push_back(out_index_info{h, 0, out_i});
|
||||
}
|
||||
|
||||
for (size_t tx_index = 0; tx_index != blocks[h]->m_transactions.size(); tx_index++)
|
||||
|
|
@ -587,7 +660,7 @@ bool test_generator::build_outputs_indext_for_chain(const blockchain_vector& blo
|
|||
{
|
||||
uint64_t amount = get_amount_from_variant(blocks[h]->m_transactions[tx_index].vout[out_i]);
|
||||
tx_outs_indx.push_back(index[amount].size());
|
||||
index[amount].push_back(std::tuple<size_t, size_t, size_t>(h, tx_index + 1, out_i));
|
||||
index[amount].push_back(out_index_info{h, tx_index + 1, out_i});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -652,6 +725,7 @@ bool test_generator::build_stake_modifier(stake_modifier_type& sm, const test_ge
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
currency::wide_difficulty_type test_generator::get_difficulty_for_next_block(const crypto::hash& head_id, bool pow) const
|
||||
{
|
||||
std::vector<const block_info*> blocks;
|
||||
|
|
@ -660,6 +734,29 @@ currency::wide_difficulty_type test_generator::get_difficulty_for_next_block(con
|
|||
return get_difficulty_for_next_block(blocks, pow);
|
||||
}
|
||||
|
||||
|
||||
bool test_generator::get_params_for_next_pos_block(const crypto::hash& head_id, currency::wide_difficulty_type& pos_difficulty, crypto::hash& last_pow_block_hash,
|
||||
crypto::hash& last_pos_block_kernel_hash) const
|
||||
{
|
||||
std::vector<const block_info*> blocks;
|
||||
get_block_chain(blocks, head_id, std::numeric_limits<size_t>::max());
|
||||
|
||||
pos_difficulty = get_difficulty_for_next_block(blocks, false);
|
||||
|
||||
uint64_t pos_idx = get_last_block_of_type(true, blocks);
|
||||
if (pos_idx != 0)
|
||||
last_pos_block_kernel_hash = blocks[pos_idx]->ks_hash;
|
||||
|
||||
uint64_t pow_idx = get_last_block_of_type(false, blocks);
|
||||
if (pow_idx == 0)
|
||||
return false;
|
||||
|
||||
last_pow_block_hash = get_block_hash(blocks[pow_idx]->b);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* static */ currency::wide_difficulty_type test_generator::get_difficulty_for_next_block(const std::vector<const block_info*>& blocks, bool pow)
|
||||
{
|
||||
std::vector<uint64_t> timestamps;
|
||||
|
|
@ -932,7 +1029,7 @@ bool test_generator::construct_pow_block_with_alias_info_in_coinbase(const accou
|
|||
struct output_index
|
||||
{
|
||||
const currency::tx_out_v out_v;
|
||||
uint64_t amount;
|
||||
uint64_t amount; // actual amount (decoded, cannot be zero)
|
||||
size_t tx_no; // index of transaction in block
|
||||
size_t out_no; // index of out in transaction
|
||||
size_t idx; // global index
|
||||
|
|
@ -969,7 +1066,7 @@ struct output_index
|
|||
}*/
|
||||
};
|
||||
|
||||
typedef std::map<uint64_t, std::vector<size_t> > map_output_t; // amount -> [N -> global out index]
|
||||
typedef std::map<uint64_t, std::vector<size_t> > map_output_t; // amount -> [N -> global out index] (for 'my' outputs, no specific order)
|
||||
typedef std::map<uint64_t, std::vector<output_index> > map_output_idx_t; // amount -> [global out index -> 'output_index']
|
||||
typedef std::pair<uint64_t, size_t> outloc_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -266,10 +266,18 @@ public:
|
|||
bool check_tx_verification_context(const currency::tx_verification_context& tvc, bool tx_added, size_t event_idx, const currency::transaction& /*tx*/)
|
||||
{
|
||||
if (m_invalid_tx_index == event_idx)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(tvc.m_verification_failed, false, ENDL << "event #" << event_idx << ": the tx passed the verification, although it had been marked as invalid" << ENDL);
|
||||
return tvc.m_verification_failed;
|
||||
}
|
||||
|
||||
if (m_unverifiable_tx_index == event_idx)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(tvc.m_verification_impossible, false, ENDL << "event #" << event_idx << ": the tx passed normally, although it had been marked as unverifiable" << ENDL);
|
||||
return tvc.m_verification_impossible;
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(tx_added, false, ENDL << "event #" << event_idx << ": the tx has not been added for some reason" << ENDL);
|
||||
|
||||
return !tvc.m_verification_failed && tx_added;
|
||||
}
|
||||
|
|
@ -277,10 +285,16 @@ public:
|
|||
bool check_block_verification_context(const currency::block_verification_context& bvc, size_t event_idx, const currency::block& /*block*/)
|
||||
{
|
||||
if (m_invalid_block_index == event_idx)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(bvc.m_verification_failed, false, ENDL << "event #" << event_idx << ": the block passed the verification, although it had been marked as invalid" << ENDL);
|
||||
return bvc.m_verification_failed;
|
||||
}
|
||||
|
||||
if (m_orphan_block_index == event_idx)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(bvc.m_marked_as_orphaned, false, ENDL << "event #" << event_idx << ": the block passed normally, although it had been marked as orphaned" << ENDL);
|
||||
return bvc.m_marked_as_orphaned;
|
||||
}
|
||||
|
||||
return !bvc.m_verification_failed;
|
||||
}
|
||||
|
|
@ -375,9 +389,16 @@ public:
|
|||
crypto::hash ks_hash;
|
||||
};
|
||||
|
||||
// amount vec_ind, tx_index, out index in tx
|
||||
typedef std::map<uint64_t, std::vector<std::tuple<size_t, size_t, size_t> > > outputs_index;
|
||||
typedef std::unordered_map<crypto::hash, std::vector<uint64_t> > tx_global_indexes;
|
||||
|
||||
struct out_index_info
|
||||
{
|
||||
size_t block_height;
|
||||
size_t in_block_tx_index;
|
||||
size_t in_tx_out_index;
|
||||
};
|
||||
|
||||
typedef std::map<uint64_t, std::vector<out_index_info> > outputs_index; // amount -> [gindex -> out_index_info]
|
||||
typedef std::unordered_map<crypto::hash, std::vector<uint64_t> > tx_global_indexes; // tx_hash -> vector of tx's outputs global indices
|
||||
|
||||
typedef std::vector<const block_info*> blockchain_vector;
|
||||
|
||||
|
|
@ -406,6 +427,7 @@ public:
|
|||
//-----------
|
||||
static currency::wide_difficulty_type get_difficulty_for_next_block(const std::vector<const block_info*>& blocks, bool pow = true);
|
||||
currency::wide_difficulty_type get_difficulty_for_next_block(const crypto::hash& head_id, bool pow = true) const;
|
||||
bool get_params_for_next_pos_block(const crypto::hash& head_id, currency::wide_difficulty_type& pos_difficulty, crypto::hash& last_pow_block_hash, crypto::hash& last_pos_block_kernel_hash) const;
|
||||
currency::wide_difficulty_type get_cumul_difficulty_for_next_block(const crypto::hash& head_id, bool pow = true) const;
|
||||
void get_block_chain(std::vector<const block_info*>& blockchain, const crypto::hash& head, size_t n) const;
|
||||
void get_last_n_block_sizes(std::vector<size_t>& block_sizes, const crypto::hash& head, size_t n) const;
|
||||
|
|
@ -421,7 +443,6 @@ public:
|
|||
|
||||
bool find_kernel(const std::list<currency::account_base>& accs,
|
||||
const blockchain_vector& blck_chain,
|
||||
const outputs_index& indexes,
|
||||
wallets_vector& wallets,
|
||||
currency::pos_entry& pe,
|
||||
size_t& found_wallet_index,
|
||||
|
|
@ -431,6 +452,7 @@ public:
|
|||
bool build_wallets(const blockchain_vector& blocks,
|
||||
const std::list<currency::account_base>& accs,
|
||||
const tx_global_indexes& txs_outs,
|
||||
const outputs_index& oi,
|
||||
wallets_vector& wallets,
|
||||
const currency::core_runtime_config& cc = currency::get_default_core_runtime_config());
|
||||
|
||||
|
|
@ -483,6 +505,9 @@ public:
|
|||
|
||||
bool add_block_info(const currency::block& b, const std::list<currency::transaction>& tx_list);
|
||||
|
||||
bool remove_block_info(const currency::block& blk);
|
||||
bool remove_block_info(const crypto::hash& block_id);
|
||||
|
||||
bool construct_block(currency::block& blk,
|
||||
uint64_t height,
|
||||
const crypto::hash& prev_id,
|
||||
|
|
|
|||
|
|
@ -1082,6 +1082,7 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(zarcanum_test_n_inputs_validation);
|
||||
GENERATE_AND_PLAY(zarcanum_gen_time_balance);
|
||||
GENERATE_AND_PLAY(zarcanum_txs_with_big_shuffled_decoy_set_shuffled);
|
||||
GENERATE_AND_PLAY(zarcanum_pos_block_math);
|
||||
|
||||
// GENERATE_AND_PLAY(gen_block_reward);
|
||||
// END OF TESTS */
|
||||
|
|
|
|||
|
|
@ -13,6 +13,53 @@ using namespace epee;
|
|||
using namespace crypto;
|
||||
using namespace currency;
|
||||
|
||||
// helpers
|
||||
|
||||
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)
|
||||
{
|
||||
blockchain_storage& bcs = c.get_blockchain_storage();
|
||||
|
||||
// these values (median and diff) are correct only for the next main chain block, it's incorrect for altblocks, especially for old altblocks
|
||||
// but for now we assume they will work fine
|
||||
uint64_t block_size_median = bcs.get_current_comulative_blocksize_limit() / 2;
|
||||
currency::wide_difficulty_type difficulty = bcs.get_next_diff_conditional(true);
|
||||
|
||||
crypto::hash prev_id = get_block_hash(prev_block);
|
||||
size_t height = get_block_height(prev_block) + 1;
|
||||
|
||||
block_extended_info bei = AUTO_VAL_INIT(bei);
|
||||
bool r = bcs.get_block_extended_info_by_hash(prev_id, bei);
|
||||
CHECK_AND_ASSERT_MES(r, false, "get_block_extended_info_by_hash failed for hash = " << prev_id);
|
||||
|
||||
|
||||
const transaction& stake = coinstake_scr_block.miner_tx;
|
||||
crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake);
|
||||
size_t stake_output_idx = 0;
|
||||
size_t stake_output_gidx = 0;
|
||||
uint64_t stake_output_amount =boost::get<currency::tx_out_bare>( stake.vout[stake_output_idx]).amount;
|
||||
crypto::key_image stake_output_key_image;
|
||||
keypair kp;
|
||||
generate_key_image_helper(acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image);
|
||||
crypto::public_key stake_output_pubkey = boost::get<txout_to_key>(boost::get<currency::tx_out_bare>(stake.vout[stake_output_idx]).target).key;
|
||||
|
||||
pos_block_builder pb;
|
||||
pb.step1_init_header(bcs.get_core_runtime_config().hard_forks, height, prev_id);
|
||||
pb.step2_set_txs(std::vector<transaction>());
|
||||
pb.step3_build_stake_kernel(stake_output_amount, stake_output_gidx, stake_output_key_image, difficulty, prev_id, null_hash, prev_block.timestamp);
|
||||
pb.step4_generate_coinbase_tx(block_size_median, bei.already_generated_coins, acc.get_public_address());
|
||||
|
||||
if (!before_sign_cb(pb.m_block))
|
||||
return false;
|
||||
|
||||
pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, acc);
|
||||
output = pb.m_block;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
checkpoints_test::checkpoints_test()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(checkpoints_test, set_checkpoint);
|
||||
|
|
|
|||
|
|
@ -139,8 +139,6 @@ void pos_block_builder::step3b(
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
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,
|
||||
|
|
@ -199,6 +197,7 @@ void pos_block_builder::step4_generate_coinbase_tx(size_t median_size,
|
|||
}
|
||||
|
||||
// supports Zarcanum and mixins
|
||||
// (se.outputs can be unsorted)
|
||||
void pos_block_builder::step5_sign(const currency::tx_source_entry& se, const currency::account_keys& stakeholder_keys)
|
||||
{
|
||||
bool r = false;
|
||||
|
|
@ -219,25 +218,28 @@ void pos_block_builder::step5_sign(const currency::tx_source_entry& se, const cu
|
|||
|
||||
stake_input.k_image = m_context.sk.kimage;
|
||||
|
||||
size_t prepared_real_out_index = 0;
|
||||
std::vector<tx_source_entry::output_entry> prepared_outputs = prepare_outputs_entries_for_key_offsets(se.outputs, se.real_output, prepared_real_out_index);
|
||||
|
||||
std::vector<crypto::CLSAG_GGXG_input_ref_t> ring;
|
||||
for(const auto& el : se.outputs)
|
||||
for(const auto& el : prepared_outputs)
|
||||
{
|
||||
stake_input.key_offsets.push_back(el.out_reference);
|
||||
ring.emplace_back(el.stealth_address, el.amount_commitment, el.concealing_point);
|
||||
}
|
||||
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
|
||||
crypto::hash tx_hash_for_sig = 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, se.real_output, m_blinding_masks_sum, m_context.stake_amount, m_context.stake_out_blinding_mask,
|
||||
secret_x, m_context.secret_q, prepared_real_out_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
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(se.outputs.size() == 1, "PoS blocks with NLSAG and mixing are not supported atm");
|
||||
|
||||
// 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]);
|
||||
|
|
@ -255,7 +257,7 @@ void pos_block_builder::step5_sign(const currency::tx_source_entry& se, const cu
|
|||
m_step = 5;
|
||||
}
|
||||
|
||||
|
||||
// pre-Zarcanum sign function
|
||||
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)
|
||||
{
|
||||
|
|
@ -269,47 +271,3 @@ void pos_block_builder::step5_sign(const crypto::public_key& stake_tx_pub_key, s
|
|||
|
||||
step5_sign(se, stakeholder_account.get_keys());
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
blockchain_storage& bcs = c.get_blockchain_storage();
|
||||
|
||||
// these values (median and diff) are correct only for the next main chain block, it's incorrect for altblocks, especially for old altblocks
|
||||
// but for now we assume they will work fine
|
||||
uint64_t block_size_median = bcs.get_current_comulative_blocksize_limit() / 2;
|
||||
currency::wide_difficulty_type difficulty = bcs.get_next_diff_conditional(true);
|
||||
|
||||
crypto::hash prev_id = get_block_hash(prev_block);
|
||||
size_t height = get_block_height(prev_block) + 1;
|
||||
|
||||
block_extended_info bei = AUTO_VAL_INIT(bei);
|
||||
bool r = bcs.get_block_extended_info_by_hash(prev_id, bei);
|
||||
CHECK_AND_ASSERT_MES(r, false, "get_block_extended_info_by_hash failed for hash = " << prev_id);
|
||||
|
||||
|
||||
const transaction& stake = coinstake_scr_block.miner_tx;
|
||||
crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake);
|
||||
size_t stake_output_idx = 0;
|
||||
size_t stake_output_gidx = 0;
|
||||
uint64_t stake_output_amount =boost::get<currency::tx_out_bare>( stake.vout[stake_output_idx]).amount;
|
||||
crypto::key_image stake_output_key_image;
|
||||
keypair kp;
|
||||
generate_key_image_helper(acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image);
|
||||
crypto::public_key stake_output_pubkey = boost::get<txout_to_key>(boost::get<currency::tx_out_bare>(stake.vout[stake_output_idx]).target).key;
|
||||
|
||||
pos_block_builder pb;
|
||||
pb.step1_init_header(bcs.get_core_runtime_config().hard_forks, height, prev_id);
|
||||
pb.step2_set_txs(std::vector<transaction>());
|
||||
pb.step3_build_stake_kernel(stake_output_amount, stake_output_gidx, stake_output_key_image, difficulty, prev_id, null_hash, prev_block.timestamp);
|
||||
pb.step4_generate_coinbase_tx(block_size_median, bei.already_generated_coins, acc.get_public_address());
|
||||
|
||||
if (!before_sign_cb(pb.m_block))
|
||||
return false;
|
||||
|
||||
pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, acc);
|
||||
output = pb.m_block;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,8 +69,6 @@ struct pos_block_builder
|
|||
|
||||
void 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);
|
||||
|
||||
//void step5_sign_zarcanum(const crypto::public_key& stake_tx_pub_key, size_t stake_tx_out_index, const currency::account_base& stakeholder_account);
|
||||
|
||||
|
||||
currency::block m_block {};
|
||||
size_t m_step = 0;
|
||||
|
|
@ -84,25 +82,3 @@ struct pos_block_builder
|
|||
|
||||
currency::pos_mining_context m_context {};
|
||||
};
|
||||
|
||||
/* 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 currency::account_public_address &reward_receiving_address,
|
||||
const currency::account_public_address &stakeholder_address,
|
||||
currency::transaction& tx,
|
||||
const currency::blobdata& extra_nonce = currency::blobdata(),
|
||||
size_t max_outs = CURRENCY_MINER_TX_MAX_OUTS,
|
||||
currency::keypair tx_one_time_key = currency::keypair::generate()); */
|
||||
|
||||
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);
|
||||
|
||||
inline bool mine_next_pos_block_in_playtime(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)
|
||||
{
|
||||
return mine_next_pos_block_in_playtime_sign_cb(c, prev_block, coinstake_scr_block, acc, [](currency::block&){ return true; }, output);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,51 @@
|
|||
|
||||
#define AMOUNT_TO_TRANSFER_ZARCANUM_BASIC (TESTS_DEFAULT_FEE*10)
|
||||
|
||||
|
||||
using namespace currency;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// helpers
|
||||
|
||||
void invalidate_CLSAG_GGXG_sig(crypto::CLSAG_GGXG_signature& sig)
|
||||
{
|
||||
sig.c = 7;
|
||||
}
|
||||
|
||||
void invalidate_bppe_sig(crypto::bppe_signature& sig)
|
||||
{
|
||||
sig.delta_1.make_random();
|
||||
}
|
||||
|
||||
void invalidate_pub_key(crypto::public_key& pk)
|
||||
{
|
||||
pk.data[5] = 0x33;
|
||||
}
|
||||
|
||||
bool invalidate_zarcanum_sig(size_t n, zarcanum_sig& sig)
|
||||
{
|
||||
switch(n)
|
||||
{
|
||||
case 0: break;
|
||||
case 1: invalidate_pub_key(sig.C); break;
|
||||
case 2: sig.c.make_random(); break;
|
||||
case 3: invalidate_CLSAG_GGXG_sig(sig.clsag_ggxg); break;
|
||||
case 4: invalidate_pub_key(sig.C_prime); break;
|
||||
case 5: sig.d.make_random(); break;
|
||||
case 6: invalidate_pub_key(sig.E); break;
|
||||
case 7: invalidate_bppe_sig(sig.E_range_proof); break;
|
||||
case 8: invalidate_pub_key(sig.pseudo_out_amount_commitment); break;
|
||||
case 9: sig.y0.make_random(); break;
|
||||
case 10: sig.y1.make_random(); break;
|
||||
case 11: sig.y2.make_random(); break;
|
||||
case 12: sig.y3.make_random(); break;
|
||||
case 13: sig.y4.make_random(); break;
|
||||
default: return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
zarcanum_basic_test::zarcanum_basic_test()
|
||||
{
|
||||
|
|
@ -339,6 +380,48 @@ zarcanum_pos_block_math::zarcanum_pos_block_math()
|
|||
m_hardforks.set_hardfork_height(ZANO_HARDFORK_04_ZARCANUM, 0);
|
||||
}
|
||||
|
||||
bool make_next_pos_block(test_generator& generator, std::vector<test_event_entry>& events, const block& prev_block, const account_base& stake_acc,
|
||||
uint64_t amount_to_find, size_t nmix, block& result)
|
||||
{
|
||||
bool r = false;
|
||||
std::vector<tx_source_entry> sources;
|
||||
|
||||
size_t height = get_block_height(prev_block) + 1;
|
||||
crypto::hash prev_id = get_block_hash(prev_block);
|
||||
r = fill_tx_sources(sources, events, prev_block, stake_acc.get_keys(), amount_to_find, nmix, true, true, false);
|
||||
CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources failed");
|
||||
CHECK_AND_ASSERT_MES(shuffle_source_entries(sources), false, "");
|
||||
auto it = std::max_element(sources.begin(), sources.end(), [&](const tx_source_entry& lhs, const tx_source_entry& rhs){ return lhs.amount < rhs.amount; });
|
||||
const tx_source_entry& se = *it;
|
||||
const tx_source_entry::output_entry& oe = se.outputs[se.real_output];
|
||||
|
||||
crypto::key_image stake_output_key_image {};
|
||||
currency::keypair ephemeral_keys {};
|
||||
r = generate_key_image_helper(stake_acc.get_keys(), se.real_out_tx_key, se.real_output_in_tx_index, ephemeral_keys, stake_output_key_image);
|
||||
CHECK_AND_ASSERT_MES(r, false, "generate_key_image_helper failed");
|
||||
uint64_t stake_output_gindex = boost::get<uint64_t>(oe.out_reference);
|
||||
|
||||
currency::wide_difficulty_type pos_diff{};
|
||||
crypto::hash last_pow_block_hash{}, last_pos_block_kernel_hash{};
|
||||
r = generator.get_params_for_next_pos_block(prev_id, pos_diff, last_pow_block_hash, last_pos_block_kernel_hash);
|
||||
CHECK_AND_ASSERT_MES(r, false, "get_params_for_next_pos_block failed");
|
||||
|
||||
pos_block_builder pb;
|
||||
pb.step1_init_header(generator.get_hardforks(), height, prev_id);
|
||||
pb.step2_set_txs(std::vector<transaction>());
|
||||
|
||||
pb.step3a(pos_diff, last_pow_block_hash, last_pos_block_kernel_hash);
|
||||
|
||||
pb.step3b(se.amount, stake_output_key_image, se.real_out_tx_key, se.real_output_in_tx_index, se.real_out_amount_blinding_mask, stake_acc.get_keys().view_secret_key,
|
||||
stake_output_gindex, prev_block.timestamp, POS_SCAN_WINDOW, POS_SCAN_STEP);
|
||||
|
||||
pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(prev_block), stake_acc.get_public_address());
|
||||
|
||||
pb.step5_sign(se, stake_acc.get_keys());
|
||||
result = pb.m_block;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool zarcanum_pos_block_math::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
bool r = false;
|
||||
|
|
@ -347,63 +430,44 @@ bool zarcanum_pos_block_math::generate(std::vector<test_event_entry>& events) co
|
|||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());
|
||||
DO_CALLBACK(events, "configure_core"); // necessary to set m_hardforks
|
||||
MAKE_NEXT_BLOCK(events, blk_1, blk_0, miner_acc);
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 10);
|
||||
|
||||
//generator.get_tx_out_gindex
|
||||
|
||||
// try to make a PoS block with locked stake after the hardfork
|
||||
|
||||
block blk_1_pos;
|
||||
// blocks with an invalid zarcanum sig
|
||||
for(size_t i = 1; ; ++i)
|
||||
{
|
||||
const block& prev_block = blk_1r;
|
||||
const transaction& stake_tx = blk_1.miner_tx;
|
||||
const account_base& stake_acc = miner_acc;
|
||||
size_t stake_out_in_tx_index = 0;
|
||||
size_t stake_output_gindex = 0;
|
||||
|
||||
crypto::hash prev_id = get_block_hash(prev_block);
|
||||
size_t height = get_block_height(prev_block) + 1;
|
||||
currency::wide_difficulty_type diff = generator.get_difficulty_for_next_block(prev_id, false);
|
||||
crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake_tx);
|
||||
|
||||
pos_block_builder pb;
|
||||
pb.step1_init_header(generator.get_hardforks(), height, prev_id);
|
||||
pb.step2_set_txs(std::vector<transaction>());
|
||||
|
||||
pb.step3a(diff, prev_id, null_hash);
|
||||
|
||||
crypto::key_derivation derivation {};
|
||||
crypto::scalar_t stake_out_blinding_mask {};
|
||||
uint64_t stake_output_amount = 0;
|
||||
crypto::public_key stealth_address {};
|
||||
crypto::secret_key secret_x {};
|
||||
crypto::key_image stake_output_key_image {};
|
||||
|
||||
r = generate_key_derivation(stake_tx_pub_key, stake_acc.get_keys().view_secret_key, derivation);
|
||||
CHECK_AND_ASSERT_MES(r, false, "generate_key_derivation failed");
|
||||
r = is_out_to_acc(stake_acc.get_public_address(), boost::get<currency::tx_out_zarcanum>(stake_tx.vout[stake_out_in_tx_index]), derivation, stake_out_in_tx_index, stake_output_amount, stake_out_blinding_mask);
|
||||
CHECK_AND_ASSERT_MES(r, false, "is_out_to_acc failed");
|
||||
r = crypto::derive_public_key(derivation, stake_out_in_tx_index, stake_acc.get_public_address().spend_public_key, stealth_address);
|
||||
CHECK_AND_ASSERT_MES(r, false, "derive_public_key failed");
|
||||
crypto::derive_secret_key(derivation, stake_out_in_tx_index, stake_acc.get_keys().spend_secret_key, secret_x);
|
||||
crypto::generate_key_image(stealth_address, secret_x, stake_output_key_image);
|
||||
|
||||
|
||||
pb.step3b(stake_output_amount, stake_output_key_image, stake_tx_pub_key, stake_out_in_tx_index, stake_out_blinding_mask, stake_acc.get_keys().view_secret_key,
|
||||
stake_output_gindex, prev_block.timestamp, POS_SCAN_WINDOW, POS_SCAN_STEP);
|
||||
|
||||
pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(prev_block), stake_acc.get_public_address());
|
||||
|
||||
pb.step5_sign(stake_tx_pub_key, stake_out_in_tx_index, stake_tx_pub_key, stake_acc);
|
||||
|
||||
blk_1_pos = pb.m_block;
|
||||
block blk_1_pos_bad;
|
||||
CHECK_AND_ASSERT_MES(make_next_pos_block(generator, events, blk_1r, miner_acc, COIN, 10, blk_1_pos_bad), false, "");
|
||||
LOG_PRINT_CYAN("i = " << i, LOG_LEVEL_0);
|
||||
if (!invalidate_zarcanum_sig(i, boost::get<zarcanum_sig>(blk_1_pos_bad.miner_tx.signatures[0])))
|
||||
break;
|
||||
generator.add_block_info(blk_1_pos_bad, std::list<transaction>{});
|
||||
DO_CALLBACK(events, "mark_invalid_block");
|
||||
ADD_CUSTOM_EVENT(events, blk_1_pos_bad);
|
||||
}
|
||||
|
||||
ADD_CUSTOM_EVENT(events, blk_1_pos);
|
||||
// make a normal PoS block
|
||||
std::list<currency::account_base> miner_stake_sources( {miner_acc} );
|
||||
MAKE_NEXT_POS_BLOCK(events, blk_2, blk_1r, miner_acc, miner_stake_sources);
|
||||
// ... and a PoW block
|
||||
MAKE_NEXT_BLOCK(events, blk_3, blk_2, miner_acc);
|
||||
|
||||
// make a PoS block and than change its nonce, so its hash also changes
|
||||
// this block should fail
|
||||
MAKE_NEXT_POS_BLOCK(events, blk_4_bad, blk_3, miner_acc, miner_stake_sources);
|
||||
generator.remove_block_info(blk_4_bad);
|
||||
events.pop_back();
|
||||
blk_4_bad.nonce = 0xc0ffee; // this will change block's hash
|
||||
generator.add_block_info(blk_4_bad, std::list<transaction>{});
|
||||
DO_CALLBACK(events, "mark_invalid_block");
|
||||
ADD_CUSTOM_EVENT(events, blk_4_bad);
|
||||
|
||||
// finally, make a normal block
|
||||
MAKE_NEXT_POS_BLOCK(events, blk_4, blk_3, miner_acc, miner_stake_sources);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
zarcanum_txs_with_big_shuffled_decoy_set_shuffled::zarcanum_txs_with_big_shuffled_decoy_set_shuffled()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue