Push common learner configuration logic down to NodeStorage; Pre and Post character production logic, extracted keyring unlock UX.

pull/562/head
Kieran Prasch 2018-11-22 10:11:11 -08:00
parent 305eadc8d8
commit e343a675ac
No known key found for this signature in database
GPG Key ID: 199AB839D4125A62
2 changed files with 296 additions and 213 deletions

View File

@ -18,85 +18,35 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
import os
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurve
from cryptography.x509 import Certificate
from web3.middleware import geth_poa_middleware
from constant_sorrow.constants import NO_BLOCKCHAIN_CONNECTION, CONTRACT_NOT_AVAILABLE
from constant_sorrow.constants import (
UNINITIALIZED_CONFIGURATION,
NO_KEYRING_ATTACHED
)
from nucypher.blockchain.eth.agents import NucypherTokenAgent, MinerAgent
from nucypher.blockchain.eth.chains import Blockchain
from nucypher.config.constants import DEFAULT_CONFIG_ROOT
from nucypher.config.node import NodeConfiguration
from nucypher.crypto.powers import CryptoPower
class UrsulaConfiguration(NodeConfiguration):
from nucypher.characters.lawful import Ursula
_character_class = Ursula
_name = 'ursula'
_CHARACTER_CLASS = Ursula
_NAME = 'ursula'
DEFAULT_DB_FILEPATH = os.path.join(DEFAULT_CONFIG_ROOT, '{}.db'.format(_name))
DEFAULT_REST_HOST = '127.0.0.1'
DEFAULT_REST_PORT = 9151
__DEFAULT_TLS_CURVE = ec.SECP384R1
def __init__(self,
rest_host: str = None,
rest_port: int = None,
# TLS
tls_curve: EllipticCurve = None,
certificate: Certificate = None,
certificate_filepath: str = None,
# Ursula
db_filepath: str = None,
interface_signature=None,
crypto_power: CryptoPower = None,
# Blockchain
poa: bool = False,
provider_uri: str = None,
*args, **kwargs
) -> None:
# REST
self.rest_host = rest_host or self.DEFAULT_REST_HOST
self.rest_port = rest_port or self.DEFAULT_REST_PORT
self.db_filepath = db_filepath or self.DEFAULT_DB_FILEPATH
#
# TLS
#
self.tls_curve = tls_curve or self.__DEFAULT_TLS_CURVE
self.certificate = certificate
self.certificate_filepath = certificate_filepath
# Ursula
self.interface_signature = interface_signature
self.crypto_power = crypto_power
#
# Blockchain
#
self.poa = poa
self.provider_uri = provider_uri
self.blockchain = NO_BLOCKCHAIN_CONNECTION
self.token_agent = CONTRACT_NOT_AVAILABLE
self.miner_agent = CONTRACT_NOT_AVAILABLE
self.policy_agent = CONTRACT_NOT_AVAILABLE
CONFIG_FILENAME = '{}.config'.format(_NAME)
DEFAULT_CONFIG_FILE_LOCATION = os.path.join(DEFAULT_CONFIG_ROOT, CONFIG_FILENAME)
DEFAULT_DB_NAME = '{}.db'.format(_NAME)
def __init__(self, db_filepath: str = None, *args, **kwargs) -> None:
self.db_filepath = db_filepath or UNINITIALIZED_CONFIGURATION
super().__init__(*args, **kwargs)
def generate_runtime_filepaths(self, config_root: str) -> dict:
base_filepaths = NodeConfiguration.generate_runtime_filepaths(config_root=config_root)
filepaths = dict(db_filepath=os.path.join(config_root, self.db_filepath))
base_filepaths = super().generate_runtime_filepaths(config_root=config_root)
filepaths = dict(db_filepath=os.path.join(config_root, self.DEFAULT_DB_NAME))
base_filepaths.update(filepaths)
return base_filepaths
@ -107,36 +57,40 @@ class UrsulaConfiguration(NodeConfiguration):
rest_port=self.rest_port,
db_filepath=self.db_filepath,
)
if not self.dev:
certificate_filepath = self.certificate_filepath or self.keyring.certificate_filepath
payload.update(dict(certificate_filepath=certificate_filepath))
return {**super().static_payload, **payload}
@property
def dynamic_payload(self) -> dict:
payload = dict(
network_middleware=self.network_middleware,
tls_curve=self.tls_curve, # TODO: Needs to be in static payload with mapping
tls_curve=self.tls_curve, # TODO: Needs to be in static payload with [str -> curve] mapping
certificate=self.certificate,
interface_signature=self.interface_signature,
timestamp=None,
)
return {**super().dynamic_payload, **payload}
def produce(self, password: str = None, **overrides):
def produce(self, **overrides):
"""Produce a new Ursula from configuration"""
if not self.dev:
self.read_keyring()
self.keyring.unlock(password=password)
# Build a merged dict of Ursula parameters
merged_parameters = {**self.static_payload, **self.dynamic_payload, **overrides}
#
# Pre-Init
#
# Verify the configuration file refers to the same configuration root as this instance
config_root_from_config_file = merged_parameters.pop('config_root')
if config_root_from_config_file != self.config_root:
message = "Configuration root mismatch {} and {}.".format(config_root_from_config_file, self.config_root)
raise self.ConfigurationError(message)
if self.federated_only is False:
self.blockchain = Blockchain.connect(provider_uri=self.provider_uri)
if self.poa: # TODO: move this..?
if self.poa:
w3 = self.miner_agent.blockchain.interface.w3
w3.middleware_stack.inject(geth_poa_middleware, layer=0)
@ -144,9 +98,15 @@ class UrsulaConfiguration(NodeConfiguration):
self.miner_agent = MinerAgent(blockchain=self.blockchain)
merged_parameters.update(blockchain=self.blockchain)
ursula = self._character_class(**merged_parameters)
#
# Init
#
ursula = self._CHARACTER_CLASS(**merged_parameters)
if self.dev: # TODO: Move this..?
#
# Post-Init
#
if self.dev_mode:
class MockDatastoreThreadPool(object):
def callInThread(self, f, *args, **kwargs):
return f(*args, **kwargs)
@ -154,15 +114,33 @@ class UrsulaConfiguration(NodeConfiguration):
return ursula
def __write(self, password: str, no_registry: bool):
_new_installation_path = self.initialize(password=password, import_registry=no_registry)
_configuration_filepath = self.to_configuration_file(filepath=self.config_file_location)
@classmethod
def generate(cls, password: str, no_registry: bool, *args, **kwargs) -> 'UrsulaConfiguration':
"""Hook-up a new initial installation and write configuration file to the disk"""
ursula_config = cls(dev_mode=False, is_me=True, *args, **kwargs)
ursula_config.__write(password=password, no_registry=no_registry)
return ursula_config
class AliceConfiguration(NodeConfiguration):
from nucypher.characters.lawful import Alice
_character_class = Alice
_name = 'alice'
_CHARACTER_CLASS = Alice
_NAME = 'alice'
CONFIG_FILENAME = '{}.config'.format(_NAME)
DEFAULT_CONFIG_FILE_LOCATION = os.path.join(DEFAULT_CONFIG_ROOT, CONFIG_FILENAME)
class BobConfiguration(NodeConfiguration):
from nucypher.characters.lawful import Bob
_character_class = Bob
_name = 'bob'
_CHARACTER_CLASS = Bob
_NAME = 'bob'
CONFIG_FILENAME = '{}.config'.format(_NAME)
DEFAULT_CONFIG_FILE_LOCATION = os.path.join(DEFAULT_CONFIG_ROOT, CONFIG_FILENAME)

