@ -24,7 +24,7 @@ from test_framework.util import (
assert_equal ,
)
class C FiltersClient( P2PInterface ) :
class FiltersClient( P2PInterface ) :
def __init__ ( self ) :
super ( ) . __init__ ( )
# Store the cfilters received.
@ -39,6 +39,7 @@ class CFiltersClient(P2PInterface):
""" Store cfilters received in a list. """
self . cfilters . append ( message )
class CompactFiltersTest ( BitcoinTestFramework ) :
def set_test_params ( self ) :
self . setup_clean_chain = True
@ -51,8 +52,8 @@ class CompactFiltersTest(BitcoinTestFramework):
def run_test ( self ) :
# Node 0 supports COMPACT_FILTERS, node 1 does not.
node 0 = self . nodes [ 0 ] . add_p2p_connection ( C FiltersClient( ) )
node 1 = self . nodes [ 1 ] . add_p2p_connection ( C FiltersClient( ) )
peer_ 0 = self . nodes [ 0 ] . add_p2p_connection ( FiltersClient( ) )
peer_ 1 = self . nodes [ 1 ] . add_p2p_connection ( FiltersClient( ) )
# Nodes 0 & 1 share the same first 999 blocks in the chain.
self . nodes [ 0 ] . generate ( 999 )
@ -61,16 +62,16 @@ class CompactFiltersTest(BitcoinTestFramework):
# Stale blocks by disconnecting nodes 0 & 1, mining, then reconnecting
self . disconnect_nodes ( 0 , 1 )
self . nodes [ 0 ] . generate ( 1 )
self . wait_until( lambda : self . nodes [ 0 ] . getblockcount ( ) == 1000 )
stale_block_hash = self . nodes [ 0 ] . getblockhash ( 1000 )
stale_block_hash = self . nodes [ 0 ] . generate ( 1 ) [ 0 ]
self . nodes[ 0 ] . syncwithvalidationinterfacequeue ( )
assert_equal( self . nodes [ 0 ] . getblockcount ( ) , 1000 )
self . nodes [ 1 ] . generate ( 1001 )
self . wait_until ( lambda : self . nodes [ 1 ] . getblockcount ( ) == 2000 )
assert_equal ( self . nodes [ 1 ] . getblockcount ( ) , 2000 )
# Check that nodes have signalled NODE_COMPACT_FILTERS correctly.
assert node 0. nServices & NODE_COMPACT_FILTERS != 0
assert node 1. nServices & NODE_COMPACT_FILTERS == 0
assert peer_ 0. nServices & NODE_COMPACT_FILTERS != 0
assert peer_ 1. nServices & NODE_COMPACT_FILTERS == 0
# Check that the localservices is as expected.
assert int ( self . nodes [ 0 ] . getnetworkinfo ( ) [ ' localservices ' ] , 16 ) & NODE_COMPACT_FILTERS != 0
@ -79,10 +80,10 @@ class CompactFiltersTest(BitcoinTestFramework):
self . log . info ( " get cfcheckpt on chain to be re-orged out. " )
request = msg_getcfcheckpt (
filter_type = FILTER_TYPE_BASIC ,
stop_hash = int ( stale_block_hash , 16 )
stop_hash = int ( stale_block_hash , 16 ) ,
)
node 0. send_and_ping ( message = request )
response = node 0. last_message [ ' cfcheckpt ' ]
peer_ 0. send_and_ping ( message = request )
response = peer_ 0. last_message [ ' cfcheckpt ' ]
assert_equal ( response . filter_type , request . filter_type )
assert_equal ( response . stop_hash , request . stop_hash )
assert_equal ( len ( response . headers ) , 1 )
@ -90,6 +91,7 @@ class CompactFiltersTest(BitcoinTestFramework):
self . log . info ( " Reorg node 0 to a new chain. " )
self . connect_nodes ( 0 , 1 )
self . sync_blocks ( timeout = 600 )
self . nodes [ 0 ] . syncwithvalidationinterfacequeue ( )
main_block_hash = self . nodes [ 0 ] . getblockhash ( 1000 )
assert main_block_hash != stale_block_hash , " node 0 chain did not reorganize "
@ -98,10 +100,10 @@ class CompactFiltersTest(BitcoinTestFramework):
tip_hash = self . nodes [ 0 ] . getbestblockhash ( )
request = msg_getcfcheckpt (
filter_type = FILTER_TYPE_BASIC ,
stop_hash = int ( tip_hash , 16 )
stop_hash = int ( tip_hash , 16 ) ,
)
node 0. send_and_ping ( request )
response = node 0. last_message [ ' cfcheckpt ' ]
peer_ 0. send_and_ping ( request )
response = peer_ 0. last_message [ ' cfcheckpt ' ]
assert_equal ( response . filter_type , request . filter_type )
assert_equal ( response . stop_hash , request . stop_hash )
@ -109,51 +111,51 @@ class CompactFiltersTest(BitcoinTestFramework):
tip_cfcheckpt = self . nodes [ 0 ] . getblockfilter ( tip_hash , ' basic ' ) [ ' header ' ]
assert_equal (
response . headers ,
[ int ( header , 16 ) for header in ( main_cfcheckpt , tip_cfcheckpt ) ]
[ int ( header , 16 ) for header in ( main_cfcheckpt , tip_cfcheckpt ) ] ,
)
self . log . info ( " Check that peers can fetch cfcheckpt on stale chain. " )
request = msg_getcfcheckpt (
filter_type = FILTER_TYPE_BASIC ,
stop_hash = int ( stale_block_hash , 16 )
stop_hash = int ( stale_block_hash , 16 ) ,
)
node 0. send_and_ping ( request )
response = node 0. last_message [ ' cfcheckpt ' ]
peer_ 0. send_and_ping ( request )
response = peer_ 0. last_message [ ' cfcheckpt ' ]
stale_cfcheckpt = self . nodes [ 0 ] . getblockfilter ( stale_block_hash , ' basic ' ) [ ' header ' ]
assert_equal (
response . headers ,
[ int ( header , 16 ) for header in ( stale_cfcheckpt , ) ]
[ int ( header , 16 ) for header in ( stale_cfcheckpt , ) ] ,
)
self . log . info ( " Check that peers can fetch cfheaders on active chain. " )
request = msg_getcfheaders (
filter_type = FILTER_TYPE_BASIC ,
start_height = 1 ,
stop_hash = int ( main_block_hash , 16 )
stop_hash = int ( main_block_hash , 16 ) ,
)
node 0. send_and_ping ( request )
response = node 0. last_message [ ' cfheaders ' ]
peer_ 0. send_and_ping ( request )
response = peer_ 0. last_message [ ' cfheaders ' ]
main_cfhashes = response . hashes
assert_equal ( len ( main_cfhashes ) , 1000 )
assert_equal (
compute_last_header ( response . prev_header , response . hashes ) ,
int ( main_cfcheckpt , 16 )
int ( main_cfcheckpt , 16 ) ,
)
self . log . info ( " Check that peers can fetch cfheaders on stale chain. " )
request = msg_getcfheaders (
filter_type = FILTER_TYPE_BASIC ,
start_height = 1 ,
stop_hash = int ( stale_block_hash , 16 )
stop_hash = int ( stale_block_hash , 16 ) ,
)
node 0. send_and_ping ( request )
response = node 0. last_message [ ' cfheaders ' ]
peer_ 0. send_and_ping ( request )
response = peer_ 0. last_message [ ' cfheaders ' ]
stale_cfhashes = response . hashes
assert_equal ( len ( stale_cfhashes ) , 1000 )
assert_equal (
compute_last_header ( response . prev_header , response . hashes ) ,
int ( stale_cfcheckpt , 16 )
int ( stale_cfcheckpt , 16 ) ,
)
self . log . info ( " Check that peers can fetch cfilters. " )
@ -161,11 +163,10 @@ class CompactFiltersTest(BitcoinTestFramework):
request = msg_getcfilters (
filter_type = FILTER_TYPE_BASIC ,
start_height = 1 ,
stop_hash = int ( stop_hash , 16 )
stop_hash = int ( stop_hash , 16 ) ,
)
node0 . send_message ( request )
node0 . sync_with_ping ( )
response = node0 . pop_cfilters ( )
peer_0 . send_and_ping ( request )
response = peer_0 . pop_cfilters ( )
assert_equal ( len ( response ) , 10 )
self . log . info ( " Check that cfilter responses are correct. " )
@ -180,11 +181,10 @@ class CompactFiltersTest(BitcoinTestFramework):
request = msg_getcfilters (
filter_type = FILTER_TYPE_BASIC ,
start_height = 1000 ,
stop_hash = int ( stale_block_hash , 16 )
stop_hash = int ( stale_block_hash , 16 ) ,
)
node0 . send_message ( request )
node0 . sync_with_ping ( )
response = node0 . pop_cfilters ( )
peer_0 . send_and_ping ( request )
response = peer_0 . pop_cfilters ( )
assert_equal ( len ( response ) , 1 )
cfilter = response [ 0 ]
@ -197,23 +197,23 @@ class CompactFiltersTest(BitcoinTestFramework):
requests = [
msg_getcfcheckpt (
filter_type = FILTER_TYPE_BASIC ,
stop_hash = int ( main_block_hash , 16 )
stop_hash = int ( main_block_hash , 16 ) ,
) ,
msg_getcfheaders (
filter_type = FILTER_TYPE_BASIC ,
start_height = 1000 ,
stop_hash = int ( main_block_hash , 16 )
stop_hash = int ( main_block_hash , 16 ) ,
) ,
msg_getcfilters (
filter_type = FILTER_TYPE_BASIC ,
start_height = 1000 ,
stop_hash = int ( main_block_hash , 16 )
stop_hash = int ( main_block_hash , 16 ) ,
) ,
]
for request in requests :
node 1 = self . nodes [ 1 ] . add_p2p_connection ( P2PInterface ( ) )
node 1. send_message ( request )
node 1. wait_for_disconnect ( )
peer_ 1 = self . nodes [ 1 ] . add_p2p_connection ( P2PInterface ( ) )
peer_ 1. send_message ( request )
peer_ 1. wait_for_disconnect ( )
self . log . info ( " Check that invalid requests result in disconnection. " )
requests = [
@ -221,18 +221,18 @@ class CompactFiltersTest(BitcoinTestFramework):
msg_getcfilters (
filter_type = FILTER_TYPE_BASIC ,
start_height = 0 ,
stop_hash = int ( main_block_hash , 16 )
stop_hash = int ( main_block_hash , 16 ) ,
) ,
# Requesting too many filter headers results in disconnection.
msg_getcfheaders (
filter_type = FILTER_TYPE_BASIC ,
start_height = 0 ,
stop_hash = int ( tip_hash , 16 )
stop_hash = int ( tip_hash , 16 ) ,
) ,
# Requesting unknown filter type results in disconnection.
msg_getcfcheckpt (
filter_type = 255 ,
stop_hash = int ( main_block_hash , 16 )
stop_hash = int ( main_block_hash , 16 ) ,
) ,
# Requesting unknown hash results in disconnection.
msg_getcfcheckpt (
@ -241,9 +241,10 @@ class CompactFiltersTest(BitcoinTestFramework):
) ,
]
for request in requests :
node0 = self . nodes [ 0 ] . add_p2p_connection ( P2PInterface ( ) )
node0 . send_message ( request )
node0 . wait_for_disconnect ( )
peer_0 = self . nodes [ 0 ] . add_p2p_connection ( P2PInterface ( ) )
peer_0 . send_message ( request )
peer_0 . wait_for_disconnect ( )
def compute_last_header ( prev_header , hashes ) :
""" Compute the last filter header from a starting header and a sequence of filter hashes. """
@ -252,5 +253,6 @@ def compute_last_header(prev_header, hashes):
header = hash256 ( ser_uint256 ( filter_hash ) + header )
return uint256_from_str ( header )
if __name__ == ' __main__ ' :
CompactFiltersTest ( ) . main ( )