Skip to content

Commit 3ade2f6

Browse files
committed
Add standard limits for P2WSH with tests
1 parent 03dd707 commit 3ade2f6

File tree

4 files changed

+181
-2
lines changed

4 files changed

+181
-2
lines changed

qa/rpc-tests/p2p-segwit.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,6 +1706,116 @@ def test_getblocktemplate_before_lockin(self):
17061706
assert(block_version & (1 << VB_WITNESS_BIT) != 0)
17071707
self.nodes[0].setmocktime(0) # undo mocktime
17081708

1709+
def test_non_standard_witness(self):
1710+
print("\tTesting detection of non-standard P2WSH witness")
1711+
pad = chr(1).encode('latin-1')
1712+
1713+
# Create scripts for tests
1714+
scripts = []
1715+
scripts.append(CScript([OP_DROP] * 100))
1716+
scripts.append(CScript([OP_DROP] * 99))
1717+
scripts.append(CScript([pad * 59] * 59 + [OP_DROP] * 60))
1718+
scripts.append(CScript([pad * 59] * 59 + [OP_DROP] * 61))
1719+
1720+
p2wsh_scripts = []
1721+
1722+
assert(len(self.utxo))
1723+
tx = CTransaction()
1724+
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
1725+
1726+
# For each script, generate a pair of P2WSH and P2SH-P2WSH output.
1727+
outputvalue = (self.utxo[0].nValue - 1000) // (len(scripts) * 2)
1728+
for i in scripts:
1729+
p2wsh = CScript([OP_0, sha256(i)])
1730+
p2sh = hash160(p2wsh)
1731+
p2wsh_scripts.append(p2wsh)
1732+
tx.vout.append(CTxOut(outputvalue, p2wsh))
1733+
tx.vout.append(CTxOut(outputvalue, CScript([OP_HASH160, p2sh, OP_EQUAL])))
1734+
tx.rehash()
1735+
txid = tx.sha256
1736+
self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True)
1737+
1738+
self.nodes[0].generate(1)
1739+
sync_blocks(self.nodes)
1740+
1741+
# Creating transactions for tests
1742+
p2wsh_txs = []
1743+
p2sh_txs = []
1744+
for i in range(len(scripts)):
1745+
p2wsh_tx = CTransaction()
1746+
p2wsh_tx.vin.append(CTxIn(COutPoint(txid,i*2)))
1747+
p2wsh_tx.vout.append(CTxOut(outputvalue - 5000, CScript([OP_0, hash160(hex_str_to_bytes(""))])))
1748+
p2wsh_tx.wit.vtxinwit.append(CTxInWitness())
1749+
p2wsh_tx.rehash()
1750+
p2wsh_txs.append(p2wsh_tx)
1751+
p2sh_tx = CTransaction()
1752+
p2sh_tx.vin.append(CTxIn(COutPoint(txid,i*2+1), CScript([p2wsh_scripts[i]])))
1753+
p2sh_tx.vout.append(CTxOut(outputvalue - 5000, CScript([OP_0, hash160(hex_str_to_bytes(""))])))
1754+
p2sh_tx.wit.vtxinwit.append(CTxInWitness())
1755+
p2sh_tx.rehash()
1756+
p2sh_txs.append(p2sh_tx)
1757+
1758+
# Testing native P2WSH
1759+
# Witness stack size, excluding witnessScript, over 100 is non-standard
1760+
p2wsh_txs[0].wit.vtxinwit[0].scriptWitness.stack = [pad] * 101 + [scripts[0]]
1761+
self.std_node.test_transaction_acceptance(p2wsh_txs[0], True, False, b'bad-witness-nonstandard')
1762+
# Non-standard nodes should accept
1763+
self.test_node.test_transaction_acceptance(p2wsh_txs[0], True, True)
1764+
1765+
# Stack element size over 80 bytes is non-standard
1766+
p2wsh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 81] * 100 + [scripts[1]]
1767+
# It can't be used to blind a node to the transaction
1768+
self.std_node.announce_tx_and_wait_for_getdata(p2wsh_txs[1])
1769+
self.std_node.test_transaction_acceptance(p2wsh_txs[1], True, False, b'bad-witness-nonstandard')
1770+
self.std_node.announce_tx_and_wait_for_getdata(p2wsh_txs[1])
1771+
self.std_node.test_transaction_acceptance(p2wsh_txs[1], True, False, b'bad-witness-nonstandard')
1772+
# Non-standard nodes should accept
1773+
self.test_node.test_transaction_acceptance(p2wsh_txs[1], True, True)
1774+
# Standard nodes should accept if element size is not over 80 bytes
1775+
p2wsh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 80] * 100 + [scripts[1]]
1776+
self.std_node.announce_tx_and_wait_for_getdata(p2wsh_txs[1])
1777+
self.std_node.test_transaction_acceptance(p2wsh_txs[1], True, True)
1778+
1779+
# witnessScript size at 3600 bytes is standard
1780+
p2wsh_txs[2].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, scripts[2]]
1781+
self.test_node.test_transaction_acceptance(p2wsh_txs[2], True, True)
1782+
self.std_node.test_transaction_acceptance(p2wsh_txs[2], True, True)
1783+
1784+
# witnessScript size at 3601 bytes is non-standard
1785+
p2wsh_txs[3].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, pad, scripts[3]]
1786+
self.std_node.test_transaction_acceptance(p2wsh_txs[3], True, False, b'bad-witness-nonstandard')
1787+
# Non-standard nodes should accept
1788+
self.test_node.test_transaction_acceptance(p2wsh_txs[3], True, True)
1789+
1790+
# Repeating the same tests with P2SH-P2WSH
1791+
p2sh_txs[0].wit.vtxinwit[0].scriptWitness.stack = [pad] * 101 + [scripts[0]]
1792+
self.std_node.test_transaction_acceptance(p2sh_txs[0], True, False, b'bad-witness-nonstandard')
1793+
self.test_node.test_transaction_acceptance(p2sh_txs[0], True, True)
1794+
p2sh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 81] * 100 + [scripts[1]]
1795+
self.std_node.announce_tx_and_wait_for_getdata(p2sh_txs[1])
1796+
self.std_node.test_transaction_acceptance(p2sh_txs[1], True, False, b'bad-witness-nonstandard')
1797+
self.std_node.announce_tx_and_wait_for_getdata(p2sh_txs[1])
1798+
self.std_node.test_transaction_acceptance(p2sh_txs[1], True, False, b'bad-witness-nonstandard')
1799+
self.test_node.test_transaction_acceptance(p2sh_txs[1], True, True)
1800+
p2sh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 80] * 100 + [scripts[1]]
1801+
self.std_node.announce_tx_and_wait_for_getdata(p2sh_txs[1])
1802+
self.std_node.test_transaction_acceptance(p2sh_txs[1], True, True)
1803+
p2sh_txs[2].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, scripts[2]]
1804+
self.test_node.test_transaction_acceptance(p2sh_txs[2], True, True)
1805+
self.std_node.test_transaction_acceptance(p2sh_txs[2], True, True)
1806+
p2sh_txs[3].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, pad, scripts[3]]
1807+
self.std_node.test_transaction_acceptance(p2sh_txs[3], True, False, b'bad-witness-nonstandard')
1808+
self.test_node.test_transaction_acceptance(p2sh_txs[3], True, True)
1809+
1810+
self.nodes[0].generate(1) # Mine and clean up the mempool of non-standard node
1811+
# Valid but non-standard transactions in a block should be accepted by standard node
1812+
sync_blocks(self.nodes)
1813+
assert_equal(len(self.nodes[0].getrawmempool()), 0)
1814+
assert_equal(len(self.nodes[1].getrawmempool()), 0)
1815+
1816+
self.utxo.pop(0)
1817+
1818+
17091819
def run_test(self):
17101820
# Setup the p2p connections and start up the network thread.
17111821
self.test_node = TestNode() # sets NODE_WITNESS|NODE_NETWORK
@@ -1778,6 +1888,7 @@ def run_test(self):
17781888
self.test_segwit_versions()
17791889
self.test_premature_coinbase_witness_spend()
17801890
self.test_signature_version_1()
1891+
self.test_non_standard_witness()
17811892
sync_blocks(self.nodes)
17821893
if self.test_upgrade:
17831894
self.test_upgrade_after_activation(self.nodes[2], 2)

