transaction data inlining + correct contains check
This commit is contained in:
parent
87c3292d62
commit
e7b13e7319
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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]',
|
||||
|
@ -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]):
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user