mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-10-01 01:26:08 -04:00
python work
This commit is contained in:
parent
cd04a8a74c
commit
df0b06bf3c
@ -230,7 +230,7 @@ struct NodeInfo @0xe125d847e3f9f419 {
|
|||||||
outboundProtocols @1 :ProtocolTypeSet; # protocols that can go outbound
|
outboundProtocols @1 :ProtocolTypeSet; # protocols that can go outbound
|
||||||
addressTypes @2 :AddressTypeSet; # address types supported
|
addressTypes @2 :AddressTypeSet; # address types supported
|
||||||
envelopeSupport @3 :List(UInt8); # supported rpc envelope/receipt versions
|
envelopeSupport @3 :List(UInt8); # supported rpc envelope/receipt versions
|
||||||
cryptoSupport @4 :List(CryptoKind); # cryptography systems supported
|
cryptoSupport @4 :List( ); # cryptography systems supported
|
||||||
dialInfoDetailList @5 :List(DialInfoDetail); # inbound dial info details for this node
|
dialInfoDetailList @5 :List(DialInfoDetail); # inbound dial info details for this node
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,7 +534,8 @@ struct Answer @0xacacb8b6988c1058 {
|
|||||||
appCallA @2 :OperationAppCallA;
|
appCallA @2 :OperationAppCallA;
|
||||||
getValueA @3 :OperationGetValueA;
|
getValueA @3 :OperationGetValueA;
|
||||||
setValueA @4 :OperationSetValueA;
|
setValueA @4 :OperationSetValueA;
|
||||||
watchValueA @5 :OperationWatchValueA;
|
watchValueA @5 :OperationWatchValueA;
|
||||||
|
|
||||||
# #[cfg(feature="unstable-blockstore")]
|
# #[cfg(feature="unstable-blockstore")]
|
||||||
#supplyBlockA @6 :OperationSupplyBlockA;
|
#supplyBlockA @6 :OperationSupplyBlockA;
|
||||||
#findBlockA @7 :OperationFindBlockA;
|
#findBlockA @7 :OperationFindBlockA;
|
||||||
|
@ -1 +0,0 @@
|
|||||||
from .error import *
|
|
@ -1,11 +1,211 @@
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from .state import VeilidState
|
from typing import Self
|
||||||
|
|
||||||
|
from .state import *
|
||||||
|
from .config import *
|
||||||
|
from .error import *
|
||||||
|
from .types import *
|
||||||
|
|
||||||
|
class RoutingContext(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
async def with_privacy(self) -> Self:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def with_custom_privacy(self, stability: Stability) -> Self:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def with_sequencing(self, sequencing: Sequencing) -> Self:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def app_call(self, target: TypedKey | RouteId, request: bytes) -> bytes:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def app_message(self, target: TypedKey | RouteId, message: bytes):
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def create_dht_record(self, kind: CryptoKind, schema: DHTSchema) -> DHTRecordDescriptor:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def open_dht_record(self, key: TypedKey, writer: Optional[KeyPair]) -> DHTRecordDescriptor:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def close_dht_record(self, key: TypedKey):
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def delete_dht_record(self, key: TypedKey):
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def get_dht_value(self, key: TypedKey, subkey: ValueSubkey, force_refresh: bool) -> Optional[ValueData]:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def set_dht_value(self, key: TypedKey, subkey: ValueSubkey, data: bytes) -> Optional[ValueData]:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def watch_dht_values(self, key: TypedKey, subkeys: list[(ValueSubkey, ValueSubkey)], expiration: Timestamp, count: int) -> Timestamp:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def cancel_dht_values(self, key: TypedKey, subkeys: list[(ValueSubkey, ValueSubkey)]) -> bool:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TableDBTransaction(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
async def commit(self):
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def rollback(self):
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def store(self, col: int, key: bytes, value: bytes):
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def delete(self, col: int, key: bytes):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class TableDB(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
async def get_column_count(self) -> int:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def get_keys(self, col: int) -> list[str]:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def transact(self) -> TableDBTransaction:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def store(self, col: int, key: bytes, value: bytes):
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def load(self, col: int, key: bytes) -> Optional[bytes]:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def delete(self, col: int, key: bytes) -> Optional[bytes]:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class CryptoSystem(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
async def cached_dh(self, key: PublicKey, secret: SecretKey) -> SharedSecret:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def compute_dh(self, key: PublicKey, secret: SecretKey) -> SharedSecret:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def random_bytes(self, len: int) -> bytes:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def default_salt_length(self) -> int:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def hash_password(self, password: bytes, salt: bytes) -> str:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def verify_password(self, password: bytes, password_hash: str) -> bool:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def derive_shared_secret(self, password: bytes, salt: bytes) -> SharedSecret:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def random_nonce(self) -> Nonce:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def random_shared_secret(self) -> SharedSecret:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def generate_key_pair(self) -> KeyPair:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def generate_hash(self, data: bytes) -> HashDigest:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def validate_key_pair(self, key: PublicKey, secret: SecretKey) -> bool:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def validate_hash(self, data: bytes, hash_digest: HashDigest) -> bool:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def distance(self, key1: CryptoKey, key2: CryptoKey) -> CryptoKeyDistance:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def sign(self, key: PublicKey, secret: SecretKey, data: bytes) -> Signature:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def verify(self, key: PublicKey, data: bytes, signature: Signature):
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def aead_overhead(self) -> int:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def decrypt_aead(self, body: bytes, nonce: Nonce, shared_secret: SharedSecret, associated_data: Optional[bytes]) -> bytes:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def encrypt_aead(self, body: bytes, nonce: Nonce, shared_secret: SharedSecret, associated_data: Optional[bytes]) -> bytes:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def crypt_no_auth(self, body: bytes, nonce: Nonce, shared_secret: SharedSecret) -> bytes:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class VeilidAPI(ABC):
|
class VeilidAPI(ABC):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def control(self, args: list[str]) -> str:
|
async def control(self, args: list[str]) -> str:
|
||||||
pass
|
pass
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_state(self) -> VeilidState:
|
async def get_state(self) -> VeilidState:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def attach(self):
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def detach(self):
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def new_private_route(self) -> NewPrivateRouteResult:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def new_custom_private_route(self, kinds: list[CryptoKind], stability: Stability, sequencing: Sequencing) -> NewPrivateRouteResult:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def import_remote_private_route(self, blob: bytes) -> RouteId:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def release_private_route(self, route_id: RouteId):
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def app_call_reply(self, call_id: OperationId, message: bytes):
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def new_routing_context(self) -> RoutingContext:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def open_table_db(self, name: str, column_count: int) -> TableDB:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def delete_table_db(self, name: str):
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def get_crypto_system(self, kind: CryptoKind) -> CryptoSystem:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def best_crypto_system(self) -> CryptoSystem:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def verify_signatures(self, node_ids: list[TypedKey], data: bytes, signatures: list[TypedSignature]) -> list[TypedKey]:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def generate_signatures(self, data: bytes, key_pairs: list[TypedKeyPair]) -> list[TypedSignature]:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def generate_key_pair(self, kind: CryptoKind) -> list[TypedKeyPair]:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def now(self) -> Timestamp:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def debug(self, command: str) -> str:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def veilid_version_string(self) -> str:
|
||||||
|
pass
|
||||||
|
@abstractmethod
|
||||||
|
async def veilid_version(self) -> VeilidVersion:
|
||||||
pass
|
pass
|
||||||
|
|
@ -1,5 +1,6 @@
|
|||||||
from typing import Self, Optional
|
from typing import Self, Optional
|
||||||
from enum import StrEnum
|
from enum import StrEnum
|
||||||
|
from json import dumps
|
||||||
|
|
||||||
class VeilidConfigLogLevel(StrEnum):
|
class VeilidConfigLogLevel(StrEnum):
|
||||||
OFF = 'Off'
|
OFF = 'Off'
|
||||||
@ -38,6 +39,8 @@ class VeilidConfigCapabilities:
|
|||||||
j['protocol_accept_ws'],
|
j['protocol_accept_ws'],
|
||||||
j['protocol_connect_wss'],
|
j['protocol_connect_wss'],
|
||||||
j['protocol_accept_wss'])
|
j['protocol_accept_wss'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
class VeilidConfigProtectedStore:
|
class VeilidConfigProtectedStore:
|
||||||
allow_insecure_fallback: bool
|
allow_insecure_fallback: bool
|
||||||
@ -61,6 +64,8 @@ class VeilidConfigProtectedStore:
|
|||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
return VeilidConfigProtectedStore(j['allow_insecure_fallback'], j['always_use_insecure_storage'],
|
return VeilidConfigProtectedStore(j['allow_insecure_fallback'], j['always_use_insecure_storage'],
|
||||||
j['directory'], j['delete'], j['device_encryption_key_password'], j['new_device_encryption_key_password'])
|
j['directory'], j['delete'], j['device_encryption_key_password'], j['new_device_encryption_key_password'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
class VeilidConfigTableStore:
|
class VeilidConfigTableStore:
|
||||||
directory: str
|
directory: str
|
||||||
@ -73,6 +78,8 @@ class VeilidConfigTableStore:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
return VeilidConfigTableStore(j['directory'], j['delete'])
|
return VeilidConfigTableStore(j['directory'], j['delete'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
class VeilidConfigBlockStore:
|
class VeilidConfigBlockStore:
|
||||||
directory: str
|
directory: str
|
||||||
@ -85,6 +92,8 @@ class VeilidConfigBlockStore:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
return VeilidConfigBlockStore(j['directory'], j['delete'])
|
return VeilidConfigBlockStore(j['directory'], j['delete'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
class VeilidConfigRoutingTable:
|
class VeilidConfigRoutingTable:
|
||||||
node_id: list[str]
|
node_id: list[str]
|
||||||
@ -119,6 +128,8 @@ class VeilidConfigRoutingTable:
|
|||||||
j['limit_attached_strong'],
|
j['limit_attached_strong'],
|
||||||
j['limit_attached_good'],
|
j['limit_attached_good'],
|
||||||
j['limit_attached_weak'])
|
j['limit_attached_weak'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
|
||||||
class VeilidConfigRPC:
|
class VeilidConfigRPC:
|
||||||
@ -151,6 +162,286 @@ class VeilidConfigRPC:
|
|||||||
j['timeout_ms'],
|
j['timeout_ms'],
|
||||||
j['max_route_hop_count'],
|
j['max_route_hop_count'],
|
||||||
j['default_route_hop_count'])
|
j['default_route_hop_count'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
class VeilidConfigDHT:
|
||||||
|
max_find_node_count: int
|
||||||
|
resolve_node_timeout_ms: int
|
||||||
|
resolve_node_count: int
|
||||||
|
resolve_node_fanout: int
|
||||||
|
get_value_timeout_ms: int
|
||||||
|
get_value_count: int
|
||||||
|
get_value_fanout: int
|
||||||
|
set_value_timeout_ms: int
|
||||||
|
set_value_count: int
|
||||||
|
set_value_fanout: int
|
||||||
|
min_peer_count: int
|
||||||
|
min_peer_refresh_time_ms: int
|
||||||
|
validate_dial_info_receipt_time_ms: int
|
||||||
|
local_subkey_cache_size: int
|
||||||
|
local_max_subkey_cache_memory_mb: int
|
||||||
|
remote_subkey_cache_size: int
|
||||||
|
remote_max_records: int
|
||||||
|
remote_max_subkey_cache_memory_mb: int
|
||||||
|
remote_max_storage_space_mb: int
|
||||||
|
|
||||||
|
def __init__(self, max_find_node_count: int, resolve_node_timeout_ms: int, resolve_node_count: int,
|
||||||
|
resolve_node_fanout: int, get_value_timeout_ms: int, get_value_count: int, get_value_fanout: int,
|
||||||
|
set_value_timeout_ms: int, set_value_count: int, set_value_fanout: int,
|
||||||
|
min_peer_count: int, min_peer_refresh_time_ms: int, validate_dial_info_receipt_time_ms: int,
|
||||||
|
local_subkey_cache_size: int, local_max_subkey_cache_memory_mb: int,
|
||||||
|
remote_subkey_cache_size: int, remote_max_records: int, remote_max_subkey_cache_memory_mb: int, remote_max_storage_space_mb: int):
|
||||||
|
|
||||||
|
self.max_find_node_count = max_find_node_count
|
||||||
|
self.resolve_node_timeout_ms =resolve_node_timeout_ms
|
||||||
|
self.resolve_node_count = resolve_node_count
|
||||||
|
self.resolve_node_fanout = resolve_node_fanout
|
||||||
|
self.get_value_timeout_ms = get_value_timeout_ms
|
||||||
|
self.get_value_count = get_value_count
|
||||||
|
self.get_value_fanout = get_value_fanout
|
||||||
|
self.set_value_timeout_ms = set_value_timeout_ms
|
||||||
|
self.set_value_count = set_value_count
|
||||||
|
self.set_value_fanout = set_value_fanout
|
||||||
|
self.min_peer_count = min_peer_count
|
||||||
|
self.min_peer_refresh_time_ms = min_peer_refresh_time_ms
|
||||||
|
self.validate_dial_info_receipt_time_ms = validate_dial_info_receipt_time_ms
|
||||||
|
self.local_subkey_cache_size = local_subkey_cache_size
|
||||||
|
self.local_max_subkey_cache_memory_mb = local_max_subkey_cache_memory_mb
|
||||||
|
self.remote_subkey_cache_size = remote_subkey_cache_size
|
||||||
|
self.remote_max_records = remote_max_records
|
||||||
|
self.remote_max_subkey_cache_memory_mb = remote_max_subkey_cache_memory_mb
|
||||||
|
self.remote_max_storage_space_mb = remote_max_storage_space_mb
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
return VeilidConfigDHT(
|
||||||
|
j['max_find_node_count'],
|
||||||
|
j['resolve_node_timeout_ms'],
|
||||||
|
j['resolve_node_count'],
|
||||||
|
j['resolve_node_fanout'],
|
||||||
|
j['get_value_timeout_ms'],
|
||||||
|
j['get_value_count'],
|
||||||
|
j['get_value_fanout'],
|
||||||
|
j['set_value_timeout_ms'],
|
||||||
|
j['set_value_count'],
|
||||||
|
j['set_value_fanout'],
|
||||||
|
j['min_peer_count'],
|
||||||
|
j['min_peer_refresh_time_ms'],
|
||||||
|
j['validate_dial_info_receipt_time_ms'],
|
||||||
|
j['local_subkey_cache_size'],
|
||||||
|
j['local_max_subkey_cache_memory_mb'],
|
||||||
|
j['remote_subkey_cache_size'],
|
||||||
|
j['remote_max_records'],
|
||||||
|
j['remote_max_subkey_cache_memory_mb'],
|
||||||
|
j['remote_max_storage_space_mb'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
class VeilidConfigTLS:
|
||||||
|
certificate_path: str
|
||||||
|
private_key_path: str
|
||||||
|
connection_initial_timeout_ms: int
|
||||||
|
|
||||||
|
def __init__(self, certificate_path: str, private_key_path: str, connection_initial_timeout_ms: int):
|
||||||
|
self.certificate_path = certificate_path
|
||||||
|
self.private_key_path = private_key_path
|
||||||
|
self.connection_initial_timeout_ms = connection_initial_timeout_ms
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
return VeilidConfigTLS(
|
||||||
|
j['certificate_path'],
|
||||||
|
j['private_key_path'],
|
||||||
|
j['connection_initial_timeout_ms'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
class VeilidConfigHTTPS:
|
||||||
|
enabled: bool
|
||||||
|
listen_address: str
|
||||||
|
path: str
|
||||||
|
url: Optional[str]
|
||||||
|
|
||||||
|
def __init__(self, enabled: bool, listen_address: str, path: str, url: Optional[str]):
|
||||||
|
self.enabled = enabled
|
||||||
|
self.listen_address = listen_address
|
||||||
|
self.path = path
|
||||||
|
self.url = url
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
return VeilidConfigHTTPS(
|
||||||
|
j['enabled'],
|
||||||
|
j['listen_address'],
|
||||||
|
j['path'],
|
||||||
|
j['url'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
class VeilidConfigHTTP:
|
||||||
|
enabled: bool
|
||||||
|
listen_address: str
|
||||||
|
path: str
|
||||||
|
url: Optional[str]
|
||||||
|
|
||||||
|
def __init__(self, enabled: bool, listen_address: str, path: str, url: Optional[str]):
|
||||||
|
self.enabled = enabled
|
||||||
|
self.listen_address = listen_address
|
||||||
|
self.path = path
|
||||||
|
self.url = url
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
return VeilidConfigHTTP(
|
||||||
|
j['enabled'],
|
||||||
|
j['listen_address'],
|
||||||
|
j['path'],
|
||||||
|
j['url'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
class VeilidConfigApplication:
|
||||||
|
https: VeilidConfigHTTPS
|
||||||
|
http: VeilidConfigHTTP
|
||||||
|
|
||||||
|
def __init__(self, https: VeilidConfigHTTPS, http: VeilidConfigHTTP):
|
||||||
|
self.https = https
|
||||||
|
self.http = http
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
return VeilidConfigApplication(
|
||||||
|
VeilidConfigHTTPS.from_json(j['https']),
|
||||||
|
VeilidConfigHTTP.from_json(j['http']))
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
|
||||||
|
class VeilidConfigUDP:
|
||||||
|
enabled: bool
|
||||||
|
socket_pool_size: int
|
||||||
|
listen_address: str
|
||||||
|
public_address: Optional[str]
|
||||||
|
|
||||||
|
def __init__(self, enabled: bool, socket_pool_size: int, listen_address: str, public_address: Optional[str]):
|
||||||
|
self.enabled = enabled
|
||||||
|
self.socket_pool_size = socket_pool_size
|
||||||
|
self.listen_address = listen_address
|
||||||
|
self.public_address = public_address
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
return VeilidConfigUDP(
|
||||||
|
j['enabled'],
|
||||||
|
j['socket_pool_size'],
|
||||||
|
j['listen_address'],
|
||||||
|
j['public_address'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
class VeilidConfigTCP:
|
||||||
|
connect: bool
|
||||||
|
listen: bool
|
||||||
|
max_connections: int
|
||||||
|
listen_address: str
|
||||||
|
public_address: Optional[str]
|
||||||
|
|
||||||
|
def __init__(self, connect: bool, listen: bool, max_connections: int, listen_address: str, public_address: Optional[str]):
|
||||||
|
self.connect = connect
|
||||||
|
self.listen = listen
|
||||||
|
self.max_connections = max_connections
|
||||||
|
self.listen_address = listen_address
|
||||||
|
self.public_address = public_address
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
return VeilidConfigTCP(
|
||||||
|
j['connect'],
|
||||||
|
j['listen'],
|
||||||
|
j['max_connections'],
|
||||||
|
j['listen_address'],
|
||||||
|
j['public_address'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
class VeilidConfigWS:
|
||||||
|
connect: bool
|
||||||
|
listen: bool
|
||||||
|
max_connections: int
|
||||||
|
listen_address: str
|
||||||
|
path: str
|
||||||
|
url: Optional[str]
|
||||||
|
|
||||||
|
def __init__(self, connect: bool, listen: bool, max_connections: int, listen_address: str, path: str, url: Optional[str]):
|
||||||
|
self.connect = connect
|
||||||
|
self.listen = listen
|
||||||
|
self.max_connections = max_connections
|
||||||
|
self.listen_address = listen_address
|
||||||
|
self.path = path
|
||||||
|
self.url = url
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
return VeilidConfigWS(
|
||||||
|
j['connect'],
|
||||||
|
j['listen'],
|
||||||
|
j['max_connections'],
|
||||||
|
j['listen_address'],
|
||||||
|
j['path'],
|
||||||
|
j['url'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
class VeilidConfigWSS:
|
||||||
|
connect: bool
|
||||||
|
listen: bool
|
||||||
|
max_connections: int
|
||||||
|
listen_address: str
|
||||||
|
path: str
|
||||||
|
url: Optional[str]
|
||||||
|
|
||||||
|
def __init__(self, connect: bool, listen: bool, max_connections: int, listen_address: str, path: str, url: Optional[str]):
|
||||||
|
self.connect = connect
|
||||||
|
self.listen = listen
|
||||||
|
self.max_connections = max_connections
|
||||||
|
self.listen_address = listen_address
|
||||||
|
self.path = path
|
||||||
|
self.url = url
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
return VeilidConfigWSS(
|
||||||
|
j['connect'],
|
||||||
|
j['listen'],
|
||||||
|
j['max_connections'],
|
||||||
|
j['listen_address'],
|
||||||
|
j['path'],
|
||||||
|
j['url'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
class VeilidConfigProtocol:
|
||||||
|
udp: VeilidConfigUDP
|
||||||
|
tcp: VeilidConfigTCP
|
||||||
|
ws: VeilidConfigWS
|
||||||
|
wss: VeilidConfigWSS
|
||||||
|
|
||||||
|
def __init__(self, udp: VeilidConfigUDP, tcp: VeilidConfigTCP, ws: VeilidConfigWS, wss: VeilidConfigWSS):
|
||||||
|
self.udp = udp
|
||||||
|
self.tcp = tcp
|
||||||
|
self.ws = ws
|
||||||
|
self.wss = wss
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
return VeilidConfigProtocol(
|
||||||
|
VeilidConfigUDP.from_json(j['udp']),
|
||||||
|
VeilidConfigTCP.from_json(j['tcp']),
|
||||||
|
VeilidConfigWS.from_json(j['ws']),
|
||||||
|
VeilidConfigWSS.from_json(j['wss']))
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
|
||||||
class VeilidConfigNetwork:
|
class VeilidConfigNetwork:
|
||||||
@ -221,6 +512,8 @@ class VeilidConfigNetwork:
|
|||||||
VeilidConfigTLS.from_json(j['tls']),
|
VeilidConfigTLS.from_json(j['tls']),
|
||||||
VeilidConfigApplication.from_json(j['application']),
|
VeilidConfigApplication.from_json(j['application']),
|
||||||
VeilidConfigProtocol.from_json(j['protocol']))
|
VeilidConfigProtocol.from_json(j['protocol']))
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
class VeilidConfig:
|
class VeilidConfig:
|
||||||
program_name: str
|
program_name: str
|
||||||
@ -245,10 +538,14 @@ class VeilidConfig:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
return VeilidConfig(j['program_name'], j['namespace'],
|
return VeilidConfig(j['program_name'], j['namespace'],
|
||||||
VeilidConfigCapabilities.from_json(j['capabilities']),
|
VeilidConfigCapabilities.from_json(j['capabilities']),
|
||||||
VeilidConfigProtectedStore.from_json(j['protected_store']),
|
VeilidConfigProtectedStore.from_json(j['protected_store']),
|
||||||
VeilidConfigTableStore.from_json(j['table_store']),
|
VeilidConfigTableStore.from_json(j['table_store']),
|
||||||
VeilidConfigBlockStore.from_json(j['block_store']),
|
VeilidConfigBlockStore.from_json(j['block_store']),
|
||||||
VeilidConfigNetwork.from_json(j['network']))
|
VeilidConfigNetwork.from_json(j['network']))
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
from typing import Self
|
from typing import Self, Any
|
||||||
|
|
||||||
class VeilidAPIError(Exception):
|
class VeilidAPIError(Exception):
|
||||||
"""Veilid API error exception base class"""
|
"""Veilid API error exception base class"""
|
||||||
@ -131,3 +131,12 @@ class VeilidAPIErrorGeneric(VeilidAPIError):
|
|||||||
def __init__(self, message: str):
|
def __init__(self, message: str):
|
||||||
super().__init__("Generic")
|
super().__init__("Generic")
|
||||||
self.message = message
|
self.message = message
|
||||||
|
|
||||||
|
|
||||||
|
def raise_api_result(api_result: dict) -> Any:
|
||||||
|
if "value" in api_result:
|
||||||
|
return api_result["value"]
|
||||||
|
elif "error" in api_result:
|
||||||
|
raise VeilidAPIError.from_json(api_result["error"])
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid format for ApiResult")
|
314
veilid-python/veilid_python/json_api.py
Normal file
314
veilid-python/veilid_python/json_api.py
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
import json;
|
||||||
|
import asyncio;
|
||||||
|
from typing import Callable, Awaitable
|
||||||
|
|
||||||
|
from .api import *;
|
||||||
|
from .state import *
|
||||||
|
from .config import *
|
||||||
|
from .error import *
|
||||||
|
from .types import *
|
||||||
|
from .operations import *
|
||||||
|
|
||||||
|
class _JsonRoutingContext(RoutingContext):
|
||||||
|
api: VeilidAPI
|
||||||
|
rc_id: int
|
||||||
|
|
||||||
|
def __init__(self, api: VeilidAPI, rc_id: int):
|
||||||
|
self.api = api
|
||||||
|
self.rc_id = rc_id
|
||||||
|
|
||||||
|
async def with_privacy(self) -> Self:
|
||||||
|
new_rc_id = raise_api_result(await self.send_ndjson_request(Operation.ROUTING_CONTEXT,
|
||||||
|
rc_id = self.rc_id,
|
||||||
|
rc_op = RoutingContextOperation.WITH_PRIVACY))
|
||||||
|
return _JsonRoutingContext(self.api, new_rc_id)
|
||||||
|
|
||||||
|
async def with_custom_privacy(self, stability: Stability) -> Self:
|
||||||
|
new_rc_id = raise_api_result(await self.send_ndjson_request(Operation.ROUTING_CONTEXT,
|
||||||
|
rc_id = self.rc_id,
|
||||||
|
rc_op = RoutingContextOperation.WITH_CUSTOM_PRIVACY,
|
||||||
|
stability = stability))
|
||||||
|
return _JsonRoutingContext(self.api, new_rc_id)
|
||||||
|
async def with_sequencing(self, sequencing: Sequencing) -> Self:
|
||||||
|
new_rc_id = raise_api_result(await self.send_ndjson_request(Operation.ROUTING_CONTEXT,
|
||||||
|
rc_id = self.rc_id,
|
||||||
|
rc_op = RoutingContextOperation.WITH_SEQUENCING,
|
||||||
|
sequencing = sequencing))
|
||||||
|
return _JsonRoutingContext(self.api, new_rc_id)
|
||||||
|
async def app_call(self, target: TypedKey | RouteId, request: bytes) -> bytes:
|
||||||
|
return urlsafe_b64decode_no_pad(raise_api_result(await self.send_ndjson_request(Operation.ROUTING_CONTEXT,
|
||||||
|
rc_id = self.rc_id,
|
||||||
|
rc_op = RoutingContextOperation.APP_CALL,
|
||||||
|
target = target,
|
||||||
|
request = request)))
|
||||||
|
async def app_message(self, target: TypedKey | RouteId, message: bytes):
|
||||||
|
raise_api_result(await self.send_ndjson_request(Operation.ROUTING_CONTEXT,
|
||||||
|
rc_id = self.rc_id,
|
||||||
|
rc_op = RoutingContextOperation.APP_MESSAGE,
|
||||||
|
target = target,
|
||||||
|
message = message))
|
||||||
|
async def create_dht_record(self, kind: CryptoKind, schema: DHTSchema) -> DHTRecordDescriptor:
|
||||||
|
return DHTRecordDescriptor.from_json(raise_api_result(await self.send_ndjson_request(Operation.ROUTING_CONTEXT,
|
||||||
|
rc_id = self.rc_id,
|
||||||
|
rc_op = RoutingContextOperation.CREATE_DHT_RECORD,
|
||||||
|
kind = kind,
|
||||||
|
schema = schema)))
|
||||||
|
async def open_dht_record(self, key: TypedKey, writer: Optional[KeyPair]) -> DHTRecordDescriptor:
|
||||||
|
pass
|
||||||
|
async def close_dht_record(self, key: TypedKey):
|
||||||
|
pass
|
||||||
|
async def delete_dht_record(self, key: TypedKey):
|
||||||
|
pass
|
||||||
|
async def get_dht_value(self, key: TypedKey, subkey: ValueSubkey, force_refresh: bool) -> Optional[ValueData]:
|
||||||
|
pass
|
||||||
|
async def set_dht_value(self, key: TypedKey, subkey: ValueSubkey, data: bytes) -> Optional[ValueData]:
|
||||||
|
pass
|
||||||
|
async def watch_dht_values(self, key: TypedKey, subkeys: list[(ValueSubkey, ValueSubkey)], expiration: Timestamp, count: int) -> Timestamp:
|
||||||
|
pass
|
||||||
|
async def cancel_dht_values(self, key: TypedKey, subkeys: list[(ValueSubkey, ValueSubkey)]) -> bool:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class _JsonTableDBTransaction(TableDBTransaction):
|
||||||
|
async def commit(self):
|
||||||
|
pass
|
||||||
|
async def rollback(self):
|
||||||
|
pass
|
||||||
|
async def store(self, col: int, key: bytes, value: bytes):
|
||||||
|
pass
|
||||||
|
async def delete(self, col: int, key: bytes):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class _JsonTableDB(TableDB):
|
||||||
|
async def get_column_count(self) -> int:
|
||||||
|
pass
|
||||||
|
async def get_keys(self, col: int) -> list[str]:
|
||||||
|
pass
|
||||||
|
async def transact(self) -> TableDBTransaction:
|
||||||
|
pass
|
||||||
|
async def store(self, col: int, key: bytes, value: bytes):
|
||||||
|
pass
|
||||||
|
async def load(self, col: int, key: bytes) -> Optional[bytes]:
|
||||||
|
pass
|
||||||
|
async def delete(self, col: int, key: bytes) -> Optional[bytes]:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class _JsonCryptoSystem(CryptoSystem):
|
||||||
|
async def cached_dh(self, key: PublicKey, secret: SecretKey) -> SharedSecret:
|
||||||
|
pass
|
||||||
|
async def compute_dh(self, key: PublicKey, secret: SecretKey) -> SharedSecret:
|
||||||
|
pass
|
||||||
|
async def random_bytes(self, len: int) -> bytes:
|
||||||
|
pass
|
||||||
|
async def default_salt_length(self) -> int:
|
||||||
|
pass
|
||||||
|
async def hash_password(self, password: bytes, salt: bytes) -> str:
|
||||||
|
pass
|
||||||
|
async def verify_password(self, password: bytes, password_hash: str) -> bool:
|
||||||
|
pass
|
||||||
|
async def derive_shared_secret(self, password: bytes, salt: bytes) -> SharedSecret:
|
||||||
|
pass
|
||||||
|
async def random_nonce(self) -> Nonce:
|
||||||
|
pass
|
||||||
|
async def random_shared_secret(self) -> SharedSecret:
|
||||||
|
pass
|
||||||
|
async def generate_key_pair(self) -> KeyPair:
|
||||||
|
pass
|
||||||
|
async def generate_hash(self, data: bytes) -> HashDigest:
|
||||||
|
pass
|
||||||
|
async def validate_key_pair(self, key: PublicKey, secret: SecretKey) -> bool:
|
||||||
|
pass
|
||||||
|
async def validate_hash(self, data: bytes, hash_digest: HashDigest) -> bool:
|
||||||
|
pass
|
||||||
|
async def distance(self, key1: CryptoKey, key2: CryptoKey) -> CryptoKeyDistance:
|
||||||
|
pass
|
||||||
|
async def sign(self, key: PublicKey, secret: SecretKey, data: bytes) -> Signature:
|
||||||
|
pass
|
||||||
|
async def verify(self, key: PublicKey, data: bytes, signature: Signature):
|
||||||
|
pass
|
||||||
|
async def aead_overhead(self) -> int:
|
||||||
|
pass
|
||||||
|
async def decrypt_aead(self, body: bytes, nonce: Nonce, shared_secret: SharedSecret, associated_data: Optional[bytes]) -> bytes:
|
||||||
|
pass
|
||||||
|
async def encrypt_aead(self, body: bytes, nonce: Nonce, shared_secret: SharedSecret, associated_data: Optional[bytes]) -> bytes:
|
||||||
|
pass
|
||||||
|
async def crypt_no_auth(self, body: bytes, nonce: Nonce, shared_secret: SharedSecret) -> bytes:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class _JsonVeilidAPI(VeilidAPI):
|
||||||
|
reader: asyncio.StreamReader
|
||||||
|
writer: asyncio.StreamWriter
|
||||||
|
update_callback: Callable[[VeilidUpdate], Awaitable]
|
||||||
|
handle_recv_messages_task: Optional[asyncio.Task]
|
||||||
|
# Shared Mutable State
|
||||||
|
lock: asyncio.Lock
|
||||||
|
next_id: int
|
||||||
|
in_flight_requests: dict
|
||||||
|
|
||||||
|
def __init__(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter, update_callback: Callable[[VeilidUpdate], Awaitable]):
|
||||||
|
self.reader = reader
|
||||||
|
self.writer = writer
|
||||||
|
self.update_callback = update_callback
|
||||||
|
self.handle_recv_messages_task = None
|
||||||
|
self.lock = asyncio.Lock()
|
||||||
|
self.next_id = 1
|
||||||
|
self.in_flight_requests = dict()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def connect(host: str, port: int, update_callback: Callable[[VeilidUpdate], Awaitable]) -> Self:
|
||||||
|
reader, writer = await asyncio.open_connection(host, port)
|
||||||
|
veilid_api = _JsonVeilidAPI(reader, writer, update_callback)
|
||||||
|
veilid_api.handle_recv_messages_task = asyncio.create_task(veilid_api.handle_recv_messages(), name = "JsonVeilidAPI.handle_recv_messages")
|
||||||
|
return veilid_api
|
||||||
|
|
||||||
|
async def handle_recv_message_response(self, j: dict):
|
||||||
|
id = j['id']
|
||||||
|
await self.lock.acquire()
|
||||||
|
try:
|
||||||
|
# Get and remove the in-flight request
|
||||||
|
reqfuture = self.in_flight_requests.pop(id, None)
|
||||||
|
finally:
|
||||||
|
self.lock.release()
|
||||||
|
# Resolve the request's future to the response json
|
||||||
|
reqfuture.set_result(j)
|
||||||
|
|
||||||
|
async def handle_recv_messages(self):
|
||||||
|
# Read lines until we're done
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
linebytes = await self.reader.readline()
|
||||||
|
if not linebytes.endswith(b'\n'):
|
||||||
|
break
|
||||||
|
|
||||||
|
# Parse line as ndjson
|
||||||
|
j = json.loads(linebytes.strip())
|
||||||
|
|
||||||
|
# Process the message
|
||||||
|
if j['type'] == "Response":
|
||||||
|
await self.handle_recv_message_response(j)
|
||||||
|
elif j['type'] == "Update":
|
||||||
|
await self.update_callback(VeilidUpdate.from_json(j))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
self.reader = None
|
||||||
|
self.writer.close()
|
||||||
|
await self.writer.wait_closed()
|
||||||
|
self.writer = None
|
||||||
|
|
||||||
|
async def allocate_request_future(self, id: int) -> asyncio.Future:
|
||||||
|
reqfuture = asyncio.get_running_loop().create_future()
|
||||||
|
|
||||||
|
await self.lock.acquire()
|
||||||
|
try:
|
||||||
|
self.in_flight_requests[id] = reqfuture
|
||||||
|
finally:
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
|
return reqfuture
|
||||||
|
|
||||||
|
async def cancel_request_future(self, id: int):
|
||||||
|
await self.lock.acquire()
|
||||||
|
try:
|
||||||
|
reqfuture = self.in_flight_requests.pop(id, None)
|
||||||
|
reqfuture.cancel()
|
||||||
|
finally:
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
|
async def send_ndjson_request(self, op: Operation, **kwargs) -> dict:
|
||||||
|
|
||||||
|
# Get next id
|
||||||
|
await self.lock.acquire()
|
||||||
|
try:
|
||||||
|
id = self.next_id
|
||||||
|
self.next_id += 1
|
||||||
|
finally:
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
|
# Make NDJSON string for request
|
||||||
|
req = { "id": id, "op": op }
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
setattr(req, k, v)
|
||||||
|
reqstr = VeilidJSONEncoder.dumps(req) + "\n"
|
||||||
|
reqbytes = reqstr.encode()
|
||||||
|
|
||||||
|
# Allocate future for request
|
||||||
|
reqfuture = await self.allocate_request_future(id)
|
||||||
|
|
||||||
|
# Send to socket
|
||||||
|
try:
|
||||||
|
self.writer.write(reqbytes)
|
||||||
|
await self.writer.drain()
|
||||||
|
finally:
|
||||||
|
# Send failed, release future
|
||||||
|
self.cancel_request_future(id)
|
||||||
|
|
||||||
|
# Wait for response
|
||||||
|
response = await reqfuture
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
async def control(self, args: list[str]) -> str:
|
||||||
|
return raise_api_result(await self.send_ndjson_request(Operation.CONTROL, args = args))
|
||||||
|
async def get_state(self) -> VeilidState:
|
||||||
|
return VeilidState.from_json(raise_api_result(await self.send_ndjson_request(Operation.GET_STATE)))
|
||||||
|
async def attach(self):
|
||||||
|
raise_api_result(await self.send_ndjson_request(Operation.ATTACH))
|
||||||
|
async def detach(self):
|
||||||
|
raise_api_result(await self.send_ndjson_request(Operation.DETACH))
|
||||||
|
async def new_private_route(self) -> NewPrivateRouteResult:
|
||||||
|
return NewPrivateRouteResult.from_json(raise_api_result(await self.send_ndjson_request(Operation.NEW_PRIVATE_ROUTE)))
|
||||||
|
async def new_custom_private_route(self, kinds: list[CryptoKind], stability: Stability, sequencing: Sequencing) -> NewPrivateRouteResult:
|
||||||
|
return NewPrivateRouteResult.from_json(raise_api_result(
|
||||||
|
await self.send_ndjson_request(Operation.NEW_CUSTOM_PRIVATE_ROUTE,
|
||||||
|
kinds = kinds,
|
||||||
|
stability = stability,
|
||||||
|
sequencing = sequencing)
|
||||||
|
))
|
||||||
|
async def import_remote_private_route(self, blob: bytes) -> RouteId:
|
||||||
|
return RouteId(raise_api_result(
|
||||||
|
await self.send_ndjson_request(Operation.IMPORT_REMOTE_PRIVATE_ROUTE,
|
||||||
|
blob = blob)
|
||||||
|
))
|
||||||
|
async def release_private_route(self, route_id: RouteId):
|
||||||
|
raise_api_result(
|
||||||
|
await self.send_ndjson_request(Operation.RELEASE_PRIVATE_ROUTE,
|
||||||
|
route_id = route_id)
|
||||||
|
)
|
||||||
|
async def app_call_reply(self, call_id: OperationId, message: bytes):
|
||||||
|
raise_api_result(
|
||||||
|
await self.send_ndjson_request(Operation.APP_CALL_REPLY,
|
||||||
|
call_id = call_id,
|
||||||
|
message = message)
|
||||||
|
)
|
||||||
|
async def new_routing_context(self) -> RoutingContext:
|
||||||
|
rc_id = raise_api_result(await self.send_ndjson_request(Operation.NEW_ROUTING_CONTEXT))
|
||||||
|
return RoutingContext(self, rc_id)
|
||||||
|
|
||||||
|
async def open_table_db(self, name: str, column_count: int) -> TableDB:
|
||||||
|
pass
|
||||||
|
async def delete_table_db(self, name: str):
|
||||||
|
pass
|
||||||
|
async def get_crypto_system(self, kind: CryptoKind) -> CryptoSystem:
|
||||||
|
pass
|
||||||
|
async def best_crypto_system(self) -> CryptoSystem:
|
||||||
|
pass
|
||||||
|
async def verify_signatures(self, node_ids: list[TypedKey], data: bytes, signatures: list[TypedSignature]) -> list[TypedKey]:
|
||||||
|
pass
|
||||||
|
async def generate_signatures(self, data: bytes, key_pairs: list[TypedKeyPair]) -> list[TypedSignature]:
|
||||||
|
pass
|
||||||
|
async def generate_key_pair(self, kind: CryptoKind) -> list[TypedKeyPair]:
|
||||||
|
pass
|
||||||
|
async def now(self) -> Timestamp:
|
||||||
|
pass
|
||||||
|
async def debug(self, command: str) -> str:
|
||||||
|
pass
|
||||||
|
async def veilid_version_string(self) -> str:
|
||||||
|
pass
|
||||||
|
async def veilid_version(self) -> VeilidVersion:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def json_api_connect(host:str, port:int) -> VeilidAPI:
|
||||||
|
return _JsonVeilidAPI.connect(host, port)
|
91
veilid-python/veilid_python/operations.py
Normal file
91
veilid-python/veilid_python/operations.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
from enum import StrEnum
|
||||||
|
from typing import Self
|
||||||
|
|
||||||
|
class Operation(StrEnum):
|
||||||
|
CONTROL = "Control"
|
||||||
|
GET_STATE = "GetState"
|
||||||
|
ATTACH = "Attach"
|
||||||
|
DETACH = "Detach"
|
||||||
|
NEW_PRIVATE_ROUTE = "NewPrivateRoute"
|
||||||
|
NEW_CUSTOM_PRIVATE_ROUTE = "NewCustomPrivateRoute"
|
||||||
|
IMPORT_REMOTE_PRIVATE_ROUTE = "ImportRemotePrivateRoute"
|
||||||
|
RELEASE_PRIVATE_ROUTE = "ReleasePrivateRoute"
|
||||||
|
APP_CALL_REPLY = "AppCallReply"
|
||||||
|
NEW_ROUTING_CONTEXT = "NewRoutingContext"
|
||||||
|
ROUTING_CONTEXT = "RoutingContext"
|
||||||
|
OPEN_TABLE_DB = "OpenTableDb"
|
||||||
|
DELETE_TABLE_DB = "DeleteTableDb"
|
||||||
|
TABLE_DB = "TableDb"
|
||||||
|
TABLE_DB_TRANSACTION = "TableDbTransaction"
|
||||||
|
GET_CRYPTO_SYSTEM = "GetCryptoSystem"
|
||||||
|
BEST_CRYPTO_SYSTEM = "BestCryptoSystem"
|
||||||
|
CRYPTO_SYSTEM = "CryptoSystem"
|
||||||
|
VERIFY_SIGNATURES = "VerifySignatures"
|
||||||
|
GENERATE_SIGNATURES = "GenerateSignatures"
|
||||||
|
GENERATE_KEY_PAIR = "GenerateKeyPair"
|
||||||
|
NOW = "Now"
|
||||||
|
DEBUG = "Debug"
|
||||||
|
VEILID_VERSION_STRING = "VeilidVersionString"
|
||||||
|
VEILID_VERSION = "VeilidVersion"
|
||||||
|
|
||||||
|
class RoutingContextOperation(StrEnum):
|
||||||
|
INVALID_ID = "InvalidId"
|
||||||
|
RELEASE = "Release"
|
||||||
|
WITH_PRIVACY = "WithPrivacy"
|
||||||
|
WITH_CUSTOM_PRIVACY = "WithCustomPrivacy"
|
||||||
|
WITH_SEQUENCING = "WithSequencing"
|
||||||
|
APP_CALL = "AppCall"
|
||||||
|
APP_MESSAGE = "AppMessage"
|
||||||
|
CREATE_DHT_RECORD = "CreateDhtRecord"
|
||||||
|
OPEN_DHT_RECORD = "OpenDhtRecord"
|
||||||
|
CLOSE_DHT_RECORD = "CloseDhtRecord"
|
||||||
|
DELETE_DHT_RECORD = "DeleteDhtRecord"
|
||||||
|
GET_DHT_VALUE = "GetDhtValue"
|
||||||
|
SET_DHT_VALUE = "SetDhtValue"
|
||||||
|
WATCH_DHT_VALUES = "WatchDhtValues"
|
||||||
|
CANCEL_DHT_WATCH = "CancelDhtWatch"
|
||||||
|
|
||||||
|
class TableDbOperation(StrEnum):
|
||||||
|
INVALID_ID = "InvalidId"
|
||||||
|
RELEASE = "Release"
|
||||||
|
GET_COLUMN_COUNT = "GetColumnCount"
|
||||||
|
GET_KEYS = "GetKeys"
|
||||||
|
TRANSACT = "Transact"
|
||||||
|
STORE = "Store"
|
||||||
|
LOAD = "Load"
|
||||||
|
DELETE = "Delete"
|
||||||
|
|
||||||
|
class TableDBTransactionOperation(StrEnum):
|
||||||
|
INVALID_ID = "InvalidId"
|
||||||
|
COMMIT = "Commit"
|
||||||
|
ROLLBACK = "Rollback"
|
||||||
|
STORE = "Store"
|
||||||
|
DELETE = "Delete"
|
||||||
|
|
||||||
|
class CryptoSystemOperation(StrEnum):
|
||||||
|
INVALID_ID = "InvalidId"
|
||||||
|
RELEASE = "Release"
|
||||||
|
CACHED_DH = "CachedDh"
|
||||||
|
COMPUTE_DH = "ComputeDh"
|
||||||
|
RANDOM_BYTES = "RandomBytes"
|
||||||
|
DEFAULT_SALT_LENGTH = "DefaultSaltLength"
|
||||||
|
HASH_PASSWORD = "HashPassword"
|
||||||
|
VERIFY_PASSWORD = "VerifyPassword"
|
||||||
|
DERIVE_SHARED_SECRET = "DeriveSharedSecret"
|
||||||
|
RANDOM_NONCE = "RandomNonce"
|
||||||
|
RANDOM_SHARED_SECRET = "RandomSharedSecret"
|
||||||
|
GENERATE_KEY_PAIR = "GenerateKeyPair"
|
||||||
|
GENERATE_HASH = "GenerateHash"
|
||||||
|
VALIDATE_KEY_PAIR = "ValidateKeyPair"
|
||||||
|
VALIDATE_HASH = "ValidateHash"
|
||||||
|
DISTANCE = "Distance"
|
||||||
|
SIGN = "Sign"
|
||||||
|
VERIFY = "Verify"
|
||||||
|
AEAD_OVERHEAD = "AeadOverhead"
|
||||||
|
DECRYPT_AEAD = "DecryptAead"
|
||||||
|
ENCRYPT_AEAD = "EncryptAead"
|
||||||
|
CRYPT_NO_AUTH = "CryptNoAuth"
|
||||||
|
|
||||||
|
class RecvMessageType(StrEnum):
|
||||||
|
RESPONSE = "Response"
|
||||||
|
UPDATE = "Update"
|
@ -1,4 +0,0 @@
|
|||||||
class Request:
|
|
||||||
|
|
||||||
def __init__(self, id: int):
|
|
||||||
self.id = id
|
|
@ -1,7 +1,8 @@
|
|||||||
from typing import Self, Optional
|
from typing import Self, Optional
|
||||||
from enum import StrEnum
|
from enum import StrEnum
|
||||||
from .types import Timestamp, TimestampDuration, ByteCount
|
|
||||||
from .config import VeilidConfig
|
from .types import *
|
||||||
|
from .config import *
|
||||||
|
|
||||||
class AttachmentState(StrEnum):
|
class AttachmentState(StrEnum):
|
||||||
DETACHED = 'Detached'
|
DETACHED = 'Detached'
|
||||||
@ -25,6 +26,7 @@ class VeilidStateAttachment:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
return VeilidStateAttachment(
|
return VeilidStateAttachment(
|
||||||
AttachmentState(j['state']),
|
AttachmentState(j['state']),
|
||||||
j['public_internet_ready'],
|
j['public_internet_ready'],
|
||||||
@ -54,6 +56,7 @@ class RPCStats:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
return RPCStats(
|
return RPCStats(
|
||||||
j['messages_sent'],
|
j['messages_sent'],
|
||||||
j['messages_rcvd'],
|
j['messages_rcvd'],
|
||||||
@ -76,6 +79,7 @@ class LatencyStats:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
return LatencyStats(
|
return LatencyStats(
|
||||||
TimestampDuration(j['fastest']),
|
TimestampDuration(j['fastest']),
|
||||||
TimestampDuration(j['average']),
|
TimestampDuration(j['average']),
|
||||||
@ -96,6 +100,7 @@ class TransferStats:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
return TransferStats(
|
return TransferStats(
|
||||||
ByteCount(j['total']),
|
ByteCount(j['total']),
|
||||||
ByteCount(j['maximum']),
|
ByteCount(j['maximum']),
|
||||||
@ -113,6 +118,7 @@ class TransferStatsDownUp:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
return TransferStatsDownUp(
|
return TransferStatsDownUp(
|
||||||
TransferStats.from_json(j['down']),
|
TransferStats.from_json(j['down']),
|
||||||
TransferStats.from_json(j['up']))
|
TransferStats.from_json(j['up']))
|
||||||
@ -131,6 +137,7 @@ class PeerStats:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
return PeerStats(
|
return PeerStats(
|
||||||
j['time_added'],
|
j['time_added'],
|
||||||
RPCStats.from_json(j['rpc_stats']),
|
RPCStats.from_json(j['rpc_stats']),
|
||||||
@ -149,6 +156,7 @@ class PeerTableData:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
return PeerTableData(
|
return PeerTableData(
|
||||||
j['node_ids'],
|
j['node_ids'],
|
||||||
j['peer_address'],
|
j['peer_address'],
|
||||||
@ -168,6 +176,7 @@ class VeilidStateNetwork:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
return VeilidStateNetwork(
|
return VeilidStateNetwork(
|
||||||
j['started'],
|
j['started'],
|
||||||
ByteCount(j['bps_down']),
|
ByteCount(j['bps_down']),
|
||||||
@ -182,10 +191,10 @@ class VeilidStateConfig:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
return VeilidStateConfig(
|
return VeilidStateConfig(
|
||||||
j['config'])
|
j['config'])
|
||||||
|
|
||||||
|
|
||||||
class VeilidState:
|
class VeilidState:
|
||||||
attachment: VeilidStateAttachment
|
attachment: VeilidStateAttachment
|
||||||
network: VeilidStateNetwork
|
network: VeilidStateNetwork
|
||||||
@ -198,8 +207,143 @@ class VeilidState:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(j: dict) -> Self:
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
return VeilidState(
|
return VeilidState(
|
||||||
VeilidStateAttachment.from_json(j['attachment']),
|
VeilidStateAttachment.from_json(j['attachment']),
|
||||||
VeilidStateNetwork.from_json(j['network']),
|
VeilidStateNetwork.from_json(j['network']),
|
||||||
VeilidStateConfig.from_json(j['config']))
|
VeilidStateConfig.from_json(j['config']))
|
||||||
|
|
||||||
|
class VeilidLog:
|
||||||
|
log_level: VeilidLogLevel
|
||||||
|
message: str
|
||||||
|
backtrace: Optional[str]
|
||||||
|
|
||||||
|
def __init__(self, log_level: VeilidLogLevel, message: str, backtrace: Optional[str]):
|
||||||
|
self.log_level = log_level
|
||||||
|
self.message = message
|
||||||
|
self.backtrace = backtrace
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
|
return VeilidLog(
|
||||||
|
VeilidLogLevel(j['attachment']),
|
||||||
|
j['message'],
|
||||||
|
j['backtrace'])
|
||||||
|
|
||||||
|
class VeilidAppMessage:
|
||||||
|
sender: Optional[TypedKey]
|
||||||
|
message: bytes
|
||||||
|
|
||||||
|
def __init__(self, sender: Optional[TypedKey], message: bytes):
|
||||||
|
self.sender = sender
|
||||||
|
self.message = message
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
|
return VeilidAppMessage(
|
||||||
|
None if j['sender'] is None else TypedKey(j['sender']),
|
||||||
|
urlsafe_b64decode_no_pad(j['message']))
|
||||||
|
|
||||||
|
class VeilidAppCall:
|
||||||
|
sender: Optional[TypedKey]
|
||||||
|
message: bytes
|
||||||
|
operation_id: str
|
||||||
|
|
||||||
|
def __init__(self, sender: Optional[TypedKey], message: bytes, operation_id: str):
|
||||||
|
self.sender = sender
|
||||||
|
self.message = message
|
||||||
|
self.operation_id = operation_id
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
|
return VeilidAppCall(
|
||||||
|
None if j['sender'] is None else TypedKey(j['sender']),
|
||||||
|
urlsafe_b64decode_no_pad(j['message']),
|
||||||
|
j['operation_id'])
|
||||||
|
|
||||||
|
class VeilidRouteChange:
|
||||||
|
dead_routes: list[RouteId]
|
||||||
|
dead_remote_routes: list[RouteId]
|
||||||
|
|
||||||
|
def __init__(self, dead_routes: list[RouteId], dead_remote_routes: list[RouteId]):
|
||||||
|
self.dead_routes = dead_routes
|
||||||
|
self.dead_remote_routes = dead_remote_routes
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
|
return VeilidRouteChange(
|
||||||
|
map(lambda x: RouteId(x), j['dead_routes']),
|
||||||
|
map(lambda x: RouteId(x), j['dead_remote_routes']))
|
||||||
|
|
||||||
|
class VeilidValueChange:
|
||||||
|
key: TypedKey
|
||||||
|
subkeys: list[ValueSubkey]
|
||||||
|
count: int
|
||||||
|
value: ValueData
|
||||||
|
|
||||||
|
def __init__(self, key: TypedKey, subkeys: list[ValueSubkey], count: int, value: ValueData):
|
||||||
|
self.key = key
|
||||||
|
self.subkeys = subkeys
|
||||||
|
self.count = count
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
|
return VeilidValueChange(
|
||||||
|
TypedKey(j['key']),
|
||||||
|
map(lambda x: ValueSubkey(x), j['subkeys']),
|
||||||
|
j['count'],
|
||||||
|
ValueData.from_json(j['value']))
|
||||||
|
|
||||||
|
|
||||||
|
class VeilidUpdateKind(StrEnum):
|
||||||
|
LOG = "Log"
|
||||||
|
APP_MESSAGE = "AppMessage"
|
||||||
|
APP_CALL = "AppCall"
|
||||||
|
ATTACHMENT = "Attachment"
|
||||||
|
NETWORK = "Network"
|
||||||
|
CONFIG = "Config"
|
||||||
|
ROUTE_CHANGE = "RouteChange"
|
||||||
|
VALUE_CHANGE = "ValueChange"
|
||||||
|
SHUTDOWN = "Shutdown"
|
||||||
|
|
||||||
|
class VeilidUpdate:
|
||||||
|
kind: VeilidUpdateKind
|
||||||
|
detail: Optional[VeilidLog | VeilidAppMessage | VeilidAppCall | VeilidStateAttachment | VeilidStateNetwork | VeilidStateConfig | VeilidRouteChange | VeilidValueChange]
|
||||||
|
|
||||||
|
def __init__(self, kind: VeilidUpdateKind, detail: Optional[VeilidLog | VeilidAppMessage | VeilidAppCall | VeilidStateAttachment | VeilidStateNetwork | VeilidStateConfig | VeilidRouteChange | VeilidValueChange]):
|
||||||
|
self.kind = kind
|
||||||
|
self.detail = detail
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
'''JSON object hook'''
|
||||||
|
kind = VeilidUpdateKind(j['kind'])
|
||||||
|
detail = None
|
||||||
|
match kind:
|
||||||
|
case VeilidUpdateKind.LOG:
|
||||||
|
detail = VeilidLog.from_json(j)
|
||||||
|
case VeilidUpdateKind.APP_MESSAGE:
|
||||||
|
detail = VeilidAppMessage.from_json(j)
|
||||||
|
case VeilidUpdateKind.APP_CALL:
|
||||||
|
detail = VeilidAppCall.from_json(j)
|
||||||
|
case VeilidUpdateKind.ATTACHMENT:
|
||||||
|
detail = VeilidStateAttachment.from_json(j)
|
||||||
|
case VeilidUpdateKind.NETWORK:
|
||||||
|
detail = VeilidStateNetwork.from_json(j)
|
||||||
|
case VeilidUpdateKind.CONFIG:
|
||||||
|
detail = VeilidStateConfig.from_json(j)
|
||||||
|
case VeilidUpdateKind.ROUTE_CHANGE:
|
||||||
|
detail = VeilidRouteChange.from_json(j)
|
||||||
|
case VeilidUpdateKind.VALUE_CHANGE:
|
||||||
|
detail = VeilidValueChange.from_json(j)
|
||||||
|
case VeilidUpdateKind.SHUTDOWN:
|
||||||
|
detail = None
|
||||||
|
case _:
|
||||||
|
raise ValueError("Unknown VeilidUpdateKind")
|
||||||
|
|
||||||
|
@ -1,4 +1,38 @@
|
|||||||
import time
|
import time
|
||||||
|
import json
|
||||||
|
import base64
|
||||||
|
|
||||||
|
from enum import StrEnum
|
||||||
|
from typing import Self, Optional, Any
|
||||||
|
|
||||||
|
def urlsafe_b64encode_no_pad(b: bytes) -> str:
|
||||||
|
"""
|
||||||
|
Removes any `=` used as padding from the encoded string.
|
||||||
|
"""
|
||||||
|
encoded = str(base64.urlsafe_b64encode(b))
|
||||||
|
return encoded.rstrip("=")
|
||||||
|
|
||||||
|
|
||||||
|
def urlsafe_b64decode_no_pad(s: str) -> bytes:
|
||||||
|
"""
|
||||||
|
Adds back in the required padding before decoding.
|
||||||
|
"""
|
||||||
|
padding = 4 - (len(s) % 4)
|
||||||
|
string = string + ("=" * padding)
|
||||||
|
return base64.urlsafe_b64decode(s)
|
||||||
|
|
||||||
|
class VeilidJSONEncoder(json.JSONEncoder):
|
||||||
|
def default(self, o):
|
||||||
|
if isinstance(o, bytes):
|
||||||
|
return urlsafe_b64encode_no_pad(o)
|
||||||
|
if hasattr(o, "to_json") and callable(o.to_json):
|
||||||
|
return o.to_json()
|
||||||
|
return json.JSONEncoder.default(self, o)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def dumps(req: Any, *args, **kwargs) -> str:
|
||||||
|
return json.dumps(req, cls = VeilidJSONEncoder, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Timestamp(int):
|
class Timestamp(int):
|
||||||
pass
|
pass
|
||||||
@ -7,4 +41,195 @@ class TimestampDuration(int):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
class ByteCount(int):
|
class ByteCount(int):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class OperationId(int):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class RouteId(str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class TypedKey(str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class TypedKeyPair(str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class TypedSignature(str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class CryptoKey(str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class CryptoKeyDistance(str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class PublicKey(CryptoKey):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class SecretKey(CryptoKey):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class SharedSecret(CryptoKey):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Signature(str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Nonce(str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class KeyPair(str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class HashDigest(CryptoKey):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ValueSubkey(int):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ValueSeqNum(int):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class VeilidVersion:
|
||||||
|
_major: int
|
||||||
|
_minor: int
|
||||||
|
_patch: int
|
||||||
|
def __init__(self, major: int, minor: int, patch: int):
|
||||||
|
self._major = major
|
||||||
|
self._minor = minor
|
||||||
|
self._patch = patch
|
||||||
|
@property
|
||||||
|
def major(self):
|
||||||
|
return self._major
|
||||||
|
@property
|
||||||
|
def minor(self):
|
||||||
|
return self._minor
|
||||||
|
@property
|
||||||
|
def patch(self):
|
||||||
|
return self._patch
|
||||||
|
|
||||||
|
class VeilidLogLevel(StrEnum):
|
||||||
|
ERROR = 'Error'
|
||||||
|
WARN = 'Warn'
|
||||||
|
INFO = 'Info'
|
||||||
|
DEBUG = 'Debug'
|
||||||
|
TRACE = 'Trace'
|
||||||
|
|
||||||
|
class NewPrivateRouteResult:
|
||||||
|
route_id: RouteId
|
||||||
|
blob: bytes
|
||||||
|
|
||||||
|
def __init__(self, route_id: RouteId, blob: bytes):
|
||||||
|
self.route_id = route_id
|
||||||
|
self.blob = blob
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
return NewPrivateRouteResult(
|
||||||
|
RouteId(j['route_id']),
|
||||||
|
urlsafe_b64decode_no_pad(j['blob']))
|
||||||
|
|
||||||
|
class CryptoKind(StrEnum):
|
||||||
|
CRYPTO_KIND_NONE = "NONE"
|
||||||
|
CRYPTO_KIND_VLD0 = "VLD0"
|
||||||
|
|
||||||
|
class Stability(StrEnum):
|
||||||
|
LOW_LATENCY = "LowLatency"
|
||||||
|
RELIABLE = "Reliable"
|
||||||
|
|
||||||
|
class Sequencing(StrEnum):
|
||||||
|
NO_PREFERENCE = "NoPreference"
|
||||||
|
PREFER_ORDERED = "PreferOrdered"
|
||||||
|
ENSURE_ORDERED = "EnsureOrdered"
|
||||||
|
|
||||||
|
class DHTSchemaKind(StrEnum):
|
||||||
|
DFLT = "DFLT"
|
||||||
|
SMPL = "SMPL"
|
||||||
|
|
||||||
|
class DHTSchemaSMPLMember:
|
||||||
|
m_key: PublicKey
|
||||||
|
m_cnt: int
|
||||||
|
def __init__(self, m_key: PublicKey, m_cnt: int):
|
||||||
|
self.m_key = m_key
|
||||||
|
self.m_cnt = m_cnt
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
return DHTSchemaSMPLMember(
|
||||||
|
PublicKey(j['m_key']),
|
||||||
|
j['m_cnt'])
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
class DHTSchema:
|
||||||
|
kind: DHTSchemaKind
|
||||||
|
|
||||||
|
def __init__(self, kind: DHTSchemaKind, **kwargs):
|
||||||
|
self.kind = kind
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
setattr(self, k, v)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def dflt(o_cnt: int) -> Self:
|
||||||
|
Self(DHTSchemaKind.DFLT, o_cnt = o_cnt)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def smpl(o_cnt: int, members: list[DHTSchemaSMPLMember]) -> Self:
|
||||||
|
Self(DHTSchemaKind.SMPL, o_cnt = o_cnt, members = members)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
if DHTSchemaKind(j['kind']) == DHTSchemaKind.DFLT:
|
||||||
|
return DHTSchema.dflt(j['o_cnt'])
|
||||||
|
if DHTSchemaKind(j['kind']) == DHTSchemaKind.SMPL:
|
||||||
|
return DHTSchema.smpl(
|
||||||
|
j['o_cnt'],
|
||||||
|
map(lambda x: DHTSchemaSMPLMember.from_json(x), j['members']))
|
||||||
|
raise Exception("Unknown DHTSchema kind", j['kind'])
|
||||||
|
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
class DHTRecordDescriptor:
|
||||||
|
key: TypedKey
|
||||||
|
owner: PublicKey
|
||||||
|
owner_secret: Optional[SecretKey]
|
||||||
|
schema: DHTSchema
|
||||||
|
|
||||||
|
def __init__(self, key: TypedKey, owner: PublicKey, owner_secret: Optional[SecretKey], schema: DHTSchema):
|
||||||
|
self.key = key
|
||||||
|
self.owner = owner
|
||||||
|
self.owner_secret = owner_secret
|
||||||
|
self.schema = schema
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
DHTRecordDescriptor(
|
||||||
|
TypedKey(j['key']),
|
||||||
|
PublicKey(j['owner']),
|
||||||
|
None if j['owner_secret'] is None else SecretKey(j['owner_secret']),
|
||||||
|
DHTSchema.from_json(j['schema']))
|
||||||
|
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
class ValueData:
|
||||||
|
seq: ValueSeqNum
|
||||||
|
data: bytes
|
||||||
|
writer: PublicKey
|
||||||
|
|
||||||
|
def __init__(self, seq: ValueSeqNum, data: bytes, writer: PublicKey):
|
||||||
|
self.seq = seq
|
||||||
|
self.data = data
|
||||||
|
self.writer = writer
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(j: dict) -> Self:
|
||||||
|
DHTRecordDescriptor(
|
||||||
|
ValueSeqNum(j['seq']),
|
||||||
|
urlsafe_b64decode_no_pad(j['data']),
|
||||||
|
PublicKey(j['writer']))
|
||||||
|
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user