aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorSjors Provoost <sjors@sprovoost.nl>2018-01-23 17:56:15 +0100
committerSjors Provoost <sjors@sprovoost.nl>2018-01-23 17:56:15 +0100
commit596c44633fd03e76cc12f2fd37452e223ba43115 (patch)
tree44646cccab6cd1dd47b1a4036d6260d517d066cd /test
parent44080a90a29292df96e92f22242785c5040000a1 (diff)
downloadbitcoin-596c44633fd03e76cc12f2fd37452e223ba43115.tar.xz
[wallet] use P2WPKH change output if any destination is P2WPKH or P2WSH
Only if -changetype is not set and -addresstype is not "legacy".
Diffstat (limited to 'test')
-rwxr-xr-xtest/functional/address_types.py125
1 files changed, 110 insertions, 15 deletions
diff --git a/test/functional/address_types.py b/test/functional/address_types.py
index cb119c04b0..32c561aae3 100755
--- a/test/functional/address_types.py
+++ b/test/functional/address_types.py
@@ -4,16 +4,24 @@
# 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:
+There are 5 nodes-under-test:
- node0 uses legacy addresses
- node1 uses p2sh/segwit addresses
- node2 uses p2sh/segwit addresses and bech32 addresses for change
- node3 uses bech32 addresses
+ - node4 uses a p2sh/segwit addresses for change
-node4 exists to generate new blocks.
+node5 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:
+## Multisig address test
+
+Test that adding a multisig address with:
+ - an uncompressed pubkey always gives a legacy address
+ - only compressed pubkeys gives the an `-addresstype` address
+
+## Sending to address types test
+
+A series of tests, iterating over node0-node4. 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
@@ -21,21 +29,51 @@ of the test, one node sends:
- 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, but with explicit address_type
-parameters passed to getnewaddress and getrawchangeaddress. Node0 and node3 send to p2sh,
-node 1 sends to bech32, and node2 sends to legacy. As every node sends coins after receiving,
-this also verifies that spending coins sent to all these address types works."""
+multisig addresses.
+
+Repeat test, but with explicit address_type parameters passed to getnewaddress
+and getrawchangeaddress:
+ - node0 and node3 send to p2sh.
+ - node1 sends to bech32.
+ - node2 sends to legacy.
+
+As every node sends coins after receiving, this also
+verifies that spending coins sent to all these address types works.
+
+## Change type test
+
+Test that the nodes generate the correct change address type:
+ - node0 always uses a legacy change address.
+ - node1 uses a bech32 addresses for change if any destination address is bech32.
+ - node2 always uses a bech32 address for change
+ - node3 always uses a bech32 address for change
+ - node4 always uses p2sh/segwit output for change.
+"""
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
+from test_framework.util import (
+ assert_equal,
+ assert_greater_than,
+ assert_raises_rpc_error,
+ connect_nodes_bi,
+ sync_blocks,
+ sync_mempools,
+)
class AddressTypeTest(BitcoinTestFramework):
def set_test_params(self):
- self.num_nodes = 5
- self.extra_args = [["-addresstype=legacy"], ["-addresstype=p2sh-segwit"], ["-addresstype=p2sh-segwit", "-changetype=bech32"], ["-addresstype=bech32"], []]
+ self.num_nodes = 6
+ self.extra_args = [
+ ["-addresstype=legacy"],
+ ["-addresstype=p2sh-segwit"],
+ ["-addresstype=p2sh-segwit", "-changetype=bech32"],
+ ["-addresstype=bech32"],
+ ["-changetype=p2sh-segwit"],
+ []
+ ]
def setup_network(self):
self.setup_nodes()
@@ -104,10 +142,26 @@ class AddressTypeTest(BitcoinTestFramework):
# Unknown type
assert(False)
+ def test_change_output_type(self, node_sender, destinations, expected_type):
+ txid = self.nodes[node_sender].sendmany(fromaccount="", amounts=dict.fromkeys(destinations, 0.001))
+ raw_tx = self.nodes[node_sender].getrawtransaction(txid)
+ tx = self.nodes[node_sender].decoderawtransaction(raw_tx)
+
+ # Make sure the transaction has change:
+ assert_equal(len(tx["vout"]), len(destinations) + 1)
+
+ # Make sure the destinations are included, and remove them:
+ output_addresses = [vout['scriptPubKey']['addresses'][0] for vout in tx["vout"]]
+ change_addresses = [d for d in output_addresses if d not in destinations]
+ assert_equal(len(change_addresses), 1)
+
+ self.log.debug("Check if change address " + change_addresses[0] + " is " + expected_type)
+ self.test_address(node_sender, change_addresses[0], multisig=False, typ=expected_type)
+
def run_test(self):
- # Mine 101 blocks on node4 to bring nodes out of IBD and make sure that
+ # Mine 101 blocks on node5 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)
+ self.nodes[5].generate(101)
sync_blocks(self.nodes)
uncompressed_1 = "0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee"
@@ -182,8 +236,8 @@ class AddressTypeTest(BitcoinTestFramework):
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)
+ # node5 collects fee and block subsidy to keep accounting simple
+ self.nodes[5].generate(1)
sync_blocks(self.nodes)
new_balances = self.get_balances()
@@ -195,5 +249,46 @@ class AddressTypeTest(BitcoinTestFramework):
to_node %= 4
assert_equal(new_balances[to_node], old_balances[to_node] + to_send * 10 * (2 + n))
+ # Get one p2sh/segwit address from node2 and two bech32 addresses from node3:
+ to_address_p2sh = self.nodes[2].getnewaddress()
+ to_address_bech32_1 = self.nodes[3].getnewaddress()
+ to_address_bech32_2 = self.nodes[3].getnewaddress()
+
+ # Fund node 4:
+ self.nodes[5].sendtoaddress(self.nodes[4].getnewaddress(), Decimal("1"))
+ self.nodes[5].generate(1)
+ sync_blocks(self.nodes)
+ assert_equal(self.nodes[4].getbalance(), 1)
+
+ self.log.info("Nodes with addresstype=legacy never use a P2WPKH change output")
+ self.test_change_output_type(0, [to_address_bech32_1], 'legacy')
+
+ self.log.info("Nodes with addresstype=p2sh-segwit only use a P2WPKH change output if any destination address is bech32:")
+ self.test_change_output_type(1, [to_address_p2sh], 'p2sh-segwit')
+ self.test_change_output_type(1, [to_address_bech32_1], 'bech32')
+ self.test_change_output_type(1, [to_address_p2sh, to_address_bech32_1], 'bech32')
+ self.test_change_output_type(1, [to_address_bech32_1, to_address_bech32_2], 'bech32')
+
+ self.log.info("Nodes with change_type=bech32 always use a P2WPKH change output:")
+ self.test_change_output_type(2, [to_address_bech32_1], 'bech32')
+ self.test_change_output_type(2, [to_address_p2sh], 'bech32')
+
+ self.log.info("Nodes with addresstype=bech32 always use a P2WPKH change output (unless changetype is set otherwise):")
+ self.test_change_output_type(3, [to_address_bech32_1], 'bech32')
+ self.test_change_output_type(3, [to_address_p2sh], 'bech32')
+
+ self.log.info('getrawchangeaddress defaults to addresstype if -changetype is not set and argument is absent')
+ self.test_address(3, self.nodes[3].getrawchangeaddress(), multisig=False, typ='bech32')
+
+ self.log.info('getrawchangeaddress fails with invalid changetype argument')
+ assert_raises_rpc_error(-5, "Unknown address type 'bech23'", self.nodes[3].getrawchangeaddress, 'bech23')
+
+ self.log.info("Nodes with changetype=p2sh-segwit never use a P2WPKH change output")
+ self.test_change_output_type(4, [to_address_bech32_1], 'p2sh-segwit')
+ self.test_address(4, self.nodes[4].getrawchangeaddress(), multisig=False, typ='p2sh-segwit')
+ self.log.info("Except for getrawchangeaddress if specified:")
+ self.test_address(4, self.nodes[4].getrawchangeaddress(), multisig=False, typ='p2sh-segwit')
+ self.test_address(4, self.nodes[4].getrawchangeaddress('bech32'), multisig=False, typ='bech32')
+
if __name__ == '__main__':
AddressTypeTest().main()