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 21KB

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