verRctNonSemanticsSimpleCached: fix fragility

This commit is contained in:
Jeffrey Ryan 2023-01-13 20:53:25 -06:00 committed by jeffro256
parent 99be9a044f
commit c59e0096b6
12 changed files with 715 additions and 111 deletions

View file

@ -57,6 +57,7 @@
#include "common/notify.h"
#include "common/varint.h"
#include "common/pruning.h"
#include "common/data_cache.h"
#include "time_helper.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
@ -98,7 +99,8 @@ Blockchain::Blockchain(tx_memory_pool& tx_pool) :
m_difficulty_for_next_block(1),
m_btc_valid(false),
m_batch_success(true),
m_prepare_height(0)
m_prepare_height(0),
m_rct_ver_cache()
{
LOG_PRINT_L3("Blockchain::" << __func__);
}
@ -3211,7 +3213,7 @@ bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const
}
return false;
}
bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_prefix_hash, const std::vector<std::vector<rct::ctkey>> &pubkeys) const
bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_prefix_hash, const std::vector<std::vector<rct::ctkey>> &pubkeys)
{
PERF_TIMER(expand_transaction_2);
CHECK_AND_ASSERT_MES(tx.version == 2, false, "Transaction version is not 2");
@ -3534,6 +3536,13 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
false, "Transaction spends at least one output which is too young");
}
// Warn that new RCT types are present, and thus the cache is not being used effectively
static constexpr const std::uint8_t RCT_CACHE_TYPE = rct::RCTTypeBulletproofPlus;
if (tx.rct_signatures.type > RCT_CACHE_TYPE)
{
MWARNING("RCT cache is not caching new verification results. Please update RCT_CACHE_TYPE!");
}
if (tx.version == 1)
{
if (threads > 1)
@ -3555,12 +3564,6 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
}
else
{
if (!expand_transaction_2(tx, tx_prefix_hash, pubkeys))
{
MERROR_VER("Failed to expand rct signatures!");
return false;
}
// from version 2, check ringct signatures
// obviously, the original and simple rct APIs use a mixRing that's indexes
// in opposite orders, because it'd be too simple otherwise...
@ -3578,61 +3581,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
case rct::RCTTypeCLSAG:
case rct::RCTTypeBulletproofPlus:
{
// check all this, either reconstructed (so should really pass), or not
{
if (pubkeys.size() != rv.mixRing.size())
{
MERROR_VER("Failed to check ringct signatures: mismatched pubkeys/mixRing size");
return false;
}
for (size_t i = 0; i < pubkeys.size(); ++i)
{
if (pubkeys[i].size() != rv.mixRing[i].size())
{
MERROR_VER("Failed to check ringct signatures: mismatched pubkeys/mixRing size");
return false;
}
}
for (size_t n = 0; n < pubkeys.size(); ++n)
{
for (size_t m = 0; m < pubkeys[n].size(); ++m)
{
if (pubkeys[n][m].dest != rct::rct2pk(rv.mixRing[n][m].dest))
{
MERROR_VER("Failed to check ringct signatures: mismatched pubkey at vin " << n << ", index " << m);
return false;
}
if (pubkeys[n][m].mask != rct::rct2pk(rv.mixRing[n][m].mask))
{
MERROR_VER("Failed to check ringct signatures: mismatched commitment at vin " << n << ", index " << m);
return false;
}
}
}
}
const size_t n_sigs = rct::is_rct_clsag(rv.type) ? rv.p.CLSAGs.size() : rv.p.MGs.size();
if (n_sigs != tx.vin.size())
{
MERROR_VER("Failed to check ringct signatures: mismatched MGs/vin sizes");
return false;
}
for (size_t n = 0; n < tx.vin.size(); ++n)
{
bool error;
if (rct::is_rct_clsag(rv.type))
error = memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.CLSAGs[n].I, 32);
else
error = rv.p.MGs[n].II.empty() || memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.MGs[n].II[0], 32);
if (error)
{
MERROR_VER("Failed to check ringct signatures: mismatched key image");
return false;
}
}
if (!rct::verRctNonSemanticsSimpleCached(rv))
if (!ver_rct_non_semantics_simple_cached(tx, pubkeys, m_rct_ver_cache, RCT_CACHE_TYPE))
{
MERROR_VER("Failed to check ringct signatures!");
return false;
@ -3641,6 +3590,12 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
}
case rct::RCTTypeFull:
{
if (!expand_transaction_2(tx, tx_prefix_hash, pubkeys))
{
MERROR_VER("Failed to expand rct signatures!");
return false;
}
// check all this, either reconstructed (so should really pass), or not
{
bool size_matches = true;