2 # Copyright (c) 2014-2016 The Bitcoin Core developers
3 # Distributed under the MIT software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 """Test the importmulti RPC."""
6 from test_framework
.test_framework
import BitcoinTestFramework
7 from test_framework
.util
import *
9 class ImportMultiTest (BitcoinTestFramework
):
10 def set_test_params(self
):
12 self
.setup_clean_chain
= True
14 def setup_network(self
):
18 self
.log
.info("Mining blocks...")
19 self
.nodes
[0].generate(1)
20 self
.nodes
[1].generate(1)
21 timestamp
= self
.nodes
[1].getblock(self
.nodes
[1].getbestblockhash())['mediantime']
23 node0_address1
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
25 #Check only one address
26 assert_equal(node0_address1
['ismine'], True)
29 assert_equal(self
.nodes
[1].getblockcount(),1)
31 #Address Test - before import
32 address_info
= self
.nodes
[1].validateaddress(node0_address1
['address'])
33 assert_equal(address_info
['iswatchonly'], False)
34 assert_equal(address_info
['ismine'], False)
37 # RPC importmulti -----------------------------------------------
40 self
.log
.info("Should import an address")
41 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
42 result
= self
.nodes
[1].importmulti([{
44 "address": address
['address']
48 assert_equal(result
[0]['success'], True)
49 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
50 assert_equal(address_assert
['iswatchonly'], True)
51 assert_equal(address_assert
['ismine'], False)
52 assert_equal(address_assert
['timestamp'], timestamp
)
53 watchonly_address
= address
['address']
54 watchonly_timestamp
= timestamp
56 self
.log
.info("Should not import an invalid address")
57 result
= self
.nodes
[1].importmulti([{
59 "address": "not valid address",
63 assert_equal(result
[0]['success'], False)
64 assert_equal(result
[0]['error']['code'], -5)
65 assert_equal(result
[0]['error']['message'], 'Invalid address')
67 # ScriptPubKey + internal
68 self
.log
.info("Should import a scriptPubKey with internal flag")
69 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
70 result
= self
.nodes
[1].importmulti([{
71 "scriptPubKey": address
['scriptPubKey'],
75 assert_equal(result
[0]['success'], True)
76 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
77 assert_equal(address_assert
['iswatchonly'], True)
78 assert_equal(address_assert
['ismine'], False)
79 assert_equal(address_assert
['timestamp'], timestamp
)
81 # ScriptPubKey + !internal
82 self
.log
.info("Should not import a scriptPubKey without internal flag")
83 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
84 result
= self
.nodes
[1].importmulti([{
85 "scriptPubKey": address
['scriptPubKey'],
88 assert_equal(result
[0]['success'], False)
89 assert_equal(result
[0]['error']['code'], -8)
90 assert_equal(result
[0]['error']['message'], 'Internal must be set for hex scriptPubKey')
91 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
92 assert_equal(address_assert
['iswatchonly'], False)
93 assert_equal(address_assert
['ismine'], False)
94 assert_equal('timestamp' in address_assert
, False)
97 # Address + Public key + !Internal
98 self
.log
.info("Should import an address with public key")
99 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
100 result
= self
.nodes
[1].importmulti([{
102 "address": address
['address']
105 "pubkeys": [ address
['pubkey'] ]
107 assert_equal(result
[0]['success'], True)
108 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
109 assert_equal(address_assert
['iswatchonly'], True)
110 assert_equal(address_assert
['ismine'], False)
111 assert_equal(address_assert
['timestamp'], timestamp
)
114 # ScriptPubKey + Public key + internal
115 self
.log
.info("Should import a scriptPubKey with internal and with public key")
116 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
118 "scriptPubKey": address
['scriptPubKey'],
120 "pubkeys": [ address
['pubkey'] ],
123 result
= self
.nodes
[1].importmulti(request
)
124 assert_equal(result
[0]['success'], True)
125 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
126 assert_equal(address_assert
['iswatchonly'], True)
127 assert_equal(address_assert
['ismine'], False)
128 assert_equal(address_assert
['timestamp'], timestamp
)
130 # ScriptPubKey + Public key + !internal
131 self
.log
.info("Should not import a scriptPubKey without internal and with public key")
132 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
134 "scriptPubKey": address
['scriptPubKey'],
136 "pubkeys": [ address
['pubkey'] ]
138 result
= self
.nodes
[1].importmulti(request
)
139 assert_equal(result
[0]['success'], False)
140 assert_equal(result
[0]['error']['code'], -8)
141 assert_equal(result
[0]['error']['message'], 'Internal must be set for hex scriptPubKey')
142 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
143 assert_equal(address_assert
['iswatchonly'], False)
144 assert_equal(address_assert
['ismine'], False)
145 assert_equal('timestamp' in address_assert
, False)
147 # Address + Private key + !watchonly
148 self
.log
.info("Should import an address with private key")
149 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
150 result
= self
.nodes
[1].importmulti([{
152 "address": address
['address']
155 "keys": [ self
.nodes
[0].dumpprivkey(address
['address']) ]
157 assert_equal(result
[0]['success'], True)
158 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
159 assert_equal(address_assert
['iswatchonly'], False)
160 assert_equal(address_assert
['ismine'], True)
161 assert_equal(address_assert
['timestamp'], timestamp
)
163 # Address + Private key + watchonly
164 self
.log
.info("Should not import an address with private key and with watchonly")
165 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
166 result
= self
.nodes
[1].importmulti([{
168 "address": address
['address']
171 "keys": [ self
.nodes
[0].dumpprivkey(address
['address']) ],
174 assert_equal(result
[0]['success'], False)
175 assert_equal(result
[0]['error']['code'], -8)
176 assert_equal(result
[0]['error']['message'], 'Incompatibility found between watchonly and keys')
177 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
178 assert_equal(address_assert
['iswatchonly'], False)
179 assert_equal(address_assert
['ismine'], False)
180 assert_equal('timestamp' in address_assert
, False)
182 # ScriptPubKey + Private key + internal
183 self
.log
.info("Should import a scriptPubKey with internal and with private key")
184 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
185 result
= self
.nodes
[1].importmulti([{
186 "scriptPubKey": address
['scriptPubKey'],
188 "keys": [ self
.nodes
[0].dumpprivkey(address
['address']) ],
191 assert_equal(result
[0]['success'], True)
192 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
193 assert_equal(address_assert
['iswatchonly'], False)
194 assert_equal(address_assert
['ismine'], True)
195 assert_equal(address_assert
['timestamp'], timestamp
)
197 # ScriptPubKey + Private key + !internal
198 self
.log
.info("Should not import a scriptPubKey without internal and with private key")
199 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
200 result
= self
.nodes
[1].importmulti([{
201 "scriptPubKey": address
['scriptPubKey'],
203 "keys": [ self
.nodes
[0].dumpprivkey(address
['address']) ]
205 assert_equal(result
[0]['success'], False)
206 assert_equal(result
[0]['error']['code'], -8)
207 assert_equal(result
[0]['error']['message'], 'Internal must be set for hex scriptPubKey')
208 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
209 assert_equal(address_assert
['iswatchonly'], False)
210 assert_equal(address_assert
['ismine'], False)
211 assert_equal('timestamp' in address_assert
, False)
215 sig_address_1
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
216 sig_address_2
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
217 sig_address_3
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
218 multi_sig_script
= self
.nodes
[0].createmultisig(2, [sig_address_1
['address'], sig_address_2
['address'], sig_address_3
['pubkey']])
219 self
.nodes
[1].generate(100)
220 transactionid
= self
.nodes
[1].sendtoaddress(multi_sig_script
['address'], 10.00)
221 self
.nodes
[1].generate(1)
222 timestamp
= self
.nodes
[1].getblock(self
.nodes
[1].getbestblockhash())['mediantime']
224 self
.log
.info("Should import a p2sh")
225 result
= self
.nodes
[1].importmulti([{
227 "address": multi_sig_script
['address']
231 assert_equal(result
[0]['success'], True)
232 address_assert
= self
.nodes
[1].validateaddress(multi_sig_script
['address'])
233 assert_equal(address_assert
['isscript'], True)
234 assert_equal(address_assert
['iswatchonly'], True)
235 assert_equal(address_assert
['timestamp'], timestamp
)
236 p2shunspent
= self
.nodes
[1].listunspent(0,999999, [multi_sig_script
['address']])[0]
237 assert_equal(p2shunspent
['spendable'], False)
238 assert_equal(p2shunspent
['solvable'], False)
241 # P2SH + Redeem script
242 sig_address_1
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
243 sig_address_2
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
244 sig_address_3
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
245 multi_sig_script
= self
.nodes
[0].createmultisig(2, [sig_address_1
['address'], sig_address_2
['address'], sig_address_3
['pubkey']])
246 self
.nodes
[1].generate(100)
247 transactionid
= self
.nodes
[1].sendtoaddress(multi_sig_script
['address'], 10.00)
248 self
.nodes
[1].generate(1)
249 timestamp
= self
.nodes
[1].getblock(self
.nodes
[1].getbestblockhash())['mediantime']
251 self
.log
.info("Should import a p2sh with respective redeem script")
252 result
= self
.nodes
[1].importmulti([{
254 "address": multi_sig_script
['address']
257 "redeemscript": multi_sig_script
['redeemScript']
259 assert_equal(result
[0]['success'], True)
260 address_assert
= self
.nodes
[1].validateaddress(multi_sig_script
['address'])
261 assert_equal(address_assert
['timestamp'], timestamp
)
263 p2shunspent
= self
.nodes
[1].listunspent(0,999999, [multi_sig_script
['address']])[0]
264 assert_equal(p2shunspent
['spendable'], False)
265 assert_equal(p2shunspent
['solvable'], True)
268 # P2SH + Redeem script + Private Keys + !Watchonly
269 sig_address_1
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
270 sig_address_2
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
271 sig_address_3
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
272 multi_sig_script
= self
.nodes
[0].createmultisig(2, [sig_address_1
['address'], sig_address_2
['address'], sig_address_3
['pubkey']])
273 self
.nodes
[1].generate(100)
274 transactionid
= self
.nodes
[1].sendtoaddress(multi_sig_script
['address'], 10.00)
275 self
.nodes
[1].generate(1)
276 timestamp
= self
.nodes
[1].getblock(self
.nodes
[1].getbestblockhash())['mediantime']
278 self
.log
.info("Should import a p2sh with respective redeem script and private keys")
279 result
= self
.nodes
[1].importmulti([{
281 "address": multi_sig_script
['address']
284 "redeemscript": multi_sig_script
['redeemScript'],
285 "keys": [ self
.nodes
[0].dumpprivkey(sig_address_1
['address']), self
.nodes
[0].dumpprivkey(sig_address_2
['address'])]
287 assert_equal(result
[0]['success'], True)
288 address_assert
= self
.nodes
[1].validateaddress(multi_sig_script
['address'])
289 assert_equal(address_assert
['timestamp'], timestamp
)
291 p2shunspent
= self
.nodes
[1].listunspent(0,999999, [multi_sig_script
['address']])[0]
292 assert_equal(p2shunspent
['spendable'], False)
293 assert_equal(p2shunspent
['solvable'], True)
295 # P2SH + Redeem script + Private Keys + Watchonly
296 sig_address_1
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
297 sig_address_2
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
298 sig_address_3
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
299 multi_sig_script
= self
.nodes
[0].createmultisig(2, [sig_address_1
['address'], sig_address_2
['address'], sig_address_3
['pubkey']])
300 self
.nodes
[1].generate(100)
301 transactionid
= self
.nodes
[1].sendtoaddress(multi_sig_script
['address'], 10.00)
302 self
.nodes
[1].generate(1)
303 timestamp
= self
.nodes
[1].getblock(self
.nodes
[1].getbestblockhash())['mediantime']
305 self
.log
.info("Should import a p2sh with respective redeem script and private keys")
306 result
= self
.nodes
[1].importmulti([{
308 "address": multi_sig_script
['address']
311 "redeemscript": multi_sig_script
['redeemScript'],
312 "keys": [ self
.nodes
[0].dumpprivkey(sig_address_1
['address']), self
.nodes
[0].dumpprivkey(sig_address_2
['address'])],
315 assert_equal(result
[0]['success'], False)
316 assert_equal(result
[0]['error']['code'], -8)
317 assert_equal(result
[0]['error']['message'], 'Incompatibility found between watchonly and keys')
320 # Address + Public key + !Internal + Wrong pubkey
321 self
.log
.info("Should not import an address with a wrong public key")
322 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
323 address2
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
324 result
= self
.nodes
[1].importmulti([{
326 "address": address
['address']
329 "pubkeys": [ address2
['pubkey'] ]
331 assert_equal(result
[0]['success'], False)
332 assert_equal(result
[0]['error']['code'], -5)
333 assert_equal(result
[0]['error']['message'], 'Consistency check failed')
334 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
335 assert_equal(address_assert
['iswatchonly'], False)
336 assert_equal(address_assert
['ismine'], False)
337 assert_equal('timestamp' in address_assert
, False)
340 # ScriptPubKey + Public key + internal + Wrong pubkey
341 self
.log
.info("Should not import a scriptPubKey with internal and with a wrong public key")
342 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
343 address2
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
345 "scriptPubKey": address
['scriptPubKey'],
347 "pubkeys": [ address2
['pubkey'] ],
350 result
= self
.nodes
[1].importmulti(request
)
351 assert_equal(result
[0]['success'], False)
352 assert_equal(result
[0]['error']['code'], -5)
353 assert_equal(result
[0]['error']['message'], 'Consistency check failed')
354 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
355 assert_equal(address_assert
['iswatchonly'], False)
356 assert_equal(address_assert
['ismine'], False)
357 assert_equal('timestamp' in address_assert
, False)
360 # Address + Private key + !watchonly + Wrong private key
361 self
.log
.info("Should not import an address with a wrong private key")
362 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
363 address2
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
364 result
= self
.nodes
[1].importmulti([{
366 "address": address
['address']
369 "keys": [ self
.nodes
[0].dumpprivkey(address2
['address']) ]
371 assert_equal(result
[0]['success'], False)
372 assert_equal(result
[0]['error']['code'], -5)
373 assert_equal(result
[0]['error']['message'], 'Consistency check failed')
374 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
375 assert_equal(address_assert
['iswatchonly'], False)
376 assert_equal(address_assert
['ismine'], False)
377 assert_equal('timestamp' in address_assert
, False)
380 # ScriptPubKey + Private key + internal + Wrong private key
381 self
.log
.info("Should not import a scriptPubKey with internal and with a wrong private key")
382 address
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
383 address2
= self
.nodes
[0].validateaddress(self
.nodes
[0].getnewaddress())
384 result
= self
.nodes
[1].importmulti([{
385 "scriptPubKey": address
['scriptPubKey'],
387 "keys": [ self
.nodes
[0].dumpprivkey(address2
['address']) ],
390 assert_equal(result
[0]['success'], False)
391 assert_equal(result
[0]['error']['code'], -5)
392 assert_equal(result
[0]['error']['message'], 'Consistency check failed')
393 address_assert
= self
.nodes
[1].validateaddress(address
['address'])
394 assert_equal(address_assert
['iswatchonly'], False)
395 assert_equal(address_assert
['ismine'], False)
396 assert_equal('timestamp' in address_assert
, False)
399 # Importing existing watch only address with new timestamp should replace saved timestamp.
400 assert_greater_than(timestamp
, watchonly_timestamp
)
401 self
.log
.info("Should replace previously saved watch only timestamp.")
402 result
= self
.nodes
[1].importmulti([{
404 "address": watchonly_address
,
408 assert_equal(result
[0]['success'], True)
409 address_assert
= self
.nodes
[1].validateaddress(watchonly_address
)
410 assert_equal(address_assert
['iswatchonly'], True)
411 assert_equal(address_assert
['ismine'], False)
412 assert_equal(address_assert
['timestamp'], timestamp
)
413 watchonly_timestamp
= timestamp
416 # restart nodes to check for proper serialization/deserialization of watch only address
419 address_assert
= self
.nodes
[1].validateaddress(watchonly_address
)
420 assert_equal(address_assert
['iswatchonly'], True)
421 assert_equal(address_assert
['ismine'], False)
422 assert_equal(address_assert
['timestamp'], watchonly_timestamp
)
424 # Bad or missing timestamps
425 self
.log
.info("Should throw on invalid or missing timestamp values")
426 assert_raises_rpc_error(-3, 'Missing required timestamp field for key',
427 self
.nodes
[1].importmulti
, [{
428 "scriptPubKey": address
['scriptPubKey'],
430 assert_raises_rpc_error(-3, 'Expected number or "now" timestamp value for key. got type string',
431 self
.nodes
[1].importmulti
, [{
432 "scriptPubKey": address
['scriptPubKey'],
437 if __name__
== '__main__':
438 ImportMultiTest ().main ()