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 eth_typing import ChecksumAddress
|
||||||
from nucypher_core import FleetStateChecksum, NodeMetadata
|
from nucypher_core import FleetStateChecksum, NodeMetadata
|
||||||
|
|
||||||
|
from nucypher import characters
|
||||||
from nucypher.utilities.logging import Logger
|
from nucypher.utilities.logging import Logger
|
||||||
|
|
||||||
from .nicknames import Nickname
|
from .nicknames import Nickname
|
||||||
|
@ -41,7 +42,7 @@ class StateDiff(NamedTuple):
|
||||||
|
|
||||||
class FleetState:
|
class FleetState:
|
||||||
"""
|
"""
|
||||||
Fleet state as perceived by a local Ursula.
|
Fleet state as perceived by a local "lawful.Ursula".
|
||||||
|
|
||||||
Assumptions we're based on:
|
Assumptions we're based on:
|
||||||
|
|
||||||
|
@ -57,7 +58,9 @@ class FleetState:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@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_ref = weakref.ref(this_node) if this_node else None
|
||||||
# `this_node` might not have its metadata available yet.
|
# `this_node` might not have its metadata available yet.
|
||||||
this_node_metadata = None
|
this_node_metadata = None
|
||||||
|
@ -66,12 +69,16 @@ class FleetState:
|
||||||
this_node_ref=this_node_ref,
|
this_node_ref=this_node_ref,
|
||||||
this_node_metadata=this_node_metadata)
|
this_node_metadata=this_node_metadata)
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(
|
||||||
nodes: Dict[ChecksumAddress, 'Ursula'],
|
self,
|
||||||
this_node_ref: Optional[weakref.ReferenceType],
|
nodes: Dict[ChecksumAddress, "characters.lawful.Ursula"],
|
||||||
this_node_metadata: Optional[NodeMetadata]):
|
this_node_ref: Optional[weakref.ReferenceType],
|
||||||
self.checksum = FleetStateChecksum(this_node=this_node_metadata,
|
this_node_metadata: Optional[NodeMetadata],
|
||||||
other_nodes=[node.metadata() for node in nodes.values()])
|
):
|
||||||
|
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.nickname = Nickname.from_seed(bytes(self.checksum), length=1)
|
||||||
self._nodes = nodes
|
self._nodes = nodes
|
||||||
self.timestamp = maya.now()
|
self.timestamp = maya.now()
|
||||||
|
@ -84,12 +91,12 @@ class FleetState:
|
||||||
timestamp=self.timestamp,
|
timestamp=self.timestamp,
|
||||||
population=self.population)
|
population=self.population)
|
||||||
|
|
||||||
def _calculate_diff(self,
|
def _calculate_diff(
|
||||||
this_node_updated: bool,
|
self,
|
||||||
nodes_to_add: Iterable['Ursula'],
|
this_node_updated: bool,
|
||||||
nodes_to_remove: Iterable[ChecksumAddress]
|
nodes_to_add: Iterable["characters.lawful.Ursula"],
|
||||||
) -> StateDiff:
|
nodes_to_remove: Iterable[ChecksumAddress],
|
||||||
|
) -> StateDiff:
|
||||||
nodes_updated = []
|
nodes_updated = []
|
||||||
for node in nodes_to_add:
|
for node in nodes_to_add:
|
||||||
if node.checksum_address in nodes_to_remove:
|
if node.checksum_address in nodes_to_remove:
|
||||||
|
@ -107,12 +114,12 @@ class FleetState:
|
||||||
nodes_updated=nodes_updated,
|
nodes_updated=nodes_updated,
|
||||||
nodes_removed=nodes_removed)
|
nodes_removed=nodes_removed)
|
||||||
|
|
||||||
def with_updated_nodes(self,
|
def with_updated_nodes(
|
||||||
nodes_to_add: Iterable['Ursula'],
|
self,
|
||||||
nodes_to_remove: Iterable[ChecksumAddress],
|
nodes_to_add: Iterable["characters.lawful.Ursula"],
|
||||||
skip_this_node: bool = False,
|
nodes_to_remove: Iterable[ChecksumAddress],
|
||||||
) -> 'FleetState':
|
skip_this_node: bool = False,
|
||||||
|
) -> "FleetState":
|
||||||
if self._this_node_ref is not None and not skip_this_node:
|
if self._this_node_ref is not None and not skip_this_node:
|
||||||
this_node = self._this_node_ref()
|
this_node = self._this_node_ref()
|
||||||
this_node_metadata = this_node.metadata()
|
this_node_metadata = this_node.metadata()
|
||||||
|
@ -169,7 +176,7 @@ class FleetState:
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self._nodes)
|
return len(self._nodes)
|
||||||
|
|
||||||
def shuffled(self) -> List['Ursula']:
|
def shuffled(self) -> List["characters.lawful.Ursula"]:
|
||||||
nodes_we_know_about = list(self._nodes.values())
|
nodes_we_know_about = list(self._nodes.values())
|
||||||
random.shuffle(nodes_we_know_about)
|
random.shuffle(nodes_we_know_about)
|
||||||
return nodes_we_know_about
|
return nodes_we_know_about
|
||||||
|
@ -206,8 +213,9 @@ class FleetSensor:
|
||||||
"""
|
"""
|
||||||
log = Logger("Learning")
|
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._domain = domain
|
||||||
|
|
||||||
self._current_state = FleetState.new(this_node)
|
self._current_state = FleetState.new(this_node)
|
||||||
|
@ -221,7 +229,7 @@ class FleetSensor:
|
||||||
|
|
||||||
self._auto_update_state = False
|
self._auto_update_state = False
|
||||||
|
|
||||||
def record_node(self, node: 'Ursula'):
|
def record_node(self, node: "characters.lawful.Ursula"):
|
||||||
|
|
||||||
if node.domain == self._domain:
|
if node.domain == self._domain:
|
||||||
# Replace the existing object with a newer object, even if they're equal
|
# Replace the existing object with a newer object, even if they're equal
|
||||||
|
@ -330,7 +338,7 @@ class FleetSensor:
|
||||||
def shuffled(self):
|
def shuffled(self):
|
||||||
return self._current_state.shuffled()
|
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
|
# 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)
|
self._nodes_to_remove.add(node.checksum_address)
|
||||||
|
|
||||||
|
@ -352,8 +360,10 @@ class FleetSensor:
|
||||||
self._remote_last_seen[checksum_address] = maya.now()
|
self._remote_last_seen[checksum_address] = maya.now()
|
||||||
self._remote_states[checksum_address] = state
|
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):
|
if isinstance(checksum_address_or_node, str):
|
||||||
node = self[checksum_address_or_node]
|
node = self[checksum_address_or_node]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -39,7 +39,7 @@ from nucypher.blockchain.eth.registry import (
|
||||||
)
|
)
|
||||||
from nucypher.blockchain.eth.signers import Signer
|
from nucypher.blockchain.eth.signers import Signer
|
||||||
from nucypher.blockchain.eth.token import NU
|
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.blockchain.eth.trackers.pre import WorkTracker
|
||||||
from nucypher.crypto.ferveo.dkg import DecryptionShareSimple, FerveoVariant, Transcript
|
from nucypher.crypto.ferveo.dkg import DecryptionShareSimple, FerveoVariant, Transcript
|
||||||
from nucypher.crypto.powers import (
|
from nucypher.crypto.powers import (
|
||||||
|
@ -319,7 +319,7 @@ class Ritualist(BaseActor):
|
||||||
)
|
)
|
||||||
|
|
||||||
# track active onchain rituals
|
# track active onchain rituals
|
||||||
self.ritual_tracker = ActiveRitualTracker(
|
self.ritual_tracker = dkg.ActiveRitualTracker(
|
||||||
ritualist=self,
|
ritualist=self,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ from nucypher_core.ferveo import AggregatedTranscript, DkgPublicKey, Transcript
|
||||||
from web3.contract.contract import Contract, ContractFunction
|
from web3.contract.contract import Contract, ContractFunction
|
||||||
from web3.types import Timestamp, TxParams, TxReceipt, Wei
|
from web3.types import Timestamp, TxParams, TxReceipt, Wei
|
||||||
|
|
||||||
|
from nucypher import types
|
||||||
|
from nucypher.blockchain.eth import events
|
||||||
from nucypher.blockchain.eth.constants import (
|
from nucypher.blockchain.eth.constants import (
|
||||||
ADJUDICATOR_CONTRACT_NAME,
|
ADJUDICATOR_CONTRACT_NAME,
|
||||||
DISPATCHER_CONTRACT_NAME,
|
DISPATCHER_CONTRACT_NAME,
|
||||||
|
@ -25,7 +27,6 @@ from nucypher.blockchain.eth.constants import (
|
||||||
SUBSCRIPTION_MANAGER_CONTRACT_NAME,
|
SUBSCRIPTION_MANAGER_CONTRACT_NAME,
|
||||||
)
|
)
|
||||||
from nucypher.blockchain.eth.decorators import contract_api
|
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.interfaces import BlockchainInterfaceFactory
|
||||||
from nucypher.blockchain.eth.registry import BaseContractRegistry
|
from nucypher.blockchain.eth.registry import BaseContractRegistry
|
||||||
from nucypher.config.constants import (
|
from nucypher.config.constants import (
|
||||||
|
@ -34,7 +35,6 @@ from nucypher.config.constants import (
|
||||||
)
|
)
|
||||||
from nucypher.crypto.powers import TransactingPower
|
from nucypher.crypto.powers import TransactingPower
|
||||||
from nucypher.crypto.utils import sha256_digest
|
from nucypher.crypto.utils import sha256_digest
|
||||||
from nucypher.types import Agent, NuNits, StakingProviderInfo, TuNits
|
|
||||||
from nucypher.utilities.logging import Logger # type: ignore
|
from nucypher.utilities.logging import Logger # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ class EthereumContractAgent:
|
||||||
)
|
)
|
||||||
|
|
||||||
self.__contract = contract
|
self.__contract = contract
|
||||||
self.events = ContractEvents(contract)
|
self.events = events.ContractEvents(contract)
|
||||||
if not transaction_gas:
|
if not transaction_gas:
|
||||||
transaction_gas = EthereumContractAgent.DEFAULT_TRANSACTION_GAS_LIMITS['default']
|
transaction_gas = EthereumContractAgent.DEFAULT_TRANSACTION_GAS_LIMITS['default']
|
||||||
self.transaction_gas = transaction_gas
|
self.transaction_gas = transaction_gas
|
||||||
|
@ -129,23 +129,26 @@ class NucypherTokenAgent(EthereumContractAgent):
|
||||||
contract_name: str = NUCYPHER_TOKEN_CONTRACT_NAME
|
contract_name: str = NUCYPHER_TOKEN_CONTRACT_NAME
|
||||||
|
|
||||||
@contract_api(CONTRACT_CALL)
|
@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"""
|
"""Get the NU balance (in NuNits) of a token holder address, or of this contract address"""
|
||||||
balance: int = self.contract.functions.balanceOf(address).call()
|
balance: int = self.contract.functions.balanceOf(address).call()
|
||||||
return NuNits(balance)
|
return types.NuNits(balance)
|
||||||
|
|
||||||
@contract_api(CONTRACT_CALL)
|
@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"""
|
"""Check the amount of tokens that an owner allowed to a spender"""
|
||||||
allowance: int = self.contract.functions.allowance(owner, spender).call()
|
allowance: int = self.contract.functions.allowance(owner, spender).call()
|
||||||
return NuNits(allowance)
|
return types.NuNits(allowance)
|
||||||
|
|
||||||
@contract_api(TRANSACTION)
|
@contract_api(TRANSACTION)
|
||||||
def increase_allowance(self,
|
def increase_allowance(
|
||||||
transacting_power: TransactingPower,
|
self,
|
||||||
spender_address: ChecksumAddress,
|
transacting_power: TransactingPower,
|
||||||
increase: NuNits
|
spender_address: ChecksumAddress,
|
||||||
) -> TxReceipt:
|
increase: types.NuNits,
|
||||||
|
) -> TxReceipt:
|
||||||
"""Increase the allowance of a spender address funded by a sender address"""
|
"""Increase the allowance of a spender address funded by a sender address"""
|
||||||
contract_function: ContractFunction = self.contract.functions.increaseAllowance(spender_address, increase)
|
contract_function: ContractFunction = self.contract.functions.increaseAllowance(spender_address, increase)
|
||||||
receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function,
|
receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function,
|
||||||
|
@ -153,11 +156,12 @@ class NucypherTokenAgent(EthereumContractAgent):
|
||||||
return receipt
|
return receipt
|
||||||
|
|
||||||
@contract_api(TRANSACTION)
|
@contract_api(TRANSACTION)
|
||||||
def decrease_allowance(self,
|
def decrease_allowance(
|
||||||
transacting_power: TransactingPower,
|
self,
|
||||||
spender_address: ChecksumAddress,
|
transacting_power: TransactingPower,
|
||||||
decrease: NuNits
|
spender_address: ChecksumAddress,
|
||||||
) -> TxReceipt:
|
decrease: types.NuNits,
|
||||||
|
) -> TxReceipt:
|
||||||
"""Decrease the allowance of a spender address funded by a sender address"""
|
"""Decrease the allowance of a spender address funded by a sender address"""
|
||||||
contract_function: ContractFunction = self.contract.functions.decreaseAllowance(spender_address, decrease)
|
contract_function: ContractFunction = self.contract.functions.decreaseAllowance(spender_address, decrease)
|
||||||
receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function,
|
receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function,
|
||||||
|
@ -165,11 +169,12 @@ class NucypherTokenAgent(EthereumContractAgent):
|
||||||
return receipt
|
return receipt
|
||||||
|
|
||||||
@contract_api(TRANSACTION)
|
@contract_api(TRANSACTION)
|
||||||
def approve_transfer(self,
|
def approve_transfer(
|
||||||
amount: NuNits,
|
self,
|
||||||
spender_address: ChecksumAddress,
|
amount: types.NuNits,
|
||||||
transacting_power: TransactingPower
|
spender_address: ChecksumAddress,
|
||||||
) -> TxReceipt:
|
transacting_power: TransactingPower,
|
||||||
|
) -> TxReceipt:
|
||||||
"""Approve the spender address to transfer an amount of tokens on behalf of the sender address"""
|
"""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)
|
self._validate_zero_allowance(amount, spender_address, transacting_power)
|
||||||
|
|
||||||
|
@ -181,7 +186,12 @@ class NucypherTokenAgent(EthereumContractAgent):
|
||||||
return receipt
|
return receipt
|
||||||
|
|
||||||
@contract_api(TRANSACTION)
|
@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."""
|
"""Transfer an amount of tokens from the sender address to the target address."""
|
||||||
contract_function: ContractFunction = self.contract.functions.transfer(target_address, amount)
|
contract_function: ContractFunction = self.contract.functions.transfer(target_address, amount)
|
||||||
receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function,
|
receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function,
|
||||||
|
@ -189,13 +199,14 @@ class NucypherTokenAgent(EthereumContractAgent):
|
||||||
return receipt
|
return receipt
|
||||||
|
|
||||||
@contract_api(TRANSACTION)
|
@contract_api(TRANSACTION)
|
||||||
def approve_and_call(self,
|
def approve_and_call(
|
||||||
amount: NuNits,
|
self,
|
||||||
target_address: ChecksumAddress,
|
amount: types.NuNits,
|
||||||
transacting_power: TransactingPower,
|
target_address: ChecksumAddress,
|
||||||
call_data: bytes = b'',
|
transacting_power: TransactingPower,
|
||||||
gas_limit: Optional[Wei] = None
|
call_data: bytes = b"",
|
||||||
) -> TxReceipt:
|
gas_limit: Optional[Wei] = None,
|
||||||
|
) -> TxReceipt:
|
||||||
self._validate_zero_allowance(amount, target_address, transacting_power)
|
self._validate_zero_allowance(amount, target_address, transacting_power)
|
||||||
|
|
||||||
payload = None
|
payload = None
|
||||||
|
@ -402,10 +413,12 @@ class PREApplicationAgent(EthereumContractAgent):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@contract_api(CONTRACT_CALL)
|
@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
|
# remove reserved fields
|
||||||
info: list = self.contract.functions.stakingProviderInfo(staking_provider).call()
|
info: list = self.contract.functions.stakingProviderInfo(staking_provider).call()
|
||||||
return StakingProviderInfo(*info[0:3])
|
return types.StakingProviderInfo(*info[0:3])
|
||||||
|
|
||||||
@contract_api(CONTRACT_CALL)
|
@contract_api(CONTRACT_CALL)
|
||||||
def get_authorized_stake(self, staking_provider: ChecksumAddress) -> int:
|
def get_authorized_stake(self, staking_provider: ChecksumAddress) -> int:
|
||||||
|
@ -441,8 +454,9 @@ class PREApplicationAgent(EthereumContractAgent):
|
||||||
yield address
|
yield address
|
||||||
|
|
||||||
@contract_api(CONTRACT_CALL)
|
@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:
|
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
|
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}")
|
self.log.debug(f"Defaulting to pagination size {pagination_size}")
|
||||||
|
@ -488,10 +502,12 @@ class PREApplicationAgent(EthereumContractAgent):
|
||||||
def checksum_address(address: int) -> ChecksumAddress:
|
def checksum_address(address: int) -> ChecksumAddress:
|
||||||
return ChecksumAddress(to_checksum_address(address.to_bytes(ETH_ADDRESS_BYTE_LENGTH, 'big')))
|
return ChecksumAddress(to_checksum_address(address.to_bytes(ETH_ADDRESS_BYTE_LENGTH, 'big')))
|
||||||
|
|
||||||
typed_staking_providers = {checksum_address(address): TuNits(authorized_tokens)
|
typed_staking_providers = {
|
||||||
for address, authorized_tokens in staking_providers.items()}
|
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,
|
def get_staking_provider_reservoir(self,
|
||||||
without: Iterable[ChecksumAddress] = None,
|
without: Iterable[ChecksumAddress] = None,
|
||||||
|
@ -760,11 +776,11 @@ class ContractAgency:
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_agent(
|
def get_agent(
|
||||||
cls,
|
cls,
|
||||||
agent_class: Type[Agent],
|
agent_class: Type[types.Agent],
|
||||||
registry: Optional[BaseContractRegistry],
|
registry: Optional[BaseContractRegistry],
|
||||||
provider_uri: Optional[str],
|
provider_uri: Optional[str],
|
||||||
contract_version: Optional[str] = None,
|
contract_version: Optional[str] = None,
|
||||||
) -> Agent:
|
) -> types.Agent:
|
||||||
if not issubclass(agent_class, EthereumContractAgent):
|
if not issubclass(agent_class, EthereumContractAgent):
|
||||||
raise TypeError("Only agent subclasses can be used from the agency.")
|
raise TypeError("Only agent subclasses can be used from the agency.")
|
||||||
|
|
||||||
|
@ -780,10 +796,10 @@ class ContractAgency:
|
||||||
registry_id = registry.id
|
registry_id = registry.id
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return cast(Agent, cls.__agents[registry_id][agent_class])
|
return cast(types.Agent, cls.__agents[registry_id][agent_class])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
agent = cast(
|
agent = cast(
|
||||||
Agent,
|
types.Agent,
|
||||||
agent_class(
|
agent_class(
|
||||||
registry=registry,
|
registry=registry,
|
||||||
provider_uri=provider_uri,
|
provider_uri=provider_uri,
|
||||||
|
|
|
@ -3,6 +3,7 @@ import os
|
||||||
|
|
||||||
from web3.contract.contract import Contract
|
from web3.contract.contract import Contract
|
||||||
|
|
||||||
|
from nucypher.blockchain.eth import agents
|
||||||
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
||||||
from nucypher.config.constants import NUCYPHER_EVENTS_THROTTLE_MAX_BLOCKS
|
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 to 1000 - smallest default heard about so far (alchemy)
|
||||||
DEFAULT_MAX_BLOCKS_PER_CALL = int(os.environ.get(NUCYPHER_EVENTS_THROTTLE_MAX_BLOCKS, 1000))
|
DEFAULT_MAX_BLOCKS_PER_CALL = int(os.environ.get(NUCYPHER_EVENTS_THROTTLE_MAX_BLOCKS, 1000))
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(
|
||||||
agent: 'EthereumContractAgent',
|
self,
|
||||||
event_name: str,
|
agent: "agents.EthereumContractAgent",
|
||||||
from_block: int,
|
event_name: str,
|
||||||
to_block: int = None, # defaults to latest block
|
from_block: int,
|
||||||
max_blocks_per_call: int = DEFAULT_MAX_BLOCKS_PER_CALL,
|
to_block: int = None, # defaults to latest block
|
||||||
**argument_filters):
|
max_blocks_per_call: int = DEFAULT_MAX_BLOCKS_PER_CALL,
|
||||||
|
**argument_filters,
|
||||||
|
):
|
||||||
self.event_filter = agent.events[event_name]
|
self.event_filter = agent.events[event_name]
|
||||||
self.from_block = from_block
|
self.from_block = from_block
|
||||||
self.to_block = to_block if to_block is not None else agent.blockchain.client.block_number
|
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.contract.contract import ContractEvent
|
||||||
from web3.datastructures import AttributeDict
|
from web3.datastructures import AttributeDict
|
||||||
|
|
||||||
|
from nucypher.blockchain.eth.actors import Ritualist
|
||||||
from nucypher.policy.conditions.utils import camel_case_to_snake
|
from nucypher.policy.conditions.utils import camel_case_to_snake
|
||||||
from nucypher.utilities.events import EventScanner, JSONifiedState
|
from nucypher.utilities.events import EventScanner, JSONifiedState
|
||||||
from nucypher.utilities.logging import Logger
|
from nucypher.utilities.logging import Logger
|
||||||
|
@ -66,7 +67,7 @@ class ActiveRitualTracker:
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
ritualist: "Ritualist",
|
ritualist: Ritualist,
|
||||||
persistent: bool = False, # TODO: use persistent storage?
|
persistent: bool = False, # TODO: use persistent storage?
|
||||||
):
|
):
|
||||||
self.log = Logger("RitualTracker")
|
self.log = Logger("RitualTracker")
|
||||||
|
|
|
@ -68,7 +68,7 @@ from web3.types import TxReceipt
|
||||||
import nucypher
|
import nucypher
|
||||||
from nucypher.acumen.nicknames import Nickname
|
from nucypher.acumen.nicknames import Nickname
|
||||||
from nucypher.acumen.perception import ArchivedFleetState, RemoteUrsulaStatus
|
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 (
|
from nucypher.blockchain.eth.agents import (
|
||||||
ContractAgency,
|
ContractAgency,
|
||||||
CoordinatorAgent,
|
CoordinatorAgent,
|
||||||
|
@ -100,6 +100,7 @@ from nucypher.crypto.powers import (
|
||||||
TLSHostingPower,
|
TLSHostingPower,
|
||||||
TransactingPower,
|
TransactingPower,
|
||||||
)
|
)
|
||||||
|
from nucypher.network import trackers
|
||||||
from nucypher.network.decryption import ThresholdDecryptionClient
|
from nucypher.network.decryption import ThresholdDecryptionClient
|
||||||
from nucypher.network.exceptions import NodeSeemsToBeDown
|
from nucypher.network.exceptions import NodeSeemsToBeDown
|
||||||
from nucypher.network.middleware import RestMiddleware
|
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.protocols import parse_node_uri
|
||||||
from nucypher.network.retrieval import PRERetrievalClient
|
from nucypher.network.retrieval import PRERetrievalClient
|
||||||
from nucypher.network.server import ProxyRESTServer, make_rest_app
|
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.types import Lingo
|
||||||
from nucypher.policy.conditions.utils import validate_condition_lingo
|
from nucypher.policy.conditions.utils import validate_condition_lingo
|
||||||
from nucypher.policy.kits import PolicyMessageKit
|
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.emitters import StdoutEmitter
|
||||||
from nucypher.utilities.logging import Logger
|
from nucypher.utilities.logging import Logger
|
||||||
from nucypher.utilities.networking import validate_operator_ip
|
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
|
banner = ALICE_BANNER
|
||||||
_default_crypto_powerups = [SigningPower, DecryptingPower, DelegatingPower]
|
_default_crypto_powerups = [SigningPower, DecryptingPower, DelegatingPower]
|
||||||
|
|
||||||
|
@ -183,7 +184,7 @@ class Alice(Character, PolicyAuthor):
|
||||||
account=checksum_address, signer=signer
|
account=checksum_address, signer=signer
|
||||||
)
|
)
|
||||||
self._crypto_power.consume_power_up(self.transacting_power)
|
self._crypto_power.consume_power_up(self.transacting_power)
|
||||||
PolicyAuthor.__init__(
|
actors.PolicyAuthor.__init__(
|
||||||
self,
|
self,
|
||||||
domain=self.domain,
|
domain=self.domain,
|
||||||
transacting_power=self.transacting_power,
|
transacting_power=self.transacting_power,
|
||||||
|
@ -369,7 +370,7 @@ class Alice(Character, PolicyAuthor):
|
||||||
|
|
||||||
def revoke(
|
def revoke(
|
||||||
self, policy: Policy, onchain: bool = True, offchain: bool = True
|
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):
|
if not (offchain or onchain):
|
||||||
raise ValueError("offchain or onchain must be True to issue revocation")
|
raise ValueError("offchain or onchain must be True to issue revocation")
|
||||||
|
|
||||||
|
@ -798,7 +799,7 @@ class Bob(Character):
|
||||||
return cleartext
|
return cleartext
|
||||||
|
|
||||||
|
|
||||||
class Ursula(Teacher, Character, Operator, Ritualist):
|
class Ursula(Teacher, Character, actors.Operator, actors.Ritualist):
|
||||||
banner = URSULA_BANNER
|
banner = URSULA_BANNER
|
||||||
_alice_class = Alice
|
_alice_class = Alice
|
||||||
|
|
||||||
|
@ -864,11 +865,11 @@ class Ursula(Teacher, Character, Operator, Ritualist):
|
||||||
|
|
||||||
# Health Checks
|
# Health Checks
|
||||||
self._availability_check = availability_check
|
self._availability_check = availability_check
|
||||||
self._availability_tracker = AvailabilityTracker(ursula=self)
|
self._availability_tracker = trackers.AvailabilityTracker(ursula=self)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
payment_method: ContractPayment
|
payment_method: ContractPayment
|
||||||
Operator.__init__(
|
actors.Operator.__init__(
|
||||||
self,
|
self,
|
||||||
is_me=is_me,
|
is_me=is_me,
|
||||||
domain=self.domain,
|
domain=self.domain,
|
||||||
|
@ -882,7 +883,7 @@ class Ursula(Teacher, Character, Operator, Ritualist):
|
||||||
)
|
)
|
||||||
|
|
||||||
# DKG Ritualist
|
# DKG Ritualist
|
||||||
Ritualist.__init__(
|
actors.Ritualist.__init__(
|
||||||
self,
|
self,
|
||||||
domain=domain,
|
domain=domain,
|
||||||
provider_uri=payment_method.provider,
|
provider_uri=payment_method.provider,
|
||||||
|
@ -1010,7 +1011,7 @@ class Ursula(Teacher, Character, Operator, Ritualist):
|
||||||
ritualist: bool = True,
|
ritualist: bool = True,
|
||||||
hendrix: bool = True,
|
hendrix: bool = True,
|
||||||
start_reactor: bool = True,
|
start_reactor: bool = True,
|
||||||
prometheus_config: "PrometheusMetricsConfig" = None,
|
prometheus_config: PrometheusMetricsConfig = None,
|
||||||
preflight: bool = True,
|
preflight: bool = True,
|
||||||
block_until_ready: bool = True,
|
block_until_ready: bool = True,
|
||||||
eager: bool = False,
|
eager: bool = False,
|
||||||
|
|
|
@ -12,8 +12,9 @@ from cryptography.hazmat.backends import default_backend
|
||||||
from nucypher_core import FleetStateChecksum, MetadataRequest, NodeMetadata
|
from nucypher_core import FleetStateChecksum, MetadataRequest, NodeMetadata
|
||||||
from requests.exceptions import SSLError
|
from requests.exceptions import SSLError
|
||||||
|
|
||||||
|
from nucypher import characters
|
||||||
from nucypher.blockchain.eth.registry import BaseContractRegistry
|
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.network.exceptions import NodeSeemsToBeDown
|
||||||
from nucypher.utilities.logging import Logger
|
from nucypher.utilities.logging import Logger
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ class NucypherMiddlewareClient:
|
||||||
self,
|
self,
|
||||||
eth_provider_uri: Optional[str],
|
eth_provider_uri: Optional[str],
|
||||||
registry: Optional["BaseContractRegistry"] = None,
|
registry: Optional["BaseContractRegistry"] = None,
|
||||||
storage: Optional["NodeStorage"] = None,
|
storage: Optional[NodeStorage] = None,
|
||||||
*args,
|
*args,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
|
@ -260,7 +261,12 @@ class RestMiddleware:
|
||||||
)
|
)
|
||||||
return response
|
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(
|
response = self.client.post(
|
||||||
node_or_sprout=ursula,
|
node_or_sprout=ursula,
|
||||||
path="reencrypt",
|
path="reencrypt",
|
||||||
|
@ -270,7 +276,10 @@ class RestMiddleware:
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def get_encrypted_decryption_share(
|
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(
|
response = self.client.post(
|
||||||
node_or_sprout=ursula,
|
node_or_sprout=ursula,
|
||||||
|
|
|
@ -23,6 +23,7 @@ from requests.exceptions import SSLError
|
||||||
from twisted.internet import reactor, task
|
from twisted.internet import reactor, task
|
||||||
from twisted.internet.defer import Deferred
|
from twisted.internet.defer import Deferred
|
||||||
|
|
||||||
|
from nucypher import characters
|
||||||
from nucypher.acumen.nicknames import Nickname
|
from nucypher.acumen.nicknames import Nickname
|
||||||
from nucypher.acumen.perception import FleetSensor
|
from nucypher.acumen.perception import FleetSensor
|
||||||
from nucypher.blockchain.eth.agents import ContractAgency, PREApplicationAgent
|
from nucypher.blockchain.eth.agents import ContractAgency, PREApplicationAgent
|
||||||
|
@ -150,7 +151,6 @@ class NodeSprout:
|
||||||
return self._metadata_payload.domain
|
return self._metadata_payload.domain
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
from nucypher.characters.lawful import Ursula
|
|
||||||
|
|
||||||
# Remote node cryptographic material
|
# Remote node cryptographic material
|
||||||
crypto_power = CryptoPower()
|
crypto_power = CryptoPower()
|
||||||
|
@ -167,16 +167,18 @@ class NodeSprout:
|
||||||
self._metadata_payload.certificate_der, backend=default_backend()
|
self._metadata_payload.certificate_der, backend=default_backend()
|
||||||
)
|
)
|
||||||
|
|
||||||
return Ursula(is_me=False,
|
return characters.lawful.Ursula(
|
||||||
crypto_power=crypto_power,
|
is_me=False,
|
||||||
rest_host=self._metadata_payload.host,
|
crypto_power=crypto_power,
|
||||||
rest_port=self._metadata_payload.port,
|
rest_host=self._metadata_payload.host,
|
||||||
checksum_address=self.checksum_address,
|
rest_port=self._metadata_payload.port,
|
||||||
domain=self._metadata_payload.domain,
|
checksum_address=self.checksum_address,
|
||||||
timestamp=self.timestamp,
|
domain=self._metadata_payload.domain,
|
||||||
operator_signature_from_metadata=self.operator_signature_from_metadata,
|
timestamp=self.timestamp,
|
||||||
certificate=tls_certificate,
|
operator_signature_from_metadata=self.operator_signature_from_metadata,
|
||||||
metadata=self._metadata)
|
certificate=tls_certificate,
|
||||||
|
metadata=self._metadata,
|
||||||
|
)
|
||||||
|
|
||||||
def mature(self):
|
def mature(self):
|
||||||
if self._is_finishing:
|
if self._is_finishing:
|
||||||
|
@ -293,8 +295,7 @@ class Learner:
|
||||||
if save_metadata and node_storage is NO_STORAGE_AVAILABLE:
|
if save_metadata and node_storage is NO_STORAGE_AVAILABLE:
|
||||||
raise ValueError("Cannot save nodes without a configured node storage")
|
raise ValueError("Cannot save nodes without a configured node storage")
|
||||||
|
|
||||||
from nucypher.characters.lawful import Ursula
|
self.node_class = node_class or characters.lawful.Ursula
|
||||||
self.node_class = node_class or Ursula
|
|
||||||
self.node_class.set_cert_storage_function(
|
self.node_class.set_cert_storage_function(
|
||||||
node_storage.store_node_certificate) # TODO: Fix this temporary workaround for on-disk cert storage. #1481
|
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:
|
def write_node_metadata(self, node, serializer=bytes) -> str:
|
||||||
return self.node_storage.store_node_metadata(node=node)
|
return self.node_storage.store_node_metadata(node=node)
|
||||||
|
|
||||||
def verify_from(self,
|
def verify_from(
|
||||||
stranger: 'Character',
|
self,
|
||||||
message: bytes,
|
stranger: "characters.base.Character",
|
||||||
signature: Signature
|
message: bytes,
|
||||||
):
|
signature: Signature,
|
||||||
|
):
|
||||||
if not signature.verify(verifying_pk=stranger.stamp.as_umbral_pubkey(), message=message):
|
if not signature.verify(
|
||||||
|
verifying_pk=stranger.stamp.as_umbral_pubkey(), message=message
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
node_on_the_other_end = self.node_class.from_seednode_metadata(
|
node_on_the_other_end = self.node_class.from_seednode_metadata(
|
||||||
stranger.seed_node_metadata(),
|
stranger.seed_node_metadata(),
|
||||||
|
|
|
@ -22,6 +22,7 @@ from nucypher_core.umbral import (
|
||||||
VerifiedCapsuleFrag,
|
VerifiedCapsuleFrag,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from nucypher.characters import lawful
|
||||||
from nucypher.crypto.signing import InvalidSignature
|
from nucypher.crypto.signing import InvalidSignature
|
||||||
from nucypher.network.client import ThresholdAccessControlClient
|
from nucypher.network.client import ThresholdAccessControlClient
|
||||||
from nucypher.network.exceptions import NodeSeemsToBeDown
|
from nucypher.network.exceptions import NodeSeemsToBeDown
|
||||||
|
@ -182,13 +183,14 @@ class PRERetrievalClient(ThresholdAccessControlClient):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def _request_reencryption(self,
|
def _request_reencryption(
|
||||||
ursula: 'Ursula',
|
self,
|
||||||
reencryption_request: ReencryptionRequest,
|
ursula: "lawful.Ursula",
|
||||||
alice_verifying_key: PublicKey,
|
reencryption_request: ReencryptionRequest,
|
||||||
policy_encrypting_key: PublicKey,
|
alice_verifying_key: PublicKey,
|
||||||
bob_encrypting_key: PublicKey,
|
policy_encrypting_key: PublicKey,
|
||||||
) -> Dict['Capsule', 'VerifiedCapsuleFrag']:
|
bob_encrypting_key: PublicKey,
|
||||||
|
) -> Dict["Capsule", "VerifiedCapsuleFrag"]:
|
||||||
"""
|
"""
|
||||||
Sends a reencryption request to a single Ursula and processes the results.
|
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.internet.task import LoopingCall
|
||||||
from twisted.python.failure import Failure
|
from twisted.python.failure import Failure
|
||||||
|
|
||||||
|
from nucypher import characters
|
||||||
from nucypher.blockchain.eth.agents import ContractAgency, PREApplicationAgent
|
from nucypher.blockchain.eth.agents import ContractAgency, PREApplicationAgent
|
||||||
from nucypher.blockchain.eth.constants import NULL_ADDRESS
|
from nucypher.blockchain.eth.constants import NULL_ADDRESS
|
||||||
from nucypher.utilities.emitters import StdoutEmitter
|
|
||||||
from nucypher.network.exceptions import NodeSeemsToBeDown
|
from nucypher.network.exceptions import NodeSeemsToBeDown
|
||||||
from nucypher.network.middleware import RestMiddleware
|
from nucypher.network.middleware import RestMiddleware
|
||||||
from nucypher.network.nodes import NodeSprout
|
from nucypher.network.nodes import NodeSprout
|
||||||
|
from nucypher.utilities.emitters import StdoutEmitter
|
||||||
from nucypher.utilities.logging import Logger
|
from nucypher.utilities.logging import Logger
|
||||||
from nucypher.utilities.task import SimpleTask
|
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__}')
|
self.log.debug(f'{ursula_or_sprout} responded to uptime check with {e.__class__.__name__}')
|
||||||
continue
|
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."""
|
"""Measure self-availability from a single remote node that participates uptime checks."""
|
||||||
try:
|
try:
|
||||||
response = self._ursula.network_middleware.check_availability(initiator=self._ursula, responder=ursula_or_sprout)
|
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,
|
BaseContractRegistry,
|
||||||
InMemoryContractRegistry,
|
InMemoryContractRegistry,
|
||||||
)
|
)
|
||||||
from nucypher.policy.policies import Policy
|
from nucypher.policy import policies
|
||||||
|
|
||||||
|
|
||||||
class PaymentMethod(ABC):
|
class PaymentMethod(ABC):
|
||||||
|
@ -25,7 +25,7 @@ class PaymentMethod(ABC):
|
||||||
shares: int
|
shares: int
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def pay(self, policy: Policy) -> Dict:
|
def pay(self, policy: "policies.Policy") -> Dict:
|
||||||
"""Carry out payment for the given policy."""
|
"""Carry out payment for the given policy."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ class SubscriptionManagerPayment(ContractPayment):
|
||||||
result = self.agent.is_policy_active(policy_id=bytes(request.hrac))
|
result = self.agent.is_policy_active(policy_id=bytes(request.hrac))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def pay(self, policy: Policy) -> TxReceipt:
|
def pay(self, policy: "policies.Policy") -> TxReceipt:
|
||||||
"""Writes a new policy to the SubscriptionManager contract."""
|
"""Writes a new policy to the SubscriptionManager contract."""
|
||||||
receipt = self.agent.create_policy(
|
receipt = self.agent.create_policy(
|
||||||
value=policy.value, # wei
|
value=policy.value, # wei
|
||||||
|
@ -176,7 +176,7 @@ class FreeReencryptions(PaymentMethod):
|
||||||
def verify(self, payee: ChecksumAddress, request: ReencryptionRequest) -> bool:
|
def verify(self, payee: ChecksumAddress, request: ReencryptionRequest) -> bool:
|
||||||
return True
|
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()}.'
|
receipt = f'Receipt for free policy {bytes(policy.hrac).hex()}.'
|
||||||
return dict(receipt=receipt.encode())
|
return dict(receipt=receipt.encode())
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,13 @@ from typing import Dict, Iterable, List, Optional, Sequence
|
||||||
|
|
||||||
import maya
|
import maya
|
||||||
from eth_typing.evm import ChecksumAddress
|
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_core.umbral import PublicKey, VerifiedKeyFrag
|
||||||
|
|
||||||
|
from nucypher import characters
|
||||||
from nucypher.crypto.powers import DecryptingPower
|
from nucypher.crypto.powers import DecryptingPower
|
||||||
from nucypher.network.middleware import RestMiddleware
|
from nucypher.network.middleware import RestMiddleware
|
||||||
|
from nucypher.policy import payment
|
||||||
from nucypher.policy.reservoir import PrefetchStrategy, make_staking_provider_reservoir
|
from nucypher.policy.reservoir import PrefetchStrategy, make_staking_provider_reservoir
|
||||||
from nucypher.policy.revocation import RevocationKit
|
from nucypher.policy.revocation import RevocationKit
|
||||||
from nucypher.utilities.concurrency import WorkerPool
|
from nucypher.utilities.concurrency import WorkerPool
|
||||||
|
@ -29,21 +31,21 @@ class Policy:
|
||||||
number of available qualified network nodes.
|
number of available qualified network nodes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(
|
||||||
publisher: 'Alice',
|
self,
|
||||||
label: bytes,
|
publisher: "characters.lawful.Alice",
|
||||||
bob: 'Bob',
|
label: bytes,
|
||||||
kfrags: Sequence[VerifiedKeyFrag],
|
bob: "characters.lawful.Bob",
|
||||||
public_key: PublicKey,
|
kfrags: Sequence[VerifiedKeyFrag],
|
||||||
threshold: int,
|
public_key: PublicKey,
|
||||||
expiration: maya.MayaDT,
|
threshold: int,
|
||||||
commencement: maya.MayaDT,
|
expiration: maya.MayaDT,
|
||||||
value: int,
|
commencement: maya.MayaDT,
|
||||||
rate: int,
|
value: int,
|
||||||
duration: int,
|
rate: int,
|
||||||
payment_method: 'PaymentMethod'
|
duration: int,
|
||||||
):
|
payment_method: "payment.PaymentMethod",
|
||||||
|
):
|
||||||
self.threshold = threshold
|
self.threshold = threshold
|
||||||
self.shares = len(kfrags)
|
self.shares = len(kfrags)
|
||||||
self.label = label
|
self.label = label
|
||||||
|
@ -75,12 +77,14 @@ class Policy:
|
||||||
)
|
)
|
||||||
return reservoir
|
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]
|
self.nodes = [ursula.checksum_address for ursula in ursulas]
|
||||||
receipt = self.payment_method.pay(policy=self)
|
receipt = self.payment_method.pay(policy=self)
|
||||||
return receipt
|
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.
|
# Handles edge case when provided address is not a known peer.
|
||||||
if address not in self.publisher.known_nodes:
|
if address not in self.publisher.known_nodes:
|
||||||
raise RuntimeError(f"{address} is not a known peer")
|
raise RuntimeError(f"{address} is not a known peer")
|
||||||
|
@ -94,11 +98,12 @@ class Policy:
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(f"{ursula} is not available for selection ({status_code}).")
|
raise RuntimeError(f"{ursula} is not available for selection ({status_code}).")
|
||||||
|
|
||||||
def _sample(self,
|
def _sample(
|
||||||
network_middleware: RestMiddleware,
|
self,
|
||||||
ursulas: Optional[Iterable['Ursula']] = None,
|
network_middleware: RestMiddleware,
|
||||||
timeout: int = 10,
|
ursulas: Optional[Iterable["characters.lawful.Ursula"]] = None,
|
||||||
) -> List['Ursula']:
|
timeout: int = 10,
|
||||||
|
) -> List["characters.lawful.Ursula"]:
|
||||||
"""Send concurrent requests to the /ping HTTP endpoint of nodes drawn from the reservoir."""
|
"""Send concurrent requests to the /ping HTTP endpoint of nodes drawn from the reservoir."""
|
||||||
|
|
||||||
ursulas = ursulas or []
|
ursulas = ursulas or []
|
||||||
|
@ -108,7 +113,7 @@ class Policy:
|
||||||
reservoir = self._make_reservoir(handpicked_addresses)
|
reservoir = self._make_reservoir(handpicked_addresses)
|
||||||
value_factory = PrefetchStrategy(reservoir, self.shares)
|
value_factory = PrefetchStrategy(reservoir, self.shares)
|
||||||
|
|
||||||
def worker(address) -> 'Ursula':
|
def worker(address) -> "characters.lawful.Ursula":
|
||||||
return self._ping_node(address, network_middleware)
|
return self._ping_node(address, network_middleware)
|
||||||
|
|
||||||
worker_pool = WorkerPool(
|
worker_pool = WorkerPool(
|
||||||
|
@ -142,7 +147,11 @@ class Policy:
|
||||||
ursulas = list(successes.values())
|
ursulas = list(successes.values())
|
||||||
return ursulas
|
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."""
|
"""Attempts to enact the policy, returns an `EnactedPolicy` object on success."""
|
||||||
|
|
||||||
ursulas = self._sample(network_middleware=network_middleware, ursulas=ursulas)
|
ursulas = self._sample(network_middleware=network_middleware, ursulas=ursulas)
|
||||||
|
@ -177,16 +186,16 @@ class Policy:
|
||||||
|
|
||||||
|
|
||||||
class EnactedPolicy:
|
class EnactedPolicy:
|
||||||
|
def __init__(
|
||||||
def __init__(self,
|
self,
|
||||||
hrac: HRAC,
|
hrac: HRAC,
|
||||||
label: bytes,
|
label: bytes,
|
||||||
public_key: PublicKey,
|
public_key: PublicKey,
|
||||||
threshold: int,
|
threshold: int,
|
||||||
treasure_map: 'EncryptedTreasureMap',
|
treasure_map: EncryptedTreasureMap,
|
||||||
revocation_kit: RevocationKit,
|
revocation_kit: RevocationKit,
|
||||||
publisher_verifying_key: PublicKey):
|
publisher_verifying_key: PublicKey,
|
||||||
|
):
|
||||||
self.hrac = hrac
|
self.hrac = hrac
|
||||||
self.label = label
|
self.label = label
|
||||||
self.public_key = public_key
|
self.public_key = public_key
|
||||||
|
|
|
@ -3,12 +3,16 @@ from typing import NamedTuple, NewType, TypeVar, Union
|
||||||
from eth_typing.evm import ChecksumAddress
|
from eth_typing.evm import ChecksumAddress
|
||||||
from web3.types import TxReceipt, Wei
|
from web3.types import TxReceipt, Wei
|
||||||
|
|
||||||
|
from nucypher.blockchain.eth import agents
|
||||||
|
|
||||||
ERC20UNits = NewType("ERC20UNits", int)
|
ERC20UNits = NewType("ERC20UNits", int)
|
||||||
NuNits = NewType("NuNits", ERC20UNits)
|
NuNits = NewType("NuNits", ERC20UNits)
|
||||||
TuNits = NewType("TuNits", ERC20UNits)
|
TuNits = NewType("TuNits", ERC20UNits)
|
||||||
|
|
||||||
Agent = TypeVar('Agent', bound='EthereumContractAgent')
|
Agent = TypeVar("Agent", bound="agents.EthereumContractAgent")
|
||||||
ContractReturnValue = TypeVar('ContractReturnValue', bound=Union[TxReceipt, Wei, int, str, bool])
|
ContractReturnValue = TypeVar(
|
||||||
|
"ContractReturnValue", bound=Union[TxReceipt, Wei, int, str, bool]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class StakingProviderInfo(NamedTuple):
|
class StakingProviderInfo(NamedTuple):
|
||||||
|
|
|
@ -15,7 +15,7 @@ from typing import Dict, Type
|
||||||
from eth_typing.evm import ChecksumAddress
|
from eth_typing.evm import ChecksumAddress
|
||||||
|
|
||||||
import nucypher
|
import nucypher
|
||||||
from nucypher.blockchain.eth.actors import NucypherTokenActor
|
from nucypher.blockchain.eth import actors
|
||||||
from nucypher.blockchain.eth.agents import (
|
from nucypher.blockchain.eth.agents import (
|
||||||
ContractAgency,
|
ContractAgency,
|
||||||
EthereumContractAgent,
|
EthereumContractAgent,
|
||||||
|
@ -23,6 +23,7 @@ from nucypher.blockchain.eth.agents import (
|
||||||
)
|
)
|
||||||
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
||||||
from nucypher.blockchain.eth.registry import BaseContractRegistry
|
from nucypher.blockchain.eth.registry import BaseContractRegistry
|
||||||
|
from nucypher.characters import lawful
|
||||||
|
|
||||||
|
|
||||||
class MetricsCollector(ABC):
|
class MetricsCollector(ABC):
|
||||||
|
@ -73,7 +74,8 @@ class BaseMetricsCollector(MetricsCollector):
|
||||||
|
|
||||||
class UrsulaInfoMetricsCollector(BaseMetricsCollector):
|
class UrsulaInfoMetricsCollector(BaseMetricsCollector):
|
||||||
"""Collector for Ursula specific metrics."""
|
"""Collector for Ursula specific metrics."""
|
||||||
def __init__(self, ursula: 'Ursula'):
|
|
||||||
|
def __init__(self, ursula: "lawful.Ursula"):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.ursula = ursula
|
self.ursula = ursula
|
||||||
|
|
||||||
|
@ -210,7 +212,7 @@ class OperatorMetricsCollector(BaseMetricsCollector):
|
||||||
}
|
}
|
||||||
|
|
||||||
def _collect_internal(self) -> None:
|
def _collect_internal(self) -> None:
|
||||||
operator_token_actor = NucypherTokenActor(
|
operator_token_actor = actors.NucypherTokenActor(
|
||||||
registry=self.contract_registry,
|
registry=self.contract_registry,
|
||||||
domain=self.domain,
|
domain=self.domain,
|
||||||
checksum_address=self.operator_address,
|
checksum_address=self.operator_address,
|
||||||
|
|
|
@ -14,6 +14,7 @@ from typing import List
|
||||||
from twisted.internet import reactor, task
|
from twisted.internet import reactor, task
|
||||||
from twisted.web.resource import Resource
|
from twisted.web.resource import Resource
|
||||||
|
|
||||||
|
from nucypher.characters import lawful
|
||||||
from nucypher.utilities.prometheus.collector import (
|
from nucypher.utilities.prometheus.collector import (
|
||||||
BlockchainMetricsCollector,
|
BlockchainMetricsCollector,
|
||||||
MetricsCollector,
|
MetricsCollector,
|
||||||
|
@ -118,9 +119,11 @@ def collect_prometheus_metrics(metrics_collectors: List[MetricsCollector]) -> No
|
||||||
collector.collect()
|
collector.collect()
|
||||||
|
|
||||||
|
|
||||||
def start_prometheus_exporter(ursula: 'Ursula',
|
def start_prometheus_exporter(
|
||||||
prometheus_config: PrometheusMetricsConfig,
|
ursula: "lawful.Ursula",
|
||||||
registry: CollectorRegistry = REGISTRY) -> None:
|
prometheus_config: PrometheusMetricsConfig,
|
||||||
|
registry: CollectorRegistry = REGISTRY,
|
||||||
|
) -> None:
|
||||||
"""Configure, collect, and serve prometheus metrics."""
|
"""Configure, collect, and serve prometheus metrics."""
|
||||||
from prometheus_client.twisted import MetricsResource
|
from prometheus_client.twisted import MetricsResource
|
||||||
from twisted.web.resource import Resource
|
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)
|
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."""
|
"""Create collectors used to obtain metrics."""
|
||||||
collectors: List[MetricsCollector] = [UrsulaInfoMetricsCollector(ursula=ursula)]
|
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 constant_sorrow.constants import CONTRACT_ATTRIBUTE, CONTRACT_CALL, TRANSACTION
|
||||||
|
|
||||||
from nucypher.blockchain.eth import agents
|
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.constants import NULL_ADDRESS
|
||||||
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
||||||
|
from nucypher.types import Agent
|
||||||
from tests.constants import MOCK_ETH_PROVIDER_URI
|
from tests.constants import MOCK_ETH_PROVIDER_URI
|
||||||
from tests.mock.interfaces import MockBlockchain
|
from tests.mock.interfaces import MockBlockchain
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue