2023-04-20 18:51:13 +00:00
|
|
|
package enr
|
|
|
|
|
|
|
|
import (
|
2023-06-01 20:01:15 +00:00
|
|
|
"errors"
|
|
|
|
|
2023-04-20 18:51:13 +00:00
|
|
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
|
|
|
"github.com/ethereum/go-ethereum/p2p/enr"
|
|
|
|
"github.com/waku-org/go-waku/waku/v2/protocol"
|
|
|
|
)
|
|
|
|
|
2023-04-25 16:09:55 +00:00
|
|
|
func WithWakuRelayShardingIndicesList(rs protocol.RelayShards) ENROption {
|
|
|
|
return func(localnode *enode.LocalNode) error {
|
|
|
|
value, err := rs.IndicesList()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
localnode.Set(enr.WithEntry(ShardingIndicesListEnrField, value))
|
|
|
|
return nil
|
2023-04-20 18:51:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-25 16:09:55 +00:00
|
|
|
func WithWakuRelayShardingBitVector(rs protocol.RelayShards) ENROption {
|
|
|
|
return func(localnode *enode.LocalNode) error {
|
|
|
|
localnode.Set(enr.WithEntry(ShardingBitVectorEnrField, rs.BitVector()))
|
|
|
|
return nil
|
|
|
|
}
|
2023-04-20 18:51:13 +00:00
|
|
|
}
|
|
|
|
|
2023-06-01 20:01:15 +00:00
|
|
|
func WithWakuRelaySharding(rs protocol.RelayShards) ENROption {
|
2023-04-25 16:09:55 +00:00
|
|
|
return func(localnode *enode.LocalNode) error {
|
|
|
|
if len(rs.Indices) >= 64 {
|
|
|
|
return WithWakuRelayShardingBitVector(rs)(localnode)
|
|
|
|
} else {
|
|
|
|
return WithWakuRelayShardingIndicesList(rs)(localnode)
|
|
|
|
}
|
2023-04-20 18:51:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-01 20:01:15 +00:00
|
|
|
func WithWakuRelayShardingTopics(topics ...string) ENROption {
|
|
|
|
return func(localnode *enode.LocalNode) error {
|
|
|
|
rs, err := protocol.TopicsToRelayShards(topics...)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(rs) != 1 {
|
|
|
|
return errors.New("expected a single RelayShards")
|
|
|
|
}
|
|
|
|
|
|
|
|
return WithWakuRelaySharding(rs[0])(localnode)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-20 18:51:13 +00:00
|
|
|
// ENR record accessors
|
|
|
|
|
2023-06-20 20:39:20 +00:00
|
|
|
func RelayShardingIndicesList(record *enr.Record) (*protocol.RelayShards, error) {
|
2023-04-20 18:51:13 +00:00
|
|
|
var field []byte
|
2023-06-20 20:39:20 +00:00
|
|
|
if err := record.Load(enr.WithEntry(ShardingIndicesListEnrField, field)); err != nil {
|
2023-04-20 18:51:13 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
res, err := protocol.FromIndicesList(field)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &res, nil
|
|
|
|
}
|
|
|
|
|
2023-06-20 20:39:20 +00:00
|
|
|
func RelayShardingBitVector(record *enr.Record) (*protocol.RelayShards, error) {
|
2023-04-20 18:51:13 +00:00
|
|
|
var field []byte
|
2023-06-20 20:39:20 +00:00
|
|
|
if err := record.Load(enr.WithEntry(ShardingBitVectorEnrField, field)); err != nil {
|
|
|
|
if enr.IsNotFound(err) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
return nil, err
|
2023-04-20 18:51:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
res, err := protocol.FromBitVector(field)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &res, nil
|
|
|
|
}
|
|
|
|
|
2023-06-20 20:39:20 +00:00
|
|
|
func RelaySharding(record *enr.Record) (*protocol.RelayShards, error) {
|
|
|
|
res, err := RelayShardingIndicesList(record)
|
2023-04-20 18:51:13 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if res != nil {
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
|
2023-06-20 20:39:20 +00:00
|
|
|
return RelayShardingBitVector(record)
|
2023-04-20 18:51:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Utils
|
|
|
|
|
2023-06-20 20:39:20 +00:00
|
|
|
func ContainsShard(record *enr.Record, cluster uint16, index uint16) bool {
|
2023-04-20 18:51:13 +00:00
|
|
|
if index > protocol.MaxShardIndex {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2023-06-20 20:39:20 +00:00
|
|
|
rs, err := RelaySharding(record)
|
2023-04-20 18:51:13 +00:00
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return rs.Contains(cluster, index)
|
|
|
|
}
|
|
|
|
|
2023-06-20 20:39:20 +00:00
|
|
|
func ContainsShardWithNsTopic(record *enr.Record, topic protocol.NamespacedPubsubTopic) bool {
|
2023-04-20 18:51:13 +00:00
|
|
|
if topic.Kind() != protocol.StaticSharding {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
shardTopic := topic.(protocol.StaticShardingPubsubTopic)
|
2023-06-20 20:39:20 +00:00
|
|
|
return ContainsShard(record, shardTopic.Cluster(), shardTopic.Shard())
|
|
|
|
}
|
2023-04-20 18:51:13 +00:00
|
|
|
|
2023-06-20 20:39:20 +00:00
|
|
|
func ContainsRelayShard(record *enr.Record, topic protocol.StaticShardingPubsubTopic) bool {
|
|
|
|
return ContainsShardWithNsTopic(record, topic)
|
2023-04-20 18:51:13 +00:00
|
|
|
}
|
|
|
|
|
2023-06-20 20:39:20 +00:00
|
|
|
func ContainsShardTopic(record *enr.Record, topic string) bool {
|
2023-04-20 18:51:13 +00:00
|
|
|
shardTopic, err := protocol.ToShardedPubsubTopic(topic)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
2023-06-20 20:39:20 +00:00
|
|
|
return ContainsShardWithNsTopic(record, shardTopic)
|
2023-04-20 18:51:13 +00:00
|
|
|
}
|