diff options
Diffstat (limited to 'src/cryptonote_core/blockchain.cpp')
-rw-r--r-- | src/cryptonote_core/blockchain.cpp | 34 |
1 files changed, 11 insertions, 23 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index da14d7575..70cbaf0fd 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1991,7 +1991,7 @@ bool Blockchain::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<u // This function overloads its sister function with // an extra value (hash of highest block that holds an output used as input) // as a return-by-reference. -bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t& max_used_block_height, crypto::hash& max_used_block_id, bool kept_by_block) +bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t& max_used_block_height, crypto::hash& max_used_block_id, tx_verification_context &tvc, bool kept_by_block) { LOG_PRINT_L3("Blockchain::" << __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); @@ -2013,26 +2013,20 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t& max_used_block #endif TIME_MEASURE_START(a); - bool res = check_tx_inputs(tx, &max_used_block_height); + bool res = check_tx_inputs(tx, tvc, &max_used_block_height); TIME_MEASURE_FINISH(a); - crypto::hash tx_prefix_hash = get_transaction_prefix_hash(tx); if(m_show_time_stats) LOG_PRINT_L0("HASH: " << "+" << " VIN/VOUT: " << tx.vin.size() << "/" << tx.vout.size() << " H: " << max_used_block_height << " chcktx: " << a + m_fake_scan_time); if (!res) return false; - // ND: Speedup: - // 1. keep a list of verified transactions, when the Blockchain tries to check a tx again, - // verify against list and skip if already verified to be correct. - m_check_tx_inputs_table.emplace(tx_prefix_hash, std::make_pair(res, max_used_block_height)); - CHECK_AND_ASSERT_MES(max_used_block_height < m_db->height(), false, "internal error: max used block index=" << max_used_block_height << " is not less then blockchain size = " << m_db->height()); max_used_block_id = m_db->get_block_hash_from_height(max_used_block_height); return true; } //------------------------------------------------------------------ -bool Blockchain::check_tx_outputs(const transaction& tx) +bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context &tvc) { LOG_PRINT_L3("Blockchain::" << __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); @@ -2041,6 +2035,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx) if (m_hardfork->get_current_version() >= 2) { for (auto &o: tx.vout) { if (!is_valid_decomposed_amount(o.amount)) { + tvc.m_invalid_output = true; return false; } } @@ -2066,7 +2061,7 @@ bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const // check_tx_input() rather than here, and use this function simply // to iterate the inputs as necessary (splitting the task // using threads, etc.) -bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_block_height) +bool Blockchain::check_tx_inputs(const transaction& tx, tx_verification_context &tvc, uint64_t* pmax_used_block_height) { LOG_PRINT_L3("Blockchain::" << __func__); size_t sig_index = 0; @@ -2075,16 +2070,6 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_bloc crypto::hash tx_prefix_hash = get_transaction_prefix_hash(tx); - auto its = m_check_tx_inputs_table.find(tx_prefix_hash); - if (its != m_check_tx_inputs_table.end()) - { - if (!its->second.first) - return false; - if (pmax_used_block_height) - *pmax_used_block_height = its->second.second; - return true; - } - // from hard fork 2, we require mixin at least 2 unless one output cannot mix with 2 others // if one output cannot mix with 2 others, we accept at most 1 output that can mix if (m_hardfork->get_current_version() >= 2) @@ -2113,11 +2098,13 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_bloc if (n_unmixable == 0) { LOG_PRINT_L1("Tx " << get_transaction_hash(tx) << " has too low mixin (" << mixin << "), and no unmixable inputs"); + tvc.m_low_mixin = true; return false; } if (n_mixable > 1) { LOG_PRINT_L1("Tx " << get_transaction_hash(tx) << " has too low mixin (" << mixin << "), and more than one mixable input with unmixable inputs"); + tvc.m_low_mixin = true; return false; } } @@ -2156,6 +2143,7 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_bloc if(ioservice_active) \ { \ work.reset(); \ + while (!ioservice.stopped()) ioservice.poll(); \ threadpool.join_all(); \ ioservice.stop(); \ ioservice_active = false; \ @@ -2176,6 +2164,7 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_bloc if(have_tx_keyimg_as_spent(in_to_key.k_image)) { LOG_PRINT_L1("Key image already spent in blockchain: " << epee::string_tools::pod_to_hex(in_to_key.k_image)); + tvc.m_double_spend = true; return false; } @@ -2667,7 +2656,8 @@ leave: #endif { // validate that transaction inputs and the keys spending them are correct. - if(!check_tx_inputs(tx)) + tx_verification_context tvc; + if(!check_tx_inputs(tx, tvc)) { LOG_PRINT_L1("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs."); @@ -2962,7 +2952,6 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync) TIME_MEASURE_FINISH(t1); m_blocks_longhash_table.clear(); m_scan_table.clear(); - m_check_tx_inputs_table.clear(); m_blocks_txs_check.clear(); m_check_txin_table.clear(); @@ -3110,7 +3099,6 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e m_fake_pow_calc_time = 0; m_scan_table.clear(); - m_check_tx_inputs_table.clear(); m_check_txin_table.clear(); TIME_MEASURE_FINISH(prepare); |