From b536a6fc83ee20cfb80da8bcb5f21c664ec7b5fe Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Fri, 4 Mar 2016 16:11:49 -0500 Subject: [PATCH] Add p2p test for feefilter --- qa/pull-tester/rpc-tests.py | 3 +- qa/rpc-tests/p2p-feefilter.py | 99 +++++++++++++++++++++++++ qa/rpc-tests/test_framework/mininode.py | 21 +++++- 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100755 qa/rpc-tests/p2p-feefilter.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index f15eaacbd..74be96da7 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -127,7 +127,6 @@ testScriptsExt = [ 'getblocktemplate_proposals.py', 'txn_doublespend.py', 'txn_clone.py --mineblock', - 'pruning.py', 'forknotify.py', 'invalidateblock.py', # 'rpcbind_test.py', #temporary, bug in libevent, see #6655 @@ -137,6 +136,8 @@ testScriptsExt = [ 'mempool_packages.py', 'maxuploadtarget.py', 'replace-by-fee.py', + 'p2p-feefilter.py', + 'pruning.py', # leave pruning last as it takes a REALLY long time ] #Enable ZMQ tests diff --git a/qa/rpc-tests/p2p-feefilter.py b/qa/rpc-tests/p2p-feefilter.py new file mode 100755 index 000000000..f85c18dcd --- /dev/null +++ b/qa/rpc-tests/p2p-feefilter.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python2 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# + +from test_framework.mininode import * +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +import time + +''' +FeeFilterTest -- test processing of feefilter messages +''' + +def hashToHex(hash): + return format(hash, '064x').decode('utf-8') + +# Wait up to 60 secs to see if the testnode has received all the expected invs +def allInvsMatch(invsExpected, testnode): + for x in xrange(60): + with mininode_lock: + if (sorted(invsExpected) == sorted(testnode.txinvs)): + return True; + time.sleep(1) + return False; + +# TestNode: bare-bones "peer". Used to track which invs are received from a node +# and to send the node feefilter messages. +class TestNode(SingleNodeConnCB): + def __init__(self): + SingleNodeConnCB.__init__(self) + self.txinvs = [] + + def on_inv(self, conn, message): + for i in message.inv: + if (i.type == 1): + self.txinvs.append(hashToHex(i.hash)) + + def clear_invs(self): + with mininode_lock: + self.txinvs = [] + + def send_filter(self, feerate): + self.send_message(msg_feefilter(feerate)) + self.sync_with_ping() + +class FeeFilterTest(BitcoinTestFramework): + def setup_network(self): + # Node1 will be used to generate txs which should be relayed from Node0 + # to our test node + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros"])) + self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-logtimemicros"])) + connect_nodes(self.nodes[0], 1) + + def run_test(self): + node1 = self.nodes[1] + # Get out of IBD + node1.generate(1) + sync_blocks(self.nodes) + + # Setup the p2p connections and start up the network thread. + test_node = TestNode() + connection = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_node) + test_node.add_connection(connection) + NetworkThread().start() + test_node.wait_for_verack() + + # Test that invs are received for all txs at feerate of 20 sat/byte + node1.settxfee(Decimal("0.00020000")) + txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)] + assert(allInvsMatch(txids, test_node)) + test_node.clear_invs() + + # Set a filter of 15 sat/byte + test_node.send_filter(15000) + + # Test that txs are still being received (paying 20 sat/byte) + txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)] + assert(allInvsMatch(txids, test_node)) + test_node.clear_invs() + + # Change tx fee rate to 10 sat/byte and test they are no longer received + node1.settxfee(Decimal("0.00010000")) + [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)] + sync_mempools(self.nodes) # must be sure node 0 has received all txs + time.sleep(10) # wait 10 secs to be sure its doesn't relay any + assert(allInvsMatch([], test_node)) + test_node.clear_invs() + + # Remove fee filter and check that txs are received again + test_node.send_filter(0) + txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)] + assert(allInvsMatch(txids, test_node)) + test_node.clear_invs() + +if __name__ == '__main__': + FeeFilterTest().main() diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 5b6bb190e..20386c642 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -1023,6 +1023,23 @@ def wait_until(predicate, attempts=float('inf'), timeout=float('inf')): return False +class msg_feefilter(object): + command = "feefilter" + + def __init__(self, feerate=0L): + self.feerate = feerate + + def deserialize(self, f): + self.feerate = struct.unpack("