add missing asserts + trace/plot + optimize avl (+ remove fsplit) + more instrumentation

This commit is contained in:
AF 2022-06-23 20:37:31 +03:00
parent 001c8e1930
commit d86609d8b3
35 changed files with 382 additions and 114 deletions

1
.gitignore vendored
View File

@ -211,3 +211,4 @@ fabric.properties
# Android studio 3.1+ serialized cache file # Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser .idea/caches/build_file_checksums.ser
/trace/

View File

@ -3,6 +3,7 @@
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" /> <excludeFolder url="file://$MODULE_DIR$/venv" />
<excludeFolder url="file://$MODULE_DIR$/trace" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />

97
plot.py
View File

@ -1,88 +1,31 @@
import asyncio import json
import random
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np 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: def plottable(log: list[tuple[float, int]]):
dr = DictResolver() if log:
dr = DelayedResolver(dr, lambda: random.uniform(0.200, 0.500)) return np.array(log).transpose()
return dr else:
return np.array([[], []])
def plot(instrumentation: Concurrency): def plot():
plt.plot(*np.array(instrumentation.logs).transpose()) 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)
with open('trace/latest.json') as file:
async def plot_every_minute(instrumentation: Concurrency): jsonified = json.load(file)
while True: if (log := jsonified.get('DelayedResolver:sleep:concurrency')) is not None:
await asyncio.sleep(60) plt.plot(*plottable(log))
plot(instrumentation) if (log := jsonified.get('ActiveBinaryTree:add:entry')) is not None:
plt.show() plt.scatter(*plottable(log), c='tomato', zorder=100, s=.5)
plt.clf() if (log := jsonified.get('ActiveBinaryTree:add:exit')) is not None:
plt.subplots_adjust(left=0.05, right=0.99, top=0.99, bottom=0.1) plt.scatter(*plottable(log), c='gold', zorder=99, s=.5)
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() plt.show()
asyncio.run(main()) if __name__ == '__main__':
plot()

View File

@ -42,6 +42,9 @@ class Block(RecursiveMentionable, Generic[HeaderType, StateType]):
hash_point_format(self.header, tab + 1), hash_point_format(self.header, tab + 1),
hash_point_format(self.state, 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}' \ return f'{previous_str}' \
f'{tabulate(tab)}(' \ f'{tabulate(tab)}(' \
f'{tabulate(tab + 1)}block' \ f'{tabulate(tab + 1)}block' \

View File

@ -125,6 +125,7 @@ class BlockChain(
previous: ChainCollectionInterface[ previous: ChainCollectionInterface[
Block[HeaderType, StateType], HeaderType, ActualStateType Block[HeaderType, StateType], HeaderType, ActualStateType
] = await self.previous() ] = await self.previous()
assert isinstance(previous, ChainCollectionInterface)
assert_trues( assert_trues(
await gather( await gather(
self.verify_link(previous.reference), self.verify_link(previous.reference),

View File

@ -54,6 +54,9 @@ class ActiveStageStateProtocol(
] ]
] ]
) -> bool: ) -> bool:
assert isinstance(previous, NullableReference)
assert isinstance(header, HashPoint)
assert isinstance(state, HashPoint)
return await self.stage_state_protocol().verify( return await self.stage_state_protocol().verify(
previous, previous,
header, header,

View File

@ -106,6 +106,8 @@ class StageStage(
self.previous.str(tab), self.previous.str(tab),
hash_point_format(self.stage, tab) hash_point_format(self.stage, tab)
) )
assert isinstance(previous_str, str)
assert isinstance(stage_str, str)
return f'{previous_str}' \ return f'{previous_str}' \
f'{tabulate(tab)}{stage_str}' f'{tabulate(tab)}{stage_str}'
@ -195,6 +197,8 @@ class StateStage(
hash_point_format(self.previous, tab), hash_point_format(self.previous, tab),
hash_point_format(self.state, tab), hash_point_format(self.state, tab),
) )
assert isinstance(previous_str, str)
assert isinstance(state_str, str)
return f'{previous_str}' \ return f'{previous_str}' \
f'{tabulate(tab)}{state_str}' f'{tabulate(tab)}{state_str}'

View File

@ -31,6 +31,8 @@ class KeyMetadata(Keyed[ActiveKeyType], Generic[ActiveKeyType, MetaDataType]):
hash_point_format(self.key, tab), hash_point_format(self.key, tab),
hash_point_format(self.metadata, tab) hash_point_format(self.metadata, tab)
) )
assert isinstance(key_str, str)
assert isinstance(metadata_str, str)
return f'{key_str}' \ return f'{key_str}' \
f'{tabulate(tab)}{metadata_str}' f'{tabulate(tab)}{metadata_str}'

View File

@ -35,6 +35,8 @@ class Stack(RecursiveMentionable, Generic[ElementType]):
self.previous.str(tab), self.previous.str(tab),
hash_point_format(self.element, tab), hash_point_format(self.element, tab),
) )
assert isinstance(previous_str, str)
assert isinstance(element_str, str)
return f'{previous_str}' \ return f'{previous_str}' \
f'{tabulate(tab)}{element_str}' f'{tabulate(tab)}{element_str}'
@ -76,6 +78,7 @@ class Stack(RecursiveMentionable, Generic[ElementType]):
pass pass
else: else:
stack: Stack[ElementType] = await reference.resolve() stack: Stack[ElementType] = await reference.resolve()
assert isinstance(stack, Stack)
yield stack.element yield stack.element
async for element in cls.iter(stack.previous): async for element in cls.iter(stack.previous):
yield element yield element
@ -85,6 +88,7 @@ class Stack(RecursiveMentionable, Generic[ElementType]):
cls, cls,
reference: NullableReference['Stack[ElementType]'] reference: NullableReference['Stack[ElementType]']
) -> list[ElementType]: ) -> list[ElementType]:
assert isinstance(reference, NullableReference)
return list( return list(
await gather( await gather(
*[element.resolve() async for element in cls.iter(reference)] *[element.resolve() async for element in cls.iter(reference)]

View File

@ -33,6 +33,8 @@ class Pair(
hash_point_format(self.element0, tab), hash_point_format(self.element0, tab),
hash_point_format(self.element1, tab), hash_point_format(self.element1, tab),
) )
assert isinstance(e0_str, str)
assert isinstance(e1_str, str)
return f'(pair)' \ return f'(pair)' \
f'{tabulate(tab)}{e0_str}' \ f'{tabulate(tab)}{e0_str}' \
f'{tabulate(tab)}{e1_str}' f'{tabulate(tab)}{e1_str}'

View File

@ -15,9 +15,11 @@ class BinaryAction(Generic[ActiveKeyType, MetaDataType, TreeType, ActionType]):
self, self,
protocolized: BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType], protocolized: BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType],
) -> ActionType: ) -> ActionType:
assert isinstance(protocolized, BinaryProtocolized)
if (split := await ProtocolizedBinarySplit.split_of(protocolized)) is None: if (split := await ProtocolizedBinarySplit.split_of(protocolized)) is None:
return await self.on_null(protocolized) return await self.on_null(protocolized)
else: else:
assert isinstance(split, ProtocolizedBinarySplit)
return await self.on_split(split) return await self.on_split(split)
async def on_null( async def on_null(

View File

@ -26,6 +26,8 @@ class AddAction(
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType], case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType],
equal: Equal equal: Equal
) -> TreeType: ) -> TreeType:
assert isinstance(case, ProtocolizedBinarySplit)
assert isinstance(equal, Equal)
if isinstance(equal, Replace): if isinstance(equal, Replace):
return await case.protocol.tree(case.split.treel, case.split.treer, self.key) return await case.protocol.tree(case.split.treel, case.split.treer, self.key)
else: else:
@ -35,6 +37,7 @@ class AddAction(
self, self,
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType] case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
) -> TreeType: ) -> TreeType:
assert isinstance(case, ProtocolizedBinarySplit)
return await case.protocol.tree( return await case.protocol.tree(
await self.on(case.protocolizedl()), await self.on(case.protocolizedl()),
case.split.treer, case.split.treer,
@ -45,6 +48,7 @@ class AddAction(
self, self,
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType] case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
) -> TreeType: ) -> TreeType:
assert isinstance(case, ProtocolizedBinarySplit)
return await case.protocol.tree( return await case.protocol.tree(
case.split.treel, case.split.treel,
await self.on(case.protocolizedr()), await self.on(case.protocolizedr()),
@ -75,18 +79,18 @@ class MergeAction(
self, self,
protocolized: BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType], protocolized: BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType],
) -> TreeType: ) -> TreeType:
assert isinstance(protocolized, BinaryProtocolized)
return self.treer return self.treer
async def on_split( async def on_split(
self, self,
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType] case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
) -> TreeType: ) -> TreeType:
protocol = case.protocol assert isinstance(case, ProtocolizedBinarySplit)
split = case.split return await case.protocol.tree(
return await protocol.tree( case.split.treel,
split.treel,
await MergeAction(self.treer).on(case.protocolizedr()), await MergeAction(self.treer).on(case.protocolizedr()),
split.key case.split.key
) )
@ -104,12 +108,15 @@ class RemoveAction(
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType], case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType],
equal: Equal equal: Equal
) -> TreeType: ) -> TreeType:
assert isinstance(case, ProtocolizedBinarySplit)
assert isinstance(equal, Equal)
return await MergeAction(case.split.treer).on(case.protocolizedl()) return await MergeAction(case.split.treer).on(case.protocolizedl())
async def on_left( async def on_left(
self, self,
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType] case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
) -> TreeType: ) -> TreeType:
assert isinstance(case, ProtocolizedBinarySplit)
return await case.protocol.tree( return await case.protocol.tree(
await self.on(case.protocolizedl()), await self.on(case.protocolizedl()),
case.split.treer, case.split.treer,
@ -120,6 +127,7 @@ class RemoveAction(
self, self,
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType] case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
) -> TreeType: ) -> TreeType:
assert isinstance(case, ProtocolizedBinarySplit)
return await case.protocol.tree( return await case.protocol.tree(
case.split.treel, case.split.treel,
await self.on(case.protocolizedr()), await self.on(case.protocolizedr()),
@ -130,6 +138,7 @@ class RemoveAction(
self, self,
protocolized: BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType], protocolized: BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType],
) -> TreeType: ) -> TreeType:
assert isinstance(protocolized, BinaryProtocolized)
return protocolized.tree return protocolized.tree
@ -147,22 +156,27 @@ class ContainsAction(
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType], case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType],
equal: Equal equal: Equal
) -> bool: ) -> bool:
assert isinstance(case, ProtocolizedBinarySplit)
assert isinstance(equal, Equal)
return True return True
async def on_left( async def on_left(
self, self,
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType] case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
) -> bool: ) -> bool:
assert isinstance(case, ProtocolizedBinarySplit)
return await self.on(case.protocolizedl()) return await self.on(case.protocolizedl())
async def on_right( async def on_right(
self, self,
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType] case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]
) -> bool: ) -> bool:
assert isinstance(case, ProtocolizedBinarySplit)
return await self.on(case.protocolizedr()) return await self.on(case.protocolizedr())
async def on_null( async def on_null(
self, self,
protocolized: BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType], protocolized: BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType],
) -> bool: ) -> bool:
assert isinstance(protocolized, BinaryProtocolized)
return False return False

