Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion gas/evaluation/generative_challenge_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,10 @@ def init_fastapi(self):
self.api = FastAPI()
self.router = APIRouter()

# httptools streams the body — handler is invoked on headers, so now is
# captured before the upload
verifier = get_verifier(
self.wallet, self.metagraph, no_force_validator_permit=True
self.wallet, self.metagraph, no_force_validator_permit=True,
)

self.router.add_api_route(
Expand All @@ -444,6 +446,7 @@ def init_fastapi(self):
port=self.config.neuron.callback_port,
log_level="info",
loop="asyncio",
http="httptools",
)
self.fast_api = FastAPIThreadedServer(config=fast_config)
self.fast_api.start()
Expand Down
24 changes: 14 additions & 10 deletions gas/protocol/epistula.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ def generate_header(


def verify_signature(
signature, body: bytes, timestamp, uuid, signed_for, signed_by, now
signature, body: bytes, timestamp, uuid, signed_for, signed_by, now,
allowed_delta_ms: int = 15000,
) -> Optional[Annotated[str, "Error Message"]]:
if not isinstance(signature, str):
return "Invalid Signature"
Expand All @@ -77,12 +78,11 @@ def verify_signature(
return "Invalid uuid"
if not isinstance(body, bytes):
return "Body is not of type bytes"
ALLOWED_DELTA_MS = 15000
keypair = Keypair(ss58_address=signed_by)
if timestamp + ALLOWED_DELTA_MS < now:
if timestamp + allowed_delta_ms < now:
staleness_ms = now - timestamp
staleness_seconds = staleness_ms / 1000.0
return f"Request is too stale: {staleness_seconds:.1f}s old (limit: {ALLOWED_DELTA_MS/1000.0}s)"
return f"Request is too stale: {staleness_seconds:.1f}s old (limit: {allowed_delta_ms/1000.0}s)"
message = f"{sha256(body).hexdigest()}.{uuid}.{timestamp}.{signed_for}"
verified = keypair.verify(message, signature)
if not verified:
Expand All @@ -102,10 +102,10 @@ async def _verify_request(
request: Request,
wallet: bt.Wallet,
metagraph: bt.Metagraph,
no_force_validator_permit: bool
no_force_validator_permit: bool,
allowed_delta_ms: int = 15000,
):
now = round(time.time() * 1000)

signed_by = request.headers.get("Epistula-Signed-By")
signed_for = request.headers.get("Epistula-Signed-For")
client_ip = request.client.host if request.client else "unknown"
Expand All @@ -115,7 +115,7 @@ async def _verify_request(
raise HTTPException(
status_code=400, detail="Bad Request, message is not intended for self"
)

if signed_by not in metagraph.hotkeys:
bt.logging.error(f"Signer not in metagraph: {signed_by} (IP: {client_ip})")
raise HTTPException(status_code=401, detail="Signer not in metagraph")
Expand All @@ -138,6 +138,7 @@ async def _verify_request(
signed_for,
signed_by,
now,
allowed_delta_ms=allowed_delta_ms,
)

if err:
Expand All @@ -149,25 +150,28 @@ async def determine_epistula_version_and_verify(
request: Request,
wallet: bt.Wallet,
metagraph: bt.Metagraph,
no_force_validator_permit: bool
no_force_validator_permit: bool,
allowed_delta_ms: int = 15000,
):
version = request.headers.get("Epistula-Version")
if version == EPISTULA_VERSION:
await _verify_request(request, wallet, metagraph, no_force_validator_permit)
await _verify_request(request, wallet, metagraph, no_force_validator_permit, allowed_delta_ms)
return
raise HTTPException(status_code=400, detail="Unknown Epistula version")


def get_verifier(
wallet: bt.Wallet,
metagraph: bt.Metagraph,
no_force_validator_permit: bool = False
no_force_validator_permit: bool = False,
allowed_delta_ms: int = 15000,
):
async def verifier(request: Request):
await determine_epistula_version_and_verify(
request,
wallet,
metagraph,
no_force_validator_permit,
allowed_delta_ms,
)
return verifier
1 change: 1 addition & 0 deletions neurons/generator/miner.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ def run(self):
port=self.config.axon.port,
log_level="info",
loop="asyncio",
http="httptools",
)
self.fast_api = FastAPIThreadedServer(config=fast_config)
self.fast_api.start()
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ dependencies = [
"opencv-python==4.11.0.86",
"wandb==0.19.9",
"uvicorn==0.27.1",
"httptools>=0.6.0",
"python-multipart==0.0.22",
"peft==0.17.0",
"aiohttp>=3.10.2",
Expand Down