diff --git a/src/crypto/zarcanum.cpp b/src/crypto/zarcanum.cpp index 043f4113..00e27460 100644 --- a/src/crypto/zarcanum.cpp +++ b/src/crypto/zarcanum.cpp @@ -204,6 +204,22 @@ namespace crypto DBG_PRINT("zarcanum_verify_proof"); bool r = false; + //std::cout << "===== zarcanum_verify_proof =====" << ENDL + // << "m: " << m << ENDL + // << "kernel_hash: " << kernel_hash << ENDL + // << "last_pow_block_id_hashed: " << last_pow_block_id_hashed << ENDL + // << "stake_ki: " << stake_ki << ENDL + // << "pos_difficulty: " << pos_difficulty << ENDL; + //size_t ii = 0; + //for(const auto& el : ring) + //{ + // std::cout << "[" << ii << "]" << ENDL + // << " amount_commitment: " << el.amount_commitment << ENDL + // << " blinded_asset_id: " << el.blinded_asset_id << ENDL + // << " concealing_point: " << el.concealing_point << ENDL + // << " stealth_address: " << el.stealth_address << ENDL; + //} + // 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); diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index a13c9a38..405e9895 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -5591,30 +5591,35 @@ bool blockchain_storage::validate_pos_block(const block& b, const txin_zc_input& stake_input = boost::get(b.miner_tx.vin[1]); 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(b.miner_tx.signatures[0]); + + if (!for_altchain) + { + // do general input check for main chain blocks only + // TODO @#@#: txs in alternative PoS blocks (including miner_tx) must be validated by validate_alt_block_txs() + const zarcanum_sig& sig = boost::get(b.miner_tx.signatures[0]); + uint64_t max_related_block_height = 0; + std::vector dummy_output_keys; // won't be used + uint64_t dummy_source_max_unlock_time_for_pos_coinbase_dummy = 0; // won't be used + scan_for_keys_context scan_contex = AUTO_VAL_INIT(scan_contex); + 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); - // TODO @#@# do general input check for main chain blocks only? - uint64_t max_related_block_height = 0; - std::vector dummy_output_keys; // won't be used - uint64_t dummy_source_max_unlock_time_for_pos_coinbase_dummy = 0; // won't be used - scan_for_keys_context scan_contex = AUTO_VAL_INIT(scan_contex); - 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 ring; + ring.reserve(scan_contex.zc_outs.size()); + for(auto& zc_out : scan_contex.zc_outs) + ring.emplace_back(zc_out.stealth_address, zc_out.amount_commitment, zc_out.blinded_asset_id, zc_out.concealing_point); - // build a ring of references - vector ring; - ring.reserve(scan_contex.zc_outs.size()); - for(auto& zc_out : scan_contex.zc_outs) - ring.emplace_back(zc_out.stealth_address, zc_out.amount_commitment, zc_out.blinded_asset_id, zc_out.concealing_point); + crypto::scalar_t last_pow_block_id_hashed = crypto::hash_helper_t::hs(CRYPTO_HDS_ZARCANUM_LAST_POW_HASH, sm.last_pow_id); - 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(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); + } - uint8_t err = 0; - 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 @@ -7155,10 +7160,13 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, } else { + // TODO @#@# properly handle ZC inputs! check_tx_input below isn't working because of incorrectly assembled ring + /* uint64_t max_related_block_height = 0; bool all_tx_ins_have_explicit_asset_ids = true; // stub for now, TODO @#@# r = check_tx_input(input_tx, input_index, input_zc, input_tx_hash, max_related_block_height, all_tx_ins_have_explicit_asset_ids); CHECK_AND_ASSERT_MES(r, false, "check_tx_input failed"); + */ } VARIANT_CASE_OTHER() LOG_ERROR("unexpected input type: " << input_v.type().name()); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 3b077130..9a8b6057 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -4064,6 +4064,11 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, currency::bl WLT_CHECK_AND_ASSERT_MES(r, false, "generate_tx_balance_proof failed"); b.miner_tx.proofs.emplace_back(std::move(balance_proof)); + // the following line are for debugging when necessary -- sowle + //err = 0; + //r = crypto::zarcanum_verify_proof(hash_for_zarcanum_sig, cxt.kernel_hash, ring, cxt.last_pow_block_id_hashed, cxt.sk.kimage, cxt.basic_diff, sig, &err); + //WLT_CHECK_AND_ASSERT_MES(r, false, "zarcanum_verify_proof failed with code " << (int)err); + return true; } //------------------------------------------------------------------ diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 97d799d7..6c375181 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -642,10 +642,10 @@ bool test_generator::find_kernel(const std::list& accs, pe.tx_out_index = td.m_internal_output_index; pe.wallet_index = context.index; - LOG_PRINT_GREEN("Found kernel: amount=" << print_money_brief(pe.amount) - << ", gindex=" << pe.g_index - << ", key_image=" << pe.keyimage - /*<< ", diff: " << this_coin_diff*/, LOG_LEVEL_1); + LOG_PRINT_GREEN("Additional kernel info: source tx id: " << pe.tx_id + << ", key_image: " << pe.keyimage + << ", gindex: " << pe.g_index + << ", out's height: " << td.m_ptx_wallet_info->m_block_height, LOG_LEVEL_1); return true; } diff --git a/tests/core_tests/zarcanum_test.cpp b/tests/core_tests/zarcanum_test.cpp index 79d783d8..5ad4afb3 100644 --- a/tests/core_tests/zarcanum_test.cpp +++ b/tests/core_tests/zarcanum_test.cpp @@ -636,7 +636,8 @@ bool zarcanum_in_alt_chain::generate(std::vector& events) cons // | // 0 10 11 21 22 23 | 24 34 35 36 <- blockchain height // (0 )..(0r)- (1 )..(1r)- !2 !- (3 )- (4 )..(4r)- (5 ) <- main chain - // tx_0 tx_1 \ tx_2 + // tx_0 tx_1 \ tx_2a + // \ tx_2b // -!5a!- (6a) <- alt chain REWIND_BLOCKS_N_WITH_TIME(events, blk_4r, blk_4, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); @@ -648,27 +649,50 @@ bool zarcanum_in_alt_chain::generate(std::vector& events) cons MAKE_NEXT_BLOCK_TX_LIST(events, blk_5, blk_4r, miner_acc, std::list({ tx_2a, tx_2b })); // now in the main chain Bob has zero coins - // check it + // check it in gen time ... CREATE_TEST_WALLET(bob_wlt, bob_acc, blk_0); REFRESH_TEST_WALLET_AT_GEN_TIME(events, bob_wlt, blk_5, 3 * CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5); CHECK_TEST_WALLET_BALANCE_AT_GEN_TIME(bob_wlt, 0); + // ... and in play time + DO_CALLBACK_PARAMS(events, "check_balance", params_check_balance(BOB_ACC_IDX, 0)); // TODO: check PoS mining against already spent key image + // HF4 + // | + // 0 .. 10 11 21 22 23 | 24 .. 34 35 36 .. 45 46 47 <- blockchain height + // (0 )..(0r)- (1 )..(1r)- !2 !- (3 )- (4 )..(4r)- (5 )- <- alt chain + // tx_0 tx_1 \ tx_2a + // \ tx_2b + // \ c1 + // -!5a!- (6a)- . . . (6ar)|(c1) <- main chain + std::list bob_stake_sources({ bob_acc }); MAKE_NEXT_POS_BLOCK(events, blk_5a, blk_4r, bob_acc, bob_stake_sources); // NOTE: tx_2a and blk_5a spend the same Bob's output MAKE_NEXT_BLOCK(events, blk_6a, blk_5a, miner_acc); - DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(get_block_height(blk_6a), get_block_hash(blk_6a))); + DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(blk_6a)); REWIND_BLOCKS_N_WITH_TIME(events, blk_6ar, blk_6a, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); DO_CALLBACK(events, "c1"); + // HF4 + // | + // 0 .. 10 11 21 22 23 | 24 .. 34 35 36 .. 45 46 47 <- blockchain height + // (0 )..(0r)- (1 )..(1r)- !2 !- (3 )- (4 )..(4r)- (5 )- . . . (5r)- !6 !- (7 ) <- main chain + // tx_0 tx_1 \ tx_2a + // \ tx_2b + // \ c1 + // -!5a!- (6a)- . . . (6ar)|(c1) <- alt chain + REWIND_BLOCKS_N_WITH_TIME(events, blk_5r, blk_5, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); MAKE_NEXT_POS_BLOCK(events, blk_6, blk_5r, alice_acc, alice_stake_sources); MAKE_NEXT_BLOCK(events, blk_7, blk_6, miner_acc); + MAKE_NEXT_BLOCK(events, blk_8, blk_7, miner_acc); + + DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(blk_8)); return true; }