async def get_mock_wallet(sd_hash, storage, balance=10.0, fee=None):
    claim = Claim()
    if fee:
        if fee['currency'] == 'LBC':
            claim.stream.fee.lbc = Decimal(fee['amount'])
        elif fee['currency'] == 'USD':
            claim.stream.fee.usd = Decimal(fee['amount'])
    claim.stream.title = "33rpm"
    claim.stream.languages.append("en")
    claim.stream.source.sd_hash = sd_hash
    claim.stream.source.media_type = "image/png"

    tx = get_claim_transaction("33rpm", claim.to_bytes())
    tx.height = 514081
    txo = tx.outputs[0]
    txo.meta.update({
        "permanent_url": "33rpm#c49566d631226492317d06ad7fdbe1ed32925124",

    })

    class FakeHeaders:
        def estimated_timestamp(self, height):
            return 1984

        def __init__(self, height):
            self.height = height

        def __getitem__(self, item):
            return {'timestamp': 1984}

    wallet = Wallet()
    ledger = Ledger({
        'db': Database(':memory:'),
        'headers': FakeHeaders(514082)
    })
    await ledger.db.open()
    wallet.generate_account(ledger)
    manager = WalletManager()
    manager.config = Config()
    manager.wallets.append(wallet)
    manager.ledgers[Ledger] = ledger
    manager.ledger.network.client = ClientSession(
        network=manager.ledger.network, server=('fakespv.lbry.com', 50001)
    )

    async def mock_resolve(*args, **kwargs):
        result = {txo.meta['permanent_url']: txo}
        claims = [
            StreamManager._convert_to_old_resolve_output(manager, result)[txo.meta['permanent_url']]
        ]
        await storage.save_claims(claims)
        return result
    manager.ledger.resolve = mock_resolve

    async def get_balance(*_):
        return balance
    manager.get_balance = get_balance

    return manager, txo.meta['permanent_url']
示例#2
0
    def test_load_and_save_wallet(self):
        wallet_dict = {
            'version':
            1,
            'name':
            'Main Wallet',
            'preferences': {},
            'accounts': [{
                'certificates': {},
                'name':
                'An Account',
                'ledger':
                'lbc_mainnet',
                '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':
                'xpub661MyMwAqRbcGWtPvbWh9sc2BCfw2cTeVDYF23o3N1t6UZ5wv3EMm'
                'Dgp66FxHuDtWdft3B5eL5xQtyzAtkdmhhC95gjRjLzSTdkho95asu9',
                'address_generator': {
                    'name': 'deterministic-chain',
                    'receiving': {
                        'gap': 17,
                        'maximum_uses_per_address': 3
                    },
                    'change': {
                        'gap': 10,
                        'maximum_uses_per_address': 3
                    }
                }
            }]
        }

        storage = WalletStorage(default=wallet_dict)
        wallet = Wallet.from_storage(storage, self.manager)
        self.assertEqual(wallet.name, 'Main Wallet')
        self.assertEqual(
            hexlify(wallet.hash),
            b'869acc4660dde0f13784ed743796adf89562cdf79fdfc9e5c6dbea98d62ccf90'
        )
        self.assertEqual(len(wallet.accounts), 1)
        account = wallet.default_account
        self.assertIsInstance(account, Account)
        self.maxDiff = None
        self.assertDictEqual(wallet_dict, wallet.to_dict())

        encrypted = wallet.pack('password')
        decrypted = Wallet.unpack('password', encrypted)
        self.assertEqual(decrypted['accounts'][0]['name'], 'An Account')
示例#3
0
    def test_create_wallet_and_accounts(self):
        wallet = Wallet()
        self.assertEqual(wallet.name, 'Wallet')
        self.assertListEqual(wallet.accounts, [])

        account1 = wallet.generate_account(self.main_ledger)
        wallet.generate_account(self.main_ledger)
        wallet.generate_account(self.test_ledger)
        self.assertEqual(wallet.default_account, account1)
        self.assertEqual(len(wallet.accounts), 3)
