def get_channel_update(self, channel, amount, key=b'a'): self._set_channel_key(channel, key) return self._make_tx( Output.pay_update_claim_pubkey_hash(amount, channel.claim_name, channel.claim_id, channel.claim, b'abc'), Input.spend(channel))
async def test_sign(self): account = self.ledger.account_class.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' )
def get_stream_update(self, tx, amount): claim = Transaction(tx[0].serialize()).outputs[0] return self._make_tx( Output.pay_update_claim_pubkey_hash( amount, claim.claim_name, claim.claim_id, claim.claim, b'abc' ), Input.spend(claim) )
def get_stream_update(self, tx, amount, channel=None): stream = Transaction(tx[0].raw).outputs[0] result = self._make_tx( Output.pay_update_claim_pubkey_hash(amount, stream.claim_name, stream.claim_id, stream.claim, b'abc'), Input.spend(stream)) if channel: result[0].outputs[0].sign(channel) result[0]._reset() return result
async def test_history_edge_cases(self): await self.blockchain.generate(300) await self.assertBalance(self.account, '0.0') address = await self.account.receiving.get_or_create_usable_address() # evil trick: mempool is unsorted on real life, but same order between python instances. reproduce it original_summary = self.conductor.spv_node.server.mempool.transaction_summaries async def random_summary(*args, **kwargs): summary = await original_summary(*args, **kwargs) if summary and len(summary) > 2: ordered = summary.copy() while summary == ordered: random.shuffle(summary) return summary self.conductor.spv_node.server.mempool.transaction_summaries = random_summary # 10 unconfirmed txs, all from blockchain wallet sends = [ self.blockchain.send_to_address(address, 10) for _ in range(10) ] # use batching to reduce issues with send_to_address on cli for batch in range(0, len(sends), 10): txids = await asyncio.gather(*sends[batch:batch + 10]) await asyncio.wait( [self.on_transaction_id(txid) for txid in txids]) remote_status = await self.ledger.network.subscribe_address(address) self.assertTrue(await self.ledger.update_history(address, remote_status)) # 20 unconfirmed txs, 10 from blockchain, 10 from local to local utxos = await self.account.get_utxos() txs = [] for utxo in utxos: tx = await Transaction.create([Input.spend(utxo)], [], [self.account], self.account) await self.broadcast(tx) txs.append(tx) await asyncio.wait( [self.on_transaction_address(tx, address) for tx in txs], timeout=1) remote_status = await self.ledger.network.subscribe_address(address) self.assertTrue(await self.ledger.update_history(address, remote_status)) # server history grows unordered txid = await self.blockchain.send_to_address(address, 1) await self.on_transaction_id(txid) self.assertTrue(await self.ledger.update_history(address, remote_status)) self.assertEqual( 21, len((await self.ledger.get_local_status_and_history(address))[1])) self.assertEqual(0, len(self.ledger._known_addresses_out_of_sync))
async def test_sending_and_receiving(self): account1, account2 = self.account, self.wallet.generate_account(self.ledger) await self.ledger.subscribe_account(account2) await self.assertBalance(account1, '0.0') await self.assertBalance(account2, '0.0') addresses = await account1.receiving.get_addresses() txids = await asyncio.gather(*( self.blockchain.send_to_address(address, 1.1) for address in addresses[:5] )) await asyncio.wait([self.on_transaction_id(txid) for txid in txids]) # mempool await self.blockchain.generate(1) await asyncio.wait([self.on_transaction_id(txid) for txid in txids]) # confirmed await self.assertBalance(account1, '5.5') await self.assertBalance(account2, '0.0') address2 = await account2.receiving.get_or_create_usable_address() tx = await Transaction.create( [], [Output.pay_pubkey_hash( coins_to_satoshis('2.0'), self.ledger.address_to_hash160(address2) )], [account1], account1 ) await self.broadcast(tx) await self.ledger.wait(tx) # mempool await self.blockchain.generate(1) await self.ledger.wait(tx) # confirmed await self.assertBalance(account1, '3.499802') await self.assertBalance(account2, '2.0') utxos = await self.account.get_utxos() tx = await Transaction.create( [Input.spend(utxos[0])], [], [account1], account1 ) await self.broadcast(tx) await self.ledger.wait(tx) # mempool await self.blockchain.generate(1) await self.ledger.wait(tx) # confirmed tx = (await account1.get_transactions(include_is_my_input=True, include_is_my_output=True))[1] self.assertEqual(satoshis_to_coins(tx.inputs[0].amount), '1.1') self.assertEqual(satoshis_to_coins(tx.inputs[1].amount), '1.1') self.assertEqual(satoshis_to_coins(tx.outputs[0].amount), '2.0') self.assertEqual(tx.outputs[0].get_address(self.ledger), address2) self.assertTrue(tx.outputs[0].is_internal_transfer) self.assertTrue(tx.outputs[1].is_internal_transfer)
async def test_get_utxo(self): address = yield self.account.receiving.get_or_create_usable_address() hash160 = self.ledger.address_to_hash160(address) tx = Transaction(is_verified=True)\ .add_outputs([Output.pay_pubkey_hash(100, hash160)]) await self.ledger.db.save_transaction_io('insert', tx, address, hash160, f'{tx.id}:1:') utxos = await self.account.get_utxos() self.assertEqual(len(utxos), 1) tx = Transaction(is_verified=True)\ .add_inputs([Input.spend(utxos[0])]) await self.ledger.db.save_transaction_io('insert', tx, address, hash160, f'{tx.id}:1:') self.assertEqual(await self.account.get_balance(include_claims=True), 0) utxos = await self.account.get_utxos() self.assertEqual(len(utxos), 0)
def get_input(): return Input.spend(get_output())
def get_abandon(self, tx): claim = Transaction(tx[0].raw).outputs[0] return self._make_tx(Output.pay_pubkey_hash(claim.amount, b'abc'), Input.spend(claim))
async def test_creating_updating_and_abandoning_claim_with_channel(self): await self.account.ensure_address_gap() address1, address2 = await self.account.receiving.get_addresses( limit=2, only_usable=True) sendtxid1 = await self.blockchain.send_to_address(address1, 5) sendtxid2 = await self.blockchain.send_to_address(address2, 5) await self.blockchain.generate(1) await asyncio.wait([ self.on_transaction_id(sendtxid1), self.on_transaction_id(sendtxid2) ]) self.assertEqual(d2l(await self.account.get_balance()), '10.0') channel = Claim() channel_txo = Output.pay_claim_name_pubkey_hash( l2d('1.0'), '@bar', channel, self.account.ledger.address_to_hash160(address1)) channel_txo.generate_channel_private_key() channel_txo.script.generate() channel_tx = await Transaction.create([], [channel_txo], [self.account], self.account) stream = Claim() stream.stream.source.media_type = "video/mp4" stream_txo = Output.pay_claim_name_pubkey_hash( l2d('1.0'), 'foo', stream, self.account.ledger.address_to_hash160(address1)) stream_tx = await Transaction.create([], [stream_txo], [self.account], self.account) stream_txo.sign(channel_txo) await stream_tx.sign([self.account]) await self.broadcast(channel_tx) await self.broadcast(stream_tx) await asyncio.wait([ # mempool self.ledger.wait(channel_tx), self.ledger.wait(stream_tx) ]) await self.blockchain.generate(1) await asyncio.wait([ # confirmed self.ledger.wait(channel_tx), self.ledger.wait(stream_tx) ]) self.assertEqual(d2l(await self.account.get_balance()), '7.985786') self.assertEqual( d2l(await self.account.get_balance(include_claims=True)), '9.985786') response = await self.ledger.resolve([], ['lbry://@bar/foo']) self.assertEqual(response['lbry://@bar/foo'].claim.claim_type, 'stream') abandon_tx = await Transaction.create( [Input.spend(stream_tx.outputs[0])], [], [self.account], self.account) await self.broadcast(abandon_tx) await self.ledger.wait(abandon_tx) await self.blockchain.generate(1) await self.ledger.wait(abandon_tx) response = await self.ledger.resolve([], ['lbry://@bar/foo']) self.assertIn('error', response['lbry://@bar/foo']) # checks for expected format in inexistent URIs response = await self.ledger.resolve([], ['lbry://404', 'lbry://@404']) self.assertEqual('lbry://404 did not resolve to a claim', response['lbry://404']['error']) self.assertEqual('lbry://@404 did not resolve to a claim', response['lbry://@404']['error'])
async def test_creating_updating_and_abandoning_claim_with_channel(self): await self.account.ensure_address_gap() address1, address2 = await self.account.receiving.get_addresses(limit=2, only_usable=True) notifications = asyncio.create_task(asyncio.wait( [asyncio.ensure_future(self.on_address_update(address1)), asyncio.ensure_future(self.on_address_update(address2))] )) await self.send_to_address_and_wait(address1, 5) await self.send_to_address_and_wait(address2, 5, 1) await notifications self.assertEqual(d2l(await self.account.get_balance()), '10.0') channel = Claim() channel_txo = Output.pay_claim_name_pubkey_hash( l2d('1.0'), '@bar', channel, self.account.ledger.address_to_hash160(address1) ) channel_txo.set_channel_private_key( await self.account.generate_channel_private_key() ) channel_txo.script.generate() channel_tx = await Transaction.create([], [channel_txo], [self.account], self.account) stream = Claim() stream.stream.source.media_type = "video/mp4" stream_txo = Output.pay_claim_name_pubkey_hash( l2d('1.0'), 'foo', stream, self.account.ledger.address_to_hash160(address1) ) stream_tx = await Transaction.create([], [stream_txo], [self.account], self.account) stream_txo.sign(channel_txo) await stream_tx.sign([self.account]) notifications = asyncio.create_task(asyncio.wait( [asyncio.ensure_future(self.ledger.wait(channel_tx)), asyncio.ensure_future(self.ledger.wait(stream_tx))] )) await self.broadcast(channel_tx) await self.broadcast(stream_tx) await notifications notifications = asyncio.create_task(asyncio.wait( [asyncio.ensure_future(self.ledger.wait(channel_tx)), asyncio.ensure_future(self.ledger.wait(stream_tx))] )) await self.generate(1) await notifications self.assertEqual(d2l(await self.account.get_balance()), '7.985786') self.assertEqual(d2l(await self.account.get_balance(include_claims=True)), '9.985786') response = await self.ledger.resolve([], ['lbry://@bar/foo']) self.assertEqual(response['lbry://@bar/foo'].claim.claim_type, 'stream') abandon_tx = await Transaction.create([Input.spend(stream_tx.outputs[0])], [], [self.account], self.account) notify = asyncio.create_task(self.ledger.wait(abandon_tx)) await self.broadcast(abandon_tx) await notify notify = asyncio.create_task(self.ledger.wait(abandon_tx)) await self.generate(1) await notify response = await self.ledger.resolve([], ['lbry://@bar/foo']) self.assertIn('error', response['lbry://@bar/foo']) # checks for expected format in inexistent URIs response = await self.ledger.resolve([], ['lbry://404', 'lbry://@404', 'lbry://@404/404']) self.assertEqual('Could not find claim at "lbry://404".', response['lbry://404']['error']['text']) self.assertEqual('Could not find channel in "lbry://@404".', response['lbry://@404']['error']['text']) self.assertEqual('Could not find channel in "lbry://@404/404".', response['lbry://@404/404']['error']['text'])