From b397cc98b615a1c8f89b33e0a2ebffafeac9c170 Mon Sep 17 00:00:00 2001 From: Lorenz Herzberger Date: Wed, 28 Sep 2022 22:18:41 +0200 Subject: [PATCH] moved election methods to planetmint Signed-off-by: Lorenz Herzberger --- planetmint/lib.py | 38 +++++++++++++-- .../transactions/types/elections/election.py | 46 +------------------ .../types/elections/validator_election.py | 5 +- tests/tendermint/test_core.py | 6 +-- .../test_validator_election.py | 6 +-- 5 files changed, 43 insertions(+), 58 deletions(-) diff --git a/planetmint/lib.py b/planetmint/lib.py index 6d89bd1..830b1c8 100644 --- a/planetmint/lib.py +++ b/planetmint/lib.py @@ -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': , + 'validators': + } + """ + 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")) diff --git a/planetmint/transactions/types/elections/election.py b/planetmint/transactions/types/elections/election.py index 25bafe0..4384a66 100644 --- a/planetmint/transactions/types/elections/election.py +++ b/planetmint/transactions/types/elections/election.py @@ -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': , - 'validators': - } - """ - 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 diff --git a/planetmint/transactions/types/elections/validator_election.py b/planetmint/transactions/types/elections/validator_election.py index 814514d..40d56cb 100644 --- a/planetmint/transactions/types/elections/validator_election.py +++ b/planetmint/transactions/types/elections/validator_election.py @@ -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: diff --git a/tests/tendermint/test_core.py b/tests/tendermint/test_core.py index 967c3b7..1884356 100644 --- a/tests/tendermint/test_core.py +++ b/tests/tendermint/test_core.py @@ -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) diff --git a/tests/upsert_validator/test_validator_election.py b/tests/upsert_validator/test_validator_election.py index 6a71fad..51068c6 100644 --- a/tests/upsert_validator/test_validator_election.py +++ b/tests/upsert_validator/test_validator_election.py @@ -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