Skip to content

Commit

Permalink
Merge pull request #199 from thenewboston-developers/BC-272-add-block…
Browse files Browse the repository at this point in the history
…-to-blockchain-once-it-gets-enough-confirmations

One more unittest
  • Loading branch information
dmugtasimov authored Mar 20, 2022
2 parents 6dd453f + 93d02a1 commit 418af43
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 9 deletions.
20 changes: 12 additions & 8 deletions node/blockchain/tasks/process_block_confirmations.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@ def get_next_block_confirmations(next_block_number) -> list[BlockConfirmation]:
return list(BlockConfirmation.objects.filter(number=next_block_number, signer__in=cv_identifiers))


def get_consensus_block_hash_with_confirmations(confirmations,
minimum_consensus) -> Optional[tuple[Hash, list[BlockConfirmation]]]:
def get_consensus_block_hash_with_confirmations(
confirmations: list[BlockConfirmation], minimum_consensus: int
) -> Optional[tuple[Hash, list[BlockConfirmation]]]:

assert len(set(confirmation.number for confirmation in confirmations)) <= 1

key_func = attrgetter('hash')
grouped_confirmations = [(Hash(hash_), list(confirmations))
for hash_, confirmations in groupby(sorted(confirmations, key=key_func), key=key_func)]
finalizable_hashes = [(hash_, confirmations)
for hash_, confirmations in grouped_confirmations
if len(confirmations) >= minimum_consensus]
grouped_confirmations = [(Hash(hash_), list(confirmations_))
for hash_, confirmations_ in groupby(sorted(confirmations, key=key_func), key=key_func)]
finalizable_hashes = [(hash_, confirmations_)
for hash_, confirmations_ in grouped_confirmations
if len(confirmations_) >= minimum_consensus]

if not finalizable_hashes:
return None # No consensus, yet
Expand All @@ -44,7 +48,7 @@ def get_consensus_block_hash_with_confirmations(confirmations,
return block_hash, consensus_confirmations


def is_valid_consensus(confirmations: list[BlockConfirmation], minimum_consensus):
def is_valid_consensus(confirmations: list[BlockConfirmation], minimum_consensus: int):
# Validate confirmations, since they may have not been validated on API call because some of them were added
# much earlier then the next block number become equal to confirmation block number
assert len(set(confirmation.signer for confirmation in confirmations)) == len(confirmations)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
from model_bakery import baker

from node.blockchain.models import Node
from node.blockchain.tasks.process_block_confirmations import get_next_block_confirmations
from node.blockchain.tasks.process_block_confirmations import (
get_consensus_block_hash_with_confirmations, get_next_block_confirmations
)
from node.blockchain.types import NodeRole


Expand All @@ -24,3 +26,20 @@ def test_get_next_block_confirmations():
assert set(get_next_block_confirmations(3)) == {bc2, bc3}

mock.assert_called_once_with((NodeRole.CONFIRMATION_VALIDATOR,))


@pytest.mark.django_db
def test_get_consensus_block_hash_with_confirmations():
bc0 = baker.make('blockchain.BlockConfirmation', number=3, signer='0' * 64, hash='a' * 128)
bc1 = baker.make('blockchain.BlockConfirmation', number=3, signer='1' * 64, hash='a' * 128)
bc2 = baker.make('blockchain.BlockConfirmation', number=3, signer='2' * 64, hash='b' * 128)

confirmations = [bc0, bc1, bc2]
result = get_consensus_block_hash_with_confirmations(confirmations, 2)
assert result
hash_, consensus_confirmations = result
assert hash_ == bc0.hash
assert consensus_confirmations == [bc0, bc1]

result = get_consensus_block_hash_with_confirmations(confirmations, 3)
assert result is None

0 comments on commit 418af43

Please sign in to comment.