View File

@ -19,44 +19,68 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
import binascii
import json
import os
import secrets
import string
from abc import ABC, abstractmethod
from json import JSONDecodeError
from tempfile import TemporaryDirectory
import shutil
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurve
from cryptography.x509 import Certificate
from twisted.logger import Logger
from typing import List
from web3.middleware import geth_poa_middleware
from constant_sorrow.constants import UNINITIALIZED_CONFIGURATION, STRANGER_CONFIGURATION, LIVE_CONFIGURATION
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurve
from twisted.logger import Logger
from constant_sorrow.constants import (
UNINITIALIZED_CONFIGURATION,
STRANGER_CONFIGURATION,
NO_BLOCKCHAIN_CONNECTION,
LIVE_CONFIGURATION,
NO_KEYRING_ATTACHED
)
from nucypher.blockchain.eth.agents import PolicyAgent, MinerAgent, NucypherTokenAgent
from nucypher.blockchain.eth.chains import Blockchain
from nucypher.characters.lawful import Ursula
from nucypher.config.constants import DEFAULT_CONFIG_ROOT, BASE_DIR
from nucypher.config.constants import DEFAULT_CONFIG_ROOT, BASE_DIR, USER_LOG_DIR
from nucypher.config.keyring import NucypherKeyring
from nucypher.config.storages import NodeStorage, ForgetfulNodeStorage, LocalFileBasedNodeStorage
from nucypher.crypto.powers import CryptoPowerUp
from nucypher.crypto.powers import CryptoPowerUp, CryptoPower
from nucypher.network.middleware import RestMiddleware
from umbral.signing import Signature
class NodeConfiguration:
class NodeConfiguration(ABC):
"""
'Sideways Engagement' of Character classes; a reflection of input parameters.
"""
_name = 'ursula'
_character_class = Ursula
# Abstract
_NAME = NotImplemented
_CHARACTER_CLASS = NotImplemented
CONFIG_FILENAME = NotImplemented
DEFAULT_CONFIG_FILE_LOCATION = NotImplemented
CONFIG_FILENAME = '{}.config'.format(_name)
DEFAULT_CONFIG_FILE_LOCATION = os.path.join(DEFAULT_CONFIG_ROOT, CONFIG_FILENAME)
# Mode
DEFAULT_OPERATING_MODE = 'decentralized'
NODE_SERIALIZER = binascii.hexlify
NODE_DESERIALIZER = binascii.unhexlify
# Configuration
__CONFIG_FILE_EXT = '.config'
__CONFIG_FILE_DESERIALIZER = json.loads
__TEMP_CONFIGURATION_DIR_PREFIX = "nucypher-tmp-"
__DEFAULT_NETWORK_MIDDLEWARE_CLASS = RestMiddleware
# Registry
__REGISTRY_NAME = 'contract_registry.json'
REGISTRY_SOURCE = os.path.join(BASE_DIR, __REGISTRY_NAME) # TODO: #461 Where will this be hosted?
# Rest + TLS
DEFAULT_REST_HOST = '127.0.0.1'
DEFAULT_REST_PORT = 9151
__DEFAULT_TLS_CURVE = ec.SECP384R1
__DEFAULT_NETWORK_MIDDLEWARE_CLASS = RestMiddleware
class ConfigurationError(RuntimeError):
pass
@ -65,90 +89,122 @@ class NodeConfiguration:
def __init__(self,
dev: bool = False,
config_root: str = None,
# Mode
dev_mode: bool = False,
federated_only: bool = False,
password: str = None,
auto_initialize: bool = False,
auto_generate_keys: bool = False,
config_file_location: str = None,
# Keyring
keyring: NucypherKeyring = None,
keyring_dir: str = None,
checksum_address: str = None,
# Identity
is_me: bool = True,
federated_only: bool = False,
network_middleware: RestMiddleware = None,
registry_source: str = None,
registry_filepath: str = None,
import_seed_registry: bool = False,
checksum_address: str = None,
# Learner
learn_on_same_thread: bool = False,
abort_on_learning_error: bool = False,
start_learning_now: bool = True,
# Configuration
config_root: str = None,
config_file_location: str = None,
# REST + TLS
rest_host: str = None,
rest_port: int = None,
tls_curve: EllipticCurve = None,
certificate: Certificate = None,
crypto_power: CryptoPower = None,
interface_signature: Signature = None,
network_middleware: RestMiddleware = None,
# Node Storage
known_nodes: set = None,
node_storage: NodeStorage = None,
load_metadata: bool = True,
save_metadata: bool = True,
# Blockchain
poa: bool = False,
provider_uri: str = None,
# Registry
registry_source: str = None,
registry_filepath: str = None,
import_seed_registry: bool = False # TODO: needs cleanup
) -> None:
# Logs
self.log = Logger(self.__class__.__name__)
#
# REST + TLS
#
self.rest_host = rest_host or self.DEFAULT_REST_HOST
self.rest_port = rest_port or self.DEFAULT_REST_PORT
self.tls_curve = tls_curve or self.__DEFAULT_TLS_CURVE
self.certificate = certificate
self.interface_signature = interface_signature
self.crypto_power = crypto_power
#
# Keyring
self.keyring = keyring or UNINITIALIZED_CONFIGURATION
#
self.keyring = keyring or NO_KEYRING_ATTACHED
self.keyring_dir = keyring_dir or UNINITIALIZED_CONFIGURATION
# Contract Registry
if import_seed_registry is True:
registry_source = self.REGISTRY_SOURCE
if not os.path.isfile(registry_source):
message = "Seed contract registry does not exist at path {}.".format(registry_filepath)
self.log.debug(message)
raise RuntimeError(message)
self.__registry_source = registry_source or self.REGISTRY_SOURCE
self.registry_filepath = registry_filepath or UNINITIALIZED_CONFIGURATION
# Configuration File and Root Directory
#
# Configuration
#
self.config_file_location = config_file_location or UNINITIALIZED_CONFIGURATION
self.config_root = UNINITIALIZED_CONFIGURATION
self.__dev = dev
if self.__dev:
#
# Mode
#
self.federated_only = federated_only
self.__dev_mode = dev_mode
if self.__dev_mode:
self.__temp_dir = UNINITIALIZED_CONFIGURATION
self.node_storage = ForgetfulNodeStorage(federated_only=federated_only, character_class=self.__class__)
else:
from nucypher.characters.lawful import Ursula # TODO : Needs cleanup
self.__temp_dir = LIVE_CONFIGURATION
self.config_root = config_root or DEFAULT_CONFIG_ROOT
self.__cache_runtime_filepaths()
self._cache_runtime_filepaths()
self.node_storage = node_storage or LocalFileBasedNodeStorage(federated_only=federated_only,
config_root=self.config_root)
#
# Identity
#
self.federated_only = federated_only
self.checksum_address = checksum_address
self.is_me = is_me
if self.is_me:
#
self.checksum_address = checksum_address
if self.is_me is True or dev_mode is True:
# Self
#
if checksum_address and not self.__dev:
self.read_keyring()
if self.checksum_address and dev_mode is False:
self.attach_keyring()
self.network_middleware = network_middleware or self.__DEFAULT_NETWORK_MIDDLEWARE_CLASS()
else:
#
# Stranger
#
self.node_storage = STRANGER_CONFIGURATION
self.keyring_dir = STRANGER_CONFIGURATION
self.keyring = STRANGER_CONFIGURATION
self.network_middleware = STRANGER_CONFIGURATION
if network_middleware:
raise self.ConfigurationError("Cannot configure a stranger to use network middleware")
raise self.ConfigurationError("Cannot configure a stranger to use network middleware.")
#
# Learner
@ -161,53 +217,127 @@ class NodeConfiguration:
self.load_metadata = load_metadata
#
# Auto-Initialization
# Blockchain
#
if auto_initialize:
self.initialize(no_registry=not import_seed_registry or federated_only, # TODO: needs cleanup
wallet=auto_generate_keys and not federated_only,
encrypting=auto_generate_keys,
password=password)
self.poa = poa
self.provider_uri = provider_uri
self.blockchain = NO_BLOCKCHAIN_CONNECTION
self.accounts = NO_BLOCKCHAIN_CONNECTION
self.token_agent = NO_BLOCKCHAIN_CONNECTION
self.miner_agent = NO_BLOCKCHAIN_CONNECTION
self.policy_agent = NO_BLOCKCHAIN_CONNECTION
#
# Development Mode
#
if dev_mode:
# Ephemeral dev settings
self.save_metadata = False
self.load_metadata = False
# Generate one-time alphanumeric development password
alphabet = string.ascii_letters + string.digits
password = ''.join(secrets.choice(alphabet) for _ in range(32))
self.initialize(password=password, import_registry=import_seed_registry)
def __call__(self, *args, **kwargs):
return self.produce(*args, **kwargs)
def cleanup(self) -> None:
if self.__dev:
if self.__dev_mode:
self.__temp_dir.cleanup()
@property
def dev(self):
return self.__dev
def dev_mode(self):
return self.__dev_mode
def produce(self, password: str = None, **overrides):
"""Initialize a new character instance and return it"""
if not self.dev:
self.read_keyring()
self.keyring.unlock(password=password)
def connect_to_blockchain(self, provider_uri: str, poa: bool, compile: bool):
if self.federated_only:
raise NodeConfiguration.ConfigurationError("Cannot connect to blockchain in federated mode")
self.blockchain = Blockchain.connect(provider_uri=provider_uri, compile=compile)
if poa is True:
w3 = self.blockchain.interface.w3
w3.middleware_stack.inject(geth_poa_middleware, layer=0)
self.accounts = self.blockchain.interface.w3.eth.accounts
self.log.debug("Established connection to provider {}".format(self.blockchain.interface.provider_uri))
def connect_to_contracts(self) -> None:
"""Initialize contract agency and set them on config"""
self.token_agent = NucypherTokenAgent(blockchain=self.blockchain)
self.miner_agent = MinerAgent(blockchain=self.blockchain)
self.policy_agent = PolicyAgent(blockchain=self.blockchain)
self.log.debug("Established connection to nucypher contracts")
def read_known_nodes(self):
self.known_nodes.update(self.node_storage.all(federated_only=self.federated_only))
return self.known_nodes
def forget_nodes(self) -> None:
self.node_storage.clear()
message = "Removed all stored node node metadata and certificates"
self.log.debug(message)
def destroy(self, force: bool = False, logs: bool = True) -> None:
# TODO: Confirm this is a nucypher dir first! (in-depth measure)
if force:
pass
if logs is True:
shutil.rmtree(USER_LOG_DIR)
try:
shutil.rmtree(self.config_root)
except FileNotFoundError:
raise
def produce(self, **overrides):
"""Initialize a new character instance and return it."""
# Build a merged dict of node parameters
merged_parameters = {**self.static_payload, **self.dynamic_payload, **overrides}
return self._character_class(**merged_parameters)
# Verify the configuration file refers to the same configuration root as this instance
config_root_from_config_file = merged_parameters.pop('config_root')
if config_root_from_config_file != self.config_root:
message = "Configuration root mismatch {} and {}.".format(config_root_from_config_file, self.config_root)
raise self.ConfigurationError(message)
character = self._CHARACTER_CLASS(**merged_parameters)
return character
@staticmethod
def _read_configuration_file(filepath) -> dict:
with open(filepath, 'r') as file:
payload = NodeConfiguration.__CONFIG_FILE_DESERIALIZER(file.read())
def _read_configuration_file(filepath: str) -> dict:
try:
with open(filepath, 'r') as file:
raw_contents = file.read()
payload = NodeConfiguration.__CONFIG_FILE_DESERIALIZER(raw_contents)
except FileNotFoundError as e:
raise # TODO: Do we need better exception handling here?
return payload
@classmethod
def from_configuration_file(cls, filepath, **overrides) -> 'NodeConfiguration':
def from_configuration_file(cls, filepath: str = None, **overrides) -> 'NodeConfiguration':
"""Initialize a NodeConfiguration from a JSON file."""
from nucypher.config.storages import NodeStorage # TODO: move
NODE_STORAGES = {storage_class._name: storage_class for storage_class in NodeStorage.__subclasses__()}
from nucypher.config.storages import NodeStorage
node_storage_subclasses = {storage._name: storage for storage in NodeStorage.__subclasses__()}
if filepath is None:
filepath = cls.DEFAULT_CONFIG_FILE_LOCATION
# Read from disk
payload = cls._read_configuration_file(filepath=filepath)
# Make NodeStorage
# Initialize NodeStorage subclass from file (sub-configuration)
storage_payload = payload['node_storage']
storage_type = storage_payload[NodeStorage._TYPE_LABEL]
storage_class = NODE_STORAGES[storage_type]
storage_class = node_storage_subclasses[storage_type]
node_storage = storage_class.from_payload(payload=storage_payload,
character_class=cls._character_class,
character_class=cls._CHARACTER_CLASS,
federated_only=payload['federated_only'],
serializer=cls.NODE_SERIALIZER,
deserializer=cls.NODE_DESERIALIZER)
@ -218,11 +348,12 @@ class NodeConfiguration:
def to_configuration_file(self, filepath: str = None) -> str:
"""Write the static_payload to a JSON file."""
if filepath is None:
filename = '{}{}'.format(self._name.lower(), self.__CONFIG_FILE_EXT)
filename = '{}{}'.format(self._NAME.lower(), self.__CONFIG_FILE_EXT)
filepath = os.path.join(self.config_root, filename)
payload = self.static_payload
del payload['is_me'] # TODO
# Save node connection data
payload.update(dict(node_storage=self.node_storage.payload()))
@ -250,6 +381,8 @@ class NodeConfiguration:
def static_payload(self) -> dict:
"""Exported static configuration values for initializing Ursula"""
payload = dict(
config_root=self.config_root,
# Identity
is_me=self.is_me,
federated_only=self.federated_only, # TODO: 466
@ -294,7 +427,7 @@ class NodeConfiguration:
registry_filepath=os.path.join(config_root, NodeConfiguration.__REGISTRY_NAME))
return filepaths
def __cache_runtime_filepaths(self) -> None:
def _cache_runtime_filepaths(self) -> None:
"""Generate runtime filepaths and cache them on the config object"""
filepaths = self.generate_runtime_filepaths(config_root=self.config_root)
for field, filepath in filepaths.items():
@ -303,28 +436,22 @@ class NodeConfiguration:
def derive_node_power_ups(self) -> List[CryptoPowerUp]:
power_ups = list()
if self.is_me and not self.dev:
for power_class in self._character_class._default_crypto_powerups:
if self.is_me and not self.dev_mode:
for power_class in self._CHARACTER_CLASS._default_crypto_powerups:
power_up = self.keyring.derive_crypto_power(power_class)
power_ups.append(power_up)
return power_ups
def initialize(self,
password: str,
no_registry: bool = False,
wallet: bool = False,
encrypting: bool = False,
tls: bool = False,
host: str = None,
curve=None,
no_keys: bool = False
import_registry: bool = True,
) -> str:
"""Initialize a new configuration."""
#
# Create Config Root
#
if self.__dev:
if self.__dev_mode:
self.__temp_dir = TemporaryDirectory(prefix=self.__TEMP_CONFIGURATION_DIR_PREFIX)
self.config_root = self.__temp_dir.name
else:
@ -340,57 +467,56 @@ class NodeConfiguration:
#
# Create Config Subdirectories
#
self.__cache_runtime_filepaths()
self._cache_runtime_filepaths()
try:
# Node Storage
self.node_storage.initialize()
# Keyring
os.mkdir(self.keyring_dir, mode=0o700) # keyring TODO: Keyring backend entry point
if not self.dev and not no_keys:
# Keyring
self.write_keyring(password=password,
wallet=wallet,
encrypting=encrypting,
tls=tls,
host=host,
tls_curve=curve)
if not self.dev_mode:
os.mkdir(self.keyring_dir, mode=0o700) # keyring TODO: Keyring backend entry point
self.write_keyring(password=password, host=self.rest_host, tls_curve=self.tls_curve)
# Registry
if not no_registry and not self.federated_only:
self.write_registry(output_filepath=self.registry_filepath,
source=self.__registry_source,
blank=no_registry)
if import_registry and not self.federated_only:
self.write_registry(output_filepath=self.registry_filepath, # type: str
source=self.__registry_source, # type: str
blank=import_registry) # type: bool
except FileExistsError:
existing_paths = [os.path.join(self.config_root, f) for f in os.listdir(self.config_root)]
message = "There are pre-existing nucypher installation files at {}: {}".format(self.config_root,
existing_paths)
message = "There are pre-existing files at {}: {}".format(self.config_root, existing_paths)
self.log.critical(message)
raise NodeConfiguration.ConfigurationError(message)
if not self.__dev:
self.validate(config_root=self.config_root, no_registry=no_registry or self.federated_only)
if not self.__dev_mode:
self.validate(config_root=self.config_root, no_registry=import_registry or self.federated_only)
# Success
message = "Created nucypher installation files at {}".format(self.config_root)
self.log.debug(message)
return self.config_root
def read_known_nodes(self):
self.known_nodes.update(self.node_storage.all(federated_only=self.federated_only))
return self.known_nodes
def attach_keyring(self, checksum_address: str = None, *args, **kwargs) -> None:
if self.keyring is not NO_KEYRING_ATTACHED:
if self.keyring.checksum_address != (checksum_address or self.checksum_address):
raise self.ConfigurationError("There is already a keyring attached to this configuration.")
return
def read_keyring(self, *args, **kwargs):
if self.checksum_address is None:
if (checksum_address or self.checksum_address) is None:
raise self.ConfigurationError("No account specified to unlock keyring")
self.keyring = NucypherKeyring(keyring_root=self.keyring_dir,
account=self.checksum_address,
self.keyring = NucypherKeyring(keyring_root=self.keyring_dir, # type: str
account=checksum_address or self.checksum_address, # type: str
*args, **kwargs)
def write_keyring(self,
password: str,
encrypting: bool,
wallet: bool,
tls: bool,
host: str,
password: str,
encrypting: bool = True,
wallet: bool = False,
tls: bool = True,
tls_curve: EllipticCurve = None,
) -> NucypherKeyring:
@ -407,8 +533,6 @@ class NodeConfiguration:
self.checksum_address = self.keyring.federated_address
else:
self.checksum_address = self.keyring.checksum_address
if tls:
self.certificate_filepath = self.keyring.certificate_filepath
return self.keyring
@ -425,7 +549,7 @@ class NodeConfiguration:
output_filepath = output_filepath or self.registry_filepath
source = source or self.REGISTRY_SOURCE
if not blank and not self.dev:
if not blank and not self.dev_mode:
# Validate Registry
with open(source, 'r') as registry_file:
try:
@ -443,22 +567,3 @@ class NodeConfiguration:
self.log.debug("Successfully wrote registry to {}".format(output_filepath))
return output_filepath
def connect_to_blockchain(self, provider_uri: str, poa: bool, compile: bool):
if self.federated_only:
raise NodeConfiguration.ConfigurationError("Cannot connect to blockchain in federated mode")
self.blockchain = Blockchain.connect(provider_uri=provider_uri, compile=compile)
if poa is True:
w3 = self.blockchain.interface.w3
w3.middleware_stack.inject(geth_poa_middleware, layer=0)
self.accounts = self.blockchain.interface.w3.eth.accounts
self.log.debug("Established connection to provider {}".format(self.blockchain.interface.provider_uri))
def connect_to_contracts(self) -> None:
"""Initialize contract agency and set them on config"""
self.token_agent = NucypherTokenAgent(blockchain=self.blockchain)
self.miner_agent = MinerAgent(blockchain=self.blockchain)
self.policy_agent = PolicyAgent(blockchain=self.blockchain)
self.log.debug("CLI established connection to nucypher contracts")