mirror of https://github.com/nucypher/nucypher.git
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.htmlpull/3159/head
parent
905de7de5d
commit
a4de8a882e
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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())
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)]
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue