Skip to content

Commit

Permalink
Introduced partial validation in accept to mempool
Browse files Browse the repository at this point in the history
  • Loading branch information
abi87 committed Apr 7, 2021
1 parent f0150a7 commit 9ed19be
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 36 deletions.
73 changes: 44 additions & 29 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,18 @@ CAmount GetMinRelayFee(const CTransactionBase& tx, unsigned int nBytes, bool fAl
return nMinFee;
}

void StoreCertToMempool(const CScCertificate &cert, CTxMemPool &pool, const CCoinsViewCache &view)
{
std::pair<uint256, CAmount> conflictingCertData = pool.FindCertWithQuality(cert.GetScId(), cert.quality);
pool.RemoveCertAndSync(conflictingCertData.first);

CAmount nCertFees = cert.GetFeeAmount(view.GetValueIn(cert));
double dCertPriority = view.GetPriority(cert, chainActive.Height());
CCertificateMemPoolEntry entry(cert, nCertFees, GetTime(), dCertPriority, chainActive.Height());
pool.addUnchecked(cert.GetHash(), entry, !IsInitialBlockDownload());
return;
}

MempoolReturnValue AcceptCertificateToMemoryPool(CTxMemPool& pool, CValidationState &state, const CScCertificate &cert,
LimitFreeFlag fLimitFree, RejectAbsurdFeeFlag fRejectAbsurdFee, ValidateSidechainProof validateScProofs)
{
Expand Down Expand Up @@ -1084,14 +1096,6 @@ MempoolReturnValue AcceptCertificateToMemoryPool(CTxMemPool& pool, CValidationSt
REJECT_INVALID, "bad-sc-cert-not-applicable");
return MempoolReturnValue::INVALID;
}

CScProofVerifier scVerifier{CScProofVerifier::Verification::Strict};
if (!view.CheckCertificateProof(cert, scVerifier))
{
state.DoS(100, error("%s(): cert proof failed to verify", __func__),
REJECT_INVALID, "bad-sc-cert-proof");
return MempoolReturnValue::INVALID;
}

// do all inputs exist?
// Note that this does not check for the presence of actual outputs (see the next check for that),
Expand Down Expand Up @@ -1149,8 +1153,7 @@ MempoolReturnValue AcceptCertificateToMemoryPool(CTxMemPool& pool, CValidationSt
double dPriority = view.GetPriority(cert, chainActive.Height());
LogPrint("mempool", "%s():%d - Computed fee=%lld, prio[%22.8f]\n", __func__, __LINE__, nFees, dPriority);

CCertificateMemPoolEntry entry(cert, nFees, GetTime(), dPriority, chainActive.Height());
unsigned int nSize = entry.GetCertificateSize();
unsigned int nSize = cert.GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION);

// Don't accept it if it can't get into a block
CAmount txMinFee = GetMinRelayFee(cert, nSize, true);
Expand Down Expand Up @@ -1231,19 +1234,36 @@ MempoolReturnValue AcceptCertificateToMemoryPool(CTxMemPool& pool, CValidationSt
return MempoolReturnValue::INVALID;
}

if (!pool.RemoveCertAndSync(conflictingCertData.first))
if (validateScProofs == ValidateSidechainProof::OFF)
return MempoolReturnValue::PARTIALLY_VALIDATED;

CScProofVerifier scVerifier{CScProofVerifier::Verification::Strict};
if (!view.CheckCertificateProof(cert, scVerifier))
{
error("%s(): cert %s depends on some conflicting quality certs", __func__, certHash.ToString());
state.DoS(100, error("%s(): cert proof failed to verify", __func__),
REJECT_INVALID, "bad-sc-cert-proof");
return MempoolReturnValue::INVALID;
}

// Store transaction in memory
pool.addUnchecked(certHash, entry, !IsInitialBlockDownload());
StoreCertToMempool(cert, pool, view);
}

return MempoolReturnValue::VALID;;
}

