Changeset View
Changeset View
Standalone View
Standalone View
test/functional/wallet_importmulti.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2014-2019 The Bitcoin Core developers | # Copyright (c) 2014-2019 The Bitcoin Core developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
"""Test the importmulti RPC. | """Test the importmulti RPC. | ||||
Test importmulti by generating keys on node0, importing the scriptPubKeys and | Test importmulti by generating keys on node0, importing the scriptPubKeys and | ||||
addresses on node1 and then testing the address info for the different address | addresses on node1 and then testing the address info for the different address | ||||
variants. | variants. | ||||
- `get_key()` and `get_multisig()` are called to generate keys on node0 and | - `get_key()` and `get_multisig()` are called to generate keys on node0 and | ||||
return the privkeys, pubkeys and all variants of scriptPubKey and address. | return the privkeys, pubkeys and all variants of scriptPubKey and address. | ||||
- `test_importmulti()` is called to send an importmulti call to node1, test | - `test_importmulti()` is called to send an importmulti call to node1, test | ||||
success, and (if unsuccessful) test the error code and error message returned.""" | success, and (if unsuccessful) test the error code and error message returned. | ||||
- `test_address()` is called to call getaddressinfo for an address on node1 | |||||
and test the values returned.""" | |||||
from collections import namedtuple | from collections import namedtuple | ||||
from test_framework.address import ( | from test_framework.address import ( | ||||
key_to_p2pkh, | key_to_p2pkh, | ||||
script_to_p2sh, | script_to_p2sh, | ||||
) | ) | ||||
from test_framework.script import ( | from test_framework.script import ( | ||||
CScript, | CScript, | ||||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | def test_importmulti(self, req, success, | ||||
error_code=None, error_message=None): | error_code=None, error_message=None): | ||||
"""Run importmulti and assert success""" | """Run importmulti and assert success""" | ||||
result = self.nodes[1].importmulti([req]) | result = self.nodes[1].importmulti([req]) | ||||
assert_equal(result[0]['success'], success) | assert_equal(result[0]['success'], success) | ||||
if error_code is not None: | if error_code is not None: | ||||
assert_equal(result[0]['error']['code'], error_code) | assert_equal(result[0]['error']['code'], error_code) | ||||
assert_equal(result[0]['error']['message'], error_message) | assert_equal(result[0]['error']['message'], error_message) | ||||
def test_address(self, address, **kwargs): | |||||
"""Get address info for `address` and test whether the returned values are as expected.""" | |||||
addr_info = self.nodes[1].getaddressinfo(address) | |||||
for key, value in kwargs.items(): | |||||
if value is None: | |||||
if key in addr_info.keys(): | |||||
raise AssertionError( | |||||
"key {} unexpectedly returned in getaddressinfo.".format(key)) | |||||
elif addr_info[key] != value: | |||||
raise AssertionError( | |||||
"key {} value {} did not match expected value {}".format( | |||||
key, addr_info[key], value)) | |||||
def run_test(self): | def run_test(self): | ||||
self.log.info("Mining blocks...") | self.log.info("Mining blocks...") | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
self.nodes[1].generate(1) | self.nodes[1].generate(1) | ||||
timestamp = self.nodes[1].getblock( | timestamp = self.nodes[1].getblock( | ||||
self.nodes[1].getbestblockhash())['mediantime'] | self.nodes[1].getbestblockhash())['mediantime'] | ||||
node0_address1 = self.nodes[0].getaddressinfo( | node0_address1 = self.nodes[0].getaddressinfo( | ||||
Show All 14 Lines | def run_test(self): | ||||
# Bitcoin Address (implicit non-internal) | # Bitcoin Address (implicit non-internal) | ||||
self.log.info("Should import an address") | self.log.info("Should import an address") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
self.test_importmulti({"scriptPubKey": {"address": address}, | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"timestamp": "now"}, | "timestamp": "now"}, | ||||
True) | True) | ||||
address_assert = self.nodes[1].getaddressinfo(address) | self.test_address(address, | ||||
assert_equal(address_assert['iswatchonly'], True) | iswatchonly=True, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal(address_assert['timestamp'], timestamp) | timestamp=timestamp, | ||||
assert_equal(address_assert['ischange'], False) | ischange=False) | ||||
watchonly_address = address | watchonly_address = address | ||||
watchonly_timestamp = timestamp | watchonly_timestamp = timestamp | ||||
self.log.info("Should not import an invalid address") | self.log.info("Should not import an invalid address") | ||||
self.test_importmulti({"scriptPubKey": {"address": "not valid address"}, | self.test_importmulti({"scriptPubKey": {"address": "not valid address"}, | ||||
"timestamp": "now"}, | "timestamp": "now"}, | ||||
False, | False, | ||||
error_code=-5, | error_code=-5, | ||||
error_message='Invalid address') | error_message='Invalid address') | ||||
# ScriptPubKey + internal | # ScriptPubKey + internal | ||||
self.log.info("Should import a scriptPubKey with internal flag") | self.log.info("Should import a scriptPubKey with internal flag") | ||||
key = self.get_key() | key = self.get_key() | ||||
self.test_importmulti({"scriptPubKey": key.p2pkh_script, | self.test_importmulti({"scriptPubKey": key.p2pkh_script, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"internal": True}, | "internal": True}, | ||||
True) | True) | ||||
address_assert = self.nodes[1].getaddressinfo(key.p2pkh_addr) | self.test_address(key.p2pkh_addr, | ||||
assert_equal(address_assert['iswatchonly'], True) | iswatchonly=True, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal(address_assert['timestamp'], timestamp) | timestamp=timestamp, | ||||
assert_equal(address_assert['ischange'], True) | ischange=True) | ||||
# ScriptPubKey + internal + label | # ScriptPubKey + internal + label | ||||
self.log.info( | self.log.info( | ||||
"Should not allow a label to be specified when internal is true") | "Should not allow a label to be specified when internal is true") | ||||
key = self.get_key() | key = self.get_key() | ||||
self.test_importmulti({"scriptPubKey": key.p2pkh_script, | self.test_importmulti({"scriptPubKey": key.p2pkh_script, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"internal": True, | "internal": True, | ||||
"label": "Example label"}, | "label": "Example label"}, | ||||
False, | False, | ||||
error_code=-8, | error_code=-8, | ||||
error_message='Internal addresses should not have a label') | error_message='Internal addresses should not have a label') | ||||
# Nonstandard scriptPubKey + !internal | # Nonstandard scriptPubKey + !internal | ||||
self.log.info( | self.log.info( | ||||
"Should not import a nonstandard scriptPubKey without internal flag") | "Should not import a nonstandard scriptPubKey without internal flag") | ||||
nonstandardScriptPubKey = key.p2pkh_script + CScript([OP_NOP]).hex() | nonstandardScriptPubKey = key.p2pkh_script + CScript([OP_NOP]).hex() | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
self.test_importmulti({"scriptPubKey": nonstandardScriptPubKey, | self.test_importmulti({"scriptPubKey": nonstandardScriptPubKey, | ||||
"timestamp": "now"}, | "timestamp": "now"}, | ||||
False, | False, | ||||
error_code=-8, | error_code=-8, | ||||
error_message='Internal must be set to true for nonstandard scriptPubKey imports.') | error_message='Internal must be set to true for nonstandard scriptPubKey imports.') | ||||
address_assert = self.nodes[1].getaddressinfo(address) | self.test_address(address, | ||||
assert_equal(address_assert['iswatchonly'], False) | iswatchonly=False, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal('timestamp' in address_assert, False) | timestamp=None) | ||||
# Address + Public key + !Internal(explicit) | # Address + Public key + !Internal(explicit) | ||||
self.log.info("Should import an address with public key") | self.log.info("Should import an address with public key") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
self.test_importmulti({"scriptPubKey": {"address": address}, | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [key.pubkey], | "pubkeys": [key.pubkey], | ||||
"internal": False}, | "internal": False}, | ||||
True) | True) | ||||
address_assert = self.nodes[1].getaddressinfo(address) | self.test_address(address, | ||||
assert_equal(address_assert['iswatchonly'], True) | iswatchonly=True, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal(address_assert['timestamp'], timestamp) | timestamp=timestamp) | ||||
# ScriptPubKey + Public key + internal | # ScriptPubKey + Public key + internal | ||||
self.log.info( | self.log.info( | ||||
"Should import a scriptPubKey with internal and with public key") | "Should import a scriptPubKey with internal and with public key") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
self.test_importmulti({"scriptPubKey": key.p2pkh_script, | self.test_importmulti({"scriptPubKey": key.p2pkh_script, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [key.pubkey], | "pubkeys": [key.pubkey], | ||||
"internal": True}, | "internal": True}, | ||||
True) | True) | ||||
address_assert = self.nodes[1].getaddressinfo(address) | self.test_address(address, | ||||
assert_equal(address_assert['iswatchonly'], True) | iswatchonly=True, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal(address_assert['timestamp'], timestamp) | timestamp=timestamp) | ||||
# Nonstandard scriptPubKey + Public key + !internal | # Nonstandard scriptPubKey + Public key + !internal | ||||
self.log.info( | self.log.info( | ||||
"Should not import a nonstandard scriptPubKey without internal and with public key") | "Should not import a nonstandard scriptPubKey without internal and with public key") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
self.test_importmulti({"scriptPubKey": nonstandardScriptPubKey, | self.test_importmulti({"scriptPubKey": nonstandardScriptPubKey, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [key.pubkey]}, | "pubkeys": [key.pubkey]}, | ||||
False, | False, | ||||
error_code=-8, | error_code=-8, | ||||
error_message='Internal must be set to true for nonstandard scriptPubKey imports.') | error_message='Internal must be set to true for nonstandard scriptPubKey imports.') | ||||
address_assert = self.nodes[1].getaddressinfo(address) | self.test_address(address, | ||||
assert_equal(address_assert['iswatchonly'], False) | iswatchonly=False, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal('timestamp' in address_assert, False) | timestamp=None) | ||||
# Address + Private key + !watchonly | # Address + Private key + !watchonly | ||||
self.log.info("Should import an address with private key") | self.log.info("Should import an address with private key") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
self.test_importmulti({"scriptPubKey": {"address": address}, | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [key.privkey]}, | "keys": [key.privkey]}, | ||||
True) | True) | ||||
address_assert = self.nodes[1].getaddressinfo(address) | self.test_address(address, | ||||
assert_equal(address_assert['iswatchonly'], False) | iswatchonly=False, | ||||
assert_equal(address_assert['ismine'], True) | ismine=True, | ||||
assert_equal(address_assert['timestamp'], timestamp) | timestamp=timestamp) | ||||
self.log.info( | self.log.info( | ||||
"Should not import an address with private key if is already imported") | "Should not import an address with private key if is already imported") | ||||
self.test_importmulti({"scriptPubKey": {"address": address}, | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [key.privkey]}, | "keys": [key.privkey]}, | ||||
False, | False, | ||||
error_code=-4, | error_code=-4, | ||||
error_message='The wallet already contains the private key for this address or script') | error_message='The wallet already contains the private key for this address or script') | ||||
# Address + Private key + watchonly | # Address + Private key + watchonly | ||||
self.log.info( | self.log.info( | ||||
"Should not import an address with private key and with watchonly") | "Should not import an address with private key and with watchonly") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
self.test_importmulti({"scriptPubKey": {"address": address}, | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [key.privkey], | "keys": [key.privkey], | ||||
"watchonly": True}, | "watchonly": True}, | ||||
False, | False, | ||||
error_code=-8, | error_code=-8, | ||||
error_message='Watch-only addresses should not include private keys') | error_message='Watch-only addresses should not include private keys') | ||||
address_assert = self.nodes[1].getaddressinfo(address) | self.test_address(address, | ||||
assert_equal(address_assert['iswatchonly'], False) | iswatchonly=False, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal('timestamp' in address_assert, False) | timestamp=None) | ||||
# ScriptPubKey + Private key + internal | # ScriptPubKey + Private key + internal | ||||
self.log.info( | self.log.info( | ||||
"Should import a scriptPubKey with internal and with private key") | "Should import a scriptPubKey with internal and with private key") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
self.test_importmulti({"scriptPubKey": key.p2pkh_script, | self.test_importmulti({"scriptPubKey": key.p2pkh_script, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [key.privkey], | "keys": [key.privkey], | ||||
"internal": True}, | "internal": True}, | ||||
True) | True) | ||||
address_assert = self.nodes[1].getaddressinfo(address) | self.test_address(address, | ||||
assert_equal(address_assert['iswatchonly'], False) | iswatchonly=False, | ||||
assert_equal(address_assert['ismine'], True) | ismine=True, | ||||
assert_equal(address_assert['timestamp'], timestamp) | timestamp=timestamp) | ||||
# Nonstandard scriptPubKey + Private key + !internal | # Nonstandard scriptPubKey + Private key + !internal | ||||
self.log.info( | self.log.info( | ||||
"Should not import a nonstandard scriptPubKey without internal and with private key") | "Should not import a nonstandard scriptPubKey without internal and with private key") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
self.test_importmulti({"scriptPubKey": nonstandardScriptPubKey, | self.test_importmulti({"scriptPubKey": nonstandardScriptPubKey, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [key.privkey]}, | "keys": [key.privkey]}, | ||||
False, | False, | ||||
error_code=-8, | error_code=-8, | ||||
error_message='Internal must be set to true for nonstandard scriptPubKey imports.') | error_message='Internal must be set to true for nonstandard scriptPubKey imports.') | ||||
address_assert = self.nodes[1].getaddressinfo(address) | self.test_address(address, | ||||
assert_equal(address_assert['iswatchonly'], False) | iswatchonly=False, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal('timestamp' in address_assert, False) | timestamp=None) | ||||
# P2SH address | # P2SH address | ||||
multisig = self.get_multisig() | multisig = self.get_multisig() | ||||
self.nodes[1].generate(100) | self.nodes[1].generate(100) | ||||
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00) | self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00) | ||||
self.nodes[1].generate(1) | self.nodes[1].generate(1) | ||||
timestamp = self.nodes[1].getblock( | timestamp = self.nodes[1].getblock( | ||||
self.nodes[1].getbestblockhash())['mediantime'] | self.nodes[1].getbestblockhash())['mediantime'] | ||||
self.log.info("Should import a p2sh") | self.log.info("Should import a p2sh") | ||||
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr}, | self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr}, | ||||
"timestamp": "now"}, | "timestamp": "now"}, | ||||
True) | True) | ||||
address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) | self.test_address(multisig.p2sh_addr, | ||||
assert_equal(address_assert['isscript'], True) | isscript=True, | ||||
assert_equal(address_assert['iswatchonly'], True) | iswatchonly=True, | ||||
assert_equal(address_assert['timestamp'], timestamp) | timestamp=timestamp) | ||||
p2shunspent = self.nodes[1].listunspent( | p2shunspent = self.nodes[1].listunspent( | ||||
0, 999999, [multisig.p2sh_addr])[0] | 0, 999999, [multisig.p2sh_addr])[0] | ||||
assert_equal(p2shunspent['spendable'], False) | assert_equal(p2shunspent['spendable'], False) | ||||
assert_equal(p2shunspent['solvable'], False) | assert_equal(p2shunspent['solvable'], False) | ||||
# P2SH + Redeem script | # P2SH + Redeem script | ||||
multisig = self.get_multisig() | multisig = self.get_multisig() | ||||
self.nodes[1].generate(100) | self.nodes[1].generate(100) | ||||
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00) | self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00) | ||||
self.nodes[1].generate(1) | self.nodes[1].generate(1) | ||||
timestamp = self.nodes[1].getblock( | timestamp = self.nodes[1].getblock( | ||||
self.nodes[1].getbestblockhash())['mediantime'] | self.nodes[1].getbestblockhash())['mediantime'] | ||||
self.log.info("Should import a p2sh with respective redeem script") | self.log.info("Should import a p2sh with respective redeem script") | ||||
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr}, | self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr}, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"redeemscript": multisig.redeem_script}, | "redeemscript": multisig.redeem_script}, | ||||
True) | True) | ||||
address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) | self.test_address(multisig.p2sh_addr, timestamp=timestamp) | ||||
assert_equal(address_assert['timestamp'], timestamp) | |||||
p2shunspent = self.nodes[1].listunspent( | p2shunspent = self.nodes[1].listunspent( | ||||
0, 999999, [multisig.p2sh_addr])[0] | 0, 999999, [multisig.p2sh_addr])[0] | ||||
assert_equal(p2shunspent['spendable'], False) | assert_equal(p2shunspent['spendable'], False) | ||||
assert_equal(p2shunspent['solvable'], True) | assert_equal(p2shunspent['solvable'], True) | ||||
# P2SH + Redeem script + Private Keys + !Watchonly | # P2SH + Redeem script + Private Keys + !Watchonly | ||||
multisig = self.get_multisig() | multisig = self.get_multisig() | ||||
self.nodes[1].generate(100) | self.nodes[1].generate(100) | ||||
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00) | self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00) | ||||
self.nodes[1].generate(1) | self.nodes[1].generate(1) | ||||
timestamp = self.nodes[1].getblock( | timestamp = self.nodes[1].getblock( | ||||
self.nodes[1].getbestblockhash())['mediantime'] | self.nodes[1].getbestblockhash())['mediantime'] | ||||
self.log.info( | self.log.info( | ||||
"Should import a p2sh with respective redeem script and private keys") | "Should import a p2sh with respective redeem script and private keys") | ||||
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr}, | self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr}, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"redeemscript": multisig.redeem_script, | "redeemscript": multisig.redeem_script, | ||||
"keys": multisig.privkeys[0:2]}, | "keys": multisig.privkeys[0:2]}, | ||||
True) | True) | ||||
address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) | self.test_address(multisig.p2sh_addr, | ||||
assert_equal(address_assert['timestamp'], timestamp) | timestamp=timestamp) | ||||
p2shunspent = self.nodes[1].listunspent( | p2shunspent = self.nodes[1].listunspent( | ||||
0, 999999, [multisig.p2sh_addr])[0] | 0, 999999, [multisig.p2sh_addr])[0] | ||||
assert_equal(p2shunspent['spendable'], False) | assert_equal(p2shunspent['spendable'], False) | ||||
assert_equal(p2shunspent['solvable'], True) | assert_equal(p2shunspent['solvable'], True) | ||||
# P2SH + Redeem script + Private Keys + Watchonly | # P2SH + Redeem script + Private Keys + Watchonly | ||||
multisig = self.get_multisig() | multisig = self.get_multisig() | ||||
Show All 20 Lines | def run_test(self): | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
wrong_key = self.get_key().pubkey | wrong_key = self.get_key().pubkey | ||||
self.test_importmulti({"scriptPubKey": {"address": address}, | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [wrong_key]}, | "pubkeys": [wrong_key]}, | ||||
False, | False, | ||||
error_code=-5, | error_code=-5, | ||||
error_message='Key does not match address destination') | error_message='Key does not match address destination') | ||||
address_assert = self.nodes[1].getaddressinfo(address) | self.test_address(address, | ||||
assert_equal(address_assert['iswatchonly'], False) | iswatchonly=False, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal('timestamp' in address_assert, False) | timestamp=None) | ||||
# ScriptPubKey + Public key + internal + Wrong pubkey | # ScriptPubKey + Public key + internal + Wrong pubkey | ||||
self.log.info( | self.log.info( | ||||
"Should not import a scriptPubKey with internal and with a wrong public key") | "Should not import a scriptPubKey with internal and with a wrong public key") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
wrong_key = self.get_key().pubkey | wrong_key = self.get_key().pubkey | ||||
self.test_importmulti({"scriptPubKey": key.p2pkh_script, | self.test_importmulti({"scriptPubKey": key.p2pkh_script, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [wrong_key], | "pubkeys": [wrong_key], | ||||
"internal": True}, | "internal": True}, | ||||
False, | False, | ||||
error_code=-5, | error_code=-5, | ||||
error_message='Key does not match address destination') | error_message='Key does not match address destination') | ||||
address_assert = self.nodes[1].getaddressinfo(address) | self.test_address(address, | ||||
assert_equal(address_assert['iswatchonly'], False) | iswatchonly=False, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal('timestamp' in address_assert, False) | timestamp=None) | ||||
# Address + Private key + !watchonly + Wrong private key | # Address + Private key + !watchonly + Wrong private key | ||||
self.log.info("Should not import an address with a wrong private key") | self.log.info("Should not import an address with a wrong private key") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
wrong_privkey = self.get_key().privkey | wrong_privkey = self.get_key().privkey | ||||
self.test_importmulti({"scriptPubKey": {"address": address}, | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [wrong_privkey]}, | "keys": [wrong_privkey]}, | ||||
False, | False, | ||||
error_code=-5, | error_code=-5, | ||||
error_message='Key does not match address destination') | error_message='Key does not match address destination') | ||||
address_assert = self.nodes[1].getaddressinfo(address) | self.test_address(address, | ||||
assert_equal(address_assert['iswatchonly'], False) | iswatchonly=False, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal('timestamp' in address_assert, False) | timestamp=None) | ||||
# ScriptPubKey + Private key + internal + Wrong private key | # ScriptPubKey + Private key + internal + Wrong private key | ||||
self.log.info( | self.log.info( | ||||
"Should not import a scriptPubKey with internal and with a wrong private key") | "Should not import a scriptPubKey with internal and with a wrong private key") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
wrong_privkey = self.get_key().privkey | wrong_privkey = self.get_key().privkey | ||||
self.test_importmulti({"scriptPubKey": key.p2pkh_script, | self.test_importmulti({"scriptPubKey": key.p2pkh_script, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [wrong_privkey], | "keys": [wrong_privkey], | ||||
"internal": True}, | "internal": True}, | ||||
False, | False, | ||||
error_code=-5, | error_code=-5, | ||||
error_message='Key does not match address destination') | error_message='Key does not match address destination') | ||||
address_assert = self.nodes[1].getaddressinfo(address) | self.test_address(address, | ||||
assert_equal(address_assert['iswatchonly'], False) | iswatchonly=False, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal('timestamp' in address_assert, False) | timestamp=None) | ||||
# Importing existing watch only address with new timestamp should | # Importing existing watch only address with new timestamp should | ||||
# replace saved timestamp. | # replace saved timestamp. | ||||
assert_greater_than(timestamp, watchonly_timestamp) | assert_greater_than(timestamp, watchonly_timestamp) | ||||
self.log.info("Should replace previously saved watch only timestamp.") | self.log.info("Should replace previously saved watch only timestamp.") | ||||
self.test_importmulti({"scriptPubKey": {"address": watchonly_address}, | self.test_importmulti({"scriptPubKey": {"address": watchonly_address}, | ||||
"timestamp": "now"}, | "timestamp": "now"}, | ||||
True) | True) | ||||
address_assert = self.nodes[1].getaddressinfo(watchonly_address) | self.test_address(watchonly_address, | ||||
assert_equal(address_assert['iswatchonly'], True) | iswatchonly=True, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal(address_assert['timestamp'], timestamp) | timestamp=timestamp) | ||||
watchonly_timestamp = timestamp | watchonly_timestamp = timestamp | ||||
# restart nodes to check for proper serialization/deserialization of | # restart nodes to check for proper serialization/deserialization of | ||||
# watch only address | # watch only address | ||||
self.stop_nodes() | self.stop_nodes() | ||||
self.start_nodes() | self.start_nodes() | ||||
address_assert = self.nodes[1].getaddressinfo(watchonly_address) | self.test_address(watchonly_address, | ||||
assert_equal(address_assert['iswatchonly'], True) | iswatchonly=True, | ||||
assert_equal(address_assert['ismine'], False) | ismine=False, | ||||
assert_equal(address_assert['timestamp'], watchonly_timestamp) | timestamp=watchonly_timestamp) | ||||
# Bad or missing timestamps | # Bad or missing timestamps | ||||
self.log.info("Should throw on invalid or missing timestamp values") | self.log.info("Should throw on invalid or missing timestamp values") | ||||
assert_raises_rpc_error(-3, 'Missing required timestamp field for key', | assert_raises_rpc_error(-3, 'Missing required timestamp field for key', | ||||
self.nodes[1].importmulti, [{"scriptPubKey": key.p2pkh_script}]) | self.nodes[1].importmulti, [{"scriptPubKey": key.p2pkh_script}]) | ||||
assert_raises_rpc_error(-3, 'Expected number or "now" timestamp value for key. got type string', | assert_raises_rpc_error(-3, 'Expected number or "now" timestamp value for key. got type string', | ||||
self.nodes[1].importmulti, [{ | self.nodes[1].importmulti, [{ | ||||
"scriptPubKey": key.p2pkh_script, | "scriptPubKey": key.p2pkh_script, | ||||
"timestamp": "" | "timestamp": "" | ||||
}]) | }]) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
ImportMultiTest().main() | ImportMultiTest().main() |