From 05e3708a745d66f7b512ddb7d7df63121e2a361c Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Mon, 10 Jul 2023 13:39:37 +0200
Subject: [PATCH] fix: python typings don't match runtime
---
.github/workflows/nucypher-core.yml | 32 +++
.../nucypher_core/__init__.pyi | 195 ++++++++++--------
nucypher-core-python/nucypher_core/ferveo.py | 2 +-
nucypher-core-python/nucypher_core/ferveo.pyi | 72 ++++---
nucypher-core-python/nucypher_core/umbral.pyi | 40 ++--
nucypher-core-python/src/lib.rs | 7 -
6 files changed, 211 insertions(+), 137 deletions(-)
diff --git a/.github/workflows/nucypher-core.yml b/.github/workflows/nucypher-core.yml
index 33fb1abe..d27b2931 100644
--- a/.github/workflows/nucypher-core.yml
+++ b/.github/workflows/nucypher-core.yml
@@ -96,6 +96,38 @@ jobs:
with:
cmd: --cwd nucypher-core-wasm/examples/node test
+ python-test:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ rust:
+ - stable
+ python:
+ - "3.10"
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-python@v4
+ with:
+ python-version: ${{ matrix.python }}
+
+ - name: Install Rust toolchain
+ uses: actions-rs/toolchain@v1
+ with:
+ profile: minimal
+ toolchain: ${{ matrix.rust }}
+ override: true
+
+ - name: Install nucypher-core Python package
+ run: pip install -e .
+ working-directory: nucypher-core-python
+
+ - name: Install pip dependencies
+ run: pip install mypy
+
+ - name: Run mypy.stubtest
+ run: python -m mypy.stubtest nucypher_core
+ working-directory: nucypher-core-python
+
trigger-wheels:
runs-on: ubuntu-latest
needs: test
diff --git a/nucypher-core-python/nucypher_core/__init__.pyi b/nucypher-core-python/nucypher_core/__init__.pyi
index fce1d08b..677d609f 100644
--- a/nucypher-core-python/nucypher_core/__init__.pyi
+++ b/nucypher-core-python/nucypher_core/__init__.pyi
@@ -1,4 +1,4 @@
-from typing import List, Dict, Sequence, Optional, Mapping, Tuple, Set
+from typing import List, Dict, Sequence, Optional, Mapping, Tuple, Set, final
from .umbral import (
SecretKey,
@@ -10,12 +10,13 @@ from .umbral import (
RecoverableSignature
)
-from .ferveo import (
+from .ferveo import (
FerveoPublicKey,
Ciphertext
)
+@final
class Address:
def __init__(self, address_bytes: bytes):
@@ -31,32 +32,31 @@ class Address:
...
+@final
class Conditions:
def __init__(self, conditions: str):
...
- @classmethod
- def from_string(cls, conditions: str) -> Conditions:
+ @staticmethod
+ def from_string(conditions: str) -> Conditions:
...
def __str__(self) -> str:
...
+@final
class Context:
def __init__(self, context: str):
...
- @classmethod
- def from_string(cls, context: str) -> Context:
- ...
-
def __str__(self) -> str:
...
+@final
class MessageKit:
@staticmethod
@@ -64,10 +64,10 @@ class MessageKit:
...
def __init__(
- self,
- policy_encrypting_key: PublicKey,
- plaintext: bytes,
- conditions: Optional[Conditions]
+ self,
+ policy_encrypting_key: PublicKey,
+ plaintext: bytes,
+ conditions: Optional[Conditions]
):
...
@@ -75,25 +75,29 @@ class MessageKit:
...
def decrypt_reencrypted(
- self,
- sk: SecretKey,
- policy_encrypting_key: PublicKey,
- vcfrags: Sequence[VerifiedCapsuleFrag]
+ self,
+ sk: SecretKey,
+ policy_encrypting_key: PublicKey,
+ vcfrags: Sequence[VerifiedCapsuleFrag]
) -> bytes:
...
+ def __bytes__(self) -> bytes:
+ ...
+
capsule: Capsule
conditions: Optional[Conditions]
+@final
class HRAC:
def __init__(
- self,
- publisher_verifying_key: PublicKey,
- bob_verifying_key: PublicKey,
- label: bytes,
+ self,
+ publisher_verifying_key: PublicKey,
+ bob_verifying_key: PublicKey,
+ label: bytes,
):
...
@@ -105,22 +109,23 @@ class HRAC:
...
+@final
class EncryptedKeyFrag:
def __init__(
- self,
- signer: Signer,
- recipient_key: PublicKey,
- hrac: HRAC,
- verified_kfrag: VerifiedKeyFrag,
+ self,
+ signer: Signer,
+ recipient_key: PublicKey,
+ hrac: HRAC,
+ verified_kfrag: VerifiedKeyFrag,
):
...
def decrypt(
- self,
- sk: SecretKey,
- hrac: HRAC,
- publisher_verifying_key: PublicKey,
+ self,
+ sk: SecretKey,
+ hrac: HRAC,
+ publisher_verifying_key: PublicKey,
) -> VerifiedKeyFrag:
...
@@ -132,15 +137,16 @@ class EncryptedKeyFrag:
...
+@final
class TreasureMap:
def __init__(
- self,
- signer: Signer,
- hrac: HRAC,
- policy_encrypting_key: PublicKey,
- assigned_kfrags: Mapping[Address, Tuple[PublicKey, VerifiedKeyFrag]],
- threshold: int,
+ self,
+ signer: Signer,
+ hrac: HRAC,
+ policy_encrypting_key: PublicKey,
+ assigned_kfrags: Mapping[Address, Tuple[PublicKey, VerifiedKeyFrag]],
+ threshold: int,
):
...
@@ -168,12 +174,13 @@ class TreasureMap:
...
+@final
class EncryptedTreasureMap:
def decrypt(
- self,
- sk: SecretKey,
- publisher_verifying_key: PublicKey,
+ self,
+ sk: SecretKey,
+ publisher_verifying_key: PublicKey,
) -> TreasureMap:
...
@@ -185,17 +192,18 @@ class EncryptedTreasureMap:
...
+@final
class ReencryptionRequest:
def __init__(
- self,
- capsules: Sequence[Capsule],
- hrac: HRAC,
- encrypted_kfrag: EncryptedKeyFrag,
- publisher_verifying_key: PublicKey,
- bob_verifying_key: PublicKey,
- conditions: Optional[Conditions],
- context: Optional[Context],
+ self,
+ capsules: Sequence[Capsule],
+ hrac: HRAC,
+ encrypted_kfrag: EncryptedKeyFrag,
+ publisher_verifying_key: PublicKey,
+ bob_verifying_key: PublicKey,
+ conditions: Optional[Conditions],
+ context: Optional[Context],
):
...
@@ -221,18 +229,19 @@ class ReencryptionRequest:
...
+@final
class ReencryptionResponse:
def __init__(self, signer: Signer, capsules_and_vcfrags: Sequence[Tuple[Capsule, VerifiedCapsuleFrag]]):
...
def verify(
- self,
- capsules: Sequence[Capsule],
- alice_verifying_key: PublicKey,
- ursula_verifying_key: PublicKey,
- policy_encrypting_key: PublicKey,
- bob_encrypting_key: PublicKey,
+ self,
+ capsules: Sequence[Capsule],
+ alice_verifying_key: PublicKey,
+ ursula_verifying_key: PublicKey,
+ policy_encrypting_key: PublicKey,
+ bob_encrypting_key: PublicKey,
) -> List[VerifiedCapsuleFrag]:
...
@@ -244,6 +253,7 @@ class ReencryptionResponse:
...
+@final
class RetrievalKit:
@staticmethod
@@ -251,10 +261,10 @@ class RetrievalKit:
...
def __init__(
- self,
- capsule: Capsule,
- queried_addresses: Set[Address],
- conditions: Optional[Conditions],
+ self,
+ capsule: Capsule,
+ queried_addresses: Set[Address],
+ conditions: Optional[Conditions],
):
...
@@ -272,19 +282,20 @@ class RetrievalKit:
...
+@final
class RevocationOrder:
def __init__(
- self,
- signer: Signer,
- staking_provider_address: Address,
- encrypted_kfrag: EncryptedKeyFrag,
+ self,
+ signer: Signer,
+ staking_provider_address: Address,
+ encrypted_kfrag: EncryptedKeyFrag,
):
...
def verify(
- self,
- alice_verifying_key: PublicKey,
+ self,
+ alice_verifying_key: PublicKey,
) -> Tuple[Address, EncryptedKeyFrag]:
...
@@ -296,20 +307,21 @@ class RevocationOrder:
...
+@final
class NodeMetadataPayload:
def __init__(
- self,
- staking_provider_address: Address,
- domain: str,
- timestamp_epoch: int,
- verifying_key: PublicKey,
- encrypting_key: PublicKey,
- ferveo_public_key: FerveoPublicKey,
- certificate_der: bytes,
- host: str,
- port: int,
- operator_signature: RecoverableSignature,
+ self,
+ staking_provider_address: Address,
+ domain: str,
+ timestamp_epoch: int,
+ verifying_key: PublicKey,
+ encrypting_key: PublicKey,
+ ferveo_public_key: FerveoPublicKey,
+ certificate_der: bytes,
+ host: str,
+ port: int,
+ operator_signature: RecoverableSignature,
):
...
@@ -337,6 +349,7 @@ class NodeMetadataPayload:
...
+@final
class NodeMetadata:
def __init__(self, signer: Signer, payload: NodeMetadataPayload):
@@ -355,18 +368,23 @@ class NodeMetadata:
...
+@final
class FleetStateChecksum:
def __init__(self, other_nodes: Sequence[NodeMetadata], this_node: Optional[NodeMetadata]):
...
+ def __bytes__(self) -> bytes:
+ ...
+
+@final
class MetadataRequest:
def __init__(
- self,
- fleet_state_checksum: FleetStateChecksum,
- announce_nodes: Sequence[NodeMetadata],
+ self,
+ fleet_state_checksum: FleetStateChecksum,
+ announce_nodes: Sequence[NodeMetadata],
):
...
@@ -382,6 +400,7 @@ class MetadataRequest:
...
+@final
class MetadataResponsePayload:
def __init__(self, timestamp_epoch: int, announce_nodes: Sequence[NodeMetadata]):
@@ -392,6 +411,7 @@ class MetadataResponsePayload:
announce_nodes: List[NodeMetadata]
+@final
class MetadataResponse:
def __init__(self, signer: Signer, payload: MetadataResponsePayload):
@@ -408,9 +428,11 @@ class MetadataResponse:
...
+@final
class ThresholdDecryptionRequest:
- def __init__(self, ritual_id: int, variant: int, ciphertext: Ciphertext, conditions: Optional[Conditions], context: Optional[Context]):
+ def __init__(self, ritual_id: int, variant: int, ciphertext: Ciphertext, conditions: Optional[Conditions],
+ context: Optional[Context]):
...
ritual_id: int
@@ -423,7 +445,8 @@ class ThresholdDecryptionRequest:
ciphertext: Ciphertext
- def encrypt(self, shared_secret: SessionSharedSecret, requester_public_key: SessionStaticKey) -> EncryptedThresholdDecryptionRequest:
+ def encrypt(self, shared_secret: SessionSharedSecret,
+ requester_public_key: SessionStaticKey) -> EncryptedThresholdDecryptionRequest:
...
@staticmethod
@@ -434,14 +457,15 @@ class ThresholdDecryptionRequest:
...
+@final
class EncryptedThresholdDecryptionRequest:
ritual_id: int
requester_public_key: SessionStaticKey
def decrypt(
- self,
- shared_secret: SessionSharedSecret
+ self,
+ shared_secret: SessionSharedSecret
) -> ThresholdDecryptionRequest:
...
@@ -453,6 +477,7 @@ class EncryptedThresholdDecryptionRequest:
...
+@final
class ThresholdDecryptionResponse:
def __init__(self, ritual_id: int, decryption_share: bytes):
@@ -473,13 +498,13 @@ class ThresholdDecryptionResponse:
...
+@final
class EncryptedThresholdDecryptionResponse:
-
ritual_id: int
def decrypt(
- self,
- shared_secret: SessionSharedSecret
+ self,
+ shared_secret: SessionSharedSecret
) -> ThresholdDecryptionResponse:
...
@@ -491,10 +516,12 @@ class EncryptedThresholdDecryptionResponse:
...
+@final
class SessionSharedSecret:
...
+@final
class SessionStaticKey:
@staticmethod
@@ -505,6 +532,7 @@ class SessionStaticKey:
...
+@final
class SessionStaticSecret:
@staticmethod
@@ -518,6 +546,7 @@ class SessionStaticSecret:
...
+@final
class SessionSecretFactory:
@staticmethod
diff --git a/nucypher-core-python/nucypher_core/ferveo.py b/nucypher-core-python/nucypher_core/ferveo.py
index ac550a22..3593b4b2 100644
--- a/nucypher-core-python/nucypher_core/ferveo.py
+++ b/nucypher-core-python/nucypher_core/ferveo.py
@@ -18,8 +18,8 @@
AggregatedTranscript = _ferveo.AggregatedTranscript
DkgPublicKey = _ferveo.DkgPublicKey
SharedSecret = _ferveo.SharedSecret
+FerveoVariant = _ferveo.FerveoVariant
ThresholdEncryptionError = _ferveo.ThresholdEncryptionError
-InvalidShareNumberParameter = _ferveo.InvalidShareNumberParameter
InvalidDkgStateToDeal = _ferveo.InvalidDkgStateToDeal
InvalidDkgStateToAggregate = _ferveo.InvalidDkgStateToAggregate
InvalidDkgStateToVerify = _ferveo.InvalidDkgStateToVerify
diff --git a/nucypher-core-python/nucypher_core/ferveo.pyi b/nucypher-core-python/nucypher_core/ferveo.pyi
index b708fa56..4d540655 100644
--- a/nucypher-core-python/nucypher_core/ferveo.pyi
+++ b/nucypher-core-python/nucypher_core/ferveo.pyi
@@ -1,13 +1,13 @@
-from typing import Sequence
-
+from typing import Sequence, final
+@final
class Keypair:
@staticmethod
def random() -> Keypair:
...
@staticmethod
- def from_secure_randomness(data: bytes) -> Keypair:
+ def from_secure_randomness(bytes: bytes) -> Keypair:
...
@staticmethod
@@ -15,7 +15,7 @@ class Keypair:
...
@staticmethod
- def from_bytes(data: bytes) -> Keypair:
+ def from_bytes(bytes: bytes) -> Keypair:
...
def __bytes__(self) -> bytes:
@@ -24,10 +24,10 @@ class Keypair:
def public_key(self) -> FerveoPublicKey:
...
-
+@final
class FerveoPublicKey:
@staticmethod
- def from_bytes(data: bytes) -> FerveoPublicKey:
+ def from_bytes(bytes: bytes) -> FerveoPublicKey:
...
def __bytes__(self) -> bytes:
@@ -36,7 +36,11 @@ class FerveoPublicKey:
def __hash__(self) -> int:
...
+ @staticmethod
+ def serialized_size() -> int:
+ ...
+@final
class Validator:
def __init__(self, address: str, public_key: FerveoPublicKey):
@@ -46,25 +50,29 @@ class Validator:
public_key: FerveoPublicKey
-
+@final
class Transcript:
@staticmethod
- def from_bytes(data: bytes) -> Transcript:
+ def from_bytes(bytes: bytes) -> Transcript:
...
def __bytes__(self) -> bytes:
...
-
+@final
class DkgPublicKey:
@staticmethod
- def from_bytes(data: bytes) -> DkgPublicKey:
+ def from_bytes(bytes: bytes) -> DkgPublicKey:
...
def __bytes__(self) -> bytes:
...
+ @staticmethod
+ def serialized_size() -> int:
+ ...
+@final
class ValidatorMessage:
def __init__(
@@ -77,7 +85,7 @@ class ValidatorMessage:
validator: Validator
transcript: Transcript
-
+@final
class Dkg:
def __init__(
@@ -98,34 +106,33 @@ class Dkg:
def aggregate_transcripts(self, messages: Sequence[ValidatorMessage]) -> AggregatedTranscript:
...
-
+@final
class Ciphertext:
@staticmethod
- def from_bytes(data: bytes) -> Ciphertext:
+ def from_bytes(bytes: bytes) -> Ciphertext:
...
def __bytes__(self) -> bytes:
...
-
+@final
class DecryptionShareSimple:
@staticmethod
- def from_bytes(data: bytes) -> DecryptionShareSimple:
+ def from_bytes(bytes: bytes) -> DecryptionShareSimple:
...
def __bytes__(self) -> bytes:
...
-
-
+@final
class DecryptionSharePrecomputed:
@staticmethod
- def from_bytes(data: bytes) -> DecryptionSharePrecomputed:
+ def from_bytes(bytes: bytes) -> DecryptionSharePrecomputed:
...
def __bytes__(self) -> bytes:
...
-
+@final
class AggregatedTranscript:
def __init__(self, messages: Sequence[ValidatorMessage]):
@@ -153,35 +160,44 @@ class AggregatedTranscript:
...
@staticmethod
- def from_bytes(data: bytes) -> AggregatedTranscript:
+ def from_bytes(bytes: bytes) -> AggregatedTranscript:
...
def __bytes__(self) -> bytes:
...
-
+@final
class SharedSecret:
@staticmethod
- def from_bytes(data: bytes) -> SharedSecret:
+ def from_bytes(bytes: bytes) -> SharedSecret:
...
def __bytes__(self) -> bytes:
...
-def encrypt(message: bytes, add: bytes, dkg_public_key: DkgPublicKey) -> Ciphertext:
+@final
+class FerveoVariant:
+ @staticmethod
+ def simple() -> str: ...
+
+ @staticmethod
+ def precomputed() -> str: ...
+
+
+def encrypt(message: bytes, aad: bytes, dkg_public_key: DkgPublicKey) -> Ciphertext:
...
def combine_decryption_shares_simple(
- decryption_shares: Sequence[DecryptionShareSimple],
+ shares: Sequence[DecryptionShareSimple],
) -> bytes:
...
def combine_decryption_shares_precomputed(
- decryption_shares: Sequence[DecryptionSharePrecomputed],
+ shares: Sequence[DecryptionSharePrecomputed],
) -> SharedSecret:
...
@@ -198,10 +214,6 @@ class ThresholdEncryptionError(Exception):
pass
-class InvalidShareNumberParameter(Exception):
- pass
-
-
class InvalidDkgStateToDeal(Exception):
pass
@@ -259,4 +271,4 @@ class ValidatorPublicKeyMismatch(Exception):
class SerializationError(Exception):
- pass
\ No newline at end of file
+ pass
diff --git a/nucypher-core-python/nucypher_core/umbral.pyi b/nucypher-core-python/nucypher_core/umbral.pyi
index 0937d27d..0733cb74 100644
--- a/nucypher-core-python/nucypher_core/umbral.pyi
+++ b/nucypher-core-python/nucypher_core/umbral.pyi
@@ -1,6 +1,7 @@
-from typing import Optional, Tuple, List, Sequence
+from typing import Optional, Tuple, List, final
+@final
class SecretKey:
@staticmethod
@@ -18,6 +19,7 @@ class SecretKey:
...
+@final
class SecretKeyFactory:
@staticmethod
@@ -28,10 +30,6 @@ class SecretKeyFactory:
def seed_size() -> int:
...
- @staticmethod
- def from_secure_randomness(seed: bytes) -> SecretKeyFactory:
- ...
-
def make_secret(self, label: bytes) -> bytes:
...
@@ -42,10 +40,11 @@ class SecretKeyFactory:
...
@staticmethod
- def from_secure_randomness(data: bytes) -> SecretKeyFactory:
+ def from_secure_randomness(seed: bytes) -> SecretKeyFactory:
...
+@final
class PublicKey:
@staticmethod
@@ -60,6 +59,7 @@ class PublicKey:
...
+@final
class Signer:
def __init__(self, secret_key: SecretKey):
@@ -72,6 +72,7 @@ class Signer:
...
+@final
class Signature:
def verify(self, verifying_pk: PublicKey, message: bytes) -> bool:
@@ -92,6 +93,7 @@ class Signature:
...
+@final
class RecoverableSignature:
@staticmethod
@@ -102,6 +104,7 @@ class RecoverableSignature:
...
+@final
class Capsule:
@staticmethod
@@ -115,14 +118,15 @@ class Capsule:
...
+@final
class KeyFrag:
def verify(
self,
verifying_pk: PublicKey,
- delegating_pk: Optional[PublicKey],
- receiving_pk: Optional[PublicKey],
- ) -> VerifiedKeyFrag:
+ delegating_pk: Optional[PublicKey] = ...,
+ receiving_pk: Optional[PublicKey] = ...,
+ ) -> VerifiedKeyFrag:
...
def skip_verification(self) -> VerifiedKeyFrag:
@@ -136,6 +140,7 @@ class KeyFrag:
...
+@final
class VerifiedKeyFrag:
def __bytes__(self) -> bytes:
@@ -153,10 +158,11 @@ def generate_kfrags(
shares: int,
sign_delegating_key: bool,
sign_receiving_key: bool,
- ) -> List[VerifiedKeyFrag]:
+) -> List[VerifiedKeyFrag]:
...
+@final
class CapsuleFrag:
def verify(
@@ -165,7 +171,7 @@ class CapsuleFrag:
verifying_pk: PublicKey,
delegating_pk: PublicKey,
receiving_pk: PublicKey,
- ) -> VerifiedCapsuleFrag:
+ ) -> VerifiedCapsuleFrag:
...
def skip_verification(self) -> VerifiedCapsuleFrag:
@@ -182,6 +188,7 @@ class CapsuleFrag:
...
+@final
class VerifiedCapsuleFrag:
def __bytes__(self) -> bytes:
@@ -198,20 +205,21 @@ def reencrypt(capsule: Capsule, kfrag: VerifiedKeyFrag) -> VerifiedCapsuleFrag:
...
+@final
class CurvePoint:
-
- def coordinates(self) -> Tuple[bytes, bytes]:
- ...
+ coordinates: Tuple[bytes, bytes]
+@final
class Parameters:
- def __init__(self) -> None:
+ def __init__(self, *args) -> None:
...
u: CurvePoint
+@final
class ReencryptionEvidence:
def __init__(
@@ -221,7 +229,7 @@ class ReencryptionEvidence:
verifying_pk: PublicKey,
delegating_pk: PublicKey,
receiving_pk: PublicKey,
- ):
+ ):
...
def __bytes__(self) -> bytes:
diff --git a/nucypher-core-python/src/lib.rs b/nucypher-core-python/src/lib.rs
index f6c34fce..723cf05b 100644
--- a/nucypher-core-python/src/lib.rs
+++ b/nucypher-core-python/src/lib.rs
@@ -141,13 +141,6 @@ impl Context {
}
}
- #[staticmethod]
- pub fn from_bytes(context: String) -> Self {
- Self {
- backend: context.into(),
- }
- }
-
fn __str__(&self) -> &str {
self.backend.as_ref()
}