Stack.iter

This commit is contained in:
AF 2022-06-06 18:48:01 +03:00
parent 2f0650cf69
commit 97fd1105d0
4 changed files with 73 additions and 95 deletions

View File

@ -68,6 +68,19 @@ class Stack(RecursiveMentionable, Generic[ElementType]):
assert isinstance(factory, RainbowFactory) assert isinstance(factory, RainbowFactory)
return cls.of(factory, map(HashPoint.of, elements)) return cls.of(factory, map(HashPoint.of, elements))
@classmethod
def iter(
cls,
reference: NullableReference['Stack[ElementType]']
) -> Iterable[HashPoint[ElementType]]:
assert isinstance(reference, NullableReference)
if reference.reference.null():
pass
else:
stack: Stack[ElementType] = reference.reference.resolve().resolve()
yield stack.element
yield from cls.iter(stack.previous)
class StackFactory(RainbowFactory[Stack[ElementType]], Generic[ElementType]): class StackFactory(RainbowFactory[Stack[ElementType]], Generic[ElementType]):
def __init__(self, factory: RainbowFactory[ElementType]): def __init__(self, factory: RainbowFactory[ElementType]):

View File

@ -30,6 +30,7 @@ from rainbowadn.wrisbt.wrisbtroot import WrisbtRoot
class TestAll(unittest.TestCase): class TestAll(unittest.TestCase):
"""examples rather than real tests"""
def test_bankchain(self): def test_bankchain(self):
with self.subTest('setup'): with self.subTest('setup'):
dr = DictResolver() dr = DictResolver()

View File

@ -19,7 +19,7 @@ from rainbowadn.hashing.resolverorigin import ResolverOrigin
from rainbowadn.hashing.static import StaticFactory, StaticMentionable from rainbowadn.hashing.static import StaticFactory, StaticMentionable
from rainbowadn.v13.algo import MINT_CONST from rainbowadn.v13.algo import MINT_CONST
from rainbowadn.v13.subject import Subject from rainbowadn.v13.subject import Subject
from rainbowadn.v13.transaction import Coin, Transaction, TransactionData from rainbowadn.v13.transaction import Coin, Transaction
__all__ = ('BankState',) __all__ = ('BankState',)
@ -87,55 +87,63 @@ class BankState(RecursiveMentionable, StaticMentionable):
HashPoint.of(Integer(self.length.resolve().integer + 1)) HashPoint.of(Integer(self.length.resolve().integer + 1))
) )
def push(self, transaction: HashPoint[Transaction]) -> 'BankState': def minted_tree(self) -> ActiveBinaryTree[Coin, Integer]:
assert isinstance(transaction, HashPoint) return ActiveBinaryTree(
transaction_resolved = transaction.resolve()
assert isinstance(transaction_resolved, Transaction)
miner: Nullable[HashPoint[Subject]] = self.miner.reference
assert isinstance(miner, Nullable)
if miner.null():
mint = MINT_CONST
else:
mint = 0
assert transaction_resolved.verify(mint)
transaction_data: TransactionData = transaction_resolved.data.resolve()
assert isinstance(transaction_data, TransactionData)
minted: ActiveBinaryTree[Coin, Integer] = ActiveBinaryTree(
AVLBTBP(HashComparator(Fail())), self.minted AVLBTBP(HashComparator(Fail())), self.minted
) )
assert isinstance(minted, ActiveBinaryTree)
used: ActiveBinaryTree[Coin, Integer] = ActiveBinaryTree( def used_tree(self) -> ActiveBinaryTree[Coin, Integer]:
return ActiveBinaryTree(
AVLBTBP(HashComparator(Fail())), self.used AVLBTBP(HashComparator(Fail())), self.used
) )
assert isinstance(used, ActiveBinaryTree)
in_coin: HashPoint[Coin] def use_coins(self, coins: Iterable[HashPoint[Coin]]) -> 'BankState':
for in_coin in transaction_data.iter_in_coins(): minted: ActiveBinaryTree[Coin, Integer] = self.minted_tree()
assert isinstance(in_coin, HashPoint) used: ActiveBinaryTree[Coin, Integer] = self.used_tree()
for in_coin in coins:
assert not minted.query_tree().query(in_coin).null() assert not minted.query_tree().query(in_coin).null()
assert used.query_tree().query(in_coin).null() assert used.query_tree().query(in_coin).null()
used = used.add(in_coin) used = used.add(in_coin)
assert isinstance(used, ActiveBinaryTree) return BankState(self.minted, used.reference, self.miner, self.length)
coin: Coin def mint_coins(
for coin, miner in transaction_resolved.iter_coins(mint, miner): self,
assert isinstance(coin, Coin) transaction: Transaction
assert isinstance(miner, Nullable) ) -> 'BankState':
assert self.verify(transaction)
miner = self.miner_nullable()
minted: ActiveBinaryTree[Coin, Integer] = self.minted_tree()
for coin, miner in transaction.iter_coins(self.mint(), miner):
assert minted.query_tree().query(HashPoint.of(coin)).null() assert minted.query_tree().query(HashPoint.of(coin)).null()
minted = minted.add(HashPoint.of(coin)) minted = minted.add(HashPoint.of(coin))
assert isinstance(minted, ActiveBinaryTree) assert isinstance(minted, ActiveBinaryTree)
return BankState(minted.reference, self.used, NullableReference(miner, self.miner.factory), self.length)
return BankState( def miner_nullable(self) -> Nullable[HashPoint[Subject]]:
minted.reference, return self.miner.reference
used.reference,
NullableReference(miner, self.miner.factory), def mint(self) -> int:
self.length if self.miner_nullable().null():
return MINT_CONST
else:
return 0
def verify(self, transaction: Transaction) -> bool:
assert isinstance(transaction, Transaction)
assert transaction.verify(self.mint())
return True
def _push(self, transaction: Transaction) -> 'BankState':
assert isinstance(transaction, Transaction)
return self.use_coins(
transaction.data.resolve().iter_in_coins()
).mint_coins(
transaction
) )
def push(self, transaction: HashPoint[Transaction]) -> 'BankState':
return self._push(transaction.resolve())
def str(self, tab: int) -> str: def str(self, tab: int) -> str:
assert isinstance(tab, int) assert isinstance(tab, int)
return f'(' \ return f'(' \

