2016-03-19 16:58:06 -03:00
#!/usr/bin/env python3
2018-07-26 18:36:45 -04:00
# Copyright (c) 2015-2018 The Bitcoin Core developers
2016-03-19 16:58:06 -03:00
# Distributed under the MIT software license, see the accompanying
2015-06-28 15:42:17 -03:00
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-01-17 20:34:40 -03:00
""" Test BIP65 (CHECKLOCKTIMEVERIFY).
2017-06-28 14:52:24 -04:00
Test that the CHECKLOCKTIMEVERIFY soft - fork activates at ( regtest ) block height
1351.
2017-01-17 20:34:40 -03:00
"""
2015-06-28 15:42:17 -03:00
2018-07-30 04:16:40 -04:00
from test_framework . blocktools import create_coinbase , create_block , create_transaction
2018-07-06 18:10:35 -04:00
from test_framework . messages import CTransaction , msg_block , ToHex
2018-08-24 16:26:42 -03:00
from test_framework . mininode import P2PInterface
2017-06-28 14:52:24 -04:00
from test_framework . script import CScript , OP_1NEGATE , OP_CHECKLOCKTIMEVERIFY , OP_DROP , CScriptNum
2018-07-06 18:10:35 -04:00
from test_framework . test_framework import BitcoinTestFramework
2018-08-24 16:26:42 -03:00
from test_framework . util import (
assert_equal ,
bytes_to_hex_str ,
hex_str_to_bytes ,
)
2018-07-06 18:10:35 -04:00
2016-03-19 17:36:32 -03:00
from io import BytesIO
2017-06-28 14:52:24 -04:00
CLTV_HEIGHT = 1351
# Reject codes that we might receive in this test
REJECT_INVALID = 16
REJECT_NONSTANDARD = 64
2015-06-28 15:42:17 -03:00
def cltv_invalidate ( tx ) :
''' Modify the signature in vin 0 of the tx to fail CLTV
Prepends - 1 CLTV DROP in the scriptSig itself .
2017-06-28 14:52:24 -04:00
TODO : test more ways that transactions using CLTV could be invalid ( eg
locktime requirements fail , sequence time requirements fail , etc ) .
2015-06-28 15:42:17 -03:00
'''
2015-12-14 16:21:34 -03:00
tx . vin [ 0 ] . scriptSig = CScript ( [ OP_1NEGATE , OP_CHECKLOCKTIMEVERIFY , OP_DROP ] +
2015-06-28 15:42:17 -03:00
list ( CScript ( tx . vin [ 0 ] . scriptSig ) ) )
2017-06-28 14:52:24 -04:00
def cltv_validate ( node , tx , height ) :
''' Modify the signature in vin 0 of the tx to pass CLTV
Prepends < height > CLTV DROP in the scriptSig , and sets
the locktime to height '''
tx . vin [ 0 ] . nSequence = 0
tx . nLockTime = height
# Need to re-sign, since nSequence and nLockTime changed
2017-09-05 20:49:18 -03:00
signed_result = node . signrawtransactionwithwallet ( ToHex ( tx ) )
2017-06-28 14:52:24 -04:00
new_tx = CTransaction ( )
new_tx . deserialize ( BytesIO ( hex_str_to_bytes ( signed_result [ ' hex ' ] ) ) )
new_tx . vin [ 0 ] . scriptSig = CScript ( [ CScriptNum ( height ) , OP_CHECKLOCKTIMEVERIFY , OP_DROP ] +
list ( CScript ( new_tx . vin [ 0 ] . scriptSig ) ) )
return new_tx
2018-08-24 16:26:42 -03:00
2017-06-28 14:52:24 -04:00
class BIP65Test ( BitcoinTestFramework ) :
2017-06-09 18:21:21 -04:00
def set_test_params ( self ) :
2015-06-28 15:42:17 -03:00
self . num_nodes = 1
2018-08-24 16:26:42 -03:00
self . extra_args = [ [ ' -whitelist=127.0.0.1 ' , ' -par=1 ' ] ] # Use only one script thread to get the exact reject reason for testing
2017-06-28 14:52:24 -04:00
self . setup_clean_chain = True
2015-06-28 15:42:17 -03:00
2018-09-09 14:32:37 -03:00
def skip_test_if_missing_module ( self ) :
self . skip_if_no_wallet ( )
2015-06-28 15:42:17 -03:00
def run_test ( self ) :
2017-10-17 17:16:39 -03:00
self . nodes [ 0 ] . add_p2p_connection ( P2PInterface ( ) )
2017-06-28 14:52:24 -04:00
self . log . info ( " Mining %d blocks " , CLTV_HEIGHT - 2 )
2018-07-30 04:16:40 -04:00
self . coinbase_txids = [ self . nodes [ 0 ] . getblock ( b ) [ ' tx ' ] [ 0 ] for b in self . nodes [ 0 ] . generate ( CLTV_HEIGHT - 2 ) ]
2015-06-28 15:42:17 -03:00
self . nodeaddress = self . nodes [ 0 ] . getnewaddress ( )
2017-06-28 14:52:24 -04:00
self . log . info ( " Test that an invalid-according-to-CLTV transaction can still appear in a block " )
2018-07-30 04:16:40 -04:00
spendtx = create_transaction ( self . nodes [ 0 ] , self . coinbase_txids [ 0 ] ,
2018-08-09 13:27:45 -04:00
self . nodeaddress , amount = 1.0 )
2015-06-28 15:42:17 -03:00
cltv_invalidate ( spendtx )
spendtx . rehash ( )
2017-06-28 14:52:24 -04:00
tip = self . nodes [ 0 ] . getbestblockhash ( )
block_time = self . nodes [ 0 ] . getblockheader ( tip ) [ ' mediantime ' ] + 1
block = create_block ( int ( tip , 16 ) , create_coinbase ( CLTV_HEIGHT - 1 ) , block_time )
block . nVersion = 3
2015-06-28 15:42:17 -03:00
block . vtx . append ( spendtx )
block . hashMerkleRoot = block . calc_merkle_root ( )
block . solve ( )
2017-08-24 16:36:02 -03:00
self . nodes [ 0 ] . p2p . send_and_ping ( msg_block ( block ) )
2017-06-28 14:52:24 -04:00
assert_equal ( self . nodes [ 0 ] . getbestblockhash ( ) , block . hash )
self . log . info ( " Test that blocks must now be at least version 4 " )
tip = block . sha256
block_time + = 1
block = create_block ( tip , create_coinbase ( CLTV_HEIGHT ) , block_time )
2015-06-28 15:42:17 -03:00
block . nVersion = 3
block . solve ( )
2018-08-24 16:26:42 -03:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' {} , bad-version(0x00000003) ' . format ( block . hash ) ] ) :
self . nodes [ 0 ] . p2p . send_and_ping ( msg_block ( block ) )
assert_equal ( int ( self . nodes [ 0 ] . getbestblockhash ( ) , 16 ) , tip )
self . nodes [ 0 ] . p2p . sync_with_ping ( )
2017-06-28 14:52:24 -04:00
self . log . info ( " Test that invalid-according-to-cltv transactions cannot appear in a block " )
2015-06-28 15:42:17 -03:00
block . nVersion = 4
2017-06-28 14:52:24 -04:00
2018-07-30 04:16:40 -04:00
spendtx = create_transaction ( self . nodes [ 0 ] , self . coinbase_txids [ 1 ] ,
2018-08-09 13:27:45 -04:00
self . nodeaddress , amount = 1.0 )
2016-07-21 19:27:55 -04:00
cltv_invalidate ( spendtx )
spendtx . rehash ( )
2017-06-28 14:52:24 -04:00
# First we show that this tx is valid except for CLTV by getting it
2018-06-23 16:16:54 -04:00
# rejected from the mempool for exactly that reason.
assert_equal (
[ { ' txid ' : spendtx . hash , ' allowed ' : False , ' reject-reason ' : ' 64: non-mandatory-script-verify-flag (Negative locktime) ' } ] ,
self . nodes [ 0 ] . testmempoolaccept ( rawtxs = [ bytes_to_hex_str ( spendtx . serialize ( ) ) ] , allowhighfees = True )
)
2017-06-28 14:52:24 -04:00
2018-06-23 16:16:54 -04:00
# Now we verify that a block with this transaction is also invalid.
2016-07-21 19:27:55 -04:00
block . vtx . append ( spendtx )
block . hashMerkleRoot = block . calc_merkle_root ( )
block . solve ( )
2018-08-24 16:26:42 -03:00
with self . nodes [ 0 ] . assert_debug_log ( expected_msgs = [ ' CheckInputs on {} failed with non-mandatory-script-verify-flag (Negative locktime) ' . format ( block . vtx [ - 1 ] . hash ) ] ) :
self . nodes [ 0 ] . p2p . send_and_ping ( msg_block ( block ) )
assert_equal ( int ( self . nodes [ 0 ] . getbestblockhash ( ) , 16 ) , tip )
self . nodes [ 0 ] . p2p . sync_with_ping ( )
2017-06-28 14:52:24 -04:00
self . log . info ( " Test that a version 4 block with a valid-according-to-CLTV transaction is accepted " )
spendtx = cltv_validate ( self . nodes [ 0 ] , spendtx , CLTV_HEIGHT - 1 )
spendtx . rehash ( )
block . vtx . pop ( 1 )
block . vtx . append ( spendtx )
block . hashMerkleRoot = block . calc_merkle_root ( )
2015-06-28 15:42:17 -03:00
block . solve ( )
2017-06-28 14:52:24 -04:00
2017-08-24 16:36:02 -03:00
self . nodes [ 0 ] . p2p . send_and_ping ( msg_block ( block ) )
2017-06-28 14:52:24 -04:00
assert_equal ( int ( self . nodes [ 0 ] . getbestblockhash ( ) , 16 ) , block . sha256 )
2015-06-28 15:42:17 -03:00
if __name__ == ' __main__ ' :
BIP65Test ( ) . main ( )