示例#4
0
 async def asyncSetUp(self):
     self.ledger = Ledger({
         'db': Database(':memory:'),
         'headers': Headers(':memory:')
     })
     await self.ledger.db.open()
     self.account = Account.generate(self.ledger, Wallet(), "torba", {'name': 'single-address'})
示例#5
0
    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'])
示例#6
0
    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)
示例#7
0
 async def asyncSetUp(self):
     self.ledger = Ledger({
         'db': Database(':memory:'),
         'headers': Headers(':memory:')
     })
     self.account = Account.generate(self.ledger, Wallet(), "lbryum")
     await self.ledger.db.open()
示例#8
0
 async def asyncSetUp(self):
     self.ledger = Ledger({
         'db': Database(':memory:'),
         'headers': Headers(':memory:')
     })
     self.wallet = Wallet()
     await self.ledger.db.open()
示例#9
0
    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())
示例#10
0
 async def test_save_max_gap(self):
     account = Account.generate(
         self.ledger, Wallet(), 'lbryum', {
                 'name': 'deterministic-chain',
                 'receiving': {'gap': 3, 'maximum_uses_per_address': 2},
                 'change': {'gap': 4, 'maximum_uses_per_address': 2}
             }
     )
     self.assertEqual(account.receiving.gap, 3)
     self.assertEqual(account.change.gap, 4)
     await account.save_max_gap()
     self.assertEqual(account.receiving.gap, 20)
     self.assertEqual(account.change.gap, 6)
     # doesn't fail for single-address account
     account2 = Account.generate(self.ledger, Wallet(), 'lbryum', {'name': 'single-address'})
     await account2.save_max_gap()
示例#11
0
    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)
示例#12
0
 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')
示例#13
0
    async def test_get_or_create_usable_address(self):
        account = Account.generate(self.ledger, Wallet(), 'lbryum')

        keys = await account.receiving.get_addresses()
        self.assertEqual(len(keys), 0)

        address = await account.receiving.get_or_create_usable_address()
        self.assertIsNotNone(address)

        keys = await account.receiving.get_addresses()
        self.assertEqual(len(keys), 20)
示例#14
0
    def test_no_password_but_encryption_preferred(self):
        wallet_dict = {
            'version':
            1,
            'name':
            'Main Wallet',
            'preferences': {
                "encrypt-on-disk": {
                    "ts": 1571762543.351794,
                    "value": True
                },
            },
            'accounts': [{
                'certificates': {},
                'name':
                'An Account',
                'ledger':
                'lbc_mainnet',
                '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':
                'xpub661MyMwAqRbcGWtPvbWh9sc2BCfw2cTeVDYF23o3N1t6UZ5wv3EMm'
                'Dgp66FxHuDtWdft3B5eL5xQtyzAtkdmhhC95gjRjLzSTdkho95asu9',
                'address_generator': {
                    'name': 'deterministic-chain',
                    'receiving': {
                        'gap': 17,
                        'maximum_uses_per_address': 3
                    },
                    'change': {
                        'gap': 10,
                        'maximum_uses_per_address': 3
                    }
                }
            }]
        }

        storage = WalletStorage(default=wallet_dict)
        wallet = Wallet.from_storage(storage, self.manager)
        self.assertEqual(
            hexlify(wallet.hash),
            b'8cc6341885e6ad46f72a17364c65f8441f09e79996c55202196b399c75f8d751'
        )
        self.assertFalse(wallet.is_encrypted)