src/main.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) 2009-2010 Satoshi Nakamoto
2-
// Copyright (c) 2009-2015 The Bitcoin Core developers
2+
// Copyright (c) 2009-2016 The Bitcoin Core developers
33
// Distributed under the MIT software license, see the accompanying
44
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
55

@@ -1273,6 +1273,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
12731273
if (fRequireStandard && !AreInputsStandard(tx, view))
12741274
return state.Invalid(false, REJECT_NONSTANDARD, "bad-txns-nonstandard-inputs");
12751275

1276+
// Check for non-standard witness in P2WSH
1277+
if (!tx.wit.IsNull() && fRequireStandard && !IsWitnessStandard(tx, view))
1278+
return state.DoS(0, false, REJECT_NONSTANDARD, "bad-witness-nonstandard", true);
1279+
12761280
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, view, STANDARD_SCRIPT_VERIFY_FLAGS);
12771281

12781282
CAmount nValueOut = tx.GetValueOut();

src/policy/policy.cpp

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) 2009-2010 Satoshi Nakamoto
2-
// Copyright (c) 2009-2015 The Bitcoin developers
2+
// Copyright (c) 2009-2016 The Bitcoin developers
33
// Distributed under the MIT software license, see the accompanying
44
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
55

@@ -154,6 +154,58 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
154154
return true;
155155
}
156156

