key-value inlining and correct verification

This commit is contained in:
AF 2022-07-27 16:12:41 +03:00
parent 19ccb3a5a0
commit 87c3292d62
10 changed files with 212 additions and 109 deletions

View File

@ -1,59 +1,41 @@
from typing import Generic, Iterable, TypeVar from typing import Generic, TypeVar
from rainbowadn.core import * from rainbowadn.core import *
from rainbowadn.inlining import *
from .keyed import * from .keyed import *
__all__ = ('KeyValue', 'KeyValueFactory',) __all__ = ('KeyValue',)
KVKeyType = TypeVar('KVKeyType') KVKeyType = TypeVar('KVKeyType')
KVValueType = TypeVar('KVValueType') KVValueType = TypeVar('KVValueType')
class KeyValue(Keyed[KVKeyType], Generic[KVKeyType, KVValueType]): class KeyValue(Keyed[KVKeyType], IAuto, Generic[KVKeyType, KVValueType]):
def __init__(self, key: HashPoint[KVKeyType], value: HashPoint[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(key, HashPoint)
assert isinstance(value, HashPoint) assert isinstance(value, HashPoint)
super().__init__(key) return await cls.from_hashpoints(key, value)
self.value = value
def points(self) -> Iterable[HashPoint]: @classmethod
return [self.key, self.value] 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): @classmethod
return bytes(self.key) + bytes(self.value) def f(
cls, f0: RainbowFactory[KVKeyType], f1: RainbowFactory[KVValueType]
def __factory__(self) -> RainbowFactory['KeyValue[KVKeyType, KVValueType]']: ) -> RainbowFactory['KeyValue[KVKeyType, KVValueType]']:
return KeyValueFactory(self.key.factory, self.value.factory) assert isinstance(f0, RainbowFactory)
assert isinstance(f1, RainbowFactory)
async def str(self, tab: int) -> str: return cls.factory(f0, f1)
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

View File

@ -42,6 +42,9 @@ class HashPoint(Generic[Mentioned]):
assert isinstance(source, bytes) assert isinstance(source, bytes)
return _hash(source) return _hash(source)
def __hash__(self):
return hash(self.point)
@classmethod @classmethod
def bytes_of_mentioned(cls, mentioned: Mentionable) -> bytes: def bytes_of_mentioned(cls, mentioned: Mentionable) -> bytes:
assert isinstance(mentioned, Mentionable) assert isinstance(mentioned, Mentionable)

View File

@ -1,5 +1,6 @@
from typing import Iterable from typing import Iterable
from rainbowadn.collection.comparison import *
from rainbowadn.core import * from rainbowadn.core import *
from ._flowstandard import * from ._flowstandard import *
from ._flowtransaction import * from ._flowtransaction import *
@ -11,10 +12,10 @@ class FlowBank(StaticMentionable, RecursiveMentionable):
@classmethod @classmethod
def from_bytes(cls, source: bytes, resolver: HashResolver) -> 'FlowBank': def from_bytes(cls, source: bytes, resolver: HashResolver) -> 'FlowBank':
return FlowBank( return FlowBank(
FlowStandardFactory.of(FlowCoin.factory()).from_bytes( FlowStandardFactory.of(FlowCoin.factory(), HashComparator(Fail())).from_bytes(
source[:HashPoint.HASH_LENGTH], resolver source[:HashPoint.HASH_LENGTH], resolver
), ),
FlowStandardFactory.of(FlowCoin.factory()).from_bytes( FlowStandardFactory.of(FlowCoin.factory(), HashComparator(Fail())).from_bytes(
source[HashPoint.HASH_LENGTH:], resolver source[HashPoint.HASH_LENGTH:], resolver
), ),
) )
@ -38,8 +39,8 @@ class FlowBank(StaticMentionable, RecursiveMentionable):
@classmethod @classmethod
def empty(cls) -> 'FlowBank': def empty(cls) -> 'FlowBank':
return FlowBank( return FlowBank(
FlowStandardFactory.empty(FlowCoin.factory()), FlowStandardFactory.empty(FlowCoin.factory(), HashComparator(Fail())),
FlowStandardFactory.empty(FlowCoin.factory()), FlowStandardFactory.empty(FlowCoin.factory(), HashComparator(Fail())),
) )
async def str(self, tab: int) -> str: async def str(self, tab: int) -> str:

View File

@ -1,5 +1,6 @@
from typing import Generic, Iterable, TypeAlias, TypeVar from typing import Generic, Iterable, TypeAlias, TypeVar
from rainbowadn.collection.comparison import *
from rainbowadn.core import * from rainbowadn.core import *
from rainbowadn.flow.verification.core import * from rainbowadn.flow.verification.core import *
from rainbowadn.nullability import * from rainbowadn.nullability import *
@ -51,7 +52,7 @@ class FlowBlock(Generic[LinkT], RecursiveMentionable):
@classmethod @classmethod
async def outer_of(cls, factory: RainbowFactory[LinkT], reference: NullableReference[FBL]) -> Index: async def outer_of(cls, factory: RainbowFactory[LinkT], reference: NullableReference[FBL]) -> Index:
if reference.null(): if reference.null():
return FlowStandardFactory.empty(FlowBlockFactory(factory)) return FlowStandardFactory.empty(FlowBlockFactory(factory), HashComparator(Fail()))
else: else:
return await (await reference.resolve()).outer() return await (await reference.resolve()).outer()
@ -102,7 +103,9 @@ class FlowBlockFactory(RainbowFactory[FBL], Generic[LinkT]):
assert isinstance(resolver, HashResolver) assert isinstance(resolver, HashResolver)
return FlowBlock( return FlowBlock(
NullableReferenceFactory(self).from_bytes(source[:HashPoint.HASH_LENGTH], resolver), 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(), ResolverOrigin(self.factory, source[2 * HashPoint.HASH_LENGTH:], resolver).hash_point(),
) )

View File

@ -1,6 +1,7 @@
import itertools import itertools
from typing import Iterable from typing import Iterable
from rainbowadn.collection.comparison import *
from rainbowadn.collection.keyvalue import * from rainbowadn.collection.keyvalue import *
from rainbowadn.core import * from rainbowadn.core import *
from rainbowadn.flow.core import * from rainbowadn.flow.core import *
@ -29,16 +30,19 @@ class FlowCheque(StaticMentionable, RecursiveMentionable):
@classmethod @classmethod
def from_bytes(cls, source: bytes, resolver: HashResolver) -> 'FlowCheque': def from_bytes(cls, source: bytes, resolver: HashResolver) -> 'FlowCheque':
return FlowCheque( return FlowCheque(
FlowStandardFactory.of(FlowTransaction.factory()).from_bytes( FlowStandardFactory.of(FlowTransaction.factory(), HashComparator(Fail())).from_bytes(
source[:HashPoint.HASH_LENGTH], resolver 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 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 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 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]]: async def _transaction_usedx(cls, transaction: FlowTransaction) -> Iterable[KeyValue[FlowCoin, FlowTransaction]]:
assert isinstance(transaction, FlowTransaction) assert isinstance(transaction, FlowTransaction)
return ( return (
KeyValue(HashPoint.of(coin), HashPoint.of(transaction)) KeyValue.of(coin, transaction)
for for
coin coin
in in
@ -162,7 +166,9 @@ class FlowCheque(StaticMentionable, RecursiveMentionable):
@classmethod @classmethod
async def _make_minted(cls, transactions: Iterable[FlowTransaction]) -> FlowStandard[FlowCoin]: async def _make_minted(cls, transactions: Iterable[FlowTransaction]) -> FlowStandard[FlowCoin]:
return await FlowStandardFactory.off( return await FlowStandardFactory.off(
FlowCoin.factory(), itertools.chain( FlowCoin.factory(),
HashComparator(Fail()),
itertools.chain(
*(await gather(*(cls._transaction_minted(transaction) for transaction in transactions))) *(await gather(*(cls._transaction_minted(transaction) for transaction in transactions)))
) )
) )
@ -170,9 +176,11 @@ class FlowCheque(StaticMentionable, RecursiveMentionable):
@classmethod @classmethod
async def _make_used(cls, transactions: Iterable[FlowTransaction]) -> FlowStandard[FlowCoin]: async def _make_used(cls, transactions: Iterable[FlowTransaction]) -> FlowStandard[FlowCoin]:
return await FlowStandardFactory.off( return await FlowStandardFactory.off(
FlowCoin.factory(), itertools.chain( FlowCoin.factory(),
HashComparator(Fail()),
itertools.chain(
*(await gather(*(cls._transaction_used(transaction) for transaction in transactions))) *(await gather(*(cls._transaction_used(transaction) for transaction in transactions)))
) ),
) )
@classmethod @classmethod
@ -181,7 +189,9 @@ class FlowCheque(StaticMentionable, RecursiveMentionable):
transactions: Iterable[FlowTransaction] transactions: Iterable[FlowTransaction]
) -> FlowStandard[KeyValue[FlowCoin, FlowTransaction]]: ) -> FlowStandard[KeyValue[FlowCoin, FlowTransaction]]:
return await FlowStandardFactory.off( 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))) *(await gather(*(cls._transaction_usedx(transaction) for transaction in transactions)))
) )
) )
@ -193,7 +203,7 @@ class FlowCheque(StaticMentionable, RecursiveMentionable):
used: FlowStandard[FlowCoin] used: FlowStandard[FlowCoin]
usedx: FlowStandard[KeyValue[FlowCoin, FlowTransaction]] usedx: FlowStandard[KeyValue[FlowCoin, FlowTransaction]]
transactions_standard, minted, used, usedx = await gather( 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_minted(transactions),
cls._make_used(transactions), cls._make_used(transactions),
cls._make_usedx(transactions), cls._make_usedx(transactions),
@ -220,6 +230,20 @@ class FlowCheque(StaticMentionable, RecursiveMentionable):
f'{tabulate(tab)})' 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( class TransactionVerification(
Verification[HashPoint[FlowTransaction]] Verification[HashPoint[FlowTransaction]]
): ):
@ -236,17 +260,8 @@ class TransactionVerification(
assert isinstance(reducer, Reducer) assert isinstance(reducer, Reducer)
assert isinstance(transaction, HashPoint) 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( usedx_reducer: Reducer[HashPoint[KeyValue[FlowCoin, FlowTransaction]], bool] = MapReducer(
CallableMapper(usedx), UsedxMapper(transaction),
reducer reducer
) )
assert isinstance(usedx_reducer, Reducer) assert isinstance(usedx_reducer, Reducer)
@ -328,7 +343,7 @@ class UsedVerification(
assert isinstance(element, HashPoint) assert isinstance(element, HashPoint)
assert_true( assert_true(
await self.cheque.usedx.contains( 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 return True

View File

@ -34,7 +34,8 @@ class FlowStandard(
def __factory__(self) -> RainbowFactory['FlowStandard[KeyT]']: def __factory__(self) -> RainbowFactory['FlowStandard[KeyT]']:
return FlowStandardFactory( return FlowStandardFactory(
self.protocolized.tree.reference.factory self.protocolized.tree.reference.factory,
self.protocolized.creation.comparator
) )
def __init__(self, protocolized: BP): def __init__(self, protocolized: BP):
@ -84,35 +85,41 @@ class FlowStandard(
class FlowStandardFactory(RainbowFactory[FlowStandard[KeyT]], Generic[KeyT]): class FlowStandardFactory(RainbowFactory[FlowStandard[KeyT]], Generic[KeyT]):
def __init__( def __init__(
self, self,
factory: RainbowFactory[BinaryTree[KeyMetadata[KeyT, Integer]]] factory: RainbowFactory[BinaryTree[KeyMetadata[KeyT, Integer]]],
comparator: Comparator[KeyT]
): ):
assert isinstance(factory, RainbowFactory) assert isinstance(factory, RainbowFactory)
assert isinstance(comparator, Comparator)
self.factory = factory self.factory = factory
self.comparator = comparator
@classmethod @classmethod
def of(cls, factory: RainbowFactory[KeyT]) -> 'FlowStandardFactory[KeyT]': def of(cls, factory: RainbowFactory[KeyT], comparator: Comparator[KeyT]) -> 'FlowStandardFactory[KeyT]':
assert isinstance(factory, RainbowFactory) assert isinstance(factory, RainbowFactory)
return FlowStandardFactory( return FlowStandardFactory(
BinaryTreeFactory(KeyMetadataFactory(factory, Integer.factory())) BinaryTreeFactory(KeyMetadataFactory(factory, Integer.factory())),
comparator
) )
@classmethod @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) 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: for key in keys:
abt = await abt.add(HashPoint.of(key)) abt = await abt.add(HashPoint.of(key))
return FlowStandard(abt.protocolized()) return FlowStandard(abt.protocolized())
@classmethod @classmethod
def protocol(cls) -> BinaryBalancing[KeyT, Integer, ABT]: def protocol(cls, comparator: Comparator[KeyT]) -> BinaryBalancing[KeyT, Integer, ABT]:
return AVL(HashComparator(Fail())) return AVL(comparator)
@classmethod @classmethod
def empty(cls, factory: RainbowFactory[KeyT]) -> 'FlowStandard[KeyT]': def empty(cls, factory: RainbowFactory[KeyT], comparator: Comparator[KeyT]) -> 'FlowStandard[KeyT]':
assert isinstance(factory, RainbowFactory) assert isinstance(factory, RainbowFactory)
return FlowStandard( 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]: 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) assert isinstance(resolver, HashResolver)
return FlowStandard( return FlowStandard(
ActiveBinaryTree( ActiveBinaryTree(
self.protocol(), self.protocol(self.comparator),
NullableReferenceFactory(self.factory).from_bytes(source, resolver) NullableReferenceFactory(self.factory).from_bytes(source, resolver)
).protocolized() ).protocolized()
) )

View File

@ -3,6 +3,7 @@ from typing import Any, Iterable
from nacl.signing import SigningKey from nacl.signing import SigningKey
from rainbowadn.atomic import * from rainbowadn.atomic import *
from rainbowadn.collection.comparison import *
from rainbowadn.collection.keyvalue import * from rainbowadn.collection.keyvalue import *
from rainbowadn.core import * from rainbowadn.core import *
from rainbowadn.flow.core import * from rainbowadn.flow.core import *
@ -132,8 +133,12 @@ class FlowTransactionData(RecursiveMentionable, StaticMentionable):
assert isinstance(resolver, HashResolver) assert isinstance(resolver, HashResolver)
return cls( return cls(
FlowStandardFactory.of(FlowCoin.factory()).from_bytes(source[:HashPoint.HASH_LENGTH], resolver), FlowStandardFactory.of(
FlowStandardFactory.of(FlowCoinData.factory()).from_bytes(source[HashPoint.HASH_LENGTH:], resolver), 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: async def _signature_verify(self, coin: FlowCoin, signature: Signature) -> bool:
@ -229,8 +234,8 @@ class FlowTransactionData(RecursiveMentionable, StaticMentionable):
@classmethod @classmethod
def empty(cls) -> 'FlowTransactionData': def empty(cls) -> 'FlowTransactionData':
return cls( return cls(
FlowStandardFactory.empty(FlowCoin.factory()), FlowStandardFactory.empty(FlowCoin.factory(), HashComparator(Fail())),
FlowStandardFactory.empty(FlowCoinData.factory()), FlowStandardFactory.empty(FlowCoinData.factory(), HashComparator(Fail())),
) )
@ -243,7 +248,7 @@ class CVMapper(Mapper[FlowCoin, bool]):
assert isinstance(element, FlowCoin) assert isinstance(element, FlowCoin)
assert_true( assert_true(
await self.signatures.contains( 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 return True
@ -302,7 +307,10 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable):
assert isinstance(resolver, HashResolver) assert isinstance(resolver, HashResolver)
return cls( return cls(
ResolverOrigin(FlowTransactionData.factory(), source[:HashPoint.HASH_LENGTH], resolver).hash_point(), 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 source[HashPoint.HASH_LENGTH:], resolver
), ),
) )
@ -339,7 +347,9 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable):
def empty(cls): def empty(cls):
return cls( return cls(
HashPoint.of(FlowTransactionData.empty()), HashPoint.of(FlowTransactionData.empty()),
FlowStandardFactory.empty(KeyValueFactory(Subject.factory(), Signature.factory()).loose()), FlowStandardFactory.empty(
KeyValue.f(Subject.factory(), Signature.factory()), KeyedComparator(HashComparator(Fail()))
),
) )
@classmethod @classmethod
@ -352,8 +362,8 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable):
used_std: FlowStandard[FlowCoin] used_std: FlowStandard[FlowCoin]
minted_std: FlowStandard[FlowCoinData] minted_std: FlowStandard[FlowCoinData]
used_std, minted_std = await gather( used_std, minted_std = await gather(
FlowStandardFactory.off(FlowCoin.factory(), used), FlowStandardFactory.off(FlowCoin.factory(), HashComparator(Fail()), used),
FlowStandardFactory.off(FlowCoinData.factory(), minted), FlowStandardFactory.off(FlowCoinData.factory(), HashComparator(Fail()), minted),
) )
assert isinstance(used_std, FlowStandard) assert isinstance(used_std, FlowStandard)
assert isinstance(minted_std, FlowStandard) assert isinstance(minted_std, FlowStandard)
@ -362,9 +372,9 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable):
minted_std, minted_std,
) )
signatures: list[KeyValue[Subject, Signature]] = [ signatures: list[KeyValue[Subject, Signature]] = [
KeyValue( KeyValue.of(
HashPoint.of(Subject(signing_key.verify_key)), Subject(signing_key.verify_key),
HashPoint.of(Signature.sign(signing_key, transaction_data.hash_point)), Signature.sign(signing_key, transaction_data.hash_point),
) )
for for
signing_key signing_key
@ -373,5 +383,7 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable):
] ]
return cls( return cls(
HashPoint.of(transaction_data), 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
)
) )

View File

@ -1,6 +1,7 @@
__all__ = ( __all__ = (
'Measure', 'Measure',
'Terminated', 'Terminate', 'Terminated', 'Terminate',
'ClassReport',
'Concurrency', 'Concurrency',
'Counter', 'Counter',
'EntryExit', 'EntryExit',
@ -9,6 +10,7 @@ __all__ = (
from ._measure import Measure from ._measure import Measure
from ._terminate import Terminate, Terminated from ._terminate import Terminate, Terminated
from .classreport import ClassReport
from .concurrency import Concurrency from .concurrency import Concurrency
from .counter import Counter from .counter import Counter
from .entryexit import EntryExit from .entryexit import EntryExit

View File

@ -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()

View File

@ -3,12 +3,13 @@ import random
from contextlib import ExitStack from contextlib import ExitStack
from typing import Any, Callable, Coroutine from typing import Any, Callable, Coroutine
from nacl.signing import SigningKey from nacl.signing import SigningKey, VerifyKey
from plot import * from plot import *
from rainbowadn.collection.trees.binary import * from rainbowadn.collection.trees.binary import *
from rainbowadn.core import * from rainbowadn.core import *
from rainbowadn.flow13 import * from rainbowadn.flow13 import *
from rainbowadn.flow13 import FlowCoin
from rainbowadn.instrument import * from rainbowadn.instrument import *
from rainbowadn.testing.resolvers import * from rainbowadn.testing.resolvers import *
from rainbowadn.v13 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( async def _generate(
blocks: int, blocks: int,
subjects_min: int, subjects_min: int,
@ -37,14 +74,7 @@ async def _generate(
bank = await bank.add( bank = await bank.add(
await FlowCheque.make( await FlowCheque.make(
[ [
await FlowTransaction.make( await _generate_transaction(subjects_min, subjects_max)
[],
[
FlowCoinData.of(Subject(SigningKey.generate().verify_key), 0)
for _ in range(random.randint(subjects_min, subjects_max))
],
[]
)
for _ in range(random.randint(transactions_min, transactions_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)) 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): async def _trace(params):
set_gather_linear() set_gather_linear()
bank = await _generate( bank = await _generate(
@ -87,6 +125,7 @@ async def _trace(params):
*params['subjects'], *params['subjects'],
*params['transactions'], *params['transactions'],
) )
await _report(bank)
await _process(bank) await _process(bank)
bank = await _migrate(bank, params) bank = await _migrate(bank, params)
set_gather_asyncio() set_gather_asyncio()
@ -108,9 +147,8 @@ async def trace(params):
print('plotted') print('plotted')
preset_long = dict(blocks=64, subjects=(8, 16), transactions=(8, 16), caching=True, delay=.35) preset_long = dict(blocks=64, subjects=(4, 8), transactions=(8, 16), caching=True, delay=.5)
preset_short = dict(blocks=16, subjects=(8, 16), transactions=(8, 16), caching=True, delay=.35) preset_short = dict(blocks=16, subjects=(4, 8), transactions=(8, 16), caching=True, delay=.5)
preset_old = dict(blocks=16, subjects=(8, 15), transactions=(8, 15), caching=False, delay=.35)
if __name__ == '__main__': if __name__ == '__main__':
asyncio.run( asyncio.run(