示例#15
0
    async def test_update_history(self):
        account = Account.generate(self.ledger, Wallet(), "torba")
        address = await account.receiving.get_or_create_usable_address()
        address_details = await self.ledger.db.get_address(address=address)
        self.assertIsNone(address_details['history'])

        self.add_header(block_height=0, merkle_root=b'abcd04')
        self.add_header(block_height=1, merkle_root=b'abcd04')
        self.add_header(block_height=2, merkle_root=b'abcd04')
        self.add_header(block_height=3, merkle_root=b'abcd04')
        self.ledger.network = MockNetwork([
            {'tx_hash': 'abcd01', 'height': 0},
            {'tx_hash': 'abcd02', 'height': 1},
            {'tx_hash': 'abcd03', 'height': 2},
        ], {
            'abcd01': hexlify(get_transaction(get_output(1)).raw),
            'abcd02': hexlify(get_transaction(get_output(2)).raw),
            'abcd03': hexlify(get_transaction(get_output(3)).raw),
        })
        await self.ledger.update_history(address, '')
        self.assertListEqual(self.ledger.network.get_history_called, [address])
        self.assertListEqual(self.ledger.network.get_transaction_called, ['abcd01', 'abcd02', 'abcd03'])

        address_details = await self.ledger.db.get_address(address=address)
        self.assertEqual(
            address_details['history'],
            '252bda9b22cc902ca2aa2de3548ee8baf06b8501ff7bfb3b0b7d980dbd1bf792:0:'
            'ab9c0654dd484ac20437030f2034e25dcb29fc507e84b91138f80adc3af738f9:1:'
            'a2ae3d1db3c727e7d696122cab39ee20a7f81856dab7019056dd539f38c548a0:2:'
        )

        self.ledger.network.get_history_called = []
        self.ledger.network.get_transaction_called = []
        await self.ledger.update_history(address, '')
        self.assertListEqual(self.ledger.network.get_history_called, [address])
        self.assertListEqual(self.ledger.network.get_transaction_called, [])

        self.ledger.network.history.append({'tx_hash': 'abcd04', 'height': 3})
        self.ledger.network.transaction['abcd04'] = hexlify(get_transaction(get_output(4)).raw)
        self.ledger.network.get_history_called = []
        self.ledger.network.get_transaction_called = []
        await self.ledger.update_history(address, '')
        self.assertListEqual(self.ledger.network.get_history_called, [address])
        self.assertListEqual(self.ledger.network.get_transaction_called, ['abcd04'])
        address_details = await self.ledger.db.get_address(address=address)
        self.assertEqual(
            address_details['history'],
            '252bda9b22cc902ca2aa2de3548ee8baf06b8501ff7bfb3b0b7d980dbd1bf792:0:'
            'ab9c0654dd484ac20437030f2034e25dcb29fc507e84b91138f80adc3af738f9:1:'
            'a2ae3d1db3c727e7d696122cab39ee20a7f81856dab7019056dd539f38c548a0:2:'
            '047cf1d53ef68f0fd586d46f90c09ff8e57a4180f67e7f4b8dd0135c3741e828:3:'
        )
示例#16
0
 async def test_unused_address_on_account_creation_does_not_cause_a_race(
         self):
     account = Account.generate(self.ledger, Wallet(), 'lbryum')
     await account.ledger.db.db.executescript(
         "update pubkey_address set used_times=10")
     await account.receiving.address_generator_lock.acquire()
     delayed1 = asyncio.ensure_future(
         account.receiving.ensure_address_gap())
     delayed = asyncio.ensure_future(
         account.receiving.get_or_create_usable_address())
     await asyncio.sleep(0)
     # wallet being created and queried at the same time
     account.receiving.address_generator_lock.release()
     await delayed1
     await delayed
示例#17
0
    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)
示例#18
0
    def test_read_write(self):
        manager = WalletManager()
        config = {'data_path': '/tmp/wallet'}
        ledger = manager.get_or_create_ledger(Ledger.get_id(), config)

        with tempfile.NamedTemporaryFile(suffix='.json') as wallet_file:
            wallet_file.write(b'{"version": 1}')
            wallet_file.seek(0)

            # create and write wallet to a file
            wallet = manager.import_wallet(wallet_file.name)
            account = wallet.generate_account(ledger)
            wallet.save()

            # read wallet from file
            wallet_storage = WalletStorage(wallet_file.name)
            wallet = Wallet.from_storage(wallet_storage, manager)

            self.assertEqual(account.public_key.address,
                             wallet.default_account.public_key.address)
