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
This commit is contained in:
z-bowen 2018-09-04 17:13:34 +02:00
parent 84a7cf7657
commit 1e3caf8ccd
10 changed files with 66 additions and 67 deletions

View File

@ -94,9 +94,9 @@ _config = copy.deepcopy(config)
from bigchaindb.common.transaction import Transaction # noqa from bigchaindb.common.transaction import Transaction # noqa
from bigchaindb import models # noqa from bigchaindb import models # noqa
from bigchaindb.upsert_validator import ValidatorElection # 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.CREATE, models.Transaction)
Transaction.register_type(Transaction.TRANSFER, models.Transaction) Transaction.register_type(Transaction.TRANSFER, models.Transaction)
Transaction.register_type(ValidatorElection.ELECTION_TYPE, ValidatorElection) Transaction.register_type(ValidatorElection.ELECTION_TYPE, ValidatorElection)
Transaction.register_type(ValidatorElectionVote.VALIDATOR_ELECTION_VOTE, ValidatorElectionVote) Transaction.register_type(Vote.VOTE, Vote)

View File

@ -17,9 +17,10 @@ from bigchaindb.utils import load_node_key
from bigchaindb.common.exceptions import (DatabaseAlreadyExists, from bigchaindb.common.exceptions import (DatabaseAlreadyExists,
DatabaseDoesNotExist, DatabaseDoesNotExist,
ValidationError) ValidationError)
from bigchaindb.common.vote import Vote
import bigchaindb import bigchaindb
from bigchaindb import (backend, ValidatorElection, from bigchaindb import (backend, ValidatorElection,
BigchainDB, ValidatorElectionVote) BigchainDB)
from bigchaindb.backend import schema from bigchaindb.backend import schema
from bigchaindb.backend import query from bigchaindb.backend import query
from bigchaindb.backend.query import PRE_COMMIT_ID from bigchaindb.backend.query import PRE_COMMIT_ID
@ -175,7 +176,7 @@ def run_upsert_validator_approve(args, bigchain):
inputs = [i for i in tx.to_inputs() if key.public_key in i.owners_before] 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) election_pub_key = ValidatorElection.to_public_key(tx.id)
approval = ValidatorElectionVote.generate(inputs, approval = Vote.generate(inputs,
[([election_pub_key], voting_power)], [([election_pub_key], voting_power)],
tx.id).sign([key.private_key]) tx.id).sign([key.private_key])
approval.validate(bigchain) approval.validate(bigchain)

View File