void StoreTxToMempool(const CTransaction &tx, CTxMemPool &pool, const CCoinsViewCache &view)
{
// Store transaction in memory
std::map<uint256, CFieldElement> scIdToCertDataHash;
for (const auto &btr : tx.GetVBwtRequestOut())
scIdToCertDataHash[btr.scId] = view.GetActiveCertDataHash(btr.scId);

CAmount nTxFees = tx.GetFeeAmount(view.GetValueIn(tx));
double dTxPriority = view.GetPriority(tx, chainActive.Height());
CTxMemPoolEntry entry(tx, nTxFees, GetTime(), dTxPriority, chainActive.Height(), mempool.HasNoInputsOf(tx));
pool.addUnchecked(tx.GetHash(), entry, !IsInitialBlockDownload(), scIdToCertDataHash);
return;
}

MempoolReturnValue AcceptTxToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, LimitFreeFlag fLimitFree,
RejectAbsurdFeeFlag fRejectAbsurdFee, ValidateSidechainProof validateScProofs)
Expand Down Expand Up @@ -1356,14 +1376,6 @@ MempoolReturnValue AcceptTxToMemoryPool(CTxMemPool& pool, CValidationState &stat
return MempoolReturnValue::INVALID;
}

CScProofVerifier scVerifier{CScProofVerifier::Verification::Strict};
if (!view.CheckScTxProof(tx, scVerifier))
{
state.Invalid(error("%s():%d - ERROR: sc-related tx [%s] proofs do not verify\n",
__func__, __LINE__, hash.ToString()), REJECT_INVALID, "bad-sc-tx-proof");
return MempoolReturnValue::INVALID;
}

// are the joinsplit's requirements met?
if (!view.HaveJoinSplitRequirements(tx))
{
Expand Down Expand Up @@ -1406,8 +1418,7 @@ MempoolReturnValue AcceptTxToMemoryPool(CTxMemPool& pool, CValidationState &stat
double dPriority = view.GetPriority(tx, chainActive.Height());
LogPrint("mempool", "%s():%d - Computed fee=%lld, prio[%22.8f]\n", __func__, __LINE__, nFees, dPriority);

CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), mempool.HasNoInputsOf(tx));
unsigned int nSize = entry.GetTxSize();
unsigned int nSize = tx.GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION);

// Accept a tx if it contains joinsplits and has at least the default fee specified by z_sendmany.
if (tx.GetVjoinsplit().size() > 0 && nFees >= ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE) {
Expand Down Expand Up @@ -1491,14 +1502,18 @@ MempoolReturnValue AcceptTxToMemoryPool(CTxMemPool& pool, CValidationState &stat
return MempoolReturnValue::INVALID;
}

// Store transaction in memory
std::map<uint256, CFieldElement> scIdToCertDataHash;
for(const auto& btr: tx.GetVBwtRequestOut())
if (validateScProofs == ValidateSidechainProof::OFF)
return MempoolReturnValue::PARTIALLY_VALIDATED;

CScProofVerifier scVerifier{CScProofVerifier::Verification::Strict};
if (!view.CheckScTxProof(tx, scVerifier))
{
scIdToCertDataHash[btr.scId] = view.GetActiveCertDataHash(btr.scId);
state.Invalid(error("%s():%d - ERROR: sc-related tx [%s] proofs do not verify\n",
__func__, __LINE__, hash.ToString()), REJECT_INVALID, "bad-sc-tx-proof");
return MempoolReturnValue::INVALID;
}

pool.addUnchecked(hash, entry, !IsInitialBlockDownload(), scIdToCertDataHash);
StoreTxToMempool(tx, pool, view);
}

return MempoolReturnValue::VALID;
Expand Down
2 changes: 2 additions & 0 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,9 +291,11 @@ void PruneAndFlush();
MempoolReturnValue AcceptTxBaseToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionBase &txBase,
LimitFreeFlag fLimitFree, RejectAbsurdFeeFlag fRejectAbsurdFee, ValidateSidechainProof validateScProofs);

