diff --git a/bigchaindb/backend/localmongodb/query.py b/bigchaindb/backend/localmongodb/query.py index 20666266..b7b21d8d 100644 --- a/bigchaindb/backend/localmongodb/query.py +++ b/bigchaindb/backend/localmongodb/query.py @@ -278,13 +278,15 @@ def get_pre_commit_state(conn, commit_id): @register_query(LocalMongoDBConnection) -def store_validator_set(conn, validator_update): - try: - return conn.run( - conn.collection('validators') - .insert_one(validator_update)) - except DuplicateKeyError: - raise MultipleValidatorOperationError('Validator update already exists') +def store_validator_set(conn, validators_update): + height = validators_update['height'] + return conn.run( + conn.collection('validators').update_one( + {"height": height}, + {"$set": validators_update}, + upsert=True + ) + ) @register_query(LocalMongoDBConnection) diff --git a/bigchaindb/core.py b/bigchaindb/core.py index 31058ffa..bfcc97e9 100644 --- a/bigchaindb/core.py +++ b/bigchaindb/core.py @@ -18,6 +18,7 @@ from abci.types_pb2 import ( from bigchaindb import BigchainDB from bigchaindb.tendermint_utils import (decode_transaction, + public_key_to_base64, calculate_hash) from bigchaindb.lib import Block, PreCommitState from bigchaindb.backend.query import PRE_COMMIT_ID @@ -135,6 +136,8 @@ class App(BaseApplication): # TODO: calculate if an election has concluded # NOTE: ensure the local validator set is updated validator_updates = self.bigchaindb.get_validator_update(self.block_transactions) + 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 = [encode_validator(v) for v in validator_updates] # Store pre-commit state to recover in case there is a crash @@ -180,7 +183,21 @@ def encode_validator(v): def decode_validator(v): - return {'address': codecs.encode(v.address, 'hex').decode().upper().rstrip('\n'), - 'pub_key': {'type': v.pub_key.type, + return {'pub_key': {'type': v.pub_key.type, 'data': codecs.encode(v.pub_key.data, 'base64').decode().rstrip('\n')}, 'voting_power': v.power} + + +def new_validator_set(bigchain, height, updates): + validators = bigchain.get_validators(height) + validators_dict = {} + for v in validators: + validators_dict[v['pub_key']['data']] = v + + updates_dict = {} + for u in updates: + updates_dict[u['public_key']] = {'pub_key': {'type': 'ed25519', + 'data': public_key_to_base64(u['public_key']) }, + 'voting_power': u['power']} + new_validators_dict = {**validators_dict, **updates_dict} + return list(new_validators_dict.values()) diff --git a/bigchaindb/lib.py b/bigchaindb/lib.py index 444e56d4..ebc549c8 100644 --- a/bigchaindb/lib.py +++ b/bigchaindb/lib.py @@ -465,9 +465,6 @@ class BigchainDB(object): def get_validators(self, height=None): result = backend.query.get_validator_set(self.connection, height) validators = result['validators'] - for v in validators: - v.pop('address') - return validators def get_validator_update(self, txns): diff --git a/tests/upsert_validator/test_validator_election_vote.py b/tests/upsert_validator/test_validator_election_vote.py index fa3d6296..ad77784f 100644 --- a/tests/upsert_validator/test_validator_election_vote.py +++ b/tests/upsert_validator/test_validator_election_vote.py @@ -226,8 +226,7 @@ def test_upsert_validator(b, node_key, node_keys, new_validator, ed25519_node_ke conn = connect() (node_pub, _) = list(node_keys.items())[0] - validators = [{'address': 'some_address', - 'pub_key': {'type': 'ed25519', + validators = [{'pub_key': {'type': 'ed25519', 'data': node_pub}, 'voting_power': 10}] @@ -241,6 +240,7 @@ def test_upsert_validator(b, node_key, node_keys, new_validator, ed25519_node_ke power = 1 public_key = '9B3119650DF82B9A5D8A12E38953EA47475C09F0C48A4E6A0ECE182944B24403' + public_key64 = public_key_to_base64(public_key) new_validator = {'public_key': public_key, 'node_id': 'some_node_id', 'power': power} @@ -266,7 +266,13 @@ def test_upsert_validator(b, node_key, node_keys, new_validator, ed25519_node_ke for v in resp.json()['result']['validators']: validator_pub_keys.append(v['pub_key']['value']) - assert (public_key_to_base64(public_key) in validator_pub_keys) + assert (public_key64 in validator_pub_keys) + new_validator_set = b.get_validators() + validator_pub_keys = [] + for v in new_validator_set: + validator_pub_keys.append(v['pub_key']['data']) + + assert (public_key64 in validator_pub_keys) # ============================================================================