示例#19
0
    async def test_generate_account(self):
        account = Account.generate(self.ledger, Wallet(), 'lbryum')
        self.assertEqual(account.ledger, self.ledger)
        self.assertIsNotNone(account.seed)
        self.assertEqual(account.public_key.ledger, self.ledger)
        self.assertEqual(account.private_key.public_key, account.public_key)

        self.assertEqual(account.public_key.ledger, self.ledger)
        self.assertEqual(account.private_key.public_key, account.public_key)

        addresses = await account.receiving.get_addresses()
        self.assertEqual(len(addresses), 0)
        addresses = await account.change.get_addresses()
        self.assertEqual(len(addresses), 0)

        await account.ensure_address_gap()

        addresses = await account.receiving.get_addresses()
        self.assertEqual(len(addresses), 20)
        addresses = await account.change.get_addresses()
        self.assertEqual(len(addresses), 6)
示例#20
0
    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'
        )
示例#21
0
    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)
示例#22
0
    async def test_ensure_address_gap(self):
        account = Account.generate(self.ledger, Wallet(), 'lbryum')

        self.assertIsInstance(account.receiving, HierarchicalDeterministic)

        async with account.receiving.address_generator_lock:
            await account.receiving._generate_keys(4, 7)
            await account.receiving._generate_keys(0, 3)
            await account.receiving._generate_keys(8, 11)
        records = await account.receiving.get_address_records()
        self.assertListEqual(
            [r['pubkey'].n for r in records],
            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
        )

        # we have 12, but default gap is 20
        new_keys = await account.receiving.ensure_address_gap()
        self.assertEqual(len(new_keys), 8)
        records = await account.receiving.get_address_records()
        self.assertListEqual(
            [r['pubkey'].n for r in records],
            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
        )

        # case #1: no new addresses needed
        empty = await account.receiving.ensure_address_gap()
        self.assertEqual(len(empty), 0)

        # case #2: only one new addressed needed
        records = await account.receiving.get_address_records()
        await self.ledger.db.set_address_history(records[0]['address'], 'a:1:')
        new_keys = await account.receiving.ensure_address_gap()
        self.assertEqual(len(new_keys), 1)

        # case #3: 20 addresses needed
        await self.ledger.db.set_address_history(new_keys[0], 'a:1:')
        new_keys = await account.receiving.ensure_address_gap()
        self.assertEqual(len(new_keys), 20)
示例#23
0
    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')
示例#24
0
    def test_merge(self):
        wallet1 = Wallet()
        wallet1.preferences['one'] = 1
        wallet1.preferences['conflict'] = 1
        wallet1.generate_account(self.main_ledger)
        wallet2 = Wallet()
        wallet2.preferences['two'] = 2
        wallet2.preferences['conflict'] = 2  # will be more recent
        wallet2.generate_account(self.main_ledger)

        self.assertEqual(len(wallet1.accounts), 1)
        self.assertEqual(wallet1.preferences, {'one': 1, 'conflict': 1})

        added = wallet1.merge(self.manager, 'password',
                              wallet2.pack('password'))
        self.assertEqual(added[0].id, wallet2.default_account.id)
        self.assertEqual(len(wallet1.accounts), 2)
        self.assertEqual(wallet1.accounts[1].id, wallet2.default_account.id)
        self.assertEqual(wallet1.preferences, {
            'one': 1,
            'two': 2,
            'conflict': 2
        })
