Skip to content

Commit 46898e7

Browse files
sdaftuarlaanwj
authored andcommitted
Version 2 transactions remain non-standard until CSV activates
Before activation, such transactions might not be mined, so don't allow into the mempool. - Tests: move get_bip9_status to util.py - Test relay of version 2 transactions Github-Pull: #7835 Rebased-From: e4ba9f6 5cb1d8a da5fdbb
1 parent cada7c2 commit 46898e7

File tree

4 files changed

+63
-17
lines changed

4 files changed

+63
-17
lines changed

qa/rpc-tests/bip68-112-113-p2p.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,6 @@ def create_test_block(self, txs, version = 536870912):
149149
block.solve()
150150
return block
151151

152-
def get_bip9_status(self, key):
153-
info = self.nodes[0].getblockchaininfo()
154-
for row in info['bip9_softforks']:
155-
if row['id'] == key:
156-
return row
157-
raise IndexError ('key:"%s" not found' % key)
158-
159152
def create_bip68txs(self, bip68inputs, txversion, locktime_delta = 0):
160153
txs = []
161154
assert(len(bip68inputs) >= 16)
@@ -223,11 +216,11 @@ def get_tests(self):
223216
self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
224217
self.nodeaddress = self.nodes[0].getnewaddress()
225218

226-
assert_equal(self.get_bip9_status('csv')['status'], 'defined')
219+
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'defined')
227220
test_blocks = self.generate_blocks(61, 4)
228221
yield TestInstance(test_blocks, sync_every_block=False) # 1
229222
# Advanced from DEFINED to STARTED, height = 143
230-
assert_equal(self.get_bip9_status('csv')['status'], 'started')
223+
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
231224

232225
# Fail to achieve LOCKED_IN 100 out of 144 signal bit 0
233226
# using a variety of bits to simulate multiple parallel softforks
@@ -237,7 +230,7 @@ def get_tests(self):
237230
test_blocks = self.generate_blocks(24, 536936448, test_blocks) # 0x20010000 (signalling not)
238231
yield TestInstance(test_blocks, sync_every_block=False) # 2
239232
# Failed to advance past STARTED, height = 287
240-
assert_equal(self.get_bip9_status('csv')['status'], 'started')
233+
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
241234

242235
# 108 out of 144 signal bit 0 to achieve lock-in
243236
# using a variety of bits to simulate multiple parallel softforks
@@ -247,7 +240,7 @@ def get_tests(self):
247240
test_blocks = self.generate_blocks(10, 536936448, test_blocks) # 0x20010000 (signalling not)
248241
yield TestInstance(test_blocks, sync_every_block=False) # 3
249242
# Advanced from STARTED to LOCKED_IN, height = 431
250-
assert_equal(self.get_bip9_status('csv')['status'], 'locked_in')
243+
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
251244

252245
# 140 more version 4 blocks
253246
test_blocks = self.generate_blocks(140, 4)
@@ -291,7 +284,7 @@ def get_tests(self):
291284
test_blocks = self.generate_blocks(2, 4)
292285
yield TestInstance(test_blocks, sync_every_block=False) # 5
293286
# Not yet advanced to ACTIVE, height = 574 (will activate for block 576, not 575)
294-
assert_equal(self.get_bip9_status('csv')['status'], 'locked_in')
287+
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
295288

296289
# Test both version 1 and version 2 transactions for all tests
297290
# BIP113 test transaction will be modified before each use to put in appropriate block time
@@ -368,7 +361,7 @@ def get_tests(self):
368361
# 1 more version 4 block to get us to height 575 so the fork should now be active for the next block
369362
test_blocks = self.generate_blocks(1, 4)
370363
yield TestInstance(test_blocks, sync_every_block=False) # 8
371-
assert_equal(self.get_bip9_status('csv')['status'], 'active')
364+
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'active')
372365

373366

374367
#################################

qa/rpc-tests/bip68-sequence.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
55

66
#
7-
# Test BIP68 implementation (mempool only)
7+
# Test BIP68 implementation
88
#
99

1010
from test_framework.test_framework import BitcoinTestFramework
@@ -27,8 +27,10 @@ class BIP68Test(BitcoinTestFramework):
2727
def setup_network(self):
2828
self.nodes = []
2929
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-blockprioritysize=0"]))
30+
self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-blockprioritysize=0", "-acceptnonstdtxn=0"]))
3031
self.is_network_split = False
3132
self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
33+
connect_nodes(self.nodes[0], 1)
3234

