mirror of
https://github.com/planetmint/planetmint.git
synced 2025-11-25 06:55:45 +00:00
moved election methods to planetmint
Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>
This commit is contained in:
parent
e0d09198d9
commit
b397cc98b6
@ -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.tendermint_utils import encode_transaction, merkleroot, key_from_base64
|
||||||
from planetmint import exceptions as core_exceptions
|
from planetmint import exceptions as core_exceptions
|
||||||
|
from planetmint.transactions.types.elections.election import Election
|
||||||
from planetmint.validation import BaseValidationRules
|
from planetmint.validation import BaseValidationRules
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -499,11 +500,11 @@ class Planetmint(object):
|
|||||||
def fastquery(self):
|
def fastquery(self):
|
||||||
return fastquery.FastQuery(self.connection)
|
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)
|
return backend.query.get_validator_set(self.connection, height)
|
||||||
|
|
||||||
def get_validators(self, height=None):
|
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"]
|
return [] if result is None else result["validators"]
|
||||||
|
|
||||||
def get_election(self, election_id):
|
def get_election(self, election_id):
|
||||||
@ -682,12 +683,41 @@ class Planetmint(object):
|
|||||||
|
|
||||||
current_validators = self.get_validators_dict()
|
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
|
# NOTE: change more than 1/3 of the current power is not allowed
|
||||||
if transaction.asset["data"]["power"] >= (1 / 3) * sum(current_validators.values()):
|
if transaction.asset["data"]["power"] >= (1 / 3) * sum(current_validators.values()):
|
||||||
raise InvalidPowerChange("`power` change must be less than 1/3 of total power")
|
raise InvalidPowerChange("`power` change must be less than 1/3 of total power")
|
||||||
|
|
||||||
return transaction
|
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"))
|
Block = namedtuple("Block", ("app_hash", "height", "transactions"))
|
||||||
|
|||||||
@ -10,13 +10,6 @@ from typing import Optional
|
|||||||
|
|
||||||
from planetmint import backend
|
from planetmint import backend
|
||||||
from planetmint.transactions.types.elections.vote import Vote
|
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.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.crypto import public_key_from_ed25519_key
|
||||||
from planetmint.transactions.common.transaction import Transaction
|
from planetmint.transactions.common.transaction import Transaction
|
||||||
@ -41,20 +34,6 @@ class Election(Transaction):
|
|||||||
# Vote ratio to approve an election
|
# Vote ratio to approve an election
|
||||||
ELECTION_THRESHOLD = 2 / 3
|
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
|
@classmethod
|
||||||
def get_validators(cls, planet, height=None): # TODO: move somewhere else
|
def get_validators(cls, planet, height=None): # TODO: move somewhere else
|
||||||
"""Return a dictionary of validators with key as `public_key` and
|
"""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.
|
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
|
return False
|
||||||
|
|
||||||
election_pk = self.to_public_key(self.id)
|
election_pk = self.to_public_key(self.id)
|
||||||
@ -178,27 +157,6 @@ class Election(Transaction):
|
|||||||
|
|
||||||
return False
|
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
|
def store(self, planet, height, is_concluded): # TODO: move somewhere else
|
||||||
planet.store_election(self.id, height, is_concluded)
|
planet.store_election(self.id, height, is_concluded)
|
||||||
|
|
||||||
@ -210,7 +168,7 @@ class Election(Transaction):
|
|||||||
for k, v in data.items():
|
for k, v in data.items():
|
||||||
if k != "seed":
|
if k != "seed":
|
||||||
response += f"{k}={v}\n"
|
response += f"{k}={v}\n"
|
||||||
response += f"status={self.get_status(planet)}"
|
response += f"status={planet.get_election_status(self)}"
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|||||||
@ -3,13 +3,10 @@
|
|||||||
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
|
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
|
||||||
# Code is Apache-2.0 and docs are 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.types.elections.election import Election
|
||||||
from planetmint.transactions.common.schema import TX_SCHEMA_VALIDATOR_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 VALIDATOR_ELECTION
|
||||||
|
|
||||||
# from planetmint.transactions.common.transaction import Transaction
|
|
||||||
|
|
||||||
from .validator_utils import new_validator_set, encode_validator, validate_asset_public_key
|
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()
|
latest_block = planet.get_latest_block()
|
||||||
if latest_block is not None:
|
if latest_block is not None:
|
||||||
latest_block_height = latest_block["height"]
|
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.
|
# TODO change to `latest_block_height + 3` when upgrading to Tendermint 0.24.0.
|
||||||
if latest_validator_change == latest_block_height + 2:
|
if latest_validator_change == latest_block_height + 2:
|
||||||
|
|||||||
@ -425,7 +425,7 @@ def test_rollback_pre_commit_state_after_crash(b):
|
|||||||
for tx in txs:
|
for tx in txs:
|
||||||
assert b.get_transaction(tx.id)
|
assert b.get_transaction(tx.id)
|
||||||
assert b.get_latest_abci_chain()
|
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(migration_election.id)
|
||||||
assert b.get_election(validator_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:
|
for tx in txs:
|
||||||
assert not b.get_transaction(tx.id)
|
assert not b.get_transaction(tx.id)
|
||||||
assert not b.get_latest_abci_chain()
|
assert not b.get_latest_abci_chain()
|
||||||
assert len(b.get_validator_change()["validators"]) == 4
|
assert len(b.get_validator_set()["validators"]) == 4
|
||||||
assert len(b.get_validator_change(2)["validators"]) == 4
|
assert len(b.get_validator_set(2)["validators"]) == 4
|
||||||
assert not b.get_election(migration_election.id)
|
assert not b.get_election(migration_election.id)
|
||||||
assert not b.get_election(validator_election.id)
|
assert not b.get_election(validator_election.id)
|
||||||
|
|
||||||
|
|||||||
@ -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):
|
def test_get_status_ongoing(b, ongoing_validator_election, new_validator):
|
||||||
status = ValidatorElection.ONGOING
|
status = ValidatorElection.ONGOING
|
||||||
resp = ongoing_validator_election.get_status(b)
|
resp = b.get_election_status(ongoing_validator_election)
|
||||||
assert resp == status
|
assert resp == status
|
||||||
|
|
||||||
|
|
||||||
def test_get_status_concluded(b, concluded_election, new_validator):
|
def test_get_status_concluded(b, concluded_election, new_validator):
|
||||||
status = ValidatorElection.CONCLUDED
|
status = ValidatorElection.CONCLUDED
|
||||||
resp = concluded_election.get_status(b)
|
resp = b.get_election_status(concluded_election)
|
||||||
assert resp == status
|
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_validators = custom_mock_get_validators
|
||||||
b.get_latest_block = set_block_height_to_3
|
b.get_latest_block = set_block_height_to_3
|
||||||
status = ValidatorElection.INCONCLUSIVE
|
status = ValidatorElection.INCONCLUSIVE
|
||||||
resp = inconclusive_election.get_status(b)
|
resp = b.get_election_status(inconclusive_election)
|
||||||
assert resp == status
|
assert resp == status
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user