Skip to content

Commit 8b49040

Browse files
committed
BIP141: Commitment structure and deployment
Includes a fix by Suhas Daftuar and LongShao007
1 parent 449f9b8 commit 8b49040

File tree

13 files changed

+225
-13
lines changed

13 files changed

+225
-13
lines changed

src/chainparams.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ class CMainParams : public CChainParams {
9292
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1462060800; // May 1st, 2016
9393
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017
9494

95+
// Deployment of SegWit (BIP141 and BIP143)
96+
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
97+
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 0;
98+
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 0; // Never / undefined
99+
95100
/**
96101
* The message start string is designed to be unlikely to occur in normal data.
97102
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
@@ -183,6 +188,11 @@ class CTestNetParams : public CChainParams {
183188
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1456790400; // March 1st, 2016
184189
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017
185190

191+
// Deployment of SegWit (BIP141 and BIP143)
192+
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
193+
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 2000000000; // Far in the future
194+
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 2100000000;
195+
186196
pchMessageStart[0] = 0x0b;
187197
pchMessageStart[1] = 0x11;
188198
pchMessageStart[2] = 0x09;
@@ -255,6 +265,9 @@ class CRegTestParams : public CChainParams {
255265
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
256266
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 0;
257267
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 999999999999ULL;
268+
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
269+
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 0;
270+
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 999999999999ULL;
258271

259272
pchMessageStart[0] = 0xfa;
260273
pchMessageStart[1] = 0xbf;
@@ -317,3 +330,4 @@ void SelectParams(const std::string& network)
317330
SelectBaseParams(network);
318331
pCurrentParams = &Params(network);
319332
}
333+

src/consensus/merkle.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,17 @@ uint256 BlockMerkleRoot(const CBlock& block, bool* mutated)
165165
return ComputeMerkleRoot(leaves, mutated);
166166
}
167167

168+
uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated)
169+
{
170+
std::vector<uint256> leaves;
171+
leaves.resize(block.vtx.size());
172+
leaves[0].SetNull(); // The witness hash of the coinbase is 0.
173+
for (size_t s = 1; s < block.vtx.size(); s++) {
174+
leaves[s] = block.vtx[s].GetWitnessHash();
175+
}
176+
return ComputeMerkleRoot(leaves, mutated);
177+
}
178+
168179
std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position)
169180
{
170181
std::vector<uint256> leaves;

src/consensus/merkle.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint2
2222
*/
2323
uint256 BlockMerkleRoot(const CBlock& block, bool* mutated = NULL);
2424

25+
/*
26+
* Compute the Merkle root of the witness transactions in a block.
27+
* *mutated is set to true if a duplicated subtree was found.
28+
*/
29+
uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated = NULL);
30+
2531
/*
2632
* Compute the Merkle branch for the tree of transactions in a block, for a
2733
* given position.

src/consensus/params.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ enum DeploymentPos
1616
{
1717
DEPLOYMENT_TESTDUMMY,
1818
DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113.
19+
DEPLOYMENT_SEGWIT, // Deployment of BIP141 and BIP143
1920
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in versionbits.cpp
2021
MAX_VERSION_BITS_DEPLOYMENTS
2122
};

src/consensus/validation.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ class CValidationState {
7777
bool CorruptionPossible() const {
7878
return corruptionPossible;
7979
}
80+
void SetCorruptionPossible() {
81+
corruptionPossible = true;
82+
}
8083
unsigned int GetRejectCode() const { return chRejectCode; }
8184
std::string GetRejectReason() const { return strRejectReason; }
8285
std::string GetDebugMessage() const { return strDebugMessage; }

src/main.cpp

Lines changed: 138 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
34443530
bool 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
}

src/main.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,15 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
453453
/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */
454454
bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
455455

456+
/** Check whether witness commitments are required for block. */
457+
bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
458+
459+
/** Update uncommitted block structures (currently: only the witness nonce). This is safe for submitted blocks. */
460+
void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams);
461+
462+
/** Produce the necessary coinbase commitment for a block (modifies the hash, don't call for mined blocks). */
463+
std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams);
464+
456465
/** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */
457466
class CVerifyDB {
458467
public:

src/miner.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ void BlockAssembler::resetBlock()
9393
// Reserve space for coinbase tx
9494
nBlockSize = 1000;
9595
nBlockSigOps = 100;
96+
fIncludeWitness = false;
9697

9798
// These counters do not include coinbase tx
9899
nBlockTx = 0;
@@ -134,6 +135,14 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
134135
? nMedianTimePast
135136
: pblock->GetBlockTime();
136137

138+
// Decide whether to include witness transactions
139+
// This is only needed in case the witness softfork activation is reverted
140+
// (which would require a very deep reorganization) or when
141+
// -promiscuousmempoolflags is used.
142+
// TODO: replace this with a call to main to assess validity of a mempool
143+
// transaction (which in most cases can be a no-op).
144+
fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus());
145+
137146
addPriorityTxs();
138147
addPackageTxs();
139148

@@ -150,6 +159,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
150159
coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus());
151160
coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
152161
pblock->vtx[0] = coinbaseTx;
162+
pblocktemplate->vchCoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus());
153163
pblocktemplate->vTxFees[0] = -nFees;
154164

155165
// Fill in header
@@ -299,6 +309,10 @@ void BlockAssembler::addScoreTxs()
299309
continue;
300310
}
301311

312+
// cannot accept witness transactions into a non-witness block
313+
if (!fIncludeWitness && !iter->GetTx().wit.IsNull())
314+
continue;
315+
302316
// If tx is dependent on other mempool txs which haven't yet been included
303317
// then put it in the waitSet
304318
if (isStillDependent(iter)) {
@@ -543,6 +557,10 @@ void BlockAssembler::addPriorityTxs()
543557
continue;
544558
}
545559

560+
// cannot accept witness transactions into a non-witness block
561+
if (!fIncludeWitness && !iter->GetTx().wit.IsNull())
562+
continue;
563+
546564
// If tx is dependent on other mempool txs which haven't yet been included
547565
// then put it in the waitSet
548566
if (isStillDependent(iter)) {

src/miner.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct CBlockTemplate
2929
CBlock block;
3030
std::vector<CAmount> vTxFees;
3131
std::vector<int64_t> vTxSigOps;
32+
std::vector<unsigned char> vchCoinbaseCommitment;
3233
};
3334

3435
// Container for tracking updates to ancestor feerate as we include (parent)
@@ -139,6 +140,7 @@ class BlockAssembler
139140
CBlock* pblock;
140141

141142
// Configuration parameters for the block size
143+
bool fIncludeWitness;
142144
unsigned int nBlockMaxSize, nBlockMinSize;
143145

144146
// Information on the current status of the block

0 commit comments

Comments
 (0)