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.""" | ||||
from test_framework import script | |||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import ( | from test_framework.util import ( | ||||
assert_equal, | assert_equal, | ||||
assert_greater_than, | assert_greater_than, | ||||
assert_raises_rpc_error, | assert_raises_rpc_error, | ||||
) | ) | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], True) | assert_equal(result[0]['success'], True) | ||||
address_assert = self.nodes[1].getaddressinfo(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], True) | assert_equal(address_assert['iswatchonly'], True) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal(address_assert['timestamp'], timestamp) | assert_equal(address_assert['timestamp'], timestamp) | ||||
assert_equal(address_assert['ischange'], True) | assert_equal(address_assert['ischange'], True) | ||||
# ScriptPubKey + !internal | # ScriptPubKey + internal + label | ||||
self.log.info("Should not import a scriptPubKey without internal flag") | self.log.info( | ||||
"Should not allow a label to be specified when internal is true") | |||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": address['scriptPubKey'], | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"internal": True, | |||||
"label": "Example label" | |||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -8) | assert_equal(result[0]['error']['code'], -8) | ||||
assert_equal(result[0]['error']['message'], | assert_equal(result[0]['error']['message'], | ||||
'Internal must be set for hex scriptPubKey') | 'Internal addresses should not have a label') | ||||
nakihito: This change was made in [[ https://github.com/bitcoin/bitcoin/pull/14454/commits/c11875c5908a17… | |||||
# Nonstandard scriptPubKey + !internal | |||||
self.log.info( | |||||
"Should not import a nonstandard scriptPubKey without internal flag") | |||||
nonstandardScriptPubKey = address['scriptPubKey'] + \ | |||||
script.CScript([script.OP_NOP]).hex() | |||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | |||||
result = self.nodes[1].importmulti([{ | |||||
"scriptPubKey": nonstandardScriptPubKey, | |||||
"timestamp": "now", | |||||
}]) | |||||
assert_equal(result[0]['success'], False) | |||||
assert_equal(result[0]['error']['code'], -8) | |||||
assert_equal( | |||||
result[0]['error']['message'], | |||||
'Internal must be set to true for nonstandard scriptPubKey imports.') | |||||
nakihitoAuthorUnsubmitted Done Inline ActionsThis change was made in PR9332. nakihito: This change was made in [[ https://github.com/bitcoin/bitcoin/pull/9332/files#diff… | |||||
address_assert = self.nodes[1].getaddressinfo(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# 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") | ||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
Show All 23 Lines | def run_test(self): | ||||
}] | }] | ||||
result = self.nodes[1].importmulti(requests=request) | result = self.nodes[1].importmulti(requests=request) | ||||
assert_equal(result[0]['success'], True) | assert_equal(result[0]['success'], True) | ||||
address_assert = self.nodes[1].getaddressinfo(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], True) | assert_equal(address_assert['iswatchonly'], True) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal(address_assert['timestamp'], timestamp) | assert_equal(address_assert['timestamp'], timestamp) | ||||
# ScriptPubKey + Public key + !internal | # Nonstandard scriptPubKey + Public key + !internal | ||||
self.log.info( | self.log.info( | ||||
"Should not import a scriptPubKey without internal and with public key") | "Should not import a nonstandard scriptPubKey without internal and with public key") | ||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
request = [{ | request = [{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": nonstandardScriptPubKey, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [address['pubkey']] | "pubkeys": [address['pubkey']] | ||||
}] | }] | ||||
result = self.nodes[1].importmulti(requests=request) | result = self.nodes[1].importmulti(requests=request) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -8) | assert_equal(result[0]['error']['code'], -8) | ||||
assert_equal(result[0]['error']['message'], | assert_equal( | ||||
'Internal must be set for hex scriptPubKey') | result[0]['error']['message'], | ||||
'Internal must be set to true for nonstandard scriptPubKey imports.') | |||||
nakihitoAuthorUnsubmitted Done Inline ActionsThis change was made in PR9332. nakihito: This change was made in [[ https://github.com/bitcoin/bitcoin/pull/9332/files#diff… | |||||
address_assert = self.nodes[1].getaddressinfo(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# 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") | ||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
Show All 33 Lines | def run_test(self): | ||||
"address": address['address'] | "address": address['address'] | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [self.nodes[0].dumpprivkey(address['address'])], | "keys": [self.nodes[0].dumpprivkey(address['address'])], | ||||
"watchonly": True | "watchonly": True | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -8) | assert_equal(result[0]['error']['code'], -8) | ||||
assert_equal(result[0]['error']['message'], | assert_equal( | ||||
'Incompatibility found between watchonly and keys') | result[0]['error']['message'], | ||||
'Watch-only addresses should not include private keys') | |||||
nakihitoAuthorUnsubmitted Done Inline ActionsThese changes were made in PR14454. nakihito: These changes were made in [[ https://github.com/bitcoin/bitcoin/pull/14454/commits/f6ed748cf04… | |||||
address_assert = self.nodes[1].getaddressinfo(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# 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") | ||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": address['scriptPubKey'], | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [self.nodes[0].dumpprivkey(address['address'])], | "keys": [self.nodes[0].dumpprivkey(address['address'])], | ||||
"internal": True | "internal": True | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], True) | assert_equal(result[0]['success'], True) | ||||
address_assert = self.nodes[1].getaddressinfo(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], True) | assert_equal(address_assert['ismine'], True) | ||||
assert_equal(address_assert['timestamp'], timestamp) | assert_equal(address_assert['timestamp'], timestamp) | ||||
# ScriptPubKey + Private key + !internal | # Nonstandard scriptPubKey + Private key + !internal | ||||
self.log.info( | self.log.info( | ||||
"Should not import a scriptPubKey without internal and with private key") | "Should not import a nonstandard scriptPubKey without internal and with private key") | ||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": nonstandardScriptPubKey, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [self.nodes[0].dumpprivkey(address['address'])] | "keys": [self.nodes[0].dumpprivkey(address['address'])] | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -8) | assert_equal(result[0]['error']['code'], -8) | ||||
assert_equal(result[0]['error']['message'], | assert_equal( | ||||
'Internal must be set for hex scriptPubKey') | result[0]['error']['message'], | ||||
'Internal must be set to true for nonstandard scriptPubKey imports.') | |||||
nakihitoAuthorUnsubmitted Done Inline ActionsThis change was made in PR9332. nakihito: This change was made in [[ https://github.com/bitcoin/bitcoin/pull/9332/files#diff… | |||||
address_assert = self.nodes[1].getaddressinfo(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# P2SH address | # P2SH address | ||||
sig_address_1 = self.nodes[0].getaddressinfo( | sig_address_1 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"redeemscript": multi_sig_script['redeemScript'], | "redeemscript": multi_sig_script['redeemScript'], | ||||
"keys": [self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])], | "keys": [self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])], | ||||
"watchonly": True | "watchonly": True | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -8) | assert_equal(result[0]['error']['code'], -8) | ||||
assert_equal(result[0]['error']['message'], | assert_equal( | ||||
'Incompatibility found between watchonly and keys') | result[0]['error']['message'], | ||||
'Watch-only addresses should not include private keys') | |||||
# Address + Public key + !Internal + Wrong pubkey | # Address + Public key + !Internal + Wrong pubkey | ||||
self.log.info("Should not import an address with a wrong public key") | self.log.info("Should not import an address with a wrong public key") | ||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": address['address'] | "address": address['address'] | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [address2['pubkey']] | "pubkeys": [address2['pubkey']] | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -5) | assert_equal(result[0]['error']['code'], -5) | ||||
assert_equal(result[0]['error']['message'], 'Consistency check failed') | assert_equal( | ||||
result[0]['error']['message'], | |||||
'Key does not match address destination') | |||||
address_assert = self.nodes[1].getaddressinfo(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# 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") | ||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
request = [{ | request = [{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": address['scriptPubKey'], | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [address2['pubkey']], | "pubkeys": [address2['pubkey']], | ||||
"internal": True | "internal": True | ||||
}] | }] | ||||
result = self.nodes[1].importmulti(request) | result = self.nodes[1].importmulti(request) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -5) | assert_equal(result[0]['error']['code'], -5) | ||||
assert_equal(result[0]['error']['message'], 'Consistency check failed') | assert_equal( | ||||
result[0]['error']['message'], | |||||
'Key does not match address destination') | |||||
address_assert = self.nodes[1].getaddressinfo(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# 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") | ||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": address['address'] | "address": address['address'] | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [self.nodes[0].dumpprivkey(address2['address'])] | "keys": [self.nodes[0].dumpprivkey(address2['address'])] | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -5) | assert_equal(result[0]['error']['code'], -5) | ||||
assert_equal(result[0]['error']['message'], 'Consistency check failed') | assert_equal( | ||||
result[0]['error']['message'], | |||||
'Key does not match address destination') | |||||
address_assert = self.nodes[1].getaddressinfo(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# 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") | ||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": address['scriptPubKey'], | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [self.nodes[0].dumpprivkey(address2['address'])], | "keys": [self.nodes[0].dumpprivkey(address2['address'])], | ||||
"internal": True | "internal": True | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -5) | assert_equal(result[0]['error']['code'], -5) | ||||
assert_equal(result[0]['error']['message'], 'Consistency check failed') | assert_equal( | ||||
result[0]['error']['message'], | |||||
'Key does not match address destination') | |||||
address_assert = self.nodes[1].getaddressinfo(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# 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) | ||||
Show All 38 Lines |
This change was made in PR14454.