@@ -293,6 +293,8 @@ struct CNodeState {
293293 bool fPreferHeaderAndIDs ;
294294 // ! Whether this peer will send us cmpctblocks if we request them
295295 bool fProvidesHeaderAndIDs ;
296+ // ! Whether this peer can give us witnesses
297+ bool fHaveWitness ;
296298
297299 CNodeState () {
298300 fCurrentlyConnected = false ;
@@ -1119,6 +1121,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
11191121 return state.DoS (0 , false , REJECT_NONSTANDARD, " premature-version2-tx" );
11201122 }
11211123
1124+ // Don't accept witness transactions before the final threshold passes
1125+ if (!tx.wit .IsNull () && !IsWitnessEnabled (chainActive.Tip (), Params ().GetConsensus ())) {
1126+ return state.DoS (0 , false , REJECT_NONSTANDARD, " no-witness-yet" , true );
1127+ }
1128+
11221129 // Only accept nLockTime-using transactions that can be mined in the next
11231130 // block; we don't want our mempool filled up with transactions that can't
11241131 // be mined yet.
@@ -1459,8 +1466,17 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
14591466
14601467 // Check against previous transactions
14611468 // This is done last to help prevent CPU exhaustion denial-of-service attacks.
1462- if (!CheckInputs (tx, state, view, true , STANDARD_SCRIPT_VERIFY_FLAGS, true ))
1463- return false ; // state filled in by CheckInputs
1469+ if (!CheckInputs (tx, state, view, true , STANDARD_SCRIPT_VERIFY_FLAGS, true )) {
1470+ // SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we
1471+ // need to turn both off, and compare against just turning off CLEANSTACK
1472+ // to see if the failure is specifically due to witness validation.
1473+ if (CheckInputs (tx, state, view, true , STANDARD_SCRIPT_VERIFY_FLAGS & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true ) &&
1474+ !CheckInputs (tx, state, view, true , STANDARD_SCRIPT_VERIFY_FLAGS & ~SCRIPT_VERIFY_CLEANSTACK, true )) {
1475+ // Only the witness is wrong, so the transaction itself may be fine.
1476+ state.SetCorruptionPossible ();
1477+ }
1478+ return false ;
1479+ }
14641480
14651481 // Check again against just the consensus-critical mandatory script
14661482 // verification flags, in case of bugs in the standard flags that cause
@@ -2406,6 +2422,11 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
24062422 nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE;
24072423 }
24082424
2425+ // Start enforcing WITNESS rules using versionbits logic.
2426+ if (IsWitnessEnabled (pindex->pprev , chainparams.GetConsensus ())) {
2427+ flags |= SCRIPT_VERIFY_WITNESS;
2428+ }
2429+
24092430 int64_t nTime2 = GetTimeMicros (); nTimeForks += nTime2 - nTime1;
24102431 LogPrint (" bench" , " - Fork checks: %.2fms [%.2fs]\n " , 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001 );
24112432
@@ -3441,6 +3462,71 @@ static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidati
34413462 return true ;
34423463}
34433464
3465+ bool IsWitnessEnabled (const CBlockIndex* pindexPrev, const Consensus::Params& params)
3466+ {
3467+ LOCK (cs_main);
3468+ return (VersionBitsState (pindexPrev, params, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == THRESHOLD_ACTIVE);
3469+ }
3470+
3471+ // Compute at which vout of the block's coinbase transaction the witness
3472+ // commitment occurs, or -1 if not found.
3473+ static int GetWitnessCommitmentIndex (const CBlock& block)
3474+ {
3475+ int commitpos = -1 ;
3476+ for (size_t o = 0 ; o < block.vtx [0 ].vout .size (); o++) {
3477+ if (block.vtx [0 ].vout [o].scriptPubKey .size () >= 38 && block.vtx [0 ].vout [o].scriptPubKey [0 ] == OP_RETURN && block.vtx [0 ].vout [o].scriptPubKey [1 ] == 0x24 && block.vtx [0 ].vout [o].scriptPubKey [2 ] == 0xaa && block.vtx [0 ].vout [o].scriptPubKey [3 ] == 0x21 && block.vtx [0 ].vout [o].scriptPubKey [4 ] == 0xa9 && block.vtx [0 ].vout [o].scriptPubKey [5 ] == 0xed ) {
3478+ commitpos = o;
3479+ }
3480+ }
3481+ return commitpos;
3482+ }
3483+
3484+ void UpdateUncommittedBlockStructures (CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams)
3485+ {
3486+ int commitpos = GetWitnessCommitmentIndex (block);
3487+ static const std::vector<unsigned char > nonce (32 , 0x00 );
3488+ if (commitpos != -1 && IsWitnessEnabled (pindexPrev, consensusParams) && block.vtx [0 ].wit .IsEmpty ()) {
3489+ block.vtx [0 ].wit .vtxinwit .resize (1 );
3490+ block.vtx [0 ].wit .vtxinwit [0 ].scriptWitness .stack .resize (1 );
3491+ block.vtx [0 ].wit .vtxinwit [0 ].scriptWitness .stack [0 ] = nonce;
3492+ }
3493+ }
3494+
3495+ std::vector<unsigned char > GenerateCoinbaseCommitment (CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams)
3496+ {
3497+ std::vector<unsigned char > commitment;
3498+ int commitpos = GetWitnessCommitmentIndex (block);
3499+ bool fHaveWitness = false ;
3500+ for (size_t t = 1 ; t < block.vtx .size (); t++) {
3501+ if (!block.vtx [t].wit .IsNull ()) {
3502+ fHaveWitness = true ;
3503+ break ;
3504+ }
3505+ }
3506+ std::vector<unsigned char > ret (32 , 0x00 );
3507+ if (fHaveWitness && IsWitnessEnabled (pindexPrev, consensusParams)) {
3508+ if (commitpos == -1 ) {
3509+ uint256 witnessroot = BlockWitnessMerkleRoot (block, NULL );
3510+ CHash256 ().Write (witnessroot.begin (), 32 ).Write (&ret[0 ], 32 ).Finalize (witnessroot.begin ());
3511+ CTxOut out;
3512+ out.nValue = 0 ;
3513+ out.scriptPubKey .resize (38 );
3514+ out.scriptPubKey [0 ] = OP_RETURN;
3515+ out.scriptPubKey [1 ] = 0x24 ;
3516+ out.scriptPubKey [2 ] = 0xaa ;
3517+ out.scriptPubKey [3 ] = 0x21 ;
3518+ out.scriptPubKey [4 ] = 0xa9 ;
3519+ out.scriptPubKey [5 ] = 0xed ;
3520+ memcpy (&out.scriptPubKey [6 ], witnessroot.begin (), 32 );
3521+ commitment = std::vector<unsigned char >(out.scriptPubKey .begin (), out.scriptPubKey .end ());
3522+ const_cast <std::vector<CTxOut>*>(&block.vtx [0 ].vout )->push_back (out);
3523+ block.vtx [0 ].UpdateHash ();
3524+ }
3525+ }
3526+ UpdateUncommittedBlockStructures (block, pindexPrev, consensusParams);
3527+ return commitment;
3528+ }
3529+
34443530bool ContextualCheckBlockHeader (const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex * const pindexPrev, int64_t nAdjustedTime)
34453531{
34463532 // Check proof of work
@@ -3497,6 +3583,43 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
34973583 }
34983584 }
34993585
3586+ // Validation for witness commitments.
3587+ // * We compute the witness hash (which is the hash including witnesses) of all the block's transactions, except the
3588+ // coinbase (where 0x0000....0000 is used instead).
3589+ // * The coinbase scriptWitness is a stack of a single 32-byte vector, containing a witness nonce (unconstrained).
3590+ // * We build a merkle tree with all those witness hashes as leaves (similar to the hashMerkleRoot in the block header).
3591+ // * There must be at least one output whose scriptPubKey is a single 36-byte push, the first 4 bytes of which are
3592+ // {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness nonce). In case there are
3593+ // multiple, the last one is used.
3594+ bool fHaveWitness = false ;
3595+ if (IsWitnessEnabled (pindexPrev, consensusParams)) {
3596+ int commitpos = GetWitnessCommitmentIndex (block);
3597+ if (commitpos != -1 ) {
3598+ bool malleated = false ;
3599+ uint256 hashWitness = BlockWitnessMerkleRoot (block, &malleated);
3600+ // The malleation check is ignored; as the transaction tree itself
3601+ // already does not permit it, it is impossible to trigger in the
3602+ // witness tree.
3603+ if (block.vtx [0 ].wit .vtxinwit .size () != 1 || block.vtx [0 ].wit .vtxinwit [0 ].scriptWitness .stack .size () != 1 || block.vtx [0 ].wit .vtxinwit [0 ].scriptWitness .stack [0 ].size () != 32 ) {
3604+ return state.DoS (100 , error (" %s : invalid witness nonce size" , __func__), REJECT_INVALID, " bad-witness-nonce-size" , true );
3605+ }
3606+ CHash256 ().Write (hashWitness.begin (), 32 ).Write (&block.vtx [0 ].wit .vtxinwit [0 ].scriptWitness .stack [0 ][0 ], 32 ).Finalize (hashWitness.begin ());
3607+ if (memcmp (hashWitness.begin (), &block.vtx [0 ].vout [commitpos].scriptPubKey [6 ], 32 )) {
3608+ return state.DoS (100 , error (" %s : witness merkle commitment mismatch" , __func__), REJECT_INVALID, " bad-witness-merkle-match" , true );
3609+ }
3610+ fHaveWitness = true ;
3611+ }
3612+ }
3613+
3614+ // No witness data is allowed in blocks that don't commit to witness data, as this would otherwise leave room for spam
3615+ if (!fHaveWitness ) {
3616+ for (size_t i = 0 ; i < block.vtx .size (); i++) {
3617+ if (!block.vtx [i].wit .IsNull ()) {
3618+ return state.DoS (100 , error (" %s : unexpected witness data found" , __func__), REJECT_INVALID, " unexpected-witness" , true );
3619+ }
3620+ }
3621+ }
3622+
35003623 return true ;
35013624}
35023625
@@ -5278,7 +5401,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
52785401 else if (!fMissingInputs2 )
52795402 {
52805403 int nDos = 0 ;
5281- if (stateDummy.IsInvalid (nDos) && nDos > 0 )
5404+ if (stateDummy.IsInvalid (nDos) && nDos > 0 && (!state. CorruptionPossible () || State (fromPeer)-> fHaveWitness ) )
52825405 {
52835406 // Punish peer that gave us an invalid orphan tx
52845407 Misbehaving (fromPeer, nDos);
@@ -5289,8 +5412,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
52895412 // Probably non-standard or insufficient fee/priority
52905413 LogPrint (" mempool" , " removed orphan tx %s\n " , orphanHash.ToString ());
52915414 vEraseQueue.push_back (orphanHash);
5292- assert (recentRejects);
5293- recentRejects->insert (orphanHash);
5415+ if (!stateDummy.CorruptionPossible ()) {
5416+ assert (recentRejects);
5417+ recentRejects->insert (orphanHash);
5418+ }
52945419 }
52955420 mempool.check (pcoinsTip);
52965421 }
@@ -5325,8 +5450,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
53255450 LogPrint (" mempool" , " not keeping orphan with rejected parents %s\n " ,tx.GetHash ().ToString ());
53265451 }
53275452 } else {
5328- assert (recentRejects);
5329- recentRejects->insert (tx.GetHash ());
5453+ if (!state.CorruptionPossible ()) {
5454+ assert (recentRejects);
5455+ recentRejects->insert (tx.GetHash ());
5456+ }
53305457
53315458 if (pfrom->fWhitelisted && GetBoolArg (" -whitelistforcerelay" , DEFAULT_WHITELISTFORCERELAY)) {
53325459 // Always relay transactions received from whitelisted peers, even
@@ -5355,8 +5482,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
53555482 if (state.GetRejectCode () < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P
53565483 pfrom->PushMessage (NetMsgType::REJECT, strCommand, (unsigned char )state.GetRejectCode (),
53575484 state.GetRejectReason ().substr (0 , MAX_REJECT_MESSAGE_LENGTH), inv.hash );
5358- if (nDoS > 0 )
5485+ if (nDoS > 0 && (!state.CorruptionPossible () || State (pfrom->id )->fHaveWitness )) {
5486+ // When a non-witness-supporting peer gives us a transaction that would
5487+ // be accepted if witness validation was off, we can't blame them for it.
53595488 Misbehaving (pfrom->GetId (), nDoS);
5489+ }
53605490 }
53615491 FlushStateToDisk (state, FLUSH_STATE_PERIODIC);
53625492 }
0 commit comments