PageRenderTime 1449ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/test/functional/wallet_address_types.py

https://github.com/bitcoin/bitcoin
Python | 400 lines | 308 code | 14 blank | 78 comment | 38 complexity | cb8e93f4dd6a07983ad34b081a0dd38b MD5 | raw file
  1. #!/usr/bin/env python3
  2. # Copyright (c) 2017-2021 The Bitcoin Core developers
  3. # Distributed under the MIT software license, see the accompanying
  4. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5. """Test that the wallet can send and receive using all combinations of address types.
  6. There are 5 nodes-under-test:
  7. - node0 uses legacy addresses
  8. - node1 uses p2sh/segwit addresses
  9. - node2 uses p2sh/segwit addresses and bech32 addresses for change
  10. - node3 uses bech32 addresses
  11. - node4 uses a p2sh/segwit addresses for change
  12. node5 exists to generate new blocks.
  13. ## Multisig address test
  14. Test that adding a multisig address with:
  15. - an uncompressed pubkey always gives a legacy address
  16. - only compressed pubkeys gives the an `-addresstype` address
  17. ## Sending to address types test
  18. A series of tests, iterating over node0-node4. In each iteration of the test, one node sends:
  19. - 10/101th of its balance to itself (using getrawchangeaddress for single key addresses)
  20. - 20/101th to the next node
  21. - 30/101th to the node after that
  22. - 40/101th to the remaining node
  23. - 1/101th remains as fee+change
  24. Iterate over each node for single key addresses, and then over each node for
  25. multisig addresses.
  26. Repeat test, but with explicit address_type parameters passed to getnewaddress
  27. and getrawchangeaddress:
  28. - node0 and node3 send to p2sh.
  29. - node1 sends to bech32.
  30. - node2 sends to legacy.
  31. As every node sends coins after receiving, this also
  32. verifies that spending coins sent to all these address types works.
  33. ## Change type test
  34. Test that the nodes generate the correct change address type:
  35. - node0 always uses a legacy change address.
  36. - node1 uses a bech32 addresses for change if any destination address is bech32.
  37. - node2 always uses a bech32 address for change
  38. - node3 always uses a bech32 address for change
  39. - node4 always uses p2sh/segwit output for change.
  40. """
  41. from decimal import Decimal
  42. import itertools
  43. from test_framework.blocktools import COINBASE_MATURITY
  44. from test_framework.test_framework import BitcoinTestFramework
  45. from test_framework.descriptors import (
  46. descsum_create,
  47. descsum_check,
  48. )
  49. from test_framework.util import (
  50. assert_equal,
  51. assert_greater_than,
  52. assert_raises_rpc_error,
  53. )
  54. class AddressTypeTest(BitcoinTestFramework):
  55. def set_test_params(self):
  56. self.num_nodes = 6
  57. self.extra_args = [
  58. ["-addresstype=legacy"],
  59. ["-addresstype=p2sh-segwit"],
  60. ["-addresstype=p2sh-segwit", "-changetype=bech32"],
  61. ["-addresstype=bech32"],
  62. ["-changetype=p2sh-segwit"],
  63. [],
  64. ]
  65. # whitelist all peers to speed up tx relay / mempool sync
  66. for args in self.extra_args:
  67. args.append("-whitelist=noban@127.0.0.1")
  68. self.supports_cli = False
  69. def skip_test_if_missing_module(self):
  70. self.skip_if_no_wallet()
  71. def setup_network(self):
  72. self.setup_nodes()
  73. # Fully mesh-connect nodes for faster mempool sync
  74. for i, j in itertools.product(range(self.num_nodes), repeat=2):
  75. if i > j:
  76. self.connect_nodes(i, j)
  77. self.sync_all()
  78. def get_balances(self, key='trusted'):
  79. """Return a list of balances."""
  80. return [self.nodes[i].getbalances()['mine'][key] for i in range(4)]
  81. def test_address(self, node, address, multisig, typ):
  82. """Run sanity checks on an address."""
  83. info = self.nodes[node].getaddressinfo(address)
  84. assert self.nodes[node].validateaddress(address)['isvalid']
  85. assert_equal(info.get('solvable'), True)
  86. if not multisig and typ == 'legacy':
  87. # P2PKH
  88. assert not info['isscript']
  89. assert not info['iswitness']
  90. assert 'pubkey' in info
  91. elif not multisig and typ == 'p2sh-segwit':
  92. # P2SH-P2WPKH
  93. assert info['isscript']
  94. assert not info['iswitness']
  95. assert_equal(info['script'], 'witness_v0_keyhash')
  96. assert 'pubkey' in info
  97. elif not multisig and typ == 'bech32':
  98. # P2WPKH
  99. assert not info['isscript']
  100. assert info['iswitness']
  101. assert_equal(info['witness_version'], 0)
  102. assert_equal(len(info['witness_program']), 40)
  103. assert 'pubkey' in info
  104. elif not multisig and typ == "bech32m":
  105. # P2TR single sig
  106. assert info["isscript"]
  107. assert info["iswitness"]
  108. assert_equal(info["witness_version"], 1)
  109. assert_equal(len(info["witness_program"]), 64)
  110. elif typ == 'legacy':
  111. # P2SH-multisig
  112. assert info['isscript']
  113. assert_equal(info['script'], 'multisig')
  114. assert not info['iswitness']
  115. assert 'pubkeys' in info
  116. elif typ == 'p2sh-segwit':
  117. # P2SH-P2WSH-multisig
  118. assert info['isscript']
  119. assert_equal(info['script'], 'witness_v0_scripthash')
  120. assert not info['iswitness']
  121. assert info['embedded']['isscript']
  122. assert_equal(info['embedded']['script'], 'multisig')
  123. assert info['embedded']['iswitness']
  124. assert_equal(info['embedded']['witness_version'], 0)
  125. assert_equal(len(info['embedded']['witness_program']), 64)
  126. assert 'pubkeys' in info['embedded']
  127. elif typ == 'bech32':
  128. # P2WSH-multisig
  129. assert info['isscript']
  130. assert_equal(info['script'], 'multisig')
  131. assert info['iswitness']
  132. assert_equal(info['witness_version'], 0)
  133. assert_equal(len(info['witness_program']), 64)
  134. assert 'pubkeys' in info
  135. else:
  136. # Unknown type
  137. assert False
  138. def test_desc(self, node, address, multisig, typ, utxo):
  139. """Run sanity checks on a descriptor reported by getaddressinfo."""
  140. info = self.nodes[node].getaddressinfo(address)
  141. assert 'desc' in info
  142. assert_equal(info['desc'], utxo['desc'])
  143. assert self.nodes[node].validateaddress(address)['isvalid']
  144. # Use a ridiculously roundabout way to find the key origin info through
  145. # the PSBT logic. However, this does test consistency between the PSBT reported
  146. # fingerprints/paths and the descriptor logic.
  147. psbt = self.nodes[node].createpsbt([{'txid':utxo['txid'], 'vout':utxo['vout']}],[{address:0.00010000}])
  148. psbt = self.nodes[node].walletprocesspsbt(psbt, False, "ALL", True)
  149. decode = self.nodes[node].decodepsbt(psbt['psbt'])
  150. key_descs = {}
  151. for deriv in decode['inputs'][0]['bip32_derivs']:
  152. assert_equal(len(deriv['master_fingerprint']), 8)
  153. assert_equal(deriv['path'][0], 'm')
  154. key_descs[deriv['pubkey']] = '[' + deriv['master_fingerprint'] + deriv['path'][1:] + ']' + deriv['pubkey']
  155. # Verify the descriptor checksum against the Python implementation
  156. assert descsum_check(info['desc'])
  157. # Verify that stripping the checksum and recreating it using Python roundtrips
  158. assert info['desc'] == descsum_create(info['desc'][:-9])
  159. # Verify that stripping the checksum and feeding it to getdescriptorinfo roundtrips
  160. assert info['desc'] == self.nodes[0].getdescriptorinfo(info['desc'][:-9])['descriptor']
  161. assert_equal(info['desc'][-8:], self.nodes[0].getdescriptorinfo(info['desc'][:-9])['checksum'])
  162. # Verify that keeping the checksum and feeding it to getdescriptorinfo roundtrips
  163. assert info['desc'] == self.nodes[0].getdescriptorinfo(info['desc'])['descriptor']
  164. assert_equal(info['desc'][-8:], self.nodes[0].getdescriptorinfo(info['desc'])['checksum'])
  165. if not multisig and typ == 'legacy':
  166. # P2PKH
  167. assert_equal(info['desc'], descsum_create("pkh(%s)" % key_descs[info['pubkey']]))
  168. elif not multisig and typ == 'p2sh-segwit':
  169. # P2SH-P2WPKH
  170. assert_equal(info['desc'], descsum_create("sh(wpkh(%s))" % key_descs[info['pubkey']]))
  171. elif not multisig and typ == 'bech32':
  172. # P2WPKH
  173. assert_equal(info['desc'], descsum_create("wpkh(%s)" % key_descs[info['pubkey']]))
  174. elif typ == 'legacy':
  175. # P2SH-multisig
  176. assert_equal(info['desc'], descsum_create("sh(multi(2,%s,%s))" % (key_descs[info['pubkeys'][0]], key_descs[info['pubkeys'][1]])))
  177. elif typ == 'p2sh-segwit':
  178. # P2SH-P2WSH-multisig
  179. assert_equal(info['desc'], descsum_create("sh(wsh(multi(2,%s,%s)))" % (key_descs[info['embedded']['pubkeys'][0]], key_descs[info['embedded']['pubkeys'][1]])))
  180. elif typ == 'bech32':
  181. # P2WSH-multisig
  182. assert_equal(info['desc'], descsum_create("wsh(multi(2,%s,%s))" % (key_descs[info['pubkeys'][0]], key_descs[info['pubkeys'][1]])))
  183. else:
  184. # Unknown type
  185. assert False
  186. def test_change_output_type(self, node_sender, destinations, expected_type):
  187. txid = self.nodes[node_sender].sendmany(dummy="", amounts=dict.fromkeys(destinations, 0.001))
  188. tx = self.nodes[node_sender].gettransaction(txid=txid, verbose=True)['decoded']
  189. # Make sure the transaction has change:
  190. assert_equal(len(tx["vout"]), len(destinations) + 1)
  191. # Make sure the destinations are included, and remove them:
  192. output_addresses = [vout['scriptPubKey']['address'] for vout in tx["vout"]]
  193. change_addresses = [d for d in output_addresses if d not in destinations]
  194. assert_equal(len(change_addresses), 1)
  195. self.log.debug("Check if change address " + change_addresses[0] + " is " + expected_type)
  196. self.test_address(node_sender, change_addresses[0], multisig=False, typ=expected_type)
  197. def run_test(self):
  198. # Mine 101 blocks on node5 to bring nodes out of IBD and make sure that
  199. # no coinbases are maturing for the nodes-under-test during the test
  200. self.generate(self.nodes[5], COINBASE_MATURITY + 1)
  201. uncompressed_1 = "0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee"
  202. uncompressed_2 = "047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77"
  203. compressed_1 = "0296b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52"
  204. compressed_2 = "037211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073"
  205. if not self.options.descriptors:
  206. # Tests for addmultisigaddress's address type behavior is only for legacy wallets.
  207. # Descriptor wallets do not have addmultsigaddress so these tests are not needed for those.
  208. # addmultisigaddress with at least 1 uncompressed key should return a legacy address.
  209. for node in range(4):
  210. self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, uncompressed_2])['address'], True, 'legacy')
  211. self.test_address(node, self.nodes[node].addmultisigaddress(2, [compressed_1, uncompressed_2])['address'], True, 'legacy')
  212. self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, compressed_2])['address'], True, 'legacy')
  213. # addmultisigaddress with all compressed keys should return the appropriate address type (even when the keys are not ours).
  214. self.test_address(0, self.nodes[0].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'legacy')
  215. self.test_address(1, self.nodes[1].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit')
  216. self.test_address(2, self.nodes[2].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit')
  217. self.test_address(3, self.nodes[3].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'bech32')
  218. do_multisigs = [False]
  219. if not self.options.descriptors:
  220. do_multisigs.append(True)
  221. for explicit_type, multisig, from_node in itertools.product([False, True], do_multisigs, range(4)):
  222. address_type = None
  223. if explicit_type and not multisig:
  224. if from_node == 1:
  225. address_type = 'bech32'
  226. elif from_node == 0 or from_node == 3:
  227. address_type = 'p2sh-segwit'
  228. else:
  229. address_type = 'legacy'
  230. self.log.info("Sending from node {} ({}) with{} multisig using {}".format(from_node, self.extra_args[from_node], "" if multisig else "out", "default" if address_type is None else address_type))
  231. old_balances = self.get_balances()
  232. self.log.debug("Old balances are {}".format(old_balances))
  233. to_send = (old_balances[from_node] / (COINBASE_MATURITY + 1)).quantize(Decimal("0.00000001"))
  234. sends = {}
  235. addresses = {}
  236. self.log.debug("Prepare sends")
  237. for n, to_node in enumerate(range(from_node, from_node + 4)):
  238. to_node %= 4
  239. change = False
  240. if not multisig:
  241. if from_node == to_node:
  242. # When sending non-multisig to self, use getrawchangeaddress
  243. address = self.nodes[to_node].getrawchangeaddress(address_type=address_type)
  244. change = True
  245. else:
  246. address = self.nodes[to_node].getnewaddress(address_type=address_type)
  247. else:
  248. addr1 = self.nodes[to_node].getnewaddress()
  249. addr2 = self.nodes[to_node].getnewaddress()
  250. address = self.nodes[to_node].addmultisigaddress(2, [addr1, addr2])['address']
  251. # Do some sanity checking on the created address
  252. if address_type is not None:
  253. typ = address_type
  254. elif to_node == 0:
  255. typ = 'legacy'
  256. elif to_node == 1 or (to_node == 2 and not change):
  257. typ = 'p2sh-segwit'
  258. else:
  259. typ = 'bech32'
  260. self.test_address(to_node, address, multisig, typ)
  261. # Output entry
  262. sends[address] = to_send * 10 * (1 + n)
  263. addresses[to_node] = (address, typ)
  264. self.log.debug("Sending: {}".format(sends))
  265. self.nodes[from_node].sendmany("", sends)
  266. self.sync_mempools()
  267. unconf_balances = self.get_balances('untrusted_pending')
  268. self.log.debug("Check unconfirmed balances: {}".format(unconf_balances))
  269. assert_equal(unconf_balances[from_node], 0)
  270. for n, to_node in enumerate(range(from_node + 1, from_node + 4)):
  271. to_node %= 4
  272. assert_equal(unconf_balances[to_node], to_send * 10 * (2 + n))
  273. # node5 collects fee and block subsidy to keep accounting simple
  274. self.generate(self.nodes[5], 1)
  275. # Verify that the receiving wallet contains a UTXO with the expected address, and expected descriptor
  276. for n, to_node in enumerate(range(from_node, from_node + 4)):
  277. to_node %= 4
  278. found = False
  279. for utxo in self.nodes[to_node].listunspent():
  280. if utxo['address'] == addresses[to_node][0]:
  281. found = True
  282. self.test_desc(to_node, addresses[to_node][0], multisig, addresses[to_node][1], utxo)
  283. break
  284. assert found
  285. new_balances = self.get_balances()
  286. self.log.debug("Check new balances: {}".format(new_balances))
  287. # We don't know what fee was set, so we can only check bounds on the balance of the sending node
  288. assert_greater_than(new_balances[from_node], to_send * 10)
  289. assert_greater_than(to_send * 11, new_balances[from_node])
  290. for n, to_node in enumerate(range(from_node + 1, from_node + 4)):
  291. to_node %= 4
  292. assert_equal(new_balances[to_node], old_balances[to_node] + to_send * 10 * (2 + n))
  293. # Get one p2sh/segwit address from node2 and two bech32 addresses from node3:
  294. to_address_p2sh = self.nodes[2].getnewaddress()
  295. to_address_bech32_1 = self.nodes[3].getnewaddress()
  296. to_address_bech32_2 = self.nodes[3].getnewaddress()
  297. # Fund node 4:
  298. self.nodes[5].sendtoaddress(self.nodes[4].getnewaddress(), Decimal("1"))
  299. self.generate(self.nodes[5], 1)
  300. assert_equal(self.nodes[4].getbalance(), 1)
  301. self.log.info("Nodes with addresstype=legacy never use a P2WPKH change output (unless changetype is set otherwise):")
  302. self.test_change_output_type(0, [to_address_bech32_1], 'legacy')
  303. if self.options.descriptors:
  304. self.log.info("Nodes with addresstype=p2sh-segwit match the change output")
  305. self.test_change_output_type(1, [to_address_p2sh], 'p2sh-segwit')
  306. self.test_change_output_type(1, [to_address_bech32_1], 'bech32')
  307. self.test_change_output_type(1, [to_address_p2sh, to_address_bech32_1], 'bech32')
  308. self.test_change_output_type(1, [to_address_bech32_1, to_address_bech32_2], 'bech32')
  309. else:
  310. self.log.info("Nodes with addresstype=p2sh-segwit match the change output")
  311. self.test_change_output_type(1, [to_address_p2sh], 'p2sh-segwit')
  312. self.test_change_output_type(1, [to_address_bech32_1], 'bech32')
  313. self.test_change_output_type(1, [to_address_p2sh, to_address_bech32_1], 'bech32')
  314. self.test_change_output_type(1, [to_address_bech32_1, to_address_bech32_2], 'bech32')
  315. self.log.info("Nodes with change_type=bech32 always use a P2WPKH change output:")
  316. self.test_change_output_type(2, [to_address_bech32_1], 'bech32')
  317. self.test_change_output_type(2, [to_address_p2sh], 'bech32')
  318. if self.options.descriptors:
  319. self.log.info("Nodes with addresstype=bech32 match the change output (unless changetype is set otherwise):")
  320. self.test_change_output_type(3, [to_address_bech32_1], 'bech32')
  321. self.test_change_output_type(3, [to_address_p2sh], 'p2sh-segwit')
  322. else:
  323. self.log.info("Nodes with addresstype=bech32 match the change output (unless changetype is set otherwise):")
  324. self.test_change_output_type(3, [to_address_bech32_1], 'bech32')
  325. self.test_change_output_type(3, [to_address_p2sh], 'p2sh-segwit')
  326. self.log.info('getrawchangeaddress defaults to addresstype if -changetype is not set and argument is absent')
  327. self.test_address(3, self.nodes[3].getrawchangeaddress(), multisig=False, typ='bech32')
  328. self.log.info('test invalid address type arguments')
  329. assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].addmultisigaddress, 2, [compressed_1, compressed_2], None, '')
  330. assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getnewaddress, None, '')
  331. assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getrawchangeaddress, '')
  332. assert_raises_rpc_error(-5, "Unknown address type 'bech23'", self.nodes[3].getrawchangeaddress, 'bech23')
  333. self.log.info("Nodes with changetype=p2sh-segwit never use a P2WPKH change output")
  334. self.test_change_output_type(4, [to_address_bech32_1], 'p2sh-segwit')
  335. self.test_address(4, self.nodes[4].getrawchangeaddress(), multisig=False, typ='p2sh-segwit')
  336. self.log.info("Except for getrawchangeaddress if specified:")
  337. self.test_address(4, self.nodes[4].getrawchangeaddress(), multisig=False, typ='p2sh-segwit')
  338. self.test_address(4, self.nodes[4].getrawchangeaddress('bech32'), multisig=False, typ='bech32')
  339. if self.options.descriptors:
  340. self.log.info("Descriptor wallets have bech32m addresses")
  341. self.test_address(4, self.nodes[4].getnewaddress("", "bech32m"), multisig=False, typ="bech32m")
  342. self.test_address(4, self.nodes[4].getrawchangeaddress("bech32m"), multisig=False, typ="bech32m")
  343. else:
  344. self.log.info("Legacy wallets cannot make bech32m addresses")
  345. assert_raises_rpc_error(-8, "Legacy wallets cannot provide bech32m addresses", self.nodes[0].getnewaddress, "", "bech32m")
  346. assert_raises_rpc_error(-8, "Legacy wallets cannot provide bech32m addresses", self.nodes[0].getrawchangeaddress, "bech32m")
  347. if __name__ == '__main__':
  348. AddressTypeTest().main()