gather
This commit is contained in:
parent
1a19695e6e
commit
8daaefa4a4
88
plot.py
Normal file
88
plot.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import asyncio
|
||||||
|
import random
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
from nacl.signing import SigningKey
|
||||||
|
|
||||||
|
from rainbowadn.chain import *
|
||||||
|
from rainbowadn.core import *
|
||||||
|
from rainbowadn.nullability import *
|
||||||
|
from rainbowadn.testing.delayedresolver import DelayedResolver
|
||||||
|
from rainbowadn.testing.dictresolver import DictResolver
|
||||||
|
from rainbowadn.testing.instrumentation import Concurrency
|
||||||
|
from rainbowadn.v13 import *
|
||||||
|
|
||||||
|
plt.rcParams['figure.figsize'] = [12, 6]
|
||||||
|
|
||||||
|
plt.style.use("dark_background")
|
||||||
|
|
||||||
|
plt.subplots_adjust(left=0.05, right=0.99, top=0.99, bottom=0.1)
|
||||||
|
|
||||||
|
|
||||||
|
def get_dr() -> ExtendableResolver:
|
||||||
|
dr = DictResolver()
|
||||||
|
dr = DelayedResolver(dr, lambda: random.uniform(0.200, 0.500))
|
||||||
|
return dr
|
||||||
|
|
||||||
|
|
||||||
|
def plot(instrumentation: Concurrency):
|
||||||
|
plt.plot(*np.array(instrumentation.logs).transpose())
|
||||||
|
|
||||||
|
|
||||||
|
async def plot_every_minute(instrumentation: Concurrency):
|
||||||
|
while True:
|
||||||
|
await asyncio.sleep(60)
|
||||||
|
plot(instrumentation)
|
||||||
|
plt.show()
|
||||||
|
plt.clf()
|
||||||
|
plt.subplots_adjust(left=0.05, right=0.99, top=0.99, bottom=0.1)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
set_gather_asyncio()
|
||||||
|
bank: BankChain = BankChain.empty(ReductionChainMetaFactory().loose())
|
||||||
|
key_0 = SigningKey.generate()
|
||||||
|
transaction_0 = Transaction.make(
|
||||||
|
[],
|
||||||
|
[CoinData.of(Subject(key_0.verify_key), 100_000)],
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
coin_0, coin_1 = await transaction_0.coins(MINT_CONST, NotNull(HashPoint.of(Subject(key_0.verify_key))))
|
||||||
|
bank = await bank.adds(
|
||||||
|
[
|
||||||
|
transaction_0,
|
||||||
|
Transaction.make(
|
||||||
|
[coin_1],
|
||||||
|
[CoinData.of(Subject(SigningKey.generate().verify_key), 10_000)],
|
||||||
|
[key_0]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
for _ in range(16):
|
||||||
|
bank = await bank.adds(
|
||||||
|
[
|
||||||
|
Transaction.make(
|
||||||
|
[],
|
||||||
|
[CoinData.of(Subject(SigningKey.generate().verify_key), 0)] * 16,
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
for _ in range(16)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
print('built')
|
||||||
|
assert_true(await bank.verify())
|
||||||
|
bank = BankChain.from_reference(
|
||||||
|
ReductionChainMetaFactory(), await get_dr().migrate_resolved(bank.reference)
|
||||||
|
)
|
||||||
|
print('saved')
|
||||||
|
set_gather_asyncio()
|
||||||
|
with Concurrency(DelayedResolver, 'sleep') as sleeps:
|
||||||
|
# task = asyncio.create_task(plot_every_minute(sleeps))
|
||||||
|
assert_true(await bank.verify())
|
||||||
|
# task.cancel()
|
||||||
|
plot(sleeps)
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(main())
|
@ -37,13 +37,18 @@ class Block(RecursiveMentionable, Generic[HeaderType, StateType]):
|
|||||||
|
|
||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
return f'{await self.previous.str(tab)}' \
|
previous_str, header_str, state_str = await gather(
|
||||||
|
self.previous.str(tab),
|
||||||
|
hash_point_format(self.header, tab + 1),
|
||||||
|
hash_point_format(self.state, tab + 1),
|
||||||
|
)
|
||||||
|
return f'{previous_str}' \
|
||||||
f'{tabulate(tab)}(' \
|
f'{tabulate(tab)}(' \
|
||||||
f'{tabulate(tab + 1)}block' \
|
f'{tabulate(tab + 1)}block' \
|
||||||
f'{tabulate(tab + 1)}(header)' \
|
f'{tabulate(tab + 1)}(header)' \
|
||||||
f'{tabulate(tab + 1)}{await hash_point_format(self.header, tab + 1)}' \
|
f'{tabulate(tab + 1)}{header_str}' \
|
||||||
f'{tabulate(tab + 1)}(state)' \
|
f'{tabulate(tab + 1)}(state)' \
|
||||||
f'{tabulate(tab + 1)}{await hash_point_format(self.state, tab + 1)}' \
|
f'{tabulate(tab + 1)}{state_str}' \
|
||||||
f'{tabulate(tab)})'
|
f'{tabulate(tab)})'
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import asyncio
|
|
||||||
from typing import Generic, TypeVar
|
from typing import Generic, TypeVar
|
||||||
|
|
||||||
from rainbowadn.core import *
|
from rainbowadn.core import *
|
||||||
@ -126,8 +125,12 @@ class BlockChain(
|
|||||||
previous: ChainCollectionInterface[
|
previous: ChainCollectionInterface[
|
||||||
Block[HeaderType, StateType], HeaderType, ActualStateType
|
Block[HeaderType, StateType], HeaderType, ActualStateType
|
||||||
] = await self.previous()
|
] = await self.previous()
|
||||||
assert_true(await self.verify_link(previous.reference))
|
assert_trues(
|
||||||
assert_true(await asyncio.create_task(previous.verify()))
|
await gather(
|
||||||
|
self.verify_link(previous.reference),
|
||||||
|
previous.verify(),
|
||||||
|
)
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def _verify_link(
|
async def _verify_link(
|
||||||
|
@ -36,6 +36,30 @@ class ActiveStageStateProtocol(
|
|||||||
self.stage_factory = stage_factory
|
self.stage_factory = stage_factory
|
||||||
self.base_state_factory = base_state_factory
|
self.base_state_factory = base_state_factory
|
||||||
|
|
||||||
|
async def verify(
|
||||||
|
self,
|
||||||
|
previous: NullableReference[
|
||||||
|
StateStage[
|
||||||
|
HeaderType,
|
||||||
|
BaseStateType,
|
||||||
|
StageType
|
||||||
|
]
|
||||||
|
],
|
||||||
|
header: HashPoint[HeaderType],
|
||||||
|
state: HashPoint[
|
||||||
|
StateStage[
|
||||||
|
HeaderType,
|
||||||
|
BaseStateType,
|
||||||
|
StageType
|
||||||
|
]
|
||||||
|
]
|
||||||
|
) -> bool:
|
||||||
|
return await self.stage_state_protocol().verify(
|
||||||
|
previous,
|
||||||
|
header,
|
||||||
|
state
|
||||||
|
)
|
||||||
|
|
||||||
async def derive(
|
async def derive(
|
||||||
self,
|
self,
|
||||||
previous: NullableReference[
|
previous: NullableReference[
|
||||||
|
@ -73,17 +73,17 @@ class StageStage(
|
|||||||
else:
|
else:
|
||||||
previous_stage: StageStage[HeaderType, BaseStateType, StageType] = await self.previous.resolve()
|
previous_stage: StageStage[HeaderType, BaseStateType, StageType] = await self.previous.resolve()
|
||||||
assert isinstance(previous_stage, StageStage)
|
assert isinstance(previous_stage, StageStage)
|
||||||
assert_true(
|
assert_trues(
|
||||||
await self.protocol.verify_stage(
|
await gather(
|
||||||
|
self.protocol.verify_stage(
|
||||||
previous_stage.stage,
|
previous_stage.stage,
|
||||||
self.stage
|
self.stage
|
||||||
)
|
),
|
||||||
)
|
previous_stage.verify(
|
||||||
assert_true(
|
|
||||||
await previous_stage.verify(
|
|
||||||
previous,
|
previous,
|
||||||
header,
|
header,
|
||||||
base_factory
|
base_factory
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
@ -102,8 +102,12 @@ class StageStage(
|
|||||||
|
|
||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
return f'{await self.previous.str(tab)}' \
|
previous_str, stage_str = await gather(
|
||||||
f'{tabulate(tab)}{await hash_point_format(self.stage, tab)}'
|
self.previous.str(tab),
|
||||||
|
hash_point_format(self.stage, tab)
|
||||||
|
)
|
||||||
|
return f'{previous_str}' \
|
||||||
|
f'{tabulate(tab)}{stage_str}'
|
||||||
|
|
||||||
|
|
||||||
class StageStageFactory(RainbowFactory[StageStage[HeaderType, BaseStateType, StageType]]):
|
class StageStageFactory(RainbowFactory[StageStage[HeaderType, BaseStateType, StageType]]):
|
||||||
@ -157,19 +161,19 @@ class StateStage(
|
|||||||
assert isinstance(header, HashPoint)
|
assert isinstance(header, HashPoint)
|
||||||
previous_stage: StageStage[HeaderType, BaseStateType, StageType] = await self.previous.resolve()
|
previous_stage: StageStage[HeaderType, BaseStateType, StageType] = await self.previous.resolve()
|
||||||
assert isinstance(previous_stage, StageStage)
|
assert isinstance(previous_stage, StageStage)
|
||||||
assert_true(
|
assert_trues(
|
||||||
await self.protocol.verify_state(
|
await gather(
|
||||||
|
self.protocol.verify_state(
|
||||||
previous_stage.stage,
|
previous_stage.stage,
|
||||||
self.state
|
self.state
|
||||||
)
|
),
|
||||||
)
|
previous_stage.verify(
|
||||||
assert_true(
|
|
||||||
await previous_stage.verify(
|
|
||||||
previous,
|
previous,
|
||||||
header,
|
header,
|
||||||
self.state.factory
|
self.state.factory
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def points(self) -> Iterable[HashPoint]:
|
def points(self) -> Iterable[HashPoint]:
|
||||||
@ -187,8 +191,12 @@ class StateStage(
|
|||||||
|
|
||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
return f'{await hash_point_format(self.previous, tab)}' \
|
previous_str, state_str = await gather(
|
||||||
f'{tabulate(tab)}{await hash_point_format(self.state, tab)}'
|
hash_point_format(self.previous, tab),
|
||||||
|
hash_point_format(self.state, tab),
|
||||||
|
)
|
||||||
|
return f'{previous_str}' \
|
||||||
|
f'{tabulate(tab)}{state_str}'
|
||||||
|
|
||||||
|
|
||||||
class StateStageFactory(RainbowFactory[StateStage[HeaderType, BaseStateType, StageType]]):
|
class StateStageFactory(RainbowFactory[StateStage[HeaderType, BaseStateType, StageType]]):
|
||||||
|
@ -11,18 +11,6 @@ StateType = TypeVar('StateType')
|
|||||||
|
|
||||||
|
|
||||||
class MetaReductionStateProtocol(ActiveStateProtocol[HeaderType, StateType]):
|
class MetaReductionStateProtocol(ActiveStateProtocol[HeaderType, StateType]):
|
||||||
async def verify(
|
|
||||||
self,
|
|
||||||
previous: NullableReference[StateType],
|
|
||||||
header: HashPoint[HeaderType],
|
|
||||||
state: HashPoint[StateType]
|
|
||||||
) -> bool:
|
|
||||||
assert isinstance(previous, NullableReference)
|
|
||||||
assert isinstance(header, HashPoint)
|
|
||||||
assert isinstance(state, HashPoint)
|
|
||||||
assert_eq(state, await self.derive(previous, header))
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _initial_state(self) -> HashPoint[StateType]:
|
def _initial_state(self) -> HashPoint[StateType]:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@ -24,7 +24,15 @@ class KeyedComparator(
|
|||||||
) -> Comparison:
|
) -> Comparison:
|
||||||
assert isinstance(original, HashPoint)
|
assert isinstance(original, HashPoint)
|
||||||
assert isinstance(key, HashPoint)
|
assert isinstance(key, HashPoint)
|
||||||
return await self.comparator.compare(
|
original_resolved: Keyed[ComparatorKeyType]
|
||||||
(await original.resolve()).key,
|
key_resolved: Keyed[ComparatorKeyType]
|
||||||
(await key.resolve()).key,
|
original_resolved, key_resolved = await gather(
|
||||||
|
original.resolve(),
|
||||||
|
key.resolve(),
|
||||||
|
)
|
||||||
|
assert isinstance(original_resolved, Keyed)
|
||||||
|
assert isinstance(key_resolved, Keyed)
|
||||||
|
return await self.comparator.compare(
|
||||||
|
original_resolved.key,
|
||||||
|
key_resolved.key,
|
||||||
)
|
)
|
||||||
|
@ -10,9 +10,13 @@ class PlainComparator(ProtocolComparator[Plain]):
|
|||||||
async 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(original, HashPoint)
|
||||||
assert isinstance(key, HashPoint)
|
assert isinstance(key, HashPoint)
|
||||||
original_value: Plain = await original.resolve()
|
original_value: Plain
|
||||||
|
key_value: Plain
|
||||||
|
original_value, key_value = await gather(
|
||||||
|
original.resolve(),
|
||||||
|
key.resolve(),
|
||||||
|
)
|
||||||
assert isinstance(original_value, Plain)
|
assert isinstance(original_value, Plain)
|
||||||
key_value: Plain = await key.resolve()
|
|
||||||
assert isinstance(key_value, Plain)
|
assert isinstance(key_value, Plain)
|
||||||
if key_value.source < original_value.source:
|
if key_value.source < original_value.source:
|
||||||
return Left()
|
return Left()
|
||||||
|
@ -27,8 +27,12 @@ class KeyMetadata(Keyed[ActiveKeyType], Generic[ActiveKeyType, MetaDataType]):
|
|||||||
|
|
||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
return f'{await hash_point_format(self.key, tab)}' \
|
key_str, metadata_str = await gather(
|
||||||
f'{tabulate(tab)}{await hash_point_format(self.metadata, tab)}'
|
hash_point_format(self.key, tab),
|
||||||
|
hash_point_format(self.metadata, tab)
|
||||||
|
)
|
||||||
|
return f'{key_str}' \
|
||||||
|
f'{tabulate(tab)}{metadata_str}'
|
||||||
|
|
||||||
|
|
||||||
class KeyMetadataFactory(
|
class KeyMetadataFactory(
|
||||||
|
@ -30,8 +30,14 @@ class Array(RecursiveMentionable, Generic[ElementType]):
|
|||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
formatted = f'('
|
formatted = f'('
|
||||||
for hash_point in self.array:
|
formatted += ''.join(
|
||||||
formatted += f'{tabulate(tab + 1)}{await hash_point_format(hash_point, tab + 1)}'
|
f'{tabulate(tab + 1)}{hash_point_str}'
|
||||||
|
for hash_point_str in gather(
|
||||||
|
*(
|
||||||
|
hash_point_format(hash_point, tab + 1) for hash_point in self.array
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
return f'{formatted}' \
|
return f'{formatted}' \
|
||||||
f'{tabulate(tab)})'
|
f'{tabulate(tab)})'
|
||||||
|
|
||||||
|
@ -31,8 +31,12 @@ class Stack(RecursiveMentionable, Generic[ElementType]):
|
|||||||
|
|
||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
return f'{await self.previous.str(tab)}' \
|
previous_str, element_str = await gather(
|
||||||
f'{tabulate(tab)}{await hash_point_format(self.element, tab)}'
|
self.previous.str(tab),
|
||||||
|
hash_point_format(self.element, tab),
|
||||||
|
)
|
||||||
|
return f'{previous_str}' \
|
||||||
|
f'{tabulate(tab)}{element_str}'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def of(
|
def of(
|
||||||
@ -76,6 +80,17 @@ class Stack(RecursiveMentionable, Generic[ElementType]):
|
|||||||
async for element in cls.iter(stack.previous):
|
async for element in cls.iter(stack.previous):
|
||||||
yield element
|
yield element
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def list(
|
||||||
|
cls,
|
||||||
|
reference: NullableReference['Stack[ElementType]']
|
||||||
|
) -> list[ElementType]:
|
||||||
|
return list(
|
||||||
|
await gather(
|
||||||
|
*[element.resolve() async for element in cls.iter(reference)]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class StackFactory(RainbowFactory[Stack[ElementType]], Generic[ElementType]):
|
class StackFactory(RainbowFactory[Stack[ElementType]], Generic[ElementType]):
|
||||||
def __init__(self, factory: RainbowFactory[ElementType]):
|
def __init__(self, factory: RainbowFactory[ElementType]):
|
||||||
|
@ -29,9 +29,13 @@ class Pair(
|
|||||||
|
|
||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
|
e0_str, e1_str = await gather(
|
||||||
|
hash_point_format(self.element0, tab),
|
||||||
|
hash_point_format(self.element1, tab),
|
||||||
|
)
|
||||||
return f'(pair)' \
|
return f'(pair)' \
|
||||||
f'{tabulate(tab)}{await hash_point_format(self.element0, tab)}' \
|
f'{tabulate(tab)}{e0_str}' \
|
||||||
f'{tabulate(tab)}{await hash_point_format(self.element1, tab)}'
|
f'{tabulate(tab)}{e1_str}'
|
||||||
|
|
||||||
|
|
||||||
class PairFactory(
|
class PairFactory(
|
||||||
|
@ -23,13 +23,17 @@ class AVL(BinaryBalancing[ActiveKeyType, Integer, TreeType]):
|
|||||||
creation: BinaryCreation[ActiveKeyType, Integer, TreeType]
|
creation: BinaryCreation[ActiveKeyType, Integer, TreeType]
|
||||||
) -> HashPoint[Integer]:
|
) -> HashPoint[Integer]:
|
||||||
assert isinstance(creation, BinaryCreation)
|
assert isinstance(creation, BinaryCreation)
|
||||||
|
height_l, height_r = await gather(
|
||||||
|
self.height(BinaryProtocolized(creation, treel)),
|
||||||
|
self.height(BinaryProtocolized(creation, treer)),
|
||||||
|
)
|
||||||
return HashPoint.of(
|
return HashPoint.of(
|
||||||
Integer(
|
Integer(
|
||||||
1
|
1
|
||||||
+
|
+
|
||||||
max(
|
max(
|
||||||
await self.height(BinaryProtocolized(creation, treel)),
|
height_l,
|
||||||
await self.height(BinaryProtocolized(creation, treer))
|
height_r,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -80,7 +84,11 @@ class BalanceAction(
|
|||||||
self,
|
self,
|
||||||
case: ProtocolizedBinarySplit[ActiveKeyType, Integer, TreeType]
|
case: ProtocolizedBinarySplit[ActiveKeyType, Integer, TreeType]
|
||||||
) -> TreeType:
|
) -> TreeType:
|
||||||
delta = (await AVL.height(case.protocolizedl())) - (await AVL.height(case.protocolizedr()))
|
height_l, height_r = await gather(
|
||||||
|
AVL.height(case.protocolizedl()),
|
||||||
|
AVL.height(case.protocolizedr()),
|
||||||
|
)
|
||||||
|
delta = height_l - height_r
|
||||||
assert isinstance(delta, int)
|
assert isinstance(delta, int)
|
||||||
if delta < -1:
|
if delta < -1:
|
||||||
return await self.on_symmetric(InnerOuter(case.protocol), case.split)
|
return await self.on_symmetric(InnerOuter(case.protocol), case.split)
|
||||||
@ -98,15 +106,19 @@ class BalanceAction(
|
|||||||
assert isinstance(symmetry, Symmetric)
|
assert isinstance(symmetry, Symmetric)
|
||||||
assert isinstance(split, BinarySplit)
|
assert isinstance(split, BinarySplit)
|
||||||
splito = await symmetry.protocol.fsplit(symmetry.outer(split))
|
splito = await symmetry.protocol.fsplit(symmetry.outer(split))
|
||||||
if (
|
height_oi, height_oo = await gather(
|
||||||
(await AVL.height(symmetry.protocolizedi(splito)))
|
AVL.height(symmetry.protocolizedi(splito)),
|
||||||
>
|
AVL.height(symmetry.protocolizedo(splito)),
|
||||||
(await AVL.height(symmetry.protocolizedo(splito)))
|
)
|
||||||
):
|
if height_oi > height_oo:
|
||||||
splitoi = await symmetry.protocol.fsplit(symmetry.inner(splito))
|
splitoi = await symmetry.protocol.fsplit(symmetry.inner(splito))
|
||||||
|
inner, outer = await gather(
|
||||||
|
symmetry.tree(symmetry.inner(split), symmetry.inner(splitoi), split.key),
|
||||||
|
symmetry.tree(symmetry.outer(splitoi), symmetry.outer(splito), splito.key),
|
||||||
|
)
|
||||||
return await symmetry.tree(
|
return await symmetry.tree(
|
||||||
await symmetry.tree(symmetry.inner(split), symmetry.inner(splitoi), split.key),
|
inner,
|
||||||
await symmetry.tree(symmetry.outer(splitoi), symmetry.outer(splito), splito.key),
|
outer,
|
||||||
splitoi.key
|
splitoi.key
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@ -37,9 +37,14 @@ class BinaryTree(RecursiveMentionable, Generic[TreeKeyType]):
|
|||||||
|
|
||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
return f'{await self.treel.str(tab)}' \
|
treel_str, key_str, treer_str = await gather(
|
||||||
f'{tabulate(tab)}{await hash_point_format(self.key, tab)}' \
|
self.treel.str(tab),
|
||||||
f'{tabulate(tab)}{await self.treer.str(tab)}'
|
hash_point_format(self.key, tab),
|
||||||
|
self.treer.str(tab),
|
||||||
|
)
|
||||||
|
return f'{treel_str}' \
|
||||||
|
f'{tabulate(tab)}{key_str}' \
|
||||||
|
f'{tabulate(tab)}{treer_str}'
|
||||||
|
|
||||||
|
|
||||||
class BinaryTreeFactory(RainbowFactory[BinaryTree[TreeKeyType]], Generic[TreeKeyType]):
|
class BinaryTreeFactory(RainbowFactory[BinaryTree[TreeKeyType]], Generic[TreeKeyType]):
|
||||||
|
@ -31,12 +31,16 @@ class BalancedCreation(
|
|||||||
|
|
||||||
async 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)
|
assert isinstance(key, HashPoint)
|
||||||
|
balancedl, balancedr = await gather(
|
||||||
|
self.protocol.balance(BinaryProtocolized(self, treel)),
|
||||||
|
self.protocol.balance(BinaryProtocolized(self, treer)),
|
||||||
|
)
|
||||||
return await self.protocol.balance(
|
return await self.protocol.balance(
|
||||||
BinaryProtocolized(
|
BinaryProtocolized(
|
||||||
self,
|
self,
|
||||||
await self._tree(
|
await self._tree(
|
||||||
await self.protocol.balance(BinaryProtocolized(self, treel)),
|
balancedl,
|
||||||
await self.protocol.balance(BinaryProtocolized(self, treer)),
|
balancedr,
|
||||||
key
|
key
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from .asserts import *
|
from .asserts import *
|
||||||
from .extendableresolver import ExtendableResolver
|
from .extendableresolver import ExtendableResolver
|
||||||
|
from .gather import *
|
||||||
from .hash_point_format import *
|
from .hash_point_format import *
|
||||||
from .hashpoint import HashPoint
|
from .hashpoint import HashPoint
|
||||||
from .hashresolver import HashResolver
|
from .hashresolver import HashResolver
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from typing import Optional, TypeVar
|
from typing import Iterable, Optional, TypeVar
|
||||||
|
|
||||||
__all__ = ('assert_true', 'assert_false', 'assert_none', 'assert_eq',)
|
__all__ = ('assert_true', 'assert_trues', 'assert_false', 'assert_none', 'assert_eq',)
|
||||||
|
|
||||||
|
|
||||||
def assert_true(value: bool) -> bool:
|
def assert_true(value: bool) -> bool:
|
||||||
@ -8,6 +8,12 @@ def assert_true(value: bool) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def assert_trues(values: Iterable[bool]) -> bool:
|
||||||
|
for value in values:
|
||||||
|
assert_true(value)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def assert_false(value: bool) -> bool:
|
def assert_false(value: bool) -> bool:
|
||||||
assert value is False
|
assert value is False
|
||||||
return True
|
return True
|
||||||
|
35
rainbowadn/core/gather.py
Normal file
35
rainbowadn/core/gather.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import asyncio
|
||||||
|
from typing import AsyncIterable, TypeVar
|
||||||
|
|
||||||
|
__all__ = ('gather', 'asum', 'alist', 'set_gather_asyncio', 'set_gather_linear',)
|
||||||
|
|
||||||
|
_gather = asyncio.gather
|
||||||
|
|
||||||
|
|
||||||
|
async def _local_gather(*args):
|
||||||
|
return [await arg for arg in args]
|
||||||
|
|
||||||
|
|
||||||
|
def set_gather_asyncio():
|
||||||
|
global _gather
|
||||||
|
_gather = asyncio.gather
|
||||||
|
|
||||||
|
|
||||||
|
def set_gather_linear():
|
||||||
|
global _gather
|
||||||
|
_gather = _local_gather
|
||||||
|
|
||||||
|
|
||||||
|
def gather(*args):
|
||||||
|
return _gather(*args)
|
||||||
|
|
||||||
|
|
||||||
|
async def asum(iterable):
|
||||||
|
return sum(await gather(*iterable))
|
||||||
|
|
||||||
|
|
||||||
|
T = TypeVar('T')
|
||||||
|
|
||||||
|
|
||||||
|
async def alist(aiterable: AsyncIterable[T]) -> list[T]:
|
||||||
|
return [x async for x in aiterable]
|
@ -40,14 +40,12 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]):
|
|||||||
async def encrypt(cls, decrypted: EncryptedType, key: bytes) -> 'Encrypted[EncryptedType]':
|
async def encrypt(cls, decrypted: EncryptedType, key: bytes) -> 'Encrypted[EncryptedType]':
|
||||||
assert isinstance(key, bytes)
|
assert isinstance(key, bytes)
|
||||||
hashpoints = tuple(decrypted.points()) if isinstance(decrypted, RecursiveMentionable) else ()
|
hashpoints = tuple(decrypted.points()) if isinstance(decrypted, RecursiveMentionable) else ()
|
||||||
resolution: tuple[HashPoint[Encrypted[EncryptedType]], ...] = tuple(
|
resolution = tuple(
|
||||||
[
|
await gather(
|
||||||
await cls.encrypt_hashpoint(hash_point, key)
|
*(
|
||||||
for
|
cls.encrypt_hashpoint(hash_point, key) for hash_point in hashpoints
|
||||||
hash_point
|
)
|
||||||
in
|
)
|
||||||
hashpoints
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
return cls.construct(
|
return cls.construct(
|
||||||
key,
|
key,
|
||||||
|
29
rainbowadn/testing/delayedresolver.py
Normal file
29
rainbowadn/testing/delayedresolver.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import asyncio
|
||||||
|
from typing import Callable, TypeVar
|
||||||
|
|
||||||
|
from rainbowadn.core import *
|
||||||
|
|
||||||
|
__all__ = ('DelayedResolver',)
|
||||||
|
|
||||||
|
Mentioned = TypeVar('Mentioned')
|
||||||
|
|
||||||
|
|
||||||
|
class DelayedResolver(ExtendableResolver):
|
||||||
|
def __init__(self, resolver: HashResolver, delay: Callable[[], float]):
|
||||||
|
self.resolver = resolver
|
||||||
|
self.delay = delay
|
||||||
|
|
||||||
|
async def sleep(self):
|
||||||
|
await asyncio.sleep(self.delay())
|
||||||
|
|
||||||
|
async def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
|
||||||
|
assert isinstance(point, bytes)
|
||||||
|
await self.sleep()
|
||||||
|
resolved, resolver = await self.resolver.resolve(point)
|
||||||
|
return resolved, DelayedResolver(resolver, self.delay)
|
||||||
|
|
||||||
|
async def extend(self, hash_point: HashPoint[Mentioned]) -> ExtendableResolver:
|
||||||
|
if isinstance(self.resolver, ExtendableResolver):
|
||||||
|
return DelayedResolver(await self.resolver.extend(hash_point), self.delay)
|
||||||
|
else:
|
||||||
|
raise TypeError
|
@ -25,8 +25,9 @@ class DictResolver(ExtendableResolver):
|
|||||||
assert isinstance(value, Mentionable)
|
assert isinstance(value, Mentionable)
|
||||||
self.table[hash_point.point] = HashPoint.bytes_of_mentioned(value)
|
self.table[hash_point.point] = HashPoint.bytes_of_mentioned(value)
|
||||||
if isinstance(value, RecursiveMentionable):
|
if isinstance(value, RecursiveMentionable):
|
||||||
for hash_point in value.points():
|
await gather(
|
||||||
await self.save(hash_point)
|
*(self.save(hp) for hp in value.points())
|
||||||
|
)
|
||||||
|
|
||||||
async def extend(self, hash_point: HashPoint[Mentioned]) -> 'ExtendableResolver':
|
async def extend(self, hash_point: HashPoint[Mentioned]) -> 'ExtendableResolver':
|
||||||
await self.save(hash_point)
|
await self.save(hash_point)
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
import functools
|
import functools
|
||||||
|
import time
|
||||||
|
from typing import Generic, TypeVar
|
||||||
|
|
||||||
|
__all__ = ('Instrumentation', 'Counter', 'Concurrency',)
|
||||||
|
|
||||||
|
|
||||||
class Instrumentation:
|
IType = TypeVar('IType')
|
||||||
|
|
||||||
|
|
||||||
|
class Instrumentation(Generic[IType]):
|
||||||
deinstrumentation = {}
|
deinstrumentation = {}
|
||||||
|
|
||||||
def __init__(self, target, methodname: str):
|
def __init__(self, target, methodname: str):
|
||||||
@ -11,7 +18,7 @@ class Instrumentation:
|
|||||||
def instrument(self, method, *args, **kwargs):
|
def instrument(self, method, *args, **kwargs):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self: IType) -> IType:
|
||||||
assert not hasattr(self, 'method')
|
assert not hasattr(self, 'method')
|
||||||
self.method = getattr(self.target, self.methodname)
|
self.method = getattr(self.target, self.methodname)
|
||||||
|
|
||||||
@ -23,6 +30,8 @@ class Instrumentation:
|
|||||||
|
|
||||||
setattr(self.target, self.methodname, self.wrap)
|
setattr(self.target, self.methodname, self.wrap)
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
def schedule_deinstrumentation(self):
|
def schedule_deinstrumentation(self):
|
||||||
self.deinstrumentation[self.wrap] = self.method
|
self.deinstrumentation[self.wrap] = self.method
|
||||||
del self.wrap
|
del self.wrap
|
||||||
@ -45,3 +54,25 @@ class Counter(Instrumentation):
|
|||||||
def instrument(self, method, *args, **kwargs):
|
def instrument(self, method, *args, **kwargs):
|
||||||
self.counter += 1
|
self.counter += 1
|
||||||
return method(*args, **kwargs)
|
return method(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class Concurrency(Instrumentation):
|
||||||
|
start = time.time()
|
||||||
|
|
||||||
|
def __init__(self, target, methodname: str):
|
||||||
|
super().__init__(target, methodname)
|
||||||
|
self.concurrency = 0
|
||||||
|
self.logs: list[tuple[float, int]] = []
|
||||||
|
|
||||||
|
def time(self) -> float:
|
||||||
|
return time.time() - self.start
|
||||||
|
|
||||||
|
async def instrument(self, method, *args, **kwargs):
|
||||||
|
self.logs.append((self.time(), self.concurrency))
|
||||||
|
self.concurrency += 1
|
||||||
|
self.logs.append((self.time(), self.concurrency))
|
||||||
|
result = await method(*args, **kwargs)
|
||||||
|
self.logs.append((self.time(), self.concurrency))
|
||||||
|
self.concurrency -= 1
|
||||||
|
self.logs.append((self.time(), self.concurrency))
|
||||||
|
return result
|
||||||
|
@ -16,16 +16,22 @@ from rainbowadn.encryption import *
|
|||||||
from rainbowadn.nullability import *
|
from rainbowadn.nullability import *
|
||||||
from rainbowadn.v13 import *
|
from rainbowadn.v13 import *
|
||||||
from rainbowadn.wrisbt import *
|
from rainbowadn.wrisbt import *
|
||||||
|
from .delayedresolver import DelayedResolver
|
||||||
from .dictresolver import DictResolver
|
from .dictresolver import DictResolver
|
||||||
from .instrumentation import Counter
|
from .instrumentation import *
|
||||||
|
|
||||||
|
|
||||||
class TestAll(unittest.IsolatedAsyncioTestCase):
|
class TestAll(unittest.IsolatedAsyncioTestCase):
|
||||||
"""examples rather than real tests"""
|
"""examples rather than real tests"""
|
||||||
|
|
||||||
async def test_bankchain(self):
|
@classmethod
|
||||||
with self.subTest('setup'):
|
def dr(cls) -> ExtendableResolver:
|
||||||
dr = DictResolver()
|
dr = DictResolver()
|
||||||
|
dr = DelayedResolver(dr, lambda: 0.000)
|
||||||
|
return dr
|
||||||
|
|
||||||
|
async def test_bankchain(self):
|
||||||
|
set_gather_asyncio()
|
||||||
with self.subTest('create empty'):
|
with self.subTest('create empty'):
|
||||||
bank: BankChain = BankChain.empty(ReductionChainMetaFactory().loose())
|
bank: BankChain = BankChain.empty(ReductionChainMetaFactory().loose())
|
||||||
with self.subTest('prepare transactions'):
|
with self.subTest('prepare transactions'):
|
||||||
@ -51,19 +57,22 @@ class TestAll(unittest.IsolatedAsyncioTestCase):
|
|||||||
bank = await bank.adds(
|
bank = await bank.adds(
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
print(bank.reference.str(0))
|
print(await bank.reference.str(0))
|
||||||
with self.subTest('verify'):
|
with self.subTest('verify'):
|
||||||
assert_true(await bank.verify())
|
assert_true(await bank.verify())
|
||||||
with self.subTest('recover'):
|
with self.subTest('recover'):
|
||||||
await dr.save(HashPoint.of(bank.reference))
|
|
||||||
bank = BankChain.from_reference(
|
bank = BankChain.from_reference(
|
||||||
ReductionChainMetaFactory(), await dr.migrate_resolved(bank.reference)
|
ReductionChainMetaFactory(), await self.dr().migrate_resolved(bank.reference)
|
||||||
)
|
)
|
||||||
print(bank.reference.str(0))
|
set_gather_asyncio()
|
||||||
|
print('recovering')
|
||||||
|
print(await bank.reference.str(0))
|
||||||
|
print('recovered')
|
||||||
with self.subTest('verify'):
|
with self.subTest('verify'):
|
||||||
assert_true(await bank.verify())
|
assert_true(await bank.verify())
|
||||||
|
|
||||||
async def test_wrisbt(self):
|
async def test_wrisbt(self):
|
||||||
|
set_gather_linear()
|
||||||
with self.subTest('setup'):
|
with self.subTest('setup'):
|
||||||
stoptime = time.process_time()
|
stoptime = time.process_time()
|
||||||
|
|
||||||
@ -75,7 +84,6 @@ class TestAll(unittest.IsolatedAsyncioTestCase):
|
|||||||
stoptime = now
|
stoptime = now
|
||||||
return delta
|
return delta
|
||||||
|
|
||||||
dr = DictResolver()
|
|
||||||
n = 2500
|
n = 2500
|
||||||
keysize = 7
|
keysize = 7
|
||||||
with self.subTest('create empty'):
|
with self.subTest('create empty'):
|
||||||
@ -89,10 +97,10 @@ class TestAll(unittest.IsolatedAsyncioTestCase):
|
|||||||
assert_true(await btree.contains(key))
|
assert_true(await btree.contains(key))
|
||||||
measure('add')
|
measure('add')
|
||||||
with self.subTest('save'):
|
with self.subTest('save'):
|
||||||
await dr.save(HashPoint.of(btree))
|
btree = await self.dr().migrate_resolved(btree)
|
||||||
measure('save')
|
measure('save')
|
||||||
|
set_gather_asyncio()
|
||||||
with self.subTest('resolve and iterate'):
|
with self.subTest('resolve and iterate'):
|
||||||
btree = await dr.migrate_resolved(btree)
|
|
||||||
assert_eq(len(await btree.keys()), n)
|
assert_eq(len(await btree.keys()), n)
|
||||||
print(btree.height)
|
print(btree.height)
|
||||||
measure('resolve and iterate')
|
measure('resolve and iterate')
|
||||||
@ -106,13 +114,14 @@ class TestAll(unittest.IsolatedAsyncioTestCase):
|
|||||||
measure('resolve and add')
|
measure('resolve and add')
|
||||||
|
|
||||||
async def test_wrisbt_index(self):
|
async def test_wrisbt_index(self):
|
||||||
|
set_gather_linear()
|
||||||
with self.subTest('create empty'):
|
with self.subTest('create empty'):
|
||||||
factory: RainbowFactory[Pair[Plain, Plain]] = PairFactory(Plain.factory(), Plain.factory()).loose()
|
factory: RainbowFactory[Pair[Plain, Plain]] = PairFactory(Plain.factory(), Plain.factory()).loose()
|
||||||
chain: ChainCollectionInterface[Any, Pair[Plain, Plain], WrisbtRoot] = BlockChainFactory(
|
chain: ChainCollectionInterface[Any, Pair[Plain, Plain], WrisbtRoot] = BlockChainFactory(
|
||||||
WrisbtChainProtocol(factory, 2).loose()
|
WrisbtChainProtocol(factory, 2).loose()
|
||||||
).empty().loose()
|
).empty().loose()
|
||||||
with self.subTest('fill'):
|
with self.subTest('fill'):
|
||||||
for _ in range(1000):
|
for _ in range(100):
|
||||||
chain = await chain.add(
|
chain = await chain.add(
|
||||||
HashPoint.of(
|
HashPoint.of(
|
||||||
Pair(
|
Pair(
|
||||||
@ -122,6 +131,7 @@ class TestAll(unittest.IsolatedAsyncioTestCase):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
with self.subTest('check'):
|
with self.subTest('check'):
|
||||||
|
set_gather_asyncio()
|
||||||
assert_true(await chain.verify())
|
assert_true(await chain.verify())
|
||||||
with self.subTest('measure height'):
|
with self.subTest('measure height'):
|
||||||
reference = await chain.actual_state()
|
reference = await chain.actual_state()
|
||||||
@ -129,6 +139,7 @@ class TestAll(unittest.IsolatedAsyncioTestCase):
|
|||||||
print((await reference.resolve()).height)
|
print((await reference.resolve()).height)
|
||||||
|
|
||||||
async def test_avl(self):
|
async def test_avl(self):
|
||||||
|
set_gather_linear()
|
||||||
tree: ActiveBinaryTree[Plain, Integer] = ActiveBinaryTree.empty(
|
tree: ActiveBinaryTree[Plain, Integer] = ActiveBinaryTree.empty(
|
||||||
AVL(PlainComparator(Replace())), Plain.factory()
|
AVL(PlainComparator(Replace())), Plain.factory()
|
||||||
)
|
)
|
||||||
@ -137,6 +148,7 @@ class TestAll(unittest.IsolatedAsyncioTestCase):
|
|||||||
print(await tree.reference.str(0))
|
print(await tree.reference.str(0))
|
||||||
|
|
||||||
async def test_avl_stress(self):
|
async def test_avl_stress(self):
|
||||||
|
set_gather_linear()
|
||||||
protocol = AVL(PlainComparator(Replace()))
|
protocol = AVL(PlainComparator(Replace()))
|
||||||
tree: ActiveBinaryTree[Plain, Integer] = ActiveBinaryTree.empty(
|
tree: ActiveBinaryTree[Plain, Integer] = ActiveBinaryTree.empty(
|
||||||
protocol, Plain.factory()
|
protocol, Plain.factory()
|
||||||
@ -146,10 +158,10 @@ class TestAll(unittest.IsolatedAsyncioTestCase):
|
|||||||
print(await AVL.height(tree.protocolized()))
|
print(await AVL.height(tree.protocolized()))
|
||||||
|
|
||||||
async def test_encryption(self):
|
async def test_encryption(self):
|
||||||
|
set_gather_asyncio()
|
||||||
instrumentation = Counter(Encrypted, 'encrypt')
|
instrumentation = Counter(Encrypted, 'encrypt')
|
||||||
with self.subTest('setup'):
|
with self.subTest('setup'):
|
||||||
key = b'a' * 32
|
key = b'a' * 32
|
||||||
dr = DictResolver()
|
|
||||||
with self.subTest('create empty'):
|
with self.subTest('create empty'):
|
||||||
tree: ActiveBinaryTree[Plain, Integer] = ActiveBinaryTree.empty(
|
tree: ActiveBinaryTree[Plain, Integer] = ActiveBinaryTree.empty(
|
||||||
AVL(PlainComparator(Replace())), Plain.factory()
|
AVL(PlainComparator(Replace())), Plain.factory()
|
||||||
@ -174,8 +186,7 @@ class TestAll(unittest.IsolatedAsyncioTestCase):
|
|||||||
with instrumentation:
|
with instrumentation:
|
||||||
eeed = await Encrypted.encrypt(target, key)
|
eeed = await Encrypted.encrypt(target, key)
|
||||||
print(instrumentation.counter)
|
print(instrumentation.counter)
|
||||||
await dr.save(HashPoint.of(eeed))
|
print(await (await self.dr().migrate_resolved(eeed)).decrypted.str(0))
|
||||||
print(await (await dr.migrate_resolved(eeed)).decrypted.str(0))
|
|
||||||
with self.subTest('re-encrypt'):
|
with self.subTest('re-encrypt'):
|
||||||
new_key = b'b' * 32
|
new_key = b'b' * 32
|
||||||
target = eeed.decrypted
|
target = eeed.decrypted
|
||||||
|
@ -18,9 +18,14 @@ class BankProtocol(ReductionProtocol[NullableReference[Stack[Transaction]], Bank
|
|||||||
reduce: Reducible[NullableReference[Stack[Transaction]], BankState]
|
reduce: Reducible[NullableReference[Stack[Transaction]], BankState]
|
||||||
) -> ReductionResult[NullableReference[Stack[Transaction]], BankState]:
|
) -> ReductionResult[NullableReference[Stack[Transaction]], BankState]:
|
||||||
assert isinstance(reduce, Reducible)
|
assert isinstance(reduce, Reducible)
|
||||||
bank_state: BankState = await reduce.accumulator.resolve()
|
bank_state: BankState
|
||||||
|
reference: NullableReference[Stack[Transaction]]
|
||||||
|
bank_state, reference = await gather(
|
||||||
|
reduce.accumulator.resolve(),
|
||||||
|
reduce.reductor.resolve(),
|
||||||
|
)
|
||||||
assert isinstance(bank_state, BankState)
|
assert isinstance(bank_state, BankState)
|
||||||
reference: NullableReference[Stack[Transaction]] = await reduce.reductor.resolve()
|
assert isinstance(reference, NullableReference)
|
||||||
if reference.null():
|
if reference.null():
|
||||||
return Reduced(HashPoint.of(bank_state.without_miner()))
|
return Reduced(HashPoint.of(bank_state.without_miner()))
|
||||||
else:
|
else:
|
||||||
|
@ -90,23 +90,41 @@ class BankState(RecursiveMentionable, StaticMentionable):
|
|||||||
minted: ActiveBinaryTree[Coin, Integer] = self.minted_tree()
|
minted: ActiveBinaryTree[Coin, Integer] = self.minted_tree()
|
||||||
used: ActiveBinaryTree[Coin, Integer] = self.used_tree()
|
used: ActiveBinaryTree[Coin, Integer] = self.used_tree()
|
||||||
async for in_coin in coins:
|
async for in_coin in coins:
|
||||||
assert_true(await minted.contains(in_coin))
|
minted_contains, used_contains, used = await gather(
|
||||||
assert_false(await used.contains(in_coin))
|
minted.contains(in_coin),
|
||||||
used = await used.add(in_coin)
|
used.contains(in_coin),
|
||||||
|
used.add(in_coin)
|
||||||
|
)
|
||||||
|
assert_true(minted_contains)
|
||||||
|
assert_false(used_contains)
|
||||||
|
assert isinstance(used, ActiveBinaryTree)
|
||||||
return BankState(self.minted, used.reference, self.miner, self.length)
|
return BankState(self.minted, used.reference, self.miner, self.length)
|
||||||
|
|
||||||
|
async def _mint_coins(
|
||||||
|
self,
|
||||||
|
transaction: Transaction
|
||||||
|
) -> 'BankState':
|
||||||
|
miner = self.miner_nullable()
|
||||||
|
minted: ActiveBinaryTree[Coin, Integer] = self.minted_tree()
|
||||||
|
async for coin, miner in transaction.iter_coins(self.mint(), miner):
|
||||||
|
minted_contains, minted = await gather(
|
||||||
|
minted.contains(HashPoint.of(coin)),
|
||||||
|
minted.add(HashPoint.of(coin)),
|
||||||
|
)
|
||||||
|
assert_false(minted_contains)
|
||||||
|
assert isinstance(minted, ActiveBinaryTree)
|
||||||
|
return BankState(minted.reference, self.used, NullableReference(miner, self.miner.factory), self.length)
|
||||||
|
|
||||||
async def mint_coins(
|
async def mint_coins(
|
||||||
self,
|
self,
|
||||||
transaction: Transaction
|
transaction: Transaction
|
||||||
) -> 'BankState':
|
) -> 'BankState':
|
||||||
assert_true(await self.verify(transaction))
|
verified, bank_state = await gather(
|
||||||
miner = self.miner_nullable()
|
self.verify(transaction),
|
||||||
minted: ActiveBinaryTree[Coin, Integer] = self.minted_tree()
|
self._mint_coins(transaction),
|
||||||
async for coin, miner in transaction.iter_coins(self.mint(), miner):
|
)
|
||||||
assert_false(await minted.contains(HashPoint.of(coin)))
|
assert_true(verified)
|
||||||
minted = await minted.add(HashPoint.of(coin))
|
return bank_state
|
||||||
assert isinstance(minted, ActiveBinaryTree)
|
|
||||||
return BankState(minted.reference, self.used, NullableReference(miner, self.miner.factory), self.length)
|
|
||||||
|
|
||||||
def miner_nullable(self) -> Nullable[HashPoint[Subject]]:
|
def miner_nullable(self) -> Nullable[HashPoint[Subject]]:
|
||||||
return self.miner.reference
|
return self.miner.reference
|
||||||
@ -137,14 +155,20 @@ class BankState(RecursiveMentionable, StaticMentionable):
|
|||||||
|
|
||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
|
miner_str, minted_str, used_str, length_str = await gather(
|
||||||
|
self.miner.str(tab + 1),
|
||||||
|
self.minted.str(tab + 1),
|
||||||
|
self.used.str(tab + 1),
|
||||||
|
hash_point_format(self.length, tab + 1),
|
||||||
|
)
|
||||||
return f'(' \
|
return f'(' \
|
||||||
f'{tabulate(tab + 1)}bank' \
|
f'{tabulate(tab + 1)}bank' \
|
||||||
f'{tabulate(tab + 1)}(miner)' \
|
f'{tabulate(tab + 1)}(miner)' \
|
||||||
f'{tabulate(tab + 1)}{await self.miner.str(tab + 1)}' \
|
f'{tabulate(tab + 1)}{miner_str}' \
|
||||||
f'{tabulate(tab + 1)}(minted)' \
|
f'{tabulate(tab + 1)}(minted)' \
|
||||||
f'{tabulate(tab + 1)}{await self.minted.str(tab + 1)}' \
|
f'{tabulate(tab + 1)}{minted_str}' \
|
||||||
f'{tabulate(tab + 1)}(used)' \
|
f'{tabulate(tab + 1)}(used)' \
|
||||||
f'{tabulate(tab + 1)}{await self.used.str(tab + 1)}' \
|
f'{tabulate(tab + 1)}{used_str}' \
|
||||||
f'{tabulate(tab + 1)}(length)' \
|
f'{tabulate(tab + 1)}(length)' \
|
||||||
f'{tabulate(tab + 1)}{await hash_point_format(self.length, tab + 1)}' \
|
f'{tabulate(tab + 1)}{length_str}' \
|
||||||
f'{tabulate(tab)})'
|
f'{tabulate(tab)})'
|
||||||
|
@ -49,8 +49,12 @@ class CoinData(RecursiveMentionable, StaticMentionable):
|
|||||||
|
|
||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
return f'{await hash_point_format(self.owner, tab)}' \
|
owner_str, value_str = await gather(
|
||||||
f'{tabulate(tab)}{await hash_point_format(self.value, tab)}'
|
hash_point_format(self.owner, tab),
|
||||||
|
hash_point_format(self.value, tab),
|
||||||
|
)
|
||||||
|
return f'{owner_str}' \
|
||||||
|
f'{tabulate(tab)}{value_str}'
|
||||||
|
|
||||||
|
|
||||||
class Coin(RecursiveMentionable, StaticMentionable):
|
class Coin(RecursiveMentionable, StaticMentionable):
|
||||||
@ -90,13 +94,23 @@ class Coin(RecursiveMentionable, StaticMentionable):
|
|||||||
|
|
||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
|
data_str, index_str = await gather(
|
||||||
|
hash_point_format(self.data, tab + 1),
|
||||||
|
hash_point_format(self.index, tab + 1),
|
||||||
|
)
|
||||||
return f'(' \
|
return f'(' \
|
||||||
f'{tabulate(tab + 1)}coin' \
|
f'{tabulate(tab + 1)}coin' \
|
||||||
f'{tabulate(tab + 1)}{await hash_point_format(self.data, tab + 1)}' \
|
f'{tabulate(tab + 1)}{data_str}' \
|
||||||
f'{tabulate(tab + 1)}(origin)' \
|
f'{tabulate(tab + 1)}(origin)' \
|
||||||
f'{tabulate(tab + 1)}{await hash_point_format(self.index, tab + 1)}' \
|
f'{tabulate(tab + 1)}{index_str}' \
|
||||||
f'{tabulate(tab)})'
|
f'{tabulate(tab)})'
|
||||||
|
|
||||||
|
async def int_value(self) -> int:
|
||||||
|
return await (await self.data_resolved()).int_value()
|
||||||
|
|
||||||
|
async def owner_resolved(self) -> Subject:
|
||||||
|
return await (await self.data_resolved()).owner.resolve()
|
||||||
|
|
||||||
|
|
||||||
class TransactionData(RecursiveMentionable, StaticMentionable):
|
class TransactionData(RecursiveMentionable, StaticMentionable):
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -130,19 +144,32 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
|
|||||||
).from_bytes(source[HashPoint.HASH_LENGTH:], resolver),
|
).from_bytes(source[HashPoint.HASH_LENGTH:], resolver),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def _signature_verify(self, coin: Coin, signature: Signature) -> bool:
|
||||||
|
assert_true(
|
||||||
|
signature.verify(
|
||||||
|
await coin.owner_resolved(),
|
||||||
|
self.hash_point
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
async def _verify_signatures(
|
async def _verify_signatures(
|
||||||
self,
|
self,
|
||||||
signatures: NullableReference[Stack[Signature]]
|
signatures: NullableReference[Stack[Signature]]
|
||||||
) -> bool:
|
) -> bool:
|
||||||
for coin, signature in zip(
|
assert_trues(
|
||||||
[x async for x in self.iter_in_coins_resolved()],
|
await gather(
|
||||||
[x async for x in Stack.iter(signatures)],
|
*[
|
||||||
|
self._signature_verify(coin, signature)
|
||||||
|
for
|
||||||
|
coin, signature
|
||||||
|
in
|
||||||
|
zip(
|
||||||
|
await self.in_coins_resolved(),
|
||||||
|
await Stack.list(signatures),
|
||||||
strict=True
|
strict=True
|
||||||
):
|
)
|
||||||
assert_true(
|
]
|
||||||
(await signature.resolve()).verify(
|
|
||||||
await (await coin.data_resolved()).owner.resolve(),
|
|
||||||
self.hash_point
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
@ -150,18 +177,24 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
|
|||||||
def iter_in_coins(self) -> AsyncIterable[HashPoint[Coin]]:
|
def iter_in_coins(self) -> AsyncIterable[HashPoint[Coin]]:
|
||||||
return Stack.iter(self.in_coins)
|
return Stack.iter(self.in_coins)
|
||||||
|
|
||||||
async def iter_in_coins_resolved(self) -> AsyncIterable[Coin]:
|
async def in_coins_resolved(self) -> list[Coin]:
|
||||||
async for coin in self.iter_in_coins():
|
return await Stack.list(self.in_coins)
|
||||||
yield await coin.resolve()
|
|
||||||
|
|
||||||
async def _total_in(self) -> int:
|
async def _total_in(self) -> int:
|
||||||
return sum([await (await coin.data_resolved()).int_value() async for coin in self.iter_in_coins_resolved()])
|
return await asum(
|
||||||
|
coin.int_value() for coin in await self.in_coins_resolved()
|
||||||
|
)
|
||||||
|
|
||||||
def iter_out_coins(self) -> AsyncIterable[HashPoint[CoinData]]:
|
def iter_out_coins(self) -> AsyncIterable[HashPoint[CoinData]]:
|
||||||
return Stack.iter(self.out_coins)
|
return Stack.iter(self.out_coins)
|
||||||
|
|
||||||
|
async def out_coins_resolved(self) -> list[CoinData]:
|
||||||
|
return await Stack.list(self.out_coins)
|
||||||
|
|
||||||
async def _total_out(self) -> int:
|
async def _total_out(self) -> int:
|
||||||
return sum([await (await coin.resolve()).int_value() async for coin in self.iter_out_coins()])
|
return await asum(
|
||||||
|
coin.int_value() for coin in await self.out_coins_resolved()
|
||||||
|
)
|
||||||
|
|
||||||
async def _verify_values(self, mint: int) -> bool:
|
async def _verify_values(self, mint: int) -> bool:
|
||||||
assert isinstance(mint, int)
|
assert isinstance(mint, int)
|
||||||
@ -170,7 +203,11 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
|
|||||||
|
|
||||||
async def extra(self, mint: int) -> int:
|
async def extra(self, mint: int) -> int:
|
||||||
assert isinstance(mint, int)
|
assert isinstance(mint, int)
|
||||||
return (await self._total_in()) + mint - (await self._total_out())
|
total_in, total_out = await gather(
|
||||||
|
self._total_in(),
|
||||||
|
self._total_out(),
|
||||||
|
)
|
||||||
|
return total_in + mint - total_out
|
||||||
|
|
||||||
async def verify(
|
async def verify(
|
||||||
self,
|
self,
|
||||||
@ -179,16 +216,24 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
|
|||||||
) -> bool:
|
) -> bool:
|
||||||
assert isinstance(signatures, NullableReference)
|
assert isinstance(signatures, NullableReference)
|
||||||
assert isinstance(mint, int)
|
assert isinstance(mint, int)
|
||||||
assert_true(await self._verify_signatures(signatures))
|
assert_trues(
|
||||||
assert_true(await self._verify_values(mint))
|
await gather(
|
||||||
|
self._verify_signatures(signatures),
|
||||||
|
self._verify_values(mint),
|
||||||
|
)
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
|
in_str, out_str = await gather(
|
||||||
|
self.in_coins.str(tab),
|
||||||
|
self.out_coins.str(tab),
|
||||||
|
)
|
||||||
return f'(in)' \
|
return f'(in)' \
|
||||||
f'{tabulate(tab)}{await self.in_coins.str(tab)}' \
|
f'{tabulate(tab)}{in_str}' \
|
||||||
f'{tabulate(tab)}(out)' \
|
f'{tabulate(tab)}(out)' \
|
||||||
f'{tabulate(tab)}{await self.out_coins.str(tab)}'
|
f'{tabulate(tab)}{out_str}'
|
||||||
|
|
||||||
|
|
||||||
class Transaction(RecursiveMentionable, StaticMentionable):
|
class Transaction(RecursiveMentionable, StaticMentionable):
|
||||||
@ -276,10 +321,14 @@ class Transaction(RecursiveMentionable, StaticMentionable):
|
|||||||
|
|
||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
|
data_str, signatures_str = await gather(
|
||||||
|
hash_point_format(self.data, tab + 1),
|
||||||
|
self.signatures.str(tab + 1),
|
||||||
|
)
|
||||||
return f'(' \
|
return f'(' \
|
||||||
f'{tabulate(tab + 1)}transaction' \
|
f'{tabulate(tab + 1)}transaction' \
|
||||||
f'{tabulate(tab + 1)}{hash_point_format(self.data, tab + 1)}' \
|
f'{tabulate(tab + 1)}{data_str}' \
|
||||||
f'{tabulate(tab + 1)}{self.signatures.str(tab + 1)}' \
|
f'{tabulate(tab + 1)}{signatures_str}' \
|
||||||
f'{tabulate(tab)})'
|
f'{tabulate(tab)})'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -156,8 +156,13 @@ class WeakReferenceIndexSetBTree(RecursiveMentionable):
|
|||||||
f'{tabulate(tab)}('
|
f'{tabulate(tab)}('
|
||||||
for key_index in range(self.keys):
|
for key_index in range(self.keys):
|
||||||
formatted += f'{tabulate(tab + 1)}{self.key_no(key_index).hex()}'
|
formatted += f'{tabulate(tab + 1)}{self.key_no(key_index).hex()}'
|
||||||
for child_index in range(self.children):
|
formatted += ''.join(
|
||||||
formatted += f'{tabulate(tab + 1)}{await hash_point_format(self.child_no(child_index), tab + 1)}'
|
f'{tabulate(tab + 1)}{child_formatted}' for child_formatted in (
|
||||||
|
await gather(
|
||||||
|
hash_point_format(self.child_no(child_index), tab + 1) for child_index in range(self.children)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return f'{formatted}' \
|
return f'{formatted}' \
|
||||||
f'{tabulate(tab)})'
|
f'{tabulate(tab)})'
|
||||||
|
@ -33,9 +33,13 @@ class WrisbtIndex(RecursiveMentionable):
|
|||||||
|
|
||||||
async def str(self, tab: int) -> str:
|
async def str(self, tab: int) -> str:
|
||||||
assert isinstance(tab, int)
|
assert isinstance(tab, int)
|
||||||
|
total_str, delta_str = await gather(
|
||||||
|
hash_point_format(self.total, tab),
|
||||||
|
hash_point_format(self.delta, tab),
|
||||||
|
)
|
||||||
return f'(index)' \
|
return f'(index)' \
|
||||||
f'{tabulate(tab)}{await hash_point_format(self.total, tab)}' \
|
f'{tabulate(tab)}{total_str}' \
|
||||||
f'{tabulate(tab)}{await hash_point_format(self.delta, tab)}'
|
f'{tabulate(tab)}{delta_str}'
|
||||||
|
|
||||||
|
|
||||||
class WrisbtIndexFactory(RainbowFactory[WrisbtIndex]):
|
class WrisbtIndexFactory(RainbowFactory[WrisbtIndex]):
|
||||||
|
@ -41,10 +41,15 @@ class WrisbtProtocol(MetaReductionStateProtocol[TargetType, WrisbtIndex]):
|
|||||||
total: WrisbtRoot = await index.total.resolve()
|
total: WrisbtRoot = await index.total.resolve()
|
||||||
assert isinstance(total, WrisbtRoot)
|
assert isinstance(total, WrisbtRoot)
|
||||||
|
|
||||||
|
total_index, delta_index = await gather(
|
||||||
|
total.index(header, empty),
|
||||||
|
empty.index(header, total),
|
||||||
|
)
|
||||||
|
|
||||||
return HashPoint.of(
|
return HashPoint.of(
|
||||||
WrisbtIndex(
|
WrisbtIndex(
|
||||||
HashPoint.of(await total.index(header, empty)),
|
HashPoint.of(total_index),
|
||||||
HashPoint.of(await empty.index(header, total)),
|
HashPoint.of(delta_index),
|
||||||
index.keymin
|
index.keymin
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -86,7 +86,11 @@ class WrisbtRoot(RecursiveMentionable):
|
|||||||
assert isinstance(exclude, WrisbtRoot)
|
assert isinstance(exclude, WrisbtRoot)
|
||||||
key: bytes = target.point
|
key: bytes = target.point
|
||||||
assert isinstance(key, bytes)
|
assert isinstance(key, bytes)
|
||||||
if await exclude.contains(key) or await self.contains(key):
|
exclude_contains, self_contains = await gather(
|
||||||
|
exclude.contains(key),
|
||||||
|
self.contains(key),
|
||||||
|
)
|
||||||
|
if exclude_contains or self_contains:
|
||||||
return self
|
return self
|
||||||
tree: WrisbtRoot = self
|
tree: WrisbtRoot = self
|
||||||
value: Mentionable = await target.resolve()
|
value: Mentionable = await target.resolve()
|
||||||
|
Loading…
Reference in New Issue
Block a user