fix(consensus): reject Sprout JoinSplits (unverified proof + vpub_new inflation vector)
Sprout JoinSplit proofs/sigs/nullifiers/anchors are never verified (the verifier arg to CheckTransaction is unused), yet vpub_new is counted as transparent value-in -- a forged all-zero JoinSplit mints arbitrary value from nothing. Reproduced on an isolated ac_private=1 chain: 500,000 minted into a z-addr, accepted + mined + verifychain=true. Reject any non-coinbase tx carrying a JoinSplit in ContextualCheckTransaction (covers both mempool acceptance and ConnectBlock). DragonX is Sapling-only from genesis with zero JoinSplits in its history (mainnet supply audit), so this is inert on all legitimate traffic and never invalidates a historical block. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
10
src/main.cpp
10
src/main.cpp
@@ -1283,6 +1283,16 @@ bool ContextualCheckTransaction(int32_t slowflag,const CBlock *block, CBlockInde
|
|||||||
const bool overwinterActive = nHeight >=1 ? true : false; //NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
|
const bool overwinterActive = nHeight >=1 ? true : false; //NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
|
||||||
const bool saplingActive = nHeight >=1 ? true : false; //NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING);
|
const bool saplingActive = nHeight >=1 ? true : false; //NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING);
|
||||||
|
|
||||||
|
// SECURITY FIX (JoinSplit inflation): reject Sprout JoinSplits at consensus. DragonX is
|
||||||
|
// Sapling-only from genesis (zero JoinSplits in its entire history, verified by the mainnet
|
||||||
|
// supply audit); a tx carrying one is illegitimate. Their zk-proof/sig/nullifier/anchor are
|
||||||
|
// never verified while vpub_new is counted as transparent value-in -> unlimited inflation.
|
||||||
|
// Coinbase/notary (IsMint) exempt. Unconditional is safe: no historical block has a JoinSplit.
|
||||||
|
if (!tx.IsMint() && !tx.vjoinsplit.empty()) {
|
||||||
|
return state.DoS(100, error("ContextualCheckTransaction(): Sprout JoinSplits are disabled (inflation vector)"),
|
||||||
|
REJECT_INVALID, "bad-txns-joinsplit-disabled");
|
||||||
|
}
|
||||||
|
|
||||||
if (saplingActive) {
|
if (saplingActive) {
|
||||||
// Reject transactions with valid version but missing overwintered flag
|
// Reject transactions with valid version but missing overwintered flag
|
||||||
if (tx.nVersion >= SAPLING_MIN_TX_VERSION && !tx.fOverwintered) {
|
if (tx.nVersion >= SAPLING_MIN_TX_VERSION && !tx.fOverwintered) {
|
||||||
|
|||||||
Reference in New Issue
Block a user