From 7803e6320fb012acb1ff8d1cead60e27dfc811d9 Mon Sep 17 00:00:00 2001 From: z-bowen Date: Wed, 12 Sep 2018 18:47:45 +0200 Subject: [PATCH] Problem: The way `end_block` checks for concluded elections assumes there is only one type of election (so we can't conclude an `upsert-validator` and a `migration` at the same height) Solution: Re-engineered the code in `Elections` that checks for `approved_elections` to check all election types simultaneously, then return concluded elections sorted by election type --- bigchaindb/core.py | 15 +++++++-------- bigchaindb/elections/election.py | 24 ++++++++++++++++-------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/bigchaindb/core.py b/bigchaindb/core.py index f936bd91..9a448f51 100644 --- a/bigchaindb/core.py +++ b/bigchaindb/core.py @@ -20,13 +20,13 @@ from abci.types_pb2 import ( ) from bigchaindb import BigchainDB +from bigchaindb.elections.election import Election from bigchaindb.version import __tm_supported_versions__ from bigchaindb.utils import tendermint_version_is_compatible from bigchaindb.tendermint_utils import (decode_transaction, calculate_hash) from bigchaindb.lib import Block, PreCommitState from bigchaindb.backend.query import PRE_COMMIT_ID -from bigchaindb.upsert_validator import ValidatorElection import bigchaindb.upsert_validator.validator_utils as vutils from bigchaindb.events import EventTypes, Event @@ -219,15 +219,14 @@ class App(BaseApplication): else: self.block_txn_hash = block['app_hash'] - # Check if the current block concluded any validator elections and - # update the locally tracked validator set - validator_update = ValidatorElection.approved_update(self.bigchaindb, - self.new_height, - self.block_transactions) + # Check the current block to see if any elections have concluded. + concluded_elections = Election.approved_elections(self.bigchaindb, + self.new_height, + self.block_transactions) + validator_update = concluded_elections.get('VALIDATOR_ELECTION') update = [validator_update] if validator_update else [] - # Store pre-commit state to recover in case there is a crash - # during `commit` + # Store pre-commit state to recover in case there is a crash during `commit` pre_commit_state = PreCommitState(commit_id=PRE_COMMIT_ID, height=self.new_height, transactions=self.block_txn_ids) diff --git a/bigchaindb/elections/election.py b/bigchaindb/elections/election.py index b78e1456..7700ea1c 100644 --- a/bigchaindb/elections/election.py +++ b/bigchaindb/elections/election.py @@ -242,24 +242,32 @@ class Election(Transaction): return response @classmethod - def approved_update(cls, bigchain, new_height, txns): - votes = {} + def approved_elections(cls, bigchain, new_height, txns): + elections = {} for txn in txns: if not isinstance(txn, Vote): continue election_id = txn.asset['id'] - election_votes = votes.get(election_id, []) + e = bigchain.get_transaction(election_id) + election_operation = e.OPERATION + election_operation_votes = elections.get(election_operation, {}) + # Once we conclude an election of a given type, we stop looking at that election class + if type(election_operation_votes) != dict: + continue + election_votes = election_operation_votes.get(election_id, []) election_votes.append(txn) - votes[election_id] = election_votes + election_operation_votes[election_id] = election_votes + elections[election_operation] = election_operation_votes election = cls.has_concluded(bigchain, election_id, election_votes, new_height) - # Once an election concludes any other conclusion for the same - # or any other election is invalidated if election: + # Once we conclude an election, we store the result in the db cls.store_election_results(bigchain, election, new_height) - return cls.on_approval(bigchain, election, new_height) - return None + # And keep the transaction filed under the election_type + elections[election_operation] = election.on_approval(bigchain, election, new_height) + approved_elections = {k: v for (k, v) in elections.items() if type(v) != dict} + return approved_elections @classmethod def on_approval(cls, bigchain, election, new_height):