def setup_class(cls): """Set up the test class.""" cls.crypto1 = Crypto() cls.crypto2 = Crypto() cls.mailbox1 = OEFMailBox(cls.crypto1.public_key, oef_addr="127.0.0.1", oef_port=10000) cls.mailbox2 = OEFMailBox(cls.crypto2.public_key, oef_addr="127.0.0.1", oef_port=10000) cls.mailbox1.connect() cls.mailbox2.connect()
def setup_class(cls): """Test that if the controller agent does not receive enough registrations, it stops.""" tac_parameters = TACParameters(min_nb_agents=2, start_time=datetime.datetime.now(), registration_timeout=5) cls.controller_agent = ControllerAgent('controller', '127.0.0.1', 10000, tac_parameters, NullMonitor()) cls.controller_agent.mailbox.connect() job = Thread(target=cls.controller_agent.start) job.start() cls.crypto = Crypto() cls.agent1 = TOEFAgent(cls.crypto.public_key, oef_addr='127.0.0.1', oef_port=10000) cls.agent1.connect() tac_msg = TACMessage(tac_type=TACMessage.Type.REGISTER, agent_name='agent_name') tac_bytes = TACSerializer().encode(tac_msg) cls.agent1.outbox.put_message( to=cls.controller_agent.crypto.public_key, sender=cls.crypto.public_key, protocol_id=TACMessage.protocol_id, message=tac_bytes) job.join()
def test_react(): """Tests income messages.""" node = LocalNode() agent_name = "MyAgent" private_key_pem_path = os.path.join(CUR_PATH, "data", "priv.pem") crypto = Crypto(private_key_pem_path=private_key_pem_path) public_key = crypto.public_key mailbox = MailBox(OEFLocalConnection(public_key, node)) msg = DefaultMessage(type=DefaultMessage.Type.BYTES, content=b"hello") message_bytes = DefaultSerializer().encode(msg) envelope = Envelope(to="Agent1", sender=public_key, protocol_id="default", message=message_bytes) agent = AEA(agent_name, mailbox, private_key_pem_path=private_key_pem_path, directory=str(Path(CUR_PATH, "data", "dummy_aea"))) t = Thread(target=agent.start) try: t.start() agent.mailbox.inbox._queue.put(envelope) time.sleep(1) handler = agent.resources \ .handler_registry.fetch_by_skill('default', "dummy") assert envelope in handler.handled_envelopes, \ "The envelope is not inside the handled_envelopes." finally: agent.stop() t.join()
def test_connection(network_node): """Test that a mailbox can connect to the OEF.""" crypto = Crypto() mailbox = OEFMailBox(crypto.public_key, oef_addr="127.0.0.1", oef_port=10000) mailbox.connect() mailbox.disconnect()
def _create_temporary_private_key() -> bytes: """ Create a temporary private key. :return: the private key in pem format. """ crypto = Crypto() pem = crypto._private_key.private_bytes(Encoding.PEM, PrivateFormat.TraditionalOpenSSL, NoEncryption()) # type: ignore return pem
def test_initialization_from_existing_private_key(): """Test that the initialization from an existing private key works correctly.""" private_key_pem_path = ROOT_DIR + "/tests/data/priv.pem" private_key = load_pem_private_key( open(private_key_pem_path, "rb").read(), None, default_backend()) c = Crypto(private_key_pem_path=private_key_pem_path) expected_public_key = private_key.public_key().public_bytes( encoding=Encoding.PEM, format=PublicFormat.SubjectPublicKeyInfo) actual_public_key = c.public_key_pem assert expected_public_key == actual_public_key
def test_handle(): """Tests handle method of an agent.""" node = LocalNode() agent_name = "MyAgent" private_key_pem_path = os.path.join(CUR_PATH, "data", "priv.pem") crypto = Crypto(private_key_pem_path=private_key_pem_path) public_key = crypto.public_key mailbox = MailBox(OEFLocalConnection(public_key, node)) msg = DefaultMessage(type=DefaultMessage.Type.BYTES, content=b"hello") message_bytes = DefaultSerializer().encode(msg) envelope = Envelope(to="Agent1", sender=public_key, protocol_id="unknown_protocol", message=message_bytes) agent = AEA(agent_name, mailbox, private_key_pem_path=private_key_pem_path, directory=str(Path(CUR_PATH, "data", "dummy_aea"))) t = Thread(target=agent.start) try: t.start() agent.mailbox.inbox._queue.put(envelope) env = agent.mailbox.outbox._queue.get(block=True, timeout=5.0) assert env.protocol_id == "default", \ "The envelope is not the expected protocol (Unsupported protocol)" # DECODING ERROR msg = "hello".encode("utf-8") envelope = Envelope(to=public_key, sender=public_key, protocol_id='default', message=msg) agent.mailbox.inbox._queue.put(envelope) # UNSUPPORTED SKILL msg = FIPASerializer().encode( FIPAMessage(performative=FIPAMessage.Performative.ACCEPT, message_id=0, dialogue_id=0, destination=public_key, target=1)) envelope = Envelope(to=public_key, sender=public_key, protocol_id="fipa", message=msg) agent.mailbox.inbox._queue.put(envelope) finally: agent.stop() t.join()
def transfer( self, crypto: Crypto, destination_address: Address, amount: int, tx_fee: int, tx_nonce: str, chain_id: int = 1, **kwargs, ) -> Optional[str]: """ Submit a transfer transaction to the ledger. :param crypto: the crypto object associated to the payer. :param destination_address: the destination address of the payee. :param amount: the amount of wealth to be transferred. :param tx_fee: the transaction fee. :param tx_nonce: verifies the authenticity of the tx :param chain_id: the Chain ID of the Ethereum transaction. Default is 1 (i.e. mainnet). :return: tx digest if present, otherwise None """ tx_digest = None nonce = self._try_get_transaction_count(crypto.address) if nonce is None: return tx_digest transaction = { "nonce": nonce, "chainId": chain_id, "to": destination_address, "value": amount, "gas": tx_fee, "gasPrice": self._api.toWei(self._gas_price, GAS_ID), "data": tx_nonce, } gas_estimate = self._try_get_gas_estimate(transaction) if gas_estimate is None or tx_fee <= gas_estimate: # pragma: no cover logger.warning( "Need to increase tx_fee in the configs to cover the gas consumption of the transaction. Estimated gas consumption is: {}.".format( gas_estimate ) ) return tx_digest signed_transaction = crypto.sign_transaction(transaction) tx_digest = self.send_signed_transaction(tx_signed=signed_transaction,) return tx_digest
def _try_validate_private_key_pem_path(private_key_pem_path: str) -> None: """ Try to validate a private key. :param private_key_pem_path: the path to the private key. :return: None :raises: an exception if the private key is invalid. """ try: Crypto(private_key_pem_path=private_key_pem_path) except ValueError: logger.error("This is not a valid private key file: '{}'".format( private_key_pem_path)) exit(-1)
def setup_class(cls): """ Set the test up. Steps: - Register a service - Check that the registration worked. """ cls.crypto1 = Crypto() cls.mailbox1 = OEFMailBox(cls.crypto1.public_key, oef_addr="127.0.0.1", oef_port=10000) cls.mailbox1.connect() cls.request_id = 1 cls.foo_datamodel = DataModel( "foo", [Attribute("bar", int, True, "A bar attribute.")]) cls.desc = Description({"bar": 1}, data_model=cls.foo_datamodel) msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=cls.request_id, service_description=cls.desc, service_id="") msg_bytes = OEFSerializer().encode(msg) cls.mailbox1.outbox.put_message(to=DEFAULT_OEF, sender=cls.crypto1.public_key, protocol_id=OEFMessage.protocol_id, message=msg_bytes) time.sleep(1.0) cls.request_id += 1 search_request = OEFMessage( oef_type=OEFMessage.Type.SEARCH_SERVICES, id=cls.request_id, query=Query([Constraint("bar", ConstraintType("==", 1))], model=cls.foo_datamodel)) cls.mailbox1.outbox.put_message( to=DEFAULT_OEF, sender=cls.crypto1.public_key, protocol_id=OEFMessage.protocol_id, message=OEFSerializer().encode(search_request)) envelope = cls.mailbox1.inbox.get(block=True, timeout=5.0) search_result = OEFSerializer().decode(envelope.message) assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT assert search_result.get("id") == cls.request_id assert search_result.get("agents") == [cls.crypto1.public_key]
def run(ctx: Context, connection_name: str): """Run the agent.""" _try_to_load_agent_config(ctx) agent_name = cast(str, ctx.agent_config.agent_name) private_key_pem_path = cast(str, ctx.agent_config.private_key_pem_path) if private_key_pem_path == "": private_key_pem_path = _create_temporary_private_key_pem_path() else: _try_validate_private_key_pem_path(private_key_pem_path) crypto = Crypto(private_key_pem_path=private_key_pem_path) public_key = crypto.public_key connection_name = ctx.agent_config.default_connection if connection_name is None else connection_name _try_to_load_protocols(ctx) try: connection = _setup_connection(connection_name, public_key, ctx) except AEAConfigException as e: logger.error(str(e)) exit(-1) return logger.debug("Installing all the dependencies...") for d in ctx.get_dependencies(): logger.debug("Installing {}...".format(d)) try: subp = subprocess.Popen( [sys.executable, "-m", "pip", "install", d]) subp.wait(30.0) except Exception: logger.error( "An error occurred while installing {}. Stopping...".format(d)) exit(-1) mailbox = MailBox(connection) agent = AEA(agent_name, mailbox, private_key_pem_path=private_key_pem_path, directory=str(Path("."))) try: agent.start() except KeyboardInterrupt: logger.info("Interrupted.") except Exception as e: logger.exception(e) finally: agent.stop()
def test_act(): """Tests the act function of the AeA.""" node = LocalNode() agent_name = "MyAgent" private_key_pem_path = os.path.join(CUR_PATH, "data", "priv.pem") crypto = Crypto(private_key_pem_path=private_key_pem_path) public_key = crypto.public_key mailbox = MailBox(OEFLocalConnection(public_key, node)) agent = AEA(agent_name, mailbox, private_key_pem_path=private_key_pem_path, directory=str(Path(CUR_PATH, "data", "dummy_aea"))) t = Thread(target=agent.start) try: t.start() time.sleep(1) behaviour = agent.resources.behaviour_registry.fetch("dummy") assert behaviour[0].nb_act_called > 0, "Act() wasn't called" finally: agent.stop() t.join()
def __init__(self, name: str, private_key_pem_path: Optional[str] = None, timeout: float = 1.0, debug: bool = False) -> None: """ Instantiate the agent. :param name: the name of the agent :param private_key_pem_path: the path to the private key of the agent. :param timeout: the time in (fractions of) seconds to time out an agent between act and react :param debug: if True, run the agent in debug mode. :return: None """ self._name = name self._crypto = Crypto(private_key_pem_path=private_key_pem_path) self._liveness = Liveness() self._timeout = timeout self.debug = debug self.mailbox = None # type: Optional[MailBox]
# distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # ------------------------------------------------------------------------------ """ Generate a private key to be used for the Trading Agent Competition. It prints the key in PEM format to the specified file. """ from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption import argparse from aea.crypto.base import Crypto parser = argparse.ArgumentParser("generate_private_key", description=__doc__) parser.add_argument("out_file", type=str, help="Where to save the private key.") if __name__ == '__main__': args = parser.parse_args() crypto = Crypto() pem = crypto._private_key.private_bytes(Encoding.PEM, PrivateFormat.TraditionalOpenSSL, NoEncryption()) # type: ignore file = open(args.out_file, "wb") file.write(pem) file.close()
def transfer( self, crypto: Crypto, destination_address: Address, amount: int, tx_fee: int, tx_nonce: str = "", denom: str = "testfet", account_number: int = 0, sequence: int = 0, gas: int = 80000, memo: str = "", sync_mode: str = "sync", chain_id: str = "aea-testnet", **kwargs, ) -> Optional[str]: """ Submit a transfer transaction to the ledger. :param crypto: the crypto object associated to the payer. :param destination_address: the destination address of the payee. :param amount: the amount of wealth to be transferred. :param tx_fee: the transaction fee. :param tx_nonce: verifies the authenticity of the tx :param chain_id: the Chain ID of the Ethereum transaction. Default is 1 (i.e. mainnet). :return: tx digest if present, otherwise None """ result = self._try_get_account_number_and_sequence(crypto.address) if result is not None: account_number, sequence = result transfer = { "type": "cosmos-sdk/MsgSend", "value": { "from_address": crypto.address, "to_address": destination_address, "amount": [{ "denom": denom, "amount": str(amount) }], }, } tx = { "account_number": str(account_number), "sequence": str(sequence), "chain_id": chain_id, "fee": { "gas": str(gas), "amount": [{ "denom": denom, "amount": str(tx_fee) }], }, "memo": memo, "msgs": [transfer], } signature = crypto.sign_transaction(tx) base64_pbk = base64.b64encode(bytes.fromhex( crypto.public_key)).decode("utf-8") pushable_tx = { "tx": { "msg": [transfer], "fee": { "gas": str(gas), "amount": [{ "denom": denom, "amount": str(tx_fee) }], }, "memo": memo, "signatures": [{ "signature": signature, "pub_key": { "type": "tendermint/PubKeySecp256k1", "value": base64_pbk, }, "account_number": str(account_number), "sequence": str(sequence), }], }, "mode": sync_mode, } # TODO retrieve, gas dynamically tx_digest = self.send_signed_transaction(tx_signed=pushable_tx) return tx_digest
def test_example(network_node): """Test the mailbox.""" crypto1 = Crypto() crypto2 = Crypto() mailbox1 = OEFMailBox(crypto1.public_key, "127.0.0.1", 10000) mailbox2 = OEFMailBox(crypto2.public_key, "127.0.0.1", 10000) mailbox1.connect() mailbox2.connect() msg = DefaultMessage(type=DefaultMessage.Type.BYTES, content=b"hello") msg_bytes = DefaultSerializer().encode(msg) mailbox1.outbox.put( Envelope( to=crypto2.public_key, sender=crypto1.public_key, protocol_id=DefaultMessage.protocol_id, message=msg_bytes, )) msg = FIPAMessage( message_id=0, dialogue_id=0, target=0, performative=FIPAMessage.Performative.CFP, query=None, ) msg_bytes = FIPASerializer().encode(msg) mailbox1.outbox.put( Envelope( to=crypto2.public_key, sender=crypto1.public_key, protocol_id=FIPAMessage.protocol_id, message=msg_bytes, )) msg = FIPAMessage( message_id=0, dialogue_id=0, target=0, performative=FIPAMessage.Performative.PROPOSE, proposal=[], ) msg_bytes = FIPASerializer().encode(msg) mailbox1.outbox.put( Envelope( to=crypto2.public_key, sender=crypto1.public_key, protocol_id=FIPAMessage.protocol_id, message=msg_bytes, )) msg = FIPAMessage( message_id=0, dialogue_id=0, target=0, performative=FIPAMessage.Performative.ACCEPT, ) msg_bytes = FIPASerializer().encode(msg) mailbox1.outbox.put( Envelope( to=crypto2.public_key, sender=crypto1.public_key, protocol_id=FIPAMessage.protocol_id, message=msg_bytes, )) msg = FIPAMessage( message_id=0, dialogue_id=0, target=0, performative=FIPAMessage.Performative.DECLINE, ) msg_bytes = FIPASerializer().encode(msg) mailbox1.outbox.put( Envelope( to=crypto2.public_key, sender=crypto1.public_key, protocol_id=FIPAMessage.protocol_id, message=msg_bytes, )) time.sleep(5.0) envelope = mailbox2.inbox.get(block=True, timeout=2.0) msg = DefaultSerializer().decode(envelope.message) assert msg.get("content") == b"hello" envelope = mailbox2.inbox.get(block=True, timeout=2.0) msg = FIPASerializer().decode(envelope.message) assert envelope.protocol_id == "fipa" assert msg.get("performative") == FIPAMessage.Performative.CFP envelope = mailbox2.inbox.get(block=True, timeout=2.0) msg = FIPASerializer().decode(envelope.message) assert envelope.protocol_id == "fipa" assert msg.get("performative") == FIPAMessage.Performative.PROPOSE envelope = mailbox2.inbox.get(block=True, timeout=2.0) msg = FIPASerializer().decode(envelope.message) assert envelope.protocol_id == "fipa" assert msg.get("performative") == FIPAMessage.Performative.ACCEPT envelope = mailbox2.inbox.get(block=True, timeout=2.0) msg = FIPASerializer().decode(envelope.message) assert envelope.protocol_id == "fipa" assert msg.get("performative") == FIPAMessage.Performative.DECLINE mailbox1.disconnect() mailbox2.disconnect()