mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-04 21:04:58 +02:00
Merge #14565: Overhaul importmulti logic
eacff95deAdd release notes (Pieter Wuille)bdacbda25Overhaul importmulti logic (Pieter Wuille) Pull request description: This is an alternative to #14558 (it will warn when fields are being ignored). In addition: * It makes sure no changes to the wallet are made when an error in the input exists. * It validates all arguments, and will fail if anything fails to parse. * Adds a whole bunch of sanity checks Tree-SHA512: fdee0b6aca8c643663f0bc295a7c1d69c1960951493b06abf32c58977f3e565f75918dbd0402dde36e508dc746c9310a968a0ebbacccc385a57ac2a68b49c1d0
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user