def _handleFoundValues(self, values): """ We got some values! Exciting. But let's make sure they're all the same or freak out a little bit. Also, make sure we tell the nearest node that *didn't* have the value to store it. """ value_dict = defaultdict(list) ttl_dict = defaultdict(list) for v in values: try: d = objects.Value() d.ParseFromString(v) value_dict[d.valueKey].append(d.serializedData) ttl_dict[d.valueKey].append(d.ttl) except Exception: pass value = [] for k, v in value_dict.items(): ttl = ttl_dict[k] if len(v) > 1: valueCounts = Counter(v) v = [valueCounts.most_common(1)[0][0]] ttlCounts = Counter(ttl_dict[k]) ttl = [ttlCounts.most_common(1)[0][0]] val = objects.Value() val.valueKey = k val.serializedData = v[0] val.ttl = ttl[0] value.append(val.SerializeToString()) if self.saveToNearestWitoutValue: ds = [] peerToSaveTo = self.nearestWithoutValue.popleft() if peerToSaveTo is not None: for v in value: try: val = objects.Value() val.ParseFromString(v) ds.append( self.protocol.callStore(peerToSaveTo, self.node.id, val.valueKey, val.serializedData, val.ttl)) except Exception: pass return defer.gatherResults(ds).addCallback(lambda _: value) return value
def _handleFoundValues(self, values): """ We got some values! Exciting. But let's make sure they're all the same or freak out a little bit. Also, make sure we tell the nearest node that *didn't* have the value to store it. """ valueCounts = Counter(values) if len(valueCounts) != 1: args = (self.node.long_id, str(values)) self.log.warning("got multiple values for key %i: %s" % args) value = valueCounts.most_common(1)[0][0] ds = [] peerToSaveTo = self.nearestWithoutValue.popleft() if peerToSaveTo is not None: for v in value: try: val = objects.Value() val.ParseFromString(v) ds.append( self.protocol.callStore(peerToSaveTo, self.node.id, val.valueKey, val.serializedData)) except Exception: pass return defer.gatherResults(ds).addCallback(lambda _: value) return value
def parse_messages(messages): if messages is not None: for message in messages: try: value = objects.Value() value.ParseFromString(message) try: box = Box(PrivateKey(self.signing_key.encode()), PublicKey(value.valueKey)) ciphertext = value.serializedData plaintext = box.decrypt(ciphertext) p = objects.Plaintext_Message() p.ParseFromString(plaintext) signature = p.signature p.ClearField("signature") verify_key = nacl.signing.VerifyKey(p.signed_pubkey[64:]) verify_key.verify(p.SerializeToString(), signature) h = nacl.hash.sha512(p.signed_pubkey) pow_hash = h[64:128] if int(pow_hash[:6], 16) >= 50 or hexlify(p.sender_guid) != h[:40]: raise Exception('Invalid guid') listener.notify(p.sender_guid, p.encryption_pubkey, p.subject, objects.Plaintext_Message.Type.Name(p.type), p.message) except Exception: pass signature = self.signing_key.sign(value.valueKey)[:64] self.kserver.delete(self.kserver.node.id, value.valueKey, signature) except Exception: pass
def test_rpc_find_value(self): self._connecting_to_connected() self.protocol.router.addContact(self.protocol.sourceNode) # Set a value to find m = message.Message() m.messageID = digest("msgid") m.sender.MergeFrom(self.protocol.sourceNode.getProto()) m.command = message.Command.Value("STORE") m.protoVer = self.version m.arguments.extend([ digest("Keyword"), "Key", self.protocol.sourceNode.getProto().SerializeToString(), str(10) ]) m.signature = self.signing_key.sign(m.SerializeToString())[:64] data = m.SerializeToString() self.handler.on_connection_made() self.handler.receive_message(data) self.assertTrue( self.storage.getSpecific(digest("Keyword"), "Key") == self.protocol.sourceNode.getProto().SerializeToString()) # Send the find_value rpc m = message.Message() m.messageID = digest("msgid") m.sender.MergeFrom(self.protocol.sourceNode.getProto()) m.command = message.Command.Value("FIND_VALUE") m.protoVer = self.version m.testnet = False m.arguments.append(digest("Keyword")) m.signature = self.signing_key.sign(m.SerializeToString())[:64] data = m.SerializeToString() self.handler.receive_message(data) del m.arguments[-1] value = objects.Value() value.valueKey = "Key" value.serializedData = self.protocol.sourceNode.getProto( ).SerializeToString() value.ttl = 10 m.arguments.append("value") m.arguments.append(value.SerializeToString()) m.ClearField("signature") expected_message = m.SerializeToString() self.clock.advance(100 * constants.PACKET_TIMEOUT) connection.REACTOR.runUntilCurrent() m_calls = self.proto_mock.send_datagram.call_args_list sent_packets = tuple( packet.Packet.from_bytes(call[0][0]) for call in self.proto_mock.send_datagram.call_args_list) received_message = sent_packets[1].payload a = message.Message() a.ParseFromString(received_message) a.ClearField("signature") received_message = a.SerializeToString() self.assertEqual(received_message, expected_message) self.assertEqual(len(m_calls), 3)
def rpc_values(self, sender, *serialized_values): self.addToRouter(sender) for val in serialized_values[:100]: try: v = objects.Value() v.ParseFromString(val) self.storage[v.keyword] = (v.valueKey, v.serializedData, int(v.ttl)) except Exception: pass return ["True"]
def parse_response(moderators): if moderators is not None: m.clear_all() def parse_profile(profile, node): if profile is not None: # TODO: should check signatures here before entering in database m.save_moderator(node.id.encode("hex"), node.pubkey, profile.bitcoin_key.public_key, profile.bitcoin_key.signature, profile.name, profile.avatar_hash, profile.moderation_fee, profile.handle, profile.short_description) moderator = { "id": message_id, "moderator": { "guid": node.id.encode("hex"), "name": profile.name, "handle": profile.handle, "short_description": profile.short_description, "avatar_hash": profile.avatar_hash.encode("hex"), "about": profile.about, "fee": profile.moderation_fee } } self.transport.write( str( bleach.clean(json.dumps(moderator, indent=4), tags=ALLOWED_TAGS))) else: m.delete_moderator(node.id) for mod in moderators: try: val = objects.Value() val.ParseFromString(mod) n = objects.Node() n.ParseFromString(val.serializedData) node_to_ask = Node( n.guid, n.nodeAddress.ip, n.nodeAddress.port, n.publicKey, None if not n.HasField("relayAddress") else (n.relayAddress.ip, n.relayAddress.port), n.natType, n.vendor) if n.guid == KeyChain(self.factory.db).guid: parse_profile( Profile(self.factory.db).get(), node_to_ask) else: self.factory.mserver.get_profile(node_to_ask)\ .addCallback(parse_profile, node_to_ask) except Exception: pass
def handle_result(result): print "JSONRPC result:", result for mod in result: try: val = objects.Value() val.ParseFromString(mod) node = objects.Node() node.ParseFromString(val.serializedData) print node except Exception as e: print 'malformed protobuf', e.message
def parse_messages(messages): if messages is not None: self.log.info("retrieved %s message(s) from the dht" % len(messages)) for message in messages: try: value = objects.Value() value.ParseFromString(message) try: box = Box(PrivateKey(self.signing_key.encode()), PublicKey(value.valueKey)) ciphertext = value.serializedData plaintext = box.decrypt(ciphertext).decode("zlib") p = objects.Plaintext_Message() p.ParseFromString(plaintext) signature = p.signature p.ClearField("signature") verify_key = nacl.signing.VerifyKey( p.signed_pubkey[64:]) verify_key.verify(p.SerializeToString(), signature) h = nacl.hash.sha512(p.signed_pubkey) pow_hash = h[64:128] if int(pow_hash[:6], 16) >= 50 or p.sender_guid.encode( "hex") != h[:40]: raise Exception('Invalid guid') if p.type == objects.Plaintext_Message.Type.Value( "ORDER_CONFIRMATION"): c = Contract(self.db, hash_value=p.subject) c.accept_order_confirmation( self.protocol.get_notification_listener(), confirmation_json=p.message) elif p.type == objects.Plaintext_Message.Type.Value( "RECEIPT"): c = Contract(self.db, hash_value=p.subject) c.accept_receipt( self.protocol.get_notification_listener(), self.protocol.multiplexer.blockchain, receipt_json=p.message) else: listener.notify(p, signature) except Exception: pass signature = self.signing_key.sign(value.valueKey)[:64] self.kserver.delete(self.kserver.node.id, value.valueKey, signature) except Exception: pass
def parse_response(moderators): if moderators is not None: m.clear_all() def parse_profile(profile, node): if profile is not None: m.save_moderator( node.id.encode("hex"), node.signed_pubkey, profile.encryption_key.public_key, profile.encryption_key.signature, profile.bitcoin_key.public_key, profile.bitcoin_key.signature, profile.name, profile.avatar_hash, profile.moderation_fee, profile.handle, profile.short_description) moderator = { "id": message_id, "moderator": { "guid": node.id.encode("hex"), "name": profile.name, "handle": profile.handle, "short_description": profile.short_description, "avatar_hash": profile.avatar_hash.encode("hex"), "about": profile.about, "fee": profile.moderation_fee } } self.sendMessage(json.dumps(moderator, indent=4), False) else: m.delete_moderator(node.id) for mod in moderators: try: val = objects.Value() val.ParseFromString(mod) n = objects.Node() n.ParseFromString(val.serializedData) node_to_ask = Node(n.guid, n.ip, n.port, n.signedPublicKey) if n.guid == KeyChain(self.factory.db).guid: parse_profile( Profile(self.factory.db).get(), node_to_ask) else: self.factory.mserver.get_profile(node_to_ask)\ .addCallback(parse_profile, node_to_ask) except Exception: pass
def test_rpc_find_value(self): self._connecting_to_connected() # Set a value to find m = message.Message() m.messageID = digest("msgid") m.sender.MergeFrom(self.protocol.sourceNode.getProto()) m.command = message.Command.Value("STORE") m.arguments.extend([ digest("Keyword"), "Key", self.protocol.sourceNode.getProto().SerializeToString() ]) data = m.SerializeToString() self.handler.receive_message(data) self.assertTrue( self.storage.getSpecific(digest("Keyword"), "Key") == self.protocol.sourceNode.getProto().SerializeToString()) # Send the find_value rpc m = message.Message() m.messageID = digest("msgid") m.sender.MergeFrom(self.protocol.sourceNode.getProto()) m.command = message.Command.Value("FIND_VALUE") m.arguments.append(digest("Keyword")) data = m.SerializeToString() self.handler.receive_message(data) del m.arguments[-1] value = objects.Value() value.valueKey = "Key" value.serializedData = self.protocol.sourceNode.getProto( ).SerializeToString() m.arguments.append("value") m.arguments.append(value.SerializeToString()) expected_message = m.SerializeToString() self.clock.advance(100 * constants.PACKET_TIMEOUT) connection.REACTOR.runUntilCurrent() m_calls = self.proto_mock.send_datagram.call_args_list sent_packets = tuple( packet.Packet.from_bytes(call[0][0]) for call in self.proto_mock.send_datagram.call_args_list) received_message = sent_packets[1].payload self.assertEqual(received_message, expected_message) self.assertEqual(len(m_calls), 3)
def send_values(inv_list): values = [] if inv_list[0]: for requested_inv in inv_list[1]: try: i = objects.Inv() i.ParseFromString(requested_inv) value = self.storage.getSpecific(i.keyword, i.valueKey) if value is not None: v = objects.Value() v.keyword = i.keyword v.valueKey = i.valueKey v.serializedData = value v.ttl = int(round(self.storage.get_ttl(i.keyword, i.valueKey))) values.append(v.SerializeToString()) except Exception: pass if len(values) > 0: self.callValues(node, values)
def parse_response(moderators): if moderators is None: return None def parse_profiles(responses): for k, v in responses.items(): if v is None: del responses[k] return responses ds = {} for mod in moderators: try: val = objects.Value() val.ParseFromString(mod) n = objects.Node() n.ParseFromString(val.serializedData) ds[val.serializedData] = self.get_profile(node.Node(n.guid, n.ip, n.port, n.signedPublicKey)) except Exception: pass return deferredDict(ds).addCallback(parse_profiles)