def test_query_on_introduction(self): """ Test querying a peer that was just introduced to us. """ send_ok = [] def mock_send(_): send_ok.append(1) self.nodes[1].overlay.send_remote_select_subscribed_channels = mock_send peer = self.nodes[0].my_peer self.nodes[1].overlay.introduction_response_callback(peer, None, None) self.assertIn(peer.mid, self.nodes[1].overlay.queried_subscribed_channels_peers) self.assertTrue(send_ok) # Make sure the same peer will not be queried twice in case the walker returns to it self.nodes[1].overlay.introduction_response_callback(peer, None, None) self.assertEqual(len(send_ok), 1) # Test clearing queried peers set when it outgrows its capacity self.nodes[1].overlay.queried_peers_limit = 2 self.nodes[1].overlay.introduction_response_callback(Peer(default_eccrypto.generate_key("low")), None, None) self.assertEqual(len(self.nodes[1].overlay.queried_subscribed_channels_peers), 2) self.nodes[1].overlay.introduction_response_callback(Peer(default_eccrypto.generate_key("low")), None, None) self.assertEqual(len(self.nodes[1].overlay.queried_subscribed_channels_peers), 1)
def __init__(self, configuration, endpoint_override=None, enable_statistics=False, extra_communities=None): if endpoint_override: self.endpoint = endpoint_override else: self.endpoint = UDPEndpoint(port=configuration['port'], ip=configuration['address']) self.endpoint.open() if enable_statistics: self.endpoint = StatisticsEndpoint(self, self.endpoint) self.network = Network() # Load/generate keys self.keys = {} for key_block in configuration['keys']: if key_block['file'] and isfile(key_block['file']): with open(key_block['file'], 'r') as f: content = f.read() try: # IPv8 Standardized bin format self.keys[key_block['alias']] = Peer(default_eccrypto.key_from_private_bin(content)) except ValueError: try: # Try old Tribler M2Crypto PEM format content = b64decode(content[31:-30].replace('\n', '')) peer = Peer(M2CryptoSK(keystring=content)) peer.mid # This will error out if the keystring is not M2Crypto self.keys[key_block['alias']] = peer except: # Try old LibNacl format content = "LibNaCLSK:" + content self.keys[key_block['alias']] = Peer(default_eccrypto.key_from_private_bin(content)) else: self.keys[key_block['alias']] = Peer(default_eccrypto.generate_key(key_block['generation'])) if key_block['file']: with open(key_block['file'], 'w') as f: f.write(self.keys[key_block['alias']].key.key_to_bin()) # Setup logging logging.basicConfig(**configuration['logger']) self.overlay_lock = RLock() self.strategies = [] self.overlays = [] for overlay in configuration['overlays']: overlay_class = _COMMUNITIES.get(overlay['class'], (extra_communities or {}).get(overlay['class'])) my_peer = self.keys[overlay['key']] overlay_instance = overlay_class(my_peer, self.endpoint, self.network, **overlay['initialize']) self.overlays.append(overlay_instance) for walker in overlay['walkers']: strategy_class = _WALKERS.get(walker['strategy'], overlay_instance.get_available_strategies().get(walker['strategy'])) args = walker['init'] target_peers = walker['peers'] self.strategies.append((strategy_class(overlay_instance, **args), target_peers)) for config in overlay['on_start']: reactor.callWhenRunning(getattr(overlay_instance, config[0]), *config[1:]) self.state_machine_lc = LoopingCall(self.on_tick) self.state_machine_lc.start(configuration['walker_interval'], False)
def setup_test(window=1, packet_size=1000, packets=10000): """ Create two nodes who will be sending packets to each other. :param window: the window size for packets (1 is synchronous) :param packet_size: the size of each packet :param packets: the number of packets to send in the experiment :return: the deferred that fires once the experiment is complete """ configuration = get_default_configuration() configuration['overlays'] = [] configuration['keys'] = [] master_peer = Peer(ECCrypto().generate_key(u"low")) peer_ipv8 = IPv8(configuration) peer_ipv8.keys = {'my_peer': Peer(ECCrypto().generate_key(u"low"))} peer_ipv8.overlays = [ LoadOverlay(master_peer, peer_ipv8.keys['my_peer'], peer_ipv8.endpoint, peer_ipv8.network, window, packet_size, packets) ] counterparty_ipv8 = IPv8(configuration) counterparty_ipv8.keys = {'my_peer': Peer(ECCrypto().generate_key(u"low"))} counterparty_ipv8.overlays = [ LoadOverlay(master_peer, counterparty_ipv8.keys['my_peer'], counterparty_ipv8.endpoint, counterparty_ipv8.network, 0, packet_size, packets) ] peer_ipv8.overlays[0].send(counterparty_ipv8.endpoint.get_address()) return DeferredList( [peer_ipv8.overlays[0].done, counterparty_ipv8.overlays[0].done])
def test_query_on_introduction(self): """ Test querying a peer that was just introduced to us. """ send_ok = [] def mock_send(_): send_ok.append(1) self.nodes[1].overlay.send_remote_select_subscribed_channels = mock_send peer = self.nodes[0].my_peer payload = Mock() self.nodes[1].overlay.introduction_response_callback(peer, None, payload) self.assertIn(peer.mid, self.nodes[1].overlay.queried_peers) self.assertTrue(send_ok) # Make sure the same peer will not be queried twice in case the walker returns to it self.nodes[1].overlay.introduction_response_callback(peer, None, payload) self.assertEqual(len(send_ok), 1) # Test clearing queried peers set when it outgrows its capacity self.nodes[1].overlay.settings.queried_peers_limit = 2 self.nodes[1].overlay.introduction_response_callback(Peer(default_eccrypto.generate_key("low")), None, payload) self.assertEqual(len(self.nodes[1].overlay.queried_peers), 2) self.nodes[1].overlay.introduction_response_callback(Peer(default_eccrypto.generate_key("low")), None, payload) # The set has been cleared, so the number of queried peers must be dropped back to 1 self.assertEqual(len(self.nodes[1].overlay.queried_peers), 1) # Ensure that we're not going to query ourselves self.nodes[1].overlay.introduction_response_callback(self.nodes[1].overlay.my_peer, None, payload) self.assertEqual(len(send_ok), 3)
def received_transaction(self, source_address: Address, data: bytes) -> None: """ Callback when we receive a transaction from another peer. :param source_address: The network address of the peer that has sent us the transaction. :param data: The serialized, raw data in the packet. """ payload = self._ez_unpack_noauth(BandwidthTransactionPayload, data, global_time=False) tx = BandwidthTransactionData.from_payload(payload) if not tx.is_valid(): self.logger.info("Transaction %s not valid, ignoring it", tx) return if payload.public_key_a == self.my_pk or payload.public_key_b == self.my_pk: # This transaction involves this peer. latest_tx = self.database.get_latest_transaction(tx.public_key_a, tx.public_key_b) if payload.public_key_b == self.my_peer.public_key.key_to_bin(): from_peer = Peer(payload.public_key_a, source_address) if latest_tx: # Check if the amount in the received transaction is higher than the amount of the latest one # in the database. if payload.amount > latest_tx.amount: # Sign it, store it, and send it back tx.sign(self.my_peer.key, as_a=False) self.database.BandwidthTransaction.insert(tx) self.send_transaction(tx, from_peer.address, payload.request_id) else: self.logger.info("Received older bandwidth transaction - sending back the latest one") self.send_transaction(latest_tx, from_peer.address, payload.request_id) else: # This transaction is the first one with party A. Sign it, store it, and send it back. tx.sign(self.my_peer.key, as_a=False) self.database.BandwidthTransaction.insert(tx) from_peer = Peer(payload.public_key_a, source_address) self.send_transaction(tx, from_peer.address, payload.request_id) elif payload.public_key_a == self.my_peer.public_key.key_to_bin(): # It seems that we initiated this transaction. Check if we are waiting for it. cache = self.request_cache.get("bandwidth-tx-sign", payload.request_id) if not cache: self.logger.info("Received bandwidth transaction %s without associated cache entry, ignoring it", tx) return if not latest_tx or (latest_tx and latest_tx.amount >= tx.amount): self.database.BandwidthTransaction.insert(tx) cache.future.set_result(tx) else: # This transaction involves two unknown peers. We can add it to our database. self.database.BandwidthTransaction.insert(tx)
async def test_send_random_multiple_torrents(self): """ Test whether sending a single channel with a multiple torrents to another peer works correctly """ with db_session: channel = self.nodes[0].overlay.metadata_store.ChannelMetadata.create_channel("test", "bla") for _ in range(10): self.add_random_torrent(self.nodes[0].overlay.metadata_store.TorrentMetadata, channel=channel) channel.commit_channel_torrent() await self.nodes[0].overlay.prepare_gossip_blob_cache() self.nodes[0].overlay.send_random_to(Peer(self.nodes[1].my_peer.public_key, self.nodes[1].endpoint.wan_address)) await self.deliver_messages(timeout=0.5) with db_session: channel = self.nodes[1].overlay.metadata_store.ChannelMetadata.get() torrents1 = self.nodes[1].overlay.metadata_store.TorrentMetadata.select()[:] self.assertLess(channel.contents_len, 10) self.assertLess(0, channel.contents_len) # We must delete the old and create all-new torrent entries for the next test. # Otherwise, it becomes non-deterministic. with db_session: channel = self.nodes[0].overlay.metadata_store.ChannelMetadata.get() self.nodes[0].overlay.metadata_store.TorrentMetadata.select( lambda g: g.metadata_type == REGULAR_TORRENT ).delete() self.nodes[1].overlay.metadata_store.TorrentMetadata.select().delete() for _ in range(10): self.add_random_torrent(self.nodes[0].overlay.metadata_store.TorrentMetadata, channel=channel) channel.commit_channel_torrent() # Initiate the gossip again. This time, it should be sent from the blob cache # so the torrents on the receiving end should not change this time. self.nodes[0].overlay.send_random_to(Peer(self.nodes[1].my_peer.public_key, self.nodes[1].endpoint.wan_address)) await self.deliver_messages(timeout=0.5) with db_session: torrents2 = self.nodes[1].overlay.metadata_store.TorrentMetadata.select()[:] self.assertEqual(len(torrents1), len(torrents2)) await self.nodes[0].overlay.prepare_gossip_blob_cache() self.nodes[0].overlay.send_random_to(Peer(self.nodes[1].my_peer.public_key, self.nodes[1].endpoint.wan_address)) await self.deliver_messages(timeout=0.5) with db_session: torrents3 = self.nodes[1].overlay.metadata_store.TorrentMetadata.select()[:] self.assertLess(len(torrents2), len(torrents3))
def test_strategy_multi_peer(self): """ If we have multiple peers, we should select one and send it our channel views. Also, we should still inspect our download queue. """ self.community.get_peers_return = [ Peer(default_eccrypto.generate_key(u"very-low")), Peer(default_eccrypto.generate_key(u"very-low")), Peer(default_eccrypto.generate_key(u"very-low")), ] self.strategy.take_step() self.assertEqual(1, len(self.community.send_random_to_called)) self.assertIn(self.community.send_random_to_called[0], self.community.get_peers_return)
def test_channels_peers_mapping_drop_excess_peers(self): """ Test dropping old excess peers from a channel to peers mapping """ mapping = ChannelsPeersMapping() chan_pk = Mock() chan_id = 123 num_excess_peers = 20 t = time.time() - 1000 first_peer_timestamp = t for k in range(0, mapping.max_peers_per_channel + num_excess_peers): peer = Peer(default_eccrypto.generate_key("very-low"), ("1.2.3.4", 5)) peer.last_response = t t += 1.0 mapping.add(peer, chan_pk, chan_id) if k == 0: first_peer_timestamp = peer.last_response chan_peers_3 = mapping.get_last_seen_peers_for_channel( chan_pk, chan_id, 3) assert len(chan_peers_3) == 3 chan_peers = mapping.get_last_seen_peers_for_channel(chan_pk, chan_id) assert len(chan_peers) == mapping.max_peers_per_channel assert chan_peers_3 == chan_peers[0:3] assert chan_peers == sorted(chan_peers, key=lambda x: x.last_response, reverse=True) # Make sure only the older peers are dropped as excess for p in chan_peers: assert p.last_response > first_peer_timestamp # Test removing a peer directly, e.g. as a result of a query timeout peer = Peer(default_eccrypto.generate_key("very-low"), ("1.2.3.4", 5)) mapping.add(peer, chan_pk, chan_id) mapping.remove_peer(peer) for p in chan_peers: mapping.remove_peer(p) assert mapping.get_last_seen_peers_for_channel(chan_pk, chan_id) == [] # Make sure the stuff is cleaned up assert len(mapping._peers_channels) == 0 assert len(mapping._channels_dict) == 0
async def on_payout_block(self, source_address, data): if not self.bandwidth_wallet: self.logger.warning( "Got payout while not having a TrustChain community running!") return payload = self._ez_unpack_noauth(PayoutPayload, data, global_time=False) peer = Peer(payload.public_key, source_address) block = TriblerBandwidthBlock.from_payload(payload, self.serializer) try: blocks = await self.bandwidth_wallet.trustchain.process_half_block( block, peer) except: return # Send the next payout if blocks and payload.circuit_id in self.relay_from_to and block.transaction[ b'down'] > payload.base_amount: relay = self.relay_from_to[payload.circuit_id] self._logger.info("Sending next payout to peer %s", relay.peer) self.do_payout( relay.peer, relay.circuit_id, block.transaction[b'down'] - payload.base_amount * 2, payload.base_amount) # Check whether the block has been added to the database and has been verified if not self.bandwidth_wallet.trustchain.persistence.contains(block): self.logger.warning( "Not proceeding with payout - received payout block is not valid" ) return
def on_generic_introduction_request(self, source_address, data, prefix): auth, dist, payload = self._ez_unpack_auth(IntroductionRequestPayload, data) peer = Peer(auth.public_key_bin, source_address) peer.address = UDPv4LANAddress(*payload.source_lan_address) peer.last_response = time.time() service_id = prefix[2:] self.on_peer_introduction_request(peer, source_address, service_id) self.network.add_verified_peer(peer) self.network.discover_services(peer, [ service_id, ]) intro_peers = [ p for p in self.network.get_peers_for_service(service_id) if not p == peer ] if intro_peers: intro_peer = random.choice(intro_peers) else: intro_peer = None packet = self.create_introduction_response(payload.destination_address, peer.address, payload.identifier, introduction=intro_peer, prefix=prefix) self.endpoint.send(peer.address, packet)
def test_peer_inequality_address(self): """ Check if peers with the same key and a different address are not equal. """ other = Peer(self.peer.key) self.assertNotEqual(self.peer, other)
def test_peer_inequality_key(self): """ Check if peers with a different key and same address are not equal. """ other = Peer(ECCrypto().generate_key(u"very-low"), self.peer.address) self.assertNotEqual(self.peer, other)
def test_peer_equality(self): """ Check if peers with the same key and address are equal. """ other = Peer(self.peer.key, self.peer.address) self.assertEqual(self.peer, other)
class MyCommunity(Community): master_peer = Peer(ECCrypto().generate_key(u"medium")) def started(self): async def check_peers(): global INSTANCES, LOW_EDGE, LOW_EDGE_PEER, START_TIME if self.get_peers(): if LOW_EDGE and self.my_peer != LOW_EDGE_PEER: print("%.4f,%.4f" % (LOW_EDGE, time.time() - START_TIME)) async def shutdown(): for instance in INSTANCES: await instance.stop(False) get_event_loop().stop() ensure_future(shutdown()) else: LOW_EDGE = time.time() - START_TIME LOW_EDGE_PEER = self.my_peer self.register_task("check_peers", check_peers, interval=0.1, delay=0) def create_introduction_response(self, lan_socket_address, socket_address, identifier, introduction=None): return super(MyCommunity, self).create_introduction_response( lan_socket_address, socket_address, identifier, introduction, b'1') def create_introduction_request(self, socket_address): return super(MyCommunity, self).create_introduction_request(socket_address, b'2')
def create_node(self): config = TunnelCommunitySettings() mock_ipv8 = MockIPv8("curve25519", TriblerTunnelCommunity, settings={'remove_tunnel_delay': 0}, config=config, exitnode_cache=Path(self.temporary_directory()) / "exitnode_cache.dat") mock_ipv8.overlay.settings.max_circuits = 1 db = BandwidthDatabase( db_path=MEMORY_DB, my_pub_key=mock_ipv8.my_peer.public_key.key_to_bin()) # Load the bandwidth accounting community mock_ipv8.overlay.bandwidth_community = BandwidthAccountingCommunity( mock_ipv8.my_peer, mock_ipv8.endpoint, mock_ipv8.network, settings=BandwidthAccountingSettings(), database=db) mock_ipv8.overlay.dht_provider = MockDHTProvider( Peer(mock_ipv8.overlay.my_peer.key, mock_ipv8.overlay.my_estimated_wan)) return mock_ipv8
class MyCommunity(Community): master_peer = Peer(ECCrypto().generate_key(u"medium")) def started(self): def check_peers(): global INSTANCES, LOW_EDGE, LOW_EDGE_PEER, START_TIME if self.get_peers(): if LOW_EDGE and self.my_peer != LOW_EDGE_PEER: for instance in INSTANCES: instance.stop(False) reactor.callFromThread(reactor.stop) print("%.4f,%.4f" % (LOW_EDGE, time.time() - START_TIME)) else: LOW_EDGE = time.time() - START_TIME LOW_EDGE_PEER = self.my_peer self.register_task("check_peers", LoopingCall(check_peers)).start(0.1, True) def create_introduction_response(self, lan_socket_address, socket_address, identifier, introduction=None): return super(MyCommunity, self).create_introduction_response( lan_socket_address, socket_address, identifier, introduction, b'1') def create_introduction_request(self, socket_address): return super(MyCommunity, self).create_introduction_request(socket_address, b'2')
async def test_send_and_get_channel_update_back(self): """ Test if sending back information on updated version of a channel works """ with db_session: # Add channel to node 0 channel = self.nodes[0].overlay.metadata_store.ChannelMetadata.create_channel("test", "bla") for _ in range(20): self.add_random_torrent(self.nodes[0].overlay.metadata_store.TorrentMetadata, channel=channel) channel.commit_channel_torrent() channel_v1_dict = channel.to_dict() channel_v1_dict.pop("health") self.add_random_torrent(self.nodes[0].overlay.metadata_store.TorrentMetadata, channel=channel) channel.commit_channel_torrent() with db_session: # Add the outdated version of the channel to node 1 self.nodes[1].overlay.metadata_store.ChannelMetadata.from_dict(channel_v1_dict) # node1 --outdated_channel--> node0 await self.nodes[1].overlay.prepare_gossip_blob_cache() self.nodes[1].overlay.send_random_to(Peer(self.nodes[0].my_peer.public_key, self.nodes[0].endpoint.wan_address)) await self.deliver_messages(timeout=0.5) with db_session: self.assertEqual( self.nodes[1].overlay.metadata_store.ChannelMetadata.select()[:][0].timestamp, self.nodes[0].overlay.metadata_store.ChannelMetadata.select()[:][0].timestamp, )
async def test_send_personal_and_random_channels(self): """ Test whether sending the personal channel works correctly """ with db_session: # Add non-personal channel channel = self.nodes[0].overlay.metadata_store.ChannelMetadata.create_channel("non-personal", "bla") self.add_random_torrent(self.nodes[0].overlay.metadata_store.TorrentMetadata, channel=channel) channel.commit_channel_torrent() # Add personal channel self.nodes[0].overlay.metadata_store.ChannelNode._my_key = default_eccrypto.generate_key(u"curve25519") # After the previous line the previously created channel becomes non-personal channel = self.nodes[0].overlay.metadata_store.ChannelMetadata.create_channel("personal", "bla") self.add_random_torrent(self.nodes[0].overlay.metadata_store.TorrentMetadata, channel=channel) channel.commit_channel_torrent() await self.nodes[0].overlay.prepare_gossip_blob_cache() self.nodes[0].overlay.send_random_to(Peer(self.nodes[1].my_peer.public_key, self.nodes[1].endpoint.wan_address)) await self.deliver_messages(timeout=0.5) with db_session: self.assertEqual(len(self.nodes[1].overlay.metadata_store.ChannelMetadata.select()), 2) channels = self.nodes[1].overlay.metadata_store.ChannelMetadata.select()[:] self.assertEqual(channels[0].contents_len, 1) self.assertEqual(channels[1].contents_len, 1)
class RemoteQueryTestnetCommunity(RemoteQueryCommunity): master_peer = Peer( unhexlify( "4c69624e61434c504b3a7fcf64783215dba08c1623fb14c3c86127b8591f858c56763e2281" "a8e121ef08caae395b2597879f7f4658b608f22df280073661f85174fd7c565cbee3e4328f" ) )
class MockedCommunity(Community, CommunityRoutines): master_peer = Peer(default_eccrypto.generate_key(u"very-low")) def __init__(self, *args, **kwargs): if kwargs.get("work_dir"): self.work_dir = kwargs.pop("work_dir") super().__init__(*args, **kwargs) self._req = RequestCache() for base in self.__class__.__bases__: if issubclass(base, MessageStateMachine): base.setup_messages(self) @property def persistence(self) -> BaseDB: return MockDBManager() @property def settings(self) -> Any: return MockSettings() def send_packet(self, *args, **kwargs) -> None: self.ez_send(*args, **kwargs) @property def request_cache(self) -> RequestCache: return self._req async def unload(self): await self._req.shutdown() return await super().unload()
async def test_get_channels_peers(rest_api, endpoint, metadata_store, mock_gigachannel_community): # pylint: disable=W0621, C0321 """ Test getting debug info about the state of channels to peers mapping """ mapping = mock_gigachannel_community.channels_peers = ChannelsPeersMapping( ) peer_key = default_eccrypto.generate_key("curve25519") chan_key = default_eccrypto.generate_key("curve25519") with db_session: chan = metadata_store.ChannelMetadata(sign_with=chan_key, name="bla", infohash=random_infohash()) peer = Peer(peer_key, ("1.2.3.4", 5)) mapping.add(peer, chan.public_key, chan.id_) result = await do_request( rest_api, 'remote_query/channels_peers', request_type="GET", expected_code=200, ) first_result = result["channels_list"][0] assert first_result["channel_name"] == chan.title assert first_result["channel_pk"] == hexlify(chan.public_key) assert first_result["channel_id"] == chan.id_ assert first_result["peers"][0][0] == hexlify(peer.mid)
async def run(self): await super().run() config = self.session.config self._task_manager = TaskManager() port = config.ipv8.port address = config.ipv8.address self.logger.info('Starting ipv8') self.logger.info(f'Port: {port}. Address: {address}') ipv8_config_builder = ( ConfigBuilder().set_port(port).set_address(address).clear_overlays( ).clear_keys() # We load the keys ourselves .set_working_directory(str(config.state_dir)).set_walker_interval( config.ipv8.walk_interval)) if config.gui_test_mode: endpoint = DispatcherEndpoint([]) else: # IPv8 includes IPv6 support by default. # We only load IPv4 to not kill all Tribler overlays (currently, it would instantly crash all users). # If you want to test IPv6 in Tribler you can set ``endpoint = None`` here. endpoint = DispatcherEndpoint(["UDPIPv4"], UDPIPv4={ 'port': port, 'ip': address }) ipv8 = IPv8(ipv8_config_builder.finalize(), enable_statistics=config.ipv8.statistics and not config.gui_test_mode, endpoint_override=endpoint) await ipv8.start() self.ipv8 = ipv8 key_component = await self.require_component(KeyComponent) self.peer = Peer(key_component.primary_key) if config.ipv8.statistics and not config.gui_test_mode: # Enable gathering IPv8 statistics for overlay in ipv8.overlays: ipv8.endpoint.enable_community_statistics( overlay.get_prefix(), True) if config.ipv8.walk_scaling_enabled and not config.gui_test_mode: from tribler_core.components.ipv8.ipv8_health_monitor import IPv8Monitor IPv8Monitor(ipv8, config.ipv8.walk_interval, config.ipv8.walk_scaling_upper_limit).start( self._task_manager) if config.dht.enabled: self._init_dht_discovery_community() if not config.gui_test_mode: if config.discovery_community.enabled: self._init_peer_discovery_community() else: if config.dht.enabled: self.dht_discovery_community.routing_tables[ UDPv4Address] = RoutingTable('\x00' * 20)
def on_generic_introduction_request(self, source_address, data, prefix): auth, dist, payload = self._ez_unpack_auth(IntroductionRequestPayload, data) peer = Peer(auth.public_key_bin, source_address) peer.last_response = time.time() self.network.add_verified_peer(peer) self.network.discover_services(peer, [ prefix[2:], ]) intro_peers = [ p for p in self.network.get_peers_for_service(prefix[2:]) if not (p == peer) ] if intro_peers: intro_peer = random.choice(intro_peers) else: intro_peer = None packet = self.create_introduction_response(payload.destination_address, peer.address, payload.identifier, introduction=intro_peer) packet = prefix + packet[22:-self.signature_length] signature = default_eccrypto.create_signature(self.my_peer.key, packet) self.endpoint.send(peer.address, packet + signature)
class EndpointServer(Community): """ Make some small modifications to the Community to allow it a dynamic prefix. We will also only answer introduction requests. """ master_peer = Peer(default_eccrypto.generate_key(u"very-low")) def __init__(self, endpoint): my_peer = Peer(default_eccrypto.generate_key(u"very-low")) self.signature_length = default_eccrypto.get_signature_length(my_peer.public_key) super(EndpointServer, self).__init__(my_peer, endpoint, Network()) self.churn_strategy = SimpleChurn(self) self.churn_lc = self.register_task("churn", LoopingCall(self.churn_strategy.take_step)).start(30.0, now=False) def on_packet(self, packet, warn_unknown=False): source_address, data = packet try: probable_peer = self.network.get_verified_by_address(source_address) if probable_peer: probable_peer.last_response = time.time() if data[22] == chr(246): self.on_generic_introduction_request(source_address, data, data[:22]) elif warn_unknown: self.logger.warning("Tracker received unknown message %s", str(data[22])) except: import traceback traceback.print_exc() def on_generic_introduction_request(self, source_address, data, prefix): auth, dist, payload = self._ez_unpack_auth(IntroductionRequestPayload, data) peer = Peer(auth.public_key_bin, source_address) peer.last_response = time.time() self.network.add_verified_peer(peer) self.network.discover_services(peer, [prefix[2:], ]) intro_peers = [p for p in self.network.get_peers_for_service(prefix[2:]) if not(p == peer)] if intro_peers: intro_peer = random.choice(intro_peers) else: intro_peer = None packet = self.create_introduction_response(payload.destination_address, peer.address, payload.identifier, introduction=intro_peer) packet = prefix + packet[22:-self.signature_length] signature = default_eccrypto.create_signature(self.my_peer.key, packet) self.endpoint.send(peer.address, packet + signature) def get_peer_for_introduction(self, exclude=None): """ We explicitly provide create_introduction_response with a peer. If on_generic_introduction_request provides None, this method should not suggest a peer. More so as the get_peer_for_introduction peer would be for the DiscoveryCommunity. """ return None
def __init__(self, endpoint): my_peer = Peer(default_eccrypto.generate_key(u"very-low")) self.signature_length = default_eccrypto.get_signature_length( my_peer.public_key) super(EndpointServer, self).__init__(my_peer, endpoint, Network()) self.churn_strategy = SimpleChurn(self) self.churn_task = self.register_task("churn", self.churn_strategy.take_step, interval=30)
def __init__(self, endpoint): my_peer = Peer(default_eccrypto.generate_key(u"very-low")) self.signature_length = default_eccrypto.get_signature_length( my_peer.public_key) super(EndpointServer, self).__init__(my_peer, endpoint, Network()) self.churn_strategy = SimpleChurn(self) self.churn_lc = self.register_task( "churn", LoopingCall(self.churn_strategy.take_step)).start(30.0, now=False)
def test_strategy_one_peer(self): """ If we have one peer, we should send it our channel views and inspect our download queue. """ self.community.get_peers_return = [Peer(default_eccrypto.generate_key(u"very-low"))] self.strategy.take_step() self.assertEqual(1, len(self.community.send_random_to_called)) self.assertEqual(self.community.get_peers_return[0], self.community.send_random_to_called[0])
class TriblerTunnelTestnetCommunity(TriblerTunnelCommunity): """ This community defines a testnet for the anonymous tunnels. """ master_peer = ( "4c69624e61434c504b3a7773497078402b39b61b4d26851dad4a8d956243558ff387239a80429c362f52df70e1e" "8a97182311d7fb9c13fb80fae616bc82c691c7f03e69560da8c7295d8") master_peer = Peer(unhexlify(master_peer))
class MsgCommunity(Community): master_peer = Peer( unhexlify( "307e301006072a8648ce3d020106052b81040024036a000400bd9cae587628a7d169fa193729465b4d" "2e4a382b5fac38e356a225339e8ff5336c70fd426d173796090416be826bcc5730533a0000e5c6db19" "107f6930d3c3a1017fe131fa396840e4facd620add83dadbd4d79185d4eabdf843efc292d7f898af46" "297c76736c")) inbox = [] def __init__(self, my_peer, endpoint, network): super(MsgCommunity, self).__init__(my_peer, endpoint, network) # Register the message handler for messages with the identifier "1". self.add_message_handler(1, self.on_message) def started(self): print("Started") # async def start_communication(): # for p in self.get_peers(): # self.send_message(p.address, "yoyo") # self.register_task("start_communication", start_communication, interval=5.0, delay=0) def send_message(self, mid, message): # Send a message with our digital signature on it. # We use the latest version of our Lamport clock. for p in self.get_peers(): m = b64encode(p.mid).decode("utf-8") if m == mid: self.endpoint.send( p.address, self.ezr_pack(1, MyMessage(message.encode('utf-8')))) print("Sending message '%s' to %s" % (message, mid)) return True else: print("Skipping mid " + m) print("Peer %s not found, cannot send message '%s'" % (mid, message)) return False def delete_message(self, message_id): l = len(self.inbox) self.inbox = [i for i in self.inbox if i['id'] != message_id] return l != len(self.inbox) @lazy_wrapper(MyMessage) def on_message(self, peer, payload): print("Got message from peer") message = { 'time': time.time(), 'id': str(uuid4()), 'peer': peer, 'message': payload.message } self.inbox.append(message)
def __init__(self, path, port, interface='127.0.0.1', configuration=None): """ Create a test peer with a REST API interface. :param path: the for the working directory of this peer :param port: this peer's port :param interface: IP or alias of the peer. Defaults to '127.0.0.1' :param configuration: IPv8 configuration object. Defaults to None """ self._logger = logging.getLogger(self.__class__.__name__) self._logger.info("Peer starting-up.") self._rest_manager = None self._port = port self._interface = interface self._path = path self._configuration = configuration # Check to see if we've received a custom configuration if configuration is None: # Create a default configuration self._configuration = get_default_configuration() self._configuration['logger'] = {'level': "ERROR"} overlays = ['AttestationCommunity', 'IdentityCommunity'] self._configuration['overlays'] = [o for o in self._configuration['overlays'] if o['class'] in overlays] for o in self._configuration['overlays']: o['walkers'] = [{ 'strategy': "RandomWalk", 'peers': 20, 'init': { 'timeout': 60.0 } }] self._create_working_directory(self._path) self._logger.info("Created working directory.") os.chdir(self._path) self._ipv8 = IPv8(self._configuration) os.chdir(os.path.dirname(__file__)) # Change the master_peers of the IPv8 object's overlays, in order to avoid conflict with the live networks for idx, overlay in enumerate(self._ipv8.overlays): self._ipv8.overlays[idx].master_peer = Peer(COMMUNITY_TO_MASTER_PEER_KEY[type(overlay).__name__]) self._rest_manager = TestPeer.RestAPITestWrapper(self._ipv8, self._port, self._interface) self._rest_manager.start() self._logger.info("Peer started up.")