transaction data inlining + correct contains check

This commit is contained in:
AF 2022-07-28 21:02:11 +03:00
parent 87c3292d62
commit e7b13e7319
10 changed files with 75 additions and 58 deletions

View File

@ -24,13 +24,13 @@ class KeyValue(Keyed[KVKeyType], IAuto, Generic[KVKeyType, KVValueType]):
) -> 'KeyValue[KVKeyType, KVValueType]': ) -> 'KeyValue[KVKeyType, KVValueType]':
assert isinstance(key, HashPoint) assert isinstance(key, HashPoint)
assert isinstance(value, HashPoint) assert isinstance(value, HashPoint)
return await cls.from_hashpoints(key, value) return await cls.auto_off(key, value)
@classmethod @classmethod
def of(cls, vk: KVKeyType, vv: KVValueType) -> 'KeyValue[KVKeyType, KVValueType]': def of(cls, vk: KVKeyType, vv: KVValueType) -> 'KeyValue[KVKeyType, KVValueType]':
assert isinstance(vk, Mentionable) assert isinstance(vk, Mentionable)
assert isinstance(vv, Mentionable) assert isinstance(vv, Mentionable)
return cls.from_values(vk, vv) return cls.auto_of(vk, vv)
@classmethod @classmethod
def f( def f(
@ -38,4 +38,4 @@ class KeyValue(Keyed[KVKeyType], IAuto, Generic[KVKeyType, KVValueType]):
) -> RainbowFactory['KeyValue[KVKeyType, KVValueType]']: ) -> RainbowFactory['KeyValue[KVKeyType, KVValueType]']:
assert isinstance(f0, RainbowFactory) assert isinstance(f0, RainbowFactory)
assert isinstance(f1, RainbowFactory) assert isinstance(f1, RainbowFactory)
return cls.factory(f0, f1) return cls.auto_f(f0, f1)

View File