View File

@ -17,6 +17,7 @@ class Symmetric(
self, self,
protocol: BinaryCreation[ActiveKeyType, MetaDataType, TreeType], protocol: BinaryCreation[ActiveKeyType, MetaDataType, TreeType],
): ):
assert isinstance(protocol, BinaryCreation)
self.protocol = protocol self.protocol = protocol
def inner( def inner(
@ -43,12 +44,14 @@ class Symmetric(
self, self,
split: BinarySplit[ActiveKeyType, MetaDataType, TreeType] split: BinarySplit[ActiveKeyType, MetaDataType, TreeType]
) -> BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType]: ) -> BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType]:
assert isinstance(split, BinarySplit)
return BinaryProtocolized(self.protocol, self.inner(split)) return BinaryProtocolized(self.protocol, self.inner(split))
def protocolizedo( def protocolizedo(
self, self,
split: BinarySplit[ActiveKeyType, MetaDataType, TreeType] split: BinarySplit[ActiveKeyType, MetaDataType, TreeType]
) -> BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType]: ) -> BinaryProtocolized[ActiveKeyType, MetaDataType, TreeType]:
assert isinstance(split, BinarySplit)
return BinaryProtocolized(self.protocol, self.outer(split)) return BinaryProtocolized(self.protocol, self.outer(split))
@ -57,12 +60,14 @@ class InnerOuter(Symmetric):
self, self,
split: BinarySplit[ActiveKeyType, MetaDataType, TreeType] split: BinarySplit[ActiveKeyType, MetaDataType, TreeType]
) -> TreeType: ) -> TreeType:
assert isinstance(split, BinarySplit)
return split.treel return split.treel
def outer( def outer(
self, self,
split: BinarySplit[ActiveKeyType, MetaDataType, TreeType] split: BinarySplit[ActiveKeyType, MetaDataType, TreeType]
) -> TreeType: ) -> TreeType:
assert isinstance(split, BinarySplit)
return split.treer return split.treer
async def tree( async def tree(
@ -71,6 +76,7 @@ class InnerOuter(Symmetric):
outer: TreeType, outer: TreeType,
key: HashPoint[ActiveKeyType] key: HashPoint[ActiveKeyType]
) -> TreeType: ) -> TreeType:
assert isinstance(key, HashPoint)
return await self.protocol.tree(inner, outer, key) return await self.protocol.tree(inner, outer, key)
@ -79,12 +85,14 @@ class OuterInner(Symmetric):
self, self,
split: BinarySplit[ActiveKeyType, MetaDataType, TreeType] split: BinarySplit[ActiveKeyType, MetaDataType, TreeType]
) -> TreeType: ) -> TreeType:
assert isinstance(split, BinarySplit)
return split.treer return split.treer
def outer( def outer(
self, self,
split: BinarySplit[ActiveKeyType, MetaDataType, TreeType] split: BinarySplit[ActiveKeyType, MetaDataType, TreeType]
) -> TreeType: ) -> TreeType:
assert isinstance(split, BinarySplit)
return split.treel return split.treel
async def tree( async def tree(
@ -93,4 +101,5 @@ class OuterInner(Symmetric):
outer: TreeType, outer: TreeType,
key: HashPoint[ActiveKeyType] key: HashPoint[ActiveKeyType]
) -> TreeType: ) -> TreeType:
assert isinstance(key, HashPoint)
return await self.protocol.tree(outer, inner, key) return await self.protocol.tree(outer, inner, key)

View File