157+
bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
158+
{
159+
if (tx.IsCoinBase())
160+
return true; // Coinbases are skipped
161+
162+
for (unsigned int i = 0; i < tx.vin.size(); i++)
163+
{
164+
// We don't care if witness for this input is empty, since it must not be bloated.
165+
// If the script is invalid without witness, it would be caught sooner or later during validation.
166+
if (tx.wit.vtxinwit[i].IsNull())
167+
continue;
168+
169+
const CTxOut &prev = mapInputs.GetOutputFor(tx.vin[i]);
170+
171+
// get the scriptPubKey corresponding to this input:
172+
CScript prevScript = prev.scriptPubKey;
173+
174+
if (prevScript.IsPayToScriptHash()) {
175+
std::vector <std::vector<unsigned char> > stack;
176+
// If the scriptPubKey is P2SH, we try to extract the redeemScript casually by converting the scriptSig
177+
// into a stack. We do not check IsPushOnly nor compare the hash as these will be done later anyway.
178+
// If the check fails at this stage, we know that this txid must be a bad one.
179+
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SIGVERSION_BASE))
180+
return false;
181+
if (stack.empty())
182+
return false;
183+
prevScript = CScript(stack.back().begin(), stack.back().end());
184+
}
185+
186+
int witnessversion = 0;
187+
std::vector<unsigned char> witnessprogram;
188+
189+
// Non-witness program must not be associated with any witness
190+
if (!prevScript.IsWitnessProgram(witnessversion, witnessprogram))
191+
return false;
192+
193+
// Check P2WSH standard limits
194+
if (witnessversion == 0 && witnessprogram.size() == 32) {
195+
if (tx.wit.vtxinwit[i].scriptWitness.stack.back().size() > MAX_STANDARD_P2WSH_SCRIPT_SIZE)
196+
return false;
197+
size_t sizeWitnessStack = tx.wit.vtxinwit[i].scriptWitness.stack.size() - 1;
198+
if (sizeWitnessStack > MAX_STANDARD_P2WSH_STACK_ITEMS)
199+
return false;
200+
for (unsigned int j = 0; j < sizeWitnessStack; j++) {
201+
if (tx.wit.vtxinwit[i].scriptWitness.stack[j].size() > MAX_STANDARD_P2WSH_STACK_ITEM_SIZE)
202+
return false;
203+
}
204+
}
205+
}
206+
return true;
207+
}
208+
157209
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
158210

159211
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost)

src/policy/policy.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ static const unsigned int MAX_STANDARD_TX_SIGOPS_COST = MAX_BLOCK_SIGOPS_COST/5;
3030
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
3131
/** Default for -bytespersigop */
3232
static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
33+
/** The maximum number of witness stack items in a standard P2WSH script */
34+
static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEMS = 100;
35+
/** The maximum size of each witness stack item in a standard P2WSH script */
36+
static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEM_SIZE = 80;
37+
/** The maximum size of a standard witnessScript */
38+
static const unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE = 3600;
3339
/**
3440
* Standard script verification flags that standard transactions will comply
3541
* with. However scripts violating these flags may still be present in valid
@@ -69,6 +75,12 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnes
6975
* @return True if all inputs (scriptSigs) use only standard transaction forms
7076
*/
7177
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
78+
/**
79+
* Check if the transaction is over standard P2WSH resources limit:
80+
* 3600bytes witnessScript size, 80bytes per witness stack element, 100 witness stack elements
81+
* These limits are adequate for multi-signature up to n-of-100 using OP_CHECKSIG, OP_ADD, and OP_EQUAL,
82+
*/
83+
bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
7284

7385
extern unsigned int nBytesPerSigOp;
7486

0 commit comments

Comments
 (0)