示例#25
0
    async def test_queries(self):
        wallet1 = Wallet()
        account1 = await self.create_account(wallet1)
        self.assertEqual(
            26, await self.ledger.db.get_address_count(accounts=[account1]))
        wallet2 = Wallet()
        account2 = await self.create_account(wallet2)
        account3 = await self.create_account(wallet2)
        self.assertEqual(
            26, await self.ledger.db.get_address_count(accounts=[account2]))

        self.assertEqual(
            0, await self.ledger.db.get_transaction_count(
                accounts=[account1, account2, account3]))
        self.assertEqual(0, await self.ledger.db.get_utxo_count())
        self.assertListEqual([], await self.ledger.db.get_utxos())
        self.assertEqual(0, await self.ledger.db.get_txo_count())
        self.assertEqual(0, await self.ledger.db.get_balance(wallet=wallet1))
        self.assertEqual(0, await self.ledger.db.get_balance(wallet=wallet2))
        self.assertEqual(0, await
                         self.ledger.db.get_balance(accounts=[account1]))
        self.assertEqual(0, await
                         self.ledger.db.get_balance(accounts=[account2]))
        self.assertEqual(0, await
                         self.ledger.db.get_balance(accounts=[account3]))

        tx1 = await self.create_tx_from_nothing(account1, 1)
        self.assertEqual(
            1, await self.ledger.db.get_transaction_count(accounts=[account1]))
        self.assertEqual(
            0, await self.ledger.db.get_transaction_count(accounts=[account2]))
        self.assertEqual(
            1, await self.ledger.db.get_utxo_count(accounts=[account1]))
        self.assertEqual(
            1, await self.ledger.db.get_txo_count(accounts=[account1]))
        self.assertEqual(
            0, await self.ledger.db.get_txo_count(accounts=[account2]))
        self.assertEqual(10**8, await
                         self.ledger.db.get_balance(wallet=wallet1))
        self.assertEqual(0, await self.ledger.db.get_balance(wallet=wallet2))
        self.assertEqual(10**8, await
                         self.ledger.db.get_balance(accounts=[account1]))
        self.assertEqual(0, await
                         self.ledger.db.get_balance(accounts=[account2]))
        self.assertEqual(0, await
                         self.ledger.db.get_balance(accounts=[account3]))

        tx2 = await self.create_tx_from_txo(tx1.outputs[0], account2, 2)
        tx2b = await self.create_tx_from_nothing(account3, 2)
        self.assertEqual(
            2, await self.ledger.db.get_transaction_count(accounts=[account1]))
        self.assertEqual(
            1, await self.ledger.db.get_transaction_count(accounts=[account2]))
        self.assertEqual(
            1, await self.ledger.db.get_transaction_count(accounts=[account3]))
        self.assertEqual(
            0, await self.ledger.db.get_utxo_count(accounts=[account1]))
        self.assertEqual(
            1, await self.ledger.db.get_txo_count(accounts=[account1]))
        self.assertEqual(
            1, await self.ledger.db.get_utxo_count(accounts=[account2]))
        self.assertEqual(
            1, await self.ledger.db.get_txo_count(accounts=[account2]))
        self.assertEqual(
            1, await self.ledger.db.get_utxo_count(accounts=[account3]))
        self.assertEqual(
            1, await self.ledger.db.get_txo_count(accounts=[account3]))
        self.assertEqual(0, await self.ledger.db.get_balance(wallet=wallet1))
        self.assertEqual(10**8 + 10**8, await
                         self.ledger.db.get_balance(wallet=wallet2))
        self.assertEqual(0, await
                         self.ledger.db.get_balance(accounts=[account1]))
        self.assertEqual(10**8, await
                         self.ledger.db.get_balance(accounts=[account2]))
        self.assertEqual(10**8, await
                         self.ledger.db.get_balance(accounts=[account3]))

        tx3 = await self.create_tx_to_nowhere(tx2.outputs[0], 3)
        self.assertEqual(
            2, await self.ledger.db.get_transaction_count(accounts=[account1]))
        self.assertEqual(
            2, await self.ledger.db.get_transaction_count(accounts=[account2]))
        self.assertEqual(
            0, await self.ledger.db.get_utxo_count(accounts=[account1]))
        self.assertEqual(
            1, await self.ledger.db.get_txo_count(accounts=[account1]))
        self.assertEqual(
            0, await self.ledger.db.get_utxo_count(accounts=[account2]))
        self.assertEqual(
            1, await self.ledger.db.get_txo_count(accounts=[account2]))
        self.assertEqual(0, await self.ledger.db.get_balance(wallet=wallet1))
        self.assertEqual(10**8, await
                         self.ledger.db.get_balance(wallet=wallet2))
        self.assertEqual(0, await
                         self.ledger.db.get_balance(accounts=[account1]))
        self.assertEqual(0, await
                         self.ledger.db.get_balance(accounts=[account2]))
        self.assertEqual(10**8, await
                         self.ledger.db.get_balance(accounts=[account3]))

        txs = await self.ledger.db.get_transactions(
            accounts=[account1, account2])
        self.assertListEqual([tx3.id, tx2.id, tx1.id], [tx.id for tx in txs])
        self.assertListEqual([3, 2, 1], [tx.height for tx in txs])

        txs = await self.ledger.db.get_transactions(wallet=wallet1,
                                                    accounts=wallet1.accounts)
        self.assertListEqual([tx2.id, tx1.id], [tx.id for tx in txs])
        self.assertEqual(txs[0].inputs[0].is_my_account, True)
        self.assertEqual(txs[0].outputs[0].is_my_account, False)
        self.assertEqual(txs[1].inputs[0].is_my_account, False)
        self.assertEqual(txs[1].outputs[0].is_my_account, True)

        txs = await self.ledger.db.get_transactions(wallet=wallet2,
                                                    accounts=[account2])
        self.assertListEqual([tx3.id, tx2.id], [tx.id for tx in txs])
        self.assertEqual(txs[0].inputs[0].is_my_account, True)
        self.assertEqual(txs[0].outputs[0].is_my_account, False)
        self.assertEqual(txs[1].inputs[0].is_my_account, False)
        self.assertEqual(txs[1].outputs[0].is_my_account, True)
        self.assertEqual(
            2, await self.ledger.db.get_transaction_count(accounts=[account2]))

        tx = await self.ledger.db.get_transaction(txid=tx2.id)
        self.assertEqual(tx.id, tx2.id)
        self.assertFalse(tx.inputs[0].is_my_account)
        self.assertFalse(tx.outputs[0].is_my_account)
        tx = await self.ledger.db.get_transaction(wallet=wallet1, txid=tx2.id)
        self.assertTrue(tx.inputs[0].is_my_account)
        self.assertFalse(tx.outputs[0].is_my_account)
        tx = await self.ledger.db.get_transaction(wallet=wallet2, txid=tx2.id)
        self.assertFalse(tx.inputs[0].is_my_account)
        self.assertTrue(tx.outputs[0].is_my_account)

        # height 0 sorted to the top with the rest in descending order
        tx4 = await self.create_tx_from_nothing(account1, 0)
        txos = await self.ledger.db.get_txos()
        self.assertListEqual([0, 2, 2, 1], [txo.tx_ref.height for txo in txos])
        self.assertListEqual([tx4.id, tx2.id, tx2b.id, tx1.id],
                             [txo.tx_ref.id for txo in txos])
        txs = await self.ledger.db.get_transactions(
            accounts=[account1, account2])
        self.assertListEqual([0, 3, 2, 1], [tx.height for tx in txs])
        self.assertListEqual([tx4.id, tx3.id, tx2.id, tx1.id],
                             [tx.id for tx in txs])
