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 | |||||
success, and (if unsuccessful) test the error code and error message 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 71 Lines • ▼ Show 20 Lines | def get_multisig(self): | ||||
# p2sh | # p2sh | ||||
CScript([OP_HASH160, hash160( | CScript([OP_HASH160, hash160( | ||||
script_code), OP_EQUAL]).hex(), | script_code), OP_EQUAL]).hex(), | ||||
# p2sh addr | # p2sh addr | ||||
script_to_p2sh(script_code), | script_to_p2sh(script_code), | ||||
# redeem script | # redeem script | ||||
script_code.hex()) | script_code.hex()) | ||||
def test_importmulti(self, req, success, | |||||
error_code=None, error_message=None): | |||||
"""Run importmulti and assert success""" | |||||
result = self.nodes[1].importmulti([req]) | |||||
assert_equal(result[0]['success'], success) | |||||
if error_code is not None: | |||||
assert_equal(result[0]['error']['code'], error_code) | |||||
assert_equal(result[0]['error']['message'], error_message) | |||||
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 11 Lines | def run_test(self): | ||||
assert_equal(address_info['ismine'], False) | assert_equal(address_info['ismine'], False) | ||||
# RPC importmulti ----------------------------------------------- | # RPC importmulti ----------------------------------------------- | ||||
# 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 | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"scriptPubKey": { | "timestamp": "now"}, | ||||
"address": address | True) | ||||
}, | |||||
"timestamp": "now", | |||||
}]) | |||||
assert_equal(result[0]['success'], True) | |||||
address_assert = self.nodes[1].getaddressinfo(address) | address_assert = self.nodes[1].getaddressinfo(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'], False) | assert_equal(address_assert['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") | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": {"address": "not valid address"}, | ||||
"scriptPubKey": { | "timestamp": "now"}, | ||||
"address": "not valid address", | False, | ||||
}, | error_code=-5, | ||||
"timestamp": "now", | error_message='Invalid address') | ||||
}]) | |||||
assert_equal(result[0]['success'], False) | |||||
assert_equal(result[0]['error']['code'], -5) | |||||
assert_equal(result[0]['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() | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": key.p2pkh_script, | ||||
"scriptPubKey": key.p2pkh_script, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"internal": True | "internal": True}, | ||||
}]) | True) | ||||
assert_equal(result[0]['success'], True) | |||||
address_assert = self.nodes[1].getaddressinfo(key.p2pkh_addr) | address_assert = self.nodes[1].getaddressinfo(key.p2pkh_addr) | ||||
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 + 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() | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": key.p2pkh_script, | ||||
"scriptPubKey": key.p2pkh_script, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"internal": True, | "internal": True, | ||||
"label": "Example label" | "label": "Example label"}, | ||||
}]) | False, | ||||
assert_equal(result[0]['success'], False) | error_code=-8, | ||||
assert_equal(result[0]['error']['code'], -8) | error_message='Internal addresses should not have a label') | ||||
assert_equal(result[0]['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 | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": nonstandardScriptPubKey, | ||||
"scriptPubKey": nonstandardScriptPubKey, | "timestamp": "now"}, | ||||
"timestamp": "now", | False, | ||||
}]) | error_code=-8, | ||||
assert_equal(result[0]['success'], False) | error_message='Internal must be set to true for nonstandard scriptPubKey imports.') | ||||
assert_equal(result[0]['error']['code'], -8) | |||||
assert_equal( | |||||
result[0]['error']['message'], | |||||
'Internal must be set to true for nonstandard scriptPubKey imports.') | |||||
address_assert = self.nodes[1].getaddressinfo(address) | address_assert = self.nodes[1].getaddressinfo(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") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"scriptPubKey": { | |||||
"address": address | |||||
}, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [key.pubkey], | "pubkeys": [key.pubkey], | ||||
"internal": False | "internal": False}, | ||||
}]) | True) | ||||
assert_equal(result[0]['success'], True) | |||||
address_assert = self.nodes[1].getaddressinfo(address) | address_assert = self.nodes[1].getaddressinfo(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 | # 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 | ||||
request = [{ | self.test_importmulti({"scriptPubKey": key.p2pkh_script, | ||||
"scriptPubKey": key.p2pkh_script, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [key.pubkey], | "pubkeys": [key.pubkey], | ||||
"internal": True | "internal": True}, | ||||
}] | True) | ||||
result = self.nodes[1].importmulti(requests=request) | |||||
assert_equal(result[0]['success'], True) | |||||
address_assert = self.nodes[1].getaddressinfo(address) | address_assert = self.nodes[1].getaddressinfo(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) | ||||
# 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 | ||||
request = [{ | self.test_importmulti({"scriptPubKey": nonstandardScriptPubKey, | ||||
"scriptPubKey": nonstandardScriptPubKey, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [key.pubkey] | "pubkeys": [key.pubkey]}, | ||||
}] | False, | ||||
result = self.nodes[1].importmulti(requests=request) | error_code=-8, | ||||
assert_equal(result[0]['success'], False) | error_message='Internal must be set to true for nonstandard scriptPubKey imports.') | ||||
assert_equal(result[0]['error']['code'], -8) | |||||
assert_equal( | |||||
result[0]['error']['message'], | |||||
'Internal must be set to true for nonstandard scriptPubKey imports.') | |||||
address_assert = self.nodes[1].getaddressinfo(address) | address_assert = self.nodes[1].getaddressinfo(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") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"scriptPubKey": { | |||||
"address": address | |||||
}, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [key.privkey] | "keys": [key.privkey]}, | ||||
}]) | True) | ||||
assert_equal(result[0]['success'], True) | |||||
address_assert = self.nodes[1].getaddressinfo(address) | address_assert = self.nodes[1].getaddressinfo(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) | ||||
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") | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"scriptPubKey": { | |||||
"address": address | |||||
}, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [key.privkey] | "keys": [key.privkey]}, | ||||
}]) | False, | ||||
assert_equal(result[0]['success'], False) | error_code=-4, | ||||
assert_equal(result[0]['error']['code'], -4) | error_message='The wallet already contains the private key for this address or script') | ||||
assert_equal(result[0]['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 | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"scriptPubKey": { | |||||
"address": address | |||||
}, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [key.privkey], | "keys": [key.privkey], | ||||
"watchonly": True | "watchonly": True}, | ||||
}]) | False, | ||||
assert_equal(result[0]['success'], False) | error_code=-8, | ||||
assert_equal(result[0]['error']['code'], -8) | error_message='Watch-only addresses should not include private keys') | ||||
assert_equal( | |||||
result[0]['error']['message'], | |||||
'Watch-only addresses should not include private keys') | |||||
address_assert = self.nodes[1].getaddressinfo(address) | address_assert = self.nodes[1].getaddressinfo(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") | ||||
key = self.get_key() | key = self.get_key() | ||||
address = key.p2pkh_addr | address = key.p2pkh_addr | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": key.p2pkh_script, | ||||
"scriptPubKey": key.p2pkh_script, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [key.privkey], | "keys": [key.privkey], | ||||
"internal": True | "internal": True}, | ||||
}]) | True) | ||||
assert_equal(result[0]['success'], True) | |||||
address_assert = self.nodes[1].getaddressinfo(address) | address_assert = self.nodes[1].getaddressinfo(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) | ||||
# 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 | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": nonstandardScriptPubKey, | ||||
"scriptPubKey": nonstandardScriptPubKey, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [key.privkey] | "keys": [key.privkey]}, | ||||
}]) | False, | ||||
assert_equal(result[0]['success'], False) | error_code=-8, | ||||
assert_equal(result[0]['error']['code'], -8) | error_message='Internal must be set to true for nonstandard scriptPubKey imports.') | ||||
assert_equal( | |||||
result[0]['error']['message'], | |||||
'Internal must be set to true for nonstandard scriptPubKey imports.') | |||||
address_assert = self.nodes[1].getaddressinfo(address) | address_assert = self.nodes[1].getaddressinfo(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 | ||||
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") | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr}, | ||||
"scriptPubKey": { | "timestamp": "now"}, | ||||
"address": multisig.p2sh_addr | True) | ||||
}, | |||||
"timestamp": "now", | |||||
}]) | |||||
assert_equal(result[0]['success'], True) | |||||
address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) | address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) | ||||
assert_equal(address_assert['isscript'], True) | assert_equal(address_assert['isscript'], True) | ||||
assert_equal(address_assert['iswatchonly'], True) | assert_equal(address_assert['iswatchonly'], True) | ||||
assert_equal(address_assert['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'], 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") | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr}, | ||||
"scriptPubKey": { | |||||
"address": multisig.p2sh_addr | |||||
}, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"redeemscript": multisig.redeem_script | "redeemscript": multisig.redeem_script}, | ||||
}]) | True) | ||||
assert_equal(result[0]['success'], True) | |||||
address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) | address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) | ||||
assert_equal(address_assert['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") | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr}, | ||||
"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) | ||||
assert_equal(result[0]['success'], True) | |||||
address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) | address_assert = self.nodes[1].getaddressinfo(multisig.p2sh_addr) | ||||
assert_equal(address_assert['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") | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr}, | ||||
"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], | ||||
"watchonly": True | "watchonly": True}, | ||||
}]) | False, | ||||
assert_equal(result[0]['success'], False) | error_code=-8, | ||||
assert_equal(result[0]['error']['code'], -8) | error_message='Watch-only addresses should not include private keys') | ||||
assert_equal( | |||||
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") | ||||
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 | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"scriptPubKey": { | |||||
"address": address | |||||
}, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [wrong_key] | "pubkeys": [wrong_key]}, | ||||
}]) | False, | ||||
assert_equal(result[0]['success'], False) | error_code=-5, | ||||
assert_equal(result[0]['error']['code'], -5) | error_message='Key does not match address destination') | ||||
assert_equal( | |||||
result[0]['error']['message'], | |||||
'Key does not match address destination') | |||||
address_assert = self.nodes[1].getaddressinfo(address) | address_assert = self.nodes[1].getaddressinfo(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") | ||||
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 | ||||
request = [{ | self.test_importmulti({"scriptPubKey": key.p2pkh_script, | ||||
"scriptPubKey": key.p2pkh_script, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [wrong_key], | "pubkeys": [wrong_key], | ||||
"internal": True | "internal": True}, | ||||
}] | False, | ||||
result = self.nodes[1].importmulti(request) | error_code=-5, | ||||
assert_equal(result[0]['success'], False) | error_message='Key does not match address destination') | ||||
assert_equal(result[0]['error']['code'], -5) | |||||
assert_equal( | |||||
result[0]['error']['message'], | |||||
'Key does not match address destination') | |||||
address_assert = self.nodes[1].getaddressinfo(address) | address_assert = self.nodes[1].getaddressinfo(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") | ||||
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 | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"scriptPubKey": { | |||||
"address": address | |||||
}, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [wrong_privkey] | "keys": [wrong_privkey]}, | ||||
}]) | False, | ||||
assert_equal(result[0]['success'], False) | error_code=-5, | ||||
assert_equal(result[0]['error']['code'], -5) | error_message='Key does not match address destination') | ||||
assert_equal( | |||||
result[0]['error']['message'], | |||||
'Key does not match address destination') | |||||
address_assert = self.nodes[1].getaddressinfo(address) | address_assert = self.nodes[1].getaddressinfo(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") | ||||
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 | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": key.p2pkh_script, | ||||
"scriptPubKey": key.p2pkh_script, | |||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [wrong_privkey], | "keys": [wrong_privkey], | ||||
"internal": True | "internal": True}, | ||||
}]) | False, | ||||
assert_equal(result[0]['success'], False) | error_code=-5, | ||||
assert_equal(result[0]['error']['code'], -5) | error_message='Key does not match address destination') | ||||
assert_equal( | |||||
result[0]['error']['message'], | |||||
'Key does not match address destination') | |||||
address_assert = self.nodes[1].getaddressinfo(address) | address_assert = self.nodes[1].getaddressinfo(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) | ||||
self.log.info("Should replace previously saved watch only timestamp.") | self.log.info("Should replace previously saved watch only timestamp.") | ||||
result = self.nodes[1].importmulti([{ | self.test_importmulti({"scriptPubKey": {"address": watchonly_address}, | ||||
"scriptPubKey": { | "timestamp": "now"}, | ||||
"address": watchonly_address, | True) | ||||
}, | |||||
"timestamp": "now", | |||||
}]) | |||||
assert_equal(result[0]['success'], True) | |||||
address_assert = self.nodes[1].getaddressinfo(watchonly_address) | address_assert = self.nodes[1].getaddressinfo(watchonly_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) | ||||
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 | ||||
Show All 20 Lines |