def test_callFindNode(self):
        self._connecting_to_connected()

        n = Node(digest("S"), self.addr1[0], self.addr1[1])
        self.wire_protocol[self.addr1] = self.con
        keyword = Node(digest("nodetofind"))
        self.protocol.callFindNode(n, keyword)

        self.clock.advance(100 * constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        sent_packet = packet.Packet.from_bytes(
            self.proto_mock.send_datagram.call_args_list[0][0][0])
        sent_message = sent_packet.payload

        m = message.Message()
        m.ParseFromString(sent_message)
        self.assertTrue(len(m.messageID) == 20)
        self.assertEqual(self.protocol.sourceNode.getProto().guid,
                         m.sender.guid)
        self.assertEqual(self.protocol.sourceNode.getProto().signedPublicKey,
                         m.sender.signedPublicKey)
        self.assertTrue(m.command == message.FIND_NODE)
        self.assertEqual(self.proto_mock.send_datagram.call_args_list[0][0][1],
                         self.addr1)
        self.assertEqual(m.arguments[0], keyword.id)
Beispiel #2
0
 def rpc_find_node(self, sender, nodeid, key):
     self.log.info("finding neighbors of %i in local table" %
                   long(nodeid.encode('hex'), 16))
     source = Node(nodeid, sender[0], sender[1])
     self.router.addContact(source)
     node = Node(key)
     return map(tuple, self.router.findNeighbors(node, exclude=source))
    def test_create_proto(self):
        rid = hashlib.sha1(str(random.getrandbits(255))).digest()
        pubkey = digest("pubkey")

        addr = objects.Node.IPAddress()
        addr.ip = "127.0.0.1"
        addr.port = 1234

        relay_addr = objects.Node.IPAddress()
        relay_addr.ip = "127.0.0.1"
        relay_addr.port = 1234

        n1 = objects.Node()
        n1.guid = rid
        n1.signedPublicKey = pubkey
        n1.vendor = False
        n1.nodeAddress.MergeFrom(addr)
        n1.natType = objects.FULL_CONE
        n2 = Node(rid, "127.0.0.1", 1234, digest("pubkey"), None, objects.FULL_CONE, False)
        self.assertEqual(n1, n2.getProto())

        n1.vendor = True
        n1.relayAddress.MergeFrom(relay_addr)
        n2 = Node(rid, "127.0.0.1", 1234, digest("pubkey"), ("127.0.0.1", 1234), objects.FULL_CONE, True)
        self.assertEqual(n1, n2.getProto())
Beispiel #4
0
    def test_rpc_find_without_value(self):
        self._connecting_to_connected()

        node1 = Node(digest("id1"), "127.0.0.1", 12345, digest("key1"))
        node2 = Node(digest("id2"), "127.0.0.1", 22222, digest("key2"))
        node3 = Node(digest("id3"), "127.0.0.1", 77777, digest("key3"))
        self.protocol.router.addContact(node1)
        self.protocol.router.addContact(node2)
        self.protocol.router.addContact(node3)
        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]
        m.arguments.extend([node2.getProto().SerializeToString(), node3.getProto().SerializeToString(), node1.getProto().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_packet = packet.Packet.from_bytes(self.proto_mock.send_datagram.call_args_list[0][0][0])
        received_message = sent_packet.payload

        m = message.Message()
        m.ParseFromString(received_message)

        self.assertEqual(received_message, expected_message)
        self.assertEqual(len(m_calls), 2)
    def test_distanceCalculation(self):
        ridone = hashlib.sha1(str(random.getrandbits(255)))
        ridtwo = hashlib.sha1(str(random.getrandbits(255)))

        shouldbe = int(ridone.hexdigest(), 16) ^ int(ridtwo.hexdigest(), 16)
        none = Node(ridone.digest())
        ntwo = Node(ridtwo.digest())
        self.assertEqual(none.distanceTo(ntwo), shouldbe)
    def test_distanceCalculation(self):
        ridone = hashlib.sha1(str(random.getrandbits(255)))
        ridtwo = hashlib.sha1(str(random.getrandbits(255)))

        shouldbe = int(ridone.hexdigest(), 16) ^ int(ridtwo.hexdigest(), 16)
        none = Node(ridone.digest())
        ntwo = Node(ridtwo.digest())
        self.assertEqual(none.distanceTo(ntwo), shouldbe)
    def test_rpc_find_node(self):
        self._connecting_to_connected()

        node1 = Node(digest("id1"), "127.0.0.1", 12345, digest("key1"))
        node2 = Node(digest("id2"), "127.0.0.1", 22222, digest("key2"))
        node3 = Node(digest("id3"), "127.0.0.1", 77777, digest("key3"))
        self.protocol.router.addContact(node1)
        self.protocol.router.addContact(node2)
        self.protocol.router.addContact(node3)
        m = message.Message()
        m.messageID = digest("msgid")
        m.sender.MergeFrom(self.protocol.sourceNode.getProto())
        m.command = message.Command.Value("FIND_NODE")
        m.arguments.append(digest("nodetofind"))
        data = m.SerializeToString()
        del m.arguments[-1]
        m.arguments.extend([
            node2.getProto().SerializeToString(),
            node1.getProto().SerializeToString(),
            node3.getProto().SerializeToString()
        ])
        expected_message = m.SerializeToString()
        self.handler.receive_message(data)

        self.clock.advance(100 * constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        m_calls = self.proto_mock.send_datagram.call_args_list
        sent_packet = packet.Packet.from_bytes(
            self.proto_mock.send_datagram.call_args_list[0][0][0])
        received_message = sent_packet.payload
        a = message.Message()
        a.ParseFromString(received_message)
        self.assertEqual(received_message, expected_message)
        self.assertEqual(len(m_calls), 2)
Beispiel #8
0
 def test_refreshIDs(self):
     node1 = Node(digest("id1"), "127.0.0.1", 12345, pubkey=digest("key1"))
     node2 = Node(digest("id2"), "127.0.0.1", 22222, pubkey=digest("key2"))
     node3 = Node(digest("id3"), "127.0.0.1", 77777, pubkey=digest("key3"))
     self.protocol.router.addContact(node1)
     self.protocol.router.addContact(node2)
     self.protocol.router.addContact(node3)
     for b in self.protocol.router.buckets:
         b.lastUpdated = (time.time() - 5000)
     ids = self.protocol.getRefreshIDs()
     self.assertTrue(len(ids) == 1)
Beispiel #9
0
    def test_rpc_find_without_value(self):
        self._connecting_to_connected()

        node1 = Node(digest("id1"),
                     "127.0.0.1",
                     12345,
                     digest("key1"),
                     nat_type=objects.FULL_CONE)
        node2 = Node(digest("id2"),
                     "127.0.0.1",
                     22222,
                     digest("key2"),
                     nat_type=objects.FULL_CONE)
        node3 = Node(digest("id3"),
                     "127.0.0.1",
                     77777,
                     digest("key3"),
                     nat_type=objects.FULL_CONE)
        self.protocol.router.addContact(node1)
        self.protocol.router.addContact(node2)
        self.protocol.router.addContact(node3)
        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.on_connection_made()
        self.handler.receive_message(data)

        del m.arguments[-1]
        m.arguments.extend([
            node3.getProto().SerializeToString(),
            node1.getProto().SerializeToString(),
            node2.getProto().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_packet = packet.Packet.from_bytes(
            self.proto_mock.send_datagram.call_args_list[0][0][0])
        received_message = sent_packet.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), 2)
Beispiel #10
0
    def test_create_proto(self):
        rid = hashlib.sha1(str(random.getrandbits(255))).digest()
        pubkey = digest("pubkey")
        vendor = True

        n1 = objects.Node()
        n1.guid = rid
        n1.signedPublicKey = pubkey
        n1.vendor = False
        n2 = Node(rid, signed_pubkey=digest("pubkey"))
        self.assertEqual(n1, n2.getProto())

        n1.vendor = True
        n2 = Node(rid, signed_pubkey=pubkey, vendor=vendor)
        self.assertEqual(n1, n2.getProto())
 def test_getNodeList(self):
     node1 = Node(digest("id1"), "127.0.0.1", 1234, digest("key1"), None, FULL_CONE, True)
     node2 = Node(digest("id2"), "248.130.11.21", 1111, digest("key2"), None, FULL_CONE, True)
     node3 = Node(digest("id3"), "987.567.23.1", 23456, digest("key3"), None, FULL_CONE, False)
     response = (True, (node1.getProto().SerializeToString(), node2.getProto().SerializeToString(),
                        node3.getProto().SerializeToString(),
                        "sdfasdfsd"))
     r = RPCFindResponse(response)
     nodes = r.getNodeList()
     self.assertEqual(nodes[0].getProto(), node1.getProto())
     self.assertEqual(nodes[1].getProto(), node2.getProto())
     self.assertEqual(nodes[2].getProto(), node3.getProto())
 def test_getNodeList(self):
     node1 = Node(digest("id1"), "127.0.0.1", 12345, signed_pubkey=digest("key1"), vendor=True)
     node2 = Node(digest("id2"), "127.0.0.1", 22222, signed_pubkey=digest("key2"), vendor=True)
     node3 = Node(digest("id3"), "127.0.0.1", 77777, signed_pubkey=digest("key3"))
     response = (True, (node1.getProto().SerializeToString(), node2.getProto().SerializeToString(),
                        node3.getProto().SerializeToString(),
                        "sdfasdfsd"))
     r = RPCFindResponse(response)
     nodes = r.getNodeList()
     self.assertEqual(nodes[0].getProto(), node1.getProto())
     self.assertEqual(nodes[1].getProto(), node2.getProto())
     self.assertEqual(nodes[2].getProto(), node3.getProto())
Beispiel #13
0
    def prepare():
        """
        Prepare the application state.
        """
        thisNodeIP = config.NODE_IP
        thisNodePort = config.NODE_PORT
        thisNodeHash = Hash(sha1(config.NODE_ID_NAME).digest())
        AppState.thisNode = Node(thisNodeHash, (thisNodeIP, thisNodePort))

        AppState.heartbeat = config.HEARTBEAT

        AppState.tokenSecret = utils.randomBits(160)

        AppState.maxPeersPerTorrent = config.MAX_PEERS_PER_TORRENT

        AppState.k = config.K
        AppState.maxNodesPerPucket = config.MAX_NODES_PER_BUCKET

        AppState.routingTable = RoutingTable()

        if config.PEER_STORAGE == 'file':
            AppState.peerStorage = dht.peerstorage.FilePeerStorage(
                config.PEER_STORAGE_DIR)
        elif config.PEER_STORAGE == 'mysql':
            AppState.peerStorage = dht.peerstorage.MySQLPeerStorage()

        # {transactionID: {(RPCQuery, Node, timestamp)}}
        AppState.outstandingQueries = {}
Beispiel #14
0
 def loadState(cls, fname, ip_address, port, multiplexer, db, callback=None, storage=None):
     """
     Load the state of this node (the alpha/ksize/id/immediate neighbors)
     from a cache file with the given fname.
     """
     with open(fname, 'r') as f:
         data = pickle.load(f)
     if data['testnet'] != multiplexer.testnet:
         raise Exception('Cache uses wrong network parameters')
     n = Node(data['id'], ip_address, port, data['signed_pubkey'], data['vendor'])
     s = Server(n, db, data['ksize'], data['alpha'], storage=storage)
     s.protocol.connect_multiplexer(multiplexer)
     if len(data['neighbors']) > 0:
         if callback is not None:
             s.bootstrap(data['neighbors']).addCallback(callback)
         else:
             s.bootstrap(data['neighbors'])
     else:
         # TODO: load seed from config file
         if callback is not None:
             s.bootstrap(s.querySeed("seed.openbazaar.org:8080",
                                     "5b44be5c18ced1bc9400fe5e79c8ab90204f06bebacc04dd9c70a95eaca6e117"))\
                 .addCallback(callback)
         else:
             s.bootstrap(s.querySeed("seed.openbazaar.org:8080",
                                     "5b44be5c18ced1bc9400fe5e79c8ab90204f06bebacc04dd9c70a95eaca6e117"))
     return s
Beispiel #15
0
    def test_callStore(self):
        self._connecting_to_connected()

        n = Node(digest("guid"), self.addr1[0], self.addr1[1],
                 digest("pubkey"), None, objects.FULL_CONE, False)
        self.wire_protocol[self.addr1] = self.con
        self.protocol.callStore(
            n, digest("Keyword"), digest("Key"),
            self.protocol.sourceNode.getProto().SerializeToString(), 10)

        self.clock.advance(100 * constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        sent_packet = packet.Packet.from_bytes(
            self.proto_mock.send_datagram.call_args_list[0][0][0])
        sent_message = sent_packet.payload

        m = message.Message()
        m.ParseFromString(sent_message)
        self.assertTrue(len(m.messageID) == 20)
        self.assertEqual(self.protocol.sourceNode.getProto().guid,
                         m.sender.guid)
        self.assertEqual(self.protocol.sourceNode.getProto().publicKey,
                         m.sender.publicKey)
        self.assertTrue(m.command == message.STORE)
        self.assertEqual(self.proto_mock.send_datagram.call_args_list[0][0][1],
                         self.addr1)
        self.assertEqual(m.arguments[0], digest("Keyword"))
        self.assertEqual(m.arguments[1], digest("Key"))
        self.assertEqual(
            m.arguments[2],
            self.protocol.sourceNode.getProto().SerializeToString())
Beispiel #16
0
        def func(node, *args):
            msgID = sha1(str(random.getrandbits(255))).digest()

            m = Message()
            m.messageID = msgID
            m.sender.MergeFrom(self.sourceNode.getProto())
            m.command = Command.Value(name.upper())
            m.protoVer = PROTOCOL_VERSION
            for arg in args:
                m.arguments.append(str(arg))
            m.testnet = self.multiplexer.testnet
            data = m.SerializeToString()

            address = (node.ip, node.port)
            relay_addr = None
            if node.nat_type == SYMMETRIC or \
                    (node.nat_type == RESTRICTED and self.sourceNode.nat_type == SYMMETRIC):
                relay_addr = node.relay_node

            d = defer.Deferred()
            if m.command != HOLE_PUNCH:
                timeout = reactor.callLater(self._waitTimeout, self.timeout, node)
                self._outstanding[msgID] = [d, address, timeout]
                self.log.debug("calling remote function %s on %s (msgid %s)" % (name, address, b64encode(msgID)))

            self.multiplexer.send_message(data, address, relay_addr)

            if self.multiplexer[address].state != State.CONNECTED and \
                            node.nat_type == RESTRICTED and \
                            self.sourceNode.nat_type != SYMMETRIC:
                self.hole_punch(Node(digest("null"), node.relay_node[0], node.relay_node[1], nat_type=FULL_CONE),
                                address[0], address[1], "True")
                self.log.debug("sending hole punch message to %s" % address[0] + ":" + str(address[1]))

            return d
 def setUp(self):
     self.catcher = []
     observer = self.catcher.append
     log.addObserver(observer)
     self.addCleanup(log.removeObserver, observer)
     self.node = Node(digest("test"), "127.0.0.1", 1234)
     self.router = RoutingTable(self, 20, self.node.id)
    def test_callDelete(self):
        self._connecting_to_connected()

        n = Node(digest("S"), self.addr1[0], self.addr1[1])
        self.wire_protocol[self.addr1] = self.con
        self.protocol.callDelete(n, digest("Keyword"), digest("Key"),
                                 digest("Signature"))

        self.clock.advance(constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        sent_packet = packet.Packet.from_bytes(
            self.proto_mock.send_datagram.call_args_list[0][0][0])
        sent_message = sent_packet.payload

        m = message.Message()
        m.ParseFromString(sent_message)
        self.assertEqual(self.proto_mock.send_datagram.call_args_list[0][0][1],
                         self.addr1)
        self.assertTrue(len(m.messageID) == 20)
        self.assertEqual(self.protocol.sourceNode.getProto().guid,
                         m.sender.guid)
        self.assertEqual(self.protocol.sourceNode.getProto().publicKey,
                         m.sender.publicKey)
        self.assertTrue(m.command == message.DELETE)
        self.assertEqual(m.arguments[0], digest("Keyword"))
        self.assertEqual(m.arguments[1], digest("Key"))
        self.assertEqual(m.arguments[2], digest("Signature"))
Beispiel #19
0
    def resolve(self, guid):
        """
        Given a guid return a `Node` object containing its ip and port or none if it's
        not found.

        Args:
            guid: the 20 raw bytes representing the guid.
        """
        node_to_find = Node(guid)

        def check_for_node(nodes):
            for node in nodes:
                if node.id == node_to_find.id:
                    return node
            return None
        index = self.protocol.router.getBucketFor(node_to_find)
        nodes = self.protocol.router.buckets[index].getNodes()
        for node in nodes:
            if node.id == node_to_find.id:
                return defer.succeed(node)
        nearest = self.protocol.router.findNeighbors(node_to_find)
        if len(nearest) == 0:
            self.log.warning("There are no known neighbors to find node %s" % node_to_find.id.encode("hex"))
            return defer.succeed(None)
        spider = NodeSpiderCrawl(self.protocol, node_to_find, nearest, self.ksize, self.alpha)
        return spider.find().addCallback(check_for_node)
 def test_addSameIP(self):
     self.router.addContact(self.node)
     self.router.addContact(Node(digest("asdf"), "127.0.0.1", 1234))
     self.assertTrue(len(self.router.buckets), 1)
     self.assertTrue(len(self.router.buckets[0].nodes), 1)
     self.assertTrue(
         self.router.buckets[0].getNodes()[0].id == digest("asdf"))
Beispiel #21
0
    def delete(self, keyword, key, signature):
        """
        Delete the given key/value pair from the keyword dictionary on the network.
        To delete you must provide a signature covering the key that you wish to
        delete. It will be verified against the public key stored in the value. We
        use our ksize as alpha to make sure we reach as many nodes storing our value
        as possible.

        Args:
            keyword: the `string` keyword where the data being deleted is stored.
            key: the 20 byte hash of the data.
            signature: a signature covering the key.

        """
        self.log.info("deleting '%s':'%s' from the network" % (keyword, hexlify(key)))
        dkey = digest(keyword)

        def delete(nodes):
            self.log.debug("deleting '%s' on %s" % (key, [str(i) for i in nodes]))
            ds = [self.protocol.callDelete(node, dkey, key, signature) for node in nodes]

            if self.storage.getSpecific(dkey, key) is not None:
                self.storage.delete(dkey, key)

            return defer.DeferredList(ds).addCallback(_anyRespondSuccess)

        node = Node(dkey)
        nearest = self.protocol.router.findNeighbors(node)
        if len(nearest) == 0:
            self.log.warning("There are no known neighbors to delete key %s" % key)
            return defer.succeed(False)
        spider = NodeSpiderCrawl(self.protocol, node, nearest, self.ksize, self.ksize)
        return spider.find().addCallback(delete)
Beispiel #22
0
 def receive_message(self, datagram):
     if len(datagram) < 166:
         self.log.warning(
             "received datagram too small from %s, ignoring" %
             self.addr)
         return False
     try:
         m = Message()
         m.ParseFromString(datagram)
         self.node = Node(
             m.sender.guid, m.sender.nodeAddress.ip,
             m.sender.nodeAddress.port, m.sender.publicKey,
             None if not m.sender.HasField("relayAddress") else
             (m.sender.relayAddress.ip, m.sender.relayAddress.port),
             m.sender.natType, m.sender.vendor)
         self.remote_node_version = m.protoVer
         if self.time_last_message == 0:
             h = nacl.hash.sha512(m.sender.publicKey)
             pow_hash = h[40:]
             if int(pow_hash[:6],
                    16) >= 50 or m.sender.guid.encode("hex") != h[:40]:
                 raise Exception('Invalid GUID')
         for processor in self.processors:
             if m.command in processor or m.command == NOT_FOUND:
                 processor.receive_message(m, self.node,
                                           self.connection,
                                           self.ban_score)
         if m.command != PING:
             self.time_last_message = time.time()
     except Exception:
         # If message isn't formatted property then ignore
         self.log.warning(
             "received an invalid message from %s, ignoring" %
             self.addr)
         return False
        def handle_shutdown(self):
            try:
                self.connection.unregister()
            except Exception:
                pass

            if self.node is None:
                self.node = Node(digest("null"), str(self.connection.dest_addr[0]),
                                 int(self.connection.dest_addr[1]))
            for processor in self.processors:
                processor.timeout(self.node)

            if self.addr:
                self.log.info("connection with %s terminated" % self.addr)
            try:
                self.ban_score.scoring_loop.stop()
            except Exception:
                pass
            try:
                self.keep_alive_loop.stop()
            except Exception:
                pass
            if self.relay_node == (self.connection.dest_addr[0], self.connection.dest_addr[1]):
                self.log.info("Disconnected from relay node. Picking new one...")
                self.change_relay_node()
Beispiel #24
0
 def send(node_to_send):
     n = node_to_send if node_to_send is not None else Node(
         unhexlify(guid), "123.4.5.6", 1234)
     self.factory.mserver.send_message(
         n, recipient_encryption_key,
         Plaintext_Message.Type.Value(message_type.upper()), message,
         subject)
    def test_acceptResponse(self):
        self._connecting_to_connected()

        def handle_response(resp):
            self.assertTrue(resp[0])
            self.assertEqual(resp[1][0], self.protocol.sourceNode.id)

        n = Node(digest("S"), self.addr1[0], self.addr1[1])
        self.wire_protocol[self.addr1] = self.con
        d = self.protocol.callPing(n)

        self.clock.advance(1)
        connection.REACTOR.runUntilCurrent()
        sent_packet = packet.Packet.from_bytes(
            self.proto_mock.send_datagram.call_args_list[0][0][0])
        sent_message = sent_packet.payload

        m = message.Message()
        m.ParseFromString(sent_message)
        timeout = reactor.callLater(5, self.protocol._timeout, m.messageID)
        self.protocol._outstanding[m.messageID] = (d, timeout)
        m.arguments.append(self.protocol.sourceNode.id)
        self.handler.receive_message(m.SerializeToString())

        return d.addCallback(handle_response)
    def test_transferKeyValues(self):
        self._connecting_to_connected()
        self.wire_protocol[self.addr1] = self.con

        self.protocol.addToRouter(mknode())

        self.protocol.storage[digest("keyword")] = (
            digest("key"),
            self.protocol.sourceNode.getProto().SerializeToString())
        self.protocol.transferKeyValues(
            Node(digest("id"), self.addr1[0], self.addr1[1]))

        self.clock.advance(1)
        connection.REACTOR.runUntilCurrent()
        sent_packet = packet.Packet.from_bytes(
            self.proto_mock.send_datagram.call_args_list[0][0][0])
        sent_message = sent_packet.payload
        x = message.Message()
        x.ParseFromString(sent_message)

        m = message.Message()
        m.sender.MergeFrom(self.protocol.sourceNode.getProto())
        m.command = message.Command.Value("STORE")
        m.arguments.append(digest("keyword"))
        m.arguments.append(digest("key"))
        m.arguments.append(
            self.protocol.sourceNode.getProto().SerializeToString())
        self.assertEqual(x.sender, m.sender)
        self.assertEqual(x.command, m.command)
        self.assertEqual(x.arguments[0], m.arguments[0])
        self.assertEqual(x.arguments[1], m.arguments[1])
        self.assertEqual(x.arguments[2], m.arguments[2])
    def test_handleFoundValues(self):
        self._connecting_to_connected()
        self.wire_protocol[self.addr1] = self.con

        self.protocol.router.addContact(self.node1)
        self.protocol.router.addContact(self.node2)
        self.protocol.router.addContact(self.node3)

        node = Node(digest("s"))
        nearest = self.protocol.router.findNeighbors(node)
        spider = ValueSpiderCrawl(self.protocol, node, nearest,
                                  dht.constants.KSIZE, dht.constants.ALPHA)
        val = Value()
        val.valueKey = digest("contractID")
        val.serializedData = self.node1.getProto().SerializeToString()
        val1 = val.SerializeToString()
        value = spider._handleFoundValues([(val1, )])
        self.assertEqual(value[0], val.SerializeToString())

        # test handle multiple values
        val.serializedData = self.node2.getProto().SerializeToString()
        val2 = val.SerializeToString()
        found_values = [(val1, ), (val1, ), (val2, )]
        self.assertEqual(spider._handleFoundValues(found_values), (val1, ))

        # test store value at nearest without value
        spider.nearestWithoutValue.push(self.node1)
        spider._handleFoundValues(found_values)
        self.clock.advance(100 * constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        self.assertTrue(len(self.proto_mock.send_datagram.call_args_list) > 1)
        self.proto_mock.send_datagram.call_args_list = []
Beispiel #28
0
 def parse_results(values):
     if values is not None:
         for v in values:
             try:
                 val = Value()
                 val.ParseFromString(v)
                 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:
                     proto = self.factory.db.listings.get_proto()
                     l = Listings()
                     l.ParseFromString(proto)
                     for listing in l.listing:
                         if listing.contract_hash == val.valueKey:
                             respond(listing, node_to_ask)
                 else:
                     self.factory.mserver.get_contract_metadata(node_to_ask, val.valueKey)\
                         .addCallback(respond, node_to_ask)
             except Exception:
                 pass
Beispiel #29
0
 def rpc_find_value(self, sender, nodeid, key):
     source = Node(nodeid, sender[0], sender[1])
     self.router.addContact(source)
     value = self.storage.get(key, None)
     if value is None:
         return self.rpc_find_node(sender, nodeid, key)
     return {'value': value}
Beispiel #30
0
 def change_relay_node(self):
     potential_relay_nodes = []
     for bucket in self.processors[0].router.buckets:
         for node in bucket.nodes.values():
             if node.nat_type == FULL_CONE:
                 potential_relay_nodes.append((node.ip, node.port))
     if len(potential_relay_nodes) == 0:
         for seed in SEEDS:
             try:
                 potential_relay_nodes.append(
                     (socket.gethostbyname(seed[0].split(":")[0]),
                      28469 if self.processors[0].TESTNET else 18469))
             except socket.gaierror:
                 pass
     shuffle(potential_relay_nodes)
     self.relay_node = potential_relay_nodes[0]
     for processor in self.processors:
         if PING in processor:
             if (self.relay_node[0],
                     self.relay_node[1]) in processor.multiplexer:
                 processor.multiplexer[(self.relay_node[0],
                                        self.relay_node[1])].shutdown()
             processor.callPing(
                 Node(digest("null"),
                      self.relay_node[0],
                      self.relay_node[1],
                      relay_node=None,
                      nat_type=FULL_CONE))
 def receive_message(self, datagram):
     if len(datagram) < 166:
         self.log.warning("received datagram too small from %s, ignoring" % self.addr)
         return False
     m = Message()
     try:
         m.ParseFromString(datagram)
         self.node = Node(m.sender.guid,
                          m.sender.nodeAddress.ip,
                          m.sender.nodeAddress.port,
                          m.sender.publicKey,
                          None if not m.sender.HasField("relayAddress") else
                          (m.sender.relayAddress.ip, m.sender.relayAddress.port),
                          m.sender.natType,
                          m.sender.vendor)
         pubkey = m.sender.publicKey
         verify_key = nacl.signing.VerifyKey(pubkey)
         signature = m.signature
         m.ClearField("signature")
         verify_key.verify(m.SerializeToString(), signature)
         h = nacl.hash.sha512(m.sender.publicKey)
         pow_hash = h[40:]
         if int(pow_hash[:6], 16) >= 50 or m.sender.guid.encode("hex") != h[:40]:
             raise Exception('Invalid GUID')
     except Exception:
         # If message isn't formatted property then ignore
         self.log.warning("received an invalid message from %s, ignoring" % self.addr)
         return False
     for processor in self.processors:
         if m.command in processor or m.command == NOT_FOUND:
             processor.receive_message(m, self.node, self.connection, self.ban_score)
Beispiel #32
0
 def loadState(cls,
               fname,
               ip_address,
               port,
               multiplexer,
               db,
               callback=None,
               storage=None):
     """
     Load the state of this node (the alpha/ksize/id/immediate neighbors)
     from a cache file with the given fname.
     """
     with open(fname, 'r') as f:
         data = pickle.load(f)
     if data['testnet'] != multiplexer.testnet:
         raise Exception('Cache uses wrong network parameters')
     n = Node(data['id'], ip_address, port, data['signed_pubkey'],
              data['vendor'])
     s = Server(n, db, data['ksize'], data['alpha'], storage=storage)
     s.protocol.connect_multiplexer(multiplexer)
     if len(data['neighbors']) > 0:
         if callback is not None:
             s.bootstrap(data['neighbors']).addCallback(callback)
         else:
             s.bootstrap(data['neighbors'])
     else:
         if callback is not None:
             s.bootstrap(s.querySeed(SEED))\
                 .addCallback(callback)
         else:
             s.bootstrap(s.querySeed(SEED))
     return s
Beispiel #33
0
        def initTable(results):
            potential_relay_nodes = []
            for addr, result in results.items():
                if result[0]:
                    n = objects.Node()
                    try:
                        n.ParseFromString(result[1][0])
                        h = nacl.hash.sha512(n.publicKey)
                        hash_pow = h[40:]
                        if int(hash_pow[:6], 16) >= 50 or hexlify(
                                n.guid) != h[:40]:
                            raise Exception('Invalid GUID')
                        node = Node(
                            n.guid, addr[0], addr[1], n.publicKey,
                            None if not n.HasField("relayAddress") else
                            (n.relayAddress.ip, n.relayAddress.port),
                            n.natType, n.vendor)
                        self.protocol.router.addContact(node)
                        if n.natType == objects.FULL_CONE:
                            potential_relay_nodes.append((addr[0], addr[1]))
                    except Exception:
                        self.log.warning(
                            "bootstrap node returned invalid GUID")
            if len(potential_relay_nodes
                   ) > 0 and self.node.nat_type != objects.FULL_CONE:
                shuffle(potential_relay_nodes)
                self.node.relay_node = potential_relay_nodes[0]

            d.callback(True)
Beispiel #34
0
    def transferKeyValues(self, node):
        """
        Given a new node, send it all the keys/values it should be storing.

        @param node: A new node that just joined (or that we just found out
        about).

        Process:
        For each key in storage, get k closest nodes.  If newnode is closer
        than the furtherst in that list, and the node for this server
        is closer than the closest in that list, then store the key/value
        on the new node (per section 2.5 of the paper)
        """
        ds = []
        for keyword in self.storage.iterkeys():
            keynode = Node(keyword)
            neighbors = self.router.findNeighbors(keynode, exclude=node)
            if len(neighbors) > 0:
                newNodeClose = node.distanceTo(
                    keynode) < neighbors[-1].distanceTo(keynode)
                thisNodeClosest = self.sourceNode.distanceTo(
                    keynode) < neighbors[0].distanceTo(keynode)
            if len(neighbors) == 0 \
                    or (newNodeClose and thisNodeClosest) \
                    or (thisNodeClosest and len(neighbors) < self.ksize):
                for k, v in self.storage.iteritems(keyword):
                    ds.append(self.callStore(node, keyword, k, v))
        return defer.gatherResults(ds)
Beispiel #35
0
    def receive_message(self, message, connection, ban_score):
        sender = Node(
            message.sender.guid, message.sender.nodeAddress.ip,
            message.sender.nodeAddress.port, message.sender.signedPublicKey,
            None if not message.sender.HasField("relayAddress") else
            (message.sender.relayAddress.ip, message.sender.relayAddress.port),
            message.sender.natType, message.sender.vendor)

        if message.testnet != self.multiplexer.testnet:
            self.log.warning(
                "received message from %s with incorrect network parameters." %
                str(connection.dest_addr))
            connection.shutdown()
            return False

        if message.protoVer < PROTOCOL_VERSION:
            self.log.warning(
                "received message from %s with incompatible protocol version."
                % str(connection.dest_addr))
            connection.shutdown()
            return False

        # Check that the GUID is valid. If not, ignore
        if self.router.isNewNode(sender):
            try:
                pubkey = message.sender.signedPublicKey[len(message.sender.
                                                            signedPublicKey) -
                                                        32:]
                verify_key = nacl.signing.VerifyKey(pubkey)
                verify_key.verify(message.sender.signedPublicKey)
                h = nacl.hash.sha512(message.sender.signedPublicKey)
                pow_hash = h[64:128]
                if int(pow_hash[:6], 16) >= 50 or hexlify(
                        message.sender.guid) != h[:40]:
                    raise Exception('Invalid GUID')

            except Exception:
                self.log.warning(
                    "received message from sender with invalid GUID, ignoring")
                connection.shutdown()
                return False

        if message.sender.vendor:
            self.db.VendorStore().save_vendor(
                message.sender.guid.encode("hex"),
                message.sender.SerializeToString())

        msgID = message.messageID
        if message.command == NOT_FOUND:
            data = None
        else:
            data = tuple(message.arguments)
        if msgID in self._outstanding:
            self._acceptResponse(msgID, data, sender)
        elif message.command != NOT_FOUND:
            #ban_score.process_message(m)
            self._acceptRequest(msgID,
                                str(Command.Name(message.command)).lower(),
                                data, sender, connection)
Beispiel #36
0
    def bootstrap(self, addrs, deferred=None):
        """
        Bootstrap the server by connecting to other known nodes in the network.

        Args:
            addrs: A `list` of (ip, port) `tuple` pairs.  Note that only IP addresses
                   are acceptable - hostnames will cause an error.
        """

        # if the transport hasn't been initialized yet, wait a second
        if self.protocol.multiplexer.transport is None:
            return task.deferLater(reactor, 1, self.bootstrap, addrs)
        self.log.info("bootstrapping with %s addresses, finding neighbors..." % len(addrs))

        if deferred is None:
            d = defer.Deferred()
        else:
            d = deferred

        def initTable(results):
            response = False
            potential_relay_nodes = []
            for addr, result in results.items():
                if result[0]:
                    response = True
                    n = objects.Node()
                    try:
                        n.ParseFromString(result[1][0])
                        h = nacl.hash.sha512(n.publicKey)
                        hash_pow = h[40:]
                        if int(hash_pow[:6], 16) >= 50 or hexlify(n.guid) != h[:40]:
                            raise Exception('Invalid GUID')
                        node = Node(n.guid, addr[0], addr[1], n.publicKey,
                                    None if not n.HasField("relayAddress") else
                                    (n.relayAddress.ip, n.relayAddress.port),
                                    n.natType,
                                    n.vendor)
                        self.protocol.router.addContact(node)
                        if n.natType == objects.FULL_CONE:
                            potential_relay_nodes.append((addr[0], addr[1]))
                    except Exception:
                        self.log.warning("bootstrap node returned invalid GUID")
            if not response:
                if self.protocol.multiplexer.testnet:
                    self.bootstrap(self.querySeed(SEEDS_TESTNET), d)
                else:
                    self.bootstrap(self.querySeed(SEEDS), d)
                return
            if len(potential_relay_nodes) > 0 and self.node.nat_type != objects.FULL_CONE:
                shuffle(potential_relay_nodes)
                self.node.relay_node = potential_relay_nodes[0]

            d.callback(True)
        ds = {}
        for addr in addrs:
            if addr != (self.node.ip, self.node.port):
                ds[addr] = self.protocol.ping(Node(digest("null"), addr[0], addr[1], nat_type=objects.FULL_CONE))
        deferredDict(ds).addCallback(initTable)
        return d
Beispiel #37
0
 def __init__(self, private_key, public_key, alias=None):
     self.private_key = private_key
     self.public_key = public_key
     self._node = Node()
     if alias:
         self.alias = alias
     else:
         self.alias = {}
    def setUp(self):
        self.public_ip = '123.45.67.89'
        self.port = 12345
        self.own_addr = (self.public_ip, self.port)
        self.addr1 = ('132.54.76.98', 54321)
        self.addr2 = ('231.76.45.89', 15243)
        self.addr3 = ("193.193.111.00", 99999)

        self.clock = task.Clock()
        connection.REACTOR.callLater = self.clock.callLater

        self.proto_mock = mock.Mock(spec_set=rudp.ConnectionMultiplexer)
        self.handler_mock = mock.Mock(spec_set=connection.Handler)
        self.con = connection.Connection(
            self.proto_mock,
            self.handler_mock,
            self.own_addr,
            self.addr1
        )

        valid_key = "63d901c4d57cde34fc1f1e28b9af5d56ed342cae5c2fb470046d0130a4226b0c"
        self.signing_key = nacl.signing.SigningKey(valid_key, encoder=nacl.encoding.HexEncoder)
        verify_key = self.signing_key.verify_key
        h = nacl.hash.sha512(verify_key.encode())
        self.storage = ForgetfulStorage()
        self.node = Node(unhexlify(h[:40]), self.public_ip, self.port, verify_key.encode(), None, FULL_CONE, True)
        self.db = Database(filepath="test.db")
        self.protocol = KademliaProtocol(self.node, self.storage, 20, self.db, self.signing_key)


        self.wire_protocol = PulseShopProtocol(self.db, self.own_addr, FULL_CONE)
        self.wire_protocol.register_processor(self.protocol)

        self.protocol.connect_multiplexer(self.wire_protocol)
        self.handler = self.wire_protocol.ConnHandler([self.protocol], self.wire_protocol, None,
                                                      self.wire_protocol.ban_score)

        transport = mock.Mock(spec_set=udp.Port)
        ret_val = address.IPv4Address('UDP', self.public_ip, self.port)
        transport.attach_mock(mock.Mock(return_value=ret_val), 'getHost')
        self.wire_protocol.makeConnection(transport)

        self.node1 = Node(digest("id1"), self.addr1[0], self.addr1[1], digest("key1"), None, FULL_CONE, True)
        self.node2 = Node(digest("id2"), self.addr2[0], self.addr2[1], digest("key2"), None, FULL_CONE, True)
        self.node3 = Node(digest("id3"), self.addr3[0], self.addr3[1], digest("key3"), None, FULL_CONE, True)
    def setUp(self):
        self.public_ip = '123.45.67.89'
        self.port = 12345
        self.own_addr = (self.public_ip, self.port)
        self.addr1 = ('132.54.76.98', 54321)
        self.addr2 = ('231.76.45.89', 15243)
        self.addr3 = ("193.193.111.00", 99999)

        self.clock = task.Clock()
        connection.REACTOR.callLater = self.clock.callLater

        self.proto_mock = mock.Mock(spec_set=rudp.ConnectionMultiplexer)
        self.handler_mock = mock.Mock(spec_set=connection.Handler)
        self.con = connection.Connection(
            self.proto_mock,
            self.handler_mock,
            self.own_addr,
            self.addr1
        )

        valid_key = "1a5c8e67edb8d279d1ae32fa2da97e236b95e95c837dc8c3c7c2ff7a7cc29855"
        self.signing_key = nacl.signing.SigningKey(valid_key, encoder=nacl.encoding.HexEncoder)
        verify_key = self.signing_key.verify_key
        signed_pubkey = self.signing_key.sign(str(verify_key))
        h = nacl.hash.sha512(signed_pubkey)
        self.storage = ForgetfulStorage()
        self.node = Node(unhexlify(h[:40]), self.public_ip, self.port, signed_pubkey, True)
        self.db = Database(filepath=":memory:")
        self.protocol = KademliaProtocol(self.node, self.storage, 20, self.db)

        self.wire_protocol = OpenBazaarProtocol(self.own_addr)
        self.wire_protocol.register_processor(self.protocol)

        self.protocol.connect_multiplexer(self.wire_protocol)
        self.handler = self.wire_protocol.ConnHandler([self.protocol], self.wire_protocol)

        transport = mock.Mock(spec_set=udp.Port)
        ret_val = address.IPv4Address('UDP', self.public_ip, self.port)
        transport.attach_mock(mock.Mock(return_value=ret_val), 'getHost')
        self.wire_protocol.makeConnection(transport)

        self.node1 = Node(digest("id1"), self.addr1[0], self.addr1[1], digest("key1"), True)
        self.node2 = Node(digest("id2"), self.addr2[0], self.addr2[1], digest("key2"), True)
        self.node3 = Node(digest("id3"), self.addr3[0], self.addr3[1], digest("key3"), True)
    def on_response_received(self, transaction):
        # Update the id of the remote node.
        transaction.response_node.id_20 = transaction.response["r"]["id"]

        # Add the node that reponded to us. We most likely already have this one.
        self._server.remote_nodes.add(transaction.response_node)

        # A find_node or get_peers response may carry extra nodes.
        if transaction.query["q"] == "find_node" or transaction.query["q"] == "get_peers":
            nodes = transaction.response["r"].get("nodes", "")

            for i in xrange(0, len(nodes), 26):
                id_26 = nodes[i : i + 26]
                if not self._server.remote_nodes.get_node(id_26):
                    self._server.remote_nodes.add(Node.from_id_26(id_26))
    def _receiver(self):
        """
        Run in a different thread, and have as only goal to receive messages,
        parse them, and put them into a thread safe queue for further handling
        """
        while True:
            try:
                # Receive message
                raw_message, connect_info = self._sock.recvfrom(4096)
                message = bdecode(raw_message)
#                print "Received f " + str(connect_info) + ":\t" + str(message)

                # This is a query from another peer.
                if message['y'] == 'q':
                    # Retrieve or create source node.
                    id_26 = message['a']['id'] + socket.inet_aton(connect_info[0]) + struct.pack(r'!H', connect_info[1])
                    source_node = self.remote_nodes.get_node(id_26) or Node.from_id_26(id_26)

                    transaction = Transaction(query=message, query_node=source_node, response_node=self.node) # create transaction
                    self._running_transactions[transaction.id] = transaction # Add it to running transactions

                    for handler in self.on_query_received:
                        handler(transaction)  # Notify listeners

                elif message['y'] == 'e':
                    raise Exception

                # This is a response to a transaction we started.
                elif message['y'] == 'r':
                    transaction = self._running_transactions.pop(message["t"]) # pop transaction
                    transaction.response = message

                    for handler in self.on_response_received:
                        handler(transaction)  # Notify listeners

                else:
                    raise Exception

            except socket.timeout:
                pass
            except BTFailure:
                pass
            except:
                print traceback.format_exc()
    def test_rpc_find_node(self):
        self._connecting_to_connected()

        node1 = Node(digest("id1"), "127.0.0.1", 12345, digest("key1"), nat_type=objects.FULL_CONE)
        node2 = Node(digest("id2"), "127.0.0.1", 22222, digest("key2"), nat_type=objects.FULL_CONE)
        node3 = Node(digest("id3"), "127.0.0.1", 77777, digest("key3"), nat_type=objects.FULL_CONE)
        self.protocol.router.addContact(node1)
        self.protocol.router.addContact(node2)
        self.protocol.router.addContact(node3)
        m = message.Message()
        m.messageID = digest("msgid")
        m.sender.MergeFrom(self.protocol.sourceNode.getProto())
        m.command = message.Command.Value("FIND_NODE")
        m.protoVer = self.version
        m.testnet = False
        m.arguments.append(digest("nodetofind"))
        m.signature = self.signing_key.sign(m.SerializeToString())[:64]
        data = m.SerializeToString()
        del m.arguments[-1]
        m.arguments.extend(
            [
                node2.getProto().SerializeToString(),
                node1.getProto().SerializeToString(),
                node3.getProto().SerializeToString(),
            ]
        )
        m.ClearField("signature")
        expected_message = m.SerializeToString()
        self.handler.on_connection_made()
        self.handler.receive_message(data)

        self.clock.advance(100 * constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        m_calls = self.proto_mock.send_datagram.call_args_list
        sent_packet = packet.Packet.from_bytes(self.proto_mock.send_datagram.call_args_list[0][0][0])
        received_message = sent_packet.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), 2)
Beispiel #43
0
class Drogulus(object):
    """
    Represents a node in the Drogulus distributed hash table. This is the
    class that generally should be instantiated.
    """

    def __init__(self, private_key, public_key, alias=None):
        self.private_key = private_key
        self.public_key = public_key
        self._node = Node()
        if alias:
            self.alias = alias
        else:
            self.alias = {}

    def join(self):
        """
        Causes the node to join the distributed hash table. Returns a deferred
        that fires when the operation is complete.
        """
        pass

    def whois(self, public_key):
        """
        Given the public key of an entity that uses the drogulus will return a
        deferred that fires when information about them stored in the DHT is
        retrieved.
        """
        return self.get(public_key, None)

    def get(self, public_key, key_name):
        """
        Gets the value associated with a compound key made of the passed in
        public key and meaningful key name. Returns a deferred that fires when
        the value is retrieved.
        """
        target = construct_key(public_key, key_name)
        return self._node.retrieve(target)

    def set(self, key_name, value, duplicate=DUPLICATION_COUNT, meta=None,
            expires=EXPIRY_DURATION):
        """
        Stores a value at a compound key made from the local node's public key
        and the passed in meaningful key name. Returns a deferred that fires
        when the value has been stored to duplicate number of nodes. An
        optional meta dictionary and expires duration (to be added to the
        current time) can also be specified.
        """
        timestamp = time.time()

        if meta is None:
            meta = {}

        if expires < 1:
            expires = -1
        else:
            expires = timestamp + expires

        signature = generate_signature(value, timestamp, expires, key_name,
                                       meta, self.private_key)

        return self._node.replicate(self.public_key, key_name, value,
                                    timestamp, expires, meta, signature,
                                    duplicate)
class ValueSpiderCrawlTest(unittest.TestCase):
    def setUp(self):
        self.public_ip = '123.45.67.89'
        self.port = 12345
        self.own_addr = (self.public_ip, self.port)
        self.addr1 = ('132.54.76.98', 54321)
        self.addr2 = ('231.76.45.89', 15243)
        self.addr3 = ("193.193.111.00", 99999)

        self.clock = task.Clock()
        connection.REACTOR.callLater = self.clock.callLater

        self.proto_mock = mock.Mock(spec_set=rudp.ConnectionMultiplexer)
        self.handler_mock = mock.Mock(spec_set=connection.Handler)
        self.con = connection.Connection(
            self.proto_mock,
            self.handler_mock,
            self.own_addr,
            self.addr1
        )

        valid_key = "63d901c4d57cde34fc1f1e28b9af5d56ed342cae5c2fb470046d0130a4226b0c"
        self.signing_key = nacl.signing.SigningKey(valid_key, encoder=nacl.encoding.HexEncoder)
        verify_key = self.signing_key.verify_key
        h = nacl.hash.sha512(verify_key.encode())
        self.storage = ForgetfulStorage()
        self.node = Node(unhexlify(h[:40]), self.public_ip, self.port, verify_key.encode(), None, FULL_CONE, True)
        self.db = Database(filepath="test.db")
        self.protocol = KademliaProtocol(self.node, self.storage, 20, self.db, self.signing_key)

        self.wire_protocol = OpenBazaarProtocol(self.db, self.own_addr, FULL_CONE)
        self.wire_protocol.register_processor(self.protocol)

        self.protocol.connect_multiplexer(self.wire_protocol)
        self.handler = self.wire_protocol.ConnHandler([self.protocol], self.wire_protocol, None)

        transport = mock.Mock(spec_set=udp.Port)
        ret_val = address.IPv4Address('UDP', self.public_ip, self.port)
        transport.attach_mock(mock.Mock(return_value=ret_val), 'getHost')
        self.wire_protocol.makeConnection(transport)

        self.node1 = Node(digest("id1"), self.addr1[0], self.addr1[1], digest("key1"), None, FULL_CONE, True)
        self.node2 = Node(digest("id2"), self.addr2[0], self.addr2[1], digest("key2"), None, FULL_CONE, True)
        self.node3 = Node(digest("id3"), self.addr3[0], self.addr3[1], digest("key3"), None, FULL_CONE, True)

    def tearDown(self):
        self.con.shutdown()
        self.wire_protocol.shutdown()
        os.remove("test.db")

    def test_find(self):
        self._connecting_to_connected()
        self.wire_protocol[self.addr1] = self.con
        self.wire_protocol[self.addr2] = self.con
        self.wire_protocol[self.addr3] = self.con

        self.protocol.router.addContact(self.node1)
        self.protocol.router.addContact(self.node2)
        self.protocol.router.addContact(self.node3)

        node = Node(digest("s"))
        nearest = self.protocol.router.findNeighbors(node)
        spider = ValueSpiderCrawl(self.protocol, node, nearest, 20, 3)
        spider.find()

        self.clock.advance(100 * constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        self.assertEqual(len(self.proto_mock.send_datagram.call_args_list), 7)

    def test_nodesFound(self):
        self._connecting_to_connected()
        self.wire_protocol[self.addr1] = self.con
        self.wire_protocol[self.addr2] = self.con
        self.wire_protocol[self.addr3] = self.con

        self.protocol.router.addContact(self.node1)
        self.protocol.router.addContact(self.node2)
        self.protocol.router.addContact(self.node3)

        # test response with uncontacted nodes
        node = Node(digest("s"))
        nearest = self.protocol.router.findNeighbors(node)
        spider = ValueSpiderCrawl(self.protocol, node, nearest, 20, 3)
        response = (True, (self.node1.getProto().SerializeToString(), self.node2.getProto().SerializeToString(),
                           self.node3.getProto().SerializeToString()))
        responses = {self.node1.id: response}
        spider._nodesFound(responses)
        self.clock.advance(100 * constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        self.assertEqual(len(self.proto_mock.send_datagram.call_args_list), 7)

        # test all been contacted
        spider = ValueSpiderCrawl(self.protocol, node, nearest, 20, 3)
        for peer in spider.nearest.getUncontacted():
            spider.nearest.markContacted(peer)
        response = (True, (self.node1.getProto().SerializeToString(), self.node2.getProto().SerializeToString(),
                           self.node3.getProto().SerializeToString()))
        responses = {self.node2.id: response}
        resp = spider._nodesFound(responses)
        self.assertTrue(resp is None)

        # test didn't happen
        spider = ValueSpiderCrawl(self.protocol, node, nearest, 20, 3)
        response = (False, (self.node1.getProto().SerializeToString(), self.node2.getProto().SerializeToString(),
                            self.node3.getProto().SerializeToString()))
        responses = {self.node1.id: response}
        spider._nodesFound(responses)
        self.assertTrue(len(spider.nearest) == 2)

        # test got value
        val = Value()
        val.valueKey = digest("contractID")
        val.serializedData = self.protocol.sourceNode.getProto().SerializeToString()
        val.ttl = 10
        response = (True, ("value", val.SerializeToString()))
        responses = {self.node3.id: response}
        spider.nearestWithoutValue = NodeHeap(node, 1)
        value = spider._nodesFound(responses)
        self.assertEqual(value[0], val.SerializeToString())

    def test_handleFoundValues(self):
        self._connecting_to_connected()
        self.wire_protocol[self.addr1] = self.con

        self.protocol.router.addContact(self.node1)
        self.protocol.router.addContact(self.node2)
        self.protocol.router.addContact(self.node3)

        node = Node(digest("s"))
        nearest = self.protocol.router.findNeighbors(node)
        spider = ValueSpiderCrawl(self.protocol, node, nearest, 20, 3)
        val = Value()
        val.valueKey = digest("contractID")
        val.serializedData = self.node1.getProto().SerializeToString()
        val.ttl = 10
        val1 = val.SerializeToString()
        value = spider._handleFoundValues([val1])
        self.assertEqual(value[0], val.SerializeToString())

        # test handle multiple values
        val.serializedData = self.node2.getProto().SerializeToString()
        val2 = val.SerializeToString()
        val.valueKey = digest("contractID2")
        val3 = val.SerializeToString()
        found_values = [val1, val2, val2, val3]
        self.assertEqual(spider._handleFoundValues(found_values), [val3, val2])

        # test store value at nearest without value
        spider.nearestWithoutValue.push(self.node1)
        spider._handleFoundValues(found_values)
        self.clock.advance(100 * constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        self.assertTrue(len(self.proto_mock.send_datagram.call_args_list) > 1)
        self.proto_mock.send_datagram.call_args_list = []

    def _connecting_to_connected(self):
        remote_synack_packet = packet.Packet.from_data(
            42,
            self.con.own_addr,
            self.con.dest_addr,
            ack=0,
            syn=True
        )
        self.con.receive_packet(remote_synack_packet, self.addr1)

        self.clock.advance(0)
        connection.REACTOR.runUntilCurrent()

        self.next_remote_seqnum = 43

        m_calls = self.proto_mock.send_datagram.call_args_list
        sent_syn_packet = packet.Packet.from_bytes(m_calls[0][0][0])
        seqnum = sent_syn_packet.sequence_number

        self.handler_mock.reset_mock()
        self.proto_mock.reset_mock()

        self.next_seqnum = seqnum + 1
class NodeSpiderCrawlTest(unittest.TestCase):
    def setUp(self):
        self.public_ip = '123.45.67.89'
        self.port = 12345
        self.own_addr = (self.public_ip, self.port)
        self.addr1 = ('132.54.76.98', 54321)
        self.addr2 = ('231.76.45.89', 15243)
        self.addr3 = ("193.193.111.00", 99999)

        self.clock = task.Clock()
        connection.REACTOR.callLater = self.clock.callLater

        self.proto_mock = mock.Mock(spec_set=rudp.ConnectionMultiplexer)
        self.handler_mock = mock.Mock(spec_set=connection.Handler)
        self.con = connection.Connection(
            self.proto_mock,
            self.handler_mock,
            self.own_addr,
            self.addr1
        )

        valid_key = "63d901c4d57cde34fc1f1e28b9af5d56ed342cae5c2fb470046d0130a4226b0c"
        self.signing_key = nacl.signing.SigningKey(valid_key, encoder=nacl.encoding.HexEncoder)
        verify_key = self.signing_key.verify_key
        h = nacl.hash.sha512(verify_key.encode())
        self.storage = ForgetfulStorage()
        self.node = Node(unhexlify(h[:40]), self.public_ip, self.port, verify_key.encode(), None, FULL_CONE, True)
        self.db = Database(filepath="test.db")
        self.protocol = KademliaProtocol(self.node, self.storage, 20, self.db, self.signing_key)

        self.wire_protocol = PulseShopProtocol(self.db, self.own_addr, FULL_CONE)
        self.wire_protocol.register_processor(self.protocol)

        self.protocol.connect_multiplexer(self.wire_protocol)
        self.handler = self.wire_protocol.ConnHandler([self.protocol], self.wire_protocol, None,
                                                      self.wire_protocol.ban_score)

        transport = mock.Mock(spec_set=udp.Port)
        ret_val = address.IPv4Address('UDP', self.public_ip, self.port)
        transport.attach_mock(mock.Mock(return_value=ret_val), 'getHost')
        self.wire_protocol.makeConnection(transport)

        self.node1 = Node(digest("id1"), self.addr1[0], self.addr1[1], digest("key1"), None, FULL_CONE, True)
        self.node2 = Node(digest("id2"), self.addr2[0], self.addr2[1], digest("key2"), None, FULL_CONE, True)
        self.node3 = Node(digest("id3"), self.addr3[0], self.addr3[1], digest("key3"), None, FULL_CONE, True)

    def tearDown(self):
        self.con.shutdown()
        self.wire_protocol.shutdown()
        os.remove("test.db")

    def test_find(self):
        self._connecting_to_connected()
        self.wire_protocol[self.addr1] = self.con
        self.wire_protocol[self.addr2] = self.con
        self.wire_protocol[self.addr3] = self.con

        self.protocol.router.addContact(self.node1)
        self.protocol.router.addContact(self.node2)
        self.protocol.router.addContact(self.node3)

        node = Node(digest("s"))
        nearest = self.protocol.router.findNeighbors(node)
        spider = NodeSpiderCrawl(self.protocol, node, nearest, 20, 3)
        spider.find()

        self.clock.advance(constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        self.assertEqual(len(self.proto_mock.send_datagram.call_args_list), 4)

    def test_nodesFound(self):
        self._connecting_to_connected()
        self.wire_protocol[self.addr1] = self.con
        self.wire_protocol[self.addr2] = self.con
        self.wire_protocol[self.addr3] = self.con

        self.protocol.router.addContact(self.node1)
        self.protocol.router.addContact(self.node2)
        self.protocol.router.addContact(self.node3)

        node = Node(digest("s"))
        nearest = self.protocol.router.findNeighbors(node)
        spider = NodeSpiderCrawl(self.protocol, node, nearest, 20, 3)
        response = (True, (self.node1.getProto().SerializeToString(), self.node2.getProto().SerializeToString(),
                           self.node3.getProto().SerializeToString()))
        responses = {self.node1.id: response}
        spider._nodesFound(responses)

        self.clock.advance(constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        self.assertEqual(len(self.proto_mock.send_datagram.call_args_list), 4)

        response = (True, (self.node1.getProto().SerializeToString(), self.node2.getProto().SerializeToString(),
                           self.node3.getProto().SerializeToString()))
        responses = {self.node1.id: response}
        nodes = spider._nodesFound(responses)
        node_protos = []
        for n in nodes:
            node_protos.append(n.getProto())

        self.assertTrue(self.node1.getProto() in node_protos)
        self.assertTrue(self.node2.getProto() in node_protos)
        self.assertTrue(self.node3.getProto() in node_protos)

        response = (False, (self.node1.getProto().SerializeToString(), self.node2.getProto().SerializeToString(),
                            self.node3.getProto().SerializeToString()))
        responses = {self.node1.id: response}
        nodes = spider._nodesFound(responses)
        node_protos = []
        for n in nodes:
            node_protos.append(n.getProto())

        self.assertTrue(self.node2.getProto() in node_protos)
        self.assertTrue(self.node3.getProto() in node_protos)

    def _connecting_to_connected(self):
        remote_synack_packet = packet.Packet.from_data(
            42,
            self.con.own_addr,
            self.con.dest_addr,
            ack=0,
            syn=True
        )
        self.con.receive_packet(remote_synack_packet, self.addr1)

        self.clock.advance(0)
        connection.REACTOR.runUntilCurrent()

        self.next_remote_seqnum = 43

        m_calls = self.proto_mock.send_datagram.call_args_list
        sent_syn_packet = packet.Packet.from_bytes(m_calls[0][0][0])
        seqnum = sent_syn_packet.sequence_number

        self.handler_mock.reset_mock()
        self.proto_mock.reset_mock()

        self.next_seqnum = seqnum + 1
class NodeSpiderCrawlTest(unittest.TestCase):
    def setUp(self):
        self.public_ip = '123.45.67.89'
        self.port = 12345
        self.own_addr = (self.public_ip, self.port)
        self.addr1 = ('132.54.76.98', 54321)
        self.addr2 = ('231.76.45.89', 15243)
        self.addr3 = ("193.193.111.00", 99999)

        self.clock = task.Clock()
        connection.REACTOR.callLater = self.clock.callLater

        self.proto_mock = mock.Mock(spec_set=rudp.ConnectionMultiplexer)
        self.handler_mock = mock.Mock(spec_set=connection.Handler)
        self.con = connection.Connection(
            self.proto_mock,
            self.handler_mock,
            self.own_addr,
            self.addr1
        )

        valid_key = "1a5c8e67edb8d279d1ae32fa2da97e236b95e95c837dc8c3c7c2ff7a7cc29855"
        self.signing_key = nacl.signing.SigningKey(valid_key, encoder=nacl.encoding.HexEncoder)
        verify_key = self.signing_key.verify_key
        signed_pubkey = self.signing_key.sign(str(verify_key))
        h = nacl.hash.sha512(signed_pubkey)
        self.storage = ForgetfulStorage()
        self.node = Node(unhexlify(h[:40]), self.public_ip, self.port, signed_pubkey, True)
        self.db = Database(filepath=":memory:")
        self.protocol = KademliaProtocol(self.node, self.storage, 20, self.db)

        self.wire_protocol = OpenBazaarProtocol(self.own_addr, "Full Cone")
        self.wire_protocol.register_processor(self.protocol)

        self.protocol.connect_multiplexer(self.wire_protocol)
        self.handler = self.wire_protocol.ConnHandler([self.protocol], self.wire_protocol)

        transport = mock.Mock(spec_set=udp.Port)
        ret_val = address.IPv4Address('UDP', self.public_ip, self.port)
        transport.attach_mock(mock.Mock(return_value=ret_val), 'getHost')
        self.wire_protocol.makeConnection(transport)

        self.node1 = Node(digest("id1"), self.addr1[0], self.addr1[1], digest("key1"), True)
        self.node2 = Node(digest("id2"), self.addr2[0], self.addr2[1], digest("key2"), True)
        self.node3 = Node(digest("id3"), self.addr3[0], self.addr3[1], digest("key3"), True)

    def test_find(self):
        self._connecting_to_connected()
        self.wire_protocol[self.addr1] = self.con
        self.wire_protocol[self.addr2] = self.con
        self.wire_protocol[self.addr3] = self.con

        self.protocol.router.addContact(self.node1)
        self.protocol.router.addContact(self.node2)
        self.protocol.router.addContact(self.node3)

        node = Node(digest("s"))
        nearest = self.protocol.router.findNeighbors(node)
        spider = NodeSpiderCrawl(self.protocol, node, nearest, 20, 3)
        spider.find()

        self.clock.advance(100 * constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        self.assertEqual(len(self.proto_mock.send_datagram.call_args_list), 4)

    def test_nodesFound(self):
        self._connecting_to_connected()
        self.wire_protocol[self.addr1] = self.con
        self.wire_protocol[self.addr2] = self.con
        self.wire_protocol[self.addr3] = self.con

        self.protocol.router.addContact(self.node1)
        self.protocol.router.addContact(self.node2)
        self.protocol.router.addContact(self.node3)

        node = Node(digest("s"))
        nearest = self.protocol.router.findNeighbors(node)
        spider = NodeSpiderCrawl(self.protocol, node, nearest, 20, 3)
        response = (True, (self.node1.getProto().SerializeToString(), self.node2.getProto().SerializeToString(),
                           self.node3.getProto().SerializeToString()))
        responses = {self.node1.id: response}
        spider._nodesFound(responses)

        self.clock.advance(100 * constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        self.assertEqual(len(self.proto_mock.send_datagram.call_args_list), 4)

        response = (True, (self.node1.getProto().SerializeToString(), self.node2.getProto().SerializeToString(),
                           self.node3.getProto().SerializeToString()))
        responses = {self.node1.id: response}
        nodes = spider._nodesFound(responses)
        node_protos = []
        for n in nodes:
            node_protos.append(n.getProto())

        self.assertTrue(self.node1.getProto() in node_protos)
        self.assertTrue(self.node2.getProto() in node_protos)
        self.assertTrue(self.node3.getProto() in node_protos)

        response = (False, (self.node1.getProto().SerializeToString(), self.node2.getProto().SerializeToString(),
                            self.node3.getProto().SerializeToString()))
        responses = {self.node1.id: response}
        nodes = spider._nodesFound(responses)
        node_protos = []
        for n in nodes:
            node_protos.append(n.getProto())

        self.assertTrue(self.node2.getProto() in node_protos)
        self.assertTrue(self.node3.getProto() in node_protos)

    def _connecting_to_connected(self):
        remote_synack_packet = packet.Packet.from_data(
            42,
            self.con.own_addr,
            self.con.dest_addr,
            ack=0,
            syn=True
        )
        self.con.receive_packet(remote_synack_packet)

        self.clock.advance(0)
        connection.REACTOR.runUntilCurrent()

        self.next_remote_seqnum = 43

        m_calls = self.proto_mock.send_datagram.call_args_list
        sent_syn_packet = packet.Packet.from_bytes(m_calls[0][0][0])
        seqnum = sent_syn_packet.sequence_number

        self.handler_mock.reset_mock()
        self.proto_mock.reset_mock()

        self.next_seqnum = seqnum + 1
Beispiel #47
0
 def test_tuple(self):
     n = Node('127.0.0.1', 0, 'testkey')
     i = n.__iter__()
     self.assertIn('127.0.0.1', i)
     self.assertIn(0, i)
     self.assertIn('testkey', i)
 def test_tuple(self):
     n = Node("127.0.0.1", 0, "testkey")
     i = n.__iter__()
     self.assertIn("127.0.0.1", i)
     self.assertIn(0, i)
     self.assertIn("testkey", i)
Beispiel #49
0
class ValueSpiderCrawlTest(unittest.TestCase):

    def setUp(self):
        self.public_ip = '123.45.67.89'
        self.port = 12345
        self.own_addr = (self.public_ip, self.port)
        self.addr1 = ('132.54.76.98', 54321)
        self.addr2 = ('231.76.45.89', 15243)
        self.addr3 = ("193.193.111.00", 99999)

        self.clock = task.Clock()
        connection.REACTOR.callLater = self.clock.callLater

        self.proto_mock = mock.Mock(spec_set=rudp.ConnectionMultiplexer)
        self.handler_mock = mock.Mock(spec_set=connection.Handler)
        self.con = connection.Connection(
            self.proto_mock,
            self.handler_mock,
            self.own_addr,
            self.addr1
        )

        valid_key = "1a5c8e67edb8d279d1ae32fa2da97e236b95e95c837dc8c3c7c2ff7a7cc29855"
        self.signing_key = nacl.signing.SigningKey(valid_key, encoder=nacl.encoding.HexEncoder)
        verify_key = self.signing_key.verify_key
        signed_pubkey = self.signing_key.sign(str(verify_key))
        h = nacl.hash.sha512(signed_pubkey)
        self.storage = ForgetfulStorage()
        self.node = Node(unhexlify(h[:40]), self.public_ip, self.port, signed_pubkey, True)
        self.protocol = KademliaProtocol(self.node, self.storage, 20)

        transport = mock.Mock(spec_set=udp.Port)
        ret_val = address.IPv4Address('UDP', self.public_ip, self.port)
        transport.attach_mock(mock.Mock(return_value=ret_val), 'getHost')
        self.protocol.makeConnection(transport)

        self.node1 = Node(digest("id1"), self.addr1[0], self.addr1[1], digest("key1"), True)
        self.node2 = Node(digest("id2"), self.addr2[0], self.addr2[1], digest("key2"), True)
        self.node3 = Node(digest("id3"), self.addr3[0], self.addr3[1], digest("key3"), True)

    def tearDown(self):
        self.con.shutdown()
        self.protocol.shutdown()

    def test_find(self):
        self._connecting_to_connected()
        self.protocol[self.addr1] = self.con
        self.protocol[self.addr2] = self.con
        self.protocol[self.addr3] = self.con

        self.protocol.router.addContact(self.node1)
        self.protocol.router.addContact(self.node2)
        self.protocol.router.addContact(self.node3)

        node = Node(digest("s"))
        nearest = self.protocol.router.findNeighbors(node)
        spider = ValueSpiderCrawl(self.protocol, node, nearest, 20, 3)
        spider.find()

        self.clock.advance(100 * constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        self.assertEqual(len(self.proto_mock.send_datagram.call_args_list), 4)

    def test_nodesFound(self):
        self._connecting_to_connected()
        self.protocol[self.addr1] = self.con
        self.protocol[self.addr2] = self.con
        self.protocol[self.addr3] = self.con

        self.protocol.router.addContact(self.node1)
        self.protocol.router.addContact(self.node2)
        self.protocol.router.addContact(self.node3)

        # test resonse with uncontacted nodes
        node = Node(digest("s"))
        nearest = self.protocol.router.findNeighbors(node)
        spider = ValueSpiderCrawl(self.protocol, node, nearest, 20, 3)
        response = (True, (self.node1.getProto().SerializeToString(), self.node2.getProto().SerializeToString(),
                           self.node3.getProto().SerializeToString()))
        responses = {self.node1.id: response}
        spider._nodesFound(responses)
        self.clock.advance(100 * constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        self.assertEqual(len(self.proto_mock.send_datagram.call_args_list), 4)

        # test all been contacted
        spider = ValueSpiderCrawl(self.protocol, node, nearest, 20, 3)
        for peer in spider.nearest.getUncontacted():
            spider.nearest.markContacted(peer)
        response = (True, (self.node1.getProto().SerializeToString(), self.node2.getProto().SerializeToString(),
                           self.node3.getProto().SerializeToString()))
        responses = {self.node2.id: response}
        resp = spider._nodesFound(responses)
        self.assertTrue(resp is None)

        # test didn't happen
        spider = ValueSpiderCrawl(self.protocol, node, nearest, 20, 3)
        response = (False, (self.node1.getProto().SerializeToString(), self.node2.getProto().SerializeToString(),
                            self.node3.getProto().SerializeToString()))
        responses = {self.node1.id: response}
        spider._nodesFound(responses)
        self.assertTrue(len(spider.nearest) == 2)

        # test got value
        val = Value()
        val.valueKey = digest("contractID")
        val.serializedData = self.protocol.sourceNode.getProto().SerializeToString()
        response = (True, ("value", val.SerializeToString()))
        responses = {self.node3.id: response}
        spider.nearestWithoutValue = NodeHeap(node, 1)
        value = spider._nodesFound(responses)
        self.assertEqual(value[0], val.SerializeToString())

    def test_handleFoundValues(self):
        self._connecting_to_connected()
        self.protocol[self.addr1] = self.con

        self.protocol.router.addContact(self.node1)
        self.protocol.router.addContact(self.node2)
        self.protocol.router.addContact(self.node3)

        node = Node(digest("s"))
        nearest = self.protocol.router.findNeighbors(node)
        spider = ValueSpiderCrawl(self.protocol, node, nearest, 20, 3)
        val = Value()
        val.valueKey = digest("contractID")
        val.serializedData = self.node1.getProto().SerializeToString()
        val1 = val.SerializeToString()
        value = spider._handleFoundValues([(val1,)])
        self.assertEqual(value[0], val.SerializeToString())

        # test handle multiple values
        val.serializedData = self.node2.getProto().SerializeToString()
        val2 = val.SerializeToString()
        found_values = [(val1,), (val1,), (val2,)]
        self.assertEqual(spider._handleFoundValues(found_values), (val1,))

        # test store value at nearest without value
        spider.nearestWithoutValue.push(self.node1)
        spider._handleFoundValues(found_values)
        self.clock.advance(100 * constants.PACKET_TIMEOUT)
        connection.REACTOR.runUntilCurrent()
        self.assertTrue(len(self.proto_mock.send_datagram.call_args_list) > 1)
        self.proto_mock.send_datagram.call_args_list = []

    def _connecting_to_connected(self):
        remote_synack_packet = packet.Packet.from_data(
            42,
            self.con.own_addr,
            self.con.dest_addr,
            ack=0,
            syn=True
        )
        self.con.receive_packet(remote_synack_packet)

        self.clock.advance(0)
        connection.REACTOR.runUntilCurrent()

        self.next_remote_seqnum = 43

        m_calls = self.proto_mock.send_datagram.call_args_list
        sent_syn_packet = packet.Packet.from_bytes(m_calls[0][0][0])
        seqnum = sent_syn_packet.sequence_number

        self.handler_mock.reset_mock()
        self.proto_mock.reset_mock()

        self.next_seqnum = seqnum + 1