Reject ztxs with duplicate zkproofs
This is a greatly simplified and slightly tweaked version of https://github.com/PirateNetwork/pirate/commit/af2e3713e286d61353edffd0b4c89c931b455cb4 Their version will detect duplicate zkproofs across transactions while this code will only detect duplicate zkproofs in a single ztx. If dupes are found, the tx will be denied entry into the mempool. This provides most of the benefit (increased CPU cost to attackers) with the least code change and no annoyance to full node operators. Detecting duplicate zkproofs across transactions requires a one-time reindex of all of history, which means significant downtime for nodes. Since Hush + HSCs have a much more strict policy on number of shielded outputs and shielded inputs, only detecting duplicate zkproofs in individual ztxs seems sufficient for now. No correctly functioning node or wallet will ever create duplicate zkproofs, so there is no worry of this accidentally affecting normal users. Currently this is not a consensus rule but it could become one in the future.
This commit is contained in:
@@ -29,6 +29,8 @@ static const unsigned char REJECT_MALFORMED = 0x01;
|
||||
static const unsigned char REJECT_INVALID = 0x10;
|
||||
static const unsigned char REJECT_OBSOLETE = 0x11;
|
||||
static const unsigned char REJECT_DUPLICATE = 0x12;
|
||||
static const unsigned char REJECT_DUPLICATE_OUTPUT_PROOF = 0x13;
|
||||
static const unsigned char REJECT_DUPLICATE_SPEND_PROOF = 0x14;
|
||||
static const unsigned char REJECT_NONSTANDARD = 0x40;
|
||||
static const unsigned char REJECT_DUST = 0x41;
|
||||
static const unsigned char REJECT_INSUFFICIENTFEE = 0x42;
|
||||
|
||||
+25
-1
@@ -1751,7 +1751,31 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
||||
{
|
||||
return error("AcceptToMemoryPool: CheckTransaction failed");
|
||||
}
|
||||
|
||||
|
||||
// Reject duplicate output proofs in a single ztx in mempool
|
||||
// Migrate this to CheckTransaction() to make it a consensus requirement
|
||||
{
|
||||
set<libzcash::GrothProof> vSaplingOutputProof;
|
||||
BOOST_FOREACH(const OutputDescription& output, tx.vShieldedOutput)
|
||||
{
|
||||
if (vSaplingOutputProof.count(output.zkproof))
|
||||
return state.Invalid(error("AcceptToMemoryPool: duplicate output proof"),REJECT_DUPLICATE_OUTPUT_PROOF, "bad-txns-duplicate-output-proof");
|
||||
vSaplingOutputProof.insert(output.zkproof);
|
||||
}
|
||||
}
|
||||
|
||||
// Reject duplicate spend proofs in a single ztx in mempool
|
||||
// Migrate this to CheckTransaction() to make it a consensus requirement
|
||||
{
|
||||
set<libzcash::GrothProof> vSaplingSpendProof;
|
||||
BOOST_FOREACH(const SpendDescription& spend, tx.vShieldedSpend)
|
||||
{
|
||||
if (vSaplingSpendProof.count(spend.zkproof))
|
||||
return state.Invalid(error("AcceptToMemoryPool: duplicate spend proof"),REJECT_DUPLICATE_SPEND_PROOF, "bad-txns-duplicate-spend-proof");
|
||||
vSaplingSpendProof.insert(spend.zkproof);
|
||||
}
|
||||
}
|
||||
|
||||
// DoS level set to 10 to be more forgiving.
|
||||
// Check transaction contextually against the set of consensus rules which apply in the next block to be mined.
|
||||
if (!ContextualCheckTransaction(0,0,0,tx, state, nextBlockHeight, (dosLevel == -1) ? 10 : dosLevel))
|
||||
|
||||
Reference in New Issue
Block a user