3335
def run_test(self):
3436
# Generate some coins
@@ -43,10 +45,18 @@ def run_test(self):
4345
print "Running test sequence-lock-unconfirmed-inputs"
4446
self.test_sequence_lock_unconfirmed_inputs()
4547

46-
# This test needs to change when BIP68 becomes consensus
47-
print "Running test BIP68 not consensus"
48+
print "Running test BIP68 not consensus before versionbits activation"
4849
self.test_bip68_not_consensus()
4950

51+
print "Verifying nVersion=2 transactions aren't standard"
52+
self.test_version2_relay(before_activation=True)
53+
54+
print "Activating BIP68 (and 112/113)"
55+
self.activateCSV()
56+
57+
print "Verifying nVersion=2 transactions are now standard"
58+
self.test_version2_relay(before_activation=False)
59+
5060
print "Passed\n"
5161

5262
# Test that BIP68 is not in effect if tx version is 1, or if
@@ -334,8 +344,12 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock):
334344
self.nodes[0].invalidateblock(self.nodes[0].getblockhash(cur_height+1))
335345
self.nodes[0].generate(10)
336346

337-
# Make sure that BIP68 isn't being used to validate blocks.
347+
# Make sure that BIP68 isn't being used to validate blocks, prior to
348+
# versionbits activation. If more blocks are mined prior to this test
349+
# being run, then it's possible the test has activated the soft fork, and
350+
# this test should be moved to run earlier, or deleted.
338351
def test_bip68_not_consensus(self):
352+
assert(get_bip9_status(self.nodes[0], 'csv')['status'] != 'active')
339353
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
340354

341355
tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
@@ -382,6 +396,30 @@ def test_bip68_not_consensus(self):
382396
self.nodes[0].submitblock(ToHex(block))
383397
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
384398

399+
def activateCSV(self):
400+
# activation should happen at block height 432 (3 periods)
401+
min_activation_height = 432
402+
height = self.nodes[0].getblockcount()
403+
assert(height < 432)
404+
self.nodes[0].generate(432-height)
405+
assert(get_bip9_status(self.nodes[0], 'csv')['status'] == 'active')
406+
sync_blocks(self.nodes)
407+
408+
# Use self.nodes[1] to test standardness relay policy
409+
def test_version2_relay(self, before_activation):
410+
inputs = [ ]
411+
outputs = { self.nodes[1].getnewaddress() : 1.0 }
412+
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
413+
rawtxfund = self.nodes[1].fundrawtransaction(rawtx)['hex']
414+
tx = FromHex(CTransaction(), rawtxfund)
415+
tx.nVersion = 2
416+
tx_signed = self.nodes[1].signrawtransaction(ToHex(tx))["hex"]
417+
try:
418+
tx_id = self.nodes[1].sendrawtransaction(tx_signed)
419+
assert(before_activation == False)
420+
except:
421+
assert(before_activation)
422+
385423

386424
if __name__ == '__main__':
387425
BIP68Test().main()

qa/rpc-tests/test_framework/util.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,3 +490,10 @@ def create_lots_of_big_transactions(node, txouts, utxos, fee):
490490
txid = node.sendrawtransaction(signresult["hex"], True)
491491
txids.append(txid)
492492
return txids
493+
494+
def get_bip9_status(node, key):
495+
info = node.getblockchaininfo()
496+
for row in info['bip9_softforks']:
497+
if row['id'] == key:
498+
return row
499+
raise IndexError ('key:"%s" not found' % key)

src/main.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,14 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
10221022
if (fRequireStandard && !IsStandardTx(tx, reason))
10231023
return state.DoS(0, false, REJECT_NONSTANDARD, reason);
10241024

1025+
// Don't relay version 2 transactions until CSV is active, and we can be
1026+
// sure that such transactions will be mined (unless we're on
1027+
// -testnet/-regtest).
1028+
const CChainParams& chainparams = Params();
1029+
if (fRequireStandard && tx.nVersion >= 2 && VersionBitsTipState(chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV) != THRESHOLD_ACTIVE) {
1030+
return state.DoS(0, false, REJECT_NONSTANDARD, "premature-version2-tx");
1031+
}
1032+
10251033
// Only accept nLockTime-using transactions that can be mined in the next
10261034
// block; we don't want our mempool filled up with transactions that can't
10271035
// be mined yet.

0 commit comments

Comments
 (0)