async
This commit is contained in:
parent
69297cdac1
commit
cf727d87b0
@ -40,15 +40,15 @@ class Block(RecursiveMentionable, Generic[HeaderType, StateType]):
|
||||
self.state.factory,
|
||||
)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'{self.previous.str(tab)}' \
|
||||
return f'{await self.previous.str(tab)}' \
|
||||
f'{tabulate(tab)}(' \
|
||||
f'{tabulate(tab + 1)}block' \
|
||||
f'{tabulate(tab + 1)}(header)' \
|
||||
f'{tabulate(tab + 1)}{hash_point_format(self.header, tab + 1)}' \
|
||||
f'{tabulate(tab + 1)}{await hash_point_format(self.header, tab + 1)}' \
|
||||
f'{tabulate(tab + 1)}(state)' \
|
||||
f'{tabulate(tab + 1)}{hash_point_format(self.state, tab + 1)}' \
|
||||
f'{tabulate(tab + 1)}{await hash_point_format(self.state, tab + 1)}' \
|
||||
f'{tabulate(tab)})'
|
||||
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
import asyncio
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
from rainbowadn.chain.block import Block, BlockFactory
|
||||
from rainbowadn.chain.blockchainprotocol import BlockChainProtocol
|
||||
from rainbowadn.chain.chaincollectionfactory import ChainCollectionFactory
|
||||
from rainbowadn.chain.chaincollectioninterface import ChainCollectionInterface
|
||||
from rainbowadn.core.asserts import assert_eq, assert_true
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.nullability.null import Null
|
||||
from rainbowadn.core.nullability.nullablereference import NullableReference
|
||||
@ -52,7 +54,7 @@ class BlockChain(
|
||||
]:
|
||||
return BlockChainFactory(self.protocol)
|
||||
|
||||
def add(
|
||||
async def add(
|
||||
self,
|
||||
header: HashPoint[HeaderType]
|
||||
) -> ChainCollectionInterface[
|
||||
@ -66,11 +68,11 @@ class BlockChain(
|
||||
assert isinstance(header, HashPoint)
|
||||
return self.factory().from_reference(
|
||||
NullableReference.off(
|
||||
self._add(header)
|
||||
await self._add(header)
|
||||
)
|
||||
)
|
||||
|
||||
def state(
|
||||
async def state(
|
||||
self
|
||||
) -> NullableReference[
|
||||
StateType
|
||||
@ -81,11 +83,11 @@ class BlockChain(
|
||||
self.protocol.state_factory
|
||||
)
|
||||
else:
|
||||
block: Block[HeaderType, StateType] = self.reference.resolve()
|
||||
block: Block[HeaderType, StateType] = await self.reference.resolve()
|
||||
assert isinstance(block, Block)
|
||||
return NullableReference.of(block.state)
|
||||
|
||||
def _add(
|
||||
async def _add(
|
||||
self,
|
||||
header: HashPoint[HeaderType]
|
||||
) -> Block[
|
||||
@ -96,13 +98,13 @@ class BlockChain(
|
||||
return Block(
|
||||
self.reference,
|
||||
header,
|
||||
self.protocol.state_protocol.derive(
|
||||
self.state(),
|
||||
await self.protocol.state_protocol.derive(
|
||||
await self.state(),
|
||||
header,
|
||||
)
|
||||
)
|
||||
|
||||
def previous(
|
||||
async def previous(
|
||||
self
|
||||
) -> ChainCollectionInterface[
|
||||
Block[
|
||||
@ -116,19 +118,22 @@ class BlockChain(
|
||||
block: Block[
|
||||
HeaderType,
|
||||
StateType
|
||||
] = self.reference.resolve()
|
||||
] = await self.reference.resolve()
|
||||
assert isinstance(block, Block)
|
||||
return self.factory().from_reference(block.previous)
|
||||
|
||||
def verify(self) -> bool:
|
||||
async def verify(self) -> bool:
|
||||
if self.reference.null():
|
||||
return True
|
||||
else:
|
||||
assert self.verify_link(self.previous().reference)
|
||||
assert self.previous().verify()
|
||||
previous: ChainCollectionInterface[
|
||||
Block[HeaderType, StateType], HeaderType, ActualStateType
|
||||
] = await self.previous()
|
||||
assert_true(await self.verify_link(previous.reference))
|
||||
assert_true(await asyncio.create_task(previous.verify()))
|
||||
return True
|
||||
|
||||
def _verify_link(
|
||||
async def _verify_link(
|
||||
self,
|
||||
block: Block[
|
||||
HeaderType,
|
||||
@ -143,20 +148,22 @@ class BlockChain(
|
||||
) -> bool:
|
||||
assert isinstance(block, Block)
|
||||
assert isinstance(previous, NullableReference)
|
||||
assert block.previous == previous
|
||||
assert_eq(block.previous, previous)
|
||||
previous_chain = self.factory().from_reference(previous)
|
||||
assert isinstance(previous_chain, BlockChain)
|
||||
assert self.protocol.state_protocol.verify(
|
||||
previous_chain.state(),
|
||||
assert_true(
|
||||
await self.protocol.state_protocol.verify(
|
||||
await previous_chain.state(),
|
||||
block.header,
|
||||
block.state,
|
||||
)
|
||||
)
|
||||
return True
|
||||
|
||||
def _actual_state_factory(self) -> RainbowFactory[ActualStateType]:
|
||||
return self.protocol.actual_state_factory()
|
||||
|
||||
def _actual_state(
|
||||
async def _actual_state(
|
||||
self,
|
||||
block: Block[
|
||||
HeaderType,
|
||||
@ -164,7 +171,7 @@ class BlockChain(
|
||||
]
|
||||
) -> HashPoint[ActualStateType]:
|
||||
assert isinstance(block, Block)
|
||||
return self.protocol.actual_state(block.state.resolve())
|
||||
return await self.protocol.actual_state(await block.state.resolve())
|
||||
|
||||
def loose(self) -> ChainCollectionInterface[
|
||||
Block[
|
||||
|
@ -30,7 +30,7 @@ class BlockChainProtocol(
|
||||
def actual_state_factory(self) -> RainbowFactory[ActualStateType]:
|
||||
raise NotImplementedError
|
||||
|
||||
def actual_state(
|
||||
async def actual_state(
|
||||
self,
|
||||
state: StateType
|
||||
) -> HashPoint[ActualStateType]:
|
||||
|
@ -26,14 +26,14 @@ class BlockCollectionInterface(
|
||||
assert isinstance(reference, NullableReference)
|
||||
super().__init__(reference)
|
||||
|
||||
def _verify_link(
|
||||
async def _verify_link(
|
||||
self,
|
||||
block: BlockType,
|
||||
previous: NullableReference[BlockType]
|
||||
) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
def verify_link(
|
||||
async def verify_link(
|
||||
self,
|
||||
previous: NullableReference[BlockType]
|
||||
) -> bool:
|
||||
@ -41,24 +41,24 @@ class BlockCollectionInterface(
|
||||
if self.reference.null():
|
||||
return True
|
||||
else:
|
||||
return self._verify_link(
|
||||
self.reference.resolve(),
|
||||
return await self._verify_link(
|
||||
await self.reference.resolve(),
|
||||
previous
|
||||
)
|
||||
|
||||
def _actual_state_factory(self) -> RainbowFactory[ActualStateType]:
|
||||
raise NotImplementedError
|
||||
|
||||
def _actual_state(self, block: BlockType) -> HashPoint[ActualStateType]:
|
||||
async def _actual_state(self, block: BlockType) -> HashPoint[ActualStateType]:
|
||||
raise NotImplementedError
|
||||
|
||||
def actual_state(self) -> NullableReference[ActualStateType]:
|
||||
async def actual_state(self) -> NullableReference[ActualStateType]:
|
||||
if self.reference.null():
|
||||
return NullableReference(Null(), self._actual_state_factory())
|
||||
else:
|
||||
return NullableReference.of(self._actual_state(self.reference.resolve()))
|
||||
return NullableReference.of(await self._actual_state(await self.reference.resolve()))
|
||||
|
||||
def add(
|
||||
async def add(
|
||||
self,
|
||||
header: HashPoint[HeaderType]
|
||||
) -> 'BlockCollectionInterface[BlockType, HeaderType, ActualStateType]':
|
||||
|
@ -20,8 +20,11 @@ class ChainCollectionInterface(
|
||||
Generic[BlockType, HeaderType, ActualStateType],
|
||||
abc.ABC
|
||||
):
|
||||
def add(self, header: HashPoint[HeaderType]) -> 'ChainCollectionInterface[BlockType, HeaderType, ActualStateType]':
|
||||
async def add(
|
||||
self,
|
||||
header: HashPoint[HeaderType]
|
||||
) -> 'ChainCollectionInterface[BlockType, HeaderType, ActualStateType]':
|
||||
raise NotImplementedError
|
||||
|
||||
def verify(self) -> bool:
|
||||
async def verify(self) -> bool:
|
||||
raise NotImplementedError
|
||||
|
@ -34,10 +34,10 @@ class Reduction(
|
||||
def __factory__(self) -> RainbowFactory['Reduction[ReductorType, AccumulatorType]']:
|
||||
return ReductionFactory(self.reductor.factory, self.accumulator.factory)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'(reduction)' \
|
||||
f'{tabulate(tab)}{hash_point_format(self.accumulator, tab)}'
|
||||
f'{tabulate(tab)}{await hash_point_format(self.accumulator, tab)}'
|
||||
|
||||
|
||||
class ReductionFactory(
|
||||
|
@ -50,3 +50,13 @@ class ReductionChainMetaFactory(
|
||||
accumulator_factory,
|
||||
)
|
||||
)
|
||||
|
||||
def loose(self) -> AbstractReductionChainMetaFactory[
|
||||
Block[
|
||||
ReductorType,
|
||||
StateStage[ReductorType, AccumulatorType, Reduction[ReductorType, AccumulatorType]]
|
||||
],
|
||||
ReductorType,
|
||||
AccumulatorType
|
||||
]:
|
||||
return self
|
||||
|
@ -66,7 +66,7 @@ class ReductionChainProtocol(
|
||||
def actual_state_factory(self) -> RainbowFactory[AccumulatorType]:
|
||||
return self.accumulator_factory
|
||||
|
||||
def actual_state(
|
||||
async def actual_state(
|
||||
self,
|
||||
state: StateStage[
|
||||
ReductorType,
|
||||
|
@ -12,7 +12,7 @@ AccumulatorType = TypeVar('AccumulatorType')
|
||||
|
||||
|
||||
class ReductionProtocol(Generic[ReductorType, AccumulatorType]):
|
||||
def reduce(
|
||||
async def reduce(
|
||||
self,
|
||||
reduction: Reduction[ReductorType, AccumulatorType]
|
||||
) -> ReductionResult[ReductorType, AccumulatorType]:
|
||||
@ -21,7 +21,7 @@ class ReductionProtocol(Generic[ReductorType, AccumulatorType]):
|
||||
def initial(self, factory: RainbowFactory[AccumulatorType]) -> HashPoint[AccumulatorType]:
|
||||
raise NotImplementedError
|
||||
|
||||
def header_filter(
|
||||
async def header_filter(
|
||||
self,
|
||||
state: HashPoint[AccumulatorType]
|
||||
) -> HashPoint[AccumulatorType]:
|
||||
|
@ -26,7 +26,7 @@ class ReductionStageProtocol(
|
||||
self.protocol = protocol
|
||||
super().__init__()
|
||||
|
||||
def _derive_accumulator(
|
||||
async def _derive_accumulator(
|
||||
self,
|
||||
previous: NullableReference[AccumulatorType],
|
||||
) -> HashPoint[AccumulatorType]:
|
||||
@ -34,9 +34,9 @@ class ReductionStageProtocol(
|
||||
if previous.null():
|
||||
return self.protocol.initial(previous.factory)
|
||||
else:
|
||||
return self.protocol.header_filter(previous.hashpoint())
|
||||
return await self.protocol.header_filter(previous.hashpoint())
|
||||
|
||||
def derive_header(
|
||||
async def derive_header(
|
||||
self,
|
||||
previous: NullableReference[AccumulatorType],
|
||||
header: HashPoint[ReductorType]
|
||||
@ -46,7 +46,7 @@ class ReductionStageProtocol(
|
||||
return HashPoint.of(
|
||||
Reduction(
|
||||
header,
|
||||
self._derive_accumulator(previous)
|
||||
await self._derive_accumulator(previous)
|
||||
)
|
||||
)
|
||||
|
||||
@ -63,9 +63,9 @@ class ReductionStageProtocol(
|
||||
else:
|
||||
raise TypeError
|
||||
|
||||
def derive_stage_or_state(
|
||||
async def derive_stage_or_state(
|
||||
self,
|
||||
stage: HashPoint[Reduction[ReductorType, AccumulatorType]]
|
||||
) -> Derived[ReductorType, Reduction[ReductorType, AccumulatorType]]:
|
||||
assert isinstance(stage, HashPoint)
|
||||
return self._derived_from_reduced(self.protocol.reduce(stage.resolve()))
|
||||
return self._derived_from_reduced(await self.protocol.reduce(await stage.resolve()))
|
||||
|
@ -5,6 +5,7 @@ from rainbowadn.chain.stages.derivation.derivedstage import DerivedStage
|
||||
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.core.asserts import assert_eq
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.nullability.null import Null
|
||||
from rainbowadn.core.nullability.nullablereference import NullableReference
|
||||
@ -21,21 +22,21 @@ class ActiveStageProtocol(
|
||||
StageProtocol[HeaderType, BaseStateType, StageType],
|
||||
Generic[HeaderType, BaseStateType, StageType]
|
||||
):
|
||||
def derive_header(
|
||||
async def derive_header(
|
||||
self,
|
||||
previous: NullableReference[BaseStateType],
|
||||
header: HashPoint[HeaderType],
|
||||
) -> HashPoint[StageType]:
|
||||
raise NotImplementedError
|
||||
|
||||
def derive_stage_or_state(
|
||||
async def derive_stage_or_state(
|
||||
self,
|
||||
stage: HashPoint[StageType],
|
||||
) -> Derived[BaseStateType, StageType]:
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def _previous_base_state(
|
||||
async def _previous_base_state(
|
||||
cls,
|
||||
previous_reference: NullableReference[StateStage[HeaderType, BaseStateType, StageType]],
|
||||
base_state_factory: RainbowFactory[BaseStateType],
|
||||
@ -45,11 +46,11 @@ class ActiveStageProtocol(
|
||||
if previous_reference.null():
|
||||
return NullableReference(Null(), base_state_factory)
|
||||
else:
|
||||
previous_state_stage: StateStage[HeaderType, BaseStateType, StageType] = previous_reference.resolve()
|
||||
previous_state_stage: StateStage[HeaderType, BaseStateType, StageType] = await previous_reference.resolve()
|
||||
assert isinstance(previous_state_stage, StateStage)
|
||||
return NullableReference.of(previous_state_stage.state)
|
||||
|
||||
def _derive_cycle(
|
||||
async def _derive_cycle(
|
||||
self,
|
||||
stage: StageStage[HeaderType, BaseStateType, StageType],
|
||||
stage_factory: RainbowFactory[StageType]
|
||||
@ -57,7 +58,7 @@ class ActiveStageProtocol(
|
||||
assert isinstance(stage, StageStage)
|
||||
assert isinstance(stage_factory, RainbowFactory)
|
||||
while True:
|
||||
derived = self.derive_stage_or_state(stage.stage)
|
||||
derived: Derived[BaseStateType, StageType] = await self.derive_stage_or_state(stage.stage)
|
||||
assert isinstance(derived, Derived)
|
||||
if isinstance(derived, DerivedStage):
|
||||
stage = StageStage(self, NullableReference.off(stage), derived.stage)
|
||||
@ -67,7 +68,7 @@ class ActiveStageProtocol(
|
||||
else:
|
||||
raise TypeError
|
||||
|
||||
def _derive_initial_stage(
|
||||
async def _derive_initial_stage(
|
||||
self,
|
||||
previous: NullableReference[BaseStateType],
|
||||
header: HashPoint[HeaderType],
|
||||
@ -85,10 +86,10 @@ class ActiveStageProtocol(
|
||||
stage_factory
|
||||
)
|
||||
),
|
||||
self.derive_header(previous, header)
|
||||
await self.derive_header(previous, header)
|
||||
)
|
||||
|
||||
def derive_full(
|
||||
async def derive_full(
|
||||
self,
|
||||
previous_reference: NullableReference[StateStage[HeaderType, BaseStateType, StageType]],
|
||||
header: HashPoint[HeaderType],
|
||||
@ -99,9 +100,9 @@ class ActiveStageProtocol(
|
||||
assert isinstance(header, HashPoint)
|
||||
assert isinstance(base_state_factory, RainbowFactory)
|
||||
assert isinstance(stage_factory, RainbowFactory)
|
||||
return self._derive_cycle(
|
||||
self._derive_initial_stage(
|
||||
self._previous_base_state(
|
||||
return await self._derive_cycle(
|
||||
await self._derive_initial_stage(
|
||||
await self._previous_base_state(
|
||||
previous_reference,
|
||||
base_state_factory
|
||||
),
|
||||
@ -111,7 +112,7 @@ class ActiveStageProtocol(
|
||||
stage_factory
|
||||
)
|
||||
|
||||
def verify_header(
|
||||
async def verify_header(
|
||||
self,
|
||||
previous: NullableReference[BaseStateType],
|
||||
header: HashPoint[HeaderType],
|
||||
@ -120,35 +121,35 @@ class ActiveStageProtocol(
|
||||
assert isinstance(previous, NullableReference)
|
||||
assert isinstance(header, HashPoint)
|
||||
assert isinstance(stage, HashPoint)
|
||||
assert stage == self.derive_header(previous, header)
|
||||
assert_eq(stage, await self.derive_header(previous, header))
|
||||
return True
|
||||
|
||||
def verify_stage(
|
||||
async def verify_stage(
|
||||
self,
|
||||
previous: HashPoint[StageType],
|
||||
stage: HashPoint[StageType]
|
||||
) -> bool:
|
||||
assert isinstance(previous, HashPoint)
|
||||
assert isinstance(stage, HashPoint)
|
||||
derived = self.derive_stage_or_state(previous)
|
||||
derived: Derived[BaseStateType, StageType] = await self.derive_stage_or_state(previous)
|
||||
assert isinstance(derived, Derived)
|
||||
if isinstance(derived, DerivedStage):
|
||||
assert stage == derived.stage
|
||||
assert_eq(stage, derived.stage)
|
||||
return True
|
||||
else:
|
||||
raise TypeError
|
||||
|
||||
def verify_state(
|
||||
async def verify_state(
|
||||
self,
|
||||
stage: HashPoint[StageType],
|
||||
state: HashPoint[BaseStateType]
|
||||
) -> bool:
|
||||
assert isinstance(stage, HashPoint)
|
||||
assert isinstance(state, HashPoint)
|
||||
derived = self.derive_stage_or_state(stage)
|
||||
derived: Derived[BaseStateType, StageType] = await self.derive_stage_or_state(stage)
|
||||
assert isinstance(derived, Derived)
|
||||
if isinstance(derived, DerivedState):
|
||||
assert state == derived.state
|
||||
assert_eq(state, derived.state)
|
||||
return True
|
||||
else:
|
||||
raise TypeError
|
||||
|
@ -37,7 +37,7 @@ class ActiveStageStateProtocol(
|
||||
self.stage_factory = stage_factory
|
||||
self.base_state_factory = base_state_factory
|
||||
|
||||
def derive(
|
||||
async def derive(
|
||||
self,
|
||||
previous: NullableReference[
|
||||
StateStage[
|
||||
@ -56,7 +56,7 @@ class ActiveStageStateProtocol(
|
||||
]:
|
||||
assert isinstance(previous, NullableReference)
|
||||
assert isinstance(header, HashPoint)
|
||||
return self.protocol.derive_full(
|
||||
return await self.protocol.derive_full(
|
||||
previous,
|
||||
header,
|
||||
self.base_state_factory,
|
||||
|
@ -1,6 +1,7 @@
|
||||
from typing import Generic, Iterable, TypeVar
|
||||
|
||||
from rainbowadn.chain.stages.stageprotocol import StageProtocol
|
||||
from rainbowadn.core.asserts import assert_true
|
||||
from rainbowadn.core.hash_point_format import hash_point_format, tabulate
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.hashresolver import HashResolver
|
||||
@ -47,7 +48,7 @@ class StageStage(
|
||||
self.stage = stage
|
||||
|
||||
@classmethod
|
||||
def _previous_state(
|
||||
async def _previous_state(
|
||||
cls,
|
||||
previous: NullableReference['StateStage[HeaderType, BaseStateType, StageType]'],
|
||||
base_factory: RainbowFactory[BaseStateType],
|
||||
@ -57,11 +58,11 @@ class StageStage(
|
||||
if previous.null():
|
||||
return NullableReference(Null(), base_factory)
|
||||
else:
|
||||
state_stage: StateStage[HeaderType, BaseStateType, StageType] = previous.resolve()
|
||||
state_stage: StateStage[HeaderType, BaseStateType, StageType] = await previous.resolve()
|
||||
assert isinstance(state_stage, StateStage)
|
||||
return NullableReference.of(state_stage.state)
|
||||
|
||||
def verify(
|
||||
async def verify(
|
||||
self,
|
||||
previous: NullableReference['StateStage[HeaderType, BaseStateType, StageType]'],
|
||||
header: HashPoint[HeaderType],
|
||||
@ -71,22 +72,28 @@ class StageStage(
|
||||
assert isinstance(header, HashPoint)
|
||||
assert isinstance(base_factory, RainbowFactory)
|
||||
if self.previous.null():
|
||||
return self.protocol.verify_header(
|
||||
self._previous_state(previous, base_factory),
|
||||
return await self.protocol.verify_header(
|
||||
await self._previous_state(previous, base_factory),
|
||||
header,
|
||||
self.stage
|
||||
)
|
||||
else:
|
||||
previous_stage: StageStage[HeaderType, BaseStateType, StageType] = self.previous.resolve()
|
||||
previous_stage: StageStage[HeaderType, BaseStateType, StageType] = await self.previous.resolve()
|
||||
assert isinstance(previous_stage, StageStage)
|
||||
return self.protocol.verify_stage(
|
||||
assert_true(
|
||||
await self.protocol.verify_stage(
|
||||
previous_stage.stage,
|
||||
self.stage
|
||||
) and previous_stage.verify(
|
||||
)
|
||||
)
|
||||
assert_true(
|
||||
await previous_stage.verify(
|
||||
previous,
|
||||
header,
|
||||
base_factory
|
||||
)
|
||||
)
|
||||
return True
|
||||
|
||||
def points(self) -> Iterable[HashPoint]:
|
||||
return [*self.previous.points(), self.stage]
|
||||
@ -100,10 +107,10 @@ class StageStage(
|
||||
self.stage.factory
|
||||
)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'{self.previous.str(tab)}' \
|
||||
f'{tabulate(tab)}{hash_point_format(self.stage, tab)}'
|
||||
return f'{await self.previous.str(tab)}' \
|
||||
f'{tabulate(tab)}{await hash_point_format(self.stage, tab)}'
|
||||
|
||||
|
||||
class StageStageFactory(RainbowFactory[StageStage[HeaderType, BaseStateType, StageType]]):
|
||||
@ -148,23 +155,29 @@ class StateStage(
|
||||
self.state = state
|
||||
self.stage_factory = stage_factory
|
||||
|
||||
def verify(
|
||||
async def verify(
|
||||
self,
|
||||
previous: NullableReference['StateStage[HeaderType, BaseStateType, StageType]'],
|
||||
header: HashPoint[HeaderType]
|
||||
) -> bool:
|
||||
assert isinstance(previous, NullableReference)
|
||||
assert isinstance(header, HashPoint)
|
||||
previous_stage: StageStage[HeaderType, BaseStateType, StageType] = self.previous.resolve()
|
||||
previous_stage: StageStage[HeaderType, BaseStateType, StageType] = await self.previous.resolve()
|
||||
assert isinstance(previous_stage, StageStage)
|
||||
return self.protocol.verify_state(
|
||||
assert_true(
|
||||
await self.protocol.verify_state(
|
||||
previous_stage.stage,
|
||||
self.state
|
||||
) and previous_stage.verify(
|
||||
)
|
||||
)
|
||||
assert_true(
|
||||
await previous_stage.verify(
|
||||
previous,
|
||||
header,
|
||||
self.state.factory
|
||||
)
|
||||
)
|
||||
return True
|
||||
|
||||
def points(self) -> Iterable[HashPoint]:
|
||||
return [self.previous, self.state]
|
||||
@ -179,10 +192,10 @@ class StateStage(
|
||||
self.state.factory
|
||||
)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'{hash_point_format(self.previous, tab)}' \
|
||||
f'{tabulate(tab)}{hash_point_format(self.state, tab)}'
|
||||
return f'{await hash_point_format(self.previous, tab)}' \
|
||||
f'{tabulate(tab)}{await hash_point_format(self.state, tab)}'
|
||||
|
||||
|
||||
class StateStageFactory(RainbowFactory[StateStage[HeaderType, BaseStateType, StageType]]):
|
||||
|
@ -11,7 +11,7 @@ StageType = TypeVar('StageType')
|
||||
|
||||
|
||||
class StageProtocol(Generic[HeaderType, BaseStateType, StageType]):
|
||||
def verify_header(
|
||||
async def verify_header(
|
||||
self,
|
||||
previous: NullableReference[BaseStateType],
|
||||
header: HashPoint[HeaderType],
|
||||
@ -19,14 +19,14 @@ class StageProtocol(Generic[HeaderType, BaseStateType, StageType]):
|
||||
) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
def verify_stage(
|
||||
async def verify_stage(
|
||||
self,
|
||||
previous: HashPoint[StageType],
|
||||
stage: HashPoint[StageType]
|
||||
) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
def verify_state(
|
||||
async def verify_state(
|
||||
self,
|
||||
stage: HashPoint[StageType],
|
||||
state: HashPoint[BaseStateType]
|
||||
|
@ -2,6 +2,7 @@ from typing import Generic, TypeVar
|
||||
|
||||
from rainbowadn.chain.stages.stage import StateStage
|
||||
from rainbowadn.chain.states.stateprotocol import StateProtocol
|
||||
from rainbowadn.core.asserts import assert_true
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.nullability.nullablereference import NullableReference
|
||||
|
||||
@ -16,7 +17,7 @@ class StageStateProtocol(
|
||||
StateProtocol[HeaderType, StateStage[HeaderType, BaseStateType, StageType]],
|
||||
Generic[HeaderType, BaseStateType, StageType]
|
||||
):
|
||||
def verify(
|
||||
async def verify(
|
||||
self,
|
||||
previous: NullableReference[StateStage[HeaderType, BaseStateType, StageType]],
|
||||
header: HashPoint[HeaderType],
|
||||
@ -25,4 +26,5 @@ class StageStateProtocol(
|
||||
assert isinstance(previous, NullableReference)
|
||||
assert isinstance(header, HashPoint)
|
||||
assert isinstance(state, HashPoint)
|
||||
return state.resolve().verify(previous, header)
|
||||
assert_true(await (await state.resolve()).verify(previous, header))
|
||||
return True
|
||||
|
@ -1,6 +1,7 @@
|
||||
from typing import TypeVar
|
||||
|
||||
from rainbowadn.chain.states.stateprotocol import StateProtocol
|
||||
from rainbowadn.core.asserts import assert_eq
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.nullability.nullablereference import NullableReference
|
||||
|
||||
@ -11,7 +12,7 @@ StateType = TypeVar('StateType')
|
||||
|
||||
|
||||
class ActiveStateProtocol(StateProtocol[HeaderType, StateType]):
|
||||
def verify(
|
||||
async def verify(
|
||||
self,
|
||||
previous: NullableReference[StateType],
|
||||
header: HashPoint[HeaderType],
|
||||
@ -20,10 +21,10 @@ class ActiveStateProtocol(StateProtocol[HeaderType, StateType]):
|
||||
assert isinstance(previous, NullableReference)
|
||||
assert isinstance(header, HashPoint)
|
||||
assert isinstance(state, HashPoint)
|
||||
assert state == self.derive(previous, header)
|
||||
assert_eq(state, await self.derive(previous, header))
|
||||
return True
|
||||
|
||||
def derive(
|
||||
async def derive(
|
||||
self,
|
||||
previous: NullableReference[StateType],
|
||||
header: HashPoint[HeaderType],
|
||||
|
@ -1,6 +1,7 @@
|
||||
from typing import TypeVar
|
||||
|
||||
from rainbowadn.chain.states.activestateprotocol import ActiveStateProtocol
|
||||
from rainbowadn.core.asserts import assert_eq
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.nullability.nullablereference import NullableReference
|
||||
|
||||
@ -11,7 +12,7 @@ StateType = TypeVar('StateType')
|
||||
|
||||
|
||||
class MetaReductionStateProtocol(ActiveStateProtocol[HeaderType, StateType]):
|
||||
def verify(
|
||||
async def verify(
|
||||
self,
|
||||
previous: NullableReference[StateType],
|
||||
header: HashPoint[HeaderType],
|
||||
@ -20,20 +21,20 @@ class MetaReductionStateProtocol(ActiveStateProtocol[HeaderType, StateType]):
|
||||
assert isinstance(previous, NullableReference)
|
||||
assert isinstance(header, HashPoint)
|
||||
assert isinstance(state, HashPoint)
|
||||
assert state == self.derive(previous, header)
|
||||
assert_eq(state, await self.derive(previous, header))
|
||||
return True
|
||||
|
||||
def _initial_state(self) -> HashPoint[StateType]:
|
||||
raise NotImplementedError
|
||||
|
||||
def _derive(
|
||||
async def _derive(
|
||||
self,
|
||||
previous: HashPoint[StateType],
|
||||
header: HashPoint[HeaderType],
|
||||
) -> HashPoint[StateType]:
|
||||
raise NotImplementedError
|
||||
|
||||
def derive(
|
||||
async def derive(
|
||||
self,
|
||||
previous: NullableReference[StateType],
|
||||
header: HashPoint[HeaderType],
|
||||
@ -45,4 +46,4 @@ class MetaReductionStateProtocol(ActiveStateProtocol[HeaderType, StateType]):
|
||||
else:
|
||||
previous_state: HashPoint[StateType] = previous.hashpoint()
|
||||
assert isinstance(previous_state, HashPoint)
|
||||
return self._derive(previous_state, header)
|
||||
return await self._derive(previous_state, header)
|
||||
|
@ -10,7 +10,7 @@ StateType = TypeVar('StateType')
|
||||
|
||||
|
||||
class StateProtocol(Generic[HeaderType, StateType]):
|
||||
def verify(
|
||||
async def verify(
|
||||
self,
|
||||
previous: NullableReference[StateType],
|
||||
header: HashPoint[HeaderType],
|
||||
|
24
rainbowadn/core/asserts.py
Normal file
24
rainbowadn/core/asserts.py
Normal file
@ -0,0 +1,24 @@
|
||||
from typing import Optional, TypeVar
|
||||
|
||||
|
||||
def assert_true(value: bool) -> bool:
|
||||
assert value is True
|
||||
return True
|
||||
|
||||
|
||||
def assert_false(value: bool) -> bool:
|
||||
assert value is False
|
||||
return True
|
||||
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
def assert_none(value: Optional[T]) -> bool:
|
||||
assert value is None
|
||||
return True
|
||||
|
||||
|
||||
def assert_eq(value: T, other: T) -> bool:
|
||||
assert value == other
|
||||
return True
|
20
rainbowadn/core/extendableresolver.py
Normal file
20
rainbowadn/core/extendableresolver.py
Normal file
@ -0,0 +1,20 @@
|
||||
import abc
|
||||
from typing import TypeVar
|
||||
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.hashresolver import HashResolver
|
||||
from rainbowadn.core.resolvermetaorigin import ResolverMetaOrigin
|
||||
|
||||
Mentioned = TypeVar('Mentioned')
|
||||
|
||||
|
||||
class ExtendableResolver(HashResolver, abc.ABC):
|
||||
async def extend(self, hash_point: HashPoint[Mentioned]) -> 'ExtendableResolver':
|
||||
raise NotImplementedError
|
||||
|
||||
async def migrate(self, hash_point: HashPoint[Mentioned]) -> HashPoint[Mentioned]:
|
||||
assert isinstance(hash_point, HashPoint)
|
||||
return ResolverMetaOrigin(await self.extend(hash_point)).hash_point(hash_point.factory, hash_point.point)
|
||||
|
||||
async def migrate_resolved(self, mentioned: Mentioned) -> Mentioned:
|
||||
return await (await self.migrate(HashPoint.of(mentioned))).resolve()
|
@ -1,15 +1,16 @@
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.mentionable import Mentionable
|
||||
from rainbowadn.core.recursivementionable import RecursiveMentionable
|
||||
|
||||
__all__ = ('hash_point_format', 'tabulate',)
|
||||
|
||||
|
||||
def hash_point_format(hash_point: HashPoint, tab: int) -> str:
|
||||
async def hash_point_format(hash_point: HashPoint, tab: int) -> str:
|
||||
assert isinstance(hash_point, HashPoint)
|
||||
assert isinstance(tab, int)
|
||||
value = hash_point.resolve()
|
||||
value: Mentionable = await hash_point.resolve()
|
||||
if isinstance(value, RecursiveMentionable):
|
||||
return value.str(tab)
|
||||
return await value.str(tab)
|
||||
else:
|
||||
return str(value)
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import hashlib
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
from rainbowadn.core.asserts import assert_eq
|
||||
from rainbowadn.core.localorigin import LocalOrigin
|
||||
from rainbowadn.core.mentionable import Mentionable
|
||||
from rainbowadn.core.origin import Origin
|
||||
@ -24,7 +25,7 @@ class HashPoint(Generic[Mentioned]):
|
||||
):
|
||||
assert isinstance(point, bytes)
|
||||
assert isinstance(origin, Origin)
|
||||
assert len(point) == self.HASH_LENGTH
|
||||
assert_eq(len(point), self.HASH_LENGTH)
|
||||
self.point = point
|
||||
self.origin = origin
|
||||
self.factory = origin.factory
|
||||
@ -46,7 +47,7 @@ class HashPoint(Generic[Mentioned]):
|
||||
assert isinstance(mentioned, Mentionable)
|
||||
topology_hash: bytes = mentioned.__topology_hash__()
|
||||
assert isinstance(topology_hash, bytes)
|
||||
assert len(topology_hash) == cls.HASH_LENGTH
|
||||
assert_eq(len(topology_hash), cls.HASH_LENGTH)
|
||||
return topology_hash + bytes(mentioned)
|
||||
|
||||
@classmethod
|
||||
@ -56,10 +57,10 @@ class HashPoint(Generic[Mentioned]):
|
||||
cls.hash(cls.bytes_of_mentioned(mentioned)), LocalOrigin(mentioned)
|
||||
)
|
||||
|
||||
def resolve(self) -> Mentioned:
|
||||
resolved = self.origin.resolve()
|
||||
async def resolve(self) -> Mentioned:
|
||||
resolved: Mentioned = await self.origin.resolve()
|
||||
assert isinstance(resolved, Mentionable)
|
||||
assert self.point == self.hash(self.bytes_of_mentioned(resolved))
|
||||
assert_eq(self.point, self.hash(self.bytes_of_mentioned(resolved)))
|
||||
return resolved
|
||||
|
||||
def __eq__(self, other):
|
||||
|
@ -2,5 +2,5 @@ __all__ = ('HashResolver',)
|
||||
|
||||
|
||||
class HashResolver:
|
||||
def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
|
||||
async def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
|
||||
raise NotImplementedError
|
||||
|
@ -1,5 +1,6 @@
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
from rainbowadn.core.asserts import assert_eq
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.metaorigin import MetaOrigin
|
||||
from rainbowadn.core.origin import Origin
|
||||
@ -18,5 +19,5 @@ class LocalMetaOrigin(MetaOrigin[Mentioned], Generic[Mentioned]):
|
||||
def origin(self, factory: RainbowFactory[Mentioned], point: bytes) -> Origin[Mentioned]:
|
||||
assert isinstance(factory, RainbowFactory)
|
||||
assert isinstance(point, bytes)
|
||||
assert len(point) == HashPoint.HASH_LENGTH
|
||||
assert_eq(len(point), HashPoint.HASH_LENGTH)
|
||||
return self._origin
|
||||
|
@ -14,5 +14,5 @@ class LocalOrigin(Origin[Mentioned], Generic[Mentioned]):
|
||||
super().__init__(value.__factory__())
|
||||
self.value: Mentioned = value
|
||||
|
||||
def resolve(self) -> Mentioned:
|
||||
async def resolve(self) -> Mentioned:
|
||||
return self.value
|
||||
|
@ -1,5 +1,6 @@
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
from rainbowadn.core.asserts import assert_eq
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.origin import Origin
|
||||
from rainbowadn.core.rainbow_factory import RainbowFactory
|
||||
@ -16,5 +17,5 @@ class MetaOrigin(Generic[Mentioned]):
|
||||
def hash_point(self, factory: RainbowFactory[Mentioned], point: bytes) -> HashPoint[Mentioned]:
|
||||
assert isinstance(factory, RainbowFactory)
|
||||
assert isinstance(point, bytes)
|
||||
assert len(point) == HashPoint.HASH_LENGTH
|
||||
assert_eq(len(point), HashPoint.HASH_LENGTH)
|
||||
return HashPoint(point, self.origin(factory, point))
|
||||
|
@ -48,11 +48,11 @@ class NullableReference(RecursiveMentionable, Generic[Referenced]):
|
||||
def off(cls, value: Referenced) -> 'NullableReference[Referenced]':
|
||||
return cls.of(HashPoint.of(value))
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
if self.null():
|
||||
return f'-'
|
||||
else:
|
||||
return f'{hash_point_format(self.hashpoint(), tab)}'
|
||||
return f'{await hash_point_format(self.hashpoint(), tab)}'
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, NullableReference):
|
||||
@ -67,9 +67,9 @@ class NullableReference(RecursiveMentionable, Generic[Referenced]):
|
||||
assert not self.null()
|
||||
return self.reference.resolve()
|
||||
|
||||
def resolve(self) -> Referenced:
|
||||
async def resolve(self) -> Referenced:
|
||||
assert not self.null()
|
||||
return self.hashpoint().resolve()
|
||||
return await self.hashpoint().resolve()
|
||||
|
||||
|
||||
class NullableReferenceFactory(RainbowFactory[NullableReference[Referenced]], Generic[Referenced]):
|
||||
|
@ -11,5 +11,5 @@ class Origin(Generic[Mentioned]):
|
||||
def __init__(self, factory: RainbowFactory[Mentioned]):
|
||||
self.factory = factory
|
||||
|
||||
def resolve(self) -> Mentioned:
|
||||
async def resolve(self) -> Mentioned:
|
||||
raise NotImplementedError
|
||||
|
@ -11,7 +11,7 @@ class RecursiveMentionable(Mentionable, abc.ABC):
|
||||
def points(self) -> Iterable[HashPoint]:
|
||||
raise NotImplementedError
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'(recursive {self.__class__.__name__})'
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
from rainbowadn.core.asserts import assert_eq
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.hashresolver import HashResolver
|
||||
from rainbowadn.core.metaorigin import MetaOrigin
|
||||
@ -20,12 +21,5 @@ class ResolverMetaOrigin(MetaOrigin[Mentioned], Generic[Mentioned]):
|
||||
def origin(self, factory: RainbowFactory[Mentioned], point: bytes) -> Origin[Mentioned]:
|
||||
assert isinstance(factory, RainbowFactory)
|
||||
assert isinstance(point, bytes)
|
||||
assert len(point) == HashPoint.HASH_LENGTH
|
||||
assert_eq(len(point), HashPoint.HASH_LENGTH)
|
||||
return ResolverOrigin(factory, point, self.resolver)
|
||||
|
||||
def migrate(self, hash_point: HashPoint[Mentioned]) -> HashPoint[Mentioned]:
|
||||
assert isinstance(hash_point, HashPoint)
|
||||
return self.hash_point(hash_point.factory, hash_point.point)
|
||||
|
||||
def migrate_resolved(self, mentioned: Mentioned) -> Mentioned:
|
||||
return self.migrate(HashPoint.of(mentioned)).resolve()
|
||||
|
@ -1,5 +1,6 @@
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
from rainbowadn.core.asserts import assert_eq
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.hashresolver import HashResolver
|
||||
from rainbowadn.core.mentionable import Mentionable
|
||||
@ -26,14 +27,14 @@ class ResolverOrigin(Origin[Mentioned], Generic[Mentioned]):
|
||||
self.resolver = resolver
|
||||
super().__init__(factory)
|
||||
|
||||
def resolve(self) -> Mentioned:
|
||||
resolved, resolver = self.resolver.resolve(self.point)
|
||||
async def resolve(self) -> Mentioned:
|
||||
resolved, resolver = await self.resolver.resolve(self.point)
|
||||
assert isinstance(resolved, bytes)
|
||||
assert isinstance(resolver, HashResolver)
|
||||
mentioned: Mentioned = self.factory.from_bytes(resolved[HashPoint.HASH_LENGTH:], resolver)
|
||||
assert isinstance(mentioned, Mentionable)
|
||||
assert mentioned.__topology_hash__() == resolved[:HashPoint.HASH_LENGTH]
|
||||
assert self.point == HashPoint.hash(HashPoint.bytes_of_mentioned(mentioned))
|
||||
assert_eq(mentioned.__topology_hash__(), resolved[:HashPoint.HASH_LENGTH])
|
||||
assert_eq(self.point, HashPoint.hash(HashPoint.bytes_of_mentioned(mentioned)))
|
||||
return mentioned
|
||||
|
||||
def hash_point(self) -> HashPoint[Mentioned]:
|
||||
|
@ -32,11 +32,11 @@ class Array(RecursiveMentionable, Generic[ElementType]):
|
||||
def __factory__(self) -> RainbowFactory['Array']:
|
||||
return ArrayFactory(self.factory)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
formatted = f'('
|
||||
for hash_point in self.array:
|
||||
formatted += f'{tabulate(tab + 1)}{hash_point_format(hash_point, tab + 1)}'
|
||||
formatted += f'{tabulate(tab + 1)}{await hash_point_format(hash_point, tab + 1)}'
|
||||
return f'{formatted}' \
|
||||
f'{tabulate(tab)})'
|
||||
|
||||
|
@ -29,10 +29,10 @@ class KeyMetadata(Keyed[ActiveKeyType], Generic[ActiveKeyType, MetaDataType]):
|
||||
def __factory__(self) -> RainbowFactory['KeyMetadata[ActiveKeyType, MetaDataType]']:
|
||||
return KeyMetadataFactory(self.key.factory, self.metadata.factory)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'{hash_point_format(self.key, tab)}' \
|
||||
f'{tabulate(tab)}{hash_point_format(self.metadata, tab)}'
|
||||
return f'{await hash_point_format(self.key, tab)}' \
|
||||
f'{tabulate(tab)}{await hash_point_format(self.metadata, tab)}'
|
||||
|
||||
|
||||
class KeyMetadataFactory(
|
||||
|
@ -32,11 +32,11 @@ class Pair(
|
||||
def __factory__(self) -> RainbowFactory['Pair[E0Type, E1Type]']:
|
||||
return PairFactory(self.element0.factory, self.element1.factory)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'(pair)' \
|
||||
f'{tabulate(tab)}{hash_point_format(self.element0, tab)}' \
|
||||
f'{tabulate(tab)}{hash_point_format(self.element1, tab)}'
|
||||
f'{tabulate(tab)}{await hash_point_format(self.element0, tab)}' \
|
||||
f'{tabulate(tab)}{await hash_point_format(self.element1, tab)}'
|
||||
|
||||
|
||||
class PairFactory(
|
||||
|
@ -1,4 +1,4 @@
|
||||
from typing import Generic, Iterable, TypeVar
|
||||
from typing import AsyncIterable, Generic, Iterable, TypeVar
|
||||
|
||||
from rainbowadn.core.hash_point_format import hash_point_format, tabulate
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
@ -35,10 +35,10 @@ class Stack(RecursiveMentionable, Generic[ElementType]):
|
||||
def __bytes__(self):
|
||||
return bytes(self.previous) + bytes(self.element)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'{self.previous.str(tab)}' \
|
||||
f'{tabulate(tab)}{hash_point_format(self.element, tab)}'
|
||||
return f'{await self.previous.str(tab)}' \
|
||||
f'{tabulate(tab)}{await hash_point_format(self.element, tab)}'
|
||||
|
||||
@classmethod
|
||||
def of(
|
||||
@ -69,17 +69,18 @@ class Stack(RecursiveMentionable, Generic[ElementType]):
|
||||
return cls.of(factory, map(HashPoint.of, elements))
|
||||
|
||||
@classmethod
|
||||
def iter(
|
||||
async def iter(
|
||||
cls,
|
||||
reference: NullableReference['Stack[ElementType]']
|
||||
) -> Iterable[HashPoint[ElementType]]:
|
||||
) -> AsyncIterable[HashPoint[ElementType]]:
|
||||
assert isinstance(reference, NullableReference)
|
||||
if reference.null():
|
||||
pass
|
||||
else:
|
||||
stack: Stack[ElementType] = reference.resolve()
|
||||
stack: Stack[ElementType] = await reference.resolve()
|
||||
yield stack.element
|
||||
yield from cls.iter(stack.previous)
|
||||
async for element in cls.iter(stack.previous):
|
||||
yield element
|
||||
|
||||
|
||||
class StackFactory(RainbowFactory[Stack[ElementType]], Generic[ElementType]):
|
||||
|
@ -12,31 +12,25 @@ ActionType = TypeVar('ActionType')
|
||||
|
||||
|
||||
class BinaryTreeAction(Generic[ActiveKeyType, MetaDataType, TreeType, ActionType]):
|
||||
def on(
|
||||
async def on(
|
||||
self,
|
||||
protocol: BinaryTreeCreationProtocol[ActiveKeyType, MetaDataType, TreeType],
|
||||
tree: TreeType
|
||||
) -> ActionType:
|
||||
if (split := protocol.split(tree)) is None:
|
||||
return self.on_null(protocol, tree)
|
||||
if (split := await protocol.split(tree)) is None:
|
||||
return await self.on_null(protocol, tree)
|
||||
else:
|
||||
return self.on_split(BinaryTreeCase(protocol, split, tree))
|
||||
return await self.on_split(BinaryTreeCase(protocol, split, tree))
|
||||
|
||||
def on_null(
|
||||
async def on_null(
|
||||
self,
|
||||
protocol: BinaryTreeCreationProtocol[ActiveKeyType, MetaDataType, TreeType],
|
||||
tree: TreeType
|
||||
) -> ActionType:
|
||||
raise NotImplementedError
|
||||
|
||||
def on_split(
|
||||
async def on_split(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> ActionType:
|
||||
raise NotImplementedError
|
||||
|
||||
def per(
|
||||
self: 'BinaryTreeAction[ActiveKeyType, MetaDataType, TreeType, ActionType]',
|
||||
_protocol: BinaryTreeCreationProtocol[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> 'BinaryTreeAction[ActiveKeyType, MetaDataType, TreeType, ActionType]':
|
||||
return self
|
||||
|
@ -23,36 +23,36 @@ class CompareAction(
|
||||
assert isinstance(key, HashPoint)
|
||||
self.key = key
|
||||
|
||||
def on_split(
|
||||
async def on_split(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> ActionType:
|
||||
assert isinstance(case, BinaryTreeCase)
|
||||
comparison: Comparison = case.protocol.comparator.compare(case.split.key, self.key)
|
||||
comparison: Comparison = await case.protocol.comparator.compare(case.split.key, self.key)
|
||||
assert isinstance(comparison, Comparison)
|
||||
if isinstance(comparison, Equal):
|
||||
return self.on_equal(case, comparison)
|
||||
return await self.on_equal(case, comparison)
|
||||
elif isinstance(comparison, Left):
|
||||
return self.on_left(case)
|
||||
return await self.on_left(case)
|
||||
elif isinstance(comparison, Right):
|
||||
return self.on_right(case)
|
||||
return await self.on_right(case)
|
||||
else:
|
||||
raise TypeError
|
||||
|
||||
def on_equal(
|
||||
async def on_equal(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType],
|
||||
equal: Equal
|
||||
) -> ActionType:
|
||||
raise NotImplementedError
|
||||
|
||||
def on_left(
|
||||
async def on_left(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> ActionType:
|
||||
raise NotImplementedError
|
||||
|
||||
def on_right(
|
||||
async def on_right(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> ActionType:
|
||||
|
@ -22,34 +22,42 @@ class AddAction(
|
||||
],
|
||||
Generic[ActiveKeyType, MetaDataType, TreeType]
|
||||
):
|
||||
def on_equal(
|
||||
async def on_equal(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType],
|
||||
equal: Equal
|
||||
) -> TreeType:
|
||||
if isinstance(equal, Replace):
|
||||
return case.protocol.tree(case.split.treel, case.split.treer, self.key)
|
||||
return await case.protocol.tree(case.split.treel, case.split.treer, self.key)
|
||||
else:
|
||||
raise TypeError
|
||||
|
||||
def on_left(
|
||||
async def on_left(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
return case.protocol.tree(self.on(case.protocol, case.split.treel), case.split.treer, case.split.key)
|
||||
return await case.protocol.tree(
|
||||
await self.on(case.protocol, case.split.treel),
|
||||
case.split.treer,
|
||||
case.split.key
|
||||
)
|
||||
|
||||
def on_right(
|
||||
async def on_right(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
return case.protocol.tree(case.split.treel, self.on(case.protocol, case.split.treer), case.split.key)
|
||||
return await case.protocol.tree(
|
||||
case.split.treel,
|
||||
await self.on(case.protocol, case.split.treer),
|
||||
case.split.key
|
||||
)
|
||||
|
||||
def on_null(
|
||||
async def on_null(
|
||||
self,
|
||||
protocol: BinaryTreeCreationProtocol[ActiveKeyType, MetaDataType, TreeType],
|
||||
tree: TreeType
|
||||
) -> TreeType:
|
||||
return protocol.tree(tree, tree, self.key)
|
||||
return await protocol.tree(tree, tree, self.key)
|
||||
|
||||
|
||||
class MergeAction(
|
||||
@ -64,22 +72,22 @@ class MergeAction(
|
||||
def __init__(self, treer: TreeType):
|
||||
self.treer = treer
|
||||
|
||||
def on_null(
|
||||
async def on_null(
|
||||
self,
|
||||
protocol: BinaryTreeCreationProtocol[ActiveKeyType, MetaDataType, TreeType],
|
||||
tree: TreeType
|
||||
) -> TreeType:
|
||||
return self.treer
|
||||
|
||||
def on_split(
|
||||
async def on_split(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
protocol = case.protocol
|
||||
split = case.split
|
||||
return protocol.tree(
|
||||
return await protocol.tree(
|
||||
split.treel,
|
||||
MergeAction(self.treer).on(protocol, split.treer),
|
||||
await MergeAction(self.treer).on(protocol, split.treer),
|
||||
split.key
|
||||
)
|
||||
|
||||
@ -93,26 +101,34 @@ class RemoveAction(
|
||||
],
|
||||
Generic[ActiveKeyType, MetaDataType, TreeType]
|
||||
):
|
||||
def on_equal(
|
||||
async def on_equal(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType],
|
||||
equal: Equal
|
||||
) -> TreeType:
|
||||
return MergeAction(case.split.treer).on(case.protocol, case.split.treel)
|
||||
return await MergeAction(case.split.treer).on(case.protocol, case.split.treel)
|
||||
|
||||
def on_left(
|
||||
async def on_left(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
return case.protocol.tree(self.on(case.protocol, case.split.treel), case.split.treer, case.split.key)
|
||||
return await case.protocol.tree(
|
||||
await self.on(case.protocol, case.split.treel),
|
||||
case.split.treer,
|
||||
case.split.key
|
||||
)
|
||||
|
||||
def on_right(
|
||||
async def on_right(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
return case.protocol.tree(case.split.treel, self.on(case.protocol, case.split.treer), case.split.key)
|
||||
return await case.protocol.tree(
|
||||
case.split.treel,
|
||||
await self.on(case.protocol, case.split.treer),
|
||||
case.split.key
|
||||
)
|
||||
|
||||
def on_null(
|
||||
async def on_null(
|
||||
self,
|
||||
protocol: BinaryTreeCreationProtocol[ActiveKeyType, MetaDataType, TreeType],
|
||||
tree: TreeType
|
||||
@ -129,26 +145,26 @@ class ContainsAction(
|
||||
],
|
||||
Generic[ActiveKeyType, MetaDataType, TreeType]
|
||||
):
|
||||
def on_equal(
|
||||
async def on_equal(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType],
|
||||
equal: Equal
|
||||
) -> bool:
|
||||
return True
|
||||
|
||||
def on_left(
|
||||
async def on_left(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> bool:
|
||||
return self.on(case.protocol, case.split.treel)
|
||||
return await self.on(case.protocol, case.split.treel)
|
||||
|
||||
def on_right(
|
||||
async def on_right(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> bool:
|
||||
return self.on(case.protocol, case.split.treer)
|
||||
return await self.on(case.protocol, case.split.treer)
|
||||
|
||||
def on_null(
|
||||
async def on_null(
|
||||
self,
|
||||
protocol: BinaryTreeCreationProtocol[ActiveKeyType, MetaDataType, TreeType],
|
||||
tree: TreeType
|
||||
|
@ -34,7 +34,7 @@ class Symmetric(
|
||||
) -> TreeType:
|
||||
raise NotImplementedError
|
||||
|
||||
def tree(
|
||||
async def tree(
|
||||
self,
|
||||
inner: TreeType,
|
||||
outer: TreeType,
|
||||
@ -56,13 +56,13 @@ class InnerOuter(Symmetric):
|
||||
) -> TreeType:
|
||||
return split.treer
|
||||
|
||||
def tree(
|
||||
async def tree(
|
||||
self,
|
||||
inner: TreeType,
|
||||
outer: TreeType,
|
||||
key: HashPoint[ActiveKeyType]
|
||||
) -> TreeType:
|
||||
return self.case.protocol.tree(inner, outer, key)
|
||||
return await self.case.protocol.tree(inner, outer, key)
|
||||
|
||||
|
||||
class OuterInner(Symmetric):
|
||||
@ -78,10 +78,10 @@ class OuterInner(Symmetric):
|
||||
) -> TreeType:
|
||||
return split.treel
|
||||
|
||||
def tree(
|
||||
async def tree(
|
||||
self,
|
||||
inner: TreeType,
|
||||
outer: TreeType,
|
||||
key: HashPoint[ActiveKeyType]
|
||||
) -> TreeType:
|
||||
return self.case.protocol.tree(outer, inner, key)
|
||||
return await self.case.protocol.tree(outer, inner, key)
|
||||
|
@ -65,17 +65,17 @@ class ActiveBinaryTree(
|
||||
reference
|
||||
)
|
||||
|
||||
def add(self, key: HashPoint[ActiveKeyType]) -> 'ActiveBinaryTree[ActiveKeyType, MetaDataType]':
|
||||
async def add(self, key: HashPoint[ActiveKeyType]) -> 'ActiveBinaryTree[ActiveKeyType, MetaDataType]':
|
||||
assert isinstance(key, HashPoint)
|
||||
return AddAction(key).on(self.creation, self)
|
||||
return await AddAction(key).on(self.creation, self)
|
||||
|
||||
def remove(self, key: HashPoint[ActiveKeyType]) -> 'ActiveBinaryTree[ActiveKeyType, MetaDataType]':
|
||||
async def remove(self, key: HashPoint[ActiveKeyType]) -> 'ActiveBinaryTree[ActiveKeyType, MetaDataType]':
|
||||
assert isinstance(key, HashPoint)
|
||||
return RemoveAction(key).on(self.creation, self)
|
||||
return await RemoveAction(key).on(self.creation, self)
|
||||
|
||||
def contains(self, key: HashPoint[ActiveKeyType]) -> bool:
|
||||
async def contains(self, key: HashPoint[ActiveKeyType]) -> bool:
|
||||
assert isinstance(key, HashPoint)
|
||||
return ContainsAction(key).on(self.creation, self)
|
||||
return await ContainsAction(key).on(self.creation, self)
|
||||
|
||||
def loose(self) -> CollectionInterface[
|
||||
BinaryTree[KeyMetadata[ActiveKeyType, MetaDataType]]
|
||||
@ -90,7 +90,7 @@ class ActiveCreationProtocol(
|
||||
ActiveBinaryTree[ActiveKeyType, MetaDataType]
|
||||
]
|
||||
):
|
||||
def split(
|
||||
async def split(
|
||||
self,
|
||||
tree: ActiveBinaryTree[ActiveKeyType, MetaDataType]
|
||||
) -> Optional[
|
||||
@ -104,15 +104,15 @@ class ActiveCreationProtocol(
|
||||
if tree.reference.null():
|
||||
return None
|
||||
else:
|
||||
resolved: BinaryTree[KeyMetadata[ActiveKeyType, MetaDataType]] = tree.reference.resolve()
|
||||
resolved: BinaryTree[KeyMetadata[ActiveKeyType, MetaDataType]] = await tree.reference.resolve()
|
||||
assert isinstance(resolved, BinaryTree)
|
||||
key_metadata: KeyMetadata[ActiveKeyType, MetaDataType] = resolved.key.resolve()
|
||||
key_metadata: KeyMetadata[ActiveKeyType, MetaDataType] = await resolved.key.resolve()
|
||||
assert isinstance(key_metadata, KeyMetadata)
|
||||
return BinaryTreeSplit(
|
||||
tree.create(resolved.treel), key_metadata.key, key_metadata.metadata, tree.create(resolved.treer)
|
||||
)
|
||||
|
||||
def _tree(
|
||||
async def _tree(
|
||||
self,
|
||||
treel: ActiveBinaryTree,
|
||||
treer: ActiveBinaryTree,
|
||||
@ -127,7 +127,7 @@ class ActiveCreationProtocol(
|
||||
BinaryTree(
|
||||
treel.reference,
|
||||
treer.reference,
|
||||
HashPoint.of(KeyMetadata(key, self.protocol.metadata(treel, treer, key, self)))
|
||||
HashPoint.of(KeyMetadata(key, await self.protocol.metadata(treel, treer, key, self)))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -18,7 +18,7 @@ class AVL(BinaryTreeBalancingProtocol[ActiveKeyType, Integer, TreeType]):
|
||||
def empty_metadata(self) -> HashPoint[Integer]:
|
||||
return HashPoint.of(Integer(0))
|
||||
|
||||
def metadata(
|
||||
async def metadata(
|
||||
self,
|
||||
treel: TreeType,
|
||||
treer: TreeType,
|
||||
@ -26,85 +26,90 @@ class AVL(BinaryTreeBalancingProtocol[ActiveKeyType, Integer, TreeType]):
|
||||
protocol: BinaryTreeCreationProtocol[ActiveKeyType, Integer, TreeType]
|
||||
) -> HashPoint[Integer]:
|
||||
return HashPoint.of(
|
||||
Integer(1 + max(self.height(treel, protocol), self.height(treer, protocol)))
|
||||
Integer(1 + max(await self.height(treel, protocol), await self.height(treer, protocol)))
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def height(
|
||||
async def height(
|
||||
cls,
|
||||
tree: TreeType,
|
||||
protocol: BinaryTreeCreationProtocol[ActiveKeyType, Integer, TreeType]
|
||||
) -> int:
|
||||
return HeightAction().on(protocol, tree)
|
||||
return await HeightAction().on(protocol, tree)
|
||||
|
||||
def balance(
|
||||
async def balance(
|
||||
self,
|
||||
tree: TreeType,
|
||||
protocol: BinaryTreeCreationProtocol[ActiveKeyType, Integer, TreeType]
|
||||
) -> TreeType:
|
||||
return BalanceAction().on(protocol, tree)
|
||||
return await BalanceAction().on(protocol, tree)
|
||||
|
||||
|
||||
class HeightAction(
|
||||
BinaryTreeAction[ActiveKeyType, Integer, TreeType, int],
|
||||
Generic[ActiveKeyType, TreeType]
|
||||
):
|
||||
def on_null(
|
||||
async def on_null(
|
||||
self,
|
||||
protocol: BinaryTreeCreationProtocol[ActiveKeyType, Integer, TreeType],
|
||||
tree: TreeType
|
||||
) -> int:
|
||||
return 0
|
||||
|
||||
def on_split(
|
||||
async def on_split(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, Integer, TreeType]
|
||||
) -> int:
|
||||
return case.split.metadata.resolve().integer
|
||||
metadata: Integer = await case.split.metadata.resolve()
|
||||
return metadata.integer
|
||||
|
||||
|
||||
class BalanceAction(
|
||||
BinaryTreeAction[ActiveKeyType, Integer, TreeType, TreeType],
|
||||
Generic[ActiveKeyType, TreeType]
|
||||
):
|
||||
def on_null(
|
||||
async def on_null(
|
||||
self,
|
||||
protocol: BinaryTreeCreationProtocol[ActiveKeyType, Integer, TreeType],
|
||||
tree: TreeType
|
||||
) -> TreeType:
|
||||
return tree
|
||||
|
||||
def on_split(
|
||||
async def on_split(
|
||||
self,
|
||||
case: BinaryTreeCase[ActiveKeyType, Integer, TreeType]
|
||||
) -> TreeType:
|
||||
split, protocol = case.split, case.protocol
|
||||
delta = AVL.height(split.treel, protocol) - AVL.height(split.treer, protocol)
|
||||
delta = (await AVL.height(split.treel, protocol)) - (await AVL.height(split.treer, protocol))
|
||||
assert isinstance(delta, int)
|
||||
if delta < -1:
|
||||
return self.on_symmetric(InnerOuter(case))
|
||||
return await self.on_symmetric(InnerOuter(case))
|
||||
elif delta > 1:
|
||||
return self.on_symmetric(OuterInner(case))
|
||||
return await self.on_symmetric(OuterInner(case))
|
||||
else:
|
||||
return case.tree
|
||||
|
||||
@classmethod
|
||||
def on_symmetric(
|
||||
async def on_symmetric(
|
||||
cls,
|
||||
symmetric: Symmetric[ActiveKeyType, Integer, TreeType]
|
||||
) -> TreeType:
|
||||
protocol, split = symmetric.case.protocol, symmetric.case.split
|
||||
splito = protocol.fsplit(symmetric.outer(split))
|
||||
if AVL.height(symmetric.inner(splito), protocol) > AVL.height(symmetric.outer(splito), protocol):
|
||||
splitoi = protocol.fsplit(symmetric.inner(splito))
|
||||
return symmetric.tree(
|
||||
symmetric.tree(symmetric.inner(split), symmetric.inner(splitoi), split.key),
|
||||
symmetric.tree(symmetric.outer(splitoi), symmetric.outer(splito), splito.key),
|
||||
splito = await protocol.fsplit(symmetric.outer(split))
|
||||
if (
|
||||
(await AVL.height(symmetric.inner(splito), protocol))
|
||||
>
|
||||
(await AVL.height(symmetric.outer(splito), protocol))
|
||||
):
|
||||
splitoi = await protocol.fsplit(symmetric.inner(splito))
|
||||
return await symmetric.tree(
|
||||
await symmetric.tree(symmetric.inner(split), symmetric.inner(splitoi), split.key),
|
||||
await symmetric.tree(symmetric.outer(splitoi), symmetric.outer(splito), splito.key),
|
||||
splitoi.key
|
||||
)
|
||||
else:
|
||||
return symmetric.tree(
|
||||
symmetric.tree(symmetric.inner(split), symmetric.inner(splito), split.key),
|
||||
return await symmetric.tree(
|
||||
await symmetric.tree(symmetric.inner(split), symmetric.inner(splito), split.key),
|
||||
symmetric.outer(splito),
|
||||
splito.key
|
||||
)
|
||||
|
@ -25,15 +25,15 @@ class BalancedTreeCreationProtocol(
|
||||
self.protocol = protocol
|
||||
super().__init__(protocol.comparator)
|
||||
|
||||
def _tree(self, treel: TreeType, treer: TreeType, key: HashPoint[ActiveKeyType]) -> TreeType:
|
||||
async def _tree(self, treel: TreeType, treer: TreeType, key: HashPoint[ActiveKeyType]) -> TreeType:
|
||||
raise NotImplementedError
|
||||
|
||||
def tree(self, treel: TreeType, treer: TreeType, key: HashPoint[ActiveKeyType]) -> TreeType:
|
||||
async def tree(self, treel: TreeType, treer: TreeType, key: HashPoint[ActiveKeyType]) -> TreeType:
|
||||
assert isinstance(key, HashPoint)
|
||||
return self.protocol.balance(
|
||||
self._tree(
|
||||
self.protocol.balance(treel, self),
|
||||
self.protocol.balance(treer, self),
|
||||
return await self.protocol.balance(
|
||||
await self._tree(
|
||||
await self.protocol.balance(treel, self),
|
||||
await self.protocol.balance(treer, self),
|
||||
key
|
||||
),
|
||||
self
|
||||
|
@ -40,11 +40,11 @@ class BinaryTree(RecursiveMentionable, Generic[TreeKeyType]):
|
||||
def __bytes__(self):
|
||||
return bytes(self.treel) + bytes(self.treer) + bytes(self.key)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'{self.treel.str(tab)}' \
|
||||
f'{tabulate(tab)}{hash_point_format(self.key, tab)}' \
|
||||
f'{tabulate(tab)}{self.treer.str(tab)}'
|
||||
return f'{await self.treel.str(tab)}' \
|
||||
f'{tabulate(tab)}{await hash_point_format(self.key, tab)}' \
|
||||
f'{tabulate(tab)}{await self.treer.str(tab)}'
|
||||
|
||||
|
||||
class BinaryTreeFactory(RainbowFactory[BinaryTree[TreeKeyType]], Generic[TreeKeyType]):
|
||||
|
@ -22,7 +22,7 @@ class BinaryTreeBalancingProtocol(Generic[ActiveKeyType, MetaDataType, TreeType]
|
||||
def empty_metadata(self) -> HashPoint[MetaDataType]:
|
||||
raise NotImplementedError
|
||||
|
||||
def metadata(
|
||||
async def metadata(
|
||||
self,
|
||||
treel: TreeType,
|
||||
treer: TreeType,
|
||||
@ -31,7 +31,7 @@ class BinaryTreeBalancingProtocol(Generic[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> HashPoint[MetaDataType]:
|
||||
raise NotImplementedError
|
||||
|
||||
def balance(
|
||||
async def balance(
|
||||
self,
|
||||
tree: TreeType,
|
||||
protocol: BinaryTreeCreationProtocol[ActiveKeyType, MetaDataType, TreeType]
|
||||
|
@ -15,18 +15,18 @@ class BinaryTreeCreationProtocol(Generic[ActiveKeyType, MetaDataType, TreeType])
|
||||
def __init__(self, comparator: Comparator[ActiveKeyType]):
|
||||
self.comparator = comparator
|
||||
|
||||
def split(self, tree: TreeType) -> Optional[
|
||||
async def split(self, tree: TreeType) -> Optional[
|
||||
BinaryTreeSplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
]:
|
||||
"""result of this method is supposed to be used right after the call, therefore all values are resolved"""
|
||||
raise NotImplementedError
|
||||
|
||||
def fsplit(self, tree: TreeType) -> BinaryTreeSplit[
|
||||
async def fsplit(self, tree: TreeType) -> BinaryTreeSplit[
|
||||
ActiveKeyType, MetaDataType, TreeType
|
||||
]:
|
||||
split = self.split(tree)
|
||||
split: Optional[BinaryTreeSplit[ActiveKeyType, MetaDataType, TreeType]] = await self.split(tree)
|
||||
assert split is not None
|
||||
return split
|
||||
|
||||
def tree(self, treel: TreeType, treer: TreeType, key: HashPoint[ActiveKeyType]) -> TreeType:
|
||||
async def tree(self, treel: TreeType, treer: TreeType, key: HashPoint[ActiveKeyType]) -> TreeType:
|
||||
raise NotImplementedError
|
||||
|
@ -47,5 +47,5 @@ KeyType = TypeVar('KeyType')
|
||||
|
||||
|
||||
class Comparator(Generic[KeyType]):
|
||||
def compare(self, original: HashPoint[KeyType], key: HashPoint[KeyType]) -> Comparison:
|
||||
async def compare(self, original: HashPoint[KeyType], key: HashPoint[KeyType]) -> Comparison:
|
||||
raise NotImplementedError
|
||||
|
@ -10,7 +10,7 @@ KeyType = TypeVar('KeyType')
|
||||
|
||||
|
||||
class HashComparator(ProtocolComparator[KeyType], Generic[KeyType]):
|
||||
def compare(self, original: HashPoint[KeyType], key: HashPoint[KeyType]) -> Comparison:
|
||||
async def compare(self, original: HashPoint[KeyType], key: HashPoint[KeyType]) -> Comparison:
|
||||
assert isinstance(original, HashPoint)
|
||||
assert isinstance(key, HashPoint)
|
||||
if key.point < original.point:
|
||||
|
@ -17,14 +17,14 @@ class KeyedComparator(
|
||||
self.comparator = comparator
|
||||
super().__init__()
|
||||
|
||||
def compare(
|
||||
async def compare(
|
||||
self,
|
||||
original: HashPoint[Keyed[ComparatorKeyType]],
|
||||
key: HashPoint[Keyed[ComparatorKeyType]]
|
||||
) -> Comparison:
|
||||
assert isinstance(original, HashPoint)
|
||||
assert isinstance(key, HashPoint)
|
||||
return self.comparator.compare(
|
||||
original.resolve().key,
|
||||
key.resolve().key,
|
||||
return await self.comparator.compare(
|
||||
(await original.resolve()).key,
|
||||
(await key.resolve()).key,
|
||||
)
|
||||
|
@ -7,12 +7,12 @@ __all__ = ('PlainComparator',)
|
||||
|
||||
|
||||
class PlainComparator(ProtocolComparator[Plain]):
|
||||
def compare(self, original: HashPoint[Plain], key: HashPoint[Plain]) -> Comparison:
|
||||
async def compare(self, original: HashPoint[Plain], key: HashPoint[Plain]) -> Comparison:
|
||||
assert isinstance(original, HashPoint)
|
||||
assert isinstance(key, HashPoint)
|
||||
original_value: Plain = original.resolve()
|
||||
original_value: Plain = await original.resolve()
|
||||
assert isinstance(original_value, Plain)
|
||||
key_value: Plain = key.resolve()
|
||||
key_value: Plain = await key.resolve()
|
||||
assert isinstance(key_value, Plain)
|
||||
if key_value.source < original_value.source:
|
||||
return Left()
|
||||
|
@ -3,6 +3,7 @@ from typing import Generic, Iterable, TypeVar
|
||||
from nacl.bindings import crypto_hash_sha256
|
||||
from nacl.secret import SecretBox
|
||||
|
||||
from rainbowadn.core.asserts import assert_eq
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.hashresolver import HashResolver
|
||||
from rainbowadn.core.mentionable import Mentionable
|
||||
@ -43,15 +44,17 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]):
|
||||
return self.resolution
|
||||
|
||||
@classmethod
|
||||
def encrypt(cls, decrypted: EncryptedType, key: bytes) -> 'Encrypted[EncryptedType]':
|
||||
async def encrypt(cls, decrypted: EncryptedType, key: bytes) -> 'Encrypted[EncryptedType]':
|
||||
assert isinstance(key, bytes)
|
||||
hashpoints = tuple(decrypted.points()) if isinstance(decrypted, RecursiveMentionable) else ()
|
||||
resolution = tuple(
|
||||
cls.encrypt_hashpoint(hashpoint, key)
|
||||
resolution: tuple[HashPoint[Encrypted[EncryptedType]], ...] = tuple(
|
||||
[
|
||||
await cls.encrypt_hashpoint(hashpoint, key)
|
||||
for
|
||||
hashpoint
|
||||
in
|
||||
hashpoints
|
||||
]
|
||||
)
|
||||
return cls.construct(
|
||||
key,
|
||||
@ -61,7 +64,7 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]):
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def encrypt_hashpoint(
|
||||
async def encrypt_hashpoint(
|
||||
cls, hashpoint: HashPoint[EncryptedType], key: bytes
|
||||
) -> HashPoint['Encrypted[EncryptedType]']:
|
||||
assert isinstance(hashpoint, HashPoint)
|
||||
@ -75,7 +78,7 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]):
|
||||
resolver.mapping[hashpoint.point],
|
||||
key
|
||||
).hash_point()
|
||||
return HashPoint.of(cls.encrypt(hashpoint.resolve(), key))
|
||||
return HashPoint.of(await cls.encrypt(await hashpoint.resolve(), key))
|
||||
|
||||
@classmethod
|
||||
def construct(
|
||||
@ -129,7 +132,7 @@ class EncryptedFactory(RainbowFactory[Encrypted[EncryptedType]], Generic[Encrypt
|
||||
resolver,
|
||||
)
|
||||
hashpoints = tuple(decrypted.points()) if isinstance(decrypted, RecursiveMentionable) else ()
|
||||
assert len(hashpoints) == resolution_size
|
||||
assert_eq(len(hashpoints), resolution_size)
|
||||
resolution: tuple[HashPoint[Encrypted], ...] = tuple(
|
||||
ResolverOrigin(
|
||||
EncryptedFactory(
|
||||
@ -155,9 +158,9 @@ class EncryptedResolver(HashResolver):
|
||||
self.mapping = mapping
|
||||
self.key = key
|
||||
|
||||
def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
|
||||
async def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
|
||||
assert isinstance(point, bytes)
|
||||
encrypted = self.mapping[point].resolve()
|
||||
encrypted: Encrypted = await self.mapping[point].resolve()
|
||||
return HashPoint.bytes_of_mentioned(encrypted.decrypted), EncryptedResolver(encrypted.mapping, self.key)
|
||||
|
||||
|
||||
@ -171,10 +174,10 @@ class ShortcutOrigin(Origin[Encrypted[EncryptedType]], Generic[EncryptedType]):
|
||||
self.hashpoint = hashpoint
|
||||
super().__init__(self.factory)
|
||||
|
||||
def resolve(self) -> Encrypted[EncryptedType]:
|
||||
encrypted = self.hashpoint.resolve()
|
||||
encrypted = self.factory.from_bytes(bytes(encrypted), ShortcutResolver(encrypted))
|
||||
assert HashPoint.of(encrypted) == self.hashpoint
|
||||
async def resolve(self) -> Encrypted[EncryptedType]:
|
||||
source: Encrypted = await self.hashpoint.resolve()
|
||||
encrypted: Encrypted[EncryptedType] = self.factory.from_bytes(bytes(source), ShortcutResolver(source))
|
||||
assert_eq(HashPoint.of(encrypted), self.hashpoint)
|
||||
return encrypted
|
||||
|
||||
def hash_point(self) -> HashPoint[Encrypted[EncryptedType]]:
|
||||
@ -191,9 +194,9 @@ class ShortcutResolver(HashResolver):
|
||||
hashpoint.point: hashpoint for hashpoint in encrypted.resolution
|
||||
}
|
||||
|
||||
def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
|
||||
async def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
|
||||
assert isinstance(point, bytes)
|
||||
resolved: Encrypted = self.mapping[point].resolve()
|
||||
resolved: Encrypted = await self.mapping[point].resolve()
|
||||
return (
|
||||
HashPoint.bytes_of_mentioned(resolved),
|
||||
ShortcutResolver(resolved)
|
||||
|
@ -1,28 +1,33 @@
|
||||
from collections import OrderedDict
|
||||
from typing import MutableMapping
|
||||
|
||||
from rainbowadn.core.extendableresolver import ExtendableResolver, Mentioned
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.hashresolver import HashResolver
|
||||
from rainbowadn.core.mentionable import Mentionable
|
||||
from rainbowadn.core.recursivementionable import RecursiveMentionable
|
||||
|
||||
|
||||
class DictResolver(HashResolver):
|
||||
class DictResolver(ExtendableResolver):
|
||||
def __init__(self):
|
||||
self.table: MutableMapping[bytes, bytes] = OrderedDict()
|
||||
|
||||
def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
|
||||
async def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
|
||||
assert isinstance(point, bytes)
|
||||
return self.table[point], self
|
||||
|
||||
def save(self, hash_point: HashPoint) -> None:
|
||||
async def save(self, hash_point: HashPoint) -> None:
|
||||
assert isinstance(hash_point, HashPoint)
|
||||
if hash_point.point in self.table:
|
||||
pass
|
||||
else:
|
||||
value: Mentionable = hash_point.resolve()
|
||||
value: Mentionable = await hash_point.resolve()
|
||||
assert isinstance(value, Mentionable)
|
||||
self.table[hash_point.point] = HashPoint.bytes_of_mentioned(value)
|
||||
if isinstance(value, RecursiveMentionable):
|
||||
for hash_point in value.points():
|
||||
self.save(hash_point)
|
||||
await self.save(hash_point)
|
||||
|
||||
async def extend(self, hash_point: HashPoint[Mentioned]) -> 'ExtendableResolver':
|
||||
await self.save(hash_point)
|
||||
return self
|
||||
|
@ -2,5 +2,5 @@ from rainbowadn.core.hashresolver import HashResolver
|
||||
|
||||
|
||||
class FailResolver(HashResolver):
|
||||
def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
|
||||
async def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
|
||||
raise TypeError('fail-resolver always fails')
|
||||
|
@ -18,9 +18,13 @@ class Instrumentation:
|
||||
self.instrument(*args, **kwargs)
|
||||
return self.method(*args, **kwargs)
|
||||
|
||||
setattr(self.target, self.methodname, wrap)
|
||||
self.wrap = wrap
|
||||
|
||||
setattr(self.target, self.methodname, self.wrap)
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
assert getattr(self.target, self.methodname) is self.wrap
|
||||
del self.wrap
|
||||
setattr(self.target, self.methodname, self.method)
|
||||
del self.method
|
||||
|
||||
|
@ -9,10 +9,10 @@ import nacl.signing
|
||||
from rainbowadn.chain.blockchain import BlockChainFactory
|
||||
from rainbowadn.chain.chaincollectioninterface import ChainCollectionInterface
|
||||
from rainbowadn.chain.reduction.reductionchainmetafactory import ReductionChainMetaFactory
|
||||
from rainbowadn.core.asserts import assert_eq, assert_false, assert_true
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.nullability.notnull import NotNull
|
||||
from rainbowadn.core.rainbow_factory import RainbowFactory
|
||||
from rainbowadn.core.resolvermetaorigin import ResolverMetaOrigin
|
||||
from rainbowadn.data.atomic.integer import Integer
|
||||
from rainbowadn.data.atomic.plain import Plain
|
||||
from rainbowadn.data.collection.pair import Pair, PairFactory
|
||||
@ -32,14 +32,14 @@ from rainbowadn.wrisbt.wrisbtparametres import WrisbtParametres
|
||||
from rainbowadn.wrisbt.wrisbtroot import WrisbtRoot
|
||||
|
||||
|
||||
class TestAll(unittest.TestCase):
|
||||
class TestAll(unittest.IsolatedAsyncioTestCase):
|
||||
"""examples rather than real tests"""
|
||||
|
||||
def test_bankchain(self):
|
||||
async def test_bankchain(self):
|
||||
with self.subTest('setup'):
|
||||
dr = DictResolver()
|
||||
with self.subTest('create empty'):
|
||||
bank = BankChain.empty(ReductionChainMetaFactory())
|
||||
bank: BankChain = BankChain.empty(ReductionChainMetaFactory().loose())
|
||||
with self.subTest('prepare transactions'):
|
||||
key_0 = nacl.signing.SigningKey.generate()
|
||||
transaction_0 = Transaction.make(
|
||||
@ -47,9 +47,9 @@ class TestAll(unittest.TestCase):
|
||||
[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))))
|
||||
coin_0, coin_1 = await transaction_0.coins(MINT_CONST, NotNull(HashPoint.of(Subject(key_0.verify_key))))
|
||||
with self.subTest('add transactions'):
|
||||
bank = bank.adds(
|
||||
bank = await bank.adds(
|
||||
[
|
||||
transaction_0,
|
||||
Transaction.make(
|
||||
@ -60,22 +60,22 @@ class TestAll(unittest.TestCase):
|
||||
]
|
||||
)
|
||||
with self.subTest('add empty'):
|
||||
bank = bank.adds(
|
||||
bank = await bank.adds(
|
||||
[]
|
||||
)
|
||||
print(bank)
|
||||
with self.subTest('verify'):
|
||||
assert bank.verify()
|
||||
assert_true(await bank.verify())
|
||||
with self.subTest('recover'):
|
||||
dr.save(HashPoint.of(bank.reference))
|
||||
await dr.save(HashPoint.of(bank.reference))
|
||||
bank = BankChain.from_reference(
|
||||
ReductionChainMetaFactory(), ResolverMetaOrigin(dr).migrate_resolved(bank.reference)
|
||||
ReductionChainMetaFactory(), await dr.migrate_resolved(bank.reference)
|
||||
)
|
||||
print(bank)
|
||||
with self.subTest('verify'):
|
||||
assert bank.verify()
|
||||
assert_true(await bank.verify())
|
||||
|
||||
def test_wrisbt(self):
|
||||
async def test_wrisbt(self):
|
||||
with self.subTest('setup'):
|
||||
stoptime = time.process_time()
|
||||
|
||||
@ -91,33 +91,33 @@ class TestAll(unittest.TestCase):
|
||||
n = 2500
|
||||
keysize = 7
|
||||
with self.subTest('create empty'):
|
||||
btree = WrisbtRoot.empty(WrisbtParametres(1, keysize))
|
||||
btree: WrisbtRoot = WrisbtRoot.empty(WrisbtParametres(1, keysize))
|
||||
measure('init')
|
||||
with self.subTest('add keys', n=n):
|
||||
for _ in range(n):
|
||||
key = os.urandom(keysize)
|
||||
assert not btree.contains(key)
|
||||
btree = btree.add(key)
|
||||
assert btree.contains(key)
|
||||
assert_false(await btree.contains(key))
|
||||
btree = await btree.add(key)
|
||||
assert_true(await btree.contains(key))
|
||||
measure('add')
|
||||
with self.subTest('save'):
|
||||
dr.save(HashPoint.of(btree))
|
||||
await dr.save(HashPoint.of(btree))
|
||||
measure('save')
|
||||
with self.subTest('resolve and iterate'):
|
||||
btree = ResolverMetaOrigin(dr).migrate_resolved(btree)
|
||||
assert len(btree.keys()) == n
|
||||
btree = await dr.migrate_resolved(btree)
|
||||
assert_eq(len(await 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(keysize)
|
||||
assert not btree.contains(key)
|
||||
btree = btree.add(key)
|
||||
assert btree.contains(key)
|
||||
assert_false(await btree.contains(key))
|
||||
btree = await btree.add(key)
|
||||
assert_true(await btree.contains(key))
|
||||
print(btree.height)
|
||||
measure('resolve and add')
|
||||
|
||||
def test_wrisbt_index(self):
|
||||
async def test_wrisbt_index(self):
|
||||
with self.subTest('create empty'):
|
||||
factory: RainbowFactory[Pair[Plain, Plain]] = PairFactory(Plain.factory(), Plain.factory()).loose()
|
||||
chain: ChainCollectionInterface[Any, Pair[Plain, Plain], WrisbtRoot] = BlockChainFactory(
|
||||
@ -125,7 +125,7 @@ class TestAll(unittest.TestCase):
|
||||
).empty().loose()
|
||||
with self.subTest('fill'):
|
||||
for _ in range(1000):
|
||||
chain = chain.add(
|
||||
chain = await chain.add(
|
||||
HashPoint.of(
|
||||
Pair(
|
||||
HashPoint.of(Plain(os.urandom(16))),
|
||||
@ -134,29 +134,29 @@ class TestAll(unittest.TestCase):
|
||||
)
|
||||
)
|
||||
with self.subTest('check'):
|
||||
assert chain
|
||||
assert_true(await chain.verify())
|
||||
with self.subTest('measure height'):
|
||||
reference = chain.actual_state().reference
|
||||
reference = await chain.actual_state()
|
||||
assert not reference.null()
|
||||
print(reference.resolve().resolve().height)
|
||||
print((await reference.resolve()).height)
|
||||
|
||||
def test_avl(self):
|
||||
async def test_avl(self):
|
||||
tree: ActiveBinaryTree[Plain, Integer] = ActiveBinaryTree.empty(
|
||||
AVL(PlainComparator(Replace())), Plain.factory()
|
||||
)
|
||||
for i in range(26):
|
||||
tree = tree.add(HashPoint.of(Plain(bytes([ord('A') + i]))))
|
||||
print(tree.reference.str(0))
|
||||
tree = await tree.add(HashPoint.of(Plain(bytes([ord('A') + i]))))
|
||||
print(await tree.reference.str(0))
|
||||
|
||||
def test_avl_stress(self):
|
||||
async def test_avl_stress(self):
|
||||
tree: ActiveBinaryTree[Plain, Integer] = ActiveBinaryTree.empty(
|
||||
AVL(PlainComparator(Replace())), Plain.factory()
|
||||
)
|
||||
for i in range(250):
|
||||
tree = tree.add(HashPoint.of(Plain(os.urandom(16))))
|
||||
print(tree.loose().reference.resolve().key.resolve().metadata.resolve().integer)
|
||||
tree = await tree.add(HashPoint.of(Plain(os.urandom(16))))
|
||||
print((await (await (await tree.loose().reference.resolve()).key.resolve()).metadata.resolve()).integer)
|
||||
|
||||
def test_encryption(self):
|
||||
async def test_encryption(self):
|
||||
instrumentation = Counter(Encrypted, 'encrypt')
|
||||
with self.subTest('setup'):
|
||||
key = b'a' * 32
|
||||
@ -167,29 +167,29 @@ class TestAll(unittest.TestCase):
|
||||
)
|
||||
with self.subTest('fill'):
|
||||
for char in string.ascii_uppercase:
|
||||
tree = tree.add(HashPoint.of(Plain(char.encode())))
|
||||
print(tree.reference.str(0))
|
||||
tree = await tree.add(HashPoint.of(Plain(char.encode())))
|
||||
print(await tree.reference.str(0))
|
||||
with self.subTest('encrypt'):
|
||||
target = tree.reference
|
||||
with instrumentation:
|
||||
target = Encrypted.encrypt(target, key).decrypted
|
||||
target = (await Encrypted.encrypt(target, key)).decrypted
|
||||
print(instrumentation.counter)
|
||||
tree = tree.create(target)
|
||||
print(tree.reference.str(0))
|
||||
print(await tree.reference.str(0))
|
||||
with self.subTest('alter'):
|
||||
tree = tree.add(HashPoint.of(Plain(b'NEWKEY')))
|
||||
tree = tree.remove(HashPoint.of(Plain(b'F')))
|
||||
print(tree.reference.str(0))
|
||||
tree = await tree.add(HashPoint.of(Plain(b'NEWKEY')))
|
||||
tree = await tree.remove(HashPoint.of(Plain(b'F')))
|
||||
print(await tree.reference.str(0))
|
||||
with self.subTest('encrypt and migrate'):
|
||||
target = tree.reference
|
||||
with instrumentation:
|
||||
eeed = Encrypted.encrypt(target, key)
|
||||
eeed = await Encrypted.encrypt(target, key)
|
||||
print(instrumentation.counter)
|
||||
dr.save(HashPoint.of(eeed))
|
||||
print(ResolverMetaOrigin(dr).migrate_resolved(eeed).decrypted.str(0))
|
||||
await dr.save(HashPoint.of(eeed))
|
||||
print(await (await dr.migrate_resolved(eeed)).decrypted.str(0))
|
||||
with self.subTest('re-encrypt'):
|
||||
new_key = b'b' * 32
|
||||
target = eeed.decrypted
|
||||
with instrumentation:
|
||||
Encrypted.encrypt(target, new_key)
|
||||
await Encrypted.encrypt(target, new_key)
|
||||
print(instrumentation.counter)
|
||||
|
@ -6,5 +6,5 @@ Referenced = TypeVar('Referenced')
|
||||
|
||||
|
||||
class ThresholdProtocol(Generic[Referenced]):
|
||||
def threshold(self, referenced: Referenced) -> bytes:
|
||||
async def threshold(self, referenced: Referenced) -> bytes:
|
||||
raise NotImplementedError
|
||||
|
@ -22,9 +22,9 @@ class ValidReference(RecursiveMentionable, Generic[Referenced]):
|
||||
def points(self) -> Iterable[HashPoint]:
|
||||
return [self.reference]
|
||||
|
||||
def resolve(self) -> Referenced:
|
||||
referenced: Referenced = self.reference.resolve()
|
||||
assert self.reference.point < self.protocol.threshold(referenced)
|
||||
async def resolve(self) -> Referenced:
|
||||
referenced: Referenced = await self.reference.resolve()
|
||||
assert self.reference.point < (await self.protocol.threshold(referenced))
|
||||
return referenced
|
||||
|
||||
def __bytes__(self):
|
||||
|
@ -62,23 +62,20 @@ class BankChain(Generic[BlockType]):
|
||||
)
|
||||
)
|
||||
|
||||
def add(self, stack: NullableReference[Stack[Transaction]]) -> 'BankChain[BlockType]':
|
||||
async def add(self, stack: NullableReference[Stack[Transaction]]) -> 'BankChain[BlockType]':
|
||||
assert isinstance(stack, NullableReference)
|
||||
return BankChain(
|
||||
self.chain.add(HashPoint.of(stack))
|
||||
await self.chain.add(HashPoint.of(stack))
|
||||
)
|
||||
|
||||
def adds(self, transactions: list[Transaction]) -> 'BankChain[BlockType]':
|
||||
async def adds(self, transactions: list[Transaction]) -> 'BankChain[BlockType]':
|
||||
assert isinstance(transactions, list)
|
||||
return self.add(
|
||||
return await self.add(
|
||||
Stack.off(
|
||||
Transaction.factory(),
|
||||
reversed(transactions)
|
||||
)
|
||||
)
|
||||
|
||||
def verify(self) -> bool:
|
||||
return self.chain.verify()
|
||||
|
||||
def __str__(self):
|
||||
return self.reference.str(0)
|
||||
async def verify(self) -> bool:
|
||||
return await self.chain.verify()
|
||||
|
@ -19,22 +19,22 @@ __all__ = ('BankProtocol',)
|
||||
|
||||
|
||||
class BankProtocol(ReductionProtocol[NullableReference[Stack[Transaction]], BankState]):
|
||||
def reduce(
|
||||
async def reduce(
|
||||
self,
|
||||
reduction: Reduction[NullableReference[Stack[Transaction]], BankState]
|
||||
) -> ReductionResult[NullableReference[Stack[Transaction]], BankState]:
|
||||
assert isinstance(reduction, Reduction)
|
||||
bank_state: BankState = reduction.accumulator.resolve()
|
||||
bank_state: BankState = await reduction.accumulator.resolve()
|
||||
assert isinstance(bank_state, BankState)
|
||||
reference: NullableReference[Stack[Transaction]] = reduction.reductor.resolve()
|
||||
reference: NullableReference[Stack[Transaction]] = await reduction.reductor.resolve()
|
||||
if reference.null():
|
||||
return Reduced(HashPoint.of(bank_state.without_miner()))
|
||||
else:
|
||||
stack: Stack[Transaction] = reference.resolve()
|
||||
stack: Stack[Transaction] = await reference.resolve()
|
||||
assert isinstance(stack, Stack)
|
||||
return Reduction(
|
||||
HashPoint.of(stack.previous),
|
||||
HashPoint.of(bank_state.push(stack.element))
|
||||
HashPoint.of(await bank_state.push(stack.element))
|
||||
)
|
||||
|
||||
def initial(self, factory: RainbowFactory[BankState]) -> HashPoint[BankState]:
|
||||
@ -54,6 +54,6 @@ class BankProtocol(ReductionProtocol[NullableReference[Stack[Transaction]], Bank
|
||||
)
|
||||
)
|
||||
|
||||
def header_filter(self, state: HashPoint[BankState]) -> HashPoint[BankState]:
|
||||
async def header_filter(self, state: HashPoint[BankState]) -> HashPoint[BankState]:
|
||||
assert isinstance(state, HashPoint)
|
||||
return HashPoint.of(state.resolve().without_miner().advance())
|
||||
return HashPoint.of(await (await state.resolve()).without_miner().advance())
|
||||
|
@ -1,5 +1,6 @@
|
||||
from typing import Iterable
|
||||
from typing import AsyncIterable, Iterable
|
||||
|
||||
from rainbowadn.core.asserts import assert_false, assert_true
|
||||
from rainbowadn.core.hash_point_format import hash_point_format, tabulate
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.hashresolver import HashResolver
|
||||
@ -79,12 +80,12 @@ class BankState(RecursiveMentionable, StaticMentionable):
|
||||
self.length
|
||||
)
|
||||
|
||||
def advance(self) -> 'BankState':
|
||||
async def advance(self) -> 'BankState':
|
||||
return BankState(
|
||||
self.minted,
|
||||
self.used,
|
||||
NullableReference(Null(), self.miner.factory),
|
||||
HashPoint.of(Integer(self.length.resolve().integer + 1))
|
||||
HashPoint.of(Integer((await self.length.resolve()).integer + 1))
|
||||
)
|
||||
|
||||
def minted_tree(self) -> ActiveBinaryTree[Coin, Integer]:
|
||||
@ -97,25 +98,25 @@ class BankState(RecursiveMentionable, StaticMentionable):
|
||||
AVL(HashComparator(Fail())), self.used
|
||||
)
|
||||
|
||||
def use_coins(self, coins: Iterable[HashPoint[Coin]]) -> 'BankState':
|
||||
async def use_coins(self, coins: AsyncIterable[HashPoint[Coin]]) -> 'BankState':
|
||||
minted: ActiveBinaryTree[Coin, Integer] = self.minted_tree()
|
||||
used: ActiveBinaryTree[Coin, Integer] = self.used_tree()
|
||||
for in_coin in coins:
|
||||
assert minted.contains(in_coin)
|
||||
assert not used.contains(in_coin)
|
||||
used = used.add(in_coin)
|
||||
async for in_coin in coins:
|
||||
assert_true(await minted.contains(in_coin))
|
||||
assert_false(await used.contains(in_coin))
|
||||
used = await used.add(in_coin)
|
||||
return BankState(self.minted, used.reference, self.miner, self.length)
|
||||
|
||||
def mint_coins(
|
||||
async def mint_coins(
|
||||
self,
|
||||
transaction: Transaction
|
||||
) -> 'BankState':
|
||||
assert self.verify(transaction)
|
||||
assert_true(await self.verify(transaction))
|
||||
miner = self.miner_nullable()
|
||||
minted: ActiveBinaryTree[Coin, Integer] = self.minted_tree()
|
||||
for coin, miner in transaction.iter_coins(self.mint(), miner):
|
||||
assert not minted.contains(HashPoint.of(coin))
|
||||
minted = minted.add(HashPoint.of(coin))
|
||||
async for coin, miner in transaction.iter_coins(self.mint(), miner):
|
||||
assert_false(await minted.contains(HashPoint.of(coin)))
|
||||
minted = await minted.add(HashPoint.of(coin))
|
||||
assert isinstance(minted, ActiveBinaryTree)
|
||||
return BankState(minted.reference, self.used, NullableReference(miner, self.miner.factory), self.length)
|
||||
|
||||
@ -128,32 +129,34 @@ class BankState(RecursiveMentionable, StaticMentionable):
|
||||
else:
|
||||
return 0
|
||||
|
||||
def verify(self, transaction: Transaction) -> bool:
|
||||
async def verify(self, transaction: Transaction) -> bool:
|
||||
assert isinstance(transaction, Transaction)
|
||||
assert transaction.verify(self.mint())
|
||||
assert_true(await transaction.verify(self.mint()))
|
||||
return True
|
||||
|
||||
def _push(self, transaction: Transaction) -> 'BankState':
|
||||
async def _push(self, transaction: Transaction) -> 'BankState':
|
||||
assert isinstance(transaction, Transaction)
|
||||
return self.use_coins(
|
||||
transaction.data_resolved().iter_in_coins()
|
||||
return await (
|
||||
await self.use_coins(
|
||||
(await transaction.data_resolved()).iter_in_coins()
|
||||
)
|
||||
).mint_coins(
|
||||
transaction
|
||||
)
|
||||
|
||||
def push(self, transaction: HashPoint[Transaction]) -> 'BankState':
|
||||
return self._push(transaction.resolve())
|
||||
async def push(self, transaction: HashPoint[Transaction]) -> 'BankState':
|
||||
return await self._push(await transaction.resolve())
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'(' \
|
||||
f'{tabulate(tab + 1)}bank' \
|
||||
f'{tabulate(tab + 1)}(miner)' \
|
||||
f'{tabulate(tab + 1)}{self.miner.str(tab + 1)}' \
|
||||
f'{tabulate(tab + 1)}{await self.miner.str(tab + 1)}' \
|
||||
f'{tabulate(tab + 1)}(minted)' \
|
||||
f'{tabulate(tab + 1)}{self.minted.str(tab + 1)}' \
|
||||
f'{tabulate(tab + 1)}{await self.minted.str(tab + 1)}' \
|
||||
f'{tabulate(tab + 1)}(used)' \
|
||||
f'{tabulate(tab + 1)}{self.used.str(tab + 1)}' \
|
||||
f'{tabulate(tab + 1)}{await self.used.str(tab + 1)}' \
|
||||
f'{tabulate(tab + 1)}(length)' \
|
||||
f'{tabulate(tab + 1)}{hash_point_format(self.length, tab + 1)}' \
|
||||
f'{tabulate(tab + 1)}{await hash_point_format(self.length, tab + 1)}' \
|
||||
f'{tabulate(tab)})'
|
||||
|
@ -2,6 +2,7 @@ import nacl.bindings
|
||||
import nacl.exceptions
|
||||
import nacl.signing
|
||||
|
||||
from rainbowadn.core.asserts import assert_eq
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.data.atomic.atomic import Atomic
|
||||
from rainbowadn.v13.subject import Subject
|
||||
@ -16,7 +17,7 @@ class BadSignature(nacl.exceptions.BadSignatureError):
|
||||
class Signature(Atomic):
|
||||
def __init__(self, source: bytes):
|
||||
assert isinstance(source, bytes)
|
||||
assert len(source) == nacl.bindings.crypto_sign_BYTES
|
||||
assert_eq(len(source), nacl.bindings.crypto_sign_BYTES)
|
||||
self.source = source
|
||||
|
||||
@classmethod
|
||||
|
@ -1,7 +1,8 @@
|
||||
from typing import Iterable
|
||||
from typing import AsyncIterable, Iterable
|
||||
|
||||
import nacl.signing
|
||||
|
||||
from rainbowadn.core.asserts import assert_true
|
||||
from rainbowadn.core.hash_point_format import hash_point_format, tabulate
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.hashresolver import HashResolver
|
||||
@ -31,8 +32,8 @@ class CoinData(RecursiveMentionable, StaticMentionable):
|
||||
self.owner = owner
|
||||
self.value = value
|
||||
|
||||
def int_value(self) -> int:
|
||||
return self.value.resolve().integer
|
||||
async def int_value(self) -> int:
|
||||
return (await self.value.resolve()).integer
|
||||
|
||||
@classmethod
|
||||
def of(cls, owner: Subject, value: int) -> 'CoinData':
|
||||
@ -55,10 +56,10 @@ class CoinData(RecursiveMentionable, StaticMentionable):
|
||||
ResolverOrigin(Integer.factory(), source[HashPoint.HASH_LENGTH:], resolver).hash_point(),
|
||||
)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'{hash_point_format(self.owner, tab)}' \
|
||||
f'{tabulate(tab)}{hash_point_format(self.value, tab)}'
|
||||
return f'{await hash_point_format(self.owner, tab)}' \
|
||||
f'{tabulate(tab)}{await hash_point_format(self.value, tab)}'
|
||||
|
||||
|
||||
class Coin(RecursiveMentionable, StaticMentionable):
|
||||
@ -75,8 +76,8 @@ class Coin(RecursiveMentionable, StaticMentionable):
|
||||
self.origin = origin
|
||||
self.index = index
|
||||
|
||||
def data_resolved(self) -> CoinData:
|
||||
return self.data.resolve()
|
||||
async def data_resolved(self) -> CoinData:
|
||||
return await self.data.resolve()
|
||||
|
||||
def points(self) -> Iterable[HashPoint]:
|
||||
return [self.data, self.origin, self.index]
|
||||
@ -96,13 +97,13 @@ class Coin(RecursiveMentionable, StaticMentionable):
|
||||
ResolverOrigin(Integer.factory(), source[2 * HashPoint.HASH_LENGTH:], resolver).hash_point(),
|
||||
)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'(' \
|
||||
f'{tabulate(tab + 1)}coin' \
|
||||
f'{tabulate(tab + 1)}{hash_point_format(self.data, tab + 1)}' \
|
||||
f'{tabulate(tab + 1)}{await hash_point_format(self.data, tab + 1)}' \
|
||||
f'{tabulate(tab + 1)}(origin)' \
|
||||
f'{tabulate(tab + 1)}{hash_point_format(self.index, tab + 1)}' \
|
||||
f'{tabulate(tab + 1)}{await hash_point_format(self.index, tab + 1)}' \
|
||||
f'{tabulate(tab)})'
|
||||
|
||||
|
||||
@ -138,59 +139,65 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
|
||||
).from_bytes(source[HashPoint.HASH_LENGTH:], resolver),
|
||||
)
|
||||
|
||||
def _verify_signatures(
|
||||
async def _verify_signatures(
|
||||
self,
|
||||
signatures: NullableReference[Stack[Signature]]
|
||||
) -> bool:
|
||||
for coin, signature in zip(self.iter_in_coins_resolved(), Stack.iter(signatures), strict=True):
|
||||
assert signature.resolve().verify(
|
||||
coin.data_resolved().owner.resolve(),
|
||||
for coin, signature in zip(
|
||||
[x async for x in self.iter_in_coins_resolved()],
|
||||
[x async for x in Stack.iter(signatures)],
|
||||
strict=True
|
||||
):
|
||||
assert_true(
|
||||
(await signature.resolve()).verify(
|
||||
await (await coin.data_resolved()).owner.resolve(),
|
||||
self.hash_point
|
||||
)
|
||||
)
|
||||
return True
|
||||
|
||||
def iter_in_coins(self) -> Iterable[HashPoint[Coin]]:
|
||||
def iter_in_coins(self) -> AsyncIterable[HashPoint[Coin]]:
|
||||
return Stack.iter(self.in_coins)
|
||||
|
||||
def iter_in_coins_resolved(self) -> Iterable[Coin]:
|
||||
for coin in Stack.iter(self.in_coins):
|
||||
yield coin.resolve()
|
||||
async def iter_in_coins_resolved(self) -> AsyncIterable[Coin]:
|
||||
async for coin in self.iter_in_coins():
|
||||
yield await coin.resolve()
|
||||
|
||||
def _total_in(self) -> int:
|
||||
return sum(coin.data_resolved().int_value() for coin in self.iter_in_coins_resolved())
|
||||
async def _total_in(self) -> int:
|
||||
return sum([await (await coin.data_resolved()).int_value() async for coin in self.iter_in_coins_resolved()])
|
||||
|
||||
def iter_out_coins(self) -> Iterable[HashPoint[CoinData]]:
|
||||
def iter_out_coins(self) -> AsyncIterable[HashPoint[CoinData]]:
|
||||
return Stack.iter(self.out_coins)
|
||||
|
||||
def _total_out(self) -> int:
|
||||
return sum(coin.resolve().int_value() for coin in self.iter_out_coins())
|
||||
async def _total_out(self) -> int:
|
||||
return sum([await (await coin.resolve()).int_value() async for coin in self.iter_out_coins()])
|
||||
|
||||
def _verify_values(self, mint: int) -> bool:
|
||||
async def _verify_values(self, mint: int) -> bool:
|
||||
assert isinstance(mint, int)
|
||||
assert self._total_out() <= self._total_in() + mint
|
||||
assert (await self.extra(mint)) >= 0
|
||||
return True
|
||||
|
||||
def extra(self, mint: int) -> int:
|
||||
async def extra(self, mint: int) -> int:
|
||||
assert isinstance(mint, int)
|
||||
return self._total_in() + mint - self._total_out()
|
||||
return (await self._total_in()) + mint - (await self._total_out())
|
||||
|
||||
def verify(
|
||||
async def verify(
|
||||
self,
|
||||
signatures: NullableReference[Stack[Signature]],
|
||||
mint: int
|
||||
) -> bool:
|
||||
assert isinstance(signatures, NullableReference)
|
||||
assert isinstance(mint, int)
|
||||
assert self._verify_signatures(signatures)
|
||||
assert self._verify_values(mint)
|
||||
assert_true(await self._verify_signatures(signatures))
|
||||
assert_true(await self._verify_values(mint))
|
||||
return True
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'(in)' \
|
||||
f'{tabulate(tab)}{self.in_coins.str(tab)}' \
|
||||
f'{tabulate(tab)}{await self.in_coins.str(tab)}' \
|
||||
f'{tabulate(tab)}(out)' \
|
||||
f'{tabulate(tab)}{self.out_coins.str(tab)}'
|
||||
f'{tabulate(tab)}{await self.out_coins.str(tab)}'
|
||||
|
||||
|
||||
class Transaction(RecursiveMentionable, StaticMentionable):
|
||||
@ -206,8 +213,8 @@ class Transaction(RecursiveMentionable, StaticMentionable):
|
||||
self.hash_point = HashPoint.of(self)
|
||||
assert isinstance(self.hash_point, HashPoint)
|
||||
|
||||
def data_resolved(self) -> TransactionData:
|
||||
return self.data.resolve()
|
||||
async def data_resolved(self) -> TransactionData:
|
||||
return await self.data.resolve()
|
||||
|
||||
def points(self) -> Iterable[HashPoint]:
|
||||
return [self.data, *self.signatures.points()]
|
||||
@ -228,19 +235,19 @@ class Transaction(RecursiveMentionable, StaticMentionable):
|
||||
NullableReferenceFactory(stack_factory).from_bytes(source[HashPoint.HASH_LENGTH:], resolver),
|
||||
)
|
||||
|
||||
def iter_coins(
|
||||
async def iter_coins(
|
||||
self,
|
||||
mint: int,
|
||||
miner: Nullable[HashPoint[Subject]]
|
||||
) -> Iterable[tuple[Coin, Nullable[HashPoint[Subject]]]]:
|
||||
transaction_data: TransactionData = self.data_resolved()
|
||||
) -> AsyncIterable[tuple[Coin, Nullable[HashPoint[Subject]]]]:
|
||||
transaction_data: TransactionData = await self.data_resolved()
|
||||
assert isinstance(transaction_data, TransactionData)
|
||||
index = 0
|
||||
out_coin: HashPoint[CoinData]
|
||||
for out_coin in transaction_data.iter_out_coins():
|
||||
async for out_coin in transaction_data.iter_out_coins():
|
||||
assert isinstance(out_coin, HashPoint)
|
||||
if miner.null():
|
||||
miner = NotNull(out_coin.resolve().owner)
|
||||
miner = NotNull((await out_coin.resolve()).owner)
|
||||
assert isinstance(miner, Nullable)
|
||||
coin: Coin = Coin(out_coin, self.hash_point, HashPoint.of(Integer(index)))
|
||||
assert isinstance(coin, Coin)
|
||||
@ -251,7 +258,7 @@ class Transaction(RecursiveMentionable, StaticMentionable):
|
||||
HashPoint.of(
|
||||
CoinData(
|
||||
miner.resolve(),
|
||||
HashPoint.of(Integer(transaction_data.extra(mint)))
|
||||
HashPoint.of(Integer(await transaction_data.extra(mint)))
|
||||
)
|
||||
),
|
||||
self.hash_point,
|
||||
@ -260,23 +267,23 @@ class Transaction(RecursiveMentionable, StaticMentionable):
|
||||
assert isinstance(coin, Coin)
|
||||
yield coin, miner
|
||||
|
||||
def coins(
|
||||
async def coins(
|
||||
self,
|
||||
mint: int,
|
||||
miner: Nullable[HashPoint[Subject]]
|
||||
) -> list[Coin]:
|
||||
assert isinstance(mint, int)
|
||||
assert isinstance(miner, Nullable)
|
||||
return [coin for coin, _ in self.iter_coins(mint, miner)]
|
||||
return [coin async for coin, _ in self.iter_coins(mint, miner)]
|
||||
|
||||
def verify(self, mint: int):
|
||||
async def verify(self, mint: int):
|
||||
assert isinstance(mint, int)
|
||||
data: TransactionData = self.data_resolved()
|
||||
data: TransactionData = await self.data_resolved()
|
||||
assert isinstance(data, TransactionData)
|
||||
assert data.verify(self.signatures, mint)
|
||||
assert_true(await data.verify(self.signatures, mint))
|
||||
return True
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'(' \
|
||||
f'{tabulate(tab + 1)}transaction' \
|
||||
|
@ -1,6 +1,7 @@
|
||||
import bisect
|
||||
from typing import Iterable, Sequence
|
||||
from typing import AsyncIterable, Iterable, Sequence
|
||||
|
||||
from rainbowadn.core.asserts import assert_eq
|
||||
from rainbowadn.core.hash_point_format import hash_point_format, tabulate
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.hashresolver import HashResolver
|
||||
@ -47,7 +48,7 @@ class WeakReferenceIndexSetBTree(RecursiveMentionable):
|
||||
else:
|
||||
self.keys = self.length // (parametres.keysize + HashPoint.HASH_LENGTH)
|
||||
self.children = self.keys + 1
|
||||
assert self.length == self.keys * parametres.keysize + self.children * HashPoint.HASH_LENGTH
|
||||
assert_eq(self.length, self.keys * parametres.keysize + self.children * HashPoint.HASH_LENGTH)
|
||||
|
||||
self.parametres = parametres
|
||||
self.keymin = parametres.keymin
|
||||
@ -60,7 +61,7 @@ class WeakReferenceIndexSetBTree(RecursiveMentionable):
|
||||
|
||||
self.keyend = self.keys * self.keysize
|
||||
|
||||
assert len(cache) == self.children
|
||||
assert_eq(len(cache), self.children)
|
||||
self.cache = cache
|
||||
|
||||
def full(self) -> bool:
|
||||
@ -95,11 +96,11 @@ class WeakReferenceIndexSetBTree(RecursiveMentionable):
|
||||
self.bytes_no(index, self.keyend, HashPoint.HASH_LENGTH)
|
||||
)
|
||||
|
||||
def child_resolved_no(self, index: int) -> 'WeakReferenceIndexSetBTree':
|
||||
async def child_resolved_no(self, index: int) -> 'WeakReferenceIndexSetBTree':
|
||||
assert isinstance(index, int)
|
||||
assert 0 <= index < self.children
|
||||
assert not self.leaf
|
||||
return self.child_no(index).resolve()
|
||||
return await self.child_no(index).resolve()
|
||||
|
||||
def balanced(self) -> bool:
|
||||
return self.keys <= 2 * self.keymin
|
||||
@ -157,7 +158,7 @@ class WeakReferenceIndexSetBTree(RecursiveMentionable):
|
||||
self.range(self.keymin + 1, 2 * self.keymin + 1),
|
||||
)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
|
||||
formatted = f'{self.height}' \
|
||||
@ -165,14 +166,14 @@ class WeakReferenceIndexSetBTree(RecursiveMentionable):
|
||||
for key_index in range(self.keys):
|
||||
formatted += f'{tabulate(tab + 1)}{self.key_no(key_index).hex()}'
|
||||
for child_index in range(self.children):
|
||||
formatted += f'{tabulate(tab + 1)}{hash_point_format(self.child_no(child_index), tab + 1)}'
|
||||
formatted += f'{tabulate(tab + 1)}{await hash_point_format(self.child_no(child_index), tab + 1)}'
|
||||
|
||||
return f'{formatted}' \
|
||||
f'{tabulate(tab)})'
|
||||
|
||||
def contains(self, key: bytes) -> bool:
|
||||
async def contains(self, key: bytes) -> bool:
|
||||
assert isinstance(key, bytes)
|
||||
assert len(key) == self.keysize
|
||||
assert_eq(len(key), self.keysize)
|
||||
|
||||
assert self.balanced()
|
||||
|
||||
@ -187,13 +188,13 @@ class WeakReferenceIndexSetBTree(RecursiveMentionable):
|
||||
assert key > self.key_no(index - 1)
|
||||
if self.leaf:
|
||||
return False
|
||||
child: WeakReferenceIndexSetBTree = self.child_resolved_no(index)
|
||||
child: WeakReferenceIndexSetBTree = await self.child_resolved_no(index)
|
||||
assert isinstance(child, WeakReferenceIndexSetBTree)
|
||||
return child.contains(key)
|
||||
return await child.contains(key)
|
||||
|
||||
def add(self, key: bytes) -> 'WeakReferenceIndexSetBTree':
|
||||
async def add(self, key: bytes) -> 'WeakReferenceIndexSetBTree':
|
||||
assert isinstance(key, bytes)
|
||||
assert len(key) == self.keysize
|
||||
assert_eq(len(key), self.keysize)
|
||||
|
||||
assert self.balanced()
|
||||
|
||||
@ -214,9 +215,9 @@ class WeakReferenceIndexSetBTree(RecursiveMentionable):
|
||||
self.root,
|
||||
()
|
||||
)
|
||||
child: WeakReferenceIndexSetBTree = self.child_resolved_no(index)
|
||||
child: WeakReferenceIndexSetBTree = await self.child_resolved_no(index)
|
||||
assert isinstance(child, WeakReferenceIndexSetBTree)
|
||||
child: WeakReferenceIndexSetBTree = child.add(key)
|
||||
child: WeakReferenceIndexSetBTree = await child.add(key)
|
||||
assert isinstance(child, WeakReferenceIndexSetBTree)
|
||||
if child.full():
|
||||
left, middle, right = child.split()
|
||||
@ -269,7 +270,7 @@ class WeakReferenceIndexSetBTree(RecursiveMentionable):
|
||||
)
|
||||
)
|
||||
|
||||
def iter_keys(self) -> Iterable[bytes]:
|
||||
async def iter_keys(self) -> AsyncIterable[bytes]:
|
||||
if self.leaf:
|
||||
for key_index in range(self.keys):
|
||||
yield self.key_no(key_index)
|
||||
@ -279,7 +280,8 @@ class WeakReferenceIndexSetBTree(RecursiveMentionable):
|
||||
if mode:
|
||||
yield self.key_no(real_index)
|
||||
else:
|
||||
yield from self.child_resolved_no(real_index).iter_keys()
|
||||
async for key in (await self.child_resolved_no(real_index)).iter_keys():
|
||||
yield key
|
||||
|
||||
|
||||
class KeyView(Sequence[WeakReferenceIndexSetBTree]):
|
||||
|
@ -40,6 +40,6 @@ class WrisbtChainProtocol(
|
||||
def actual_state_factory(self) -> RainbowFactory[WrisbtRoot]:
|
||||
return WrisbtRootFactory(WrisbtParametres(self.keymin, HashPoint.HASH_LENGTH))
|
||||
|
||||
def actual_state(self, state: WrisbtIndex) -> HashPoint[WrisbtRoot]:
|
||||
async def actual_state(self, state: WrisbtIndex) -> HashPoint[WrisbtRoot]:
|
||||
assert isinstance(state, WrisbtIndex)
|
||||
return state.total
|
||||
|
@ -36,11 +36,11 @@ class WrisbtIndex(RecursiveMentionable):
|
||||
def __factory__(self) -> RainbowFactory['WrisbtIndex']:
|
||||
return WrisbtIndexFactory(self.keymin)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'(index)' \
|
||||
f'{tabulate(tab)}{hash_point_format(self.total, tab)}' \
|
||||
f'{tabulate(tab)}{hash_point_format(self.delta, tab)}'
|
||||
f'{tabulate(tab)}{await hash_point_format(self.total, tab)}' \
|
||||
f'{tabulate(tab)}{await hash_point_format(self.delta, tab)}'
|
||||
|
||||
|
||||
class WrisbtIndexFactory(RainbowFactory[WrisbtIndex]):
|
||||
|
@ -26,25 +26,25 @@ class WrisbtProtocol(MetaReductionStateProtocol[TargetType, WrisbtIndex]):
|
||||
)
|
||||
)
|
||||
|
||||
def _derive(
|
||||
async def _derive(
|
||||
self,
|
||||
previous: HashPoint[WrisbtIndex],
|
||||
header: HashPoint[TargetType]
|
||||
) -> HashPoint[WrisbtIndex]:
|
||||
assert isinstance(previous, HashPoint)
|
||||
assert isinstance(header, HashPoint)
|
||||
index: WrisbtIndex = previous.resolve()
|
||||
index: WrisbtIndex = await previous.resolve()
|
||||
assert isinstance(index, WrisbtIndex)
|
||||
|
||||
empty: WrisbtRoot = WrisbtRoot.empty(WrisbtParametres(self.keymin, HashPoint.HASH_LENGTH))
|
||||
assert isinstance(empty, WrisbtRoot)
|
||||
total: WrisbtRoot = index.total.resolve()
|
||||
total: WrisbtRoot = await index.total.resolve()
|
||||
assert isinstance(total, WrisbtRoot)
|
||||
|
||||
return HashPoint.of(
|
||||
WrisbtIndex(
|
||||
HashPoint.of(total.index(header, empty)),
|
||||
HashPoint.of(empty.index(header, total)),
|
||||
HashPoint.of(await total.index(header, empty)),
|
||||
HashPoint.of(await empty.index(header, total)),
|
||||
index.keymin
|
||||
)
|
||||
)
|
||||
|
@ -1,5 +1,6 @@
|
||||
from typing import Iterable
|
||||
|
||||
from rainbowadn.core.asserts import assert_eq
|
||||
from rainbowadn.core.hash_point_format import hash_point_format, tabulate
|
||||
from rainbowadn.core.hashpoint import HashPoint
|
||||
from rainbowadn.core.hashresolver import HashResolver
|
||||
@ -25,8 +26,8 @@ class WrisbtRoot(RecursiveMentionable):
|
||||
self.height = height
|
||||
self.parametres = parametres
|
||||
|
||||
def root_resolved(self) -> 'WeakReferenceIndexSetBTree':
|
||||
return self.root.resolve()
|
||||
async def root_resolved(self) -> 'WeakReferenceIndexSetBTree':
|
||||
return await self.root.resolve()
|
||||
|
||||
def points(self) -> Iterable[HashPoint]:
|
||||
return [self.root]
|
||||
@ -42,26 +43,26 @@ class WrisbtRoot(RecursiveMentionable):
|
||||
assert isinstance(parametres, WrisbtParametres)
|
||||
return WrisbtRoot(HashPoint.of(WeakReferenceIndexSetBTree(b'', 0, parametres, True, ())), 0, parametres)
|
||||
|
||||
def str(self, tab: int) -> str:
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
return f'(root)' \
|
||||
f'{tabulate(tab)}{self.height}' \
|
||||
f'{tabulate(tab)}{hash_point_format(self.root, tab)}'
|
||||
f'{tabulate(tab)}{await hash_point_format(self.root, tab)}'
|
||||
|
||||
def contains(self, key: bytes) -> bool:
|
||||
async def contains(self, key: bytes) -> bool:
|
||||
assert isinstance(key, bytes)
|
||||
assert len(key) == self.parametres.keysize
|
||||
assert_eq(len(key), self.parametres.keysize)
|
||||
|
||||
root: WeakReferenceIndexSetBTree = self.root_resolved()
|
||||
root: WeakReferenceIndexSetBTree = await self.root_resolved()
|
||||
assert isinstance(root, WeakReferenceIndexSetBTree)
|
||||
|
||||
return root.contains(key)
|
||||
return await root.contains(key)
|
||||
|
||||
def add(self, key: bytes) -> 'WrisbtRoot':
|
||||
async def add(self, key: bytes) -> 'WrisbtRoot':
|
||||
assert isinstance(key, bytes)
|
||||
assert len(key) == self.parametres.keysize
|
||||
assert_eq(len(key), self.parametres.keysize)
|
||||
|
||||
root: WeakReferenceIndexSetBTree = self.root_resolved().add(key)
|
||||
root: WeakReferenceIndexSetBTree = await (await self.root_resolved()).add(key)
|
||||
assert isinstance(root, WeakReferenceIndexSetBTree)
|
||||
|
||||
if root.full():
|
||||
@ -84,25 +85,25 @@ class WrisbtRoot(RecursiveMentionable):
|
||||
assert isinstance(root, WeakReferenceIndexSetBTree)
|
||||
return cls(HashPoint.of(root), root.height, root.parametres)
|
||||
|
||||
def keys(self) -> list[bytes]:
|
||||
return list(self.root_resolved().iter_keys())
|
||||
async def keys(self) -> list[bytes]:
|
||||
return list([x async for x in (await self.root_resolved()).iter_keys()])
|
||||
|
||||
def index(
|
||||
async def index(
|
||||
self, target: HashPoint, exclude: 'WrisbtRoot'
|
||||
) -> 'WrisbtRoot':
|
||||
assert isinstance(target, HashPoint)
|
||||
assert isinstance(exclude, WrisbtRoot)
|
||||
key: bytes = target.point
|
||||
assert isinstance(key, bytes)
|
||||
if exclude.contains(key) or self.contains(key):
|
||||
if await exclude.contains(key) or await self.contains(key):
|
||||
return self
|
||||
tree = self
|
||||
value: Mentionable = target.resolve()
|
||||
tree: WrisbtRoot = self
|
||||
value: Mentionable = await target.resolve()
|
||||
assert isinstance(value, Mentionable)
|
||||
if isinstance(value, RecursiveMentionable):
|
||||
for hash_point in value.points():
|
||||
tree = tree.index(hash_point, exclude)
|
||||
tree = tree.add(key)
|
||||
tree = await tree.index(hash_point, exclude)
|
||||
tree = await tree.add(key)
|
||||
return tree
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user