2 # Copyright (c) 2015-2016 The Bitcoin Core developers
3 # Distributed under the MIT software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 """Test nodes responses to having many blocks in flight.
7 In this test we connect to one node over p2p, send it numerous inv's, and
8 compare the resulting number of getdata requests to a max allowed value. We
9 test for exceeding 128 blocks in flight, which was the limit an 0.9 client will
10 reach. [0.10 clients shouldn't request more than 16 from a single peer.]
13 from test_framework
.mininode
import *
14 from test_framework
.test_framework
import BitcoinTestFramework
15 from test_framework
.util
import *
20 class TestManager(NodeConnCB
):
21 # set up NodeConnCB callbacks, overriding base class
22 def on_getdata(self
, conn
, message
):
23 self
.log
.debug("got getdata %s" % repr(message
))
25 for inv
in message
.inv
:
26 if inv
.hash not in self
.blockReqCounts
:
27 self
.blockReqCounts
[inv
.hash] = 0
28 self
.blockReqCounts
[inv
.hash] += 1
30 def on_close(self
, conn
):
31 if not self
.disconnectOkay
:
32 raise EarlyDisconnectError(0)
35 NodeConnCB
.__init
__(self
)
36 self
.log
= logging
.getLogger("BlockRelayTest")
38 def add_new_connection(self
, connection
):
39 self
.connection
= connection
40 self
.blockReqCounts
= {}
41 self
.disconnectOkay
= False
44 self
.connection
.rpc
.generate(1) # Leave IBD
46 numBlocksToGenerate
= [8, 16, 128, 1024]
47 for count
in range(len(numBlocksToGenerate
)):
49 for i
in range(numBlocksToGenerate
[count
]):
50 current_invs
.append(CInv(2, random
.randrange(0, 1 << 256)))
51 if len(current_invs
) >= 50000:
52 self
.connection
.send_message(msg_inv(current_invs
))
54 if len(current_invs
) > 0:
55 self
.connection
.send_message(msg_inv(current_invs
))
57 # Wait and see how many blocks were requested
62 for key
in self
.blockReqCounts
:
63 total_requests
+= self
.blockReqCounts
[key
]
64 if self
.blockReqCounts
[key
] > 1:
65 raise AssertionError("Error, test failed: block %064x requested more than once" % key
)
66 if total_requests
> MAX_REQUESTS
:
67 raise AssertionError("Error, too many blocks (%d) requested" % total_requests
)
68 print("Round %d: success (total requests: %d)" % (count
, total_requests
))
70 self
.disconnectOkay
= True
71 self
.connection
.disconnect_node()
74 class MaxBlocksInFlightTest(BitcoinTestFramework
):
75 def add_options(self
, parser
):
76 parser
.add_option("--testbinary", dest
="testbinary",
77 default
=os
.getenv("BITCOIND", "bitcoind"),
78 help="Binary to test max block requests behavior")
82 self
.setup_clean_chain
= True
85 def setup_network(self
):
86 self
.nodes
= start_nodes(self
.num_nodes
, self
.options
.tmpdir
,
87 extra_args
=[['-debug', '-whitelist=127.0.0.1']],
88 binary
=[self
.options
.testbinary
])
92 test
.add_new_connection(NodeConn('127.0.0.1', p2p_port(0), self
.nodes
[0], test
))
93 NetworkThread().start() # Start up network handling in another thread
96 if __name__
== '__main__':
97 MaxBlocksInFlightTest().main()