def setUp(self): """ Gives us some messages to play with. """ self.uuid = str(uuid4()) self.node = '9876543210abcd'.decode('hex') self.value = 1.234 self.timestamp = time.time() self.expires = self.timestamp + 1000 self.public_key = PUBLIC_KEY self.name = 'a_human_readable_key_name' self.key = construct_key(self.public_key, self.name) self.meta = { 'mime': 'numeric', 'description': 'a test value' } self.version = '0.1' self.sig = generate_signature(self.value, self.timestamp, self.expires, self.name, self.meta, self.version, PRIVATE_KEY) self.message = 'value' self.nodes = (('hash1', '127.0.0.1', 1908, '0.1'), ('hash2', '0.0.0.0', 1908, '0.1')) self.mock_message = Value(self.uuid, self.node, self.key, self.value, self.timestamp, self.expires, self.version, self.public_key, self.name, self.meta, self.sig, self.version)
def setUp(self): """ A message to play with. """ self.uuid = str(uuid4()) self.node = "9876543210abcd".decode("hex") self.value = 1.234 self.timestamp = time.time() self.expires = self.timestamp + 1000 self.public_key = PUBLIC_KEY self.name = "a_human_readable_key_name" self.key = construct_key(self.public_key, self.name) self.meta = {"mime": "numeric", "description": "a test value"} self.sig = generate_signature(self.value, self.timestamp, self.expires, self.name, self.meta, PRIVATE_KEY) self.version = "0.1" self.message = "value" self.mock_value = Value( self.uuid, self.node, self.key, self.value, self.timestamp, self.expires, self.public_key, self.name, self.meta, self.sig, self.version, )
def test_construct_key_empty_name(self): """ Ensures that a DHT key is constructed given only the public key. """ pk_hasher = hashlib.sha512() pk_hasher.update(PUBLIC_KEY) expected = pk_hasher.digest() actual = construct_key(PUBLIC_KEY) self.assertEqual(expected, actual)
def test_validate_message_bad_key_from_name(self): """ Ensure the correct result is returned if the message is invalid because of an incorrect 'key' value with wrong name. """ key = construct_key(PUBLIC_KEY, 'wrong_name') val = Value(1, 1, key, self.value, self.timestamp, self.expires, PUBLIC_KEY, self.name, self.meta, self.signature, self.version) expected = (False, 7) actual = validate_message(val) self.assertEqual(expected, actual)
def send_store(self, contact, public_key, name, value, timestamp, expires, meta, signature): """ Sends a Store message to the given contact. The value contained within the message is stored against a key derived from the public_key and name. Furthermore, the message is cryptographically signed using the value, timestamp, expires, name and meta values. """ uuid = str(uuid4()) compound_key = construct_key(public_key, name) store = Store(uuid, self.id, compound_key, value, timestamp, expires, public_key, name, meta, signature, self.version) return self.send_message(contact, store)
def test_construct_key(self): """ Ensures that a DHT key is constructed correctly given correct inputs. """ name = 'foo/bar.baz' pk_hasher = hashlib.sha512() pk_hasher.update(PUBLIC_KEY) pk_hash = pk_hasher.digest() name_hasher = hashlib.sha512() name_hasher.update(name) name_hash = name_hasher.digest() hasher = hashlib.sha512() hasher.update(pk_hash + name_hash) expected = hasher.digest() actual = construct_key(PUBLIC_KEY, name) self.assertEqual(expected, actual)
def replicate(self, public_key, name, value, timestamp, expires, created_with, meta, signature, duplicate): """ Will replicate args to "duplicate" number of nodes in the distributed hash table. Returns a deferred that will fire with a list of send_store deferreds when "duplicate" number of closest nodes have been identified. Obviously, the list can be turned in to a deferred_list to fire when the store commands have completed. Even if "duplicate" is > K no more than K items will be contained within the list result. """ if duplicate < 1: # Guard to ensure meaningful duplication count. raise ValueError('Duplication count may not be less than 1') result = defer.Deferred() compound_key = construct_key(public_key, name) lookup = NodeLookup(compound_key, FindNode, self) def on_success(nodes): """ A list of close nodes have been found so send store messages to the "duplicate" closest number of them and fire the "result" deferred with the resulting DeferredList of pending deferreds. """ deferreds = self._process_lookup_result(nodes, public_key, name, value, timestamp, expires, created_with, meta, signature, duplicate) result.callback(deferreds) def on_error(error): """ Catch all for errors during the lookup phase. Simply pass them on via the "result" deferred. """ result.errback(error) lookup.addCallback(on_success) lookup.addErrback(on_error) return result
def setUp(self): """ Set some values used in all tests. """ self.signature = ('\x80 \xf6\x155\x93Z\xdf1t*\xc6\xc8b\x9b~\xc0\xa6' + '\xf8\xa7\xc0\xd5\x91\xa2Q\xd7\\\xd1\x1a\x0eX' + '\x855>\xc4\xa3\xa1l\xe26\x9d\x94\x9f\x92\t\xf8' + '\x8f\xe6iblp\x84}\x0cc(\xb7c\xba\x97J\x87u\x9f' + '\xd6\x1a]A\x870\x1df\xe8i\xe8\xbe\xf2\xc6\x8f' + '\xd0\x8f\xd18\xb8\\\xbc\x01\x1a\x1fP\xd6I\x06' + '\xf3K\xb1\x1e@\xc4ma61\xd4\x12\xf4!\x9dm3\x01n' + '\x17\xbcr\xe0\xf4Y-\xc7=\x87\xc4Xv\x84\xfa') self.value = 'value' self.timestamp = 1350544046.084875 self.expires = 1352221970.14242 self.name = 'name' self.meta = {'meta': 'value'} self.version = '0.1' self.key = construct_key(PUBLIC_KEY, self.name)
def setUp(self): """ Set some values used in all tests. """ self.signature = ('\x882f\xf9A\xcd\xf9\xb1\xcc\xdbl\x1c\xb2\xdb' + '\xa3UQ\x9a\x08\x96\x12\x83^d\xd8M\xc2`\x81Hz' + '\x84~\xf4\x9d\x0e\xbd\x81\xc4/\x94\x9dfg\xb2aq' + '\xa6\xf8!k\x94\x0c\x9b\xb5\x8e \xcd\xfb\x87' + '\x83`wu\xeb\xf2\x19\xd6X\xdd\xb3\x98\xb5\xbc#B' + '\xe3\n\x85G\xb4\x9c\x9b\xb0-\xd2B\x83W\xb8\xca' + '\xecv\xa9\xc4\x9d\xd8\xd0\xf1&\x1a\xfaw\xa0\x99' + '\x1b\x84\xdad$\xebO\x1a\x9e:w\x14d_\xe3\x03#\x95' + '\x9d\x10B\xe7\x13') self.value = 'value' self.timestamp = 1350544046.084875 self.expires = 1352221970.14242 self.name = 'name' self.meta = {'meta': 'value'} self.version = '0.1' self.key = construct_key(PUBLIC_KEY, self.name)