Stack.iter
This commit is contained in:
parent
2f0650cf69
commit
97fd1105d0
@ -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]):
|
||||||
|
@ -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()
|
||||||
|
@ -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'(' \
|
||||||
|
@ -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)'
|
||||||
|
Loading…
Reference in New Issue
Block a user