def create_wallet(self): """ Create wallet by creating seed, storing it and setting up API access """ if self.created: return fail(RuntimeError(f'Iota wallet with name {self.wallet_name} already exists.')) self._logger.info(f'Creating Iota wallet with name {self.wallet_name}') # generate random seed and store it in the database as a String instead of TryteString self.seed = Seed.random() self.database.add(DatabaseSeed(name=self.wallet_name, seed=self.seed.__str__())) self.database.commit() # initialize connection with API through the provider and get an active non-spent address self.provider = PyOTAIotaProvider(testnet=self.testnet, seed=self.seed) self.created = True return succeed([])
async def test_task_select_tracker(torrent_checker): with db_session: tracker = torrent_checker.mds.TrackerState( url="http://localhost/tracker") torrent_checker.mds.TorrentState(infohash=b'a' * 20, seeders=5, leechers=10, trackers={tracker}) controlled_session = HttpTrackerSession("127.0.0.1", ("localhost", 8475), "/announce", 5, None) controlled_session.connect_to_tracker = lambda: succeed(None) torrent_checker._create_session_for_request = lambda *args, **kwargs: controlled_session result = await torrent_checker.check_random_tracker() assert not result assert len(controlled_session.infohash_list) == 1
async def test_start_download_from_file(test_download, mock_dlmgr, rest_api): """ Testing whether we can start a download from a file """ mock_dlmgr.start_download_from_uri = lambda *_, **__: succeed(test_download ) post_data = {'uri': f"file:{TESTS_DATA_DIR / 'video.avi.torrent'}"} expected_json = { 'started': True, 'infohash': 'c9a19e7fe5d9a6c106d6ea3c01746ac88ca3c7a5' } await do_request(rest_api, 'downloads', expected_code=200, request_type='PUT', post_data=post_data, expected_json=expected_json)
async def test_connect_to_tracker_bep33(bep33_session, mock_dlmgr): """ Test the metainfo lookup of the BEP33 DHT session """ dht_health_dict = { "infohash": hexlify(b'a' * 20), "seeders": 1, "leechers": 2 } mock_dlmgr.dht_health_manager = Mock() mock_dlmgr.dht_health_manager.get_health = lambda *_, **__: succeed( {"DHT": [dht_health_dict]}) metainfo = await bep33_session.connect_to_tracker() assert 'DHT' in metainfo assert metainfo['DHT'][0]['leechers'] == 2 assert metainfo['DHT'][0]['seeders'] == 1
async def test_get_pending_multiple(self): """ Tests the pending balance with no transactions """ self.wallet.create_wallet() # Inject the valued transaction self.tx1.is_confirmed = False self.tx2.is_confirmed = False self.tx2.value = 1 self.wallet.provider.get_seed_transactions = lambda: succeed( [self.tx1, self.tx2]) await self.wallet.update_transactions_database() result = await self.wallet.get_pending() # Since the transaction is confirmed, no value should be added self.assertEqual(self.tx2.value + self.tx1.value, result) self.wallet.cancel_all_pending_tasks()
def crawl_chain(self, peer, latest_block_num=0): """ Crawl the whole chain of a specific peer. :param latest_block_num: The latest block number of the peer in question, if available. """ if self.request_cache.has("chaincrawl", ChainCrawlCache.get_number_for(peer)): self.logger.debug( "Skipping crawl of peer %s, another crawl is pending", peer ) return succeed(None) crawl_future = Future() cache = ChainCrawlCache( self, peer, crawl_future, known_chain_length=latest_block_num ) self.request_cache.add(cache) ensure_future(self.send_next_partial_chain_crawl_request(cache)) return crawl_future
def create_wallet(self): """ If no account exists yet, create a new one. """ if self.account: return fail( RuntimeError( f'Ethereum wallet with name {self.wallet_name} already exists' )) self._logger.info('Creating Ethereum wallet with name %s', self.wallet_name) if not self.account: self.account = Web3().eth.account.create() self.created = True self.database.add_key(self.wallet_name, self.account.key, self.account.address) return succeed(None)
async def test_wallet_creation(self): """ Test the creating, opening, transactions and balance query of a wallet """ await self.wallet.create_wallet() self.assertIsNotNone(self.wallet.wallet) self.assertTrue(self.wallet.get_address().result()) self.wallet.wallet.utxos_update = lambda **_: None # We don't want to do an actual HTTP request here self.wallet.wallet.balance = lambda **_: 3 balance = await self.wallet.get_balance() self.assertDictEqual(balance, {'available': 3, 'pending': 0, 'currency': self.network_currency, 'precision': self.precision}) self.wallet.wallet.transactions_update = lambda **_: None # We don't want to do an actual HTTP request here transactions = await self.wallet.get_transactions() self.assertFalse(transactions) self.wallet.get_transactions = lambda: succeed([{"id": "abc"}]) await self.wallet.monitor_transaction("abc")
async def transfer_multiple(self, transfers: list, **kwargs) -> list: """ Submit multiple transfers simultaneously to the Monero blockchain. May reduce fee. :param transfers: list of tuples of format (address, Decimal(amount)) :param kwargs: payment_id, priority, unlock_time (see `transfer` method above) :return: list of resulting hashes or return InsufficientFundsException """ balance = await self.get_balance() total_amount = float(sum([transfer[1] for transfer in transfers])) if balance['available'] < total_amount: return fail(InsufficientFunds('Insufficient funds found in Monero wallet for all transfers')) if self._wallet_connection_alive(): results = await self.wallet.transfer_multiple(transfers, **kwargs) hashes = [result[0].hash for result in results] return succeed(hashes) return fail(WalletConnectionError('No connection to wallet for making transfers'))
async def test_get_metainfo_duplicate_request(fake_dlmgr): """ Test whether the same request is returned when invoking get_metainfo twice with the same infohash """ infohash = b"a" * 20 metainfo = {'pieces': ['a']} download_impl = Mock() download_impl.tdef.get_metainfo = lambda: None download_impl.future_metainfo = Future() get_event_loop().call_later(0.1, download_impl.future_metainfo.set_result, metainfo) fake_dlmgr.initialize() fake_dlmgr.start_download = Mock(return_value=download_impl) fake_dlmgr.tribler_session.config.get_default_number_hops = lambda: 1 fake_dlmgr.remove_download = Mock(return_value=succeed(None)) results = await gather(fake_dlmgr.get_metainfo(infohash), fake_dlmgr.get_metainfo(infohash)) assert results == [metainfo, metainfo] fake_dlmgr.start_download.assert_called_once() fake_dlmgr.remove_download.assert_called_once()
async def test_transfer_multiple_wallet(self): """ Make multiple transfers at once, enough balance. """ w = self.new_wallet() transfers = [ (TEST_ADDRESS, Decimal('20.2')), (TEST_ADDRESS, Decimal('7.8')) ] mock_wallet = MockObject() mock_wallet.refresh = lambda: None mock_wallet.balance = lambda **_: 57.3 mock_wallet.transfer_multiple = \ lambda *_, **__: succeed([(Transaction(hash=TEST_HASH), Decimal('20.2')), (Transaction(hash=TEST_HASH), Decimal('7.8'))]) w.wallet = mock_wallet hashes = await w.transfer_multiple(transfers, priority=3) self.assertEqual(2, len(hashes.result())) w.cancel_all_pending_tasks()
def create_wallet(self): """ Create a new bitcoin wallet. """ from bitcoinlib.wallets import wallet_exists, HDWallet, WalletError if wallet_exists(self.wallet_name, databasefile=self.db_path): return fail( RuntimeError( f"Bitcoin wallet with name {self.wallet_name} already exists." )) self._logger.info("Creating wallet in %s", self.wallet_dir) try: self.wallet = HDWallet.create(self.wallet_name, network=self.network, databasefile=self.db_path) self.wallet.new_key('tribler_payments') self.wallet.new_key('tribler_change', change=1) self.created = True except WalletError as exc: self._logger.error("Cannot create BTC wallet!") return fail(exc) return succeed(None)
async def test_start_download_while_getting_metainfo(fake_dlmgr): """ Testing adding a torrent while a metainfo request is running. """ infohash = b"a" * 20 metainfo_session = Mock() metainfo_session.get_torrents = lambda: [] metainfo_dl = Mock() metainfo_dl.get_def = lambda: Mock(get_infohash=lambda: infohash) fake_dlmgr.initialize() fake_dlmgr.get_session = lambda *_: metainfo_session fake_dlmgr.downloads[infohash] = metainfo_dl fake_dlmgr.metainfo_requests[infohash] = [metainfo_dl, 1] fake_dlmgr.remove_download = Mock(return_value=succeed(None)) tdef = TorrentDefNoMetainfo(infohash, 'name', f'magnet:?xt=urn:btih:{hexlify(infohash)}&') download = fake_dlmgr.start_download(tdef=tdef, checkpoint_disabled=True) assert metainfo_dl != download await sleep(.1) assert fake_dlmgr.downloads[infohash] == download fake_dlmgr.remove_download.assert_called_once_with(metainfo_dl, remove_content=True, remove_checkpoint=False)
async def test_btc_wallet(wallet, tmpdir): """ Test the creating, opening, transactions and balance query of a Bitcoin (testnet) wallet """ await wallet.create_wallet() assert wallet.wallet assert wallet.get_address() wallet.wallet.utxos_update = lambda **_: None # We don't want to do an actual HTTP request here wallet.wallet.balance = lambda **_: 3 balance = await wallet.get_balance() assert balance == { 'available': 3, 'pending': 0, 'currency': 'BTC', 'precision': 8 } wallet.wallet.transactions_update = lambda **_: None # We don't want to do an actual HTTP request here transactions = await wallet.get_transactions() assert not transactions wallet.get_transactions = lambda: succeed([{"id": "abc"}]) await wallet.monitor_transaction("abc")
def mock_get_metainfo_bad(*args, **kwargs): return succeed({b'info': {b'name': b'bla'}})
def connect_peer(_): return succeed([b"abc"])
def mock_dlmgr(session, mocker, tmpdir): mocker.patch.object(session, 'dlmgr') session.dlmgr.shutdown = lambda: succeed(None) session.dlmgr.get_checkpoint_dir = lambda: tmpdir
def mocked_do_payout(*_, **__): return succeed(None)
def connect_peer(_): return succeed([])
def mocked_pause_checkpoint(): mocked_pause_checkpoint.called = True return succeed(None)
def fake_get_metainfo(*args, **kwargs): return succeed(channel_tdef.get_metainfo())
def create_wallet(self, *args, **kwargs): return succeed(None)
def sign_block(self, peer, public_key=EMPTY_PK, block_type=b'unknown', transaction=None, linked=None, additional_info=None): """ Create, sign, persist and send a block signed message :param peer: The peer with whom you have interacted, as a IPv8 peer :param public_key: The public key of the other party you transact with :param block_type: The type of the block to be constructed, as a string :param transaction: A string describing the interaction in this block :param linked: The block that the requester is asking us to sign :param additional_info: Stores additional information, on the transaction """ # NOTE to the future: This method reads from the database, increments and then writes back. If in some future # this method is allowed to execute in parallel, be sure to lock from before .create up to after .add_block # In this particular case there must be an implicit transaction due to the following assert assert peer is not None or peer is None and linked is None and public_key == ANY_COUNTERPARTY_PK, \ "Peer, linked block should not be provided when creating a no counterparty source block. Public key " \ "should be that reserved for any counterpary." assert transaction is None and linked is not None or transaction is not None and linked is None, \ "Either provide a linked block or a transaction, not both %s, %s" % (peer, self.my_peer) assert (additional_info is None or additional_info is not None and linked is not None and transaction is None), \ "Either no additional info is provided or one provides it for a linked block" assert (linked is None or linked.link_public_key == self.my_peer.public_key.key_to_bin() or linked.link_public_key == ANY_COUNTERPARTY_PK ), "Cannot counter sign block not addressed to self" assert linked is None or linked.link_sequence_number == UNKNOWN_SEQ, \ "Cannot counter sign block that is not a request" assert transaction is None or isinstance( transaction, dict), "Transaction should be a dictionary" assert additional_info is None or isinstance( additional_info, dict), "Additional info should be a dictionary" self.persistence_integrity_check() if linked and linked.link_public_key != ANY_COUNTERPARTY_PK: block_type = linked.type block = self.get_block_class(block_type).create( block_type, transaction, self.persistence, self.my_peer.public_key.key_to_bin(), link=linked, additional_info=additional_info, link_pk=public_key) block.sign(self.my_peer.key) validation = block.validate(self.persistence) self.logger.info("Signed block to %s (%s) validation result %s", hexlify(block.link_public_key)[-8:], block, validation) if validation[0] != ValidationResult.partial_next and validation[ 0] != ValidationResult.valid: self.logger.error("Signed block did not validate?! Result %s", repr(validation)) return fail(RuntimeError("Signed block did not validate.")) if not self.persistence.contains(block): self.persistence.add_block(block) self.notify_listeners(block) # This is a source block with no counterparty if not peer and public_key == ANY_COUNTERPARTY_PK: if block.type not in self.settings.block_types_bc_disabled: self.send_block(block) return succeed((block, None)) # If there is a counterparty to sign, we send it self.send_block(block, address=peer.address) # We broadcast the block in the network if we initiated a transaction if block.type not in self.settings.block_types_bc_disabled and not linked: self.send_block(block) if peer == self.my_peer: # We created a self-signed block if block.type not in self.settings.block_types_bc_disabled: self.send_block(block) return succeed( (block, None)) if public_key == ANY_COUNTERPARTY_PK else succeed( (block, linked)) elif not linked: # We keep track of this outstanding sign request. sign_future = Future() self.request_cache.add( HalfBlockSignCache(self, block, sign_future, peer.address)) return sign_future else: # We return a future that fires immediately with both half blocks. if block.type not in self.settings.block_types_bc_disabled: self.send_block_pair(linked, block) return succeed((linked, block))
def get_transactions(self): return succeed(self.transaction_history)
def fake_get_metainfo(_, **__): meta_info = TorrentDef.load(TORRENT_UBUNTU_FILE).get_metainfo() return succeed(meta_info)
def send_request(self, *args): return succeed(self.response)
def fake_get_metainfo(*_, **__): return succeed(None)
def mock_get_metainfo_good(*args, **kwargs): return succeed({b'info': {b'name': channel.dirname.encode('utf-8')}})
def mock_download_from_tdef(*_, **__): global initiated_download initiated_download = True mock_dl = MockObject() mock_dl.future_finished = succeed(None) return mock_dl
def get_address(self): return succeed( b64encode(self.trustchain.my_peer.public_key.key_to_bin()).decode( 'utf-8'))