@ -1,4 +1,4 @@
from typing import Generic, TypeVar from typing import Generic, Optional, TypeVar
from rainbowadn.atomic import * from rainbowadn.atomic import *
from rainbowadn.core import * from rainbowadn.core import *
@ -22,11 +22,14 @@ class AVL(BinaryBalancing[ActiveKeyType, Integer, TreeType]):
key: HashPoint[ActiveKeyType], key: HashPoint[ActiveKeyType],
creation: BinaryCreation[ActiveKeyType, Integer, TreeType] creation: BinaryCreation[ActiveKeyType, Integer, TreeType]
) -> HashPoint[Integer]: ) -> HashPoint[Integer]:
assert isinstance(key, HashPoint)
assert isinstance(creation, BinaryCreation) assert isinstance(creation, BinaryCreation)
height_l, height_r = await gather( height_l, height_r = await gather(
self.height(BinaryProtocolized(creation, treel)), self.height(BinaryProtocolized(creation, treel)),
self.height(BinaryProtocolized(creation, treer)), self.height(BinaryProtocolized(creation, treer)),
) )
assert isinstance(height_l, int)
assert isinstance(height_r, int)
return HashPoint.of( return HashPoint.of(
Integer( Integer(
1 1
@ -43,12 +46,22 @@ class AVL(BinaryBalancing[ActiveKeyType, Integer, TreeType]):
cls, cls,
protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType], protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType],
) -> int: ) -> int:
assert isinstance(protocolized, BinaryProtocolized)
return await HeightAction().on(protocolized) 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( async def balance(
self, self,
protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType], protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType],
) -> TreeType: ) -> TreeType:
assert isinstance(protocolized, BinaryProtocolized)
return await BalanceAction().on(protocolized) return await BalanceAction().on(protocolized)
@ -60,16 +73,45 @@ class HeightAction(
self, self,
protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType], protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType],
) -> int: ) -> int:
assert isinstance(protocolized, BinaryProtocolized)
return 0 return 0
async def on_split( async def on_split(
self, self,
case: ProtocolizedBinarySplit[ActiveKeyType, Integer, TreeType] case: ProtocolizedBinarySplit[ActiveKeyType, Integer, TreeType]
) -> int: ) -> int:
assert isinstance(case, ProtocolizedBinarySplit)
metadata: Integer = await case.split.metadata.resolve() metadata: Integer = await case.split.metadata.resolve()
assert isinstance(metadata, Integer)
return 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( class BalanceAction(
BinaryAction[ActiveKeyType, Integer, TreeType, TreeType], BinaryAction[ActiveKeyType, Integer, TreeType, TreeType],
Generic[ActiveKeyType, TreeType] Generic[ActiveKeyType, TreeType]
@ -78,22 +120,30 @@ class BalanceAction(
self, self,
protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType], protocolized: BinaryProtocolized[ActiveKeyType, Integer, TreeType],
) -> TreeType: ) -> TreeType:
assert isinstance(protocolized, BinaryProtocolized)
return protocolized.tree return protocolized.tree
async def on_split( async def on_split(
self, self,
case: ProtocolizedBinarySplit[ActiveKeyType, Integer, TreeType] case: ProtocolizedBinarySplit[ActiveKeyType, Integer, TreeType]
) -> TreeType: ) -> TreeType:
height_l, height_r = await gather( assert isinstance(case, ProtocolizedBinarySplit)
AVL.height(case.protocolizedl()), (height_l, splitl), (height_r, splitr) = await gather(
AVL.height(case.protocolizedr()), 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 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) 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: 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: else:
return case.tree return case.tree
@ -101,19 +151,24 @@ class BalanceAction(
async def on_symmetric( async def on_symmetric(
cls, cls,
symmetry: Symmetric[ActiveKeyType, Integer, TreeType], symmetry: Symmetric[ActiveKeyType, Integer, TreeType],
split: BinarySplit[ActiveKeyType, Integer, TreeType] treei: TreeType,
key: HashPoint[ActiveKeyType],
splito: BinarySplit[ActiveKeyType, Integer, TreeType],
) -> TreeType: ) -> TreeType:
assert isinstance(symmetry, Symmetric) assert isinstance(symmetry, Symmetric)
assert isinstance(split, BinarySplit) assert isinstance(key, HashPoint)
splito = await symmetry.protocol.fsplit(symmetry.outer(split)) assert isinstance(splito, BinarySplit)
height_oi, height_oo = await gather( (height_oi, splitoi), height_oo = await gather(
AVL.height(symmetry.protocolizedi(splito)), AVL.full_height(symmetry.protocolizedi(splito)),
AVL.height(symmetry.protocolizedo(splito)), AVL.height(symmetry.protocolizedo(splito)),
) )
assert isinstance(height_oi, int)
assert isinstance(height_oo, int)
if height_oi > height_oo: 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( 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), symmetry.tree(symmetry.outer(splitoi), symmetry.outer(splito), splito.key),
) )
return await symmetry.tree( return await symmetry.tree(
@ -123,7 +178,7 @@ class BalanceAction(
) )
else: else:
return await symmetry.tree( 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), symmetry.outer(splito),
splito.key splito.key
) )

View File

@ -42,6 +42,9 @@ class BinaryTree(RecursiveMentionable, Generic[TreeKeyType]):
hash_point_format(self.key, tab), hash_point_format(self.key, tab),
self.treer.str(tab), self.treer.str(tab),
) )
assert isinstance(treel_str, str)
assert isinstance(key_str, str)
assert isinstance(treer_str, str)
return f'{treel_str}' \ return f'{treel_str}' \
f'{tabulate(tab)}{key_str}' \ f'{tabulate(tab)}{key_str}' \
f'{tabulate(tab)}{treer_str}' f'{tabulate(tab)}{treer_str}'

