go libp2p kad dht

重要的参数

alpha: 同一时间最多只能向alpha个节点查询。默认值为10
beta: 迭代查询结束条件,所有非unreachable的节点按照距离排序后,前beta个节点全部都查询过即可结束。默认值为3
K(bucketSize): 默认值为20

  1. 迭代查询开始时,从K桶中选取最多K个节点。
  2. 迭代查询结束后,所有非unreachable的节点按照距离排序,向前(最多)K个节点中那些未查询或者正在查询的节点发起查询。
  3. FindProviders和GetValue需要找到K个记录才能结束查找。
  4. handleGetValue,handleGetProviders和handleFindPeer会从K桶中选取最多K个节点信息,回复给对方

请求

var Message_MessageType_value = map[string]int32{
	"PUT_VALUE":     0,
	"GET_VALUE":     1,
	"ADD_PROVIDER":  2,
	"GET_PROVIDERS": 3,
	"FIND_NODE":     4,
	"PING":          5,
}

所有DHT节点收到请求后,调用各请求的处理函数,然后将发送者的节点ID保存到路由表中。

FindPeer

首先在本地查找,如果当前已经和该peer连接,或者可连接(之前连接过,优雅关闭了),则查询结束。否则向外迭代查询,发送"FIND_NODE"请求。

其它节点收到请求后,如果目标节点是自己,就将自己的节点信息发回去,否则将K桶中距离最近的K个节点信息回复给对方。

PutValue

首先在本地查找记录,如果本地有记录,且value比本地记录更旧,则报错返回;否则向外迭代查询,发送"FIND_NODE"请求,得到一批距离key最近的节点(最多K个),向它们发送"PUT_VALUE"请求,将记录发给它们。

其它节收到"PUT_VALUE"请求后,首先和本地记录进行比较,比本地记录新就替换。

GetValue

首先在本地查找,同时向外迭代查询,发送"GET_VALUE"请求,得到一些记录和距离资源最近的节点信息(最多K个),通过对这些记录进行比较,得到最新的记录,然后向这些节点中那些没有返回记录或者返回旧的记录的节点发送"PUT_VALUE"请求,将记录发给它们。

其它节点收到"GET_VALUE"请求后,将本地记录和K桶中距离最近的K个节点信息回复给对方。

value

value目前默认有两个validator: pk和ipns。pk用于验证ID和公钥是否匹配,无所谓新旧。
ipns记录可能是最新的,也可能是旧的。先比较序列号(Sequence),相等则比较有效期(validity),如果还是相等最后通过比较字节大小来判断。

type IpnsEntry struct {
	Value        []byte                  `protobuf:"bytes,1,req,name=value" json:"value,omitempty"`
	Signature    []byte                  `protobuf:"bytes,2,req,name=signature" json:"signature,omitempty"`
	ValidityType *IpnsEntry_ValidityType `protobuf:"varint,3,opt,name=validityType,enum=ipns.pb.IpnsEntry_ValidityType" json:"validityType,omitempty"`
	Validity     []byte                  `protobuf:"bytes,4,opt,name=validity" json:"validity,omitempty"`
	Sequence     *uint64                 `protobuf:"varint,5,opt,name=sequence" json:"sequence,omitempty"`
	Ttl          *uint64                 `protobuf:"varint,6,opt,name=ttl" json:"ttl,omitempty"`
	// in order for nodes to properly validate a record upon receipt, they need the public
	// key associated with it. For old RSA keys, its easiest if we just send this as part of
	// the record itself. For newer ed25519 keys, the public key can be embedded in the
	// peerID, making this field unnecessary.
	PubKey               []byte   `protobuf:"bytes,7,opt,name=pubKey" 
}

value的pb结构是Record,Record带有时间戳,但是该时间戳没有被使用,datastore的value时间戳是保存时的时间戳。

// Record represents a dht record that contains a value
// for a key value pair
type Record struct {
	// The key that references this record
	Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
	// The actual value this record is storing
	Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
	// Time the record was received, set by receiver
	TimeReceived         string   `protobuf:"bytes,5,opt,name=timeReceived,proto3" json:"timeReceived,omitempty"`
}

值得注意的是,handleGetValue从datastore获取到value后,会检查value的时间,如果距离上次保存已经超过(默认)36h,则视为无效(本着对其它节点负责的态度?)。
PutValue和handlePutValue由于是写操作,所以不需检查时间戳,而GetValue也没有检查这个时间戳,可能是因为记录虽旧,但有好过无。

Provide

首先将provider记录保存在本地,接着向外迭代查询,发送"FIND_NODE"请求,得到一批距离key最近的节点(最多K个),向它们发送"ADD_PROVIDER"请求,将记录发给它们。

其它节点收到"ADD_PROVIDER"请求后,先将provider中的节点信息添加到peerstore,再将记录保存起来。

FindProviders

首先在本地查找,如果本地有不少于K个(该资源的)provider记录,则查询结束,否则向外迭代查询,发送"GET_PROVIDERS"请求。

其它节点收到请求后,将其本地(该资源的)所有provider记录以及K桶中距离最近的K个节点信息回复给对方。

provider

provider记录可能是有效的,也可能无效,所以FindProviders得到的是一组(最多K个)记录,这些记录只要有一个是有效的即可。

所有provider记录由ProviderManager管理,provider结构本身并没有时间戳,而是在添加provider时附带时间戳,以便ProviderManager定期对那些过期的provider记录进行清理。

type Message_Peer struct {
	// ID of a given peer.
	Id byteString `protobuf:"bytes,1,opt,name=id,proto3,customtype=byteString" json:"id"`
	// multiaddrs for a given peer
	Addrs [][]byte `protobuf:"bytes,2,rep,name=addrs,proto3" json:"addrs,omitempty"`
	// used to signal the sender's connection capabilities to the peer
	Connection           Message_ConnectionType `protobuf:"varint,3,opt,name=connection,proto3,enum=dht.pb.Message_ConnectionType" json:"connection,omitempty"`
}

思考:
provider记录没有签名,是否可以构造大量的虚假provider记录,对网络进行DDOS攻击?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值