ttest_wallet_vertical.py - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- ttest_wallet_vertical.py (357049B) --- 1 import unittest 2 from unittest import mock 3 import shutil 4 import tempfile 5 from typing import Sequence 6 import asyncio 7 import copy 8 9 from electrum import storage, bitcoin, keystore, bip32, wallet 10 from electrum import Transaction 11 from electrum import SimpleConfig 12 from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_UNCONF_PARENT 13 from electrum.wallet import (sweep, Multisig_Wallet, Standard_Wallet, Imported_Wallet, 14 restore_wallet_from_text, Abstract_Wallet, BumpFeeStrategy) 15 from electrum.util import bfh, bh2u, create_and_start_event_loop 16 from electrum.transaction import (TxOutput, Transaction, PartialTransaction, PartialTxOutput, 17 PartialTxInput, tx_from_any, TxOutpoint) 18 from electrum.mnemonic import seed_type 19 20 from electrum.plugins.trustedcoin import trustedcoin 21 22 from . import TestCaseForTestnet 23 from . import ElectrumTestCase 24 25 26 UNICODE_HORROR_HEX = 'e282bf20f09f988020f09f98882020202020e3818620e38191e3819fe381be20e3828fe3828b2077cda2cda2cd9d68cda16fcda2cda120ccb8cda26bccb5cd9f6eccb4cd98c7ab77ccb8cc9b73cd9820cc80cc8177cd98cda2e1b8a9ccb561d289cca1cda27420cca7cc9568cc816fccb572cd8fccb5726f7273cca120ccb6cda1cda06cc4afccb665cd9fcd9f20ccb6cd9d696ecda220cd8f74cc9568ccb7cca1cd9f6520cd9fcd9f64cc9b61cd9c72cc95cda16bcca2cca820cda168ccb465cd8f61ccb7cca2cca17274cc81cd8f20ccb4ccb7cda0c3b2ccb5ccb666ccb82075cca7cd986ec3adcc9bcd9c63cda2cd8f6fccb7cd8f64ccb8cda265cca1cd9d3fcd9e' 27 UNICODE_HORROR = bfh(UNICODE_HORROR_HEX).decode('utf-8') 28 assert UNICODE_HORROR == '₿ 😀 😈 う けたま わる w͢͢͝h͡o͢͡ ̸͢k̵͟n̴͘ǫw̸̛s͘ ̀́w͘͢ḩ̵a҉̡͢t ̧̕h́o̵r͏̵rors̡ ̶͡͠lį̶e͟͟ ̶͝in͢ ͏t̕h̷̡͟e ͟͟d̛a͜r̕͡k̢̨ ͡h̴e͏a̷̢̡rt́͏ ̴̷͠ò̵̶f̸ u̧͘ní̛͜c͢͏o̷͏d̸͢e̡͝?͞' 29 30 31 class WalletIntegrityHelper: 32 33 gap_limit = 1 # make tests run faster 34 35 @classmethod 36 def check_seeded_keystore_sanity(cls, test_obj, ks): 37 test_obj.assertTrue(ks.is_deterministic()) 38 test_obj.assertFalse(ks.is_watching_only()) 39 test_obj.assertFalse(ks.can_import()) 40 test_obj.assertTrue(ks.has_seed()) 41 42 @classmethod 43 def check_xpub_keystore_sanity(cls, test_obj, ks): 44 test_obj.assertTrue(ks.is_deterministic()) 45 test_obj.assertTrue(ks.is_watching_only()) 46 test_obj.assertFalse(ks.can_import()) 47 test_obj.assertFalse(ks.has_seed()) 48 49 @classmethod 50 def create_standard_wallet(cls, ks, *, config: SimpleConfig, gap_limit=None): 51 db = storage.WalletDB('', manual_upgrades=False) 52 db.put('keystore', ks.dump()) 53 db.put('gap_limit', gap_limit or cls.gap_limit) 54 w = Standard_Wallet(db, None, config=config) 55 w.synchronize() 56 return w 57 58 @classmethod 59 def create_imported_wallet(cls, *, config: SimpleConfig, privkeys: bool): 60 db = storage.WalletDB('', manual_upgrades=False) 61 if privkeys: 62 k = keystore.Imported_KeyStore({}) 63 db.put('keystore', k.dump()) 64 w = Imported_Wallet(db, None, config=config) 65 return w 66 67 @classmethod 68 def create_multisig_wallet(cls, keystores: Sequence, multisig_type: str, *, 69 config: SimpleConfig, gap_limit=None): 70 """Creates a multisig wallet.""" 71 db = storage.WalletDB('', manual_upgrades=True) 72 for i, ks in enumerate(keystores): 73 cosigner_index = i + 1 74 db.put('x%d/' % cosigner_index, ks.dump()) 75 db.put('wallet_type', multisig_type) 76 db.put('gap_limit', gap_limit or cls.gap_limit) 77 w = Multisig_Wallet(db, None, config=config) 78 w.synchronize() 79 return w 80 81 82 class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): 83 84 def setUp(self): 85 super().setUp() 86 self.config = SimpleConfig({'electrum_path': self.electrum_path}) 87 88 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 89 def test_electrum_seed_standard(self, mock_save_db): 90 seed_words = 'cycle rocket west magnet parrot shuffle foot correct salt library feed song' 91 self.assertEqual(seed_type(seed_words), 'standard') 92 93 ks = keystore.from_seed(seed_words, '', False) 94 95 WalletIntegrityHelper.check_seeded_keystore_sanity(self, ks) 96 self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) 97 98 self.assertEqual(ks.xprv, 'xprv9s21ZrQH143K32jECVM729vWgGq4mUDJCk1ozqAStTphzQtCTuoFmFafNoG1g55iCnBTXUzz3zWnDb5CVLGiFvmaZjuazHDL8a81cPQ8KL6') 99 self.assertEqual(ks.xpub, 'xpub661MyMwAqRbcFWohJWt7PHsFEJfZAvw9ZxwQoDa4SoMgsDDM1T7WK3u9E4edkC4ugRnZ8E4xDZRpk8Rnts3Nbt97dPwT52CwBdDWroaZf8U') 100 101 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 102 self.assertEqual(w.txin_type, 'p2pkh') 103 104 self.assertEqual(w.get_receiving_addresses()[0], '1NNkttn1YvVGdqBW4PR6zvc3Zx3H5owKRf') 105 self.assertEqual(w.get_change_addresses()[0], '1KSezYMhAJMWqFbVFB2JshYg69UpmEXR4D') 106 107 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 108 def test_electrum_seed_segwit(self, mock_save_db): 109 seed_words = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' 110 self.assertEqual(seed_type(seed_words), 'segwit') 111 112 ks = keystore.from_seed(seed_words, '', False) 113 114 WalletIntegrityHelper.check_seeded_keystore_sanity(self, ks) 115 self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) 116 117 self.assertEqual(ks.xprv, 'zprvAZswDvNeJeha8qZ8g7efN3FXYVJLaEUsE9TW6qXDEbVe74AZ75c2sZFZXPNFzxnhChDQ89oC8C5AjWwHmH1HeRKE1c4kKBQAmjUDdKDUZw2') 118 self.assertEqual(ks.xpub, 'zpub6nsHdRuY92FsMKdbn9BfjBCG6X8pyhCibNP6uDvpnw2cyrVhecvHRMa3Ne8kdJZxjxgwnpbHLkcR4bfnhHy6auHPJyDTQ3kianeuVLdkCYQ') 119 120 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 121 self.assertEqual(w.txin_type, 'p2wpkh') 122 123 self.assertEqual(w.get_receiving_addresses()[0], 'bc1q3g5tmkmlvxryhh843v4dz026avatc0zzr6h3af') 124 self.assertEqual(w.get_change_addresses()[0], 'bc1qdy94n2q5qcp0kg7v9yzwe6wvfkhnvyzje7nx2p') 125 126 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 127 def test_electrum_seed_segwit_passphrase(self, mock_save_db): 128 seed_words = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' 129 self.assertEqual(seed_type(seed_words), 'segwit') 130 131 ks = keystore.from_seed(seed_words, UNICODE_HORROR, False) 132 133 WalletIntegrityHelper.check_seeded_keystore_sanity(self, ks) 134 self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) 135 136 self.assertEqual(ks.xprv, 'zprvAZDmEQiCLUcZXPfrBXoksCD2R6RMAzAre7SUyBotibisy9c7vGhLYvHaP3d9rYU12DKAWdZfscPNA7qEPgTkCDqX5sE93ryAJAQvkDbfLxU') 137 self.assertEqual(ks.xpub, 'zpub6nD7dvF6ArArjskKHZLmEL9ky8FqaSti1LN5maDWGwFrqwwGTp1b6ic4EHwciFNaYDmCXcQYxXSiF9BjcLCMPcaYkVN2nQD6QjYQ8vpSR3Z') 138 139 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 140 self.assertEqual(w.txin_type, 'p2wpkh') 141 142 self.assertEqual(w.get_receiving_addresses()[0], 'bc1qx94dutas7ysn2my645cyttujrms5d9p57f6aam') 143 self.assertEqual(w.get_change_addresses()[0], 'bc1qcywwsy87sdp8vz5rfjh3sxdv6rt95kujdqq38g') 144 145 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 146 def test_electrum_seed_old(self, mock_save_db): 147 seed_words = 'powerful random nobody notice nothing important anyway look away hidden message over' 148 self.assertEqual(seed_type(seed_words), 'old') 149 150 ks = keystore.from_seed(seed_words, '', False) 151 152 WalletIntegrityHelper.check_seeded_keystore_sanity(self, ks) 153 self.assertTrue(isinstance(ks, keystore.Old_KeyStore)) 154 155 self.assertEqual(ks.mpk, 'e9d4b7866dd1e91c862aebf62a49548c7dbf7bcc6e4b7b8c9da820c7737968df9c09d5a3e271dc814a29981f81b3faaf2737b551ef5dcc6189cf0f8252c442b3') 156 157 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 158 self.assertEqual(w.txin_type, 'p2pkh') 159 160 self.assertEqual(w.get_receiving_addresses()[0], '1FJEEB8ihPMbzs2SkLmr37dHyRFzakqUmo') 161 self.assertEqual(w.get_change_addresses()[0], '1KRW8pH6HFHZh889VDq6fEKvmrsmApwNfe') 162 163 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 164 def test_electrum_seed_2fa_legacy_pre27(self, mock_save_db): 165 # pre-version-2.7 2fa seed 166 seed_words = 'bind clever room kidney crucial sausage spy edit canvas soul liquid ribbon slam open alpha suffer gate relax voice carpet law hill woman tonight abstract' 167 self.assertEqual(seed_type(seed_words), '2fa') 168 169 xprv1, xpub1, xprv2, xpub2 = trustedcoin.TrustedCoinPlugin.xkeys_from_seed(seed_words, '') 170 171 ks1 = keystore.from_xprv(xprv1) 172 self.assertTrue(isinstance(ks1, keystore.BIP32_KeyStore)) 173 self.assertEqual(ks1.xprv, 'xprv9s21ZrQH143K2TsDemiaPqaTuBkW3gns4sGi9f65pWtg27nmmmAut6fErgaHFxj3d4rHgyFKjhvtAUafqF3wwU8Bkou8LefQgBtRWjUKN3V') 174 self.assertEqual(ks1.xpub, 'xpub661MyMwAqRbcEwwgkoFakyXCTDazT9WiS6CJx3VhNrRetv7vKJVARtyihwCVatSsUtVsEYcvdxhvDtkSk8qKV3VVtcL3csz6sQTbGzmEckd') 175 self.assertEqual(ks1.xpub, xpub1) 176 177 ks2 = keystore.from_xprv(xprv2) 178 self.assertTrue(isinstance(ks2, keystore.BIP32_KeyStore)) 179 self.assertEqual(ks2.xprv, 'xprv9s21ZrQH143K3r6H1h91TqRECE7tmDB5PYGZDKPuSjefTzNbDMauUMUnjsUSv8X8nuzQsrtGmtCuA51CNz7XimRj2HPYxUxXGGf4KB7M74y') 180 self.assertEqual(ks2.xpub, 'xpub661MyMwAqRbcGLAk7ig1pyMxkFxPAftvkmCA1hoX15BeLnhjktuA29oGb7bh9opQgNERu6iWhwcY6b5bZX57dYsGo7zYjwXTNCryfKuPfek') 181 self.assertEqual(ks2.xpub, xpub2) 182 183 long_user_id, short_id = trustedcoin.get_user_id( 184 {'x1/': {'xpub': xpub1}, 185 'x2/': {'xpub': xpub2}}) 186 xtype = bip32.xpub_type(xpub1) 187 xpub3 = trustedcoin.make_xpub(trustedcoin.get_signing_xpub(xtype), long_user_id) 188 ks3 = keystore.from_xpub(xpub3) 189 WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks3) 190 self.assertTrue(isinstance(ks3, keystore.BIP32_KeyStore)) 191 192 w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2, ks3], '2of3', config=self.config) 193 self.assertEqual(w.txin_type, 'p2sh') 194 195 self.assertEqual(w.get_receiving_addresses()[0], '3Bw5jczNModhFAbvfwvUHbdGrC2Lh2qRQp') 196 self.assertEqual(w.get_change_addresses()[0], '3Ke6pKrmtSyyQaMob1ES4pk8siAAkRmst9') 197 198 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 199 def test_electrum_seed_2fa_legacy_post27(self, mock_save_db): 200 # post-version-2.7 2fa seed 201 seed_words = 'kiss live scene rude gate step hip quarter bunker oxygen motor glove' 202 self.assertEqual(seed_type(seed_words), '2fa') 203 204 xprv1, xpub1, xprv2, xpub2 = trustedcoin.TrustedCoinPlugin.xkeys_from_seed(seed_words, '') 205 206 ks1 = keystore.from_xprv(xprv1) 207 self.assertTrue(isinstance(ks1, keystore.BIP32_KeyStore)) 208 self.assertEqual(ks1.xprv, 'xprv9uraXy9F3HP7i8QDqwNTBiD8Jf4bPD4Epif8cS8qbUbgeidUesyZpKmzfcSeHutsGfFnjgih7kzwTB5UQVRNB5LoXaNc8pFusKYx3KVVvYR') 209 self.assertEqual(ks1.xpub, 'xpub68qvwUg8sewQvcUgwxuTYr9rrgu5nfn6BwajQpYT9p8fXWxdCRHpN86UWruWJAD1ede8Sv8ERrTa22Gyc4SBfm7zFpcyoVWVBKCVwnw6s1J') 210 self.assertEqual(ks1.xpub, xpub1) 211 212 ks2 = keystore.from_xprv(xprv2) 213 self.assertTrue(isinstance(ks2, keystore.BIP32_KeyStore)) 214 self.assertEqual(ks2.xprv, 'xprv9uraXy9F3HP7kKSiRAvLV7Nrjj7YzspDys7dvGLLu4tLZT49CEBxPWp88dHhVxvZ69SHrPQMUCWjj4Ka2z9kNvs1HAeEf3extGGeSWqEVqf') 215 self.assertEqual(ks2.xpub, 'xpub68qvwUg8sewQxoXBXCTLrFKbHkx3QLY5M63EiejxTQRKSFPHjmWCwK8byvZMM2wZNYA3SmxXoma3M1zxhGESHZwtB7SwrxRgKXAG8dCD2eS') 216 self.assertEqual(ks2.xpub, xpub2) 217 218 long_user_id, short_id = trustedcoin.get_user_id( 219 {'x1/': {'xpub': xpub1}, 220 'x2/': {'xpub': xpub2}}) 221 xtype = bip32.xpub_type(xpub1) 222 xpub3 = trustedcoin.make_xpub(trustedcoin.get_signing_xpub(xtype), long_user_id) 223 ks3 = keystore.from_xpub(xpub3) 224 WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks3) 225 self.assertTrue(isinstance(ks3, keystore.BIP32_KeyStore)) 226 227 w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2, ks3], '2of3', config=self.config) 228 self.assertEqual(w.txin_type, 'p2sh') 229 230 self.assertEqual(w.get_receiving_addresses()[0], '35L8XmCDoEBKeaWRjvmZvoZvhp8BXMMMPV') 231 self.assertEqual(w.get_change_addresses()[0], '3PeZEcumRqHSPNN43hd4yskGEBdzXgY8Cy') 232 233 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 234 def test_electrum_seed_2fa_segwit(self, mock_save_db): 235 seed_words = 'universe topic remind silver february ranch shine worth innocent cattle enhance wise' 236 self.assertEqual(seed_type(seed_words), '2fa_segwit') 237 238 xprv1, xpub1, xprv2, xpub2 = trustedcoin.TrustedCoinPlugin.xkeys_from_seed(seed_words, '') 239 240 ks1 = keystore.from_xprv(xprv1) 241 self.assertTrue(isinstance(ks1, keystore.BIP32_KeyStore)) 242 self.assertEqual(ks1.xprv, 'ZprvAm1R3RZMrkSLYKZer8QECGoc8oA1RQuKfsztHkBTmi2yF8RhmN1JRb7Ag69mMrL88sP67WiaegaSSDnKndorWEpFr7a5B2QgrD7TkERSYX6') 243 self.assertEqual(ks1.xpub, 'Zpub6yzmSw6Fh7zdkoe7x9wEZQkLgpzVpsdB36vV68b5L3Zx7vkrJuKYyPReXMSjBegmtUjFBxP2uZEdL87cYvtTtGaVuwtRRCTSFUsoAdKZMge') 244 self.assertEqual(ks1.xpub, xpub1) 245 246 ks2 = keystore.from_xprv(xprv2) 247 self.assertTrue(isinstance(ks2, keystore.BIP32_KeyStore)) 248 self.assertEqual(ks2.xprv, 'ZprvAm1R3RZMrkSLab4jVKTwuroBgKEfnsmK9CQa1ErkuRzpsPauYuv9z2UzhDNn9YgbLHcmXpmxbNq4MdDRAUM5B2N9Wr3Uq9yp2c4AtTJDFdi') 249 self.assertEqual(ks2.xpub, 'Zpub6yzmSw6Fh7zdo59CbLzxGzjvEM5ACLVAWRLAodGNTmXokBv46TEQXpoUYUaoxPCeynysxg7APfScikCQ2jhCfM3NcNEk46BCVfSSrdrSkbR') 250 self.assertEqual(ks2.xpub, xpub2) 251 252 long_user_id, short_id = trustedcoin.get_user_id( 253 {'x1/': {'xpub': xpub1}, 254 'x2/': {'xpub': xpub2}}) 255 xtype = bip32.xpub_type(xpub1) 256 xpub3 = trustedcoin.make_xpub(trustedcoin.get_signing_xpub(xtype), long_user_id) 257 ks3 = keystore.from_xpub(xpub3) 258 WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks3) 259 self.assertTrue(isinstance(ks3, keystore.BIP32_KeyStore)) 260 261 w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2, ks3], '2of3', config=self.config) 262 self.assertEqual(w.txin_type, 'p2wsh') 263 264 self.assertEqual(w.get_receiving_addresses()[0], 'bc1qpmufh0zjp5prfsrk2yskcy82sa26srqkd97j0457andc6m0gh5asw7kqd2') 265 self.assertEqual(w.get_change_addresses()[0], 'bc1qd4q50nft7kxm9yglfnpup9ed2ukj3tkxp793y0zya8dc9m39jcwq308dxz') 266 267 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 268 def test_bip39_seed_bip44_standard(self, mock_save_db): 269 seed_words = 'treat dwarf wealth gasp brass outside high rent blood crowd make initial' 270 self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) 271 272 ks = keystore.from_bip39_seed(seed_words, '', "m/44'/0'/0'") 273 274 self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) 275 276 self.assertEqual(ks.xprv, 'xprv9zGLcNEb3cHUKizLVBz6RYeE9bEZAVPjH2pD1DEzCnPcsemWc3d3xTao8sfhfUmDLMq6e3RcEMEvJG1Et8dvfL8DV4h7mwm9J6AJsW9WXQD') 277 self.assertEqual(ks.xpub, 'xpub6DFh1smUsyqmYD4obDX6ngaxhd53Zx7aeFjoobebm7vbkT6f9awJWFuGzBT9FQJEWFBL7UyhMXtYzRcwDuVbcxtv9Ce2W9eMm4KXLdvdbjv') 278 279 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 280 self.assertEqual(w.txin_type, 'p2pkh') 281 282 self.assertEqual(w.get_receiving_addresses()[0], '16j7Dqk3Z9DdTdBtHcCVLaNQy9MTgywUUo') 283 self.assertEqual(w.get_change_addresses()[0], '1GG5bVeWgAp5XW7JLCphse14QaC4qiHyWn') 284 285 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 286 def test_bip39_seed_bip44_standard_passphrase(self, mock_save_db): 287 seed_words = 'treat dwarf wealth gasp brass outside high rent blood crowd make initial' 288 self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) 289 290 ks = keystore.from_bip39_seed(seed_words, UNICODE_HORROR, "m/44'/0'/0'") 291 292 self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) 293 294 self.assertEqual(ks.xprv, 'xprv9z8izheguGnLopSqkY7GcGFrP2Gu6rzBvvHo6uB9B8DWJhsows6WDZAsbBTaP3ncP2AVbTQphyEQkahrB9s1L7ihZtfz5WGQPMbXwsUtSik') 295 self.assertEqual(ks.xpub, 'xpub6D85QDBajeLe2JXJrZeGyQCaw47PWKi3J9DPuHakjTkVBWCxVQQkmMVMSSfnw39tj9FntbozpRtb1AJ8ubjeVSBhyK4M5mzdvsXZzKPwodT') 296 297 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 298 self.assertEqual(w.txin_type, 'p2pkh') 299 300 self.assertEqual(w.get_receiving_addresses()[0], '1F88g2naBMhDB7pYFttPWGQgryba3hPevM') 301 self.assertEqual(w.get_change_addresses()[0], '1H4QD1rg2zQJ4UjuAVJr5eW1fEM8WMqyxh') 302 303 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 304 def test_bip39_seed_bip49_p2sh_segwit(self, mock_save_db): 305 seed_words = 'treat dwarf wealth gasp brass outside high rent blood crowd make initial' 306 self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) 307 308 ks = keystore.from_bip39_seed(seed_words, '', "m/49'/0'/0'") 309 310 self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) 311 312 self.assertEqual(ks.xprv, 'yprvAJEYHeNEPcyBoQYM7sGCxDiNCTX65u4ANgZuSGTrKN5YCC9MP84SBayrgaMyZV7zvkHrr3HVPTK853s2SPk4EttPazBZBmz6QfDkXeE8Zr7') 313 self.assertEqual(ks.xpub, 'ypub6XDth9u8DzXV1tcpDtoDKMf6kVMaVMn1juVWEesTshcX4zUVvfNgjPJLXrD9N7AdTLnbHFL64KmBn3SNaTe69iZYbYCqLCCNPZKbLz9niQ4') 314 315 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 316 self.assertEqual(w.txin_type, 'p2wpkh-p2sh') 317 318 self.assertEqual(w.get_receiving_addresses()[0], '35ohQTdNykjkF1Mn9nAVEFjupyAtsPAK1W') 319 self.assertEqual(w.get_change_addresses()[0], '3KaBTcviBLEJajTEMstsA2GWjYoPzPK7Y7') 320 321 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 322 def test_bip39_seed_bip84_native_segwit(self, mock_save_db): 323 # test case from bip84 324 seed_words = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about' 325 self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) 326 327 ks = keystore.from_bip39_seed(seed_words, '', "m/84'/0'/0'") 328 329 self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) 330 331 self.assertEqual(ks.xprv, 'zprvAdG4iTXWBoARxkkzNpNh8r6Qag3irQB8PzEMkAFeTRXxHpbF9z4QgEvBRmfvqWvGp42t42nvgGpNgYSJA9iefm1yYNZKEm7z6qUWCroSQnE') 332 self.assertEqual(ks.xpub, 'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs') 333 334 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 335 self.assertEqual(w.txin_type, 'p2wpkh') 336 337 self.assertEqual(w.get_receiving_addresses()[0], 'bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu') 338 self.assertEqual(w.get_change_addresses()[0], 'bc1q8c6fshw2dlwun7ekn9qwf37cu2rn755upcp6el') 339 340 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 341 def test_electrum_multisig_seed_standard(self, mock_save_db): 342 seed_words = 'blast uniform dragon fiscal ensure vast young utility dinosaur abandon rookie sure' 343 self.assertEqual(seed_type(seed_words), 'standard') 344 345 ks1 = keystore.from_seed(seed_words, '', True) 346 WalletIntegrityHelper.check_seeded_keystore_sanity(self, ks1) 347 self.assertTrue(isinstance(ks1, keystore.BIP32_KeyStore)) 348 self.assertEqual(ks1.xprv, 'xprv9s21ZrQH143K3t9vo23J3hajRbzvkRLJ6Y1zFrUFAfU3t8oooMPfb7f87cn5KntgqZs5nipZkCiBFo5ZtaSD2eDo7j7CMuFV8Zu6GYLTpY6') 349 self.assertEqual(ks1.xpub, 'xpub661MyMwAqRbcGNEPu3aJQqXTydqR9t49Tkwb4Esrj112kw8xLthv8uybxvaki4Ygt9xiwZUQGeFTG7T2TUzR3eA4Zp3aq5RXsABHFBUrq4c') 350 351 # electrum seed: ghost into match ivory badge robot record tackle radar elbow traffic loud 352 ks2 = keystore.from_xpub('xpub661MyMwAqRbcGfCPEkkyo5WmcrhTq8mi3xuBS7VEZ3LYvsgY1cCFDbenT33bdD12axvrmXhuX3xkAbKci3yZY9ZEk8vhLic7KNhLjqdh5ec') 353 WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks2) 354 self.assertTrue(isinstance(ks2, keystore.BIP32_KeyStore)) 355 356 w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2', config=self.config) 357 self.assertEqual(w.txin_type, 'p2sh') 358 359 self.assertEqual(w.get_receiving_addresses()[0], '32ji3QkAgXNz6oFoRfakyD3ys1XXiERQYN') 360 self.assertEqual(w.get_change_addresses()[0], '36XWwEHrrVCLnhjK5MrVVGmUHghr9oWTN1') 361 362 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 363 def test_electrum_multisig_seed_segwit(self, mock_save_db): 364 seed_words = 'snow nest raise royal more walk demise rotate smooth spirit canyon gun' 365 self.assertEqual(seed_type(seed_words), 'segwit') 366 367 ks1 = keystore.from_seed(seed_words, '', True) 368 WalletIntegrityHelper.check_seeded_keystore_sanity(self, ks1) 369 self.assertTrue(isinstance(ks1, keystore.BIP32_KeyStore)) 370 self.assertEqual(ks1.xprv, 'ZprvAjxLRqPiDfPDxXrm8JvcoCGRAW6xUtktucG6AMtdzaEbTEJN8qcECvujfhtDU3jLJ9g3Dr3Gz5m1ypfMs8iSUh62gWyHZ73bYLRWyeHf6y4') 371 self.assertEqual(ks1.xpub, 'Zpub6xwgqLvc42wXB1wEELTdALD9iXwStMUkGqBgxkJFYumaL2dWgNvUkjEDWyDFZD3fZuDWDzd1KQJ4NwVHS7hs6H6QkpNYSShfNiUZsgMdtNg') 372 373 # electrum seed: hedgehog sunset update estate number jungle amount piano friend donate upper wool 374 ks2 = keystore.from_xpub('Zpub6y4oYeETXAbzLNg45wcFDGwEG3vpgsyMJybiAfi2pJtNF3i3fJVxK2BeZJaw7VeKZm192QHvXP3uHDNpNmNDbQft9FiMzkKUhNXQafUMYUY') 375 WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks2) 376 self.assertTrue(isinstance(ks2, keystore.BIP32_KeyStore)) 377 378 w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2', config=self.config) 379 self.assertEqual(w.txin_type, 'p2wsh') 380 381 self.assertEqual(w.get_receiving_addresses()[0], 'bc1qvzezdcv6vs5h45ugkavp896e0nde5c5lg5h0fwe2xyfhnpkxq6gq7pnwlc') 382 self.assertEqual(w.get_change_addresses()[0], 'bc1qxqf840dqswcmu7a8v82fj6ej0msx08flvuy6kngr7axstjcaq6us9hrehd') 383 384 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 385 def test_bip39_multisig_seed_bip45_standard(self, mock_save_db): 386 seed_words = 'treat dwarf wealth gasp brass outside high rent blood crowd make initial' 387 self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) 388 389 ks1 = keystore.from_bip39_seed(seed_words, '', "m/45'/0") 390 self.assertTrue(isinstance(ks1, keystore.BIP32_KeyStore)) 391 self.assertEqual(ks1.xprv, 'xprv9vyEFyXf7pYVv4eDU3hhuCEAHPHNGuxX73nwtYdpbLcqwJCPwFKknAK8pHWuHHBirCzAPDZ7UJHrYdhLfn1NkGp9rk3rVz2aEqrT93qKRD9') 392 self.assertEqual(ks1.xpub, 'xpub69xafV4YxC6o8Yiga5EiGLAtqR7rgNgNUGiYgw3S9g9pp6XYUne1KxdcfYtxwmA3eBrzMFuYcNQKfqsXCygCo4GxQFHfywxpUbKNfYvGJka') 393 394 # bip39 seed: tray machine cook badge night page project uncover ritual toward person enact 395 # der: m/45'/0 396 ks2 = keystore.from_xpub('xpub6B26nSWddbWv7J3qQn9FbwPPQktSBdPQfLfHhRK4375QoZq8fvM8rQey1koGSTxC5xVoMzNMaBETMUmCqmXzjc8HyAbN7LqrvE4ovGRwNGg') 397 WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks2) 398 self.assertTrue(isinstance(ks2, keystore.BIP32_KeyStore)) 399 400 w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2', config=self.config) 401 self.assertEqual(w.txin_type, 'p2sh') 402 403 self.assertEqual(w.get_receiving_addresses()[0], '3JPTQ2nitVxXBJ1yhMeDwH6q417UifE3bN') 404 self.assertEqual(w.get_change_addresses()[0], '3FGyDuxgUDn2pSZe5xAJH1yUwSdhzDMyEE') 405 406 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 407 def test_bip39_multisig_seed_p2sh_segwit(self, mock_save_db): 408 # bip39 seed: pulse mixture jazz invite dune enrich minor weapon mosquito flight fly vapor 409 # der: m/49'/0'/0' 410 # NOTE: there is currently no bip43 standard derivation path for p2wsh-p2sh 411 ks1 = keystore.from_xprv('YprvAUXFReVvDjrPerocC3FxVH748sJUTvYjkAhtKop5VnnzVzMEHr1CHrYQKZwfJn1As3X4LYMav6upxd5nDiLb6SCjRZrBH76EFvyQAG4cn79') 412 self.assertTrue(isinstance(ks1, keystore.BIP32_KeyStore)) 413 self.assertEqual(ks1.xpub, 'Ypub6hWbqA2p47QgsLt5J4nxrR3ngu8xsPGb7PdV8CDh48KyNngNqPKSqertAqYhQ4umELu1UsZUCYfj9XPA6AdSMZWDZQobwF7EJ8uNrECaZg1') 414 415 # bip39 seed: slab mixture skin evoke harsh tattoo rare crew sphere extend balcony frost 416 # der: m/49'/0'/0' 417 ks2 = keystore.from_xpub('Ypub6iNDhL4WWq5kFZcdFqHHwX4YTH4rYGp8xbndpRrY7WNZFFRfogSrL7wRTajmVHgR46AT1cqUG1mrcRd7h1WXwBsgX2QvT3zFbBCDiSDLkau') 418 WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks2) 419 self.assertTrue(isinstance(ks2, keystore.BIP32_KeyStore)) 420 421 w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2', config=self.config) 422 self.assertEqual(w.txin_type, 'p2wsh-p2sh') 423 424 self.assertEqual(w.get_receiving_addresses()[0], '35LeC45QgCVeRor1tJD6LiDgPbybBXisns') 425 self.assertEqual(w.get_change_addresses()[0], '39RhtDchc6igmx5tyoimhojFL1ZbQBrXa6') 426 427 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 428 def test_bip32_extended_version_bytes(self, mock_save_db): 429 seed_words = 'crouch dumb relax small truck age shine pink invite spatial object tenant' 430 self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) 431 bip32_seed = keystore.bip39_to_seed(seed_words, '') 432 self.assertEqual('0df68c16e522eea9c1d8e090cfb2139c3b3a2abed78cbcb3e20be2c29185d3b8df4e8ce4e52a1206a688aeb88bfee249585b41a7444673d1f16c0d45755fa8b9', 433 bh2u(bip32_seed)) 434 435 def create_keystore_from_bip32seed(xtype): 436 ks = keystore.BIP32_KeyStore({}) 437 ks.add_xprv_from_seed(bip32_seed, xtype=xtype, derivation='m/') 438 return ks 439 440 ks = create_keystore_from_bip32seed(xtype='standard') 441 self.assertEqual('033a05ec7ae9a9833b0696eb285a762f17379fa208b3dc28df1c501cf84fe415d0', ks.derive_pubkey(0, 0).hex()) 442 self.assertEqual('02bf27f41683d84183e4e930e66d64fc8af5508b4b5bf3c473c505e4dbddaeed80', ks.derive_pubkey(1, 0).hex()) 443 444 ks = create_keystore_from_bip32seed(xtype='standard') # p2pkh 445 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 446 self.assertEqual(ks.xprv, 'xprv9s21ZrQH143K3nyWMZVjzGL4KKAE1zahmhTHuV5pdw4eK3o3igC5QywgQG7UTRe6TGBniPDpPFWzXMeMUFbBj8uYsfXGjyMmF54wdNt8QBm') 447 self.assertEqual(ks.xpub, 'xpub661MyMwAqRbcGH3yTb2kMQGnsLziRTJZ8vNthsVSCGbdBr8CGDWKxnGAFYgyKTzBtwvPPmfVAWJuFmxRXjSbUTg87wDkWQ5GmzpfUcN9t8Z') 448 self.assertEqual(w.get_receiving_addresses()[0], '19fWEVaXqgJFFn7JYNr6ouxyjZy3uK7CdK') 449 self.assertEqual(w.get_change_addresses()[0], '1EEX7da31qndYyeKdbM665w1ze5gbkkAZZ') 450 451 ks = create_keystore_from_bip32seed(xtype='p2wpkh-p2sh') 452 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 453 self.assertEqual(ks.xprv, 'yprvABrGsX5C9janu6AdBvHNCMRZVHJfxcaCgoyWgsyi1wSXN9cGyLMe33bpRU54TLJ1ruJbTrpNqusYQeFvBx1CXNb9k1DhKtBFWo8b1sLbXhN') 454 self.assertEqual(ks.xpub, 'ypub6QqdH2c5z7967aF6HwpNZVNJ3K9AN5J442u7VGPKaGyWEwwRWsftaqvJGkeZKNe7Jb3C9FG3dAfT94ZzFRrcGhMizGvB6Jtm3itJsEFhxMC') 455 self.assertEqual(w.get_receiving_addresses()[0], '34SAT5gGF5UaBhhSZ8qEuuxYvZ2cm7Zi23') 456 self.assertEqual(w.get_change_addresses()[0], '38unULZaetSGSKvDx7Krukh8zm8NQnxGiA') 457 458 ks = create_keystore_from_bip32seed(xtype='p2wpkh') 459 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 460 self.assertEqual(ks.xprv, 'zprvAWgYBBk7JR8GkPMk2H4zQSX4fFT7uEZhbvVjUGsbPwpQRFRWDzXCf7FxSg2eTEwwGYRQDLQwJaE6HvsUueRDKcGkcLv7unzjnXCEQVWhrF9') 461 self.assertEqual(ks.xpub, 'zpub6jftahH18ngZxsSD8JbzmaToDHHcJhHYy9RLGfHCxHMPJ3kemXqTCuaSHxc9KHJ2iE9ztirc5q212MBYy8Gd4w3KrccbgDiFKSwxFpYKEH6') 462 self.assertEqual(w.get_receiving_addresses()[0], 'bc1qtuynwzd0d6wptvyqmc6ehkm70zcamxpshyzu5e') 463 self.assertEqual(w.get_change_addresses()[0], 'bc1qjy5zunxh6hjysele86qqywfa437z4xwmleq8wk') 464 465 ks = create_keystore_from_bip32seed(xtype='standard') # p2sh 466 w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1', config=self.config) 467 self.assertEqual(ks.xprv, 'xprv9s21ZrQH143K3nyWMZVjzGL4KKAE1zahmhTHuV5pdw4eK3o3igC5QywgQG7UTRe6TGBniPDpPFWzXMeMUFbBj8uYsfXGjyMmF54wdNt8QBm') 468 self.assertEqual(ks.xpub, 'xpub661MyMwAqRbcGH3yTb2kMQGnsLziRTJZ8vNthsVSCGbdBr8CGDWKxnGAFYgyKTzBtwvPPmfVAWJuFmxRXjSbUTg87wDkWQ5GmzpfUcN9t8Z') 469 self.assertEqual(w.get_receiving_addresses()[0], '3F4nm8Vunb7mxVvqhUP238PYge2hpU5qYv') 470 self.assertEqual(w.get_change_addresses()[0], '3N8jvKGmxzVHENn6B4zTdZt3N9bmRKjj96') 471 472 ks = create_keystore_from_bip32seed(xtype='p2wsh-p2sh') 473 w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1', config=self.config) 474 self.assertEqual(ks.xprv, 'YprvANkMzkodih9AKfL18akM2RmND5LwAyFo15dBc9FFPiGvzLBBjjjv8ATkEB2Y1mWv6NNaLSpVj8G3XosgVBA9frhpaUL6jHeFQXQTbqVPcv2') 475 self.assertEqual(ks.xpub, 'Ypub6bjiQGLXZ4hTY9QUEcHMPZi6m7BRaRyeNJYnQXerx3ous8WLHH4AfxnE5Tc2sos1Y47B1qGAWP3xGEBkYf1ZRBUPpk2aViMkwTABT6qoiBb') 476 self.assertEqual(w.get_receiving_addresses()[0], '3L1BxLLASGKE3DR1ruraWm3hZshGCKqcJx') 477 self.assertEqual(w.get_change_addresses()[0], '3NDGcbZVXTpaQWRhiuVPpXsNt4g2JiCX4E') 478 479 ks = create_keystore_from_bip32seed(xtype='p2wsh') 480 w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1', config=self.config) 481 self.assertEqual(ks.xprv, 'ZprvAhadJRUYsNgeAxX7xwXyEWrsP3VP7bFHvC9QPY98miep3RzQzPuUkE7tFNz81gAqW1VP5vR4BncbR6VFCsaAU6PRSp2XKCTjgFU6zRpk6Xp') 482 self.assertEqual(ks.xpub, 'Zpub6vZyhw1ShkEwPSbb4y4ybeobw5KsX3y9HR51BvYkL4BnvEKZXwDjJ2SN6fZcsiWvwhDymJriy3QW9WoKGMRaDR9zh5j15dBFDBDpqjK1ekQ') 483 self.assertEqual(w.get_receiving_addresses()[0], 'bc1q84x0yrztvcjg88qef4d6978zccxulcmc9y88xcg4ghjdau999x7q7zv2qe') 484 self.assertEqual(w.get_change_addresses()[0], 'bc1q0fj5mra96hhnum80kllklc52zqn6kppt3hyzr49yhr3ecr42z3tsrkg3gs') 485 486 487 class TestWalletKeystoreAddressIntegrityForTestnet(TestCaseForTestnet): 488 489 def setUp(self): 490 super().setUp() 491 self.config = SimpleConfig({'electrum_path': self.electrum_path}) 492 493 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 494 def test_bip39_multisig_seed_p2sh_segwit_testnet(self, mock_save_db): 495 # bip39 seed: finish seminar arrange erosion sunny coil insane together pretty lunch lunch rose 496 # der: m/49'/1'/0' 497 # NOTE: there is currently no bip43 standard derivation path for p2wsh-p2sh 498 ks1 = keystore.from_xprv('Uprv9BEixD3As2LK5h6G2SNT3cTqbZpsWYPceKTSuVAm1yuSybxSvQz2MV1o8cHTtctQmj4HAenb3eh5YJv4YRZjv35i8fofVnNbs4Dd2B4i5je') 499 self.assertTrue(isinstance(ks1, keystore.BIP32_KeyStore)) 500 self.assertEqual(ks1.xpub, 'Upub5QE5Mia4hPtcJBAj8TuTQkQa9bfMv17U1YP3hsaNaKSRrQHbTxJGuHLGyv3MbKZixuPyjfXGUdbTjE4KwyFcX8YD7PX5ybTDbP11UT8UpZR') 501 502 # bip39 seed: square page wood spy oil story rebel give milk screen slide shuffle 503 # der: m/49'/1'/0' 504 ks2 = keystore.from_xpub('Upub5QRzUGRJuWJe5MxGzwgQAeyJjzcdGTXkkq77w6EfBkCyf5iWppSaZ4caY2MgWcU9LP4a4uE5apUFN4wLoENoe9tpu26mrUxeGsH84dN3JFh') 505 WalletIntegrityHelper.check_xpub_keystore_sanity(self, ks2) 506 self.assertTrue(isinstance(ks2, keystore.BIP32_KeyStore)) 507 508 w = WalletIntegrityHelper.create_multisig_wallet([ks1, ks2], '2of2', config=self.config) 509 self.assertEqual(w.txin_type, 'p2wsh-p2sh') 510 511 self.assertEqual(w.get_receiving_addresses()[0], '2MzsfTfTGomPRne6TkctMmoDj6LwmVkDrMt') 512 self.assertEqual(w.get_change_addresses()[0], '2NFp9w8tbYYP9Ze2xQpeYBJQjx3gbXymHX7') 513 514 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 515 def test_bip32_extended_version_bytes(self, mock_save_db): 516 seed_words = 'crouch dumb relax small truck age shine pink invite spatial object tenant' 517 self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) 518 bip32_seed = keystore.bip39_to_seed(seed_words, '') 519 self.assertEqual('0df68c16e522eea9c1d8e090cfb2139c3b3a2abed78cbcb3e20be2c29185d3b8df4e8ce4e52a1206a688aeb88bfee249585b41a7444673d1f16c0d45755fa8b9', 520 bh2u(bip32_seed)) 521 522 def create_keystore_from_bip32seed(xtype): 523 ks = keystore.BIP32_KeyStore({}) 524 ks.add_xprv_from_seed(bip32_seed, xtype=xtype, derivation='m/') 525 return ks 526 527 ks = create_keystore_from_bip32seed(xtype='standard') 528 self.assertEqual('033a05ec7ae9a9833b0696eb285a762f17379fa208b3dc28df1c501cf84fe415d0', ks.derive_pubkey(0, 0).hex()) 529 self.assertEqual('02bf27f41683d84183e4e930e66d64fc8af5508b4b5bf3c473c505e4dbddaeed80', ks.derive_pubkey(1, 0).hex()) 530 531 ks = create_keystore_from_bip32seed(xtype='standard') # p2pkh 532 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 533 self.assertEqual(ks.xprv, 'tprv8ZgxMBicQKsPecD328MF9ux3dSaSFWci7FNQmuWH7uZ86eY8i3XpvjK8KSH8To2QphiZiUqaYc6nzDC6bTw8YCB9QJjaQL5pAApN4z7vh2B') 534 self.assertEqual(ks.xpub, 'tpubD6NzVbkrYhZ4Y5Epun1qZKcACU6NQqocgYyC4RYaYBMWw8nuLSMR7DvzVamkqxwRgrTJ1MBMhc8wwxT2vbHqMu8RBXy4BvjWMxR5EdZroxE') 535 self.assertEqual(w.get_receiving_addresses()[0], 'mpBTXYfWehjW2tavFwpUdqBJbZZkup13k2') 536 self.assertEqual(w.get_change_addresses()[0], 'mtkUQgf1psDtL67wMAKTv19LrdgPWy6GDQ') 537 538 ks = create_keystore_from_bip32seed(xtype='p2wpkh-p2sh') 539 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 540 self.assertEqual(ks.xprv, 'uprv8tXDerPXZ1QsVuQ9rV8sN13YoQitC8cD2MtdZJQAVuw19kMMxhhPYnyGLeEiThgLELqNTxS91GTLsVofKAM9LRrkGeRzzEuJRtt1Tcostr7') 541 self.assertEqual(ks.xpub, 'upub57Wa4MvRPNyAiPUcxWfsj8zHMSZNbbL4PapEMgon4FTz2YgWWF1e6bHkBvpDKk2Rg2Zy9LsonXFFbv7jNeCZ5kdKWv8UkfcoxpdjJrZuBX6') 542 self.assertEqual(w.get_receiving_addresses()[0], '2MuzNWpcHrXyvPVKzEGT7Xrwp8uEnXXjWnK') 543 self.assertEqual(w.get_change_addresses()[0], '2MzTzY5VcGLwce7YmdEwjXhgQD7LYEKLJTm') 544 545 ks = create_keystore_from_bip32seed(xtype='p2wpkh') 546 w = WalletIntegrityHelper.create_standard_wallet(ks, config=self.config) 547 self.assertEqual(ks.xprv, 'vprv9DMUxX4ShgxMMCbGgqvVa693yNsL8kbhwUQrLhJ3svJtCrAbDMrxArdQMrCJTcLFdyxBDS2hTvotknRE2rmA8fYM8z8Ra9inhcwerEsG6Ev') 548 self.assertEqual(ks.xpub, 'vpub5SLqN2bLY4WeZgfjnsTVwE5nXQhpYDKZJhLT95hfSFqs5eVjkuBCiewtD8moKegM5fgmtpUNFBboVCjJ6LcZszJvPFpuLaSJEYhNhUAnrCS') 549 self.assertEqual(w.get_receiving_addresses()[0], 'tb1qtuynwzd0d6wptvyqmc6ehkm70zcamxpsaze002') 550 self.assertEqual(w.get_change_addresses()[0], 'tb1qjy5zunxh6hjysele86qqywfa437z4xwm4lm549') 551 552 ks = create_keystore_from_bip32seed(xtype='standard') # p2sh 553 w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1', config=self.config) 554 self.assertEqual(ks.xprv, 'tprv8ZgxMBicQKsPecD328MF9ux3dSaSFWci7FNQmuWH7uZ86eY8i3XpvjK8KSH8To2QphiZiUqaYc6nzDC6bTw8YCB9QJjaQL5pAApN4z7vh2B') 555 self.assertEqual(ks.xpub, 'tpubD6NzVbkrYhZ4Y5Epun1qZKcACU6NQqocgYyC4RYaYBMWw8nuLSMR7DvzVamkqxwRgrTJ1MBMhc8wwxT2vbHqMu8RBXy4BvjWMxR5EdZroxE') 556 self.assertEqual(w.get_receiving_addresses()[0], '2N6czpsRwQ3d8AHZPNbztf5NotzEsaZmVQ8') 557 self.assertEqual(w.get_change_addresses()[0], '2NDgwz4CoaSzdSAQdrCcLFWsJaVowCNgiPA') 558 559 ks = create_keystore_from_bip32seed(xtype='p2wsh-p2sh') 560 w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1', config=self.config) 561 self.assertEqual(ks.xprv, 'Uprv95RJn67y7xyEvUZXo9brC5PMXCm9QVHoLdYJUZfhsgmQmvvGj75fduqC9MCC28uETouMLYSFtUqqzfRRcPW6UuyR77YQPeNJKd9t3XutF8b') 562 self.assertEqual(ks.xpub, 'Upub5JQfBberxLXY8xdzuB8rZDL65Ebdox1ehrTuGx5KS2JPejFRGePvBi9fzdmgtBFKuVdx1vsvfjdkj5jVfsMWEEjzMPEtA55orYubtrCZmRr') 563 self.assertEqual(w.get_receiving_addresses()[0], '2NBZQ25GC3ipaF13ZY3UT8i2xnDuS17pJqx') 564 self.assertEqual(w.get_change_addresses()[0], '2NDmUgLVX8vKvcJ4FQ37GSUre6QtBzKkb6k') 565 566 ks = create_keystore_from_bip32seed(xtype='p2wsh') 567 w = WalletIntegrityHelper.create_multisig_wallet([ks], '1of1', config=self.config) 568 self.assertEqual(ks.xprv, 'Vprv16YtLrHXxePM6noKqtFtMtmUgBE9bEpF3fPLmpvuPksssLostujtdHBwqhEeVuzESz22UY8hyPx9ed684SQpCmUKSVhpxPFbvVNY7qnviNR') 569 self.assertEqual(ks.xpub, 'Vpub5dEvVGKn7251zFq7jXvUmJRbFCk5ka19cxz84LyCp2gGhq4eXJZUomop1qjGt5uFK8kkmQUV8PzJcNM4PZmX2URbDiwJjyuJ8GyFHRrEmmG') 570 self.assertEqual(w.get_receiving_addresses()[0], 'tb1q84x0yrztvcjg88qef4d6978zccxulcmc9y88xcg4ghjdau999x7qf2696k') 571 self.assertEqual(w.get_change_addresses()[0], 'tb1q0fj5mra96hhnum80kllklc52zqn6kppt3hyzr49yhr3ecr42z3ts5777jl') 572 573 574 class TestWalletSending(TestCaseForTestnet): 575 576 def setUp(self): 577 super().setUp() 578 self.config = SimpleConfig({'electrum_path': self.electrum_path}) 579 580 def create_standard_wallet_from_seed(self, seed_words, *, config=None, gap_limit=2): 581 if config is None: 582 config = self.config 583 ks = keystore.from_seed(seed_words, '', False) 584 return WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=gap_limit, config=config) 585 586 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 587 def test_sending_between_p2wpkh_and_compressed_p2pkh(self, mock_save_db): 588 wallet1 = self.create_standard_wallet_from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver') 589 wallet2 = self.create_standard_wallet_from_seed('cycle rocket west magnet parrot shuffle foot correct salt library feed song') 590 591 # bootstrap wallet1 592 funding_tx = Transaction('01000000014576dacce264c24d81887642b726f5d64aa7825b21b350c7b75a57f337da6845010000006b483045022100a3f8b6155c71a98ad9986edd6161b20d24fad99b6463c23b463856c0ee54826d02200f606017fd987696ebbe5200daedde922eee264325a184d5bbda965ba5160821012102e5c473c051dae31043c335266d0ef89c1daab2f34d885cc7706b267f3269c609ffffffff0240420f00000000001600148a28bddb7f61864bdcf58b2ad13d5aeb3abc3c42a2ddb90e000000001976a914c384950342cb6f8df55175b48586838b03130fad88ac00000000') 593 funding_txid = funding_tx.txid() 594 funding_output_value = 1000000 595 self.assertEqual('add2535aedcbb5ba79cc2260868bb9e57f328738ca192937f2c92e0e94c19203', funding_txid) 596 wallet1.receive_tx_callback(funding_txid, funding_tx, TX_HEIGHT_UNCONFIRMED) 597 598 # wallet1 -> wallet2 599 outputs = [PartialTxOutput.from_address_and_value(wallet2.get_receiving_address(), 250000)] 600 tx = wallet1.mktx(outputs=outputs, password=None, fee=5000, tx_version=1) 601 602 self.assertTrue(tx.is_complete()) 603 self.assertTrue(tx.is_segwit()) 604 self.assertEqual(1, len(tx.inputs())) 605 self.assertEqual(wallet1.txin_type, tx.inputs()[0].script_type) 606 tx_copy = tx_from_any(tx.serialize()) 607 self.assertTrue(wallet1.is_mine(wallet1.get_txin_address(tx_copy.inputs()[0]))) 608 609 self.assertEqual('010000000001010392c1940e2ec9f2372919ca3887327fe5b98b866022cc79bab5cbed5a53d2ad0000000000feffffff0290d00300000000001976a914ea7804a2c266063572cc009a63dc25dcc0e9d9b588ac285e0b0000000000160014690b59a8140602fb23cc2904ece9cc4daf361052024730440220608a5339ca894592da82119e1e4a1d09335d70a552c683687223b8ed724465e902201b3f0feccf391b1b6257e4b18970ae57d7ca060af2dae519b3690baad2b2a34e0121030faee9b4a25b7db82023ca989192712cdd4cb53d3d9338591c7909e581ae1c0c00000000', 610 str(tx_copy)) 611 self.assertEqual('3c06ae4d9be8226a472b3e7f7c127c7e3016f525d658d26106b80b4c7e3228e2', tx_copy.txid()) 612 self.assertEqual('d8d930ae91dce73118c3fffabbdfcfb87f5d91673fb4c7dfd0fbe7cf03bf426b', tx_copy.wtxid()) 613 self.assertEqual(tx.wtxid(), tx_copy.wtxid()) 614 615 wallet1.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED) # TX_HEIGHT_UNCONF_PARENT but nvm 616 wallet2.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED) 617 618 # wallet2 -> wallet1 619 outputs = [PartialTxOutput.from_address_and_value(wallet1.get_receiving_address(), 100000)] 620 tx = wallet2.mktx(outputs=outputs, password=None, fee=5000, tx_version=1) 621 622 self.assertTrue(tx.is_complete()) 623 self.assertFalse(tx.is_segwit()) 624 self.assertEqual(1, len(tx.inputs())) 625 self.assertEqual(wallet2.txin_type, tx.inputs()[0].script_type) 626 tx_copy = tx_from_any(tx.serialize()) 627 self.assertTrue(wallet2.is_mine(wallet2.get_txin_address(tx_copy.inputs()[0]))) 628 629 self.assertEqual('0100000001e228327e4c0bb80661d258d625f516307e7c127c7f3e2b476a22e89b4dae063c000000006a47304402200c7b06ff882db5ffe9d6e2a3cc2cabf5cd1b4224f1453d1e3dadd13b3d391e2c02201d23fde8482b05837f27d43021d17a1be2ee619dfc889ee80d4c2761e7c7ffb20121030b482838721a38d94847699fed8818b5c5f56500ef72f13489e365b65e5749cffeffffff02a086010000000000160014284520c815980d426264766d8d930013dd20aa6068360200000000001976a914ca4c60999c46c2108326590b125aefd476dcb11888ac00000000', 630 str(tx_copy)) 631 self.assertEqual('4ff22c31dd884dedbb905fae275508d1f7bb4948c1c979d2567132848fdff24a', tx_copy.txid()) 632 self.assertEqual('4ff22c31dd884dedbb905fae275508d1f7bb4948c1c979d2567132848fdff24a', tx_copy.wtxid()) 633 self.assertEqual(tx.wtxid(), tx_copy.wtxid()) 634 635 wallet1.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED) 636 wallet2.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED) 637 638 # wallet level checks 639 self.assertEqual((0, funding_output_value - 250000 - 5000 + 100000, 0), wallet1.get_balance()) 640 self.assertEqual((0, 250000 - 5000 - 100000, 0), wallet2.get_balance()) 641 642 @mock.patch.object(wallet.Abstract_Wallet, 'save_db') 643 def test_sending_between_p2sh_2of3_and_uncompressed_p2pkh(self, mock_save_db): 644 wallet1a = WalletIntegrityHelper.create_multisig_wallet( 645 [ 646 keystore.from_seed('blast uniform dragon fiscal ensure vast young utility dinosaur abandon rookie sure', '', True), 647 keystore.from_xpub('tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'), 648 keystore.from_xpub('tpubD6NzVbkrYhZ4XJzYkhsCbDCcZRmDAKSD7bXi9mdCni7acVt45fxbTVZyU6jRGh29ULKTjoapkfFsSJvQHitcVKbQgzgkkYsAmaovcro7Mhf') 649 ], 650 '2of3', gap_limit=2, 651 config=self.config 652 ) 653 wallet1b = WalletIntegrityHelper.create_multisig_wallet( 654 [ 655 keystore.from_seed('cycle rocket west magnet parrot shuffle foot correct salt library feed song', '', True), 656 keystore.from_xpub('tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'), 657 keystore.from_xpub('tpubD6NzVbkrYhZ4YARFMEZPckrqJkw59GZD1PXtQnw14ukvWDofR7Z1HMeSCxfYEZVvg4VdZ8zGok5VxHwdrLqew5cMdQntWc5mT7mh1CSgrnX') 658 ], 659 '2of3', gap_limit=2, 660 config=self.config 661 ) 662 # ^ third seed: ghost into match ivory badge robot record tackle radar elbow traffic loud 663 wallet2 = self.create_standard_wallet_from_seed('powerful random nobody notice nothing important anyway look away hidden message over') 664 665 # bootstrap wallet1 666 funding_tx = Transaction('010000000001014121f99dc02f0364d2dab3d08905ff4c36fc76c55437fd90b769c35cc18618280100000000fdffffff02d4c22d00000000001600143fd1bc5d32245850c8cb5be5b09c73ccbb9a0f75001bb7000000000017a91480c2353f6a7bc3c71e99e062655b19adb3dd2e4887024830450221008781c78df0c9d4b5ea057333195d5d76bc29494d773f14fa80e27d2f288b2c360220762531614799b6f0fb8d539b18cb5232ab4253dd4385435157b28a44ff63810d0121033de77d21926e09efd04047ae2d39dbd3fb9db446e8b7ed53e0f70f9c9478f735dac11300') 667 funding_txid = funding_tx.txid() 668 funding_output_value = 12000000 669 self.assertEqual('b25cd55687c9e528c2cfd546054f35fb6741f7cf32d600f07dfecdf2e1d42071', funding_txid) 670 wallet1a.receive_tx_callback(funding_txid, funding_tx, TX_HEIGHT_UNCONFIRMED) 671 672 # wallet1 -> wallet2 673 outputs = [PartialTxOutput.from_address_and_value(wallet2.get_receiving_address(), 370000)] 674 tx = wallet1a.mktx(outputs=outputs, password=None, fee=5000, tx_version=1) 675 partial_tx = tx.serialize_as_bytes().hex() parazyd.org:70 /git/electrum/file/electrum/tests/test_wallet_vertical.py.gph:685: line too long