URI: 
       ttest_commands.py - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
       ttest_commands.py (13026B)
       ---
            1 import unittest
            2 from unittest import mock
            3 from decimal import Decimal
            4 
            5 from electrum.util import create_and_start_event_loop
            6 from electrum.commands import Commands, eval_bool
            7 from electrum import storage, wallet
            8 from electrum.wallet import restore_wallet_from_text
            9 from electrum.simple_config import SimpleConfig
           10 
           11 from . import TestCaseForTestnet, ElectrumTestCase
           12 
           13 
           14 class TestCommands(ElectrumTestCase):
           15 
           16     def setUp(self):
           17         super().setUp()
           18         self.asyncio_loop, self._stop_loop, self._loop_thread = create_and_start_event_loop()
           19         self.config = SimpleConfig({'electrum_path': self.electrum_path})
           20 
           21     def tearDown(self):
           22         super().tearDown()
           23         self.asyncio_loop.call_soon_threadsafe(self._stop_loop.set_result, 1)
           24         self._loop_thread.join(timeout=1)
           25 
           26     def test_setconfig_non_auth_number(self):
           27         self.assertEqual(7777, Commands._setconfig_normalize_value('rpcport', "7777"))
           28         self.assertEqual(7777, Commands._setconfig_normalize_value('rpcport', '7777'))
           29         self.assertAlmostEqual(Decimal(2.3), Commands._setconfig_normalize_value('somekey', '2.3'))
           30 
           31     def test_setconfig_non_auth_number_as_string(self):
           32         self.assertEqual("7777", Commands._setconfig_normalize_value('somekey', "'7777'"))
           33 
           34     def test_setconfig_non_auth_boolean(self):
           35         self.assertEqual(True, Commands._setconfig_normalize_value('show_console_tab', "true"))
           36         self.assertEqual(True, Commands._setconfig_normalize_value('show_console_tab', "True"))
           37 
           38     def test_setconfig_non_auth_list(self):
           39         self.assertEqual(['file:///var/www/', 'https://electrum.org'],
           40             Commands._setconfig_normalize_value('url_rewrite', "['file:///var/www/','https://electrum.org']"))
           41         self.assertEqual(['file:///var/www/', 'https://electrum.org'],
           42             Commands._setconfig_normalize_value('url_rewrite', '["file:///var/www/","https://electrum.org"]'))
           43 
           44     def test_setconfig_auth(self):
           45         self.assertEqual("7777", Commands._setconfig_normalize_value('rpcuser', "7777"))
           46         self.assertEqual("7777", Commands._setconfig_normalize_value('rpcuser', '7777'))
           47         self.assertEqual("7777", Commands._setconfig_normalize_value('rpcpassword', '7777'))
           48         self.assertEqual("2asd", Commands._setconfig_normalize_value('rpcpassword', '2asd'))
           49         self.assertEqual("['file:///var/www/','https://electrum.org']",
           50             Commands._setconfig_normalize_value('rpcpassword', "['file:///var/www/','https://electrum.org']"))
           51 
           52     def test_eval_bool(self):
           53         self.assertFalse(eval_bool("False"))
           54         self.assertFalse(eval_bool("false"))
           55         self.assertFalse(eval_bool("0"))
           56         self.assertTrue(eval_bool("True"))
           57         self.assertTrue(eval_bool("true"))
           58         self.assertTrue(eval_bool("1"))
           59 
           60     def test_convert_xkey(self):
           61         cmds = Commands(config=self.config)
           62         xpubs = {
           63             ("xpub6CCWFbvCbqF92kGwm9nV7t7RvVoQUKaq5USMdyVP6jvv1NgN52KAX6NNYCeE8Ca7JQC4K5tZcnQrubQcjJ6iixfPs4pwAQJAQgTt6hBjg11", "standard"),
           64             ("ypub6X2mZGb7kWnct3U4bWa7KyCw6TwrQwaKzaxaRNPGUkJo4UVbKgUj9A2WZQbp87E2i3Js4ZV85SmQnt2BSzWjXCLzjQXMkK7egQXXVHT4eKn", "p2wpkh-p2sh"),
           65             ("zpub6qs2rwG2uCL6jLfBRsMjY4JSGS6JMZZpuhUoCmH9rkgg7aJpaLeHmDgeacZQ81sx7gRfp35gY77xgAdkAgvkKS2bbkDnLDw8x8bAsuKBrvP", "p2wpkh"),
           66         }
           67         for xkey1, xtype1 in xpubs:
           68             for xkey2, xtype2 in xpubs:
           69                 self.assertEqual(xkey2, cmds._run('convert_xkey', (xkey1, xtype2)))
           70 
           71         xprvs = {
           72             ("xprv9yD9r6PJmTgqpGCUf8FUkkAhNTxv4rryiFWkqb5mYQPw8aMDXUzuyJ3tgv5vUqYkdK1E6Q5jKxPss4HkMBYV4q8AfG8t7rxgyS4xQX4ndAm", "standard"),
           73             ("yprvAJ3R9m4Dv9EKfZPbVV36xqGCYS7N1UrUdN2ycyyevQmpBgASn9AUbMi2i83WUkCg2x82qsgHnckRkLuK4sxVs4omXbqJhmnBFA8bo8ssinK", "p2wpkh-p2sh"),
           74             ("zprvAcsgTRj94pmoWraiKqpjAvMhiQFox6qyYUZCQNsYJR9hEmyg2oL3DRNAjL16UerbSbEqbMGrFH6yddWsnaNWfJVNPwXjHgbfWtCFBgDxFkX", "p2wpkh"),
           75         }
           76         for xkey1, xtype1 in xprvs:
           77             for xkey2, xtype2 in xprvs:
           78                 self.assertEqual(xkey2, cmds._run('convert_xkey', (xkey1, xtype2)))
           79 
           80     @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
           81     def test_encrypt_decrypt(self, mock_save_db):
           82         wallet = restore_wallet_from_text('p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN',
           83                                           path='if_this_exists_mocking_failed_648151893',
           84                                           config=self.config)['wallet']
           85         cmds = Commands(config=self.config)
           86         cleartext = "asdasd this is the message"
           87         pubkey = "021f110909ded653828a254515b58498a6bafc96799fb0851554463ed44ca7d9da"
           88         ciphertext = cmds._run('encrypt', (pubkey, cleartext))
           89         self.assertEqual(cleartext, cmds._run('decrypt', (pubkey, ciphertext), wallet=wallet))
           90 
           91     @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
           92     def test_export_private_key_imported(self, mock_save_db):
           93         wallet = restore_wallet_from_text('p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL',
           94                                           path='if_this_exists_mocking_failed_648151893',
           95                                           config=self.config)['wallet']
           96         cmds = Commands(config=self.config)
           97         # single address tests
           98         with self.assertRaises(Exception):
           99             cmds._run('getprivatekeys', ("asdasd",), wallet=wallet)  # invalid addr, though might raise "not in wallet"
          100         with self.assertRaises(Exception):
          101             cmds._run('getprivatekeys', ("bc1qgfam82qk7uwh5j2xxmcd8cmklpe0zackyj6r23",), wallet=wallet)  # not in wallet
          102         self.assertEqual("p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL",
          103                          cmds._run('getprivatekeys', ("bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw",), wallet=wallet))
          104         # list of addresses tests
          105         with self.assertRaises(Exception):
          106             cmds._run('getprivatekeys', (['bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', 'asd'], ), wallet=wallet)
          107         self.assertEqual(['p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL', 'p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN'],
          108                          cmds._run('getprivatekeys', (['bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', 'bc1q9pzjpjq4nqx5ycnywekcmycqz0wjp2nq604y2n'], ), wallet=wallet))
          109 
          110     @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
          111     def test_export_private_key_deterministic(self, mock_save_db):
          112         wallet = restore_wallet_from_text('bitter grass shiver impose acquire brush forget axis eager alone wine silver',
          113                                           gap_limit=2,
          114                                           path='if_this_exists_mocking_failed_648151893',
          115                                           config=self.config)['wallet']
          116         cmds = Commands(config=self.config)
          117         # single address tests
          118         with self.assertRaises(Exception):
          119             cmds._run('getprivatekeys', ("asdasd",), wallet=wallet)  # invalid addr, though might raise "not in wallet"
          120         with self.assertRaises(Exception):
          121             cmds._run('getprivatekeys', ("bc1qgfam82qk7uwh5j2xxmcd8cmklpe0zackyj6r23",), wallet=wallet)  # not in wallet
          122         self.assertEqual("p2wpkh:L15oxP24NMNAXxq5r2aom24pHPtt3Fet8ZutgL155Bad93GSubM2",
          123                          cmds._run('getprivatekeys', ("bc1q3g5tmkmlvxryhh843v4dz026avatc0zzr6h3af",), wallet=wallet))
          124         # list of addresses tests
          125         with self.assertRaises(Exception):
          126             cmds._run('getprivatekeys', (['bc1q3g5tmkmlvxryhh843v4dz026avatc0zzr6h3af', 'asd'],), wallet=wallet)
          127         self.assertEqual(['p2wpkh:L15oxP24NMNAXxq5r2aom24pHPtt3Fet8ZutgL155Bad93GSubM2', 'p2wpkh:L4rYY5QpfN6wJEF4SEKDpcGhTPnCe9zcGs6hiSnhpprZqVywFifN'],
          128                          cmds._run('getprivatekeys', (['bc1q3g5tmkmlvxryhh843v4dz026avatc0zzr6h3af', 'bc1q9pzjpjq4nqx5ycnywekcmycqz0wjp2nq604y2n'], ), wallet=wallet))
          129 
          130 
          131 class TestCommandsTestnet(TestCaseForTestnet):
          132 
          133     def setUp(self):
          134         super().setUp()
          135         self.asyncio_loop, self._stop_loop, self._loop_thread = create_and_start_event_loop()
          136         self.config = SimpleConfig({'electrum_path': self.electrum_path})
          137 
          138     def tearDown(self):
          139         super().tearDown()
          140         self.asyncio_loop.call_soon_threadsafe(self._stop_loop.set_result, 1)
          141         self._loop_thread.join(timeout=1)
          142 
          143     def test_convert_xkey(self):
          144         cmds = Commands(config=self.config)
          145         xpubs = {
          146             ("tpubD8p5qNfjczgTGbh9qgNxsbFgyhv8GgfVkmp3L88qtRm5ibUYiDVCrn6WYfnGey5XVVw6Bc5QNQUZW5B4jFQsHjmaenvkFUgWtKtgj5AdPm9", "standard"),
          147             ("upub59wfQ8qJTg6ZSuvwtR313Qdp8gP8TSBwTof5dPQ3QVsYp1N9t29Rr9TGF1pj8kAXUg3mKbmrTKasA2qmBJKb1bGUzB6ApDZpVC7LoHhyvBo", "p2wpkh-p2sh"),
          148             ("vpub5UmvhoWDcMe3JD84impdFVjKJeXaQ4BSNvBJQnHvnWFRs7BP8gJzUD7QGDnK8epStKAa55NQuywR3KTKtzjbopx5rWnbQ8PJkvAzBtgaGBc", "p2wpkh"),
          149         }
          150         for xkey1, xtype1 in xpubs:
          151             for xkey2, xtype2 in xpubs:
          152                 self.assertEqual(xkey2, cmds._run('convert_xkey', (xkey1, xtype2)))
          153 
          154         xprvs = {
          155             ("tprv8c83gxdVUcznP8fMx2iNUBbaQgQC7MUbBUDG3c6YU9xgt7Dn5pfcgHUeNZTAvuYmNgVHjyTzYzGWwJr7GvKCm2FkPaaJipyipbfJeB3tdPW", "standard"),
          156             ("uprv8vxJzdJQdJYGERrUnPVzgGh5aeYe3yU66ajUpzzRrALZwD31LUqBJM8nPmQkvpCgnKc6VT4Z1ed4pbTfzcjDZFwMFvGjJjoD6Kix2pCwVe7", "p2wpkh-p2sh"),
          157             ("vprv9FnaJHyKmz5k5j3bckHctMnakch5zbTb1hFhcPtKEAiSzJrEb8zjvQnvQyNLvircBxiuEvf7UJycht5EiK9EMVcx8Fy9techN3nbRQRFhEv", "p2wpkh"),
          158         }
          159         for xkey1, xtype1 in xprvs:
          160             for xkey2, xtype2 in xprvs:
          161                 self.assertEqual(xkey2, cmds._run('convert_xkey', (xkey1, xtype2)))
          162 
          163     def test_serialize(self):
          164         cmds = Commands(config=self.config)
          165         jsontx = {
          166             "inputs": [
          167                 {
          168                     "prevout_hash": "9d221a69ca3997cbeaf5624d723e7dc5f829b1023078c177d37bdae95f37c539",
          169                     "prevout_n": 1,
          170                     "value_sats": 1000000,
          171                     "privkey": "p2wpkh:cVDXzzQg6RoCTfiKpe8MBvmm5d5cJc6JLuFApsFDKwWa6F5TVHpD"
          172                 }
          173             ],
          174             "outputs": [
          175                 {
          176                     "address": "tb1q4s8z6g5jqzllkgt8a4har94wl8tg0k9m8kv5zd",
          177                     "value_sats": 990000
          178                 }
          179             ]
          180         }
          181         self.assertEqual("0200000000010139c5375fe9da7bd377c1783002b129f8c57d3e724d62f5eacb9739ca691a229d0100000000feffffff01301b0f0000000000160014ac0e2d229200bffb2167ed6fd196aef9d687d8bb0247304402206367fb2ddd723985f5f51e0f2435084c0a66f5c26f4403a75d3dd417b71a20450220545dc3637bcb49beedbbdf5063e05cad63be91af4f839886451c30ecd6edf1d20121021f110909ded653828a254515b58498a6bafc96799fb0851554463ed44ca7d9da00000000",
          182                          cmds._run('serialize', (jsontx,)))
          183 
          184     def test_serialize_custom_nsequence(self):
          185         cmds = Commands(config=self.config)
          186         jsontx = {
          187             "inputs": [
          188                 {
          189                     "prevout_hash": "9d221a69ca3997cbeaf5624d723e7dc5f829b1023078c177d37bdae95f37c539",
          190                     "prevout_n": 1,
          191                     "value_sats": 1000000,
          192                     "privkey": "p2wpkh:cVDXzzQg6RoCTfiKpe8MBvmm5d5cJc6JLuFApsFDKwWa6F5TVHpD",
          193                     "nsequence": 0xfffffffd
          194                 }
          195             ],
          196             "outputs": [
          197                 {
          198                     "address": "tb1q4s8z6g5jqzllkgt8a4har94wl8tg0k9m8kv5zd",
          199                     "value_sats": 990000
          200                 }
          201             ]
          202         }
          203         self.assertEqual("0200000000010139c5375fe9da7bd377c1783002b129f8c57d3e724d62f5eacb9739ca691a229d0100000000fdffffff01301b0f0000000000160014ac0e2d229200bffb2167ed6fd196aef9d687d8bb0247304402201c551df0458528d19ba1dd79b134dcf0055f7b029dfc3d0d024e6253d069d13e02206d03cfc85a6fc648acb6fc6be630e4567d1dd00ddbcdee551ee0711414e2f33f0121021f110909ded653828a254515b58498a6bafc96799fb0851554463ed44ca7d9da00000000",
          204                          cmds._run('serialize', (jsontx,)))
          205 
          206     @mock.patch.object(wallet.Abstract_Wallet, 'save_db')
          207     def test_getprivatekeyforpath(self, mock_save_db):
          208         wallet = restore_wallet_from_text('north rent dawn bunker hamster invest wagon market romance pig either squeeze',
          209                                           gap_limit=2,
          210                                           path='if_this_exists_mocking_failed_648151893',
          211                                           config=self.config)['wallet']
          212         cmds = Commands(config=self.config)
          213         self.assertEqual("p2wpkh:cUzm7zPpWgLYeURgff4EsoMjhskCpsviBH4Y3aZcrBX8UJSRPjC2",
          214                          cmds._run('getprivatekeyforpath', ([0, 10000],), wallet=wallet))
          215         self.assertEqual("p2wpkh:cUzm7zPpWgLYeURgff4EsoMjhskCpsviBH4Y3aZcrBX8UJSRPjC2",
          216                          cmds._run('getprivatekeyforpath', ("m/0/10000",), wallet=wallet))
          217         self.assertEqual("p2wpkh:cQAj4WGf1socCPCJNMjXYCJ8Bs5JUAk5pbDr4ris44QdgAXcV24S",
          218                          cmds._run('getprivatekeyforpath', ("m/5h/100000/88h/7",), wallet=wallet))