Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13115702
D6131.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Subscribers
None
D6131.diff
View Options
diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py
new file mode 100755
--- /dev/null
+++ b/test/functional/wallet_address_types.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python3
+# Copyright (c) 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 that the wallet can send and receive using all combinations of address types.
+
+There are 4 nodes-under-test:
+ - node0 uses legacy addresses
+ - node1 uses legacy addresses
+ - node2 uses legacy addresses
+ - node3 uses legacy addresses
+
+node4 exists to generate new blocks.
+
+The script is a series of tests, iterating over the 4 nodes. In each iteration
+of the test, one node sends:
+ - 10/101th of its balance to itself (using getrawchangeaddress for single key addresses)
+ - 20/101th to the next node
+ - 30/101th to the node after that
+ - 40/101th to the remaining node
+ - 1/101th remains as fee+change
+
+Iterate over each node for single key addresses, and then over each node for
+multisig addresses. In a second iteration, the same is done. As every node
+sends coins after receiving, this also verifies that spending coins sent to
+all these address works."""
+
+from decimal import Decimal
+import itertools
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal, assert_greater_than, connect_nodes_bi, sync_blocks, sync_mempools
+
+
+class AddressTypeTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 5
+ # whitelist all peers to speed up tx relay / mempool sync
+ self.extra_args = [["-whitelist=127.0.0.1"]] * self.num_nodes
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ def setup_network(self):
+ self.setup_nodes()
+
+ # Fully mesh-connect nodes for faster mempool sync
+ for i, j in itertools.product(range(self.num_nodes), repeat=2):
+ if i > j:
+ connect_nodes_bi(self.nodes[i], self.nodes[j])
+ self.sync_all()
+
+ def get_balances(self, confirmed=True):
+ """Return a list of confirmed or unconfirmed balances."""
+ if confirmed:
+ return [self.nodes[i].getbalance() for i in range(4)]
+ else:
+ return [self.nodes[i].getunconfirmedbalance() for i in range(4)]
+
+ def test_address(self, node, address, multisig, typ):
+ """Run sanity checks on an address."""
+ self.log.info(address)
+ info = self.nodes[node].getaddressinfo(address)
+ assert(self.nodes[node].validateaddress(address)['isvalid'])
+ if not multisig and typ == 'legacy':
+ # P2PKH
+ assert(not info['isscript'])
+ assert('pubkey' in info)
+ elif typ == 'legacy':
+ # P2SH-multisig
+ assert(info['isscript'])
+ assert_equal(info['script'], 'multisig')
+ assert('pubkeys' in info)
+ else:
+ # Unknown type
+ assert(False)
+
+ def run_test(self):
+ # Mine 101 blocks on node4 to bring nodes out of IBD and make sure that
+ # no coinbases are maturing for the nodes-under-test during the test
+ self.nodes[4].generate(101)
+ sync_blocks(self.nodes)
+
+ uncompressed_1 = "0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee"
+ uncompressed_2 = "047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77"
+ compressed_1 = "0296b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52"
+ compressed_2 = "037211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073"
+
+ # addmultisigaddress with at least 1 uncompressed key should return a
+ # legacy address.
+ for node in range(4):
+ self.test_address(node, self.nodes[node].addmultisigaddress(
+ 2, [uncompressed_1, uncompressed_2])['address'], True, 'legacy')
+ self.test_address(node, self.nodes[node].addmultisigaddress(
+ 2, [compressed_1, uncompressed_2])['address'], True, 'legacy')
+ self.test_address(node, self.nodes[node].addmultisigaddress(
+ 2, [uncompressed_1, compressed_2])['address'], True, 'legacy')
+ # addmultisigaddress with all compressed keys should return the
+ # appropriate address type (even when the keys are not ours).
+ self.test_address(0, self.nodes[0].addmultisigaddress(
+ 2, [compressed_1, compressed_2])['address'], True, 'legacy')
+
+ for multisig, from_node in itertools.product([False, True], range(4)):
+ self.log.info(
+ "Sending from node {} with{} multisig".format(from_node, "" if multisig else "out"))
+ old_balances = self.get_balances()
+ self.log.debug("Old balances are {}".format(old_balances))
+ to_send = (
+ old_balances[from_node] /
+ 101).quantize(
+ Decimal("0.00000001"))
+ sends = {}
+
+ self.log.debug("Prepare sends")
+ for n, to_node in enumerate(range(from_node, from_node + 4)):
+ to_node %= 4
+ if not multisig:
+ if from_node == to_node:
+ # When sending non-multisig to self, use
+ # getrawchangeaddress
+ address = self.nodes[to_node].getrawchangeaddress()
+ else:
+ address = self.nodes[to_node].getnewaddress()
+ else:
+ addr1 = self.nodes[to_node].getnewaddress()
+ addr2 = self.nodes[to_node].getnewaddress()
+ address = self.nodes[to_node].addmultisigaddress(2, [addr1, addr2])[
+ 'address']
+
+ # Do some sanity checking on the created address
+ typ = 'legacy'
+ self.test_address(to_node, address, multisig, typ)
+
+ # Output entry
+ sends[address] = to_send * 10 * (1 + n)
+
+ self.log.debug("Sending: {}".format(sends))
+ self.nodes[from_node].sendmany("", sends)
+ sync_mempools(self.nodes)
+
+ unconf_balances = self.get_balances(False)
+ self.log.debug(
+ "Check unconfirmed balances: {}".format(unconf_balances))
+ assert_equal(unconf_balances[from_node], 0)
+ for n, to_node in enumerate(range(from_node + 1, from_node + 4)):
+ to_node %= 4
+ assert_equal(unconf_balances[to_node], to_send * 10 * (2 + n))
+
+ # node4 collects fee and block subsidy to keep accounting simple
+ self.nodes[4].generate(1)
+ sync_blocks(self.nodes)
+
+ new_balances = self.get_balances()
+ self.log.debug("Check new balances: {}".format(new_balances))
+ # We don't know what fee was set, so we can only check bounds on
+ # the balance of the sending node
+ assert_greater_than(new_balances[from_node], to_send * 10)
+ assert_greater_than(to_send * 11, new_balances[from_node])
+ for n, to_node in enumerate(range(from_node + 1, from_node + 4)):
+ to_node %= 4
+ assert_equal(
+ new_balances[to_node], old_balances[to_node] + to_send * 10 * (2 + n))
+
+
+if __name__ == '__main__':
+ AddressTypeTest().main()
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 1, 11:47 (3 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187694
Default Alt Text
D6131.diff (7 KB)
Attached To
D6131: Add address_types test
Event Timeline
Log In to Comment