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)
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]):
def __init__(self, factory: RainbowFactory[ElementType]):

View File

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

View File

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

View File

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