哈希信息是否等同于主线 DHT 中的对等 ID



我正在研究主线DHT,我不明白一个细微差别。

在这里:https://www.bittorrent.org/beps/bep_0005.html 写道:"距离指标"用于比较两个节点 ID 或节点 ID 和"接近度"的信息哈希。

还写道:"宣布控制查询节点的对等方正在端口上下载种子。announce_peer有四个参数:"id"包含查询节点的节点ID,"info_hash"包含种子的信息哈希,"port"包含端口作为整数,以及响应上一个get_peers查询而收到的"token"。

因此,例如,我们有一个 ID 为 223456789zxcvbnmasdf 的对等体,其 IP 为 86.23.145.714,端口为:7853 我知道这个同行下载了 2 个带有信息哈希的种子文件:023456789zxcvbnmasdf 和 123456789zxcvbnmasdf。

那么我的 k 桶记录到底应该是什么样子的呢? 喜欢这个:

{"id": "223456789zxcvbnmasdf", "ip": "86.23.145.714", "port": "7853", "torrents": ["023456789zxcvbnmasdg", "123456789zxcvbnmasdh"]} ?

或者种子文件应该像 k 存储桶中的"等效"记录(具有重复的 IP 和端口)以及对等

{"id": "223456789zxcvbnmasdf", "ip": "86.23.145.714", "port": "7853"},
{"id": "023456789zxcvbnmasdg", "ip": "86.23.145.714", "port": "7853"},
{"id": "123456789zxcvbnmasdh", "ip": "86.23.145.714", "port": "7853"} ?

我问是因为这不仅仅是实现的细微差别。因为"k"在所有客户端中通常是 20 或其他整数。因此,如果我使用 k-buckets 将种子文件存储为全权限成员,我将有更少的空间来存储真正的对等方数据。

感谢您的回答!

如何在内部构建数据取决于您。它所要做的就是履行规范的合同。原则上,人们可以根据异或距离将种子与存储桶相关联 - 例如出于资源核算原因 - 但大多数实现将路由表和存储分开。

主路由表仅包含节点,即DHT覆盖本身的结构成员。另一方面,种子不是叠加层的一部分。它们是存储在覆盖层(哈希表抽象)之上的数据。因此得名分布式哈希表。即它们存在于不同的抽象级别。

k-buckets datastructure是bit-torrent协议的实现细节,以便对等方回复足够快的FIND_PEERSFIND_VALUE

我在 kademlia 实现中所做的是将路由表保留在 python 字典中,默认情况下,我在 5 秒内计算最近的对等体,这是我用来等待 UDP 回复的超时。为此,我需要将路由表保持在 1 000 000 个条目以下。

就像我上面说的,路由表是一个简单的pythondict,它将peerid映射到(address, port)

路由表存储对等方而不是值,即不存储infohash地址。

当我收到FIND_PEERS消息时,程序会回复以下代码:

async def peers(self, address, uid):
"""Remote procedure that returns peers that are near UID"""
log.debug("[%r] find peers uid=%r from %r", self._uid, uid, address)
# XXX: if this takes more than 5 seconds (see RPCProtocol) it
# will timeout in the other side.
uids = nearest(self._replication, self._peers.keys(), uid)
out = [self._peers[x] for x in uids]
return out

当我收到FIND_VALUE消息时,程序会回复以下代码:

async def value(self, address, key):
"""Remote procedure that returns the associated value or peers that
are near KEY"""
log.debug("[%r] value key=%r from %r", self._uid, key, address)
out = await lookup(key)
if out is None:
# value is not found, reply with peers that are near KEY
out = nearest(self._replication, self._peers.keys(), uid)
return (b"PEERS", out)
else:
return (b"VALUE", out)

以下是nearest的定义:

def nearest(k, peers, uid):
"""Return K nearest to to UID peers in PEERS according to XOR"""
# XXX: It only works with len(peers) < 10^6 more than that count
# of peers and the time it takes to compute the nearest peers will
# timeout after 5 seconds on the other side. See RPCProtocol and
# Peer.peers.
return nsmallest(k, peers, key=functools.partial(operator.xor, uid))

也就是说,它根据peeridpeers进行排序,并返回最小的knsmallest应该是sort(peers, key=functools.partial(operator.xor, uid))[:k]的优化版本,其中uidpeeridinfohash(分别为FIND_PEERSFIND_VALUE)。

现在回到您的问题:

哈希信息等同于主线DHT中的对等ID吗?

hashinfo是一个哈希的东西,与peerid即相同类型的哈希。 它们是路由表中可能的键。也就是说,种子文件与哈希相关联,对等体与称为peerid的同一种哈希相关联。对等方拥有靠近其peerid的密钥的"所有权"。但是,如果您愿意,hashinfo不会存储在路由表或 k 存储桶中。hashinfo存储在另一个映射中,该映射将hashinfo哈希与其值相关联。

我问是因为这不仅仅是实现的细微差别。因为"k"在所有客户端中通常是 20 或其他整数。因此,如果我使用 k-buckets 将种子文件存储为全权限成员,我将有更少的空间来存储真正的对等方数据。

这里对我试图在上面解释的同样的事情存在误解。hashinfo是存储字典中的键。而peerid是路由表中的密钥,又名。K-buckets 数据结构。它们都具有相同的格式,因为这就是 kademlia 路由算法的工作方式。您必须能够将hashinfopeeridxor进行比较,以便能够分辨哪些对等方"拥有"哪个hashinfo值。

正如您在第二个代码片段中看到的那样,当另一个对等方请求与哈希关联的值时,它会调用类似于storage.get(key)lookup(key),除了在我的情况下,代码将值存储在数据库中。


也许对 k 桶用于存储DHT 路由信息这一事实存在误解。最重要的是,洪流协议使用 DHT 来存储洪流路由信息。


值得一提的是,qadom的 peer.py 文件是我实现受kademlia启发的DHT的地方(除了我使用256位哈希并放弃alphak参数并使用单个REPLICATION参数)。代码大部分时间都在检查测试。

此外,我从另一个项目中获得灵感,称为kademlia,它(尝试?)实现k-buckets。

据我了解,torrent DHT路由看起来像qadombag功能,除了接收对等方必须对公告进行身份验证,而在qadom包中是免费的。

另外,检查原始的卡德姆利亚论文。

最新更新