moved election methods to planetmint

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>
This commit is contained in:
Lorenz Herzberger 2022-09-28 22:18:41 +02:00
parent e0d09198d9
commit b397cc98b6
No known key found for this signature in database
GPG Key ID: FA5EE906EB55316A
5 changed files with 43 additions and 58 deletions

View File

@ -44,6 +44,7 @@ from planetmint.transactions.common.transaction_mode_types import (
)
from planetmint.tendermint_utils import encode_transaction, merkleroot, key_from_base64
from planetmint import exceptions as core_exceptions
from planetmint.transactions.types.elections.election import Election
from planetmint.validation import BaseValidationRules
logger = logging.getLogger(__name__)
@ -499,11 +500,11 @@ class Planetmint(object):
def fastquery(self):
return fastquery.FastQuery(self.connection)
def get_validator_change(self, height=None):
def get_validator_set(self, height=None):
return backend.query.get_validator_set(self.connection, height)
def get_validators(self, height=None):
result = self.get_validator_change(height)
result = self.get_validator_set(height)
return [] if result is None else result["validators"]
def get_election(self, election_id):
@ -682,12 +683,41 @@ class Planetmint(object):
current_validators = self.get_validators_dict()
# super(ValidatorElection, self).validate(planet, current_transactions=current_transactions)
# NOTE: change more than 1/3 of the current power is not allowed
if transaction.asset["data"]["power"] >= (1 / 3) * sum(current_validators.values()):
raise InvalidPowerChange("`power` change must be less than 1/3 of total power")
return transaction
def get_election_status(self, transaction):
election = self.get_election(transaction.id)
if election and election["is_concluded"]:
return Election.CONCLUDED
return Election.INCONCLUSIVE if self.has_validator_set_changed(transaction) else Election.ONGOING
def has_validator_set_changed(self, transaction): # TODO: move somewhere else
latest_change = self.get_validator_change()
if latest_change is None:
return False
latest_change_height = latest_change["height"]
election = self.get_election(transaction.id)
return latest_change_height > election["height"]
def get_validator_change(self): # TODO: move somewhere else
"""Return the validator set from the most recent approved block
:return: {
'height': <block_height>,
'validators': <validator_set>
}
"""
latest_block = self.get_latest_block()
if latest_block is None:
return None
return self.get_validator_set(latest_block["height"])
Block = namedtuple("Block", ("app_hash", "height", "transactions"))

View File

@ -10,13 +10,6 @@ from typing import Optional
from planetmint import backend
from planetmint.transactions.types.elections.vote import Vote
from planetmint.transactions.common.exceptions import (
InvalidSignature,
MultipleInputsError,
InvalidProposer,
UnequalValidatorSet,
DuplicateTransaction,
)
from planetmint.tendermint_utils import key_from_base64, public_key_to_base64
from planetmint.transactions.common.crypto import public_key_from_ed25519_key
from planetmint.transactions.common.transaction import Transaction
@ -41,20 +34,6 @@ class Election(Transaction):
# Vote ratio to approve an election
ELECTION_THRESHOLD = 2 / 3
@classmethod
def get_validator_change(cls, planet): # TODO: move somewhere else
"""Return the validator set from the most recent approved block
:return: {
'height': <block_height>,
'validators': <validator_set>
}
"""
latest_block = planet.get_latest_block()
if latest_block is None:
return None
return planet.get_validator_change(latest_block["height"])
@classmethod
def get_validators(cls, planet, height=None): # TODO: move somewhere else
"""Return a dictionary of validators with key as `public_key` and
@ -165,7 +144,7 @@ class Election(Transaction):
Custom elections may override this function and introduce additional checks.
"""
if self.has_validator_set_changed(planet):
if planet.has_validator_set_changed(self):
return False
election_pk = self.to_public_key(self.id)
@ -178,27 +157,6 @@ class Election(Transaction):
return False
def get_status(self, planet): # TODO: move somewhere else
election = self.get_election(self.id, planet)
if election and election["is_concluded"]:
return self.CONCLUDED
return self.INCONCLUSIVE if self.has_validator_set_changed(planet) else self.ONGOING
def has_validator_set_changed(self, planet): # TODO: move somewhere else
latest_change = self.get_validator_change(planet)
if latest_change is None:
return False
latest_change_height = latest_change["height"]
election = self.get_election(self.id, planet)
return latest_change_height > election["height"]
def get_election(self, election_id, planet): # TODO: move somewhere else
return planet.get_election(election_id)
def store(self, planet, height, is_concluded): # TODO: move somewhere else
planet.store_election(self.id, height, is_concluded)
@ -210,7 +168,7 @@ class Election(Transaction):
for k, v in data.items():
if k != "seed":
response += f"{k}={v}\n"
response += f"status={self.get_status(planet)}"
response += f"status={planet.get_election_status(self)}"
return response

View File

@ -3,13 +3,10 @@
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0
from planetmint.transactions.common.exceptions import InvalidPowerChange
from planetmint.transactions.types.elections.election import Election
from planetmint.transactions.common.schema import TX_SCHEMA_VALIDATOR_ELECTION
from planetmint.transactions.common.transaction import VALIDATOR_ELECTION
# from planetmint.transactions.common.transaction import Transaction
from .validator_utils import new_validator_set, encode_validator, validate_asset_public_key
@ -28,7 +25,7 @@ class ValidatorElection(Election):
latest_block = planet.get_latest_block()
if latest_block is not None:
latest_block_height = latest_block["height"]
latest_validator_change = planet.get_validator_change()["height"]
latest_validator_change = planet.get_validator_set()["height"]
# TODO change to `latest_block_height + 3` when upgrading to Tendermint 0.24.0.
if latest_validator_change == latest_block_height + 2:

View File

@ -425,7 +425,7 @@ def test_rollback_pre_commit_state_after_crash(b):
for tx in txs:
assert b.get_transaction(tx.id)
assert b.get_latest_abci_chain()
assert len(b.get_validator_change()["validators"]) == 1
assert len(b.get_validator_set()["validators"]) == 1
assert b.get_election(migration_election.id)
assert b.get_election(validator_election.id)
@ -436,8 +436,8 @@ def test_rollback_pre_commit_state_after_crash(b):
for tx in txs:
assert not b.get_transaction(tx.id)
assert not b.get_latest_abci_chain()
assert len(b.get_validator_change()["validators"]) == 4
assert len(b.get_validator_change(2)["validators"]) == 4
assert len(b.get_validator_set()["validators"]) == 4
assert len(b.get_validator_set(2)["validators"]) == 4
assert not b.get_election(migration_election.id)
assert not b.get_election(validator_election.id)

View File

@ -112,13 +112,13 @@ def test_upsert_validator_invalid_election(b_mock, new_validator, node_key, fixe
def test_get_status_ongoing(b, ongoing_validator_election, new_validator):
status = ValidatorElection.ONGOING
resp = ongoing_validator_election.get_status(b)
resp = b.get_election_status(ongoing_validator_election)
assert resp == status
def test_get_status_concluded(b, concluded_election, new_validator):
status = ValidatorElection.CONCLUDED
resp = concluded_election.get_status(b)
resp = b.get_election_status(concluded_election)
assert resp == status
@ -169,7 +169,7 @@ def test_get_status_inconclusive(b, inconclusive_election, new_validator):
b.get_validators = custom_mock_get_validators
b.get_latest_block = set_block_height_to_3
status = ValidatorElection.INCONCLUSIVE
resp = inconclusive_election.get_status(b)
resp = b.get_election_status(inconclusive_election)
assert resp == status