Problem: Validator set not updated upon election conclusion

Solution: Update the validator set tracked by BigchainDB
This commit is contained in:
Vanshdeep Singh 2018-08-08 11:27:22 +02:00
parent b12856a9df
commit ae8f494396
4 changed files with 37 additions and 15 deletions

View File

@ -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)

View File

@ -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())

View File

@ -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):

View File

@ -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)
# ============================================================================