Changeset View
Changeset View
Standalone View
Standalone View
test/functional/wallet_importmulti.py
Show First 20 Lines • Show All 95 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, | def test_importmulti(self, req, success, error_code=None, | ||||
error_code=None, error_message=None): | error_message=None, warnings=[]): | ||||
"""Run importmulti and assert success""" | """Run importmulti and assert success""" | ||||
result = self.nodes[1].importmulti([req]) | result = self.nodes[1].importmulti([req]) | ||||
observed_warnings = [] | |||||
if 'warnings' in result[0]: | |||||
observed_warnings = result[0]['warnings'] | |||||
assert_equal( | |||||
"\n".join( | |||||
sorted(warnings)), "\n".join( | |||||
sorted(observed_warnings))) | |||||
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): | def test_address(self, address, **kwargs): | ||||
"""Get address info for `address` and test whether the returned values are as expected.""" | """Get address info for `address` and test whether the returned values are as expected.""" | ||||
addr_info = self.nodes[1].getaddressinfo(address) | addr_info = self.nodes[1].getaddressinfo(address) | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
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 \"not valid 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) | ||||
Show All 34 Lines | def run_test(self): | ||||
# 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, | ||||
warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) | |||||
self.test_address(address, | self.test_address(address, | ||||
iswatchonly=True, | iswatchonly=True, | ||||
ismine=False, | ismine=False, | ||||
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, | ||||
warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) | |||||
self.test_address(address, | self.test_address(address, | ||||
iswatchonly=True, | iswatchonly=True, | ||||
ismine=False, | ismine=False, | ||||
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") | ||||
Show All 29 Lines | def run_test(self): | ||||
"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 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, | True, | ||||
error_code=-8, | warnings=["All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag."]) | ||||
error_message='Watch-only addresses should not include private keys') | |||||
self.test_address(address, | self.test_address(address, | ||||
iswatchonly=False, | iswatchonly=False, | ||||
ismine=False, | ismine=True, | ||||
timestamp=None) | timestamp=timestamp) | ||||
# 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", | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
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, | ||||
self.test_address(multisig.p2sh_addr, timestamp=timestamp) | warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) | ||||
self.test_address( | |||||
multisig.p2sh_addr, | |||||
timestamp=timestamp, | |||||
iswatchonly=True, | |||||
ismine=False, | |||||
solvable=True) | |||||
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, | ||||
warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) | |||||
self.test_address(multisig.p2sh_addr, | self.test_address(multisig.p2sh_addr, | ||||
timestamp=timestamp) | timestamp=timestamp, | ||||
ismine=False, | |||||
iswatchonly=True, | |||||
solvable=True) | |||||
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], | ||||
"watchonly": True}, | "watchonly": True}, | ||||
False, | True) | ||||
error_code=-8, | self.test_address(multisig.p2sh_addr, | ||||
error_message='Watch-only addresses should not include private keys') | iswatchonly=True, | ||||
ismine=False, | |||||
solvable=True, | |||||
timestamp=timestamp) | |||||
# 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 the wrong public key as non-solvable") | |||||
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": {"address": address}, | self.test_importmulti({"scriptPubKey": {"address": address}, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [wrong_key]}, | "pubkeys": [wrong_key]}, | ||||
False, | True, | ||||
error_code=-5, | warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) | ||||
error_message='Key does not match address destination') | |||||
self.test_address(address, | self.test_address(address, | ||||
iswatchonly=False, | iswatchonly=True, | ||||
ismine=False, | ismine=False, | ||||
timestamp=None) | solvable=False, | ||||
timestamp=timestamp) | |||||
# 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 import a scriptPubKey with internal and with a wrong public key as non-solvable") | ||||
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, | True, | ||||
error_code=-5, | warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) | ||||
error_message='Key does not match address destination') | |||||
self.test_address(address, | self.test_address(address, | ||||
iswatchonly=False, | iswatchonly=True, | ||||
ismine=False, | ismine=False, | ||||
timestamp=None) | solvable=False, | ||||
timestamp=timestamp) | |||||
# 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 import an address with a wrong private key as non-solvable") | |||||
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, | True, | ||||
error_code=-5, | warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) | ||||
error_message='Key does not match address destination') | |||||
self.test_address(address, | self.test_address(address, | ||||
iswatchonly=False, | iswatchonly=True, | ||||
ismine=False, | ismine=False, | ||||
timestamp=None) | solvable=False, | ||||
timestamp=timestamp) | |||||
# 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 import a scriptPubKey with internal and with a wrong private key as non-solvable") | ||||
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, | True, | ||||
error_code=-5, | warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) | ||||
error_message='Key does not match address destination') | |||||
self.test_address(address, | self.test_address(address, | ||||
iswatchonly=False, | iswatchonly=True, | ||||
ismine=False, | ismine=False, | ||||
timestamp=None) | solvable=False, | ||||
timestamp=timestamp) | |||||
# 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) | ||||
Show All 28 Lines |