Skip to content

Commit

Permalink
refactor(platform): updates to StreamInfo and ClusterInfo models (#127)
Browse files Browse the repository at this point in the history
* refactor(platform): remove configuration from `platform.create_cluster`

* refactor(runner): make small adjustment to task kill logic

* refactor(platform): add StreamInfo to client types

* fix(platform): HMAC params in wrong order

* feat(platform): add expiration to ClusterInfo record

* refactor(tests): fix encoding test, add fuzzing
  • Loading branch information
fubuloubu authored Oct 4, 2024
1 parent 01c3f77 commit 832fabe
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 18 deletions.
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"pytest>=6.0", # Core testing package
"pytest-xdist", # Multi-process runner
"pytest-cov", # Coverage analyzer plugin
# "hypothesis>=6.2.0,<7.0", # Strategy-based fuzzer
"hypothesis", # Strategy-based fuzzer
"hypothesis-jsonschema", # Generate strategies for pydantic models
],
"lint": [
"black>=24", # Auto-formatter and linter
Expand Down
1 change: 0 additions & 1 deletion silverback/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,6 @@ def new_cluster(
cluster = workspace_client.create_cluster(
cluster_name=cluster_name,
cluster_slug=cluster_slug,
configuration=configuration,
)
click.echo(f"{click.style('SUCCESS', fg='green')}: Created '{cluster.name}'")
# TODO: Pay for cluster via new stream
Expand Down
8 changes: 1 addition & 7 deletions silverback/cluster/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from .types import (
BotHealth,
BotInfo,
ClusterConfiguration,
ClusterHealth,
ClusterInfo,
ClusterState,
Expand Down Expand Up @@ -286,16 +285,11 @@ def create_cluster(
self,
cluster_slug: str | None = None,
cluster_name: str | None = None,
configuration: ClusterConfiguration = ClusterConfiguration(),
) -> ClusterInfo:
response = self.client.post(
"/clusters/",
params=dict(workspace=str(self.id)),
json=dict(
name=cluster_name,
slug=cluster_slug,
configuration=configuration.model_dump(),
),
json=dict(name=cluster_name, slug=cluster_slug),
)

handle_error_with_response(response)
Expand Down
11 changes: 10 additions & 1 deletion silverback/cluster/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from datetime import datetime
from typing import Annotated, Any

from ape.types import AddressType
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives.hmac import HMAC, hashes
from eth_pydantic_types import Address, HexBytes
Expand All @@ -12,7 +13,7 @@


def normalize_bytes(val: bytes, length: int = 16) -> bytes:
return b"\x00" * (length - len(val)) + val
return val + b"\x00" * (length - len(val))


class WorkspaceInfo(BaseModel):
Expand Down Expand Up @@ -269,6 +270,12 @@ def __str__(self) -> str:
return self.name.capitalize()


class StreamInfo(BaseModel):
chain_id: int
manager: AddressType
stream_id: int


class ClusterInfo(BaseModel):
# NOTE: Raw API object (gets exported)
id: uuid.UUID # NOTE: Keep this private, used as a temporary secret key for payment
Expand All @@ -278,6 +285,8 @@ class ClusterInfo(BaseModel):
name: str # User-friendly display name
slug: str # Shorthand name, for CLI and URI usage

expiration: datetime | None = None # NOTE: self-hosted clusters have no expiration

created: datetime # When the resource was first created
status: ResourceStatus
last_updated: datetime # Last time the resource was changed (upgrade, provisioning, etc.)
Expand Down
4 changes: 3 additions & 1 deletion silverback/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,9 @@ async def run(self):
logger.warning(f"Runtime error(s) detected, shutting down:\n{runtime_errors}")

# Cancel any still running
(task.cancel() for task in tasks_running)
for task in tasks_running:
task.cancel()

# NOTE: All listener tasks are shut down now

# Execute Silverback shutdown task(s) before shutting down the broker and app
Expand Down
26 changes: 19 additions & 7 deletions tests/test_cluster.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import uuid
from eth_utils import to_checksum_address
from hypothesis import given
from hypothesis import strategies as st
from hypothesis_jsonschema import from_schema

from silverback.cluster.types import ClusterConfiguration

CONFIG_SCHEMA = ClusterConfiguration.model_json_schema()

def test_hmac_signature():
config = ClusterConfiguration()
cluster_id = uuid.uuid4()
owner = "0x4838B106FCe9647Bdf1E7877BF73cE8B0BAD5f97"

@given( # type: ignore[call-overload]
cluster_id=st.uuids(version=4),
owner=st.binary(min_size=20, max_size=20).map(to_checksum_address),
config_dict=from_schema(CONFIG_SCHEMA),
)
def test_hmac_signature(cluster_id, owner, config_dict):
# NOTE: Ignore `version` fuzzed value
config_dict["version"] = 1
config = ClusterConfiguration(**config_dict)
product_code = config.get_product_code(owner, cluster_id)
# NOTE: There is a gap of empty bytes between 8-16
encoded_config, sig = product_code[:8], product_code[16:]
# NOTE: Ensure we can properly decode the encoded product code into a configuration
assert config == ClusterConfiguration.decode(product_code[:16])
assert config.validate_product_code(owner, product_code[16:], cluster_id)
assert config == ClusterConfiguration.decode(encoded_config)
assert config.validate_product_code(owner, sig, cluster_id)

0 comments on commit 832fabe

Please sign in to comment.