Make the use of string literal type hints compatible with PEP 484

Because:
- Not doing so causes F821 linting errors

https://peps.python.org/pep-0484/#forward-references
https://www.flake8rules.com/rules/F821.html
pull/3159/head
Owen Campbell 2023-06-27 12:41:53 +01:00
parent 905de7de5d
commit a4de8a882e
No known key found for this signature in database
GPG Key ID: 628F79BCBE9C2B73
16 changed files with 237 additions and 170 deletions

View File

@ -11,6 +11,7 @@ import maya
from eth_typing import ChecksumAddress
from nucypher_core import FleetStateChecksum, NodeMetadata
from nucypher import characters
from nucypher.utilities.logging import Logger
from .nicknames import Nickname
@ -41,7 +42,7 @@ class StateDiff(NamedTuple):
class FleetState:
"""
Fleet state as perceived by a local Ursula.
Fleet state as perceived by a local "lawful.Ursula".
Assumptions we're based on:
@ -57,7 +58,9 @@ class FleetState:
"""
@classmethod
def new(cls, this_node: Optional['Ursula'] = None) -> 'FleetState':
def new(
cls, this_node: Optional["characters.lawful.Ursula"] = None
) -> "FleetState":
this_node_ref = weakref.ref(this_node) if this_node else None
# `this_node` might not have its metadata available yet.
this_node_metadata = None
@ -66,12 +69,16 @@ class FleetState:
this_node_ref=this_node_ref,
this_node_metadata=this_node_metadata)
def __init__(self,
nodes: Dict[ChecksumAddress, 'Ursula'],
this_node_ref: Optional[weakref.ReferenceType],
this_node_metadata: Optional[NodeMetadata]):
self.checksum = FleetStateChecksum(this_node=this_node_metadata,
other_nodes=[node.metadata() for node in nodes.values()])
def __init__(
self,
nodes: Dict[ChecksumAddress, "characters.lawful.Ursula"],
this_node_ref: Optional[weakref.ReferenceType],
this_node_metadata: Optional[NodeMetadata],
):
self.checksum = FleetStateChecksum(
this_node=this_node_metadata,
other_nodes=[node.metadata() for node in nodes.values()],
)
self.nickname = Nickname.from_seed(bytes(self.checksum), length=1)
self._nodes = nodes
self.timestamp = maya.now()
@ -84,12 +91,12 @@ class FleetState:
timestamp=self.timestamp,
population=self.population)
def _calculate_diff(self,
this_node_updated: bool,
nodes_to_add: Iterable['Ursula'],
nodes_to_remove: Iterable[ChecksumAddress]
) -> StateDiff:
def _calculate_diff(
self,
this_node_updated: bool,
nodes_to_add: Iterable["characters.lawful.Ursula"],
nodes_to_remove: Iterable[ChecksumAddress],
) -> StateDiff:
nodes_updated = []
for node in nodes_to_add:
if node.checksum_address in nodes_to_remove:
@ -107,12 +114,12 @@ class FleetState:
nodes_updated=nodes_updated,
nodes_removed=nodes_removed)
def with_updated_nodes(self,
nodes_to_add: Iterable['Ursula'],
nodes_to_remove: Iterable[ChecksumAddress],
skip_this_node: bool = False,
) -> 'FleetState':
def with_updated_nodes(
self,
nodes_to_add: Iterable["characters.lawful.Ursula"],
nodes_to_remove: Iterable[ChecksumAddress],
skip_this_node: bool = False,
) -> "FleetState":
if self._this_node_ref is not None and not skip_this_node:
this_node = self._this_node_ref()
this_node_metadata = this_node.metadata()
@ -169,7 +176,7 @@ class FleetState:
def __len__(self):
return len(self._nodes)
def shuffled(self) -> List['Ursula']:
def shuffled(self) -> List["characters.lawful.Ursula"]:
nodes_we_know_about = list(self._nodes.values())
random.shuffle(nodes_we_know_about)
return nodes_we_know_about
@ -206,8 +213,9 @@ class FleetSensor:
"""
log = Logger("Learning")
def __init__(self, domain: str, this_node: Optional['Ursula'] = None):
def __init__(
self, domain: str, this_node: Optional["characters.lawful.Ursula"] = None
):
self._domain = domain
self._current_state = FleetState.new(this_node)
@ -221,7 +229,7 @@ class FleetSensor:
self._auto_update_state = False
def record_node(self, node: 'Ursula'):
def record_node(self, node: "characters.lawful.Ursula"):
if node.domain == self._domain:
# Replace the existing object with a newer object, even if they're equal
@ -330,7 +338,7 @@ class FleetSensor:
def shuffled(self):
return self._current_state.shuffled()
def mark_as(self, label: Exception, node: 'Ursula'):
def mark_as(self, label: Exception, node: "characters.lawful.Ursula"):
# TODO: for now we're not using `label` in any way, so we're just ignoring it
self._nodes_to_remove.add(node.checksum_address)
@ -352,8 +360,10 @@ class FleetSensor:
self._remote_last_seen[checksum_address] = maya.now()
self._remote_states[checksum_address] = state
def status_info(self, checksum_address_or_node: Union[ChecksumAddress, 'Ursula']) -> 'RemoteUrsulaStatus':
def status_info(
self,
checksum_address_or_node: Union[ChecksumAddress, "characters.lawful.Ursula"],
) -> "RemoteUrsulaStatus":
if isinstance(checksum_address_or_node, str):
node = self[checksum_address_or_node]
else:

View File

@ -39,7 +39,7 @@ from nucypher.blockchain.eth.registry import (
)
from nucypher.blockchain.eth.signers import Signer
from nucypher.blockchain.eth.token import NU
from nucypher.blockchain.eth.trackers.dkg import ActiveRitualTracker
from nucypher.blockchain.eth.trackers import dkg
from nucypher.blockchain.eth.trackers.pre import WorkTracker
from nucypher.crypto.ferveo.dkg import DecryptionShareSimple, FerveoVariant, Transcript
from nucypher.crypto.powers import (
@ -319,7 +319,7 @@ class Ritualist(BaseActor):
)
# track active onchain rituals
self.ritual_tracker = ActiveRitualTracker(
self.ritual_tracker = dkg.ActiveRitualTracker(
ritualist=self,
)

View File

@ -15,6 +15,8 @@ from nucypher_core.ferveo import AggregatedTranscript, DkgPublicKey, Transcript
from web3.contract.contract import Contract, ContractFunction
from web3.types import Timestamp, TxParams, TxReceipt, Wei
from nucypher import types
from nucypher.blockchain.eth import events
from nucypher.blockchain.eth.constants import (
ADJUDICATOR_CONTRACT_NAME,
DISPATCHER_CONTRACT_NAME,
@ -25,7 +27,6 @@ from nucypher.blockchain.eth.constants import (
SUBSCRIPTION_MANAGER_CONTRACT_NAME,
)
from nucypher.blockchain.eth.decorators import contract_api
from nucypher.blockchain.eth.events import ContractEvents
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
from nucypher.blockchain.eth.registry import BaseContractRegistry
from nucypher.config.constants import (
@ -34,7 +35,6 @@ from nucypher.config.constants import (
)
from nucypher.crypto.powers import TransactingPower
from nucypher.crypto.utils import sha256_digest
from nucypher.types import Agent, NuNits, StakingProviderInfo, TuNits
from nucypher.utilities.logging import Logger # type: ignore
@ -87,7 +87,7 @@ class EthereumContractAgent:
)
self.__contract = contract
self.events = ContractEvents(contract)
self.events = events.ContractEvents(contract)
if not transaction_gas:
transaction_gas = EthereumContractAgent.DEFAULT_TRANSACTION_GAS_LIMITS['default']
self.transaction_gas = transaction_gas
@ -129,23 +129,26 @@ class NucypherTokenAgent(EthereumContractAgent):
contract_name: str = NUCYPHER_TOKEN_CONTRACT_NAME
@contract_api(CONTRACT_CALL)
def get_balance(self, address: ChecksumAddress) -> NuNits:
def get_balance(self, address: ChecksumAddress) -> types.NuNits:
"""Get the NU balance (in NuNits) of a token holder address, or of this contract address"""
balance: int = self.contract.functions.balanceOf(address).call()
return NuNits(balance)
return types.NuNits(balance)
@contract_api(CONTRACT_CALL)
def get_allowance(self, owner: ChecksumAddress, spender: ChecksumAddress) -> NuNits:
def get_allowance(
self, owner: ChecksumAddress, spender: ChecksumAddress
) -> types.NuNits:
"""Check the amount of tokens that an owner allowed to a spender"""
allowance: int = self.contract.functions.allowance(owner, spender).call()
return NuNits(allowance)
return types.NuNits(allowance)
@contract_api(TRANSACTION)
def increase_allowance(self,
transacting_power: TransactingPower,
spender_address: ChecksumAddress,
increase: NuNits
) -> TxReceipt:
def increase_allowance(
self,
transacting_power: TransactingPower,
spender_address: ChecksumAddress,
increase: types.NuNits,
) -> TxReceipt:
"""Increase the allowance of a spender address funded by a sender address"""
contract_function: ContractFunction = self.contract.functions.increaseAllowance(spender_address, increase)
receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function,
@ -153,11 +156,12 @@ class NucypherTokenAgent(EthereumContractAgent):
return receipt
@contract_api(TRANSACTION)
def decrease_allowance(self,
transacting_power: TransactingPower,
spender_address: ChecksumAddress,
decrease: NuNits
) -> TxReceipt:
def decrease_allowance(
self,
transacting_power: TransactingPower,
spender_address: ChecksumAddress,
decrease: types.NuNits,
) -> TxReceipt:
"""Decrease the allowance of a spender address funded by a sender address"""
contract_function: ContractFunction = self.contract.functions.decreaseAllowance(spender_address, decrease)
receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function,
@ -165,11 +169,12 @@ class NucypherTokenAgent(EthereumContractAgent):
return receipt
@contract_api(TRANSACTION)
def approve_transfer(self,
amount: NuNits,
spender_address: ChecksumAddress,
transacting_power: TransactingPower
) -> TxReceipt:
def approve_transfer(
self,
amount: types.NuNits,
spender_address: ChecksumAddress,
transacting_power: TransactingPower,
) -> TxReceipt:
"""Approve the spender address to transfer an amount of tokens on behalf of the sender address"""
self._validate_zero_allowance(amount, spender_address, transacting_power)
@ -181,7 +186,12 @@ class NucypherTokenAgent(EthereumContractAgent):
return receipt
@contract_api(TRANSACTION)
def transfer(self, amount: NuNits, target_address: ChecksumAddress, transacting_power: TransactingPower) -> TxReceipt:
def transfer(
self,
amount: types.NuNits,
target_address: ChecksumAddress,
transacting_power: TransactingPower,
) -> TxReceipt:
"""Transfer an amount of tokens from the sender address to the target address."""
contract_function: ContractFunction = self.contract.functions.transfer(target_address, amount)
receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function,
@ -189,13 +199,14 @@ class NucypherTokenAgent(EthereumContractAgent):
return receipt
@contract_api(TRANSACTION)
def approve_and_call(self,
amount: NuNits,
target_address: ChecksumAddress,
transacting_power: TransactingPower,
call_data: bytes = b'',
gas_limit: Optional[Wei] = None
) -> TxReceipt:
def approve_and_call(
self,
amount: types.NuNits,
target_address: ChecksumAddress,
transacting_power: TransactingPower,
call_data: bytes = b"",
gas_limit: Optional[Wei] = None,
) -> TxReceipt:
self._validate_zero_allowance(amount, target_address, transacting_power)
payload = None
@ -402,10 +413,12 @@ class PREApplicationAgent(EthereumContractAgent):
return result
@contract_api(CONTRACT_CALL)
def get_staking_provider_info(self, staking_provider: ChecksumAddress) -> StakingProviderInfo:
def get_staking_provider_info(
self, staking_provider: ChecksumAddress
) -> types.StakingProviderInfo:
# remove reserved fields
info: list = self.contract.functions.stakingProviderInfo(staking_provider).call()
return StakingProviderInfo(*info[0:3])
return types.StakingProviderInfo(*info[0:3])
@contract_api(CONTRACT_CALL)
def get_authorized_stake(self, staking_provider: ChecksumAddress) -> int:
@ -441,8 +454,9 @@ class PREApplicationAgent(EthereumContractAgent):
yield address
@contract_api(CONTRACT_CALL)
def get_all_active_staking_providers(self, pagination_size: Optional[int] = None) -> Tuple[TuNits, Dict[ChecksumAddress, TuNits]]:
def get_all_active_staking_providers(
self, pagination_size: Optional[int] = None
) -> Tuple[types.TuNits, Dict[ChecksumAddress, types.TuNits]]:
if pagination_size is None:
pagination_size = self.DEFAULT_PROVIDERS_PAGINATION_SIZE_LIGHT_NODE if self.blockchain.is_light else self.DEFAULT_PROVIDERS_PAGINATION_SIZE
self.log.debug(f"Defaulting to pagination size {pagination_size}")
@ -488,10 +502,12 @@ class PREApplicationAgent(EthereumContractAgent):
def checksum_address(address: int) -> ChecksumAddress:
return ChecksumAddress(to_checksum_address(address.to_bytes(ETH_ADDRESS_BYTE_LENGTH, 'big')))
typed_staking_providers = {checksum_address(address): TuNits(authorized_tokens)
for address, authorized_tokens in staking_providers.items()}
typed_staking_providers = {
checksum_address(address): types.TuNits(authorized_tokens)
for address, authorized_tokens in staking_providers.items()
}
return TuNits(n_tokens), typed_staking_providers
return types.TuNits(n_tokens), typed_staking_providers
def get_staking_provider_reservoir(self,
without: Iterable[ChecksumAddress] = None,
@ -760,11 +776,11 @@ class ContractAgency:
@classmethod
def get_agent(
cls,
agent_class: Type[Agent],
agent_class: Type[types.Agent],
registry: Optional[BaseContractRegistry],
provider_uri: Optional[str],
contract_version: Optional[str] = None,
) -> Agent:
) -> types.Agent:
if not issubclass(agent_class, EthereumContractAgent):
raise TypeError("Only agent subclasses can be used from the agency.")
@ -780,10 +796,10 @@ class ContractAgency:
registry_id = registry.id
try:
return cast(Agent, cls.__agents[registry_id][agent_class])
return cast(types.Agent, cls.__agents[registry_id][agent_class])
except KeyError:
agent = cast(
Agent,
types.Agent,
agent_class(
registry=registry,
provider_uri=provider_uri,

View File

@ -3,6 +3,7 @@ import os
from web3.contract.contract import Contract
from nucypher.blockchain.eth import agents
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
from nucypher.config.constants import NUCYPHER_EVENTS_THROTTLE_MAX_BLOCKS
@ -71,13 +72,15 @@ class ContractEventsThrottler:
# default to 1000 - smallest default heard about so far (alchemy)
DEFAULT_MAX_BLOCKS_PER_CALL = int(os.environ.get(NUCYPHER_EVENTS_THROTTLE_MAX_BLOCKS, 1000))
def __init__(self,
agent: 'EthereumContractAgent',
event_name: str,
from_block: int,
to_block: int = None, # defaults to latest block
max_blocks_per_call: int = DEFAULT_MAX_BLOCKS_PER_CALL,
**argument_filters):
def __init__(
self,
agent: "agents.EthereumContractAgent",
event_name: str,
from_block: int,
to_block: int = None, # defaults to latest block
max_blocks_per_call: int = DEFAULT_MAX_BLOCKS_PER_CALL,
**argument_filters,
):
self.event_filter = agent.events[event_name]
self.from_block = from_block
self.to_block = to_block if to_block is not None else agent.blockchain.client.block_number

View File

@ -6,6 +6,7 @@ from twisted.internet import threads
from web3.contract.contract import ContractEvent
from web3.datastructures import AttributeDict
from nucypher.blockchain.eth.actors import Ritualist
from nucypher.policy.conditions.utils import camel_case_to_snake
from nucypher.utilities.events import EventScanner, JSONifiedState
from nucypher.utilities.logging import Logger
@ -66,7 +67,7 @@ class ActiveRitualTracker:
def __init__(
self,
ritualist: "Ritualist",
ritualist: Ritualist,
persistent: bool = False, # TODO: use persistent storage?
):
self.log = Logger("RitualTracker")

View File

@ -68,7 +68,7 @@ from web3.types import TxReceipt
import nucypher
from nucypher.acumen.nicknames import Nickname
from nucypher.acumen.perception import ArchivedFleetState, RemoteUrsulaStatus
from nucypher.blockchain.eth.actors import Operator, PolicyAuthor, Ritualist
from nucypher.blockchain.eth import actors
from nucypher.blockchain.eth.agents import (
ContractAgency,
CoordinatorAgent,
@ -100,6 +100,7 @@ from nucypher.crypto.powers import (
TLSHostingPower,
TransactingPower,
)
from nucypher.network import trackers
from nucypher.network.decryption import ThresholdDecryptionClient
from nucypher.network.exceptions import NodeSeemsToBeDown
from nucypher.network.middleware import RestMiddleware
@ -107,7 +108,6 @@ from nucypher.network.nodes import TEACHER_NODES, NodeSprout, Teacher
from nucypher.network.protocols import parse_node_uri
from nucypher.network.retrieval import PRERetrievalClient
from nucypher.network.server import ProxyRESTServer, make_rest_app
from nucypher.network.trackers import AvailabilityTracker
from nucypher.policy.conditions.types import Lingo
from nucypher.policy.conditions.utils import validate_condition_lingo
from nucypher.policy.kits import PolicyMessageKit
@ -116,9 +116,10 @@ from nucypher.policy.policies import Policy
from nucypher.utilities.emitters import StdoutEmitter
from nucypher.utilities.logging import Logger
from nucypher.utilities.networking import validate_operator_ip
from nucypher.utilities.prometheus.metrics import PrometheusMetricsConfig
class Alice(Character, PolicyAuthor):
class Alice(Character, actors.PolicyAuthor):
banner = ALICE_BANNER
_default_crypto_powerups = [SigningPower, DecryptingPower, DelegatingPower]
@ -183,7 +184,7 @@ class Alice(Character, PolicyAuthor):
account=checksum_address, signer=signer
)
self._crypto_power.consume_power_up(self.transacting_power)
PolicyAuthor.__init__(
actors.PolicyAuthor.__init__(
self,
domain=self.domain,
transacting_power=self.transacting_power,
@ -369,7 +370,7 @@ class Alice(Character, PolicyAuthor):
def revoke(
self, policy: Policy, onchain: bool = True, offchain: bool = True
) -> Tuple[TxReceipt, Dict[ChecksumAddress, Tuple["Revocation", Exception]]]:
) -> Tuple[TxReceipt, Dict[ChecksumAddress, Tuple["actors.Revocation", Exception]]]:
if not (offchain or onchain):
raise ValueError("offchain or onchain must be True to issue revocation")
@ -798,7 +799,7 @@ class Bob(Character):
return cleartext
class Ursula(Teacher, Character, Operator, Ritualist):
class Ursula(Teacher, Character, actors.Operator, actors.Ritualist):
banner = URSULA_BANNER
_alice_class = Alice
@ -864,11 +865,11 @@ class Ursula(Teacher, Character, Operator, Ritualist):
# Health Checks
self._availability_check = availability_check
self._availability_tracker = AvailabilityTracker(ursula=self)
self._availability_tracker = trackers.AvailabilityTracker(ursula=self)
try:
payment_method: ContractPayment
Operator.__init__(
actors.Operator.__init__(
self,
is_me=is_me,
domain=self.domain,
@ -882,7 +883,7 @@ class Ursula(Teacher, Character, Operator, Ritualist):
)
# DKG Ritualist
Ritualist.__init__(
actors.Ritualist.__init__(
self,
domain=domain,
provider_uri=payment_method.provider,
@ -1010,7 +1011,7 @@ class Ursula(Teacher, Character, Operator, Ritualist):
ritualist: bool = True,
hendrix: bool = True,
start_reactor: bool = True,
prometheus_config: "PrometheusMetricsConfig" = None,
prometheus_config: PrometheusMetricsConfig = None,
preflight: bool = True,
block_until_ready: bool = True,
eager: bool = False,

View File

@ -12,8 +12,9 @@ from cryptography.hazmat.backends import default_backend
from nucypher_core import FleetStateChecksum, MetadataRequest, NodeMetadata
from requests.exceptions import SSLError
from nucypher import characters
from nucypher.blockchain.eth.registry import BaseContractRegistry
from nucypher.config.storages import ForgetfulNodeStorage
from nucypher.config.storages import ForgetfulNodeStorage, NodeStorage
from nucypher.network.exceptions import NodeSeemsToBeDown
from nucypher.utilities.logging import Logger
@ -29,7 +30,7 @@ class NucypherMiddlewareClient:
self,
eth_provider_uri: Optional[str],
registry: Optional["BaseContractRegistry"] = None,
storage: Optional["NodeStorage"] = None,
storage: Optional[NodeStorage] = None,
*args,
**kwargs,
):
@ -260,7 +261,12 @@ class RestMiddleware:
)
return response
def reencrypt(self, ursula: "Ursula", reencryption_request_bytes: bytes, timeout=8):
def reencrypt(
self,
ursula: "characters.lawful.Ursula",
reencryption_request_bytes: bytes,
timeout=8,
):
response = self.client.post(
node_or_sprout=ursula,
path="reencrypt",
@ -270,7 +276,10 @@ class RestMiddleware:
return response
def get_encrypted_decryption_share(
self, ursula: "Ursula", decryption_request_bytes: bytes, timeout=8
self,
ursula: "characters.lawful.Ursula",
decryption_request_bytes: bytes,
timeout=8,
):
response = self.client.post(
node_or_sprout=ursula,

View File

@ -23,6 +23,7 @@ from requests.exceptions import SSLError
from twisted.internet import reactor, task
from twisted.internet.defer import Deferred
from nucypher import characters
from nucypher.acumen.nicknames import Nickname
from nucypher.acumen.perception import FleetSensor
from nucypher.blockchain.eth.agents import ContractAgency, PREApplicationAgent
@ -150,7 +151,6 @@ class NodeSprout:
return self._metadata_payload.domain
def finish(self):
from nucypher.characters.lawful import Ursula
# Remote node cryptographic material
crypto_power = CryptoPower()
@ -167,16 +167,18 @@ class NodeSprout:
self._metadata_payload.certificate_der, backend=default_backend()
)
return Ursula(is_me=False,
crypto_power=crypto_power,
rest_host=self._metadata_payload.host,
rest_port=self._metadata_payload.port,
checksum_address=self.checksum_address,
domain=self._metadata_payload.domain,
timestamp=self.timestamp,
operator_signature_from_metadata=self.operator_signature_from_metadata,
certificate=tls_certificate,
metadata=self._metadata)
return characters.lawful.Ursula(
is_me=False,
crypto_power=crypto_power,
rest_host=self._metadata_payload.host,
rest_port=self._metadata_payload.port,
checksum_address=self.checksum_address,
domain=self._metadata_payload.domain,
timestamp=self.timestamp,
operator_signature_from_metadata=self.operator_signature_from_metadata,
certificate=tls_certificate,
metadata=self._metadata,
)
def mature(self):
if self._is_finishing:
@ -293,8 +295,7 @@ class Learner:
if save_metadata and node_storage is NO_STORAGE_AVAILABLE:
raise ValueError("Cannot save nodes without a configured node storage")
from nucypher.characters.lawful import Ursula
self.node_class = node_class or Ursula
self.node_class = node_class or characters.lawful.Ursula
self.node_class.set_cert_storage_function(
node_storage.store_node_certificate) # TODO: Fix this temporary workaround for on-disk cert storage. #1481
@ -745,13 +746,15 @@ class Learner:
def write_node_metadata(self, node, serializer=bytes) -> str:
return self.node_storage.store_node_metadata(node=node)
def verify_from(self,
stranger: 'Character',
message: bytes,
signature: Signature
):
if not signature.verify(verifying_pk=stranger.stamp.as_umbral_pubkey(), message=message):
def verify_from(
self,
stranger: "characters.base.Character",
message: bytes,
signature: Signature,
):
if not signature.verify(
verifying_pk=stranger.stamp.as_umbral_pubkey(), message=message
):
try:
node_on_the_other_end = self.node_class.from_seednode_metadata(
stranger.seed_node_metadata(),

View File

@ -22,6 +22,7 @@ from nucypher_core.umbral import (
VerifiedCapsuleFrag,
)
from nucypher.characters import lawful
from nucypher.crypto.signing import InvalidSignature
from nucypher.network.client import ThresholdAccessControlClient
from nucypher.network.exceptions import NodeSeemsToBeDown
@ -182,13 +183,14 @@ class PRERetrievalClient(ThresholdAccessControlClient):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def _request_reencryption(self,
ursula: 'Ursula',
reencryption_request: ReencryptionRequest,
alice_verifying_key: PublicKey,
policy_encrypting_key: PublicKey,
bob_encrypting_key: PublicKey,
) -> Dict['Capsule', 'VerifiedCapsuleFrag']:
def _request_reencryption(
self,
ursula: "lawful.Ursula",
reencryption_request: ReencryptionRequest,
alice_verifying_key: PublicKey,
policy_encrypting_key: PublicKey,
bob_encrypting_key: PublicKey,
) -> Dict["Capsule", "VerifiedCapsuleFrag"]:
"""
Sends a reencryption request to a single Ursula and processes the results.