@ -5,6 +5,7 @@
import base58 import base58
from bigchaindb import backend from bigchaindb import backend
from bigchaindb.common.vote import Vote
from bigchaindb.common.exceptions import (InvalidSignature, from bigchaindb.common.exceptions import (InvalidSignature,
MultipleInputsError, MultipleInputsError,
InvalidProposer, InvalidProposer,
@ -24,7 +25,7 @@ class Election(Transaction):
# by setting an ELECTION_TYPE and renaming CREATE = ELECTION_TYPE and ALLOWED_OPERATIONS = (ELECTION_TYPE,) # by setting an ELECTION_TYPE and renaming CREATE = ELECTION_TYPE and ALLOWED_OPERATIONS = (ELECTION_TYPE,)
ELECTION_TYPE = None ELECTION_TYPE = None
# the model for votes issued by the election # the model for votes issued by the election
VOTE_TYPE = None VOTE_TYPE = Vote
# Election Statuses: # Election Statuses:
ONGOING = 'ongoing' ONGOING = 'ongoing'
CONCLUDED = 'concluded' CONCLUDED = 'concluded'
@ -164,7 +165,7 @@ class Election(Transaction):
def count_votes(cls, election_pk, transactions, getter=getattr): def count_votes(cls, election_pk, transactions, getter=getattr):
votes = 0 votes = 0
for txn in transactions: for txn in transactions:
if getter(txn, 'operation') == 'VALIDATOR_ELECTION_VOTE': if getter(txn, 'operation') == 'VOTE':
for output in getter(txn, 'outputs'): for output in getter(txn, 'outputs'):
# NOTE: We enforce that a valid vote to election id will have only # 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 # election_pk in the output public keys, including any other public key

View File

@ -63,7 +63,7 @@ definitions:
- CREATE - CREATE
- TRANSFER - TRANSFER
- VALIDATOR_ELECTION - VALIDATOR_ELECTION
- VALIDATOR_ELECTION_VOTE - VOTE
asset: asset:
type: object type: object
additionalProperties: false additionalProperties: false

View File

@ -5,14 +5,14 @@
--- ---
"$schema": "http://json-schema.org/draft-04/schema#" "$schema": "http://json-schema.org/draft-04/schema#"
type: object type: object
title: Validator Election Vote Schema - Vote on a validator set change title: Vote Schema - Vote on an election
required: required:
- operation - operation
- outputs - outputs
properties: properties:
operation: operation:
type: string type: string
value: "VALIDATOR_ELECTION_VOTE" value: "VOTE"
outputs: outputs:
type: array type: array
items: items:

View File

@ -9,13 +9,13 @@ from bigchaindb.common.schema import (_validate_schema,
TX_SCHEMA_VALIDATOR_ELECTION_VOTE) 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 # NOTE: This class inherits TRANSFER txn type. The `TRANSFER` property is
# overriden to re-use methods from parent class # overriden to re-use methods from parent class
TRANSFER = VALIDATOR_ELECTION_VOTE TRANSFER = VOTE
ALLOWED_OPERATIONS = (VALIDATOR_ELECTION_VOTE,) ALLOWED_OPERATIONS = (VOTE,)
def validate(self, bigchain, current_transactions=[]): def validate(self, bigchain, current_transactions=[]):
"""Validate election vote transaction """Validate election vote transaction
@ -28,7 +28,7 @@ class ValidatorElectionVote(Transaction):
bigchain (BigchainDB): an instantiated bigchaindb.lib.BigchainDB object. bigchain (BigchainDB): an instantiated bigchaindb.lib.BigchainDB object.
Returns: Returns:
ValidatorElectionVote object Vote object
Raises: Raises:
ValidationError: If the election vote is invalid ValidationError: If the election vote is invalid
@ -39,7 +39,7 @@ class ValidatorElectionVote(Transaction):
@classmethod @classmethod
def generate(cls, inputs, recipients, election_id, metadata=None): def generate(cls, inputs, recipients, election_id, metadata=None):
(inputs, outputs) = cls.validate_transfer(inputs, recipients, election_id, metadata) (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) cls.validate_schema(election_vote.to_dict(), skip_id=True)
return election_vote return election_vote

View File

@ -3,5 +3,4 @@
# Code is Apache-2.0 and docs are CC-BY-4.0 # 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 from bigchaindb.upsert_validator.validator_election import ValidatorElection # noqa

View File

@ -6,7 +6,6 @@ from bigchaindb.common.exceptions import InvalidPowerChange
from bigchaindb.common.election import Election from bigchaindb.common.election import Election
from bigchaindb.common.schema import (_validate_schema, from bigchaindb.common.schema import (_validate_schema,
TX_SCHEMA_VALIDATOR_ELECTION) TX_SCHEMA_VALIDATOR_ELECTION)
from . import ValidatorElectionVote
from .validator_utils import (new_validator_set, encode_validator) from .validator_utils import (new_validator_set, encode_validator)
@ -17,8 +16,6 @@ class ValidatorElection(Election):
# by renaming CREATE to VALIDATOR_ELECTION # by renaming CREATE to VALIDATOR_ELECTION
CREATE = ELECTION_TYPE CREATE = ELECTION_TYPE
ALLOWED_OPERATIONS = (ELECTION_TYPE,) ALLOWED_OPERATIONS = (ELECTION_TYPE,)
DB_TABLE = 'validators'
VOTE_TYPE = ValidatorElectionVote
def validate(self, bigchain, current_transactions=[]): def validate(self, bigchain, current_transactions=[]):
"""For more details refer BEP-21: https://github.com/bigchaindb/BEPs/tree/master/21 """For more details refer BEP-21: https://github.com/bigchaindb/BEPs/tree/master/21

View File

@ -4,7 +4,7 @@
import pytest import pytest
from bigchaindb import ValidatorElectionVote from bigchaindb import Vote
from bigchaindb.backend.localmongodb import query from bigchaindb.backend.localmongodb import query
from bigchaindb.lib import Block from bigchaindb.lib import Block
from bigchaindb.upsert_validator import ValidatorElection from bigchaindb.upsert_validator import ValidatorElection
@ -89,7 +89,7 @@ def vote(election, voter, keys, b):
election_pub_key = ValidatorElection.to_public_key(election.id) election_pub_key = ValidatorElection.to_public_key(election.id)
v = ValidatorElectionVote.generate([election_input], v = Vote.generate([election_input],
[([election_pub_key], votes)], [([election_pub_key], votes)],
election_id=election.id)\ election_id=election.id)\
.sign([key.private_key]) .sign([key.private_key])

View File

@ -6,10 +6,11 @@ import pytest
import codecs import codecs
from bigchaindb.tendermint_utils import public_key_to_base64 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.exceptions import AmountError
from bigchaindb.common.crypto import generate_key_pair from bigchaindb.common.crypto import generate_key_pair
from bigchaindb.common.exceptions import ValidationError from bigchaindb.common.exceptions import ValidationError
from bigchaindb.common.vote import Vote
from tests.utils import generate_block from tests.utils import generate_block
pytestmark = [pytest.mark.execute] pytestmark = [pytest.mark.execute]
@ -27,7 +28,7 @@ def test_upsert_validator_valid_election_vote(b_mock, valid_election, ed25519_no
election_pub_key = ValidatorElection.to_public_key(valid_election.id) election_pub_key = ValidatorElection.to_public_key(valid_election.id)
vote = ValidatorElectionVote.generate([input0], vote = Vote.generate([input0],
[([election_pub_key], votes)], [([election_pub_key], votes)],
election_id=valid_election.id)\ election_id=valid_election.id)\
.sign([key0.private_key]) .sign([key0.private_key])
@ -48,7 +49,7 @@ def test_upsert_validator_valid_non_election_vote(b_mock, valid_election, ed2551
# Ensure that threshold conditions are now allowed # Ensure that threshold conditions are now allowed
with pytest.raises(ValidationError): with pytest.raises(ValidationError):
ValidatorElectionVote.generate([input0], Vote.generate([input0],
[([election_pub_key, key0.public_key], votes)], [([election_pub_key, key0.public_key], votes)],
election_id=valid_election.id)\ election_id=valid_election.id)\
.sign([key0.private_key]) .sign([key0.private_key])
@ -66,7 +67,7 @@ def test_upsert_validator_delegate_election_vote(b_mock, valid_election, ed25519
public_key0 = input0.owners_before[0] public_key0 = input0.owners_before[0]
key0 = ed25519_node_keys[public_key0] key0 = ed25519_node_keys[public_key0]
delegate_vote = ValidatorElectionVote.generate([input0], delegate_vote = Vote.generate([input0],
[([alice.public_key], 3), ([key0.public_key], votes-3)], [([alice.public_key], 3), ([key0.public_key], votes-3)],
election_id=valid_election.id)\ election_id=valid_election.id)\
.sign([key0.private_key]) .sign([key0.private_key])
@ -77,14 +78,14 @@ def test_upsert_validator_delegate_election_vote(b_mock, valid_election, ed25519
election_pub_key = ValidatorElection.to_public_key(valid_election.id) election_pub_key = ValidatorElection.to_public_key(valid_election.id)
alice_votes = delegate_vote.to_inputs()[0] alice_votes = delegate_vote.to_inputs()[0]
alice_casted_vote = ValidatorElectionVote.generate([alice_votes], alice_casted_vote = Vote.generate([alice_votes],
[([election_pub_key], 3)], [([election_pub_key], 3)],
election_id=valid_election.id)\ election_id=valid_election.id)\
.sign([alice.private_key]) .sign([alice.private_key])
assert alice_casted_vote.validate(b_mock) assert alice_casted_vote.validate(b_mock)
key0_votes = delegate_vote.to_inputs()[1] key0_votes = delegate_vote.to_inputs()[1]
key0_casted_vote = ValidatorElectionVote.generate([key0_votes], key0_casted_vote = Vote.generate([key0_votes],
[([election_pub_key], votes-3)], [([election_pub_key], votes-3)],
election_id=valid_election.id)\ election_id=valid_election.id)\
.sign([key0.private_key]) .sign([key0.private_key])
@ -103,7 +104,7 @@ def test_upsert_validator_invalid_election_vote(b_mock, valid_election, ed25519_
election_pub_key = ValidatorElection.to_public_key(valid_election.id) election_pub_key = ValidatorElection.to_public_key(valid_election.id)
vote = ValidatorElectionVote.generate([input0], vote = Vote.generate([input0],
[([election_pub_key], votes+1)], [([election_pub_key], votes+1)],
election_id=valid_election.id)\ election_id=valid_election.id)\
.sign([key0.private_key]) .sign([key0.private_key])
@ -125,7 +126,7 @@ def test_valid_election_votes_received(b_mock, valid_election, ed25519_node_keys
key0 = ed25519_node_keys[public_key0] key0 = ed25519_node_keys[public_key0]
# delegate some votes to alice # delegate some votes to alice
delegate_vote = ValidatorElectionVote.generate([input0], delegate_vote = Vote.generate([input0],
[([alice.public_key], 4), ([key0.public_key], votes-4)], [([alice.public_key], 4), ([key0.public_key], votes-4)],
election_id=valid_election.id)\ election_id=valid_election.id)\
.sign([key0.private_key]) .sign([key0.private_key])
@ -136,7 +137,7 @@ def test_valid_election_votes_received(b_mock, valid_election, ed25519_node_keys
alice_votes = delegate_vote.to_inputs()[0] alice_votes = delegate_vote.to_inputs()[0]
key0_votes = delegate_vote.to_inputs()[1] key0_votes = delegate_vote.to_inputs()[1]
alice_casted_vote = ValidatorElectionVote.generate([alice_votes], alice_casted_vote = Vote.generate([alice_votes],
[([election_public_key], 2), ([alice.public_key], 2)], [([election_public_key], 2), ([alice.public_key], 2)],
election_id=valid_election.id)\ election_id=valid_election.id)\
.sign([alice.private_key]) .sign([alice.private_key])
@ -147,7 +148,7 @@ def test_valid_election_votes_received(b_mock, valid_election, ed25519_node_keys
# Check if the delegated vote is count as valid vote # Check if the delegated vote is count as valid vote
assert valid_election.get_commited_votes(b_mock) == 2 assert valid_election.get_commited_votes(b_mock) == 2
key0_casted_vote = ValidatorElectionVote.generate([key0_votes], key0_casted_vote = Vote.generate([key0_votes],
[([election_public_key], votes-4)], [([election_public_key], votes-4)],
election_id=valid_election.id)\ election_id=valid_election.id)\
.sign([key0.private_key]) .sign([key0.private_key])
@ -356,7 +357,7 @@ def to_inputs(election, i, ed25519_node_keys):
def gen_vote(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) (input_i, votes_i, key_i) = to_inputs(election, i, ed25519_node_keys)
election_pub_key = ValidatorElection.to_public_key(election.id) election_pub_key = ValidatorElection.to_public_key(election.id)
return ValidatorElectionVote.generate([input_i], return Vote.generate([input_i],
[([election_pub_key], votes_i)], [([election_pub_key], votes_i)],
election_id=election.id)\ election_id=election.id)\
.sign([key_i.private_key]) .sign([key_i.private_key])