From 6b6e07ec4648b847e357f75e2cbea6f1648920b0 Mon Sep 17 00:00:00 2001 From: jMyles Date: Sat, 18 Jan 2020 01:22:05 -0800 Subject: [PATCH] An empty or intentionally misleading TreasureMap warrants a more severe Exception than NotEnoughUrsulas: introducing TreasureMap.IsDisorienting --- nucypher/policy/collections.py | 15 +++++++++++---- .../blockchain/test_rpc_control_blockchain.py | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/nucypher/policy/collections.py b/nucypher/policy/collections.py index b1358b99e..7db128f2b 100644 --- a/nucypher/policy/collections.py +++ b/nucypher/policy/collections.py @@ -23,7 +23,7 @@ from typing import List, Optional, Tuple import maya import msgpack -from bytestring_splitter import BytestringSplitter, VariableLengthBytestring +from bytestring_splitter import BytestringSplitter, VariableLengthBytestring, BytestringSplittingError from constant_sorrow.constants import CFRAG_NOT_RETAINED from constant_sorrow.constants import NO_DECRYPTION_PERFORMED from cryptography.hazmat.backends.openssl import backend @@ -61,6 +61,11 @@ class TreasureMap: Called when no known nodes have it. """ + class IsDisorienting(NotFound): + """ + Called when an oriented TreasureMap lists fewer than m destinations. + """ + node_id_splitter = BytestringSplitter((to_checksum_address, int(PUBLIC_ADDRESS_LENGTH)), ID_LENGTH) from nucypher.crypto.signing import InvalidSignature # Raised when the public signature (typically intended for Ursula) is not valid. @@ -201,13 +206,15 @@ class TreasureMap: raise self.InvalidSignature( "This TreasureMap does not contain the correct signature from Alice to Bob.") else: - m = map_in_the_clear[0] self._m = map_in_the_clear[0] - if self._m > 0: + try: self._destinations = dict(self.node_id_splitter.repeat(map_in_the_clear[1:])) - else: + except BytestringSplittingError: self._destinations = {} + if len(self._destinations) < self._m or self._m == 0: + raise self.IsDisorienting(f"TreasureMap lists only {len(self._destinations)} destination, but requires interaction with {self._m} nodes.") + def __eq__(self, other): return bytes(self) == bytes(other) diff --git a/tests/characters/control/blockchain/test_rpc_control_blockchain.py b/tests/characters/control/blockchain/test_rpc_control_blockchain.py index 56d161861..f875a7a81 100644 --- a/tests/characters/control/blockchain/test_rpc_control_blockchain.py +++ b/tests/characters/control/blockchain/test_rpc_control_blockchain.py @@ -146,5 +146,5 @@ def test_bob_rpc_character_control_retrieve_with_tmap( b'Wrong!') tmap_64 = b64encode(bytes(wrong_tmap)).decode() params['treasure_map'] = tmap_64 - with pytest.raises(Ursula.NotEnoughUrsulas): + with pytest.raises(TreasureMap.IsDisorienting): bob_rpc_controller.send(request_data)