add missing asserts + trace/plot + optimize avl (+ remove fsplit) + more instrumentation
This commit is contained in:
parent
001c8e1930
commit
d86609d8b3
1
.gitignore
vendored
1
.gitignore
vendored
@ -211,3 +211,4 @@ fabric.properties
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
/trace/
|
||||
|
@ -3,6 +3,7 @@
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/trace" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
97
plot.py
97
plot.py
@ -1,88 +1,31 @@
|
||||
import asyncio
|
||||
import random
|
||||
import json
|
||||
|
||||
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 plottable(log: list[tuple[float, int]]):
|
||||
if log:
|
||||
return np.array(log).transpose()
|
||||
else:
|
||||
return np.array([[], []])
|
||||
|
||||
|
||||
def plot(instrumentation: Concurrency):
|
||||
plt.plot(*np.array(instrumentation.logs).transpose())
|
||||
def plot():
|
||||
plt.rcParams['figure.figsize'] = [16, 9]
|
||||
plt.style.use("dark_background")
|
||||
plt.subplots_adjust(left=0.03, right=0.99, top=0.99, bottom=0.05)
|
||||
|
||||
|
||||
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)
|
||||
with open('trace/latest.json') as file:
|
||||
jsonified = json.load(file)
|
||||
if (log := jsonified.get('DelayedResolver:sleep:concurrency')) is not None:
|
||||
plt.plot(*plottable(log))
|
||||
if (log := jsonified.get('ActiveBinaryTree:add:entry')) is not None:
|
||||
plt.scatter(*plottable(log), c='tomato', zorder=100, s=.5)
|
||||
if (log := jsonified.get('ActiveBinaryTree:add:exit')) is not None:
|
||||
plt.scatter(*plottable(log), c='gold', zorder=99, s=.5)
|
||||
plt.show()
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
if __name__ == '__main__':
|
||||
plot()
|
||||
|
@ -42,6 +42,9 @@ class Block(RecursiveMentionable, Generic[HeaderType, StateType]):
|
||||
hash_point_format(self.header, tab + 1),
|
||||
hash_point_format(self.state, tab + 1),
|
||||
)
|
||||
assert isinstance(previous_str, str)
|
||||
assert isinstance(header_str, str)
|
||||
assert isinstance(state_str, str)
|
||||
return f'{previous_str}' \
|
||||
f'{tabulate(tab)}(' \
|
||||
f'{tabulate(tab + 1)}block' \
|
||||
|
@ -125,6 +125,7 @@ class BlockChain(
|
||||
previous: ChainCollectionInterface[
|
||||
Block[HeaderType, StateType], HeaderType, ActualStateType
|
||||
] = await self.previous()
|
||||
assert isinstance(previous, ChainCollectionInterface)
|
||||
assert_trues(
|
||||
await gather(
|
||||
self.verify_link(previous.reference),
|
||||
|
@ -54,6 +54,9 @@ class ActiveStageStateProtocol(
|
||||
]
|
||||
]
|
||||
) -> bool:
|
||||
assert isinstance(previous, NullableReference)
|
||||
assert isinstance(header, HashPoint)
|
||||
assert isinstance(state, HashPoint)
|
||||
return await self.stage_state_protocol().verify(
|
||||
previous,
|
||||
header,
|
||||
|
@ -106,6 +106,8 @@ class StageStage(
|
||||
self.previous.str(tab),
|
||||
hash_point_format(self.stage, tab)
|
||||
)
|
||||
assert isinstance(previous_str, str)
|
||||
assert isinstance(stage_str, str)
|
||||
return f'{previous_str}' \
|
||||
f'{tabulate(tab)}{stage_str}'
|
||||
|
||||
@ -195,6 +197,8 @@ class StateStage(
|
||||
hash_point_format(self.previous, tab),
|
||||
hash_point_format(self.state, tab),
|
||||
)
|
||||
assert isinstance(previous_str, str)
|
||||
assert isinstance(state_str, str)
|
||||
return f'{previous_str}' \
|
||||
f'{tabulate(tab)}{state_str}'
|
||||
|
||||
|
@ -31,6 +31,8 @@ class KeyMetadata(Keyed[ActiveKeyType], Generic[ActiveKeyType, MetaDataType]):
|
||||
hash_point_format(self.key, tab),
|
||||
hash_point_format(self.metadata, tab)
|
||||
)
|
||||
assert isinstance(key_str, str)
|
||||
assert isinstance(metadata_str, str)
|
||||
return f'{key_str}' \
|
||||
f'{tabulate(tab)}{metadata_str}'
|
||||
|
||||
|
@ -35,6 +35,8 @@ class Stack(RecursiveMentionable, Generic[ElementType]):
|
||||
self.previous.str(tab),
|
||||
hash_point_format(self.element, tab),
|
||||
)
|
||||
assert isinstance(previous_str, str)
|
||||
assert isinstance(element_str, str)
|
||||
return f'{previous_str}' \
|
||||
f'{tabulate(tab)}{element_str}'
|
||||
|
||||
@ -76,6 +78,7 @@ class Stack(RecursiveMentionable, Generic[ElementType]):
|
||||
pass
|
||||
else:
|
||||
stack: Stack[ElementType] = await reference.resolve()
|
||||
assert isinstance(stack, Stack)
|
||||
yield stack.element
|
||||
async for element in cls.iter(stack.previous):
|
||||
yield element
|
||||
@ -85,6 +88,7 @@ class Stack(RecursiveMentionable, Generic[ElementType]):
|
||||
cls,
|
||||
reference: NullableReference['Stack[ElementType]']
|
||||
) -> list[ElementType]:
|
||||
assert isinstance(reference, NullableReference)
|
||||
return list(
|
||||
await gather(
|
||||
*[element.resolve() async for element in cls.iter(reference)]
|
||||
|
@ -33,6 +33,8 @@ class Pair(
|
||||
hash_point_format(self.element0, tab),
|
||||
hash_point_format(self.element1, tab),
|
||||
)
|
||||
assert isinstance(e0_str, str)
|
||||
assert isinstance(e1_str, str)
|
||||
return f'(pair)' \
|
||||
f'{tabulate(tab)}{e0_str}' \
|
||||
f'{tabulate(tab)}{e1_str}'
|
||||
|
@ -15,9 +15,11 @@ class BinaryAction(Generic[ActiveKeyType, MetaDataType, TreeType, ActionType]):
|
||||
self,
|
||||
protocolized: BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType],
|
||||
) -> ActionType:
|
||||
assert isinstance(protocolized, BinaryProtocolized)
|
||||
if (split := await ProtocolizedBinarySplit.split_of(protocolized)) is None:
|
||||
return await self.on_null(protocolized)
|
||||
else:
|
||||
assert isinstance(split, ProtocolizedBinarySplit)
|
||||
return await self.on_split(split)
|
||||
|
||||
async def on_null(
|
||||
|
@ -26,6 +26,8 @@ class AddAction(
|
||||
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType],
|
||||
equal: Equal
|
||||
) -> TreeType:
|
||||
assert isinstance(case, ProtocolizedBinarySplit)
|
||||
assert isinstance(equal, Equal)
|
||||
if isinstance(equal, Replace):
|
||||
return await case.protocol.tree(case.split.treel, case.split.treer, self.key)
|
||||
else:
|
||||
@ -35,6 +37,7 @@ class AddAction(
|
||||
self,
|
||||
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
assert isinstance(case, ProtocolizedBinarySplit)
|
||||
return await case.protocol.tree(
|
||||
await self.on(case.protocolizedl()),
|
||||
case.split.treer,
|
||||
@ -45,6 +48,7 @@ class AddAction(
|
||||
self,
|
||||
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
assert isinstance(case, ProtocolizedBinarySplit)
|
||||
return await case.protocol.tree(
|
||||
case.split.treel,
|
||||
await self.on(case.protocolizedr()),
|
||||
@ -75,18 +79,18 @@ class MergeAction(
|
||||
self,
|
||||
protocolized: BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType],
|
||||
) -> TreeType:
|
||||
assert isinstance(protocolized, BinaryProtocolized)
|
||||
return self.treer
|
||||
|
||||
async def on_split(
|
||||
self,
|
||||
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
protocol = case.protocol
|
||||
split = case.split
|
||||
return await protocol.tree(
|
||||
split.treel,
|
||||
assert isinstance(case, ProtocolizedBinarySplit)
|
||||
return await case.protocol.tree(
|
||||
case.split.treel,
|
||||
await MergeAction(self.treer).on(case.protocolizedr()),
|
||||
split.key
|
||||
case.split.key
|
||||
)
|
||||
|
||||
|
||||
@ -104,12 +108,15 @@ class RemoveAction(
|
||||
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType],
|
||||
equal: Equal
|
||||
) -> TreeType:
|
||||
assert isinstance(case, ProtocolizedBinarySplit)
|
||||
assert isinstance(equal, Equal)
|
||||
return await MergeAction(case.split.treer).on(case.protocolizedl())
|
||||
|
||||
async def on_left(
|
||||
self,
|
||||
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
assert isinstance(case, ProtocolizedBinarySplit)
|
||||
return await case.protocol.tree(
|
||||
await self.on(case.protocolizedl()),
|
||||
case.split.treer,
|
||||
@ -120,6 +127,7 @@ class RemoveAction(
|
||||
self,
|
||||
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
assert isinstance(case, ProtocolizedBinarySplit)
|
||||
return await case.protocol.tree(
|
||||
case.split.treel,
|
||||
await self.on(case.protocolizedr()),
|
||||
@ -130,6 +138,7 @@ class RemoveAction(
|
||||
self,
|
||||
protocolized: BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType],
|
||||
) -> TreeType:
|
||||
assert isinstance(protocolized, BinaryProtocolized)
|
||||
return protocolized.tree
|
||||
|
||||
|
||||
@ -147,22 +156,27 @@ class ContainsAction(
|
||||
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType],
|
||||
equal: Equal
|
||||
) -> bool:
|
||||
assert isinstance(case, ProtocolizedBinarySplit)
|
||||
assert isinstance(equal, Equal)
|
||||
return True
|
||||
|
||||
async def on_left(
|
||||
self,
|
||||
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> bool:
|
||||
assert isinstance(case, ProtocolizedBinarySplit)
|
||||
return await self.on(case.protocolizedl())
|
||||
|
||||
async def on_right(
|
||||
self,
|
||||
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> bool:
|
||||
assert isinstance(case, ProtocolizedBinarySplit)
|
||||
return await self.on(case.protocolizedr())
|
||||
|
||||
async def on_null(
|
||||
self,
|
||||
protocolized: BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType],
|
||||
) -> bool:
|
||||
assert isinstance(protocolized, BinaryProtocolized)
|
||||
return False
|
||||
|
@ -17,6 +17,7 @@ class Symmetric(
|
||||
self,
|
||||
protocol: BinaryCreation[ActiveKeyType, MetaDataType, TreeType],
|
||||
):
|
||||
assert isinstance(protocol, BinaryCreation)
|
||||
self.protocol = protocol
|
||||
|
||||
def inner(
|
||||
@ -43,12 +44,14 @@ class Symmetric(
|
||||
self,
|
||||
split: BinarySplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType]:
|
||||
assert isinstance(split, BinarySplit)
|
||||
return BinaryProtocolized(self.protocol, self.inner(split))
|
||||
|
||||
def protocolizedo(
|
||||
self,
|
||||
split: BinarySplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType]:
|
||||
assert isinstance(split, BinarySplit)
|
||||
return BinaryProtocolized(self.protocol, self.outer(split))
|
||||
|
||||
|
||||
@ -57,12 +60,14 @@ class InnerOuter(Symmetric):
|
||||
self,
|
||||
split: BinarySplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
assert isinstance(split, BinarySplit)
|
||||
return split.treel
|
||||
|
||||
def outer(
|
||||
self,
|
||||
split: BinarySplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
assert isinstance(split, BinarySplit)
|
||||
return split.treer
|
||||
|
||||
async def tree(
|
||||
@ -71,6 +76,7 @@ class InnerOuter(Symmetric):
|
||||
outer: TreeType,
|
||||
key: HashPoint[ActiveKeyType]
|
||||
) -> TreeType:
|
||||
assert isinstance(key, HashPoint)
|
||||
return await self.protocol.tree(inner, outer, key)
|
||||
|
||||
|
||||
@ -79,12 +85,14 @@ class OuterInner(Symmetric):
|
||||
self,
|
||||
split: BinarySplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
assert isinstance(split, BinarySplit)
|
||||
return split.treer
|
||||
|
||||
def outer(
|
||||
self,
|
||||
split: BinarySplit[ActiveKeyType, MetaDataType, TreeType]
|
||||
) -> TreeType:
|
||||
assert isinstance(split, BinarySplit)
|
||||
return split.treel
|
||||
|
||||
async def tree(
|
||||
@ -93,4 +101,5 @@ class OuterInner(Symmetric):
|
||||
outer: TreeType,
|
||||
key: HashPoint[ActiveKeyType]
|
||||
) -> TreeType:
|
||||
assert isinstance(key, HashPoint)
|
||||
return await self.protocol.tree(outer, inner, key)
|
||||
|
@ -1,4 +1,4 @@
|
||||
from typing import Generic, TypeVar
|
||||
from typing import Generic, Optional, TypeVar
|
||||
|
||||
from rainbowadn.atomic import *
|
||||
from rainbowadn.core import *
|
||||
@ -22,11 +22,14 @@ class AVL(BinaryBalancing[ActiveKeyType, Integer, TreeType]):
|
||||
key: HashPoint[ActiveKeyType],
|
||||
creation: BinaryCreation[ActiveKeyType, Integer, TreeType]
|
||||
) -> HashPoint[Integer]:
|
||||
assert isinstance(key, HashPoint)
|
||||
assert isinstance(creation, BinaryCreation)
|
||||
height_l, height_r = await gather(
|
||||
self.height(BinaryProtocolized(creation, treel)),
|
||||
self.height(BinaryProtocolized(creation, treer)),
|
||||
)
|
||||
assert isinstance(height_l, int)
|
||||
assert isinstance(height_r, int)
|
||||
return HashPoint.of(
|
||||
Integer(
|
||||
1
|
||||
@ -43,12 +46,22 @@ class AVL(BinaryBalancing[ActiveKeyType, Integer, TreeType]):
|
||||
cls,
|
||||
protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType],
|
||||
) -> int:
|
||||
assert isinstance(protocolized, BinaryProtocolized)
|
||||
return await HeightAction().on(protocolized)
|
||||
|
||||
@classmethod
|
||||
async def full_height(
|
||||
cls,
|
||||
protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType],
|
||||
) -> tuple[int, Optional[BinarySplit[ActiveKeyType, Integer, TreeType]]]:
|
||||
assert isinstance(protocolized, BinaryProtocolized)
|
||||
return await FullHeightAction().on(protocolized)
|
||||
|
||||
async def balance(
|
||||
self,
|
||||
protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType],
|
||||
) -> TreeType:
|
||||
assert isinstance(protocolized, BinaryProtocolized)
|
||||
return await BalanceAction().on(protocolized)
|
||||
|
||||
|
||||
@ -60,16 +73,45 @@ class HeightAction(
|
||||
self,
|
||||
protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType],
|
||||
) -> int:
|
||||
assert isinstance(protocolized, BinaryProtocolized)
|
||||
return 0
|
||||
|
||||
async def on_split(
|
||||
self,
|
||||
case: ProtocolizedBinarySplit[ActiveKeyType, Integer, TreeType]
|
||||
) -> int:
|
||||
assert isinstance(case, ProtocolizedBinarySplit)
|
||||
metadata: Integer = await case.split.metadata.resolve()
|
||||
assert isinstance(metadata, Integer)
|
||||
return metadata.integer
|
||||
|
||||
|
||||
class FullHeightAction(
|
||||
BinaryAction[
|
||||
ActiveKeyType,
|
||||
Integer,
|
||||
TreeType,
|
||||
tuple[int, Optional[BinarySplit[ActiveKeyType, Integer, TreeType]]]
|
||||
],
|
||||
Generic[ActiveKeyType, TreeType]
|
||||
):
|
||||
async def on_null(
|
||||
self,
|
||||
protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType],
|
||||
) -> tuple[int, Optional[BinarySplit[ActiveKeyType, Integer, TreeType]]]:
|
||||
assert isinstance(protocolized, BinaryProtocolized)
|
||||
return 0, None
|
||||
|
||||
async def on_split(
|
||||
self,
|
||||
case: ProtocolizedBinarySplit[ActiveKeyType, Integer, TreeType]
|
||||
) -> tuple[int, Optional[BinarySplit[ActiveKeyType, Integer, TreeType]]]:
|
||||
assert isinstance(case, ProtocolizedBinarySplit)
|
||||
metadata: Integer = await case.split.metadata.resolve()
|
||||
assert isinstance(metadata, Integer)
|
||||
return metadata.integer, case.split
|
||||
|
||||
|
||||
class BalanceAction(
|
||||
BinaryAction[ActiveKeyType, Integer, TreeType, TreeType],
|
||||
Generic[ActiveKeyType, TreeType]
|
||||
@ -78,22 +120,30 @@ class BalanceAction(
|
||||
self,
|
||||
protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType],
|
||||
) -> TreeType:
|
||||
assert isinstance(protocolized, BinaryProtocolized)
|
||||
return protocolized.tree
|
||||
|
||||
async def on_split(
|
||||
self,
|
||||
case: ProtocolizedBinarySplit[ActiveKeyType, Integer, TreeType]
|
||||
) -> TreeType:
|
||||
height_l, height_r = await gather(
|
||||
AVL.height(case.protocolizedl()),
|
||||
AVL.height(case.protocolizedr()),
|
||||
assert isinstance(case, ProtocolizedBinarySplit)
|
||||
(height_l, splitl), (height_r, splitr) = await gather(
|
||||
AVL.full_height(case.protocolizedl()),
|
||||
AVL.full_height(case.protocolizedr()),
|
||||
)
|
||||
assert isinstance(height_l, int)
|
||||
assert isinstance(height_r, int)
|
||||
delta = height_l - height_r
|
||||
assert isinstance(delta, int)
|
||||
if delta < -1:
|
||||
return await self.on_symmetric(InnerOuter(case.protocol), case.split)
|
||||
splitr: BinarySplit[ActiveKeyType, Integer, TreeType]
|
||||
assert isinstance(splitr, BinarySplit)
|
||||
return await self.on_symmetric(InnerOuter(case.protocol), case.split.treel, case.split.key, splitr)
|
||||
elif delta > 1:
|
||||
return await self.on_symmetric(OuterInner(case.protocol), case.split)
|
||||
splitl: BinarySplit[ActiveKeyType, Integer, TreeType]
|
||||
assert isinstance(splitl, BinarySplit)
|
||||
return await self.on_symmetric(OuterInner(case.protocol), case.split.treer, case.split.key, splitl)
|
||||
else:
|
||||
return case.tree
|
||||
|
||||
@ -101,19 +151,24 @@ class BalanceAction(
|
||||
async def on_symmetric(
|
||||
cls,
|
||||
symmetry: Symmetric[ActiveKeyType, Integer, TreeType],
|
||||
split: BinarySplit[ActiveKeyType, Integer, TreeType]
|
||||
treei: TreeType,
|
||||
key: HashPoint[ActiveKeyType],
|
||||
splito: BinarySplit[ActiveKeyType, Integer, TreeType],
|
||||
) -> TreeType:
|
||||
assert isinstance(symmetry, Symmetric)
|
||||
assert isinstance(split, BinarySplit)
|
||||
splito = await symmetry.protocol.fsplit(symmetry.outer(split))
|
||||
height_oi, height_oo = await gather(
|
||||
AVL.height(symmetry.protocolizedi(splito)),
|
||||
assert isinstance(key, HashPoint)
|
||||
assert isinstance(splito, BinarySplit)
|
||||
(height_oi, splitoi), height_oo = await gather(
|
||||
AVL.full_height(symmetry.protocolizedi(splito)),
|
||||
AVL.height(symmetry.protocolizedo(splito)),
|
||||
)
|
||||
assert isinstance(height_oi, int)
|
||||
assert isinstance(height_oo, int)
|
||||
if height_oi > height_oo:
|
||||
splitoi = await symmetry.protocol.fsplit(symmetry.inner(splito))
|
||||
splitoi: BinarySplit[ActiveKeyType, Integer, TreeType]
|
||||
assert isinstance(splitoi, BinarySplit)
|
||||
inner, outer = await gather(
|
||||
symmetry.tree(symmetry.inner(split), symmetry.inner(splitoi), split.key),
|
||||
symmetry.tree(treei, symmetry.inner(splitoi), key),
|
||||
symmetry.tree(symmetry.outer(splitoi), symmetry.outer(splito), splito.key),
|
||||
)
|
||||
return await symmetry.tree(
|
||||
@ -123,7 +178,7 @@ class BalanceAction(
|
||||
)
|
||||
else:
|
||||
return await symmetry.tree(
|
||||
await symmetry.tree(symmetry.inner(split), symmetry.inner(splito), split.key),
|
||||
await symmetry.tree(treei, symmetry.inner(splito), key),
|
||||
symmetry.outer(splito),
|
||||
splito.key
|
||||
)
|
||||
|
@ -42,6 +42,9 @@ class BinaryTree(RecursiveMentionable, Generic[TreeKeyType]):
|
||||
hash_point_format(self.key, tab),
|
||||
self.treer.str(tab),
|
||||
)
|
||||
assert isinstance(treel_str, str)
|
||||
assert isinstance(key_str, str)
|
||||
assert isinstance(treer_str, str)
|
||||
return f'{treel_str}' \
|
||||
f'{tabulate(tab)}{key_str}' \
|
||||
f'{tabulate(tab)}{treer_str}'
|
||||
|
@ -22,12 +22,5 @@ class BinaryCreation(Generic[ActiveKeyType, MetaDataType, TreeType]):
|
||||
"""result of this method is supposed to be used right after the call, therefore all values are resolved"""
|
||||
raise NotImplementedError
|
||||
|
||||
async def fsplit(self, tree: TreeType) -> BinarySplit[
|
||||
ActiveKeyType, MetaDataType, TreeType
|
||||
]:
|
||||
split: Optional[BinarySplit[ActiveKeyType, MetaDataType, TreeType]] = await self.split(tree)
|
||||
assert split is not None
|
||||
return split
|
||||
|
||||
async def tree(self, treel: TreeType, treer: TreeType, key: HashPoint[ActiveKeyType]) -> TreeType:
|
||||
raise NotImplementedError
|
||||
|
@ -42,6 +42,7 @@ class ProtocolizedBinarySplit(
|
||||
) -> Optional[
|
||||
'ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]'
|
||||
]:
|
||||
assert isinstance(protocolized, BinaryProtocolized)
|
||||
if (split := await protocolized.split()) is None:
|
||||
return None
|
||||
else:
|
||||
|
@ -3,6 +3,7 @@ from typing import TypeVar
|
||||
|
||||
from .hashpoint import HashPoint
|
||||
from .hashresolver import HashResolver
|
||||
from .mentionable import Mentionable
|
||||
from .resolvermetaorigin import ResolverMetaOrigin
|
||||
|
||||
__all__ = ('ExtendableResolver',)
|
||||
@ -19,4 +20,5 @@ class ExtendableResolver(HashResolver, abc.ABC):
|
||||
return ResolverMetaOrigin(await self.extend(hash_point)).hash_point(hash_point.factory, hash_point.point)
|
||||
|
||||
async def migrate_resolved(self, mentioned: Mentioned) -> Mentioned:
|
||||
assert isinstance(mentioned, Mentionable)
|
||||
return await (await self.migrate(HashPoint.of(mentioned))).resolve()
|
||||
|
@ -9,6 +9,7 @@ async def hash_point_format(hash_point: HashPoint, tab: int) -> str:
|
||||
assert isinstance(hash_point, HashPoint)
|
||||
assert isinstance(tab, int)
|
||||
value: Mentionable = await hash_point.resolve()
|
||||
assert isinstance(value, Mentionable)
|
||||
if isinstance(value, RecursiveMentionable):
|
||||
return await value.str(tab)
|
||||
else:
|
||||
|
@ -9,6 +9,7 @@ Mentioned = TypeVar('Mentioned')
|
||||
|
||||
class Origin(Generic[Mentioned]):
|
||||
def __init__(self, factory: RainbowFactory[Mentioned]):
|
||||
assert isinstance(factory, RainbowFactory)
|
||||
self.factory = factory
|
||||
|
||||
async def resolve(self) -> Mentioned:
|
||||
|
@ -25,6 +25,7 @@ class StaticMentionable(Mentionable, abc.ABC):
|
||||
|
||||
class StaticFactory(RainbowFactory[StaticMentioned], Generic[StaticMentioned]):
|
||||
def __init__(self, cls: Type[StaticMentioned]):
|
||||
assert issubclass(cls, StaticMentionable)
|
||||
self.cls: Type[StaticMentioned] = cls
|
||||
|
||||
def from_bytes(self, source: bytes, resolver: HashResolver) -> StaticMentioned:
|
||||
|
@ -26,6 +26,7 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]):
|
||||
assert isinstance(decrypted, Mentionable)
|
||||
|
||||
self.factory: RainbowFactory[EncryptedType] = decrypted.__factory__()
|
||||
assert isinstance(self.factory, RainbowFactory)
|
||||
self.key = key
|
||||
|
||||
self.resolution = resolution
|
||||
@ -38,6 +39,7 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]):
|
||||
|
||||
@classmethod
|
||||
async def encrypt(cls, decrypted: EncryptedType, key: bytes) -> 'Encrypted[EncryptedType]':
|
||||
assert isinstance(decrypted, Mentionable)
|
||||
assert isinstance(key, bytes)
|
||||
hashpoints = tuple(decrypted.points()) if isinstance(decrypted, RecursiveMentionable) else ()
|
||||
resolution = tuple(
|
||||
@ -79,6 +81,10 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]):
|
||||
hashpoints: tuple[HashPoint, ...],
|
||||
decrypted: EncryptedType
|
||||
) -> 'Encrypted[EncryptedType]':
|
||||
assert isinstance(key, bytes)
|
||||
assert isinstance(resolution, tuple)
|
||||
assert isinstance(hashpoints, tuple)
|
||||
assert isinstance(decrypted, Mentionable)
|
||||
mapping: dict[bytes, HashPoint[Encrypted]] = {
|
||||
hash_point.point: encrypted for hash_point, encrypted in zip(hashpoints, resolution)
|
||||
}
|
||||
@ -122,6 +128,7 @@ class EncryptedFactory(RainbowFactory[Encrypted[EncryptedType]], Generic[Encrypt
|
||||
plain[8 + resolution_size * HashPoint.HASH_LENGTH:],
|
||||
resolver,
|
||||
)
|
||||
assert isinstance(decrypted, Mentionable)
|
||||
hashpoints = tuple(decrypted.points()) if isinstance(decrypted, RecursiveMentionable) else ()
|
||||
assert_eq(len(hashpoints), resolution_size)
|
||||
resolution: tuple[HashPoint[Encrypted], ...] = tuple(
|
||||
@ -152,6 +159,7 @@ class EncryptedResolver(HashResolver):
|
||||
async def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
|
||||
assert isinstance(point, bytes)
|
||||
encrypted: Encrypted = await self.mapping[point].resolve()
|
||||
assert isinstance(encrypted, Encrypted)
|
||||
return HashPoint.bytes_of_mentioned(encrypted.decrypted), EncryptedResolver(encrypted.mapping, self.key)
|
||||
|
||||
|
||||
@ -167,7 +175,9 @@ class ShortcutOrigin(Origin[Encrypted[EncryptedType]], Generic[EncryptedType]):
|
||||
|
||||
async def resolve(self) -> Encrypted[EncryptedType]:
|
||||
source: Encrypted = await self.hashpoint.resolve()
|
||||
assert isinstance(source, Encrypted)
|
||||
encrypted: Encrypted[EncryptedType] = self.factory.from_bytes(bytes(source), ShortcutResolver(source))
|
||||
assert isinstance(encrypted, Encrypted)
|
||||
assert_eq(HashPoint.of(encrypted), self.hashpoint)
|
||||
return encrypted
|
||||
|
||||
@ -188,6 +198,7 @@ class ShortcutResolver(HashResolver):
|
||||
async def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
|
||||
assert isinstance(point, bytes)
|
||||
resolved: Encrypted = await self.mapping[point].resolve()
|
||||
assert isinstance(resolved, Encrypted)
|
||||
return (
|
||||
HashPoint.bytes_of_mentioned(resolved),
|
||||
ShortcutResolver(resolved)
|
||||
|
@ -41,9 +41,11 @@ class NullableReference(RecursiveMentionable, Generic[Referenced]):
|
||||
|
||||
@classmethod
|
||||
def off(cls, value: Referenced) -> 'NullableReference[Referenced]':
|
||||
assert isinstance(value, Mentionable)
|
||||
return cls.of(HashPoint.of(value))
|
||||
|
||||
async def str(self, tab: int) -> str:
|
||||
assert isinstance(tab, int)
|
||||
if self.null():
|
||||
return f'-'
|
||||
else:
|
||||
|
@ -1,17 +1,21 @@
|
||||
import functools
|
||||
import time
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
__all__ = ('Instrumentation', 'Counter', 'Concurrency',)
|
||||
from contextlib import ExitStack
|
||||
from typing import Callable, Generic, TypeVar
|
||||
|
||||
__all__ = ('Instrumentation', 'Counter', 'Concurrency', 'EntryExit',)
|
||||
|
||||
IType = TypeVar('IType')
|
||||
|
||||
|
||||
class Instrumentation(Generic[IType]):
|
||||
deinstrumentation = {}
|
||||
method: Callable
|
||||
wrap: Callable
|
||||
|
||||
def __init__(self, target, methodname: str):
|
||||
assert isinstance(methodname, str)
|
||||
assert callable(getattr(target, methodname))
|
||||
self.target = target
|
||||
self.methodname = methodname
|
||||
|
||||
@ -21,6 +25,7 @@ class Instrumentation(Generic[IType]):
|
||||
def __enter__(self: IType) -> IType:
|
||||
assert not hasattr(self, 'method')
|
||||
self.method = getattr(self.target, self.methodname)
|
||||
assert callable(self.method)
|
||||
|
||||
@functools.wraps(self.method)
|
||||
def wrap(*args, **kwargs):
|
||||
@ -45,9 +50,13 @@ class Instrumentation(Generic[IType]):
|
||||
self.schedule_deinstrumentation()
|
||||
self.deinstrument()
|
||||
|
||||
def enter(self: IType, stack: ExitStack) -> IType:
|
||||
return stack.enter_context(self)
|
||||
|
||||
|
||||
class Counter(Instrumentation):
|
||||
def __init__(self, target, methodname: str):
|
||||
assert isinstance(methodname, str)
|
||||
super().__init__(target, methodname)
|
||||
self.counter = 0
|
||||
|
||||
@ -60,19 +69,39 @@ class Concurrency(Instrumentation):
|
||||
start = time.time()
|
||||
|
||||
def __init__(self, target, methodname: str):
|
||||
assert isinstance(methodname, str)
|
||||
super().__init__(target, methodname)
|
||||
self.concurrency = 0
|
||||
self.logs: list[tuple[float, int]] = []
|
||||
self.log: list[tuple[float, int]] = []
|
||||
|
||||
def time(self) -> float:
|
||||
return time.time() - self.start
|
||||
|
||||
def point(self) -> tuple[float, int]:
|
||||
return self.time(), self.concurrency
|
||||
|
||||
async def instrument(self, method, *args, **kwargs):
|
||||
self.logs.append((self.time(), self.concurrency))
|
||||
self.log.append(self.point())
|
||||
self.concurrency += 1
|
||||
self.logs.append((self.time(), self.concurrency))
|
||||
self.log.append(self.point())
|
||||
result = await method(*args, **kwargs)
|
||||
self.logs.append((self.time(), self.concurrency))
|
||||
self.log.append(self.point())
|
||||
self.concurrency -= 1
|
||||
self.logs.append((self.time(), self.concurrency))
|
||||
self.log.append(self.point())
|
||||
return result
|
||||
|
||||
|
||||
class EntryExit(Instrumentation):
|
||||
def __init__(self, target, methodname: str, point: Callable[[], tuple[float, int]]):
|
||||
assert callable(point)
|
||||
assert isinstance(methodname, str)
|
||||
super().__init__(target, methodname)
|
||||
self.point = point
|
||||
self.entry_log: list[tuple[float, int]] = []
|
||||
self.exit_log: list[tuple[float, int]] = []
|
||||
|
||||
async def instrument(self, method, *args, **kwargs):
|
||||
self.entry_log.append(self.point())
|
||||
result = await method(*args, **kwargs)
|
||||
self.exit_log.append(self.point())
|
||||
return result
|
||||
|
4
rainbowadn/testing/resolvers/__init__.py
Normal file
4
rainbowadn/testing/resolvers/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
from .cachingresolver import CachingResolver
|
||||
from .delayedresolver import DelayedResolver
|
||||
from .dictresolver import DictResolver
|
||||
from .failresolver import FailResolver
|
30
rainbowadn/testing/resolvers/cachingresolver.py
Normal file
30
rainbowadn/testing/resolvers/cachingresolver.py
Normal file
@ -0,0 +1,30 @@
|
||||
from typing import TypeVar
|
||||
|
||||
from rainbowadn.core import *
|
||||
|
||||
__all__ = ('CachingResolver',)
|
||||
|
||||
Mentioned = TypeVar('Mentioned')
|
||||
|
||||
|
||||
class CachingResolver(ExtendableResolver):
|
||||
def __init__(self, resolver: HashResolver):
|
||||
assert isinstance(resolver, HashResolver)
|
||||
self.resolver = resolver
|
||||
self.cache: dict[bytes, tuple[bytes, CachingResolver]] = {}
|
||||
|
||||
async def resolve(self, point: bytes) -> tuple[bytes, HashResolver]:
|
||||
assert isinstance(point, bytes)
|
||||
if point not in self.cache:
|
||||
resolved, resolver = await self.resolver.resolve(point)
|
||||
assert isinstance(resolved, bytes)
|
||||
assert isinstance(resolver, HashResolver)
|
||||
self.cache[point] = resolved, CachingResolver(resolver)
|
||||
return self.cache[point]
|
||||
|
||||
async def extend(self, hash_point: HashPoint[Mentioned]) -> ExtendableResolver:
|
||||
assert isinstance(hash_point, HashPoint)
|
||||
if isinstance(self.resolver, ExtendableResolver):
|
||||
return CachingResolver(await self.resolver.extend(hash_point))
|
||||
else:
|
||||
raise TypeError
|
@ -10,6 +10,8 @@ Mentioned = TypeVar('Mentioned')
|
||||
|
||||
class DelayedResolver(ExtendableResolver):
|
||||
def __init__(self, resolver: HashResolver, delay: Callable[[], float]):
|
||||
assert isinstance(resolver, HashResolver)
|
||||
assert callable(delay)
|
||||
self.resolver = resolver
|
||||
self.delay = delay
|
||||
|
||||
@ -20,9 +22,12 @@ class DelayedResolver(ExtendableResolver):
|
||||
assert isinstance(point, bytes)
|
||||
await self.sleep()
|
||||
resolved, resolver = await self.resolver.resolve(point)
|
||||
assert isinstance(resolved, bytes)
|
||||
assert isinstance(resolver, HashResolver)
|
||||
return resolved, DelayedResolver(resolver, self.delay)
|
||||
|
||||
async def extend(self, hash_point: HashPoint[Mentioned]) -> ExtendableResolver:
|
||||
assert isinstance(hash_point, HashPoint)
|
||||
if isinstance(self.resolver, ExtendableResolver):
|
||||
return DelayedResolver(await self.resolver.extend(hash_point), self.delay)
|
||||
else:
|
@ -30,5 +30,6 @@ class DictResolver(ExtendableResolver):
|
||||
)
|
||||
|
||||
async def extend(self, hash_point: HashPoint[Mentioned]) -> 'ExtendableResolver':
|
||||
assert isinstance(hash_point, HashPoint)
|
||||
await self.save(hash_point)
|
||||
return self
|
@ -16,9 +16,8 @@ from rainbowadn.encryption import *
|
||||
from rainbowadn.nullability import *
|
||||
from rainbowadn.v13 import *
|
||||
from rainbowadn.wrisbt import *
|
||||
from .delayedresolver import DelayedResolver
|
||||
from .dictresolver import DictResolver
|
||||
from .instrumentation import *
|
||||
from .resolvers import *
|
||||
|
||||
|
||||
class TestAll(unittest.IsolatedAsyncioTestCase):
|
||||
|
@ -20,6 +20,7 @@ class ValidReference(RecursiveMentionable, Generic[Referenced]):
|
||||
|
||||
async def resolve(self) -> Referenced:
|
||||
referenced: Referenced = await self.reference.resolve()
|
||||
assert isinstance(referenced, Mentionable)
|
||||
assert self.reference.point < (await self.protocol.threshold(referenced))
|
||||
return referenced
|
||||
|
||||
|
@ -104,8 +104,11 @@ class BankState(RecursiveMentionable, StaticMentionable):
|
||||
self,
|
||||
transaction: Transaction
|
||||
) -> 'BankState':
|
||||
assert isinstance(transaction, Transaction)
|
||||
miner = self.miner_nullable()
|
||||
assert isinstance(miner, Nullable)
|
||||
minted: ActiveBinaryTree[Coin, Integer] = self.minted_tree()
|
||||
assert isinstance(minted, ActiveBinaryTree)
|
||||
async for coin, miner in transaction.iter_coins(self.mint(), miner):
|
||||
minted_contains, minted = await gather(
|
||||
minted.contains(HashPoint.of(coin)),
|
||||
@ -119,11 +122,13 @@ class BankState(RecursiveMentionable, StaticMentionable):
|
||||
self,
|
||||
transaction: Transaction
|
||||
) -> 'BankState':
|
||||
assert isinstance(transaction, Transaction)
|
||||
verified, bank_state = await gather(
|
||||
self.verify(transaction),
|
||||
self._mint_coins(transaction),
|
||||
)
|
||||
assert_true(verified)
|
||||
assert isinstance(bank_state, BankState)
|
||||
return bank_state
|
||||
|
||||
def miner_nullable(self) -> Nullable[HashPoint[Subject]]:
|
||||
@ -161,6 +166,10 @@ class BankState(RecursiveMentionable, StaticMentionable):
|
||||
self.used.str(tab + 1),
|
||||
hash_point_format(self.length, tab + 1),
|
||||
)
|
||||
assert isinstance(miner_str, str)
|
||||
assert isinstance(minted_str, str)
|
||||
assert isinstance(used_str, str)
|
||||
assert isinstance(length_str, str)
|
||||
return f'(' \
|
||||
f'{tabulate(tab + 1)}bank' \
|
||||
f'{tabulate(tab + 1)}(miner)' \
|
||||
|
@ -53,6 +53,8 @@ class CoinData(RecursiveMentionable, StaticMentionable):
|
||||
hash_point_format(self.owner, tab),
|
||||
hash_point_format(self.value, tab),
|
||||
)
|
||||
assert isinstance(owner_str, str)
|
||||
assert isinstance(value_str, str)
|
||||
return f'{owner_str}' \
|
||||
f'{tabulate(tab)}{value_str}'
|
||||
|
||||
@ -98,6 +100,8 @@ class Coin(RecursiveMentionable, StaticMentionable):
|
||||
hash_point_format(self.data, tab + 1),
|
||||
hash_point_format(self.index, tab + 1),
|
||||
)
|
||||
assert isinstance(data_str, str)
|
||||
assert isinstance(index_str, str)
|
||||
return f'(' \
|
||||
f'{tabulate(tab + 1)}coin' \
|
||||
f'{tabulate(tab + 1)}{data_str}' \
|
||||
@ -145,6 +149,8 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
|
||||
)
|
||||
|
||||
async def _signature_verify(self, coin: Coin, signature: Signature) -> bool:
|
||||
assert isinstance(coin, Coin)
|
||||
assert isinstance(signature, Signature)
|
||||
assert_true(
|
||||
signature.verify(
|
||||
await coin.owner_resolved(),
|
||||
@ -157,6 +163,7 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
|
||||
self,
|
||||
signatures: NullableReference[Stack[Signature]]
|
||||
) -> bool:
|
||||
assert isinstance(signatures, NullableReference)
|
||||
assert_trues(
|
||||
await gather(
|
||||
*[
|
||||
@ -207,6 +214,8 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
|
||||
self._total_in(),
|
||||
self._total_out(),
|
||||
)
|
||||
assert isinstance(total_in, int)
|
||||
assert isinstance(total_out, int)
|
||||
return total_in + mint - total_out
|
||||
|
||||
async def verify(
|
||||
@ -230,6 +239,8 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
|
||||
self.in_coins.str(tab),
|
||||
self.out_coins.str(tab),
|
||||
)
|
||||
assert isinstance(in_str, str)
|
||||
assert isinstance(out_str, str)
|
||||
return f'(in)' \
|
||||
f'{tabulate(tab)}{in_str}' \
|
||||
f'{tabulate(tab)}(out)' \
|
||||
@ -276,6 +287,8 @@ class Transaction(RecursiveMentionable, StaticMentionable):
|
||||
mint: int,
|
||||
miner: Nullable[HashPoint[Subject]]
|
||||
) -> AsyncIterable[tuple[Coin, Nullable[HashPoint[Subject]]]]:
|
||||
assert isinstance(mint, int)
|
||||
assert isinstance(miner, Nullable)
|
||||
transaction_data: TransactionData = await self.data_resolved()
|
||||
assert isinstance(transaction_data, TransactionData)
|
||||
index = 0
|
||||
@ -325,6 +338,8 @@ class Transaction(RecursiveMentionable, StaticMentionable):
|
||||
hash_point_format(self.data, tab + 1),
|
||||
self.signatures.str(tab + 1),
|
||||
)
|
||||
assert isinstance(data_str, str)
|
||||
assert isinstance(signatures_str, str)
|
||||
return f'(' \
|
||||
f'{tabulate(tab + 1)}transaction' \
|
||||
f'{tabulate(tab + 1)}{data_str}' \
|
||||
@ -338,6 +353,9 @@ class Transaction(RecursiveMentionable, StaticMentionable):
|
||||
out_coins: list[CoinData],
|
||||
keys: list[nacl.signing.SigningKey],
|
||||
) -> 'Transaction':
|
||||
assert isinstance(in_coins, list)
|
||||
assert isinstance(out_coins, list)
|
||||
assert isinstance(keys, list)
|
||||
transaction_data = TransactionData(
|
||||
Stack.off(Coin.factory(), reversed(in_coins)),
|
||||
Stack.off(CoinData.factory(), reversed(out_coins)),
|
||||
|
@ -271,12 +271,19 @@ class WeakReferenceIndexSetBTree(RecursiveMentionable):
|
||||
for key_index in range(self.keys):
|
||||
yield self.key_no(key_index)
|
||||
else:
|
||||
children: list[WeakReferenceIndexSetBTree] = list(
|
||||
await gather(
|
||||
*(
|
||||
self.child_resolved_no(child) for child in range(self.children)
|
||||
)
|
||||
)
|
||||
)
|
||||
for index in range(self.keys * 2 + 1):
|
||||
real_index, mode = divmod(index, 2)
|
||||
if mode:
|
||||
yield self.key_no(real_index)
|
||||
else:
|
||||
async for key in (await self.child_resolved_no(real_index)).iter_keys():
|
||||
async for key in children[real_index].iter_keys():
|
||||
yield key
|
||||
|
||||
|
||||
|
106
trace.py
Normal file
106
trace.py
Normal file
@ -0,0 +1,106 @@
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import random
|
||||
import shutil
|
||||
import time
|
||||
from contextlib import ExitStack
|
||||
|
||||
from nacl.signing import SigningKey
|
||||
|
||||
from plot import plot
|
||||
from rainbowadn.chain import *
|
||||
from rainbowadn.collection.trees.binary import *
|
||||
from rainbowadn.core import *
|
||||
from rainbowadn.nullability import *
|
||||
from rainbowadn.testing.instrumentation import *
|
||||
from rainbowadn.testing.resolvers import *
|
||||
from rainbowadn.v13 import *
|
||||
|
||||
|
||||
def get_dr() -> ExtendableResolver:
|
||||
dr = DictResolver()
|
||||
dr = DelayedResolver(dr, lambda: random.uniform(0.200, 0.500))
|
||||
# dr = CachingResolver(dr)
|
||||
return dr
|
||||
|
||||
|
||||
def target_str(target) -> str:
|
||||
match target:
|
||||
case type(__name__=name):
|
||||
return name
|
||||
case object(__class__=type(__name__=name)):
|
||||
return name
|
||||
|
||||
|
||||
def jsonify(instrumentation: Instrumentation) -> dict:
|
||||
prefix = f'{target_str(instrumentation.target)}:{instrumentation.methodname}'
|
||||
match instrumentation:
|
||||
case Counter(counter=counter):
|
||||
return {f'{prefix}:counter': counter}
|
||||
case Concurrency(log=log):
|
||||
return {f'{prefix}:concurrency': log}
|
||||
case EntryExit(entry_log=entry_log, exit_log=exit_log):
|
||||
return {
|
||||
f'{prefix}:entry': entry_log,
|
||||
f'{prefix}:exit': exit_log,
|
||||
}
|
||||
case _:
|
||||
return {}
|
||||
|
||||
|
||||
async def main():
|
||||
set_gather_linear()
|
||||
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 ExitStack() as stack:
|
||||
sleep_cc = Concurrency(DelayedResolver, 'sleep').enter(stack)
|
||||
avl_ex = EntryExit(ActiveBinaryTree, 'add', sleep_cc.point).enter(stack)
|
||||
assert_true(await bank.verify())
|
||||
print(Instrumentation.deinstrumentation)
|
||||
fn = f'trace/{int(time.time())}-{os.urandom(2).hex()}.json'
|
||||
with open(fn, 'w') as file:
|
||||
json.dump(
|
||||
jsonify(sleep_cc) | jsonify(avl_ex),
|
||||
file
|
||||
)
|
||||
shutil.copy(fn, f'trace/latest.json')
|
||||
plot()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
Loading…
Reference in New Issue
Block a user