mirror of https://github.com/nucypher/nucypher.git
Shifting things around a bit, introducing ProxyRESTRoutes, and starting to implmenet rest_information().
parent
a6baa8c2c7
commit
d2250b2a84
|
@ -1092,12 +1092,12 @@ class Ursula(Character, VerifiableNode, Miner):
|
||||||
blockchain_power = BlockchainPower(blockchain=self.blockchain, account=self.checksum_public_address)
|
blockchain_power = BlockchainPower(blockchain=self.blockchain, account=self.checksum_public_address)
|
||||||
self._crypto_power.consume_power_up(blockchain_power)
|
self._crypto_power.consume_power_up(blockchain_power)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
rest_server = ProxyRESTServer(
|
rest_server = ProxyRESTServer(
|
||||||
rest_host=rest_host,
|
rest_host=rest_host,
|
||||||
rest_port=rest_port,
|
rest_port=rest_port,
|
||||||
db_name=db_name,
|
db_name=db_name,
|
||||||
tls_private_key=tls_private_key,
|
|
||||||
tls_curve=tls_curve,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
tls_hosting_keypair = HostingKeypair(
|
tls_hosting_keypair = HostingKeypair(
|
||||||
|
@ -1117,9 +1117,18 @@ class Ursula(Character, VerifiableNode, Miner):
|
||||||
if not federated_only:
|
if not federated_only:
|
||||||
self.substantiate_stamp()
|
self.substantiate_stamp()
|
||||||
|
|
||||||
|
def rest_information(self):
|
||||||
|
hosting_power = self._crypto_power.power_ups(TLSHostingPower)
|
||||||
|
|
||||||
|
return (
|
||||||
|
hosting_power.rest_server.rest_interface,
|
||||||
|
hosting_power.keypair.certificate,
|
||||||
|
hosting_power.keypair.pubkey
|
||||||
|
)
|
||||||
|
|
||||||
def __bytes__(self):
|
def __bytes__(self):
|
||||||
|
|
||||||
interface_info = VariableLengthBytestring(self.rest_interface)
|
interface_info = VariableLengthBytestring(self.rest_information()[0])
|
||||||
|
|
||||||
if self.dht_interface:
|
if self.dht_interface:
|
||||||
interface_info += VariableLengthBytestring(self.dht_interface)
|
interface_info += VariableLengthBytestring(self.dht_interface)
|
||||||
|
@ -1218,11 +1227,13 @@ class Ursula(Character, VerifiableNode, Miner):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rest_app(self):
|
def rest_app(self):
|
||||||
if not self._rest_app:
|
rest_app_on_server = self._crypto_power.power_ups(TLSHostingPower).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."
|
m = "This Ursula doesn't have a REST app attached. If you want one, init with is_me and attach_server."
|
||||||
raise AttributeError(m)
|
raise AttributeError(m)
|
||||||
else:
|
else:
|
||||||
return self._rest_app
|
return rest_app_on_server
|
||||||
|
|
||||||
def interface_info_with_metadata(self):
|
def interface_info_with_metadata(self):
|
||||||
# TODO: Do we ever actually use this without using the rest of the serialized Ursula? 337
|
# TODO: Do we ever actually use this without using the rest of the serialized Ursula? 337
|
||||||
|
|
|
@ -87,8 +87,8 @@ class VerifiableNode:
|
||||||
self.validate_metadata(accept_federated_only) # This is both the stamp and interface check.
|
self.validate_metadata(accept_federated_only) # This is both the stamp and interface check.
|
||||||
|
|
||||||
# The node's metadata is valid; let's be sure the interface is in order.
|
# The node's metadata is valid; let's be sure the interface is in order.
|
||||||
response = network_middleware.node_information(host=self.rest_interface.host,
|
response = network_middleware.node_information(host=self.rest_information()[0].host,
|
||||||
port=self.rest_interface.port)
|
port=self.rest_information()[0].port)
|
||||||
if not response.status_code == 200:
|
if not response.status_code == 200:
|
||||||
raise RuntimeError("Or something.") # TODO: Raise an error here? Or return False? Or something?
|
raise RuntimeError("Or something.") # TODO: Raise an error here? Or return False? Or something?
|
||||||
signature, identity_evidence, verifying_key, encrypting_key, public_address, rest_info, dht_info = self._internal_splitter(response.content)
|
signature, identity_evidence, verifying_key, encrypting_key, public_address, rest_info, dht_info = self._internal_splitter(response.content)
|
||||||
|
@ -112,7 +112,7 @@ class VerifiableNode:
|
||||||
self._evidence_of_decentralized_identity = signature
|
self._evidence_of_decentralized_identity = signature
|
||||||
|
|
||||||
def _signable_interface_info_message(self):
|
def _signable_interface_info_message(self):
|
||||||
message = self.canonical_public_address + self.rest_interface + self.dht_interface
|
message = self.canonical_public_address + self.rest_information()[0] + self.dht_interface
|
||||||
return message
|
return message
|
||||||
|
|
||||||
def _sign_interface_info(self):
|
def _sign_interface_info(self):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import binascii
|
import binascii
|
||||||
import random
|
import random
|
||||||
from typing import ClassVar
|
from logging import getLogger
|
||||||
|
|
||||||
import kademlia
|
import kademlia
|
||||||
from apistar import http, Route, App
|
from apistar import http, Route, App
|
||||||
|
@ -101,33 +101,47 @@ class NucypherSeedOnlyDHTServer(NucypherDHTServer):
|
||||||
|
|
||||||
|
|
||||||
class ProxyRESTServer:
|
class ProxyRESTServer:
|
||||||
|
log = getLogger("characters")
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
rest_host=None,
|
rest_host,
|
||||||
rest_port=None,
|
rest_port,
|
||||||
db_name=None,
|
routes,
|
||||||
tls_private_key=None,
|
) -> None:
|
||||||
tls_curve=None,
|
|
||||||
certificate=None,
|
|
||||||
common_name=None,
|
|
||||||
*args, ** kwargs) -> None:
|
|
||||||
self.rest_interface = InterfaceInfo(host=rest_host, port=rest_port)
|
self.rest_interface = InterfaceInfo(host=rest_host, port=rest_port)
|
||||||
|
|
||||||
|
def start_datastore(self, db_name):
|
||||||
|
if not db_name:
|
||||||
|
raise TypeError("In order to start a datastore, you need to supply a db_name.")
|
||||||
|
|
||||||
|
from nucypher.keystore import keystore
|
||||||
|
from nucypher.keystore.db import Base
|
||||||
|
from sqlalchemy.engine import create_engine
|
||||||
|
|
||||||
|
self.log.info("Starting datastore {}".format(db_name))
|
||||||
|
engine = create_engine('sqlite:///{}'.format(db_name))
|
||||||
|
Base.metadata.create_all(engine)
|
||||||
|
self.datastore = keystore.KeyStore(engine)
|
||||||
|
self.db_engine = engine
|
||||||
|
|
||||||
|
def rest_url(self):
|
||||||
|
return "{}:{}".format(self.rest_information()[0].host, self.rest_information()[0].port)
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
# Actual REST Endpoints and utilities
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
def get_deployer(self):
|
||||||
|
deployer = self._crypto_power.power_ups(TLSHostingPower).get_deployer(rest_app=self._rest_app,
|
||||||
|
port=self.rest_information()[0].port)
|
||||||
|
return deployer
|
||||||
|
|
||||||
|
|
||||||
|
class ProxyRESTRoutes:
|
||||||
|
|
||||||
|
def __init__(self, db_name=None):
|
||||||
|
|
||||||
self.db_name = db_name
|
self.db_name = db_name
|
||||||
self._rest_app = None
|
|
||||||
|
|
||||||
def public_material(self, power_class: ClassVar):
|
|
||||||
"""Implemented on Ursula"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def canonical_public_address(self):
|
|
||||||
"""Implemented on Ursula"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def stamp(self, *args, **kwargs):
|
|
||||||
"""Implemented on Ursula"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def attach_rest_server(self):
|
|
||||||
|
|
||||||
routes = [
|
routes = [
|
||||||
Route('/kFrag/{id_as_hex}',
|
Route('/kFrag/{id_as_hex}',
|
||||||
|
@ -156,27 +170,6 @@ class ProxyRESTServer:
|
||||||
self._rest_app = App(routes=routes)
|
self._rest_app = App(routes=routes)
|
||||||
self.start_datastore(self.db_name)
|
self.start_datastore(self.db_name)
|
||||||
|
|
||||||
def start_datastore(self, db_name):
|
|
||||||
if not db_name:
|
|
||||||
raise TypeError("In order to start a datastore, you need to supply a db_name.")
|
|
||||||
|
|
||||||
from nucypher.keystore import keystore
|
|
||||||
from nucypher.keystore.db import Base
|
|
||||||
from sqlalchemy.engine import create_engine
|
|
||||||
|
|
||||||
self.log.info("Starting datastore {}".format(db_name))
|
|
||||||
engine = create_engine('sqlite:///{}'.format(db_name))
|
|
||||||
Base.metadata.create_all(engine)
|
|
||||||
self.datastore = keystore.KeyStore(engine)
|
|
||||||
self.db_engine = engine
|
|
||||||
|
|
||||||
def rest_url(self):
|
|
||||||
return "{}:{}".format(self.rest_interface.host, self.rest_interface.port)
|
|
||||||
|
|
||||||
#####################################
|
|
||||||
# Actual REST Endpoints and utilities
|
|
||||||
#####################################
|
|
||||||
|
|
||||||
def public_information(self):
|
def public_information(self):
|
||||||
"""
|
"""
|
||||||
REST endpoint for public keys and address..
|
REST endpoint for public keys and address..
|
||||||
|
@ -331,11 +324,6 @@ class ProxyRESTServer:
|
||||||
self.log.info("Bad TreasureMap ID; not storing {}".format(treasure_map_id))
|
self.log.info("Bad TreasureMap ID; not storing {}".format(treasure_map_id))
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
def get_deployer(self):
|
|
||||||
deployer = self._crypto_power.power_ups(TLSHostingPower).get_deployer(rest_app=self._rest_app,
|
|
||||||
port=self.rest_interface.port)
|
|
||||||
return deployer
|
|
||||||
|
|
||||||
|
|
||||||
class TLSHostingPower(KeyPairBasedPower):
|
class TLSHostingPower(KeyPairBasedPower):
|
||||||
_keypair_class = HostingKeypair
|
_keypair_class = HostingKeypair
|
||||||
|
|
|
@ -96,7 +96,10 @@ def make_ursulas(ether_addresses: list,
|
||||||
ursula.federated_only = True
|
ursula.federated_only = True
|
||||||
|
|
||||||
ursulas.add(ursula)
|
ursulas.add(ursula)
|
||||||
_TEST_KNOWN_URSULAS_CACHE[ursula.rest_information().port] = ursula
|
|
||||||
|
# Store this Ursula in our global cache.
|
||||||
|
port = ursula.rest_information()[0].port
|
||||||
|
_TEST_KNOWN_URSULAS_CACHE[port] = ursula
|
||||||
|
|
||||||
if know_each_other and not bare:
|
if know_each_other and not bare:
|
||||||
|
|
||||||
|
@ -108,7 +111,7 @@ def make_ursulas(ether_addresses: list,
|
||||||
event_loop.run_until_complete(
|
event_loop.run_until_complete(
|
||||||
ursula.dht_server.bootstrap(
|
ursula.dht_server.bootstrap(
|
||||||
[("localhost", starting_port + _c) for _c in range(len(ursulas))]))
|
[("localhost", starting_port + _c) for _c in range(len(ursulas))]))
|
||||||
ursula.publish_dht_information()
|
# ursula.publish_dht_information()
|
||||||
|
|
||||||
return ursulas
|
return ursulas
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue