mirror of https://github.com/nucypher/nucypher.git
Derive HostingPower from Keyring
parent
4131c8ca0c
commit
5f84157b96
|
@ -1170,7 +1170,7 @@ def ursula(config,
|
|||
click.secho("Running in {} mode".format(config.operating_mode), fg='blue')
|
||||
|
||||
# Bootnodes, Seeds, Known Nodes
|
||||
ursula_config.get_bootnodes()
|
||||
ursula_config.load_bootnodes()
|
||||
quantity_known_nodes = len(ursula_config.known_nodes)
|
||||
if quantity_known_nodes > 0:
|
||||
click.secho("Loaded {} known nodes from storages".format(quantity_known_nodes, fg='blue'))
|
||||
|
|
|
@ -574,7 +574,7 @@ class Character(Learner):
|
|||
|
||||
@property
|
||||
def rest_interface(self):
|
||||
return self._crypto_power.power_ups(TLSHostingPower).rest_server.rest_url()
|
||||
return self.rest_server.rest_url()
|
||||
|
||||
@property
|
||||
def stamp(self):
|
||||
|
|
|
@ -398,7 +398,6 @@ class Ursula(Character, VerifiableNode, Miner):
|
|||
rest_port: int,
|
||||
certificate: Certificate = None,
|
||||
certificate_filepath: str = None,
|
||||
tls_private_key = None, # TODO: Derive from keyring
|
||||
|
||||
db_name: str = None,
|
||||
db_filepath: str = None,
|
||||
|
@ -442,31 +441,32 @@ class Ursula(Character, VerifiableNode, Miner):
|
|||
if is_me is True: # TODO: 340
|
||||
self._stored_treasure_maps = dict()
|
||||
|
||||
#
|
||||
# Staking Ursula
|
||||
#
|
||||
if not federated_only:
|
||||
Miner.__init__(self, is_me=is_me, miner_agent=miner_agent, checksum_address=checksum_address)
|
||||
|
||||
# Access staking node via node's transacting keys
|
||||
# Access staking node via node's transacting keys TODO: Better handle ephemeral staking self ursula
|
||||
blockchain_power = BlockchainPower(blockchain=self.blockchain, account=self.checksum_public_address)
|
||||
self._crypto_power.consume_power_up(blockchain_power)
|
||||
|
||||
# Use blockchain power to substantiate stamp
|
||||
# Use blockchain power to substantiate stamp, instead of signing key
|
||||
self.substantiate_stamp(passphrase=passphrase)
|
||||
|
||||
#
|
||||
# ProxyRESTServer and TLSHostingPower
|
||||
# ProxyRESTServer and TLSHostingPower # TODO: Maybe we want _power_ups to be public after all?
|
||||
#
|
||||
if not crypto_power or (TLSHostingPower not in crypto_power._power_ups):
|
||||
# TODO: Maybe we want _power_ups to be public after all?
|
||||
# We'll hook all the TLS stuff up unless the crypto_power was already passed.
|
||||
|
||||
#
|
||||
# Self-Ursula
|
||||
# Ephemeral Self-Ursula
|
||||
#
|
||||
if is_me:
|
||||
self.suspicious_activities_witnessed = {'vladimirs': [], 'bad_treasure_maps': []}
|
||||
|
||||
#
|
||||
# REST Server
|
||||
# REST Server (Ephemeral Self-Ursula)
|
||||
#
|
||||
rest_routes = ProxyRESTRoutes(
|
||||
db_name=db_name,
|
||||
|
@ -484,62 +484,41 @@ class Ursula(Character, VerifiableNode, Miner):
|
|||
certificate_dir=self.known_certificates_dir,
|
||||
)
|
||||
|
||||
rest_server = ProxyRESTServer(
|
||||
rest_host=rest_host,
|
||||
rest_port=rest_port,
|
||||
routes=rest_routes,
|
||||
)
|
||||
self.rest_url = rest_server.rest_url
|
||||
self.datastore = rest_routes.datastore # TODO: Maybe organize this better?
|
||||
|
||||
#
|
||||
# TLSHostingPower
|
||||
# TLSHostingPower (Ephemeral Self-Ursula)
|
||||
#
|
||||
tls_hosting_keypair = HostingKeypair(
|
||||
curve=tls_curve,
|
||||
host=rest_host,
|
||||
certificate=certificate,
|
||||
certificate_filepath=certificate_filepath,
|
||||
private_key=tls_private_key
|
||||
)
|
||||
|
||||
tls_hosting_power = TLSHostingPower(rest_server=rest_server,
|
||||
keypair=tls_hosting_keypair)
|
||||
tls_hosting_keypair = HostingKeypair(curve=tls_curve, host=rest_host)
|
||||
tls_hosting_power = TLSHostingPower(keypair=tls_hosting_keypair, host=rest_host)
|
||||
self.rest_server = ProxyRESTServer(rest_host=rest_host, rest_port=rest_port,
|
||||
routes=rest_routes, hosting_power=tls_hosting_power)
|
||||
|
||||
#
|
||||
# Stranger-Ursula
|
||||
#
|
||||
else:
|
||||
|
||||
# TLSHostingPower
|
||||
if certificate or certificate_filepath:
|
||||
tls_hosting_power = TLSHostingPower(host=rest_host,
|
||||
public_certificate_filepath=certificate_filepath,
|
||||
public_certificate=certificate)
|
||||
else:
|
||||
tls_hosting_keypair = HostingKeypair(curve=tls_curve, host=rest_host)
|
||||
tls_hosting_power = TLSHostingPower(host=rest_host, keypair=tls_hosting_keypair)
|
||||
|
||||
# REST Server
|
||||
# Unless the caller passed a crypto power,
|
||||
# we'll make our own TLSHostingPower for this stranger.
|
||||
rest_server = ProxyRESTServer(
|
||||
# Unless the caller passed a crypto power we'll make our own TLSHostingPower for this stranger.
|
||||
self.rest_server = ProxyRESTServer(
|
||||
rest_host=rest_host,
|
||||
rest_port=rest_port
|
||||
rest_port=rest_port,
|
||||
hosting_power=tls_hosting_power
|
||||
)
|
||||
|
||||
#
|
||||
# TLSHostingPower
|
||||
#
|
||||
if certificate or certificate_filepath:
|
||||
tls_hosting_power = TLSHostingPower(rest_server=rest_server,
|
||||
certificate_filepath=certificate_filepath,
|
||||
certificate=certificate)
|
||||
else:
|
||||
tls_hosting_keypair = HostingKeypair(
|
||||
curve=tls_curve,
|
||||
host=rest_host,
|
||||
certificate_filepath=certificate_filepath)
|
||||
tls_hosting_power = TLSHostingPower(rest_server=rest_server,
|
||||
keypair=tls_hosting_keypair)
|
||||
|
||||
#
|
||||
# OK - Now we have a ProxyRestServer and a TLSHostingPower for some Ursula
|
||||
#
|
||||
self._crypto_power.consume_power_up(tls_hosting_power) # Consume!
|
||||
|
||||
else:
|
||||
self.log.info("Not adhering rest_server; Using the one on crypto_power.")
|
||||
|
||||
#
|
||||
# Verifiable Node
|
||||
#
|
||||
|
@ -565,7 +544,7 @@ class Ursula(Character, VerifiableNode, Miner):
|
|||
hosting_power = self._crypto_power.power_ups(TLSHostingPower)
|
||||
|
||||
return (
|
||||
hosting_power.rest_server.rest_interface,
|
||||
self.rest_server.rest_interface,
|
||||
hosting_power.keypair.certificate,
|
||||
hosting_power.keypair.pubkey
|
||||
)
|
||||
|
@ -608,7 +587,7 @@ class Ursula(Character, VerifiableNode, Miner):
|
|||
port: int,
|
||||
federated_only: bool = False) -> 'Ursula':
|
||||
|
||||
response = network_middleware.node_information(host, port) # TODO
|
||||
response = network_middleware.node_information(host, port) # TODO: pre-load certificates here?
|
||||
if not response.status_code == 200:
|
||||
raise RuntimeError("Got a bad response: {}".format(response))
|
||||
|
||||
|
@ -686,16 +665,30 @@ class Ursula(Character, VerifiableNode, Miner):
|
|||
def from_storage(cls,
|
||||
node_storage: NodeStorage,
|
||||
checksum_adress: str,
|
||||
federated_only: bool = False, *args, **kwargs) -> 'Ursula':
|
||||
return node_storage.get(checksum_address=checksum_adress)
|
||||
federated_only: bool = False) -> 'Ursula':
|
||||
return node_storage.get(checksum_address=checksum_adress,
|
||||
federated_only=federated_only)
|
||||
|
||||
#
|
||||
# Properties
|
||||
#
|
||||
@property
|
||||
def datastore(self):
|
||||
try:
|
||||
return self.rest_server.routes.datastore
|
||||
except AttributeError:
|
||||
raise AttributeError("No rest server attached")
|
||||
|
||||
@property
|
||||
def rest_url(self):
|
||||
try:
|
||||
return self.rest_server.rest_url
|
||||
except AttributeError:
|
||||
raise AttributeError("No rest server attached")
|
||||
|
||||
@property
|
||||
def rest_app(self):
|
||||
rest_app_on_server = self._crypto_power.power_ups(TLSHostingPower).rest_server.rest_app
|
||||
rest_app_on_server = self.rest_server.rest_app
|
||||
|
||||
if not rest_app_on_server:
|
||||
m = "This Ursula doesn't have a REST app attached. If you want one, init with is_me and attach_server."
|
||||
|
|
|
@ -34,7 +34,6 @@ class UrsulaConfiguration(NodeConfiguration):
|
|||
# TLS
|
||||
tls_curve: EllipticCurve = None,
|
||||
certificate: Certificate = None,
|
||||
tls_private_key: bytes = None, # TODO: from config here
|
||||
certificate_filepath: str = None,
|
||||
|
||||
# Ursula
|
||||
|
@ -63,7 +62,6 @@ class UrsulaConfiguration(NodeConfiguration):
|
|||
self.tls_curve = tls_curve or self.__DEFAULT_TLS_CURVE
|
||||
self.certificate = certificate
|
||||
self.certificate_filepath = certificate_filepath
|
||||
self.tls_private_key = tls_private_key
|
||||
|
||||
# Ursula
|
||||
self.interface_signature = interface_signature
|
||||
|
@ -114,9 +112,6 @@ class UrsulaConfiguration(NodeConfiguration):
|
|||
timestamp=None,
|
||||
miner_agent=self.miner_agent
|
||||
)
|
||||
if not self.temp:
|
||||
tls_private_key = self.keyring.tls_private_key
|
||||
payload.update(dict(tls_private_key=tls_private_key))
|
||||
return {**super().dynamic_payload, **payload}
|
||||
|
||||
def produce(self, passphrase: str = None, **overrides):
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import os
|
||||
from collections import namedtuple
|
||||
from os.path import abspath, dirname
|
||||
|
||||
|
@ -12,12 +11,11 @@ PROJECT_ROOT = abspath(dirname(nucypher.__file__))
|
|||
APP_DIR = AppDirs("nucypher", "NuCypher")
|
||||
DEFAULT_CONFIG_ROOT = APP_DIR.user_data_dir
|
||||
|
||||
#
|
||||
# Bootnodes
|
||||
#
|
||||
Bootnode = namedtuple('Bootnode', ['checksum_address', 'rest_url'])
|
||||
BOOTNODES = (
|
||||
Bootnode('0xDbf2Bc4b81eB46CdDfa52348Ecf3c142841267E0', 'https://18.223.117.103:9151'),
|
||||
)
|
||||
|
||||
# Test Constants # TODO: Tidy up filepath here
|
||||
TEST_CONTRACTS_DIR = os.path.join(BASE_DIR, 'tests', 'blockchain', 'eth', 'contracts', 'contracts')
|
||||
NUMBER_OF_URSULAS_IN_MOCK_NETWORK = 10
|
||||
|
|
|
@ -25,6 +25,7 @@ from umbral.keys import UmbralPrivateKey, UmbralPublicKey
|
|||
from nucypher.config.constants import DEFAULT_CONFIG_ROOT
|
||||
from nucypher.crypto.api import generate_self_signed_certificate
|
||||
from nucypher.crypto.powers import SigningPower, EncryptingPower, KeyPairBasedPower, DerivedKeyBasedPower
|
||||
from nucypher.network.server import TLSHostingPower
|
||||
|
||||
FILE_ENCODING = 'utf-8'
|
||||
|
||||
|
@ -388,19 +389,6 @@ class NucypherKeyring:
|
|||
def __del__(self) -> None:
|
||||
self.lock()
|
||||
|
||||
#
|
||||
# Private Keys
|
||||
#
|
||||
@property
|
||||
@unlock_required
|
||||
def tls_private_key(self):
|
||||
"""TODO: Deprecate and use self.derive_crypto_power instead"""
|
||||
key_data = _read_keyfile(keypath=self.__tls_keypath, deserializer=None)
|
||||
__tls_key = serialization.load_pem_private_key(data=key_data,
|
||||
password=self.__derived_key_material,
|
||||
backend=default_backend())
|
||||
return __tls_key
|
||||
|
||||
#
|
||||
# Public Keys
|
||||
#
|
||||
|
@ -520,10 +508,10 @@ class NucypherKeyring:
|
|||
if issubclass(power_class, KeyPairBasedPower):
|
||||
|
||||
codex = {SigningPower: self.__signing_keypath,
|
||||
EncryptingPower: self.__root_keypath
|
||||
EncryptingPower: self.__root_keypath,
|
||||
TLSHostingPower: self.__tls_keypath, # TODO
|
||||
# BlockchainPower: self.__wallet_path, # TODO
|
||||
# TLSHostingPower: self.__tls_keypath} # TODO
|
||||
}
|
||||
}
|
||||
|
||||
# Create Power
|
||||
try:
|
||||
|
|
|
@ -18,12 +18,11 @@ from cryptography.hazmat.primitives.serialization import Encoding
|
|||
|
||||
from nucypher.characters.lawful import Ursula
|
||||
from nucypher.config.constants import DEFAULT_CONFIG_ROOT, BASE_DIR, BOOTNODES
|
||||
from nucypher.config.keyring import NucypherKeyring, _write_tls_certificate, _read_tls_public_certificate
|
||||
from nucypher.config.keyring import NucypherKeyring, _write_tls_certificate
|
||||
from nucypher.config.storages import NodeStorage, InMemoryNodeStorage
|
||||
from nucypher.crypto.powers import CryptoPowerUp
|
||||
from nucypher.crypto.signing import signature_splitter
|
||||
from nucypher.network.middleware import RestMiddleware
|
||||
from nucypher.network.nodes import VerifiableNode
|
||||
|
||||
|
||||
class NodeConfiguration:
|
||||
|
@ -395,7 +394,7 @@ class NodeConfiguration:
|
|||
curve=tls_curve,
|
||||
keyring_root=self.keyring_dir)
|
||||
|
||||
# TODO: Operating mode switch
|
||||
# TODO: Operating mode switch #466
|
||||
if self.federated_only or not wallet:
|
||||
self.checksum_address = self.keyring.federated_address
|
||||
else:
|
||||
|
|
|
@ -24,8 +24,11 @@ class ProxyRESTServer:
|
|||
def __init__(self,
|
||||
rest_host: str,
|
||||
rest_port: int,
|
||||
hosting_power = None,
|
||||
routes: 'ProxyRESTRoutes' = None,
|
||||
) -> None:
|
||||
|
||||
self.routes = routes
|
||||
self.rest_interface = InterfaceInfo(host=rest_host, port=rest_port)
|
||||
if routes: # if is me
|
||||
self.rest_app = routes.rest_app
|
||||
|
@ -33,6 +36,8 @@ class ProxyRESTServer:
|
|||
else:
|
||||
self.rest_app = constants.PUBLIC_ONLY
|
||||
|
||||
self.__hosting_power = hosting_power
|
||||
|
||||
def rest_url(self):
|
||||
return "{}:{}".format(self.rest_interface.host, self.rest_interface.port)
|
||||
|
||||
|
@ -291,18 +296,17 @@ class TLSHostingPower(KeyPairBasedPower):
|
|||
not_found_error = NoHostingPower
|
||||
|
||||
def __init__(self,
|
||||
rest_server,
|
||||
certificate=None,
|
||||
certificate_filepath=None,
|
||||
host: str,
|
||||
public_certificate=None,
|
||||
public_certificate_filepath=None,
|
||||
*args, **kwargs) -> None:
|
||||
|
||||
if certificate and certificate_filepath:
|
||||
if public_certificate and public_certificate_filepath:
|
||||
# TODO: Design decision here: if they do pass both, and they're identical, do we let that slide?
|
||||
raise ValueError("Pass either a certificate or a certificate_filepath, not both.")
|
||||
raise ValueError("Pass either a public_certificate or a public_certificate_filepath, not both.")
|
||||
|
||||
if certificate:
|
||||
kwargs['keypair'] = HostingKeypair(certificate=certificate, host=rest_server.rest_interface.host)
|
||||
elif certificate_filepath:
|
||||
kwargs['keypair'] = HostingKeypair(certificate_filepath=certificate_filepath)
|
||||
self.rest_server = rest_server
|
||||
if public_certificate:
|
||||
kwargs['keypair'] = HostingKeypair(certificate=public_certificate, host=host)
|
||||
elif public_certificate_filepath:
|
||||
kwargs['keypair'] = HostingKeypair(certificate_filepath=public_certificate_filepath, host=host)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
|
|
@ -16,7 +16,7 @@ from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
|
|||
from nucypher.blockchain.eth.registry import TemporaryEthereumContractRegistry
|
||||
from nucypher.blockchain.eth.sol.compile import SolidityCompiler
|
||||
from nucypher.config.characters import UrsulaConfiguration, AliceConfiguration, BobConfiguration
|
||||
from nucypher.config.constants import TEST_CONTRACTS_DIR
|
||||
from nucypher.config.constants import BASE_DIR
|
||||
from nucypher.config.node import NodeConfiguration
|
||||
from nucypher.data_sources import DataSource
|
||||
from nucypher.keystore import keystore
|
||||
|
@ -29,6 +29,8 @@ from nucypher.utilities.sandbox.constants import (DEFAULT_NUMBER_OF_URSULAS_IN_D
|
|||
from nucypher.utilities.sandbox.middleware import MockRestMiddleware
|
||||
from nucypher.utilities.sandbox.ursula import make_federated_ursulas, make_decentralized_ursulas
|
||||
|
||||
TEST_CONTRACTS_DIR = os.path.join(BASE_DIR, 'tests', 'blockchain', 'eth', 'contracts', 'contracts')
|
||||
|
||||
|
||||
#
|
||||
# Temporary
|
||||
|
|
Loading…
Reference in New Issue