Skip to content

Commit 8960cc8

Browse files
authored
Merge pull request #195 from thenewboston-developers/BC-272-add-block-to-blockchain-once-it-gets-enough-confirmations
Starting process_block_confirmations_task
2 parents f620b8c + dcc77ac commit 8960cc8

File tree

6 files changed

+28
-7
lines changed

6 files changed

+28
-7
lines changed

node/blockchain/facade.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import math
23
from typing import TYPE_CHECKING, Optional, Type, TypeVar # noqa: I101
34

45
from node.blockchain.constants import BLOCK_LOCK
@@ -263,8 +264,12 @@ def yield_nodes(roles=None):
263264

264265
@staticmethod
265266
def get_confirmation_validator_identifiers():
266-
return ORMNode.objects.filter_by_roles((NodeRole.CONFIRMATION_VALIDATOR,)).values_list('_id', flat=True)
267+
return ORMNode.objects.filter_confirmation_validators().values_list('_id', flat=True)
267268

268269
@staticmethod
269270
def is_confirmation_validator(identifier):
270271
return ORMNode.objects.is_confirmation_validator(identifier)
272+
273+
@staticmethod
274+
def get_minimum_consensus():
275+
return int(math.ceil(ORMNode.objects.filter_confirmation_validators().count() * 2 / 3))

node/blockchain/models/node.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ def filter_by_roles(self, roles: Collection[NodeRole]):
5252

5353
raise AssertionError('Should have exited on previous shortcut guard condition')
5454

55+
def filter_confirmation_validators(self):
56+
return self.filter_by_roles((NodeRole.CONFIRMATION_VALIDATOR,))
57+
5558

5659
class NodeManager(DjongoManager.from_queryset(NodeQuerySet)): # type: ignore
5760

node/blockchain/tasks/process_block_confirmations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def process_next_block():
1717
cv_identifiers = facade.get_confirmation_validator_identifiers()
1818
confirmations = BlockConfirmation.objects.filter(number=next_block_number, signer__in=cv_identifiers)
1919
grouped_confirmations = groupby(confirmations.order_by('hash'), key=attrgetter('hash'))
20-
minimum_consensus = len(cv_identifiers) * 2 / 3
20+
minimum_consensus = facade.get_minimum_consensus()
2121

2222
finalizable_hashes = [
2323
hash_ for hash_, _confirmations in grouped_confirmations if len(list(_confirmations)) >= minimum_consensus

node/blockchain/tests/fixtures/mocks.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,9 @@ def mock_get_primary_validator(primary_validator_node):
1313
def start_send_new_block_task_mock():
1414
with patch('node.blockchain.views.signed_change_request.start_send_new_block_task') as mock:
1515
yield mock
16+
17+
18+
@pytest.fixture(autouse=True)
19+
def start_process_block_confirmations_task_mock():
20+
with patch('node.blockchain.views.block_confirmation.start_process_block_confirmations_task') as mock:
21+
yield mock

node/blockchain/views/block_confirmation.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from node.blockchain.facade import BlockchainFacade
66
from node.blockchain.models.block_confirmation import BlockConfirmation as ORMBlockConfirmation
77
from node.blockchain.serializers.block_confirmation import BlockConfirmationSerializer
8+
from node.blockchain.tasks.process_block_confirmations import start_process_block_confirmations_task
9+
from node.core.utils.misc import apply_on_commit
810

911

1012
class BlockConfirmationViewSet(GenericViewSet):
@@ -16,8 +18,12 @@ def create(self, request, *args, **kwargs):
1618
block_confirmation = serializer.save()
1719

1820
facade = BlockchainFacade.get_instance()
19-
if facade.get_next_block_number() == block_confirmation.get_number():
21+
next_block_number = facade.get_next_block_number()
22+
is_next_block_number = block_confirmation.get_number() == next_block_number
23+
if is_next_block_number:
2024
block_confirmation.validate_all(facade)
25+
else:
26+
block_confirmation.validate_business_logic()
2127

2228
ORMBlockConfirmation.objects.update_or_create(
2329
number=block_confirmation.get_number(),
@@ -28,8 +34,9 @@ def create(self, request, *args, **kwargs):
2834
},
2935
)
3036

31-
# TODO(dmu) CRITICAL: https://thenewboston.atlassian.net/browse/BC-272
32-
# if next block number and we have enough confirmations then run a celery task
33-
# to add the block to the blockchain
37+
if is_next_block_number and (
38+
ORMBlockConfirmation.objects.filter(number=next_block_number).count() >= facade.get_minimum_consensus()
39+
):
40+
apply_on_commit(start_process_block_confirmations_task)
3441

3542
return Response(serializer.data, status=status.HTTP_201_CREATED)

node/blockchain/views/signed_change_request.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def create(self, request, *args, **kwargs):
3030
# of validators instead of the list existed before the block (fix it)
3131
# https://thenewboston.atlassian.net/browse/BC-268
3232
block_number = block.get_block_number() # it is important to put block number to a variable first
33-
apply_on_commit(lambda: start_send_new_block_task(block_number))
33+
apply_on_commit(lambda block_number_=block_number: start_send_new_block_task(block_number_))
3434
return Response(serializer.data, status=status.HTTP_201_CREATED)
3535

3636
pv_node = blockchain_facade.get_primary_validator()

0 commit comments

Comments
 (0)