diff --git a/main.py b/main.py index 0d107b0..9a285be 100644 --- a/main.py +++ b/main.py @@ -1,173 +1,4 @@ -import os -import string -import time -from collections import OrderedDict -from typing import Any, MutableMapping - -import nacl.signing - -from rainbowadn.chain.blockchain import BlockChainFactory -from rainbowadn.chain.chaincollectioninterface import ChainCollectionInterface -from rainbowadn.chain.reduction.reductionchainmetafactory import ReductionChainMetaFactory -from rainbowadn.data.atomic.integer import Integer -from rainbowadn.data.atomic.plain import Plain -from rainbowadn.data.collection.trees.binary.activebinarytree import ActiveBinaryTree -from rainbowadn.data.collection.trees.binary.avl import AVLBTBP -from rainbowadn.data.collection.trees.comparison.comparator import Replace -from rainbowadn.data.collection.trees.comparison.plaincomparator import PlainComparator -from rainbowadn.encryption.encrypted import Encrypted -from rainbowadn.hashing.hashmentionable import HashMentionable -from rainbowadn.hashing.hashpoint import HashPoint -from rainbowadn.hashing.hashresolver import HashResolver -from rainbowadn.hashing.nullability.notnull import NotNull -from rainbowadn.hashing.recursivementionable import RecursiveMentionable -from rainbowadn.hashing.resolvermetaorigin import ResolverMetaOrigin -from rainbowadn.v13.algo import MINT_CONST -from rainbowadn.v13.bankchain import BankChain -from rainbowadn.v13.subject import Subject -from rainbowadn.v13.transaction import CoinData, Transaction -from rainbowadn.wrisbt.wrisbtchainprotocol import WrisbtChainProtocol -from rainbowadn.wrisbt.wrisbtparametres import WrisbtParametres -from rainbowadn.wrisbt.wrisbtroot import WrisbtRoot - - -class DumbResolver(HashResolver): - def __init__(self): - self.table: MutableMapping[bytes, bytes] = OrderedDict() - - def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']: - assert isinstance(point, bytes) - return self.table[point], self - - def save(self, hash_point: HashPoint) -> None: - assert isinstance(hash_point, HashPoint) - if hash_point.point in self.table: - pass - else: - value: HashMentionable = hash_point.resolve() - assert isinstance(value, HashMentionable) - self.table[hash_point.point] = HashPoint.bytes_of_mentioned(value) - if isinstance(value, RecursiveMentionable): - for hash_point in value.points(): - self.save(hash_point) - - -def main0(): - dr = DumbResolver() - bank = BankChain.empty(ReductionChainMetaFactory()) - key_0 = nacl.signing.SigningKey.generate() - transaction_0 = Transaction.make( - [], - [CoinData.of(Subject(key_0.verify_key), 1_000_000)], - [] - ) - coin_0, coin_1 = transaction_0.coins(MINT_CONST, NotNull(HashPoint.of(Subject(key_0.verify_key)))) - bank = bank.adds( - [ - transaction_0, - Transaction.make( - [coin_1], - [CoinData.of(Subject(nacl.signing.SigningKey.generate().verify_key), 10_000)], - [key_0] - ), - ] - ) - bank = bank.adds( - [] - ) - print(bank) - print(bank.verify()) - dr.save(HashPoint.of(bank.reference)) - bank = BankChain.from_reference( - ReductionChainMetaFactory(), ResolverMetaOrigin(dr).migrate(HashPoint.of(bank.reference)).resolve() - ) - print(bank) - print(bank.verify()) - # for key, value in dr.table.items(): - # print(key.hex(), value.hex()) - - -def main1(): - stoptime = time.process_time() - - def measure(message: str) -> float: - nonlocal stoptime - now = time.process_time() - delta = now - stoptime - print(message, delta) - stoptime = now - return delta - - dr = DumbResolver() - btree = WrisbtRoot.empty(WrisbtParametres(1, 5)) - n = 10000 - measure('init') - for _ in range(n): - key = os.urandom(5) - assert not btree.contains(key) - btree = btree.add(key) - assert btree.contains(key) - measure('add') - dr.save(HashPoint.of(btree)) - measure('save') - btree = ResolverMetaOrigin(dr).migrate(HashPoint.of(btree)).resolve() - assert len(btree.keys()) == n - print(btree.height) - measure('resolve and iterate') - for _ in range(n): - key = os.urandom(5) - assert not btree.contains(key) - btree = btree.add(key) - assert btree.contains(key) - measure('resolve and add') - - -def main2(): - chain: ChainCollectionInterface[Any, Plain, WrisbtRoot] = BlockChainFactory( - WrisbtChainProtocol(Plain.factory(), 2).loose() - ).empty().loose() - for _ in range(1000): - chain = chain.add(HashPoint.of(Plain(os.urandom(16)))) - - assert chain - # noinspection PyUnresolvedReferences - print(chain.actual_state().reference.value.resolve().height) - - -def main3(): - tree: ActiveBinaryTree[Plain, Integer] = ActiveBinaryTree.empty( - AVLBTBP(PlainComparator(Replace())), Plain.factory() - ) - for i in range(26): - tree = tree.add(HashPoint.of(Plain(bytes([ord('A') + i])))) - print(tree.reference.str(0)) - - -def main(): - key = b'a' * 32 - dr = DumbResolver() - tree: ActiveBinaryTree[Plain, Integer] = ActiveBinaryTree.empty( - AVLBTBP(PlainComparator(Replace())), Plain.factory() - ) - for char in string.ascii_uppercase: - tree = tree.add(HashPoint.of(Plain(char.encode()))) - print(tree.reference.str(0)) - target = tree.reference - target = Encrypted.encrypt(target, key).decrypted - print(Encrypted.ecc) - tree = tree.create(target) - print(tree.reference.str(0)) - tree = tree.add(HashPoint.of(Plain(b'NEWKEY'))) - tree = tree.remove(HashPoint.of(Plain(b'Q'))) - print(tree.reference.str(0)) - target = tree.reference - eeed = Encrypted.encrypt(target, key) - print(Encrypted.ecc) - dr.save(HashPoint.of(eeed)) - # for key, value in dr.table.items(): - # print(key.hex(), value.hex()) - print(ResolverMetaOrigin(dr).migrate(HashPoint.of(eeed)).resolve().decrypted.str(0)) - +import unittest if __name__ == '__main__': - main() + unittest.main('rainbowadn.testing.test_all') diff --git a/rainbowadn/chain/blockchain.py b/rainbowadn/chain/blockchain.py index 9e550d9..d881ec2 100644 --- a/rainbowadn/chain/blockchain.py +++ b/rainbowadn/chain/blockchain.py @@ -5,7 +5,6 @@ from rainbowadn.chain.blockchainprotocol import BlockChainProtocol from rainbowadn.chain.chaincollectionfactory import ChainCollectionFactory from rainbowadn.chain.chaincollectioninterface import ChainCollectionInterface from rainbowadn.hashing.hashpoint import HashPoint -from rainbowadn.hashing.nullability.notnull import NotNull from rainbowadn.hashing.nullability.null import Null from rainbowadn.hashing.nullability.nullablereference import NullableReference from rainbowadn.hashing.rainbow_factory import RainbowFactory @@ -76,20 +75,18 @@ class BlockChain( ) -> NullableReference[ StateType ]: - if isinstance(self.reference.reference, Null): + if self.reference.reference.null(): return NullableReference( Null(), self.protocol.state_factory ) - elif isinstance(self.reference.reference, NotNull): + else: block: Block[ HeaderType, StateType - ] = self.reference.reference.value.resolve() + ] = self.reference.reference.resolve().resolve() assert isinstance(block, Block) return NullableReference.of(block.state) - else: - raise TypeError def _add( self, @@ -118,23 +115,21 @@ class BlockChain( HeaderType, ActualStateType ]: - assert isinstance(self.reference.reference, NotNull) + assert not self.reference.reference.null() block: Block[ HeaderType, StateType - ] = self.reference.reference.value.resolve() + ] = self.reference.reference.resolve().resolve() assert isinstance(block, Block) return self.factory().from_reference(block.previous) def verify(self) -> bool: - if isinstance(self.reference.reference, Null): + if self.reference.reference.null(): return True - elif isinstance(self.reference.reference, NotNull): + else: return self.verify_link( self.previous().reference ) and self.previous().verify() - else: - raise TypeError def _verify_link( self, diff --git a/rainbowadn/chain/blockcollectioninterface.py b/rainbowadn/chain/blockcollectioninterface.py index e36437e..e5a4a9c 100644 --- a/rainbowadn/chain/blockcollectioninterface.py +++ b/rainbowadn/chain/blockcollectioninterface.py @@ -2,7 +2,6 @@ from typing import Generic, TypeVar from rainbowadn.data.collection.collection_interface.collectioninterface import CollectionInterface from rainbowadn.hashing.hashpoint import HashPoint -from rainbowadn.hashing.nullability.notnull import NotNull from rainbowadn.hashing.nullability.null import Null from rainbowadn.hashing.nullability.nullablereference import NullableReference from rainbowadn.hashing.rainbow_factory import RainbowFactory @@ -39,15 +38,13 @@ class BlockCollectionInterface( previous: NullableReference[BlockType] ) -> bool: assert isinstance(previous, NullableReference) - if isinstance(self.reference.reference, Null): + if self.reference.reference.null(): return True - elif isinstance(self.reference.reference, NotNull): + else: return self._verify_link( - self.reference.reference.value.resolve(), + self.reference.reference.resolve().resolve(), previous ) - else: - raise TypeError def _actual_state_factory(self) -> RainbowFactory[ActualStateType]: raise NotImplementedError @@ -56,12 +53,10 @@ class BlockCollectionInterface( raise NotImplementedError def actual_state(self) -> NullableReference[ActualStateType]: - if isinstance(self.reference.reference, Null): + if self.reference.reference.null(): return NullableReference(Null(), self._actual_state_factory()) - elif isinstance(self.reference.reference, NotNull): - return NullableReference.of(self._actual_state(self.reference.reference.value.resolve())) else: - raise TypeError + return NullableReference.of(self._actual_state(self.reference.reference.resolve().resolve())) def add( self, diff --git a/rainbowadn/chain/reduction/reductionstageprotocol.py b/rainbowadn/chain/reduction/reductionstageprotocol.py index c5baeef..76c4681 100644 --- a/rainbowadn/chain/reduction/reductionstageprotocol.py +++ b/rainbowadn/chain/reduction/reductionstageprotocol.py @@ -9,8 +9,6 @@ from rainbowadn.chain.stages.derivation.derived import Derived from rainbowadn.chain.stages.derivation.derivedstage import DerivedStage from rainbowadn.chain.stages.derivation.derivedstate import DerivedState from rainbowadn.hashing.hashpoint import HashPoint -from rainbowadn.hashing.nullability.notnull import NotNull -from rainbowadn.hashing.nullability.null import Null from rainbowadn.hashing.nullability.nullablereference import NullableReference __all__ = ('ReductionStageProtocol',) @@ -33,12 +31,10 @@ class ReductionStageProtocol( previous: NullableReference[AccumulatorType], ) -> HashPoint[AccumulatorType]: assert isinstance(previous, NullableReference) - if isinstance(previous.reference, Null): + if previous.reference.null(): return self.protocol.initial(previous.factory) - elif isinstance(previous.reference, NotNull): - return previous.reference.value else: - raise TypeError + return previous.reference.resolve() def derive_header( self, diff --git a/rainbowadn/chain/stages/derivation/activestageprotocol.py b/rainbowadn/chain/stages/derivation/activestageprotocol.py index 3210a3d..8f28050 100644 --- a/rainbowadn/chain/stages/derivation/activestageprotocol.py +++ b/rainbowadn/chain/stages/derivation/activestageprotocol.py @@ -6,7 +6,6 @@ from rainbowadn.chain.stages.derivation.derivedstate import DerivedState from rainbowadn.chain.stages.stage import StageStage, StageStageFactory, StateStage from rainbowadn.chain.stages.stageprotocol import StageProtocol from rainbowadn.hashing.hashpoint import HashPoint -from rainbowadn.hashing.nullability.notnull import NotNull from rainbowadn.hashing.nullability.null import Null from rainbowadn.hashing.nullability.nullablereference import NullableReference from rainbowadn.hashing.rainbow_factory import RainbowFactory @@ -43,16 +42,14 @@ class ActiveStageProtocol( ) -> NullableReference[BaseStateType]: assert isinstance(previous_reference, NullableReference) assert isinstance(base_state_factory, RainbowFactory) - if isinstance(previous_reference.reference, Null): + if previous_reference.reference.null(): return NullableReference(Null(), base_state_factory) - elif isinstance(previous_reference.reference, NotNull): + else: previous_state_stage: StateStage[HeaderType, BaseStateType, StageType] = ( - previous_reference.reference.value.resolve() + previous_reference.reference.resolve().resolve() ) assert isinstance(previous_state_stage, StateStage) return NullableReference.of(previous_state_stage.state) - else: - raise TypeError def _derive_cycle( self, diff --git a/rainbowadn/chain/stages/derivation/activestagestateprotocol.py b/rainbowadn/chain/stages/derivation/activestagestateprotocol.py index 62bbe36..f0a13fb 100644 --- a/rainbowadn/chain/stages/derivation/activestagestateprotocol.py +++ b/rainbowadn/chain/stages/derivation/activestagestateprotocol.py @@ -37,32 +37,6 @@ class ActiveStageStateProtocol( self.stage_factory = stage_factory self.base_state_factory = base_state_factory - def _initial_state(self) -> HashPoint[ - StateStage[ - HeaderType, - BaseStateType, - StageType - ] - ]: - raise TypeError('use .derive()') - - def _derive( - self, - previous: HashPoint[StateStage[ - HeaderType, - BaseStateType, - StageType - ]], - header: HashPoint[HeaderType] - ) -> HashPoint[ - StateStage[ - HeaderType, - BaseStateType, - StageType - ] - ]: - raise TypeError('use .derive()') - def derive( self, previous: NullableReference[ diff --git a/rainbowadn/chain/stages/stage.py b/rainbowadn/chain/stages/stage.py index 7e325ab..a9692f3 100644 --- a/rainbowadn/chain/stages/stage.py +++ b/rainbowadn/chain/stages/stage.py @@ -4,7 +4,6 @@ from rainbowadn.chain.stages.stageprotocol import StageProtocol from rainbowadn.hashing.hash_point_format import hash_point_format, tabulate from rainbowadn.hashing.hashpoint import HashPoint from rainbowadn.hashing.hashresolver import HashResolver -from rainbowadn.hashing.nullability.notnull import NotNull from rainbowadn.hashing.nullability.null import Null from rainbowadn.hashing.nullability.nullablereference import NullableReference, NullableReferenceFactory from rainbowadn.hashing.rainbow_factory import RainbowFactory @@ -55,14 +54,12 @@ class StageStage( ) -> NullableReference[BaseStateType]: assert isinstance(previous, NullableReference) assert isinstance(base_factory, RainbowFactory) - if isinstance(previous.reference, Null): + if previous.reference.null(): return NullableReference(Null(), base_factory) - elif isinstance(previous.reference, NotNull): - state_stage: StateStage[HeaderType, BaseStateType, StageType] = previous.reference.value.resolve() + else: + state_stage: StateStage[HeaderType, BaseStateType, StageType] = previous.reference.resolve().resolve() assert isinstance(state_stage, StateStage) return NullableReference.of(state_stage.state) - else: - raise TypeError def verify( self, @@ -73,14 +70,16 @@ class StageStage( assert isinstance(previous, NullableReference) assert isinstance(header, HashPoint) assert isinstance(base_factory, RainbowFactory) - if isinstance(self.previous.reference, Null): + if self.previous.reference.null(): return self.protocol.verify_header( self._previous_state(previous, base_factory), header, self.stage ) - elif isinstance(self.previous.reference, NotNull): - previous_stage: StageStage[HeaderType, BaseStateType, StageType] = self.previous.reference.value.resolve() + else: + previous_stage: StageStage[HeaderType, BaseStateType, StageType] = ( + self.previous.reference.resolve().resolve() + ) assert isinstance(previous_stage, StageStage) return self.protocol.verify_stage( previous_stage.stage, @@ -90,8 +89,6 @@ class StageStage( header, base_factory ) - else: - raise TypeError def points(self) -> Iterable[HashPoint]: return [*self.previous.points(), self.stage] diff --git a/rainbowadn/chain/states/activestateprotocol.py b/rainbowadn/chain/states/activestateprotocol.py index 9df85d2..09f3167 100644 --- a/rainbowadn/chain/states/activestateprotocol.py +++ b/rainbowadn/chain/states/activestateprotocol.py @@ -2,8 +2,6 @@ from typing import TypeVar from rainbowadn.chain.states.stateprotocol import StateProtocol from rainbowadn.hashing.hashpoint import HashPoint -from rainbowadn.hashing.nullability.notnull import NotNull -from rainbowadn.hashing.nullability.null import Null from rainbowadn.hashing.nullability.nullablereference import NullableReference __all__ = ('ActiveStateProtocol',) @@ -25,28 +23,9 @@ class ActiveStateProtocol(StateProtocol[HeaderType, StateType]): assert state == self.derive(previous, header) return True - def _initial_state(self) -> HashPoint[StateType]: - raise NotImplementedError - - def _derive( - self, - previous: HashPoint[StateType], - header: HashPoint[HeaderType], - ) -> HashPoint[StateType]: - raise NotImplementedError - def derive( self, previous: NullableReference[StateType], header: HashPoint[HeaderType], ) -> HashPoint[StateType]: - assert isinstance(previous, NullableReference) - assert isinstance(header, HashPoint) - if isinstance(previous.reference, Null): - previous_state: HashPoint[StateType] = self._initial_state() - elif isinstance(previous.reference, NotNull): - previous_state: HashPoint[StateType] = previous.reference.value - else: - raise TypeError - assert isinstance(previous_state, HashPoint) - return self._derive(previous_state, header) + raise NotImplementedError diff --git a/rainbowadn/chain/states/metareductionstateprotocol.py b/rainbowadn/chain/states/metareductionstateprotocol.py new file mode 100644 index 0000000..b541226 --- /dev/null +++ b/rainbowadn/chain/states/metareductionstateprotocol.py @@ -0,0 +1,48 @@ +from typing import TypeVar + +from rainbowadn.chain.states.activestateprotocol import ActiveStateProtocol +from rainbowadn.hashing.hashpoint import HashPoint +from rainbowadn.hashing.nullability.nullablereference import NullableReference + +__all__ = ('MetaReductionStateProtocol',) + +HeaderType = TypeVar('HeaderType') +StateType = TypeVar('StateType') + + +class MetaReductionStateProtocol(ActiveStateProtocol[HeaderType, StateType]): + def verify( + self, + previous: NullableReference[StateType], + header: HashPoint[HeaderType], + state: HashPoint[StateType] + ) -> bool: + assert isinstance(previous, NullableReference) + assert isinstance(header, HashPoint) + assert isinstance(state, HashPoint) + assert state == self.derive(previous, header) + return True + + def _initial_state(self) -> HashPoint[StateType]: + raise NotImplementedError + + def _derive( + self, + previous: HashPoint[StateType], + header: HashPoint[HeaderType], + ) -> HashPoint[StateType]: + raise NotImplementedError + + def derive( + self, + previous: NullableReference[StateType], + header: HashPoint[HeaderType], + ) -> HashPoint[StateType]: + assert isinstance(previous, NullableReference) + assert isinstance(header, HashPoint) + if previous.reference.null(): + previous_state: HashPoint[StateType] = self._initial_state() + else: + previous_state: HashPoint[StateType] = previous.reference.resolve() + assert isinstance(previous_state, HashPoint) + return self._derive(previous_state, header) diff --git a/rainbowadn/data/collection/keymetadataquerycollection.py b/rainbowadn/data/collection/keymetadataquerycollection.py index 975ccf4..cd8de8c 100644 --- a/rainbowadn/data/collection/keymetadataquerycollection.py +++ b/rainbowadn/data/collection/keymetadataquerycollection.py @@ -30,11 +30,7 @@ class KeyMetadataQueryCollection(QueryCollectionInterface[ActiveKeyType], Generi HashPoint[KeyMetadata[ActiveKeyType, MetaDataType]] ] = self.collection.query(HashPoint.of(KeyMetadata(key, self.metadata))) assert isinstance(result, Nullable) - if isinstance(result, Null): + if result.null(): return Null() - elif isinstance(result, NotNull): - hash_point: HashPoint[KeyMetadata[ActiveKeyType, MetaDataType]] = result.value - assert isinstance(hash_point, HashPoint) - return NotNull(hash_point.resolve().key) else: - raise TypeError + return NotNull(result.resolve().resolve().key) diff --git a/rainbowadn/data/collection/mapping/querymapping.py b/rainbowadn/data/collection/mapping/querymapping.py index 4e9dbbd..e780d12 100644 --- a/rainbowadn/data/collection/mapping/querymapping.py +++ b/rainbowadn/data/collection/mapping/querymapping.py @@ -30,11 +30,9 @@ class QueryMapping(Generic[KVKeyType, KVValueType]): HashPoint[KeyValue[KVKeyType, KVValueType]] ] = self.collection.query(HashPoint.of(KeyValue(key, self.empty_value))) assert isinstance(query_result, Nullable) - if isinstance(query_result, Null): + if query_result.null(): return Null() - elif isinstance(query_result, NotNull): - key_value: KeyValue[KVKeyType, KVValueType] = query_result.value.resolve() + else: + key_value: KeyValue[KVKeyType, KVValueType] = query_result.resolve().resolve() assert isinstance(key_value, KeyValue) return NotNull(key_value.value) - else: - raise TypeError diff --git a/rainbowadn/data/collection/trees/binary/activebinarytree.py b/rainbowadn/data/collection/trees/binary/activebinarytree.py index 7645cfd..da67b2f 100644 --- a/rainbowadn/data/collection/trees/binary/activebinarytree.py +++ b/rainbowadn/data/collection/trees/binary/activebinarytree.py @@ -12,7 +12,6 @@ from rainbowadn.data.collection.trees.binary.querybinarytree import QueryBinaryT from rainbowadn.data.collection.trees.comparison.comparator import (Comparator, Comparison, Equal, Left, Replace, Right) from rainbowadn.data.collection.trees.comparison.keyedcomparator import KeyedComparator from rainbowadn.hashing.hashpoint import HashPoint -from rainbowadn.hashing.nullability.notnull import NotNull from rainbowadn.hashing.nullability.null import Null from rainbowadn.hashing.nullability.nullablereference import NullableReference from rainbowadn.hashing.rainbow_factory import RainbowFactory @@ -142,7 +141,7 @@ class ActiveBinaryTree( class ActiveCreationProtocol(BalancedTreeCreationProtocol[ActiveKeyType, MetaDataType, ActiveBinaryTree]): def splittable(self, tree: ActiveBinaryTree[ActiveKeyType, MetaDataType]) -> bool: assert isinstance(tree, ActiveBinaryTree) - return isinstance(tree.reference.reference, NotNull) + return not tree.reference.reference.null() def split( self, @@ -154,8 +153,7 @@ class ActiveCreationProtocol(BalancedTreeCreationProtocol[ActiveKeyType, MetaDat ActiveBinaryTree[ActiveKeyType, MetaDataType] ]: assert isinstance(tree, ActiveBinaryTree) - assert isinstance(tree.reference.reference, NotNull) - hash_point: HashPoint[BinaryTree[KeyMetadata[ActiveKeyType, MetaDataType]]] = tree.reference.reference.value + hash_point: HashPoint[BinaryTree[KeyMetadata[ActiveKeyType, MetaDataType]]] = tree.reference.reference.resolve() assert isinstance(hash_point, HashPoint) resolved: BinaryTree[KeyMetadata[ActiveKeyType, MetaDataType]] = hash_point.resolve() assert isinstance(resolved, BinaryTree) diff --git a/rainbowadn/data/collection/trees/binary/querybinarytree.py b/rainbowadn/data/collection/trees/binary/querybinarytree.py index b0198c3..ccce22a 100644 --- a/rainbowadn/data/collection/trees/binary/querybinarytree.py +++ b/rainbowadn/data/collection/trees/binary/querybinarytree.py @@ -27,10 +27,10 @@ class QueryBinaryTree(QueryCollectionInterface[KeyType], Generic[KeyType]): assert isinstance(key, HashPoint) reference: Nullable[HashPoint[BinaryTree[KeyType]]] = self.reference.reference assert isinstance(reference, Nullable) - if isinstance(reference, Null): + if reference.null(): return Null() - elif isinstance(reference, NotNull): - hash_point: HashPoint[BinaryTree[KeyType]] = reference.value + else: + hash_point: HashPoint[BinaryTree[KeyType]] = reference.resolve() assert isinstance(hash_point, HashPoint) tree: BinaryTree[KeyType] = hash_point.resolve() assert isinstance(tree, BinaryTree) @@ -44,5 +44,3 @@ class QueryBinaryTree(QueryCollectionInterface[KeyType], Generic[KeyType]): return QueryBinaryTree(self.comparator, tree.treer).query(key) else: raise TypeError - else: - raise TypeError diff --git a/rainbowadn/hashing/nullability/notnull.py b/rainbowadn/hashing/nullability/notnull.py index a56cdb5..6748b4b 100644 --- a/rainbowadn/hashing/nullability/notnull.py +++ b/rainbowadn/hashing/nullability/notnull.py @@ -8,11 +8,17 @@ NullableType = TypeVar('NullableType') class NotNull(Nullable[NullableType], Generic[NullableType]): + def null(self) -> bool: + return False + + def _resolve(self) -> NullableType: + return self._value + def __init__(self, value: NullableType): - self.value = value + self._value = value def __eq__(self, other): if isinstance(other, NotNull): - return self.value == other.value + return self._value == other._value else: return NotImplemented diff --git a/rainbowadn/hashing/nullability/null.py b/rainbowadn/hashing/nullability/null.py index a23232b..a472cba 100644 --- a/rainbowadn/hashing/nullability/null.py +++ b/rainbowadn/hashing/nullability/null.py @@ -8,6 +8,12 @@ NullableType = TypeVar('NullableType') class Null(Nullable[NullableType], Generic[NullableType]): + def null(self) -> bool: + return True + + def _resolve(self) -> NullableType: + raise TypeError('null') + def __eq__(self, other): if isinstance(other, Null): return True diff --git a/rainbowadn/hashing/nullability/nullable.py b/rainbowadn/hashing/nullability/nullable.py index 9261d35..4a0cc21 100644 --- a/rainbowadn/hashing/nullability/nullable.py +++ b/rainbowadn/hashing/nullability/nullable.py @@ -7,4 +7,14 @@ NullableType = TypeVar('NullableType') class Nullable(Generic[NullableType], abc.ABC): - pass + def null(self) -> bool: + """must never change""" + raise NotImplementedError + + def _resolve(self) -> NullableType: + """if .null(), throw""" + raise NotImplementedError + + def resolve(self) -> NullableType: + assert not self.null() + return self._resolve() diff --git a/rainbowadn/hashing/nullability/nullablereference.py b/rainbowadn/hashing/nullability/nullablereference.py index f472a20..696e562 100644 --- a/rainbowadn/hashing/nullability/nullablereference.py +++ b/rainbowadn/hashing/nullability/nullablereference.py @@ -20,22 +20,16 @@ class NullableReference(RecursiveMentionable, Generic[ReferencedType]): return NullableReferenceFactory(self.factory) def points(self) -> Iterable[HashPoint]: - if isinstance(self.reference, NotNull): - return [self.reference.value] - elif isinstance(self.reference, Null): + if self.reference.null(): return [] else: - raise TypeError + return [self.reference.resolve()] def __bytes__(self): - if isinstance(self.reference, NotNull): - hash_point: HashPoint[ReferencedType] = self.reference.value - assert isinstance(hash_point, HashPoint) - return hash_point.point - elif isinstance(self.reference, Null): + if self.reference.null(): return HashPoint.NULL_HASH else: - raise TypeError + return self.reference.resolve().point def __init__( self, reference: Nullable[HashPoint[ReferencedType]], factory: RainbowFactory[ReferencedType] @@ -55,12 +49,10 @@ class NullableReference(RecursiveMentionable, Generic[ReferencedType]): return cls.of(HashPoint.of(value)) def str(self, tab: int) -> str: - if isinstance(self.reference, Null): + if self.reference.null(): return f'-' - elif isinstance(self.reference, NotNull): - return f'{hash_point_format(self.reference.value, tab)}' else: - raise TypeError + return f'{hash_point_format(self.reference.resolve(), tab)}' def __eq__(self, other): if isinstance(other, NullableReference): diff --git a/rainbowadn/hashing/reduce_nullable_reference.py b/rainbowadn/hashing/reduce_nullable_reference.py index bcd9532..d6678a2 100644 --- a/rainbowadn/hashing/reduce_nullable_reference.py +++ b/rainbowadn/hashing/reduce_nullable_reference.py @@ -2,8 +2,6 @@ from typing import TypeVar from rainbowadn.hashing.hashpoint import HashPoint from rainbowadn.hashing.hashresolver import HashResolver -from rainbowadn.hashing.nullability.notnull import NotNull -from rainbowadn.hashing.nullability.null import Null from rainbowadn.hashing.nullability.nullablereference import NullableReference __all__ = ('reduce_nullable_reference',) @@ -17,9 +15,7 @@ def reduce_nullable_reference( ) -> NullableReference[ReReferencedType]: assert isinstance(reference, NullableReference) assert isinstance(resolver, HashResolver) - if isinstance(reference.reference, Null): + if reference.reference.null(): return reference.factory.from_bytes(HashPoint.NULL_HASH, resolver) - elif isinstance(reference.reference, NotNull): - return reference.reference.value.resolve() else: - raise TypeError + return reference.reference.resolve().resolve() diff --git a/rainbowadn/testing/dictresolver.py b/rainbowadn/testing/dictresolver.py new file mode 100644 index 0000000..79cbacc --- /dev/null +++ b/rainbowadn/testing/dictresolver.py @@ -0,0 +1,28 @@ +from collections import OrderedDict +from typing import MutableMapping + +from rainbowadn.hashing.hashmentionable import HashMentionable +from rainbowadn.hashing.hashpoint import HashPoint +from rainbowadn.hashing.hashresolver import HashResolver +from rainbowadn.hashing.recursivementionable import RecursiveMentionable + + +class DictResolver(HashResolver): + def __init__(self): + self.table: MutableMapping[bytes, bytes] = OrderedDict() + + def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']: + assert isinstance(point, bytes) + return self.table[point], self + + def save(self, hash_point: HashPoint) -> None: + assert isinstance(hash_point, HashPoint) + if hash_point.point in self.table: + pass + else: + value: HashMentionable = hash_point.resolve() + assert isinstance(value, HashMentionable) + self.table[hash_point.point] = HashPoint.bytes_of_mentioned(value) + if isinstance(value, RecursiveMentionable): + for hash_point in value.points(): + self.save(hash_point) diff --git a/rainbowadn/testing/test_all.py b/rainbowadn/testing/test_all.py new file mode 100644 index 0000000..2eb03fd --- /dev/null +++ b/rainbowadn/testing/test_all.py @@ -0,0 +1,163 @@ +import os +import string +import time +import unittest +from typing import Any + +import nacl.signing + +from rainbowadn.chain.blockchain import BlockChainFactory +from rainbowadn.chain.chaincollectioninterface import ChainCollectionInterface +from rainbowadn.chain.reduction.reductionchainmetafactory import ReductionChainMetaFactory +from rainbowadn.data.atomic.integer import Integer +from rainbowadn.data.atomic.plain import Plain +from rainbowadn.data.collection.trees.binary.activebinarytree import ActiveBinaryTree +from rainbowadn.data.collection.trees.binary.avl import AVLBTBP +from rainbowadn.data.collection.trees.comparison.comparator import Replace +from rainbowadn.data.collection.trees.comparison.plaincomparator import PlainComparator +from rainbowadn.encryption.encrypted import Encrypted +from rainbowadn.hashing.hashpoint import HashPoint +from rainbowadn.hashing.nullability.notnull import NotNull +from rainbowadn.hashing.resolvermetaorigin import ResolverMetaOrigin +from rainbowadn.testing.dictresolver import DictResolver +from rainbowadn.v13.algo import MINT_CONST +from rainbowadn.v13.bankchain import BankChain +from rainbowadn.v13.subject import Subject +from rainbowadn.v13.transaction import CoinData, Transaction +from rainbowadn.wrisbt.wrisbtchainprotocol import WrisbtChainProtocol +from rainbowadn.wrisbt.wrisbtparametres import WrisbtParametres +from rainbowadn.wrisbt.wrisbtroot import WrisbtRoot + + +class TestAll(unittest.TestCase): + def test_bankchain(self): + with self.subTest('setup'): + dr = DictResolver() + with self.subTest('create empty'): + bank = BankChain.empty(ReductionChainMetaFactory()) + with self.subTest('prepare transactions'): + key_0 = nacl.signing.SigningKey.generate() + transaction_0 = Transaction.make( + [], + [CoinData.of(Subject(key_0.verify_key), 1_000_000)], + [] + ) + coin_0, coin_1 = transaction_0.coins(MINT_CONST, NotNull(HashPoint.of(Subject(key_0.verify_key)))) + with self.subTest('add transactions'): + bank = bank.adds( + [ + transaction_0, + Transaction.make( + [coin_1], + [CoinData.of(Subject(nacl.signing.SigningKey.generate().verify_key), 10_000)], + [key_0] + ), + ] + ) + with self.subTest('add empty'): + bank = bank.adds( + [] + ) + print(bank) + with self.subTest('verify'): + assert bank.verify() + with self.subTest('recover'): + dr.save(HashPoint.of(bank.reference)) + bank = BankChain.from_reference( + ReductionChainMetaFactory(), ResolverMetaOrigin(dr).migrate(HashPoint.of(bank.reference)).resolve() + ) + print(bank) + with self.subTest('verify'): + assert bank.verify() + + def test_wrisbt(self): + with self.subTest('setup'): + stoptime = time.process_time() + + def measure(message: str) -> float: + nonlocal stoptime + now = time.process_time() + delta = now - stoptime + print(message, delta) + stoptime = now + return delta + + dr = DictResolver() + n = 10000 + with self.subTest('create empty'): + btree = WrisbtRoot.empty(WrisbtParametres(1, 5)) + measure('init') + with self.subTest('add keys', n=n): + for _ in range(n): + key = os.urandom(5) + assert not btree.contains(key) + btree = btree.add(key) + assert btree.contains(key) + measure('add') + with self.subTest('save'): + dr.save(HashPoint.of(btree)) + measure('save') + with self.subTest('resolve and iterate'): + btree = ResolverMetaOrigin(dr).migrate(HashPoint.of(btree)).resolve() + assert len(btree.keys()) == n + print(btree.height) + measure('resolve and iterate') + with self.subTest('resolve and add', n=n): + for _ in range(n): + key = os.urandom(5) + assert not btree.contains(key) + btree = btree.add(key) + assert btree.contains(key) + measure('resolve and add') + + def test_wrisbt_index(self): + with self.subTest('create empty'): + chain: ChainCollectionInterface[Any, Plain, WrisbtRoot] = BlockChainFactory( + WrisbtChainProtocol(Plain.factory(), 2).loose() + ).empty().loose() + with self.subTest('fill'): + for _ in range(1000): + chain = chain.add(HashPoint.of(Plain(os.urandom(16)))) + with self.subTest('check'): + assert chain + with self.subTest('measure height'): + reference = chain.actual_state().reference + assert not reference.null() + print(reference.resolve().resolve().height) + + def test_avl(self): + tree: ActiveBinaryTree[Plain, Integer] = ActiveBinaryTree.empty( + AVLBTBP(PlainComparator(Replace())), Plain.factory() + ) + for i in range(26): + tree = tree.add(HashPoint.of(Plain(bytes([ord('A') + i])))) + print(tree.reference.str(0)) + + def test_encryption(self): + with self.subTest('setup'): + key = b'a' * 32 + dr = DictResolver() + with self.subTest('create empty'): + tree: ActiveBinaryTree[Plain, Integer] = ActiveBinaryTree.empty( + AVLBTBP(PlainComparator(Replace())), Plain.factory() + ) + with self.subTest('fill'): + for char in string.ascii_uppercase: + tree = tree.add(HashPoint.of(Plain(char.encode()))) + print(tree.reference.str(0)) + with self.subTest('encrypt'): + target = tree.reference + target = Encrypted.encrypt(target, key).decrypted + print(Encrypted.ecc) + tree = tree.create(target) + print(tree.reference.str(0)) + with self.subTest('alter'): + tree = tree.add(HashPoint.of(Plain(b'NEWKEY'))) + tree = tree.remove(HashPoint.of(Plain(b'Q'))) + print(tree.reference.str(0)) + with self.subTest('encrypt'): + target = tree.reference + eeed = Encrypted.encrypt(target, key) + print(Encrypted.ecc) + dr.save(HashPoint.of(eeed)) + print(ResolverMetaOrigin(dr).migrate(HashPoint.of(eeed)).resolve().decrypted.str(0)) diff --git a/rainbowadn/v13/bankprotocol.py b/rainbowadn/v13/bankprotocol.py index 389100a..411605f 100644 --- a/rainbowadn/v13/bankprotocol.py +++ b/rainbowadn/v13/bankprotocol.py @@ -3,16 +3,15 @@ from rainbowadn.chain.reduction.reduction import Reduction from rainbowadn.chain.reduction.reductionprotocol import ReductionProtocol from rainbowadn.chain.reduction.reductionresult import ReductionResult from rainbowadn.data.atomic.integer import Integer -from rainbowadn.hashing.static import StaticFactory -from rainbowadn.data.collection.trees.binary.binarytree import BinaryTreeFactory from rainbowadn.data.collection.keymetadata import KeyMetadataFactory from rainbowadn.data.collection.stack.stack import Stack +from rainbowadn.data.collection.trees.binary.binarytree import BinaryTreeFactory from rainbowadn.hashing.hashpoint import HashPoint -from rainbowadn.hashing.nullability.notnull import NotNull from rainbowadn.hashing.nullability.null import Null from rainbowadn.hashing.nullability.nullable import Nullable from rainbowadn.hashing.nullability.nullablereference import NullableReference from rainbowadn.hashing.rainbow_factory import RainbowFactory +from rainbowadn.hashing.static import StaticFactory from rainbowadn.v13.bankstate import BankState from rainbowadn.v13.subject import Subject from rainbowadn.v13.transaction import Coin, Transaction @@ -30,17 +29,15 @@ class BankProtocol(ReductionProtocol[NullableReference[Stack[Transaction]], Bank assert isinstance(bank_state, BankState) reference: Nullable[HashPoint[Stack[Transaction]]] = reduction.reductor.resolve().reference assert isinstance(reference, Nullable) - if isinstance(reference, Null): + if reference.null(): return Reduced(HashPoint.of(bank_state.without_miner())) - elif isinstance(reference, NotNull): - stack: Stack[Transaction] = reference.value.resolve() + else: + stack: Stack[Transaction] = reference.resolve().resolve() assert isinstance(stack, Stack) return Reduction( HashPoint.of(stack.previous), HashPoint.of(bank_state.push(stack.element)) ) - else: - raise TypeError def initial(self, factory: RainbowFactory[BankState]) -> HashPoint[BankState]: assert isinstance(factory, RainbowFactory) diff --git a/rainbowadn/v13/bankstate.py b/rainbowadn/v13/bankstate.py index 614a77b..5800a8a 100644 --- a/rainbowadn/v13/bankstate.py +++ b/rainbowadn/v13/bankstate.py @@ -10,7 +10,6 @@ from rainbowadn.data.collection.trees.comparison.hashcomparator import HashCompa from rainbowadn.hashing.hash_point_format import tabulate from rainbowadn.hashing.hashpoint import HashPoint from rainbowadn.hashing.hashresolver import HashResolver -from rainbowadn.hashing.nullability.notnull import NotNull from rainbowadn.hashing.nullability.null import Null from rainbowadn.hashing.nullability.nullable import Nullable from rainbowadn.hashing.nullability.nullablereference import NullableReference, NullableReferenceFactory @@ -96,12 +95,10 @@ class BankState(RecursiveMentionable, StaticMentionable): miner: Nullable[HashPoint[Subject]] = self.miner.reference assert isinstance(miner, Nullable) - if isinstance(miner, Null): + if miner.null(): mint = MINT_CONST - elif isinstance(miner, NotNull): - mint = 0 else: - raise TypeError + mint = 0 assert transaction_resolved.verify(mint) transaction_data: TransactionData = transaction_resolved.data.resolve() @@ -119,8 +116,8 @@ class BankState(RecursiveMentionable, StaticMentionable): in_coin: HashPoint[Coin] for in_coin in transaction_data.iter_in_coins(): assert isinstance(in_coin, HashPoint) - assert isinstance(minted.query_tree().query(in_coin), NotNull) - assert isinstance(used.query_tree().query(in_coin), Null) + assert not minted.query_tree().query(in_coin).null() + assert used.query_tree().query(in_coin).null() used = used.add(in_coin) assert isinstance(used, ActiveBinaryTree) @@ -128,7 +125,7 @@ class BankState(RecursiveMentionable, StaticMentionable): for coin, miner in transaction_resolved.iter_coins(mint, miner): assert isinstance(coin, Coin) assert isinstance(miner, Nullable) - assert isinstance(minted.query_tree().query(HashPoint.of(coin)), Null) + assert minted.query_tree().query(HashPoint.of(coin)).null() minted = minted.add(HashPoint.of(coin)) assert isinstance(minted, ActiveBinaryTree) diff --git a/rainbowadn/v13/transaction.py b/rainbowadn/v13/transaction.py index 7614ab3..f7456de 100644 --- a/rainbowadn/v13/transaction.py +++ b/rainbowadn/v13/transaction.py @@ -8,7 +8,6 @@ from rainbowadn.hashing.hash_point_format import hash_point_format, tabulate from rainbowadn.hashing.hashpoint import HashPoint from rainbowadn.hashing.hashresolver import HashResolver from rainbowadn.hashing.nullability.notnull import NotNull -from rainbowadn.hashing.nullability.null import Null from rainbowadn.hashing.nullability.nullable import Nullable from rainbowadn.hashing.nullability.nullablereference import NullableReference, NullableReferenceFactory from rainbowadn.hashing.rainbow_factory import RainbowFactory @@ -143,14 +142,14 @@ class TransactionData(RecursiveMentionable, StaticMentionable): ) -> bool: assert isinstance(in_coins, NullableReference) assert isinstance(signatures, NullableReference) - if isinstance(in_coins.reference, Null): - assert isinstance(signatures.reference, Null) + if in_coins.reference.null(): + assert signatures.reference.null() return True - elif isinstance(in_coins.reference, NotNull): - assert isinstance(signatures.reference, NotNull) - in_coins_stack: Stack[Coin] = in_coins.reference.value.resolve() + else: + assert not signatures.reference.null() + in_coins_stack: Stack[Coin] = in_coins.reference.resolve().resolve() assert isinstance(in_coins_stack, Stack) - signatures_stack: Stack[Signature] = signatures.reference.value.resolve() + signatures_stack: Stack[Signature] = signatures.reference.resolve().resolve() assert isinstance(signatures_stack, Stack) coin: Coin = in_coins_stack.element.resolve() assert isinstance(coin, Coin) @@ -164,21 +163,19 @@ class TransactionData(RecursiveMentionable, StaticMentionable): owner, self.hash_point ) - else: - raise TypeError def iter_in_coins(self) -> Iterable[HashPoint[Coin]]: in_coins: NullableReference[Stack[Coin]] = self.in_coins assert isinstance(in_coins, NullableReference) - while isinstance(in_coins.reference, NotNull): - in_coins_stack: Stack[Coin] = in_coins.reference.value.resolve() + while not in_coins.reference.null(): + in_coins_stack: Stack[Coin] = in_coins.reference.resolve().resolve() assert isinstance(in_coins_stack, Stack) coin: HashPoint[Coin] = in_coins_stack.element assert isinstance(coin, HashPoint) yield coin in_coins = in_coins_stack.previous assert isinstance(in_coins, NullableReference) - assert isinstance(in_coins.reference, Null) + assert in_coins.reference.null() def _total_in(self) -> int: total_in = 0 @@ -191,15 +188,15 @@ class TransactionData(RecursiveMentionable, StaticMentionable): def iter_out_coins(self) -> Iterable[HashPoint[CoinData]]: out_coins: NullableReference[Stack[CoinData]] = self.out_coins assert isinstance(out_coins, NullableReference) - while isinstance(out_coins.reference, NotNull): - out_coins_stack: Stack[CoinData] = out_coins.reference.value.resolve() + while not out_coins.reference.null(): + out_coins_stack: Stack[CoinData] = out_coins.reference.resolve().resolve() assert isinstance(out_coins_stack, Stack) coin: HashPoint[CoinData] = out_coins_stack.element assert isinstance(coin, HashPoint) yield coin out_coins = out_coins_stack.previous assert isinstance(out_coins, NullableReference) - assert isinstance(out_coins.reference, Null) + assert out_coins.reference.null() def _total_out(self) -> int: total_out = 0 @@ -278,18 +275,18 @@ class Transaction(RecursiveMentionable, StaticMentionable): out_coin: HashPoint[CoinData] for out_coin in transaction_data.iter_out_coins(): assert isinstance(out_coin, HashPoint) - if isinstance(miner, Null): + if miner.null(): miner = NotNull(out_coin.resolve().owner) assert isinstance(miner, Nullable) coin: Coin = Coin(out_coin, self.hash_point, HashPoint.of(Integer(index))) assert isinstance(coin, Coin) yield coin, miner index += 1 - if isinstance(miner, NotNull): + if not miner.null(): coin: Coin = Coin( HashPoint.of( CoinData( - miner.value, + miner.resolve(), HashPoint.of(Integer(transaction_data.extra(mint))) ) ), diff --git a/rainbowadn/wrisbt/wrisbtprotocol.py b/rainbowadn/wrisbt/wrisbtprotocol.py index 7140527..10e5c95 100644 --- a/rainbowadn/wrisbt/wrisbtprotocol.py +++ b/rainbowadn/wrisbt/wrisbtprotocol.py @@ -1,6 +1,6 @@ from typing import TypeVar -from rainbowadn.chain.states.activestateprotocol import ActiveStateProtocol +from rainbowadn.chain.states.metareductionstateprotocol import MetaReductionStateProtocol from rainbowadn.hashing.hashpoint import HashPoint from rainbowadn.wrisbt.wrisbtindex import WrisbtIndex from rainbowadn.wrisbt.wrisbtparametres import WrisbtParametres @@ -11,7 +11,7 @@ __all__ = ('WrisbtProtocol',) TargetType = TypeVar('TargetType') -class WrisbtProtocol(ActiveStateProtocol[TargetType, WrisbtIndex]): +class WrisbtProtocol(MetaReductionStateProtocol[TargetType, WrisbtIndex]): def __init__(self, keymin: int): assert isinstance(keymin, int) assert keymin >= 2