def setup_class(cls): """Set the test up""" cls.cwd = os.getcwd() cls.t = tempfile.mkdtemp() os.chdir(cls.t) crypto = make_crypto(DEFAULT_LEDGER) cls.node_host = "localhost" cls.node_port = "11234" cls.identity = Identity("", address=crypto.address) cls.key_file = os.path.join(cls.t, "keyfile") key_file_desc = open(cls.key_file, "ab") crypto.dump(key_file_desc) key_file_desc.close() cls.peer_crypto = make_crypto(DEFAULT_LEDGER) cls.cert_request = CertRequest( cls.peer_crypto.public_key, POR_DEFAULT_SERVICE_ID, DEFAULT_LEDGER, "2021-01-01", "2021-01-02", f"./{crypto.address}_cert.txt", ) _process_cert(crypto, cls.cert_request, cls.t)
def test_agent_record(change_directory): """Test signature and public key proper retrieval from a CertRequest""" agent_key_1 = make_crypto(DEFAULT_LEDGER) agent_key_2 = make_crypto(DEFAULT_LEDGER) peer_public_key_1 = make_crypto(DEFAULT_LEDGER).public_key peer_public_key_2 = make_crypto(DEFAULT_LEDGER).public_key cert_path = "test_acn_cert.txt" cert = CertRequest( peer_public_key_1, "test_service", DEFAULT_LEDGER, "2021-01-01", "2022-01-01", cert_path, ) _process_cert(agent_key_1, cert, change_directory) # success agent_record = AgentRecord.from_cert_request(cert, agent_key_1.address, peer_public_key_1) assert (agent_record.address == agent_key_1.address and agent_record.public_key == agent_key_1.public_key and agent_record.representative_public_key == peer_public_key_1 and agent_record.signature == cert.get_signature() and agent_record.message == cert.get_message(peer_public_key_1)) # success agent_record = AgentRecord( agent_key_1.address, peer_public_key_1, cert.get_message(peer_public_key_1), cert.get_signature(), DEFAULT_LEDGER, ) assert (agent_record.address == agent_key_1.address and agent_record.public_key == agent_key_1.public_key and agent_record.representative_public_key == peer_public_key_1 and agent_record.signature == cert.get_signature() and agent_record.message == cert.get_message(peer_public_key_1)) # error: wrong signer with pytest.raises( ValueError, match= "Invalid signature for provided representative_public_key and agent address!", ): AgentRecord.from_cert_request(cert, agent_key_2.address, peer_public_key_1) # error: wrong signer with pytest.raises( ValueError, match= "Invalid signature for provided representative_public_key and agent address!", ): AgentRecord.from_cert_request(cert, agent_key_1.address, peer_public_key_2)
def setup(self): """Set up.""" self.crypto = make_crypto(DEFAULT_LEDGER) self.crypto2 = make_crypto(DEFAULT_LEDGER) identity = Identity("", address=self.crypto.address) self.oef_search_dialogues = OefSearchDialogues(self.crypto.address) # create the connection and multiplexer objects configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="soef.fetch.ai", soef_port=9002, restricted_to_protocols={PublicId.from_str("fetchai/oef_search:0.3.0")}, connection_id=SOEFConnection.connection_id, ) self.connection = SOEFConnection( configuration=configuration, identity=identity, ) self.connection.channel.unique_page_address = "some addr" self.connection2 = SOEFConnection( configuration=configuration, identity=Identity("", address=self.crypto2.address), ) self.loop = asyncio.get_event_loop() self.loop.run_until_complete(self.connection.connect()) self.loop.run_until_complete(self.connection2.connect())
def test_fetchai(self): """Test that the fetchai private key is overwritten or not dependending on the user input.""" result = self.runner.invoke(cli, [*CLI_LOG_OPTION, "generate-key", FETCHAI]) assert result.exit_code == 0 assert Path(FETCHAI_PRIVATE_KEY_FILE).exists() # This tests if the file has been created and its content is correct. make_crypto(FETCHAI, private_key_path=FETCHAI_PRIVATE_KEY_FILE) content = Path(FETCHAI_PRIVATE_KEY_FILE).read_bytes() # Saying 'no' leave the files as it is. result = self.runner.invoke(cli, [*CLI_LOG_OPTION, "generate-key", FETCHAI], input="n") assert result.exit_code == 0 assert Path(FETCHAI_PRIVATE_KEY_FILE).read_bytes() == content # Saying 'yes' overwrites the file. result = self.runner.invoke(cli, [*CLI_LOG_OPTION, "generate-key", FETCHAI], input="y") assert result.exit_code == 0 assert Path(FETCHAI_PRIVATE_KEY_FILE).read_bytes() != content make_crypto(FETCHAI, private_key_path=FETCHAI_PRIVATE_KEY_FILE)
def try_validate_private_key_path(ledger_id: str, private_key_path: str, exit_on_error: bool = True) -> None: """ Try validate a private key path. :param ledger_id: one of 'fetchai', 'ethereum' :param private_key_path: the path to the private key. :return: None :raises: ValueError if the identifier is invalid. """ try: # to validate the file, we just try to create a crypto object # with private_key_path as parameter make_crypto(ledger_id, private_key_path=private_key_path) except Exception as e: # pylint: disable=broad-except # thats ok, will exit or reraise error_msg = "This is not a valid private key file: '{}'\n Exception: '{}'".format( private_key_path, e) if exit_on_error: _default_logger.exception( error_msg) # show exception traceback on exit sys.exit(1) else: # pragma: no cover _default_logger.error(error_msg) raise
def setup(self): """Set up.""" self.crypto = make_crypto(DEFAULT_LEDGER) self.crypto2 = make_crypto(DEFAULT_LEDGER) identity = Identity("", address=self.crypto.address) self.oef_search_dialogues = OefSearchDialogues(self.crypto.address) self.data_dir = tempfile.mkdtemp() # create the connection and multiplexer objects configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="s-oef.fetch.ai", soef_port=443, restricted_to_protocols={ OefSearchMessage.protocol_specification_id }, connection_id=SOEFConnection.connection_id, ) self.connection = SOEFConnection( configuration=configuration, data_dir=self.data_dir, identity=identity, ) self.connection2 = SOEFConnection( configuration=configuration, data_dir=self.data_dir, identity=Identity("", address=self.crypto2.address), ) self.loop = asyncio.get_event_loop() self.loop.run_until_complete(self.connection.connect()) self.loop.run_until_complete(self.connection2.connect()) self.connection.channel.unique_page_address = "some_addr"
def setup(self): """Set up.""" self.crypto = make_crypto(DEFAULT_LEDGER) self.crypto2 = make_crypto(DEFAULT_LEDGER) self.data_dir = tempfile.mkdtemp() identity = Identity("", address=self.crypto.address) self.oef_search_dialogues = OefSearchDialogues(self.crypto.address) # create the connection and multiplexer objects self.token_storage_path = "test.storage" configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="s-oef.fetch.ai", soef_port=443, token_storage_path=self.token_storage_path, restricted_to_protocols={ OefSearchMessage.protocol_specification_id }, connection_id=SOEFConnection.connection_id, ) self.connection = SOEFConnection( configuration=configuration, data_dir=self.data_dir, identity=identity, )
def test_fetchai(self): """Test that the fetch private key is created correctly.""" result = self.runner.invoke(cli, [*CLI_LOG_OPTION, "generate-key", FETCHAI]) assert result.exit_code == 0 assert Path(FETCHAI_PRIVATE_KEY_FILE).exists() make_crypto(FETCHAI, private_key_path=FETCHAI_PRIVATE_KEY_FILE) Path(FETCHAI_PRIVATE_KEY_FILE).unlink()
def test_ethereum(self): """Test that the fetch private key is created correctly.""" result = self.runner.invoke(cli, [*CLI_LOG_OPTION, "generate-key", ETHEREUM]) assert result.exit_code == 0 assert Path(ETHEREUM_PRIVATE_KEY_FILE).exists() make_crypto(ETHEREUM, private_key_path=ETHEREUM_PRIVATE_KEY_FILE) Path(ETHEREUM_PRIVATE_KEY_FILE).unlink()
def __init__(self, **kwargs): """ Initialize a libp2p client connection. """ super().__init__(**kwargs) ledger_id = self.configuration.config.get("ledger_id", DEFAULT_LEDGER) if ledger_id not in SUPPORTED_LEDGER_IDS: raise ValueError( # pragma: nocover "Ledger id '{}' is not supported. Supported ids: '{}'".format( ledger_id, SUPPORTED_LEDGER_IDS)) # TODO: ensure ledger_id matches with provided key of p2p node. key_file = self.configuration.config.get( "client_key_file") # Optional[str] nodes = self.configuration.config.get("nodes") assert nodes is not None, "At least one node should be provided" nodes = list(cast(List, nodes)) nodes_uris = [node["uri"] for node in nodes] assert len(nodes_uris) == len( nodes), "Delegate Uri should be provided for each node" if (self.has_crypto_store and self.crypto_store.crypto_objects.get( ledger_id, None) is not None): # pragma: no cover key = self.crypto_store.crypto_objects[ledger_id] elif key_file is not None: key = make_crypto(ledger_id, private_key_path=key_file) else: key = make_crypto(ledger_id) # client connection id self.key = key logger.debug("Public key used by libp2p client: {}".format( key.public_key)) # delegate uris self.delegate_uris = [Uri(node_uri) for node_uri in nodes_uris] # delegates certificates # TOFIX(LR) will be mandatory self.delegate_certs = [] # select a delegate index = random.randint(0, len(self.delegate_uris) - 1) # nosec self.node_uri = self.delegate_uris[index] # self.node_cert = self.delegate_certs[index] logger.debug("Node to use as delegate: {}".format(self.node_uri)) # tcp connection self._reader = None # type: Optional[asyncio.StreamReader] self._writer = None # type: Optional[asyncio.StreamWriter] self._loop = None # type: Optional[AbstractEventLoop] self._in_queue = None # type: Optional[asyncio.Queue] self._process_messages_task = None # type: Union[asyncio.Future, None]
def test_all(self): """Test that all the private keys are created correctly when running 'aea generate-key all'.""" result = self.runner.invoke(cli, [*CLI_LOG_OPTION, "generate-key", "all"]) assert result.exit_code == 0 assert Path(FETCHAI_PRIVATE_KEY_FILE).exists() assert Path(ETHEREUM_PRIVATE_KEY_FILE).exists() make_crypto(FETCHAI, private_key_path=FETCHAI_PRIVATE_KEY_FILE) make_crypto(ETHEREUM, private_key_path=ETHEREUM_PRIVATE_KEY_FILE) Path(FETCHAI_PRIVATE_KEY_FILE).unlink() Path(ETHEREUM_PRIVATE_KEY_FILE).unlink()
def setup(self): """Set the test up""" super().setup() temp_dir_gen = os.path.join(self.t, "temp_dir_gen") os.mkdir(temp_dir_gen) self.genesis = _make_libp2p_connection(data_dir=temp_dir_gen, port=DEFAULT_PORT + 1, build_directory=self.t) self.multiplexer_genesis = Multiplexer([self.genesis], protocols=[DefaultMessage]) self.multiplexer_genesis.connect() self.log_files.append(self.genesis.node.log_file) self.multiplexers.append(self.multiplexer_genesis) genesis_peer = self.genesis.node.multiaddrs[0] with open("node_key", "wb") as f: make_crypto(DEFAULT_LEDGER).dump(f) self.relay_key_path = "node_key" temp_dir_rel = os.path.join(self.t, "temp_dir_rel") os.mkdir(temp_dir_rel) self.relay = _make_libp2p_connection( data_dir=temp_dir_rel, port=DEFAULT_PORT + 2, entry_peers=[genesis_peer], node_key_file=self.relay_key_path, build_directory=self.t, ) self.multiplexer_relay = Multiplexer([self.relay], protocols=[DefaultMessage]) self.multiplexer_relay.connect() self.log_files.append(self.relay.node.log_file) self.multiplexers.append(self.multiplexer_relay) relay_peer = self.relay.node.multiaddrs[0] temp_dir_1 = os.path.join(self.t, "temp_dir_1") os.mkdir(temp_dir_1) self.connection = _make_libp2p_connection( data_dir=temp_dir_1, port=DEFAULT_PORT + 3, relay=False, entry_peers=[relay_peer], build_directory=self.t, ) self.multiplexer = Multiplexer([self.connection], protocols=[DefaultMessage]) self.multiplexer.connect() self.log_files.append(self.connection.node.log_file) self.multiplexers.append(self.multiplexer)
def make_multiplexer_and_dialogues( ) -> Tuple[Multiplexer, OefSearchDialogues, Crypto, SOEFConnection]: """Return multplexer, dialogues and crypto instances.""" crypto = make_crypto(DEFAULT_LEDGER) identity = Identity("", address=crypto.address) oef_search_dialogues = OefSearchDialogues(crypto.address) # create the connection and multiplexer objects configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="s-oef.fetch.ai", soef_port=443, restricted_to_protocols={ OefSearchMessage.protocol_specification_id, OefSearchMessage.protocol_id, }, connection_id=SOEFConnection.connection_id, ) soef_connection = SOEFConnection( configuration=configuration, data_dir=MagicMock(), identity=identity, ) multiplexer = Multiplexer([soef_connection]) return multiplexer, oef_search_dialogues, crypto, soef_connection
def __init__( self, crypto_id_to_path: Optional[Dict[str, Optional[str]]] = None) -> None: """ Initialize the crypto store. :param crypto_id_to_path: dictionary from crypto id to an (optional) path to the private key. """ if crypto_id_to_path is None: crypto_id_to_path = {} crypto_objects = {} # type: Dict[str, Crypto] public_keys = {} # type: Dict[str, str] addresses = {} # type: Dict[str, str] private_keys = {} # type: Dict[str, str] for identifier, path in crypto_id_to_path.items(): crypto = make_crypto(identifier, private_key_path=path) crypto_objects[identifier] = crypto public_keys[identifier] = cast(str, crypto.public_key) addresses[identifier] = cast(str, crypto.address) private_keys[identifier] = cast(str, crypto.private_key) self._crypto_objects = crypto_objects self._public_keys = public_keys self._addresses = addresses self._private_keys = private_keys
async def test_node_not_running(self): """Test the node is not running.""" with tempfile.TemporaryDirectory() as dirname: conn = _make_libp2p_client_connection( data_dir=dirname, peer_public_key=make_crypto(DEFAULT_LEDGER).public_key ) with pytest.raises(Exception): await conn.connect()
def setup_class(cls): """Set the test up""" cls.cwd = os.getcwd() cls.t = tempfile.mkdtemp() os.chdir(cls.t) cls.log_files = [] cls.multiplexers = [] try: cls.genesis = _make_libp2p_connection(DEFAULT_PORT + 1) cls.multiplexer_genesis = Multiplexer([cls.genesis]) cls.log_files.append(cls.genesis.node.log_file) cls.multiplexer_genesis.connect() cls.multiplexers.append(cls.multiplexer_genesis) genesis_peer = cls.genesis.node.multiaddrs[0] with open("node_key", "wb") as f: make_crypto(DEFAULT_LEDGER).dump(f) cls.relay_key_path = "node_key" cls.relay = _make_libp2p_connection( port=DEFAULT_PORT + 2, entry_peers=[genesis_peer], node_key_file=cls.relay_key_path, ) cls.multiplexer_relay = Multiplexer([cls.relay]) cls.log_files.append(cls.relay.node.log_file) cls.multiplexer_relay.connect() cls.multiplexers.append(cls.multiplexer_relay) relay_peer = cls.relay.node.multiaddrs[0] cls.connection = _make_libp2p_connection(DEFAULT_PORT + 3, relay=False, entry_peers=[relay_peer]) cls.multiplexer = Multiplexer([cls.connection]) cls.log_files.append(cls.connection.node.log_file) cls.multiplexer.connect() cls.multiplexers.append(cls.multiplexer) except Exception as e: cls.teardown_class() raise e
def test_multiaddr_consistency(): """Test multiaddress consistency.""" key = make_crypto(DEFAULT_LEDGER) maddr1 = MultiAddr(HOST, PORT, key.public_key) tmpdir = tempfile.mkdtemp() key_file = tmpdir + "/key" with open(key_file, "wb+") as k: key.dump(k) key2 = make_crypto(DEFAULT_LEDGER, private_key_path=key_file) maddr2 = MultiAddr(HOST, PORT, key2.public_key) rmtree(tmpdir) assert str(maddr1) == str(maddr2) assert maddr1.public_key == maddr2.public_key assert maddr1.peer_id == maddr2.peer_id
def create_private_key(ledger_id: str, private_key_file: str) -> None: """ Create a private key for the specified ledger identifier. :param ledger_id: the ledger identifier. :param private_key_file: the private key file. :return: None :raises: ValueError if the identifier is invalid. """ crypto = make_crypto(ledger_id) crypto.dump(open(private_key_file, "wb"))
def test_fetchai(self): """Test that the fetchai private key can be deposited in a custom file.""" test_file = "test.txt" result = self.runner.invoke( cli, [*CLI_LOG_OPTION, "generate-key", FETCHAI, test_file]) assert result.exit_code == 0 assert Path(test_file).exists() # This tests if the file has been created and its content is correct. crypto = make_crypto(FETCHAI, private_key_path=test_file) content = Path(test_file).read_bytes() assert content.decode("utf-8") == crypto.private_key
def create_private_key(ledger_id: str, private_key_file: Optional[str] = None) -> None: """ Create a private key for the specified ledger identifier. :param ledger_id: the ledger identifier. :return: None :raises: ValueError if the identifier is invalid. """ if private_key_file is None: private_key_file = IDENTIFIER_TO_KEY_FILES[ledger_id] crypto = make_crypto(ledger_id) crypto.dump(open(private_key_file, "wb"))
def test_multiaddr_correctness(): """Test multiaddress correctness.""" tmpdir = tempfile.mkdtemp() key_file = tmpdir + "/key" with open(key_file, "w+") as k: k.write(PRIV_KEY) key = make_crypto(DEFAULT_LEDGER, private_key_path=key_file) maddr = MultiAddr(HOST, PORT, key.public_key) rmtree(tmpdir) assert maddr._peerid == PEER_ID
async def ledger_apis_connection(request): """Make a connection.""" crypto = make_crypto(DEFAULT_LEDGER) identity = Identity("name", crypto.address) crypto_store = CryptoStore() directory = Path(ROOT_DIR, "packages", "fetchai", "connections", "ledger") connection = Connection.from_dir(directory, identity=identity, crypto_store=crypto_store) connection = cast(Connection, connection) await connection.connect() yield connection await connection.disconnect()
def setup_class(cls): """Set the test up""" cls.cwd = os.getcwd() cls.t = tempfile.mkdtemp() os.chdir(cls.t) crypto = make_crypto(COSMOS) cls.node_host = "localhost" cls.node_port = "11234" cls.identity = Identity("", address=crypto.address) cls.key_file = os.path.join(cls.t, "keyfile") key_file_desc = open(cls.key_file, "ab") crypto.dump(key_file_desc) key_file_desc.close()
def _make_libp2p_client_connection( node_port: int = 11234, node_host: str = "127.0.0.1") -> P2PLibp2pClientConnection: crypto = make_crypto(FETCHAI) identity = Identity("", address=crypto.address) configuration = ConnectionConfig( client_key_file=None, nodes=[{ "uri": "{}:{}".format(node_host, node_port) }], connection_id=P2PLibp2pClientConnection.connection_id, ) return P2PLibp2pClientConnection(configuration=configuration, identity=identity)
async def test_reconnect_on_receive_fail(): """Test reconnect on receive fails.""" with tempfile.TemporaryDirectory() as dirname: con = _make_libp2p_client_connection( data_dir=dirname, peer_public_key=make_crypto(DEFAULT_LEDGER).public_key ) mock_reader = Mock() mock_reader.readexactly.side_effect = ConnectionError("oops") con._reader = mock_reader con._in_queue = Mock() with patch.object( con, "_perform_connection_to_node", return_value=done_future ) as connect_mock: assert await con._receive() is None connect_mock.assert_called()
async def test_reconnect_on_send_fail(): """Test reconnect on send fails.""" with tempfile.TemporaryDirectory() as dirname: con = _make_libp2p_client_connection( data_dir=dirname, peer_public_key=make_crypto(DEFAULT_LEDGER).public_key ) # test reconnect on send fails with patch.object( con, "_perform_connection_to_node", return_value=done_future ) as connect_mock, patch.object( con, "_ensure_valid_envelope_for_external_comms" ): with pytest.raises(ValueError, match="Writer is not set."): await con.send(Mock()) connect_mock.assert_called()
async def test_connect_attempts(): """Test connect attempts.""" # test connects with tempfile.TemporaryDirectory() as dirname: con = _make_libp2p_client_connection( data_dir=dirname, peer_public_key=make_crypto(DEFAULT_LEDGER).public_key ) con.connect_retries = 2 with patch( "asyncio.open_connection", side_effect=Exception("test exception on connect"), ) as open_connection_mock: with pytest.raises(Exception, match="test exception on connect"): await con.connect() assert open_connection_mock.call_count == con.connect_retries
def _make_libp2p_connection( port: int = 10234, host: str = "127.0.0.1", relay: bool = True, delegate: bool = False, entry_peers: Optional[Sequence[MultiAddr]] = None, delegate_port: int = 11234, delegate_host: str = "127.0.0.1", node_key_file: Optional[str] = None, agent_address: Optional[Address] = None, ) -> P2PLibp2pConnection: log_file = "libp2p_node_{}.log".format(port) if os.path.exists(log_file): os.remove(log_file) address = agent_address if address is None: address = make_crypto(COSMOS).address identity = Identity("", address=address) if relay and delegate: configuration = ConnectionConfig( node_key_file=node_key_file, local_uri="{}:{}".format(host, port), public_uri="{}:{}".format(host, port), entry_peers=entry_peers, log_file=log_file, delegate_uri="{}:{}".format(delegate_host, delegate_port), connection_id=P2PLibp2pConnection.connection_id, ) elif relay and not delegate: configuration = ConnectionConfig( node_key_file=node_key_file, local_uri="{}:{}".format(host, port), public_uri="{}:{}".format(host, port), entry_peers=entry_peers, log_file=log_file, connection_id=P2PLibp2pConnection.connection_id, ) else: configuration = ConnectionConfig( node_key_file=node_key_file, local_uri="{}:{}".format(host, port), entry_peers=entry_peers, log_file=log_file, connection_id=P2PLibp2pConnection.connection_id, ) return P2PLibp2pConnection(configuration=configuration, identity=identity)
def _make_libp2p_client_connection( node_port: int = 11234, node_host: str = "127.0.0.1", uri: Optional[str] = None, ) -> P2PLibp2pClientConnection: crypto = make_crypto(COSMOS) identity = Identity("", address=crypto.address) configuration = ConnectionConfig( client_key_file=None, nodes=[{ "uri": str(uri) if uri is not None else "{}:{}".format( node_host, node_port) }], connection_id=P2PLibp2pClientConnection.connection_id, ) return P2PLibp2pClientConnection(configuration=configuration, identity=identity)
def setup(self): """Set the test up""" super().setup() temp_dir_gen = os.path.join(self.t, "temp_dir_gen") os.mkdir(temp_dir_gen) self.genesis = _make_libp2p_connection(data_dir=temp_dir_gen, port=DEFAULT_PORT) self.multiplexer_genesis = Multiplexer([self.genesis], protocols=[DefaultMessage]) self.log_files.append(self.genesis.node.log_file) self.multiplexer_genesis.connect() self.multiplexers.append(self.multiplexer_genesis) genesis_peer = self.genesis.node.multiaddrs[0] temp_dir_1 = os.path.join(self.t, "temp_dir_1") os.mkdir(temp_dir_1) self.connection1 = _make_libp2p_connection(data_dir=temp_dir_1, port=DEFAULT_PORT + 1, entry_peers=[genesis_peer]) self.multiplexer1 = Multiplexer([self.connection1], protocols=[DefaultMessage]) self.log_files.append(self.connection1.node.log_file) self.multiplexer1.connect() self.multiplexers.append(self.multiplexer1) self.connection_key = make_crypto(DEFAULT_LEDGER) temp_dir_2 = os.path.join(self.t, "temp_dir_2") os.mkdir(temp_dir_2) self.connection2 = _make_libp2p_connection( data_dir=temp_dir_2, port=DEFAULT_PORT + 2, entry_peers=[genesis_peer], agent_key=self.connection_key, ) self.multiplexer2 = Multiplexer([self.connection2], protocols=[DefaultMessage]) self.log_files.append(self.connection2.node.log_file) self.multiplexer2.connect() self.multiplexers.append(self.multiplexer2)