diff --git a/rainbowadn/chain/composition/__init__.py b/rainbowadn/chain/composition/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/rainbowadn/encryption/encrypted.py b/rainbowadn/encryption/encrypted.py index ddd0d2a..274a01d 100644 --- a/rainbowadn/encryption/encrypted.py +++ b/rainbowadn/encryption/encrypted.py @@ -21,10 +21,12 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]): self, key: bytes, resolution: tuple[HashPoint['Encrypted'], ...], + mapping: dict[bytes, HashPoint['Encrypted']], decrypted: EncryptedType ): assert isinstance(key, bytes) assert isinstance(resolution, tuple) + assert isinstance(mapping, dict) assert isinstance(decrypted, HashMentionable) self.factory: RainbowFactory[EncryptedType] = decrypted.__factory__() @@ -33,11 +35,7 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]): self.resolution = resolution self.decrypted: EncryptedType = decrypted - self.hashpoints = tuple(decrypted.points()) if isinstance(decrypted, RecursiveMentionable) else () - assert len(self.hashpoints) == len(self.resolution) - self.mapping: dict[bytes, HashPoint[Encrypted]] = { - hashpoint.point: encrypted for hashpoint, encrypted in zip(self.hashpoints, resolution) - } + self.mapping = mapping def points(self) -> Iterable[HashPoint]: return self.resolution @@ -49,22 +47,19 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]): cls.ecc += 1 assert isinstance(key, bytes) hashpoints = tuple(decrypted.points()) if isinstance(decrypted, RecursiveMentionable) else () - encrypted: Encrypted[EncryptedType] = object.__new__(cls) - encrypted.__init__( - key, - tuple( - cls.encrypt_hashpoint(hashpoint, key) - for - hashpoint - in - hashpoints - ), - decrypted.__factory__().from_bytes( - bytes(decrypted), - EncryptedResolver(encrypted) - ) + resolution = tuple( + cls.encrypt_hashpoint(hashpoint, key) + for + hashpoint + in + hashpoints + ) + return cls.construct( + key, + resolution, + hashpoints, + decrypted ) - return encrypted @classmethod def encrypt_hashpoint( @@ -75,14 +70,35 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]): if isinstance(hashpoint.origin, ResolverOrigin): resolver: HashResolver = hashpoint.origin.resolver assert isinstance(resolver, HashResolver) - if isinstance(resolver, EncryptedResolver) and resolver.encrypted.key == key: + if isinstance(resolver, EncryptedResolver) and resolver.key == key: return ShortcutOrigin( hashpoint.factory, - resolver.encrypted.mapping[hashpoint.point], + resolver.mapping[hashpoint.point], key ).hash_point() return HashPoint.of(cls.encrypt(hashpoint.resolve(), key)) + @classmethod + def construct( + cls, + key: bytes, + resolution: tuple[HashPoint['Encrypted'], ...], + hashpoints: tuple[HashPoint, ...], + decrypted: EncryptedType + ) -> 'Encrypted[EncryptedType]': + mapping: dict[bytes, HashPoint[Encrypted]] = { + hashpoint.point: encrypted for hashpoint, encrypted in zip(hashpoints, resolution) + } + return Encrypted( + key, + resolution, + mapping, + decrypted.__factory__().from_bytes( + bytes(decrypted), + EncryptedResolver(mapping, key) + ) + ) + def __bytes__(self): source: bytes = len(self.resolution).to_bytes(8, 'little') + b''.join( encrypted.point @@ -109,10 +125,9 @@ class EncryptedFactory(RainbowFactory[Encrypted[EncryptedType]], Generic[Encrypt assert isinstance(resolver, HashResolver) plain: bytes = SecretBox(self.key).decrypt(source) resolution_size: int = int.from_bytes(plain[:8], 'little') - encrypted: Encrypted[EncryptedType] = object.__new__(Encrypted) decrypted: EncryptedType = self.factory.from_bytes( plain[8 + resolution_size * HashPoint.HASH_LENGTH:], - EncryptedResolver(encrypted) + resolver, ) hashpoints = tuple(decrypted.points()) if isinstance(decrypted, RecursiveMentionable) else () assert len(hashpoints) == resolution_size @@ -126,26 +141,28 @@ class EncryptedFactory(RainbowFactory[Encrypted[EncryptedType]], Generic[Encrypt resolver ).hash_point() for i, hashpoint in enumerate(hashpoints) ) - encrypted.__init__( + return Encrypted.construct( self.key, resolution, + hashpoints, decrypted ) - return encrypted def loose(self) -> RainbowFactory[Encrypted[EncryptedType]]: return self class EncryptedResolver(HashResolver): - def __init__(self, encrypted: Encrypted): - assert isinstance(encrypted, Encrypted) - self.encrypted = encrypted + def __init__(self, mapping: dict[bytes, HashPoint[Encrypted]], key: bytes): + assert isinstance(mapping, dict) + assert isinstance(key, bytes) + self.mapping = mapping + self.key = key def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']: assert isinstance(point, bytes) - encrypted = self.encrypted.mapping[point].resolve() - return HashPoint.bytes_of_mentioned(encrypted.decrypted), EncryptedResolver(encrypted) + encrypted = self.mapping[point].resolve() + return HashPoint.bytes_of_mentioned(encrypted.decrypted), EncryptedResolver(encrypted.mapping, self.key) class ShortcutOrigin(Origin[Encrypted[EncryptedType]], Generic[EncryptedType]):