Skip to content

Commit

Permalink
Adds Schema for accepting minimum version as parameter and draft to h…
Browse files Browse the repository at this point in the history
…andle this parameter
  • Loading branch information
vzotova committed Aug 2, 2024
1 parent 07f7da5 commit f35724e
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 2 deletions.
18 changes: 18 additions & 0 deletions porter/fields/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
from base64 import b64decode, b64encode
import re

import click
from marshmallow import fields
Expand Down Expand Up @@ -108,3 +109,20 @@ def _deserialize(self, value, attr, data, **kwargs):
f"Unexpected object type, {type(result)}; expected {self.expected_type}")

return result


class VersionString(String):

def _serialize(self, value, attr, obj, **kwargs) -> str:
if (type(value) is not list or len(value) == 0 or len(value) > 3):
raise InvalidInputData(
f"Unexpected object type, {type(value)}; expected list[3]")

return ".".join(value)

def _deserialize(self, value, attr, data, **kwargs) -> list:
pattern = r'(\d+\.)?(\d+\.)?(\d+)'
match = re.findall(pattern, value)
if len(match) != 1:
raise InvalidInputData("Minimum version must have x.x.x format")
return match[0]
4 changes: 4 additions & 0 deletions porter/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ def get_ursulas(
include_ursulas: Optional[List[ChecksumAddress]] = None,
timeout: Optional[int] = None,
duration: Optional[int] = None,
min_version: Optional[str] = None,
) -> Dict:
ursulas_info = self.implementer.get_ursulas(
quantity=quantity,
exclude_ursulas=exclude_ursulas,
include_ursulas=include_ursulas,
timeout=timeout,
duration=duration,
min_version=min_version,
)

response_data = {"ursulas": ursulas_info} # list of UrsulaInfo objects
Expand Down Expand Up @@ -104,13 +106,15 @@ def bucket_sampling(
exclude_ursulas: Optional[List[ChecksumAddress]] = None,
timeout: Optional[int] = None,
duration: Optional[int] = None,
min_version: Optional[str] = None,
) -> Dict:
ursulas, block_number = self.implementer.bucket_sampling(
quantity=quantity,
random_seed=random_seed,
exclude_ursulas=exclude_ursulas,
timeout=timeout,
duration=duration,
min_version=min_version,
)

response_data = {"ursulas": ursulas, "block_number": block_number}
Expand Down
36 changes: 34 additions & 2 deletions porter/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,18 +155,40 @@ def _initialize_endpoints(eth_endpoint: str, polygon_endpoint: str):
):
BlockchainInterfaceFactory.initialize_interface(endpoint=polygon_endpoint)

@staticmethod
def _parse_version(version: Optional[str] = None) -> list:
if not version:
return [0, 0, 0]
parsed = version.split("\.")
if len(parsed) <= 1:
raise InvalidInputData("Minimum version must have x.x.x format")

Check failure on line 164 in porter/main.py

View workflow job for this annotation

GitHub Actions / ruff-lint

Ruff (F821)

porter/main.py:164:19: F821 Undefined name `InvalidInputData`
return parsed

@staticmethod
def _is_version_greater_or_equal(min_version: list, version: list) -> bool:
for i in version:
if (version[i] < min_version[i]):
return False
return True

def _get_ursula_version(self, ursula: Ursula) -> list:
response = self.network_middleware.client.get(node_or_sprout=ursula, path="status/?json=true")
return self._parse_version(response["version"])

def get_ursulas(
self,
quantity: int,
exclude_ursulas: Optional[Sequence[ChecksumAddress]] = None,
include_ursulas: Optional[Sequence[ChecksumAddress]] = None,
timeout: Optional[int] = None,
duration: Optional[int] = None,
min_version: Optional[str] = None,
) -> List[UrsulaInfo]:
timeout = self._configure_timeout(
"sampling", timeout, self.MAX_GET_URSULAS_TIMEOUT
)
duration = duration or 0
min_version_parsed = self._parse_version(min_version)

reservoir = self._make_reservoir(exclude_ursulas, include_ursulas, duration)
available_nodes_to_sample = len(reservoir.values) + len(reservoir.reservoir)
Expand All @@ -185,7 +207,11 @@ def get_ursula_info(ursula_address) -> Porter.UrsulaInfo:
ursula = self.known_nodes[ursula_address]
try:
# ensure node is up and reachable
self.network_middleware.ping(ursula)
# self.network_middleware.ping(ursula)
version = self._get_ursula_version(ursula)
if not self._is_version_greater_or_equal(min_version_parsed, version):
raise ValueError(f"Ursula ({ursula_address}) has too old version ({version})")

return Porter.UrsulaInfo(checksum_address=ursula_address,
uri=f"{ursula.rest_interface.formal_uri}",
encrypting_key=ursula.public_keys(DecryptingPower))
Expand Down Expand Up @@ -299,11 +325,13 @@ def bucket_sampling(
exclude_ursulas: Optional[Sequence[ChecksumAddress]] = None,
timeout: Optional[int] = None,
duration: Optional[int] = None,
min_version: Optional[str] = None,
) -> Tuple[List[ChecksumAddress], int]:
timeout = self._configure_timeout(
"bucket_sampling", timeout, self.MAX_BUCKET_SAMPLING_TIMEOUT
)
duration = duration or 0
min_version_parsed = self._parse_version(min_version)

if self.domain not in self._ALLOWED_DOMAINS_FOR_BUCKET_SAMPLING:
raise ValueError("Bucket sampling is only for TACo Mainnet")
Expand Down Expand Up @@ -418,7 +446,11 @@ def make_sure_ursula_is_online(ursula_address) -> ChecksumAddress:
ursula = self.known_nodes[ursula_address]
try:
# ensure node is up and reachable
self.network_middleware.ping(ursula)
# self.network_middleware.ping(ursula)
version = self._get_ursula_version(ursula)
if not self._is_version_greater_or_equal(min_version_parsed, version):
raise ValueError(f"Ursula ({ursula_address}) has too old version ({version})")

return ursula_address
except Exception as e:
message = f"Ursula ({ursula_address}) is unreachable: {str(e)}"
Expand Down
25 changes: 25 additions & 0 deletions porter/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
Integer,
NonNegativeInteger,
PositiveInteger,
VersionString,
StringList,
)
from porter.fields.exceptions import InvalidArgumentCombo, InvalidInputData
Expand Down Expand Up @@ -125,6 +126,18 @@ class GetUrsulas(BaseSchema):
),
)

min_version = VersionString(
required=False,
load_only=True,
click=click.option(
"--min-version",
"-mv",
help="Minimum acceptable version of Ursula",
type=click.STRING,
required=False,
),
)

# output
ursulas = marshmallow_fields.List(marshmallow_fields.Nested(UrsulaInfoSchema), dump_only=True)

Expand Down Expand Up @@ -369,6 +382,18 @@ class BucketSampling(BaseSchema):
),
)

min_version = VersionString(
required=False,
load_only=True,
click=click.option(
"--min-version",
"-mv",
help="Minimum acceptable version of Ursula",
type=click.STRING,
required=False,
),
)

# output
ursulas = marshmallow_fields.List(UrsulaChecksumAddress, dump_only=True)
block_number = marshmallow_fields.Int(dump_only=True)

0 comments on commit f35724e

Please sign in to comment.