100 lines
2.9 KiB
Python
Raw Normal View History

2025-10-30 11:48:34 +01:00
from abc import ABC, abstractmethod
2026-02-13 01:03:47 +04:00
from typing import Annotated, Any, Self, Union
2025-10-30 11:48:34 +01:00
2026-02-13 01:03:47 +04:00
from pydantic import BeforeValidator, Field, RootModel
2025-10-30 11:48:34 +01:00
from core.models import NbeSerializer
from models.transactions.operations.proofs import (
Ed25519Signature,
NbeSignature,
ZkAndEd25519Signature,
ZkSignature,
)
2026-02-13 01:03:47 +04:00
from node.api.serializers.fields import BytesFromIntArray
2025-10-30 11:48:34 +01:00
from utils.protocols import EnforceSubclassFromRandom
from utils.random import random_bytes
class OperationProofSerializer(EnforceSubclassFromRandom, ABC):
@abstractmethod
def into_operation_proof(cls) -> NbeSignature:
raise NotImplementedError
2026-02-13 01:03:47 +04:00
class Ed25519SignatureSerializer(OperationProofSerializer, RootModel[bytes]):
root: BytesFromIntArray
2025-10-30 11:48:34 +01:00
def into_operation_proof(self) -> NbeSignature:
return Ed25519Signature.model_validate(
{
"signature": self.root,
}
)
@classmethod
def from_random(cls, *args, **kwargs) -> Self:
2026-02-13 01:03:47 +04:00
return cls.model_validate(list(random_bytes(64)))
2025-10-30 11:48:34 +01:00
2026-02-13 01:03:47 +04:00
class ZkSignatureSerializer(OperationProofSerializer, RootModel[bytes]):
root: BytesFromIntArray
2025-10-30 11:48:34 +01:00
def into_operation_proof(self) -> NbeSignature:
return ZkSignature.model_validate(
{
"signature": self.root,
}
)
@classmethod
def from_random(cls, *args, **kwargs) -> Self:
2026-02-13 01:03:47 +04:00
return cls.model_validate(list(random_bytes(32)))
2025-10-30 11:48:34 +01:00
class ZkAndEd25519SignaturesSerializer(OperationProofSerializer, NbeSerializer):
2026-02-13 01:03:47 +04:00
zk_signature: BytesFromIntArray = Field(alias="zk_sig")
ed25519_signature: BytesFromIntArray = Field(alias="ed25519_sig")
2025-10-30 11:48:34 +01:00
def into_operation_proof(self) -> NbeSignature:
return ZkAndEd25519Signature.model_validate(
{
"zk_signature": self.zk_signature,
"ed25519_signature": self.ed25519_signature,
}
)
@classmethod
def from_random(cls, *args, **kwargs) -> Self:
return ZkAndEd25519SignaturesSerializer.model_validate(
{
2026-02-13 01:03:47 +04:00
"zk_sig": list(random_bytes(32)),
"ed25519_sig": list(random_bytes(64)),
2025-10-30 11:48:34 +01:00
}
)
2026-02-13 01:03:47 +04:00
PROOF_TAG_TO_SERIALIZER = {
"Ed25519Sig": Ed25519SignatureSerializer,
"ZkSig": ZkSignatureSerializer,
"ZkAndEd25519Sigs": ZkAndEd25519SignaturesSerializer,
}
def _parse_proof(data: Any) -> OperationProofSerializer:
if isinstance(data, OperationProofSerializer):
return data
if isinstance(data, dict):
for tag, serializer_class in PROOF_TAG_TO_SERIALIZER.items():
if tag in data:
return serializer_class.model_validate(data[tag])
return data
2025-10-30 11:48:34 +01:00
OperationProofSerializerVariants = Union[
Ed25519SignatureSerializer, ZkSignatureSerializer, ZkAndEd25519SignaturesSerializer
]
2026-02-13 01:03:47 +04:00
OperationProofSerializerField = Annotated[
OperationProofSerializerVariants,
BeforeValidator(_parse_proof),
]