Support agents with different blockchain connections.

pull/2861/head
Kieran Prasch 2022-01-13 21:23:19 -08:00
parent 0f82db319e
commit cdaa6b1358
7 changed files with 35 additions and 30 deletions

View File

@ -18,7 +18,7 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
from decimal import Decimal, localcontext
from math import log
from typing import Tuple
from typing import Tuple, Optional
from nucypher.blockchain.eth.agents import (
AdjudicatorAgent,
@ -448,26 +448,26 @@ class EconomicsFactory:
__economics = dict()
@classmethod
def get_economics(cls, registry: BaseContractRegistry) -> BaseEconomics:
def get_economics(cls, registry: BaseContractRegistry, provider_uri: Optional[str] = None) -> BaseEconomics:
registry_id = registry.id
try:
return cls.__economics[registry_id]
except KeyError:
economics = EconomicsFactory.retrieve_from_blockchain(registry=registry)
economics = EconomicsFactory.retrieve_from_blockchain(registry=registry, provider_uri=provider_uri)
cls.__economics[registry_id] = economics
return economics
@staticmethod
def retrieve_from_blockchain(registry: BaseContractRegistry) -> BaseEconomics:
def retrieve_from_blockchain(registry: BaseContractRegistry, provider_uri: Optional[str] = None) -> BaseEconomics:
# Agents
token_agent = ContractAgency.get_agent(NucypherTokenAgent, registry=registry)
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=registry)
adjudicator_agent = ContractAgency.get_agent(AdjudicatorAgent, registry=registry)
token_agent = ContractAgency.get_agent(NucypherTokenAgent, registry=registry, provider_uri=provider_uri)
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=registry, provider_uri=provider_uri)
adjudicator_agent = ContractAgency.get_agent(AdjudicatorAgent, registry=registry, provider_uri=provider_uri)
worklock_deployed = True
try:
worklock_agent = ContractAgency.get_agent(WorkLockAgent, registry=registry)
worklock_agent = ContractAgency.get_agent(WorkLockAgent, registry=registry, provider_uri=provider_uri)
except registry.UnknownContract:
worklock_deployed = False

View File

@ -61,7 +61,7 @@ class CanonicalRegistrySource(ABC):
raise NotImplementedError
def __repr__(self):
return self.get_publication_endpoint()
return str(self.get_publication_endpoint())
class GithubRegistrySource(CanonicalRegistrySource):

View File

@ -165,17 +165,13 @@ class Character(Learner):
# Blockchainy
if not self.federated_only:
self.provider_uri = provider_uri
# TODO: Implicit / lazy blockchain connection here?
# if not BlockchainInterfaceFactory.is_interface_initialized(provider_uri=provider_uri):
# BlockchainInterfaceFactory.initialize_interface(provider_uri=provider_uri)
self.registry = registry or InMemoryContractRegistry.from_latest_publication(network=domain) # See #1580
else:
self.registry = NO_BLOCKCHAIN_CONNECTION.bool_value(False)
# REST
self.network_middleware = network_middleware or RestMiddleware(registry=self.registry)
self.network_middleware = network_middleware or RestMiddleware(registry=self.registry,
provider_uri=provider_uri)
# Learner
Learner.__init__(self,

View File

@ -61,6 +61,7 @@ from web3.types import TxReceipt
import nucypher
from nucypher.acumen.nicknames import Nickname
from nucypher.acumen.perception import ArchivedFleetState, RemoteUrsulaStatus
from nucypher.blockchain.economics import EconomicsFactory
from nucypher.blockchain.eth.actors import ThresholdWorker
from nucypher.blockchain.eth.agents import ContractAgency
from nucypher.blockchain.eth.agents import StakingEscrowAgent
@ -92,7 +93,7 @@ from nucypher.network.retrieval import RetrievalClient
from nucypher.network.server import ProxyRESTServer, make_rest_app
from nucypher.network.trackers import AvailabilityTracker
from nucypher.policy.kits import PolicyMessageKit
from nucypher.policy.payment import ContractPayment, PaymentMethod, FreeReencryptions
from nucypher.policy.payment import PaymentMethod, FreeReencryptions
from nucypher.policy.policies import Policy, BlockchainPolicy, FederatedPolicy
from nucypher.utilities.logging import Logger
from nucypher.utilities.networking import validate_worker_ip
@ -169,7 +170,10 @@ class Alice(Character):
self._crypto_power.consume_power_up(self.transacting_power)
# BlockchainPolicyAuthor was here
self.staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=self.registry)
self.economics = EconomicsFactory.get_economics(registry=self.registry, provider_uri=provider_uri)
self.staking_agent = ContractAgency.get_agent(StakingEscrowAgent,
registry=self.registry,
provider_uri=provider_uri)
self.log = Logger(self.__class__.__name__)
if is_me:

View File

