From 87c3292d6240c0319501ef42ee595a11ab2b568f Mon Sep 17 00:00:00 2001 From: timotheyca Date: Wed, 27 Jul 2022 16:12:41 +0300 Subject: [PATCH] key-value inlining and correct verification --- rainbowadn/collection/keyvalue.py | 74 ++++++++++----------------- rainbowadn/core/hashpoint.py | 3 ++ rainbowadn/flow13/_flowbank.py | 9 ++-- rainbowadn/flow13/_flowblock.py | 7 ++- rainbowadn/flow13/_flowcheque.py | 57 +++++++++++++-------- rainbowadn/flow13/_flowstandard.py | 29 +++++++---- rainbowadn/flow13/_flowtransaction.py | 38 +++++++++----- rainbowadn/instrument/__init__.py | 2 + rainbowadn/instrument/classreport.py | 40 +++++++++++++++ trace_flow.py | 62 +++++++++++++++++----- 10 files changed, 212 insertions(+), 109 deletions(-) create mode 100644 rainbowadn/instrument/classreport.py diff --git a/rainbowadn/collection/keyvalue.py b/rainbowadn/collection/keyvalue.py index 5112af3..0fd4b6e 100644 --- a/rainbowadn/collection/keyvalue.py +++ b/rainbowadn/collection/keyvalue.py @@ -1,59 +1,41 @@ -from typing import Generic, Iterable, TypeVar +from typing import Generic, TypeVar from rainbowadn.core import * +from rainbowadn.inlining import * from .keyed import * -__all__ = ('KeyValue', 'KeyValueFactory',) +__all__ = ('KeyValue',) KVKeyType = TypeVar('KVKeyType') KVValueType = TypeVar('KVValueType') -class KeyValue(Keyed[KVKeyType], Generic[KVKeyType, KVValueType]): - def __init__(self, key: HashPoint[KVKeyType], value: HashPoint[KVValueType]): +class KeyValue(Keyed[KVKeyType], IAuto, Generic[KVKeyType, KVValueType]): + value: HashPoint[KVValueType] + + def __init__(self, *args): + IAuto.__init__(self, *args) + key, self.value = self.hashpoints() + Keyed.__init__(self, key) + + @classmethod + async def off( + cls, key: HashPoint[KVKeyType], value: HashPoint[KVValueType] + ) -> 'KeyValue[KVKeyType, KVValueType]': assert isinstance(key, HashPoint) assert isinstance(value, HashPoint) - super().__init__(key) - self.value = value + return await cls.from_hashpoints(key, value) - def points(self) -> Iterable[HashPoint]: - return [self.key, self.value] + @classmethod + def of(cls, vk: KVKeyType, vv: KVValueType) -> 'KeyValue[KVKeyType, KVValueType]': + assert isinstance(vk, Mentionable) + assert isinstance(vv, Mentionable) + return cls.from_values(vk, vv) - def __bytes__(self): - return bytes(self.key) + bytes(self.value) - - def __factory__(self) -> RainbowFactory['KeyValue[KVKeyType, KVValueType]']: - return KeyValueFactory(self.key.factory, self.value.factory) - - async def str(self, tab: int) -> str: - assert isinstance(tab, int) - key_str, value_str = await gather( - hash_point_format(self.key, tab), - hash_point_format(self.value, tab) - ) - assert isinstance(key_str, str) - assert isinstance(value_str, str) - return f'{key_str}' \ - f'{tabulate(tab)}{value_str}' - - -class KeyValueFactory( - RainbowFactory[KeyValue[KVKeyType, KVValueType]], - Generic[KVKeyType, KVValueType] -): - def __init__(self, key_factory: RainbowFactory[KVKeyType], value_factory: RainbowFactory[KVValueType]): - assert isinstance(key_factory, RainbowFactory) - assert isinstance(value_factory, RainbowFactory) - self.key_factory = key_factory - self.value_factory = value_factory - - def from_bytes(self, source: bytes, resolver: HashResolver) -> KeyValue[KVKeyType, KVValueType]: - assert isinstance(source, bytes) - assert isinstance(resolver, HashResolver) - return KeyValue( - ResolverOrigin(self.key_factory, source[:HashPoint.HASH_LENGTH], resolver).hash_point(), - ResolverOrigin(self.value_factory, source[HashPoint.HASH_LENGTH:], resolver).hash_point(), - ) - - def loose(self) -> RainbowFactory[KeyValue[KVKeyType, KVValueType]]: - return self + @classmethod + def f( + cls, f0: RainbowFactory[KVKeyType], f1: RainbowFactory[KVValueType] + ) -> RainbowFactory['KeyValue[KVKeyType, KVValueType]']: + assert isinstance(f0, RainbowFactory) + assert isinstance(f1, RainbowFactory) + return cls.factory(f0, f1) diff --git a/rainbowadn/core/hashpoint.py b/rainbowadn/core/hashpoint.py index 225b33d..64b3e6d 100644 --- a/rainbowadn/core/hashpoint.py +++ b/rainbowadn/core/hashpoint.py @@ -42,6 +42,9 @@ class HashPoint(Generic[Mentioned]): assert isinstance(source, bytes) return _hash(source) + def __hash__(self): + return hash(self.point) + @classmethod def bytes_of_mentioned(cls, mentioned: Mentionable) -> bytes: assert isinstance(mentioned, Mentionable) diff --git a/rainbowadn/flow13/_flowbank.py b/rainbowadn/flow13/_flowbank.py index 0acbec1..69c965a 100644 --- a/rainbowadn/flow13/_flowbank.py +++ b/rainbowadn/flow13/_flowbank.py @@ -1,5 +1,6 @@ from typing import Iterable +from rainbowadn.collection.comparison import * from rainbowadn.core import * from ._flowstandard import * from ._flowtransaction import * @@ -11,10 +12,10 @@ class FlowBank(StaticMentionable, RecursiveMentionable): @classmethod def from_bytes(cls, source: bytes, resolver: HashResolver) -> 'FlowBank': return FlowBank( - FlowStandardFactory.of(FlowCoin.factory()).from_bytes( + FlowStandardFactory.of(FlowCoin.factory(), HashComparator(Fail())).from_bytes( source[:HashPoint.HASH_LENGTH], resolver ), - FlowStandardFactory.of(FlowCoin.factory()).from_bytes( + FlowStandardFactory.of(FlowCoin.factory(), HashComparator(Fail())).from_bytes( source[HashPoint.HASH_LENGTH:], resolver ), ) @@ -38,8 +39,8 @@ class FlowBank(StaticMentionable, RecursiveMentionable): @classmethod def empty(cls) -> 'FlowBank': return FlowBank( - FlowStandardFactory.empty(FlowCoin.factory()), - FlowStandardFactory.empty(FlowCoin.factory()), + FlowStandardFactory.empty(FlowCoin.factory(), HashComparator(Fail())), + FlowStandardFactory.empty(FlowCoin.factory(), HashComparator(Fail())), ) async def str(self, tab: int) -> str: diff --git a/rainbowadn/flow13/_flowblock.py b/rainbowadn/flow13/_flowblock.py index 81b3ce7..2b49768 100644 --- a/rainbowadn/flow13/_flowblock.py +++ b/rainbowadn/flow13/_flowblock.py @@ -1,5 +1,6 @@ from typing import Generic, Iterable, TypeAlias, TypeVar +from rainbowadn.collection.comparison import * from rainbowadn.core import * from rainbowadn.flow.verification.core import * from rainbowadn.nullability import * @@ -51,7 +52,7 @@ class FlowBlock(Generic[LinkT], RecursiveMentionable): @classmethod async def outer_of(cls, factory: RainbowFactory[LinkT], reference: NullableReference[FBL]) -> Index: if reference.null(): - return FlowStandardFactory.empty(FlowBlockFactory(factory)) + return FlowStandardFactory.empty(FlowBlockFactory(factory), HashComparator(Fail())) else: return await (await reference.resolve()).outer() @@ -102,7 +103,9 @@ class FlowBlockFactory(RainbowFactory[FBL], Generic[LinkT]): assert isinstance(resolver, HashResolver) return FlowBlock( NullableReferenceFactory(self).from_bytes(source[:HashPoint.HASH_LENGTH], resolver), - FlowStandardFactory.of(self).from_bytes(source[HashPoint.HASH_LENGTH:2 * HashPoint.HASH_LENGTH], resolver), + FlowStandardFactory.of(self, HashComparator(Fail())).from_bytes( + source[HashPoint.HASH_LENGTH:2 * HashPoint.HASH_LENGTH], resolver + ), ResolverOrigin(self.factory, source[2 * HashPoint.HASH_LENGTH:], resolver).hash_point(), ) diff --git a/rainbowadn/flow13/_flowcheque.py b/rainbowadn/flow13/_flowcheque.py index 659f4c7..7ce311c 100644 --- a/rainbowadn/flow13/_flowcheque.py +++ b/rainbowadn/flow13/_flowcheque.py @@ -1,6 +1,7 @@ import itertools from typing import Iterable +from rainbowadn.collection.comparison import * from rainbowadn.collection.keyvalue import * from rainbowadn.core import * from rainbowadn.flow.core import * @@ -29,16 +30,19 @@ class FlowCheque(StaticMentionable, RecursiveMentionable): @classmethod def from_bytes(cls, source: bytes, resolver: HashResolver) -> 'FlowCheque': return FlowCheque( - FlowStandardFactory.of(FlowTransaction.factory()).from_bytes( + FlowStandardFactory.of(FlowTransaction.factory(), HashComparator(Fail())).from_bytes( source[:HashPoint.HASH_LENGTH], resolver ), - FlowStandardFactory.of(FlowCoin.factory()).from_bytes( + FlowStandardFactory.of(FlowCoin.factory(), HashComparator(Fail())).from_bytes( source[HashPoint.HASH_LENGTH:2 * HashPoint.HASH_LENGTH], resolver ), - FlowStandardFactory.of(FlowCoin.factory()).from_bytes( + FlowStandardFactory.of(FlowCoin.factory(), HashComparator(Fail())).from_bytes( source[2 * HashPoint.HASH_LENGTH:3 * HashPoint.HASH_LENGTH], resolver ), - FlowStandardFactory.of(KeyValueFactory(FlowCoin.factory(), FlowTransaction.factory()).loose()).from_bytes( + FlowStandardFactory.of( + KeyValue.f(FlowCoin.factory(), FlowTransaction.factory()), + KeyedComparator(HashComparator(Fail())) + ).from_bytes( source[3 * HashPoint.HASH_LENGTH:], resolver ), ) @@ -152,7 +156,7 @@ class FlowCheque(StaticMentionable, RecursiveMentionable): async def _transaction_usedx(cls, transaction: FlowTransaction) -> Iterable[KeyValue[FlowCoin, FlowTransaction]]: assert isinstance(transaction, FlowTransaction) return ( - KeyValue(HashPoint.of(coin), HashPoint.of(transaction)) + KeyValue.of(coin, transaction) for coin in @@ -162,7 +166,9 @@ class FlowCheque(StaticMentionable, RecursiveMentionable): @classmethod async def _make_minted(cls, transactions: Iterable[FlowTransaction]) -> FlowStandard[FlowCoin]: return await FlowStandardFactory.off( - FlowCoin.factory(), itertools.chain( + FlowCoin.factory(), + HashComparator(Fail()), + itertools.chain( *(await gather(*(cls._transaction_minted(transaction) for transaction in transactions))) ) ) @@ -170,9 +176,11 @@ class FlowCheque(StaticMentionable, RecursiveMentionable): @classmethod async def _make_used(cls, transactions: Iterable[FlowTransaction]) -> FlowStandard[FlowCoin]: return await FlowStandardFactory.off( - FlowCoin.factory(), itertools.chain( + FlowCoin.factory(), + HashComparator(Fail()), + itertools.chain( *(await gather(*(cls._transaction_used(transaction) for transaction in transactions))) - ) + ), ) @classmethod @@ -181,7 +189,9 @@ class FlowCheque(StaticMentionable, RecursiveMentionable): transactions: Iterable[FlowTransaction] ) -> FlowStandard[KeyValue[FlowCoin, FlowTransaction]]: return await FlowStandardFactory.off( - KeyValueFactory(FlowCoin.factory(), FlowTransaction.factory()).loose(), itertools.chain( + KeyValue.f(FlowCoin.factory(), FlowTransaction.factory()), + KeyedComparator(HashComparator(Fail())), + itertools.chain( *(await gather(*(cls._transaction_usedx(transaction) for transaction in transactions))) ) ) @@ -193,7 +203,7 @@ class FlowCheque(StaticMentionable, RecursiveMentionable): used: FlowStandard[FlowCoin] usedx: FlowStandard[KeyValue[FlowCoin, FlowTransaction]] transactions_standard, minted, used, usedx = await gather( - FlowStandardFactory.off(FlowTransaction.factory(), transactions), + FlowStandardFactory.off(FlowTransaction.factory(), HashComparator(Fail()), transactions), cls._make_minted(transactions), cls._make_used(transactions), cls._make_usedx(transactions), @@ -220,6 +230,20 @@ class FlowCheque(StaticMentionable, RecursiveMentionable): f'{tabulate(tab)})' +class UsedxMapper(Mapper[HashPoint[FlowCoin], HashPoint[KeyValue[FlowCoin, FlowTransaction]]]): + def __init__(self, transaction: HashPoint[FlowTransaction]): + assert isinstance(transaction, HashPoint) + self.transaction = transaction + + async def map(self, element: HashPoint[FlowCoin]) -> HashPoint[KeyValue[FlowCoin, FlowTransaction]]: + return HashPoint.of( + await KeyValue.off( + element, + self.transaction + ) + ) + + class TransactionVerification( Verification[HashPoint[FlowTransaction]] ): @@ -236,17 +260,8 @@ class TransactionVerification( assert isinstance(reducer, Reducer) assert isinstance(transaction, HashPoint) - def usedx(coin: HashPoint[FlowCoin]) -> HashPoint[KeyValue[FlowCoin, FlowTransaction]]: - assert isinstance(coin, HashPoint) - return HashPoint.of( - KeyValue( - coin, - transaction - ) - ) - usedx_reducer: Reducer[HashPoint[KeyValue[FlowCoin, FlowTransaction]], bool] = MapReducer( - CallableMapper(usedx), + UsedxMapper(transaction), reducer ) assert isinstance(usedx_reducer, Reducer) @@ -328,7 +343,7 @@ class UsedVerification( assert isinstance(element, HashPoint) assert_true( await self.cheque.usedx.contains( - HashPoint.of(KeyValue(element, HashPoint.of(FlowTransaction.empty()))) + HashPoint.of(await KeyValue.off(element, HashPoint.of(FlowTransaction.empty()))) ) ) return True diff --git a/rainbowadn/flow13/_flowstandard.py b/rainbowadn/flow13/_flowstandard.py index 7837a30..09c02bb 100644 --- a/rainbowadn/flow13/_flowstandard.py +++ b/rainbowadn/flow13/_flowstandard.py @@ -34,7 +34,8 @@ class FlowStandard( def __factory__(self) -> RainbowFactory['FlowStandard[KeyT]']: return FlowStandardFactory( - self.protocolized.tree.reference.factory + self.protocolized.tree.reference.factory, + self.protocolized.creation.comparator ) def __init__(self, protocolized: BP): @@ -84,35 +85,41 @@ class FlowStandard( class FlowStandardFactory(RainbowFactory[FlowStandard[KeyT]], Generic[KeyT]): def __init__( self, - factory: RainbowFactory[BinaryTree[KeyMetadata[KeyT, Integer]]] + factory: RainbowFactory[BinaryTree[KeyMetadata[KeyT, Integer]]], + comparator: Comparator[KeyT] ): assert isinstance(factory, RainbowFactory) + assert isinstance(comparator, Comparator) self.factory = factory + self.comparator = comparator @classmethod - def of(cls, factory: RainbowFactory[KeyT]) -> 'FlowStandardFactory[KeyT]': + def of(cls, factory: RainbowFactory[KeyT], comparator: Comparator[KeyT]) -> 'FlowStandardFactory[KeyT]': assert isinstance(factory, RainbowFactory) return FlowStandardFactory( - BinaryTreeFactory(KeyMetadataFactory(factory, Integer.factory())) + BinaryTreeFactory(KeyMetadataFactory(factory, Integer.factory())), + comparator ) @classmethod - async def off(cls, factory: RainbowFactory[KeyT], keys: Iterable[KeyT]) -> 'FlowStandard[KeyT]': + async def off( + cls, factory: RainbowFactory[KeyT], comparator: Comparator[KeyT], keys: Iterable[KeyT] + ) -> 'FlowStandard[KeyT]': assert isinstance(factory, RainbowFactory) - abt: ActiveBinaryTree[KeyT, Integer] = cls.empty(factory).protocolized.tree + abt: ActiveBinaryTree[KeyT, Integer] = cls.empty(factory, comparator).protocolized.tree for key in keys: abt = await abt.add(HashPoint.of(key)) return FlowStandard(abt.protocolized()) @classmethod - def protocol(cls) -> BinaryBalancing[KeyT, Integer, ABT]: - return AVL(HashComparator(Fail())) + def protocol(cls, comparator: Comparator[KeyT]) -> BinaryBalancing[KeyT, Integer, ABT]: + return AVL(comparator) @classmethod - def empty(cls, factory: RainbowFactory[KeyT]) -> 'FlowStandard[KeyT]': + def empty(cls, factory: RainbowFactory[KeyT], comparator: Comparator[KeyT]) -> 'FlowStandard[KeyT]': assert isinstance(factory, RainbowFactory) return FlowStandard( - ActiveBinaryTree.empty(cls.protocol(), factory).protocolized() + ActiveBinaryTree.empty(cls.protocol(comparator), factory).protocolized() ) def from_bytes(self, source: bytes, resolver: HashResolver) -> FlowStandard[KeyT]: @@ -120,7 +127,7 @@ class FlowStandardFactory(RainbowFactory[FlowStandard[KeyT]], Generic[KeyT]): assert isinstance(resolver, HashResolver) return FlowStandard( ActiveBinaryTree( - self.protocol(), + self.protocol(self.comparator), NullableReferenceFactory(self.factory).from_bytes(source, resolver) ).protocolized() ) diff --git a/rainbowadn/flow13/_flowtransaction.py b/rainbowadn/flow13/_flowtransaction.py index b15e4b6..0c49619 100644 --- a/rainbowadn/flow13/_flowtransaction.py +++ b/rainbowadn/flow13/_flowtransaction.py @@ -3,6 +3,7 @@ from typing import Any, Iterable from nacl.signing import SigningKey from rainbowadn.atomic import * +from rainbowadn.collection.comparison import * from rainbowadn.collection.keyvalue import * from rainbowadn.core import * from rainbowadn.flow.core import * @@ -132,8 +133,12 @@ class FlowTransactionData(RecursiveMentionable, StaticMentionable): assert isinstance(resolver, HashResolver) return cls( - FlowStandardFactory.of(FlowCoin.factory()).from_bytes(source[:HashPoint.HASH_LENGTH], resolver), - FlowStandardFactory.of(FlowCoinData.factory()).from_bytes(source[HashPoint.HASH_LENGTH:], resolver), + FlowStandardFactory.of( + FlowCoin.factory(), HashComparator(Fail()) + ).from_bytes(source[:HashPoint.HASH_LENGTH], resolver), + FlowStandardFactory.of( + FlowCoinData.factory(), HashComparator(Fail()) + ).from_bytes(source[HashPoint.HASH_LENGTH:], resolver), ) async def _signature_verify(self, coin: FlowCoin, signature: Signature) -> bool: @@ -229,8 +234,8 @@ class FlowTransactionData(RecursiveMentionable, StaticMentionable): @classmethod def empty(cls) -> 'FlowTransactionData': return cls( - FlowStandardFactory.empty(FlowCoin.factory()), - FlowStandardFactory.empty(FlowCoinData.factory()), + FlowStandardFactory.empty(FlowCoin.factory(), HashComparator(Fail())), + FlowStandardFactory.empty(FlowCoinData.factory(), HashComparator(Fail())), ) @@ -243,7 +248,7 @@ class CVMapper(Mapper[FlowCoin, bool]): assert isinstance(element, FlowCoin) assert_true( await self.signatures.contains( - HashPoint.of(KeyValue((await element.data.resolve()).owner, HashPoint.of(Signature.empty()))) + HashPoint.of(await KeyValue.off((await element.data.resolve()).owner, HashPoint.of(Signature.empty()))) ) ) return True @@ -302,7 +307,10 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable): assert isinstance(resolver, HashResolver) return cls( ResolverOrigin(FlowTransactionData.factory(), source[:HashPoint.HASH_LENGTH], resolver).hash_point(), - FlowStandardFactory.of(KeyValueFactory(Subject.factory(), Signature.factory()).loose()).from_bytes( + FlowStandardFactory.of( + KeyValue.f(Subject.factory(), Signature.factory()), + KeyedComparator(HashComparator(Fail())) + ).from_bytes( source[HashPoint.HASH_LENGTH:], resolver ), ) @@ -339,7 +347,9 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable): def empty(cls): return cls( HashPoint.of(FlowTransactionData.empty()), - FlowStandardFactory.empty(KeyValueFactory(Subject.factory(), Signature.factory()).loose()), + FlowStandardFactory.empty( + KeyValue.f(Subject.factory(), Signature.factory()), KeyedComparator(HashComparator(Fail())) + ), ) @classmethod @@ -352,8 +362,8 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable): used_std: FlowStandard[FlowCoin] minted_std: FlowStandard[FlowCoinData] used_std, minted_std = await gather( - FlowStandardFactory.off(FlowCoin.factory(), used), - FlowStandardFactory.off(FlowCoinData.factory(), minted), + FlowStandardFactory.off(FlowCoin.factory(), HashComparator(Fail()), used), + FlowStandardFactory.off(FlowCoinData.factory(), HashComparator(Fail()), minted), ) assert isinstance(used_std, FlowStandard) assert isinstance(minted_std, FlowStandard) @@ -362,9 +372,9 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable): minted_std, ) signatures: list[KeyValue[Subject, Signature]] = [ - KeyValue( - HashPoint.of(Subject(signing_key.verify_key)), - HashPoint.of(Signature.sign(signing_key, transaction_data.hash_point)), + KeyValue.of( + Subject(signing_key.verify_key), + Signature.sign(signing_key, transaction_data.hash_point), ) for signing_key @@ -373,5 +383,7 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable): ] return cls( HashPoint.of(transaction_data), - await FlowStandardFactory.off(KeyValueFactory(Subject.factory(), Signature.factory()).loose(), signatures) + await FlowStandardFactory.off( + KeyValue.f(Subject.factory(), Signature.factory()), KeyedComparator(HashComparator(Fail())), signatures + ) ) diff --git a/rainbowadn/instrument/__init__.py b/rainbowadn/instrument/__init__.py index 3ff3b66..c55f897 100644 --- a/rainbowadn/instrument/__init__.py +++ b/rainbowadn/instrument/__init__.py @@ -1,6 +1,7 @@ __all__ = ( 'Measure', 'Terminated', 'Terminate', + 'ClassReport', 'Concurrency', 'Counter', 'EntryExit', @@ -9,6 +10,7 @@ __all__ = ( from ._measure import Measure from ._terminate import Terminate, Terminated +from .classreport import ClassReport from .concurrency import Concurrency from .counter import Counter from .entryexit import EntryExit diff --git a/rainbowadn/instrument/classreport.py b/rainbowadn/instrument/classreport.py new file mode 100644 index 0000000..6d41e4d --- /dev/null +++ b/rainbowadn/instrument/classreport.py @@ -0,0 +1,40 @@ +from io import StringIO + +from rainbowadn.core import * + +__all__ = ('ClassReport',) + + +class ClassReport: + def __init__(self): + self.report: set[tuple[str, bytes, bytes]] = set() + + @classmethod + def _tuple(cls, mentionable: Mentionable) -> tuple[str, bytes, bytes]: + return type(mentionable).__name__, bytes(HashPoint.of(mentionable)), bytes(mentionable) + + def _cointains(self, mentionable: Mentionable) -> bool: + return self._tuple(mentionable) in self.report + + async def _recurse(self, recursive: RecursiveMentionable): + for mentioned in await gather(*map(HashPoint.resolve, recursive.points())): + await self.walk(mentioned) + + def _contain(self, mentionable: Mentionable) -> None: + self.report.add(self._tuple(mentionable)) + + async def _save(self, mentionable: Mentionable): + self._contain(mentionable) + if isinstance(mentionable, RecursiveMentionable): + await self._recurse(mentionable) + + async def walk(self, mentionable: Mentionable): + if self._cointains(mentionable): + return + await self._save(mentionable) + + def format(self) -> str: + s = StringIO() + for type_, point, bytes_ in sorted(self.report): + s.write(f'{type_:<32}:{point.hex()}:{bytes_.hex()}\n') + return s.getvalue() diff --git a/trace_flow.py b/trace_flow.py index 78a35f6..944d58e 100644 --- a/trace_flow.py +++ b/trace_flow.py @@ -3,12 +3,13 @@ import random from contextlib import ExitStack from typing import Any, Callable, Coroutine -from nacl.signing import SigningKey +from nacl.signing import SigningKey, VerifyKey from plot import * from rainbowadn.collection.trees.binary import * from rainbowadn.core import * from rainbowadn.flow13 import * +from rainbowadn.flow13 import FlowCoin from rainbowadn.instrument import * from rainbowadn.testing.resolvers import * from rainbowadn.v13 import * @@ -25,6 +26,42 @@ def get_instrumentations() -> list[Instrumentation]: ] +minted: set[HashPoint[FlowCoin]] = set() +reverse: dict[VerifyKey, SigningKey] = {} + + +def _generate_subject() -> Subject: + signing_key = SigningKey.generate() + verify_key = signing_key.verify_key + reverse[verify_key] = signing_key + return Subject(verify_key) + + +async def _generate_transaction( + subjects_min: int, + subjects_max: int, +): + in_coins: list[FlowCoin] = [] + keys: list[SigningKey] = [] + for _ in range(random.randint(subjects_min, subjects_max)): + if not minted: + break + coin = await minted.pop().resolve() + in_coins.append(coin) + keys.append(reverse[(await coin.owner_resolved()).verify_key]) + transaction = await FlowTransaction.make( + in_coins, + [ + FlowCoinData.of(_generate_subject(), 0) + for _ in range(random.randint(subjects_min, subjects_max)) + ], + keys + ) + for coinhp in await (await transaction.minted_reducer()).reduce(FlowIterate([])): + minted.add(coinhp) + return transaction + + async def _generate( blocks: int, subjects_min: int, @@ -37,14 +74,7 @@ async def _generate( bank = await bank.add( await FlowCheque.make( [ - await FlowTransaction.make( - [], - [ - FlowCoinData.of(Subject(SigningKey.generate().verify_key), 0) - for _ in range(random.randint(subjects_min, subjects_max)) - ], - [] - ) + await _generate_transaction(subjects_min, subjects_max) for _ in range(random.randint(transactions_min, transactions_max)) ] ) @@ -80,6 +110,14 @@ async def _process(bank: BankBlock) -> None: print('measured', *(f'{t:.3f}' for t in measurement.log)) +async def _report(bank: BankBlock): + with open('trace/latest-report.txt', 'w') as file: + report = ClassReport() + await report.walk(bank.reference) + file.write(report.format()) + print('reported') + + async def _trace(params): set_gather_linear() bank = await _generate( @@ -87,6 +125,7 @@ async def _trace(params): *params['subjects'], *params['transactions'], ) + await _report(bank) await _process(bank) bank = await _migrate(bank, params) set_gather_asyncio() @@ -108,9 +147,8 @@ async def trace(params): print('plotted') -preset_long = dict(blocks=64, subjects=(8, 16), transactions=(8, 16), caching=True, delay=.35) -preset_short = dict(blocks=16, subjects=(8, 16), transactions=(8, 16), caching=True, delay=.35) -preset_old = dict(blocks=16, subjects=(8, 15), transactions=(8, 15), caching=False, delay=.35) +preset_long = dict(blocks=64, subjects=(4, 8), transactions=(8, 16), caching=True, delay=.5) +preset_short = dict(blocks=16, subjects=(4, 8), transactions=(8, 16), caching=True, delay=.5) if __name__ == '__main__': asyncio.run(