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: e4ba9f6b0402cf7a2ad0d74f617c434a26c6e124 5cb1d8a2071d05beb9907a423178895fd8a5c359 da5fdbb3a2778523cce70d635c1aa2b31a693bc6
This commit is contained in:
parent
cada7c2418
commit
46898e7e94
@ -149,13 +149,6 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|||||||
block.solve()
|
block.solve()
|
||||||
return block
|
return block
|
||||||
|
|
||||||
def get_bip9_status(self, key):
|
|
||||||
info = self.nodes[0].getblockchaininfo()
|
|
||||||
for row in info['bip9_softforks']:
|
|
||||||
if row['id'] == key:
|
|
||||||
return row
|
|
||||||
raise IndexError ('key:"%s" not found' % key)
|
|
||||||
|
|
||||||
def create_bip68txs(self, bip68inputs, txversion, locktime_delta = 0):
|
def create_bip68txs(self, bip68inputs, txversion, locktime_delta = 0):
|
||||||
txs = []
|
txs = []
|
||||||
assert(len(bip68inputs) >= 16)
|
assert(len(bip68inputs) >= 16)
|
||||||
@ -223,11 +216,11 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|||||||
self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
|
self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
|
||||||
self.nodeaddress = self.nodes[0].getnewaddress()
|
self.nodeaddress = self.nodes[0].getnewaddress()
|
||||||
|
|
||||||
assert_equal(self.get_bip9_status('csv')['status'], 'defined')
|
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'defined')
|
||||||
test_blocks = self.generate_blocks(61, 4)
|
test_blocks = self.generate_blocks(61, 4)
|
||||||
yield TestInstance(test_blocks, sync_every_block=False) # 1
|
yield TestInstance(test_blocks, sync_every_block=False) # 1
|
||||||
# Advanced from DEFINED to STARTED, height = 143
|
# Advanced from DEFINED to STARTED, height = 143
|
||||||
assert_equal(self.get_bip9_status('csv')['status'], 'started')
|
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
|
||||||
|
|
||||||
# Fail to achieve LOCKED_IN 100 out of 144 signal bit 0
|
# Fail to achieve LOCKED_IN 100 out of 144 signal bit 0
|
||||||
# using a variety of bits to simulate multiple parallel softforks
|
# using a variety of bits to simulate multiple parallel softforks
|
||||||
@ -237,7 +230,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|||||||
test_blocks = self.generate_blocks(24, 536936448, test_blocks) # 0x20010000 (signalling not)
|
test_blocks = self.generate_blocks(24, 536936448, test_blocks) # 0x20010000 (signalling not)
|
||||||
yield TestInstance(test_blocks, sync_every_block=False) # 2
|
yield TestInstance(test_blocks, sync_every_block=False) # 2
|
||||||
# Failed to advance past STARTED, height = 287
|
# Failed to advance past STARTED, height = 287
|
||||||
assert_equal(self.get_bip9_status('csv')['status'], 'started')
|
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
|
||||||
|
|
||||||
# 108 out of 144 signal bit 0 to achieve lock-in
|
# 108 out of 144 signal bit 0 to achieve lock-in
|
||||||
# using a variety of bits to simulate multiple parallel softforks
|
# using a variety of bits to simulate multiple parallel softforks
|
||||||
@ -247,7 +240,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|||||||
test_blocks = self.generate_blocks(10, 536936448, test_blocks) # 0x20010000 (signalling not)
|
test_blocks = self.generate_blocks(10, 536936448, test_blocks) # 0x20010000 (signalling not)
|
||||||
yield TestInstance(test_blocks, sync_every_block=False) # 3
|
yield TestInstance(test_blocks, sync_every_block=False) # 3
|
||||||
# Advanced from STARTED to LOCKED_IN, height = 431
|
# Advanced from STARTED to LOCKED_IN, height = 431
|
||||||
assert_equal(self.get_bip9_status('csv')['status'], 'locked_in')
|
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
|
||||||
|
|
||||||
# 140 more version 4 blocks
|
# 140 more version 4 blocks
|
||||||
test_blocks = self.generate_blocks(140, 4)
|
test_blocks = self.generate_blocks(140, 4)
|
||||||
@ -291,7 +284,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|||||||
test_blocks = self.generate_blocks(2, 4)
|
test_blocks = self.generate_blocks(2, 4)
|
||||||
yield TestInstance(test_blocks, sync_every_block=False) # 5
|
yield TestInstance(test_blocks, sync_every_block=False) # 5
|
||||||
# Not yet advanced to ACTIVE, height = 574 (will activate for block 576, not 575)
|
# Not yet advanced to ACTIVE, height = 574 (will activate for block 576, not 575)
|
||||||
assert_equal(self.get_bip9_status('csv')['status'], 'locked_in')
|
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
|
||||||
|
|
||||||
# Test both version 1 and version 2 transactions for all tests
|
# Test both version 1 and version 2 transactions for all tests
|
||||||
# BIP113 test transaction will be modified before each use to put in appropriate block time
|
# BIP113 test transaction will be modified before each use to put in appropriate block time
|
||||||
@ -368,7 +361,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|||||||
# 1 more version 4 block to get us to height 575 so the fork should now be active for the next block
|
# 1 more version 4 block to get us to height 575 so the fork should now be active for the next block
|
||||||
test_blocks = self.generate_blocks(1, 4)
|
test_blocks = self.generate_blocks(1, 4)
|
||||||
yield TestInstance(test_blocks, sync_every_block=False) # 8
|
yield TestInstance(test_blocks, sync_every_block=False) # 8
|
||||||
assert_equal(self.get_bip9_status('csv')['status'], 'active')
|
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'active')
|
||||||
|
|
||||||
|
|
||||||
#################################
|
#################################
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test BIP68 implementation (mempool only)
|
# Test BIP68 implementation
|
||||||
#
|
#
|
||||||
|
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
@ -27,8 +27,10 @@ class BIP68Test(BitcoinTestFramework):
|
|||||||
def setup_network(self):
|
def setup_network(self):
|
||||||
self.nodes = []
|
self.nodes = []
|
||||||
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-blockprioritysize=0"]))
|
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-blockprioritysize=0"]))
|
||||||
|
self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-blockprioritysize=0", "-acceptnonstdtxn=0"]))
|
||||||
self.is_network_split = False
|
self.is_network_split = False
|
||||||
self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
|
self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
|
||||||
|
connect_nodes(self.nodes[0], 1)
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
# Generate some coins
|
# Generate some coins
|
||||||
@ -43,10 +45,18 @@ class BIP68Test(BitcoinTestFramework):
|
|||||||
print "Running test sequence-lock-unconfirmed-inputs"
|
print "Running test sequence-lock-unconfirmed-inputs"
|
||||||
self.test_sequence_lock_unconfirmed_inputs()
|
self.test_sequence_lock_unconfirmed_inputs()
|
||||||
|
|
||||||
# This test needs to change when BIP68 becomes consensus
|
print "Running test BIP68 not consensus before versionbits activation"
|
||||||
print "Running test BIP68 not consensus"
|
|
||||||
self.test_bip68_not_consensus()
|
self.test_bip68_not_consensus()
|
||||||
|
|
||||||
|
print "Verifying nVersion=2 transactions aren't standard"
|
||||||
|
self.test_version2_relay(before_activation=True)
|
||||||
|
|
||||||
|
print "Activating BIP68 (and 112/113)"
|
||||||
|
self.activateCSV()
|
||||||
|
|
||||||
|
print "Verifying nVersion=2 transactions are now standard"
|
||||||
|
self.test_version2_relay(before_activation=False)
|
||||||
|
|
||||||
print "Passed\n"
|
print "Passed\n"
|
||||||
|
|
||||||
# Test that BIP68 is not in effect if tx version is 1, or if
|
# Test that BIP68 is not in effect if tx version is 1, or if
|
||||||
@ -334,8 +344,12 @@ class BIP68Test(BitcoinTestFramework):
|
|||||||
self.nodes[0].invalidateblock(self.nodes[0].getblockhash(cur_height+1))
|
self.nodes[0].invalidateblock(self.nodes[0].getblockhash(cur_height+1))
|
||||||
self.nodes[0].generate(10)
|
self.nodes[0].generate(10)
|
||||||
|
|
||||||
# Make sure that BIP68 isn't being used to validate blocks.
|
# Make sure that BIP68 isn't being used to validate blocks, prior to
|
||||||
|
# versionbits activation. If more blocks are mined prior to this test
|
||||||
|
# being run, then it's possible the test has activated the soft fork, and
|
||||||
|
# this test should be moved to run earlier, or deleted.
|
||||||
def test_bip68_not_consensus(self):
|
def test_bip68_not_consensus(self):
|
||||||
|
assert(get_bip9_status(self.nodes[0], 'csv')['status'] != 'active')
|
||||||
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
|
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
|
||||||
|
|
||||||
tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
|
tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
|
||||||
@ -382,6 +396,30 @@ class BIP68Test(BitcoinTestFramework):
|
|||||||
self.nodes[0].submitblock(ToHex(block))
|
self.nodes[0].submitblock(ToHex(block))
|
||||||
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
|
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
|
||||||
|
|
||||||
|
def activateCSV(self):
|
||||||
|
# activation should happen at block height 432 (3 periods)
|
||||||
|
min_activation_height = 432
|
||||||
|
height = self.nodes[0].getblockcount()
|
||||||
|
assert(height < 432)
|
||||||
|
self.nodes[0].generate(432-height)
|
||||||
|
assert(get_bip9_status(self.nodes[0], 'csv')['status'] == 'active')
|
||||||
|
sync_blocks(self.nodes)
|
||||||
|
|
||||||
|
# Use self.nodes[1] to test standardness relay policy
|
||||||
|
def test_version2_relay(self, before_activation):
|
||||||
|
inputs = [ ]
|
||||||
|
outputs = { self.nodes[1].getnewaddress() : 1.0 }
|
||||||
|
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||||
|
rawtxfund = self.nodes[1].fundrawtransaction(rawtx)['hex']
|
||||||
|
tx = FromHex(CTransaction(), rawtxfund)
|
||||||
|
tx.nVersion = 2
|
||||||
|
tx_signed = self.nodes[1].signrawtransaction(ToHex(tx))["hex"]
|
||||||
|
try:
|
||||||
|
tx_id = self.nodes[1].sendrawtransaction(tx_signed)
|
||||||
|
assert(before_activation == False)
|
||||||
|
except:
|
||||||
|
assert(before_activation)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
BIP68Test().main()
|
BIP68Test().main()
|
||||||
|
@ -490,3 +490,10 @@ def create_lots_of_big_transactions(node, txouts, utxos, fee):
|
|||||||
txid = node.sendrawtransaction(signresult["hex"], True)
|
txid = node.sendrawtransaction(signresult["hex"], True)
|
||||||
txids.append(txid)
|
txids.append(txid)
|
||||||
return txids
|
return txids
|
||||||
|
|
||||||
|
def get_bip9_status(node, key):
|
||||||
|
info = node.getblockchaininfo()
|
||||||
|
for row in info['bip9_softforks']:
|
||||||
|
if row['id'] == key:
|
||||||
|
return row
|
||||||
|
raise IndexError ('key:"%s" not found' % key)
|
||||||
|
@ -1022,6 +1022,14 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
|
|||||||
if (fRequireStandard && !IsStandardTx(tx, reason))
|
if (fRequireStandard && !IsStandardTx(tx, reason))
|
||||||
return state.DoS(0, false, REJECT_NONSTANDARD, reason);
|
return state.DoS(0, false, REJECT_NONSTANDARD, reason);
|
||||||
|
|
||||||
|
// Don't relay version 2 transactions until CSV is active, and we can be
|
||||||
|
// sure that such transactions will be mined (unless we're on
|
||||||
|
// -testnet/-regtest).
|
||||||
|
const CChainParams& chainparams = Params();
|
||||||
|
if (fRequireStandard && tx.nVersion >= 2 && VersionBitsTipState(chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV) != THRESHOLD_ACTIVE) {
|
||||||
|
return state.DoS(0, false, REJECT_NONSTANDARD, "premature-version2-tx");
|
||||||
|
}
|
||||||
|
|
||||||
// Only accept nLockTime-using transactions that can be mined in the next
|
// Only accept nLockTime-using transactions that can be mined in the next
|
||||||
// block; we don't want our mempool filled up with transactions that can't
|
// block; we don't want our mempool filled up with transactions that can't
|
||||||
// be mined yet.
|
// be mined yet.
|
||||||
|
Loading…
Reference in New Issue
Block a user