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]':
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)

View File

@ -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,

View File

@ -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]',

View File

@ -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]):

View File

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

View File

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

View File

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

View File

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

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]':
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)

View File

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