View File

@ -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""" """result of this method is supposed to be used right after the call, therefore all values are resolved"""
raise NotImplementedError 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: async def tree(self, treel: TreeType, treer: TreeType, key: HashPoint[ActiveKeyType]) -> TreeType:
raise NotImplementedError raise NotImplementedError

View File

@ -42,6 +42,7 @@ class ProtocolizedBinarySplit(
) -> Optional[ ) -> Optional[
'ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]' 'ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType]'
]: ]:
assert isinstance(protocolized, BinaryProtocolized)
if (split := await protocolized.split()) is None: if (split := await protocolized.split()) is None:
return None return None
else: else:

View File

@ -3,6 +3,7 @@ from typing import TypeVar
from .hashpoint import HashPoint from .hashpoint import HashPoint
from .hashresolver import HashResolver from .hashresolver import HashResolver
from .mentionable import Mentionable
from .resolvermetaorigin import ResolverMetaOrigin from .resolvermetaorigin import ResolverMetaOrigin
__all__ = ('ExtendableResolver',) __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) return ResolverMetaOrigin(await self.extend(hash_point)).hash_point(hash_point.factory, hash_point.point)
async def migrate_resolved(self, mentioned: Mentioned) -> Mentioned: async def migrate_resolved(self, mentioned: Mentioned) -> Mentioned:
assert isinstance(mentioned, Mentionable)
return await (await self.migrate(HashPoint.of(mentioned))).resolve() return await (await self.migrate(HashPoint.of(mentioned))).resolve()

View File

@ -9,6 +9,7 @@ async def hash_point_format(hash_point: HashPoint, tab: int) -> str:
assert isinstance(hash_point, HashPoint) assert isinstance(hash_point, HashPoint)
assert isinstance(tab, int) assert isinstance(tab, int)
value: Mentionable = await hash_point.resolve() value: Mentionable = await hash_point.resolve()
assert isinstance(value, Mentionable)
if isinstance(value, RecursiveMentionable): if isinstance(value, RecursiveMentionable):
return await value.str(tab) return await value.str(tab)
else: else:

View File

@ -9,6 +9,7 @@ Mentioned = TypeVar('Mentioned')
class Origin(Generic[Mentioned]): class Origin(Generic[Mentioned]):
def __init__(self, factory: RainbowFactory[Mentioned]): def __init__(self, factory: RainbowFactory[Mentioned]):
assert isinstance(factory, RainbowFactory)
self.factory = factory self.factory = factory
async def resolve(self) -> Mentioned: async def resolve(self) -> Mentioned:

View File

@ -25,6 +25,7 @@ class StaticMentionable(Mentionable, abc.ABC):
class StaticFactory(RainbowFactory[StaticMentioned], Generic[StaticMentioned]): class StaticFactory(RainbowFactory[StaticMentioned], Generic[StaticMentioned]):
def __init__(self, cls: Type[StaticMentioned]): def __init__(self, cls: Type[StaticMentioned]):
assert issubclass(cls, StaticMentionable)
self.cls: Type[StaticMentioned] = cls self.cls: Type[StaticMentioned] = cls
def from_bytes(self, source: bytes, resolver: HashResolver) -> StaticMentioned: def from_bytes(self, source: bytes, resolver: HashResolver) -> StaticMentioned:

View File

@ -26,6 +26,7 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]):
assert isinstance(decrypted, Mentionable) assert isinstance(decrypted, Mentionable)
self.factory: RainbowFactory[EncryptedType] = decrypted.__factory__() self.factory: RainbowFactory[EncryptedType] = decrypted.__factory__()
assert isinstance(self.factory, RainbowFactory)
self.key = key self.key = key
self.resolution = resolution self.resolution = resolution
@ -38,6 +39,7 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]):
@classmethod @classmethod
async def encrypt(cls, decrypted: EncryptedType, key: bytes) -> 'Encrypted[EncryptedType]': async def encrypt(cls, decrypted: EncryptedType, key: bytes) -> 'Encrypted[EncryptedType]':
assert isinstance(decrypted, Mentionable)
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( resolution = tuple(
@ -79,6 +81,10 @@ class Encrypted(RecursiveMentionable, Generic[EncryptedType]):
hashpoints: tuple[HashPoint, ...], hashpoints: tuple[HashPoint, ...],
decrypted: EncryptedType decrypted: EncryptedType
) -> 'Encrypted[EncryptedType]': ) -> 'Encrypted[EncryptedType]':
assert isinstance(key, bytes)
assert isinstance(resolution, tuple)
assert isinstance(hashpoints, tuple)
assert isinstance(decrypted, Mentionable)
mapping: dict[bytes, HashPoint[Encrypted]] = { mapping: dict[bytes, HashPoint[Encrypted]] = {
hash_point.point: encrypted for hash_point, encrypted in zip(hashpoints, resolution) 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:], plain[8 + resolution_size * HashPoint.HASH_LENGTH:],
resolver, resolver,
) )
assert isinstance(decrypted, Mentionable)
hashpoints = tuple(decrypted.points()) if isinstance(decrypted, RecursiveMentionable) else () hashpoints = tuple(decrypted.points()) if isinstance(decrypted, RecursiveMentionable) else ()
assert_eq(len(hashpoints), resolution_size) assert_eq(len(hashpoints), resolution_size)
resolution: tuple[HashPoint[Encrypted], ...] = tuple( resolution: tuple[HashPoint[Encrypted], ...] = tuple(
@ -152,6 +159,7 @@ class EncryptedResolver(HashResolver):
async def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']: async def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
assert isinstance(point, bytes) assert isinstance(point, bytes)
encrypted: Encrypted = await self.mapping[point].resolve() encrypted: Encrypted = await self.mapping[point].resolve()
assert isinstance(encrypted, Encrypted)
return HashPoint.bytes_of_mentioned(encrypted.decrypted), EncryptedResolver(encrypted.mapping, self.key) 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]: async def resolve(self) -> Encrypted[EncryptedType]:
source: Encrypted = await self.hashpoint.resolve() source: Encrypted = await self.hashpoint.resolve()
assert isinstance(source, Encrypted)
encrypted: Encrypted[EncryptedType] = self.factory.from_bytes(bytes(source), ShortcutResolver(source)) encrypted: Encrypted[EncryptedType] = self.factory.from_bytes(bytes(source), ShortcutResolver(source))
assert isinstance(encrypted, Encrypted)
assert_eq(HashPoint.of(encrypted), self.hashpoint) assert_eq(HashPoint.of(encrypted), self.hashpoint)
return encrypted return encrypted
@ -188,6 +198,7 @@ class ShortcutResolver(HashResolver):
async def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']: async def resolve(self, point: bytes) -> tuple[bytes, 'HashResolver']:
assert isinstance(point, bytes) assert isinstance(point, bytes)
resolved: Encrypted = await self.mapping[point].resolve() resolved: Encrypted = await self.mapping[point].resolve()
assert isinstance(resolved, Encrypted)
return ( return (
HashPoint.bytes_of_mentioned(resolved), HashPoint.bytes_of_mentioned(resolved),
ShortcutResolver(resolved) ShortcutResolver(resolved)

View File

@ -41,9 +41,11 @@ class NullableReference(RecursiveMentionable, Generic[Referenced]):
@classmethod @classmethod
def off(cls, value: Referenced) -> 'NullableReference[Referenced]': def off(cls, value: Referenced) -> 'NullableReference[Referenced]':
assert isinstance(value, Mentionable)
return cls.of(HashPoint.of(value)) return cls.of(HashPoint.of(value))
async def str(self, tab: int) -> str: async def str(self, tab: int) -> str:
assert isinstance(tab, int)
if self.null(): if self.null():
return f'-' return f'-'
else: else:

View File

@ -1,17 +1,21 @@
import functools import functools
import time import time
from typing import Generic, TypeVar from contextlib import ExitStack
from typing import Callable, Generic, TypeVar
__all__ = ('Instrumentation', 'Counter', 'Concurrency',)
__all__ = ('Instrumentation', 'Counter', 'Concurrency', 'EntryExit',)
IType = TypeVar('IType') IType = TypeVar('IType')
class Instrumentation(Generic[IType]): class Instrumentation(Generic[IType]):
deinstrumentation = {} deinstrumentation = {}
method: Callable
wrap: Callable
def __init__(self, target, methodname: str): def __init__(self, target, methodname: str):
assert isinstance(methodname, str)
assert callable(getattr(target, methodname))
self.target = target self.target = target
self.methodname = methodname self.methodname = methodname
@ -21,6 +25,7 @@ class Instrumentation(Generic[IType]):
def __enter__(self: IType) -> IType: 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)
assert callable(self.method)
@functools.wraps(self.method) @functools.wraps(self.method)
def wrap(*args, **kwargs): def wrap(*args, **kwargs):
@ -45,9 +50,13 @@ class Instrumentation(Generic[IType]):
self.schedule_deinstrumentation() self.schedule_deinstrumentation()
self.deinstrument() self.deinstrument()
def enter(self: IType, stack: ExitStack) -> IType:
return stack.enter_context(self)
class Counter(Instrumentation): class Counter(Instrumentation):
def __init__(self, target, methodname: str): def __init__(self, target, methodname: str):
assert isinstance(methodname, str)
super().__init__(target, methodname) super().__init__(target, methodname)
self.counter = 0 self.counter = 0
@ -60,19 +69,39 @@ class Concurrency(Instrumentation):
start = time.time() start = time.time()
def __init__(self, target, methodname: str): def __init__(self, target, methodname: str):
assert isinstance(methodname, str)
super().__init__(target, methodname) super().__init__(target, methodname)
self.concurrency = 0 self.concurrency = 0
self.logs: list[tuple[float, int]] = [] self.log: list[tuple[float, int]] = []
def time(self) -> float: def time(self) -> float:
return time.time() - self.start return time.time() - self.start
def point(self) -> tuple[float, int]:
return self.time(), self.concurrency
async def instrument(self, method, *args, **kwargs): async def instrument(self, method, *args, **kwargs):
self.logs.append((self.time(), self.concurrency)) self.log.append(self.point())
self.concurrency += 1 self.concurrency += 1
self.logs.append((self.time(), self.concurrency)) self.log.append(self.point())
result = await method(*args, **kwargs) result = await method(*args, **kwargs)
self.logs.append((self.time(), self.concurrency)) self.log.append(self.point())
self.concurrency -= 1 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 return result

View File

@ -0,0 +1,4 @@
from .cachingresolver import CachingResolver
from .delayedresolver import DelayedResolver
from .dictresolver import DictResolver
from .failresolver import FailResolver

View 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

View File

@ -10,6 +10,8 @@ Mentioned = TypeVar('Mentioned')
class DelayedResolver(ExtendableResolver): class DelayedResolver(ExtendableResolver):
def __init__(self, resolver: HashResolver, delay: Callable[[], float]): def __init__(self, resolver: HashResolver, delay: Callable[[], float]):
assert isinstance(resolver, HashResolver)
assert callable(delay)
self.resolver = resolver self.resolver = resolver
self.delay = delay self.delay = delay
@ -20,9 +22,12 @@ class DelayedResolver(ExtendableResolver):
assert isinstance(point, bytes) assert isinstance(point, bytes)
await self.sleep() await self.sleep()
resolved, resolver = await self.resolver.resolve(point) resolved, resolver = await self.resolver.resolve(point)
assert isinstance(resolved, bytes)
assert isinstance(resolver, HashResolver)
return resolved, DelayedResolver(resolver, self.delay) return resolved, DelayedResolver(resolver, self.delay)
async def extend(self, hash_point: HashPoint[Mentioned]) -> ExtendableResolver: async def extend(self, hash_point: HashPoint[Mentioned]) -> ExtendableResolver:
assert isinstance(hash_point, HashPoint)
if isinstance(self.resolver, ExtendableResolver): if isinstance(self.resolver, ExtendableResolver):
return DelayedResolver(await self.resolver.extend(hash_point), self.delay) return DelayedResolver(await self.resolver.extend(hash_point), self.delay)
else: else:

View File

@ -30,5 +30,6 @@ class DictResolver(ExtendableResolver):
) )
async def extend(self, hash_point: HashPoint[Mentioned]) -> 'ExtendableResolver': async def extend(self, hash_point: HashPoint[Mentioned]) -> 'ExtendableResolver':
assert isinstance(hash_point, HashPoint)
await self.save(hash_point) await self.save(hash_point)
return self return self

View File

@ -16,9 +16,8 @@ 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 .instrumentation import * from .instrumentation import *
from .resolvers import *
class TestAll(unittest.IsolatedAsyncioTestCase): class TestAll(unittest.IsolatedAsyncioTestCase):

View File

@ -20,6 +20,7 @@ class ValidReference(RecursiveMentionable, Generic[Referenced]):
async def resolve(self) -> Referenced: async def resolve(self) -> Referenced:
referenced: Referenced = await self.reference.resolve() referenced: Referenced = await self.reference.resolve()
assert isinstance(referenced, Mentionable)
assert self.reference.point < (await self.protocol.threshold(referenced)) assert self.reference.point < (await self.protocol.threshold(referenced))
return referenced return referenced

View File

@ -104,8 +104,11 @@ class BankState(RecursiveMentionable, StaticMentionable):
self, self,
transaction: Transaction transaction: Transaction
) -> 'BankState': ) -> 'BankState':
assert isinstance(transaction, Transaction)
miner = self.miner_nullable() miner = self.miner_nullable()
assert isinstance(miner, Nullable)
minted: ActiveBinaryTree[Coin, Integer] = self.minted_tree() minted: ActiveBinaryTree[Coin, Integer] = self.minted_tree()
assert isinstance(minted, ActiveBinaryTree)
async for coin, miner in transaction.iter_coins(self.mint(), miner): async for coin, miner in transaction.iter_coins(self.mint(), miner):
minted_contains, minted = await gather( minted_contains, minted = await gather(
minted.contains(HashPoint.of(coin)), minted.contains(HashPoint.of(coin)),
@ -119,11 +122,13 @@ class BankState(RecursiveMentionable, StaticMentionable):
self, self,
transaction: Transaction transaction: Transaction
) -> 'BankState': ) -> 'BankState':
assert isinstance(transaction, Transaction)
verified, bank_state = await gather( verified, bank_state = await gather(
self.verify(transaction), self.verify(transaction),
self._mint_coins(transaction), self._mint_coins(transaction),
) )
assert_true(verified) assert_true(verified)
assert isinstance(bank_state, BankState)
return bank_state return bank_state
def miner_nullable(self) -> Nullable[HashPoint[Subject]]: def miner_nullable(self) -> Nullable[HashPoint[Subject]]:
@ -161,6 +166,10 @@ class BankState(RecursiveMentionable, StaticMentionable):
self.used.str(tab + 1), self.used.str(tab + 1),
hash_point_format(self.length, 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'(' \ return f'(' \
f'{tabulate(tab + 1)}bank' \ f'{tabulate(tab + 1)}bank' \
f'{tabulate(tab + 1)}(miner)' \ f'{tabulate(tab + 1)}(miner)' \

View File

@ -53,6 +53,8 @@ class CoinData(RecursiveMentionable, StaticMentionable):
hash_point_format(self.owner, tab), hash_point_format(self.owner, tab),
hash_point_format(self.value, tab), hash_point_format(self.value, tab),
) )
assert isinstance(owner_str, str)
assert isinstance(value_str, str)
return f'{owner_str}' \ return f'{owner_str}' \
f'{tabulate(tab)}{value_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.data, tab + 1),
hash_point_format(self.index, tab + 1), hash_point_format(self.index, tab + 1),
) )
assert isinstance(data_str, str)
assert isinstance(index_str, str)
return f'(' \ return f'(' \
f'{tabulate(tab + 1)}coin' \ f'{tabulate(tab + 1)}coin' \
f'{tabulate(tab + 1)}{data_str}' \ f'{tabulate(tab + 1)}{data_str}' \
@ -145,6 +149,8 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
) )
async def _signature_verify(self, coin: Coin, signature: Signature) -> bool: async def _signature_verify(self, coin: Coin, signature: Signature) -> bool:
assert isinstance(coin, Coin)
assert isinstance(signature, Signature)
assert_true( assert_true(
signature.verify( signature.verify(
await coin.owner_resolved(), await coin.owner_resolved(),
@ -157,6 +163,7 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
self, self,
signatures: NullableReference[Stack[Signature]] signatures: NullableReference[Stack[Signature]]
) -> bool: ) -> bool:
assert isinstance(signatures, NullableReference)
assert_trues( assert_trues(
await gather( await gather(
*[ *[
@ -207,6 +214,8 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
self._total_in(), self._total_in(),
self._total_out(), self._total_out(),
) )
assert isinstance(total_in, int)
assert isinstance(total_out, int)
return total_in + mint - total_out return total_in + mint - total_out
async def verify( async def verify(
@ -230,6 +239,8 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
self.in_coins.str(tab), self.in_coins.str(tab),
self.out_coins.str(tab), self.out_coins.str(tab),
) )
assert isinstance(in_str, str)
assert isinstance(out_str, str)
return f'(in)' \ return f'(in)' \
f'{tabulate(tab)}{in_str}' \ f'{tabulate(tab)}{in_str}' \
f'{tabulate(tab)}(out)' \ f'{tabulate(tab)}(out)' \
@ -276,6 +287,8 @@ class Transaction(RecursiveMentionable, StaticMentionable):
mint: int, mint: int,
miner: Nullable[HashPoint[Subject]] miner: Nullable[HashPoint[Subject]]
) -> AsyncIterable[tuple[Coin, Nullable[HashPoint[Subject]]]]: ) -> AsyncIterable[tuple[Coin, Nullable[HashPoint[Subject]]]]:
assert isinstance(mint, int)
assert isinstance(miner, Nullable)
transaction_data: TransactionData = await self.data_resolved() transaction_data: TransactionData = await self.data_resolved()
assert isinstance(transaction_data, TransactionData) assert isinstance(transaction_data, TransactionData)
index = 0 index = 0
@ -325,6 +338,8 @@ class Transaction(RecursiveMentionable, StaticMentionable):
hash_point_format(self.data, tab + 1), hash_point_format(self.data, tab + 1),
self.signatures.str(tab + 1), self.signatures.str(tab + 1),
) )
assert isinstance(data_str, str)
assert isinstance(signatures_str, str)
return f'(' \ return f'(' \
f'{tabulate(tab + 1)}transaction' \ f'{tabulate(tab + 1)}transaction' \
f'{tabulate(tab + 1)}{data_str}' \ f'{tabulate(tab + 1)}{data_str}' \
@ -338,6 +353,9 @@ class Transaction(RecursiveMentionable, StaticMentionable):
out_coins: list[CoinData], out_coins: list[CoinData],
keys: list[nacl.signing.SigningKey], keys: list[nacl.signing.SigningKey],
) -> 'Transaction': ) -> 'Transaction':
assert isinstance(in_coins, list)
assert isinstance(out_coins, list)
assert isinstance(keys, list)
transaction_data = TransactionData( transaction_data = TransactionData(
Stack.off(Coin.factory(), reversed(in_coins)), Stack.off(Coin.factory(), reversed(in_coins)),
Stack.off(CoinData.factory(), reversed(out_coins)), Stack.off(CoinData.factory(), reversed(out_coins)),

View File

@ -271,12 +271,19 @@ class WeakReferenceIndexSetBTree(RecursiveMentionable):
for key_index in range(self.keys): for key_index in range(self.keys):
yield self.key_no(key_index) yield self.key_no(key_index)
else: 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): for index in range(self.keys * 2 + 1):
real_index, mode = divmod(index, 2) real_index, mode = divmod(index, 2)
if mode: if mode:
yield self.key_no(real_index) yield self.key_no(real_index)
else: 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 yield key

106
trace.py Normal file
View 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())