mirror of
https://github.com/wownero/wownero.git
synced 2026-10-28 11:58:34 +01:00
Refactored tx verification NIC logic
Encapsulated `nic_verified_hf_version` and `txs_by_txid` to make it impossible for callers to skip updating it.
This commit is contained in:
@@ -2057,7 +2057,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
|||||||
|
|
||||||
// Add pool supplement txs to the main mempool with relay_method::block
|
// Add pool supplement txs to the main mempool with relay_method::block
|
||||||
CRITICAL_REGION_LOCAL(m_tx_pool);
|
CRITICAL_REGION_LOCAL(m_tx_pool);
|
||||||
for (auto& extra_block_tx : extra_block_txs.txs_by_txid)
|
for (auto& extra_block_tx : extra_block_txs)
|
||||||
{
|
{
|
||||||
const crypto::hash& txid = extra_block_tx.first;
|
const crypto::hash& txid = extra_block_tx.first;
|
||||||
transaction& tx = extra_block_tx.second.first;
|
transaction& tx = extra_block_tx.second.first;
|
||||||
@@ -2084,8 +2084,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
|||||||
.weight = get_transaction_weight(tx),
|
.weight = get_transaction_weight(tx),
|
||||||
.res = true}});
|
.res = true}});
|
||||||
}
|
}
|
||||||
extra_block_txs.txs_by_txid.clear();
|
extra_block_txs.clear();
|
||||||
extra_block_txs.nic_verified_hf_version = 0;
|
|
||||||
|
|
||||||
bei.block_cumulative_weight = cryptonote::get_transaction_weight(b.miner_tx);
|
bei.block_cumulative_weight = cryptonote::get_transaction_weight(b.miner_tx);
|
||||||
for (const crypto::hash &txid: b.tx_hashes)
|
for (const crypto::hash &txid: b.tx_hashes)
|
||||||
@@ -4176,15 +4175,15 @@ leave:
|
|||||||
bool find_tx_failure{!found_tx_in_pool};
|
bool find_tx_failure{!found_tx_in_pool};
|
||||||
if (!found_tx_in_pool) // if not in mempool:
|
if (!found_tx_in_pool) // if not in mempool:
|
||||||
{
|
{
|
||||||
const auto extra_txs_it{extra_block_txs.txs_by_txid.find(tx_id)};
|
const auto extra_txs_it{extra_block_txs.find(tx_id)};
|
||||||
if (extra_txs_it != extra_block_txs.txs_by_txid.end()) // if in block supplement:
|
if (extra_txs_it != extra_block_txs.end()) // if in block supplement:
|
||||||
{
|
{
|
||||||
tx = std::move(extra_txs_it->second.first);
|
tx = std::move(extra_txs_it->second.first);
|
||||||
txblob = std::move(extra_txs_it->second.second);
|
txblob = std::move(extra_txs_it->second.second);
|
||||||
tx_weight = tx.pruned ? get_pruned_transaction_weight(tx) : get_transaction_weight(tx, txblob.size());
|
tx_weight = tx.pruned ? get_pruned_transaction_weight(tx) : get_transaction_weight(tx, txblob.size());
|
||||||
fee = get_tx_fee(tx);
|
fee = get_tx_fee(tx);
|
||||||
pruned = tx.pruned;
|
pruned = tx.pruned;
|
||||||
extra_block_txs.txs_by_txid.erase(extra_txs_it);
|
extra_block_txs.erase(extra_txs_it);
|
||||||
txpool_events.emplace_back(txpool_event{tx, tx_id, txblob.size(), tx_weight, true});
|
txpool_events.emplace_back(txpool_event{tx, tx_id, txblob.size(), tx_weight, true});
|
||||||
find_tx_failure = false;
|
find_tx_failure = false;
|
||||||
}
|
}
|
||||||
@@ -4197,7 +4196,7 @@ leave:
|
|||||||
// txs twice.
|
// txs twice.
|
||||||
if (find_tx_failure) // did not find txid in mempool or provided extra block txs
|
if (find_tx_failure) // did not find txid in mempool or provided extra block txs
|
||||||
{
|
{
|
||||||
const bool fully_supplemented_block = extra_block_txs.txs_by_txid.size() >= bl.tx_hashes.size();
|
const bool fully_supplemented_block = extra_block_txs.size() >= bl.tx_hashes.size();
|
||||||
if (fully_supplemented_block)
|
if (fully_supplemented_block)
|
||||||
MERROR_VER("Block with id: " << id << " has at least one unknown transaction with id: " << tx_id);
|
MERROR_VER("Block with id: " << id << " has at least one unknown transaction with id: " << tx_id);
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1460,7 +1460,7 @@ namespace cryptonote
|
|||||||
// saving each block, then it doesn't matter either way: cleanup_handle_incoming_blocks()
|
// saving each block, then it doesn't matter either way: cleanup_handle_incoming_blocks()
|
||||||
// always triggers a sync.
|
// always triggers a sync.
|
||||||
size_t block_total_bytes = block_blob.size();
|
size_t block_total_bytes = block_blob.size();
|
||||||
for (const auto &t : extra_block_txs.txs_by_txid)
|
for (const auto &t : extra_block_txs)
|
||||||
block_total_bytes += t.second.second.size();
|
block_total_bytes += t.second.second.size();
|
||||||
|
|
||||||
CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
|
CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
|
||||||
|
|||||||
@@ -469,7 +469,7 @@ bool ver_non_input_consensus(const transaction& tx, tx_verification_context& tvc
|
|||||||
return ver_non_input_consensus_templated(&tx, &tx + 1, tvc, hf_version);
|
return ver_non_input_consensus_templated(&tx, &tx + 1, tvc, hf_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ver_non_input_consensus(const pool_supplement& ps, tx_verification_context& tvc,
|
bool ver_non_input_consensus(pool_supplement& ps, tx_verification_context& tvc,
|
||||||
const std::uint8_t hf_version)
|
const std::uint8_t hf_version)
|
||||||
{
|
{
|
||||||
// We already verified the pool supplement for this hard fork version! Yippee!
|
// We already verified the pool supplement for this hard fork version! Yippee!
|
||||||
|
|||||||
@@ -89,12 +89,46 @@ bool ver_mixed_rct_semantics(std::vector<const rct::rctSig*> rvv);
|
|||||||
*/
|
*/
|
||||||
struct pool_supplement
|
struct pool_supplement
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
using txs_by_txid_t = std::unordered_map<crypto::hash, std::pair<transaction, blobdata>>;
|
||||||
|
|
||||||
|
bool add_tx(const crypto::hash& id, transaction&& tx, const blobdata& blob)
|
||||||
|
{
|
||||||
|
// Any new tx invalidates previous verification
|
||||||
|
nic_verified_hf_version = 0;
|
||||||
|
|
||||||
|
return txs_by_txid.emplace(id, std::make_pair(std::move(tx), blob)).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
txs_by_txid.clear();
|
||||||
|
|
||||||
|
// Empty set can technically stay validated, but reset it to 0 anyway.
|
||||||
|
nic_verified_hf_version = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
txs_by_txid_t::iterator begin() { return txs_by_txid.begin(); }
|
||||||
|
txs_by_txid_t::iterator end() { return txs_by_txid.end(); }
|
||||||
|
|
||||||
|
txs_by_txid_t::const_iterator begin() const { return txs_by_txid.begin(); }
|
||||||
|
txs_by_txid_t::const_iterator end() const { return txs_by_txid.end(); }
|
||||||
|
|
||||||
|
txs_by_txid_t::iterator find(const crypto::hash& id) { return txs_by_txid.find(id); }
|
||||||
|
|
||||||
|
txs_by_txid_t::iterator erase(txs_by_txid_t::iterator it) { return txs_by_txid.erase(it); }
|
||||||
|
|
||||||
|
size_t size() const { return txs_by_txid.size(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The only function which can set nic_verified_hf_version to non-zero value
|
||||||
|
friend bool ver_non_input_consensus(pool_supplement& ps, tx_verification_context& tvc, std::uint8_t hf_version);
|
||||||
|
|
||||||
// Map of supplemental tx info that we might need to validate a block
|
// Map of supplemental tx info that we might need to validate a block
|
||||||
// Maps TXID -> transaction and blob
|
// Maps TXID -> transaction and blob
|
||||||
std::unordered_map<crypto::hash, std::pair<transaction, blobdata>> txs_by_txid;
|
txs_by_txid_t txs_by_txid;
|
||||||
// If non-zero, then consider all the txs' non-input consensus (NIC) rules verified for this
|
// If non-zero, then consider all the txs' non-input consensus (NIC) rules verified for this
|
||||||
// hard fork. User: If you add an unverified transaction to txs_by_txid, set this field to zero!
|
// hard fork. User: If you add an unverified transaction to txs_by_txid, set this field to zero!
|
||||||
mutable std::uint8_t nic_verified_hf_version = 0;
|
std::uint8_t nic_verified_hf_version = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,7 +158,7 @@ struct pool_supplement
|
|||||||
bool ver_non_input_consensus(const transaction& tx, tx_verification_context& tvc,
|
bool ver_non_input_consensus(const transaction& tx, tx_verification_context& tvc,
|
||||||
std::uint8_t hf_version);
|
std::uint8_t hf_version);
|
||||||
|
|
||||||
bool ver_non_input_consensus(const pool_supplement& ps, tx_verification_context& tvc,
|
bool ver_non_input_consensus(pool_supplement& ps, tx_verification_context& tvc,
|
||||||
std::uint8_t hf_version);
|
std::uint8_t hf_version);
|
||||||
|
|
||||||
} // namespace cryptonote
|
} // namespace cryptonote
|
||||||
|
|||||||
@@ -91,8 +91,6 @@ namespace cryptonote
|
|||||||
const bool allow_pruned,
|
const bool allow_pruned,
|
||||||
cryptonote::pool_supplement& pool_supplement)
|
cryptonote::pool_supplement& pool_supplement)
|
||||||
{
|
{
|
||||||
pool_supplement.nic_verified_hf_version = 0;
|
|
||||||
|
|
||||||
if (tx_entries.size() > blk_tx_hashes.size())
|
if (tx_entries.size() > blk_tx_hashes.size())
|
||||||
{
|
{
|
||||||
MERROR("Failed to make pool supplement: Too many transaction blobs!");
|
MERROR("Failed to make pool supplement: Too many transaction blobs!");
|
||||||
@@ -140,7 +138,7 @@ namespace cryptonote
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pool_supplement.txs_by_txid.emplace(tx_hash, std::make_pair(std::move(tx), tx_entry.blob));
|
pool_supplement.add_tx(tx_hash, std::move(tx), tx_entry.blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user