2016-10-20 09:04:18 +02:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
|
|
|
# Distributed under the MIT software license, see the accompanying
|
|
|
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
2019-01-07 10:55:35 +01:00
|
|
|
"""Test the importmulti RPC."""
|
2018-09-10 19:01:13 +02:00
|
|
|
|
|
|
|
from test_framework import script
|
2016-10-20 09:04:18 +02:00
|
|
|
from test_framework.test_framework import BitcoinTestFramework
|
2018-09-10 20:04:31 +02:00
|
|
|
from test_framework.util import (
|
|
|
|
assert_equal,
|
|
|
|
assert_greater_than,
|
|
|
|
assert_raises_rpc_error,
|
|
|
|
)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
2018-09-10 20:04:31 +02:00
|
|
|
|
|
|
|
class ImportMultiTest(BitcoinTestFramework):
|
2017-09-01 18:47:13 +02:00
|
|
|
def set_test_params(self):
|
2016-10-20 09:04:18 +02:00
|
|
|
self.num_nodes = 2
|
|
|
|
self.setup_clean_chain = True
|
|
|
|
|
2018-09-13 12:33:15 +02:00
|
|
|
def skip_test_if_missing_module(self):
|
|
|
|
self.skip_if_no_wallet()
|
|
|
|
|
2017-05-02 20:02:55 +02:00
|
|
|
def setup_network(self):
|
|
|
|
self.setup_nodes()
|
2016-10-20 09:04:18 +02:00
|
|
|
|
|
|
|
def run_test (self):
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Mining blocks...")
|
2016-10-20 09:04:18 +02:00
|
|
|
self.nodes[0].generate(1)
|
|
|
|
self.nodes[1].generate(1)
|
2017-02-15 11:12:00 +01:00
|
|
|
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
|
2016-10-20 09:04:18 +02:00
|
|
|
|
2020-12-17 13:46:20 +01:00
|
|
|
node0_address1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
|
|
|
|
#Check only one address
|
|
|
|
assert_equal(node0_address1['ismine'], True)
|
|
|
|
|
|
|
|
#Node 1 sync test
|
|
|
|
assert_equal(self.nodes[1].getblockcount(),1)
|
|
|
|
|
|
|
|
#Address Test - before import
|
2020-12-17 13:46:20 +01:00
|
|
|
address_info = self.nodes[1].getaddressinfo(node0_address1['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_info['iswatchonly'], False)
|
|
|
|
assert_equal(address_info['ismine'], False)
|
|
|
|
|
|
|
|
|
|
|
|
# RPC importmulti -----------------------------------------------
|
|
|
|
|
2021-09-11 21:56:58 +02:00
|
|
|
# Bitcoin Address (implicit non-internal)
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should import an address")
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": {
|
|
|
|
"address": address['address']
|
2017-02-03 22:23:13 +01:00
|
|
|
},
|
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], True)
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], True)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal(address_assert['timestamp'], timestamp)
|
2021-09-11 21:56:58 +02:00
|
|
|
assert_equal(address_assert['ischange'], False)
|
2017-02-15 11:12:00 +01:00
|
|
|
watchonly_address = address['address']
|
|
|
|
watchonly_timestamp = timestamp
|
2016-10-20 09:04:18 +02:00
|
|
|
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should not import an invalid address")
|
2017-02-15 15:31:04 +01:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": {
|
|
|
|
"address": "not valid address",
|
|
|
|
},
|
|
|
|
"timestamp": "now",
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], False)
|
|
|
|
assert_equal(result[0]['error']['code'], -5)
|
|
|
|
assert_equal(result[0]['error']['message'], 'Invalid address')
|
2016-10-20 09:04:18 +02:00
|
|
|
|
|
|
|
# ScriptPubKey + internal
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should import a scriptPubKey with internal flag")
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": address['scriptPubKey'],
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"internal": True
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], True)
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], True)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal(address_assert['timestamp'], timestamp)
|
2021-09-11 21:56:58 +02:00
|
|
|
assert_equal(address_assert['ischange'], True)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
2018-09-10 19:01:13 +02:00
|
|
|
# Nonstandard scriptPubKey + !internal
|
|
|
|
self.log.info("Should not import a nonstandard scriptPubKey without internal flag")
|
2021-08-27 21:03:02 +02:00
|
|
|
nonstandardScriptPubKey = address['scriptPubKey'] + script.CScript([script.OP_NOP]).hex()
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
2018-09-10 19:01:13 +02:00
|
|
|
"scriptPubKey": nonstandardScriptPubKey,
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], False)
|
|
|
|
assert_equal(result[0]['error']['code'], -8)
|
2018-09-10 19:01:13 +02:00
|
|
|
assert_equal(result[0]['error']['message'], 'Internal must be set to true for nonstandard scriptPubKey imports.')
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], False)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal('timestamp' in address_assert, False)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
|
|
|
|
2021-09-11 21:56:58 +02:00
|
|
|
# Address + Public key + !Internal(explicit)
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should import an address with public key")
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": {
|
|
|
|
"address": address['address']
|
|
|
|
},
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2021-09-11 21:56:58 +02:00
|
|
|
"pubkeys": [ address['pubkey'] ],
|
|
|
|
"internal": False
|
2016-10-20 09:04:18 +02:00
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], True)
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], True)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal(address_assert['timestamp'], timestamp)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
# ScriptPubKey + Public key + internal
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should import a scriptPubKey with internal and with public key")
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
request = [{
|
|
|
|
"scriptPubKey": address['scriptPubKey'],
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"pubkeys": [ address['pubkey'] ],
|
|
|
|
"internal": True
|
2017-01-23 13:22:32 +01:00
|
|
|
}]
|
2018-11-13 22:49:17 +01:00
|
|
|
result = self.nodes[1].importmulti(requests=request)
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(result[0]['success'], True)
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], True)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal(address_assert['timestamp'], timestamp)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
2018-09-10 19:01:13 +02:00
|
|
|
# Nonstandard scriptPubKey + Public key + !internal
|
|
|
|
self.log.info("Should not import a nonstandard scriptPubKey without internal and with public key")
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
request = [{
|
2018-09-10 19:01:13 +02:00
|
|
|
"scriptPubKey": nonstandardScriptPubKey,
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"pubkeys": [ address['pubkey'] ]
|
2017-01-23 13:22:32 +01:00
|
|
|
}]
|
2018-11-13 22:49:17 +01:00
|
|
|
result = self.nodes[1].importmulti(requests=request)
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(result[0]['success'], False)
|
|
|
|
assert_equal(result[0]['error']['code'], -8)
|
2018-09-10 19:01:13 +02:00
|
|
|
assert_equal(result[0]['error']['message'], 'Internal must be set to true for nonstandard scriptPubKey imports.')
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], False)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal('timestamp' in address_assert, False)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
|
|
|
# Address + Private key + !watchonly
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should import an address with private key")
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": {
|
|
|
|
"address": address['address']
|
|
|
|
},
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"keys": [ self.nodes[0].dumpprivkey(address['address']) ]
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], True)
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], False)
|
|
|
|
assert_equal(address_assert['ismine'], True)
|
2017-02-14 14:24:27 +01:00
|
|
|
assert_equal(address_assert['timestamp'], timestamp)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
Merge #11483: Fix importmulti bug when importing an already imported key
a44a21517 Fix importmulti bug when importing an already imported key (Pedro Branco)
Pull request description:
This PR fixes a bug in `importmulti` RPC call where it returns an invalid response when importing an already imported key.
Before:
```sh
❯ bitcoin-cli -regtest importmulti '[{ "keys": ["cNcMUunXhVK1dXJ5riixtpYSxPXZnUAMGS4vpzwChdKmYY3Rz99v"], "scriptPubKey": { "address": "n4YZAf4WE2XF3t4BfeYS2nHAhb8CVx91BR" }, "timestamp": 1507655239 }]'
[{ "success": true }]
❯ bitcoin-cli -regtest importmulti '[{ "keys": ["cNcMUunXhVK1dXJ5riixtpYSxPXZnUAMGS4vpzwChdKmYY3Rz99v"], "scriptPubKey": { "address": "n4YZAf4WE2XF3t4BfeYS2nHAhb8CVx91BR" }, "timestamp": 1507655239 }]' '{ "rescan": false }'
[ false ]
❯ bitcoin-cli -regtest importmulti '[{ "keys": ["cNcMUunXhVK1dXJ5riixtpYSxPXZnUAMGS4vpzwChdKmYY3Rz99v"], "scriptPubKey": { "address": "n4YZAf4WE2XF3t4BfeYS2nHAhb8CVx91BR" }, "timestamp": 1507655239 }]' '{ "rescan": true }'
error code: -1
error message:
JSON value is not a boolean as expected
```
After this fix:
```sh
❯ bitcoin-cli -rpcuser=u -rpcpassword=p -regtest importmulti '[{ "keys": ["cNcMUunXhVK1dXJ5riixtpYSxPXZnUAMGS4vpzwChdKmYY3Rz99v"], "scriptPubKey": { "address": "n4YZAf4WE2XF3t4BfeYS2nHAhb8CVx91BR" }, "timestamp": 1507655139 }]'
[{ "success": true }]
❯ bitcoin-cli -rpcuser=u -rpcpassword=p -regtest importmulti '[{ "keys": ["cNcMUunXhVK1dXJ5riixtpYSxPXZnUAMGS4vpzwChdKmYY3Rz99v"], "scriptPubKey": { "address": "n4YZAf4WE2XF3t4BfeYS2nHAhb8CVx91BR" }, "timestamp": 1507655139 }]'
[{ "success": false, "error": { "code": -4, "message": "The wallet already contains the private key for this address or script" } }]
```
Tree-SHA512: 4acebdfb7d0ebd7cd48e943b93ed1cec072db1ace5c42b3f5cc225603764b6e804e4b823b0710965826aafc2f0c615c53d5aefcfdb9bc9c379f5221b798a318c
2017-10-17 21:40:48 +02:00
|
|
|
self.log.info("Should not import an address with private key if is already imported")
|
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": {
|
|
|
|
"address": address['address']
|
|
|
|
},
|
|
|
|
"timestamp": "now",
|
|
|
|
"keys": [ self.nodes[0].dumpprivkey(address['address']) ]
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], False)
|
|
|
|
assert_equal(result[0]['error']['code'], -4)
|
|
|
|
assert_equal(result[0]['error']['message'], 'The wallet already contains the private key for this address or script')
|
|
|
|
|
2016-10-20 09:04:18 +02:00
|
|
|
# Address + Private key + watchonly
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should not import an address with private key and with watchonly")
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": {
|
|
|
|
"address": address['address']
|
|
|
|
},
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"keys": [ self.nodes[0].dumpprivkey(address['address']) ],
|
|
|
|
"watchonly": True
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], False)
|
|
|
|
assert_equal(result[0]['error']['code'], -8)
|
|
|
|
assert_equal(result[0]['error']['message'], 'Incompatibility found between watchonly and keys')
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], False)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal('timestamp' in address_assert, False)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
|
|
|
# ScriptPubKey + Private key + internal
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should import a scriptPubKey with internal and with private key")
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": address['scriptPubKey'],
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"keys": [ self.nodes[0].dumpprivkey(address['address']) ],
|
|
|
|
"internal": True
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], True)
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], False)
|
|
|
|
assert_equal(address_assert['ismine'], True)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal(address_assert['timestamp'], timestamp)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
2018-09-10 19:01:13 +02:00
|
|
|
# Nonstandard scriptPubKey + Private key + !internal
|
|
|
|
self.log.info("Should not import a nonstandard scriptPubKey without internal and with private key")
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
2018-09-10 19:01:13 +02:00
|
|
|
"scriptPubKey": nonstandardScriptPubKey,
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"keys": [ self.nodes[0].dumpprivkey(address['address']) ]
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], False)
|
|
|
|
assert_equal(result[0]['error']['code'], -8)
|
2018-09-10 19:01:13 +02:00
|
|
|
assert_equal(result[0]['error']['message'], 'Internal must be set to true for nonstandard scriptPubKey imports.')
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], False)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal('timestamp' in address_assert, False)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
# P2SH address
|
2020-12-17 13:46:20 +01:00
|
|
|
sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
|
|
|
sig_address_2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
|
|
|
sig_address_3 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2020-05-15 11:34:41 +02:00
|
|
|
multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']])
|
2016-10-20 09:04:18 +02:00
|
|
|
self.nodes[1].generate(100)
|
2018-04-02 00:23:23 +02:00
|
|
|
self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
|
2016-10-20 09:04:18 +02:00
|
|
|
self.nodes[1].generate(1)
|
2017-02-15 11:12:00 +01:00
|
|
|
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
|
2016-10-20 09:04:18 +02:00
|
|
|
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should import a p2sh")
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": {
|
|
|
|
"address": multi_sig_script['address']
|
2017-02-03 22:23:13 +01:00
|
|
|
},
|
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], True)
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['isscript'], True)
|
|
|
|
assert_equal(address_assert['iswatchonly'], True)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal(address_assert['timestamp'], timestamp)
|
2016-10-20 09:04:18 +02:00
|
|
|
p2shunspent = self.nodes[1].listunspent(0,999999, [multi_sig_script['address']])[0]
|
|
|
|
assert_equal(p2shunspent['spendable'], False)
|
|
|
|
assert_equal(p2shunspent['solvable'], False)
|
|
|
|
|
|
|
|
|
|
|
|
# P2SH + Redeem script
|
2020-12-17 13:46:20 +01:00
|
|
|
sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
|
|
|
sig_address_2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
|
|
|
sig_address_3 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2020-05-15 11:34:41 +02:00
|
|
|
multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']])
|
2016-10-20 09:04:18 +02:00
|
|
|
self.nodes[1].generate(100)
|
2018-04-02 00:23:23 +02:00
|
|
|
self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
|
2016-10-20 09:04:18 +02:00
|
|
|
self.nodes[1].generate(1)
|
2017-02-15 11:12:00 +01:00
|
|
|
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
|
2016-10-20 09:04:18 +02:00
|
|
|
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should import a p2sh with respective redeem script")
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": {
|
|
|
|
"address": multi_sig_script['address']
|
|
|
|
},
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"redeemscript": multi_sig_script['redeemScript']
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], True)
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address'])
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal(address_assert['timestamp'], timestamp)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
|
|
|
p2shunspent = self.nodes[1].listunspent(0,999999, [multi_sig_script['address']])[0]
|
|
|
|
assert_equal(p2shunspent['spendable'], False)
|
|
|
|
assert_equal(p2shunspent['solvable'], True)
|
|
|
|
|
|
|
|
|
|
|
|
# P2SH + Redeem script + Private Keys + !Watchonly
|
2020-12-17 13:46:20 +01:00
|
|
|
sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
|
|
|
sig_address_2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
|
|
|
sig_address_3 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2020-05-15 11:34:41 +02:00
|
|
|
multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']])
|
2016-10-20 09:04:18 +02:00
|
|
|
self.nodes[1].generate(100)
|
2018-04-02 00:23:23 +02:00
|
|
|
self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
|
2016-10-20 09:04:18 +02:00
|
|
|
self.nodes[1].generate(1)
|
2017-02-15 11:12:00 +01:00
|
|
|
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
|
2016-10-20 09:04:18 +02:00
|
|
|
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should import a p2sh with respective redeem script and private keys")
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": {
|
|
|
|
"address": multi_sig_script['address']
|
|
|
|
},
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"redeemscript": multi_sig_script['redeemScript'],
|
|
|
|
"keys": [ self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])]
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], True)
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address'])
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal(address_assert['timestamp'], timestamp)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
|
|
|
p2shunspent = self.nodes[1].listunspent(0,999999, [multi_sig_script['address']])[0]
|
|
|
|
assert_equal(p2shunspent['spendable'], False)
|
|
|
|
assert_equal(p2shunspent['solvable'], True)
|
|
|
|
|
|
|
|
# P2SH + Redeem script + Private Keys + Watchonly
|
2020-12-17 13:46:20 +01:00
|
|
|
sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
|
|
|
sig_address_2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
|
|
|
sig_address_3 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2020-05-15 11:34:41 +02:00
|
|
|
multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']])
|
2016-10-20 09:04:18 +02:00
|
|
|
self.nodes[1].generate(100)
|
2018-04-02 00:23:23 +02:00
|
|
|
self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
|
2016-10-20 09:04:18 +02:00
|
|
|
self.nodes[1].generate(1)
|
2017-03-17 20:34:55 +01:00
|
|
|
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
|
2016-10-20 09:04:18 +02:00
|
|
|
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should import a p2sh with respective redeem script and private keys")
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": {
|
|
|
|
"address": multi_sig_script['address']
|
|
|
|
},
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"redeemscript": multi_sig_script['redeemScript'],
|
|
|
|
"keys": [ self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])],
|
|
|
|
"watchonly": True
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], False)
|
|
|
|
assert_equal(result[0]['error']['code'], -8)
|
|
|
|
assert_equal(result[0]['error']['message'], 'Incompatibility found between watchonly and keys')
|
|
|
|
|
|
|
|
|
|
|
|
# Address + Public key + !Internal + Wrong pubkey
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should not import an address with a wrong public key")
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
|
|
|
address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": {
|
|
|
|
"address": address['address']
|
|
|
|
},
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"pubkeys": [ address2['pubkey'] ]
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], False)
|
|
|
|
assert_equal(result[0]['error']['code'], -5)
|
|
|
|
assert_equal(result[0]['error']['message'], 'Consistency check failed')
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], False)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal('timestamp' in address_assert, False)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
# ScriptPubKey + Public key + internal + Wrong pubkey
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should not import a scriptPubKey with internal and with a wrong public key")
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
|
|
|
address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
request = [{
|
|
|
|
"scriptPubKey": address['scriptPubKey'],
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"pubkeys": [ address2['pubkey'] ],
|
|
|
|
"internal": True
|
2017-01-23 13:22:32 +01:00
|
|
|
}]
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti(request)
|
|
|
|
assert_equal(result[0]['success'], False)
|
|
|
|
assert_equal(result[0]['error']['code'], -5)
|
|
|
|
assert_equal(result[0]['error']['message'], 'Consistency check failed')
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], False)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal('timestamp' in address_assert, False)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
# Address + Private key + !watchonly + Wrong private key
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should not import an address with a wrong private key")
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
|
|
|
address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": {
|
|
|
|
"address": address['address']
|
|
|
|
},
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"keys": [ self.nodes[0].dumpprivkey(address2['address']) ]
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], False)
|
|
|
|
assert_equal(result[0]['error']['code'], -5)
|
|
|
|
assert_equal(result[0]['error']['message'], 'Consistency check failed')
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], False)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal('timestamp' in address_assert, False)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
# ScriptPubKey + Private key + internal + Wrong private key
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should not import a scriptPubKey with internal and with a wrong private key")
|
2020-12-17 13:46:20 +01:00
|
|
|
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
|
|
|
address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": address['scriptPubKey'],
|
2017-02-03 22:23:13 +01:00
|
|
|
"timestamp": "now",
|
2016-10-20 09:04:18 +02:00
|
|
|
"keys": [ self.nodes[0].dumpprivkey(address2['address']) ],
|
|
|
|
"internal": True
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], False)
|
|
|
|
assert_equal(result[0]['error']['code'], -5)
|
|
|
|
assert_equal(result[0]['error']['message'], 'Consistency check failed')
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
2016-10-20 09:04:18 +02:00
|
|
|
assert_equal(address_assert['iswatchonly'], False)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal('timestamp' in address_assert, False)
|
|
|
|
|
2017-03-17 20:34:55 +01:00
|
|
|
|
|
|
|
# Importing existing watch only address with new timestamp should replace saved timestamp.
|
|
|
|
assert_greater_than(timestamp, watchonly_timestamp)
|
2017-03-19 10:13:45 +01:00
|
|
|
self.log.info("Should replace previously saved watch only timestamp.")
|
2017-03-17 20:34:55 +01:00
|
|
|
result = self.nodes[1].importmulti([{
|
|
|
|
"scriptPubKey": {
|
|
|
|
"address": watchonly_address,
|
|
|
|
},
|
|
|
|
"timestamp": "now",
|
|
|
|
}])
|
|
|
|
assert_equal(result[0]['success'], True)
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(watchonly_address)
|
2017-03-17 20:34:55 +01:00
|
|
|
assert_equal(address_assert['iswatchonly'], True)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
|
|
|
assert_equal(address_assert['timestamp'], timestamp)
|
|
|
|
watchonly_timestamp = timestamp
|
|
|
|
|
|
|
|
|
2017-02-15 11:12:00 +01:00
|
|
|
# restart nodes to check for proper serialization/deserialization of watch only address
|
2017-06-02 12:08:48 +02:00
|
|
|
self.stop_nodes()
|
2017-09-01 18:47:13 +02:00
|
|
|
self.start_nodes()
|
2020-12-17 13:46:20 +01:00
|
|
|
address_assert = self.nodes[1].getaddressinfo(watchonly_address)
|
2017-02-15 11:12:00 +01:00
|
|
|
assert_equal(address_assert['iswatchonly'], True)
|
|
|
|
assert_equal(address_assert['ismine'], False)
|
2017-03-29 11:16:42 +02:00
|
|
|
assert_equal(address_assert['timestamp'], watchonly_timestamp)
|
2016-10-20 09:04:18 +02:00
|
|
|
|
2017-02-03 22:23:13 +01:00
|
|
|
# Bad or missing timestamps
|
2017-03-09 21:16:20 +01:00
|
|
|
self.log.info("Should throw on invalid or missing timestamp values")
|
2019-09-25 11:34:51 +02:00
|
|
|
assert_raises_rpc_error(-3, 'Missing required timestamp field for key',
|
2017-02-03 22:23:13 +01:00
|
|
|
self.nodes[1].importmulti, [{
|
|
|
|
"scriptPubKey": address['scriptPubKey'],
|
|
|
|
}])
|
2019-09-25 11:34:51 +02:00
|
|
|
assert_raises_rpc_error(-3, 'Expected number or "now" timestamp value for key. got type string',
|
2017-02-03 22:23:13 +01:00
|
|
|
self.nodes[1].importmulti, [{
|
|
|
|
"scriptPubKey": address['scriptPubKey'],
|
|
|
|
"timestamp": "",
|
|
|
|
}])
|
|
|
|
|
|
|
|
|
2016-10-20 09:04:18 +02:00
|
|
|
if __name__ == '__main__':
|
|
|
|
ImportMultiTest ().main ()
|