From 1e3caf8ccdc0913211ec8c7abbb93abbfb8a97d3 Mon Sep 17 00:00:00 2001 From: z-bowen Date: Tue, 4 Sep 2018 17:13:34 +0200 Subject: [PATCH] Problem: `UpsertValidatorVote` can be generalized to just be `Vote` Solution: Renamed, refactored and moved the `Vote` class to tie in with the more general `Election` base class --- bigchaindb/__init__.py | 4 +- bigchaindb/commands/bigchaindb.py | 9 +- bigchaindb/common/election.py | 5 +- .../common/schema/transaction_v2.0.yaml | 2 +- ...nsaction_validator_election_vote_v2.0.yaml | 4 +- .../vote.py} | 12 +-- bigchaindb/upsert_validator/__init__.py | 1 - .../upsert_validator/validator_election.py | 3 - tests/upsert_validator/conftest.py | 10 +-- ..._vote.py => test_upsert_validator_vote.py} | 83 ++++++++++--------- 10 files changed, 66 insertions(+), 67 deletions(-) rename bigchaindb/{upsert_validator/validator_election_vote.py => common/vote.py} (86%) rename tests/upsert_validator/{test_validator_election_vote.py => test_upsert_validator_vote.py} (79%) diff --git a/bigchaindb/__init__.py b/bigchaindb/__init__.py index b936d8aa..b63afa3d 100644 --- a/bigchaindb/__init__.py +++ b/bigchaindb/__init__.py @@ -94,9 +94,9 @@ _config = copy.deepcopy(config) from bigchaindb.common.transaction import Transaction # noqa from bigchaindb import models # noqa from bigchaindb.upsert_validator import ValidatorElection # noqa -from bigchaindb.upsert_validator import ValidatorElectionVote # noqa +from bigchaindb.common.vote import Vote # noqa Transaction.register_type(Transaction.CREATE, models.Transaction) Transaction.register_type(Transaction.TRANSFER, models.Transaction) Transaction.register_type(ValidatorElection.ELECTION_TYPE, ValidatorElection) -Transaction.register_type(ValidatorElectionVote.VALIDATOR_ELECTION_VOTE, ValidatorElectionVote) +Transaction.register_type(Vote.VOTE, Vote) diff --git a/bigchaindb/commands/bigchaindb.py b/bigchaindb/commands/bigchaindb.py index 19cb0e2d..d4678ca2 100644 --- a/bigchaindb/commands/bigchaindb.py +++ b/bigchaindb/commands/bigchaindb.py @@ -17,9 +17,10 @@ from bigchaindb.utils import load_node_key from bigchaindb.common.exceptions import (DatabaseAlreadyExists, DatabaseDoesNotExist, ValidationError) +from bigchaindb.common.vote import Vote import bigchaindb from bigchaindb import (backend, ValidatorElection, - BigchainDB, ValidatorElectionVote) + BigchainDB) from bigchaindb.backend import schema from bigchaindb.backend import query from bigchaindb.backend.query import PRE_COMMIT_ID @@ -175,9 +176,9 @@ def run_upsert_validator_approve(args, bigchain): inputs = [i for i in tx.to_inputs() if key.public_key in i.owners_before] election_pub_key = ValidatorElection.to_public_key(tx.id) - approval = ValidatorElectionVote.generate(inputs, - [([election_pub_key], voting_power)], - tx.id).sign([key.private_key]) + approval = Vote.generate(inputs, + [([election_pub_key], voting_power)], + tx.id).sign([key.private_key]) approval.validate(bigchain) resp = bigchain.write_transaction(approval, 'broadcast_tx_commit') diff --git a/bigchaindb/common/election.py b/bigchaindb/common/election.py index f4a81ec3..ddc92495 100644 --- a/bigchaindb/common/election.py +++ b/bigchaindb/common/election.py @@ -5,6 +5,7 @@ import base58 from bigchaindb import backend +from bigchaindb.common.vote import Vote from bigchaindb.common.exceptions import (InvalidSignature, MultipleInputsError, InvalidProposer, @@ -24,7 +25,7 @@ class Election(Transaction): # by setting an ELECTION_TYPE and renaming CREATE = ELECTION_TYPE and ALLOWED_OPERATIONS = (ELECTION_TYPE,) ELECTION_TYPE = None # the model for votes issued by the election - VOTE_TYPE = None + VOTE_TYPE = Vote # Election Statuses: ONGOING = 'ongoing' CONCLUDED = 'concluded' @@ -164,7 +165,7 @@ class Election(Transaction): def count_votes(cls, election_pk, transactions, getter=getattr): votes = 0 for txn in transactions: - if getter(txn, 'operation') == 'VALIDATOR_ELECTION_VOTE': + if getter(txn, 'operation') == '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 diff --git a/bigchaindb/common/schema/transaction_v2.0.yaml b/bigchaindb/common/schema/transaction_v2.0.yaml index acc8c6b5..562c0d86 100644 --- a/bigchaindb/common/schema/transaction_v2.0.yaml +++ b/bigchaindb/common/schema/transaction_v2.0.yaml @@ -63,7 +63,7 @@ definitions: - CREATE - TRANSFER - VALIDATOR_ELECTION - - VALIDATOR_ELECTION_VOTE + - VOTE asset: type: object additionalProperties: false diff --git a/bigchaindb/common/schema/transaction_validator_election_vote_v2.0.yaml b/bigchaindb/common/schema/transaction_validator_election_vote_v2.0.yaml index c17fb229..5e7c4763 100644 --- a/bigchaindb/common/schema/transaction_validator_election_vote_v2.0.yaml +++ b/bigchaindb/common/schema/transaction_validator_election_vote_v2.0.yaml @@ -5,14 +5,14 @@ --- "$schema": "http://json-schema.org/draft-04/schema#" type: object -title: Validator Election Vote Schema - Vote on a validator set change +title: Vote Schema - Vote on an election required: - operation - outputs properties: operation: type: string - value: "VALIDATOR_ELECTION_VOTE" + value: "VOTE" outputs: type: array items: diff --git a/bigchaindb/upsert_validator/validator_election_vote.py b/bigchaindb/common/vote.py similarity index 86% rename from bigchaindb/upsert_validator/validator_election_vote.py rename to bigchaindb/common/vote.py index 7620b289..7b6230ba 100644 --- a/bigchaindb/upsert_validator/validator_election_vote.py +++ b/bigchaindb/common/vote.py @@ -9,13 +9,13 @@ from bigchaindb.common.schema import (_validate_schema, TX_SCHEMA_VALIDATOR_ELECTION_VOTE) -class ValidatorElectionVote(Transaction): +class Vote(Transaction): - VALIDATOR_ELECTION_VOTE = 'VALIDATOR_ELECTION_VOTE' + VOTE = 'VOTE' # NOTE: This class inherits TRANSFER txn type. The `TRANSFER` property is # overriden to re-use methods from parent class - TRANSFER = VALIDATOR_ELECTION_VOTE - ALLOWED_OPERATIONS = (VALIDATOR_ELECTION_VOTE,) + TRANSFER = VOTE + ALLOWED_OPERATIONS = (VOTE,) def validate(self, bigchain, current_transactions=[]): """Validate election vote transaction @@ -28,7 +28,7 @@ class ValidatorElectionVote(Transaction): bigchain (BigchainDB): an instantiated bigchaindb.lib.BigchainDB object. Returns: - ValidatorElectionVote object + Vote object Raises: ValidationError: If the election vote is invalid @@ -39,7 +39,7 @@ class ValidatorElectionVote(Transaction): @classmethod def generate(cls, inputs, recipients, election_id, metadata=None): (inputs, outputs) = cls.validate_transfer(inputs, recipients, election_id, metadata) - election_vote = cls(cls.VALIDATOR_ELECTION_VOTE, {'id': election_id}, inputs, outputs, metadata) + election_vote = cls(cls.VOTE, {'id': election_id}, inputs, outputs, metadata) cls.validate_schema(election_vote.to_dict(), skip_id=True) return election_vote diff --git a/bigchaindb/upsert_validator/__init__.py b/bigchaindb/upsert_validator/__init__.py index 90a02a0b..0aa49f35 100644 --- a/bigchaindb/upsert_validator/__init__.py +++ b/bigchaindb/upsert_validator/__init__.py @@ -3,5 +3,4 @@ # Code is Apache-2.0 and docs are CC-BY-4.0 -from bigchaindb.upsert_validator.validator_election_vote import ValidatorElectionVote # noqa from bigchaindb.upsert_validator.validator_election import ValidatorElection # noqa diff --git a/bigchaindb/upsert_validator/validator_election.py b/bigchaindb/upsert_validator/validator_election.py index 3cc4fc26..0b94c71e 100644 --- a/bigchaindb/upsert_validator/validator_election.py +++ b/bigchaindb/upsert_validator/validator_election.py @@ -6,7 +6,6 @@ from bigchaindb.common.exceptions import InvalidPowerChange from bigchaindb.common.election import Election from bigchaindb.common.schema import (_validate_schema, TX_SCHEMA_VALIDATOR_ELECTION) -from . import ValidatorElectionVote from .validator_utils import (new_validator_set, encode_validator) @@ -17,8 +16,6 @@ class ValidatorElection(Election): # by renaming CREATE to VALIDATOR_ELECTION CREATE = ELECTION_TYPE ALLOWED_OPERATIONS = (ELECTION_TYPE,) - DB_TABLE = 'validators' - VOTE_TYPE = ValidatorElectionVote def validate(self, bigchain, current_transactions=[]): """For more details refer BEP-21: https://github.com/bigchaindb/BEPs/tree/master/21 diff --git a/tests/upsert_validator/conftest.py b/tests/upsert_validator/conftest.py index 8bb472f4..30f1f300 100644 --- a/tests/upsert_validator/conftest.py +++ b/tests/upsert_validator/conftest.py @@ -4,7 +4,7 @@ import pytest -from bigchaindb import ValidatorElectionVote +from bigchaindb import Vote from bigchaindb.backend.localmongodb import query from bigchaindb.lib import Block from bigchaindb.upsert_validator import ValidatorElection @@ -89,9 +89,9 @@ def vote(election, voter, keys, b): election_pub_key = ValidatorElection.to_public_key(election.id) - v = ValidatorElectionVote.generate([election_input], - [([election_pub_key], votes)], - election_id=election.id)\ - .sign([key.private_key]) + v = Vote.generate([election_input], + [([election_pub_key], votes)], + election_id=election.id)\ + .sign([key.private_key]) b.store_bulk_transactions([v]) return v diff --git a/tests/upsert_validator/test_validator_election_vote.py b/tests/upsert_validator/test_upsert_validator_vote.py similarity index 79% rename from tests/upsert_validator/test_validator_election_vote.py rename to tests/upsert_validator/test_upsert_validator_vote.py index a9303675..6cea8ac6 100644 --- a/tests/upsert_validator/test_validator_election_vote.py +++ b/tests/upsert_validator/test_upsert_validator_vote.py @@ -6,10 +6,11 @@ import pytest import codecs from bigchaindb.tendermint_utils import public_key_to_base64 -from bigchaindb.upsert_validator import ValidatorElection, ValidatorElectionVote +from bigchaindb.upsert_validator import ValidatorElection from bigchaindb.common.exceptions import AmountError from bigchaindb.common.crypto import generate_key_pair from bigchaindb.common.exceptions import ValidationError +from bigchaindb.common.vote import Vote from tests.utils import generate_block pytestmark = [pytest.mark.execute] @@ -27,10 +28,10 @@ def test_upsert_validator_valid_election_vote(b_mock, valid_election, ed25519_no election_pub_key = ValidatorElection.to_public_key(valid_election.id) - vote = ValidatorElectionVote.generate([input0], - [([election_pub_key], votes)], - election_id=valid_election.id)\ - .sign([key0.private_key]) + vote = Vote.generate([input0], + [([election_pub_key], votes)], + election_id=valid_election.id)\ + .sign([key0.private_key]) assert vote.validate(b_mock) @@ -48,10 +49,10 @@ def test_upsert_validator_valid_non_election_vote(b_mock, valid_election, ed2551 # Ensure that threshold conditions are now allowed with pytest.raises(ValidationError): - ValidatorElectionVote.generate([input0], - [([election_pub_key, key0.public_key], votes)], - election_id=valid_election.id)\ - .sign([key0.private_key]) + Vote.generate([input0], + [([election_pub_key, key0.public_key], votes)], + election_id=valid_election.id)\ + .sign([key0.private_key]) @pytest.mark.tendermint @@ -66,10 +67,10 @@ def test_upsert_validator_delegate_election_vote(b_mock, valid_election, ed25519 public_key0 = input0.owners_before[0] key0 = ed25519_node_keys[public_key0] - delegate_vote = ValidatorElectionVote.generate([input0], - [([alice.public_key], 3), ([key0.public_key], votes-3)], - election_id=valid_election.id)\ - .sign([key0.private_key]) + delegate_vote = Vote.generate([input0], + [([alice.public_key], 3), ([key0.public_key], votes-3)], + election_id=valid_election.id)\ + .sign([key0.private_key]) assert delegate_vote.validate(b_mock) @@ -77,17 +78,17 @@ def test_upsert_validator_delegate_election_vote(b_mock, valid_election, ed25519 election_pub_key = ValidatorElection.to_public_key(valid_election.id) alice_votes = delegate_vote.to_inputs()[0] - alice_casted_vote = ValidatorElectionVote.generate([alice_votes], - [([election_pub_key], 3)], - election_id=valid_election.id)\ - .sign([alice.private_key]) + alice_casted_vote = Vote.generate([alice_votes], + [([election_pub_key], 3)], + election_id=valid_election.id)\ + .sign([alice.private_key]) assert alice_casted_vote.validate(b_mock) key0_votes = delegate_vote.to_inputs()[1] - key0_casted_vote = ValidatorElectionVote.generate([key0_votes], - [([election_pub_key], votes-3)], - election_id=valid_election.id)\ - .sign([key0.private_key]) + key0_casted_vote = Vote.generate([key0_votes], + [([election_pub_key], votes-3)], + election_id=valid_election.id)\ + .sign([key0.private_key]) assert key0_casted_vote.validate(b_mock) @@ -103,10 +104,10 @@ def test_upsert_validator_invalid_election_vote(b_mock, valid_election, ed25519_ election_pub_key = ValidatorElection.to_public_key(valid_election.id) - vote = ValidatorElectionVote.generate([input0], - [([election_pub_key], votes+1)], - election_id=valid_election.id)\ - .sign([key0.private_key]) + vote = Vote.generate([input0], + [([election_pub_key], votes+1)], + election_id=valid_election.id)\ + .sign([key0.private_key]) with pytest.raises(AmountError): assert vote.validate(b_mock) @@ -125,10 +126,10 @@ def test_valid_election_votes_received(b_mock, valid_election, ed25519_node_keys key0 = ed25519_node_keys[public_key0] # delegate some votes to alice - delegate_vote = ValidatorElectionVote.generate([input0], - [([alice.public_key], 4), ([key0.public_key], votes-4)], - election_id=valid_election.id)\ - .sign([key0.private_key]) + delegate_vote = Vote.generate([input0], + [([alice.public_key], 4), ([key0.public_key], votes-4)], + election_id=valid_election.id)\ + .sign([key0.private_key]) b_mock.store_bulk_transactions([delegate_vote]) assert valid_election.get_commited_votes(b_mock) == 0 @@ -136,10 +137,10 @@ def test_valid_election_votes_received(b_mock, valid_election, ed25519_node_keys alice_votes = delegate_vote.to_inputs()[0] key0_votes = delegate_vote.to_inputs()[1] - alice_casted_vote = ValidatorElectionVote.generate([alice_votes], - [([election_public_key], 2), ([alice.public_key], 2)], - election_id=valid_election.id)\ - .sign([alice.private_key]) + alice_casted_vote = Vote.generate([alice_votes], + [([election_public_key], 2), ([alice.public_key], 2)], + election_id=valid_election.id)\ + .sign([alice.private_key]) assert alice_casted_vote.validate(b_mock) b_mock.store_bulk_transactions([alice_casted_vote]) @@ -147,10 +148,10 @@ def test_valid_election_votes_received(b_mock, valid_election, ed25519_node_keys # Check if the delegated vote is count as valid vote assert valid_election.get_commited_votes(b_mock) == 2 - key0_casted_vote = ValidatorElectionVote.generate([key0_votes], - [([election_public_key], votes-4)], - election_id=valid_election.id)\ - .sign([key0.private_key]) + key0_casted_vote = Vote.generate([key0_votes], + [([election_public_key], votes-4)], + election_id=valid_election.id)\ + .sign([key0.private_key]) assert key0_casted_vote.validate(b_mock) b_mock.store_bulk_transactions([key0_casted_vote]) @@ -356,10 +357,10 @@ def to_inputs(election, i, ed25519_node_keys): def gen_vote(election, i, ed25519_node_keys): (input_i, votes_i, key_i) = to_inputs(election, i, ed25519_node_keys) election_pub_key = ValidatorElection.to_public_key(election.id) - return ValidatorElectionVote.generate([input_i], - [([election_pub_key], votes_i)], - election_id=election.id)\ - .sign([key_i.private_key]) + return Vote.generate([input_i], + [([election_pub_key], votes_i)], + election_id=election.id)\ + .sign([key_i.private_key]) def reset_validator_set(b, node_keys, height):