Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): support almanac contract v2.0.0 #560

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
5 changes: 3 additions & 2 deletions python/src/uagents/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ def sign_digest(self, digest: bytes) -> str:
"""
return self._identity.sign_digest(digest)

def sign_registration(self) -> str:
def sign_registration(self, current_time: int) -> str:
"""
Sign the registration data for Almanac contract.
Returns:
Expand All @@ -702,7 +702,8 @@ def sign_registration(self) -> str:
assert self._almanac_contract.address is not None
return self._identity.sign_registration(
str(self._almanac_contract.address),
self._almanac_contract.get_sequence(self.address),
current_time,
str(self.wallet.address()),
)

def update_endpoints(self, endpoints: List[AgentEndpoint]):
Expand Down
5 changes: 3 additions & 2 deletions python/src/uagents/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"fetch1mezzhfj7qgveewzwzdk6lz5sae4dunpmmsjr9u7z0tpmdsae8zmquq3y0y"
)
TESTNET_CONTRACT_ALMANAC = (
"fetch1tjagw8g8nn4cwuw00cf0m5tl4l6wfw9c0ue507fhx9e3yrsck8zs0l3q4w"
"fetch135h26ys2nwqealykzey532gamw4l4s07aewpwc0cyd8z6m92vyhsplf0vp"
)
MAINNET_CONTRACT_NAME_SERVICE = (
"fetch1479lwv5vy8skute5cycuz727e55spkhxut0valrcm38x9caa2x8q99ef0q"
Expand All @@ -26,12 +26,13 @@
REGISTRATION_UPDATE_INTERVAL_SECONDS = 3600
REGISTRATION_RETRY_INTERVAL_SECONDS = 60
AVERAGE_BLOCK_INTERVAL = 6
ALMANAC_CONTRACT_VERSION = "1.0.0"
ALMANAC_CONTRACT_VERSION = "2.0.0"

AGENTVERSE_URL = "https://agentverse.ai"
ALMANAC_API_URL = AGENTVERSE_URL + "/v1/almanac"
ALMANAC_API_TIMEOUT_SECONDS = 1.0
ALMANAC_API_MAX_RETRIES = 10
ALMANAC_REGISTRATION_WAIT = 100
MAILBOX_POLL_INTERVAL_SECONDS = 1.0

WALLET_MESSAGING_POLL_INTERVAL_SECONDS = 2.0
Expand Down
8 changes: 7 additions & 1 deletion python/src/uagents/crypto/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,18 @@ def sign_digest(self, digest: bytes) -> str:
"""Sign the provided digest."""
return _encode_bech32("sig", self._sk.sign_digest(digest))

def sign_registration(self, contract_address: str, sequence: int) -> str:
def sign_registration(
self,
contract_address: str,
sequence: int,
wallet_address: str,
) -> str:
"""Sign the registration data for the Almanac contract."""
hasher = hashlib.sha256()
hasher.update(encode_length_prefixed(contract_address))
hasher.update(encode_length_prefixed(self.address))
hasher.update(encode_length_prefixed(sequence))
hasher.update(encode_length_prefixed(wallet_address))
return self.sign_digest(hasher.digest())

def sign_arbitrary(self, data: bytes) -> Tuple[str, str]:
Expand Down
4 changes: 2 additions & 2 deletions python/src/uagents/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ async def register(
protocols: List[str],
endpoints: List[AgentEndpoint],
signature: str,
current_time: int,
):
"""
Register an agent with the Almanac contract.
Expand All @@ -309,12 +310,11 @@ async def register(

transaction = Transaction()

sequence = self.get_sequence(agent_address)
almanac_msg = self.get_registration_msg(
protocols=protocols,
endpoints=endpoints,
signature=signature,
sequence=sequence,
sequence=current_time,
address=agent_address,
)

Expand Down
12 changes: 9 additions & 3 deletions python/src/uagents/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import hashlib
import json
import logging
import time
from abc import ABC, abstractmethod
from typing import Any, Dict, List, Optional, Union

Expand All @@ -15,6 +16,7 @@
ALMANAC_API_MAX_RETRIES,
ALMANAC_API_TIMEOUT_SECONDS,
ALMANAC_API_URL,
ALMANAC_REGISTRATION_WAIT,
REGISTRATION_FEE,
REGISTRATION_UPDATE_INTERVAL_SECONDS,
)
Expand Down Expand Up @@ -209,14 +211,17 @@ async def register(

self._logger.info("Registering on almanac contract...")

signature = self._sign_registration(agent_address)
current_time = int(time.time()) - ALMANAC_REGISTRATION_WAIT

signature = self._sign_registration(current_time)
await self._almanac_contract.register(
self._ledger,
self._wallet,
agent_address,
protocols,
endpoints,
signature,
current_time,
)
self._logger.info("Registering on almanac contract...complete")
else:
Expand All @@ -225,7 +230,7 @@ async def register(
def _get_balance(self) -> int:
return self._ledger.query_bank_balance(Address(self._wallet.address()))

def _sign_registration(self, agent_address: str) -> str:
def _sign_registration(self, current_time: int) -> str:
"""
Sign the registration data for Almanac contract.

Expand All @@ -239,7 +244,8 @@ def _sign_registration(self, agent_address: str) -> str:
assert self._almanac_contract.address is not None
return self._identity.sign_registration(
str(self._almanac_contract.address),
self._almanac_contract.get_sequence(agent_address),
current_time,
str(self._wallet.address()),
)


Expand Down
11 changes: 8 additions & 3 deletions python/tests/test_agent_registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@
EXPECTED_FUNDS = Coin(amount="8640000000000000", denom="atestfet")


def generate_digest(agent_address: str, contract_address: str, sequence: int) -> bytes:
def generate_digest(
agent_address: str, contract_address: str, sequence: int, wallet_address: str
) -> bytes:
hasher = hashlib.sha256()
hasher.update(encode_length_prefixed(contract_address))
hasher.update(encode_length_prefixed(agent_address))
hasher.update(encode_length_prefixed(sequence))
hasher.update(encode_length_prefixed(wallet_address))
return hasher.digest()


Expand Down Expand Up @@ -112,15 +115,17 @@ async def test_mock_almanac_registration(self):
endpoint=["http://localhost:8000/submit"], seed="almanact_reg_agent"
)

signature = agent.sign_registration()
signature = agent.sign_registration(0)

almanac_msg = agent._almanac_contract.get_registration_msg(
list(agent.protocols.keys()), agent._endpoints, signature, 0, agent.address
)

contract_address = str(agent._almanac_contract.address)

digest = generate_digest(agent.address, contract_address, 0)
digest = generate_digest(
agent.address, contract_address, 0, str(agent.wallet.address())
)

self.assertEqual(
mock_almanac_registration(almanac_msg, digest),
Expand Down
Loading