Changeset View
Changeset View
Standalone View
Standalone View
test/functional/p2p_filter.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2020 The Bitcoin Core developers | # Copyright (c) 2020 The Bitcoin Core developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
""" | """ | ||||
Test BIP 37 | Test BIP 37 | ||||
""" | """ | ||||
from test_framework.messages import ( | from test_framework.messages import ( | ||||
CInv, | |||||
MSG_BLOCK, | MSG_BLOCK, | ||||
MSG_FILTERED_BLOCK, | MSG_FILTERED_BLOCK, | ||||
msg_getdata, | |||||
msg_filterload, | |||||
msg_filteradd, | msg_filteradd, | ||||
msg_filterclear, | msg_filterclear, | ||||
msg_filterload, | |||||
msg_getdata, | |||||
) | ) | ||||
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 | ||||
class FilterNode(P2PInterface): | class FilterNode(P2PInterface): | ||||
# This is a P2SH watch-only wallet | # This is a P2SH watch-only wallet | ||||
watch_script_pubkey = 'a914ffffffffffffffffffffffffffffffffffffffff87' | watch_script_pubkey = 'a914ffffffffffffffffffffffffffffffffffffffff87' | ||||
# The initial filter (n=10, fp=0.000001) with just the above scriptPubKey | # The initial filter (n=10, fp=0.000001) with just the above scriptPubKey | ||||
# added | # added | ||||
watch_filter_init = msg_filterload( | watch_filter_init = msg_filterload( | ||||
data=b'@\x00\x08\x00\x80\x00\x00 \x00\xc0\x00 \x04\x00\x08$\x00\x04\x80\x00\x00 \x00\x00\x00\x00\x80\x00\x00@\x00\x02@ \x00', | data=b'@\x00\x08\x00\x80\x00\x00 \x00\xc0\x00 \x04\x00\x08$\x00\x04\x80\x00\x00 \x00\x00\x00\x00\x80\x00\x00@\x00\x02@ \x00', | ||||
nHashFuncs=19, | nHashFuncs=19, | ||||
nTweak=0, | nTweak=0, | ||||
nFlags=1, | nFlags=1, | ||||
) | ) | ||||
def on_inv(self, message): | def on_inv(self, message): | ||||
want = msg_getdata() | want = msg_getdata() | ||||
for i in message.inv: | for i in message.inv: | ||||
# inv messages can only contain TX or BLOCK, so translate BLOCK to | # inv messages can only contain TX or BLOCK, so translate BLOCK to | ||||
# FILTERED_BLOCK | # FILTERED_BLOCK | ||||
if i.type == MSG_BLOCK: | if i.type == MSG_BLOCK: | ||||
i.type = MSG_FILTERED_BLOCK | want.inv.append(CInv(MSG_FILTERED_BLOCK, i.hash)) | ||||
else: | |||||
want.inv.append(i) | want.inv.append(i) | ||||
if len(want.inv): | if len(want.inv): | ||||
self.send_message(want) | self.send_message(want) | ||||
def on_merkleblock(self, message): | def on_merkleblock(self, message): | ||||
self.merkleblock_received = True | self.merkleblock_received = True | ||||
def on_tx(self, message): | def on_tx(self, message): | ||||
self.tx_received = True | self.tx_received = True | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
filter_node.send_and_ping(msg_filterclear()) | filter_node.send_and_ping(msg_filterclear()) | ||||
for _ in range(5): | for _ in range(5): | ||||
txid = self.nodes[0].sendtoaddress( | txid = self.nodes[0].sendtoaddress( | ||||
self.nodes[0].getnewaddress(), 7) | self.nodes[0].getnewaddress(), 7) | ||||
filter_node.wait_for_tx(txid) | filter_node.wait_for_tx(txid) | ||||
self.log.info( | self.log.info( | ||||
'Check that request for filtered blocks is ignored if no filter' | |||||
' is set') | |||||
filter_node.merkleblock_received = False | |||||
filter_node.tx_received = False | |||||
with self.nodes[0].assert_debug_log(expected_msgs=['received getdata']): | |||||
block_hash = self.nodes[0].generatetoaddress( | |||||
1, self.nodes[0].getnewaddress())[0] | |||||
filter_node.wait_for_inv([CInv(MSG_BLOCK, int(block_hash, 16))]) | |||||
filter_node.sync_with_ping() | |||||
assert not filter_node.merkleblock_received | |||||
assert not filter_node.tx_received | |||||
self.log.info( | |||||
'Check that sending "filteradd" if no filter is set is treated as ' | |||||
'misbehavior') | |||||
with self.nodes[0].assert_debug_log(['Misbehaving']): | |||||
filter_node.send_and_ping(msg_filteradd(data=b'letsmisbehave')) | |||||
self.log.info( | |||||
"Check that division-by-zero remote crash bug [CVE-2013-5700] is fixed") | "Check that division-by-zero remote crash bug [CVE-2013-5700] is fixed") | ||||
filter_node.send_and_ping(msg_filterload(data=b'', nHashFuncs=1)) | filter_node.send_and_ping(msg_filterload(data=b'', nHashFuncs=1)) | ||||
filter_node.send_and_ping( | filter_node.send_and_ping( | ||||
msg_filteradd( | msg_filteradd( | ||||
data=b'letstrytocrashthisnode')) | data=b'letstrytocrashthisnode')) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
FilterTest().main() | FilterTest().main() |