View File

@ -137,73 +137,26 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
def _verify_signatures( def _verify_signatures(
self, self,
in_coins: NullableReference[Stack[Coin]], signatures: NullableReference[Stack[Signature]]
signatures: NullableReference[Stack[Signature]],
) -> bool: ) -> bool:
assert isinstance(in_coins, NullableReference) for coin, signature in zip(self.iter_in_coins(), Stack.iter(signatures), strict=True):
assert isinstance(signatures, NullableReference) assert signature.resolve().verify(
if in_coins.reference.null(): coin.resolve().data.resolve().owner.resolve(),
assert signatures.reference.null() self.hash_point
return True )
else:
assert not signatures.reference.null()
in_coins_stack: Stack[Coin] = in_coins.reference.resolve().resolve()
assert isinstance(in_coins_stack, Stack)
signatures_stack: Stack[Signature] = signatures.reference.resolve().resolve()
assert isinstance(signatures_stack, Stack)
coin: Coin = in_coins_stack.element.resolve()
assert isinstance(coin, Coin)
coin_data: CoinData = coin.data.resolve()
assert isinstance(coin_data, CoinData)
owner: Subject = coin_data.owner.resolve()
assert isinstance(owner, Subject)
signature: Signature = signatures_stack.element.resolve()
assert isinstance(signature, Signature)
assert signature.verify(owner, self.hash_point)
assert self._verify_signatures(in_coins_stack.previous, signatures_stack.previous)
return True return True
def iter_in_coins(self) -> Iterable[HashPoint[Coin]]: def iter_in_coins(self) -> Iterable[HashPoint[Coin]]:
in_coins: NullableReference[Stack[Coin]] = self.in_coins return Stack.iter(self.in_coins)
assert isinstance(in_coins, NullableReference)
while not in_coins.reference.null():
in_coins_stack: Stack[Coin] = in_coins.reference.resolve().resolve()
assert isinstance(in_coins_stack, Stack)
coin: HashPoint[Coin] = in_coins_stack.element
assert isinstance(coin, HashPoint)
yield coin
in_coins = in_coins_stack.previous
assert isinstance(in_coins, NullableReference)
assert in_coins.reference.null()
def _total_in(self) -> int: def _total_in(self) -> int:
total_in = 0 return sum(coin.resolve().data.resolve().value.resolve().integer for coin in self.iter_in_coins())
coin: HashPoint[Coin]
for coin in self.iter_in_coins():
assert isinstance(coin, HashPoint)
total_in += coin.resolve().data.resolve().value.resolve().integer
return total_in
def iter_out_coins(self) -> Iterable[HashPoint[CoinData]]: def iter_out_coins(self) -> Iterable[HashPoint[CoinData]]:
out_coins: NullableReference[Stack[CoinData]] = self.out_coins return Stack.iter(self.out_coins)
assert isinstance(out_coins, NullableReference)
while not out_coins.reference.null():
out_coins_stack: Stack[CoinData] = out_coins.reference.resolve().resolve()
assert isinstance(out_coins_stack, Stack)
coin: HashPoint[CoinData] = out_coins_stack.element
assert isinstance(coin, HashPoint)
yield coin
out_coins = out_coins_stack.previous
assert isinstance(out_coins, NullableReference)
assert out_coins.reference.null()
def _total_out(self) -> int: def _total_out(self) -> int:
total_out = 0 return sum(coin.resolve().value.resolve().integer for coin in self.iter_out_coins())
coin: HashPoint[CoinData]
for coin in self.iter_out_coins():
assert isinstance(coin, HashPoint)
total_out += coin.resolve().value.resolve().integer
return total_out
def _verify_values(self, mint: int) -> bool: def _verify_values(self, mint: int) -> bool:
assert isinstance(mint, int) assert isinstance(mint, int)
@ -221,7 +174,9 @@ class TransactionData(RecursiveMentionable, StaticMentionable):
) -> bool: ) -> bool:
assert isinstance(signatures, NullableReference) assert isinstance(signatures, NullableReference)
assert isinstance(mint, int) assert isinstance(mint, int)
return self._verify_signatures(self.in_coins, signatures) and self._verify_values(mint) assert self._verify_signatures(signatures)
assert self._verify_values(mint)
return True
def str(self, tab: int) -> str: def str(self, tab: int) -> str:
assert isinstance(tab, int) assert isinstance(tab, int)
@ -308,7 +263,8 @@ class Transaction(RecursiveMentionable, StaticMentionable):
assert isinstance(mint, int) assert isinstance(mint, int)
data: TransactionData = self.data.resolve() data: TransactionData = self.data.resolve()
assert isinstance(data, TransactionData) assert isinstance(data, TransactionData)
return data.verify(self.signatures, mint) assert data.verify(self.signatures, mint)
return True
def __str__(self): def __str__(self):
return f'(transaction)' return f'(transaction)'