Browse Source

Add p2p test for feefilter

0.13
Alex Morcos 9 years ago
parent
commit
b536a6fc83
  1. 3
      qa/pull-tester/rpc-tests.py
  2. 99
      qa/rpc-tests/p2p-feefilter.py
  3. 21
      qa/rpc-tests/test_framework/mininode.py

3
qa/pull-tester/rpc-tests.py

@ -127,7 +127,6 @@ testScriptsExt = [
'getblocktemplate_proposals.py', 'getblocktemplate_proposals.py',
'txn_doublespend.py', 'txn_doublespend.py',
'txn_clone.py --mineblock', 'txn_clone.py --mineblock',
'pruning.py',
'forknotify.py', 'forknotify.py',
'invalidateblock.py', 'invalidateblock.py',
# 'rpcbind_test.py', #temporary, bug in libevent, see #6655 # 'rpcbind_test.py', #temporary, bug in libevent, see #6655
@ -137,6 +136,8 @@ testScriptsExt = [
'mempool_packages.py', 'mempool_packages.py',
'maxuploadtarget.py', 'maxuploadtarget.py',
'replace-by-fee.py', 'replace-by-fee.py',
'p2p-feefilter.py',
'pruning.py', # leave pruning last as it takes a REALLY long time
] ]
#Enable ZMQ tests #Enable ZMQ tests

99
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()

21
qa/rpc-tests/test_framework/mininode.py

@ -1023,6 +1023,23 @@ def wait_until(predicate, attempts=float('inf'), timeout=float('inf')):
return False return False
class msg_feefilter(object):
command = "feefilter"
def __init__(self, feerate=0L):
self.feerate = feerate
def deserialize(self, f):
self.feerate = struct.unpack("<Q", f.read(8))[0]
def serialize(self):
r = ""
r += struct.pack("<Q", self.feerate)
return r
def __repr__(self):
return "msg_feefilter(feerate=%08x)" % self.feerate
# This is what a callback should look like for NodeConn # This is what a callback should look like for NodeConn
# Reimplement the on_* functions to provide handling for events # Reimplement the on_* functions to provide handling for events
class NodeConnCB(object): class NodeConnCB(object):
@ -1098,6 +1115,7 @@ class NodeConnCB(object):
def on_close(self, conn): pass def on_close(self, conn): pass
def on_mempool(self, conn): pass def on_mempool(self, conn): pass
def on_pong(self, conn, message): pass def on_pong(self, conn, message): pass
def on_feefilter(self, conn, message): pass
# More useful callbacks and functions for NodeConnCB's which have a single NodeConn # More useful callbacks and functions for NodeConnCB's which have a single NodeConn
class SingleNodeConnCB(NodeConnCB): class SingleNodeConnCB(NodeConnCB):
@ -1145,7 +1163,8 @@ class NodeConn(asyncore.dispatcher):
"headers": msg_headers, "headers": msg_headers,
"getheaders": msg_getheaders, "getheaders": msg_getheaders,
"reject": msg_reject, "reject": msg_reject,
"mempool": msg_mempool "mempool": msg_mempool,
"feefilter": msg_feefilter
} }
MAGIC_BYTES = { MAGIC_BYTES = {
"mainnet": "\xf9\xbe\xb4\xd9", # mainnet "mainnet": "\xf9\xbe\xb4\xd9", # mainnet

Loading…
Cancel
Save