Skip to content

Commit

Permalink
Improve documentation and rename BCBlock.is_valid to `is_noncontext…
Browse files Browse the repository at this point in the history
…ually_valid`.

Also assert that all transactions in a `BCBlock` are `BCTransaction`s.

Signed-off-by: Daira Emma Hopwood <daira@jacaranda.org>
  • Loading branch information
daira committed Oct 19, 2023
1 parent 97c3d2a commit 9e50b82
Showing 1 changed file with 29 additions and 5 deletions.
34 changes: 29 additions & 5 deletions simtfl/bc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
"""
Abstractions for best-chain transactions, contexts, and blocks.
"""

from collections import deque
from dataclasses import dataclass

from ..util import Unique


class BCTransaction:
"""A transaction for a best-chain protocol."""

@dataclass(frozen=True)
class _TXO:
tx: 'BCTransaction'
index: int
value: int

"""A transaction for a best-chain protocol."""
def __init__(self, inputs, output_values, fee, issuance=0):
"""
Constructs a `BCTransaction` with the given inputs, output values, fee,
and (if it is a coinbase transaction) issuance.
The elements of `inputs` are TXO objects obtained from the `output` method
of another BCTransaction.
of another `BCTransaction`.
For a coinbase transaction, pass `inputs=[]`, and `fee` as a negative value
of magnitude equal to the total amount of fees paid by other transactions
in the block.
Expand Down Expand Up @@ -46,6 +51,11 @@ def is_coinbase(self):


class BCContext:
"""
A context that allows checking transactions for contextual validity in a
best-chain protocol.
"""

def __init__(self):
"""Constructs an empty `BCContext`."""
self.transactions = deque()
Expand Down Expand Up @@ -73,19 +83,26 @@ def add_if_valid(self, tx):


class BCBlock:
"""A block in a best-chain protocol."""

def __init__(self, parent, added_score, transactions, allow_invalid=False):
"""
Constructs a `BCBlock` with the given parent block, score relative to the parent, and transactions.
Constructs a `BCBlock` with the given parent block, score relative to the parent,
and transactions.
If `allow_invalid` is set, the block need not be valid.
Use `parent=None` to construct the genesis block.
"""
assert all((isinstance(tx, BCTransaction) for tx in transactions))
self.parent = parent
self.score = (0 if parent is None else self.parent.score) + added_score
self.transactions = transactions
self.hash = Unique()
assert allow_invalid or self.is_valid()
assert allow_invalid or self.is_noncontextually_valid()

def is_valid(self):
def is_noncontextually_valid(self):
"""
Are non-contextual consensus rules satisfied for this block?
"""
return (
len(self.transactions) > 0 and
self.transactions[0].is_coinbase() and
Expand All @@ -96,9 +113,16 @@ def is_valid(self):

@dataclass
class BCProtocol:
"""A best-chain protocol."""

Transaction: type[object] = BCTransaction
"""The type of transactions for this protocol."""

Context: type[object] = BCContext
"""The type of contexts for this protocol."""

Block: type[object] = BCBlock
"""The type of blocks for this protocol."""


__all__ = ['BCTransaction', 'BCContext', 'BCBlock', 'BCProtocol']
Expand Down

0 comments on commit 9e50b82

Please sign in to comment.