示例#26
0
    def test_wallet_file_schema(self):
        wallet_dict = {
            'version':
            1,
            'name':
            'Main Wallet',
            'preferences': {},
            'accounts': [
                {
                    'certificates': {
                        'x': 'y'
                    },
                    'name':
                    'Account 1',
                    'ledger':
                    'lbc_mainnet',
                    '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':
                    'xpub661MyMwAqRbcGWtPvbWh9sc2BCfw2cTeVDYF23o3N1t6UZ5wv3EMm'
                    'Dgp66FxHuDtWdft3B5eL5xQtyzAtkdmhhC95gjRjLzSTdkho95asu9',
                    'address_generator': {
                        'name': 'deterministic-chain',
                        'receiving': {
                            'gap': 17,
                            'maximum_uses_per_address': 3
                        },
                        'change': {
                            'gap': 10,
                            'maximum_uses_per_address': 3
                        }
                    }
                },
                {
                    'certificates': {
                        'a': 'b'
                    },
                    'name':
                    'Account 2',
                    'ledger':
                    'lbc_mainnet',
                    'modified_on':
                    123,
                    'seed':
                    "carbon smart garage balance margin twelve chest sword toast envelope bottom stomac"
                    "h absent",
                    'encrypted':
                    True,
                    'private_key':
                    'xprv9s21ZrQH143K42ovpZygnjfHdAqSd9jo7zceDfPRogM7bkkoNVv7'
                    'DRNLEoB8HoirMgH969NrgL8jNzLEegqFzPRWM37GXd4uE8uuRkx4LAe',
                    'public_key':
                    'xpub661MyMwAqRbcGWtPvbWh9sc2BCfw2cTeVDYF23o3N1t6UZ5wv3EMm'
                    'Dgp66FxHuDtWdft3B5eL5xQtyzAtkdmhhC95gjRjLzSTdkho95asu9',
                    'address_generator': {
                        'name': 'single-address',
                    }
                },
            ]
        }

        storage = WalletStorage(default=wallet_dict)
        wallet = Wallet.from_storage(storage, self.manager)
        self.assertDictEqual(wallet_dict, wallet.to_dict())
        with open(os.path.join(*schema_v2.__path__, 'wallet.json')) as f:
            wallet_schema = json.load(f)
        jsonschema.validate(schema=wallet_schema, instance=wallet.to_dict())