inline void StoreTxToMempool(const CTransaction &tx, CTxMemPool &pool, const CCoinsViewCache &view);
MempoolReturnValue AcceptTxToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx,
LimitFreeFlag fLimitFree, RejectAbsurdFeeFlag fRejectAbsurdFee, ValidateSidechainProof validateScProofs);

inline void StoreCertToMempool(const CScCertificate &cert, CTxMemPool &pool, const CCoinsViewCache &view);
MempoolReturnValue AcceptCertificateToMemoryPool(CTxMemPool& pool, CValidationState &state, const CScCertificate &cert,
LimitFreeFlag fLimitFree, RejectAbsurdFeeFlag fRejectAbsurdFee, ValidateSidechainProof validateScProofs);

Expand Down
3 changes: 2 additions & 1 deletion src/txBaseMsgProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ void TxBaseMsgProcessor::ProcessTxBaseMsg(const processMempoolTx& mempoolProcess

{
LOCK(cs_main);
res = mempoolProcess(mempool, state, txToProcess, LimitFreeFlag::ON,RejectAbsurdFeeFlag::OFF, ValidateSidechainProof::OFF);
// TEMPORARILY ValidateSidechainProof::ON BEFORE HANDLING PARTIALLY_VALIDATED CASE
res = mempoolProcess(mempool, state, txToProcess, LimitFreeFlag::ON,RejectAbsurdFeeFlag::OFF, ValidateSidechainProof::ON);
mempool.check(pcoinsTip);
}

Expand Down
10 changes: 5 additions & 5 deletions src/txmempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
CMemPoolEntry(_nFee, _nTime, _dPriority, _nHeight),
tx(_tx), hadNoDependencies(poolHasNoInputsOf)
{
nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
nTxSize = tx.GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION);
nModSize = tx.CalculateModifiedSize(nTxSize);
nUsageSize = RecursiveDynamicUsage(tx);
}
Expand All @@ -63,7 +63,7 @@ CCertificateMemPoolEntry::CCertificateMemPoolEntry(const CScCertificate& _cert,
CMemPoolEntry(_nFee, _nTime, _dPriority, _nHeight),
cert(_cert)
{
nCertificateSize = ::GetSerializeSize(cert, SER_NETWORK, PROTOCOL_VERSION);
nCertificateSize = cert.GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION);
nModSize = cert.CalculateModifiedSize(nCertificateSize);
nUsageSize = RecursiveDynamicUsage(cert);
}
Expand Down Expand Up @@ -1606,12 +1606,12 @@ std::pair<uint256, CAmount> CTxMemPool::FindCertWithQuality(const uint256& scId,
return res;
}

bool CTxMemPool::RemoveCertAndSync(const uint256& certToRmHash)
void CTxMemPool::RemoveCertAndSync(const uint256& certToRmHash)
{
LOCK(cs);

if(mapCertificate.count(certToRmHash) == 0)
return true; //nothing to remove
return; //nothing to remove

CScCertificate certToRm = mapCertificate.at(certToRmHash).GetCertificate();
std::list<CTransaction> conflictingTxs;
Expand All @@ -1628,5 +1628,5 @@ bool CTxMemPool::RemoveCertAndSync(const uint256& certToRmHash)
SyncWithWallets(c, nullptr);
}

return true;
return;
}
2 changes: 1 addition & 1 deletion src/txmempool.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class CTxMemPool
void setSanityCheck(bool _fSanityCheck) { fSanityCheck = _fSanityCheck; }

std::pair<uint256, CAmount> FindCertWithQuality(const uint256& scId, int64_t certQuality);
bool RemoveCertAndSync(const uint256& certToRmHash);
void RemoveCertAndSync(const uint256& certToRmHash);

bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate = true,
const std::map<uint256, CFieldElement>& scIdToCertDataHash = std::map<uint256, CFieldElement>{});
Expand Down

0 comments on commit 9ed19be

Please sign in to comment.