@ -152,6 +152,11 @@ class ContainsAction(
], ],
Generic[ActiveKeyType, MetaDataType, TreeType] 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( async def on_equal(
self, self,
case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType], case: ProtocolizedBinarySplit[ActiveKeyType, MetaDataType, TreeType],
@ -159,6 +164,9 @@ class ContainsAction(
) -> bool: ) -> bool:
assert isinstance(case, ProtocolizedBinarySplit) assert isinstance(case, ProtocolizedBinarySplit)
assert isinstance(equal, Equal) assert isinstance(equal, Equal)
if self.exact:
return self.key == case.split.key
else:
return True return True
async def on_left( async def on_left(

View File

@ -78,9 +78,9 @@ class ActiveBinaryTree(
assert isinstance(key, HashPoint) assert isinstance(key, HashPoint)
return await RemoveAction(key).on(self.protocolized()) 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) 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[ async def split(self, key: HashPoint[ActiveKeyType]) -> tuple[
'ActiveBinaryTree[ActiveKeyType, MetaDataType]', 'ActiveBinaryTree[ActiveKeyType, MetaDataType]',

View File

@ -323,7 +323,8 @@ class MintedVerification(
assert isinstance(element, HashPoint) assert isinstance(element, HashPoint)
assert_true( assert_true(
await self.cheque.transactions.contains( await self.cheque.transactions.contains(
(await element.resolve()).transaction (await element.resolve()).transaction,
exact=True
) )
) )
return True return True
@ -343,7 +344,8 @@ 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(await KeyValue.off(element, HashPoint.of(FlowTransaction.empty()))) HashPoint.of(await KeyValue.off(element, HashPoint.of(FlowTransaction.empty()))),
exact=False
) )
) )
return True return True
@ -363,7 +365,8 @@ class UsedXVerification(
assert isinstance(transaction, HashPoint) assert isinstance(transaction, HashPoint)
assert_true( assert_true(
await self.cheque.transactions.contains( await self.cheque.transactions.contains(
transaction transaction,
exact=True
) )
) )
return True return True
@ -374,14 +377,22 @@ class UsedXVerification(
) -> bool: ) -> bool:
assert isinstance(transaction, HashPoint) assert isinstance(transaction, HashPoint)
assert isinstance(coin, HashPoint) assert isinstance(coin, HashPoint)
data_resolved: FlowTransactionData = await (await transaction.resolve()).data_resolved() assert_true(
assert isinstance(data_resolved, FlowTransactionData) await (await transaction.resolve()).data.in_coins.contains(
assert_true(await data_resolved.in_coins.contains(coin)) coin,
exact=True
)
)
return True return True
async def _verify_coin_registred_as_used(self, coin: HashPoint[FlowCoin]) -> bool: async def _verify_coin_registred_as_used(self, coin: HashPoint[FlowCoin]) -> bool:
assert isinstance(coin, HashPoint) assert isinstance(coin, HashPoint)
assert_true(await self.cheque.used.contains(coin)) assert_true(
await self.cheque.used.contains(
coin,
exact=True
)
)
return True return True
async def _verify(self, pair: KeyValue[FlowCoin, FlowTransaction]): async def _verify(self, pair: KeyValue[FlowCoin, FlowTransaction]):

View File

@ -42,8 +42,8 @@ class FlowStandard(
assert isinstance(protocolized, BinaryProtocolized) assert isinstance(protocolized, BinaryProtocolized)
self.protocolized = protocolized self.protocolized = protocolized
async def contains(self, key: HashPoint[KeyT]) -> bool: async def contains(self, key: HashPoint[KeyT], *, exact: bool) -> bool:
return await self.protocolized.tree.contains(key) return await self.protocolized.tree.contains(key, exact=exact)
def _protocolized(self: FS) -> BP: def _protocolized(self: FS) -> BP:
return self.protocolized return self.protocolized

View File

@ -8,6 +8,7 @@ from rainbowadn.collection.keyvalue import *
from rainbowadn.core import * from rainbowadn.core import *
from rainbowadn.flow.core import * from rainbowadn.flow.core import *
from rainbowadn.flow.verification.core import * from rainbowadn.flow.verification.core import *
# from rainbowadn.inlining import *
from rainbowadn.v13 import * from rainbowadn.v13 import *
from ._flowstandard import * from ._flowstandard import *
from ._resolvemapper import * from ._resolvemapper import *
@ -73,6 +74,10 @@ class FlowCoin(RecursiveMentionable, StaticMentionable):
self.data = data self.data = data
self.transaction = transaction self.transaction = transaction
@classmethod
def size(cls) -> int:
return 2 * HashPoint.HASH_LENGTH
async def data_resolved(self) -> FlowCoinData: async def data_resolved(self) -> FlowCoinData:
return await self.data.resolve() return await self.data.resolve()
@ -248,7 +253,8 @@ 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(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 return True
@ -282,21 +288,18 @@ class SPVMapper(Mapper[KeyValue[Subject, Signature], bool]):
class FlowTransaction(RecursiveMentionable, StaticMentionable): class FlowTransaction(RecursiveMentionable, StaticMentionable):
def __init__( def __init__(
self, self,
data: HashPoint[FlowTransactionData], data: FlowTransactionData,
signatures: FlowStandard[KeyValue[Subject, Signature]] signatures: FlowStandard[KeyValue[Subject, Signature]]
): ):
assert isinstance(data, HashPoint) assert isinstance(data, FlowTransactionData)
assert isinstance(signatures, FlowStandard) assert isinstance(signatures, FlowStandard)
self.data = data self.data = data
self.signatures = signatures self.signatures = signatures
self.hash_point = HashPoint.of(self) self.hash_point = HashPoint.of(self)
assert isinstance(self.hash_point, HashPoint) assert isinstance(self.hash_point, HashPoint)
async def data_resolved(self) -> FlowTransactionData:
return await self.data.resolve()
def points(self) -> Iterable[HashPoint]: def points(self) -> Iterable[HashPoint]:
return [self.data, *self.signatures.points()] return [*self.data.points(), *self.signatures.points()]
def __bytes__(self): def __bytes__(self):
return bytes(self.data) + bytes(self.signatures) return bytes(self.data) + bytes(self.signatures)
@ -306,12 +309,12 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable):
assert isinstance(source, bytes) assert isinstance(source, bytes)
assert isinstance(resolver, HashResolver) assert isinstance(resolver, HashResolver)
return cls( return cls(
ResolverOrigin(FlowTransactionData.factory(), source[:HashPoint.HASH_LENGTH], resolver).hash_point(), FlowTransactionData.from_bytes(source[:-HashPoint.HASH_LENGTH], resolver),
FlowStandardFactory.of( FlowStandardFactory.of(
KeyValue.f(Subject.factory(), Signature.factory()), KeyValue.f(Subject.factory(), Signature.factory()),
KeyedComparator(HashComparator(Fail())) KeyedComparator(HashComparator(Fail()))
).from_bytes( ).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)) return HashPoint.of(FlowCoin(data, self.hash_point))
async def used_reducer(self) -> Reducer[HashPoint[FlowCoin], Any]: async def used_reducer(self) -> Reducer[HashPoint[FlowCoin], Any]:
transaction_data: FlowTransactionData = await self.data_resolved() return await self.data.in_coins.reducer()
assert isinstance(transaction_data, FlowTransactionData)
return await transaction_data.in_coins.reducer()
async def minted_reducer(self) -> Reducer[HashPoint[FlowCoin], Any]: async def minted_reducer(self) -> Reducer[HashPoint[FlowCoin], Any]:
transaction_data: FlowTransactionData = await self.data_resolved() return MapReducer(CallableMapper(self._coin), await self.data.out_coins.reducer())
assert isinstance(transaction_data, FlowTransactionData)
return MapReducer(CallableMapper(self._coin), await transaction_data.out_coins.reducer())
async def verify(self): async def verify(self):
data: FlowTransactionData = await self.data_resolved() assert_true(await self.data.verify(self.signatures))
assert isinstance(data, FlowTransactionData)
assert_true(await data.verify(self.signatures))
return True return True
async def str(self, tab: int) -> str: async def str(self, tab: int) -> str:
assert isinstance(tab, int) assert isinstance(tab, int)
return f'(' \ return f'(' \
f'{tabulate(tab + 1)}transaction' \ 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 + 1)}(signatures)' \
f'{tabulate(tab)})' f'{tabulate(tab)})'
@classmethod @classmethod
def empty(cls): def empty(cls):
return cls( return cls(
HashPoint.of(FlowTransactionData.empty()), FlowTransactionData.empty(),
FlowStandardFactory.empty( FlowStandardFactory.empty(
KeyValue.f(Subject.factory(), Signature.factory()), KeyedComparator(HashComparator(Fail())) KeyValue.f(Subject.factory(), Signature.factory()), KeyedComparator(HashComparator(Fail()))
), ),
@ -382,7 +379,7 @@ class FlowTransaction(RecursiveMentionable, StaticMentionable):
keys keys
] ]
return cls( return cls(
HashPoint.of(transaction_data), transaction_data,
await FlowStandardFactory.off( await FlowStandardFactory.off(
KeyValue.f(Subject.factory(), Signature.factory()), KeyedComparator(HashComparator(Fail())), signatures KeyValue.f(Subject.factory(), Signature.factory()), KeyedComparator(HashComparator(Fail())), signatures
) )

View File

@ -11,7 +11,7 @@ Tree = TypeVar('Tree')
class FlowTree(Generic[Key, Tree]): class FlowTree(Generic[Key, Tree]):
async def contains(self, key: Key) -> bool: async def contains(self, key: Key, *, exact: bool) -> bool:
raise NotImplementedError raise NotImplementedError
async def verify_contains_all(self, keys: Reducer[Key, bool]) -> bool: 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 self.tree = tree
async def verify(self, element: Key) -> bool: 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 return True
@ -62,5 +62,5 @@ class DoesNotContainVerification(Verification[Key], Generic[Key, Tree]):
self.tree = tree self.tree = tree
async def verify(self, element: Key) -> bool: 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 return True

View File

@ -71,7 +71,7 @@ class IAuto(RecursiveMentionable):
assert isinstance(size, int) assert isinstance(size, int)
sized.append((index, factory, size)) sized.append((index, factory, size))
for index, uninlined in self.uninlined: 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) merged_unsized: Iterable[tuple[int, RainbowFactory]] = heapq.merge(inlined_unsized, uninlined_unsized)
return IAutoFactory( return IAutoFactory(
type(self), type(self),
@ -94,12 +94,12 @@ class IAuto(RecursiveMentionable):
return await gather(*map(HashPoint.resolve, self.hashpoints())) return await gather(*map(HashPoint.resolve, self.hashpoints()))
@classmethod @classmethod
def factory(cls: Type[_IAuto], *factories: RainbowFactory) -> RainbowFactory[_IAuto]: def auto_f(cls: Type[_IAuto], *factories: RainbowFactory) -> RainbowFactory[_IAuto]:
assert issubclass(cls, IAuto) assert issubclass(cls, IAuto)
return IAutoFactory.of(cls, *factories) return IAutoFactory.of(cls, *factories)
@classmethod @classmethod
def from_values(cls: Type[_IAuto], *values: Mentionable) -> _IAuto: def auto_of(cls: Type[_IAuto], *values: Mentionable) -> _IAuto:
assert issubclass(cls, IAuto) assert issubclass(cls, IAuto)
sized: _IList = [] sized: _IList = []
unsized: _IList = [] unsized: _IList = []
@ -128,7 +128,7 @@ class IAuto(RecursiveMentionable):
return index, await hashpoint.resolve() return index, await hashpoint.resolve()
@classmethod @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) assert issubclass(cls, IAuto)
sized: _UList = [] sized: _UList = []
unsized: _UList = [] unsized: _UList = []
@ -282,8 +282,9 @@ class IAutoFactory(Inlining[IAuto], Generic[_IAuto]):
assert isinstance(source, bytes) assert isinstance(source, bytes)
assert isinstance(resolver, HashResolver) assert isinstance(resolver, HashResolver)
yield from self._parse_affix(source[:self.prefix_size], resolver, self.prefix) 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) postfix_start = len(source) - self.postfix_size
yield from self._parse_affix(source[-self.postfix_size:], resolver, self.postfix) 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: def _parse_merged(self, source: bytes, resolver: HashResolver) -> _IAuto:
assert isinstance(source, bytes) assert isinstance(source, bytes)

View File

@ -21,16 +21,16 @@ class IPair(IAuto, Generic[E0, E1]):
async def off(cls, e0: HashPoint[E0], e1: HashPoint[E1]) -> 'IPair[E0, E1]': async def off(cls, e0: HashPoint[E0], e1: HashPoint[E1]) -> 'IPair[E0, E1]':
assert isinstance(e0, HashPoint) assert isinstance(e0, HashPoint)
assert isinstance(e1, HashPoint) assert isinstance(e1, HashPoint)
return await cls.from_hashpoints(e0, e1) return await cls.auto_off(e0, e1)
@classmethod @classmethod
def of(cls, v0: E0, v1: E1) -> 'IPair[E0, E1]': def of(cls, v0: E0, v1: E1) -> 'IPair[E0, E1]':
assert isinstance(v0, Mentionable) assert isinstance(v0, Mentionable)
assert isinstance(v1, Mentionable) assert isinstance(v1, Mentionable)
return cls.from_values(v0, v1) return cls.auto_of(v0, v1)
@classmethod @classmethod
def f(cls, f0: RainbowFactory[E0], f1: RainbowFactory[E1]) -> RainbowFactory['IPair[E0, E1]']: def f(cls, f0: RainbowFactory[E0], f1: RainbowFactory[E1]) -> RainbowFactory['IPair[E0, E1]']:
assert isinstance(f0, RainbowFactory) assert isinstance(f0, RainbowFactory)
assert isinstance(f1, RainbowFactory) assert isinstance(f1, RainbowFactory)
return cls.factory(f0, f1) return cls.auto_f(f0, f1)

View File

@ -15,22 +15,22 @@ class TestInlining(unittest.IsolatedAsyncioTestCase):
return result return result
async def test_unit(self): async def test_unit(self):
print(await (IAuto.factory(IUnit.factory(), IUnit.factory()).from_bytes(b'', FailResolver())).str(0)) print(await (IAuto.auto_f(IUnit.factory(), IUnit.factory()).from_bytes(b'', FailResolver())).str(0))
print(bytes(IAuto.from_values(IUnit(), IUnit()))) print(bytes(IAuto.auto_of(IUnit(), IUnit())))
async def test_byte(self): async def test_byte(self):
# iB short for IByte # iB short for IByte
print(await (IAuto.factory(IByte.factory(), IByte.factory()).from_bytes(b'iB', FailResolver())).str(0)) print(await (IAuto.auto_f(IByte.factory(), IByte.factory()).from_bytes(b'iB', FailResolver())).str(0))
print(bytes(IAuto.from_values(IByte(0x69), IByte(0x42)))) print(bytes(IAuto.auto_of(IByte(0x69), IByte(0x42))))
async def test_mixed(self): async def test_mixed(self):
print(await (IAuto.factory(IByte.factory(), IUnit.factory()).from_bytes(b'!', FailResolver())).str(0)) print(await (IAuto.auto_f(IByte.factory(), IUnit.factory()).from_bytes(b'!', FailResolver())).str(0))
print(bytes(IAuto.from_values(IByte(0x21), IUnit()))) print(bytes(IAuto.auto_of(IByte(0x21), IUnit())))
async def test_complex_infix(self): 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( print(
await IAuto.factory( await IAuto.auto_f(
IByte.factory(), Integer.factory(), IByte.factory() IByte.factory(), Integer.factory(), IByte.factory()
).from_bytes(b, FailResolver()).str(0) ).from_bytes(b, FailResolver()).str(0)
) )
@ -41,13 +41,13 @@ class TestInlining(unittest.IsolatedAsyncioTestCase):
( (
b := bytes( b := bytes(
await dr.migrate_resolved( 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() ).hex()
) )
print( print(
await IAuto.factory( await IAuto.auto_f(
IByte.factory(), Integer.factory(), Integer.factory(), IByte.factory() IByte.factory(), Integer.factory(), Integer.factory(), IByte.factory()
).from_bytes(b, dr).str(0) ).from_bytes(b, dr).str(0)
) )