示例#27
0
 async def test_generate_keys_over_batch_threshold_saves_it_properly(self):
     account = Account.generate(self.ledger, Wallet(), 'lbryum')
     async with account.receiving.address_generator_lock:
         await account.receiving._generate_keys(0, 200)
     records = await account.receiving.get_address_records()
     self.assertEqual(len(records), 201)
示例#28
0
    async def test_update_history(self):
        txid1 = '252bda9b22cc902ca2aa2de3548ee8baf06b8501ff7bfb3b0b7d980dbd1bf792'
        txid2 = 'ab9c0654dd484ac20437030f2034e25dcb29fc507e84b91138f80adc3af738f9'
        txid3 = 'a2ae3d1db3c727e7d696122cab39ee20a7f81856dab7019056dd539f38c548a0'
        txid4 = '047cf1d53ef68f0fd586d46f90c09ff8e57a4180f67e7f4b8dd0135c3741e828'

        account = Account.generate(self.ledger, Wallet(), "torba")
        address = await account.receiving.get_or_create_usable_address()
        address_details = await self.ledger.db.get_address(address=address)
        self.assertIsNone(address_details['history'])

        self.add_header(block_height=0, merkle_root=b'abcd04')
        self.add_header(block_height=1, merkle_root=b'abcd04')
        self.add_header(block_height=2, merkle_root=b'abcd04')
        self.add_header(block_height=3, merkle_root=b'abcd04')
        self.ledger.network = MockNetwork(
            [
                {
                    'tx_hash': txid1,
                    'height': 0
                },
                {
                    'tx_hash': txid2,
                    'height': 1
                },
                {
                    'tx_hash': txid3,
                    'height': 2
                },
            ], {
                txid1: hexlify(get_transaction(get_output(1)).raw),
                txid2: hexlify(get_transaction(get_output(2)).raw),
                txid3: hexlify(get_transaction(get_output(3)).raw),
            })
        await self.ledger.update_history(address, '')
        self.assertListEqual(self.ledger.network.get_history_called, [address])
        self.assertListEqual(self.ledger.network.get_transaction_called,
                             [txid1, txid2, txid3])

        address_details = await self.ledger.db.get_address(address=address)

        self.assertEqual(address_details['history'], f'{txid1}:0:'
                         f'{txid2}:1:'
                         f'{txid3}:2:')

        self.ledger.network.get_history_called = []
        self.ledger.network.get_transaction_called = []
        for cache_item in self.ledger._tx_cache.values():
            cache_item.tx.is_verified = True
        await self.ledger.update_history(address, '')
        self.assertListEqual(self.ledger.network.get_history_called, [address])
        self.assertListEqual(self.ledger.network.get_transaction_called, [])

        self.ledger.network.history.append({'tx_hash': txid4, 'height': 3})
        self.ledger.network.transaction[txid4] = hexlify(
            get_transaction(get_output(4)).raw)
        self.ledger.network.get_history_called = []
        self.ledger.network.get_transaction_called = []
        await self.ledger.update_history(address, '')
        self.assertListEqual(self.ledger.network.get_history_called, [address])
        self.assertListEqual(self.ledger.network.get_transaction_called,
                             [txid4])
        address_details = await self.ledger.db.get_address(address=address)
        self.assertEqual(
            address_details['history'], f'{txid1}:0:'
            f'{txid2}:1:'
            f'{txid3}:2:'
            f'{txid4}:3:')