async def start(self, spv_node: 'SPVNode', seed=None, connect=True): self.data_path = tempfile.mkdtemp() wallets_dir = os.path.join(self.data_path, 'wallets') os.mkdir(wallets_dir) wallet_file_name = os.path.join(wallets_dir, 'my_wallet.json') with open(wallet_file_name, 'w') as wallet_file: wallet_file.write('{"version": 1, "accounts": []}\n') self.manager = self.manager_class.from_config({ 'ledgers': { self.ledger_class.get_id(): { 'api_port': self.port, 'default_servers': [(spv_node.hostname, spv_node.port)], 'data_path': self.data_path } }, 'wallets': [wallet_file_name] }) self.ledger = self.manager.ledgers[self.ledger_class] self.wallet = self.manager.default_wallet if not self.wallet: raise ValueError('Wallet is required.') if seed or self.default_seed: Account.from_dict( self.ledger, self.wallet, {'seed': seed or self.default_seed} ) else: self.wallet.generate_account(self.ledger) self.account = self.wallet.default_account if connect: await self.manager.start()
async def start(self, spv_node: 'SPVNode', seed=None, connect=True, config=None): wallets_dir = os.path.join(self.data_path, 'wallets') wallet_file_name = os.path.join(wallets_dir, 'my_wallet.json') if not os.path.isdir(wallets_dir): os.mkdir(wallets_dir) with open(wallet_file_name, 'w') as wallet_file: wallet_file.write('{"version": 1, "accounts": []}\n') self.manager = self.manager_class.from_config({ 'ledgers': { self.ledger_class.get_id(): { 'use_go_hub': not strtobool( os.environ.get('ENABLE_LEGACY_SEARCH') or 'yes'), 'api_port': self.port, 'explicit_servers': [(spv_node.hostname, spv_node.port)], 'default_servers': Config.lbryum_servers.default, 'data_path': self.data_path, 'known_hubs': config.known_hubs if config else KnownHubsList(), 'hub_timeout': 30, 'concurrent_hub_requests': 32, 'fee_per_name_char': 200000 } }, 'wallets': [wallet_file_name] }) self.manager.config = config self.ledger = self.manager.ledgers[self.ledger_class] self.wallet = self.manager.default_wallet if not self.wallet: raise ValueError('Wallet is required.') if seed or self.default_seed: Account.from_dict(self.ledger, self.wallet, {'seed': seed or self.default_seed}) else: self.wallet.generate_account(self.ledger) self.account = self.wallet.default_account if connect: await self.manager.start()
def test_decrypt_wallet(self): account = Account.from_dict(self.ledger, Wallet(), self.encrypted_account) self.assertTrue(account.encrypted) account.decrypt(self.password) self.assertEqual(account.init_vectors['private_key'], self.init_vector) self.assertEqual(account.init_vectors['seed'], self.init_vector) self.assertFalse(account.encrypted) self.assertEqual(account.seed, self.unencrypted_account['seed']) self.assertEqual(account.private_key.extended_key_string(), self.unencrypted_account['private_key']) self.assertEqual( account.to_dict(encrypt_password=self.password)['seed'], self.encrypted_account['seed']) self.assertEqual( account.to_dict(encrypt_password=self.password)['private_key'], self.encrypted_account['private_key']) self.assertEqual(account.to_dict()['seed'], self.unencrypted_account['seed']) self.assertEqual(account.to_dict()['private_key'], self.unencrypted_account['private_key'])
async def test_load_and_save_account(self): account_data = { 'name': 'My Account', 'modified_on': 123, 'seed': "carbon smart garage balance margin twelve chest sword toast envelope bottom stomac" "h absent", 'encrypted': False, 'private_key': 'xprv9s21ZrQH143K42ovpZygnjfHdAqSd9jo7zceDfPRogM7bkkoNVv7' 'DRNLEoB8HoirMgH969NrgL8jNzLEegqFzPRWM37GXd4uE8uuRkx4LAe', 'public_key': 'xpub661MyMwAqRbcGWtPvbWh9sc2BCfw2cTeVDYF23o3N1t6UZ5wv3EM' 'mDgp66FxHuDtWdft3B5eL5xQtyzAtkdmhhC95gjRjLzSTdkho95asu9', 'address_generator': { 'name': 'single-address' }, 'certificates': {} } account = Account.from_dict(self.ledger, Wallet(), account_data) await account.ensure_address_gap() addresses = await account.receiving.get_addresses() self.assertEqual(len(addresses), 1) addresses = await account.change.get_addresses() self.assertEqual(len(addresses), 1) self.maxDiff = None account_data['ledger'] = 'lbc_mainnet' self.assertDictEqual(account_data, account.to_dict())
async def test_generate_account_from_seed(self): account = Account.from_dict( self.ledger, Wallet(), { "seed": "carbon smart garage balance margin twelve chest sword toas" "t envelope bottom stomach absent" }) self.assertEqual( account.private_key.extended_key_string(), 'xprv9s21ZrQH143K42ovpZygnjfHdAqSd9jo7zceDfPRogM7bkkoNVv7DRNLEoB8' 'HoirMgH969NrgL8jNzLEegqFzPRWM37GXd4uE8uuRkx4LAe') self.assertEqual( account.public_key.extended_key_string(), 'xpub661MyMwAqRbcGWtPvbWh9sc2BCfw2cTeVDYF23o3N1t6UZ5wv3EMmDgp66FxH' 'uDtWdft3B5eL5xQtyzAtkdmhhC95gjRjLzSTdkho95asu9') address = await account.receiving.ensure_address_gap() self.assertEqual(address[0], 'bCqJrLHdoiRqEZ1whFZ3WHNb33bP34SuGx') private_key = await self.ledger.get_private_key_for_address( account.wallet, 'bCqJrLHdoiRqEZ1whFZ3WHNb33bP34SuGx') self.assertEqual( private_key.extended_key_string(), 'xprv9vwXVierUTT4hmoe3dtTeBfbNv1ph2mm8RWXARU6HsZjBaAoFaS2FRQu4fptR' 'AyJWhJW42dmsEaC1nKnVKKTMhq3TVEHsNj1ca3ciZMKktT') private_key = await self.ledger.get_private_key_for_address( account.wallet, 'BcQjRlhDOIrQez1WHfz3whnB33Bp34sUgX') self.assertIsNone(private_key)
def test_merge_diff(self): account_data = { 'name': 'My Account', 'modified_on': 123, 'seed': "carbon smart garage balance margin twelve chest sword toast envelope bottom stomac" "h absent", 'encrypted': False, 'private_key': 'xprv9s21ZrQH143K3TsAz5efNV8K93g3Ms3FXcjaWB9fVUsMwAoE3ZT4vYymkp' '5BxKKfnpz8J6sHDFriX1SnpvjNkzcks8XBnxjGLS83BTyfpna', 'public_key': 'xpub661MyMwAqRbcFwwe67Bfjd53h5WXmKm6tqfBJZZH3pQLoy8Nb6mKUMJFc7' 'UbpVNzmwFPN2evn3YHnig1pkKVYcvCV8owTd2yAcEkJfCX53g', 'address_generator': { 'name': 'deterministic-chain', 'receiving': { 'gap': 5, 'maximum_uses_per_address': 2 }, 'change': { 'gap': 5, 'maximum_uses_per_address': 2 } } } account = Account.from_dict(self.ledger, Wallet(), account_data) self.assertEqual(account.name, 'My Account') self.assertEqual(account.modified_on, 123) self.assertEqual(account.change.gap, 5) self.assertEqual(account.change.maximum_uses_per_address, 2) self.assertEqual(account.receiving.gap, 5) self.assertEqual(account.receiving.maximum_uses_per_address, 2) account_data['name'] = 'Changed Name' account_data['address_generator']['change']['gap'] = 6 account_data['address_generator']['change'][ 'maximum_uses_per_address'] = 7 account_data['address_generator']['receiving']['gap'] = 8 account_data['address_generator']['receiving'][ 'maximum_uses_per_address'] = 9 account.merge(account_data) # no change because modified_on is not newer self.assertEqual(account.name, 'My Account') account_data['modified_on'] = 200.00 account.merge(account_data) self.assertEqual(account.name, 'Changed Name') self.assertEqual(account.change.gap, 6) self.assertEqual(account.change.maximum_uses_per_address, 7) self.assertEqual(account.receiving.gap, 8) self.assertEqual(account.receiving.maximum_uses_per_address, 9)
def test_encrypt_decrypt_read_only_account(self): account_data = self.unencrypted_account.copy() del account_data['seed'] del account_data['private_key'] account = Account.from_dict(self.ledger, Wallet(), account_data) encrypted = account.to_dict('password') self.assertFalse(encrypted['seed']) self.assertFalse(encrypted['private_key']) account.encrypt('password') account.decrypt('password')
async def asyncSetUp(self): self.ledger = Ledger({ 'db': Database(':memory:'), 'headers': Headers(':memory:') }) await self.ledger.db.open() self.account = Account.from_dict( self.ledger, Wallet(), { "seed": "carbon smart garage balance margin twelve chest sword " "toast envelope bottom stomach absent" }) addresses = await self.account.ensure_address_gap() self.pubkey_hash = [ self.ledger.address_to_hash160(a) for a in addresses ] self.hash_cycler = cycle(self.pubkey_hash)
async def test_generate_account_from_seed(self): account = Account.from_dict( self.ledger, Wallet(), { "seed": "carbon smart garage balance margin twelve chest sword toas" "t envelope bottom stomach absent", 'address_generator': {'name': 'single-address'} } ) self.assertEqual( account.private_key.extended_key_string(), 'xprv9s21ZrQH143K42ovpZygnjfHdAqSd9jo7zceDfPRogM7bkkoNVv7' 'DRNLEoB8HoirMgH969NrgL8jNzLEegqFzPRWM37GXd4uE8uuRkx4LAe', ) self.assertEqual( account.public_key.extended_key_string(), 'xpub661MyMwAqRbcGWtPvbWh9sc2BCfw2cTeVDYF23o3N1t6UZ5wv3EM' 'mDgp66FxHuDtWdft3B5eL5xQtyzAtkdmhhC95gjRjLzSTdkho95asu9', ) address = await account.receiving.ensure_address_gap() self.assertEqual(address[0], account.public_key.address) private_key = await self.ledger.get_private_key_for_address( account.wallet, address[0] ) self.assertEqual( private_key.extended_key_string(), 'xprv9s21ZrQH143K42ovpZygnjfHdAqSd9jo7zceDfPRogM7bkkoNVv7' 'DRNLEoB8HoirMgH969NrgL8jNzLEegqFzPRWM37GXd4uE8uuRkx4LAe', ) invalid_key = await self.ledger.get_private_key_for_address( account.wallet, 'BcQjRlhDOIrQez1WHfz3whnB33Bp34sUgX' ) self.assertIsNone(invalid_key) self.assertEqual( hexlify(private_key.wif()), b'1cef6c80310b1bcbcfa3176ea809ac840f48cda634c475d402e6bd68d5bb3827d601' )
async def asyncSetUp(self): wallet_dir = tempfile.mkdtemp() self.addCleanup(shutil.rmtree, wallet_dir) self.ledger = Ledger({ 'db': Database(os.path.join(wallet_dir, 'blockchain.db')), 'headers': Headers(':memory:'), }) await self.ledger.db.open() self.account = Account.from_dict( self.ledger, Wallet(), { "seed": "carbon smart garage balance margin twelve chest sword " "toast envelope bottom stomach absent" }) addresses = await self.account.ensure_address_gap() self.pubkey_hash = [ self.ledger.address_to_hash160(a) for a in addresses ] self.hash_cycler = cycle(self.pubkey_hash)
async def test_sign(self): account = Account.from_dict( self.ledger, Wallet(), { "seed": "carbon smart garage balance margin twelve chest sword toas" "t envelope bottom stomach absent" }) await account.ensure_address_gap() address1, address2 = await account.receiving.get_addresses(limit=2) pubkey_hash1 = self.ledger.address_to_hash160(address1) pubkey_hash2 = self.ledger.address_to_hash160(address2) tx = Transaction() \ .add_inputs([Input.spend(get_output(int(2*COIN), pubkey_hash1))]) \ .add_outputs([Output.pay_pubkey_hash(int(1.9*COIN), pubkey_hash2)]) await tx.sign([account]) self.assertEqual( hexlify(tx.inputs[0].script.values['signature']), b'304402200dafa26ad7cf38c5a971c8a25ce7d85a076235f146126762296b1223c42ae21e022020ef9eeb8' b'398327891008c5c0be4357683f12cb22346691ff23914f457bf679601')