@ -38,8 +38,9 @@ class NucypherMiddlewareClient:
library = requests
timeout = 1.2
def __init__(self, registry=None, *args, **kwargs):
def __init__(self, registry=None, provider_uri: str = None, *args, **kwargs):
self.registry = registry
self.provider_uri = provider_uri
@staticmethod
def response_cleaner(response):
@ -55,7 +56,7 @@ class NucypherMiddlewareClient:
if node_or_sprout:
if node_or_sprout is not EXEMPT_FROM_VERIFICATION:
node = node_or_sprout.mature() # Morph into a node.
node.verify_node(network_middleware_client=self, registry=self.registry)
node.verify_node(network_middleware_client=self, registry=self.registry, provider_uri=self.provider_uri)
return self.parse_node_or_host_and_port(node_or_sprout, host, port)
def parse_node_or_host_and_port(self, node, host, port):
@ -175,8 +176,8 @@ class RestMiddleware:
def __init__(self, *args, **kwargs):
super().__init__(status=HTTPStatus.FORBIDDEN, *args, **kwargs)
def __init__(self, registry=None):
self.client = self._client_class(registry)
def __init__(self, registry=None, provider_uri: str = None):
self.client = self._client_class(registry=registry, provider_uri=provider_uri)
def get_certificate(self, host, port, timeout=3, retry_attempts: int = 3, retry_rate: int = 2,
current_attempt: int = 0):

View File

@ -1068,16 +1068,16 @@ class Teacher:
raise self.UnbondedWorker(f"Worker {self.worker_address} is not bonded")
return staker_address == self.checksum_address
def _staker_is_really_staking(self, registry: BaseContractRegistry) -> bool:
def _staker_is_really_staking(self, registry: BaseContractRegistry, provider_uri: Optional[str] = None) -> bool:
"""
This method assumes the stamp's signature is valid and accurate.
As a follow-up, this checks that the staker is, indeed, staking.
"""
# Lazy agent get or create
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=registry) # type: StakingEscrowAgent
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=registry, provider_uri=provider_uri) # type: StakingEscrowAgent
try:
economics = EconomicsFactory.get_economics(registry=registry)
economics = EconomicsFactory.get_economics(registry=registry, provider_uri=provider_uri)
except Exception:
raise # TODO: Get StandardEconomics NRN
@ -1088,7 +1088,7 @@ class Teacher:
is_staking = max(stake_current_period, stake_next_period) >= min_stake
return is_staking
def validate_worker(self, registry: BaseContractRegistry = None) -> None:
def validate_worker(self, registry: BaseContractRegistry = None, provider_uri: Optional[str] = None) -> None:
# Federated
if self.federated_only:
@ -1113,7 +1113,7 @@ class Teacher:
self.log.debug(message)
raise self.UnbondedWorker(message)
if self._staker_is_really_staking(registry=registry): # <-- Blockchain CALL
if self._staker_is_really_staking(registry=registry, provider_uri=provider_uri): # <-- Blockchain CALL
self.verified_worker = True
else:
raise self.NotStaking(f"Staker {self.checksum_address} is not staking")
@ -1131,7 +1131,7 @@ class Teacher:
else:
raise self.InvalidNode("Metadata signature is invalid")
def validate_metadata(self, registry: BaseContractRegistry = None):
def validate_metadata(self, registry: BaseContractRegistry = None, provider_uri: Optional[str] = None):
# Verify the metadata signature
if not self.verified_metadata:
@ -1143,7 +1143,7 @@ class Teacher:
# Offline check of valid stamp signature by worker
try:
self.validate_worker(registry=registry)
self.validate_worker(registry=registry, provider_uri=provider_uri)
except self.WrongMode:
if bool(registry):
raise
@ -1151,6 +1151,7 @@ class Teacher:
def verify_node(self,
network_middleware_client,
registry: BaseContractRegistry = None,
provider_uri: Optional[str] = None,
certificate_filepath: Optional[Path] = None,
force: bool = False
) -> bool:
@ -1182,7 +1183,7 @@ class Teacher:
"on-chain Staking verification will not be performed.")
# This is both the stamp's client signature and interface metadata check; May raise InvalidNode
self.validate_metadata(registry=registry)
self.validate_metadata(registry=registry, provider_uri=provider_uri)
# The node's metadata is valid; let's be sure the interface is in order.
if not certificate_filepath:

View File

@ -81,7 +81,6 @@ class ContractPayment(PaymentMethod, ABC):
self.provider = provider
self.network = network
self.registry = InMemoryContractRegistry.from_latest_publication(network=network)
self.economics = EconomicsFactory.get_economics(registry=self.registry)
self.__agent = None # delay blockchain/registry reads until later
@property
@ -134,6 +133,10 @@ class PolicyManagerPayment(ContractPayment):
_AGENT = PolicyManagerAgent
NAME = 'PolicyManager'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.economics = EconomicsFactory.get_economics(registry=self.registry, provider_uri=self.provider)
def verify(self, payee: ChecksumAddress, request: ReencryptionRequest) -> bool:
"""Verify policy payment by reading the PolicyManager contract"""