mirror of https://github.com/nucypher/nucypher.git
use the staking and payment provider uris as default conditions providers before Ursula's construction.
parent
8a551d34ab
commit
57ce72ade9
|
@ -325,31 +325,30 @@ class Ritualist(BaseActor):
|
|||
condition_provider_uris
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _is_permitted_condition_chain(chain_id: int) -> bool:
|
||||
return int(chain_id) in [int(cid) for cid in _CONDITION_CHAINS.keys()]
|
||||
|
||||
@staticmethod
|
||||
def _make_condition_provider(uri: str) -> HTTPProvider:
|
||||
provider = HTTPProvider(endpoint_uri=uri)
|
||||
return provider
|
||||
|
||||
def connect_condition_providers(
|
||||
self, condition_provider_uris: Optional[Dict[int, List[str]]] = None
|
||||
) -> DefaultDict[int, Set[HTTPProvider]]:
|
||||
"""Multi-provider support"""
|
||||
|
||||
# If condition_provider_uris is `None` the node operator
|
||||
# If condition_provider_uris is None the node operator
|
||||
# did not configure any additional condition providers.
|
||||
condition_provider_uris = condition_provider_uris or dict()
|
||||
|
||||
# These are the chains that the Ritualist will connect to for conditions evaluation (read-only).
|
||||
condition_providers = defaultdict(set)
|
||||
|
||||
# Borrow default RPC endpoints from the Operator.
|
||||
eth_chain = self.application_agent.blockchain
|
||||
|
||||
# Presumably, they've already configured their polygon engpoint (or we'd not be this far),
|
||||
# so we can use that for the polygon condition provider.
|
||||
polygon_chain = self.payment_method.agent.blockchain
|
||||
condition_providers[eth_chain.client.chain_id].add(eth_chain.provider)
|
||||
condition_providers[polygon_chain.client.chain_id].add(polygon_chain.provider)
|
||||
# Done borrowing.
|
||||
|
||||
# Now, add any additional providers that were passed in.
|
||||
for chain_id, condition_provider_uris in condition_provider_uris.items():
|
||||
if chain_id not in _CONDITION_CHAINS:
|
||||
if not self._is_permitted_condition_chain(chain_id):
|
||||
# this is a safety check to prevent the Ritualist from connecting to
|
||||
# chains that are not supported by ursulas on the network;
|
||||
# Prevents the Ursula/Ritualist from starting up if this happens.
|
||||
|
@ -357,11 +356,12 @@ class Ritualist(BaseActor):
|
|||
f"Chain ID {chain_id} is not supported for condition evaluation by the Ritualist."
|
||||
)
|
||||
|
||||
providers = list()
|
||||
providers = set()
|
||||
for uri in condition_provider_uris:
|
||||
provider = HTTPProvider(endpoint_uri=uri)
|
||||
providers.append(provider)
|
||||
condition_providers[chain_id].update(providers)
|
||||
provider = self._make_condition_provider(uri)
|
||||
providers.add(provider)
|
||||
|
||||
condition_providers[int(chain_id)] = providers
|
||||
|
||||
# Log the chains that the Ritualist is connected to.
|
||||
humanized_chain_ids = ", ".join(
|
||||
|
|
|
@ -34,11 +34,18 @@ class NetworksInventory: # TODO: See #1564
|
|||
pass
|
||||
|
||||
@classmethod
|
||||
def get_ethereum_chain_id(cls, network): # TODO: Use this (where?) to make sure we're in the right chain
|
||||
def get_ethereum_chain_id(cls, network):
|
||||
try:
|
||||
return cls.__to_ethereum_chain_id[network]
|
||||
return cls.__to_chain_id_eth[network]
|
||||
except KeyError:
|
||||
return 1337 # TODO: what about chain id when testing?
|
||||
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):
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import json
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
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,
|
||||
|
@ -56,9 +58,27 @@ class UrsulaConfiguration(CharacterConfiguration):
|
|||
self.rest_host = rest_host
|
||||
self.certificate = certificate
|
||||
self.operator_address = operator_address
|
||||
self.availability_check = availability_check if availability_check is not None else self.DEFAULT_AVAILABILITY_CHECKS
|
||||
self.availability_check = (
|
||||
availability_check
|
||||
if availability_check is not None
|
||||
else self.DEFAULT_AVAILABILITY_CHECKS
|
||||
)
|
||||
super().__init__(
|
||||
dev_mode=dev_mode, keystore_path=keystore_path, *args, **kwargs
|
||||
)
|
||||
self.condition_provider_uris = condition_provider_uris or dict()
|
||||
super().__init__(dev_mode=dev_mode, keystore_path=keystore_path, *args, **kwargs)
|
||||
self.configure_condition_provider_uris()
|
||||
|
||||
def configure_condition_provider_uris(self) -> None:
|
||||
"""Configure default condition provider URIs for mainnet and polygon network."""
|
||||
|
||||
# Polygon
|
||||
polygon_chain_id = NetworksInventory.get_polygon_chain_id(self.payment_network)
|
||||
self.condition_provider_uris[polygon_chain_id] = [self.payment_provider]
|
||||
|
||||
# Ethereum
|
||||
staking_chain_id = NetworksInventory.get_ethereum_chain_id(self.domain)
|
||||
self.condition_provider_uris[staking_chain_id] = [self.eth_provider_uri]
|
||||
|
||||
@classmethod
|
||||
def address_from_filepath(cls, filepath: Path) -> str:
|
||||
|
|
|
@ -4,9 +4,10 @@ import random
|
|||
import pytest
|
||||
from web3 import Web3
|
||||
|
||||
from nucypher.blockchain.eth.actors import Operator
|
||||
from nucypher.blockchain.eth.actors import Operator, Ritualist
|
||||
from nucypher.blockchain.eth.agents import ContractAgency, PREApplicationAgent
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
||||
from nucypher.blockchain.eth.networks import NetworksInventory
|
||||
from nucypher.blockchain.eth.signers.software import Web3Signer
|
||||
from nucypher.config.constants import TEMPORARY_DOMAIN
|
||||
from nucypher.crypto.powers import CryptoPower, TransactingPower
|
||||
|
@ -35,6 +36,21 @@ def mock_condition_blockchains(session_mocker):
|
|||
{TESTERCHAIN_CHAIN_ID: "eth-tester/pyevm"},
|
||||
)
|
||||
|
||||
session_mocker.patch.object(
|
||||
NetworksInventory, "get_polygon_chain_id", return_value=TESTERCHAIN_CHAIN_ID
|
||||
)
|
||||
|
||||
session_mocker.patch.object(
|
||||
NetworksInventory, "get_ethereum_chain_id", return_value=TESTERCHAIN_CHAIN_ID
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def mock_multichain_configuration(module_mocker, testerchain):
|
||||
module_mocker.patch.object(
|
||||
Ritualist, "_make_condition_provider", return_value=testerchain.provider
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope='session', autouse=True)
|
||||
def nucypher_contracts(project):
|
||||
|
|
|
@ -3,6 +3,8 @@ from collections import defaultdict
|
|||
import pytest
|
||||
from eth_utils.crypto import keccak
|
||||
|
||||
from nucypher.blockchain.eth.actors import Ritualist
|
||||
from nucypher.blockchain.eth.networks import NetworksInventory
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.network.nodes import Learner
|
||||
from nucypher.network.trackers import AvailabilityTracker
|
||||
|
@ -144,3 +146,18 @@ def mock_condition_blockchains(session_mocker):
|
|||
"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
|
||||
)
|
||||
|
||||
session_mocker.patch.object(
|
||||
NetworksInventory, "get_ethereum_chain_id", return_value=TESTERCHAIN_CHAIN_ID
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def mock_multichain_configuration(module_mocker, testerchain):
|
||||
module_mocker.patch.object(
|
||||
Ritualist, "_make_condition_provider", return_value=testerchain.provider
|
||||
)
|
||||
|
|
|
@ -5,6 +5,8 @@ from unittest.mock import PropertyMock
|
|||
|
||||
import pytest
|
||||
|
||||
import nucypher
|
||||
from nucypher.blockchain.eth.actors import Ritualist
|
||||
from nucypher.blockchain.eth.trackers.dkg import ActiveRitualTracker
|
||||
from nucypher.cli.literature import (
|
||||
COLLECT_NUCYPHER_PASSWORD,
|
||||
|
@ -31,6 +33,7 @@ from tests.constants import (
|
|||
MOCK_ETH_PROVIDER_URI,
|
||||
MOCK_IP_ADDRESS,
|
||||
YES_ENTER,
|
||||
TESTERCHAIN_CHAIN_ID,
|
||||
)
|
||||
from tests.utils.ursula import select_test_port
|
||||
|
||||
|
@ -180,7 +183,9 @@ def test_ursula_view_configuration(custom_filepath: Path, click_runner, nominal_
|
|||
assert custom_config_filepath.is_file(), 'Configuration file does not exist'
|
||||
|
||||
|
||||
def test_run_ursula_from_config_file(custom_filepath: Path, click_runner, mock_funding_and_bonding):
|
||||
def test_run_ursula_from_config_file(
|
||||
custom_filepath: Path, click_runner, mock_funding_and_bonding, mocker
|
||||
):
|
||||
|
||||
# Ensure the configuration file still exists
|
||||
custom_config_filepath = custom_filepath / UrsulaConfiguration.generate_filename()
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
@ -148,7 +149,7 @@ def test_default_character_configuration_preservation(
|
|||
|
||||
# Restore from JSON file
|
||||
restored_configuration = configuration_class.from_configuration_file()
|
||||
assert character_config.serialize() == restored_configuration.serialize()
|
||||
assert json.loads(character_config.serialize()) == json.loads(restored_configuration.serialize())
|
||||
|
||||
# File still exists after reading
|
||||
assert written_filepath.exists()
|
||||
|
|
|
@ -4,7 +4,7 @@ from pathlib import Path
|
|||
from typing import Iterable, Optional
|
||||
|
||||
from nucypher.blockchain.economics import EconomicsFactory
|
||||
from nucypher.blockchain.eth.actors import Operator
|
||||
from nucypher.blockchain.eth.actors import Operator, Ritualist
|
||||
from nucypher.blockchain.eth.agents import (
|
||||
AdjudicatorAgent,
|
||||
ContractAgency,
|
||||
|
@ -15,6 +15,7 @@ from nucypher.blockchain.eth.interfaces import (
|
|||
BlockchainInterface,
|
||||
BlockchainInterfaceFactory,
|
||||
)
|
||||
from nucypher.blockchain.eth.networks import NetworksInventory
|
||||
from nucypher.blockchain.eth.registry import InMemoryContractRegistry
|
||||
from nucypher.blockchain.eth.signers import KeystoreSigner
|
||||
from nucypher.characters.lawful import Ursula
|
||||
|
@ -26,6 +27,7 @@ from tests.constants import (
|
|||
KEYFILE_NAME_TEMPLATE,
|
||||
MOCK_KEYSTORE_PATH,
|
||||
NUMBER_OF_MOCK_KEYSTORE_ACCOUNTS,
|
||||
TESTERCHAIN_CHAIN_ID,
|
||||
)
|
||||
from tests.mock.interfaces import MockBlockchain, mock_registry_source_manager
|
||||
from tests.mock.io import MockStdinWrapper
|
||||
|
@ -245,3 +247,20 @@ def staking_providers(testerchain, test_registry, monkeymodule):
|
|||
|
||||
Operator.get_staking_provider_address = faked
|
||||
return testerchain.stake_providers_accounts
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def mock_condition_blockchains(session_mocker):
|
||||
"""adds testerchain's chain ID to permitted conditional chains"""
|
||||
session_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
|
||||
)
|
||||
|
||||
session_mocker.patch.object(
|
||||
NetworksInventory, "get_ethereum_chain_id", return_value=TESTERCHAIN_CHAIN_ID
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue