mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
[test] Add test for cfheaders
This commit is contained in:
parent
f6b58c1506
commit
5308c97cca
3 changed files with 107 additions and 1 deletions
|
@ -5,12 +5,16 @@
|
||||||
"""Tests NODE_COMPACT_FILTERS (BIP 157/158).
|
"""Tests NODE_COMPACT_FILTERS (BIP 157/158).
|
||||||
|
|
||||||
Tests that a node configured with -blockfilterindex and -peerblockfilters can serve
|
Tests that a node configured with -blockfilterindex and -peerblockfilters can serve
|
||||||
cfcheckpts.
|
cfheaders and cfcheckpts.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from test_framework.messages import (
|
from test_framework.messages import (
|
||||||
FILTER_TYPE_BASIC,
|
FILTER_TYPE_BASIC,
|
||||||
|
hash256,
|
||||||
msg_getcfcheckpt,
|
msg_getcfcheckpt,
|
||||||
|
msg_getcfheaders,
|
||||||
|
ser_uint256,
|
||||||
|
uint256_from_str,
|
||||||
)
|
)
|
||||||
from test_framework.mininode import P2PInterface
|
from test_framework.mininode import P2PInterface
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
|
@ -100,12 +104,45 @@ class CompactFiltersTest(BitcoinTestFramework):
|
||||||
[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)
|
||||||
|
)
|
||||||
|
node0.send_and_ping(request)
|
||||||
|
response = node0.last_message['cfheaders']
|
||||||
|
assert_equal(len(response.hashes), 1000)
|
||||||
|
assert_equal(
|
||||||
|
compute_last_header(response.prev_header, response.hashes),
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
node0.send_and_ping(request)
|
||||||
|
response = node0.last_message['cfheaders']
|
||||||
|
assert_equal(len(response.hashes), 1000)
|
||||||
|
assert_equal(
|
||||||
|
compute_last_header(response.prev_header, response.hashes),
|
||||||
|
int(stale_cfcheckpt, 16)
|
||||||
|
)
|
||||||
|
|
||||||
self.log.info("Requests to node 1 without NODE_COMPACT_FILTERS results in disconnection.")
|
self.log.info("Requests to node 1 without NODE_COMPACT_FILTERS results in disconnection.")
|
||||||
requests = [
|
requests = [
|
||||||
msg_getcfcheckpt(
|
msg_getcfcheckpt(
|
||||||
filter_type=FILTER_TYPE_BASIC,
|
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)
|
||||||
|
),
|
||||||
]
|
]
|
||||||
for request in requests:
|
for request in requests:
|
||||||
node1 = self.nodes[1].add_p2p_connection(P2PInterface())
|
node1 = self.nodes[1].add_p2p_connection(P2PInterface())
|
||||||
|
@ -114,6 +151,12 @@ class CompactFiltersTest(BitcoinTestFramework):
|
||||||
|
|
||||||
self.log.info("Check that invalid requests result in disconnection.")
|
self.log.info("Check that invalid requests result in disconnection.")
|
||||||
requests = [
|
requests = [
|
||||||
|
# Requesting too many filter headers results in disconnection.
|
||||||
|
msg_getcfheaders(
|
||||||
|
filter_type=FILTER_TYPE_BASIC,
|
||||||
|
start_height=0,
|
||||||
|
stop_hash=int(tip_hash, 16)
|
||||||
|
),
|
||||||
# Requesting unknown filter type results in disconnection.
|
# Requesting unknown filter type results in disconnection.
|
||||||
msg_getcfcheckpt(
|
msg_getcfcheckpt(
|
||||||
filter_type=255,
|
filter_type=255,
|
||||||
|
@ -130,5 +173,12 @@ class CompactFiltersTest(BitcoinTestFramework):
|
||||||
node0.send_message(request)
|
node0.send_message(request)
|
||||||
node0.wait_for_disconnect()
|
node0.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."""
|
||||||
|
header = ser_uint256(prev_header)
|
||||||
|
for filter_hash in hashes:
|
||||||
|
header = hash256(ser_uint256(filter_hash) + header)
|
||||||
|
return uint256_from_str(header)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
CompactFiltersTest().main()
|
CompactFiltersTest().main()
|
||||||
|
|
|
@ -1516,6 +1516,59 @@ class msg_no_witness_blocktxn(msg_blocktxn):
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
return self.block_transactions.serialize(with_witness=False)
|
return self.block_transactions.serialize(with_witness=False)
|
||||||
|
|
||||||
|
class msg_getcfheaders:
|
||||||
|
__slots__ = ("filter_type", "start_height", "stop_hash")
|
||||||
|
msgtype = b"getcfheaders"
|
||||||
|
|
||||||
|
def __init__(self, filter_type, start_height, stop_hash):
|
||||||
|
self.filter_type = filter_type
|
||||||
|
self.start_height = start_height
|
||||||
|
self.stop_hash = stop_hash
|
||||||
|
|
||||||
|
def deserialize(self, f):
|
||||||
|
self.filter_type = struct.unpack("<B", f.read(1))[0]
|
||||||
|
self.start_height = struct.unpack("<I", f.read(4))[0]
|
||||||
|
self.stop_hash = deser_uint256(f)
|
||||||
|
|
||||||
|
def serialize(self):
|
||||||
|
r = b""
|
||||||
|
r += struct.pack("<B", self.filter_type)
|
||||||
|
r += struct.pack("<I", self.start_height)
|
||||||
|
r += ser_uint256(self.stop_hash)
|
||||||
|
return r
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "msg_getcfheaders(filter_type={:#x}, start_height={}, stop_hash={:x})".format(
|
||||||
|
self.filter_type, self.start_height, self.stop_hash)
|
||||||
|
|
||||||
|
class msg_cfheaders:
|
||||||
|
__slots__ = ("filter_type", "stop_hash", "prev_header", "hashes")
|
||||||
|
msgtype = b"cfheaders"
|
||||||
|
|
||||||
|
def __init__(self, filter_type=None, stop_hash=None, prev_header=None, hashes=None):
|
||||||
|
self.filter_type = filter_type
|
||||||
|
self.stop_hash = stop_hash
|
||||||
|
self.prev_header = prev_header
|
||||||
|
self.hashes = hashes
|
||||||
|
|
||||||
|
def deserialize(self, f):
|
||||||
|
self.filter_type = struct.unpack("<B", f.read(1))[0]
|
||||||
|
self.stop_hash = deser_uint256(f)
|
||||||
|
self.prev_header = deser_uint256(f)
|
||||||
|
self.hashes = deser_uint256_vector(f)
|
||||||
|
|
||||||
|
def serialize(self):
|
||||||
|
r = b""
|
||||||
|
r += struct.pack("<B", self.filter_type)
|
||||||
|
r += ser_uint256(self.stop_hash)
|
||||||
|
r += ser_uint256(self.prev_header)
|
||||||
|
r += ser_uint256_vector(self.hashes)
|
||||||
|
return r
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "msg_cfheaders(filter_type={:#x}, stop_hash={:x})".format(
|
||||||
|
self.filter_type, self.stop_hash)
|
||||||
|
|
||||||
class msg_getcfcheckpt:
|
class msg_getcfcheckpt:
|
||||||
__slots__ = ("filter_type", "stop_hash")
|
__slots__ = ("filter_type", "stop_hash")
|
||||||
msgtype = b"getcfcheckpt"
|
msgtype = b"getcfcheckpt"
|
||||||
|
|
|
@ -31,6 +31,7 @@ from test_framework.messages import (
|
||||||
msg_block,
|
msg_block,
|
||||||
MSG_BLOCK,
|
MSG_BLOCK,
|
||||||
msg_blocktxn,
|
msg_blocktxn,
|
||||||
|
msg_cfheaders,
|
||||||
msg_cfcheckpt,
|
msg_cfcheckpt,
|
||||||
msg_cmpctblock,
|
msg_cmpctblock,
|
||||||
msg_feefilter,
|
msg_feefilter,
|
||||||
|
@ -68,6 +69,7 @@ MESSAGEMAP = {
|
||||||
b"addr": msg_addr,
|
b"addr": msg_addr,
|
||||||
b"block": msg_block,
|
b"block": msg_block,
|
||||||
b"blocktxn": msg_blocktxn,
|
b"blocktxn": msg_blocktxn,
|
||||||
|
b"cfheaders": msg_cfheaders,
|
||||||
b"cfcheckpt": msg_cfcheckpt,
|
b"cfcheckpt": msg_cfcheckpt,
|
||||||
b"cmpctblock": msg_cmpctblock,
|
b"cmpctblock": msg_cmpctblock,
|
||||||
b"feefilter": msg_feefilter,
|
b"feefilter": msg_feefilter,
|
||||||
|
@ -330,6 +332,7 @@ class P2PInterface(P2PConnection):
|
||||||
def on_addr(self, message): pass
|
def on_addr(self, message): pass
|
||||||
def on_block(self, message): pass
|
def on_block(self, message): pass
|
||||||
def on_blocktxn(self, message): pass
|
def on_blocktxn(self, message): pass
|
||||||
|
def on_cfheaders(self, message): pass
|
||||||
def on_cfcheckpt(self, message): pass
|
def on_cfcheckpt(self, message): pass
|
||||||
def on_cmpctblock(self, message): pass
|
def on_cmpctblock(self, message): pass
|
||||||
def on_feefilter(self, message): pass
|
def on_feefilter(self, message): pass
|
||||||
|
|
Loading…
Add table
Reference in a new issue