diff --git a/bigchaindb/backend/localmongodb/query.py b/bigchaindb/backend/localmongodb/query.py index 48e980d0..6fc5ba80 100644 --- a/bigchaindb/backend/localmongodb/query.py +++ b/bigchaindb/backend/localmongodb/query.py @@ -283,6 +283,18 @@ def store_validator_set(conn, validators_update): ) +@register_query(LocalMongoDBConnection) +def store_election(conn, election): + height = election['height'] + return conn.run( + conn.collection('elections').replace_one( + {'height': height}, + election, + upsert=True + ) + ) + + @register_query(LocalMongoDBConnection) def get_validator_set(conn, height=None): query = {} @@ -300,11 +312,11 @@ def get_validator_set(conn, height=None): @register_query(LocalMongoDBConnection) -def get_election_result_by_id(conn, election_id, table): +def get_election(conn, election_id): query = {'election_id': election_id} cursor = conn.run( - conn.collection(table) + conn.collection('elections') .find(query, projection={'_id': False}) ) diff --git a/bigchaindb/backend/query.py b/bigchaindb/backend/query.py index 89995eff..30daf009 100644 --- a/bigchaindb/backend/query.py +++ b/bigchaindb/backend/query.py @@ -351,6 +351,13 @@ def store_validator_set(conn, validator_update): raise NotImplementedError +@singledispatch +def store_election(conn, validator_update): + """Store election results""" + + raise NotImplementedError + + @singledispatch def get_validator_set(conn, height): """Get validator set for a given `height`, if `height` is not specified @@ -361,7 +368,7 @@ def get_validator_set(conn, height): @singledispatch -def get_election_result_by_id(conn, election_id, table): +def get_election(conn, election_id): """Return a validator set change with the specified election_id """ diff --git a/bigchaindb/common/election.py b/bigchaindb/common/election.py index 7c07fe8b..f4a81ec3 100644 --- a/bigchaindb/common/election.py +++ b/bigchaindb/common/election.py @@ -23,8 +23,6 @@ class Election(Transaction): # NOTE: this transaction class extends create so the operation inheritance is achieved # by setting an ELECTION_TYPE and renaming CREATE = ELECTION_TYPE and ALLOWED_OPERATIONS = (ELECTION_TYPE,) ELECTION_TYPE = None - # the name of the mongodb table managed by the election - DB_TABLE = None # the model for votes issued by the election VOTE_TYPE = None # Election Statuses: @@ -160,7 +158,7 @@ class Election(Transaction): @classmethod def to_public_key(cls, election_id): - return base58.b58encode(bytes.fromhex(election_id)) + return base58.b58encode(bytes.fromhex(election_id)).decode() @classmethod def count_votes(cls, election_pk, transactions, getter=getattr): @@ -207,7 +205,7 @@ class Election(Transaction): return False def get_status(self, bigchain): - concluded = self.get_election_result(self.id, bigchain) + concluded = self.get_election(self.id, bigchain) if concluded: return self.CONCLUDED @@ -220,10 +218,14 @@ class Election(Transaction): else: return self.ONGOING - def get_election_result(self, election_id, bigchain): - result = bigchain.get_election_result_by_id(election_id, self.DB_TABLE) + def get_election(self, election_id, bigchain): + result = bigchain.get_election(election_id) return result + @classmethod + def store_election(cls, bigchain, election, height): + bigchain.store_election(height, election) + @classmethod def is_approved(cls, bigchain, new_height, txns): votes = {} @@ -240,6 +242,7 @@ class Election(Transaction): # Once an election concludes any other conclusion for the same # or any other election is invalidated if election: + cls.store_election(bigchain, election, new_height) return cls.on_approval(bigchain, election, new_height) return [] diff --git a/bigchaindb/lib.py b/bigchaindb/lib.py index 94268b12..f0f5a348 100644 --- a/bigchaindb/lib.py +++ b/bigchaindb/lib.py @@ -428,8 +428,8 @@ class BigchainDB(object): result = self.get_validator_change(height) return [] if result is None else result['validators'] - def get_election_result_by_id(self, election_id, table): - result = backend.query.get_election_result_by_id(self.connection, election_id, table) + def get_election(self, election_id): + result = backend.query.get_election(self.connection, election_id) return result def store_pre_commit_state(self, state): @@ -475,6 +475,14 @@ class BigchainDB(object): self.store_abci_chain(block['height'] + 1, new_chain_id, False) + def store_election(self, height, election): + """Store election results + :param height: the block height at which the election concluded + :param election: a concluded election + """ + return backend.query.store_election(self.connection, {'height': height, + 'election_id': election.id}) + Block = namedtuple('Block', ('app_hash', 'height', 'transactions')) diff --git a/tests/upsert_validator/conftest.py b/tests/upsert_validator/conftest.py index 20906ada..8bb472f4 100644 --- a/tests/upsert_validator/conftest.py +++ b/tests/upsert_validator/conftest.py @@ -62,12 +62,10 @@ def ongoing_election(b, valid_election, ed25519_node_keys): @pytest.fixture def concluded_election(b, ongoing_election, ed25519_node_keys): - validators = b.get_validators(height=1) - validator_update = {'validators': validators, - 'height': 2, - 'election_id': ongoing_election.id} + election_result = {'height': 2, + 'election_id': ongoing_election.id} - query.store_validator_set(b.connection, validator_update) + query.store_election(b.connection, election_result) return ongoing_election