diff --git a/docs/source/conf.py b/docs/source/conf.py index e40b3da23..0015f2be0 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -178,9 +178,15 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (main_doc, 'NuCypher', 'NuCypher Documentation', - author, 'NuCypher', 'A proxy re-encryption network to empower privacy in decentralized systems.', - 'Miscellaneous'), + ( + main_doc, + "NuCypher", + "NuCypher Documentation", + author, + "NuCypher", + "A threshold access control application to empower privacy in decentralized systems.", + "Miscellaneous", + ), ] diff --git a/examples/local_simple_taco.py b/examples/local_simple_taco.py index 4273757a4..8bd115e1d 100644 --- a/examples/local_simple_taco.py +++ b/examples/local_simple_taco.py @@ -1,3 +1,4 @@ +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.signers import InMemorySigner from nucypher.characters.chaotic import NiceGuyEddie as _Enrico from nucypher.characters.chaotic import ThisBobAlwaysDecrypts @@ -8,7 +9,7 @@ THIS_IS_NOT_A_TRINKET = 55 # sometimes called "public key" signer = InMemorySigner() enrico = _Enrico(encrypting_key=THIS_IS_NOT_A_TRINKET, signer=signer) -bob = ThisBobAlwaysDecrypts(domain="lynx", eth_provider_uri="Nowhere") +bob = ThisBobAlwaysDecrypts(domain=TACoDomain.LYNX.name, eth_endpoint="Nowhere") ANYTHING_CAN_BE_PASSED_AS_RITUAL_ID = 55 diff --git a/examples/pre/finnegans_wake_demo/README.md b/examples/pre/finnegans_wake_demo/README.md index e5e86b77f..22edcfcd9 100644 --- a/examples/pre/finnegans_wake_demo/README.md +++ b/examples/pre/finnegans_wake_demo/README.md @@ -20,8 +20,7 @@ and adding your provider and wallet details. To set the variables in your curre Optionally, you can change the network the demo is running on by changing the value of `L1_NETWORK` and `L2_NETWORK`. If you change these values be sure to also change `L1_PROVIDER_URI` and `L2_PROVIDER_URI` accordingly. -Available options for `L1_NETWORK` are `tapir` or `mainnet`. -Available options for `L2_NETWORK` are `mumbai` or `mainnet` +Available options for `TACO_NETWORK` are `lynx`, `tapir` or `mainnet`. Ensure Alice's account has a bit of MATIC on polygon to pay for the policy. diff --git a/examples/pre/finnegans_wake_demo/finnegans-wake-demo-l2.py b/examples/pre/finnegans_wake_demo/finnegans-wake-demo-l2.py index 3744db254..2d65255c8 100644 --- a/examples/pre/finnegans_wake_demo/finnegans-wake-demo-l2.py +++ b/examples/pre/finnegans_wake_demo/finnegans-wake-demo-l2.py @@ -5,6 +5,7 @@ from pathlib import Path import maya +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.signers.base import Signer from nucypher.characters.lawful import Alice, Bob from nucypher.characters.lawful import Enrico as Enrico @@ -40,22 +41,21 @@ except KeyError: print("\n************** Setup **************\n") -########### -# Network # -########### +########## +# Domain # +########## -L1_NETWORK = "lynx" -L2_NETWORK = "mumbai" +TACO_DOMAIN = TACoDomain.LYNX.name ##################### # Bob the BUIDLer ## ##################### # Then, there was bob. Bob learns about the -# rest of the network from the seednode. +# rest of the domain from the seednode. bob = Bob( - domain=L1_NETWORK, - eth_provider_uri=L1_PROVIDER, + domain=TACO_DOMAIN, + eth_endpoint=L1_PROVIDER, ) # Bob puts his public keys somewhere alice can find them. @@ -67,9 +67,9 @@ encrypting_key = bob.public_keys(DecryptingPower) ###################################### # Connect to the ethereum provider. -connect_web3_provider(eth_provider_uri=L1_PROVIDER) +connect_web3_provider(blockchain_endpoint=L1_PROVIDER) # Connect to the layer 2 provider. -connect_web3_provider(eth_provider_uri=L2_PROVIDER) +connect_web3_provider(blockchain_endpoint=L2_PROVIDER) # Setup and unlock alice's ethereum wallet. # WARNING: Never give your mainnet password or mnemonic phrase to anyone. @@ -82,15 +82,16 @@ wallet.unlock_account(account=ALICE_ADDRESS, password=password) # This is Alice's PRE payment method. pre_payment_method = SubscriptionManagerPayment( - network=L2_NETWORK, eth_provider=L2_PROVIDER + domain=TACO_DOMAIN, blockchain_endpoint=L2_PROVIDER ) # This is Alice. alice = Alice( checksum_address=ALICE_ADDRESS, signer=wallet, - domain=L1_NETWORK, - eth_provider_uri=L1_PROVIDER, + domain=TACO_DOMAIN, + eth_endpoint=L1_PROVIDER, + polygon_endpoint=L2_PROVIDER, pre_payment_method=pre_payment_method, ) @@ -111,7 +112,7 @@ policy_public_key = alice.get_policy_encrypting_key_from_label(label) remote_bob = Bob.from_public_keys( encrypting_key=encrypting_key, verifying_key=verifying_key, - eth_provider_uri=L1_PROVIDER, + eth_endpoint=L1_PROVIDER, ) # These are the policy details. diff --git a/examples/pre/heartbeat_demo/alicia.py b/examples/pre/heartbeat_demo/alicia.py index 8611a1d49..f043263ca 100644 --- a/examples/pre/heartbeat_demo/alicia.py +++ b/examples/pre/heartbeat_demo/alicia.py @@ -24,6 +24,7 @@ from pathlib import Path import maya +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.signers import Signer from nucypher.characters.lawful import Alice, Bob from nucypher.policy.payment import SubscriptionManagerPayment @@ -57,16 +58,19 @@ try: except KeyError: raise RuntimeError("Missing environment variables to run demo.") -L1_NETWORK = "lynx" -L2_NETWORK = "mumbai" +TACO_DOMAIN = TACoDomain.LYNX.name ####################################### # Alicia, the Authority of the Policy # ####################################### -connect_web3_provider(eth_provider_uri=L1_PROVIDER) # Connect to the ethereum provider. -connect_web3_provider(eth_provider_uri=L2_PROVIDER) # Connect to the layer 2 provider. +connect_web3_provider( + blockchain_endpoint=L1_PROVIDER +) # Connect to the ethereum provider. +connect_web3_provider( + blockchain_endpoint=L2_PROVIDER +) # Connect to the layer 2 provider. # Setup and unlock alice's ethereum wallet. @@ -80,15 +84,16 @@ wallet.unlock_account(account=ALICE_ADDRESS, password=password) # This is Alice's PRE payment method. pre_payment_method = SubscriptionManagerPayment( - network=L2_NETWORK, eth_provider=L2_PROVIDER + domain=TACO_DOMAIN, blockchain_endpoint=L2_PROVIDER ) # This is Alicia. alicia = Alice( checksum_address=ALICE_ADDRESS, signer=wallet, - domain=L1_NETWORK, - eth_provider_uri=L1_PROVIDER, + domain=TACO_DOMAIN, + eth_endpoint=L1_PROVIDER, + polygon_endpoint=L2_PROVIDER, pre_payment_method=pre_payment_method, ) diff --git a/examples/pre/heartbeat_demo/doctor.py b/examples/pre/heartbeat_demo/doctor.py index 8c151fa0e..63c2e6fb6 100644 --- a/examples/pre/heartbeat_demo/doctor.py +++ b/examples/pre/heartbeat_demo/doctor.py @@ -9,6 +9,7 @@ import msgpack from nucypher_core import EncryptedTreasureMap, MessageKit from nucypher_core.umbral import PublicKey +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.characters.lawful import Bob from nucypher.crypto.keypairs import DecryptingKeypair, SigningKeypair from nucypher.crypto.powers import DecryptingPower, SigningPower @@ -27,7 +28,7 @@ except KeyError: raise RuntimeError("Missing environment variables to run demo.") -L1_NETWORK = "lynx" +TACO_DOMAIN = TACoDomain.LYNX.name # To create a Bob, we need the doctor's private keys previously generated. from doctor_keys import get_doctor_privkeys # noqa: E402 @@ -43,9 +44,9 @@ power_ups = [enc_power, sig_power] print("Creating the Doctor ...") doctor = Bob( - domain=L1_NETWORK, + domain=TACO_DOMAIN, crypto_power_ups=power_ups, - eth_provider_uri=L1_PROVIDER, + eth_endpoint=L1_PROVIDER, ) print("Doctor = ", doctor) diff --git a/examples/pre/heartbeat_demo/heartbeat_demo.md b/examples/pre/heartbeat_demo/heartbeat_demo.md index fcebf9a5b..ffb5f6eaf 100644 --- a/examples/pre/heartbeat_demo/heartbeat_demo.md +++ b/examples/pre/heartbeat_demo/heartbeat_demo.md @@ -47,8 +47,7 @@ and adding your provider and wallet details. To set the variables in your curre Optionally, you can change the network the demo is running on by changing the value of `L1_NETWORK` and `L2_NETWORK`. If you change these values be sure to also change `L1_PROVIDER_URI` and `L2_PROVIDER_URI` accordingly. -Available options for `L1_NETOWRK` are `tapir` or `mainnet`. -Available options for `L2_NETWORK` are `mumbai` or `polygon` +Available options for `TACO_NETWORK` are `lynx`, `tapir` or `mainnet`. Ensure Alice's account has a bit of MATIC on polygon to pay for the policy. diff --git a/examples/testnet_compound_multichain_taco.py b/examples/testnet_compound_multichain_taco.py index 7ed0fcff2..5a2514939 100644 --- a/examples/testnet_compound_multichain_taco.py +++ b/examples/testnet_compound_multichain_taco.py @@ -3,6 +3,7 @@ import os from nucypher_core.ferveo import DkgPublicKey from nucypher.blockchain.eth.agents import CoordinatorAgent +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.registry import ContractRegistry from nucypher.blockchain.eth.signers import InMemorySigner from nucypher.characters.lawful import Bob, Enrico @@ -18,11 +19,10 @@ LOG_LEVEL = "info" GlobalLoggerSettings.set_log_level(log_level_name=LOG_LEVEL) GlobalLoggerSettings.start_console_logging() -staking_provider_uri = os.environ["DEMO_L1_PROVIDER_URI"] -network = "lynx" +eth_endpoint = os.environ["DEMO_L1_PROVIDER_URI"] +domain = TACoDomain.LYNX.name -coordinator_provider_uri = os.environ["DEMO_L2_PROVIDER_URI"] -coordinator_network = "mumbai" +polygon_endpoint = os.environ["DEMO_L2_PROVIDER_URI"] ############### # Enrico @@ -30,9 +30,13 @@ coordinator_network = "mumbai" print("--------- Threshold Encryption ---------") +registry = ContractRegistry.from_latest_publication( + domain=domain, +) + coordinator_agent = CoordinatorAgent( - provider_uri=coordinator_provider_uri, - registry=ContractRegistry.from_latest_publication(domain=coordinator_network), + blockchain_endpoint=polygon_endpoint, + registry=registry, ) ritual_id = 1 # got this from a side channel ritual = coordinator_agent.get_ritual(ritual_id) @@ -96,11 +100,10 @@ print(f"\nEncrypted message:\n{bytes(threshold_message_kit).hex()}") print("--------- Threshold Decryption ---------") bob = Bob( - eth_provider_uri=staking_provider_uri, - domain=network, - coordinator_provider_uri=coordinator_provider_uri, - coordinator_network=coordinator_network, - registry=ContractRegistry.from_latest_publication(domain=network), + domain=domain, + eth_endpoint=eth_endpoint, + polygon_endpoint=polygon_endpoint, + registry=registry, ) bob.start_learning_loop(now=True) diff --git a/examples/testnet_simple_taco.py b/examples/testnet_simple_taco.py index 21778f19d..93a079621 100644 --- a/examples/testnet_simple_taco.py +++ b/examples/testnet_simple_taco.py @@ -3,6 +3,7 @@ import os from nucypher_core.ferveo import DkgPublicKey from nucypher.blockchain.eth.agents import CoordinatorAgent +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.registry import ContractRegistry from nucypher.blockchain.eth.signers import InMemorySigner from nucypher.characters.lawful import Bob, Enrico @@ -18,11 +19,10 @@ LOG_LEVEL = "info" GlobalLoggerSettings.set_log_level(log_level_name=LOG_LEVEL) GlobalLoggerSettings.start_console_logging() -staking_provider_uri = os.environ["DEMO_L1_PROVIDER_URI"] -network = "lynx" +eth_endpoint = os.environ["DEMO_L1_PROVIDER_URI"] +domain = TACoDomain.LYNX.name -coordinator_provider_uri = os.environ["DEMO_L2_PROVIDER_URI"] -coordinator_network = "mumbai" +polygon_endpoint = os.environ["DEMO_L2_PROVIDER_URI"] ############### # Enrico @@ -30,9 +30,13 @@ coordinator_network = "mumbai" print("--------- Threshold Encryption ---------") +registry = ContractRegistry.from_latest_publication( + domain=domain, +) + coordinator_agent = CoordinatorAgent( - provider_uri=coordinator_provider_uri, - registry=ContractRegistry.from_latest_publication(domain=coordinator_network), + blockchain_endpoint=polygon_endpoint, + registry=registry, ) ritual_id = 1 # got this from a side channel ritual = coordinator_agent.get_ritual(ritual_id) @@ -73,11 +77,10 @@ print(f"\nEncrypted message:\n{bytes(threshold_message_kit).hex()}") print("--------- Threshold Decryption ---------") bob = Bob( - eth_provider_uri=staking_provider_uri, - domain=network, - coordinator_provider_uri=coordinator_provider_uri, - coordinator_network=coordinator_network, - registry=ContractRegistry.from_latest_publication(domain=network), + domain=domain, + eth_endpoint=eth_endpoint, + polygon_endpoint=polygon_endpoint, + registry=registry, ) bob.start_learning_loop(now=True) diff --git a/newsfragments/3262.misc.rst b/newsfragments/3262.misc.rst new file mode 100644 index 000000000..a62add568 --- /dev/null +++ b/newsfragments/3262.misc.rst @@ -0,0 +1,3 @@ +Since the L2 network is always implied based on the TACo network connected to, we no longer need those config/parameters across the codebase, it can be inferred. +Each Character now takes optional eth and polygon endpoints. +Remove various usages of redundant L2 values. General rename from ``[eth_]provider[_uri]`` to ``[blockchain/eth/polygon]_endpoint``. diff --git a/newsfragments/3262.removal.rst b/newsfragments/3262.removal.rst new file mode 100644 index 000000000..68cc6e776 --- /dev/null +++ b/newsfragments/3262.removal.rst @@ -0,0 +1 @@ +Deprecate configuration config/parameters ``pre-payment-network``, ``coordinator_uri`` since the L2 network is implied based on TACo network used. diff --git a/nucypher/__about__.py b/nucypher/__about__.py index 0edc4fea1..9e3f0acd0 100644 --- a/nucypher/__about__.py +++ b/nucypher/__about__.py @@ -14,7 +14,7 @@ __title__ = "nucypher" __url__ = "https://github.com/nucypher/nucypher" -__summary__ = 'A proxy re-encryption network to empower privacy in decentralized systems.' +__summary__ = "A threshold access control application to empower privacy in decentralized systems." __version__ = "6.2.0" diff --git a/nucypher/blockchain/eth/actors.py b/nucypher/blockchain/eth/actors.py index 20380cfc9..ced806495 100644 --- a/nucypher/blockchain/eth/actors.py +++ b/nucypher/blockchain/eth/actors.py @@ -30,19 +30,18 @@ from nucypher.acumen.nicknames import Nickname from nucypher.blockchain.eth.agents import ( ContractAgency, CoordinatorAgent, - NucypherTokenAgent, TACoApplicationAgent, TACoChildApplicationAgent, ) from nucypher.blockchain.eth.clients import PUBLIC_CHAINS from nucypher.blockchain.eth.constants import NULL_ADDRESS from nucypher.blockchain.eth.decorators import validate_checksum_address +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory from nucypher.blockchain.eth.registry import ( ContractRegistry, ) from nucypher.blockchain.eth.signers import Signer -from nucypher.blockchain.eth.token import NU from nucypher.blockchain.eth.trackers import dkg from nucypher.blockchain.eth.trackers.bonding import OperatorBondedTracker from nucypher.blockchain.eth.utils import truncate_checksum_address @@ -70,7 +69,7 @@ class BaseActor: @validate_checksum_address def __init__( self, - domain: Optional[str], + domain: str, registry: ContractRegistry, transacting_power: Optional[TransactingPower] = None, checksum_address: Optional[ChecksumAddress] = None, @@ -94,6 +93,7 @@ class BaseActor: self.transacting_power = transacting_power self.registry = registry self.network = domain + self.taco_domain_info = TACoDomain.get_domain_info(self.network) self._saved_receipts = list() # track receipts of transmitted transactions def __repr__(self): @@ -130,24 +130,6 @@ class NucypherTokenActor(BaseActor): super().__init__(registry=registry, **kwargs) self.__token_agent = None - @property - def token_agent(self): - if self.__token_agent: - return self.__token_agent - self.__token_agent = ContractAgency.get_agent( - NucypherTokenAgent, - provider_uri=self.eth_provider_uri, - registry=self.registry, - ) - return self.__token_agent - - @property - def token_balance(self) -> NU: - """Return this actor's current token balance""" - balance = int(self.token_agent.get_balance(address=self.checksum_address)) - nu_balance = NU(balance, 'NuNit') - return nu_balance - class Operator(BaseActor): READY_TIMEOUT = None # (None or 0) == indefinite @@ -158,25 +140,24 @@ class Operator(BaseActor): def __init__( self, - eth_provider_uri: str, - coordinator_provider_uri: str, - coordinator_network: str, + eth_endpoint: str, + polygon_endpoint: str, pre_payment_method: ContractPayment, transacting_power: TransactingPower, signer: Signer = None, crypto_power: CryptoPower = None, client_password: str = None, operator_address: Optional[ChecksumAddress] = None, - condition_provider_uris: Optional[Dict[int, List[str]]] = None, + condition_blockchain_endpoints: Optional[Dict[int, List[str]]] = None, publish_finalization: bool = True, # TODO: Remove this *args, **kwargs, ): # Falsy values may be passed down from the superclass - if not eth_provider_uri: - raise ValueError("Ethereum Provider URI is required to init an operator.") - if not coordinator_provider_uri: - raise ValueError("Polygon Provider URI is required to init an operator.") + if not eth_endpoint: + raise ValueError("Ethereum endpoint URI is required to init an operator.") + if not polygon_endpoint: + raise ValueError("Polygon endpoint URI is required to init an operator.") if not pre_payment_method: raise ValueError("PRE payment method is required to init an operator.") @@ -204,24 +185,21 @@ class Operator(BaseActor): self.application_agent = ContractAgency.get_agent( TACoApplicationAgent, - provider_uri=eth_provider_uri, + blockchain_endpoint=eth_endpoint, registry=self.registry, ) - # TODO: registry usage (and subsequently "network") is inconsistent here - coordinator_network_registry = ContractRegistry.from_latest_publication( - domain=coordinator_network - ) + registry = ContractRegistry.from_latest_publication(domain=self.network) self.child_application_agent = ContractAgency.get_agent( TACoChildApplicationAgent, - registry=coordinator_network_registry, - provider_uri=coordinator_provider_uri, + registry=registry, + blockchain_endpoint=polygon_endpoint, ) self.coordinator_agent = ContractAgency.get_agent( CoordinatorAgent, - registry=coordinator_network_registry, - provider_uri=coordinator_provider_uri, + registry=registry, + blockchain_endpoint=polygon_endpoint, ) # track active onchain rituals @@ -242,7 +220,7 @@ class Operator(BaseActor): ) # used for secure decryption request channel self.condition_providers = self.connect_condition_providers( - condition_provider_uris + condition_blockchain_endpoints ) def set_provider_public_key(self) -> Union[TxReceipt, None]: @@ -266,19 +244,22 @@ class Operator(BaseActor): return provider def connect_condition_providers( - self, condition_provider_uris: Optional[Dict[int, List[str]]] = None + self, condition_blockchain_endpoints: Optional[Dict[int, List[str]]] = None ) -> DefaultDict[int, Set[HTTPProvider]]: """Multi-provider support""" - # If condition_provider_uris is None the node operator + # If condition_blockchain_endpoints is None the node operator # did not configure any additional condition providers. - condition_provider_uris = condition_provider_uris or dict() + condition_blockchain_endpoints = condition_blockchain_endpoints or dict() # These are the chains that the Operator will connect to for conditions evaluation (read-only). condition_providers = defaultdict(set) # Now, add any additional providers that were passed in. - for chain_id, condition_provider_uris in condition_provider_uris.items(): + for ( + chain_id, + condition_blockchain_endpoints, + ) in condition_blockchain_endpoints.items(): if not self._is_permitted_condition_chain(chain_id): # this is a safety check to prevent the Operator from connecting to # chains that are not supported by ursulas on the network; @@ -288,7 +269,7 @@ class Operator(BaseActor): ) providers = set() - for uri in condition_provider_uris: + for uri in condition_blockchain_endpoints: provider = self._make_condition_provider(uri) providers.add(provider) @@ -742,10 +723,12 @@ class Operator(BaseActor): class PolicyAuthor(NucypherTokenActor): """Alice base class for blockchain operations, mocking up new policies!""" - def __init__(self, eth_provider_uri: str, *args, **kwargs): + def __init__(self, eth_endpoint: str, *args, **kwargs): super().__init__(*args, **kwargs) self.application_agent = ContractAgency.get_agent( - TACoApplicationAgent, registry=self.registry, provider_uri=eth_provider_uri + TACoApplicationAgent, + registry=self.registry, + blockchain_endpoint=eth_endpoint, ) def create_policy(self, *args, **kwargs): diff --git a/nucypher/blockchain/eth/agents.py b/nucypher/blockchain/eth/agents.py index 948e1539e..953f1a734 100644 --- a/nucypher/blockchain/eth/agents.py +++ b/nucypher/blockchain/eth/agents.py @@ -81,7 +81,7 @@ class EthereumContractAgent: def __init__( self, - provider_uri: str, + blockchain_endpoint: str, registry: ContractRegistry, contract: Optional[Contract] = None, transaction_gas: Optional[Wei] = None, @@ -91,7 +91,7 @@ class EthereumContractAgent: self.registry = registry self.blockchain = BlockchainInterfaceFactory.get_or_create_interface( - eth_provider_uri=provider_uri + endpoint=blockchain_endpoint ) if not contract: # Fetch the contract @@ -106,12 +106,14 @@ class EthereumContractAgent: transaction_gas = EthereumContractAgent.DEFAULT_TRANSACTION_GAS_LIMITS['default'] self.transaction_gas = transaction_gas - self.log.info("Initialized new {} for {} with {} and {}".format( - self.__class__.__name__, - self.contract.address, - self.blockchain.eth_provider_uri, - str(self.registry) - )) + self.log.info( + "Initialized new {} for {} with {} and {}".format( + self.__class__.__name__, + self.contract.address, + self.blockchain.endpoint, + str(self.registry), + ) + ) def __repr__(self) -> str: class_name = self.__class__.__name__ @@ -845,15 +847,15 @@ class ContractAgency: cls, agent_class: Type[types.Agent], registry: Optional[ContractRegistry], - provider_uri: Optional[str], + blockchain_endpoint: Optional[str], contract_version: Optional[str] = None, ) -> types.Agent: if not issubclass(agent_class, EthereumContractAgent): raise TypeError("Only agent subclasses can be used from the agency.") - if not provider_uri: + if not blockchain_endpoint: raise ValueError( - "Need to specify an Ethereum provider URI in order to get an agent from the ContractAgency" + "Need to specify a blockchain provider URI in order to get an agent from the ContractAgency" ) if not registry: @@ -869,7 +871,7 @@ class ContractAgency: types.Agent, agent_class( registry=registry, - provider_uri=provider_uri, + blockchain_endpoint=blockchain_endpoint, ), ) cls.__agents[registry_id] = cls.__agents.get(registry_id, dict()) @@ -889,7 +891,7 @@ class ContractAgency: cls, contract_name: str, registry: ContractRegistry, - provider_uri: str, + blockchain_endpoint: str, contract_version: Optional[str] = None, ) -> EthereumContractAgent: agent_name: str = cls._contract_name_to_agent_name(name=contract_name) @@ -898,7 +900,7 @@ class ContractAgency: agent: EthereumContractAgent = cls.get_agent( agent_class=agent_class, registry=registry, - provider_uri=provider_uri, + blockchain_endpoint=blockchain_endpoint, contract_version=contract_version ) return agent diff --git a/nucypher/blockchain/eth/domains.py b/nucypher/blockchain/eth/domains.py new file mode 100644 index 000000000..5603f3642 --- /dev/null +++ b/nucypher/blockchain/eth/domains.py @@ -0,0 +1,55 @@ +from enum import Enum +from typing import NamedTuple + + +class ChainInfo(NamedTuple): + id: int + name: str + + +class EthChain(ChainInfo, Enum): + MAINNET = (1, "mainnet") + GOERLI = (5, "goerli") + SEPOLIA = (11155111, "sepolia") + + +class PolygonChain(ChainInfo, Enum): + MAINNET = (137, "polygon") + MUMBAI = (80001, "mumbai") + + +class DomainInfo(NamedTuple): + name: str + eth_chain: EthChain + polygon_chain: PolygonChain + + @property + def is_testnet(self) -> bool: + return self.eth_chain != EthChain.MAINNET + + +class TACoDomain: + class Unrecognized(RuntimeError): + """Raised when a provided domain name is not recognized.""" + + MAINNET = DomainInfo("mainnet", EthChain.MAINNET, PolygonChain.MAINNET) + LYNX = DomainInfo("lynx", EthChain.GOERLI, PolygonChain.MUMBAI) + TAPIR = DomainInfo("tapir", EthChain.SEPOLIA, PolygonChain.MUMBAI) + + DEFAULT_DOMAIN_NAME: str = MAINNET.name + + SUPPORTED_DOMAINS = [ + MAINNET, + LYNX, + TAPIR, + ] + + SUPPORTED_DOMAIN_NAMES = [domain.name for domain in SUPPORTED_DOMAINS] + + @classmethod + def get_domain_info(cls, domain: str) -> DomainInfo: + for taco_domain in cls.SUPPORTED_DOMAINS: + if taco_domain.name == domain: + return taco_domain + + raise cls.Unrecognized(f"{domain} is not a recognized domain.") diff --git a/nucypher/blockchain/eth/interfaces.py b/nucypher/blockchain/eth/interfaces.py index 84fc9715a..7691e846c 100644 --- a/nucypher/blockchain/eth/interfaces.py +++ b/nucypher/blockchain/eth/interfaces.py @@ -6,7 +6,7 @@ from urllib.parse import urlparse import requests from constant_sorrow.constants import ( - INSUFFICIENT_ETH, + INSUFFICIENT_FUNDS, NO_BLOCKCHAIN_CONNECTION, UNKNOWN_TX_STATUS, ) @@ -82,7 +82,7 @@ class BlockchainInterface: pass REASONS = { - INSUFFICIENT_ETH: 'insufficient funds for gas * price + value', + INSUFFICIENT_FUNDS: "insufficient funds for gas * price + value", } class TransactionFailed(InterfaceError): @@ -100,7 +100,7 @@ class BlockchainInterface: self.payload = transaction_dict self.contract_function = contract_function self.failures = { - BlockchainInterface.REASONS[INSUFFICIENT_ETH]: self.insufficient_eth + BlockchainInterface.REASONS[INSUFFICIENT_FUNDS]: self.insufficient_funds } self.message = self.failures.get(self.base_message, self.default) super().__init__(self.message, *args) @@ -120,7 +120,7 @@ class BlockchainInterface: return balance @property - def insufficient_eth(self) -> str: + def insufficient_funds(self) -> str: try: transaction_fee = self.payload['gas'] * self.payload['gasPrice'] except KeyError: @@ -132,15 +132,16 @@ class BlockchainInterface: f'but sender only has {prettify_eth_amount(self.get_balance())}.' return message - def __init__(self, - emitter=None, # TODO # 1754 - poa: bool = None, - light: bool = False, - eth_provider_uri: str = NO_BLOCKCHAIN_CONNECTION, - eth_provider: BaseProvider = NO_BLOCKCHAIN_CONNECTION, - gas_strategy: Optional[Union[str, Callable]] = None, - max_gas_price: Optional[int] = None): - + def __init__( + self, + emitter=None, # TODO # 1754 + poa: bool = None, + light: bool = False, + endpoint: str = NO_BLOCKCHAIN_CONNECTION, + provider: BaseProvider = NO_BLOCKCHAIN_CONNECTION, + gas_strategy: Optional[Union[str, Callable]] = None, + max_gas_price: Optional[int] = None, + ): """ TODO: #1502 - Move to API docs. @@ -206,8 +207,8 @@ class BlockchainInterface: self.log = Logger('Blockchain') self.poa = poa - self.eth_provider_uri = eth_provider_uri - self._eth_provider = eth_provider + self.endpoint = endpoint + self._provider = provider self.w3 = NO_BLOCKCHAIN_CONNECTION self.client = NO_BLOCKCHAIN_CONNECTION self.is_light = light @@ -219,7 +220,7 @@ class BlockchainInterface: self.max_gas_price = max_gas_price def __repr__(self): - r = '{name}({uri})'.format(name=self.__class__.__name__, uri=self.eth_provider_uri) + r = "{name}({uri})".format(name=self.__class__.__name__, uri=self.endpoint) return r def get_blocktime(self): @@ -292,23 +293,30 @@ class BlockchainInterface: def connect(self): - eth_provider_uri = self.eth_provider_uri - self.log.info(f"Using external Web3 Provider '{self.eth_provider_uri}'") + endpoint = self.endpoint + self.log.info(f"Using external Web3 Provider '{self.endpoint}'") # Attach Provider - self._attach_eth_provider(eth_provider=self._eth_provider, eth_provider_uri=eth_provider_uri) - self.log.info("Connecting to {}".format(self.eth_provider_uri)) - if self._eth_provider is NO_BLOCKCHAIN_CONNECTION: + self._attach_blockchain_provider( + provider=self._provider, + endpoint=endpoint, + ) + self.log.info("Connecting to {}".format(self.endpoint)) + if self._provider is NO_BLOCKCHAIN_CONNECTION: raise self.NoProvider("There are no configured blockchain providers") # Connect if not connected try: - self.w3 = self.Web3(provider=self._eth_provider) + self.w3 = self.Web3(provider=self._provider) self.client = EthereumClient.from_w3(w3=self.w3) except requests.ConnectionError: # RPC - raise self.ConnectionFailed(f'Connection Failed - {str(self.eth_provider_uri)} - is RPC enabled?') - except FileNotFoundError: # IPC File Protocol - raise self.ConnectionFailed(f'Connection Failed - {str(self.eth_provider_uri)} - is IPC enabled?') + raise self.ConnectionFailed( + f"Connection Failed - {str(self.endpoint)} - is RPC enabled?" + ) + except FileNotFoundError: # IPC File Protocol + raise self.ConnectionFailed( + f"Connection Failed - {str(self.endpoint)} - is IPC enabled?" + ) else: self.attach_middleware() @@ -316,20 +324,22 @@ class BlockchainInterface: @property def provider(self) -> BaseProvider: - return self._eth_provider + return self._provider - def _attach_eth_provider(self, - eth_provider: Optional[BaseProvider] = None, - eth_provider_uri: str = None) -> None: + def _attach_blockchain_provider( + self, + provider: Optional[BaseProvider] = None, + endpoint: str = None, + ) -> None: """ https://web3py.readthedocs.io/en/latest/providers.html#providers """ - if not eth_provider_uri and not eth_provider: + if not endpoint and not provider: raise self.NoProvider("No URI or provider instances supplied.") - if eth_provider_uri and not eth_provider: - uri_breakdown = urlparse(eth_provider_uri) + if endpoint and not provider: + uri_breakdown = urlparse(endpoint) if uri_breakdown.scheme == 'tester': providers = { @@ -352,19 +362,23 @@ class BlockchainInterface: # auto-detect for file based ipc if not provider_scheme: - if Path(eth_provider_uri).is_file(): + if Path(endpoint).is_file(): # file is available - assume ipc/file scheme - provider_scheme = 'file' - self.log.info(f"Auto-detected provider scheme as 'file://' for provider {eth_provider_uri}") + provider_scheme = "file" + self.log.info( + f"Auto-detected provider scheme as 'file://' for provider {endpoint}" + ) try: - self._eth_provider = providers[provider_scheme](eth_provider_uri) + self._provider = providers[provider_scheme](endpoint) except KeyError: - raise self.UnsupportedProvider(f"{eth_provider_uri} is an invalid or unsupported blockchain provider URI") + raise self.UnsupportedProvider( + f"{endpoint} is an invalid or unsupported blockchain provider URI" + ) else: - self.eth_provider_uri = eth_provider_uri or NO_BLOCKCHAIN_CONNECTION + self.endpoint = endpoint or NO_BLOCKCHAIN_CONNECTION else: - self._eth_provider = eth_provider + self._provider = provider @classmethod def _handle_failed_transaction(cls, @@ -689,11 +703,11 @@ class BlockchainInterfaceFactory: return cls._instance @classmethod - def is_interface_initialized(cls, eth_provider_uri: str) -> bool: + def is_interface_initialized(cls, endpoint: str) -> bool: """ - Returns True if there is an existing connection with an equal eth_provider_uri. + Returns True if there is an existing connection with an equal endpoint. """ - return bool(cls._interfaces.get(eth_provider_uri, False)) + return bool(cls._interfaces.get(endpoint, False)) @classmethod def register_interface(cls, @@ -702,48 +716,59 @@ class BlockchainInterfaceFactory: force: bool = False ) -> None: - eth_provider_uri = interface.eth_provider_uri - if (eth_provider_uri in cls._interfaces) and not force: - raise cls.InterfaceAlreadyInitialized(f"A connection already exists for {eth_provider_uri}. " - "Use .get_interface instead.") + endpoint = interface.endpoint + if (endpoint in cls._interfaces) and not force: + raise cls.InterfaceAlreadyInitialized( + f"A connection already exists for {endpoint}. " + "Use .get_interface instead." + ) cached = cls.CachedInterface(interface=interface, emitter=emitter) - cls._interfaces[eth_provider_uri] = cached + cls._interfaces[endpoint] = cached @classmethod - def initialize_interface(cls, - eth_provider_uri: str, - emitter=None, - interface_class: Interfaces = None, - *interface_args, - **interface_kwargs - ) -> None: - if not eth_provider_uri: + def initialize_interface( + cls, + endpoint: str, + emitter=None, + interface_class: Interfaces = None, + *interface_args, + **interface_kwargs, + ) -> None: + if not endpoint: # Prevent empty strings and Falsy - raise BlockchainInterface.UnsupportedProvider(f"'{eth_provider_uri}' is not a valid provider URI") + raise BlockchainInterface.UnsupportedProvider( + f"'{endpoint}' is not a valid provider URI" + ) - if eth_provider_uri in cls._interfaces: - raise cls.InterfaceAlreadyInitialized(f"A connection already exists for {eth_provider_uri}. " - f"Use .get_interface instead.") + if endpoint in cls._interfaces: + raise cls.InterfaceAlreadyInitialized( + f"A connection already exists for {endpoint}. " + f"Use .get_interface instead." + ) # Interface does not exist, initialize a new one. if not interface_class: interface_class = cls._default_interface_class - interface = interface_class(eth_provider_uri=eth_provider_uri, - *interface_args, - **interface_kwargs) + interface = interface_class( + endpoint=endpoint, *interface_args, **interface_kwargs + ) interface.connect() - cls._interfaces[eth_provider_uri] = cls.CachedInterface(interface=interface, emitter=emitter) + cls._interfaces[endpoint] = cls.CachedInterface( + interface=interface, emitter=emitter + ) @classmethod - def get_interface(cls, eth_provider_uri: str = None) -> Interfaces: + def get_interface(cls, endpoint: str = None) -> Interfaces: # Try to get an existing cached interface. - if eth_provider_uri: + if endpoint: try: - cached_interface = cls._interfaces[eth_provider_uri] + cached_interface = cls._interfaces[endpoint] except KeyError: - raise cls.InterfaceNotInitialized(f"There is no connection for {eth_provider_uri}. " - f"Call .initialize_connection, then try again.") + raise cls.InterfaceNotInitialized( + f"There is no connection for {endpoint}. " + f"Call .initialize_connection, then try again." + ) # Try to use the most recently created interface by default. else: @@ -761,14 +786,16 @@ class BlockchainInterfaceFactory: return interface @classmethod - def get_or_create_interface(cls, - eth_provider_uri: str, - *interface_args, - **interface_kwargs - ) -> BlockchainInterface: + def get_or_create_interface( + cls, endpoint: str, *interface_args, **interface_kwargs + ) -> BlockchainInterface: try: - interface = cls.get_interface(eth_provider_uri=eth_provider_uri) + interface = cls.get_interface(endpoint=endpoint) except (cls.InterfaceNotInitialized, cls.NoRegisteredInterfaces): - cls.initialize_interface(eth_provider_uri=eth_provider_uri, *interface_args, **interface_kwargs) - interface = cls.get_interface(eth_provider_uri=eth_provider_uri) + cls.initialize_interface( + endpoint=endpoint, + *interface_args, + **interface_kwargs, + ) + interface = cls.get_interface(endpoint=endpoint) return interface diff --git a/nucypher/blockchain/eth/networks.py b/nucypher/blockchain/eth/networks.py deleted file mode 100644 index b1cd572e6..000000000 --- a/nucypher/blockchain/eth/networks.py +++ /dev/null @@ -1,57 +0,0 @@ -class NetworksInventory: # TODO: See #1564 - - MAINNET = "mainnet" - LYNX = "lynx" - IBEX = "ibex" # this is required for configuration file migrations (backwards compatibility) - ETH = "ethereum" - TAPIR = "tapir" - ORYX = "oryx" - - # TODO: Use naming scheme to preserve multiple compatibility with multiple deployments to a single network? - POLYGON = 'polygon' - MUMBAI = 'mumbai' - - UNKNOWN = 'unknown' # TODO: Is there a better way to signal an unknown network? - DEFAULT = MAINNET - - __to_chain_id_eth = { - MAINNET: 1, # Ethereum Mainnet - IBEX: 5, # this is required for configuration file migrations (backwards compatibility) - LYNX: 5, # Goerli - TAPIR: 11155111, # Sepolia - ORYX: 5, # Goerli - } - __to_chain_id_polygon = { - # TODO: Use naming scheme? - POLYGON: 137, # Polygon Mainnet - MUMBAI: 80001, # Polygon Testnet (Mumbai) - } - - ETH_NETWORKS = tuple(__to_chain_id_eth.keys()) - POLY_NETWORKS = tuple(__to_chain_id_polygon.keys()) - - NETWORKS = ETH_NETWORKS + POLY_NETWORKS - - class UnrecognizedNetwork(RuntimeError): - pass - - @classmethod - def get_ethereum_chain_id(cls, network): - try: - return cls.__to_chain_id_eth[network] - except KeyError: - raise cls.UnrecognizedNetwork(network) - - @classmethod - def get_polygon_chain_id(cls, network): - try: - return cls.__to_chain_id_polygon[network] - except KeyError: - raise cls.UnrecognizedNetwork(network) - - @classmethod - def validate_network_name(cls, network_name: str): - if network_name not in cls.NETWORKS: - raise cls.UnrecognizedNetwork( - f"{network_name} is not a recognized network." - ) diff --git a/nucypher/blockchain/eth/providers.py b/nucypher/blockchain/eth/providers.py index ac681fa95..6ad8de7e0 100644 --- a/nucypher/blockchain/eth/providers.py +++ b/nucypher/blockchain/eth/providers.py @@ -14,25 +14,33 @@ class ProviderError(Exception): pass -def _get_IPC_provider(eth_provider_uri) -> BaseProvider: - uri_breakdown = urlparse(eth_provider_uri) +def _get_IPC_provider(endpoint) -> BaseProvider: + uri_breakdown = urlparse(endpoint) from nucypher.blockchain.eth.interfaces import BlockchainInterface return IPCProvider(ipc_path=uri_breakdown.path, timeout=BlockchainInterface.TIMEOUT, request_kwargs={'timeout': BlockchainInterface.TIMEOUT}) -def _get_HTTP_provider(eth_provider_uri) -> BaseProvider: +def _get_HTTP_provider(endpoint) -> BaseProvider: from nucypher.blockchain.eth.interfaces import BlockchainInterface - return HTTPProvider(endpoint_uri=eth_provider_uri, request_kwargs={'timeout': BlockchainInterface.TIMEOUT}) + + return HTTPProvider( + endpoint_uri=endpoint, + request_kwargs={"timeout": BlockchainInterface.TIMEOUT}, + ) -def _get_websocket_provider(eth_provider_uri) -> BaseProvider: +def _get_websocket_provider(endpoint) -> BaseProvider: from nucypher.blockchain.eth.interfaces import BlockchainInterface - return WebsocketProvider(endpoint_uri=eth_provider_uri, websocket_kwargs={'timeout': BlockchainInterface.TIMEOUT}) + + return WebsocketProvider( + endpoint_uri=endpoint, + websocket_kwargs={"timeout": BlockchainInterface.TIMEOUT}, + ) -def _get_auto_provider(eth_provider_uri) -> BaseProvider: +def _get_auto_provider(endpoint) -> BaseProvider: from web3.auto import w3 # how-automated-detection-works: https://web3py.readthedocs.io/en/latest/providers.html connected = w3.isConnected() @@ -61,7 +69,7 @@ def _get_ethereum_tester(test_backend: Union[PyEVMBackend, MockBackend]) -> Ethe return provider -def _get_pyevm_test_provider(eth_provider_uri) -> BaseProvider: +def _get_pyevm_test_provider(endpoint) -> BaseProvider: """ Test provider entry-point""" # https://github.com/ethereum/eth-tester#pyevm-experimental pyevm_eth_tester = _get_pyevm_test_backend() @@ -69,13 +77,13 @@ def _get_pyevm_test_provider(eth_provider_uri) -> BaseProvider: return provider -def _get_mock_test_provider(eth_provider_uri) -> BaseProvider: +def _get_mock_test_provider(endpoint) -> BaseProvider: # https://github.com/ethereum/eth-tester#mockbackend mock_backend = MockBackend() provider = _get_ethereum_tester(test_backend=mock_backend) return provider -def _get_tester_ganache(eth_provider_uri=None) -> BaseProvider: - endpoint_uri = eth_provider_uri or 'http://localhost:7545' +def _get_tester_ganache(endpoint=None) -> BaseProvider: + endpoint_uri = endpoint or "http://localhost:7545" return HTTPProvider(endpoint_uri=endpoint_uri) diff --git a/nucypher/blockchain/eth/registry.py b/nucypher/blockchain/eth/registry.py index f5e5d0bc2..86638a4d3 100644 --- a/nucypher/blockchain/eth/registry.py +++ b/nucypher/blockchain/eth/registry.py @@ -9,7 +9,7 @@ import requests from requests import Response from web3.types import ABI -from nucypher.blockchain.eth.networks import NetworksInventory +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.utilities.logging import Logger RegistryArtifact = Dict[str, Union[str, ABI]] @@ -34,10 +34,10 @@ class RegistrySource(ABC): """Raised when there are no available registry sources""" def __init__(self, domain: str, *args, **kwargs): - if domain not in NetworksInventory.NETWORKS: + if domain not in TACoDomain.SUPPORTED_DOMAIN_NAMES: raise ValueError( f"{self.__class__.__name__} not available for domain '{domain}'. " - f"Valid options are: {', '.join(list(NetworksInventory.NETWORKS))}" + f"Valid options are: {', '.join(list(TACoDomain.SUPPORTED_DOMAIN_NAMES))}" ) self.domain = domain self.data = self.get() diff --git a/nucypher/blockchain/eth/signers/software.py b/nucypher/blockchain/eth/signers/software.py index 22334fc87..554b98f3d 100644 --- a/nucypher/blockchain/eth/signers/software.py +++ b/nucypher/blockchain/eth/signers/software.py @@ -34,7 +34,9 @@ class Web3Signer(Signer): BlockchainInterfaceFactory, ) try: - blockchain = BlockchainInterfaceFactory.get_or_create_interface(eth_provider_uri=uri) + blockchain = BlockchainInterfaceFactory.get_or_create_interface( + endpoint=uri + ) except BlockchainInterface.UnsupportedProvider: raise cls.InvalidSignerURI(uri) signer = cls(client=blockchain.client) diff --git a/nucypher/blockchain/eth/trackers/bonding.py b/nucypher/blockchain/eth/trackers/bonding.py index 0e966de13..cb8c8e409 100644 --- a/nucypher/blockchain/eth/trackers/bonding.py +++ b/nucypher/blockchain/eth/trackers/bonding.py @@ -20,7 +20,7 @@ class OperatorBondedTracker(SimpleTask): application_agent = ContractAgency.get_agent( TACoApplicationAgent, registry=self._ursula.registry, - provider_uri=self._ursula.eth_provider_uri, + blockchain_endpoint=self._ursula.eth_endpoint, ) # use TACo root since unbonding happens at root and not child (more immediate this way) staking_provider_address = application_agent.get_staking_provider_from_operator( diff --git a/nucypher/characters/base.py b/nucypher/characters/base.py index fedd22d96..aca564d67 100644 --- a/nucypher/characters/base.py +++ b/nucypher/characters/base.py @@ -34,7 +34,8 @@ class Character(Learner): def __init__( self, domain: str, - eth_provider_uri: str = None, + eth_endpoint: str = None, + polygon_endpoint: str = None, known_node_class: object = None, is_me: bool = True, checksum_address: str = None, @@ -113,14 +114,17 @@ class Character(Learner): except NoSigningPower: self._stamp = NO_SIGNING_POWER - self.eth_provider_uri = eth_provider_uri + self.eth_endpoint = eth_endpoint + self.polygon_endpoint = polygon_endpoint + self.registry = registry or ContractRegistry.from_latest_publication( domain=domain - ) # See #1580 + ) # REST - self.network_middleware = network_middleware or RestMiddleware(registry=self.registry, - eth_provider_uri=eth_provider_uri) + self.network_middleware = network_middleware or RestMiddleware( + registry=self.registry, eth_endpoint=eth_endpoint + ) # Learner Learner.__init__(self, diff --git a/nucypher/characters/lawful.py b/nucypher/characters/lawful.py index 803f2729e..d00f23218 100644 --- a/nucypher/characters/lawful.py +++ b/nucypher/characters/lawful.py @@ -131,7 +131,7 @@ class Alice(Character, actors.PolicyAuthor): self, # Mode is_me: bool = True, - eth_provider_uri: str = None, + eth_endpoint: str = None, signer=None, # Ownership checksum_address: Optional[ChecksumAddress] = None, @@ -170,7 +170,7 @@ class Alice(Character, actors.PolicyAuthor): self, known_node_class=Ursula, is_me=is_me, - eth_provider_uri=eth_provider_uri, + eth_endpoint=eth_endpoint, checksum_address=checksum_address, network_middleware=network_middleware, *args, @@ -179,7 +179,7 @@ class Alice(Character, actors.PolicyAuthor): if is_me: # TODO: #289 blockchain = BlockchainInterfaceFactory.get_interface( - eth_provider_uri=self.eth_provider_uri + endpoint=self.eth_endpoint ) signer = signer or Web3Signer( blockchain.client @@ -193,7 +193,7 @@ class Alice(Character, actors.PolicyAuthor): domain=self.domain, transacting_power=self.transacting_power, registry=self.registry, - eth_provider_uri=eth_provider_uri, + eth_endpoint=eth_endpoint, ) self.log = Logger(self.__class__.__name__) @@ -216,7 +216,7 @@ class Alice(Character, actors.PolicyAuthor): def add_active_policy(self, active_policy): """ - Adds a Policy object that is active on the NuCypher network to Alice's + Adds a Policy object that is active on the TACo network to Alice's `active_policies` dictionary by the policy ID. """ if active_policy.hrac in self.active_policies: @@ -458,9 +458,8 @@ class Bob(Character): self, is_me: bool = True, verify_node_bonding: bool = False, - eth_provider_uri: str = None, - coordinator_provider_uri: str = None, # TODO: Move to a higher level and formalize - coordinator_network: str = None, # TODO: Move to a higher level and formalize + eth_endpoint: str = None, + polygon_endpoint: str = None, *args, **kwargs, ) -> None: @@ -469,26 +468,22 @@ class Bob(Character): is_me=is_me, known_node_class=Ursula, verify_node_bonding=verify_node_bonding, - eth_provider_uri=eth_provider_uri, + eth_endpoint=eth_endpoint, + polygon_endpoint=polygon_endpoint, *args, **kwargs, ) coordinator_agent = None - if coordinator_provider_uri: - if not coordinator_network: - raise ValueError( - "If coordinator_provider_uri is set, coordinator_network must also be set" - ) + if polygon_endpoint: coordinator_agent = ContractAgency.get_agent( CoordinatorAgent, - provider_uri=coordinator_provider_uri, + blockchain_endpoint=polygon_endpoint, registry=ContractRegistry.from_latest_publication( - domain=coordinator_network + domain=self.domain, ), ) self.coordinator_agent = coordinator_agent - self.coordinator_network = coordinator_network # Cache of decrypted treasure maps self._treasure_maps: Dict[int, TreasureMap] = {} @@ -705,9 +700,7 @@ class Bob(Character): def _get_coordinator_agent(self) -> CoordinatorAgent: if not self.coordinator_agent: - raise ValueError( - "No coordinator provider URI provided in Bob's constructor." - ) + raise ValueError("No polygon endpoint URI provided in Bob's constructor.") return self.coordinator_agent @@ -825,8 +818,9 @@ class Ursula(Teacher, Character, Operator): client_password: Optional[str] = None, transacting_power: Optional[TransactingPower] = None, operator_signature_from_metadata=NOT_SIGNED, - eth_provider_uri: Optional[str] = None, - condition_provider_uris: Optional[Dict[int, List[str]]] = None, + eth_endpoint: Optional[str] = None, + polygon_endpoint: Optional[str] = None, + condition_blockchain_endpoints: Optional[Dict[int, List[str]]] = None, pre_payment_method: Optional[Union[PaymentMethod, ContractPayment]] = None, # Character abort_on_learning_error: bool = False, @@ -844,7 +838,8 @@ class Ursula(Teacher, Character, Operator): domain=domain, known_node_class=Ursula, include_self_in_the_state=True, - eth_provider_uri=eth_provider_uri, + eth_endpoint=eth_endpoint, + polygon_endpoint=polygon_endpoint, **character_kwargs, ) @@ -863,13 +858,12 @@ class Ursula(Teacher, Character, Operator): signer=self.signer, crypto_power=self._crypto_power, operator_address=operator_address, - eth_provider_uri=eth_provider_uri, + eth_endpoint=eth_endpoint, + polygon_endpoint=polygon_endpoint, pre_payment_method=pre_payment_method, client_password=client_password, - condition_provider_uris=condition_provider_uris, - coordinator_provider_uri=pre_payment_method.provider, + condition_blockchain_endpoints=condition_blockchain_endpoints, transacting_power=transacting_power, - coordinator_network=pre_payment_method.network, ) except Exception: @@ -997,11 +991,9 @@ class Ursula(Teacher, Character, Operator): # Connect to Provider if not BlockchainInterfaceFactory.is_interface_initialized( - eth_provider_uri=self.eth_provider_uri + endpoint=self.eth_endpoint ): - BlockchainInterfaceFactory.initialize_interface( - eth_provider_uri=self.eth_provider_uri - ) + BlockchainInterfaceFactory.initialize_interface(endpoint=self.eth_endpoint) if preflight: self.__preflight() @@ -1189,15 +1181,15 @@ class Ursula(Teacher, Character, Operator): return cls.from_seed_and_stake_info(seed_uri=seed_uri, *args, **kwargs) @classmethod - def seednode_for_network(cls, network: str, provider_uri: str) -> "Ursula": + def seednode_for_domain(cls, domain: str, eth_endpoint: str) -> "Ursula": """Returns a default seednode ursula for a given network.""" try: - url = TEACHER_NODES[network][0] + url = TEACHER_NODES[domain][0] except KeyError: - raise ValueError(f'"{network}" is not a known network.') + raise ValueError(f'"{domain}" is not a known domain.') except IndexError: - raise ValueError(f'No default seednodes available for "{network}".') - ursula = cls.from_seed_and_stake_info(seed_uri=url, provider_uri=provider_uri) + raise ValueError(f'No default seednodes available for "{domain}".') + ursula = cls.from_seed_and_stake_info(seed_uri=url, eth_endpoint=eth_endpoint) return ursula @classmethod @@ -1205,7 +1197,7 @@ class Ursula(Teacher, Character, Operator): cls, teacher_uri: str, min_stake: int, - provider_uri: str, + eth_endpoint: str, registry: ContractRegistry = None, network_middleware: RestMiddleware = None, retry_attempts: int = 2, @@ -1220,7 +1212,7 @@ class Ursula(Teacher, Character, Operator): try: teacher = cls.from_seed_and_stake_info( seed_uri=teacher_uri, - provider_uri=provider_uri, + eth_endpoint=eth_endpoint, minimum_stake=min_stake, network_middleware=network_middleware, registry=registry, @@ -1244,14 +1236,14 @@ class Ursula(Teacher, Character, Operator): def from_seed_and_stake_info( cls, seed_uri: str, - provider_uri: str, + eth_endpoint: str, registry: ContractRegistry = None, minimum_stake: int = 0, network_middleware: RestMiddleware = None, ) -> Union["Ursula", "NodeSprout"]: if network_middleware is None: network_middleware = RestMiddleware( - registry=registry, eth_provider_uri=provider_uri + registry=registry, eth_endpoint=eth_endpoint ) # Parse node URI @@ -1280,7 +1272,9 @@ class Ursula(Teacher, Character, Operator): # Check the node's stake (optional) if minimum_stake > 0 and staking_provider_address: application_agent = ContractAgency.get_agent( - TACoApplicationAgent, provider_uri=provider_uri, registry=registry + TACoApplicationAgent, + blockchain_endpoint=eth_endpoint, + registry=registry, ) seednode_stake = application_agent.get_authorized_stake( staking_provider=staking_provider_address diff --git a/nucypher/characters/unlawful.py b/nucypher/characters/unlawful.py index 46abdac8f..b4c97ca8c 100644 --- a/nucypher/characters/unlawful.py +++ b/nucypher/characters/unlawful.py @@ -42,26 +42,25 @@ class Vladimir(Ursula): raise DevelopmentInstallationRequired( importable_name="tests.utils.middleware.EvilMiddleWare" ) - blockchain = target_ursula.application_agent.blockchain - cls.network_middleware = EvilMiddleWare( - eth_provider_uri=blockchain.eth_provider_uri - ) + eth_blockchain = target_ursula.application_agent.blockchain + cls.network_middleware = EvilMiddleWare(eth_endpoint=eth_blockchain.endpoint) + + polygon_blockchain = target_ursula.child_application_agent.blockchain crypto_power = CryptoPower(power_ups=target_ursula._default_crypto_powerups) - cls.attach_transacting_key(blockchain=blockchain) + cls.attach_transacting_key(blockchain=eth_blockchain) # Vladimir does not care about payment. bogus_pre_payment_method = FreeReencryptions() bogus_pre_payment_method.provider = Mock() bogus_pre_payment_method.agent = Mock() - bogus_pre_payment_method.network = TEMPORARY_DOMAIN bogus_pre_payment_method.agent.blockchain.client.chain_id = ( - blockchain.client.chain_id + polygon_blockchain.client.chain_id ) mock.patch( "mock.interfaces.MockBlockchain.client.chain_id", - new_callable=mock.PropertyMock(return_value=blockchain.client.chain_id), + new_callable=mock.PropertyMock(return_value=eth_blockchain.client.chain_id), ) vladimir = cls( @@ -74,8 +73,9 @@ class Vladimir(Ursula): network_middleware=cls.network_middleware, checksum_address=cls.fraud_address, operator_address=cls.fraud_address, - signer=Web3Signer(blockchain.client), - eth_provider_uri=blockchain.eth_provider_uri, + signer=Web3Signer(eth_blockchain.client), + eth_endpoint=eth_blockchain.endpoint, + polygon_endpoint=polygon_blockchain.endpoint, pre_payment_method=bogus_pre_payment_method, ) diff --git a/nucypher/cli/actions/configure.py b/nucypher/cli/actions/configure.py index 909749f70..513e06e9d 100644 --- a/nucypher/cli/actions/configure.py +++ b/nucypher/cli/actions/configure.py @@ -126,13 +126,13 @@ def handle_invalid_configuration_file(emitter: StdoutEmitter, def collect_operator_ip_address( - emitter: StdoutEmitter, network: str, provider_uri: str, force: bool = False + emitter: StdoutEmitter, domain: str, eth_endpoint: str, force: bool = False ) -> str: # From node swarm try: message = "Detecting external IP address automatically" emitter.message(message, verbosity=2) - ip = determine_external_ip_address(network=network, provider_uri=provider_uri) + ip = determine_external_ip_address(domain=domain, eth_endpoint=eth_endpoint) except UnknownIPAddress: if force: raise @@ -157,9 +157,9 @@ def perform_startup_ip_check(emitter: StdoutEmitter, ursula: Ursula, force: bool """ try: external_ip = determine_external_ip_address( - network=ursula.domain, + domain=ursula.domain, known_nodes=ursula.known_nodes, - provider_uri=ursula.eth_provider_uri, + eth_endpoint=ursula.eth_endpoint, ) except UnknownIPAddress: message = 'Cannot automatically determine external IP address' diff --git a/nucypher/cli/actions/select.py b/nucypher/cli/actions/select.py index 94c55919d..199696ae0 100644 --- a/nucypher/cli/actions/select.py +++ b/nucypher/cli/actions/select.py @@ -1,5 +1,3 @@ - - import os from pathlib import Path from typing import Optional, Type @@ -8,22 +6,20 @@ import click from tabulate import tabulate from web3.main import Web3 -from nucypher.blockchain.eth.agents import ContractAgency, NucypherTokenAgent +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory -from nucypher.blockchain.eth.networks import NetworksInventory from nucypher.blockchain.eth.registry import ( ContractRegistry, ) from nucypher.blockchain.eth.signers.base import Signer -from nucypher.blockchain.eth.token import NU from nucypher.cli.actions.configure import get_config_filepaths from nucypher.cli.literature import ( DEFAULT_TO_LONE_CONFIG_FILE, GENERIC_SELECT_ACCOUNT, IGNORE_OLD_CONFIGURATION, + NO_ACCOUNTS, NO_CONFIGURATIONS_ON_DISK, - NO_ETH_ACCOUNTS, - SELECT_NETWORK, + SELECT_DOMAIN, SELECTED_ACCOUNT, ) from nucypher.config.base import CharacterConfiguration @@ -36,53 +32,56 @@ from nucypher.utilities.emitters import StdoutEmitter def select_client_account( emitter, - eth_provider_uri: str = None, + polygon_endpoint: str = None, signer: Signer = None, signer_uri: str = None, prompt: str = None, default: int = 0, registry: ContractRegistry = None, - show_eth_balance: bool = False, - show_nu_balance: bool = False, + show_matic_balance: bool = False, show_staking: bool = False, - network: str = None, + domain: str = None, poa: bool = None, ) -> str: """ - Interactively select an ethereum wallet account from a table of nucypher account metadata. + Interactively select an ethereum wallet account from a table of account metadata. - Note: Showing ETH and/or NU balances, causes an eager blockchain connection. + Note: Showing MATIC balance causes an eager blockchain connection. """ if signer and signer_uri: raise ValueError('Pass either signer or signer_uri but not both.') - if not any((eth_provider_uri, signer_uri, signer)): + if not any((polygon_endpoint, signer_uri, signer)): raise ValueError("At least a provider URI, signer URI or signer must be provided to select an account") - if eth_provider_uri: + if polygon_endpoint: # Connect to the blockchain in order to select an account - if not BlockchainInterfaceFactory.is_interface_initialized(eth_provider_uri=eth_provider_uri): - BlockchainInterfaceFactory.initialize_interface(eth_provider_uri=eth_provider_uri, poa=poa, emitter=emitter) + if not BlockchainInterfaceFactory.is_interface_initialized( + endpoint=polygon_endpoint + ): + BlockchainInterfaceFactory.initialize_interface( + endpoint=polygon_endpoint, poa=poa, emitter=emitter + ) if not signer_uri: - signer_uri = eth_provider_uri + signer_uri = polygon_endpoint - blockchain = BlockchainInterfaceFactory.get_interface(eth_provider_uri=eth_provider_uri) + blockchain = BlockchainInterfaceFactory.get_interface(endpoint=polygon_endpoint) if signer_uri and not signer: - testnet = network != NetworksInventory.MAINNET + testnet = domain != TACoDomain.MAINNET.name signer = Signer.from_signer_uri(signer_uri, testnet=testnet) # Display accounts info - if show_nu_balance or show_staking: # Lazy registry fetching + if show_staking: # Lazy registry fetching if not registry: - if not network: - raise ValueError("Pass network name or registry; Got neither.") - registry = ContractRegistry.from_latest_publication(domain=network) + if not domain: + raise ValueError("Pass domain name or registry; Got neither.") + registry = ContractRegistry.from_latest_publication(domain=domain) enumerated_accounts = dict(enumerate(signer.accounts)) if len(enumerated_accounts) < 1: - emitter.echo(NO_ETH_ACCOUNTS, color='red', bold=True) + emitter.echo(NO_ACCOUNTS, color="red", bold=True) raise click.Abort() elif len(enumerated_accounts) == 1: # There are no choices if there is only one available address. @@ -90,23 +89,17 @@ def select_client_account( # Display account info headers = ['Account'] - if show_eth_balance: - headers.append('ETH') - if show_nu_balance: - headers.append('NU') + if show_matic_balance: + headers.append("MATIC") rows = list() for index, account in enumerated_accounts.items(): row = [account] - if show_eth_balance: - ether_balance = Web3.from_wei(blockchain.client.get_balance(account), 'ether') - row.append(f'{ether_balance} ETH') - if show_nu_balance: - token_agent = ContractAgency.get_agent( - NucypherTokenAgent, registry=registry, provider_uri=eth_provider_uri + if show_matic_balance: + matic_balance = Web3.from_wei( + blockchain.client.get_balance(account), "ether" ) - token_balance = NU.from_units(token_agent.get_balance(account, registry)) - row.append(token_balance) + row.append(f"{matic_balance} MATIC") rows.append(row) emitter.echo(tabulate(rows, headers=headers, showindex='always')) @@ -120,24 +113,19 @@ def select_client_account( return chosen_account -def select_network(emitter: StdoutEmitter, network_type: str, message: Optional[str] = None) -> str: - """Interactively select a network from nucypher networks inventory list""" +def select_domain(emitter: StdoutEmitter, message: Optional[str] = None) -> str: + """Interactively select a domain from TACo domain inventory list""" emitter.message(message=message or str(), color="yellow") - if network_type == NetworksInventory.ETH: - network_list = NetworksInventory.ETH_NETWORKS - elif network_type == NetworksInventory.POLYGON: - network_list = NetworksInventory.POLY_NETWORKS - else: - raise(ValueError("Network type must be either 'eth' or 'polygon'")) - rows = [[n] for n in network_list] + domain_list = TACoDomain.SUPPORTED_DOMAIN_NAMES + rows = [[n] for n in domain_list] emitter.echo(tabulate(rows, showindex="always")) choice = click.prompt( - SELECT_NETWORK, + SELECT_DOMAIN, default=0, type=click.IntRange(0, len(rows) - 1), ) - network = network_list[choice] - return network + domain = domain_list[choice] + return domain def select_config_file(emitter: StdoutEmitter, diff --git a/nucypher/cli/commands/taco.py b/nucypher/cli/commands/taco.py index a7bdfc752..b1c9dbf62 100644 --- a/nucypher/cli/commands/taco.py +++ b/nucypher/cli/commands/taco.py @@ -11,7 +11,7 @@ from nucypher.blockchain.eth.constants import ( AVERAGE_BLOCK_TIME_IN_SECONDS, TACO_CONTRACT_NAMES, ) -from nucypher.blockchain.eth.networks import NetworksInventory +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.cli.config import group_general_config from nucypher.cli.options import ( group_options, @@ -30,19 +30,19 @@ from nucypher.cli.utils import ( ) from nucypher.utilities.events import generate_events_csv_filepath -option_provider_uri = click.option( - "--provider-uri", - "provider_uri", +option_blockchain_endpoint = click.option( + "--blockchain-endpoint", + "blockchain_endpoint", help="Blockchain provider's URI i.e. 'file:///path/to/geth.ipc'", type=click.STRING, required=True, ) -option_network = click.option( - "--network", - help="TACo Network", +option_domain = click.option( + "--domain", + help="TACo Domain", type=click.STRING, - default=click.Choice(NetworksInventory.NETWORKS), + default=click.Choice(TACoDomain.SUPPORTED_DOMAIN_NAMES), required=True, ) @@ -50,19 +50,19 @@ option_network = click.option( class RegistryOptions: __option_name__ = "registry_options" - def __init__(self, provider_uri, poa, registry_filepath, light, network): - self.provider_uri = provider_uri + def __init__(self, blockchain_endpoint, poa, registry_filepath, light, domain): + self.blockchain_endpoint = blockchain_endpoint self.poa = poa self.registry_filepath = registry_filepath self.light = light - self.network = network + self.domain = domain def setup(self, general_config) -> tuple: emitter = setup_emitter(general_config) registry = get_registry( - network=self.network, registry_filepath=self.registry_filepath + domain=self.domain, registry_filepath=self.registry_filepath ) - return emitter, registry, self.provider_uri + return emitter, registry, self.blockchain_endpoint group_registry_options = group_options( @@ -70,8 +70,8 @@ group_registry_options = group_options( poa=option_poa, light=option_light, registry_filepath=option_registry_filepath, - network=option_network, - provider_uri=option_provider_uri, + domain=option_domain, + blockchain_endpoint=option_blockchain_endpoint, ) option_csv = click.option( @@ -117,11 +117,11 @@ def taco(): @group_general_config def application_info(general_config, registry_options): """Overall information for the TACo Application.""" - emitter, registry, provider_uri = registry_options.setup( + emitter, registry, blockchain_endpoint = registry_options.setup( general_config=general_config ) paint_application_contract_status( - emitter=emitter, registry=registry, provider_uri=provider_uri + emitter=emitter, registry=registry, eth_endpoint=blockchain_endpoint ) @@ -130,11 +130,11 @@ def application_info(general_config, registry_options): @group_general_config def active_providers(general_config, registry_options): """List of active stakers for the TACo Application""" - emitter, registry, provider_uri = registry_options.setup( + emitter, registry, blockchain_endpoint = registry_options.setup( general_config=general_config ) application_agent = ContractAgency.get_agent( - TACoApplicationAgent, registry=registry, provider_uri=provider_uri + TACoApplicationAgent, registry=registry, blockchain_endpoint=blockchain_endpoint ) ( total_staked, @@ -194,12 +194,14 @@ def events( ), ) - emitter, registry, provider_uri = registry_options.setup( + emitter, registry, blockchain_endpoint = registry_options.setup( general_config=general_config ) contract_agent = ContractAgency.get_agent_by_contract_name( - contract_name=contract_name, registry=registry, provider_uri=provider_uri + contract_name=contract_name, + registry=registry, + blockchain_endpoint=blockchain_endpoint, ) if from_block is None: diff --git a/nucypher/cli/commands/ursula.py b/nucypher/cli/commands/ursula.py index 37082dc0d..37d11d849 100644 --- a/nucypher/cli/commands/ursula.py +++ b/nucypher/cli/commands/ursula.py @@ -2,7 +2,6 @@ from pathlib import Path import click -from nucypher.blockchain.eth.networks import NetworksInventory from nucypher.cli.actions.auth import ( get_client_password, get_nucypher_password, @@ -15,26 +14,28 @@ from nucypher.cli.actions.configure import ( handle_missing_configuration_file, perform_startup_ip_check, ) -from nucypher.cli.actions.configure import forget as forget_nodes +from nucypher.cli.actions.configure import ( + forget as forget_nodes, +) from nucypher.cli.actions.select import ( select_client_account, select_config_file, - select_network, + select_domain, ) from nucypher.cli.config import group_general_config from nucypher.cli.literature import ( DEVELOPMENT_MODE_WARNING, FORCE_MODE_WARNING, SELECT_OPERATOR_ACCOUNT, - SELECT_PRE_PAYMENT_NETWORK, ) from nucypher.cli.options import ( group_options, option_config_file, option_config_root, option_dev, + option_domain, option_dry_run, - option_eth_provider_uri, + option_eth_endpoint, option_force, option_gas_strategy, option_key_material, @@ -42,12 +43,9 @@ from nucypher.cli.options import ( option_lonely, option_max_gas_price, option_min_stake, - option_network, option_poa, - option_policy_registry_filepath, + option_polygon_endpoint, option_pre_payment_method, - option_pre_payment_network, - option_pre_payment_provider, option_registry_filepath, option_signer_uri, option_teacher_uri, @@ -74,13 +72,12 @@ class UrsulaConfigOptions: def __init__( self, - eth_provider_uri: str, + eth_endpoint: str, operator_address: str, rest_host: str, rest_port: int, - network: str, + domain: str, registry_filepath: Path, - policy_registry_filepath: Path, dev: bool, poa: bool, light: bool, @@ -88,19 +85,17 @@ class UrsulaConfigOptions: max_gas_price: int, # gwei signer_uri: str, lonely: bool, + polygon_endpoint: str, pre_payment_method: str, - pre_payment_provider: str, - pre_payment_network: str, ): - self.eth_provider_uri = eth_provider_uri + self.eth_endpoint = eth_endpoint self.signer_uri = signer_uri self.operator_address = operator_address self.rest_host = rest_host self.rest_port = rest_port # FIXME: not used in generate() - self.domain = network + self.domain = domain self.registry_filepath = registry_filepath - self.policy_registry_filepath = policy_registry_filepath self.dev = dev self.poa = poa self.light = light @@ -108,8 +103,7 @@ class UrsulaConfigOptions: self.max_gas_price = max_gas_price self.lonely = lonely self.pre_payment_method = pre_payment_method - self.pre_payment_provider = pre_payment_provider - self.pre_payment_network = pre_payment_network + self.polygon_endpoint = polygon_endpoint def create_config(self, emitter, config_file): if self.dev: @@ -120,8 +114,7 @@ class UrsulaConfigOptions: poa=self.poa, light=self.light, registry_filepath=self.registry_filepath, - policy_registry_filepath=self.policy_registry_filepath, - eth_provider_uri=self.eth_provider_uri, + eth_endpoint=self.eth_endpoint, signer_uri=self.signer_uri, gas_strategy=self.gas_strategy, max_gas_price=self.max_gas_price, @@ -129,8 +122,7 @@ class UrsulaConfigOptions: rest_host=self.rest_host, rest_port=self.rest_port, pre_payment_method=self.pre_payment_method, - pre_payment_provider=self.pre_payment_provider, - pre_payment_network=self.pre_payment_network, + polygon_endpoint=self.polygon_endpoint, ) else: if not config_file: @@ -143,8 +135,7 @@ class UrsulaConfigOptions: filepath=config_file, domain=self.domain, registry_filepath=self.registry_filepath, - policy_registry_filepath=self.policy_registry_filepath, - eth_provider_uri=self.eth_provider_uri, + eth_endpoint=self.eth_endpoint, signer_uri=self.signer_uri, gas_strategy=self.gas_strategy, max_gas_price=self.max_gas_price, @@ -153,8 +144,7 @@ class UrsulaConfigOptions: poa=self.poa, light=self.light, pre_payment_method=self.pre_payment_method, - pre_payment_provider=self.pre_payment_provider, - pre_payment_network=self.pre_payment_network, + polygon_endpoint=self.polygon_endpoint, ) except FileNotFoundError: return handle_missing_configuration_file(character_config_class=UrsulaConfiguration, config_file=config_file) @@ -175,7 +165,7 @@ class UrsulaConfigOptions: self.operator_address = select_client_account( emitter=emitter, prompt=prompt, - eth_provider_uri=self.eth_provider_uri, + polygon_endpoint=self.polygon_endpoint, signer_uri=self.signer_uri, ) @@ -183,9 +173,9 @@ class UrsulaConfigOptions: if not self.rest_host: self.rest_host = collect_operator_ip_address( emitter, - network=self.domain, + domain=self.domain, force=force, - provider_uri=self.eth_provider_uri, + eth_endpoint=self.eth_endpoint, ) return UrsulaConfiguration.generate( @@ -197,16 +187,14 @@ class UrsulaConfigOptions: domain=self.domain, operator_address=self.operator_address, registry_filepath=self.registry_filepath, - policy_registry_filepath=self.policy_registry_filepath, - eth_provider_uri=self.eth_provider_uri, + eth_endpoint=self.eth_endpoint, signer_uri=self.signer_uri, gas_strategy=self.gas_strategy, max_gas_price=self.max_gas_price, poa=self.poa, light=self.light, pre_payment_method=self.pre_payment_method, - pre_payment_provider=self.pre_payment_provider, - pre_payment_network=self.pre_payment_network, + polygon_endpoint=self.polygon_endpoint, ) def get_updates(self) -> dict: @@ -216,16 +204,14 @@ class UrsulaConfigOptions: domain=self.domain, operator_address=self.operator_address, registry_filepath=self.registry_filepath, - policy_registry_filepath=self.policy_registry_filepath, - eth_provider_uri=self.eth_provider_uri, + eth_endpoint=self.eth_endpoint, signer_uri=self.signer_uri, gas_strategy=self.gas_strategy, max_gas_price=self.max_gas_price, poa=self.poa, light=self.light, pre_payment_method=self.pre_payment_method, - pre_payment_provider=self.pre_payment_provider, - pre_payment_network=self.pre_payment_network, + polygon_endpoint=self.polygon_endpoint, ) # Depends on defaults being set on Configuration classes, filtrates None values updates = {k: v for k, v in payload.items() if v is not None} @@ -235,7 +221,7 @@ class UrsulaConfigOptions: group_config_options = group_options( # NOTE: Don't set defaults here or they will be applied to config updates. Use the Config API. UrsulaConfigOptions, - eth_provider_uri=option_eth_provider_uri(), + eth_endpoint=option_eth_endpoint(), signer_uri=option_signer_uri, gas_strategy=option_gas_strategy, max_gas_price=option_max_gas_price, @@ -254,15 +240,13 @@ group_config_options = group_options( help="The host port to run Ursula network services on", type=NETWORK_PORT, ), - network=option_network(), + domain=option_domain(), registry_filepath=option_registry_filepath, - policy_registry_filepath=option_policy_registry_filepath, poa=option_poa, light=option_light, dev=option_dev, lonely=option_lonely, - pre_payment_provider=option_pre_payment_provider, - pre_payment_network=option_pre_payment_network, + polygon_endpoint=option_polygon_endpoint, pre_payment_method=option_pre_payment_method, ) @@ -290,7 +274,7 @@ class UrsulaCharacterOptions: URSULA = make_cli_character( character_config=ursula_config, emitter=emitter, - provider_uri=ursula_config.eth_provider_uri, + eth_endpoint=ursula_config.eth_endpoint, min_stake=self.min_stake, teacher_uri=self.teacher_uri, unlock_keystore=not self.config_options.dev, @@ -333,32 +317,25 @@ def init(general_config, config_options, force, config_root, key_material): _pre_launch_warnings(emitter, dev=None, force=force) if not config_root: config_root = general_config.config_root - if not config_options.eth_provider_uri: + if not config_options.eth_endpoint: raise click.BadOptionUsage( - "--eth-provider", + "--eth-endpoint", message=click.style( - "--eth-provider is required to initialize a new ursula.", fg="red" + "--eth-endpoint is required to initialize a new ursula.", fg="red" ), ) - if not config_options.pre_payment_provider: + if not config_options.polygon_endpoint: raise click.BadOptionUsage( - "--pre-payment-provider", + "--polygon-endpoint", message=click.style( - "--pre-payment-provider is required to initialize a new ursula.", + "--polygon-endpoint is required to initialize a new ursula.", fg="red", ), ) if not config_options.domain: - config_options.domain = select_network( + config_options.domain = select_domain( emitter, - message="Select Staking Network", - network_type=NetworksInventory.ETH, - ) - if not config_options.pre_payment_network: - config_options.pre_payment_network = select_network( - emitter, - message=SELECT_PRE_PAYMENT_NETWORK, - network_type=NetworksInventory.POLYGON, + message="Select TACo Domain", ) ursula_config = config_options.generate_config( emitter=emitter, config_root=config_root, force=force, key_material=key_material @@ -496,9 +473,9 @@ def config(general_config, config_options, config_file, force, action): if action == "ip-address": rest_host = collect_operator_ip_address( emitter=emitter, - network=config_options.domain, + domain=config_options.domain, force=force, - provider_uri=config_options.eth_provider_uri, + eth_endpoint=config_options.eth_endpoint, ) config_options.rest_host = rest_host if action == "migrate": diff --git a/nucypher/cli/literature.py b/nucypher/cli/literature.py index 79d729ac2..4a6024442 100644 --- a/nucypher/cli/literature.py +++ b/nucypher/cli/literature.py @@ -43,9 +43,7 @@ nucypher {init_command} """ -SELECT_NETWORK = "Select Network" - -SELECT_PRE_PAYMENT_NETWORK = "Select PRE Payment Network" +SELECT_DOMAIN = "Select TACo Domain" NO_CONFIGURATIONS_ON_DISK = "No {name} configurations found. Run 'nucypher {command} init' then try again." @@ -55,7 +53,7 @@ INVALID_JSON_IN_CONFIGURATION_WARNING = "Invalid JSON in Configuration File at { INVALID_CONFIGURATION_FILE_WARNING = "Invalid Configuration at {filepath}." -NO_ETH_ACCOUNTS = "No ETH accounts were found." +NO_ACCOUNTS = "No accounts were found." GENERIC_SELECT_ACCOUNT = "Select index of account" diff --git a/nucypher/cli/options.py b/nucypher/cli/options.py index 574dafa21..ff7a0a43e 100644 --- a/nucypher/cli/options.py +++ b/nucypher/cli/options.py @@ -14,7 +14,7 @@ from nucypher.cli.types import ( NETWORK_PORT, PRE_PAYMENT_METHOD_CHOICES, STAKED_TOKENS_RANGE, - NuCypherNetworkName, + NuCypherDomainName, ) from nucypher.utilities.logging import Logger @@ -79,19 +79,13 @@ option_parameters = click.option( help="Filepath to a JSON file containing additional parameters", type=EXISTING_READABLE_FILE, ) -option_pre_payment_provider = click.option( - "--pre-payment-provider", - "pre_payment_provider", +option_polygon_endpoint = click.option( + "--polygon-endpoint", + "polygon_endpoint", help="Connection URL for PRE payment method", type=click.STRING, required=False, ) -option_pre_payment_network = click.option( - "--pre-payment-network", - help="PRE payment network name", - type=click.STRING, - required=False, -) # TODO: Choices option_pre_payment_method = click.option( "--pre-payment-method", help="PRE payment method name", @@ -106,11 +100,6 @@ option_registry_filepath = click.option( help="Custom contract registry filepath", type=EXISTING_READABLE_FILE, ) -option_policy_registry_filepath = click.option( - "--policy-registry-filepath", - help="Custom contract registry filepath for policies", - type=EXISTING_READABLE_FILE, -) option_signer_uri = click.option("--signer", "signer_uri", "-S", default=None, type=str) option_staking_provider = click.option( "--staking-provider", @@ -180,13 +169,15 @@ def option_message_kit(required: bool = False, multiple: bool = False): required=required) -def option_network(required: bool = False, - default: str = None, # NetworksInventory.DEFAULT is not a good global default (2214) - validate: bool = False): +def option_domain( + required: bool = False, + default: str = None, # nucypher.blockchain.eth.domains.DEFAULT.name is not a good global default (#2214) + validate: bool = False, +): return click.option( - '--network', - help="NuCypher Network/Domain Name", - type=NuCypherNetworkName(validate=validate), + "--domain", + help="TACo Domain Name", + type=NuCypherDomainName(validate=validate), required=required, default=default) @@ -199,9 +190,10 @@ def option_policy_encrypting_key(required: bool = False): required=required) -def option_eth_provider_uri(default=None, required: bool = False): +def option_eth_endpoint(default=None, required: bool = False): return click.option( - '--eth-provider', 'eth_provider_uri', + "--eth-endpoint", + "eth_endpoint", help="Blockchain provider's URI i.e. 'file:///path/to/geth.ipc'", type=click.STRING, required=required, diff --git a/nucypher/cli/painting/status.py b/nucypher/cli/painting/status.py index af2d8bed0..ba15681b0 100644 --- a/nucypher/cli/painting/status.py +++ b/nucypher/cli/painting/status.py @@ -4,9 +4,9 @@ from nucypher.blockchain.eth.agents import ( ) -def paint_application_contract_status(emitter, registry, provider_uri): +def paint_application_contract_status(emitter, registry, eth_endpoint): application_agent = ContractAgency.get_agent( - TACoApplicationAgent, registry=registry, provider_uri=provider_uri + TACoApplicationAgent, registry=registry, blockchain_endpoint=eth_endpoint ) blockchain = application_agent.blockchain diff --git a/nucypher/cli/painting/transactions.py b/nucypher/cli/painting/transactions.py index 63c0ccaf0..e65615e48 100644 --- a/nucypher/cli/painting/transactions.py +++ b/nucypher/cli/painting/transactions.py @@ -5,9 +5,15 @@ from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory from nucypher.blockchain.eth.utils import etherscan_url -def paint_receipt_summary(emitter, receipt, chain_name: str = None, transaction_type=None, eth_provider_uri: str = None): - tx_hash = receipt['transactionHash'].hex() - emitter.echo("OK", color='green', nl=False, bold=True) +def paint_receipt_summary( + emitter, + receipt, + chain_name: str = None, + transaction_type=None, + blockchain_endpoint: str = None, +): + tx_hash = receipt["transactionHash"].hex() + emitter.echo("OK", color="green", nl=False, bold=True) if transaction_type: emitter.echo(f" | {transaction_type} | {tx_hash}", color='yellow', nl=False) else: @@ -16,7 +22,9 @@ def paint_receipt_summary(emitter, receipt, chain_name: str = None, transaction_ emitter.echo(f"Block #{receipt['blockNumber']} | {receipt['blockHash'].hex()}") if not chain_name: - blockchain = BlockchainInterfaceFactory.get_interface(eth_provider_uri=eth_provider_uri) + blockchain = BlockchainInterfaceFactory.get_interface( + endpoint=blockchain_endpoint + ) chain_name = blockchain.client.chain_name try: url = etherscan_url(item=tx_hash, network=chain_name) diff --git a/nucypher/cli/types.py b/nucypher/cli/types.py index f5c11ff88..c8193be0f 100644 --- a/nucypher/cli/types.py +++ b/nucypher/cli/types.py @@ -10,7 +10,7 @@ from cryptography.exceptions import InternalError from eth_utils import to_checksum_address from nucypher_core.umbral import PublicKey -from nucypher.blockchain.eth.networks import NetworksInventory +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.token import TToken from nucypher.policy.payment import PRE_PAYMENT_METHODS from nucypher.utilities.networking import InvalidOperatorIP, validate_operator_ip @@ -88,21 +88,21 @@ class DecimalRange(DecimalType): return rv -class NuCypherNetworkName(click.ParamType): - name = 'nucypher_network_name' +class NuCypherDomainName(click.ParamType): + name = "nucypher_domain_name" def __init__(self, validate: bool = True): self.validate = bool(validate) def convert(self, value, param, ctx): if self.validate: - network = str(value).lower() - if network not in NetworksInventory.ETH_NETWORKS: + domain = str(value).lower() + if domain not in TACoDomain.SUPPORTED_DOMAIN_NAMES: self.fail( - f"'{value}' is not a recognized network. Valid options are: {list(NetworksInventory.ETH_NETWORKS)}" + f"'{value}' is not a recognized domain. Valid options are: {list(TACoDomain.SUPPORTED_DOMAIN_NAMES)}" ) else: - return network + return domain else: return value diff --git a/nucypher/cli/utils.py b/nucypher/cli/utils.py index e8cdff188..cc2d8ca28 100644 --- a/nucypher/cli/utils.py +++ b/nucypher/cli/utils.py @@ -16,6 +16,7 @@ from nucypher.blockchain.eth.interfaces import ( ) from nucypher.blockchain.eth.registry import ( ContractRegistry, + LocalRegistrySource, ) from nucypher.characters.base import Character from nucypher.cli.actions.auth import ( @@ -45,7 +46,7 @@ def setup_emitter(general_config, banner: str = None) -> StdoutEmitter: def make_cli_character( character_config, emitter, - provider_uri: str, + eth_endpoint: str, unlock_keystore: bool = True, unlock_signer: bool = True, teacher_uri: str = None, @@ -82,14 +83,14 @@ def make_cli_character( min_stake=min_stake, network_middleware=character_config.network_middleware, registry=character_config.registry, - provider_uri=provider_uri, + eth_endpoint=eth_endpoint, ) sage_nodes.append(maybe_sage_node) CHARACTER = character_config( known_nodes=sage_nodes, network_middleware=character_config.network_middleware, - eth_provider_uri=provider_uri, + eth_endpoint=eth_endpoint, **config_args, ) @@ -102,28 +103,34 @@ def make_cli_character( def get_registry( - network: str, registry_filepath: Optional[Path] = None + domain: str, registry_filepath: Optional[Path] = None ) -> ContractRegistry: if registry_filepath: - registry = ContractRegistry(filepath=registry_filepath) + source = LocalRegistrySource(filepath=registry_filepath) + registry = ContractRegistry(source=source) else: - registry = ContractRegistry.from_latest_publication(domain=network) + registry = ContractRegistry.from_latest_publication(domain=domain) return registry -def connect_to_blockchain(emitter: StdoutEmitter, - eth_provider_uri: str, - debug: bool = False, - light: bool = False - ) -> BlockchainInterface: +def connect_to_blockchain( + emitter: StdoutEmitter, + blockchain_endpoint: str, + debug: bool = False, + light: bool = False, +) -> BlockchainInterface: try: # Note: Conditional for test compatibility. - if not BlockchainInterfaceFactory.is_interface_initialized(eth_provider_uri=eth_provider_uri): - BlockchainInterfaceFactory.initialize_interface(eth_provider_uri=eth_provider_uri, - light=light, - emitter=emitter) + if not BlockchainInterfaceFactory.is_interface_initialized( + endpoint=blockchain_endpoint + ): + BlockchainInterfaceFactory.initialize_interface( + endpoint=blockchain_endpoint, light=light, emitter=emitter + ) emitter.echo(message=CONNECTING_TO_BLOCKCHAIN) - blockchain = BlockchainInterfaceFactory.get_interface(eth_provider_uri=eth_provider_uri) + blockchain = BlockchainInterfaceFactory.get_interface( + endpoint=blockchain_endpoint + ) return blockchain except Exception as e: if debug: diff --git a/nucypher/config/base.py b/nucypher/config/base.py index fcaaf1d51..dfffe2685 100644 --- a/nucypher/config/base.py +++ b/nucypher/config/base.py @@ -16,8 +16,8 @@ from constant_sorrow.constants import ( ) from eth_utils.address import is_checksum_address +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory -from nucypher.blockchain.eth.networks import NetworksInventory from nucypher.blockchain.eth.registry import ( ContractRegistry, LocalRegistrySource, @@ -303,11 +303,11 @@ class CharacterConfiguration(BaseConfiguration): 'Sideways Engagement' of Character classes; a reflection of input parameters. """ - VERSION = 7 # bump when static payload scheme changes + VERSION = 8 # bump when static payload scheme changes CHARACTER_CLASS = NotImplemented MNEMONIC_KEYSTORE = False - DEFAULT_DOMAIN = NetworksInventory.DEFAULT + DEFAULT_DOMAIN = TACoDomain.DEFAULT_DOMAIN_NAME DEFAULT_NETWORK_MIDDLEWARE = RestMiddleware TEMP_CONFIGURATION_DIR_PREFIX = 'tmp-nucypher' SIGNER_ENVVAR = None @@ -321,7 +321,6 @@ class CharacterConfiguration(BaseConfiguration): # Payments DEFAULT_PRE_PAYMENT_METHOD = "SubscriptionManager" - DEFAULT_PRE_PAYMENT_NETWORK = "polygon" # Fields specified here are *not* passed into the Character's constructor # and can be understood as configuration fields only. @@ -334,8 +333,6 @@ class CharacterConfiguration(BaseConfiguration): "max_gas_price", # gwei "signer_uri", "keystore_path", - "pre_payment_provider", - "pre_payment_network", ) def __init__( @@ -368,20 +365,17 @@ class CharacterConfiguration(BaseConfiguration): # Blockchain poa: Optional[bool] = None, light: bool = False, - eth_provider_uri: Optional[str] = None, + eth_endpoint: Optional[str] = None, + polygon_endpoint: Optional[str] = None, gas_strategy: Union[Callable, str] = DEFAULT_GAS_STRATEGY, max_gas_price: Optional[int] = None, signer_uri: Optional[str] = None, # Payments # TODO: Resolve code prefixing below, possibly with the use of nested configuration fields pre_payment_method: Optional[str] = None, - pre_payment_provider: Optional[str] = None, - pre_payment_network: Optional[str] = None, # Registries registry: Optional[ContractRegistry] = None, registry_filepath: Optional[Path] = None, - policy_registry: Optional[ContractRegistry] = None, - policy_registry_filepath: Optional[Path] = None, ): self.log = Logger(self.__class__.__name__) @@ -412,17 +406,16 @@ class CharacterConfiguration(BaseConfiguration): self.registry = registry or NO_BLOCKCHAIN_CONNECTION.bool_value(False) self.registry_filepath = registry_filepath or UNINITIALIZED_CONFIGURATION - self.policy_registry = policy_registry or NO_BLOCKCHAIN_CONNECTION.bool_value(False) - self.policy_registry_filepath = policy_registry_filepath or UNINITIALIZED_CONFIGURATION - # Blockchain self.poa = poa self.is_light = light - self.eth_provider_uri = eth_provider_uri or NO_BLOCKCHAIN_CONNECTION + self.eth_endpoint = eth_endpoint or NO_BLOCKCHAIN_CONNECTION + self.polygon_endpoint = polygon_endpoint or NO_BLOCKCHAIN_CONNECTION self.signer_uri = signer_uri or None # Learner self.domain = domain + self.taco_domain_info = TACoDomain.get_domain_info(self.domain) self.learn_on_same_thread = learn_on_same_thread self.abort_on_learning_error = abort_on_learning_error self.start_learning_now = start_learning_now @@ -442,32 +435,9 @@ class CharacterConfiguration(BaseConfiguration): self.gas_strategy = gas_strategy self.max_gas_price = max_gas_price # gwei - is_initialized = BlockchainInterfaceFactory.is_interface_initialized( - eth_provider_uri=self.eth_provider_uri - ) - if not is_initialized and eth_provider_uri: - BlockchainInterfaceFactory.initialize_interface( - eth_provider_uri=self.eth_provider_uri, - poa=self.poa, - light=self.is_light, - emitter=emitter, - gas_strategy=self.gas_strategy, - max_gas_price=self.max_gas_price, - ) - else: - self.log.warn( - f"Using existing blockchain interface connection ({self.eth_provider_uri})." - ) - # TODO: this is potential fix for multichain connection, if we want to use it build it out into a loop - # for uri in eth_provider_uri (list of uris fom config): - BlockchainInterfaceFactory.get_or_create_interface( - eth_provider_uri=pre_payment_provider, - poa=self.poa, - light=self.is_light, - emitter=emitter, - gas_strategy=self.gas_strategy, - max_gas_price=self.max_gas_price, + self._connect_to_endpoints( + emitter=emitter, endpoints=[self.eth_endpoint, self.polygon_endpoint] ) if not self.registry: @@ -483,8 +453,9 @@ class CharacterConfiguration(BaseConfiguration): self.registry = ContractRegistry(source=source) self.log.info(f"Using local registry ({self.registry}).") - self.testnet = self.domain != NetworksInventory.MAINNET - self.signer = Signer.from_signer_uri(self.signer_uri, testnet=self.testnet) + self.signer = Signer.from_signer_uri( + self.signer_uri, testnet=self.taco_domain_info.is_testnet + ) # # Onchain Payments & Policies @@ -494,32 +465,9 @@ class CharacterConfiguration(BaseConfiguration): from nucypher.config.characters import BobConfiguration if not isinstance(self, BobConfiguration): - # if not pre_payment_provider: - # raise self.ConfigurationError("payment provider is required.") self.pre_payment_method = ( pre_payment_method or self.DEFAULT_PRE_PAYMENT_METHOD ) - self.pre_payment_network = ( - pre_payment_network or self.DEFAULT_PRE_PAYMENT_NETWORK - ) - self.pre_payment_provider = pre_payment_provider or ( - self.eth_provider_uri or None - ) # default to L1 payments - - # TODO: Dedupe - if not self.policy_registry: - if not self.policy_registry_filepath: - self.log.info("Fetching latest policy registry from source.") - self.policy_registry = ContractRegistry.from_latest_publication( - domain=self.pre_payment_network - ) - else: - self.policy_registry = ContractRegistry( - filepath=self.policy_registry_filepath - ) - self.log.info( - f"Using local policy registry ({self.policy_registry})." - ) if dev_mode: self.__temp_dir = UNINITIALIZED_CONFIGURATION @@ -533,11 +481,32 @@ class CharacterConfiguration(BaseConfiguration): # Network self.network_middleware = network_middleware or self.DEFAULT_NETWORK_MIDDLEWARE( - registry=self.registry, eth_provider_uri=self.eth_provider_uri + registry=self.registry, eth_endpoint=self.eth_endpoint ) super().__init__(filepath=self.config_file_location, config_root=self.config_root) + def _connect_to_endpoints(self, emitter, endpoints: List[str]) -> None: + for endpoint in endpoints: + if endpoint and endpoint != NO_BLOCKCHAIN_CONNECTION: + is_initialized = BlockchainInterfaceFactory.is_interface_initialized( + endpoint=endpoint + ) + + if not is_initialized: + BlockchainInterfaceFactory.initialize_interface( + endpoint=endpoint, + poa=self.poa, + light=self.is_light, + emitter=emitter, + gas_strategy=self.gas_strategy, + max_gas_price=self.max_gas_price, + ) + else: + self.log.warn( + f"Using existing blockchain interface connection ({endpoint})." + ) + def __call__(self, **character_kwargs): return self.produce(**character_kwargs) @@ -703,12 +672,12 @@ class CharacterConfiguration(BaseConfiguration): ) # Optional values (mode) - if self.eth_provider_uri: + if self.eth_endpoint: if not self.signer_uri: - self.signer_uri = self.eth_provider_uri + self.signer_uri = self.eth_endpoint payload.update( dict( - eth_provider_uri=self.eth_provider_uri, + eth_endpoint=self.eth_endpoint, poa=self.poa, light=self.is_light, signer_uri=self.signer_uri, @@ -717,6 +686,11 @@ class CharacterConfiguration(BaseConfiguration): if self.registry_filepath: payload.update(dict(registry_filepath=self.registry_filepath)) + if self.polygon_endpoint: + payload.update( + polygon_endpoint=self.polygon_endpoint, + ) + # Gas Price __max_price = str(self.max_gas_price) if self.max_gas_price else None payload.update(dict(gas_strategy=self.gas_strategy, max_gas_price=__max_price)) @@ -840,8 +814,8 @@ class CharacterConfiguration(BaseConfiguration): # # Strategy-Based (current implementation, inflexible & hardcoded) # 'pre_payment_strategy': 'SubscriptionManager' - # 'pre_payment_network': 'matic' - # 'pre_payment_provider': 'https:///matic.infura.io....' + # 'network': 'polygon' + # 'blockchain_endpoint': 'https:///polygon.infura.io....' # # Contract-Targeted (alternative implementation, flexible & generic) # 'pre_payment': { @@ -860,9 +834,9 @@ class CharacterConfiguration(BaseConfiguration): if pre_payment_class.ONCHAIN: # on-chain payment strategies require a blockchain connection pre_payment_strategy = pre_payment_class( - network=self.pre_payment_network, - eth_provider=self.pre_payment_provider, - registry=self.policy_registry, + domain=self.taco_domain_info.name, + blockchain_endpoint=self.polygon_endpoint, + registry=self.registry, ) else: pre_payment_strategy = pre_payment_class() diff --git a/nucypher/config/characters.py b/nucypher/config/characters.py index e79882ab1..bd7abe7a8 100644 --- a/nucypher/config/characters.py +++ b/nucypher/config/characters.py @@ -5,7 +5,6 @@ from typing import Dict, List, Optional from cryptography.x509 import Certificate from eth_utils import is_checksum_address -from nucypher.blockchain.eth.networks import NetworksInventory from nucypher.config.base import CharacterConfiguration from nucypher.config.constants import ( NUCYPHER_ENVVAR_ALICE_ETH_PASSWORD, @@ -36,7 +35,7 @@ class UrsulaConfiguration(CharacterConfiguration): keystore_path: Optional[Path] = None, rest_port: Optional[int] = None, certificate: Optional[Certificate] = None, - condition_provider_uris: Optional[Dict[str, List[str]]] = None, + condition_blockchain_endpoints: Optional[Dict[str, List[str]]] = None, *args, **kwargs, ) -> None: @@ -61,35 +60,38 @@ class UrsulaConfiguration(CharacterConfiguration): # json configurations don't allow for integer keyed dictionaries # so convert string chain id to integer - self.condition_provider_uris = dict() - if condition_provider_uris: - for chain, providers in condition_provider_uris.items(): + self.condition_blockchain_endpoints = dict() + if condition_blockchain_endpoints: + for chain, blockchain_endpoint in condition_blockchain_endpoints.items(): # convert chain from string key (for json) to integer - self.condition_provider_uris[int(chain)] = providers - self.configure_condition_provider_uris() - - def configure_condition_provider_uris(self) -> None: - """Configure default condition provider URIs for mainnet and polygon network.""" + self.condition_blockchain_endpoints[int(chain)] = blockchain_endpoint + self.configure_condition_blockchain_endpoints() + def configure_condition_blockchain_endpoints(self) -> None: + """Configure default condition provider URIs for eth and polygon network.""" # Polygon - polygon_chain_id = NetworksInventory.get_polygon_chain_id( - self.pre_payment_network + polygon_chain_id = self.taco_domain_info.polygon_chain.id + polygon_endpoints = self.condition_blockchain_endpoints.get( + polygon_chain_id, [] ) - polygon_provider_uris = self.condition_provider_uris.get(polygon_chain_id, []) - if not polygon_provider_uris: - self.condition_provider_uris[polygon_chain_id] = polygon_provider_uris + if not polygon_endpoints: + self.condition_blockchain_endpoints[polygon_chain_id] = polygon_endpoints - if self.pre_payment_provider not in polygon_provider_uris: - polygon_provider_uris.append(self.pre_payment_provider) + if self.polygon_endpoint not in polygon_endpoints: + polygon_endpoints.append(self.polygon_endpoint) # Ethereum - staking_chain_id = NetworksInventory.get_ethereum_chain_id(self.domain) - staking_provider_uris = self.condition_provider_uris.get(staking_chain_id, []) - if not staking_provider_uris: - self.condition_provider_uris[staking_chain_id] = staking_provider_uris + staking_chain_id = self.taco_domain_info.eth_chain.id + staking_chain_endpoints = self.condition_blockchain_endpoints.get( + staking_chain_id, [] + ) + if not staking_chain_endpoints: + self.condition_blockchain_endpoints[ + staking_chain_id + ] = staking_chain_endpoints - if self.eth_provider_uri not in staking_provider_uris: - staking_provider_uris.append(self.eth_provider_uri) + if self.eth_endpoint not in staking_chain_endpoints: + staking_chain_endpoints.append(self.eth_endpoint) @classmethod def address_from_filepath(cls, filepath: Path) -> str: @@ -114,13 +116,11 @@ class UrsulaConfiguration(CharacterConfiguration): operator_address=self.operator_address, rest_host=self.rest_host, rest_port=self.rest_port, - condition_provider_uris=self.condition_provider_uris, + condition_blockchain_endpoints=self.condition_blockchain_endpoints, # PRE Payments # TODO: Resolve variable prefixing below (uses nested configuration fields?) pre_payment_method=self.pre_payment_method, - pre_payment_provider=self.pre_payment_provider, - pre_payment_network=self.pre_payment_network, ) return {**super().static_payload(), **payload} @@ -181,8 +181,6 @@ class AliceConfiguration(CharacterConfiguration): payload = dict( threshold=self.threshold, shares=self.shares, - pre_payment_network=self.pre_payment_network, - pre_payment_provider=self.pre_payment_provider, pre_payment_method=self.pre_payment_method, rate=self.rate, duration=self.duration, diff --git a/nucypher/config/migrations/__init__.py b/nucypher/config/migrations/__init__.py index 52184c467..b34cbc1ec 100644 --- a/nucypher/config/migrations/__init__.py +++ b/nucypher/config/migrations/__init__.py @@ -5,6 +5,7 @@ from .configuration_v3_to_v4 import configuration_v3_to_v4 from .configuration_v4_to_v5 import configuration_v4_to_v5 from .configuration_v5_to_v6 import configuration_v5_to_v6 from .configuration_v6_to_v7 import configuration_v6_to_v7 +from .configuration_v7_to_v8 import configuration_v7_to_v8 MIGRATIONS = OrderedDict( { @@ -14,5 +15,6 @@ MIGRATIONS = OrderedDict( (4, 5): configuration_v4_to_v5, (5, 6): configuration_v5_to_v6, (6, 7): configuration_v6_to_v7, + (7, 8): configuration_v7_to_v8, } ) diff --git a/nucypher/config/migrations/configuration_v5_to_v6.py b/nucypher/config/migrations/configuration_v5_to_v6.py index 47b4acbf4..0c1813ec0 100644 --- a/nucypher/config/migrations/configuration_v5_to_v6.py +++ b/nucypher/config/migrations/configuration_v5_to_v6.py @@ -1,14 +1,15 @@ from typing import Dict -from nucypher.blockchain.eth.networks import NetworksInventory +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.config.migrations.common import perform_migration def __migration(config: Dict) -> Dict: + taco_domain_info = TACoDomain.get_domain_info(config["domain"]) eth_provider = config["eth_provider_uri"] - eth_chain_id = NetworksInventory.get_ethereum_chain_id(config["domain"]) + eth_chain_id = taco_domain_info.eth_chain.id polygon_provider = config["payment_provider"] - polygon_chain_id = NetworksInventory.get_polygon_chain_id(config["payment_network"]) + polygon_chain_id = taco_domain_info.polygon_chain.id if "condition_provider_uris" in config: return config config["condition_provider_uris"] = { diff --git a/nucypher/config/migrations/configuration_v7_to_v8.py b/nucypher/config/migrations/configuration_v7_to_v8.py new file mode 100644 index 000000000..794c78b76 --- /dev/null +++ b/nucypher/config/migrations/configuration_v7_to_v8.py @@ -0,0 +1,28 @@ +from typing import Dict + +from nucypher.config.migrations.common import perform_migration + + +def __migration(config: Dict) -> Dict: + # deprecations + del config["pre_payment_network"] + + # eth_provider_uri -> eth_endpoint + config["eth_endpoint"] = config["eth_provider_uri"] + del config["eth_provider_uri"] + + # pre_payment_provider -> polygon_endpoint + config["polygon_endpoint"] = config["pre_payment_provider"] + del config["pre_payment_provider"] + + # condition_provider_uris -> condition_blockchain_endpoints + config["condition_blockchain_endpoints"] = config["condition_provider_uris"] + del config["condition_provider_uris"] + + return config + + +def configuration_v7_to_v8(filepath) -> None: + perform_migration( + old_version=7, new_version=8, migration=__migration, filepath=filepath + ) diff --git a/nucypher/network/middleware.py b/nucypher/network/middleware.py index ce8dcd912..eabbdbdc5 100644 --- a/nucypher/network/middleware.py +++ b/nucypher/network/middleware.py @@ -28,19 +28,17 @@ class NucypherMiddlewareClient: def __init__( self, - eth_provider_uri: Optional[str], + eth_endpoint: Optional[str], registry: Optional[ContractRegistry] = None, storage: Optional[NodeStorage] = None, *args, **kwargs, ): - if not eth_provider_uri: - raise ValueError( - "eth_provider_uri is required for NucypherMiddlewareClient" - ) + if not eth_endpoint: + raise ValueError("eth_endpoint is required for NucypherMiddlewareClient") self.registry = registry - self.eth_provider_uri = eth_provider_uri + self.eth_endpoint = eth_endpoint self.storage = storage or ForgetfulNodeStorage() # for certificate storage def get_certificate(self, @@ -88,7 +86,11 @@ 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, eth_provider_uri=self.eth_provider_uri) + node.verify_node( + network_middleware_client=self, + registry=self.registry, + eth_endpoint=self.eth_endpoint, + ) return self.parse_node_or_host_and_port(node_or_sprout, host, port) def parse_node_or_host_and_port(self, node, host, port): @@ -249,8 +251,8 @@ class RestMiddleware: def __init__(self, *args, **kwargs): super().__init__(status=HTTPStatus.FORBIDDEN, *args, **kwargs) - def __init__(self, eth_provider_uri: str, registry=None): - self.client = self._client_class(registry=registry, eth_provider_uri=eth_provider_uri) + def __init__(self, eth_endpoint: str, registry=None): + self.client = self._client_class(registry=registry, eth_endpoint=eth_endpoint) def request_revocation(self, ursula, revocation): # TODO: Implement offchain revocation #2787 diff --git a/nucypher/network/nodes.py b/nucypher/network/nodes.py index 0fb24993a..a1577bfbf 100644 --- a/nucypher/network/nodes.py +++ b/nucypher/network/nodes.py @@ -28,7 +28,7 @@ from nucypher.acumen.nicknames import Nickname from nucypher.acumen.perception import FleetSensor from nucypher.blockchain.eth.agents import ContractAgency, TACoApplicationAgent from nucypher.blockchain.eth.constants import NULL_ADDRESS -from nucypher.blockchain.eth.networks import NetworksInventory +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.registry import ContractRegistry from nucypher.config.constants import SeednodeMetadata from nucypher.config.storages import ForgetfulNodeStorage @@ -46,14 +46,13 @@ from nucypher.network.protocols import InterfaceInfo, SuspiciousActivity from nucypher.utilities.logging import Logger TEACHER_NODES = { - NetworksInventory.MAINNET: ( + TACoDomain.MAINNET.name: ( 'https://closest-seed.nucypher.network:9151', 'https://seeds.nucypher.network', 'https://mainnet.nucypher.network:9151', ), - NetworksInventory.LYNX: ("https://lynx.nucypher.network:9151",), - NetworksInventory.TAPIR: ("https://tapir.nucypher.network:9151",), - NetworksInventory.ORYX: ("https://oryx.nucypher.network:9151",), + TACoDomain.LYNX.name: ("https://lynx.nucypher.network:9151",), + TACoDomain.TAPIR.name: ("https://tapir.nucypher.network:9151",), } @@ -271,8 +270,9 @@ class Learner: self.learning_deferred = Deferred() self.domain = domain + self.taco_domain_info = TACoDomain.get_domain_info(self.domain) default_middleware = self.__DEFAULT_MIDDLEWARE_CLASS( - registry=self.registry, eth_provider_uri=self.eth_provider_uri + registry=self.registry, eth_endpoint=self.eth_endpoint ) self.network_middleware = network_middleware or default_middleware self.save_metadata = save_metadata @@ -359,7 +359,7 @@ class Learner: maybe_sage_node = self.node_class.from_teacher_uri( teacher_uri=uri, min_stake=0, - provider_uri=self.eth_provider_uri, + eth_endpoint=self.eth_endpoint, network_middleware=self.network_middleware, registry=self.registry, ) @@ -383,7 +383,7 @@ class Learner: seed_node = self.node_class.from_seednode_metadata( seednode_metadata=seednode_metadata, network_middleware=self.network_middleware, - provider_uri=self.eth_provider_uri, + eth_endpoint=self.eth_endpoint, ) except Exception as e: # TODO: log traceback here? @@ -472,7 +472,7 @@ class Learner: force=force_verification_recheck, network_middleware_client=self.network_middleware.client, registry=registry, - eth_provider_uri=self.eth_provider_uri, + eth_endpoint=self.eth_endpoint, ) except SSLError: # TODO: Bucket this node as having bad TLS info - maybe it's an update that hasn't fully propagated? 567 @@ -758,7 +758,7 @@ class Learner: try: node_on_the_other_end = self.node_class.from_seednode_metadata( stranger.seed_node_metadata(), - provider_uri=self.provider_uri, + eth_endpoint=self.eth_endpoint, network_middleware=self.network_middleware, ) if node_on_the_other_end != stranger: @@ -1040,7 +1040,7 @@ class Teacher: return bytes(response) def _operator_is_bonded( - self, provider_uri: str, registry: ContractRegistry + self, eth_endpoint: str, registry: ContractRegistry ) -> bool: """ This method assumes the stamp's signature is valid and accurate. @@ -1048,7 +1048,7 @@ class Teacher: the case that the "staking provider" isn't "staking" (e.g., all her tokens have been slashed). """ application_agent = ContractAgency.get_agent( - TACoApplicationAgent, provider_uri=provider_uri, registry=registry + TACoApplicationAgent, blockchain_endpoint=eth_endpoint, registry=registry ) # type: TACoApplicationAgent staking_provider_address = application_agent.get_staking_provider_from_operator(operator_address=self.operator_address) if staking_provider_address == NULL_ADDRESS: @@ -1056,14 +1056,14 @@ class Teacher: return staking_provider_address == self.checksum_address def _staking_provider_is_really_staking( - self, registry: ContractRegistry, eth_provider_uri: Optional[str] = None + self, registry: ContractRegistry, eth_endpoint: Optional[str] = None ) -> bool: """ This method assumes the stamp's signature is valid and accurate. As a follow-up, this checks that the staking provider is, indeed, staking. """ application_agent = ContractAgency.get_agent( - TACoApplicationAgent, registry=registry, provider_uri=eth_provider_uri + TACoApplicationAgent, registry=registry, blockchain_endpoint=eth_endpoint ) # type: TACoApplicationAgent is_staking = application_agent.is_authorized(staking_provider=self.checksum_address) # checksum address here is staking provider return is_staking @@ -1071,7 +1071,7 @@ class Teacher: def validate_operator( self, registry: ContractRegistry = None, - eth_provider_uri: Optional[str] = None, + eth_endpoint: Optional[str] = None, ) -> None: # TODO: restore this enforcement # if registry and not eth_provider_uri: @@ -1088,14 +1088,14 @@ class Teacher: # On-chain staking check, if registry is present if registry: if not self._operator_is_bonded( - registry=registry, provider_uri=eth_provider_uri + registry=registry, eth_endpoint=eth_endpoint ): # <-- Blockchain CALL message = f"Operator {self.operator_address} is not bonded to staking provider {self.checksum_address}" self.log.debug(message) raise self.UnbondedOperator(message) if self._staking_provider_is_really_staking( - registry=registry, eth_provider_uri=eth_provider_uri + registry=registry, eth_endpoint=eth_endpoint ): # <-- Blockchain CALL self.log.info(f"Verified operator {self}") self.verified_operator = True @@ -1115,7 +1115,7 @@ class Teacher: raise self.InvalidNode("Metadata signature is invalid") def validate_metadata( - self, registry: ContractRegistry = None, eth_provider_uri: Optional[str] = None + self, registry: ContractRegistry = None, eth_endpoint: Optional[str] = None ): # Verify the metadata signature if not self.verified_metadata: @@ -1126,13 +1126,13 @@ class Teacher: return # Offline check of valid stamp signature by worker - self.validate_operator(registry=registry, eth_provider_uri=eth_provider_uri) + self.validate_operator(registry=registry, eth_endpoint=eth_endpoint) def verify_node( self, network_middleware_client, registry: ContractRegistry = None, - eth_provider_uri: Optional[str] = None, + eth_endpoint: Optional[str] = None, certificate_filepath: Optional[Path] = None, force: bool = False, ) -> bool: @@ -1165,7 +1165,7 @@ class Teacher: ) # This is both the stamp's client signature and interface metadata check; May raise InvalidNode - self.validate_metadata(registry=registry, eth_provider_uri=eth_provider_uri) + self.validate_metadata(registry=registry, eth_endpoint=eth_endpoint) # The node's metadata is valid; let's be sure the interface is in order. if not certificate_filepath: diff --git a/nucypher/policy/payment.py b/nucypher/policy/payment.py index b148ad942..8a443f637 100644 --- a/nucypher/policy/payment.py +++ b/nucypher/policy/payment.py @@ -6,6 +6,7 @@ from nucypher_core import ReencryptionRequest from web3.types import ChecksumAddress, Timestamp, TxReceipt, Wei from nucypher.blockchain.eth.agents import ContractAgency, SubscriptionManagerAgent +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.registry import ContractRegistry from nucypher.policy import policies @@ -64,17 +65,17 @@ class ContractPayment(PaymentMethod, ABC): def __init__( self, - eth_provider: str, - network: str, + blockchain_endpoint: str, + domain: str, registry: Optional[ContractRegistry] = None, *args, **kwargs, ): super().__init__(*args, **kwargs) - self.provider = eth_provider - self.network = network + self.blockchain_endpoint = blockchain_endpoint + self.taco_domain_info = TACoDomain.get_domain_info(domain) if not registry: - registry = ContractRegistry.from_latest_publication(domain=network) + registry = ContractRegistry.from_latest_publication(domain=domain) self.registry = registry self.__agent = None # delay blockchain/registry reads until later @@ -84,7 +85,9 @@ class ContractPayment(PaymentMethod, ABC): if self.__agent: return self.__agent # get cache agent = ContractAgency.get_agent( - agent_class=self._AGENT, provider_uri=self.provider, registry=self.registry + agent_class=self._AGENT, + blockchain_endpoint=self.blockchain_endpoint, + registry=self.registry, ) self.__agent = agent return self.__agent # set cache diff --git a/nucypher/utilities/ethereum.py b/nucypher/utilities/ethereum.py index cdcb19df1..11b283ab6 100644 --- a/nucypher/utilities/ethereum.py +++ b/nucypher/utilities/ethereum.py @@ -22,15 +22,17 @@ def encode_constructor_arguments(web3: Web3, return data -def connect_web3_provider(eth_provider_uri: str) -> None: +def connect_web3_provider(blockchain_endpoint: str) -> None: """ - Convenience function for connecting to an ethereum provider now. + Convenience function for connecting to a blockchain provider now. This may be used to optimize the startup time of some applications by establishing the connection eagerly. """ from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory - if not BlockchainInterfaceFactory.is_interface_initialized(eth_provider_uri=eth_provider_uri): - BlockchainInterfaceFactory.initialize_interface(eth_provider_uri=eth_provider_uri) - interface = BlockchainInterfaceFactory.get_interface(eth_provider_uri=eth_provider_uri) + if not BlockchainInterfaceFactory.is_interface_initialized( + endpoint=blockchain_endpoint + ): + BlockchainInterfaceFactory.initialize_interface(endpoint=blockchain_endpoint) + interface = BlockchainInterfaceFactory.get_interface(endpoint=blockchain_endpoint) interface.connect() diff --git a/nucypher/utilities/networking.py b/nucypher/utilities/networking.py index 9216c4acc..272d0e267 100644 --- a/nucypher/utilities/networking.py +++ b/nucypher/utilities/networking.py @@ -69,13 +69,13 @@ def _request(url: str, certificate=None) -> Union[str, None]: def _request_from_node( teacher, - provider_uri: str, + eth_endpoint: str, client: Optional[NucypherMiddlewareClient] = None, timeout: int = 2, log: Logger = IP_DETECTION_LOGGER, ) -> Union[str, None]: if not client: - client = NucypherMiddlewareClient(eth_provider_uri=provider_uri) + client = NucypherMiddlewareClient(eth_endpoint=eth_endpoint) try: response = client.get( node_or_sprout=teacher, path="ping", timeout=timeout @@ -100,8 +100,8 @@ def _request_from_node( def get_external_ip_from_default_teacher( - network: str, - provider_uri: str, + domain: str, + eth_endpoint: str, registry: Optional[ContractRegistry] = None, log: Logger = IP_DETECTION_LOGGER, ) -> Union[str, None]: @@ -111,21 +111,21 @@ def get_external_ip_from_default_teacher( base_error = 'Cannot determine IP using default teacher' - if network not in TEACHER_NODES: - log.debug(f'{base_error}: Unknown network "{network}".') + if domain not in TEACHER_NODES: + log.debug(f'{base_error}: Unknown domain "{domain}".') return node_storage = LocalFileBasedNodeStorage() Ursula.set_cert_storage_function(node_storage.store_node_certificate) external_ip = None - for teacher_uri in TEACHER_NODES[network]: + for teacher_uri in TEACHER_NODES[domain]: try: teacher = Ursula.from_teacher_uri( - teacher_uri=teacher_uri, provider_uri=provider_uri, min_stake=0 + teacher_uri=teacher_uri, eth_endpoint=eth_endpoint, min_stake=0 ) # TODO: Handle customized min stake here. # TODO: Pass registry here to verify stake (not essential here since it's a hardcoded node) - external_ip = _request_from_node(teacher=teacher, provider_uri=provider_uri) + external_ip = _request_from_node(teacher=teacher, eth_endpoint=eth_endpoint) # Found a reachable teacher, return from loop if external_ip: break @@ -134,7 +134,7 @@ def get_external_ip_from_default_teacher( continue if not external_ip: - log.debug(f'{base_error}: No teacher available for network "{network}".') + log.debug(f'{base_error}: No teacher available for domain "{domain}".') return return external_ip @@ -142,7 +142,7 @@ def get_external_ip_from_default_teacher( def get_external_ip_from_known_nodes( known_nodes: FleetSensor, - provider_uri: str, + eth_endpoint: str, sample_size: int = 3, log: Logger = IP_DETECTION_LOGGER, ) -> Union[str, None]: @@ -154,9 +154,9 @@ def get_external_ip_from_known_nodes( if len(known_nodes) < sample_size: return # There are too few known nodes sample = random.sample(list(known_nodes), sample_size) - client = NucypherMiddlewareClient(eth_provider_uri=provider_uri) + client = NucypherMiddlewareClient(eth_endpoint=eth_endpoint) for node in sample: - ip = _request_from_node(teacher=node, client=client, provider_uri=provider_uri) + ip = _request_from_node(teacher=node, client=client, eth_endpoint=eth_endpoint) if ip: log.info(f'Fetched external IP address ({ip}) from randomly selected known nodes.') return ip @@ -171,7 +171,7 @@ def get_external_ip_from_centralized_source(log: Logger = IP_DETECTION_LOGGER) - def determine_external_ip_address( - network: str, provider_uri: str, known_nodes: FleetSensor = None + domain: str, eth_endpoint: str, known_nodes: FleetSensor = None ) -> str: """ Attempts to automatically determine the external IP in the following priority: @@ -186,13 +186,13 @@ def determine_external_ip_address( # primary source if known_nodes: rest_host = get_external_ip_from_known_nodes( - known_nodes=known_nodes, provider_uri=provider_uri + known_nodes=known_nodes, eth_endpoint=eth_endpoint ) # fallback 1 if not rest_host: rest_host = get_external_ip_from_default_teacher( - network=network, provider_uri=provider_uri + domain=domain, eth_endpoint=eth_endpoint ) # fallback 2 diff --git a/nucypher/utilities/prometheus/collector.py b/nucypher/utilities/prometheus/collector.py index 37ad3da2d..3e08b4432 100644 --- a/nucypher/utilities/prometheus/collector.py +++ b/nucypher/utilities/prometheus/collector.py @@ -121,9 +121,10 @@ class UrsulaInfoMetricsCollector(BaseMetricsCollector): class BlockchainMetricsCollector(BaseMetricsCollector): """Collector for Blockchain specific metrics.""" - def __init__(self, eth_provider_uri: str): + + def __init__(self, eth_endpoint: str): super().__init__() - self.eth_provider_uri = eth_provider_uri + self.eth_endpoint = eth_endpoint def initialize(self, metrics_prefix: str, registry: CollectorRegistry) -> None: self.metrics = { @@ -138,7 +139,9 @@ class BlockchainMetricsCollector(BaseMetricsCollector): } def _collect_internal(self) -> None: - blockchain = BlockchainInterfaceFactory.get_or_create_interface(eth_provider_uri=self.eth_provider_uri) + blockchain = BlockchainInterfaceFactory.get_or_create_interface( + endpoint=self.eth_endpoint + ) self.metrics["eth_chain_id"].set(blockchain.client.chain_id) self.metrics["eth_current_block_number"].set(blockchain.client.block_number) @@ -150,12 +153,12 @@ class StakingProviderMetricsCollector(BaseMetricsCollector): self, staking_provider_address: ChecksumAddress, contract_registry: ContractRegistry, - eth_provider_uri: str, + eth_endpoint: str, ): super().__init__() self.staking_provider_address = staking_provider_address self.contract_registry = contract_registry - self.eth_provider_uri = eth_provider_uri + self.eth_endpoint = eth_endpoint def initialize(self, metrics_prefix: str, registry: CollectorRegistry) -> None: self.metrics = { @@ -180,7 +183,7 @@ class StakingProviderMetricsCollector(BaseMetricsCollector): application_agent = ContractAgency.get_agent( TACoApplicationAgent, registry=self.contract_registry, - provider_uri=self.eth_provider_uri, + blockchain_endpoint=self.eth_endpoint, ) authorized = application_agent.get_authorized_stake( staking_provider=self.staking_provider_address diff --git a/nucypher/utilities/prometheus/metrics.py b/nucypher/utilities/prometheus/metrics.py index 40978b4ea..fc06a3e90 100644 --- a/nucypher/utilities/prometheus/metrics.py +++ b/nucypher/utilities/prometheus/metrics.py @@ -157,16 +157,14 @@ def create_metrics_collectors(ursula: "lawful.Ursula") -> List[MetricsCollector] # Blockchain prometheus # TODO possible include information about payment - collectors.append( - BlockchainMetricsCollector(eth_provider_uri=ursula.eth_provider_uri) - ) + collectors.append(BlockchainMetricsCollector(eth_endpoint=ursula.eth_endpoint)) # Staking Provider prometheus collectors.append( StakingProviderMetricsCollector( staking_provider_address=ursula.checksum_address, contract_registry=ursula.registry, - eth_provider_uri=ursula.eth_provider_uri, + eth_endpoint=ursula.eth_endpoint, ) ) diff --git a/scripts/hooks/nucypher_agents.py b/scripts/hooks/nucypher_agents.py index 63034e2ec..6a82046af 100644 --- a/scripts/hooks/nucypher_agents.py +++ b/scripts/hooks/nucypher_agents.py @@ -27,7 +27,7 @@ from nucypher.blockchain.eth.agents import ( TACoApplicationAgent, TACoChildApplicationAgent, ) -from nucypher.blockchain.eth.networks import NetworksInventory +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.registry import ContractRegistry from nucypher.utilities.emitters import StdoutEmitter from nucypher.utilities.logging import GlobalLoggerSettings @@ -42,71 +42,56 @@ emitter = StdoutEmitter(verbosity=2) @click.command() @click.option( - "--eth-provider", - "eth_provider_uri", + "--domain", + "domain", + help="TACo domain", + type=click.Choice(TACoDomain.SUPPORTED_DOMAIN_NAMES), + default=TACoDomain.LYNX.name, +) +@click.option( + "--eth-endpoint", + "eth_endpoint", help="ETH staking network provider URI", type=click.STRING, required=True, ) @click.option( - "--eth-staking-network", - "eth_staking_network", - help="ETH staking network", - type=click.Choice(NetworksInventory.ETH_NETWORKS), - default="lynx", -) -@click.option( - "--coordinator-provider", - "coordinator_provider_uri", - help="Coordinator network provider URI", + "--polygon-endpoint", + "polygon_endpoint", + help="Polygon network provider URI", type=click.STRING, required=True, ) -@click.option( - "--coordinator-network", - "coordinator_network", - help="Coordinator network", - type=click.Choice(NetworksInventory.POLY_NETWORKS), - default="mumbai", -) def nucypher_agents( - eth_provider_uri, - eth_staking_network, - coordinator_provider_uri, - coordinator_network, + domain, + eth_endpoint, + polygon_endpoint, ): - staking_registry = ContractRegistry.from_latest_publication( - domain=eth_staking_network - ) - emitter.echo(f"NOTICE: Connecting to {eth_staking_network} network", color="yellow") + registry = ContractRegistry.from_latest_publication(domain=domain) + emitter.echo(f"NOTICE: Connecting to {domain} domain", color="yellow") taco_application_agent = ContractAgency.get_agent( agent_class=TACoApplicationAgent, - registry=staking_registry, - provider_uri=eth_provider_uri, + registry=registry, + blockchain_endpoint=eth_endpoint, ) # type: TACoApplicationAgent - coordinator_network_registry = ContractRegistry.from_latest_publication( - domain=coordinator_network - ) - emitter.echo(f"NOTICE: Connecting to {coordinator_network} network", color="yellow") - taco_child_application_agent = ContractAgency.get_agent( agent_class=TACoChildApplicationAgent, - registry=coordinator_network_registry, - provider_uri=coordinator_provider_uri, + registry=registry, + blockchain_endpoint=polygon_endpoint, ) # type: TACoChildApplicationAgent coordinator_agent = ContractAgency.get_agent( agent_class=CoordinatorAgent, - registry=coordinator_network_registry, - provider_uri=coordinator_provider_uri, + registry=registry, + blockchain_endpoint=polygon_endpoint, ) # type: CoordinatorAgent subscription_manager_agent = ContractAgency.get_agent( agent_class=SubscriptionManagerAgent, - registry=coordinator_network_registry, - provider_uri=coordinator_provider_uri, + registry=registry, + blockchain_endpoint=polygon_endpoint, ) # type: SubscriptionManagerAgent message = ( diff --git a/scripts/hooks/nucypher_dkg.py b/scripts/hooks/nucypher_dkg.py index 63441c5f7..8d5dedde4 100644 --- a/scripts/hooks/nucypher_dkg.py +++ b/scripts/hooks/nucypher_dkg.py @@ -11,6 +11,7 @@ from nucypher.blockchain.eth.agents import ( CoordinatorAgent, TACoApplicationAgent, ) +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.registry import ContractRegistry from nucypher.blockchain.eth.signers import InMemorySigner, Signer from nucypher.characters.lawful import Bob, Enrico @@ -43,33 +44,26 @@ def get_transacting_power(signer: Signer): @click.command() @click.option( - "--eth-provider", - "eth_provider_uri", + "--domain", + "domain", + help="TACo Domain", + type=click.Choice([TACoDomain.TAPIR.name, TACoDomain.LYNX.name]), + default=TACoDomain.LYNX.name, +) +@click.option( + "--eth-endpoint", + "eth_endpoint", help="ETH staking network provider URI", type=click.STRING, required=True, ) @click.option( - "--eth-staking-network", - "eth_staking_network", - help="ETH staking network", - type=click.Choice(["tapir", "lynx"]), - default="lynx", -) -@click.option( - "--coordinator-provider", - "coordinator_provider_uri", - help="Coordinator network provider URI", + "--polygon-endpoint", + "polygon_endpoint", + help="Polygon network provider URI", type=click.STRING, required=True, ) -@click.option( - "--coordinator-network", - "coordinator_network", - help="Coordinator network", - type=click.Choice(["mumbai"]), - default="mumbai", -) @click.option( "--ritual-id", "ritual_id", @@ -117,10 +111,9 @@ def get_transacting_power(signer: Signer): default=False, ) def nucypher_dkg( - eth_provider_uri, - eth_staking_network, - coordinator_provider_uri, - coordinator_network, + domain, + eth_endpoint, + polygon_endpoint, ritual_id, signer_uri, dkg_size, @@ -161,22 +154,18 @@ def nucypher_dkg( ), ) - coordinator_network_registry = ContractRegistry.from_latest_publication( - domain=coordinator_network - ) + taco_domain_info = TACoDomain.get_domain_info(domain) + registry = ContractRegistry.from_latest_publication(domain=domain) coordinator_agent = ContractAgency.get_agent( agent_class=CoordinatorAgent, - registry=coordinator_network_registry, - provider_uri=coordinator_provider_uri, + registry=registry, + blockchain_endpoint=polygon_endpoint, ) # type: CoordinatorAgent - staking_network_registry = ContractRegistry.from_latest_publication( - domain=eth_staking_network - ) application_agent = ContractAgency.get_agent( agent_class=TACoApplicationAgent, - registry=staking_network_registry, - provider_uri=eth_provider_uri, + registry=registry, + blockchain_endpoint=eth_endpoint, ) # type: TACoApplicationAgent # @@ -188,7 +177,7 @@ def nucypher_dkg( # Get GlobalAllowList contract blockchain = coordinator_agent.blockchain allow_list = blockchain.get_contract_by_name( - registry=coordinator_network_registry, contract_name=GLOBAL_ALLOW_LIST + registry=registry, contract_name=GLOBAL_ALLOW_LIST ) # @@ -202,7 +191,7 @@ def nucypher_dkg( emitter.echo("--------- Initiating Ritual ---------", color="yellow") emitter.echo( - f"Commencing DKG Ritual(s) on {coordinator_network} using {account_address}", + f"Commencing DKG Ritual(s) on {taco_domain_info.polygon_chain.name} using {account_address}", color="green", ) @@ -389,11 +378,10 @@ def nucypher_dkg( # emitter.echo("--------- Threshold Decryption ---------") bob = Bob( - eth_provider_uri=eth_provider_uri, - domain=eth_staking_network, - registry=staking_network_registry, - coordinator_network=coordinator_network, - coordinator_provider_uri=coordinator_provider_uri, + domain=domain, + eth_endpoint=eth_endpoint, + polygon_endpoint=polygon_endpoint, + registry=registry, ) bob.start_learning_loop(now=True) diff --git a/tests/acceptance/agents/test_contract_agency.py b/tests/acceptance/agents/test_contract_agency.py index 9fe139c33..e893c6803 100644 --- a/tests/acceptance/agents/test_contract_agency.py +++ b/tests/acceptance/agents/test_contract_agency.py @@ -7,12 +7,12 @@ def test_get_agent_with_different_registries(test_registry): application_agent_1 = ContractAgency.get_agent( TACoApplicationAgent, registry=test_registry, - provider_uri=TEST_ETH_PROVIDER_URI, + blockchain_endpoint=TEST_ETH_PROVIDER_URI, ) application_agent_2 = ContractAgency.get_agent( TACoApplicationAgent, registry=test_registry, - provider_uri=TEST_ETH_PROVIDER_URI, + blockchain_endpoint=TEST_ETH_PROVIDER_URI, ) assert application_agent_2.registry == application_agent_1.registry == test_registry assert application_agent_2 is application_agent_1 diff --git a/tests/acceptance/agents/test_token_agent.py b/tests/acceptance/agents/test_token_agent.py index 89fb607c5..ee9755c3f 100644 --- a/tests/acceptance/agents/test_token_agent.py +++ b/tests/acceptance/agents/test_token_agent.py @@ -13,7 +13,9 @@ from tests.constants import TEST_ETH_PROVIDER_URI @pytest.fixture(scope='module') def agent(testerchain, test_registry) -> NucypherTokenAgent: token_agent = ContractAgency.get_agent( - NucypherTokenAgent, registry=test_registry, provider_uri=TEST_ETH_PROVIDER_URI + NucypherTokenAgent, + registry=test_registry, + blockchain_endpoint=TEST_ETH_PROVIDER_URI, ) return token_agent diff --git a/tests/acceptance/characters/test_decentralized_grant.py b/tests/acceptance/characters/test_decentralized_grant.py index b862744b9..140b5bd99 100644 --- a/tests/acceptance/characters/test_decentralized_grant.py +++ b/tests/acceptance/characters/test_decentralized_grant.py @@ -30,7 +30,7 @@ def check(policy, bob, ursulas): def test_grant_subscription_manager(alice, bob, ursulas): pre_payment_method = SubscriptionManagerPayment( - eth_provider=TEST_ETH_PROVIDER_URI, network=TEMPORARY_DOMAIN + blockchain_endpoint=TEST_ETH_PROVIDER_URI, domain=TEMPORARY_DOMAIN ) alice.pre_payment_method = pre_payment_method policy = alice.grant( diff --git a/tests/acceptance/characters/test_fault_tolerance.py b/tests/acceptance/characters/test_fault_tolerance.py index d9f406769..020a1f574 100644 --- a/tests/acceptance/characters/test_fault_tolerance.py +++ b/tests/acceptance/characters/test_fault_tolerance.py @@ -137,12 +137,12 @@ def test_invalid_operators_tolerance( force=True, registry=test_registry, network_middleware_client=ursula.network_middleware.client, - eth_provider_uri=ursula.eth_provider_uri, + eth_endpoint=ursula.eth_endpoint, ) # In particular, we know that it's bonded to a staker who is really staking. assert ursula.is_confirmed assert ursula._staking_provider_is_really_staking( - registry=test_registry, eth_provider_uri=TEST_ETH_PROVIDER_URI + registry=test_registry, eth_endpoint=TEST_ETH_PROVIDER_URI ) # OK. Now we learn about this new worker. @@ -161,7 +161,7 @@ def test_invalid_operators_tolerance( # OK...so...the staker is not staking anymore ... assert not ursula._staking_provider_is_really_staking( - registry=test_registry, eth_provider_uri=TEST_ETH_PROVIDER_URI + registry=test_registry, eth_endpoint=TEST_ETH_PROVIDER_URI ) # ... but the worker node still is "verified" (since we're not forcing on-chain verification) @@ -176,7 +176,7 @@ def test_invalid_operators_tolerance( force=True, registry=test_registry, network_middleware_client=ursula.network_middleware.client, - eth_provider_uri=TEST_ETH_PROVIDER_URI, + eth_endpoint=TEST_ETH_PROVIDER_URI, ) # diff --git a/tests/acceptance/characters/test_operator.py b/tests/acceptance/characters/test_operator.py index f6a4a4383..5be008b30 100644 --- a/tests/acceptance/characters/test_operator.py +++ b/tests/acceptance/characters/test_operator.py @@ -16,7 +16,7 @@ def test_stakers_bond_to_ursulas(ursulas, test_registry, staking_providers): assert len(ursulas) == len(staking_providers) for ursula in ursulas: ursula.validate_operator( - registry=test_registry, eth_provider_uri=TEST_ETH_PROVIDER_URI + registry=test_registry, eth_endpoint=TEST_ETH_PROVIDER_URI ) assert ursula.verified_operator @@ -106,7 +106,7 @@ def test_vladimir_uses_his_own_signing_key(alice, ursulas, test_registry): message = f"Operator {vladimir.operator_address} is not bonded" with pytest.raises(vladimir.UnbondedOperator, match=message): vladimir.validate_metadata( - registry=test_registry, eth_provider_uri=TEST_ETH_PROVIDER_URI + registry=test_registry, eth_endpoint=TEST_ETH_PROVIDER_URI ) @@ -159,9 +159,7 @@ def test_ursulas_reencrypt(ursulas, alice, bob, policy_value): assert plaintexts == [message] # Let's consider also that a node may be down when granting - alice.network_middleware = NodeIsDownMiddleware( - eth_provider_uri=MOCK_ETH_PROVIDER_URI - ) + alice.network_middleware = NodeIsDownMiddleware(eth_endpoint=MOCK_ETH_PROVIDER_URI) alice.network_middleware.node_is_down(ursulas[0]) with pytest.raises(Policy.NotEnoughUrsulas): diff --git a/tests/acceptance/characters/test_transacting_power.py b/tests/acceptance/characters/test_transacting_power.py index c79100a20..52fce395e 100644 --- a/tests/acceptance/characters/test_transacting_power.py +++ b/tests/acceptance/characters/test_transacting_power.py @@ -21,7 +21,7 @@ def test_character_transacting_power_signing(testerchain, test_registry): signer = Character( is_me=True, domain=TEMPORARY_DOMAIN, - eth_provider_uri=TEST_ETH_PROVIDER_URI, + eth_endpoint=TEST_ETH_PROVIDER_URI, registry=test_registry, checksum_address=eth_address, ) diff --git a/tests/acceptance/cli/test_ursula_init.py b/tests/acceptance/cli/test_ursula_init.py index de932f4f5..8f84c9187 100644 --- a/tests/acceptance/cli/test_ursula_init.py +++ b/tests/acceptance/cli/test_ursula_init.py @@ -73,7 +73,7 @@ def mock_funded_account_password_keystore( taco_application_agent = ContractAgency.get_agent( TACoApplicationAgent, registry=test_registry, - provider_uri=TEST_ETH_PROVIDER_URI, + blockchain_endpoint=TEST_ETH_PROVIDER_URI, ) taco_application_agent.bond_operator( staking_provider=provider_address, @@ -123,17 +123,15 @@ def test_ursula_and_local_keystore_signer_integration( init_args = ( "ursula", "init", - "--network", - TEMPORARY_DOMAIN, - "--pre-payment-network", + "--domain", TEMPORARY_DOMAIN, "--operator-address", worker_account.address, "--config-root", str(config_root_path.absolute()), - "--eth-provider", + "--eth-endpoint", TEST_ETH_PROVIDER_URI, - "--pre-payment-provider", + "--polygon-endpoint", TEST_POLYGON_PROVIDER_URI, "--rest-host", MOCK_IP_ADDRESS, diff --git a/tests/acceptance/cli/test_ursula_run.py b/tests/acceptance/cli/test_ursula_run.py index db1b9338f..ebb64aba1 100644 --- a/tests/acceptance/cli/test_ursula_run.py +++ b/tests/acceptance/cli/test_ursula_run.py @@ -27,7 +27,7 @@ from tests.utils.ursula import select_test_port, start_pytest_ursula_services @mock.patch('glob.glob', return_value=list()) def test_missing_configuration_file(_default_filepath_mock, click_runner): - cmd_args = ('ursula', 'run', '--network', TEMPORARY_DOMAIN) + cmd_args = ("ursula", "run", "--domain", TEMPORARY_DOMAIN) result = click_runner.invoke(nucypher_cli, cmd_args, catch_exceptions=False) assert result.exit_code != 0 configuration_type = UrsulaConfiguration.NAME @@ -45,9 +45,9 @@ def test_ursula_run_with_prometheus_but_no_metrics_port(click_runner): "--dry-run", # Disable twisted reactor in subprocess "--lonely", # Do not load seednodes "--prometheus", # Specify collection of prometheus metrics - "--eth-provider", + "--eth-endpoint", TEST_ETH_PROVIDER_URI, - "--pre-payment-provider", + "--polygon-endpoint", TEST_POLYGON_PROVIDER_URI, ) @@ -74,12 +74,10 @@ def test_run_lone_default_development_ursula(click_runner, ursulas, testerchain) "--lonely", # Do not load seednodes, "--operator-address", ursulas[0].operator_address, - "--eth-provider", + "--eth-endpoint", TEST_ETH_PROVIDER_URI, - "--pre-payment-provider", + "--polygon-endpoint", TEST_ETH_PROVIDER_URI, - "--pre-payment-network", - TEMPORARY_DOMAIN, ) result = yield threads.deferToThread( @@ -128,12 +126,10 @@ def test_ursula_learns_via_cli(click_runner, ursulas, testerchain): "--dry-run", # Disable twisted reactor "--operator-address", ursulas[0].operator_address, - "--eth-provider", + "--eth-endpoint", TEST_ETH_PROVIDER_URI, - "--pre-payment-provider", + "--polygon-endpoint", TEST_ETH_PROVIDER_URI, - "--pre-payment-network", - TEMPORARY_DOMAIN, ) return threads.deferToThread( @@ -180,15 +176,13 @@ def test_persistent_node_storage_integration( init_args = ( "ursula", "init", - "--eth-provider", + "--eth-endpoint", TEST_ETH_PROVIDER_URI, - "--pre-payment-provider", + "--polygon-endpoint", TEST_POLYGON_PROVIDER_URI, "--operator-address", another_ursula, - "--network", - TEMPORARY_DOMAIN, - "--pre-payment-network", + "--domain", TEMPORARY_DOMAIN, "--rest-host", MOCK_IP_ADDRESS, diff --git a/tests/acceptance/conditions/conftest.py b/tests/acceptance/conditions/conftest.py index fc10b5b17..6dbbbb518 100644 --- a/tests/acceptance/conditions/conftest.py +++ b/tests/acceptance/conditions/conftest.py @@ -52,7 +52,7 @@ def erc20_evm_condition_balanceof(testerchain, test_registry): token = ContractAgency.get_agent( NucypherTokenAgent, registry=test_registry, - provider_uri=TEST_ETH_PROVIDER_URI, + blockchain_endpoint=TEST_ETH_PROVIDER_URI, ) condition = ContractCondition( contract_address=token.contract.address, @@ -115,7 +115,7 @@ def subscription_manager_get_policy_zeroized_policy_struct_condition( subscription_manager = ContractAgency.get_agent( SubscriptionManagerAgent, registry=test_registry, - provider_uri=TEST_ETH_PROVIDER_URI, + blockchain_endpoint=TEST_ETH_PROVIDER_URI, ) condition = ContractCondition( contract_address=subscription_manager.contract.address, @@ -135,7 +135,7 @@ def subscription_manager_is_active_policy_condition(testerchain, test_registry): subscription_manager = ContractAgency.get_agent( SubscriptionManagerAgent, registry=test_registry, - provider_uri=TEST_ETH_PROVIDER_URI, + blockchain_endpoint=TEST_ETH_PROVIDER_URI, ) condition = ContractCondition( contract_address=subscription_manager.contract.address, @@ -157,7 +157,7 @@ def custom_context_variable_erc20_condition( token = ContractAgency.get_agent( NucypherTokenAgent, registry=test_registry, - provider_uri=TEST_ETH_PROVIDER_URI, + blockchain_endpoint=TEST_ETH_PROVIDER_URI, ) condition = ContractCondition( contract_address=token.contract.address, diff --git a/tests/acceptance/conditions/test_conditions.py b/tests/acceptance/conditions/test_conditions.py index a35cdf720..3047a68f4 100644 --- a/tests/acceptance/conditions/test_conditions.py +++ b/tests/acceptance/conditions/test_conditions.py @@ -346,7 +346,7 @@ def test_subscription_manager_get_policy_policy_struct_condition_key_tuple_evalu subscription_manager = ContractAgency.get_agent( SubscriptionManagerAgent, registry=test_registry, - provider_uri=TEST_ETH_PROVIDER_URI, + blockchain_endpoint=TEST_ETH_PROVIDER_URI, ) # test "sponsor" key (owner is the same as sponsor for this policy) @@ -464,7 +464,7 @@ def test_subscription_manager_get_policy_policy_struct_condition_index_and_value subscription_manager = ContractAgency.get_agent( SubscriptionManagerAgent, registry=test_registry, - provider_uri=TEST_POLYGON_PROVIDER_URI, + blockchain_endpoint=TEST_POLYGON_PROVIDER_URI, ) # test "sponsor" index not equal to correct value diff --git a/tests/acceptance/conftest.py b/tests/acceptance/conftest.py index e57bc7c22..de32d8102 100644 --- a/tests/acceptance/conftest.py +++ b/tests/acceptance/conftest.py @@ -11,8 +11,11 @@ from nucypher.blockchain.eth.agents import ( TACoApplicationAgent, TACoChildApplicationAgent, ) +from nucypher.blockchain.eth.domains import ( + DomainInfo, + TACoDomain, +) from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory -from nucypher.blockchain.eth.networks import NetworksInventory from nucypher.blockchain.eth.registry import ContractRegistry, RegistrySourceManager from nucypher.blockchain.eth.signers.software import Web3Signer from nucypher.config.constants import TEMPORARY_DOMAIN @@ -25,6 +28,7 @@ from tests.constants import ( MIN_OPERATOR_SECONDS, TEST_ETH_PROVIDER_URI, TESTERCHAIN_CHAIN_ID, + TESTERCHAIN_CHAIN_INFO, ) from tests.utils.blockchain import TesterBlockchain from tests.utils.registry import ApeRegistrySource @@ -299,8 +303,8 @@ def deployed_contracts( @pytest.fixture(scope="module", autouse=True) -def test_registry(deployed_contracts): - with tests.utils.registry.mock_registry_sources(): +def test_registry(deployed_contracts, module_mocker): + with tests.utils.registry.mock_registry_sources(mocker=module_mocker): RegistrySourceManager._FALLBACK_CHAIN = (ApeRegistrySource,) source = ApeRegistrySource(domain=TEMPORARY_DOMAIN) registry = ContractRegistry(source=source) @@ -312,7 +316,7 @@ def test_registry(deployed_contracts): def testerchain(project) -> TesterBlockchain: # Extract the web3 provider containing EthereumTester from the ape project's chain manager provider = project.chain_manager.provider.web3.provider - testerchain = TesterBlockchain(eth_provider=provider) + testerchain = TesterBlockchain(provider=provider) BlockchainInterfaceFactory.register_interface(interface=testerchain, force=True) yield testerchain @@ -370,7 +374,9 @@ def staking_providers( def coordinator_agent(testerchain, test_registry): """Creates a coordinator agent""" coordinator = ContractAgency.get_agent( - CoordinatorAgent, registry=test_registry, provider_uri=TEST_ETH_PROVIDER_URI + CoordinatorAgent, + registry=test_registry, + blockchain_endpoint=TEST_ETH_PROVIDER_URI, ) return coordinator @@ -380,7 +386,7 @@ def taco_application_agent(test_registry): _taco_application_agent = ContractAgency.get_agent( TACoApplicationAgent, registry=test_registry, - provider_uri=TEST_ETH_PROVIDER_URI, + blockchain_endpoint=TEST_ETH_PROVIDER_URI, ) return _taco_application_agent @@ -391,7 +397,7 @@ def taco_child_application_agent(testerchain, test_registry): _taco_child_application_agent = ContractAgency.get_agent( TACoChildApplicationAgent, registry=test_registry, - provider_uri=TEST_ETH_PROVIDER_URI, + blockchain_endpoint=TEST_ETH_PROVIDER_URI, ) return _taco_child_application_agent @@ -426,20 +432,20 @@ def multichain_ursulas(ursulas, multichain_ids, mock_rpc_condition): return ursulas -@pytest.fixture(scope="session", autouse=True) -def mock_condition_blockchains(session_mocker): +@pytest.fixture(scope="module", autouse=True) +def mock_condition_blockchains(module_mocker): """adds testerchain's chain ID to permitted conditional chains""" - session_mocker.patch.dict( + module_mocker.patch.dict( "nucypher.policy.conditions.evm._CONDITION_CHAINS", {TESTERCHAIN_CHAIN_ID: "eth-tester/pyevm"}, ) - session_mocker.patch.object( - NetworksInventory, "get_polygon_chain_id", return_value=TESTERCHAIN_CHAIN_ID + test_domain_info = DomainInfo( + TEMPORARY_DOMAIN, TESTERCHAIN_CHAIN_INFO, TESTERCHAIN_CHAIN_INFO ) - session_mocker.patch.object( - NetworksInventory, "get_ethereum_chain_id", return_value=TESTERCHAIN_CHAIN_ID + module_mocker.patch.object( + TACoDomain, "get_domain_info", return_value=test_domain_info ) diff --git a/tests/acceptance/test_testerchain.py b/tests/acceptance/test_testerchain.py index 33b5e2730..81e5e7190 100644 --- a/tests/acceptance/test_testerchain.py +++ b/tests/acceptance/test_testerchain.py @@ -1,14 +1,12 @@ import pytest -from nucypher.blockchain.eth.clients import EthereumClient -from nucypher.blockchain.eth.signers.software import Web3Signer -from nucypher.crypto.powers import TransactingPower from tests.constants import ( DEVELOPMENT_ETH_AIRDROP_AMOUNT, NUMBER_OF_ETH_TEST_ACCOUNTS, NUMBER_OF_STAKING_PROVIDERS_IN_BLOCKCHAIN_TESTS, NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS, ) + # Prevents TesterBlockchain to be picked up by py.test as a test class from tests.utils.blockchain import TesterBlockchain as _TesterBlockchain @@ -28,7 +26,7 @@ def test_testerchain_creation(testerchain, another_testerchain): for chain in chains: # Ensure we are testing on the correct network... - assert 'tester' in chain.eth_provider_uri + assert "tester" in chain.endpoint # ... and that there are already some blocks mined chain.w3.eth.w3.testing.mine(1) diff --git a/tests/conftest.py b/tests/conftest.py index 634b01924..2698c2a30 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,11 +4,19 @@ import pytest from eth_utils.crypto import keccak from nucypher.blockchain.eth.actors import Operator -from nucypher.blockchain.eth.networks import NetworksInventory +from nucypher.blockchain.eth.domains import ( + DomainInfo, + TACoDomain, +) +from nucypher.config.constants import TEMPORARY_DOMAIN from nucypher.crypto.powers import TransactingPower from nucypher.network.nodes import Learner from nucypher.utilities.logging import GlobalLoggerSettings -from tests.constants import MOCK_IP_ADDRESS, TESTERCHAIN_CHAIN_ID +from tests.constants import ( + MOCK_IP_ADDRESS, + TESTERCHAIN_CHAIN_ID, + TESTERCHAIN_CHAIN_INFO, +) # Don't re-lock accounts in the background while making commitments LOCK_FUNCTION = TransactingPower.lock_account @@ -134,20 +142,19 @@ def disable_check_grant_requirements(session_mocker): session_mocker.patch(target, return_value=MOCK_IP_ADDRESS) -@pytest.fixture(scope="session", autouse=True) -def mock_condition_blockchains(session_mocker): +@pytest.fixture(scope="module", autouse=True) +def mock_condition_blockchains(module_mocker): """adds testerchain's chain ID to permitted conditional chains""" - session_mocker.patch.dict( + module_mocker.patch.dict( "nucypher.policy.conditions.evm._CONDITION_CHAINS", {TESTERCHAIN_CHAIN_ID: "eth-tester/pyevm"}, ) - - session_mocker.patch.object( - NetworksInventory, "get_polygon_chain_id", return_value=TESTERCHAIN_CHAIN_ID + test_domain_info = DomainInfo( + TEMPORARY_DOMAIN, TESTERCHAIN_CHAIN_INFO, TESTERCHAIN_CHAIN_INFO ) - session_mocker.patch.object( - NetworksInventory, "get_ethereum_chain_id", return_value=TESTERCHAIN_CHAIN_ID + module_mocker.patch.object( + TACoDomain, "get_domain_info", return_value=test_domain_info ) diff --git a/tests/constants.py b/tests/constants.py index 2ca1db4f8..aee733162 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -7,6 +7,7 @@ from random import SystemRandom from hexbytes import HexBytes from web3 import Web3 +from nucypher.blockchain.eth.domains import ChainInfo from nucypher.blockchain.eth.token import NU from nucypher.config.constants import ( NUCYPHER_ENVVAR_KEYSTORE_PASSWORD, @@ -37,7 +38,7 @@ NUMBER_OF_STAKING_PROVIDERS_IN_BLOCKCHAIN_TESTS = NUMBER_OF_URSULAS_IN_BLOCKCHAI # Ursulas (Operators) and Staking Providers have their own account NUMBER_OF_ETH_TEST_ACCOUNTS = NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS + NUMBER_OF_STAKING_PROVIDERS_IN_BLOCKCHAIN_TESTS + 10 -NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK = NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS +NUMBER_OF_URSULAS_IN_DEVELOPMENT_DOMAIN = NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS # # Local Signer Keystore @@ -71,6 +72,8 @@ NUMBER_OF_ALLOCATIONS_IN_TESTS = 50 # TODO: Move to constants TESTERCHAIN_CHAIN_ID = 131277322940537 +TESTERCHAIN_CHAIN_INFO = ChainInfo(131277322940537, "eth-tester") + # # Insecure Secrets diff --git a/tests/fixtures.py b/tests/fixtures.py index 21f769d64..b22cc882c 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -23,7 +23,6 @@ from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory from nucypher.blockchain.eth.signers.software import KeystoreSigner from nucypher.blockchain.eth.trackers.dkg import EventScannerTask from nucypher.characters.lawful import Enrico, Ursula -from nucypher.config.base import CharacterConfiguration from nucypher.config.characters import ( AliceConfiguration, BobConfiguration, @@ -130,8 +129,8 @@ def random_address(random_account): @pytest.fixture(scope="module") def ursula_test_config(test_registry, temp_dir_path, testerchain): config = make_ursula_test_configuration( - eth_provider_uri=TEST_ETH_PROVIDER_URI, - pre_payment_provider=TEST_ETH_PROVIDER_URI, + eth_endpoint=TEST_ETH_PROVIDER_URI, + polygon_endpoint=TEST_ETH_PROVIDER_URI, test_registry=test_registry, rest_port=select_test_port(), operator_address=testerchain.ursulas_accounts.pop(), @@ -145,8 +144,8 @@ def ursula_test_config(test_registry, temp_dir_path, testerchain): @pytest.fixture(scope="module") def alice_test_config(ursulas, testerchain, test_registry): config = make_alice_test_configuration( - eth_provider_uri=TEST_ETH_PROVIDER_URI, - pre_payment_provider=TEST_ETH_PROVIDER_URI, + eth_endpoint=TEST_ETH_PROVIDER_URI, + polygon_endpoint=TEST_ETH_PROVIDER_URI, known_nodes=ursulas, checksum_address=testerchain.alice_account, test_registry=test_registry, @@ -157,9 +156,11 @@ def alice_test_config(ursulas, testerchain, test_registry): @pytest.fixture(scope="module") def bob_test_config(testerchain, test_registry): - config = make_bob_test_configuration(eth_provider_uri=TEST_ETH_PROVIDER_URI, - test_registry=test_registry, - checksum_address=testerchain.bob_account) + config = make_bob_test_configuration( + eth_endpoint=TEST_ETH_PROVIDER_URI, + test_registry=test_registry, + checksum_address=testerchain.bob_account, + ) yield config config.cleanup() @@ -197,7 +198,7 @@ def enacted_policy(idle_policy, ursulas): # cannot set them again # deposit = NON_PAYMENT(b"0000000") # contract_end_datetime = maya.now() + datetime.timedelta(days=5) - network_middleware = MockRestMiddleware(eth_provider_uri=TEST_ETH_PROVIDER_URI) + network_middleware = MockRestMiddleware(eth_endpoint=TEST_ETH_PROVIDER_URI) # REST call happens here, as does population of TreasureMap. enacted_policy = idle_policy.enact( @@ -262,8 +263,7 @@ def alice(alice_test_config, ursulas, testerchain): @pytest.fixture(scope="module") def bob(bob_test_config, testerchain): bob = bob_test_config.produce( - coordinator_provider_uri=MOCK_ETH_PROVIDER_URI, - coordinator_network=TEMPORARY_DOMAIN, + polygon_endpoint=TEST_ETH_PROVIDER_URI, ) yield bob bob.disenchant() @@ -304,8 +304,8 @@ def lonely_ursula_maker(ursula_test_config, testerchain): @pytest.fixture(scope="module") -def mock_registry_sources(): - with tests.utils.registry.mock_registry_sources(): +def mock_registry_sources(module_mocker): + with tests.utils.registry.mock_registry_sources(module_mocker): yield @@ -323,8 +323,7 @@ def light_ursula(temp_dir_path, random_account, mocker): KeystoreSigner, "_KeystoreSigner__get_signer", return_value=random_account ) pre_payment_method = SubscriptionManagerPayment( - eth_provider=MOCK_ETH_PROVIDER_URI, - network=TEMPORARY_DOMAIN, + blockchain_endpoint=MOCK_ETH_PROVIDER_URI, domain=TEMPORARY_DOMAIN ) mocker.patch.object( @@ -338,7 +337,8 @@ def light_ursula(temp_dir_path, random_account, mocker): pre_payment_method=pre_payment_method, checksum_address=random_account.address, operator_address=random_account.address, - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, + polygon_endpoint=MOCK_ETH_PROVIDER_URI, signer=KeystoreSigner(path=temp_dir_path), ) return ursula @@ -434,17 +434,13 @@ def highperf_mocked_alice( monkeymodule, testerchain, ): - monkeymodule.setattr( - CharacterConfiguration, "DEFAULT_PRE_PAYMENT_NETWORK", TEMPORARY_DOMAIN - ) - config = AliceConfiguration( dev_mode=True, domain=TEMPORARY_DOMAIN, - eth_provider_uri=TEST_ETH_PROVIDER_URI, + eth_endpoint=TEST_ETH_PROVIDER_URI, checksum_address=testerchain.alice_account, network_middleware=MockRestMiddlewareForLargeFleetTests( - eth_provider_uri=TEST_ETH_PROVIDER_URI + eth_endpoint=TEST_ETH_PROVIDER_URI ), abort_on_learning_error=True, save_metadata=False, @@ -462,10 +458,10 @@ def highperf_mocked_alice( def highperf_mocked_bob(fleet_of_highperf_mocked_ursulas): config = BobConfiguration( dev_mode=True, - eth_provider_uri=TEST_ETH_PROVIDER_URI, + eth_endpoint=TEST_ETH_PROVIDER_URI, domain=TEMPORARY_DOMAIN, network_middleware=MockRestMiddlewareForLargeFleetTests( - eth_provider_uri=TEST_ETH_PROVIDER_URI + eth_endpoint=TEST_ETH_PROVIDER_URI ), abort_on_learning_error=True, save_metadata=False, @@ -501,9 +497,8 @@ def click_runner(): def nominal_configuration_fields(): config = UrsulaConfiguration( dev_mode=True, - pre_payment_network=TEMPORARY_DOMAIN, domain=TEMPORARY_DOMAIN, - eth_provider_uri=TEST_ETH_PROVIDER_URI, + eth_endpoint=TEST_ETH_PROVIDER_URI, ) config_fields = config.static_payload() yield tuple(config_fields.keys()) @@ -565,7 +560,7 @@ def basic_auth_file(temp_dir_path): @pytest.fixture(scope='module') def mock_rest_middleware(): - return MockRestMiddleware(eth_provider_uri=TEST_ETH_PROVIDER_URI) + return MockRestMiddleware(eth_endpoint=TEST_ETH_PROVIDER_URI) # diff --git a/tests/integration/characters/test_bob_handles_frags.py b/tests/integration/characters/test_bob_handles_frags.py index a548532ae..a383dba2b 100644 --- a/tests/integration/characters/test_bob_handles_frags.py +++ b/tests/integration/characters/test_bob_handles_frags.py @@ -83,9 +83,7 @@ def test_use_external_cache(enacted_policy, bob, ursulas): ursulas = list(ursulas) # All Ursulas are down except for two - bob.network_middleware = NodeIsDownMiddleware( - eth_provider_uri=MOCK_ETH_PROVIDER_URI - ) + bob.network_middleware = NodeIsDownMiddleware(eth_endpoint=MOCK_ETH_PROVIDER_URI) for ursula in ursulas[2:]: bob.network_middleware.node_is_down(ursula) diff --git a/tests/integration/characters/test_bob_joins_policy_and_retrieves.py b/tests/integration/characters/test_bob_joins_policy_and_retrieves.py index a79241d0f..a4b79b335 100644 --- a/tests/integration/characters/test_bob_joins_policy_and_retrieves.py +++ b/tests/integration/characters/test_bob_joins_policy_and_retrieves.py @@ -10,7 +10,7 @@ from nucypher.characters.lawful import Bob, Enrico from nucypher.config.constants import TEMPORARY_DOMAIN from tests.constants import ( MOCK_ETH_PROVIDER_URI, - NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK, + NUMBER_OF_URSULAS_IN_DEVELOPMENT_DOMAIN, ) from tests.utils.middleware import MockRestMiddleware @@ -49,8 +49,8 @@ def test_bob_retrieves(alice, ursulas, certificates_tempdir): bob = Bob( domain=TEMPORARY_DOMAIN, start_learning_now=True, - eth_provider_uri=MOCK_ETH_PROVIDER_URI, - network_middleware=MockRestMiddleware(eth_provider_uri=MOCK_ETH_PROVIDER_URI), + eth_endpoint=MOCK_ETH_PROVIDER_URI, + network_middleware=MockRestMiddleware(eth_endpoint=MOCK_ETH_PROVIDER_URI), abort_on_learning_error=True, known_nodes=a_couple_of_ursulas, ) @@ -60,7 +60,7 @@ def test_bob_retrieves(alice, ursulas, certificates_tempdir): # Alice creates a policy granting access to Bob # Just for fun, let's assume she distributes KFrags among Ursulas unknown to Bob - shares = NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK - 2 + shares = NUMBER_OF_URSULAS_IN_DEVELOPMENT_DOMAIN - 2 label = b'label://' + os.urandom(32) contract_end_datetime = maya.now() + datetime.timedelta(days=5) policy = alice.grant( diff --git a/tests/integration/characters/test_dkg_and_testnet_bypass.py b/tests/integration/characters/test_dkg_and_testnet_bypass.py index d42845d3d..4314f0acf 100644 --- a/tests/integration/characters/test_dkg_and_testnet_bypass.py +++ b/tests/integration/characters/test_dkg_and_testnet_bypass.py @@ -1,5 +1,6 @@ import pytest +from nucypher.blockchain.eth.domains import TACoDomain from nucypher.blockchain.eth.signers.software import Web3Signer from nucypher.characters.chaotic import ( NiceGuyEddie, @@ -22,8 +23,8 @@ def _attempt_decryption(BobClass, plaintext, testerchain): enrico = NiceGuyEddie(encrypting_key=trinket, signer=signer) bob = BobClass( registry=MOCK_REGISTRY_FILEPATH, - domain="lynx", - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + domain=TACoDomain.LYNX.name, + eth_endpoint=MOCK_ETH_PROVIDER_URI, ) definitely_false_condition = { diff --git a/tests/integration/characters/test_ursula_startup.py b/tests/integration/characters/test_ursula_startup.py index faac39382..0ce1a8635 100644 --- a/tests/integration/characters/test_ursula_startup.py +++ b/tests/integration/characters/test_ursula_startup.py @@ -1,9 +1,11 @@ import pytest +from nucypher.config.constants import TEMPORARY_DOMAIN + def test_new_ursula_announces_herself(lonely_ursula_maker): ursula_in_a_house, ursula_with_a_mouse = lonely_ursula_maker( - quantity=2, domain="useless_domain" + quantity=2, domain=TEMPORARY_DOMAIN ) # Neither Ursula knows about the other. @@ -36,8 +38,8 @@ def test_goerli_and_mumbai_as_conditions_providers(lonely_ursula_maker): with pytest.raises(NotImplementedError): _ursula_who_tries_to_connect_to_an_invalid_chain = lonely_ursula_maker( quantity=1, - domain="useless_domain", - condition_provider_uris={ + domain=TEMPORARY_DOMAIN, + condition_blockchain_endpoints={ INVALID_CHAIN_ID: "this is a provider URI, but it doesn't matter what we pass here because the chain_id is invalid." }, ) diff --git a/tests/integration/cli/actions/test_select_client_account.py b/tests/integration/cli/actions/test_select_client_account.py index 01451c5ed..9a015b2c4 100644 --- a/tests/integration/cli/actions/test_select_client_account.py +++ b/tests/integration/cli/actions/test_select_client_account.py @@ -12,9 +12,8 @@ from nucypher.blockchain.eth.clients import EthereumClient from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory from nucypher.blockchain.eth.signers import KeystoreSigner from nucypher.blockchain.eth.signers.software import Web3Signer -from nucypher.blockchain.eth.token import NU from nucypher.cli.actions.select import select_client_account -from nucypher.cli.literature import GENERIC_SELECT_ACCOUNT, NO_ETH_ACCOUNTS +from nucypher.cli.literature import GENERIC_SELECT_ACCOUNT, NO_ACCOUNTS from nucypher.config.constants import TEMPORARY_DOMAIN from tests.constants import ( MOCK_ETH_PROVIDER_URI, @@ -33,7 +32,7 @@ def test_select_client_account( selected_account = select_client_account( emitter=test_emitter, signer=Web3Signer(testerchain.client), - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + polygon_endpoint=MOCK_ETH_PROVIDER_URI, ) assert selected_account, "Account selection returned Falsy instead of an address" assert isinstance(selected_account, str), "Selection is not a str" @@ -56,10 +55,10 @@ def test_select_client_account_with_no_accounts( select_client_account( emitter=test_emitter, signer=Web3Signer(testerchain.client), - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + polygon_endpoint=MOCK_ETH_PROVIDER_URI, ) captured = capsys.readouterr() - assert NO_ETH_ACCOUNTS in captured.out + assert NO_ACCOUNTS in captured.out def test_select_client_account_ambiguous_source( @@ -120,7 +119,9 @@ def test_select_client_account_valid_sources( # From pre-initialized Provider mock_stdin.line(str(selection)) expected_account = testerchain.client.accounts[selection] - selected_account = select_client_account(emitter=test_emitter, eth_provider_uri=MOCK_ETH_PROVIDER_URI) + selected_account = select_client_account( + emitter=test_emitter, polygon_endpoint=MOCK_ETH_PROVIDER_URI + ) assert selected_account == expected_account assert mock_stdin.empty() captured = capsys.readouterr() @@ -136,7 +137,7 @@ def test_select_client_account_valid_sources( BlockchainInterfaceFactory, "get_interface", return_value=testerchain ) selected_account = select_client_account( - emitter=test_emitter, eth_provider_uri=MOCK_ETH_PROVIDER_URI + emitter=test_emitter, polygon_endpoint=MOCK_ETH_PROVIDER_URI ) assert selected_account == expected_account assert mock_stdin.empty() @@ -144,15 +145,17 @@ def test_select_client_account_valid_sources( assert GENERIC_SELECT_ACCOUNT in captured.out and f"Selected {selection}" in captured.out -@pytest.mark.skip('fix me') -@pytest.mark.parametrize('selection,show_staking,show_eth,show_tokens,stake_info', ( - (0, True, True, True, []), - (1, True, True, True, []), - (5, True, True, True, []), - (NUMBER_OF_ETH_TEST_ACCOUNTS-1, True, True, True, []), - (0, False, True, True, []), - (0, False, False, True, []), - (0, False, False, False, []), +@pytest.mark.skip("fix me") +@pytest.mark.parametrize( + "selection,show_staking,show_matic,stake_info", + ( + (0, True, True, []), + (1, True, True, []), + (5, True, True, []), + (NUMBER_OF_ETH_TEST_ACCOUNTS - 1, True, True, []), + (0, False, True, []), + (0, False, False, []), + (0, False, False, []), ), ) def test_select_client_account_with_balance_display( @@ -164,8 +167,7 @@ def test_select_client_account_with_balance_display( mock_token_agent, selection, show_staking, - show_eth, - show_tokens, + show_matic, stake_info, ): @@ -173,23 +175,27 @@ def test_select_client_account_with_balance_display( mock_staking_agent.get_all_stakes.return_value = stake_info # Missing network kwarg with balance display active - blockchain_read_required = any((show_staking, show_eth, show_tokens)) + blockchain_read_required = any((show_staking, show_matic)) if blockchain_read_required: - with pytest.raises(ValueError, match='Pass network name or registry; Got neither.'): - select_client_account(emitter=test_emitter, - show_eth_balance=show_eth, - show_nu_balance=show_tokens, - show_staking=show_staking, - eth_provider_uri=MOCK_ETH_PROVIDER_URI) + with pytest.raises( + ValueError, match="Pass domain name or registry; Got neither." + ): + select_client_account( + emitter=test_emitter, + show_matic_balance=show_matic, + show_staking=show_staking, + polygon_endpoint=MOCK_ETH_PROVIDER_URI, + ) # Good selection mock_stdin.line(str(selection)) - selected_account = select_client_account(emitter=test_emitter, - network=TEMPORARY_DOMAIN, - show_eth_balance=show_eth, - show_nu_balance=show_tokens, - show_staking=show_staking, - eth_provider_uri=MOCK_ETH_PROVIDER_URI) + selected_account = select_client_account( + emitter=test_emitter, + domain=TEMPORARY_DOMAIN, + show_matic_balance=show_matic, + show_staking=show_staking, + polygon_endpoint=MOCK_ETH_PROVIDER_URI, + ) # check for accurate selection consistency with client index assert selected_account == testerchain.client.accounts[selection] @@ -199,10 +205,8 @@ def test_select_client_account_with_balance_display( headers = ['Account'] if show_staking: headers.append('Staking') - if show_eth: - headers.append('ETH') - if show_tokens: - headers.append('NU') + if show_matic: + headers.append("MATIC") captured = capsys.readouterr() for column_name in headers: @@ -211,11 +215,7 @@ def test_select_client_account_with_balance_display( for account in testerchain.client.accounts: assert account in captured.out - if show_tokens: - balance = mock_token_agent.get_balance(address=account) - assert str(NU.from_units(balance)) in captured.out - - if show_eth: + if show_matic: balance = testerchain.client.get_balance(account=account) assert str(Web3.from_wei(balance, 'ether')) in captured.out diff --git a/tests/integration/cli/actions/test_select_network.py b/tests/integration/cli/actions/test_select_network.py index dafd8a518..1fd0b6741 100644 --- a/tests/integration/cli/actions/test_select_network.py +++ b/tests/integration/cli/actions/test_select_network.py @@ -1,24 +1,18 @@ import pytest -from nucypher.blockchain.eth.networks import NetworksInventory -from nucypher.cli.actions.select import select_network +from nucypher.blockchain.eth.domains import TACoDomain +from nucypher.cli.actions.select import select_domain + +__DOMAINS = TACoDomain.SUPPORTED_DOMAIN_NAMES -@pytest.mark.parametrize( - "user_input", range(0, len(NetworksInventory.ETH_NETWORKS) - 1) -) -def test_select_network_cli_action_eth(test_emitter, capsys, mock_stdin, user_input): +@pytest.mark.parametrize("user_input", range(0, len(__DOMAINS) - 1)) +def test_select_network_cli_action(test_emitter, capsys, mock_stdin, user_input: int): mock_stdin.line(str(user_input)) - selection = NetworksInventory.ETH_NETWORKS[user_input] - result = select_network(emitter=test_emitter, network_type=NetworksInventory.ETH) + selection = __DOMAINS[user_input] + result = select_domain(emitter=test_emitter) assert result == selection - assert result not in NetworksInventory.POLY_NETWORKS captured = capsys.readouterr() - for name in NetworksInventory.ETH_NETWORKS: + for name in __DOMAINS: assert name in captured.out assert mock_stdin.empty() - - -def test_select_network_cli_action_neither(test_emitter): - with pytest.raises(Exception): - select_network(emitter=test_emitter, network_type="FAKE COIN") diff --git a/tests/integration/cli/test_cli_config.py b/tests/integration/cli/test_cli_config.py index ceda1eec7..2dae91160 100644 --- a/tests/integration/cli/test_cli_config.py +++ b/tests/integration/cli/test_cli_config.py @@ -5,7 +5,7 @@ import pytest from nucypher.blockchain.eth.registry import ContractRegistry from nucypher.cli.main import nucypher_cli -from nucypher.config.characters import CharacterConfiguration, UrsulaConfiguration +from nucypher.config.characters import UrsulaConfiguration from nucypher.config.constants import ( NUCYPHER_ENVVAR_KEYSTORE_PASSWORD, TEMPORARY_DOMAIN, @@ -40,11 +40,11 @@ def test_initialize_via_cli( init_args = ( command, "init", - "--network", + "--domain", TEMPORARY_DOMAIN, - "--eth-provider", + "--eth-endpoint", MOCK_ETH_PROVIDER_URI, - "--pre-payment-provider", + "--polygon-endpoint", TEST_ETH_PROVIDER_URI, "--config-root", str(custom_filepath.absolute()), @@ -82,9 +82,6 @@ def test_reconfigure_via_cli( monkeypatch.setattr( ContractRegistry, "from_latest_publication", fake_get_latest_registry ) - monkeypatch.setattr( - CharacterConfiguration, "DEFAULT_PRE_PAYMENT_NETWORK", TEMPORARY_DOMAIN - ) custom_config_filepath = custom_filepath / config_class.generate_filename() @@ -103,13 +100,18 @@ def test_reconfigure_via_cli( # Read pre-edit state config = config_class.from_configuration_file(custom_config_filepath) - assert config.eth_provider_uri != TEST_ETH_PROVIDER_URI + assert config.eth_endpoint != TEST_ETH_PROVIDER_URI del config # Write - view_args = (config_class.CHARACTER_CLASS.__name__.lower(), 'config', - '--config-file', str(custom_config_filepath.absolute()), - '--eth-provider', TEST_ETH_PROVIDER_URI) + view_args = ( + config_class.CHARACTER_CLASS.__name__.lower(), + "config", + "--config-file", + str(custom_config_filepath.absolute()), + "--eth-endpoint", + TEST_ETH_PROVIDER_URI, + ) result = click_runner.invoke(nucypher_cli, view_args, env=ENV) assert result.exit_code == 0 @@ -121,4 +123,4 @@ def test_reconfigure_via_cli( assert str(custom_filepath) in result.output # After editing the fields have been updated - assert config.eth_provider_uri == TEST_ETH_PROVIDER_URI + assert config.eth_endpoint == TEST_ETH_PROVIDER_URI diff --git a/tests/integration/cli/test_mixed_config.py b/tests/integration/cli/test_mixed_config.py index 40ea09170..818699e2d 100644 --- a/tests/integration/cli/test_mixed_config.py +++ b/tests/integration/cli/test_mixed_config.py @@ -62,15 +62,13 @@ def test_corrupted_configuration( init_args = ( "ursula", "init", - "--eth-provider", + "--eth-endpoint", MOCK_ETH_PROVIDER_URI, - "--pre-payment-provider", + "--polygon-endpoint", TEST_POLYGON_PROVIDER_URI, "--operator-address", another_ursula, - "--network", - TEMPORARY_DOMAIN, - "--pre-payment-network", + "--domain", TEMPORARY_DOMAIN, "--rest-host", MOCK_IP_ADDRESS, @@ -105,13 +103,11 @@ def test_corrupted_configuration( init_args = ( "ursula", "init", - "--network", + "--domain", TEMPORARY_DOMAIN, - "--pre-payment-network", - TEMPORARY_DOMAIN, - "--eth-provider", + "--eth-endpoint", MOCK_ETH_PROVIDER_URI, - "--pre-payment-provider", + "--polygon-endpoint", TEST_POLYGON_PROVIDER_URI, "--operator-address", another_ursula, diff --git a/tests/integration/cli/test_ursula_cli_ip_detection.py b/tests/integration/cli/test_ursula_cli_ip_detection.py index 0ecdbec86..23214c071 100644 --- a/tests/integration/cli/test_ursula_cli_ip_detection.py +++ b/tests/integration/cli/test_ursula_cli_ip_detection.py @@ -34,11 +34,11 @@ def test_ursula_startup_ip_checkup(click_runner, mocker): args = ( "ursula", "init", - "--network", + "--domain", TEMPORARY_DOMAIN, - "--eth-provider", + "--eth-endpoint", MOCK_ETH_PROVIDER_URI, - "--pre-payment-provider", + "--polygon-endpoint", TEST_POLYGON_PROVIDER_URI, "--force", ) @@ -52,12 +52,12 @@ def test_ursula_startup_ip_checkup(click_runner, mocker): args = ( "ursula", "init", - "--network", + "--domain", TEMPORARY_DOMAIN, "--force", - "--eth-provider", + "--eth-endpoint", MOCK_ETH_PROVIDER_URI, - "--pre-payment-provider", + "--polygon-endpoint", TEST_POLYGON_PROVIDER_URI, ) result = click_runner.invoke( @@ -70,12 +70,12 @@ def test_ursula_startup_ip_checkup(click_runner, mocker): args = ( "ursula", "init", - "--network", + "--domain", TEMPORARY_DOMAIN, "--force", - "--eth-provider", + "--eth-endpoint", MOCK_ETH_PROVIDER_URI, - "--pre-payment-provider", + "--polygon-endpoint", TEST_POLYGON_PROVIDER_URI, ) result = click_runner.invoke( diff --git a/tests/integration/cli/test_ursula_config_cli.py b/tests/integration/cli/test_ursula_config_cli.py index 281daf4da..3e6ae07de 100644 --- a/tests/integration/cli/test_ursula_config_cli.py +++ b/tests/integration/cli/test_ursula_config_cli.py @@ -11,7 +11,6 @@ from nucypher.cli.literature import ( CONFIRM_IPV4_ADDRESS_QUESTION, REPEAT_FOR_CONFIRMATION, SELECT_OPERATOR_ACCOUNT, - SELECT_PRE_PAYMENT_NETWORK, SUCCESSFUL_DESTRUCTION, ) from nucypher.cli.main import nucypher_cli @@ -58,21 +57,20 @@ def test_interactive_initialize_ursula(click_runner, mocker, tmpdir): init_args = ( "ursula", "init", - "--network", + "--domain", TEMPORARY_DOMAIN, - "--eth-provider", + "--eth-endpoint", MOCK_ETH_PROVIDER_URI, - "--pre-payment-provider", + "--polygon-endpoint", MOCK_ETH_PROVIDER_URI, ) - user_input = '0\n' + '0\n' + YES_ENTER + FAKE_PASSWORD_CONFIRMED - result = click_runner.invoke(nucypher_cli, init_args, input=user_input, catch_exceptions=False) + user_input = "0\n" + YES_ENTER + FAKE_PASSWORD_CONFIRMED + result = click_runner.invoke( + nucypher_cli, init_args, input=user_input, catch_exceptions=False + ) assert result.exit_code == 0, result.output - # Select network - assert SELECT_PRE_PAYMENT_NETWORK in result.output - # Select account assert SELECT_OPERATOR_ACCOUNT in result.output @@ -92,7 +90,7 @@ def test_initialize_custom_configuration_root( init_args = ( "ursula", "init", - "--network", + "--domain", TEMPORARY_DOMAIN, "--config-root", str(custom_filepath.absolute()), @@ -100,12 +98,10 @@ def test_initialize_custom_configuration_root( MOCK_IP_ADDRESS, "--rest-port", deploy_port, - "--eth-provider", + "--eth-endpoint", MOCK_ETH_PROVIDER_URI, - "--pre-payment-provider", + "--polygon-endpoint", MOCK_ETH_PROVIDER_URI, - "--pre-payment-network", - TEMPORARY_DOMAIN, "--operator-address", testerchain.ursulas_accounts[0], ) diff --git a/tests/integration/cli/test_ursula_local_keystore_cli_functionality.py b/tests/integration/cli/test_ursula_local_keystore_cli_functionality.py index 756c5af36..4846e2fb8 100644 --- a/tests/integration/cli/test_ursula_local_keystore_cli_functionality.py +++ b/tests/integration/cli/test_ursula_local_keystore_cli_functionality.py @@ -48,15 +48,13 @@ def test_ursula_init_with_local_keystore_signer( "ursula", "init", # Layer 1 - "--network", + "--domain", TEMPORARY_DOMAIN, - "--eth-provider", - testerchain.eth_provider_uri, + "--eth-endpoint", + testerchain.endpoint, # Layer 2 - "--pre-payment-network", - TEMPORARY_DOMAIN, - "--pre-payment-provider", - testerchain.eth_provider_uri, + "--polygon-endpoint", + testerchain.endpoint, "--rest-host", MOCK_IP_ADDRESS, "--rest-port", diff --git a/tests/integration/config/test_character_configuration.py b/tests/integration/config/test_character_configuration.py index 5d017f037..7df840d54 100644 --- a/tests/integration/config/test_character_configuration.py +++ b/tests/integration/config/test_character_configuration.py @@ -44,15 +44,13 @@ all_configurations = tuple( def test_development_character_configurations( character, configuration, mocker, testerchain ): - mocker.patch.object( - CharacterConfiguration, "DEFAULT_PRE_PAYMENT_NETWORK", TEMPORARY_DOMAIN - ) params = dict( dev_mode=True, lonely=True, domain=TEMPORARY_DOMAIN, checksum_address=testerchain.unassigned_accounts[0], - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, + polygon_endpoint=MOCK_ETH_PROVIDER_URI, ) if character is Ursula: params.update(dict(operator_address=testerchain.unassigned_accounts[0])) @@ -103,7 +101,7 @@ def test_default_character_configuration_preservation( ): configuration_class.DEFAULT_CONFIG_ROOT = Path("/tmp") fake_address = "0xdeadbeef" - network = TEMPORARY_DOMAIN + domain = TEMPORARY_DOMAIN expected_filename = ( f"{configuration_class.NAME}.{configuration_class._CONFIG_FILE_EXTENSION}" @@ -125,22 +123,18 @@ def test_default_character_configuration_preservation( keystore.signing_public_key = SecretKey.random().public_key() character_config = configuration_class( checksum_address=fake_address, - eth_provider_uri=MOCK_ETH_PROVIDER_URI, - domain=network, + eth_endpoint=MOCK_ETH_PROVIDER_URI, + domain=domain, rest_host=MOCK_IP_ADDRESS, - pre_payment_provider=MOCK_ETH_PROVIDER_URI, - policy_registry=test_registry, - pre_payment_network=TEMPORARY_DOMAIN, + polygon_endpoint=MOCK_ETH_PROVIDER_URI, keystore=keystore, ) else: character_config = configuration_class( checksum_address=fake_address, - eth_provider_uri=MOCK_ETH_PROVIDER_URI, - domain=network, - pre_payment_network=TEMPORARY_DOMAIN, - policy_registry=test_registry, + eth_endpoint=MOCK_ETH_PROVIDER_URI, + domain=domain, ) generated_filepath = character_config.generate_filepath() @@ -177,8 +171,8 @@ def test_ursula_development_configuration(testerchain): checksum_address=testerchain.unassigned_accounts[0], operator_address=testerchain.unassigned_accounts[1], domain=TEMPORARY_DOMAIN, - pre_payment_network=TEMPORARY_DOMAIN, - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, + polygon_endpoint=MOCK_ETH_PROVIDER_URI, ) assert config.is_me is True assert config.dev_mode is True diff --git a/tests/integration/config/test_configuration_persistence.py b/tests/integration/config/test_configuration_persistence.py index 02161ae01..2bcf687df 100644 --- a/tests/integration/config/test_configuration_persistence.py +++ b/tests/integration/config/test_configuration_persistence.py @@ -14,11 +14,10 @@ def test_alices_powers_are_persistent(ursulas, temp_dir_path, testerchain): # Create a non-learning AliceConfiguration config_root = temp_dir_path / 'nucypher-custom-alice-config' alice_config = AliceConfiguration( - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, config_root=config_root, - network_middleware=MockRestMiddleware(eth_provider_uri=MOCK_ETH_PROVIDER_URI), + network_middleware=MockRestMiddleware(eth_endpoint=MOCK_ETH_PROVIDER_URI), domain=TEMPORARY_DOMAIN, - pre_payment_network=TEMPORARY_DOMAIN, checksum_address=testerchain.alice_account, start_learning_now=False, save_metadata=False, @@ -57,8 +56,8 @@ def test_alices_powers_are_persistent(ursulas, temp_dir_path, testerchain): bob = Bob( start_learning_now=False, domain=TEMPORARY_DOMAIN, - eth_provider_uri=MOCK_ETH_PROVIDER_URI, - network_middleware=MockRestMiddleware(eth_provider_uri=MOCK_ETH_PROVIDER_URI), + eth_endpoint=MOCK_ETH_PROVIDER_URI, + network_middleware=MockRestMiddleware(eth_endpoint=MOCK_ETH_PROVIDER_URI), ) bob_policy = alice.grant(bob, label, threshold=threshold, shares=shares, expiration=policy_end_datetime) @@ -81,7 +80,7 @@ def test_alices_powers_are_persistent(ursulas, temp_dir_path, testerchain): # A new Alice is restored from the configuration file new_alice_config = AliceConfiguration.from_configuration_file( filepath=alice_config_file, - network_middleware=MockRestMiddleware(eth_provider_uri=MOCK_ETH_PROVIDER_URI), + network_middleware=MockRestMiddleware(eth_endpoint=MOCK_ETH_PROVIDER_URI), start_learning_now=False, config_root=config_root, known_nodes=ursulas, @@ -98,9 +97,9 @@ def test_alices_powers_are_persistent(ursulas, temp_dir_path, testerchain): # Bob's eldest brother, Roberto, appears too roberto = Bob( domain=TEMPORARY_DOMAIN, - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, start_learning_now=False, - network_middleware=MockRestMiddleware(eth_provider_uri=MOCK_ETH_PROVIDER_URI), + network_middleware=MockRestMiddleware(eth_endpoint=MOCK_ETH_PROVIDER_URI), ) # Alice creates a new policy for Roberto. Note how all the parameters diff --git a/tests/integration/config/test_keystore_integration.py b/tests/integration/config/test_keystore_integration.py index cc085b209..4b7388c61 100644 --- a/tests/integration/config/test_keystore_integration.py +++ b/tests/integration/config/test_keystore_integration.py @@ -74,25 +74,27 @@ def test_characters_use_keystore(temp_dir_path, testerchain): keystore.unlock(password=INSECURE_DEVELOPMENT_PASSWORD) pre_payment_method = SubscriptionManagerPayment( - eth_provider=MOCK_ETH_PROVIDER_URI, network=TEMPORARY_DOMAIN + blockchain_endpoint=MOCK_ETH_PROVIDER_URI, domain=TEMPORARY_DOMAIN ) alice = Alice( start_learning_now=False, keystore=keystore, domain=TEMPORARY_DOMAIN, - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, + polygon_endpoint=MOCK_ETH_PROVIDER_URI, checksum_address=testerchain.alice_account, pre_payment_method=pre_payment_method, ) Bob( - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, start_learning_now=False, keystore=keystore, domain=TEMPORARY_DOMAIN, ) Ursula( - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, + polygon_endpoint=MOCK_ETH_PROVIDER_URI, start_learning_now=False, keystore=keystore, rest_host=LOOPBACK_ADDRESS, @@ -158,7 +160,7 @@ def test_ritualist(temp_dir_path, testerchain, dkg_public_key): keystore.unlock(password=INSECURE_DEVELOPMENT_PASSWORD) pre_payment_method = SubscriptionManagerPayment( - eth_provider=MOCK_ETH_PROVIDER_URI, network=TEMPORARY_DOMAIN + blockchain_endpoint=MOCK_ETH_PROVIDER_URI, domain=TEMPORARY_DOMAIN ) ursula = Ursula( @@ -170,7 +172,8 @@ def test_ritualist(temp_dir_path, testerchain, dkg_public_key): pre_payment_method=pre_payment_method, operator_address=testerchain.ursulas_accounts[0], signer=Web3Signer(testerchain.client), - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, + polygon_endpoint=MOCK_ETH_PROVIDER_URI, ) ritual_id = 23 diff --git a/tests/integration/config/test_storages.py b/tests/integration/config/test_storages.py index c5dc4387f..cea3b0649 100644 --- a/tests/integration/config/test_storages.py +++ b/tests/integration/config/test_storages.py @@ -35,7 +35,7 @@ class BaseTestNodeStorageBackends: assert ursula == node_from_storage, "Node storage {} failed".format(node_storage) pre_payment_method = SubscriptionManagerPayment( - eth_provider=MOCK_ETH_PROVIDER_URI, network=TEMPORARY_DOMAIN + blockchain_endpoint=MOCK_ETH_PROVIDER_URI, domain=TEMPORARY_DOMAIN ) # Save more nodes @@ -46,7 +46,8 @@ class BaseTestNodeStorageBackends: rest_port=select_test_port(), domain=TEMPORARY_DOMAIN, signer=signer, - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, + polygon_endpoint=MOCK_ETH_PROVIDER_URI, checksum_address=operator_addresses[i], operator_address=operator_addresses[i], pre_payment_method=pre_payment_method, diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 0f1199177..36c3fd0c9 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -14,11 +14,14 @@ from nucypher.blockchain.eth.agents import ( TACoChildApplicationAgent, ) from nucypher.blockchain.eth.clients import EthereumClient +from nucypher.blockchain.eth.domains import ( + DomainInfo, + TACoDomain, +) from nucypher.blockchain.eth.interfaces import ( BlockchainInterface, BlockchainInterfaceFactory, ) -from nucypher.blockchain.eth.networks import NetworksInventory from nucypher.blockchain.eth.registry import ( ContractRegistry, ) @@ -35,6 +38,7 @@ from tests.constants import ( MOCK_KEYSTORE_PATH, NUMBER_OF_MOCK_KEYSTORE_ACCOUNTS, TESTERCHAIN_CHAIN_ID, + TESTERCHAIN_CHAIN_INFO, ) from tests.mock.interfaces import MockBlockchain from tests.mock.io import MockStdinWrapper @@ -132,8 +136,8 @@ def mock_interface(module_mocker): @pytest.fixture(scope='module') -def test_registry(): - with mock_registry_sources(): +def test_registry(module_mocker): + with mock_registry_sources(mocker=module_mocker): mock_source = MockRegistrySource(domain=TEMPORARY_DOMAIN) registry = ContractRegistry(source=mock_source) yield registry @@ -278,20 +282,20 @@ def monkeypatch_get_staking_provider_from_operator(monkeymodule): ) -@pytest.fixture(scope="session", autouse=True) -def mock_condition_blockchains(session_mocker): +@pytest.fixture(scope="module", autouse=True) +def mock_condition_blockchains(module_mocker): """adds testerchain's chain ID to permitted conditional chains""" - session_mocker.patch.dict( + module_mocker.patch.dict( "nucypher.policy.conditions.evm._CONDITION_CHAINS", {TESTERCHAIN_CHAIN_ID: "eth-tester/pyevm"}, ) - session_mocker.patch.object( - NetworksInventory, "get_polygon_chain_id", return_value=TESTERCHAIN_CHAIN_ID + test_domain_info = DomainInfo( + TEMPORARY_DOMAIN, TESTERCHAIN_CHAIN_INFO, TESTERCHAIN_CHAIN_INFO ) - session_mocker.patch.object( - NetworksInventory, "get_ethereum_chain_id", return_value=TESTERCHAIN_CHAIN_ID + module_mocker.patch.object( + TACoDomain, "get_domain_info", return_value=test_domain_info ) diff --git a/tests/integration/learning/test_domains.py b/tests/integration/learning/test_domains.py index 1feb69a12..f68a27e6a 100644 --- a/tests/integration/learning/test_domains.py +++ b/tests/integration/learning/test_domains.py @@ -2,46 +2,90 @@ from pathlib import Path import pytest +import tests from nucypher.acumen.perception import FleetSensor +from nucypher.blockchain.eth.registry import ContractRegistry from nucypher.characters.lawful import Ursula from nucypher.config.storages import LocalFileBasedNodeStorage from nucypher.network.nodes import TEACHER_NODES +from tests.utils.registry import MockRegistrySource from tests.utils.ursula import make_ursulas -@pytest.mark.skip -def test_learner_learns_about_domains_separately(lonely_ursula_maker, caplog): - hero_learner, other_first_domain_learner = lonely_ursula_maker( - domain="nucypher1.test_suite", quantity=2 - ) - _nobody = lonely_ursula_maker(domain="nucypher1.test_suite", quantity=1).pop() - other_first_domain_learner.remember_node(_nobody) +@pytest.fixture(scope="module") +def domain_1(): + return "domain_uno" - second_domain_learners = lonely_ursula_maker(domain="nucypher2.test_suite", know_each_other=True, quantity=3) + +@pytest.fixture(scope="module") +def domain_2(): + return "domain_dos" + + +@pytest.fixture(scope="module") +def test_registry(module_mocker, domain_1, domain_2): + with tests.utils.registry.mock_registry_sources( + mocker=module_mocker, domain_names=[domain_1, domain_2] + ): + # doesn't really matter what domain is used here + registry = ContractRegistry(MockRegistrySource(domain=domain_1)) + yield registry + + +@pytest.fixture(scope="module") +def registry_1(domain_1, test_registry): + return ContractRegistry(MockRegistrySource(domain=domain_1)) + + +@pytest.fixture(scope="module") +def registry_2(domain_2, test_registry): + return ContractRegistry(MockRegistrySource(domain=domain_2)) + + +def test_learner_learns_about_domains_separately( + lonely_ursula_maker, domain_1, domain_2, registry_1, registry_2, caplog +): + hero_learner, other_first_domain_learner = lonely_ursula_maker( + domain=domain_1, + registry=registry_1, + quantity=2, + ) + _nobody = lonely_ursula_maker( + domain=domain_1, registry=registry_1, quantity=1 + ).pop() + other_first_domain_learner.remember_node(_nobody, eager=True) + + second_domain_learners = lonely_ursula_maker( + domain=domain_2, registry=registry_2, know_each_other=True, quantity=3 + ) assert len(hero_learner.known_nodes) == 0 # Learn from a teacher in our domain. - hero_learner.remember_node(other_first_domain_learner) + hero_learner.remember_node(other_first_domain_learner, eager=True) hero_learner.start_learning_loop(now=True) - hero_learner.learn_from_teacher_node() + hero_learner.learn_from_teacher_node(eager=True) # All domain 1 nodes assert len(hero_learner.known_nodes) == 2 # Learn about the second domain. hero_learner._current_teacher_node = second_domain_learners.pop() - hero_learner.learn_from_teacher_node() + hero_learner.learn_from_teacher_node(eager=True) # All domain 1 nodes assert len(hero_learner.known_nodes) == 2 - new_first_domain_learner = lonely_ursula_maker(domain="nucypher1.test_suite", quantity=1).pop() - _new_second_domain_learner = lonely_ursula_maker(domain="nucypher2.test_suite", quantity=1).pop() + new_first_domain_learner = lonely_ursula_maker( + domain=domain_1, registry=registry_1, quantity=1 + ).pop() + _new_second_domain_learner = lonely_ursula_maker( + domain=domain_2, registry=registry_2, quantity=1 + ).pop() - new_first_domain_learner.remember_node(hero_learner) + new_first_domain_learner.remember_node(hero_learner, eager=True) - new_first_domain_learner.learn_from_teacher_node() + new_first_domain_learner.learn_from_teacher_node(eager=True) # This node, in the first domain, didn't learn about the second domain. assert not set(second_domain_learners).intersection(new_first_domain_learner.known_nodes) @@ -52,8 +96,9 @@ def test_learner_learns_about_domains_separately(lonely_ursula_maker, caplog): assert _nobody in new_first_domain_learner.known_nodes -@pytest.mark.skip -def test_learner_restores_metadata_from_storage(lonely_ursula_maker, tmpdir): +def test_learner_restores_metadata_from_storage( + lonely_ursula_maker, tmpdir, domain_1, domain_2 +): # Create a local file-based node storage root = tmpdir.mkdir("known_nodes") metadata = root.mkdir("metadata") @@ -63,20 +108,24 @@ def test_learner_restores_metadata_from_storage(lonely_ursula_maker, tmpdir): storage_root=Path(root)) # Use the ursula maker with this storage so it's populated with nodes from one domain - _some_ursulas = lonely_ursula_maker(domain="fistro", - node_storage=old_storage, - know_each_other=True, - quantity=3, - save_metadata=True) + _some_ursulas = lonely_ursula_maker( + domain=domain_1, + node_storage=old_storage, + know_each_other=True, + quantity=3, + save_metadata=True, + ) # Create a pair of new learners in a different domain, using the previous storage, and learn from it - new_learners = lonely_ursula_maker(domain="duodenal", - node_storage=old_storage, - quantity=2, - know_each_other=True, - save_metadata=False) + new_learners = lonely_ursula_maker( + domain=domain_2, + node_storage=old_storage, + quantity=2, + know_each_other=True, + save_metadata=False, + ) learner, buddy = new_learners - buddy._Learner__known_nodes = FleetSensor(domain="fistro") + buddy._Learner__known_nodes = FleetSensor(domain=domain_1) # The learner shouldn't learn about any node from the first domain, since it's different. learner.learn_from_teacher_node() @@ -88,13 +137,20 @@ def test_learner_restores_metadata_from_storage(lonely_ursula_maker, tmpdir): assert set(learner.known_nodes) == {buddy} -@pytest.mark.skip def test_learner_ignores_stored_nodes_from_other_domains( - lonely_ursula_maker, tmpdir, testerchain, ursula_test_config + lonely_ursula_maker, + domain_1, + domain_2, + registry_1, + registry_2, + tmpdir, + testerchain, + ursula_test_config, ): learner, other_staker = make_ursulas( ursula_test_config, - domain="call-it-mainnet", + domain=domain_1, + registry=registry_1, quantity=2, know_each_other=True, staking_provider_addresses=testerchain.stake_providers_accounts[:2], @@ -103,7 +159,8 @@ def test_learner_ignores_stored_nodes_from_other_domains( pest, *other_ursulas_from_the_wrong_side_of_the_tracks = make_ursulas( ursula_test_config, - domain="i-dunno-testt-maybe", + domain=domain_2, + registry=registry_2, quantity=5, know_each_other=True, staking_provider_addresses=testerchain.stake_providers_accounts[2:], @@ -131,26 +188,33 @@ def test_learner_ignores_stored_nodes_from_other_domains( assert pest not in other_staker.known_nodes # But not anymore. -@pytest.mark.skip -def test_learner_with_empty_storage_uses_fallback_nodes(lonely_ursula_maker, mocker): - domain = "learner-domain" - mocker.patch.dict(TEACHER_NODES, {domain: ("teacher-uri",)}, clear=True) +def test_learner_with_empty_storage_uses_fallback_nodes( + lonely_ursula_maker, domain_1, mocker +): + mocker.patch.dict(TEACHER_NODES, {domain_1: ("teacher-uri",)}, clear=True) # Create a learner and a teacher - learner, teacher = lonely_ursula_maker(domain=domain, quantity=2, save_metadata=False) - mocker.patch.object(Ursula, 'from_teacher_uri', return_value=teacher) + learner, teacher = lonely_ursula_maker( + domain=domain_1, quantity=2, save_metadata=False + ) + mocker.patch.object(Ursula, "from_teacher_uri", return_value=teacher) # Since there are no nodes in local node storage, the learner should only learn about the teacher learner.learn_from_teacher_node() assert set(learner.known_nodes) == {teacher} -@pytest.mark.skip def test_learner_uses_both_nodes_from_storage_and_fallback_nodes( - lonely_ursula_maker, tmpdir, mocker, test_registry, ursula_test_config, testerchain + lonely_ursula_maker, + domain_1, + registry_1, + tmpdir, + mocker, + test_registry, + ursula_test_config, + testerchain, ): - domain = "learner-domain" - mocker.patch.dict(TEACHER_NODES, {domain: ("teacher-uri",)}, clear=True) + mocker.patch.dict(TEACHER_NODES, {domain_1: ("teacher-uri",)}, clear=True) # Create a local file-based node storage root = tmpdir.mkdir("known_nodes") @@ -163,7 +227,8 @@ def test_learner_uses_both_nodes_from_storage_and_fallback_nodes( # Create some nodes and persist them to local storage other_nodes = make_ursulas( ursula_test_config, - domain=domain, + domain=domain_1, + registry=registry_1, node_storage=node_storage, know_each_other=True, quantity=3, @@ -174,7 +239,8 @@ def test_learner_uses_both_nodes_from_storage_and_fallback_nodes( # Create a teacher and a learner using existing node storage learner, teacher = lonely_ursula_maker( - domain=domain, + domain=domain_1, + registry=registry_1, node_storage=node_storage, quantity=2, know_each_other=True, diff --git a/tests/integration/learning/test_firstula_circumstances.py b/tests/integration/learning/test_firstula_circumstances.py index 5d17affac..a0de34de2 100644 --- a/tests/integration/learning/test_firstula_circumstances.py +++ b/tests/integration/learning/test_firstula_circumstances.py @@ -3,15 +3,18 @@ from functools import partial import pytest_twisted as pt from twisted.internet.threads import deferToThread +from nucypher.config.constants import TEMPORARY_DOMAIN from nucypher.network.middleware import RestMiddleware from tests.constants import MOCK_ETH_PROVIDER_URI def test_proper_seed_node_instantiation(lonely_ursula_maker): _lonely_ursula_maker = partial(lonely_ursula_maker, quantity=1) - firstula = _lonely_ursula_maker(domain="this-is-meaningful-now").pop() + firstula = _lonely_ursula_maker(domain=TEMPORARY_DOMAIN).pop() firstula_as_seed_node = firstula.seed_node_metadata() - any_other_ursula = _lonely_ursula_maker(seed_nodes=[firstula_as_seed_node], domain="this-is-meaningful-now").pop() + any_other_ursula = _lonely_ursula_maker( + seed_nodes=[firstula_as_seed_node], domain=TEMPORARY_DOMAIN + ).pop() assert not any_other_ursula.known_nodes any_other_ursula.start_learning_loop(now=True) @@ -33,7 +36,7 @@ def test_get_cert_from_running_seed_node(lonely_ursula_maker): firstula_as_seed_node = firstula.seed_node_metadata() any_other_ursula = lonely_ursula_maker( seed_nodes=[firstula_as_seed_node], - network_middleware=RestMiddleware(eth_provider_uri=MOCK_ETH_PROVIDER_URI), + network_middleware=RestMiddleware(eth_endpoint=MOCK_ETH_PROVIDER_URI), ).pop() assert not any_other_ursula.known_nodes diff --git a/tests/integration/network/test_failure_modes.py b/tests/integration/network/test_failure_modes.py index bf6fc91cd..0957e3bea 100644 --- a/tests/integration/network/test_failure_modes.py +++ b/tests/integration/network/test_failure_modes.py @@ -20,9 +20,7 @@ def test_alice_can_grant_even_when_the_first_nodes_she_tries_are_down( label = b"this_is_the_path_to_which_access_is_being_granted" alice.known_nodes.current_state._nodes = {} - alice.network_middleware = NodeIsDownMiddleware( - eth_provider_uri=MOCK_ETH_PROVIDER_URI - ) + alice.network_middleware = NodeIsDownMiddleware(eth_endpoint=MOCK_ETH_PROVIDER_URI) # OK, her first and only node is down. down_node = list(ursulas)[0] @@ -78,9 +76,7 @@ def test_alice_can_grant_even_when_the_first_nodes_she_tries_are_down( def test_node_has_changed_cert(alice, ursulas): alice.known_nodes.current_state._nodes = {} - alice.network_middleware = NodeIsDownMiddleware( - eth_provider_uri=MOCK_ETH_PROVIDER_URI - ) + alice.network_middleware = NodeIsDownMiddleware(eth_endpoint=MOCK_ETH_PROVIDER_URI) alice.network_middleware.client.certs_are_broken = True firstula = list(ursulas)[0] diff --git a/tests/integration/network/test_network_actors.py b/tests/integration/network/test_network_actors.py index 8ab399f63..1c15f5ff3 100644 --- a/tests/integration/network/test_network_actors.py +++ b/tests/integration/network/test_network_actors.py @@ -67,7 +67,7 @@ def test_vladimir_illegal_interface_key_does_not_propagate(ursulas): # This Ursula is totally legit... ursula_whom_vladimir_will_imitate.verify_node( - MockRestMiddleware(eth_provider_uri=MOCK_ETH_PROVIDER_URI) + MockRestMiddleware(eth_endpoint=MOCK_ETH_PROVIDER_URI) ) globalLogPublisher.addObserver(warning_trapper) diff --git a/tests/integration/utilities/test_integration_concurrency.py b/tests/integration/utilities/test_integration_concurrency.py index 30bdea6d5..3eea06dbe 100644 --- a/tests/integration/utilities/test_integration_concurrency.py +++ b/tests/integration/utilities/test_integration_concurrency.py @@ -232,7 +232,7 @@ def test_join(join_worker_pool): assert t_end - t_start < 3 -class TestBatchValueFactory(BatchValueFactory): +class BatchTrackingBatchValueFactory(BatchValueFactory): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.batch_sizes = [] @@ -258,7 +258,9 @@ def test_batched_value_generation(join_worker_pool): seed=123, ) - factory = TestBatchValueFactory(values=list(outcomes), required_successes=10) + factory = BatchTrackingBatchValueFactory( + values=list(outcomes), required_successes=10 + ) pool = WorkerPool( worker, factory, diff --git a/tests/integration/utilities/test_prometheus_collectors.py b/tests/integration/utilities/test_prometheus_collectors.py index 7d530898f..0292edaf3 100644 --- a/tests/integration/utilities/test_prometheus_collectors.py +++ b/tests/integration/utilities/test_prometheus_collectors.py @@ -70,7 +70,7 @@ def test_ursula_info_metrics_collector(test_registry, ursulas): @pytest.mark.skipif(condition=(not PROMETHEUS_INSTALLED), reason="prometheus_client is required for test") def test_blockchain_metrics_collector(testerchain): - collector = BlockchainMetricsCollector(eth_provider_uri=MOCK_ETH_PROVIDER_URI) + collector = BlockchainMetricsCollector(eth_endpoint=MOCK_ETH_PROVIDER_URI) collector_registry = CollectorRegistry() prefix = 'test_blockchain_metrics_collector' @@ -96,7 +96,7 @@ def test_staking_provider_metrics_collector(test_registry, staking_providers): collector = StakingProviderMetricsCollector( staking_provider_address=staking_provider_address, contract_registry=test_registry, - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, ) collector_registry = CollectorRegistry() prefix = "test_staking_provider_metrics_collector" diff --git a/tests/metrics/grant_availability.py b/tests/metrics/grant_availability.py index 27bc32b65..09ec11af5 100755 --- a/tests/metrics/grant_availability.py +++ b/tests/metrics/grant_availability.py @@ -22,6 +22,7 @@ from nucypher_core.umbral import SecretKey from web3 import Web3 from web3.types import Wei +from nucypher.blockchain.eth.domains import LYNX from nucypher.blockchain.eth.signers import Signer from nucypher.characters.lawful import Alice, Bob, Ursula from nucypher.config.characters import AliceConfiguration @@ -53,9 +54,9 @@ except KeyError: raise RuntimeError(message) # Alice Configuration -DOMAIN: str = 'mainnet' # tapir +TACO_DOMAIN: str = LYNX.name # mainnet DEFAULT_SEEDNODE_URIS: List[str] = [ - *TEACHER_NODES[DOMAIN], + *TEACHER_NODES[TACO_DOMAIN], ] INSECURE_PASSWORD: str = "METRICS_INSECURE_DEVELOPMENT_PASSWORD" TEMP_ALICE_DIR: Path = Path('/', 'tmp', 'grant-metrics') @@ -154,19 +155,19 @@ def make_alice(known_nodes: Optional[Set[Ursula]] = None): # This is Alice's PRE payment method. pre_payment_method = SubscriptionManagerPayment( - network='polygon', - eth_provider=POLYGON_PROVIDER_URI + domain=TACO_DOMAIN, blockchain_endpoint=POLYGON_PROVIDER_URI ) wallet = Signer.from_signer_uri(f'keystore://{SIGNER_URI}') wallet.unlock_account(account=ALICE_ADDRESS, password=SIGNER_PASSWORD) alice_config = AliceConfiguration( - eth_provider_uri=ETHEREUM_PROVIDER_URI, + eth_endpoint=ETHEREUM_PROVIDER_URI, + polygon_endpoint=POLYGON_PROVIDER_URI, checksum_address=ALICE_ADDRESS, signer_uri=f'keystore://{SIGNER_URI}', config_root=TEMP_ALICE_DIR, - domain=DOMAIN, + domain=TACO_DOMAIN, known_nodes=known_nodes, start_learning_now=False, learn_on_same_thread=True, @@ -189,14 +190,14 @@ def setup(): GlobalLoggerSettings.set_log_level('info') -def aggregate_nodes(provider_uri: str) -> Tuple[Set[Ursula], Set[Ursula]]: +def aggregate_nodes(eth_endpoint: str) -> Tuple[Set[Ursula], Set[Ursula]]: """generates ursulas from URIs used in grant metrics collection""" seednodes = set() if DEFAULT_SEEDNODE_URIS: for uri in DEFAULT_SEEDNODE_URIS: ursula = Ursula.from_seed_and_stake_info( - seed_uri=uri, provider_uri=provider_uri + seed_uri=uri, eth_endpoint=eth_endpoint ) seednodes.add(ursula) @@ -204,7 +205,7 @@ def aggregate_nodes(provider_uri: str) -> Tuple[Set[Ursula], Set[Ursula]]: if HANDPICKED_URSULA_URIS: for uri in HANDPICKED_URSULA_URIS: ursula = Ursula.from_seed_and_stake_info( - seed_uri=uri, provider_uri=provider_uri + seed_uri=uri, eth_endpoint=eth_endpoint ) ursulas.add(ursula) @@ -213,6 +214,6 @@ def aggregate_nodes(provider_uri: str) -> Tuple[Set[Ursula], Set[Ursula]]: if __name__ == '__main__': setup() - seednodes, ursulas = aggregate_nodes(provider_uri=ETHEREUM_PROVIDER_URI) + seednodes, ursulas = aggregate_nodes(eth_endpoint=ETHEREUM_PROVIDER_URI) alice = make_alice(known_nodes=seednodes) collect(alice=alice, ursulas=ursulas) diff --git a/tests/mock/interfaces.py b/tests/mock/interfaces.py index 6d57eaa47..5bad91b1d 100644 --- a/tests/mock/interfaces.py +++ b/tests/mock/interfaces.py @@ -1,6 +1,3 @@ - - - from typing import Union from hexbytes import HexBytes diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index 93be27e83..9512dd702 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -18,8 +18,8 @@ def pytest_addhooks(pluginmanager): @pytest.fixture(scope='module') -def test_registry(): - with mock_registry_sources(): +def test_registry(module_mocker): + with mock_registry_sources(mocker=module_mocker): source = MockRegistrySource(domain=TEMPORARY_DOMAIN) yield ContractRegistry(source=source) diff --git a/tests/unit/test_character_sign_and_verify.py b/tests/unit/test_character_sign_and_verify.py index eedc4f897..61be5cfe2 100644 --- a/tests/unit/test_character_sign_and_verify.py +++ b/tests/unit/test_character_sign_and_verify.py @@ -22,7 +22,7 @@ def test_actor_without_signing_power_cannot_sign(): crypto_power=cannot_sign, start_learning_now=False, domain=TEMPORARY_DOMAIN, - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, ) # The non-signer's stamp doesn't work for signing... @@ -47,7 +47,7 @@ def test_actor_with_signing_power_can_sign(): is_me=True, start_learning_now=False, domain=TEMPORARY_DOMAIN, - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, ) stamp_of_the_signer = signer.stamp @@ -73,14 +73,14 @@ def test_anybody_can_verify(random_address): domain=TEMPORARY_DOMAIN, checksum_address=random_address, pre_payment_method=FreeReencryptions(), - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, ) # So, our story is fairly simple: an everyman meets Alice. somebody = Character( start_learning_now=False, domain=TEMPORARY_DOMAIN, - eth_provider_uri=MOCK_ETH_PROVIDER_URI, + eth_endpoint=MOCK_ETH_PROVIDER_URI, ) # Alice signs a message. diff --git a/tests/unit/test_external_ip_utilities.py b/tests/unit/test_external_ip_utilities.py index aba0b4894..dc33f79f5 100644 --- a/tests/unit/test_external_ip_utilities.py +++ b/tests/unit/test_external_ip_utilities.py @@ -23,7 +23,7 @@ from nucypher.utilities.networking import ( ) from tests.constants import MOCK_ETH_PROVIDER_URI, MOCK_IP_ADDRESS -MOCK_NETWORK = 'holodeck' +MOCK_DOMAIN = "holodeck" MOCK_PORT = 1111 @@ -33,7 +33,7 @@ class Dummy: # Teacher self.canonical_address = canonical_address self.checksum_address = to_checksum_address(canonical_address) self.certificate_filepath = None - self.domain = MOCK_NETWORK + self.domain = MOCK_DOMAIN class GoodResponse: status_code = 200 @@ -96,7 +96,7 @@ def mock_client(mocker): @pytest.fixture(autouse=True) def mock_default_teachers(mocker): - teachers = {MOCK_NETWORK: (f"{MOCK_IP_ADDRESS}:{MOCK_PORT}", )} + teachers = {MOCK_DOMAIN: (f"{MOCK_IP_ADDRESS}:{MOCK_PORT}",)} mocker.patch.dict(TEACHER_NODES, teachers, clear=True) @@ -106,22 +106,22 @@ def test_get_external_ip_from_centralized_source(mock_requests): def test_get_external_ip_from_empty_known_nodes(mock_requests): - sensor = FleetSensor(domain=MOCK_NETWORK) + sensor = FleetSensor(domain=MOCK_DOMAIN) assert len(sensor) == 0 get_external_ip_from_known_nodes( - known_nodes=sensor, provider_uri=MOCK_ETH_PROVIDER_URI + known_nodes=sensor, eth_endpoint=MOCK_ETH_PROVIDER_URI ) # skipped because there are no known nodes mock_requests.assert_not_called() def test_get_external_ip_from_known_nodes_with_one_known_node(mock_requests): - sensor = FleetSensor(domain=MOCK_NETWORK) + sensor = FleetSensor(domain=MOCK_DOMAIN) sensor.record_node(Dummy(b'deadbeefdeadbeefdead')) sensor.record_fleet_state() assert len(sensor) == 1 get_external_ip_from_known_nodes( - known_nodes=sensor, provider_uri=MOCK_ETH_PROVIDER_URI + known_nodes=sensor, eth_endpoint=MOCK_ETH_PROVIDER_URI ) # skipped because there are too few known nodes mock_requests.assert_not_called() @@ -130,7 +130,7 @@ def test_get_external_ip_from_known_nodes_with_one_known_node(mock_requests): def test_get_external_ip_from_known_nodes(mock_client): # Setup FleetSensor - sensor = FleetSensor(domain=MOCK_NETWORK) + sensor = FleetSensor(domain=MOCK_DOMAIN) sample_size = 3 sensor.record_node(Dummy(b'deadbeefdeadbeefdead')) sensor.record_node(Dummy(b'deadllamadeadllamade')) @@ -140,7 +140,7 @@ def test_get_external_ip_from_known_nodes(mock_client): # First sampled node replies get_external_ip_from_known_nodes( - known_nodes=sensor, sample_size=sample_size, provider_uri=MOCK_ETH_PROVIDER_URI + known_nodes=sensor, sample_size=sample_size, eth_endpoint=MOCK_ETH_PROVIDER_URI ) assert mock_client.call_count == 1 mock_client.call_count = 0 # reset @@ -148,7 +148,7 @@ def test_get_external_ip_from_known_nodes(mock_client): # All sampled nodes dont respond mock_client.return_value = Dummy.BadResponse get_external_ip_from_known_nodes( - known_nodes=sensor, sample_size=sample_size, provider_uri=MOCK_ETH_PROVIDER_URI + known_nodes=sensor, sample_size=sample_size, eth_endpoint=MOCK_ETH_PROVIDER_URI ) assert mock_client.call_count == sample_size @@ -156,7 +156,7 @@ def test_get_external_ip_from_known_nodes(mock_client): def test_get_external_ip_from_known_nodes_client(mocker, mock_client): # Setup FleetSensor - sensor = FleetSensor(domain=MOCK_NETWORK) + sensor = FleetSensor(domain=MOCK_DOMAIN) sample_size = 3 sensor.record_node(Dummy(b'deadbeefdeadbeefdead')) sensor.record_node(Dummy(b'deadllamadeadllamade')) @@ -166,10 +166,10 @@ def test_get_external_ip_from_known_nodes_client(mocker, mock_client): # Setup HTTP Client mocker.patch.object(Ursula, 'from_teacher_uri', return_value=Dummy(b'deadporkdeadporkdead')) - teacher_uri = TEACHER_NODES[MOCK_NETWORK][0] + teacher_uri = TEACHER_NODES[MOCK_DOMAIN][0] get_external_ip_from_known_nodes( - known_nodes=sensor, sample_size=sample_size, provider_uri=MOCK_ETH_PROVIDER_URI + known_nodes=sensor, sample_size=sample_size, eth_endpoint=MOCK_ETH_PROVIDER_URI ) assert mock_client.call_count == 1 # first node responded @@ -183,7 +183,7 @@ def test_get_external_ip_default_teacher_unreachable(mocker): # Default seednode is down mocker.patch.object(Ursula, "from_teacher_uri", side_effect=error) ip = get_external_ip_from_default_teacher( - network=MOCK_NETWORK, provider_uri=MOCK_ETH_PROVIDER_URI + domain=MOCK_DOMAIN, eth_endpoint=MOCK_ETH_PROVIDER_URI ) assert ip is None @@ -191,12 +191,12 @@ def test_get_external_ip_default_teacher_unreachable(mocker): def test_get_external_ip_from_default_teacher(mocker, mock_client, mock_requests): mock_client.return_value = Dummy.GoodResponse - teacher_uri = TEACHER_NODES[MOCK_NETWORK][0] + teacher_uri = TEACHER_NODES[MOCK_DOMAIN][0] mocker.patch.object(Ursula, 'from_teacher_uri', return_value=Dummy(b'deadbeefdeadbeefdead')) # "Success" ip = get_external_ip_from_default_teacher( - network=MOCK_NETWORK, provider_uri=MOCK_ETH_PROVIDER_URI + domain=MOCK_DOMAIN, eth_endpoint=MOCK_ETH_PROVIDER_URI ) assert ip == MOCK_IP_ADDRESS @@ -208,13 +208,13 @@ def test_get_external_ip_from_default_teacher(mocker, mock_client, mock_requests assert endpoint == f'https://{teacher_uri}/ping' -def test_get_external_ip_default_unknown_network(): +def test_get_external_ip_default_unknown_domain(): unknown_domain = 'thisisnotarealdomain' # Without fleet sensor with pytest.raises(UnknownIPAddress): determine_external_ip_address( - network=unknown_domain, provider_uri=MOCK_ETH_PROVIDER_URI + domain=unknown_domain, eth_endpoint=MOCK_ETH_PROVIDER_URI ) # with fleet sensor @@ -222,8 +222,8 @@ def test_get_external_ip_default_unknown_network(): with pytest.raises(UnknownIPAddress): determine_external_ip_address( known_nodes=sensor, - network=unknown_domain, - provider_uri=MOCK_ETH_PROVIDER_URI, + domain=unknown_domain, + eth_endpoint=MOCK_ETH_PROVIDER_URI, ) @@ -232,13 +232,13 @@ def test_get_external_ip_cascade_failure(mocker, mock_requests): second = mocker.patch('nucypher.utilities.networking.get_external_ip_from_default_teacher', return_value=None) third = mocker.patch('nucypher.utilities.networking.get_external_ip_from_centralized_source', return_value=None) - sensor = FleetSensor(domain=MOCK_NETWORK) + sensor = FleetSensor(domain=MOCK_DOMAIN) sensor.record_node(Dummy(b'deadbeefdeadbeefdead')) sensor.record_fleet_state() with pytest.raises(UnknownIPAddress, match="External IP address detection failed"): determine_external_ip_address( - network=MOCK_NETWORK, known_nodes=sensor, provider_uri=MOCK_ETH_PROVIDER_URI + domain=MOCK_DOMAIN, known_nodes=sensor, eth_endpoint=MOCK_ETH_PROVIDER_URI ) first.assert_called_once() diff --git a/tests/unit/test_ritualist.py b/tests/unit/test_ritualist.py index 51b74e46e..7e749fc5a 100644 --- a/tests/unit/test_ritualist.py +++ b/tests/unit/test_ritualist.py @@ -10,7 +10,7 @@ from tests.mock.coordinator import MockCoordinatorAgent @pytest.fixture(scope="module") def agent(mock_contract_agency) -> MockCoordinatorAgent: coordinator_agent: CoordinatorAgent = mock_contract_agency.get_agent( - CoordinatorAgent, registry=None, provider_uri=MOCK_ETH_PROVIDER_URI + CoordinatorAgent, registry=None, blockchain_endpoint=MOCK_ETH_PROVIDER_URI ) return coordinator_agent diff --git a/tests/unit/test_taco_domains.py b/tests/unit/test_taco_domains.py new file mode 100644 index 000000000..ffcde6f02 --- /dev/null +++ b/tests/unit/test_taco_domains.py @@ -0,0 +1,86 @@ +import pytest + +from nucypher.blockchain.eth.domains import ( + EthChain, + PolygonChain, + TACoDomain, +) + + +@pytest.fixture(scope="module") +def test_registry(module_mocker): + # override fixture which mocks SUPPORTED_DOMAIN_NAMES + yield + + +@pytest.fixture(scope="module", autouse=True) +def mock_condition_blockchains(module_mocker): + # override fixture which mocks get_domain_info + yield + + +@pytest.mark.parametrize( + "eth_chain_test", + ( + (EthChain.MAINNET, "mainnet", 1), + (EthChain.GOERLI, "goerli", 5), + (EthChain.SEPOLIA, "sepolia", 11155111), + ), +) +def test_eth_chains(eth_chain_test): + eth_chain, expected_name, expected_id = eth_chain_test + assert eth_chain.name == expected_name + assert eth_chain.id == expected_id + + +@pytest.mark.parametrize( + "poly_chain_test", + ( + (PolygonChain.MAINNET, "polygon", 137), + (PolygonChain.MUMBAI, "mumbai", 80001), + ), +) +def test_polygon_chains(poly_chain_test): + eth_chain, expected_name, expected_id = poly_chain_test + assert eth_chain.name == expected_name + assert eth_chain.id == expected_id + + +@pytest.mark.parametrize( + "taco_domain_test", + ( + (TACoDomain.MAINNET, "mainnet", EthChain.MAINNET, PolygonChain.MAINNET), + (TACoDomain.LYNX, "lynx", EthChain.GOERLI, PolygonChain.MUMBAI), + (TACoDomain.TAPIR, "tapir", EthChain.SEPOLIA, PolygonChain.MUMBAI), + ), +) +def test_taco_domain_info(taco_domain_test): + ( + domain_info, + expected_name, + expected_eth_chain, + expected_polygon_chain, + ) = taco_domain_test + assert domain_info.name == expected_name + assert domain_info.eth_chain == expected_eth_chain + assert domain_info.polygon_chain == expected_polygon_chain + + assert domain_info.is_testnet == (expected_name != "mainnet") + + +@pytest.mark.parametrize( + "domain_name_test", + ( + ("mainnet", TACoDomain.MAINNET), + ("lynx", TACoDomain.LYNX), + ("tapir", TACoDomain.TAPIR), + ), +) +def test_get_domain_info(domain_name_test): + domain_name, expected_domain_info = domain_name_test + assert TACoDomain.get_domain_info(domain_name) == expected_domain_info + + +def test_get_domain_info_unrecognized_domain_name(): + with pytest.raises(TACoDomain.Unrecognized): + TACoDomain.get_domain_info(domain="5am_In_Toronto") diff --git a/tests/unit/test_teacher_nodes.py b/tests/unit/test_teacher_nodes.py new file mode 100644 index 000000000..ff532d5ae --- /dev/null +++ b/tests/unit/test_teacher_nodes.py @@ -0,0 +1,22 @@ +import pytest + +from nucypher.blockchain.eth.domains import TACoDomain +from nucypher.network.nodes import TEACHER_NODES + + +@pytest.fixture(autouse=True) +def mock_teacher_nodes(mocker): + # override fixture which mocks TEACHER_NODES + yield + + +@pytest.fixture(scope="module") +def test_registry(module_mocker): + # override fixture which mocks SUPPORTED_DOMAIN_NAMES + yield + + +def test_default_teacher_seednodes_defined(): + for domain in TACoDomain.SUPPORTED_DOMAIN_NAMES: + teacher_nodes = TEACHER_NODES[domain] + assert len(teacher_nodes) > 0 diff --git a/tests/unit/test_web3_clients.py b/tests/unit/test_web3_clients.py index fe71cb953..a3e9a2ff6 100644 --- a/tests/unit/test_web3_clients.py +++ b/tests/unit/test_web3_clients.py @@ -1,13 +1,18 @@ import datetime -from unittest.mock import PropertyMock, Mock +from unittest.mock import Mock, PropertyMock import pytest from web3 import HTTPProvider, IPCProvider, WebsocketProvider -from nucypher.blockchain.eth.clients import (GanacheClient, GethClient, InfuraClient, PUBLIC_CHAINS, - ParityClient, AlchemyClient) +from nucypher.blockchain.eth.clients import ( + AlchemyClient, + GanacheClient, + GethClient, + InfuraClient, + ParityClient, +) from nucypher.blockchain.eth.interfaces import BlockchainInterface from nucypher.utilities.networking import LOOPBACK_ADDRESS @@ -139,53 +144,53 @@ class ProviderTypeTestClient(BlockchainInterfaceTestBase): self.expected_provider_class = expected_provider_class self.test_provider_to_attach = actual_provider_to_attach - def _attach_eth_provider(self, *args, **kwargs) -> None: - super()._attach_eth_provider(*args, **kwargs) + def _attach_blockchain_provider(self, *args, **kwargs) -> None: + super()._attach_blockchain_provider(*args, **kwargs) # check type assert isinstance(self.provider, self.expected_provider_class) - super()._attach_eth_provider(eth_provider=self.test_provider_to_attach) + super()._attach_blockchain_provider(provider=self.test_provider_to_attach) class InfuraTestClient(BlockchainInterfaceTestBase): - def _attach_eth_provider(self, *args, **kwargs) -> None: - super()._attach_eth_provider(eth_provider=MockInfuraProvider()) + def _attach_blockchain_provider(self, *args, **kwargs) -> None: + super()._attach_blockchain_provider(provider=MockInfuraProvider()) class AlchemyTestClient(BlockchainInterfaceTestBase): - def _attach_eth_provider(self, *args, **kwargs) -> None: - super()._attach_eth_provider(eth_provider=MockAlchemyProvider()) + def _attach_blockchain_provider(self, *args, **kwargs) -> None: + super()._attach_blockchain_provider(provider=MockAlchemyProvider()) class GethClientTestBlockchain(BlockchainInterfaceTestBase): - def _attach_eth_provider(self, *args, **kwargs) -> None: - super()._attach_eth_provider(eth_provider=MockGethProvider()) + def _attach_blockchain_provider(self, *args, **kwargs) -> None: + super()._attach_blockchain_provider(provider=MockGethProvider()) class ParityClientTestInterface(BlockchainInterfaceTestBase): - def _attach_eth_provider(self, *args, **kwargs) -> None: - super()._attach_eth_provider(eth_provider=MockParityProvider()) + def _attach_blockchain_provider(self, *args, **kwargs) -> None: + super()._attach_blockchain_provider(provider=MockParityProvider()) class GanacheClientTestInterface(BlockchainInterfaceTestBase): - def _attach_eth_provider(self, *args, **kwargs) -> None: - super()._attach_eth_provider(eth_provider=MockGanacheProvider()) + def _attach_blockchain_provider(self, *args, **kwargs) -> None: + super()._attach_blockchain_provider(provider=MockGanacheProvider()) def test_client_no_provider(): - with pytest.raises(BlockchainInterface.NoProvider) as e: + with pytest.raises(BlockchainInterface.NoProvider): interface = BlockchainInterfaceTestBase() interface.connect() def test_geth_web3_client(): - interface = GethClientTestBlockchain(eth_provider_uri='file:///ipc.geth') + interface = GethClientTestBlockchain(endpoint="file:///ipc.geth") interface.connect() assert isinstance(interface.client, GethClient) @@ -199,62 +204,75 @@ def test_geth_web3_client(): def test_autodetect_provider_type_file(tempfile_path): - - interface = ProviderTypeTestClient(eth_provider_uri=str(tempfile_path), # existing file for test - expected_provider_class=IPCProvider, - actual_provider_to_attach=MockGethProvider()) + interface = ProviderTypeTestClient( + endpoint=str(tempfile_path), # existing file for test + expected_provider_class=IPCProvider, + actual_provider_to_attach=MockGethProvider(), + ) interface.connect() assert isinstance(interface.client, GethClient) def test_autodetect_provider_type_file_none_existent(): - with pytest.raises(BlockchainInterface.UnsupportedProvider) as e: - interface = BlockchainInterfaceTestBase(eth_provider_uri='/none_existent.ipc.geth') + with pytest.raises(BlockchainInterface.UnsupportedProvider): + interface = BlockchainInterfaceTestBase(endpoint="/none_existent.ipc.geth") interface.connect() def test_detect_provider_type_file(): - interface = ProviderTypeTestClient(eth_provider_uri='file:///ipc.geth', - expected_provider_class=IPCProvider, - actual_provider_to_attach=MockGethProvider()) + interface = ProviderTypeTestClient( + endpoint="file:///ipc.geth", + expected_provider_class=IPCProvider, + actual_provider_to_attach=MockGethProvider(), + ) interface.connect() assert isinstance(interface.client, GethClient) def test_detect_provider_type_ipc(): - interface = ProviderTypeTestClient(eth_provider_uri='ipc:///ipc.geth', - expected_provider_class=IPCProvider, - actual_provider_to_attach=MockGethProvider()) + interface = ProviderTypeTestClient( + endpoint="ipc:///ipc.geth", + expected_provider_class=IPCProvider, + actual_provider_to_attach=MockGethProvider(), + ) interface.connect() assert isinstance(interface.client, GethClient) def test_detect_provider_type_http(): - interface = ProviderTypeTestClient(eth_provider_uri='http://ganache:8445', - expected_provider_class=HTTPProvider, - actual_provider_to_attach=MockGanacheProvider()) + interface = ProviderTypeTestClient( + endpoint="http://ganache:8445", + expected_provider_class=HTTPProvider, + actual_provider_to_attach=MockGanacheProvider(), + ) interface.connect() assert isinstance(interface.client, GanacheClient) def test_detect_provider_type_https(): - interface = ProviderTypeTestClient(eth_provider_uri='https://ganache:8445', - expected_provider_class=HTTPProvider, - actual_provider_to_attach=MockGanacheProvider()) + interface = ProviderTypeTestClient( + endpoint="https://ganache:8445", + expected_provider_class=HTTPProvider, + actual_provider_to_attach=MockGanacheProvider(), + ) interface.connect() assert isinstance(interface.client, GanacheClient) def test_detect_provider_type_ws(): - interface = ProviderTypeTestClient(eth_provider_uri=f'ws://{LOOPBACK_ADDRESS}:8546', - expected_provider_class=WebsocketProvider, - actual_provider_to_attach=MockWebSocketProvider()) + interface = ProviderTypeTestClient( + endpoint=f"ws://{LOOPBACK_ADDRESS}:8546", + expected_provider_class=WebsocketProvider, + actual_provider_to_attach=MockWebSocketProvider(), + ) interface.connect() assert isinstance(interface.client, GethClient) def test_infura_web3_client(): - interface = InfuraTestClient(eth_provider_uri='wss://:@goerli.infura.io/ws/v3/1234567890987654321abcdef') + interface = InfuraTestClient( + endpoint="wss://:@goerli.infura.io/ws/v3/1234567890987654321abcdef" + ) interface.connect() assert isinstance(interface.client, InfuraClient) @@ -270,7 +288,9 @@ def test_infura_web3_client(): def test_alchemy_web3_client(): - interface = AlchemyTestClient(eth_provider_uri='https://eth-rinkeby.alchemyapi.io/v2/1234567890987654321abcdef') + interface = AlchemyTestClient( + endpoint="https://eth-rinkeby.alchemyapi.io/v2/1234567890987654321abcdef" + ) interface.connect() assert isinstance(interface.client, AlchemyClient) @@ -282,7 +302,7 @@ def test_alchemy_web3_client(): def test_parity_web3_client(): - interface = ParityClientTestInterface(eth_provider_uri='file:///ipc.parity') + interface = ParityClientTestInterface(endpoint="file:///ipc.parity") interface.connect() assert isinstance(interface.client, ParityClient) @@ -293,7 +313,7 @@ def test_parity_web3_client(): def test_ganache_web3_client(): - interface = GanacheClientTestInterface(eth_provider_uri='http://ganache:8445') + interface = GanacheClientTestInterface(endpoint="http://ganache:8445") interface.connect() assert isinstance(interface.client, GanacheClient) diff --git a/tests/utils/blockchain.py b/tests/utils/blockchain.py index fb16aa5be..0cf4d807d 100644 --- a/tests/utils/blockchain.py +++ b/tests/utils/blockchain.py @@ -73,18 +73,23 @@ class TesterBlockchain(BlockchainInterface): __OPERATORS_RANGE = range(NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS) __ACCOUNT_CACHE = list() - def __init__(self, - test_accounts: int = NUMBER_OF_ETH_TEST_ACCOUNTS, - poa: bool = True, - light: bool = False, - eth_airdrop: bool = False, - *args, **kwargs): - - EXPECTED_CONFIRMATION_TIME_IN_SECONDS['free'] = 5 # Just some upper-limit - super().__init__(eth_provider_uri=self.ETH_PROVIDER_URI, - poa=poa, - light=light, - *args, **kwargs) + def __init__( + self, + test_accounts: int = NUMBER_OF_ETH_TEST_ACCOUNTS, + poa: bool = True, + light: bool = False, + eth_airdrop: bool = False, + *args, + **kwargs, + ): + EXPECTED_CONFIRMATION_TIME_IN_SECONDS["free"] = 5 # Just some upper-limit + super().__init__( + endpoint=self.ETH_PROVIDER_URI, + poa=poa, + light=light, + *args, + **kwargs, + ) self.log = Logger("test-blockchain") self.connect() diff --git a/tests/utils/config.py b/tests/utils/config.py index b2cc281b8..7ce773337 100644 --- a/tests/utils/config.py +++ b/tests/utils/config.py @@ -25,16 +25,16 @@ TEST_CHARACTER_CONFIG_BASE_PARAMS = dict( def assemble( checksum_address: str = None, - eth_provider_uri: str = None, + eth_endpoint: str = None, test_registry: ContractRegistry = None, known_nodes: List[Ursula] = None, ) -> dict: """Assemble a dictionary of keyword arguments to use when constructing a test configuration.""" # Generate runtime config params runtime_params = dict( - eth_provider_uri=eth_provider_uri, + eth_endpoint=eth_endpoint, registry=test_registry, - network_middleware=MockRestMiddleware(eth_provider_uri=eth_provider_uri), + network_middleware=MockRestMiddleware(eth_endpoint=eth_endpoint), known_nodes=known_nodes, checksum_address=checksum_address, ) @@ -47,30 +47,26 @@ def assemble( def make_ursula_test_configuration( operator_address: ChecksumAddress, rest_port: int = select_test_port(), - pre_payment_provider: str = None, + polygon_endpoint: str = None, **assemble_kwargs ) -> UrsulaConfiguration: test_params = assemble(**assemble_kwargs) ursula_config = UrsulaConfiguration( **test_params, rest_port=rest_port, - pre_payment_provider=pre_payment_provider, - pre_payment_network=TEMPORARY_DOMAIN, + polygon_endpoint=polygon_endpoint, operator_address=operator_address, - policy_registry=test_params["registry"] ) return ursula_config def make_alice_test_configuration( - pre_payment_provider: str = None, **assemble_kwargs + polygon_endpoint: str = None, **assemble_kwargs ) -> AliceConfiguration: test_params = assemble(**assemble_kwargs) config = AliceConfiguration( **test_params, - pre_payment_provider=pre_payment_provider, - pre_payment_network=TEMPORARY_DOMAIN, - policy_registry=test_params["registry"] + polygon_endpoint=polygon_endpoint, ) return config diff --git a/tests/utils/middleware.py b/tests/utils/middleware.py index 9f5146354..e50227eb0 100644 --- a/tests/utils/middleware.py +++ b/tests/utils/middleware.py @@ -5,7 +5,7 @@ from pathlib import Path import requests from flask import Response -from nucypher_core import MetadataRequest, FleetStateChecksum +from nucypher_core import FleetStateChecksum, MetadataRequest from nucypher.characters.lawful import Ursula from nucypher.network.middleware import NucypherMiddlewareClient, RestMiddleware @@ -143,7 +143,7 @@ class NodeIsDownMiddleware(MockRestMiddleware): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.client = _MiddlewareClientWithConnectionProblems( - eth_provider_uri=TEST_ETH_PROVIDER_URI + eth_endpoint=TEST_ETH_PROVIDER_URI ) def node_is_down(self, node): diff --git a/tests/utils/registry.py b/tests/utils/registry.py index 44303d541..477b5c115 100644 --- a/tests/utils/registry.py +++ b/tests/utils/registry.py @@ -5,48 +5,54 @@ from typing import List from ape.contracts import ContractInstance from eth_utils import to_checksum_address -from nucypher.blockchain.eth.networks import NetworksInventory +from nucypher.blockchain.eth.domains import ( + DomainInfo, + TACoDomain, +) from nucypher.blockchain.eth.registry import ( RegistryData, RegistrySource, RegistrySourceManager, ) from nucypher.config.constants import TEMPORARY_DOMAIN +from tests.constants import TESTERCHAIN_CHAIN_INFO @contextmanager -def mock_registry_sources(): - # capture the real values - real_networks = NetworksInventory.NETWORKS - real_eth_networks = NetworksInventory.ETH_NETWORKS - real_poly_networks = NetworksInventory.POLY_NETWORKS - real_registry_sources = RegistrySourceManager._FALLBACK_CHAIN +def mock_registry_sources(mocker, domain_names: List[str] = None): + if not domain_names: + domain_names = [TEMPORARY_DOMAIN] - # set the mock values - RegistrySourceManager._FALLBACK_CHAIN = (MockRegistrySource,) - NetworksInventory.NETWORKS = (TEMPORARY_DOMAIN,) - NetworksInventory.ETH_NETWORKS = (TEMPORARY_DOMAIN,) - NetworksInventory.POLY_NETWORKS = (TEMPORARY_DOMAIN,) + supported_domains = [] + supported_domain_names = [] + for domain_name in domain_names: + test_domain = DomainInfo( + domain_name, TESTERCHAIN_CHAIN_INFO, TESTERCHAIN_CHAIN_INFO + ) + supported_domains.append(test_domain) + supported_domain_names.append(domain_name) + + mocker.patch.object(TACoDomain, "SUPPORTED_DOMAINS", supported_domains) + mocker.patch.object(TACoDomain, "SUPPORTED_DOMAIN_NAMES", supported_domain_names) + mocker.patch.object(MockRegistrySource, "ALLOWED_DOMAINS", domain_names) + + mocker.patch.object(RegistrySourceManager, "_FALLBACK_CHAIN", (MockRegistrySource,)) yield # run the test - # restore the real values - RegistrySourceManager._FALLBACK_CHAIN = real_registry_sources - NetworksInventory.NETWORKS = real_networks - NetworksInventory.ETH_NETWORKS = real_eth_networks - NetworksInventory.POLY_NETWORKS = real_poly_networks - class MockRegistrySource(RegistrySource): + ALLOWED_DOMAINS = [TEMPORARY_DOMAIN] + name = "Mock Registry Source" is_primary = False def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - if self.domain != TEMPORARY_DOMAIN: + if self.domain not in self.ALLOWED_DOMAINS: raise ValueError( f"Somehow, MockRegistrySource is trying to get a registry for '{self.domain}'. " - f"Only '{TEMPORARY_DOMAIN}' is supported.'" + f"Only '{','.join(self.ALLOWED_DOMAINS)}' are supported.'" ) @property diff --git a/tests/utils/ursula.py b/tests/utils/ursula.py index df4e662ca..fafb9f244 100644 --- a/tests/utils/ursula.py +++ b/tests/utils/ursula.py @@ -10,7 +10,7 @@ from nucypher.characters.lawful import Ursula from nucypher.config.characters import UrsulaConfiguration from nucypher.policy.conditions.evm import _CONDITION_CHAINS from tests.constants import ( - NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK, + NUMBER_OF_URSULAS_IN_DEVELOPMENT_DOMAIN, TESTERCHAIN_CHAIN_ID, ) @@ -68,7 +68,7 @@ def make_ursulas( ursula_config: UrsulaConfiguration, staking_provider_addresses: Iterable[str], operator_addresses: Iterable[str], - quantity: int = NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK, + quantity: int = NUMBER_OF_URSULAS_IN_DEVELOPMENT_DOMAIN, know_each_other: bool = True, **ursula_overrides ) -> List[Ursula]: @@ -133,13 +133,15 @@ def mock_permitted_multichain_connections(mocker) -> List[int]: def setup_multichain_ursulas(chain_ids: List[int], ursulas: List[Ursula]) -> None: base_uri = "tester://multichain.{}" base_fallback_uri = "tester://multichain.fallback.{}" - provider_uris = [base_uri.format(i) for i in range(len(chain_ids))] - fallback_provider_uris = [ + blockchain_endpoints = [base_uri.format(i) for i in range(len(chain_ids))] + fallback_blockchain_endpoints = [ base_fallback_uri.format(i) for i in range(len(chain_ids)) ] mocked_condition_providers = { cid: {HTTPProvider(uri), HTTPProvider(furi)} - for cid, uri, furi in zip(chain_ids, provider_uris, fallback_provider_uris) + for cid, uri, furi in zip( + chain_ids, blockchain_endpoints, fallback_blockchain_endpoints + ) } for ursula in ursulas: ursula.condition_providers = mocked_condition_providers