Skip to content

Commit

Permalink
feat(consensus): Assert that consensus ended in a valid state after p…
Browse files Browse the repository at this point in the history
…rocessing a new block
  • Loading branch information
msbrogli committed Nov 7, 2024
1 parent 127c7fe commit 0bfbcb7
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
30 changes: 30 additions & 0 deletions hathor/consensus/block_consensus.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,36 @@ def log(cls) -> Any:

def update_consensus(self, block: Block) -> None:
self.update_voided_info(block)
self.assert_valid_consensus(block)

def assert_valid_consensus(self, block: Block) -> None:
"""Assert that all transactions confirmed by the block are valid.
This assertion might be slow because it runs in O(n) where n is number of transactions confirmed
by the block."""
for tx in block.iter_transactions_in_this_block():
self._assert_tx_not_voided(tx)

def _assert_tx_not_voided(self, tx: BaseTransaction) -> None:
tx_meta = tx.get_metadata()
# Since this is the last step in the consensus, the conflict resolution has already been resolved.
# Hence, at this point, all transactins confirmed by a block must be non-voided.
if tx_meta.voided_by:
if bool(self.context.consensus.soft_voided_tx_ids & tx_meta.voided_by):
return
if tx_meta.voided_by == {tx.hash, self._settings.NC_EXECUTION_FAIL_ID}:
return
for h in tx_meta.voided_by:
if h == self._settings.NC_EXECUTION_FAIL_ID:
continue
if h == tx.hash:
continue
tx2 = tx.storage.get_transaction(h)
tx2_meta = tx2.get_metadata()
tx2_voided_by: set[bytes] = tx2_meta.voided_by or set()
if self._settings.NC_EXECUTION_FAIL_ID in tx2_voided_by:
return
assert tx_meta.voided_by is None

def update_voided_info(self, block: Block) -> None:
""" This method is called only once when a new block arrives.
Expand Down
2 changes: 2 additions & 0 deletions tests/simulation/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ def setUp(self) -> None:
self.simulator = Simulator(self.seed_config)
self.simulator.start()

self.reactor = self.simulator._clock

print('-'*30)
print('Simulation seed config:', self.simulator.seed)
print('-'*30)
Expand Down

0 comments on commit 0bfbcb7

Please sign in to comment.