diff --git a/nucypher/network/protocols.py b/nucypher/network/protocols.py index 9cb31bd5f..3cec6de11 100644 --- a/nucypher/network/protocols.py +++ b/nucypher/network/protocols.py @@ -7,7 +7,6 @@ from kademlia.utils import digest from bytestring_splitter import VariableLengthBytestring from constant_sorrow import default_constant_splitter, constants -from nucypher.crypto.api import keccak_digest from nucypher.network.routing import NucypherRoutingTable @@ -58,7 +57,8 @@ class NucypherHashProtocol(KademliaProtocol): if header == constants.BYTESTRING_IS_URSULA_IFACE_INFO: from nucypher.characters import Ursula - stranger_ursula = Ursula.from_bytes(payload, federated_only=True) # TODO: Is federated_only the right thing here? + stranger_ursula = Ursula.from_bytes(payload, + federated_only=True) # TODO: Is federated_only the right thing here? if stranger_ursula.verify_interface() and key == digest(stranger_ursula.canonical_public_address): self.sourceNode._node_storage[key] = stranger_ursula # TODO: 340 @@ -128,7 +128,6 @@ class NucypherSeedOnlyProtocol(NucypherHashProtocol): class InterfaceInfo: - expected_bytes_length = lambda: VariableLengthBytestring def __init__(self, host, port): @@ -150,6 +149,3 @@ class InterfaceInfo: def __radd__(self, other): return bytes(other) + bytes(self) - - -ursula_interface_splitter = dht_value_splitter + BytestringSplitter(InterfaceInfo) * 2 diff --git a/nucypher/network/server.py b/nucypher/network/server.py index 3c27e4079..5582de76d 100644 --- a/nucypher/network/server.py +++ b/nucypher/network/server.py @@ -273,37 +273,41 @@ class ProxyRESTServer: return Response(content=cfrag_byte_stream, headers=headers) - def provide_treasure_map(self, treasure_map_id_as_hex): - # For now, grab the TreasureMap for the DHT storage. Soon, no do that. #TODO! - treasure_map_id = binascii.unhexlify(treasure_map_id_as_hex) + def provide_treasure_map(self, treasure_map_id): headers = {'Content-Type': 'application/octet-stream'} try: - treasure_map_bytes = self.dht_server.storage[digest(treasure_map_id)] - response = Response(content=treasure_map_bytes, headers=headers) + treasure_map = self.treasure_maps[digest(treasure_map_id)] + response = Response(content=bytes(treasure_map), headers=headers) + self.log.info("{} providing TreasureMap {}".format(self, treasure_map_id)) except KeyError: + self.log.info("{} doesn't have requested TreasureMap {}".format(self, treasure_map_id)) response = Response("No Treasure Map with ID {}".format(treasure_map_id), status_code=404, headers=headers) return response - def receive_treasure_map(self, treasure_map_id_as_hex, request: http.Request): - # TODO: This function is the epitome of #172. - treasure_map_id = binascii.unhexlify(treasure_map_id_as_hex) + def receive_treasure_map(self, treasure_map_id, request: http.Request): + from nucypher.policy.models import TreasureMap + + try: + treasure_map = TreasureMap.from_bytes( + bytes_representation=request.body, + verify=True) + except TreasureMap.InvalidPublicSignature: + do_store = False + else: + do_store = treasure_map.public_id() == treasure_map_id - header, signature_for_ursula, pubkey_sig_alice, ether_address, hrac, tmap_message_kit = \ - dht_with_hrac_splitter(request.body, return_remainder=True) - # TODO: This next line is possibly the worst in the entire codebase at the moment. #172. - # Also TODO: TTL? - do_store = self.dht_server.protocol.determine_legality_of_dht_key( - signature_for_ursula, pubkey_sig_alice, - hrac, digest(treasure_map_id), request.body) if do_store: - # TODO: Stop storing things in the protocol storage. Do this better. #227 - # TODO: Propagate to other nodes. #235 - # TODO: Store the ether address? - self.dht_server.protocol.storage[digest(treasure_map_id)] = request.body - return # TODO: Proper response here. + self.log.info("{} storing TreasureMap {}".format(self, treasure_map_id)) + self.dht_server.set_now(binascii.unhexlify(treasure_map_id), + constants.BYTESTRING_IS_TREASURE_MAP + bytes(treasure_map)) + + # TODO 341 - what if we already have this TreasureMap? + self.treasure_maps[digest(treasure_map_id)] = treasure_map + return Response(content=bytes(treasure_map), status_code=202) else: # TODO: Make this a proper 500 or whatever. + self.log.info("Bad TreasureMap ID; not storing {}".format(treasure_map_id)) assert False