diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2018-10-24 18:28:17 -0700 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2018-12-12 16:32:33 -0800 |
commit | bdacbda25316581ac82eac0820905c833f69c615 (patch) | |
tree | 1afde01dd940ef92b3e93efb9ce912135d4cc6f1 /test/functional | |
parent | f65bce858f266b352c9ddd1f5480431dca56fcae (diff) | |
download | bitcoin-bdacbda25316581ac82eac0820905c833f69c615.tar.xz |
Overhaul importmulti logic
This introduces various changes to the importmulti logic:
* Instead of processing input and importing things at the same time, first
process all input data and verify it, so no changes are made in case of
an error.
* Verify that no superfluous information is provided (no keys or scripts
that don't contribute to solvability in particular).
* Add way more sanity checks, by means of descending into all involved
scripts.
Diffstat (limited to 'test/functional')
-rwxr-xr-x | test/functional/wallet_importmulti.py | 110 |
1 files changed, 64 insertions, 46 deletions
diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py index a163f7018c..3492075694 100755 --- a/test/functional/wallet_importmulti.py +++ b/test/functional/wallet_importmulti.py @@ -119,9 +119,13 @@ class ImportMultiTest(BitcoinTestFramework): CScript([OP_HASH160, witness_script, OP_EQUAL]).hex(), # p2sh-p2wsh script_to_p2sh_p2wsh(script_code)) # p2sh-p2wsh addr - def test_importmulti(self, req, success, error_code=None, error_message=None): + def test_importmulti(self, req, success, error_code=None, error_message=None, warnings=[]): """Run importmulti and assert success""" 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) if error_code is not None: assert_equal(result[0]['error']['code'], error_code) @@ -178,7 +182,7 @@ class ImportMultiTest(BitcoinTestFramework): "timestamp": "now"}, False, error_code=-5, - error_message='Invalid address') + error_message='Invalid address \"not valid address\"') # ScriptPubKey + internal self.log.info("Should import a scriptPubKey with internal flag") @@ -227,7 +231,8 @@ class ImportMultiTest(BitcoinTestFramework): "timestamp": "now", "pubkeys": [key.pubkey], "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, iswatchonly=True, ismine=False, @@ -241,7 +246,8 @@ class ImportMultiTest(BitcoinTestFramework): "timestamp": "now", "pubkeys": [key.pubkey], "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, iswatchonly=True, ismine=False, @@ -284,20 +290,19 @@ class ImportMultiTest(BitcoinTestFramework): error_message='The wallet already contains the private key for this address or script') # Address + Private key + watchonly - self.log.info("Should not import an address with private key and with watchonly") + self.log.info("Should import an address with private key and with watchonly") key = self.get_key() address = key.p2pkh_addr self.test_importmulti({"scriptPubKey": {"address": address}, "timestamp": "now", "keys": [key.privkey], "watchonly": True}, - False, - error_code=-8, - error_message='Watch-only addresses should not include private keys') + True, + warnings=["All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag."]) self.test_address(address, iswatchonly=False, - ismine=False, - timestamp=None) + ismine=True, + timestamp=timestamp) # ScriptPubKey + Private key + internal self.log.info("Should import a scriptPubKey with internal and with private key") @@ -358,8 +363,9 @@ class ImportMultiTest(BitcoinTestFramework): self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr}, "timestamp": "now", "redeemscript": multisig.redeem_script}, - True) - self.test_address(multisig.p2sh_addr, timestamp=timestamp) + 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, timestamp=timestamp, iswatchonly=True, ismine=False, solvable=True) p2shunspent = self.nodes[1].listunspent(0, 999999, [multisig.p2sh_addr])[0] assert_equal(p2shunspent['spendable'], False) @@ -377,9 +383,13 @@ class ImportMultiTest(BitcoinTestFramework): "timestamp": "now", "redeemscript": multisig.redeem_script, "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, - timestamp=timestamp) + timestamp=timestamp, + ismine=False, + iswatchonly=True, + solvable=True) p2shunspent = self.nodes[1].listunspent(0, 999999, [multisig.p2sh_addr])[0] assert_equal(p2shunspent['spendable'], False) @@ -398,28 +408,31 @@ class ImportMultiTest(BitcoinTestFramework): "redeemscript": multisig.redeem_script, "keys": multisig.privkeys[0:2], "watchonly": True}, - False, - error_code=-8, - error_message='Watch-only addresses should not include private keys') + True) + self.test_address(multisig.p2sh_addr, + iswatchonly=True, + ismine=False, + solvable=True, + timestamp=timestamp) # 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() address = key.p2pkh_addr wrong_key = self.get_key().pubkey self.test_importmulti({"scriptPubKey": {"address": address}, "timestamp": "now", "pubkeys": [wrong_key]}, - False, - error_code=-5, - error_message='Key does not match address destination') + True, + warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) self.test_address(address, - iswatchonly=False, + iswatchonly=True, ismine=False, - timestamp=None) + solvable=False, + timestamp=timestamp) # ScriptPubKey + Public key + internal + Wrong pubkey - self.log.info("Should not import a scriptPubKey with internal and with a wrong public key") + self.log.info("Should import a scriptPubKey with internal and with a wrong public key as non-solvable") key = self.get_key() address = key.p2pkh_addr wrong_key = self.get_key().pubkey @@ -427,32 +440,32 @@ class ImportMultiTest(BitcoinTestFramework): "timestamp": "now", "pubkeys": [wrong_key], "internal": True}, - False, - error_code=-5, - error_message='Key does not match address destination') + True, + warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) self.test_address(address, - iswatchonly=False, + iswatchonly=True, ismine=False, - timestamp=None) + solvable=False, + timestamp=timestamp) # 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() address = key.p2pkh_addr wrong_privkey = self.get_key().privkey self.test_importmulti({"scriptPubKey": {"address": address}, "timestamp": "now", "keys": [wrong_privkey]}, - False, - error_code=-5, - error_message='Key does not match address destination') + True, + warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) self.test_address(address, - iswatchonly=False, + iswatchonly=True, ismine=False, - timestamp=None) + solvable=False, + timestamp=timestamp) # ScriptPubKey + Private key + internal + Wrong private key - self.log.info("Should not import a scriptPubKey with internal and with a wrong private key") + self.log.info("Should import a scriptPubKey with internal and with a wrong private key as non-solvable") key = self.get_key() address = key.p2pkh_addr wrong_privkey = self.get_key().privkey @@ -460,13 +473,13 @@ class ImportMultiTest(BitcoinTestFramework): "timestamp": "now", "keys": [wrong_privkey], "internal": True}, - False, - error_code=-5, - error_message='Key does not match address destination') + True, + warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) self.test_address(address, - iswatchonly=False, + iswatchonly=True, ismine=False, - timestamp=None) + solvable=False, + timestamp=timestamp) # Importing existing watch only address with new timestamp should replace saved timestamp. assert_greater_than(timestamp, watchonly_timestamp) @@ -516,7 +529,8 @@ class ImportMultiTest(BitcoinTestFramework): self.test_importmulti({"scriptPubKey": {"address": address}, "timestamp": "now", "pubkeys": [key.pubkey]}, - 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, ismine=False, solvable=True) @@ -571,7 +585,8 @@ class ImportMultiTest(BitcoinTestFramework): "timestamp": "now", "redeemscript": key.p2sh_p2wpkh_redeem_script, "pubkeys": [key.pubkey]}, - 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, solvable=True, ismine=False) @@ -591,14 +606,17 @@ class ImportMultiTest(BitcoinTestFramework): # P2SH-P2WSH multisig + redeemscript with no private key multisig = self.get_multisig() + address = multisig.p2sh_p2wsh_addr self.log.info("Should import a p2sh-p2wsh with respective redeem script but no private key") - self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_p2wsh_addr}, + self.test_importmulti({"scriptPubKey": {"address": address}, "timestamp": "now", "redeemscript": multisig.p2wsh_script, "witnessscript": multisig.redeem_script}, - 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, - solvable=True) + solvable=True, + ismine=False) if __name__ == '__main__': ImportMultiTest().main() |