View File

@ -8,12 +8,13 @@ from twisted.internet import reactor
from twisted.internet.task import LoopingCall
from twisted.python.failure import Failure
from nucypher import characters
from nucypher.blockchain.eth.agents import ContractAgency, PREApplicationAgent
from nucypher.blockchain.eth.constants import NULL_ADDRESS
from nucypher.utilities.emitters import StdoutEmitter
from nucypher.network.exceptions import NodeSeemsToBeDown
from nucypher.network.middleware import RestMiddleware
from nucypher.network.nodes import NodeSprout
from nucypher.utilities.emitters import StdoutEmitter
from nucypher.utilities.logging import Logger
from nucypher.utilities.task import SimpleTask
@ -263,7 +264,9 @@ class AvailabilityTracker:
self.log.debug(f'{ursula_or_sprout} responded to uptime check with {e.__class__.__name__}')
continue
def measure(self, ursula_or_sprout: Union['Ursula', NodeSprout]) -> None:
def measure(
self, ursula_or_sprout: Union["characters.lawful.Ursula", NodeSprout]
) -> None:
"""Measure self-availability from a single remote node that participates uptime checks."""
try:
response = self._ursula.network_middleware.check_availability(initiator=self._ursula, responder=ursula_or_sprout)

View File

@ -10,7 +10,7 @@ from nucypher.blockchain.eth.registry import (
BaseContractRegistry,
InMemoryContractRegistry,
)
from nucypher.policy.policies import Policy
from nucypher.policy import policies
class PaymentMethod(ABC):
@ -25,7 +25,7 @@ class PaymentMethod(ABC):
shares: int
@abstractmethod
def pay(self, policy: Policy) -> Dict:
def pay(self, policy: "policies.Policy") -> Dict:
"""Carry out payment for the given policy."""
raise NotImplementedError
@ -101,7 +101,7 @@ class SubscriptionManagerPayment(ContractPayment):
result = self.agent.is_policy_active(policy_id=bytes(request.hrac))
return result
def pay(self, policy: Policy) -> TxReceipt:
def pay(self, policy: "policies.Policy") -> TxReceipt:
"""Writes a new policy to the SubscriptionManager contract."""
receipt = self.agent.create_policy(
value=policy.value, # wei
@ -176,7 +176,7 @@ class FreeReencryptions(PaymentMethod):
def verify(self, payee: ChecksumAddress, request: ReencryptionRequest) -> bool:
return True
def pay(self, policy: Policy) -> Dict:
def pay(self, policy: "policies.Policy") -> Dict:
receipt = f'Receipt for free policy {bytes(policy.hrac).hex()}.'
return dict(receipt=receipt.encode())

View File

@ -2,11 +2,13 @@ from typing import Dict, Iterable, List, Optional, Sequence
import maya
from eth_typing.evm import ChecksumAddress
from nucypher_core import HRAC, Address, TreasureMap
from nucypher_core import HRAC, Address, EncryptedTreasureMap, TreasureMap
from nucypher_core.umbral import PublicKey, VerifiedKeyFrag
from nucypher import characters
from nucypher.crypto.powers import DecryptingPower
from nucypher.network.middleware import RestMiddleware
from nucypher.policy import payment
from nucypher.policy.reservoir import PrefetchStrategy, make_staking_provider_reservoir
from nucypher.policy.revocation import RevocationKit
from nucypher.utilities.concurrency import WorkerPool
@ -29,21 +31,21 @@ class Policy:
number of available qualified network nodes.
"""
def __init__(self,
publisher: 'Alice',
label: bytes,
bob: 'Bob',
kfrags: Sequence[VerifiedKeyFrag],
public_key: PublicKey,
threshold: int,
expiration: maya.MayaDT,
commencement: maya.MayaDT,
value: int,
rate: int,
duration: int,
payment_method: 'PaymentMethod'
):
def __init__(
self,
publisher: "characters.lawful.Alice",
label: bytes,
bob: "characters.lawful.Bob",
kfrags: Sequence[VerifiedKeyFrag],
public_key: PublicKey,
threshold: int,
expiration: maya.MayaDT,
commencement: maya.MayaDT,
value: int,
rate: int,
duration: int,
payment_method: "payment.PaymentMethod",
):
self.threshold = threshold
self.shares = len(kfrags)
self.label = label
@ -75,12 +77,14 @@ class Policy:
)
return reservoir
def _publish(self, ursulas: List['Ursula']) -> Dict:
def _publish(self, ursulas: List["characters.lawful.Ursula"]) -> Dict:
self.nodes = [ursula.checksum_address for ursula in ursulas]
receipt = self.payment_method.pay(policy=self)
return receipt
def _ping_node(self, address: ChecksumAddress, network_middleware: RestMiddleware) -> 'Ursula':
def _ping_node(
self, address: ChecksumAddress, network_middleware: RestMiddleware
) -> "characters.lawful.Ursula":
# Handles edge case when provided address is not a known peer.
if address not in self.publisher.known_nodes:
raise RuntimeError(f"{address} is not a known peer")
@ -94,11 +98,12 @@ class Policy:
else:
raise RuntimeError(f"{ursula} is not available for selection ({status_code}).")
def _sample(self,
network_middleware: RestMiddleware,
ursulas: Optional[Iterable['Ursula']] = None,
timeout: int = 10,
) -> List['Ursula']:
def _sample(
self,
network_middleware: RestMiddleware,
ursulas: Optional[Iterable["characters.lawful.Ursula"]] = None,
timeout: int = 10,
) -> List["characters.lawful.Ursula"]:
"""Send concurrent requests to the /ping HTTP endpoint of nodes drawn from the reservoir."""
ursulas = ursulas or []
@ -108,7 +113,7 @@ class Policy:
reservoir = self._make_reservoir(handpicked_addresses)
value_factory = PrefetchStrategy(reservoir, self.shares)
def worker(address) -> 'Ursula':
def worker(address) -> "characters.lawful.Ursula":
return self._ping_node(address, network_middleware)
worker_pool = WorkerPool(
@ -142,7 +147,11 @@ class Policy:
ursulas = list(successes.values())
return ursulas
def enact(self, network_middleware: RestMiddleware, ursulas: Optional[Iterable['Ursula']] = None) -> 'EnactedPolicy':
def enact(
self,
network_middleware: RestMiddleware,
ursulas: Optional[Iterable["characters.lawful.Ursula"]] = None,
) -> "EnactedPolicy":
"""Attempts to enact the policy, returns an `EnactedPolicy` object on success."""
ursulas = self._sample(network_middleware=network_middleware, ursulas=ursulas)
@ -177,16 +186,16 @@ class Policy:
class EnactedPolicy:
def __init__(self,
hrac: HRAC,
label: bytes,
public_key: PublicKey,
threshold: int,
treasure_map: 'EncryptedTreasureMap',
revocation_kit: RevocationKit,
publisher_verifying_key: PublicKey):
def __init__(
self,
hrac: HRAC,
label: bytes,
public_key: PublicKey,
threshold: int,
treasure_map: EncryptedTreasureMap,
revocation_kit: RevocationKit,
publisher_verifying_key: PublicKey,
):
self.hrac = hrac
self.label = label
self.public_key = public_key

View File

@ -3,12 +3,16 @@ from typing import NamedTuple, NewType, TypeVar, Union
from eth_typing.evm import ChecksumAddress
from web3.types import TxReceipt, Wei
from nucypher.blockchain.eth import agents
ERC20UNits = NewType("ERC20UNits", int)
NuNits = NewType("NuNits", ERC20UNits)
TuNits = NewType("TuNits", ERC20UNits)
Agent = TypeVar('Agent', bound='EthereumContractAgent')
ContractReturnValue = TypeVar('ContractReturnValue', bound=Union[TxReceipt, Wei, int, str, bool])
Agent = TypeVar("Agent", bound="agents.EthereumContractAgent")
ContractReturnValue = TypeVar(
"ContractReturnValue", bound=Union[TxReceipt, Wei, int, str, bool]
)
class StakingProviderInfo(NamedTuple):

View File

@ -15,7 +15,7 @@ from typing import Dict, Type
from eth_typing.evm import ChecksumAddress
import nucypher
from nucypher.blockchain.eth.actors import NucypherTokenActor
from nucypher.blockchain.eth import actors
from nucypher.blockchain.eth.agents import (
ContractAgency,
EthereumContractAgent,
@ -23,6 +23,7 @@ from nucypher.blockchain.eth.agents import (
)
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
from nucypher.blockchain.eth.registry import BaseContractRegistry
from nucypher.characters import lawful
class MetricsCollector(ABC):
@ -73,7 +74,8 @@ class BaseMetricsCollector(MetricsCollector):
class UrsulaInfoMetricsCollector(BaseMetricsCollector):
"""Collector for Ursula specific metrics."""
def __init__(self, ursula: 'Ursula'):
def __init__(self, ursula: "lawful.Ursula"):
super().__init__()
self.ursula = ursula
@ -210,7 +212,7 @@ class OperatorMetricsCollector(BaseMetricsCollector):
}
def _collect_internal(self) -> None:
operator_token_actor = NucypherTokenActor(
operator_token_actor = actors.NucypherTokenActor(
registry=self.contract_registry,
domain=self.domain,
checksum_address=self.operator_address,

View File

@ -14,6 +14,7 @@ from typing import List
from twisted.internet import reactor, task
from twisted.web.resource import Resource
from nucypher.characters import lawful
from nucypher.utilities.prometheus.collector import (
BlockchainMetricsCollector,
MetricsCollector,
@ -118,9 +119,11 @@ def collect_prometheus_metrics(metrics_collectors: List[MetricsCollector]) -> No
collector.collect()
def start_prometheus_exporter(ursula: 'Ursula',
prometheus_config: PrometheusMetricsConfig,
registry: CollectorRegistry = REGISTRY) -> None:
def start_prometheus_exporter(
ursula: "lawful.Ursula",
prometheus_config: PrometheusMetricsConfig,
registry: CollectorRegistry = REGISTRY,
) -> None:
"""Configure, collect, and serve prometheus metrics."""
from prometheus_client.twisted import MetricsResource
from twisted.web.resource import Resource
@ -148,7 +151,7 @@ def start_prometheus_exporter(ursula: 'Ursula',
reactor.listenTCP(prometheus_config.port, factory, interface=prometheus_config.listen_address)
def create_metrics_collectors(ursula: "Ursula") -> List[MetricsCollector]:
def create_metrics_collectors(ursula: "lawful.Ursula") -> List[MetricsCollector]:
"""Create collectors used to obtain metrics."""
collectors: List[MetricsCollector] = [UrsulaInfoMetricsCollector(ursula=ursula)]

View File

@ -5,9 +5,10 @@ from unittest.mock import Mock
from constant_sorrow.constants import CONTRACT_ATTRIBUTE, CONTRACT_CALL, TRANSACTION
from nucypher.blockchain.eth import agents
from nucypher.blockchain.eth.agents import Agent, ContractAgency, EthereumContractAgent
from nucypher.blockchain.eth.agents import ContractAgency, EthereumContractAgent
from nucypher.blockchain.eth.constants import NULL_ADDRESS
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
from nucypher.types import Agent
from tests.constants import MOCK_ETH_PROVIDER_URI
from tests.mock.interfaces import MockBlockchain