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
|
Merge #13054: tests: Enable automatic detection of undefined names in Python tests scripts. Remove wildcard imports.
68400d8b96 tests: Use explicit imports (practicalswift)
Pull request description:
Enable automatic detection of undefined names in Python tests scripts. Remove wildcard imports.
Wildcard imports make it unclear which names are present in the namespace, confusing both readers and many automated tools.
An additional benefit of not using wildcard imports in tests scripts is that readers of a test script then can infer the rough testing scope just by looking at the imports.
Before this commit:
```
$ contrib/devtools/lint-python.sh | head -10
./test/functional/feature_rbf.py:8:1: F403 'from test_framework.util import *' used; unable to detect undefined names
./test/functional/feature_rbf.py:9:1: F403 'from test_framework.script import *' used; unable to detect undefined names
./test/functional/feature_rbf.py:10:1: F403 'from test_framework.mininode import *' used; unable to detect undefined names
./test/functional/feature_rbf.py:15:12: F405 bytes_to_hex_str may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
./test/functional/feature_rbf.py:17:58: F405 CScript may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
./test/functional/feature_rbf.py:25:13: F405 COIN may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
./test/functional/feature_rbf.py:26:31: F405 satoshi_round may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
./test/functional/feature_rbf.py:26:60: F405 COIN may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
./test/functional/feature_rbf.py:30:41: F405 satoshi_round may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
./test/functional/feature_rbf.py:30:68: F405 COIN may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
$
```
After this commit:
```
$ contrib/devtools/lint-python.sh | head -10
$
```
Tree-SHA512: 3f826d39cffb6438388e5efcb20a9622ff8238247e882d68f7b38609877421b2a8e10e9229575f8eb6a8fa42dec4256986692e92922c86171f750a0e887438d9
2018-08-13 14:24:43 +02:00
|
|
|
from test_framework.util import assert_equal, assert_greater_than, assert_raises_rpc_error, bytes_to_hex_str
|
2016-10-20 09:04:18 +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
|
|
|
|
|
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 -----------------------------------------------
|
|
|
|
|
|
|
|
# Bitcoin Address
|
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)
|
|
|
|
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)
|
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")
|
|
|
|
nonstandardScriptPubKey = address['scriptPubKey'] + bytes_to_hex_str(script.CScript([script.OP_NOP]))
|
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
|
|
|
|
|
|
|
|
|
|
|
# Address + Public key + !Internal
|
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",
|
2016-10-20 09:04:18 +02:00
|
|
|
"pubkeys": [ address['pubkey'] ]
|
|
|
|
}])
|
|
|
|
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
|
|
|
}]
|
2016-10-20 09:04:18 +02:00
|
|
|
result = self.nodes[1].importmulti(request)
|
|
|
|
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
|
|
|
}]
|
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'], -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 ()
|