enable full safety selection through api

This commit is contained in:
John Smith
2023-06-28 11:40:02 -04:00
parent fde70610cc
commit f1292694a2
13 changed files with 310 additions and 44 deletions

View File

@@ -16,14 +16,28 @@ from .conftest import server_info
@pytest.mark.asyncio
async def test_routing_contexts(api_connection: veilid.VeilidAPI):
rc = await api_connection.new_routing_context()
async with rc:
pass
rc = await api_connection.new_routing_context()
async with rc:
rcp = await rc.with_privacy(release=False)
async with rcp:
rcps = await rcp.with_sequencing(veilid.Sequencing.ENSURE_ORDERED, release=False)
async with rcps:
rcpscp = await rcps.with_custom_privacy(veilid.Stability.RELIABLE, release=False)
await rcpscp.release()
pass
rc = await (await api_connection.new_routing_context()).with_sequencing(veilid.Sequencing.ENSURE_ORDERED)
async with rc:
pass
rc = await (await api_connection.new_routing_context()).with_custom_privacy(
veilid.SafetySelection.safe(
veilid.SafetySpec(None, 2, veilid.Stability.RELIABLE, veilid.Sequencing.ENSURE_ORDERED)
))
await rc.release()
rc = await (await api_connection.new_routing_context()).with_custom_privacy(veilid.SafetySelection.unsafe(veilid.Sequencing.ENSURE_ORDERED))
await rc.release()
@pytest.mark.asyncio

View File

@@ -27,7 +27,7 @@ class RoutingContext(ABC):
pass
@abstractmethod
async def with_custom_privacy(self, stability: types.Stability, release = True) -> Self:
async def with_custom_privacy(self, safety_selection: types.SafetySelection, release = True) -> Self:
pass
@abstractmethod

View File

@@ -16,7 +16,7 @@ from .state import VeilidState, VeilidUpdate
from .types import (CryptoKey, CryptoKeyDistance, CryptoKind,
DHTRecordDescriptor, DHTSchema, HashDigest, KeyPair,
NewPrivateRouteResult, Nonce, OperationId, PublicKey,
RouteId, SecretKey, Sequencing, SharedSecret, Signature,
RouteId, SafetySelection, SecretKey, Sequencing, SharedSecret, Signature,
Stability, Timestamp, TypedKey, TypedKeyPair,
TypedSignature, ValueData, ValueSubkey, VeilidJSONEncoder,
VeilidVersion, urlsafe_b64decode_no_pad)
@@ -459,14 +459,14 @@ class _JsonRoutingContext(RoutingContext):
await self.release()
return self.__class__(self.api, new_rc_id)
async def with_custom_privacy(self, stability: Stability, release = True) -> Self:
async def with_custom_privacy(self, safety_selection: SafetySelection, release = True) -> Self:
new_rc_id = raise_api_result(
await self.api.send_ndjson_request(
Operation.ROUTING_CONTEXT,
validate=validate_rc_op,
rc_id=self.rc_id,
rc_op=RoutingContextOperation.WITH_CUSTOM_PRIVACY,
stability=stability,
safety_selection=safety_selection,
)
)
if release:

View File

@@ -224,7 +224,7 @@
"type": "object",
"required": [
"rc_op",
"stability"
"safety_selection"
],
"properties": {
"rc_op": {
@@ -233,8 +233,8 @@
"WithCustomPrivacy"
]
},
"stability": {
"$ref": "#/definitions/Stability"
"safety_selection": {
"$ref": "#/definitions/SafetySelection"
}
}
},
@@ -1566,6 +1566,77 @@
}
}
},
"SafetySelection": {
"description": "The choice of safety route to include in compiled routes",
"oneOf": [
{
"description": "Don't use a safety route, only specify the sequencing preference",
"type": "object",
"required": [
"Unsafe"
],
"properties": {
"Unsafe": {
"$ref": "#/definitions/Sequencing"
}
},
"additionalProperties": false
},
{
"description": "Use a safety route and parameters specified by a SafetySpec",
"type": "object",
"required": [
"Safe"
],
"properties": {
"Safe": {
"$ref": "#/definitions/SafetySpec"
}
},
"additionalProperties": false
}
]
},
"SafetySpec": {
"description": "Options for safety routes (sender privacy)",
"type": "object",
"required": [
"hop_count",
"sequencing",
"stability"
],
"properties": {
"hop_count": {
"description": "must be greater than 0",
"type": "integer",
"format": "uint",
"minimum": 0.0
},
"preferred_route": {
"description": "preferred safety route set id if it still exists",
"type": [
"string",
"null"
]
},
"sequencing": {
"description": "prefer connection-oriented sequenced protocols",
"allOf": [
{
"$ref": "#/definitions/Sequencing"
}
]
},
"stability": {
"description": "prefer reliability over speed",
"allOf": [
{
"$ref": "#/definitions/Stability"
}
]
}
}
},
"Sequencing": {
"type": "string",
"enum": [

View File

@@ -67,6 +67,9 @@ class DHTSchemaKind(StrEnum):
DFLT = "DFLT"
SMPL = "SMPL"
class SafetySelectionKind(StrEnum):
UNSAFE = "Unsafe"
SAFE = "Safe"
####################################################################
@@ -357,7 +360,7 @@ class ValueData:
def __lt__(self, other):
if other is None:
return true
return True
if self.data < other.data:
return True
if self.data > other.data:
@@ -383,3 +386,61 @@ class ValueData:
def to_json(self) -> dict:
return self.__dict__
####################################################################
class SafetySpec:
preferred_route: Optional[RouteId]
hop_count: int
stability: Stability
sequencing: Sequencing
def __init__(self, preferred_route: Optional[RouteId], hop_count: int, stability: Stability, sequencing: Sequencing):
self.preferred_route = preferred_route
self.hop_count = hop_count
self.stability = stability
self.sequencing = sequencing
@classmethod
def from_json(cls, j: dict) -> Self:
return cls(RouteId(j["preferred_route"]) if "preferred_route" in j else None,
j["hop_count"],
Stability(j["stability"]),
Sequencing(j["sequencing"]))
def to_json(self) -> dict:
return self.__dict__
class SafetySelection:
kind: SafetySelectionKind
def __init__(self, kind: SafetySelectionKind, **kwargs):
self.kind = kind
for k, v in kwargs.items():
setattr(self, k, v)
@classmethod
def unsafe(cls, sequencing: Sequencing) -> Self:
return cls(SafetySelectionKind.UNSAFE, sequencing=sequencing)
@classmethod
def safe(cls, safety_spec: SafetySpec) -> Self:
return cls(SafetySelectionKind.SAFE, safety_spec=safety_spec)
@classmethod
def from_json(cls, j: dict) -> Self:
if "Safe" in j:
return cls.safe(SafetySpec.from_json(j["Safe"]))
elif "Unsafe" in j:
return cls.unsafe(Sequencing(j["Unsafe"]))
raise Exception("Invalid SafetySelection")
def to_json(self) -> dict:
if self.kind == SafetySelectionKind.UNSAFE:
return {"Unsafe": self.sequencing }
elif self.kind == SafetySelectionKind.SAFE:
return {"Safe": self.safety_spec.to_json() }
else:
raise Exception("Invalid SafetySelection")