diff --git a/rainbowadn/collection/keyvalue.py b/rainbowadn/collection/keyvalue.py index 0fd4b6e..89822f1 100644 --- a/rainbowadn/collection/keyvalue.py +++ b/rainbowadn/collection/keyvalue.py @@ -24,13 +24,13 @@ class KeyValue(Keyed[KVKeyType], IAuto, Generic[KVKeyType, KVValueType]): ) -> 'KeyValue[KVKeyType, KVValueType]': assert isinstance(key, HashPoint) assert isinstance(value, HashPoint) - return await cls.from_hashpoints(key, value) + return await cls.auto_off(key, 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) + return cls.auto_of(vk, vv) @classmethod def f( @@ -38,4 +38,4 @@ class KeyValue(Keyed[KVKeyType], IAuto, Generic[KVKeyType, KVValueType]): ) -> RainbowFactory['KeyValue[KVKeyType, KVValueType]']: assert isinstance(f0, RainbowFactory) assert isinstance(f1, RainbowFactory) - return cls.factory(f0, f1) + return cls.auto_f(f0, f1) diff --git a/rainbowadn/collection/trees/binary/actions/stdactions.py b/rainbowadn/collection/trees/binary/actions/stdactions.py index 5961af2..c25ee90 100644 --- a/rainbowadn/collection/trees/binary/actions/stdactions.py +++ b/rainbowadn/collection/trees/binary/actions/stdactions.py @@ -152,6 +152,11 @@ class ContainsAction( ], Generic[ActiveKeyType, MetaDataType, TreeType] ): + def __init__(self, key: HashPoint[ActiveKeyType], *, exact: bool): + assert isinstance(exact, bool) + self.exact = exact + super().__init__(key) + async def on_equal( self, case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType], @@ -159,7 +164,10 @@ class ContainsAction( ) -> bool: assert isinstance(case, ProtocolizedBinarySplit) assert isinstance(equal, Equal) - return True + if self.exact: + return self.key == case.split.key + else: + return True async def on_left( self, diff --git a/rainbowadn/collection/trees/binary/activebinarytree.py b/rainbowadn/collection/trees/binary/activebinarytree.py index b549d85..4da53a9 100644 --- a/rainbowadn/collection/trees/binary/activebinarytree.py +++ b/rainbowadn/collection/trees/binary/activebinarytree.py @@ -78,9 +78,9 @@ class ActiveBinaryTree( assert isinstance(key, HashPoint) return await RemoveAction(key).on(self.protocolized()) - async def contains(self, key: HashPoint[ActiveKeyType]) -> bool: + async def contains(self, key: HashPoint[ActiveKeyType], *, exact: bool) -> bool: assert isinstance(key, HashPoint) - return await ContainsAction(key).on(self.protocolized()) + return await ContainsAction(key, exact=exact).on(self.protocolized()) async def split(self, key: HashPoint[ActiveKeyType]) -> tuple[ 'ActiveBinaryTree[ActiveKeyType, MetaDataType]', diff --git a/rainbowadn/flow13/_flowcheque.py b/rainbowadn/flow13/_flowcheque.py index 7ce311c..456619e 100644 --- a/rainbowadn/flow13/_flowcheque.py +++ b/rainbowadn/flow13/_flowcheque.py @@ -323,7 +323,8 @@ class MintedVerification( assert isinstance(element, HashPoint) assert_true( await self.cheque.transactions.contains( - (await element.resolve()).transaction + (await element.resolve()).transaction, + exact=True ) ) return True @@ -343,7 +344,8 @@ class UsedVerification( assert isinstance(element, HashPoint) assert_true( await self.cheque.usedx.contains( - HashPoint.of(await KeyValue.off(element, HashPoint.of(FlowTransaction.empty()))) + HashPoint.of(await KeyValue.off(element, HashPoint.of(FlowTransaction.empty()))), + exact=False ) ) return True @@ -363,7 +365,8 @@ class UsedXVerification( assert isinstance(transaction, HashPoint) assert_true( await self.cheque.transactions.contains( - transaction + transaction, + exact=True ) ) return True @@ -374,14 +377,22 @@ class UsedXVerification( ) -> bool: assert isinstance(transaction, HashPoint) assert isinstance(coin, HashPoint) - data_resolved: FlowTransactionData = await (await transaction.resolve()).data_resolved() - assert isinstance(data_resolved, FlowTransactionData) - assert_true(await data_resolved.in_coins.contains(coin)) + assert_true( + await (await transaction.resolve()).data.in_coins.contains( + coin, + exact=True + ) + ) return True async def _verify_coin_registred_as_used(self, coin: HashPoint[FlowCoin]) -> bool: assert isinstance(coin, HashPoint) - assert_true(await self.cheque.used.contains(coin)) + assert_true( + await self.cheque.used.contains( + coin, + exact=True + ) + ) return True async def _verify(self, pair: KeyValue[FlowCoin, FlowTransaction]): diff --git a/rainbowadn/flow13/_flowstandard.py b/rainbowadn/flow13/_flowstandard.py index 09c02bb..1823b64 100644 --- a/rainbowadn/flow13/_flowstandard.py +++ b/rainbowadn/flow13/_flowstandard.py @@ -42,8 +42,8 @@ class FlowStandard( assert isinstance(protocolized, BinaryProtocolized) self.protocolized = protocolized - async def contains(self, key: HashPoint[KeyT]) -> bool: - return await self.protocolized.tree.contains(key) + async def contains(self, key: HashPoint[KeyT], *, exact: bool) -> bool: + return await self.protocolized.tree.contains(key, exact=exact) def _protocolized(self: FS) -> BP: return self.protocolized diff --git a/rainbowadn/flow13/_flowtransaction.py b/rainbowadn/flow13/_flowtransaction.py index 0c49619..387d72b 100644 --- a/rainbowadn/flow13/_flowtransaction.py +++ b/rainbowadn/flow13/_flowtransaction.py @@ -8,6 +8,7 @@ from rainbowadn.collection.keyvalue import * from rainbowadn.core import * from rainbowadn.flow.core import * from rainbowadn.flow.verification.core import * +# from rainbowadn.inlining import * from rainbowadn.v13 import * from ._flowstandard import * from ._resolvemapper import * @@ -73,6 +74,10 @@ class FlowCoin(RecursiveMentionable, StaticMentionable): self.data = data self.transaction = transaction + @classmethod + def size(cls) -> int: + return 2 * HashPoint.HASH_LENGTH + async def data_resolved(self) -> FlowCoinData: return await self.data.resolve() @@ -248,7 +253,8 @@ class CVMapper(Mapper[FlowCoin, bool]): assert isinstance(element, FlowCoin) assert_true( await self.signatures.contains( - HashPoint.of(await KeyValue.off((await element.data.resolve()).owner, HashPoint.of(Signature.empty()))) + HashPoint.of(await KeyValue.off((await element.data.resolve()).owner, HashPoint.of(Signature.empty()))), + exact=False ) ) return True @@ -282,21 +288,18 @@ class SPVMapper(Mapper[KeyValue[Subject, Signature], bool]): class FlowTransaction(RecursiveMentionable, StaticMentionable): def __init__( self, - data: HashPoint[FlowTransactionData], + data: FlowTransactionData, signatures: FlowStandard[KeyValue[Subject, Signature]] ): - assert isinstance(data, HashPoint) + assert isinstance(data, FlowTransactionData) assert isinstance(signatures, FlowStandard) self.data = data self.signatures = signatures self.hash_point = HashPoint.of(self) assert isinstance(self.hash_point, HashPoint) - async def data_resolved(self) -> FlowTransactionData: - return await self.data.resolve() - def points(self) -> Iterable[HashPoint]: - return [self.data, *self.signatures.points()] + return [*self.data.points(), *self.signatures.points()] def __bytes__(self): return bytes(self.data) + bytes(self.signatures) @@ -306,12 +309,12 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable): assert isinstance(source, bytes) assert isinstance(resolver, HashResolver) return cls( - ResolverOrigin(FlowTransactionData.factory(), source[:HashPoint.HASH_LENGTH], resolver).hash_point(), + FlowTransactionData.from_bytes(source[:-HashPoint.HASH_LENGTH], resolver), FlowStandardFactory.of( KeyValue.f(Subject.factory(), Signature.factory()), KeyedComparator(HashComparator(Fail())) ).from_bytes( - source[HashPoint.HASH_LENGTH:], resolver + source[-HashPoint.HASH_LENGTH:], resolver ), ) @@ -320,33 +323,27 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable): return HashPoint.of(FlowCoin(data, self.hash_point)) async def used_reducer(self) -> Reducer[HashPoint[FlowCoin], Any]: - transaction_data: FlowTransactionData = await self.data_resolved() - assert isinstance(transaction_data, FlowTransactionData) - return await transaction_data.in_coins.reducer() + return await self.data.in_coins.reducer() async def minted_reducer(self) -> Reducer[HashPoint[FlowCoin], Any]: - transaction_data: FlowTransactionData = await self.data_resolved() - assert isinstance(transaction_data, FlowTransactionData) - return MapReducer(CallableMapper(self._coin), await transaction_data.out_coins.reducer()) + return MapReducer(CallableMapper(self._coin), await self.data.out_coins.reducer()) async def verify(self): - data: FlowTransactionData = await self.data_resolved() - assert isinstance(data, FlowTransactionData) - assert_true(await data.verify(self.signatures)) + assert_true(await self.data.verify(self.signatures)) return True async def str(self, tab: int) -> str: assert isinstance(tab, int) return f'(' \ f'{tabulate(tab + 1)}transaction' \ - f'{tabulate(tab + 1)}{await hash_point_format(self.data, tab + 1)}' \ + f'{tabulate(tab + 1)}{await self.data.str(tab + 1)}' \ f'{tabulate(tab + 1)}(signatures)' \ f'{tabulate(tab)})' @classmethod def empty(cls): return cls( - HashPoint.of(FlowTransactionData.empty()), + FlowTransactionData.empty(), FlowStandardFactory.empty( KeyValue.f(Subject.factory(), Signature.factory()), KeyedComparator(HashComparator(Fail())) ), @@ -382,7 +379,7 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable): keys ] return cls( - HashPoint.of(transaction_data), + transaction_data, await FlowStandardFactory.off( KeyValue.f(Subject.factory(), Signature.factory()), KeyedComparator(HashComparator(Fail())), signatures ) diff --git a/rainbowadn/flow13/_flowtree.py b/rainbowadn/flow13/_flowtree.py index 558e40b..01e9f9e 100644 --- a/rainbowadn/flow13/_flowtree.py +++ b/rainbowadn/flow13/_flowtree.py @@ -11,7 +11,7 @@ Tree = TypeVar('Tree') class FlowTree(Generic[Key, Tree]): - async def contains(self, key: Key) -> bool: + async def contains(self, key: Key, *, exact: bool) -> bool: raise NotImplementedError async def verify_contains_all(self, keys: Reducer[Key, bool]) -> bool: @@ -52,7 +52,7 @@ class ContainsVerification(Verification[Key], Generic[Key, Tree]): self.tree = tree async def verify(self, element: Key) -> bool: - assert_true(await self.tree.contains(element)) + assert_true(await self.tree.contains(element, exact=True)) return True @@ -62,5 +62,5 @@ class DoesNotContainVerification(Verification[Key], Generic[Key, Tree]): self.tree = tree async def verify(self, element: Key) -> bool: - assert_false(await self.tree.contains(element)) + assert_false(await self.tree.contains(element, exact=False)) return True diff --git a/rainbowadn/inlining/iauto.py b/rainbowadn/inlining/iauto.py index 7cfd0ad..78a627f 100644 --- a/rainbowadn/inlining/iauto.py +++ b/rainbowadn/inlining/iauto.py @@ -71,7 +71,7 @@ class IAuto(RecursiveMentionable): assert isinstance(size, int) sized.append((index, factory, size)) for index, uninlined in self.uninlined: - uninlined_unsized.append((index, uninlined.factory)) + uninlined_unsized.append((index, uninlined.auto_f)) merged_unsized: Iterable[tuple[int, RainbowFactory]] = heapq.merge(inlined_unsized, uninlined_unsized) return IAutoFactory( type(self), @@ -94,12 +94,12 @@ class IAuto(RecursiveMentionable): return await gather(*map(HashPoint.resolve, self.hashpoints())) @classmethod - def factory(cls: Type[_IAuto], *factories: RainbowFactory) -> RainbowFactory[_IAuto]: + def auto_f(cls: Type[_IAuto], *factories: RainbowFactory) -> RainbowFactory[_IAuto]: assert issubclass(cls, IAuto) return IAutoFactory.of(cls, *factories) @classmethod - def from_values(cls: Type[_IAuto], *values: Mentionable) -> _IAuto: + def auto_of(cls: Type[_IAuto], *values: Mentionable) -> _IAuto: assert issubclass(cls, IAuto) sized: _IList = [] unsized: _IList = [] @@ -128,7 +128,7 @@ class IAuto(RecursiveMentionable): return index, await hashpoint.resolve() @classmethod - async def from_hashpoints(cls: Type[_IAuto], *hashpoints: HashPoint) -> _IAuto: + async def auto_off(cls: Type[_IAuto], *hashpoints: HashPoint) -> _IAuto: assert issubclass(cls, IAuto) sized: _UList = [] unsized: _UList = [] @@ -282,8 +282,9 @@ class IAutoFactory(Inlining[IAuto], Generic[_IAuto]): assert isinstance(source, bytes) assert isinstance(resolver, HashResolver) yield from self._parse_affix(source[:self.prefix_size], resolver, self.prefix) - yield self.infix_index, self.infix_factory.from_bytes(source[self.prefix_size:-self.postfix_size], resolver) - yield from self._parse_affix(source[-self.postfix_size:], resolver, self.postfix) + postfix_start = len(source) - self.postfix_size + yield self.infix_index, self.infix_factory.from_bytes(source[self.prefix_size:postfix_start], resolver) + yield from self._parse_affix(source[postfix_start:], resolver, self.postfix) def _parse_merged(self, source: bytes, resolver: HashResolver) -> _IAuto: assert isinstance(source, bytes) diff --git a/rainbowadn/inlining/ipair.py b/rainbowadn/inlining/ipair.py index 8fce4be..d219e2c 100644 --- a/rainbowadn/inlining/ipair.py +++ b/rainbowadn/inlining/ipair.py @@ -21,16 +21,16 @@ class IPair(IAuto, Generic[E0, E1]): async def off(cls, e0: HashPoint[E0], e1: HashPoint[E1]) -> 'IPair[E0, E1]': assert isinstance(e0, HashPoint) assert isinstance(e1, HashPoint) - return await cls.from_hashpoints(e0, e1) + return await cls.auto_off(e0, e1) @classmethod def of(cls, v0: E0, v1: E1) -> 'IPair[E0, E1]': assert isinstance(v0, Mentionable) assert isinstance(v1, Mentionable) - return cls.from_values(v0, v1) + return cls.auto_of(v0, v1) @classmethod def f(cls, f0: RainbowFactory[E0], f1: RainbowFactory[E1]) -> RainbowFactory['IPair[E0, E1]']: assert isinstance(f0, RainbowFactory) assert isinstance(f1, RainbowFactory) - return cls.factory(f0, f1) + return cls.auto_f(f0, f1) diff --git a/rainbowadn/testing/test_inlining.py b/rainbowadn/testing/test_inlining.py index 895c2e2..9496174 100644 --- a/rainbowadn/testing/test_inlining.py +++ b/rainbowadn/testing/test_inlining.py @@ -15,22 +15,22 @@ class TestInlining(unittest.IsolatedAsyncioTestCase): return result async def test_unit(self): - print(await (IAuto.factory(IUnit.factory(), IUnit.factory()).from_bytes(b'', FailResolver())).str(0)) - print(bytes(IAuto.from_values(IUnit(), IUnit()))) + print(await (IAuto.auto_f(IUnit.factory(), IUnit.factory()).from_bytes(b'', FailResolver())).str(0)) + print(bytes(IAuto.auto_of(IUnit(), IUnit()))) async def test_byte(self): # iB short for IByte - print(await (IAuto.factory(IByte.factory(), IByte.factory()).from_bytes(b'iB', FailResolver())).str(0)) - print(bytes(IAuto.from_values(IByte(0x69), IByte(0x42)))) + print(await (IAuto.auto_f(IByte.factory(), IByte.factory()).from_bytes(b'iB', FailResolver())).str(0)) + print(bytes(IAuto.auto_of(IByte(0x69), IByte(0x42)))) async def test_mixed(self): - print(await (IAuto.factory(IByte.factory(), IUnit.factory()).from_bytes(b'!', FailResolver())).str(0)) - print(bytes(IAuto.from_values(IByte(0x21), IUnit()))) + print(await (IAuto.auto_f(IByte.factory(), IUnit.factory()).from_bytes(b'!', FailResolver())).str(0)) + print(bytes(IAuto.auto_of(IByte(0x21), IUnit()))) async def test_complex_infix(self): - print(b := bytes(IAuto.from_values(IByte(0x21), Integer(0x21), IByte(0x21)))) + print(b := bytes(IAuto.auto_of(IByte(0x21), Integer(0x21), IByte(0x21)))) print( - await IAuto.factory( + await IAuto.auto_f( IByte.factory(), Integer.factory(), IByte.factory() ).from_bytes(b, FailResolver()).str(0) ) @@ -41,13 +41,13 @@ class TestInlining(unittest.IsolatedAsyncioTestCase): ( b := bytes( await dr.migrate_resolved( - IAuto.from_values(IByte(0x21), Integer(0x21), Integer(0x21), IByte(0x21)) + IAuto.auto_of(IByte(0x21), Integer(0x21), Integer(0x21), IByte(0x21)) ) ) ).hex() ) print( - await IAuto.factory( + await IAuto.auto_f( IByte.factory(), Integer.factory(), Integer.factory(), IByte.factory() ).from_bytes(b, dr).str(0) )