You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

importmulti.py 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. #!/usr/bin/env python3
  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 *
  8. class ImportMultiTest (BitcoinTestFramework):
  9. def set_test_params(self):
  10. self.num_nodes = 2
  11. self.setup_clean_chain = True
  12. def setup_network(self):
  13. self.setup_nodes()
  14. def run_test (self):
  15. self.log.info("Mining blocks...")
  16. self.nodes[0].generate(1)
  17. self.nodes[1].generate(1)
  18. timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
  19. # keyword definition
  20. PRIV_KEY = 'privkey'
  21. PUB_KEY = 'pubkey'
  22. ADDRESS_KEY = 'address'
  23. SCRIPT_KEY = 'script'
  24. node0_address1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  25. node0_address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  26. node0_address3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  27. #Check only one address
  28. assert_equal(node0_address1['ismine'], True)
  29. #Node 1 sync test
  30. 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)
  35. # RPC importmulti -----------------------------------------------
  36. # Bitcoin Address
  37. self.log.info("Should import an address")
  38. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  39. result = self.nodes[1].importmulti([{
  40. "scriptPubKey": {
  41. "address": address['address']
  42. },
  43. "timestamp": "now",
  44. }])
  45. assert_equal(result[0]['success'], True)
  46. address_assert = self.nodes[1].validateaddress(address['address'])
  47. assert_equal(address_assert['iswatchonly'], True)
  48. assert_equal(address_assert['ismine'], False)
  49. assert_equal(address_assert['timestamp'], timestamp)
  50. watchonly_address = address['address']
  51. watchonly_timestamp = timestamp
  52. self.log.info("Should not import an invalid address")
  53. result = self.nodes[1].importmulti([{
  54. "scriptPubKey": {
  55. "address": "not valid address",
  56. },
  57. "timestamp": "now",
  58. }])
  59. assert_equal(result[0]['success'], False)
  60. assert_equal(result[0]['error']['code'], -5)
  61. assert_equal(result[0]['error']['message'], 'Invalid address')
  62. # ScriptPubKey + internal
  63. self.log.info("Should import a scriptPubKey with internal flag")
  64. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  65. result = self.nodes[1].importmulti([{
  66. "scriptPubKey": address['scriptPubKey'],
  67. "timestamp": "now",
  68. "internal": True
  69. }])
  70. assert_equal(result[0]['success'], True)
  71. address_assert = self.nodes[1].validateaddress(address['address'])
  72. assert_equal(address_assert['iswatchonly'], True)
  73. assert_equal(address_assert['ismine'], False)
  74. assert_equal(address_assert['timestamp'], timestamp)
  75. # ScriptPubKey + !internal
  76. self.log.info("Should not import a scriptPubKey without internal flag")
  77. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  78. result = self.nodes[1].importmulti([{
  79. "scriptPubKey": address['scriptPubKey'],
  80. "timestamp": "now",
  81. }])
  82. assert_equal(result[0]['success'], False)
  83. assert_equal(result[0]['error']['code'], -8)
  84. assert_equal(result[0]['error']['message'], 'Internal must be set for hex scriptPubKey')
  85. address_assert = self.nodes[1].validateaddress(address['address'])
  86. assert_equal(address_assert['iswatchonly'], False)
  87. assert_equal(address_assert['ismine'], False)
  88. assert_equal('timestamp' in address_assert, False)
  89. # Address + Public key + !Internal
  90. self.log.info("Should import an address with public key")
  91. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  92. result = self.nodes[1].importmulti([{
  93. "scriptPubKey": {
  94. "address": address['address']
  95. },
  96. "timestamp": "now",
  97. "pubkeys": [ address['pubkey'] ]
  98. }])
  99. assert_equal(result[0]['success'], True)
  100. address_assert = self.nodes[1].validateaddress(address['address'])
  101. assert_equal(address_assert['iswatchonly'], True)
  102. assert_equal(address_assert['ismine'], False)
  103. assert_equal(address_assert['timestamp'], timestamp)
  104. # ScriptPubKey + Public key + internal
  105. self.log.info("Should import a scriptPubKey with internal and with public key")
  106. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  107. request = [{
  108. "scriptPubKey": address['scriptPubKey'],
  109. "timestamp": "now",
  110. "pubkeys": [ address['pubkey'] ],
  111. "internal": True
  112. }]
  113. result = self.nodes[1].importmulti(request)
  114. assert_equal(result[0]['success'], True)
  115. address_assert = self.nodes[1].validateaddress(address['address'])
  116. assert_equal(address_assert['iswatchonly'], True)
  117. assert_equal(address_assert['ismine'], False)
  118. assert_equal(address_assert['timestamp'], timestamp)
  119. # ScriptPubKey + Public key + !internal
  120. self.log.info("Should not import a scriptPubKey without internal and with public key")
  121. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  122. request = [{
  123. "scriptPubKey": address['scriptPubKey'],
  124. "timestamp": "now",
  125. "pubkeys": [ address['pubkey'] ]
  126. }]
  127. result = self.nodes[1].importmulti(request)
  128. assert_equal(result[0]['success'], False)
  129. assert_equal(result[0]['error']['code'], -8)
  130. assert_equal(result[0]['error']['message'], 'Internal must be set for hex scriptPubKey')
  131. address_assert = self.nodes[1].validateaddress(address['address'])
  132. assert_equal(address_assert['iswatchonly'], False)
  133. assert_equal(address_assert['ismine'], False)
  134. assert_equal('timestamp' in address_assert, False)
  135. # Address + Private key + !watchonly
  136. self.log.info("Should import an address with private key")
  137. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  138. result = self.nodes[1].importmulti([{
  139. "scriptPubKey": {
  140. "address": address['address']
  141. },
  142. "timestamp": "now",
  143. "keys": [ self.nodes[0].dumpprivkey(address['address']) ]
  144. }])
  145. assert_equal(result[0]['success'], True)
  146. address_assert = self.nodes[1].validateaddress(address['address'])
  147. assert_equal(address_assert['iswatchonly'], False)
  148. assert_equal(address_assert['ismine'], True)
  149. assert_equal(address_assert['timestamp'], timestamp)
  150. self.log.info("Should not import an address with private key if is already imported")
  151. result = self.nodes[1].importmulti([{
  152. "scriptPubKey": {
  153. "address": address['address']
  154. },
  155. "timestamp": "now",
  156. "keys": [ self.nodes[0].dumpprivkey(address['address']) ]
  157. }])
  158. assert_equal(result[0]['success'], False)
  159. assert_equal(result[0]['error']['code'], -4)
  160. assert_equal(result[0]['error']['message'], 'The wallet already contains the private key for this address or script')
  161. # Address + Private key + watchonly
  162. self.log.info("Should not import an address with private key and with watchonly")
  163. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  164. result = self.nodes[1].importmulti([{
  165. "scriptPubKey": {
  166. "address": address['address']
  167. },
  168. "timestamp": "now",
  169. "keys": [ self.nodes[0].dumpprivkey(address['address']) ],
  170. "watchonly": True
  171. }])
  172. assert_equal(result[0]['success'], False)
  173. assert_equal(result[0]['error']['code'], -8)
  174. assert_equal(result[0]['error']['message'], 'Incompatibility found between watchonly and keys')
  175. address_assert = self.nodes[1].validateaddress(address['address'])
  176. assert_equal(address_assert['iswatchonly'], False)
  177. assert_equal(address_assert['ismine'], False)
  178. assert_equal('timestamp' in address_assert, False)
  179. # ScriptPubKey + Private key + internal
  180. self.log.info("Should import a scriptPubKey with internal and with private key")
  181. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  182. result = self.nodes[1].importmulti([{
  183. "scriptPubKey": address['scriptPubKey'],
  184. "timestamp": "now",
  185. "keys": [ self.nodes[0].dumpprivkey(address['address']) ],
  186. "internal": True
  187. }])
  188. assert_equal(result[0]['success'], True)
  189. address_assert = self.nodes[1].validateaddress(address['address'])
  190. assert_equal(address_assert['iswatchonly'], False)
  191. assert_equal(address_assert['ismine'], True)
  192. assert_equal(address_assert['timestamp'], timestamp)
  193. # ScriptPubKey + Private key + !internal
  194. self.log.info("Should not import a scriptPubKey without internal and with private key")
  195. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  196. result = self.nodes[1].importmulti([{
  197. "scriptPubKey": address['scriptPubKey'],
  198. "timestamp": "now",
  199. "keys": [ self.nodes[0].dumpprivkey(address['address']) ]
  200. }])
  201. assert_equal(result[0]['success'], False)
  202. assert_equal(result[0]['error']['code'], -8)
  203. assert_equal(result[0]['error']['message'], 'Internal must be set for hex scriptPubKey')
  204. address_assert = self.nodes[1].validateaddress(address['address'])
  205. assert_equal(address_assert['iswatchonly'], False)
  206. assert_equal(address_assert['ismine'], False)
  207. assert_equal('timestamp' in address_assert, False)
  208. # P2SH address
  209. sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  210. sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  211. sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  212. multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']])
  213. self.nodes[1].generate(100)
  214. transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
  215. self.nodes[1].generate(1)
  216. timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
  217. transaction = self.nodes[1].gettransaction(transactionid)
  218. self.log.info("Should import a p2sh")
  219. result = self.nodes[1].importmulti([{
  220. "scriptPubKey": {
  221. "address": multi_sig_script['address']
  222. },
  223. "timestamp": "now",
  224. }])
  225. assert_equal(result[0]['success'], True)
  226. address_assert = self.nodes[1].validateaddress(multi_sig_script['address'])
  227. assert_equal(address_assert['isscript'], True)
  228. assert_equal(address_assert['iswatchonly'], True)
  229. assert_equal(address_assert['timestamp'], timestamp)
  230. p2shunspent = self.nodes[1].listunspent(0,999999, [multi_sig_script['address']])[0]
  231. assert_equal(p2shunspent['spendable'], False)
  232. assert_equal(p2shunspent['solvable'], False)
  233. # P2SH + Redeem script
  234. sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  235. sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  236. sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  237. multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']])
  238. self.nodes[1].generate(100)
  239. transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
  240. self.nodes[1].generate(1)
  241. timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
  242. transaction = self.nodes[1].gettransaction(transactionid)
  243. self.log.info("Should import a p2sh with respective redeem script")
  244. result = self.nodes[1].importmulti([{
  245. "scriptPubKey": {
  246. "address": multi_sig_script['address']
  247. },
  248. "timestamp": "now",
  249. "redeemscript": multi_sig_script['redeemScript']
  250. }])
  251. assert_equal(result[0]['success'], True)
  252. address_assert = self.nodes[1].validateaddress(multi_sig_script['address'])
  253. assert_equal(address_assert['timestamp'], timestamp)
  254. p2shunspent = self.nodes[1].listunspent(0,999999, [multi_sig_script['address']])[0]
  255. assert_equal(p2shunspent['spendable'], False)
  256. assert_equal(p2shunspent['solvable'], True)
  257. # P2SH + Redeem script + Private Keys + !Watchonly
  258. sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  259. sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  260. sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  261. multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']])
  262. self.nodes[1].generate(100)
  263. transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
  264. self.nodes[1].generate(1)
  265. timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
  266. transaction = self.nodes[1].gettransaction(transactionid)
  267. self.log.info("Should import a p2sh with respective redeem script and private keys")
  268. result = self.nodes[1].importmulti([{
  269. "scriptPubKey": {
  270. "address": multi_sig_script['address']
  271. },
  272. "timestamp": "now",
  273. "redeemscript": multi_sig_script['redeemScript'],
  274. "keys": [ self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])]
  275. }])
  276. assert_equal(result[0]['success'], True)
  277. address_assert = self.nodes[1].validateaddress(multi_sig_script['address'])
  278. assert_equal(address_assert['timestamp'], timestamp)
  279. p2shunspent = self.nodes[1].listunspent(0,999999, [multi_sig_script['address']])[0]
  280. assert_equal(p2shunspent['spendable'], False)
  281. assert_equal(p2shunspent['solvable'], True)
  282. # P2SH + Redeem script + Private Keys + Watchonly
  283. sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  284. sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  285. sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  286. multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']])
  287. self.nodes[1].generate(100)
  288. transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
  289. self.nodes[1].generate(1)
  290. timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
  291. transaction = self.nodes[1].gettransaction(transactionid)
  292. self.log.info("Should import a p2sh with respective redeem script and private keys")
  293. result = self.nodes[1].importmulti([{
  294. "scriptPubKey": {
  295. "address": multi_sig_script['address']
  296. },
  297. "timestamp": "now",
  298. "redeemscript": multi_sig_script['redeemScript'],
  299. "keys": [ self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])],
  300. "watchonly": True
  301. }])
  302. assert_equal(result[0]['success'], False)
  303. assert_equal(result[0]['error']['code'], -8)
  304. assert_equal(result[0]['error']['message'], 'Incompatibility found between watchonly and keys')
  305. # Address + Public key + !Internal + Wrong pubkey
  306. self.log.info("Should not import an address with a wrong public key")
  307. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  308. address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  309. result = self.nodes[1].importmulti([{
  310. "scriptPubKey": {
  311. "address": address['address']
  312. },
  313. "timestamp": "now",
  314. "pubkeys": [ address2['pubkey'] ]
  315. }])
  316. assert_equal(result[0]['success'], False)
  317. assert_equal(result[0]['error']['code'], -5)
  318. assert_equal(result[0]['error']['message'], 'Consistency check failed')
  319. address_assert = self.nodes[1].validateaddress(address['address'])
  320. assert_equal(address_assert['iswatchonly'], False)
  321. assert_equal(address_assert['ismine'], False)
  322. assert_equal('timestamp' in address_assert, False)
  323. # ScriptPubKey + Public key + internal + Wrong pubkey
  324. self.log.info("Should not import a scriptPubKey with internal and with a wrong public key")
  325. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  326. address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  327. request = [{
  328. "scriptPubKey": address['scriptPubKey'],
  329. "timestamp": "now",
  330. "pubkeys": [ address2['pubkey'] ],
  331. "internal": True
  332. }]
  333. result = self.nodes[1].importmulti(request)
  334. assert_equal(result[0]['success'], False)
  335. assert_equal(result[0]['error']['code'], -5)
  336. assert_equal(result[0]['error']['message'], 'Consistency check failed')
  337. address_assert = self.nodes[1].validateaddress(address['address'])
  338. assert_equal(address_assert['iswatchonly'], False)
  339. assert_equal(address_assert['ismine'], False)
  340. assert_equal('timestamp' in address_assert, False)
  341. # Address + Private key + !watchonly + Wrong private key
  342. self.log.info("Should not import an address with a wrong private key")
  343. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  344. address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  345. result = self.nodes[1].importmulti([{
  346. "scriptPubKey": {
  347. "address": address['address']
  348. },
  349. "timestamp": "now",
  350. "keys": [ self.nodes[0].dumpprivkey(address2['address']) ]
  351. }])
  352. assert_equal(result[0]['success'], False)
  353. assert_equal(result[0]['error']['code'], -5)
  354. assert_equal(result[0]['error']['message'], 'Consistency check failed')
  355. address_assert = self.nodes[1].validateaddress(address['address'])
  356. assert_equal(address_assert['iswatchonly'], False)
  357. assert_equal(address_assert['ismine'], False)
  358. assert_equal('timestamp' in address_assert, False)
  359. # ScriptPubKey + Private key + internal + Wrong private key
  360. self.log.info("Should not import a scriptPubKey with internal and with a wrong private key")
  361. address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  362. address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
  363. result = self.nodes[1].importmulti([{
  364. "scriptPubKey": address['scriptPubKey'],
  365. "timestamp": "now",
  366. "keys": [ self.nodes[0].dumpprivkey(address2['address']) ],
  367. "internal": True
  368. }])
  369. assert_equal(result[0]['success'], False)
  370. assert_equal(result[0]['error']['code'], -5)
  371. assert_equal(result[0]['error']['message'], 'Consistency check failed')
  372. address_assert = self.nodes[1].validateaddress(address['address'])
  373. assert_equal(address_assert['iswatchonly'], False)
  374. assert_equal(address_assert['ismine'], False)
  375. assert_equal('timestamp' in address_assert, False)
  376. # Importing existing watch only address with new timestamp should replace saved timestamp.
  377. assert_greater_than(timestamp, watchonly_timestamp)
  378. self.log.info("Should replace previously saved watch only timestamp.")
  379. result = self.nodes[1].importmulti([{
  380. "scriptPubKey": {
  381. "address": watchonly_address,
  382. },
  383. "timestamp": "now",
  384. }])
  385. assert_equal(result[0]['success'], True)
  386. address_assert = self.nodes[1].validateaddress(watchonly_address)
  387. assert_equal(address_assert['iswatchonly'], True)
  388. assert_equal(address_assert['ismine'], False)
  389. assert_equal(address_assert['timestamp'], timestamp)
  390. watchonly_timestamp = timestamp
  391. # restart nodes to check for proper serialization/deserialization of watch only address
  392. self.stop_nodes()
  393. self.start_nodes()
  394. address_assert = self.nodes[1].validateaddress(watchonly_address)
  395. assert_equal(address_assert['iswatchonly'], True)
  396. assert_equal(address_assert['ismine'], False)
  397. assert_equal(address_assert['timestamp'], watchonly_timestamp)
  398. # Bad or missing timestamps
  399. self.log.info("Should throw on invalid or missing timestamp values")
  400. assert_raises_rpc_error(-3, 'Missing required timestamp field for key',
  401. self.nodes[1].importmulti, [{
  402. "scriptPubKey": address['scriptPubKey'],
  403. }])
  404. assert_raises_rpc_error(-3, 'Expected number or "now" timestamp value for key. got type string',
  405. self.nodes[1].importmulti, [{
  406. "scriptPubKey": address['scriptPubKey'],
  407. "timestamp": "",
  408. }])
  409. if __name__ == '__main__':
  410. ImportMultiTest ().main ()