diff options
Diffstat (limited to 'test')
99 files changed, 929 insertions, 1197 deletions
diff --git a/test/README.md b/test/README.md index b40052b898..4dd512638d 100644 --- a/test/README.md +++ b/test/README.md @@ -34,7 +34,7 @@ You can run any single test by calling test/functional/test_runner.py <testname> -Or you can run any combination of tests by calling +Or you can run any combination (incl. duplicates) of tests by calling test/functional/test_runner.py <testname1> <testname2> <testname3> ... diff --git a/test/functional/README.md b/test/functional/README.md index 651b01f18a..e6c4849702 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -59,7 +59,7 @@ thread.) * RPC calls are available in p2p tests. * Can be used to write free-form tests, where specific p2p-protocol behavior -is tested. Examples: ```p2p-accept-block.py```, ```maxblocksinflight.py```. +is tested. Examples: ```p2p-accept-block.py```, ```p2p-compactblocks.py```. ## Comptool diff --git a/test/functional/abandonconflict.py b/test/functional/abandonconflict.py index 887dbebd4f..9748757641 100755 --- a/test/functional/abandonconflict.py +++ b/test/functional/abandonconflict.py @@ -10,22 +10,15 @@ which are not included in a block and are not currently in the mempool. It has no effect on transactions which are already conflicted or abandoned. """ - from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -import urllib.parse class AbandonConflictTest(BitcoinTestFramework): def __init__(self): super().__init__() self.num_nodes = 2 self.setup_clean_chain = False - - def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.00001"])) - self.nodes.append(start_node(1, self.options.tmpdir)) - connect_nodes(self.nodes[0], 1) + self.extra_args = [["-minrelaytxfee=0.00001"], []] def run_test(self): self.nodes[1].generate(100) @@ -42,8 +35,8 @@ class AbandonConflictTest(BitcoinTestFramework): assert(balance - newbalance < Decimal("0.001")) #no more than fees lost balance = newbalance - url = urllib.parse.urlparse(self.nodes[1].url) - self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1))) + # Disconnect nodes so node0's transactions don't get into node1's mempool + disconnect_nodes(self.nodes[0], 1) # Identify the 10btc outputs nA = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txA, 1)["vout"]) if vout["value"] == Decimal("10")) @@ -83,8 +76,9 @@ class AbandonConflictTest(BitcoinTestFramework): stop_node(self.nodes[0],0) self.nodes[0]=start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.0001"]) - # Verify txs no longer in mempool + # Verify txs no longer in either node's mempool assert_equal(len(self.nodes[0].getrawmempool()), 0) + assert_equal(len(self.nodes[1].getrawmempool()), 0) # Not in mempool txs from self should only reduce balance # inputs are still spent, but change not received diff --git a/test/functional/bip65-cltv-p2p.py b/test/functional/bip65-cltv-p2p.py index 63d05e8fc9..bb83042f35 100755 --- a/test/functional/bip65-cltv-p2p.py +++ b/test/functional/bip65-cltv-p2p.py @@ -39,12 +39,7 @@ class BIP65Test(ComparisonTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 - - def setup_network(self): - # Must set the blockversion for this test - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - extra_args=[['-whitelist=127.0.0.1', '-blockversion=3']], - binary=[self.options.testbinary]) + self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=3']] def run_test(self): test = TestManager(self, self.options.tmpdir) diff --git a/test/functional/bip65-cltv.py b/test/functional/bip65-cltv.py index 7f13bb9952..ddf932c746 100755 --- a/test/functional/bip65-cltv.py +++ b/test/functional/bip65-cltv.py @@ -12,15 +12,12 @@ class BIP65Test(BitcoinTestFramework): super().__init__() self.num_nodes = 3 self.setup_clean_chain = False + self.extra_args = [[], ["-blockversion=3"], ["-blockversion=4"]] def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, [])) - self.nodes.append(start_node(1, self.options.tmpdir, ["-blockversion=3"])) - self.nodes.append(start_node(2, self.options.tmpdir, ["-blockversion=4"])) + self.setup_nodes() connect_nodes(self.nodes[1], 0) connect_nodes(self.nodes[2], 0) - self.is_network_split = False self.sync_all() def run_test(self): diff --git a/test/functional/bip68-112-113-p2p.py b/test/functional/bip68-112-113-p2p.py index 0867f42585..5a322e8c0e 100755 --- a/test/functional/bip68-112-113-p2p.py +++ b/test/functional/bip68-112-113-p2p.py @@ -95,12 +95,7 @@ class BIP68_112_113Test(ComparisonTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 - - def setup_network(self): - # Must set the blockversion for this test - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - extra_args=[['-whitelist=127.0.0.1', '-blockversion=4']], - binary=[self.options.testbinary]) + self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4']] def run_test(self): test = TestManager(self, self.options.tmpdir) diff --git a/test/functional/bip68-sequence.py b/test/functional/bip68-sequence.py index 89d42a710c..db66b7719c 100755 --- a/test/functional/bip68-sequence.py +++ b/test/functional/bip68-sequence.py @@ -21,16 +21,11 @@ class BIP68Test(BitcoinTestFramework): super().__init__() self.num_nodes = 2 self.setup_clean_chain = False + self.extra_args = [[], ["-acceptnonstdtxn=0"]] - def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir)) - self.nodes.append(start_node(1, self.options.tmpdir, ["-acceptnonstdtxn=0"])) - self.is_network_split = False + def run_test(self): self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"] - connect_nodes(self.nodes[0], 1) - def run_test(self): # Generate some coins self.nodes[0].generate(110) diff --git a/test/functional/bip9-softforks.py b/test/functional/bip9-softforks.py index 60d262da81..1b2dff63d2 100755 --- a/test/functional/bip9-softforks.py +++ b/test/functional/bip9-softforks.py @@ -16,7 +16,6 @@ test that enforcement has not triggered (which triggers ACTIVE) test that enforcement has triggered """ -from test_framework.blockstore import BlockStore from test_framework.test_framework import ComparisonTestFramework from test_framework.util import * from test_framework.mininode import CTransaction, NetworkThread @@ -32,11 +31,7 @@ class BIP9SoftForksTest(ComparisonTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 - - def setup_network(self): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - extra_args=[['-whitelist=127.0.0.1']], - binary=[self.options.testbinary]) + self.extra_args = [['-whitelist=127.0.0.1']] def run_test(self): self.test = TestManager(self, self.options.tmpdir) diff --git a/test/functional/bipdersig-p2p.py b/test/functional/bipdersig-p2p.py index 22bd39fbe5..31c7ebba90 100755 --- a/test/functional/bipdersig-p2p.py +++ b/test/functional/bipdersig-p2p.py @@ -47,12 +47,6 @@ class BIP66Test(ComparisonTestFramework): super().__init__() self.num_nodes = 1 - def setup_network(self): - # Must set the blockversion for this test - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - extra_args=[['-whitelist=127.0.0.1', '-blockversion=2']], - binary=[self.options.testbinary]) - def run_test(self): test = TestManager(self, self.options.tmpdir) test.add_all_connections(self.nodes) diff --git a/test/functional/bipdersig.py b/test/functional/bipdersig.py index 371cc41bb7..41f88fb664 100755 --- a/test/functional/bipdersig.py +++ b/test/functional/bipdersig.py @@ -12,15 +12,12 @@ class BIP66Test(BitcoinTestFramework): super().__init__() self.num_nodes = 3 self.setup_clean_chain = False + self.extra_args = [[], ["-blockversion=2"], ["-blockversion=3"]] def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, [])) - self.nodes.append(start_node(1, self.options.tmpdir, ["-blockversion=2"])) - self.nodes.append(start_node(2, self.options.tmpdir, ["-blockversion=3"])) + self.setup_nodes() connect_nodes(self.nodes[1], 0) connect_nodes(self.nodes[2], 0) - self.is_network_split = False self.sync_all() def run_test(self): diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py index 596aed50ec..8596f1edaf 100755 --- a/test/functional/blockchain.py +++ b/test/functional/blockchain.py @@ -6,6 +6,11 @@ Test the following RPCs: - gettxoutsetinfo + - getdifficulty + - getbestblockhash + - getblockhash + - getblockheader + - getnetworkhashps - verifychain Tests correspond to code in rpc/blockchain.cpp. @@ -19,8 +24,6 @@ from test_framework.util import ( assert_raises_jsonrpc, assert_is_hex_string, assert_is_hash_string, - start_nodes, - connect_nodes_bi, ) @@ -31,15 +34,11 @@ class BlockchainTest(BitcoinTestFramework): self.setup_clean_chain = False self.num_nodes = 2 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes_bi(self.nodes, 0, 1) - self.is_network_split = False - self.sync_all() - def run_test(self): self._test_gettxoutsetinfo() self._test_getblockheader() + self._test_getdifficulty() + self._test_getnetworkhashps() self.nodes[0].verifychain(4, 0) def _test_gettxoutsetinfo(self): @@ -57,7 +56,8 @@ class BlockchainTest(BitcoinTestFramework): def _test_getblockheader(self): node = self.nodes[0] - assert_raises_jsonrpc(-5, "Block not found", node.getblockheader, "nonsense") + assert_raises_jsonrpc(-5, "Block not found", + node.getblockheader, "nonsense") besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) @@ -79,5 +79,16 @@ class BlockchainTest(BitcoinTestFramework): assert isinstance(int(header['versionHex'], 16), int) assert isinstance(header['difficulty'], Decimal) + def _test_getdifficulty(self): + difficulty = self.nodes[0].getdifficulty() + # 1 hash in 2 should be valid, so difficulty should be 1/2**31 + # binary => decimal => binary math is why we do this check + assert abs(difficulty * 2**31 - 1) < 0.0001 + + def _test_getnetworkhashps(self): + hashes_per_second = self.nodes[0].getnetworkhashps() + # This should be 2 hashes every 10 minutes or 1/300 + assert abs(hashes_per_second * 300 - 1) < 0.0001 + if __name__ == '__main__': BlockchainTest().main() diff --git a/test/functional/bumpfee.py b/test/functional/bumpfee.py index c51a75cc26..54fd7740c1 100755 --- a/test/functional/bumpfee.py +++ b/test/functional/bumpfee.py @@ -47,7 +47,6 @@ class BumpFeeTest(BitcoinTestFramework): self.nodes[1].walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT) connect_nodes_bi(self.nodes, 0, 1) - self.is_network_split = False self.sync_all() def run_test(self): diff --git a/test/functional/decodescript.py b/test/functional/decodescript.py index 5555e96c44..21a9f1223f 100755 --- a/test/functional/decodescript.py +++ b/test/functional/decodescript.py @@ -16,10 +16,6 @@ class DecodeScriptTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - self.is_network_split = False - def decodescript_script_sig(self): signature = '304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c509001' push_signature = '48' + signature diff --git a/test/functional/disablewallet.py b/test/functional/disablewallet.py index 2f729e19bf..d344513414 100755 --- a/test/functional/disablewallet.py +++ b/test/functional/disablewallet.py @@ -18,13 +18,11 @@ class DisableWalletTest (BitcoinTestFramework): super().__init__() self.setup_clean_chain = True self.num_nodes = 1 - - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [['-disablewallet']]) - self.is_network_split = False - self.sync_all() + self.extra_args = [["-disablewallet"]] def run_test (self): + # Make sure wallet is really disabled + assert_raises_jsonrpc(-32601, 'Method not found', self.nodes[0].getwalletinfo) x = self.nodes[0].validateaddress('3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy') assert(x['isvalid'] == False) x = self.nodes[0].validateaddress('mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ') diff --git a/test/functional/disconnect_ban.py b/test/functional/disconnect_ban.py index 3f451d49d2..f453fc0261 100755 --- a/test/functional/disconnect_ban.py +++ b/test/functional/disconnect_ban.py @@ -3,6 +3,7 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test node disconnect and ban behavior""" +import time from test_framework.mininode import wait_until from test_framework.test_framework import BitcoinTestFramework @@ -20,17 +21,13 @@ class DisconnectBanTest(BitcoinTestFramework): self.num_nodes = 2 self.setup_clean_chain = False - def setup_network(self): - self.nodes = self.setup_nodes() - connect_nodes_bi(self.nodes, 0, 1) - def run_test(self): self.log.info("Test setban and listbanned RPCs") self.log.info("setban: successfully ban single IP address") assert_equal(len(self.nodes[1].getpeerinfo()), 2) # node1 should have 2 connections to node0 at this point self.nodes[1].setban("127.0.0.1", "add") - wait_until(lambda: len(self.nodes[1].getpeerinfo()) == 0) + assert wait_until(lambda: len(self.nodes[1].getpeerinfo()) == 0, timeout=10) assert_equal(len(self.nodes[1].getpeerinfo()), 0) # all nodes must be disconnected at this point assert_equal(len(self.nodes[1].listbanned()), 1) @@ -60,11 +57,16 @@ class DisconnectBanTest(BitcoinTestFramework): self.log.info("setban: test persistence across node restart") self.nodes[1].setban("127.0.0.0/32", "add") self.nodes[1].setban("127.0.0.0/24", "add") + # Set the mocktime so we can control when bans expire + old_time = int(time.time()) + self.nodes[1].setmocktime(old_time) self.nodes[1].setban("192.168.0.1", "add", 1) # ban for 1 seconds self.nodes[1].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) # ban for 1000 seconds listBeforeShutdown = self.nodes[1].listbanned() assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address']) - wait_until(lambda: len(self.nodes[1].listbanned()) == 3) + # Move time forward by 3 seconds so the third ban has expired + self.nodes[1].setmocktime(old_time + 3) + assert_equal(len(self.nodes[1].listbanned()), 3) stop_node(self.nodes[1], 1) @@ -78,7 +80,7 @@ class DisconnectBanTest(BitcoinTestFramework): self.nodes[1].clearbanned() connect_nodes_bi(self.nodes, 0, 1) - self.log.info("Test disconnectrnode RPCs") + self.log.info("Test disconnectnode RPCs") self.log.info("disconnectnode: fail to disconnect when calling with address and nodeid") address1 = self.nodes[0].getpeerinfo()[0]['addr'] @@ -91,7 +93,7 @@ class DisconnectBanTest(BitcoinTestFramework): self.log.info("disconnectnode: successfully disconnect node by address") address1 = self.nodes[0].getpeerinfo()[0]['addr'] self.nodes[0].disconnectnode(address=address1) - wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1) + assert wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1, timeout=10) assert not [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1] self.log.info("disconnectnode: successfully reconnect node") @@ -102,7 +104,7 @@ class DisconnectBanTest(BitcoinTestFramework): self.log.info("disconnectnode: successfully disconnect node by node id") id1 = self.nodes[0].getpeerinfo()[0]['id'] self.nodes[0].disconnectnode(nodeid=id1) - wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1) + assert wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1, timeout=10) assert not [node for node in self.nodes[0].getpeerinfo() if node['id'] == id1] if __name__ == '__main__': diff --git a/test/functional/forknotify.py b/test/functional/forknotify.py index 7a365438cc..9db61c8350 100755 --- a/test/functional/forknotify.py +++ b/test/functional/forknotify.py @@ -16,8 +16,6 @@ class ForkNotifyTest(BitcoinTestFramework): self.num_nodes = 2 self.setup_clean_chain = False - alert_filename = None # Set by setup_network - def setup_network(self): self.nodes = [] self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") @@ -30,7 +28,6 @@ class ForkNotifyTest(BitcoinTestFramework): ["-blockversion=211"])) connect_nodes(self.nodes[1], 0) - self.is_network_split = False self.sync_all() def run_test(self): diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py index b86ea2d877..9ddafeb611 100755 --- a/test/functional/fundrawtransaction.py +++ b/test/functional/fundrawtransaction.py @@ -23,15 +23,12 @@ class RawTransactionsTest(BitcoinTestFramework): self.num_nodes = 4 def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - - connect_nodes_bi(self.nodes,0,1) - connect_nodes_bi(self.nodes,1,2) - connect_nodes_bi(self.nodes,0,2) - connect_nodes_bi(self.nodes,0,3) + self.setup_nodes() - self.is_network_split=False - self.sync_all() + connect_nodes_bi(self.nodes, 0, 1) + connect_nodes_bi(self.nodes, 1, 2) + connect_nodes_bi(self.nodes, 0, 2) + connect_nodes_bi(self.nodes, 0, 3) def run_test(self): min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee'] @@ -53,6 +50,11 @@ class RawTransactionsTest(BitcoinTestFramework): self.nodes[0].generate(121) self.sync_all() + # ensure that setting changePosition in fundraw with an exact match is handled properly + rawmatch = self.nodes[2].createrawtransaction([], {self.nodes[2].getnewaddress():50}) + rawmatch = self.nodes[2].fundrawtransaction(rawmatch, {"changePosition":1, "subtractFeeFromOutputs":[0]}) + assert_equal(rawmatch["changepos"], -1) + watchonly_address = self.nodes[0].getnewaddress() watchonly_pubkey = self.nodes[0].validateaddress(watchonly_address)["pubkey"] watchonly_amount = Decimal(200) @@ -462,7 +464,6 @@ class RawTransactionsTest(BitcoinTestFramework): connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) connect_nodes_bi(self.nodes,0,3) - self.is_network_split=False self.sync_all() # drain the keypool diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py index 67745f77d1..fca99c7df5 100755 --- a/test/functional/getblocktemplate_proposals.py +++ b/test/functional/getblocktemplate_proposals.py @@ -73,10 +73,6 @@ class GetBlockTemplateProposalTest(BitcoinTestFramework): self.num_nodes = 2 self.setup_clean_chain = False - def setup_network(self): - self.nodes = self.setup_nodes() - connect_nodes_bi(self.nodes, 0, 1) - def run_test(self): node = self.nodes[0] node.generate(1) # Mine a block to leave initial block download diff --git a/test/functional/getchaintips.py b/test/functional/getchaintips.py index 14222334a6..15f96c565f 100755 --- a/test/functional/getchaintips.py +++ b/test/functional/getchaintips.py @@ -31,7 +31,7 @@ class GetChainTipsTest (BitcoinTestFramework): self.split_network () self.nodes[0].generate(10) self.nodes[2].generate(20) - self.sync_all () + self.sync_all([self.nodes[:2], self.nodes[2:]]) tips = self.nodes[1].getchaintips () assert_equal (len (tips), 1) diff --git a/test/functional/httpbasics.py b/test/functional/httpbasics.py index 8f35f0ab87..4b32e8d9ca 100755 --- a/test/functional/httpbasics.py +++ b/test/functional/httpbasics.py @@ -17,7 +17,7 @@ class HTTPBasicsTest (BitcoinTestFramework): self.setup_clean_chain = False def setup_network(self): - self.nodes = self.setup_nodes() + self.setup_nodes() def run_test(self): diff --git a/test/functional/importmulti.py b/test/functional/importmulti.py index e049302632..9e3491c428 100755 --- a/test/functional/importmulti.py +++ b/test/functional/importmulti.py @@ -12,9 +12,8 @@ class ImportMultiTest (BitcoinTestFramework): self.num_nodes = 2 self.setup_clean_chain = True - def setup_network(self, split=False): - self.nodes = start_nodes(2, self.options.tmpdir) - self.is_network_split=False + def setup_network(self): + self.setup_nodes() def run_test (self): self.log.info("Mining blocks...") diff --git a/test/functional/importprunedfunds.py b/test/functional/importprunedfunds.py index b4c8ee6c70..94753fe431 100755 --- a/test/functional/importprunedfunds.py +++ b/test/functional/importprunedfunds.py @@ -14,12 +14,6 @@ class ImportPrunedFundsTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 2 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes_bi(self.nodes,0,1) - self.is_network_split=False - self.sync_all() - def run_test(self): self.log.info("Mining blocks...") self.nodes[0].generate(101) diff --git a/test/functional/invalidateblock.py b/test/functional/invalidateblock.py index 8c80b64003..c499d57b90 100755 --- a/test/functional/invalidateblock.py +++ b/test/functional/invalidateblock.py @@ -8,20 +8,15 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * class InvalidateTest(BitcoinTestFramework): - - + def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 3 def setup_network(self): - self.nodes = [] - self.is_network_split = False - self.nodes.append(start_node(0, self.options.tmpdir)) - self.nodes.append(start_node(1, self.options.tmpdir)) - self.nodes.append(start_node(2, self.options.tmpdir)) - + self.setup_nodes() + def run_test(self): self.log.info("Make sure we repopulate setBlockIndexCandidates after InvalidateBlock:") self.log.info("Mine 4 blocks on Node 0") diff --git a/test/functional/keypool.py b/test/functional/keypool.py index cb9ab688d1..c276e64c7c 100755 --- a/test/functional/keypool.py +++ b/test/functional/keypool.py @@ -84,8 +84,5 @@ class KeyPoolTest(BitcoinTestFramework): self.setup_clean_chain = False self.num_nodes = 1 - def setup_network(self): - self.nodes = self.setup_nodes() - if __name__ == '__main__': KeyPoolTest().main() diff --git a/test/functional/listsinceblock.py b/test/functional/listsinceblock.py index a75e66c8c4..f3d41e573e 100755 --- a/test/functional/listsinceblock.py +++ b/test/functional/listsinceblock.py @@ -43,7 +43,6 @@ class ListSinceBlockTest (BitcoinTestFramework): This test only checks that [tx0] is present. ''' - assert_equal(self.is_network_split, False) self.nodes[2].generate(101) self.sync_all() @@ -54,7 +53,6 @@ class ListSinceBlockTest (BitcoinTestFramework): # Split network into two self.split_network() - assert_equal(self.is_network_split, True) # send to nodes[0] from nodes[2] senttx = self.nodes[2].sendtoaddress(self.nodes[0].getnewaddress(), 1) @@ -64,7 +62,7 @@ class ListSinceBlockTest (BitcoinTestFramework): self.nodes[2].generate(7) self.log.info('lastblockhash=%s' % (lastblockhash)) - self.sync_all() + self.sync_all([self.nodes[:2], self.nodes[2:]]) self.join_network() diff --git a/test/functional/listtransactions.py b/test/functional/listtransactions.py index 68d14093ce..cba370d8b0 100755 --- a/test/functional/listtransactions.py +++ b/test/functional/listtransactions.py @@ -24,7 +24,7 @@ class ListTransactionsTest(BitcoinTestFramework): def setup_nodes(self): #This test requires mocktime enable_mocktime() - return start_nodes(self.num_nodes, self.options.tmpdir) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) def run_test(self): # Simple send, 0 to 1: diff --git a/test/functional/maxblocksinflight.py b/test/functional/maxblocksinflight.py deleted file mode 100755 index 4ef2a35a44..0000000000 --- a/test/functional/maxblocksinflight.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -"""Test nodes responses to having many blocks in flight. - -In this test we connect to one node over p2p, send it numerous inv's, and -compare the resulting number of getdata requests to a max allowed value. We -test for exceeding 128 blocks in flight, which was the limit an 0.9 client will -reach. [0.10 clients shouldn't request more than 16 from a single peer.] -""" - -from test_framework.mininode import * -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * - -MAX_REQUESTS = 128 - -class TestManager(NodeConnCB): - def on_getdata(self, conn, message): - self.log.debug("got getdata %s" % repr(message)) - # Log the requests - for inv in message.inv: - if inv.hash not in self.blockReqCounts: - self.blockReqCounts[inv.hash] = 0 - self.blockReqCounts[inv.hash] += 1 - - def on_close(self, conn): - if not self.disconnectOkay: - raise EarlyDisconnectError(0) - - def add_new_connection(self, connection): - super().add_connection(connection) - self.blockReqCounts = {} - self.disconnectOkay = False - - def run(self): - self.connection.rpc.generate(1) # Leave IBD - - numBlocksToGenerate = [8, 16, 128, 1024] - for count in range(len(numBlocksToGenerate)): - current_invs = [] - for i in range(numBlocksToGenerate[count]): - current_invs.append(CInv(2, random.randrange(0, 1 << 256))) - if len(current_invs) >= 50000: - self.connection.send_message(msg_inv(current_invs)) - current_invs = [] - if len(current_invs) > 0: - self.connection.send_message(msg_inv(current_invs)) - - # Wait and see how many blocks were requested - time.sleep(2) - - total_requests = 0 - with mininode_lock: - for key in self.blockReqCounts: - total_requests += self.blockReqCounts[key] - if self.blockReqCounts[key] > 1: - raise AssertionError("Error, test failed: block %064x requested more than once" % key) - if total_requests > MAX_REQUESTS: - raise AssertionError("Error, too many blocks (%d) requested" % total_requests) - self.log.info("Round %d: success (total requests: %d)" % (count, total_requests)) - - self.disconnectOkay = True - self.connection.disconnect_node() - - -class MaxBlocksInFlightTest(BitcoinTestFramework): - def add_options(self, parser): - parser.add_option("--testbinary", dest="testbinary", - default=os.getenv("BITCOIND", "bitcoind"), - help="Binary to test max block requests behavior") - - def __init__(self): - super().__init__() - self.setup_clean_chain = True - self.num_nodes = 1 - - def setup_network(self): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - extra_args=[['-whitelist=127.0.0.1']], - binary=[self.options.testbinary]) - - def run_test(self): - test = TestManager() - # pass log handler through to the test manager object - test.log = self.log - test.add_new_connection(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test)) - NetworkThread().start() # Start up network handling in another thread - test.run() - -if __name__ == '__main__': - MaxBlocksInFlightTest().main() diff --git a/test/functional/maxuploadtarget.py b/test/functional/maxuploadtarget.py index 9b42bf276c..bff1b53234 100755 --- a/test/functional/maxuploadtarget.py +++ b/test/functional/maxuploadtarget.py @@ -10,63 +10,24 @@ if uploadtarget has been reached. if uploadtarget has been reached. * Verify that the upload counters are reset after 24 hours. """ +from collections import defaultdict +import time from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -import time -# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending -# p2p messages to a node, generating the messages in the main testing logic. class TestNode(NodeConnCB): def __init__(self): super().__init__() - self.connection = None - self.ping_counter = 1 - self.last_pong = msg_pong() - self.block_receive_map = {} - - def add_connection(self, conn): - self.connection = conn - self.peer_disconnected = False + self.block_receive_map = defaultdict(int) def on_inv(self, conn, message): pass - # Track the last getdata message we receive (used in the test) - def on_getdata(self, conn, message): - self.last_getdata = message - def on_block(self, conn, message): message.block.calc_sha256() - try: - self.block_receive_map[message.block.sha256] += 1 - except KeyError as e: - self.block_receive_map[message.block.sha256] = 1 - - # Spin until verack message is received from the node. - # We use this to signal that our test can begin. This - # is called from the testing thread, so it needs to acquire - # the global lock. - def wait_for_verack(self): - def veracked(): - return self.verack_received - return wait_until(veracked, timeout=10) - - def wait_for_disconnect(self): - def disconnected(): - return self.peer_disconnected - return wait_until(disconnected, timeout=10) - - # Wrapper for the NodeConn's send_message function - def send_message(self, message): - self.connection.send_message(message) - - def on_pong(self, conn, message): - self.last_pong = message - - def on_close(self, conn): - self.peer_disconnected = True + self.block_receive_map[message.block.sha256] += 1 class MaxUploadTest(BitcoinTestFramework): @@ -74,15 +35,11 @@ class MaxUploadTest(BitcoinTestFramework): super().__init__() self.setup_clean_chain = True self.num_nodes = 1 + self.extra_args = [["-maxuploadtarget=800", "-blockmaxsize=999000"]] # Cache for utxos, as the listunspent may take a long time later in the test self.utxo_cache = [] - def setup_network(self): - # Start a node with maxuploadtarget of 200 MB (/24h) - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-maxuploadtarget=800", "-blockmaxsize=999000"])) - def run_test(self): # Before we connect anything, we first set the time on the node # to be in the past, otherwise things break because the CNode @@ -192,33 +149,26 @@ class MaxUploadTest(BitcoinTestFramework): stop_node(self.nodes[0], 0) self.nodes[0] = start_node(0, self.options.tmpdir, ["-whitelist=127.0.0.1", "-maxuploadtarget=1", "-blockmaxsize=999000"]) - #recreate/reconnect 3 test nodes - test_nodes = [] - connections = [] - - for i in range(3): - test_nodes.append(TestNode()) - connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_nodes[i])) - test_nodes[i].add_connection(connections[i]) + #recreate/reconnect a test node + test_nodes = [TestNode()] + connections = [NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_nodes[0])] + test_nodes[0].add_connection(connections[0]) NetworkThread().start() # Start up network handling in another thread - [x.wait_for_verack() for x in test_nodes] + test_nodes[0].wait_for_verack() #retrieve 20 blocks which should be enough to break the 1MB limit getdata_request.inv = [CInv(2, big_new_block)] for i in range(20): - test_nodes[1].send_message(getdata_request) - test_nodes[1].sync_with_ping() - assert_equal(test_nodes[1].block_receive_map[big_new_block], i+1) + test_nodes[0].send_message(getdata_request) + test_nodes[0].sync_with_ping() + assert_equal(test_nodes[0].block_receive_map[big_new_block], i+1) getdata_request.inv = [CInv(2, big_old_block)] - test_nodes[1].send_message(getdata_request) - test_nodes[1].wait_for_disconnect() - assert_equal(len(self.nodes[0].getpeerinfo()), 3) #node is still connected because of the whitelist + test_nodes[0].send_and_ping(getdata_request) + assert_equal(len(self.nodes[0].getpeerinfo()), 1) #node is still connected because of the whitelist - self.log.info("Peer 1 still connected after trying to download old block (whitelisted)") - - [c.disconnect_node() for c in connections] + self.log.info("Peer still connected after trying to download old block (whitelisted)") if __name__ == '__main__': MaxUploadTest().main() diff --git a/test/functional/mempool_limit.py b/test/functional/mempool_limit.py index a7ca576aee..2777291dd0 100755 --- a/test/functional/mempool_limit.py +++ b/test/functional/mempool_limit.py @@ -9,30 +9,25 @@ from test_framework.util import * class MempoolLimitTest(BitcoinTestFramework): - def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-maxmempool=5", "-spendzeroconfchange=0"])) - self.is_network_split = False - self.sync_all() - self.relayfee = self.nodes[0].getnetworkinfo()['relayfee'] - def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 1 - - self.txouts = gen_return_txouts() + self.extra_args = [["-maxmempool=5", "-spendzeroconfchange=0"]] def run_test(self): + txouts = gen_return_txouts() + relayfee = self.nodes[0].getnetworkinfo()['relayfee'] + txids = [] - utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], 91) + utxos = create_confirmed_utxos(relayfee, self.nodes[0], 91) #create a mempool tx that will be evicted us0 = utxos.pop() inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}] outputs = {self.nodes[0].getnewaddress() : 0.0001} tx = self.nodes[0].createrawtransaction(inputs, outputs) - self.nodes[0].settxfee(self.relayfee) # specifically fund this tx with low fee + self.nodes[0].settxfee(relayfee) # specifically fund this tx with low fee txF = self.nodes[0].fundrawtransaction(tx) self.nodes[0].settxfee(0) # return to automatic fee selection txFS = self.nodes[0].signrawtransaction(txF['hex']) @@ -42,7 +37,7 @@ class MempoolLimitTest(BitcoinTestFramework): base_fee = relayfee*100 for i in range (3): txids.append([]) - txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[30*i:30*i+30], 30, (i+1)*base_fee) + txids[i] = create_lots_of_big_transactions(self.nodes[0], txouts, utxos[30*i:30*i+30], 30, (i+1)*base_fee) # by now, the tx should be evicted, check confirmation state assert(txid not in self.nodes[0].getrawmempool()) diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py index feec8a7fd9..72f04095f4 100755 --- a/test/functional/mempool_packages.py +++ b/test/functional/mempool_packages.py @@ -16,14 +16,7 @@ class MempoolPackagesTest(BitcoinTestFramework): super().__init__() self.num_nodes = 2 self.setup_clean_chain = False - - def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000"])) - self.nodes.append(start_node(1, self.options.tmpdir, ["-maxorphantx=1000", "-limitancestorcount=5"])) - connect_nodes(self.nodes[0], 1) - self.is_network_split = False - self.sync_all() + self.extra_args = [["-maxorphantx=1000"], ["-maxorphantx=1000", "-limitancestorcount=5"]] # Build a transaction that spends parent_txid:vout # Return amount sent diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py new file mode 100755 index 0000000000..7b15476ea2 --- /dev/null +++ b/test/functional/mempool_persist.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +# Copyright (c) 2014-2017 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test mempool persistence. + +By default, bitcoind will dump mempool on shutdown and +then reload it on startup. This can be overridden with +the -persistmempool=0 command line option. + +Test is as follows: + + - start node0, node1 and node2. node1 has -persistmempool=0 + - create 5 transactions on node2 to its own address. Note that these + are not sent to node0 or node1 addresses because we don't want + them to be saved in the wallet. + - check that node0 and node1 have 5 transactions in their mempools + - shutdown all nodes. + - startup node0. Verify that it still has 5 transactions + in its mempool. Shutdown node0. This tests that by default the + mempool is persistent. + - startup node1. Verify that its mempool is empty. Shutdown node1. + This tests that with -persistmempool=0, the mempool is not + dumped to disk when the node is shut down. + - Restart node0 with -persistmempool=0. Verify that its mempool is + empty. Shutdown node0. This tests that with -persistmempool=0, + the mempool is not loaded from disk on start up. + - Restart node0 with -persistmempool. Verify that it has 5 + transactions in its mempool. This tests that -persistmempool=0 + does not overwrite a previously valid mempool stored on disk. + +""" +import time + +from test_framework.mininode import wait_until +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + +class MempoolPersistTest(BitcoinTestFramework): + + def __init__(self): + super().__init__() + # We need 3 nodes for this test. Node1 does not have a persistent mempool. + self.num_nodes = 3 + self.setup_clean_chain = False + self.extra_args = [[], ["-persistmempool=0"], []] + + def run_test(self): + chain_height = self.nodes[0].getblockcount() + assert_equal(chain_height, 200) + + self.log.debug("Mine a single block to get out of IBD") + self.nodes[0].generate(1) + self.sync_all() + + self.log.debug("Send 5 transactions from node2 (to its own address)") + for i in range(5): + self.nodes[2].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("10")) + self.sync_all() + + self.log.debug("Verify that node0 and node1 have 5 transactions in their mempools") + assert_equal(len(self.nodes[0].getrawmempool()), 5) + assert_equal(len(self.nodes[1].getrawmempool()), 5) + + self.log.debug("Stop-start node0 and node1. Verify that node0 has the transactions in its mempool and node1 does not.") + stop_nodes(self.nodes) + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir)) + self.nodes.append(start_node(1, self.options.tmpdir)) + # Give bitcoind a second to reload the mempool + time.sleep(1) + assert wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) + assert_equal(len(self.nodes[1].getrawmempool()), 0) + + self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.") + stop_nodes(self.nodes) + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir, ["-persistmempool=0"])) + # Give bitcoind a second to reload the mempool + time.sleep(1) + assert_equal(len(self.nodes[0].getrawmempool()), 0) + + self.log.debug("Stop-start node0. Verify that it has the transactions in its mempool.") + stop_nodes(self.nodes) + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir)) + assert wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) + +if __name__ == '__main__': + MempoolPersistTest().main() diff --git a/test/functional/mempool_reorg.py b/test/functional/mempool_reorg.py index 812b54ffcb..937bf4bab5 100755 --- a/test/functional/mempool_reorg.py +++ b/test/functional/mempool_reorg.py @@ -17,18 +17,10 @@ class MempoolCoinbaseTest(BitcoinTestFramework): super().__init__() self.num_nodes = 2 self.setup_clean_chain = False + self.extra_args = [["-checkmempool"]] * 2 alert_filename = None # Set by setup_network - def setup_network(self): - args = ["-checkmempool"] - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, args)) - self.nodes.append(start_node(1, self.options.tmpdir, args)) - connect_nodes(self.nodes[1], 0) - self.is_network_split = False - self.sync_all() - def run_test(self): # Start with a 200 block chain assert_equal(self.nodes[0].getblockcount(), 200) diff --git a/test/functional/mempool_resurrect_test.py b/test/functional/mempool_resurrect_test.py index 727892d1f2..a2f6228df9 100755 --- a/test/functional/mempool_resurrect_test.py +++ b/test/functional/mempool_resurrect_test.py @@ -14,13 +14,8 @@ class MempoolCoinbaseTest(BitcoinTestFramework): super().__init__() self.num_nodes = 1 self.setup_clean_chain = False - - def setup_network(self): # Just need one node for this test - args = ["-checkmempool"] - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, args)) - self.is_network_split = False + self.extra_args = [["-checkmempool"]] def run_test(self): node0_address = self.nodes[0].getnewaddress() diff --git a/test/functional/mempool_spendcoinbase.py b/test/functional/mempool_spendcoinbase.py index f562a93d86..277ea45ad5 100755 --- a/test/functional/mempool_spendcoinbase.py +++ b/test/functional/mempool_spendcoinbase.py @@ -22,13 +22,7 @@ class MempoolSpendCoinbaseTest(BitcoinTestFramework): super().__init__() self.num_nodes = 1 self.setup_clean_chain = False - - def setup_network(self): - # Just need one node for this test - args = ["-checkmempool"] - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, args)) - self.is_network_split = False + self.extra_args = [["-checkmempool"]] def run_test(self): chain_height = self.nodes[0].getblockcount() diff --git a/test/functional/merkle_blocks.py b/test/functional/merkle_blocks.py index 5963f2e7b6..06af72ef10 100755 --- a/test/functional/merkle_blocks.py +++ b/test/functional/merkle_blocks.py @@ -13,20 +13,15 @@ class MerkleBlockTest(BitcoinTestFramework): super().__init__() self.setup_clean_chain = True self.num_nodes = 4 + # Nodes 0/1 are "wallet" nodes, Nodes 2/3 are used for testing + self.extra_args = [[], [], [], ["-txindex"]] def setup_network(self): - self.nodes = [] - # Nodes 0/1 are "wallet" nodes - self.nodes.append(start_node(0, self.options.tmpdir)) - self.nodes.append(start_node(1, self.options.tmpdir)) - # Nodes 2/3 are used for testing - self.nodes.append(start_node(2, self.options.tmpdir)) - self.nodes.append(start_node(3, self.options.tmpdir, ["-txindex"])) + self.setup_nodes() connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[0], 2) connect_nodes(self.nodes[0], 3) - self.is_network_split = False self.sync_all() def run_test(self): diff --git a/test/functional/multi_rpc.py b/test/functional/multi_rpc.py index a9701c548b..6ff91a960b 100755 --- a/test/functional/multi_rpc.py +++ b/test/functional/multi_rpc.py @@ -27,9 +27,6 @@ class HTTPBasicsTest (BitcoinTestFramework): f.write(rpcauth+"\n") f.write(rpcauth2+"\n") - def setup_network(self): - self.nodes = self.setup_nodes() - def run_test(self): ################################################## diff --git a/test/functional/net.py b/test/functional/net.py index e9463c7dc7..fb46064441 100755 --- a/test/functional/net.py +++ b/test/functional/net.py @@ -7,15 +7,14 @@ Tests correspond to code in rpc/net.cpp. """ -from decimal import Decimal import time from test_framework.test_framework import BitcoinTestFramework -from test_framework.authproxy import JSONRPCException from test_framework.util import ( assert_equal, - start_nodes, + assert_raises_jsonrpc, connect_nodes_bi, + p2p_port, ) @@ -25,15 +24,42 @@ class NetTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 2 - def setup_network(self): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes_bi(self.nodes, 0, 1) - self.is_network_split = False - self.sync_all() - def run_test(self): + self._test_connection_count() + self._test_getnettotals() + self._test_getnetworkinginfo() + self._test_getaddednodeinfo() + + def _test_connection_count(self): + # connect_nodes_bi connects each node to the other + assert_equal(self.nodes[0].getconnectioncount(), 2) + + def _test_getnettotals(self): + # check that getnettotals totalbytesrecv and totalbytessent + # are consistent with getpeerinfo + peer_info = self.nodes[0].getpeerinfo() + assert_equal(len(peer_info), 2) + net_totals = self.nodes[0].getnettotals() + assert_equal(sum([peer['bytesrecv'] for peer in peer_info]), + net_totals['totalbytesrecv']) + assert_equal(sum([peer['bytessent'] for peer in peer_info]), + net_totals['totalbytessent']) + # test getnettotals and getpeerinfo by doing a ping + # the bytes sent/received should change + # note ping and pong are 32 bytes each + self.nodes[0].ping() + time.sleep(0.1) + peer_info_after_ping = self.nodes[0].getpeerinfo() + net_totals_after_ping = self.nodes[0].getnettotals() + for before, after in zip(peer_info, peer_info_after_ping): + assert_equal(before['bytesrecv_per_msg']['pong'] + 32, after['bytesrecv_per_msg']['pong']) + assert_equal(before['bytessent_per_msg']['ping'] + 32, after['bytessent_per_msg']['ping']) + assert_equal(net_totals['totalbytesrecv'] + 32*2, net_totals_after_ping['totalbytesrecv']) + assert_equal(net_totals['totalbytessent'] + 32*2, net_totals_after_ping['totalbytessent']) + + def _test_getnetworkinginfo(self): assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) - assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) # bilateral connection + assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) self.nodes[0].setnetworkactive(False) assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], False) @@ -49,6 +75,19 @@ class NetTest(BitcoinTestFramework): assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) + def _test_getaddednodeinfo(self): + assert_equal(self.nodes[0].getaddednodeinfo(), []) + # add a node (node2) to node0 + ip_port = "127.0.0.1:{}".format(p2p_port(2)) + self.nodes[0].addnode(ip_port, 'add') + # check that the node has indeed been added + added_nodes = self.nodes[0].getaddednodeinfo(ip_port) + assert_equal(len(added_nodes), 1) + assert_equal(added_nodes[0]['addednode'], ip_port) + # check that a non-existant node returns an error + assert_raises_jsonrpc(-24, "Node has not been added", + self.nodes[0].getaddednodeinfo, '1.1.1.1') + if __name__ == '__main__': NetTest().main() diff --git a/test/functional/nulldummy.py b/test/functional/nulldummy.py index 369c593a90..9717add272 100755 --- a/test/functional/nulldummy.py +++ b/test/functional/nulldummy.py @@ -41,11 +41,7 @@ class NULLDUMMYTest(BitcoinTestFramework): super().__init__() self.num_nodes = 1 self.setup_clean_chain = True - - def setup_network(self): - # Must set the blockversion for this test - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - extra_args=[['-whitelist=127.0.0.1', '-walletprematurewitness']]) + self.extra_args = [['-whitelist=127.0.0.1', '-walletprematurewitness']] def run_test(self): self.address = self.nodes[0].getnewaddress() diff --git a/test/functional/p2p-acceptblock.py b/test/functional/p2p-acceptblock.py index c09945baa6..322cb767db 100755 --- a/test/functional/p2p-acceptblock.py +++ b/test/functional/p2p-acceptblock.py @@ -54,40 +54,6 @@ from test_framework.util import * import time from test_framework.blocktools import create_block, create_coinbase -# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending -# p2p messages to a node, generating the messages in the main testing logic. -class TestNode(NodeConnCB): - def __init__(self): - super().__init__() - self.connection = None - self.ping_counter = 1 - self.last_pong = msg_pong() - - def add_connection(self, conn): - self.connection = conn - - # Track the last getdata message we receive (used in the test) - def on_getdata(self, conn, message): - self.last_getdata = message - - # Spin until verack message is received from the node. - # We use this to signal that our test can begin. This - # is called from the testing thread, so it needs to acquire - # the global lock. - def wait_for_verack(self): - while True: - with mininode_lock: - if self.verack_received: - return - time.sleep(0.05) - - # Wrapper for the NodeConn's send_message function - def send_message(self, message): - self.connection.send_message(message) - - def on_pong(self, conn, message): - self.last_pong = message - class AcceptBlockTest(BitcoinTestFramework): def add_options(self, parser): parser.add_option("--testbinary", dest="testbinary", @@ -98,22 +64,18 @@ class AcceptBlockTest(BitcoinTestFramework): super().__init__() self.setup_clean_chain = True self.num_nodes = 2 + self.extra_args = [[], ["-whitelist=127.0.0.1"]] def setup_network(self): # Node0 will be used to test behavior of processing unrequested blocks # from peers which are not whitelisted, while Node1 will be used for # the whitelisted case. - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, - binary=self.options.testbinary)) - self.nodes.append(start_node(1, self.options.tmpdir, - ["-whitelist=127.0.0.1"], - binary=self.options.testbinary)) + self.setup_nodes() def run_test(self): # Setup the p2p connections and start up the network thread. - test_node = TestNode() # connects to node0 (not whitelisted) - white_node = TestNode() # connects to node1 (whitelisted) + test_node = NodeConnCB() # connects to node0 (not whitelisted) + white_node = NodeConnCB() # connects to node1 (whitelisted) connections = [] connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_node)) @@ -238,12 +200,12 @@ class AcceptBlockTest(BitcoinTestFramework): # triggers a getdata on block 2 (it should if block 2 is missing). with mininode_lock: # Clear state so we can check the getdata request - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) test_node.send_message(msg_inv([CInv(2, blocks_h3[0].sha256)])) test_node.sync_with_ping() with mininode_lock: - getdata = test_node.last_getdata + getdata = test_node.last_message["getdata"] # Check that the getdata includes the right block assert_equal(getdata.inv[0].hash, blocks_h2f[0].sha256) diff --git a/test/functional/p2p-compactblocks.py b/test/functional/p2p-compactblocks.py index bf8d113767..9b302120ac 100755 --- a/test/functional/p2p-compactblocks.py +++ b/test/functional/p2p-compactblocks.py @@ -19,64 +19,31 @@ class TestNode(NodeConnCB): def __init__(self): super().__init__() self.last_sendcmpct = [] - self.last_headers = None - self.last_inv = None - self.last_cmpctblock = None self.block_announced = False - self.last_getdata = None - self.last_getheaders = None - self.last_getblocktxn = None - self.last_block = None - self.last_blocktxn = None # Store the hashes of blocks we've seen announced. # This is for synchronizing the p2p message traffic, # so we can eg wait until a particular block is announced. - self.set_announced_blockhashes = set() - self.connected = False - - def on_open(self, conn): - self.connected = True - - def on_close(self, conn): - self.connected = False + self.announced_blockhashes = set() def on_sendcmpct(self, conn, message): self.last_sendcmpct.append(message) - def on_block(self, conn, message): - self.last_block = message - def on_cmpctblock(self, conn, message): - self.last_cmpctblock = message self.block_announced = True - self.last_cmpctblock.header_and_shortids.header.calc_sha256() - self.set_announced_blockhashes.add(self.last_cmpctblock.header_and_shortids.header.sha256) + self.last_message["cmpctblock"].header_and_shortids.header.calc_sha256() + self.announced_blockhashes.add(self.last_message["cmpctblock"].header_and_shortids.header.sha256) def on_headers(self, conn, message): - self.last_headers = message self.block_announced = True - for x in self.last_headers.headers: + for x in self.last_message["headers"].headers: x.calc_sha256() - self.set_announced_blockhashes.add(x.sha256) + self.announced_blockhashes.add(x.sha256) def on_inv(self, conn, message): - self.last_inv = message - for x in self.last_inv.inv: + for x in self.last_message["inv"].inv: if x.type == 2: self.block_announced = True - self.set_announced_blockhashes.add(x.hash) - - def on_getdata(self, conn, message): - self.last_getdata = message - - def on_getheaders(self, conn, message): - self.last_getheaders = message - - def on_getblocktxn(self, conn, message): - self.last_getblocktxn = message - - def on_blocktxn(self, conn, message): - self.last_blocktxn = message + self.announced_blockhashes.add(x.hash) # Requires caller to hold mininode_lock def received_block_announcement(self): @@ -85,9 +52,9 @@ class TestNode(NodeConnCB): def clear_block_announcement(self): with mininode_lock: self.block_announced = False - self.last_inv = None - self.last_headers = None - self.last_cmpctblock = None + self.last_message.pop("inv", None) + self.last_message.pop("headers", None) + self.last_message.pop("cmpctblock", None) def get_headers(self, locator, hashstop): msg = msg_getheaders() @@ -103,15 +70,14 @@ class TestNode(NodeConnCB): def request_headers_and_sync(self, locator, hashstop=0): self.clear_block_announcement() self.get_headers(locator, hashstop) - assert(wait_until(self.received_block_announcement, timeout=30)) - assert(self.received_block_announcement()) + assert wait_until(self.received_block_announcement, timeout=30) self.clear_block_announcement() # Block until a block announcement for a particular block hash is # received. def wait_for_block_announcement(self, block_hash, timeout=30): def received_hash(): - return (block_hash in self.set_announced_blockhashes) + return (block_hash in self.announced_blockhashes) return wait_until(received_hash, timeout=timeout) def send_await_disconnect(self, message, timeout=30): @@ -132,17 +98,9 @@ class CompactBlocksTest(BitcoinTestFramework): self.setup_clean_chain = True # Node0 = pre-segwit, node1 = segwit-aware self.num_nodes = 2 + self.extra_args = [["-bip9params=segwit:0:0"], ["-txindex"]] self.utxos = [] - def setup_network(self): - self.nodes = [] - - # Start up node0 to be a version 1, pre-segwit node. - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - [["-bip9params=segwit:0:0"], - ["-txindex"]]) - connect_nodes(self.nodes[0], 1) - def build_block_on_tip(self, node, segwit=False): height = node.getblockcount() tip = node.getbestblockhash() @@ -214,14 +172,14 @@ class CompactBlocksTest(BitcoinTestFramework): with mininode_lock: assert predicate(peer), ( "block_hash={!r}, cmpctblock={!r}, inv={!r}".format( - block_hash, peer.last_cmpctblock, peer.last_inv)) + block_hash, peer.last_message.get("cmpctblock", None), peer.last_message.get("inv", None))) # We shouldn't get any block announcements via cmpctblock yet. - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message) # Try one more time, this time after requesting headers. test_node.request_headers_and_sync(locator=[tip]) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None and p.last_inv is not None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message and "inv" in p.last_message) # Test a few ways of using sendcmpct that should NOT # result in compact block announcements. @@ -233,7 +191,7 @@ class CompactBlocksTest(BitcoinTestFramework): sendcmpct.version = preferred_version+1 sendcmpct.announce = True test_node.send_and_ping(sendcmpct) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message) # Headers sync before next test. test_node.request_headers_and_sync(locator=[tip]) @@ -242,7 +200,7 @@ class CompactBlocksTest(BitcoinTestFramework): sendcmpct.version = preferred_version sendcmpct.announce = False test_node.send_and_ping(sendcmpct) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message) # Headers sync before next test. test_node.request_headers_and_sync(locator=[tip]) @@ -251,26 +209,26 @@ class CompactBlocksTest(BitcoinTestFramework): sendcmpct.version = preferred_version sendcmpct.announce = True test_node.send_and_ping(sendcmpct) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message) # Try one more time (no headers sync should be needed!) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message) # Try one more time, after turning on sendheaders test_node.send_and_ping(msg_sendheaders()) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message) # Try one more time, after sending a version-1, announce=false message. sendcmpct.version = preferred_version-1 sendcmpct.announce = False test_node.send_and_ping(sendcmpct) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message) # Now turn off announcements sendcmpct.version = preferred_version sendcmpct.announce = False test_node.send_and_ping(sendcmpct) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None and p.last_headers is not None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message and "headers" in p.last_message) if old_node is not None: # Verify that a peer using an older protocol version can receive @@ -280,7 +238,7 @@ class CompactBlocksTest(BitcoinTestFramework): old_node.send_and_ping(sendcmpct) # Header sync old_node.request_headers_and_sync(locator=[tip]) - check_announcement_of_new_block(node, old_node, lambda p: p.last_cmpctblock is not None) + check_announcement_of_new_block(node, old_node, lambda p: "cmpctblock" in p.last_message) # This test actually causes bitcoind to (reasonably!) disconnect us, so do this last. def test_invalid_cmpctblock_message(self): @@ -345,9 +303,9 @@ class CompactBlocksTest(BitcoinTestFramework): # Now fetch and check the compact block header_and_shortids = None with mininode_lock: - assert(test_node.last_cmpctblock is not None) + assert("cmpctblock" in test_node.last_message) # Convert the on-the-wire representation to absolute indexes - header_and_shortids = HeaderAndShortIDs(test_node.last_cmpctblock.header_and_shortids) + header_and_shortids = HeaderAndShortIDs(test_node.last_message["cmpctblock"].header_and_shortids) self.check_compactblock_construction_from_block(version, header_and_shortids, block_hash, block) # Now fetch the compact block using a normal non-announce getdata @@ -362,9 +320,9 @@ class CompactBlocksTest(BitcoinTestFramework): # Now fetch and check the compact block header_and_shortids = None with mininode_lock: - assert(test_node.last_cmpctblock is not None) + assert("cmpctblock" in test_node.last_message) # Convert the on-the-wire representation to absolute indexes - header_and_shortids = HeaderAndShortIDs(test_node.last_cmpctblock.header_and_shortids) + header_and_shortids = HeaderAndShortIDs(test_node.last_message["cmpctblock"].header_and_shortids) self.check_compactblock_construction_from_block(version, header_and_shortids, block_hash, block) def check_compactblock_construction_from_block(self, version, header_and_shortids, block_hash, block): @@ -424,20 +382,20 @@ class CompactBlocksTest(BitcoinTestFramework): for announce in ["inv", "header"]: block = self.build_block_on_tip(node, segwit=segwit) with mininode_lock: - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) if announce == "inv": test_node.send_message(msg_inv([CInv(2, block.sha256)])) - success = wait_until(lambda: test_node.last_getheaders is not None, timeout=30) + success = wait_until(lambda: "getheaders" in test_node.last_message, timeout=30) assert(success) test_node.send_header_for_blocks([block]) else: test_node.send_header_for_blocks([block]) - success = wait_until(lambda: test_node.last_getdata is not None, timeout=30) + success = wait_until(lambda: "getdata" in test_node.last_message, timeout=30) assert(success) - assert_equal(len(test_node.last_getdata.inv), 1) - assert_equal(test_node.last_getdata.inv[0].type, 4) - assert_equal(test_node.last_getdata.inv[0].hash, block.sha256) + assert_equal(len(test_node.last_message["getdata"].inv), 1) + assert_equal(test_node.last_message["getdata"].inv[0].type, 4) + assert_equal(test_node.last_message["getdata"].inv[0].hash, block.sha256) # Send back a compactblock message that omits the coinbase comp_block = HeaderAndShortIDs() @@ -453,8 +411,8 @@ class CompactBlocksTest(BitcoinTestFramework): assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock) # Expect a getblocktxn message. with mininode_lock: - assert(test_node.last_getblocktxn is not None) - absolute_indexes = test_node.last_getblocktxn.block_txn_request.to_absolute() + assert("getblocktxn" in test_node.last_message) + absolute_indexes = test_node.last_message["getblocktxn"].block_txn_request.to_absolute() assert_equal(absolute_indexes, [0]) # should be a coinbase request # Send the coinbase, and verify that the tip advances. @@ -493,8 +451,8 @@ class CompactBlocksTest(BitcoinTestFramework): msg = msg_cmpctblock(compact_block.to_p2p()) peer.send_and_ping(msg) with mininode_lock: - assert(peer.last_getblocktxn is not None) - absolute_indexes = peer.last_getblocktxn.block_txn_request.to_absolute() + assert("getblocktxn" in peer.last_message) + absolute_indexes = peer.last_message["getblocktxn"].block_txn_request.to_absolute() assert_equal(absolute_indexes, expected_result) def test_tip_after_message(node, peer, msg, tip): @@ -558,14 +516,14 @@ class CompactBlocksTest(BitcoinTestFramework): # Clear out last request. with mininode_lock: - test_node.last_getblocktxn = None + test_node.last_message.pop("getblocktxn", None) # Send compact block comp_block.initialize_from_block(block, prefill_list=[0], use_witness=with_witness) test_tip_after_message(node, test_node, msg_cmpctblock(comp_block.to_p2p()), block.sha256) with mininode_lock: # Shouldn't have gotten a request for any transaction - assert(test_node.last_getblocktxn is None) + assert("getblocktxn" not in test_node.last_message) # Incorrectly responding to a getblocktxn shouldn't cause the block to be # permanently failed. @@ -591,8 +549,8 @@ class CompactBlocksTest(BitcoinTestFramework): test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) absolute_indexes = [] with mininode_lock: - assert(test_node.last_getblocktxn is not None) - absolute_indexes = test_node.last_getblocktxn.block_txn_request.to_absolute() + assert("getblocktxn" in test_node.last_message) + absolute_indexes = test_node.last_message["getblocktxn"].block_txn_request.to_absolute() assert_equal(absolute_indexes, [6, 7, 8, 9, 10]) # Now give an incorrect response. @@ -613,11 +571,11 @@ class CompactBlocksTest(BitcoinTestFramework): assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock) # We should receive a getdata request - success = wait_until(lambda: test_node.last_getdata is not None, timeout=10) + success = wait_until(lambda: "getdata" in test_node.last_message, timeout=10) assert(success) - assert_equal(len(test_node.last_getdata.inv), 1) - assert(test_node.last_getdata.inv[0].type == 2 or test_node.last_getdata.inv[0].type == 2|MSG_WITNESS_FLAG) - assert_equal(test_node.last_getdata.inv[0].hash, block.sha256) + assert_equal(len(test_node.last_message["getdata"].inv), 1) + assert(test_node.last_message["getdata"].inv[0].type == 2 or test_node.last_message["getdata"].inv[0].type == 2|MSG_WITNESS_FLAG) + assert_equal(test_node.last_message["getdata"].inv[0].hash, block.sha256) # Deliver the block if version==2: @@ -641,15 +599,15 @@ class CompactBlocksTest(BitcoinTestFramework): num_to_request = random.randint(1, len(block.vtx)) msg.block_txn_request.from_absolute(sorted(random.sample(range(len(block.vtx)), num_to_request))) test_node.send_message(msg) - success = wait_until(lambda: test_node.last_blocktxn is not None, timeout=10) + success = wait_until(lambda: "blocktxn" in test_node.last_message, timeout=10) assert(success) [tx.calc_sha256() for tx in block.vtx] with mininode_lock: - assert_equal(test_node.last_blocktxn.block_transactions.blockhash, int(block_hash, 16)) + assert_equal(test_node.last_message["blocktxn"].block_transactions.blockhash, int(block_hash, 16)) all_indices = msg.block_txn_request.to_absolute() for index in all_indices: - tx = test_node.last_blocktxn.block_transactions.transactions.pop(0) + tx = test_node.last_message["blocktxn"].block_transactions.transactions.pop(0) tx.calc_sha256() assert_equal(tx.sha256, block.vtx[index].sha256) if version == 1: @@ -658,7 +616,7 @@ class CompactBlocksTest(BitcoinTestFramework): else: # Check that the witness matches assert_equal(tx.calc_sha256(True), block.vtx[index].calc_sha256(True)) - test_node.last_blocktxn = None + test_node.last_message.pop("blocktxn", None) current_height -= 1 # Next request should send a full block response, as we're past the @@ -666,13 +624,13 @@ class CompactBlocksTest(BitcoinTestFramework): block_hash = node.getblockhash(current_height) msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), [0]) with mininode_lock: - test_node.last_block = None - test_node.last_blocktxn = None + test_node.last_message.pop("block", None) + test_node.last_message.pop("blocktxn", None) test_node.send_and_ping(msg) with mininode_lock: - test_node.last_block.block.calc_sha256() - assert_equal(test_node.last_block.block.sha256, int(block_hash, 16)) - assert_equal(test_node.last_blocktxn, None) + test_node.last_message["block"].block.calc_sha256() + assert_equal(test_node.last_message["block"].block.sha256, int(block_hash, 16)) + assert "blocktxn" not in test_node.last_message def test_compactblocks_not_at_tip(self, node, test_node): # Test that requesting old compactblocks doesn't work. @@ -685,7 +643,7 @@ class CompactBlocksTest(BitcoinTestFramework): test_node.clear_block_announcement() test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))])) - success = wait_until(lambda: test_node.last_cmpctblock is not None, timeout=30) + success = wait_until(lambda: "cmpctblock" in test_node.last_message, timeout=30) assert(success) test_node.clear_block_announcement() @@ -693,13 +651,13 @@ class CompactBlocksTest(BitcoinTestFramework): wait_until(test_node.received_block_announcement, timeout=30) test_node.clear_block_announcement() with mininode_lock: - test_node.last_block = None + test_node.last_message.pop("block", None) test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))])) - success = wait_until(lambda: test_node.last_block is not None, timeout=30) + success = wait_until(lambda: "block" in test_node.last_message, timeout=30) assert(success) with mininode_lock: - test_node.last_block.block.calc_sha256() - assert_equal(test_node.last_block.block.sha256, int(new_blocks[0], 16)) + test_node.last_message["block"].block.calc_sha256() + assert_equal(test_node.last_message["block"].block.sha256, int(new_blocks[0], 16)) # Generate an old compactblock, and verify that it's not accepted. cur_height = node.getblockcount() @@ -726,10 +684,10 @@ class CompactBlocksTest(BitcoinTestFramework): msg = msg_getblocktxn() msg.block_txn_request = BlockTransactionsRequest(block.sha256, [0]) with mininode_lock: - test_node.last_blocktxn = None + test_node.last_message.pop("blocktxn", None) test_node.send_and_ping(msg) with mininode_lock: - assert(test_node.last_blocktxn is None) + assert "blocktxn" not in test_node.last_message def activate_segwit(self, node): node.generate(144*3) @@ -750,9 +708,9 @@ class CompactBlocksTest(BitcoinTestFramework): wait_until(lambda: l.received_block_announcement(), timeout=30) with mininode_lock: for l in listeners: - assert(l.last_cmpctblock is not None) - l.last_cmpctblock.header_and_shortids.header.calc_sha256() - assert_equal(l.last_cmpctblock.header_and_shortids.header.sha256, block.sha256) + assert "cmpctblock" in l.last_message + l.last_message["cmpctblock"].header_and_shortids.header.calc_sha256() + assert_equal(l.last_message["cmpctblock"].header_and_shortids.header.sha256, block.sha256) # Test that we don't get disconnected if we relay a compact block with valid header, # but invalid transactions. @@ -804,7 +762,7 @@ class CompactBlocksTest(BitcoinTestFramework): msg = msg_cmpctblock(cmpct_block.to_p2p()) peer.send_and_ping(msg) with mininode_lock: - assert(peer.last_getblocktxn is not None) + assert "getblocktxn" in peer.last_message return block, cmpct_block block, cmpct_block = announce_cmpct_block(node, stalling_peer) diff --git a/test/functional/p2p-feefilter.py b/test/functional/p2p-feefilter.py index 12539be950..dbccb633a5 100755 --- a/test/functional/p2p-feefilter.py +++ b/test/functional/p2p-feefilter.py @@ -22,8 +22,6 @@ def allInvsMatch(invsExpected, testnode): 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(NodeConnCB): def __init__(self): super().__init__() @@ -38,10 +36,6 @@ class TestNode(NodeConnCB): with mininode_lock: self.txinvs = [] - def send_filter(self, feerate): - self.send_message(msg_feefilter(feerate)) - self.sync_with_ping() - class FeeFilterTest(BitcoinTestFramework): def __init__(self): @@ -49,14 +43,6 @@ class FeeFilterTest(BitcoinTestFramework): self.num_nodes = 2 self.setup_clean_chain = False - 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)) - self.nodes.append(start_node(1, self.options.tmpdir)) - connect_nodes(self.nodes[0], 1) - def run_test(self): node1 = self.nodes[1] node0 = self.nodes[0] @@ -78,7 +64,7 @@ class FeeFilterTest(BitcoinTestFramework): test_node.clear_invs() # Set a filter of 15 sat/byte - test_node.send_filter(15000) + test_node.send_and_ping(msg_feefilter(15000)) # Test that txs are still being received (paying 20 sat/byte) txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] @@ -103,7 +89,7 @@ class FeeFilterTest(BitcoinTestFramework): test_node.clear_invs() # Remove fee filter and check that txs are received again - test_node.send_filter(0) + test_node.send_and_ping(msg_feefilter(0)) txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] assert(allInvsMatch(txids, test_node)) test_node.clear_invs() diff --git a/test/functional/p2p-leaktests.py b/test/functional/p2p-leaktests.py index 5853ec86f0..33b57ef33d 100755 --- a/test/functional/p2p-leaktests.py +++ b/test/functional/p2p-leaktests.py @@ -20,15 +20,8 @@ banscore = 10 class CLazyNode(NodeConnCB): def __init__(self): super().__init__() - self.connection = None self.unexpected_msg = False - self.connected = False - - def add_connection(self, conn): - self.connection = conn - - def send_message(self, message): - self.connection.send_message(message) + self.ever_connected = False def bad_message(self, message): self.unexpected_msg = True @@ -36,6 +29,7 @@ class CLazyNode(NodeConnCB): def on_open(self, conn): self.connected = True + self.ever_connected = True def on_version(self, conn, message): self.bad_message(message) def on_verack(self, conn, message): self.bad_message(message) @@ -63,9 +57,6 @@ class CLazyNode(NodeConnCB): # Node that never sends a version. We'll use this to send a bunch of messages # anyway, and eventually get disconnected. class CNodeNoVersionBan(CLazyNode): - def __init__(self): - super().__init__() - # send a bunch of veracks without sending a message. This should get us disconnected. # NOTE: implementation-specific check here. Remove if bitcoind ban behavior changes def on_open(self, conn): @@ -101,10 +92,7 @@ class P2PLeakTest(BitcoinTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 - def setup_network(self): - extra_args = [['-banscore='+str(banscore)] - for i in range(self.num_nodes)] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + self.extra_args = [['-banscore='+str(banscore)]] def run_test(self): no_version_bannode = CNodeNoVersionBan() @@ -121,7 +109,9 @@ class P2PLeakTest(BitcoinTestFramework): NetworkThread().start() # Start up network handling in another thread - assert(wait_until(lambda: no_version_bannode.connected and no_version_idlenode.connected and no_verack_idlenode.version_received, timeout=10)) + assert wait_until(lambda: no_version_bannode.ever_connected, timeout=10) + assert wait_until(lambda: no_version_idlenode.ever_connected, timeout=10) + assert wait_until(lambda: no_verack_idlenode.version_received, timeout=10) # Mine a block and make sure that it's not sent to the connected nodes self.nodes[0].generate(1) @@ -130,7 +120,7 @@ class P2PLeakTest(BitcoinTestFramework): time.sleep(5) #This node should have been banned - assert(no_version_bannode.connection.state == "closed") + assert not no_version_bannode.connected [conn.disconnect_node() for conn in connections] diff --git a/test/functional/p2p-mempool.py b/test/functional/p2p-mempool.py index 5064ce74aa..34ef249eea 100755 --- a/test/functional/p2p-mempool.py +++ b/test/functional/p2p-mempool.py @@ -12,82 +12,24 @@ from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -class TestNode(NodeConnCB): - def __init__(self): - super().__init__() - self.connection = None - self.ping_counter = 1 - self.last_pong = msg_pong() - self.block_receive_map = {} - - def add_connection(self, conn): - self.connection = conn - self.peer_disconnected = False - - def on_inv(self, conn, message): - pass - - # Track the last getdata message we receive (used in the test) - def on_getdata(self, conn, message): - self.last_getdata = message - - def on_block(self, conn, message): - message.block.calc_sha256() - try: - self.block_receive_map[message.block.sha256] += 1 - except KeyError as e: - self.block_receive_map[message.block.sha256] = 1 - - # Spin until verack message is received from the node. - # We use this to signal that our test can begin. This - # is called from the testing thread, so it needs to acquire - # the global lock. - def wait_for_verack(self): - def veracked(): - return self.verack_received - return wait_until(veracked, timeout=10) - - def wait_for_disconnect(self): - def disconnected(): - return self.peer_disconnected - return wait_until(disconnected, timeout=10) - - # Wrapper for the NodeConn's send_message function - def send_message(self, message): - self.connection.send_message(message) - - def on_pong(self, conn, message): - self.last_pong = message - - def on_close(self, conn): - self.peer_disconnected = True - - def send_mempool(self): - self.lastInv = [] - self.send_message(msg_mempool()) - class P2PMempoolTests(BitcoinTestFramework): def __init__(self): super().__init__() self.setup_clean_chain = True - self.num_nodes = 2 - - def setup_network(self): - # Start a node with maxuploadtarget of 200 MB (/24h) - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-peerbloomfilters=0"])) + self.num_nodes = 1 + self.extra_args = [["-peerbloomfilters=0"]] def run_test(self): #connect a mininode - aTestNode = TestNode() + aTestNode = NodeConnCB() node = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], aTestNode) aTestNode.add_connection(node) NetworkThread().start() aTestNode.wait_for_verack() #request mempool - aTestNode.send_mempool() + aTestNode.send_message(msg_mempool()) aTestNode.wait_for_disconnect() #mininode must be disconnected at this point diff --git a/test/functional/p2p-segwit.py b/test/functional/p2p-segwit.py index cd7b788eb4..24d4d37c42 100755 --- a/test/functional/p2p-segwit.py +++ b/test/functional/p2p-segwit.py @@ -8,7 +8,7 @@ from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from test_framework.script import * -from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment, WITNESS_COMMITMENT_HEADER +from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment, get_witness_script, WITNESS_COMMITMENT_HEADER from test_framework.key import CECKey, CPubKey import time import random @@ -35,79 +35,22 @@ def get_virtual_size(witness_block): class TestNode(NodeConnCB): def __init__(self): super().__init__() - self.connection = None - self.ping_counter = 1 - self.last_pong = msg_pong(0) - self.sleep_time = 0.05 self.getdataset = set() - self.last_reject = None - - def add_connection(self, conn): - self.connection = conn - - # Wrapper for the NodeConn's send_message function - def send_message(self, message): - self.connection.send_message(message) - - def on_inv(self, conn, message): - self.last_inv = message - - def on_block(self, conn, message): - self.last_block = message.block - self.last_block.calc_sha256() def on_getdata(self, conn, message): for inv in message.inv: self.getdataset.add(inv.hash) - self.last_getdata = message - - def on_getheaders(self, conn, message): - self.last_getheaders = message - - def on_pong(self, conn, message): - self.last_pong = message - - def on_reject(self, conn, message): - self.last_reject = message - - # Syncing helpers - def sync(self, test_function, timeout=60): - while timeout > 0: - with mininode_lock: - if test_function(): - return - time.sleep(self.sleep_time) - timeout -= self.sleep_time - raise AssertionError("Sync failed to complete") - - def wait_for_block(self, blockhash, timeout=60): - test_function = lambda: self.last_block != None and self.last_block.sha256 == blockhash - self.sync(test_function, timeout) - return - - def wait_for_getdata(self, timeout=60): - test_function = lambda: self.last_getdata != None - self.sync(test_function, timeout) - - def wait_for_getheaders(self, timeout=60): - test_function = lambda: self.last_getheaders != None - self.sync(test_function, timeout) - - def wait_for_inv(self, expected_inv, timeout=60): - test_function = lambda: self.last_inv != expected_inv - self.sync(test_function, timeout) def announce_tx_and_wait_for_getdata(self, tx, timeout=60): with mininode_lock: - self.last_getdata = None + self.last_message.pop("getdata", None) self.send_message(msg_inv(inv=[CInv(1, tx.sha256)])) self.wait_for_getdata(timeout) - return def announce_block_and_wait_for_getdata(self, block, use_header, timeout=60): with mininode_lock: - self.last_getdata = None - self.last_getheaders = None + self.last_message.pop("getdata", None) + self.last_message.pop("getheaders", None) msg = msg_headers() msg.headers = [ CBlockHeader(block) ] if use_header: @@ -117,36 +60,25 @@ class TestNode(NodeConnCB): self.wait_for_getheaders() self.send_message(msg) self.wait_for_getdata() - return - - def announce_block(self, block, use_header): - with mininode_lock: - self.last_getdata = None - if use_header: - msg = msg_headers() - msg.headers = [ CBlockHeader(block) ] - self.send_message(msg) - else: - self.send_message(msg_inv(inv=[CInv(2, block.sha256)])) def request_block(self, blockhash, inv_type, timeout=60): with mininode_lock: - self.last_block = None + self.last_message.pop("block", None) self.send_message(msg_getdata(inv=[CInv(inv_type, blockhash)])) self.wait_for_block(blockhash, timeout) - return self.last_block + return self.last_message["block"].block def test_transaction_acceptance(self, tx, with_witness, accepted, reason=None): tx_message = msg_tx(tx) if with_witness: tx_message = msg_witness_tx(tx) self.send_message(tx_message) - self.sync_with_ping(60) + self.sync_with_ping() assert_equal(tx.hash in self.connection.rpc.getrawmempool(), accepted) if (reason != None and not accepted): # Check the rejection reason as well. with mininode_lock: - assert_equal(self.last_reject.reason, reason) + assert_equal(self.last_message["reject"].reason, reason) # Test whether a witness block had the correct effect on the tip def test_witness_block(self, block, accepted, with_witness=True): @@ -154,10 +86,9 @@ class TestNode(NodeConnCB): self.send_message(msg_witness_block(block)) else: self.send_message(msg_block(block)) - self.sync_with_ping(60) + self.sync_with_ping() assert_equal(self.connection.rpc.getbestblockhash() == block.hash, accepted) - # Used to keep track of anyone-can-spend outputs that we can use in the tests class UTXO(object): def __init__(self, sha256, n, nValue): @@ -183,17 +114,13 @@ class SegWitTest(BitcoinTestFramework): super().__init__() self.setup_clean_chain = True self.num_nodes = 3 + self.extra_args = [["-whitelist=127.0.0.1"], ["-whitelist=127.0.0.1", "-acceptnonstdtxn=0"], ["-whitelist=127.0.0.1", "-bip9params=segwit:0:0"]] def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-whitelist=127.0.0.1"])) - # Start a node for testing IsStandard rules. - self.nodes.append(start_node(1, self.options.tmpdir, ["-whitelist=127.0.0.1", "-acceptnonstdtxn=0"])) + self.setup_nodes() connect_nodes(self.nodes[0], 1) - - # Disable segwit's bip9 parameter to simulate upgrading after activation. - self.nodes.append(start_node(2, self.options.tmpdir, ["-whitelist=127.0.0.1", "-bip9params=segwit:0:0"])) connect_nodes(self.nodes[0], 2) + self.sync_all() ''' Helpers ''' # Build a block on top of node0's tip. @@ -228,7 +155,7 @@ class SegWitTest(BitcoinTestFramework): block = self.build_next_block(nVersion=1) block.solve() self.test_node.send_message(msg_block(block)) - self.test_node.sync_with_ping(60) # make sure the block was processed + self.test_node.sync_with_ping() # make sure the block was processed txid = block.vtx[0].sha256 self.nodes[0].generate(99) # let the block mature @@ -244,7 +171,7 @@ class SegWitTest(BitcoinTestFramework): assert_equal(msg_tx(tx).serialize(), msg_witness_tx(tx).serialize()) self.test_node.send_message(msg_witness_tx(tx)) - self.test_node.sync_with_ping(60) # make sure the tx was processed + self.test_node.sync_with_ping() # make sure the tx was processed assert(tx.hash in self.nodes[0].getrawmempool()) # Save this transaction for later self.utxo.append(UTXO(tx.sha256, 0, 49*100000000)) @@ -279,12 +206,12 @@ class SegWitTest(BitcoinTestFramework): # TODO: fix synchronization so we can test reject reason # Right now, bitcoind delays sending reject messages for blocks # until the future, making synchronization here difficult. - #assert_equal(self.test_node.last_reject.reason, "unexpected-witness") + #assert_equal(self.test_node.last_message["reject"].reason, "unexpected-witness") # But it should not be permanently marked bad... # Resend without witness information. self.test_node.send_message(msg_block(block)) - self.test_node.sync_with_ping(60) + self.test_node.sync_with_ping() assert_equal(self.nodes[0].getbestblockhash(), block.hash) sync_blocks(self.nodes) @@ -893,7 +820,7 @@ class SegWitTest(BitcoinTestFramework): # Verify that if a peer doesn't set nServices to include NODE_WITNESS, # the getdata is just for the non-witness portion. self.old_node.announce_tx_and_wait_for_getdata(tx) - assert(self.old_node.last_getdata.inv[0].type == 1) + assert(self.old_node.last_message["getdata"].inv[0].type == 1) # Since we haven't delivered the tx yet, inv'ing the same tx from # a witness transaction ought not result in a getdata. @@ -989,9 +916,9 @@ class SegWitTest(BitcoinTestFramework): tx3.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ] # Also check that old_node gets a tx announcement, even though this is # a witness transaction. - self.old_node.wait_for_inv(CInv(1, tx2.sha256)) # wait until tx2 was inv'ed + self.old_node.wait_for_inv([CInv(1, tx2.sha256)]) # wait until tx2 was inv'ed self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=True) - self.old_node.wait_for_inv(CInv(1, tx3.sha256)) + self.old_node.wait_for_inv([CInv(1, tx3.sha256)]) # Test that getrawtransaction returns correct witness information # hash, size, vsize @@ -1028,20 +955,20 @@ class SegWitTest(BitcoinTestFramework): block1.solve() self.test_node.announce_block_and_wait_for_getdata(block1, use_header=False) - assert(self.test_node.last_getdata.inv[0].type == blocktype) + assert(self.test_node.last_message["getdata"].inv[0].type == blocktype) self.test_node.test_witness_block(block1, True) block2 = self.build_next_block(nVersion=4) block2.solve() self.test_node.announce_block_and_wait_for_getdata(block2, use_header=True) - assert(self.test_node.last_getdata.inv[0].type == blocktype) + assert(self.test_node.last_message["getdata"].inv[0].type == blocktype) self.test_node.test_witness_block(block2, True) block3 = self.build_next_block(nVersion=(VB_TOP_BITS | (1<<15))) block3.solve() self.test_node.announce_block_and_wait_for_getdata(block3, use_header=True) - assert(self.test_node.last_getdata.inv[0].type == blocktype) + assert(self.test_node.last_message["getdata"].inv[0].type == blocktype) self.test_node.test_witness_block(block3, True) # Check that we can getdata for witness blocks or regular blocks, @@ -1092,13 +1019,18 @@ class SegWitTest(BitcoinTestFramework): block4 = self.build_next_block(nVersion=4) block4.solve() self.old_node.getdataset = set() + # Blocks can be requested via direct-fetch (immediately upon processing the announcement) # or via parallel download (with an indeterminate delay from processing the announcement) # so to test that a block is NOT requested, we could guess a time period to sleep for, # and then check. We can avoid the sleep() by taking advantage of transaction getdata's # being processed after block getdata's, and announce a transaction as well, # and then check to see if that particular getdata has been received. - self.old_node.announce_block(block4, use_header=False) + # Since 0.14, inv's will only be responded to with a getheaders, so send a header + # to announce this block. + msg = msg_headers() + msg.headers = [ CBlockHeader(block4) ] + self.old_node.send_message(msg) self.old_node.announce_tx_and_wait_for_getdata(block4.vtx[0]) assert(block4.sha256 not in self.old_node.getdataset) @@ -1250,9 +1182,9 @@ class SegWitTest(BitcoinTestFramework): # Spending a higher version witness output is not allowed by policy, # even with fRequireStandard=false. self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=False) - self.test_node.sync_with_ping(60) + self.test_node.sync_with_ping() with mininode_lock: - assert(b"reserved for soft-fork upgrades" in self.test_node.last_reject.reason) + assert(b"reserved for soft-fork upgrades" in self.test_node.last_message["reject"].reason) # Building a block with the transaction must be valid, however. block = self.build_next_block() @@ -1380,7 +1312,7 @@ class SegWitTest(BitcoinTestFramework): for i in range(NUM_TESTS): # Ping regularly to keep the connection alive if (not i % 100): - self.test_node.sync_with_ping(60) + self.test_node.sync_with_ping() # Choose random number of inputs to use. num_inputs = random.randint(1, 10) # Create a slight bias for producing more utxos @@ -1721,15 +1653,10 @@ class SegWitTest(BitcoinTestFramework): assert('default_witness_commitment' in gbt_results) witness_commitment = gbt_results['default_witness_commitment'] - # TODO: this duplicates some code from blocktools.py, would be nice - # to refactor. # Check that default_witness_commitment is present. - block = CBlock() - witness_root = block.get_merkle_root([ser_uint256(0), ser_uint256(txid)]) - check_commitment = uint256_from_str(hash256(ser_uint256(witness_root)+ser_uint256(0))) - from test_framework.blocktools import WITNESS_COMMITMENT_HEADER - output_data = WITNESS_COMMITMENT_HEADER + ser_uint256(check_commitment) - script = CScript([OP_RETURN, output_data]) + witness_root = CBlock.get_merkle_root([ser_uint256(0), + ser_uint256(txid)]) + script = get_witness_script(witness_root, 0) assert_equal(witness_commitment, bytes_to_hex_str(script)) # undo mocktime diff --git a/test/functional/p2p-timeouts.py b/test/functional/p2p-timeouts.py index de4edd6800..c3b29c215b 100755 --- a/test/functional/p2p-timeouts.py +++ b/test/functional/p2p-timeouts.py @@ -28,20 +28,9 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * class TestNode(NodeConnCB): - def __init__(self): - super().__init__() - self.connected = False - self.received_version = False - - def on_open(self, conn): - self.connected = True - - def on_close(self, conn): - self.connected = False - def on_version(self, conn, message): # Don't send a verack in response - self.received_version = True + pass class TimeoutsTest(BitcoinTestFramework): def __init__(self): @@ -49,12 +38,6 @@ class TimeoutsTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 - def setup_network(self): - self.nodes = [] - - # Start up node0 to be a version 1, pre-segwit node. - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - def run_test(self): # Setup the p2p connections and start up the network thread. self.no_verack_node = TestNode() # never send verack @@ -83,7 +66,7 @@ class TimeoutsTest(BitcoinTestFramework): sleep(30) - assert(self.no_verack_node.received_version) + assert "version" in self.no_verack_node.last_message assert(self.no_verack_node.connected) assert(self.no_version_node.connected) diff --git a/test/functional/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py index da960e2d80..41921fe14e 100755 --- a/test/functional/p2p-versionbits-warning.py +++ b/test/functional/p2p-versionbits-warning.py @@ -12,7 +12,6 @@ from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * import re -import time from test_framework.blocktools import create_block, create_coinbase VB_PERIOD = 144 # versionbits period length for regtest @@ -24,28 +23,10 @@ WARN_UNKNOWN_RULES_MINED = "Unknown block versions being mined! It's possible un WARN_UNKNOWN_RULES_ACTIVE = "unknown new rules activated (versionbit {})".format(VB_UNKNOWN_BIT) VB_PATTERN = re.compile("^Warning.*versionbit") -# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending -# p2p messages to a node, generating the messages in the main testing logic. class TestNode(NodeConnCB): - def __init__(self): - super().__init__() - self.connection = None - self.ping_counter = 1 - self.last_pong = msg_pong() - - def add_connection(self, conn): - self.connection = conn - def on_inv(self, conn, message): pass - # Wrapper for the NodeConn's send_message function - def send_message(self, message): - self.connection.send_message(message) - - def on_pong(self, conn, message): - self.last_pong = message - class VersionBitsWarningTest(BitcoinTestFramework): def __init__(self): super().__init__() @@ -58,7 +39,7 @@ class VersionBitsWarningTest(BitcoinTestFramework): with open(self.alert_filename, 'w', encoding='utf8') as _: pass self.extra_args = [["-alertnotify=echo %s >> \"" + self.alert_filename + "\""]] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) + self.setup_nodes() # Send numblocks blocks via peer with nVersionToUse set. def send_blocks_with_version(self, peer, numblocks, nVersionToUse): diff --git a/test/functional/preciousblock.py b/test/functional/preciousblock.py index 30b0b5a301..04b41e76ba 100755 --- a/test/functional/preciousblock.py +++ b/test/functional/preciousblock.py @@ -41,7 +41,7 @@ class PreciousTest(BitcoinTestFramework): self.num_nodes = 3 def setup_network(self): - self.nodes = self.setup_nodes() + self.setup_nodes() def run_test(self): self.log.info("Ensure submitblock can in principle reorg to a competing chain") diff --git a/test/functional/prioritise_transaction.py b/test/functional/prioritise_transaction.py index 0b04ad17ab..a07923edba 100755 --- a/test/functional/prioritise_transaction.py +++ b/test/functional/prioritise_transaction.py @@ -14,17 +14,12 @@ class PrioritiseTransactionTest(BitcoinTestFramework): super().__init__() self.setup_clean_chain = True self.num_nodes = 1 + self.extra_args = [["-printpriority=1"]] + def run_test(self): self.txouts = gen_return_txouts() - - def setup_network(self): - self.nodes = [] - self.is_network_split = False - - self.nodes.append(start_node(0, self.options.tmpdir, ["-printpriority=1"])) self.relayfee = self.nodes[0].getnetworkinfo()['relayfee'] - def run_test(self): utxo_count = 90 utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], utxo_count) base_fee = self.relayfee*100 # our transactions are smaller than 100kb diff --git a/test/functional/proxy_test.py b/test/functional/proxy_test.py index 748e3e69f6..69384d9d85 100755 --- a/test/functional/proxy_test.py +++ b/test/functional/proxy_test.py @@ -90,7 +90,7 @@ class ProxyTest(BitcoinTestFramework): ] if self.have_ipv6: args[3] = ['-listen', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion'] - return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=args) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=args) def node_test(self, node, proxies, auth, test_onion=True): rv = [] diff --git a/test/functional/pruning.py b/test/functional/pruning.py index cc84c8c085..17019c658b 100755 --- a/test/functional/pruning.py +++ b/test/functional/pruning.py @@ -32,31 +32,21 @@ class PruneTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 6 - # Cache for utxos, as the listunspent may take a long time later in the test - self.utxo_cache_0 = [] - self.utxo_cache_1 = [] - - def setup_network(self): - self.nodes = [] - self.is_network_split = False - - # Create nodes 0 and 1 to mine - self.nodes.append(start_node(0, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=900)) - self.nodes.append(start_node(1, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=900)) - - # Create node 2 to test pruning - self.nodes.append(start_node(2, self.options.tmpdir, ["-maxreceivebuffer=20000","-prune=550"], timewait=900)) - self.prunedir = self.options.tmpdir+"/node2/regtest/blocks/" - + # Create nodes 0 and 1 to mine. + # Create node 2 to test pruning. # Create nodes 3 and 4 to test manual pruning (they will be re-started with manual pruning later) - self.nodes.append(start_node(3, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000"], timewait=900)) - self.nodes.append(start_node(4, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000"], timewait=900)) - # Create nodes 5 to test wallet in prune mode, but do not connect - self.nodes.append(start_node(5, self.options.tmpdir, ["-prune=550"])) + self.extra_args = [["-maxreceivebuffer=20000", "-blockmaxsize=999000", "-checkblocks=5"], + ["-maxreceivebuffer=20000", "-blockmaxsize=999000", "-checkblocks=5"], + ["-maxreceivebuffer=20000", "-prune=550"], + ["-maxreceivebuffer=20000", "-blockmaxsize=999000"], + ["-maxreceivebuffer=20000", "-blockmaxsize=999000"], + ["-prune=550"]] - # Determine default relay fee - self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"] + def setup_network(self): + self.setup_nodes() + + self.prunedir = self.options.tmpdir + "/node2/regtest/blocks/" connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[1], 2) @@ -332,6 +322,14 @@ class PruneTest(BitcoinTestFramework): def run_test(self): self.log.info("Warning! This test requires 4GB of disk space and takes over 30 mins (up to 2 hours)") self.log.info("Mining a big blockchain of 995 blocks") + + # Determine default relay fee + self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"] + + # Cache for utxos, as the listunspent may take a long time later in the test + self.utxo_cache_0 = [] + self.utxo_cache_1 = [] + self.create_big_chain() # Chain diagram key: # * blocks on main chain diff --git a/test/functional/rawtransactions.py b/test/functional/rawtransactions.py index d4c684136c..35debf9cab 100755 --- a/test/functional/rawtransactions.py +++ b/test/functional/rawtransactions.py @@ -24,21 +24,9 @@ class RawTransactionsTest(BitcoinTestFramework): self.num_nodes = 3 def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - - #connect to a local machine for debugging - #url = "http://bitcoinrpc:DP6DvqZtqXarpeNWyN3LZTFchCCyCUuHwNF7E8pX99x1@%s:%d" % ('127.0.0.1', 18332) - #proxy = AuthServiceProxy(url) - #proxy.url = url # store URL on proxy for info - #self.nodes.append(proxy) - - connect_nodes_bi(self.nodes,0,1) - connect_nodes_bi(self.nodes,1,2) + super().setup_network() connect_nodes_bi(self.nodes,0,2) - self.is_network_split=False - self.sync_all() - def run_test(self): #prepare some coins for multiple *rawtransaction commands diff --git a/test/functional/receivedby.py b/test/functional/receivedby.py index 248bcdbd68..a1cae301c5 100755 --- a/test/functional/receivedby.py +++ b/test/functional/receivedby.py @@ -32,7 +32,7 @@ class ReceivedByTest(BitcoinTestFramework): def setup_nodes(self): #This test requires mocktime enable_mocktime() - return start_nodes(self.num_nodes, self.options.tmpdir) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) def run_test(self): ''' diff --git a/test/functional/reindex.py b/test/functional/reindex.py index 0cebb0466f..8b8c5f3e71 100755 --- a/test/functional/reindex.py +++ b/test/functional/reindex.py @@ -24,9 +24,6 @@ class ReindexTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 - def setup_network(self): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - def reindex(self, justchainstate=False): self.nodes[0].generate(3) blockcount = self.nodes[0].getblockcount() diff --git a/test/functional/replace-by-fee.py b/test/functional/replace-by-fee.py index 163c304eba..e940ce535c 100755 --- a/test/functional/replace-by-fee.py +++ b/test/functional/replace-by-fee.py @@ -65,17 +65,12 @@ class ReplaceByFeeTest(BitcoinTestFramework): super().__init__() self.num_nodes = 1 self.setup_clean_chain = False - - def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000", - "-whitelist=127.0.0.1", - "-limitancestorcount=50", - "-limitancestorsize=101", - "-limitdescendantcount=200", - "-limitdescendantsize=101" - ])) - self.is_network_split = False + self.extra_args= [["-maxorphantx=1000", + "-whitelist=127.0.0.1", + "-limitancestorcount=50", + "-limitancestorsize=101", + "-limitdescendantcount=200", + "-limitdescendantsize=101"]] def run_test(self): make_utxo(self.nodes[0], 1*COIN) diff --git a/test/functional/rest.py b/test/functional/rest.py index 776211d301..fbcceba0fa 100755 --- a/test/functional/rest.py +++ b/test/functional/rest.py @@ -49,12 +49,8 @@ class RESTTest (BitcoinTestFramework): self.num_nodes = 3 def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes_bi(self.nodes,0,1) - connect_nodes_bi(self.nodes,1,2) - connect_nodes_bi(self.nodes,0,2) - self.is_network_split=False - self.sync_all() + super().setup_network() + connect_nodes_bi(self.nodes, 0, 2) def run_test(self): url = urllib.parse.urlparse(self.nodes[0].url) diff --git a/test/functional/rpcnamedargs.py b/test/functional/rpcnamedargs.py index f6175c8ca7..3b286000a1 100755 --- a/test/functional/rpcnamedargs.py +++ b/test/functional/rpcnamedargs.py @@ -8,7 +8,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, assert_raises_jsonrpc, - start_nodes, ) @@ -22,11 +21,6 @@ class NamedArgumentTest(BitcoinTestFramework): self.setup_clean_chain = False self.num_nodes = 1 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - self.is_network_split = False - self.sync_all() - def run_test(self): node = self.nodes[0] h = node.help(command='getinfo') diff --git a/test/functional/segwit.py b/test/functional/segwit.py index a1fffcb81a..ac95d66466 100755 --- a/test/functional/segwit.py +++ b/test/functional/segwit.py @@ -80,16 +80,13 @@ class SegWitTest(BitcoinTestFramework): super().__init__() self.setup_clean_chain = True self.num_nodes = 3 + self.extra_args = [["-walletprematurewitness", "-rpcserialversion=0"], + ["-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=1"], + ["-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness"]] def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-walletprematurewitness", "-rpcserialversion=0"])) - self.nodes.append(start_node(1, self.options.tmpdir, ["-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=1"])) - self.nodes.append(start_node(2, self.options.tmpdir, ["-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness"])) - connect_nodes(self.nodes[1], 0) - connect_nodes(self.nodes[2], 1) + super().setup_network() connect_nodes(self.nodes[0], 2) - self.is_network_split = False self.sync_all() def success_mine(self, node, txid, sign, redeem_script=""): diff --git a/test/functional/sendheaders.py b/test/functional/sendheaders.py index 1a7475ae84..44c357c6db 100755 --- a/test/functional/sendheaders.py +++ b/test/functional/sendheaders.py @@ -81,23 +81,17 @@ from test_framework.blocktools import create_block, create_coinbase direct_fetch_response_time = 0.05 -class BaseNode(NodeConnCB): +class TestNode(NodeConnCB): def __init__(self): super().__init__() - self.last_inv = None - self.last_headers = None - self.last_block = None - self.last_getdata = None self.block_announced = False - self.last_getheaders = None - self.disconnected = False self.last_blockhash_announced = None def clear_last_announcement(self): with mininode_lock: self.block_announced = False - self.last_inv = None - self.last_headers = None + self.last_message.pop("inv", None) + self.last_message.pop("headers", None) # Request data for a list of block hashes def get_data(self, block_hashes): @@ -118,29 +112,17 @@ class BaseNode(NodeConnCB): self.connection.send_message(msg) def on_inv(self, conn, message): - self.last_inv = message self.block_announced = True self.last_blockhash_announced = message.inv[-1].hash def on_headers(self, conn, message): - self.last_headers = message if len(message.headers): self.block_announced = True message.headers[-1].calc_sha256() self.last_blockhash_announced = message.headers[-1].sha256 def on_block(self, conn, message): - self.last_block = message.block - self.last_block.calc_sha256() - - def on_getdata(self, conn, message): - self.last_getdata = message - - def on_getheaders(self, conn, message): - self.last_getheaders = message - - def on_close(self, conn): - self.disconnected = True + self.last_message["block"].calc_sha256() # Test whether the last announcement we received had the # right header or the right inv @@ -155,43 +137,27 @@ class BaseNode(NodeConnCB): success = True compare_inv = [] - if self.last_inv != None: - compare_inv = [x.hash for x in self.last_inv.inv] + if "inv" in self.last_message: + compare_inv = [x.hash for x in self.last_message["inv"].inv] if compare_inv != expect_inv: success = False hash_headers = [] - if self.last_headers != None: + if "headers" in self.last_message: # treat headers as a list of block hashes - hash_headers = [ x.sha256 for x in self.last_headers.headers ] + hash_headers = [ x.sha256 for x in self.last_message["headers"].headers ] if hash_headers != expect_headers: success = False - self.last_inv = None - self.last_headers = None + self.last_message.pop("inv", None) + self.last_message.pop("headers", None) return success - # Syncing helpers - def wait_for_block(self, blockhash, timeout=60): - test_function = lambda: self.last_block != None and self.last_block.sha256 == blockhash - assert(wait_until(test_function, timeout=timeout)) - return - - def wait_for_getheaders(self, timeout=60): - test_function = lambda: self.last_getheaders != None - assert(wait_until(test_function, timeout=timeout)) - return - def wait_for_getdata(self, hash_list, timeout=60): if hash_list == []: return - test_function = lambda: self.last_getdata != None and [x.hash for x in self.last_getdata.inv] == hash_list - assert(wait_until(test_function, timeout=timeout)) - return - - def wait_for_disconnect(self, timeout=60): - test_function = lambda: self.disconnected + test_function = lambda: "getdata" in self.last_message and [x.hash for x in self.last_message["getdata"].inv] == hash_list assert(wait_until(test_function, timeout=timeout)) return @@ -210,28 +176,12 @@ class BaseNode(NodeConnCB): getblocks_message.locator.vHave = locator self.send_message(getblocks_message) -# InvNode: This peer should only ever receive inv's, because it doesn't ever send a -# "sendheaders" message. -class InvNode(BaseNode): - def __init__(self): - BaseNode.__init__(self) - -# TestNode: This peer is the one we use for most of the testing. -class TestNode(BaseNode): - def __init__(self): - BaseNode.__init__(self) - class SendHeadersTest(BitcoinTestFramework): def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 2 - def setup_network(self): - self.nodes = [] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes(self.nodes[0], 1) - # mine count blocks and return the new tip def mine_blocks(self, count): # Clear out last block announcement from each p2p listener @@ -260,7 +210,7 @@ class SendHeadersTest(BitcoinTestFramework): def run_test(self): # Setup the p2p connections and start up the network thread. - inv_node = InvNode() + inv_node = TestNode() test_node = TestNode() self.p2p_connections = [inv_node, test_node] @@ -293,7 +243,7 @@ class SendHeadersTest(BitcoinTestFramework): if i == 0: # first request the block test_node.get_data([tip]) - test_node.wait_for_block(tip, timeout=5) + test_node.wait_for_block(tip) elif i == 1: # next try requesting header and block test_node.get_headers(locator=[old_tip], hashstop=tip) @@ -308,7 +258,7 @@ class SendHeadersTest(BitcoinTestFramework): new_block = create_block(tip, create_coinbase(height+1), block_time) new_block.solve() test_node.send_header_for_blocks([new_block]) - test_node.wait_for_getdata([new_block.sha256], timeout=5) + test_node.wait_for_getdata([new_block.sha256]) test_node.send_message(msg_block(new_block)) test_node.sync_with_ping() # make sure this block is processed inv_node.clear_last_announcement() @@ -347,18 +297,18 @@ class SendHeadersTest(BitcoinTestFramework): if j == 0: # Announce via inv test_node.send_block_inv(tip) - test_node.wait_for_getheaders(timeout=5) + test_node.wait_for_getheaders() # Should have received a getheaders now test_node.send_header_for_blocks(blocks) # Test that duplicate inv's won't result in duplicate # getdata requests, or duplicate headers announcements [ inv_node.send_block_inv(x.sha256) for x in blocks ] - test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=5) + test_node.wait_for_getdata([x.sha256 for x in blocks]) inv_node.sync_with_ping() else: # Announce via headers test_node.send_header_for_blocks(blocks) - test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=5) + test_node.wait_for_getdata([x.sha256 for x in blocks]) # Test that duplicate headers won't result in duplicate # getdata requests (the check is further down) inv_node.send_header_for_blocks(blocks) @@ -368,8 +318,8 @@ class SendHeadersTest(BitcoinTestFramework): inv_node.sync_with_ping() # This block should not be announced to the inv node (since it also # broadcast it) - assert_equal(inv_node.last_inv, None) - assert_equal(inv_node.last_headers, None) + assert "inv" not in inv_node.last_message + assert "headers" not in inv_node.last_message tip = self.mine_blocks(1) assert_equal(inv_node.check_last_announcement(inv=[tip]), True) assert_equal(test_node.check_last_announcement(headers=[tip]), True) @@ -459,12 +409,12 @@ class SendHeadersTest(BitcoinTestFramework): inv_node.send_message(msg_block(blocks[-1])) inv_node.sync_with_ping() # Make sure blocks are processed - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) test_node.send_header_for_blocks(blocks) test_node.sync_with_ping() # should not have received any getdata messages with mininode_lock: - assert_equal(test_node.last_getdata, None) + assert "getdata" not in test_node.last_message # This time, direct fetch should work blocks = [] @@ -498,11 +448,11 @@ class SendHeadersTest(BitcoinTestFramework): # Announcing one block on fork should not trigger direct fetch # (less work than tip) - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) test_node.send_header_for_blocks(blocks[0:1]) test_node.sync_with_ping() with mininode_lock: - assert_equal(test_node.last_getdata, None) + assert "getdata" not in test_node.last_message # Announcing one more block on fork should trigger direct fetch for # both blocks (same work as tip) @@ -517,11 +467,11 @@ class SendHeadersTest(BitcoinTestFramework): test_node.wait_for_getdata([x.sha256 for x in blocks[2:16]], timeout=direct_fetch_response_time) # Announcing 1 more header should not trigger any response - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) test_node.send_header_for_blocks(blocks[18:19]) test_node.sync_with_ping() with mininode_lock: - assert_equal(test_node.last_getdata, None) + assert "getdata" not in test_node.last_message self.log.info("Part 4: success!") @@ -532,7 +482,7 @@ class SendHeadersTest(BitcoinTestFramework): # First we test that receipt of an unconnecting header doesn't prevent # chain sync. for i in range(10): - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) blocks = [] # Create two more blocks. for j in range(2): @@ -543,9 +493,9 @@ class SendHeadersTest(BitcoinTestFramework): height += 1 # Send the header of the second block -> this won't connect. with mininode_lock: - test_node.last_getheaders = None + test_node.last_message.pop("getheaders", None) test_node.send_header_for_blocks([blocks[1]]) - test_node.wait_for_getheaders(timeout=1) + test_node.wait_for_getheaders() test_node.send_header_for_blocks(blocks) test_node.wait_for_getdata([x.sha256 for x in blocks]) [ test_node.send_message(msg_block(x)) for x in blocks ] @@ -566,9 +516,9 @@ class SendHeadersTest(BitcoinTestFramework): for i in range(1, MAX_UNCONNECTING_HEADERS): # Send a header that doesn't connect, check that we get a getheaders. with mininode_lock: - test_node.last_getheaders = None + test_node.last_message.pop("getheaders", None) test_node.send_header_for_blocks([blocks[i]]) - test_node.wait_for_getheaders(timeout=1) + test_node.wait_for_getheaders() # Next header will connect, should re-set our count: test_node.send_header_for_blocks([blocks[0]]) @@ -581,25 +531,21 @@ class SendHeadersTest(BitcoinTestFramework): for i in range(5*MAX_UNCONNECTING_HEADERS - 1): # Send a header that doesn't connect, check that we get a getheaders. with mininode_lock: - test_node.last_getheaders = None + test_node.last_message.pop("getheaders", None) test_node.send_header_for_blocks([blocks[i%len(blocks)]]) - test_node.wait_for_getheaders(timeout=1) + test_node.wait_for_getheaders() # Eventually this stops working. - with mininode_lock: - self.last_getheaders = None test_node.send_header_for_blocks([blocks[-1]]) # Should get disconnected test_node.wait_for_disconnect() - with mininode_lock: - self.last_getheaders = True self.log.info("Part 5: success!") # Finally, check that the inv node never received a getdata request, # throughout the test - assert_equal(inv_node.last_getdata, None) + assert "getdata" not in inv_node.last_message if __name__ == '__main__': SendHeadersTest().main() diff --git a/test/functional/signmessages.py b/test/functional/signmessages.py index 91f5abef5d..42f6a9daaf 100755 --- a/test/functional/signmessages.py +++ b/test/functional/signmessages.py @@ -5,7 +5,6 @@ """Test RPC commands for signing and verifying messages.""" from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * class SignMessagesTest(BitcoinTestFramework): @@ -14,10 +13,6 @@ class SignMessagesTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - self.is_network_split = False - def run_test(self): message = 'This is just a test message' diff --git a/test/functional/signrawtransactions.py b/test/functional/signrawtransactions.py index b24162ab97..fc49c23b9f 100755 --- a/test/functional/signrawtransactions.py +++ b/test/functional/signrawtransactions.py @@ -14,10 +14,6 @@ class SignRawTransactionsTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - self.is_network_split = False - def successful_signing_test(self): """Create and sign a valid raw transaction with one input. diff --git a/test/functional/smartfees.py b/test/functional/smartfees.py index aafdb14846..4124f8025e 100755 --- a/test/functional/smartfees.py +++ b/test/functional/smartfees.py @@ -203,7 +203,6 @@ class EstimateFeeTest(BitcoinTestFramework): connect_nodes(self.nodes[0], 2) connect_nodes(self.nodes[2], 1) - self.is_network_split = False self.sync_all() def transact_and_mine(self, numblocks, mining_node): diff --git a/test/functional/test_framework/authproxy.py b/test/functional/test_framework/authproxy.py index 9ab3094b06..dfcc524313 100644 --- a/test/functional/test_framework/authproxy.py +++ b/test/functional/test_framework/authproxy.py @@ -42,6 +42,7 @@ import decimal import json import logging import socket +import time try: import urllib.parse as urlparse except ImportError: @@ -163,6 +164,7 @@ class AuthServiceProxy(object): return self._request('POST', self.__url.path, postdata.encode('utf-8')) def _get_response(self): + req_start_time = time.time() try: http_response = self.__conn.getresponse() except socket.timeout as e: @@ -183,8 +185,9 @@ class AuthServiceProxy(object): responsedata = http_response.read().decode('utf8') response = json.loads(responsedata, parse_float=decimal.Decimal) + elapsed = time.time() - req_start_time if "error" in response and response["error"] is None: - log.debug("<-%s- %s"%(response["id"], json.dumps(response["result"], default=EncodeDecimal, ensure_ascii=self.ensure_ascii))) + log.debug("<-%s- [%.6f] %s"%(response["id"], elapsed, json.dumps(response["result"], default=EncodeDecimal, ensure_ascii=self.ensure_ascii))) else: - log.debug("<-- "+responsedata) + log.debug("<-- [%.6f] %s"%(elapsed,responsedata)) return response diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py index 2c9a0857df..5dcf516dc6 100644 --- a/test/functional/test_framework/blocktools.py +++ b/test/functional/test_framework/blocktools.py @@ -25,6 +25,13 @@ def create_block(hashprev, coinbase, nTime=None): # From BIP141 WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed" + +def get_witness_script(witness_root, witness_nonce): + witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root)+ser_uint256(witness_nonce))) + output_data = WITNESS_COMMITMENT_HEADER + ser_uint256(witness_commitment) + return CScript([OP_RETURN, output_data]) + + # According to BIP141, blocks with witness rules active must commit to the # hash of all in-block transactions including witness. def add_witness_commitment(block, nonce=0): @@ -32,14 +39,12 @@ def add_witness_commitment(block, nonce=0): # transactions, with witnesses. witness_nonce = nonce witness_root = block.calc_witness_merkle_root() - witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root)+ser_uint256(witness_nonce))) # witness_nonce should go to coinbase witness. block.vtx[0].wit.vtxinwit = [CTxInWitness()] block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ser_uint256(witness_nonce)] # witness commitment is the last OP_RETURN output in coinbase - output_data = WITNESS_COMMITMENT_HEADER + ser_uint256(witness_commitment) - block.vtx[0].vout.append(CTxOut(0, CScript([OP_RETURN, output_data]))) + block.vtx[0].vout.append(CTxOut(0, get_witness_script(witness_root, witness_nonce))) block.vtx[0].rehash() block.hashMerkleRoot = block.calc_merkle_root() block.rehash() diff --git a/test/functional/test_framework/comptool.py b/test/functional/test_framework/comptool.py index 25c18bda82..9f062865a3 100755 --- a/test/functional/test_framework/comptool.py +++ b/test/functional/test_framework/comptool.py @@ -192,9 +192,7 @@ class TestManager(object): return wait_until(disconnected, timeout=10) def wait_for_verack(self): - def veracked(): - return all(node.verack_received for node in self.test_nodes) - return wait_until(veracked, timeout=10) + return all(node.wait_for_verack() for node in self.test_nodes) def wait_for_pings(self, counter): def received_pongs(): diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index d57d46f2ff..fb3ed1473a 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -20,21 +20,22 @@ msg_block, msg_tx, msg_headers, etc.: ser_*, deser_*: functions that handle serialization/deserialization """ -import struct -import socket import asyncore -import time -import sys -import random -from .util import hex_str_to_bytes, bytes_to_hex_str -from io import BytesIO from codecs import encode +from collections import defaultdict +import copy import hashlib -from threading import RLock -from threading import Thread +from io import BytesIO import logging -import copy +import random +import socket +import struct +import sys +import time +from threading import RLock, Thread + from test_framework.siphash import siphash256 +from test_framework.util import hex_str_to_bytes, bytes_to_hex_str BIP0031_VERSION = 60000 MY_VERSION = 70014 # past bip-31 for ping/pong @@ -610,7 +611,8 @@ class CBlock(CBlockHeader): return r # Calculate the merkle root given a vector of transaction hashes - def get_merkle_root(self, hashes): + @classmethod + def get_merkle_root(cls, hashes): while len(hashes) > 1: newhashes = [] for i in range(0, len(hashes), 2): @@ -1356,6 +1358,8 @@ class msg_reject(object): # Helper function def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf')): + if attempts == float('inf') and timeout == float('inf'): + timeout = 60 attempt = 0 elapsed = 0 @@ -1465,30 +1469,57 @@ class msg_witness_blocktxn(msg_blocktxn): r += self.block_transactions.serialize(with_witness=True) return r -# This is what a callback should look like for NodeConn -# Reimplement the on_* functions to provide handling for events class NodeConnCB(object): + """Callback and helper functions for P2P connection to a bitcoind node. + + Individual testcases should subclass this and override the on_* methods + if they want to alter message handling behaviour. + """ + def __init__(self): - self.verack_received = False + # Track whether we have a P2P connection open to the node + self.connected = False + self.connection = None + + # Track number of messages of each type received and the most recent + # message of each type + self.message_count = defaultdict(int) + self.last_message = {} + + # A count of the number of ping messages we've sent to the node + self.ping_counter = 1 + # deliver_sleep_time is helpful for debugging race conditions in p2p # tests; it causes message delivery to sleep for the specified time # before acquiring the global lock and delivering the next message. self.deliver_sleep_time = None + # Remember the services our peer has advertised self.peer_services = None - self.connection = None - self.ping_counter = 1 - self.last_pong = msg_pong() + + # Message receiving methods def deliver(self, conn, message): + """Receive message and dispatch message to appropriate callback. + + We keep a count of how many of each message type has been received + and the most recent message of each type. + + Optionally waits for deliver_sleep_time before dispatching message. + """ + deliver_sleep = self.get_deliver_sleep_time() if deliver_sleep is not None: time.sleep(deliver_sleep) with mininode_lock: try: - getattr(self, 'on_' + message.command.decode('ascii'))(conn, message) + command = message.command.decode('ascii') + self.message_count[command] += 1 + self.last_message[command] = message + getattr(self, 'on_' + command)(conn, message) except: - logger.exception("ERROR delivering %s" % repr(message)) + print("ERROR delivering %s (%s)" % (repr(message), + sys.exc_info()[0])) def set_deliver_sleep_time(self, value): with mininode_lock: @@ -1498,14 +1529,20 @@ class NodeConnCB(object): with mininode_lock: return self.deliver_sleep_time - # Callbacks which can be overridden by subclasses - ################################################# + # Callback methods. Can be overridden by subclasses in individual test + # cases to provide custom message handling behaviour. + + def on_open(self, conn): + self.connected = True + + def on_close(self, conn): + self.connected = False + self.connection = None def on_addr(self, conn, message): pass def on_alert(self, conn, message): pass def on_block(self, conn, message): pass def on_blocktxn(self, conn, message): pass - def on_close(self, conn): pass def on_cmpctblock(self, conn, message): pass def on_feefilter(self, conn, message): pass def on_getaddr(self, conn, message): pass @@ -1515,7 +1552,7 @@ class NodeConnCB(object): def on_getheaders(self, conn, message): pass def on_headers(self, conn, message): pass def on_mempool(self, conn): pass - def on_open(self, conn): pass + def on_pong(self, conn, message): pass def on_reject(self, conn, message): pass def on_sendcmpct(self, conn, message): pass def on_sendheaders(self, conn, message): pass @@ -1533,9 +1570,6 @@ class NodeConnCB(object): if conn.ver_send > BIP0031_VERSION: conn.send_message(msg_pong(message.nonce)) - def on_pong(self, conn, message): - self.last_pong = message - def on_verack(self, conn, message): conn.ver_recv = conn.ver_send self.verack_received = True @@ -1548,15 +1582,49 @@ class NodeConnCB(object): conn.ver_recv = conn.ver_send conn.nServices = message.nServices - # Helper functions - ################## + # Connection helper methods def add_connection(self, conn): self.connection = conn - # Wrapper for the NodeConn's send_message function + def wait_for_disconnect(self, timeout=60): + test_function = lambda: not self.connected + assert wait_until(test_function, timeout=timeout) + + # Message receiving helper methods + + def wait_for_block(self, blockhash, timeout=60): + test_function = lambda: self.last_message.get("block") and self.last_message["block"].block.rehash() == blockhash + assert wait_until(test_function, timeout=timeout) + + def wait_for_getdata(self, timeout=60): + test_function = lambda: self.last_message.get("getdata") + assert wait_until(test_function, timeout=timeout) + + def wait_for_getheaders(self, timeout=60): + test_function = lambda: self.last_message.get("getheaders") + assert wait_until(test_function, timeout=timeout) + + def wait_for_inv(self, expected_inv, timeout=60): + """Waits for an INV message and checks that the first inv object in the message was as expected.""" + if len(expected_inv) > 1: + raise NotImplementedError("wait_for_inv() will only verify the first inv object") + test_function = lambda: self.last_message.get("inv") and \ + self.last_message["inv"].inv[0].type == expected_inv[0].type and \ + self.last_message["inv"].inv[0].hash == expected_inv[0].hash + assert wait_until(test_function, timeout=timeout) + + def wait_for_verack(self, timeout=60): + test_function = lambda: self.message_count["verack"] + assert wait_until(test_function, timeout=timeout) + + # Message sending helper functions + def send_message(self, message): - self.connection.send_message(message) + if self.connection: + self.connection.send_message(message) + else: + logger.error("Cannot send message. No connection to node!") def send_and_ping(self, message): self.send_message(message) @@ -1564,27 +1632,11 @@ class NodeConnCB(object): # Sync up with the node def sync_with_ping(self, timeout=60): - def received_pong(): - return (self.last_pong.nonce == self.ping_counter) self.send_message(msg_ping(nonce=self.ping_counter)) - success = wait_until(received_pong, timeout=timeout) - if not success: - logger.error("sync_with_ping failed!") - raise AssertionError("sync_with_ping failed!") + test_function = lambda: self.last_message.get("pong") and self.last_message["pong"].nonce == self.ping_counter + assert wait_until(test_function, timeout=timeout) self.ping_counter += 1 - - return success - - # Spin until verack message is received from the node. - # Tests may want to use this as a signal that the test can begin. - # This can be called from the testing thread, so it needs to acquire the - # global lock. - def wait_for_verack(self): - while True: - with mininode_lock: - if self.verack_received: - return - time.sleep(0.05) + return True # The actual NodeConn class # This class provides an interface for a p2p connection to a specified node diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 473b7c14a9..8d8139e4e4 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -8,27 +8,55 @@ from collections import deque import logging import optparse import os -import sys import shutil +import subprocess +import sys import tempfile import time from .util import ( - initialize_chain, - start_nodes, + PortSeed, + MAX_NODES, + bitcoind_processes, + check_json_precision, connect_nodes_bi, + disable_mocktime, + disconnect_nodes, + enable_coverage, + enable_mocktime, + get_mocktime, + get_rpc_proxy, + initialize_datadir, + log_filename, + p2p_port, + rpc_url, + set_node_times, + start_node, + start_nodes, + stop_node, + stop_nodes, sync_blocks, sync_mempools, - stop_nodes, - stop_node, - enable_coverage, - check_json_precision, - initialize_chain_clean, - PortSeed, + wait_for_bitcoind_start, ) from .authproxy import JSONRPCException class BitcoinTestFramework(object): + """Base class for a bitcoin test script. + + Individual bitcoin test scripts should subclass this class and override the following methods: + + - __init__() + - add_options() + - setup_chain() + - setup_network() + - run_test() + + The main() method should not be overridden. + + This class also contains various public and private helper methods.""" + + # Methods to override in subclass test scripts. TEST_EXIT_PASSED = 0 TEST_EXIT_FAILED = 1 @@ -39,69 +67,36 @@ class BitcoinTestFramework(object): self.setup_clean_chain = False self.nodes = None - def run_test(self): - raise NotImplementedError - def add_options(self, parser): pass def setup_chain(self): self.log.info("Initializing test directory "+self.options.tmpdir) if self.setup_clean_chain: - initialize_chain_clean(self.options.tmpdir, self.num_nodes) + self._initialize_chain_clean(self.options.tmpdir, self.num_nodes) else: - initialize_chain(self.options.tmpdir, self.num_nodes, self.options.cachedir) + self._initialize_chain(self.options.tmpdir, self.num_nodes, self.options.cachedir) - def stop_node(self, num_node): - stop_node(self.nodes[num_node], num_node) - - def setup_nodes(self): - return start_nodes(self.num_nodes, self.options.tmpdir) - - def setup_network(self, split = False): - self.nodes = self.setup_nodes() + def setup_network(self): + self.setup_nodes() # Connect the nodes as a "chain". This allows us # to split the network between nodes 1 and 2 to get # two halves that can work on competing chains. - - # If we joined network halves, connect the nodes from the joint - # on outward. This ensures that chains are properly reorganised. - if not split: - connect_nodes_bi(self.nodes, 1, 2) - sync_blocks(self.nodes[1:3]) - sync_mempools(self.nodes[1:3]) - - connect_nodes_bi(self.nodes, 0, 1) - connect_nodes_bi(self.nodes, 2, 3) - self.is_network_split = split + for i in range(self.num_nodes - 1): + connect_nodes_bi(self.nodes, i, i + 1) self.sync_all() - def split_network(self): - """ - Split the network of four nodes into nodes 0/1 and 2/3. - """ - assert not self.is_network_split - stop_nodes(self.nodes) - self.setup_network(True) - - def sync_all(self): - if self.is_network_split: - sync_blocks(self.nodes[:2]) - sync_blocks(self.nodes[2:]) - sync_mempools(self.nodes[:2]) - sync_mempools(self.nodes[2:]) - else: - sync_blocks(self.nodes) - sync_mempools(self.nodes) + def setup_nodes(self): + extra_args = None + if hasattr(self, "extra_args"): + extra_args = self.extra_args + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) - def join_network(self): - """ - Join the (previously split) network halves together. - """ - assert self.is_network_split - stop_nodes(self.nodes) - self.setup_network(False) + def run_test(self): + raise NotImplementedError + + # Main function. This should not be overridden by the subclass test scripts. def main(self): @@ -124,6 +119,8 @@ class BitcoinTestFramework(object): help="The seed to use for assigning port numbers (default: current process id)") parser.add_option("--coveragedir", dest="coveragedir", help="Write tested RPC commands into this directory") + parser.add_option("--configfile", dest="configfile", + help="Location of the test framework config file") self.add_options(parser) (self.options, self.args) = parser.parse_args() @@ -163,7 +160,7 @@ class BitcoinTestFramework(object): if not self.options.noshutdown: self.log.info("Stopping nodes") - stop_nodes(self.nodes) + self.stop_nodes() else: self.log.info("Note: bitcoinds were not stopped and may still be running") @@ -197,6 +194,45 @@ class BitcoinTestFramework(object): logging.shutdown() sys.exit(self.TEST_EXIT_FAILED) + # Public helper methods. These can be accessed by the subclass test scripts. + + def start_node(self, i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): + return start_node(i, dirname, extra_args, rpchost, timewait, binary, stderr) + + def start_nodes(self, num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None): + return start_nodes(num_nodes, dirname, extra_args, rpchost, timewait, binary) + + def stop_node(self, num_node): + stop_node(self.nodes[num_node], num_node) + + def stop_nodes(self): + stop_nodes(self.nodes) + + def split_network(self): + """ + Split the network of four nodes into nodes 0/1 and 2/3. + """ + disconnect_nodes(self.nodes[1], 2) + disconnect_nodes(self.nodes[2], 1) + self.sync_all([self.nodes[:2], self.nodes[2:]]) + + def join_network(self): + """ + Join the (previously split) network halves together. + """ + connect_nodes_bi(self.nodes, 1, 2) + self.sync_all() + + def sync_all(self, node_groups=None): + if not node_groups: + node_groups = [self.nodes] + + for group in node_groups: + sync_blocks(group) + sync_mempools(group) + + # Private helper methods. These should not be accessed by the subclass test scripts. + def _start_logging(self): # Add logger and logging handlers self.log = logging.getLogger('TestFramework') @@ -225,6 +261,88 @@ class BitcoinTestFramework(object): rpc_handler.setLevel(logging.DEBUG) rpc_logger.addHandler(rpc_handler) + def _initialize_chain(self, test_dir, num_nodes, cachedir): + """Initialize a pre-mined blockchain for use by the test. + + Create a cache of a 200-block-long chain (with wallet) for MAX_NODES + Afterward, create num_nodes copies from the cache.""" + + assert num_nodes <= MAX_NODES + create_cache = False + for i in range(MAX_NODES): + if not os.path.isdir(os.path.join(cachedir, 'node' + str(i))): + create_cache = True + break + + if create_cache: + self.log.debug("Creating data directories from cached datadir") + + # find and delete old cache directories if any exist + for i in range(MAX_NODES): + if os.path.isdir(os.path.join(cachedir, "node" + str(i))): + shutil.rmtree(os.path.join(cachedir, "node" + str(i))) + + # Create cache directories, run bitcoinds: + for i in range(MAX_NODES): + datadir = initialize_datadir(cachedir, i) + args = [os.getenv("BITCOIND", "bitcoind"), "-server", "-keypool=1", "-datadir=" + datadir, "-discover=0"] + if i > 0: + args.append("-connect=127.0.0.1:" + str(p2p_port(0))) + bitcoind_processes[i] = subprocess.Popen(args) + self.log.debug("initialize_chain: bitcoind started, waiting for RPC to come up") + wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i) + self.log.debug("initialize_chain: RPC successfully started") + + self.nodes = [] + for i in range(MAX_NODES): + try: + self.nodes.append(get_rpc_proxy(rpc_url(i), i)) + except: + self.log.exception("Error connecting to node %d" % i) + sys.exit(1) + + # Create a 200-block-long chain; each of the 4 first nodes + # gets 25 mature blocks and 25 immature. + # Note: To preserve compatibility with older versions of + # initialize_chain, only 4 nodes will generate coins. + # + # blocks are created with timestamps 10 minutes apart + # starting from 2010 minutes in the past + enable_mocktime() + block_time = get_mocktime() - (201 * 10 * 60) + for i in range(2): + for peer in range(4): + for j in range(25): + set_node_times(self.nodes, block_time) + self.nodes[peer].generate(1) + block_time += 10 * 60 + # Must sync before next peer starts generating blocks + sync_blocks(self.nodes) + + # Shut them down, and clean up cache directories: + self.stop_nodes() + self.nodes = [] + disable_mocktime() + for i in range(MAX_NODES): + os.remove(log_filename(cachedir, i, "debug.log")) + os.remove(log_filename(cachedir, i, "db.log")) + os.remove(log_filename(cachedir, i, "peers.dat")) + os.remove(log_filename(cachedir, i, "fee_estimates.dat")) + + for i in range(num_nodes): + from_dir = os.path.join(cachedir, "node" + str(i)) + to_dir = os.path.join(test_dir, "node" + str(i)) + shutil.copytree(from_dir, to_dir) + initialize_datadir(test_dir, i) # Overwrite port/rpcport in bitcoin.conf + + def _initialize_chain_clean(self, test_dir, num_nodes): + """Initialize empty blockchain for use by the test. + + Create an empty blockchain and num_nodes wallets. + Useful if a test case wants complete control over initialization.""" + for i in range(num_nodes): + initialize_datadir(test_dir, i) + # Test framework for doing p2p comparison testing, which sets up some bitcoind # binaries: # 1 binary: test binary @@ -247,7 +365,7 @@ class ComparisonTestFramework(BitcoinTestFramework): help="bitcoind binary to use for reference nodes (if any)") def setup_network(self): - self.nodes = start_nodes( + self.nodes = self.start_nodes( self.num_nodes, self.options.tmpdir, extra_args=[['-whitelist=127.0.0.1']] * self.num_nodes, binary=[self.options.testbinary] + diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 899b0b5a1b..2b56fe8d62 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -226,87 +226,6 @@ def wait_for_bitcoind_start(process, url, i): raise # unknown JSON RPC exception time.sleep(0.25) -def initialize_chain(test_dir, num_nodes, cachedir): - """ - Create a cache of a 200-block-long chain (with wallet) for MAX_NODES - Afterward, create num_nodes copies from the cache - """ - - assert num_nodes <= MAX_NODES - create_cache = False - for i in range(MAX_NODES): - if not os.path.isdir(os.path.join(cachedir, 'node'+str(i))): - create_cache = True - break - - if create_cache: - logger.debug("Creating data directories from cached datadir") - - #find and delete old cache directories if any exist - for i in range(MAX_NODES): - if os.path.isdir(os.path.join(cachedir,"node"+str(i))): - shutil.rmtree(os.path.join(cachedir,"node"+str(i))) - - # Create cache directories, run bitcoinds: - for i in range(MAX_NODES): - datadir=initialize_datadir(cachedir, i) - args = [ os.getenv("BITCOIND", "bitcoind"), "-server", "-keypool=1", "-datadir="+datadir, "-discover=0" ] - if i > 0: - args.append("-connect=127.0.0.1:"+str(p2p_port(0))) - bitcoind_processes[i] = subprocess.Popen(args) - logger.debug("initialize_chain: bitcoind started, waiting for RPC to come up") - wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i) - logger.debug("initialize_chain: RPC successfully started") - - rpcs = [] - for i in range(MAX_NODES): - try: - rpcs.append(get_rpc_proxy(rpc_url(i), i)) - except: - sys.stderr.write("Error connecting to "+url+"\n") - sys.exit(1) - - # Create a 200-block-long chain; each of the 4 first nodes - # gets 25 mature blocks and 25 immature. - # Note: To preserve compatibility with older versions of - # initialize_chain, only 4 nodes will generate coins. - # - # blocks are created with timestamps 10 minutes apart - # starting from 2010 minutes in the past - enable_mocktime() - block_time = get_mocktime() - (201 * 10 * 60) - for i in range(2): - for peer in range(4): - for j in range(25): - set_node_times(rpcs, block_time) - rpcs[peer].generate(1) - block_time += 10*60 - # Must sync before next peer starts generating blocks - sync_blocks(rpcs) - - # Shut them down, and clean up cache directories: - stop_nodes(rpcs) - disable_mocktime() - for i in range(MAX_NODES): - os.remove(log_filename(cachedir, i, "debug.log")) - os.remove(log_filename(cachedir, i, "db.log")) - os.remove(log_filename(cachedir, i, "peers.dat")) - os.remove(log_filename(cachedir, i, "fee_estimates.dat")) - - for i in range(num_nodes): - from_dir = os.path.join(cachedir, "node"+str(i)) - to_dir = os.path.join(test_dir, "node"+str(i)) - shutil.copytree(from_dir, to_dir) - initialize_datadir(test_dir, i) # Overwrite port/rpcport in bitcoin.conf - -def initialize_chain_clean(test_dir, num_nodes): - """ - Create an empty blockchain and num_nodes wallets. - Useful if a test case wants complete control over initialization. - """ - for i in range(num_nodes): - datadir=initialize_datadir(test_dir, i) - def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): """ @@ -315,7 +234,7 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= datadir = os.path.join(dirname, "node"+str(i)) if binary is None: binary = os.getenv("BITCOIND", "bitcoind") - args = [binary, "-datadir=" + datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(get_mocktime())] + args = [binary, "-datadir=" + datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(get_mocktime()), "-uacomment=testnode%d" % i] if extra_args is not None: args.extend(extra_args) bitcoind_processes[i] = subprocess.Popen(args, stderr=stderr) logger.debug("initialize_chain: bitcoind started, waiting for RPC to come up") @@ -354,6 +273,8 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, timewait=None """ if extra_args is None: extra_args = [ None for _ in range(num_nodes) ] if binary is None: binary = [ None for _ in range(num_nodes) ] + assert_equal(len(extra_args), num_nodes) + assert_equal(len(binary), num_nodes) rpcs = [] try: for i in range(num_nodes): @@ -385,6 +306,17 @@ def set_node_times(nodes, t): for node in nodes: node.setmocktime(t) +def disconnect_nodes(from_connection, node_num): + for peer_id in [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']]: + from_connection.disconnectnode(nodeid=peer_id) + + for _ in range(50): + if [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']] == []: + break + time.sleep(0.1) + else: + raise AssertionError("timed out waiting for disconnect") + def connect_nodes(from_connection, node_num): ip_port = "127.0.0.1:"+str(p2p_port(node_num)) from_connection.addnode(ip_port, "onetry") diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index f7a501ab76..6174ca1d88 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -77,6 +77,7 @@ BASE_SCRIPTS= [ 'rawtransactions.py', 'reindex.py', # vv Tests less than 30s vv + "zmq_test.py", 'mempool_resurrect_test.py', 'txn_doublespend.py --mineblock', 'txn_clone.py', @@ -84,6 +85,7 @@ BASE_SCRIPTS= [ 'rest.py', 'mempool_spendcoinbase.py', 'mempool_reorg.py', + 'mempool_persist.py', 'httpbasics.py', 'multi_rpc.py', 'proxy_test.py', @@ -110,11 +112,6 @@ BASE_SCRIPTS= [ 'p2p-leaktests.py', ] -ZMQ_SCRIPTS = [ - # ZMQ test can only be run if bitcoin was built with zmq-enabled. - # call test_runner.py with -nozmq to explicitly exclude these tests. - 'zmq_test.py'] - EXTENDED_SCRIPTS = [ # These tests are not run by the travis build process. # Longest test should go first, to favor running tests in parallel @@ -143,13 +140,12 @@ EXTENDED_SCRIPTS = [ 'txn_clone.py --mineblock', 'forknotify.py', 'invalidateblock.py', - 'maxblocksinflight.py', 'p2p-acceptblock.py', 'replace-by-fee.py', ] # Place EXTENDED_SCRIPTS first since it has the 3 longest running tests -ALL_SCRIPTS = EXTENDED_SCRIPTS + BASE_SCRIPTS + ZMQ_SCRIPTS +ALL_SCRIPTS = EXTENDED_SCRIPTS + BASE_SCRIPTS NON_SCRIPTS = [ # These are python files that live in the functional tests directory, but are not test scripts. @@ -167,23 +163,25 @@ def main(): Help text and arguments for individual test script:''', formatter_class=argparse.RawTextHelpFormatter) parser.add_argument('--coverage', action='store_true', help='generate a basic coverage report for the RPC interface') - parser.add_argument('--exclude', '-x', help='specify a comma-seperated-list of scripts to exclude. Do not include the .py extension in the name.') + parser.add_argument('--exclude', '-x', help='specify a comma-seperated-list of scripts to exclude.') parser.add_argument('--extended', action='store_true', help='run the extended test suite in addition to the basic tests') parser.add_argument('--force', '-f', action='store_true', help='run tests even on platforms where they are disabled by default (e.g. windows).') parser.add_argument('--help', '-h', '-?', action='store_true', help='print help text and exit') parser.add_argument('--jobs', '-j', type=int, default=4, help='how many test scripts to run in parallel. Default=4.') parser.add_argument('--keepcache', '-k', action='store_true', help='the default behavior is to flush the cache directory on startup. --keepcache retains the cache from the previous testrun.') parser.add_argument('--quiet', '-q', action='store_true', help='only print results summary and failure logs') - parser.add_argument('--nozmq', action='store_true', help='do not run the zmq tests') args, unknown_args = parser.parse_known_args() - # Create a set to store arguments and create the passon string - tests = set(arg for arg in unknown_args if arg[:2] != "--") + # args to be passed on always start with two dashes; tests are the remaining unknown args + tests = [arg for arg in unknown_args if arg[:2] != "--"] passon_args = [arg for arg in unknown_args if arg[:2] == "--"] # Read config generated by configure. config = configparser.ConfigParser() - config.read_file(open(os.path.dirname(__file__) + "/config.ini")) + configfile = os.path.abspath(os.path.dirname(__file__)) + "/config.ini" + config.read_file(open(configfile)) + + passon_args.append("--configfile=%s" % configfile) # Set up logging logging_level = logging.INFO if args.quiet else logging.DEBUG @@ -192,7 +190,6 @@ def main(): enable_wallet = config["components"].getboolean("ENABLE_WALLET") enable_utils = config["components"].getboolean("ENABLE_UTILS") enable_bitcoind = config["components"].getboolean("ENABLE_BITCOIND") - enable_zmq = config["components"].getboolean("ENABLE_ZMQ") and not args.nozmq if config["environment"]["EXEEXT"] == ".exe" and not args.force: # https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9 @@ -205,27 +202,21 @@ def main(): print("Rerun `configure` with -enable-wallet, -with-utils and -with-daemon and rerun make") sys.exit(0) - # python3-zmq may not be installed. Handle this gracefully and with some helpful info - if enable_zmq: - try: - import zmq - except ImportError: - print("ERROR: \"import zmq\" failed. Use -nozmq to run without the ZMQ tests." - "To run zmq tests, see dependency info in /test/README.md.") - raise - # Build list of tests if tests: # Individual tests have been specified. Run specified tests that exist # in the ALL_SCRIPTS list. Accept the name with or without .py extension. - test_list = [t for t in ALL_SCRIPTS if - (t in tests or re.sub(".py$", "", t) in tests)] + tests = [re.sub("\.py$", "", t) + ".py" for t in tests] + test_list = [] + for t in tests: + if t in ALL_SCRIPTS: + test_list.append(t) + else: + print("{}WARNING!{} Test '{}' not found in full test list.".format(BOLD[1], BOLD[0], t)) else: - # No individual tests have been specified. Run base tests, and - # optionally ZMQ tests and extended tests. + # No individual tests have been specified. + # Run all base tests, and optionally run extended tests. test_list = BASE_SCRIPTS - if enable_zmq: - test_list += ZMQ_SCRIPTS if args.extended: # place the EXTENDED_SCRIPTS first since the three longest ones # are there and the list is shorter @@ -233,9 +224,12 @@ def main(): # Remove the test cases that the user has explicitly asked to exclude. if args.exclude: - for exclude_test in args.exclude.split(','): - if exclude_test + ".py" in test_list: - test_list.remove(exclude_test + ".py") + tests_excl = [re.sub("\.py$", "", t) + ".py" for t in args.exclude.split(',')] + for exclude_test in tests_excl: + if exclude_test in test_list: + test_list.remove(exclude_test) + else: + print("{}WARNING!{} Test '{}' not found in current test list.".format(BOLD[1], BOLD[0], exclude_test)) if not test_list: print("No valid test scripts specified. Check that your test is in one " diff --git a/test/functional/txn_clone.py b/test/functional/txn_clone.py index 7a3b8d3474..9b81af96cf 100755 --- a/test/functional/txn_clone.py +++ b/test/functional/txn_clone.py @@ -20,7 +20,9 @@ class TxnMallTest(BitcoinTestFramework): def setup_network(self): # Start with split network: - return super(TxnMallTest, self).setup_network(True) + super(TxnMallTest, self).setup_network() + disconnect_nodes(self.nodes[1], 2) + disconnect_nodes(self.nodes[2], 1) def run_test(self): # All nodes should start with 1,250 BTC: diff --git a/test/functional/txn_doublespend.py b/test/functional/txn_doublespend.py index 5b12cf4c29..1bd3b3271c 100755 --- a/test/functional/txn_doublespend.py +++ b/test/functional/txn_doublespend.py @@ -20,7 +20,9 @@ class TxnMallTest(BitcoinTestFramework): def setup_network(self): # Start with split network: - return super(TxnMallTest, self).setup_network(True) + super().setup_network() + disconnect_nodes(self.nodes[1], 2) + disconnect_nodes(self.nodes[2], 1) def run_test(self): # All nodes should start with 1,250 BTC: diff --git a/test/functional/wallet-accounts.py b/test/functional/wallet-accounts.py index ea12d4ec22..e6635bea1c 100755 --- a/test/functional/wallet-accounts.py +++ b/test/functional/wallet-accounts.py @@ -7,6 +7,7 @@ RPCs tested are: - getaccountaddress - getaddressesbyaccount + - listaddressgroupings - setaccount - sendfrom (with account arguments) - move (with account arguments) @@ -14,7 +15,6 @@ RPCs tested are: from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( - start_nodes, assert_equal, ) @@ -24,22 +24,59 @@ class WalletAccountsTest(BitcoinTestFramework): super().__init__() self.setup_clean_chain = True self.num_nodes = 1 - self.node_args = [[]] + self.extra_args = [[]] - def setup_network(self): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.node_args) - self.is_network_split = False - - def run_test (self): + def run_test(self): node = self.nodes[0] # Check that there's no UTXO on any of the nodes assert_equal(len(node.listunspent()), 0) - + + # Note each time we call generate, all generated coins go into + # the same address, so we call twice to get two addresses w/50 each + node.generate(1) node.generate(101) - - assert_equal(node.getbalance(), 50) - - accounts = ["a","b","c","d","e"] + assert_equal(node.getbalance(), 100) + + # there should be 2 address groups + # each with 1 address with a balance of 50 Bitcoins + address_groups = node.listaddressgroupings() + assert_equal(len(address_groups), 2) + # the addresses aren't linked now, but will be after we send to the + # common address + linked_addresses = set() + for address_group in address_groups: + assert_equal(len(address_group), 1) + assert_equal(len(address_group[0]), 2) + assert_equal(address_group[0][1], 50) + linked_addresses.add(address_group[0][0]) + + # send 50 from each address to a third address not in this wallet + # There's some fee that will come back to us when the miner reward + # matures. + common_address = "msf4WtN1YQKXvNtvdFYt9JBnUD2FB41kjr" + txid = node.sendmany( + fromaccount="", + amounts={common_address: 100}, + subtractfeefrom=[common_address], + minconf=1, + ) + tx_details = node.gettransaction(txid) + fee = -tx_details['details'][0]['fee'] + # there should be 1 address group, with the previously + # unlinked addresses now linked (they both have 0 balance) + address_groups = node.listaddressgroupings() + assert_equal(len(address_groups), 1) + assert_equal(len(address_groups[0]), 2) + assert_equal(set([a[0] for a in address_groups[0]]), linked_addresses) + assert_equal([a[1] for a in address_groups[0]], [0, 0]) + + node.generate(1) + + # we want to reset so that the "" account has what's expected. + # otherwise we're off by exactly the fee amount as that's mined + # and matures in the next 100 blocks + node.sendfrom("", common_address, fee) + accounts = ["a", "b", "c", "d", "e"] amount_to_send = 1.0 account_addresses = dict() for account in accounts: @@ -56,7 +93,7 @@ class WalletAccountsTest(BitcoinTestFramework): for i in range(len(accounts)): from_account = accounts[i] - to_account = accounts[(i+1)%len(accounts)] + to_account = accounts[(i+1) % len(accounts)] to_address = account_addresses[to_account] node.sendfrom(from_account, to_address, amount_to_send) @@ -67,7 +104,7 @@ class WalletAccountsTest(BitcoinTestFramework): assert(address != account_addresses[account]) assert_equal(node.getreceivedbyaccount(account), 2) node.move(account, "", node.getbalance(account)) - + node.generate(101) expected_account_balances = {"": 5200} @@ -97,4 +134,4 @@ class WalletAccountsTest(BitcoinTestFramework): assert_equal(node.getbalance(account), 50) if __name__ == '__main__': - WalletAccountsTest().main () + WalletAccountsTest().main() diff --git a/test/functional/wallet-hd.py b/test/functional/wallet-hd.py index 64a6c92782..aab3b4bc2d 100755 --- a/test/functional/wallet-hd.py +++ b/test/functional/wallet-hd.py @@ -6,7 +6,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( - start_nodes, start_node, assert_equal, connect_nodes_bi, @@ -22,12 +21,7 @@ class WalletHDTest(BitcoinTestFramework): super().__init__() self.setup_clean_chain = True self.num_nodes = 2 - self.node_args = [['-usehd=0'], ['-usehd=1', '-keypool=0']] - - def setup_network(self): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.node_args) - self.is_network_split = False - connect_nodes_bi(self.nodes, 0, 1) + self.extra_args = [['-usehd=0'], ['-usehd=1', '-keypool=0']] def run_test (self): tmpdir = self.options.tmpdir @@ -35,7 +29,7 @@ class WalletHDTest(BitcoinTestFramework): # Make sure can't switch off usehd after wallet creation self.stop_node(1) assert_start_raises_init_error(1, self.options.tmpdir, ['-usehd=0'], 'already existing HD wallet') - self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1]) + self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1]) connect_nodes_bi(self.nodes, 0, 1) # Make sure we use hd, keep masterkeyid @@ -44,7 +38,7 @@ class WalletHDTest(BitcoinTestFramework): # create an internal key change_addr = self.nodes[1].getrawchangeaddress() - change_addrV= self.nodes[1].validateaddress(change_addr); + change_addrV= self.nodes[1].validateaddress(change_addr) assert_equal(change_addrV["hdkeypath"], "m/0'/1'/0'") #first internal child key # Import a non-HD private key in the HD wallet @@ -72,7 +66,7 @@ class WalletHDTest(BitcoinTestFramework): # create an internal key (again) change_addr = self.nodes[1].getrawchangeaddress() - change_addrV= self.nodes[1].validateaddress(change_addr); + change_addrV= self.nodes[1].validateaddress(change_addr) assert_equal(change_addrV["hdkeypath"], "m/0'/1'/1'") #second internal child key self.sync_all() @@ -82,7 +76,7 @@ class WalletHDTest(BitcoinTestFramework): self.stop_node(1) os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat") shutil.copyfile(tmpdir + "/hd.bak", tmpdir + "/node1/regtest/wallet.dat") - self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1]) + self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1]) #connect_nodes_bi(self.nodes, 0, 1) # Assert that derivation is deterministic @@ -96,13 +90,13 @@ class WalletHDTest(BitcoinTestFramework): # Needs rescan self.stop_node(1) - self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1] + ['-rescan']) + self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1] + ['-rescan']) #connect_nodes_bi(self.nodes, 0, 1) assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1) # send a tx and make sure its using the internal chain for the changeoutput txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1) - outs = self.nodes[1].decoderawtransaction(self.nodes[1].gettransaction(txid)['hex'])['vout']; + outs = self.nodes[1].decoderawtransaction(self.nodes[1].gettransaction(txid)['hex'])['vout'] keypath = "" for out in outs: if out['value'] != 1: diff --git a/test/functional/wallet.py b/test/functional/wallet.py index 80f74fa108..efde2e005e 100755 --- a/test/functional/wallet.py +++ b/test/functional/wallet.py @@ -6,7 +6,7 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -class WalletTest (BitcoinTestFramework): +class WalletTest(BitcoinTestFramework): def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size): """Return curr_balance after asserting the fee was in range""" @@ -20,15 +20,14 @@ class WalletTest (BitcoinTestFramework): self.num_nodes = 4 self.extra_args = [['-usehd={:d}'.format(i%2==0)] for i in range(4)] - def setup_network(self, split=False): + def setup_network(self): self.nodes = start_nodes(3, self.options.tmpdir, self.extra_args[:3]) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) - self.is_network_split=False self.sync_all() - def run_test (self): + def run_test(self): # Check that there's no UTXO on none of the nodes assert_equal(len(self.nodes[0].listunspent()), 0) @@ -52,14 +51,38 @@ class WalletTest (BitcoinTestFramework): assert_equal(self.nodes[2].getbalance(), 0) # Check that only first and second nodes have UTXOs - assert_equal(len(self.nodes[0].listunspent()), 1) + utxos = self.nodes[0].listunspent() + assert_equal(len(utxos), 1) assert_equal(len(self.nodes[1].listunspent()), 1) assert_equal(len(self.nodes[2].listunspent()), 0) # Send 21 BTC from 0 to 2 using sendtoaddress call. + # Locked memory should use at least 32 bytes to sign each transaction + self.log.info("test getmemoryinfo") + memory_before = self.nodes[0].getmemoryinfo() self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11) - self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10) - + mempool_txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10) + memory_after = self.nodes[0].getmemoryinfo() + assert(memory_before['locked']['used'] + 64 <= memory_after['locked']['used']) + + self.log.info("test gettxout") + # utxo spent in mempool should be visible if you exclude mempool + # but invisible if you include mempool + confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[0]["vout"] + txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, False) + assert_equal(txout['value'], 50) + txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, True) + assert txout is None + # new utxo from mempool should be invisible if you exclude mempool + # but visible if you include mempool + txout = self.nodes[0].gettxout(mempool_txid, 0, False) + assert txout is None + txout1 = self.nodes[0].gettxout(mempool_txid, 0, True) + txout2 = self.nodes[0].gettxout(mempool_txid, 1, True) + # note the mempool tx will have randomly assigned indices + # but 10 will go to node2 and the rest will go to node0 + balance = self.nodes[0].getbalance() + assert_equal(set([txout1['value'], txout2['value']]), set([10, balance])) walletinfo = self.nodes[0].getwalletinfo() assert_equal(walletinfo['immature_balance'], 0) diff --git a/test/functional/walletbackup.py b/test/functional/walletbackup.py index af1718572f..0492132af6 100755 --- a/test/functional/walletbackup.py +++ b/test/functional/walletbackup.py @@ -44,14 +44,12 @@ class WalletBackupTest(BitcoinTestFramework): # nodes 1, 2,3 are spenders, let's give them a keypool=100 self.extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []] - # This mirrors how the network was setup in the bash test def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) + self.setup_nodes() connect_nodes(self.nodes[0], 3) connect_nodes(self.nodes[1], 3) connect_nodes(self.nodes[2], 3) connect_nodes(self.nodes[2], 0) - self.is_network_split=False self.sync_all() def one_send(self, from_node, to_address): diff --git a/test/functional/zapwallettxes.py b/test/functional/zapwallettxes.py index ce446e44a3..7987edeb54 100755 --- a/test/functional/zapwallettxes.py +++ b/test/functional/zapwallettxes.py @@ -23,13 +23,9 @@ class ZapWalletTXesTest (BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 3 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes_bi(self.nodes,0,1) - connect_nodes_bi(self.nodes,1,2) + def setup_network(self): + super().setup_network() connect_nodes_bi(self.nodes,0,2) - self.is_network_split=False - self.sync_all() def run_test (self): self.log.info("Mining blocks...") diff --git a/test/functional/zmq_test.py b/test/functional/zmq_test.py index 9e27b46381..918e13bcd4 100755 --- a/test/functional/zmq_test.py +++ b/test/functional/zmq_test.py @@ -3,11 +3,13 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the ZMQ API.""" +import configparser +import os +import struct +import sys from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -import zmq -import struct class ZMQTest (BitcoinTestFramework): @@ -18,12 +20,29 @@ class ZMQTest (BitcoinTestFramework): port = 28332 def setup_nodes(self): + # Try to import python3-zmq. Skip this test if the import fails. + try: + import zmq + except ImportError: + self.log.warning("python3-zmq module not available. Skipping zmq tests!") + sys.exit(self.TEST_EXIT_SKIPPED) + + # Check that bitcoin has been built with ZMQ enabled + config = configparser.ConfigParser() + if not self.options.configfile: + self.options.configfile = os.path.dirname(__file__) + "/config.ini" + config.read_file(open(self.options.configfile)) + + if not config["components"].getboolean("ENABLE_ZMQ"): + self.log.warning("bitcoind has not been built with zmq enabled. Skipping zmq tests!") + sys.exit(self.TEST_EXIT_SKIPPED) + self.zmqContext = zmq.Context() self.zmqSubSocket = self.zmqContext.socket(zmq.SUB) self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashblock") self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashtx") self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % self.port) - return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[ + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[ ['-zmqpubhashtx=tcp://127.0.0.1:'+str(self.port), '-zmqpubhashblock=tcp://127.0.0.1:'+str(self.port)], [], [], diff --git a/test/util/data/blanktxv1.json b/test/util/data/blanktxv1.json index 51c25a5a98..9fe2de649b 100644 --- a/test/util/data/blanktxv1.json +++ b/test/util/data/blanktxv1.json @@ -2,6 +2,8 @@ "txid": "d21633ba23f70118185227be58a63527675641ad37967e2aa461559f577aec43", "hash": "d21633ba23f70118185227be58a63527675641ad37967e2aa461559f577aec43", "version": 1, + "size": 10, + "vsize": 10, "locktime": 0, "vin": [ ], diff --git a/test/util/data/blanktxv2.json b/test/util/data/blanktxv2.json index 266919f445..e97626e421 100644 --- a/test/util/data/blanktxv2.json +++ b/test/util/data/blanktxv2.json @@ -2,6 +2,8 @@ "txid": "4ebd325a4b394cff8c57e8317ccf5a8d0e2bdf1b8526f8aad6c8e43d8240621a", "hash": "4ebd325a4b394cff8c57e8317ccf5a8d0e2bdf1b8526f8aad6c8e43d8240621a", "version": 2, + "size": 10, + "vsize": 10, "locktime": 0, "vin": [ ], diff --git a/test/util/data/tt-delin1-out.json b/test/util/data/tt-delin1-out.json index 712a2c27f8..f6dfbb51cc 100644 --- a/test/util/data/tt-delin1-out.json +++ b/test/util/data/tt-delin1-out.json @@ -2,6 +2,8 @@ "txid": "81b2035be1da1abe745c6141174a73d151009ec17b3d5ebffa2e177408c50dfd", "hash": "81b2035be1da1abe745c6141174a73d151009ec17b3d5ebffa2e177408c50dfd", "version": 1, + "size": 3040, + "vsize": 3040, "locktime": 0, "vin": [ { diff --git a/test/util/data/tt-delout1-out.json b/test/util/data/tt-delout1-out.json index afc4e95762..6769ed79ff 100644 --- a/test/util/data/tt-delout1-out.json +++ b/test/util/data/tt-delout1-out.json @@ -2,6 +2,8 @@ "txid": "c46ccd75b5050e942b2e86a3648f843f525fe6fc000bf0534ba5973063354493", "hash": "c46ccd75b5050e942b2e86a3648f843f525fe6fc000bf0534ba5973063354493", "version": 1, + "size": 3155, + "vsize": 3155, "locktime": 0, "vin": [ { diff --git a/test/util/data/tt-locktime317000-out.json b/test/util/data/tt-locktime317000-out.json index 2b9075f8ac..82b64df075 100644 --- a/test/util/data/tt-locktime317000-out.json +++ b/test/util/data/tt-locktime317000-out.json @@ -2,6 +2,8 @@ "txid": "aded538f642c17e15f4d3306b8be7e1a4d1ae0c4616d641ab51ea09ba65e5cb5", "hash": "aded538f642c17e15f4d3306b8be7e1a4d1ae0c4616d641ab51ea09ba65e5cb5", "version": 1, + "size": 3189, + "vsize": 3189, "locktime": 317000, "vin": [ { diff --git a/test/util/data/txcreate1.json b/test/util/data/txcreate1.json index f83e036f33..36741044c9 100644 --- a/test/util/data/txcreate1.json +++ b/test/util/data/txcreate1.json @@ -2,6 +2,8 @@ "txid": "fe7d174f42dce0cffa7a527e9bc8368956057619ec817648f6138b98f2533e8f", "hash": "fe7d174f42dce0cffa7a527e9bc8368956057619ec817648f6138b98f2533e8f", "version": 2, + "size": 201, + "vsize": 201, "locktime": 0, "vin": [ { diff --git a/test/util/data/txcreate2.json b/test/util/data/txcreate2.json index fb5e177db7..23fe7ace67 100644 --- a/test/util/data/txcreate2.json +++ b/test/util/data/txcreate2.json @@ -2,6 +2,8 @@ "txid": "0481afb29931341d0d7861d8a2f6f26456fa042abf54a23e96440ed7946e0715", "hash": "0481afb29931341d0d7861d8a2f6f26456fa042abf54a23e96440ed7946e0715", "version": 2, + "size": 19, + "vsize": 19, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatedata1.json b/test/util/data/txcreatedata1.json index 760518d30a..e65a1859eb 100644 --- a/test/util/data/txcreatedata1.json +++ b/test/util/data/txcreatedata1.json @@ -2,6 +2,8 @@ "txid": "07894b4d12fe7853dd911402db1620920d261b9627c447f931417d330c25f06e", "hash": "07894b4d12fe7853dd911402db1620920d261b9627c447f931417d330c25f06e", "version": 1, + "size": 176, + "vsize": 176, "locktime": 0, "vin": [ { diff --git a/test/util/data/txcreatedata2.json b/test/util/data/txcreatedata2.json index 3c6da40f90..8f1544e1c0 100644 --- a/test/util/data/txcreatedata2.json +++ b/test/util/data/txcreatedata2.json @@ -2,6 +2,8 @@ "txid": "c14b007fa3a6c1e7765919c1d14c1cfc2b8642c3a5d3be4b1fa8c4ccfec98bb0", "hash": "c14b007fa3a6c1e7765919c1d14c1cfc2b8642c3a5d3be4b1fa8c4ccfec98bb0", "version": 2, + "size": 176, + "vsize": 176, "locktime": 0, "vin": [ { diff --git a/test/util/data/txcreatedata_seq0.json b/test/util/data/txcreatedata_seq0.json index d272a4c447..e52401f418 100644 --- a/test/util/data/txcreatedata_seq0.json +++ b/test/util/data/txcreatedata_seq0.json @@ -2,6 +2,8 @@ "txid": "8df6ed527472542dd5e137c242a7c5a9f337ac34f7b257ae4af886aeaebb51b0", "hash": "8df6ed527472542dd5e137c242a7c5a9f337ac34f7b257ae4af886aeaebb51b0", "version": 2, + "size": 85, + "vsize": 85, "locktime": 0, "vin": [ { diff --git a/test/util/data/txcreatedata_seq1.json b/test/util/data/txcreatedata_seq1.json index d323255418..093ff4a56b 100644 --- a/test/util/data/txcreatedata_seq1.json +++ b/test/util/data/txcreatedata_seq1.json @@ -2,6 +2,8 @@ "txid": "c4dea671b0d7b48f8ab10bc46650e8329d3c5766931f548f513847a19f5ba75b", "hash": "c4dea671b0d7b48f8ab10bc46650e8329d3c5766931f548f513847a19f5ba75b", "version": 1, + "size": 126, + "vsize": 126, "locktime": 0, "vin": [ { diff --git a/test/util/data/txcreatemultisig1.json b/test/util/data/txcreatemultisig1.json index f6ce43c202..0cc530836a 100644 --- a/test/util/data/txcreatemultisig1.json +++ b/test/util/data/txcreatemultisig1.json @@ -2,6 +2,8 @@ "txid": "0d1d4edfc217d9db3ab6a9298f26a52eae3c52f55a6cb8ccbc14f7c727572894", "hash": "0d1d4edfc217d9db3ab6a9298f26a52eae3c52f55a6cb8ccbc14f7c727572894", "version": 1, + "size": 124, + "vsize": 124, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatemultisig2.json b/test/util/data/txcreatemultisig2.json index e09d22060f..8ad2ffdc65 100644 --- a/test/util/data/txcreatemultisig2.json +++ b/test/util/data/txcreatemultisig2.json @@ -2,6 +2,8 @@ "txid": "0d861f278a3b7bce7cb5a88d71e6e6a903336f95ad5a2c29b295b63835b6eee3", "hash": "0d861f278a3b7bce7cb5a88d71e6e6a903336f95ad5a2c29b295b63835b6eee3", "version": 1, + "size": 42, + "vsize": 42, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatemultisig3.json b/test/util/data/txcreatemultisig3.json index 88e32bd310..086bf44b8a 100644 --- a/test/util/data/txcreatemultisig3.json +++ b/test/util/data/txcreatemultisig3.json @@ -2,6 +2,8 @@ "txid": "ccc552220b46a3b5140048b03395987ce4f0fa1ddf8c635bba1fa44e0f8c1d7f", "hash": "ccc552220b46a3b5140048b03395987ce4f0fa1ddf8c635bba1fa44e0f8c1d7f", "version": 1, + "size": 53, + "vsize": 53, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatemultisig4.json b/test/util/data/txcreatemultisig4.json index fc69c7269c..d23ccc045e 100644 --- a/test/util/data/txcreatemultisig4.json +++ b/test/util/data/txcreatemultisig4.json @@ -2,6 +2,8 @@ "txid": "5e8b1cc73234e208d4b7ca9075f136b908c34101be7a048df4ba9ac758b61567", "hash": "5e8b1cc73234e208d4b7ca9075f136b908c34101be7a048df4ba9ac758b61567", "version": 1, + "size": 42, + "vsize": 42, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreateoutpubkey1.json b/test/util/data/txcreateoutpubkey1.json index 6019fa2dcd..f10aaecf7a 100644 --- a/test/util/data/txcreateoutpubkey1.json +++ b/test/util/data/txcreateoutpubkey1.json @@ -2,6 +2,8 @@ "txid": "f42b38ac12e3fafc96ba1a9ba70cbfe326744aef75df5fb9db5d6e2855ca415f", "hash": "f42b38ac12e3fafc96ba1a9ba70cbfe326744aef75df5fb9db5d6e2855ca415f", "version": 1, + "size": 54, + "vsize": 54, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreateoutpubkey2.json b/test/util/data/txcreateoutpubkey2.json index 6fc3d57527..5a473b76c3 100644 --- a/test/util/data/txcreateoutpubkey2.json +++ b/test/util/data/txcreateoutpubkey2.json @@ -2,6 +2,8 @@ "txid": "70f2a088cde460e677415fa1fb71895e90c231e6ed38ed203a35b6f848e9cc73", "hash": "70f2a088cde460e677415fa1fb71895e90c231e6ed38ed203a35b6f848e9cc73", "version": 1, + "size": 41, + "vsize": 41, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreateoutpubkey3.json b/test/util/data/txcreateoutpubkey3.json index a1a25fc834..b8389b8f7e 100644 --- a/test/util/data/txcreateoutpubkey3.json +++ b/test/util/data/txcreateoutpubkey3.json @@ -2,6 +2,8 @@ "txid": "bfc7e898ee9f6a9652d7b8cca147e2da134502e2ada0f279ed634fc8cf833f8c", "hash": "bfc7e898ee9f6a9652d7b8cca147e2da134502e2ada0f279ed634fc8cf833f8c", "version": 1, + "size": 42, + "vsize": 42, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatescript1.json b/test/util/data/txcreatescript1.json index 8ffecba411..823168e9fb 100644 --- a/test/util/data/txcreatescript1.json +++ b/test/util/data/txcreatescript1.json @@ -2,6 +2,8 @@ "txid": "f0851b68202f736b792649cfc960259c2374badcb644ab20cac726b5f72f61c9", "hash": "f0851b68202f736b792649cfc960259c2374badcb644ab20cac726b5f72f61c9", "version": 1, + "size": 20, + "vsize": 20, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatescript2.json b/test/util/data/txcreatescript2.json index 41eb69f1af..d4c7e10c78 100644 --- a/test/util/data/txcreatescript2.json +++ b/test/util/data/txcreatescript2.json @@ -2,6 +2,8 @@ "txid": "6e07a7cc075e0703f32ee8c4e5373fe654bfbc315148fda364e1be286ff290d0", "hash": "6e07a7cc075e0703f32ee8c4e5373fe654bfbc315148fda364e1be286ff290d0", "version": 1, + "size": 42, + "vsize": 42, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatescript3.json b/test/util/data/txcreatescript3.json index 90e7e27f9f..001e69511f 100644 --- a/test/util/data/txcreatescript3.json +++ b/test/util/data/txcreatescript3.json @@ -2,6 +2,8 @@ "txid": "8a234037b088e987c877030efc83374a07441c321bf9dc6dd2f206bc26507df8", "hash": "8a234037b088e987c877030efc83374a07441c321bf9dc6dd2f206bc26507df8", "version": 1, + "size": 53, + "vsize": 53, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatescript4.json b/test/util/data/txcreatescript4.json index 11783751a4..20094bcd44 100644 --- a/test/util/data/txcreatescript4.json +++ b/test/util/data/txcreatescript4.json @@ -2,6 +2,8 @@ "txid": "24225cf5e9391100d6b218134b9f03383ca4c880a1f634ac12990cf28b66adbc", "hash": "24225cf5e9391100d6b218134b9f03383ca4c880a1f634ac12990cf28b66adbc", "version": 1, + "size": 42, + "vsize": 42, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatesignv1.json b/test/util/data/txcreatesignv1.json index ff39e71b40..519d3ab066 100644 --- a/test/util/data/txcreatesignv1.json +++ b/test/util/data/txcreatesignv1.json @@ -2,6 +2,8 @@ "txid": "977e7cd286cb72cd470d539ba6cb48400f8f387d97451d45cdb8819437a303af", "hash": "977e7cd286cb72cd470d539ba6cb48400f8f387d97451d45cdb8819437a303af", "version": 1, + "size": 224, + "vsize": 224, "locktime": 0, "vin": [ { |