示例#1
0
    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
示例#2
0
    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
示例#3
0
 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
示例#4
0
    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)
示例#5
0
 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"]
示例#6
0
        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
示例#7
0
        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
示例#8
0
 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
示例#9
0
        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)
示例#11
0
 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)
示例#12
0
        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)