diff --git a/bigchaindb/backend/query.py b/bigchaindb/backend/query.py index 1a0146cb..2814816b 100644 --- a/bigchaindb/backend/query.py +++ b/bigchaindb/backend/query.py @@ -372,10 +372,10 @@ def get_validator_set(conn, height): @singledispatch def get_asset_tokens_for_public_keys(connection, asset_id, public_keys, operation): - """Retrieve a list of `VALIDATOR_ELECTION_VOTE`s `txids` that are owned by `owner`. + """Retrieve a list of tokens of type `asset_id` that are owned by `public_keys`. Args: - election_id (str): Id of the election. - election_public_key (str): base58 encoded public key of the election + asset_id (str): Id of the token. + public_keys (str): list of public keys operation: filter transaction based on `operation` Returns: Iterator of transaction that list given owner in conditions. diff --git a/bigchaindb/core.py b/bigchaindb/core.py index 9d9d7513..d46ce04a 100644 --- a/bigchaindb/core.py +++ b/bigchaindb/core.py @@ -131,16 +131,11 @@ class App(BaseApplication): else: self.block_txn_hash = block['app_hash'] - # TODO: calculate if an election has concluded - # NOTE: ensure the local validator set is updated + # Check if the current block concluded any validator elections and + # update the locally tracked validator set validator_updates = ValidatorElection.get_validator_update(self.bigchaindb, self.new_height, self.block_transactions) - # if validator_updates: - # validator_set = new_validator_set(self.bigchaindb, self.new_height, validator_updates) - # self.bigchaindb.store_validator_set(self.new_height+1, validator_set) - - # validator_updates = [vutils.encode_validator(v) for v in validator_updates] # Store pre-commit state to recover in case there is a crash # during `commit` diff --git a/bigchaindb/lib.py b/bigchaindb/lib.py index 17562428..12b8fff1 100644 --- a/bigchaindb/lib.py +++ b/bigchaindb/lib.py @@ -24,7 +24,6 @@ from bigchaindb.common.exceptions import (SchemaValidationError, from bigchaindb.tendermint_utils import encode_transaction, merkleroot from bigchaindb import exceptions as core_exceptions from bigchaindb.consensus import BaseConsensusRules -from bigchaindb.upsert_validator import ValidatorElection, ValidatorElectionVote logger = logging.getLogger(__name__) diff --git a/bigchaindb/upsert_validator/validator_election.py b/bigchaindb/upsert_validator/validator_election.py index fd38631a..62ed5bba 100644 --- a/bigchaindb/upsert_validator/validator_election.py +++ b/bigchaindb/upsert_validator/validator_election.py @@ -152,25 +152,16 @@ class ValidatorElection(Transaction): return base58.b58encode(bytes.fromhex(election_id)) @classmethod - def count_votes(cls, election_pk, txns): + def count_votes(cls, election_pk, txns, getter=getattr): votes = 0 for txn in txns: - if isinstance(txn, dict): - if txn['operation'] == 'VALIDATOR_ELECTION_VOTE': - for output in txn['outputs']: - # NOTE: We enforce that a valid vote to election id will have only - # election_pk in the output public keys, including any other public key - # along with election_pk will lead to vote being not considered valid. - if len(output['public_keys']) == 1 and [election_pk] == output['public_keys']: - votes = votes + int(output['amount']) - else: - if txn.operation == 'VALIDATOR_ELECTION_VOTE': - for output in txn.outputs: - # NOTE: We enforce that a valid vote to election id will have only - # election_pk in the output public keys, including any other public key - # along with election_pk will lead to vote being not considered valid. - if len(output.public_keys) == 1 and [election_pk] == output.public_keys: - votes = votes + int(output.amount) + if getter(txn, 'operation') == 'VALIDATOR_ELECTION_VOTE': + for output in getter(txn, 'outputs'): + # NOTE: We enforce that a valid vote to election id will have only + # election_pk in the output public keys, including any other public key + # along with election_pk will lead to vote being not considered valid. + if len(getter(output, 'public_keys')) == 1 and [election_pk] == getter(output, 'public_keys'): + votes = votes + int(getter(output, 'amount')) return votes def get_commited_votes(self, bigchain, election_pk=None): @@ -180,7 +171,7 @@ class ValidatorElection(Transaction): self.id, [election_pk], 'VALIDATOR_ELECTION_VOTE')) - return self.count_votes(election_pk, txns) + return self.count_votes(election_pk, txns, dict.get) @classmethod def conclude(cls, bigchain, txn_id, current_votes=[], height=None): @@ -210,22 +201,24 @@ class ValidatorElection(Transaction): def get_validator_update(cls, bigchain, new_height, txns): votes = {} for txn in txns: - if isinstance(txn, ValidatorElectionVote): - election_id = txn.asset['id'] - election_votes = votes.get(election_id, []) - election_votes.append(txn) - votes[election_id] = election_votes + if not isinstance(txn, ValidatorElectionVote): + continue - election = cls.conclude(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: - # The new validator set comes into effect from height = new_height+1 - validator_updates = [election.asset['data']] - curr_validator_set = bigchain.get_validators(new_height) - updated_validator_set = new_validator_set(curr_validator_set, - new_height, validator_updates) + election_id = txn.asset['id'] + election_votes = votes.get(election_id, []) + election_votes.append(txn) + votes[election_id] = election_votes - bigchain.store_validator_set(new_height+1, updated_validator_set) - return [encode_validator(election.asset['data'])] + election = cls.conclude(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: + # The new validator set comes into effect from height = new_height+1 + validator_updates = [election.asset['data']] + curr_validator_set = bigchain.get_validators(new_height) + updated_validator_set = new_validator_set(curr_validator_set, + new_height, validator_updates) + + bigchain.store_validator_set(new_height+1, updated_validator_set) + return [encode_validator(election.asset['data'])] return []