mirror of https://github.com/waku-org/nwaku.git
refactor(enr): node capabilities code clean up and reorganization
This commit is contained in:
parent
67db35e29d
commit
7639d8d273
|
@ -269,10 +269,12 @@ proc initNode(conf: WakuNodeConf,
|
||||||
else:
|
else:
|
||||||
@[]
|
@[]
|
||||||
|
|
||||||
wakuFlags = initWakuFlags(conf.lightpush,
|
wakuFlags = CapabilitiesBitfield.init(
|
||||||
conf.filter,
|
lightpush = conf.lightpush,
|
||||||
conf.store,
|
filter = conf.filter,
|
||||||
conf.relay)
|
store = conf.store,
|
||||||
|
relay = conf.relay
|
||||||
|
)
|
||||||
|
|
||||||
var node: WakuNode
|
var node: WakuNode
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ proc setupAndPublish(rng: ref HmacDrbgContext) {.async.} =
|
||||||
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
||||||
ip = ValidIpAddress.init("0.0.0.0")
|
ip = ValidIpAddress.init("0.0.0.0")
|
||||||
node = WakuNode.new(nodeKey, ip, Port(wakuPort))
|
node = WakuNode.new(nodeKey, ip, Port(wakuPort))
|
||||||
flags = initWakuFlags(lightpush = false, filter = false, store = false, relay = true)
|
flags = CapabilitiesBitfield.init(lightpush = false, filter = false, store = false, relay = true)
|
||||||
|
|
||||||
# assumes behind a firewall, so not care about being discoverable
|
# assumes behind a firewall, so not care about being discoverable
|
||||||
node.wakuDiscv5 = WakuDiscoveryV5.new(
|
node.wakuDiscv5 = WakuDiscoveryV5.new(
|
||||||
|
|
|
@ -32,7 +32,7 @@ proc setupAndSubscribe(rng: ref HmacDrbgContext) {.async.} =
|
||||||
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
||||||
ip = ValidIpAddress.init("0.0.0.0")
|
ip = ValidIpAddress.init("0.0.0.0")
|
||||||
node = WakuNode.new(nodeKey, ip, Port(wakuPort))
|
node = WakuNode.new(nodeKey, ip, Port(wakuPort))
|
||||||
flags = initWakuFlags(lightpush = false, filter = false, store = false, relay = true)
|
flags = CapabilitiesBitfield.init(lightpush = false, filter = false, store = false, relay = true)
|
||||||
|
|
||||||
# assumes behind a firewall, so not care about being discoverable
|
# assumes behind a firewall, so not care about being discoverable
|
||||||
node.wakuDiscv5 = WakuDiscoveryV5.new(
|
node.wakuDiscv5 = WakuDiscoveryV5.new(
|
||||||
|
|
|
@ -38,10 +38,12 @@ procSuite "Waku Discovery v5":
|
||||||
nodeUdpPort3 = Port(9004)
|
nodeUdpPort3 = Port(9004)
|
||||||
node3 = WakuNode.new(nodeKey3, bindIp, nodeTcpPort3)
|
node3 = WakuNode.new(nodeKey3, bindIp, nodeTcpPort3)
|
||||||
|
|
||||||
flags = initWakuFlags(lightpush = false,
|
flags = CapabilitiesBitfield.init(
|
||||||
filter = false,
|
lightpush = false,
|
||||||
store = false,
|
filter = false,
|
||||||
relay = true)
|
store = false,
|
||||||
|
relay = true
|
||||||
|
)
|
||||||
|
|
||||||
# E2E relay test paramaters
|
# E2E relay test paramaters
|
||||||
pubSubTopic = "/waku/2/default-waku/proto"
|
pubSubTopic = "/waku/2/default-waku/proto"
|
||||||
|
@ -128,10 +130,12 @@ procSuite "Waku Discovery v5":
|
||||||
extIp = ValidIpAddress.init("127.0.0.1")
|
extIp = ValidIpAddress.init("127.0.0.1")
|
||||||
expectedMultiAddr = MultiAddress.init("/ip4/200.200.200.200/tcp/9000/wss").tryGet()
|
expectedMultiAddr = MultiAddress.init("/ip4/200.200.200.200/tcp/9000/wss").tryGet()
|
||||||
|
|
||||||
flags = initWakuFlags(lightpush = false,
|
flags = CapabilitiesBitfield.init(
|
||||||
filter = false,
|
lightpush = false,
|
||||||
store = false,
|
filter = false,
|
||||||
relay = true)
|
store = false,
|
||||||
|
relay = true
|
||||||
|
)
|
||||||
|
|
||||||
nodeTcpPort1 = Port(9010)
|
nodeTcpPort1 = Port(9010)
|
||||||
nodeUdpPort1 = Port(9012)
|
nodeUdpPort1 = Port(9012)
|
||||||
|
|
|
@ -1,14 +1,113 @@
|
||||||
{.used.}
|
{.used.}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[options, sequtils],
|
std/options,
|
||||||
stew/byteutils,
|
stew/[results, byteutils],
|
||||||
testutils/unittests
|
testutils/unittests
|
||||||
import
|
import
|
||||||
../../waku/v2/protocol/waku_enr,
|
../../waku/v2/protocol/waku_enr,
|
||||||
./testlib/waku2
|
./testlib/waku2
|
||||||
|
|
||||||
suite "Waku ENR":
|
|
||||||
|
suite "Waku ENR - Capabilities bitfield":
|
||||||
|
test "check capabilities support":
|
||||||
|
## Given
|
||||||
|
let bitfield: CapabilitiesBitfield = 0b0000_1101u8 # Lightpush, Filter, Relay
|
||||||
|
|
||||||
|
## Then
|
||||||
|
check:
|
||||||
|
bitfield.supportsCapability(Capabilities.Relay)
|
||||||
|
not bitfield.supportsCapability(Capabilities.Store)
|
||||||
|
bitfield.supportsCapability(Capabilities.Filter)
|
||||||
|
bitfield.supportsCapability(Capabilities.Lightpush)
|
||||||
|
|
||||||
|
test "bitfield to capabilities list":
|
||||||
|
## Given
|
||||||
|
let bitfield = CapabilitiesBitfield.init(
|
||||||
|
relay = true,
|
||||||
|
store = false,
|
||||||
|
lightpush = true,
|
||||||
|
filter = true
|
||||||
|
)
|
||||||
|
|
||||||
|
## When
|
||||||
|
let caps = bitfield.toCapabilities()
|
||||||
|
|
||||||
|
## Then
|
||||||
|
check:
|
||||||
|
caps == @[Capabilities.Relay, Capabilities.Filter, Capabilities.Lightpush]
|
||||||
|
|
||||||
|
test "encode and extract capabilities from record":
|
||||||
|
## Given
|
||||||
|
let enrkey = generatesecp256k1key()
|
||||||
|
let caps = CapabilitiesBitfield.init(Capabilities.Relay, Capabilities.Store)
|
||||||
|
|
||||||
|
let record = Record.init(1, enrkey, wakuFlags=some(caps))
|
||||||
|
|
||||||
|
## When
|
||||||
|
let bitfieldRes = record.getCapabilitiesField()
|
||||||
|
|
||||||
|
## Then
|
||||||
|
check bitfieldRes.isOk()
|
||||||
|
|
||||||
|
let bitfield = bitfieldRes.tryGet()
|
||||||
|
check:
|
||||||
|
bitfield.toCapabilities() == @[Capabilities.Relay, Capabilities.Store]
|
||||||
|
|
||||||
|
test "cannot extract capabilities from record":
|
||||||
|
## Given
|
||||||
|
let enrkey = generatesecp256k1key()
|
||||||
|
let record = Record.init(1, enrkey, wakuFlags=none(CapabilitiesBitfield))
|
||||||
|
|
||||||
|
## When
|
||||||
|
let bitfieldRes = record.getCapabilitiesField()
|
||||||
|
|
||||||
|
## Then
|
||||||
|
check bitfieldRes.isErr()
|
||||||
|
|
||||||
|
let err = bitfieldRes.tryError()
|
||||||
|
check:
|
||||||
|
err == "Key not found in ENR"
|
||||||
|
|
||||||
|
test "check capabilities on a waku node record":
|
||||||
|
## Given
|
||||||
|
let wakuRecord = "-Hy4QC73_E3B_FkZhsOakaD4pHe-U--UoGASdG9N0F3SFFUDY_jdQbud8" &
|
||||||
|
"EXVyrlOZ5pZ7VYFBDPMRCENwy87Lh74dFIBgmlkgnY0iXNlY3AyNTZrMaECvNt1jIWbWGp" &
|
||||||
|
"AWWdlLGYm1E1OjlkQk3ONoxDC5sfw8oOFd2FrdTID"
|
||||||
|
|
||||||
|
## When
|
||||||
|
var record: Record
|
||||||
|
require waku_enr.fromBase64(record, wakuRecord)
|
||||||
|
|
||||||
|
## Then
|
||||||
|
check:
|
||||||
|
record.supportsCapability(Relay) == true
|
||||||
|
record.supportsCapability(Store) == true
|
||||||
|
record.supportsCapability(Filter) == false
|
||||||
|
record.supportsCapability(Lightpush) == false
|
||||||
|
record.getCapabilities() == @[Capabilities.Relay, Capabilities.Store]
|
||||||
|
|
||||||
|
test "check capabilities on a non-waku node record":
|
||||||
|
## Given
|
||||||
|
# non waku enr, i.e. Ethereum one
|
||||||
|
let nonWakuEnr = "enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2G" &
|
||||||
|
"xb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNl" &
|
||||||
|
"Y3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA"
|
||||||
|
|
||||||
|
## When
|
||||||
|
var nonWakuEnrRecord: Record
|
||||||
|
require waku_enr.fromURI(nonWakuEnrRecord, nonWakuEnr)
|
||||||
|
|
||||||
|
## Then
|
||||||
|
check:
|
||||||
|
nonWakuEnrRecord.getCapabilities() == []
|
||||||
|
nonWakuEnrRecord.supportsCapability(Relay) == false
|
||||||
|
nonWakuEnrRecord.supportsCapability(Store) == false
|
||||||
|
nonWakuEnrRecord.supportsCapability(Filter) == false
|
||||||
|
nonWakuEnrRecord.supportsCapability(Lightpush) == false
|
||||||
|
|
||||||
|
|
||||||
|
suite "Waku ENR - Multiaddresses":
|
||||||
|
|
||||||
test "Parse multiaddr field":
|
test "Parse multiaddr field":
|
||||||
let
|
let
|
||||||
|
@ -45,14 +144,13 @@ suite "Waku ENR":
|
||||||
enrIp = ValidIpAddress.init("127.0.0.1")
|
enrIp = ValidIpAddress.init("127.0.0.1")
|
||||||
enrTcpPort, enrUdpPort = Port(61101)
|
enrTcpPort, enrUdpPort = Port(61101)
|
||||||
enrKey = generateSecp256k1Key()
|
enrKey = generateSecp256k1Key()
|
||||||
wakuFlags = initWakuFlags(false, true, false, true)
|
|
||||||
multiaddrs = @[MultiAddress.init("/ip4/127.0.0.1/tcp/442/ws")[],
|
multiaddrs = @[MultiAddress.init("/ip4/127.0.0.1/tcp/442/ws")[],
|
||||||
MultiAddress.init("/ip4/127.0.0.1/tcp/443/wss")[]]
|
MultiAddress.init("/ip4/127.0.0.1/tcp/443/wss")[]]
|
||||||
|
|
||||||
let
|
let
|
||||||
record = enr.Record.init(enrKey, some(enrIp),
|
record = enr.Record.init(1, enrKey, some(enrIp),
|
||||||
some(enrTcpPort), some(enrUdpPort),
|
some(enrTcpPort), some(enrUdpPort),
|
||||||
some(wakuFlags),
|
none(CapabilitiesBitfield),
|
||||||
multiaddrs)
|
multiaddrs)
|
||||||
typedRecord = record.toTypedRecord.get()
|
typedRecord = record.toTypedRecord.get()
|
||||||
|
|
||||||
|
@ -64,11 +162,8 @@ suite "Waku ENR":
|
||||||
Port(typedRecord.udp.get()) == enrUdpPort
|
Port(typedRecord.udp.get()) == enrUdpPort
|
||||||
|
|
||||||
# Check Waku ENR fields
|
# Check Waku ENR fields
|
||||||
let
|
let decodedAddrs = record.get(MultiaddrEnrField, seq[byte]).tryGet().toMultiAddresses()
|
||||||
decodedFlags = record.get(WAKU_ENR_FIELD, seq[byte])[]
|
|
||||||
decodedAddrs = record.get(MULTIADDR_ENR_FIELD, seq[byte])[].toMultiAddresses()
|
|
||||||
check:
|
check:
|
||||||
decodedFlags == @[wakuFlags.byte]
|
|
||||||
decodedAddrs.contains(MultiAddress.init("/ip4/127.0.0.1/tcp/442/ws")[])
|
decodedAddrs.contains(MultiAddress.init("/ip4/127.0.0.1/tcp/442/ws")[])
|
||||||
decodedAddrs.contains(MultiAddress.init("/ip4/127.0.0.1/tcp/443/wss")[])
|
decodedAddrs.contains(MultiAddress.init("/ip4/127.0.0.1/tcp/443/wss")[])
|
||||||
|
|
||||||
|
@ -81,9 +176,9 @@ suite "Waku ENR":
|
||||||
multiaddrs = @[MultiAddress.init("/ip4/127.0.0.1/tcp/443/wss/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr31iDQpSN5Qa882BCjjwgrD")[]]
|
multiaddrs = @[MultiAddress.init("/ip4/127.0.0.1/tcp/443/wss/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr31iDQpSN5Qa882BCjjwgrD")[]]
|
||||||
|
|
||||||
let
|
let
|
||||||
record = enr.Record.init(enrKey, some(enrIp),
|
record = enr.Record.init(1, enrKey, some(enrIp),
|
||||||
some(enrTcpPort), some(enrUdpPort),
|
some(enrTcpPort), some(enrUdpPort),
|
||||||
none(WakuEnrBitfield),
|
none(CapabilitiesBitfield),
|
||||||
multiaddrs)
|
multiaddrs)
|
||||||
|
|
||||||
# Check Waku ENR fields
|
# Check Waku ENR fields
|
||||||
|
@ -126,92 +221,3 @@ suite "Waku ENR":
|
||||||
for knownMultiaddr in knownMultiaddrs:
|
for knownMultiaddr in knownMultiaddrs:
|
||||||
check decodedAddrs.contains(knownMultiaddr)
|
check decodedAddrs.contains(knownMultiaddr)
|
||||||
|
|
||||||
test "Supports specific capabilities encoded in the ENR":
|
|
||||||
let
|
|
||||||
enrIp = ValidIpAddress.init("127.0.0.1")
|
|
||||||
enrTcpPort, enrUdpPort = Port(60000)
|
|
||||||
enrKey = generateSecp256k1Key()
|
|
||||||
multiaddrs = @[MultiAddress.init("/ip4/127.0.0.1/tcp/442/ws")[]]
|
|
||||||
|
|
||||||
# TODO: Refactor enr.Record.init, provide enums as inputs enr.Record.init(capabilites=[Store,Filter])
|
|
||||||
# TODO: safer than a util function and directly using the bits
|
|
||||||
# test all flag combinations 2^4 = 16 (b0000-b1111)
|
|
||||||
records = toSeq(0b0000_0000'u8..0b0000_1111'u8)
|
|
||||||
.mapIt(enr.Record.init(enrKey,
|
|
||||||
some(enrIp),
|
|
||||||
some(enrTcpPort),
|
|
||||||
some(enrUdpPort),
|
|
||||||
some(uint8(it)),
|
|
||||||
multiaddrs))
|
|
||||||
|
|
||||||
# same order: lightpush | filter| store | relay
|
|
||||||
expectedCapabilities = @[[false, false, false, false],
|
|
||||||
[false, false, false, true],
|
|
||||||
[false, false, true, false],
|
|
||||||
[false, false, true, true],
|
|
||||||
[false, true, false, false],
|
|
||||||
[false, true, false, true],
|
|
||||||
[false, true, true, false],
|
|
||||||
[false, true, true, true],
|
|
||||||
[true, false, false, false],
|
|
||||||
[true, false, false, true],
|
|
||||||
[true, false, true, false],
|
|
||||||
[true, false, true, true],
|
|
||||||
[true, true, false, false],
|
|
||||||
[true, true, false, true],
|
|
||||||
[true, true, true, false],
|
|
||||||
[true, true, true, true]]
|
|
||||||
|
|
||||||
for i, record in records:
|
|
||||||
for j, capability in @[Lightpush, Filter, Store, Relay]:
|
|
||||||
check expectedCapabilities[i][j] == record.supportsCapability(capability)
|
|
||||||
|
|
||||||
test "Get all supported capabilities encoded in the ENR":
|
|
||||||
let
|
|
||||||
enrIp = ValidIpAddress.init("127.0.0.1")
|
|
||||||
enrTcpPort, enrUdpPort = Port(60000)
|
|
||||||
enrKey = generateSecp256k1Key()
|
|
||||||
multiaddrs = @[MultiAddress.init("/ip4/127.0.0.1/tcp/442/ws")[]]
|
|
||||||
|
|
||||||
records = @[0b0000_0000'u8,
|
|
||||||
0b0000_1111'u8,
|
|
||||||
0b0000_1001'u8,
|
|
||||||
0b0000_1110'u8,
|
|
||||||
0b0000_1000'u8,]
|
|
||||||
.mapIt(enr.Record.init(enrKey,
|
|
||||||
some(enrIp),
|
|
||||||
some(enrTcpPort),
|
|
||||||
some(enrUdpPort),
|
|
||||||
some(uint8(it)),
|
|
||||||
multiaddrs))
|
|
||||||
|
|
||||||
# expected capabilities, ordered LSB to MSB
|
|
||||||
expectedCapabilities: seq[seq[Capabilities]] = @[
|
|
||||||
#[0b0000_0000]# @[],
|
|
||||||
#[0b0000_1111]# @[Relay, Store, Filter, Lightpush],
|
|
||||||
#[0b0000_1001]# @[Relay, Lightpush],
|
|
||||||
#[0b0000_1110]# @[Store, Filter, Lightpush],
|
|
||||||
#[0b0000_1000]# @[Lightpush]]
|
|
||||||
|
|
||||||
for i, actualExpetedTuple in zip(records, expectedCapabilities):
|
|
||||||
check actualExpetedTuple[0].getCapabilities() == actualExpetedTuple[1]
|
|
||||||
|
|
||||||
test "Get supported capabilities of a non waku node":
|
|
||||||
|
|
||||||
# non waku enr, i.e. Ethereum one
|
|
||||||
let nonWakuEnr = "enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2G"&
|
|
||||||
"xb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNl"&
|
|
||||||
"Y3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA"
|
|
||||||
|
|
||||||
var nonWakuEnrRecord: Record
|
|
||||||
|
|
||||||
check:
|
|
||||||
nonWakuEnrRecord.fromURI(nonWakuEnr)
|
|
||||||
|
|
||||||
# check that it doesn't support any capability and it doesnt't break
|
|
||||||
check:
|
|
||||||
nonWakuEnrRecord.getCapabilities() == []
|
|
||||||
nonWakuEnrRecord.supportsCapability(Relay) == false
|
|
||||||
nonWakuEnrRecord.supportsCapability(Store) == false
|
|
||||||
nonWakuEnrRecord.supportsCapability(Filter) == false
|
|
||||||
nonWakuEnrRecord.supportsCapability(Lightpush) == false
|
|
||||||
|
|
|
@ -89,10 +89,12 @@ procSuite "Waku Peer Exchange":
|
||||||
node3 = WakuNode.new(nodeKey3, bindIp, nodeTcpPort3)
|
node3 = WakuNode.new(nodeKey3, bindIp, nodeTcpPort3)
|
||||||
|
|
||||||
# todo: px flag
|
# todo: px flag
|
||||||
flags = initWakuFlags(lightpush = false,
|
flags = CapabilitiesBitfield.init(
|
||||||
filter = false,
|
lightpush = false,
|
||||||
store = false,
|
filter = false,
|
||||||
relay = true)
|
store = false,
|
||||||
|
relay = true
|
||||||
|
)
|
||||||
|
|
||||||
# Mount discv5
|
# Mount discv5
|
||||||
node1.wakuDiscv5 = WakuDiscoveryV5.new(
|
node1.wakuDiscv5 = WakuDiscoveryV5.new(
|
||||||
|
|
|
@ -224,7 +224,7 @@ proc initAndStartNode(conf: NetworkMonitorConf): Result[WakuNode, string] =
|
||||||
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
||||||
nodeTcpPort = Port(60000)
|
nodeTcpPort = Port(60000)
|
||||||
nodeUdpPort = Port(9000)
|
nodeUdpPort = Port(9000)
|
||||||
flags = initWakuFlags(lightpush = false, filter = false, store = false, relay = true)
|
flags = CapabilitiesBitfield.init(lightpush = false, filter = false, store = false, relay = true)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
let
|
let
|
||||||
|
|
|
@ -135,7 +135,7 @@ type NetConfig* = object
|
||||||
enrIp*: Option[ValidIpAddress]
|
enrIp*: Option[ValidIpAddress]
|
||||||
enrPort*: Option[Port]
|
enrPort*: Option[Port]
|
||||||
discv5UdpPort*: Option[Port]
|
discv5UdpPort*: Option[Port]
|
||||||
wakuFlags*: Option[WakuEnrBitfield]
|
wakuFlags*: Option[CapabilitiesBitfield]
|
||||||
bindIp*: ValidIpAddress
|
bindIp*: ValidIpAddress
|
||||||
bindPort*: Port
|
bindPort*: Port
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ proc init*(
|
||||||
wssEnabled: bool = false,
|
wssEnabled: bool = false,
|
||||||
dns4DomainName = none(string),
|
dns4DomainName = none(string),
|
||||||
discv5UdpPort = none(Port),
|
discv5UdpPort = none(Port),
|
||||||
wakuFlags = none(WakuEnrBitfield)
|
wakuFlags = none(CapabilitiesBitfield)
|
||||||
): T {.raises: [LPError]} =
|
): T {.raises: [LPError]} =
|
||||||
## Initialize addresses
|
## Initialize addresses
|
||||||
let
|
let
|
||||||
|
@ -230,7 +230,7 @@ proc getEnr*(netConfig: NetConfig,
|
||||||
if wakuDiscV5.isSome():
|
if wakuDiscV5.isSome():
|
||||||
return wakuDiscV5.get().protocol.getRecord()
|
return wakuDiscV5.get().protocol.getRecord()
|
||||||
|
|
||||||
return enr.Record.init(nodekey,
|
return enr.Record.init(1, nodekey,
|
||||||
netConfig.enrIp,
|
netConfig.enrIp,
|
||||||
netConfig.enrPort,
|
netConfig.enrPort,
|
||||||
netConfig.discv5UdpPort,
|
netConfig.discv5UdpPort,
|
||||||
|
@ -275,7 +275,7 @@ proc new*(T: type WakuNode,
|
||||||
wssEnabled: bool = false,
|
wssEnabled: bool = false,
|
||||||
secureKey: string = "",
|
secureKey: string = "",
|
||||||
secureCert: string = "",
|
secureCert: string = "",
|
||||||
wakuFlags = none(WakuEnrBitfield),
|
wakuFlags = none(CapabilitiesBitfield),
|
||||||
nameResolver: NameResolver = nil,
|
nameResolver: NameResolver = nil,
|
||||||
sendSignedPeerRecord = false,
|
sendSignedPeerRecord = false,
|
||||||
dns4DomainName = none(string),
|
dns4DomainName = none(string),
|
||||||
|
|
|
@ -72,10 +72,10 @@ proc addBootstrapNode*(bootstrapAddr: string,
|
||||||
bootstrapAddr, reason = enrRes.error
|
bootstrapAddr, reason = enrRes.error
|
||||||
|
|
||||||
proc isWakuNode(node: Node): bool =
|
proc isWakuNode(node: Node): bool =
|
||||||
let wakuField = node.record.tryGet(WAKU_ENR_FIELD, uint8)
|
let wakuField = node.record.tryGet(CapabilitiesEnrField, uint8)
|
||||||
|
|
||||||
if wakuField.isSome():
|
if wakuField.isSome():
|
||||||
return wakuField.get().WakuEnrBitfield != 0x00 # True if any flag set to true
|
return wakuField.get() != 0x00 # True if any flag set to true
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
@ -116,14 +116,14 @@ proc new*(T: type WakuDiscoveryV5,
|
||||||
bootstrapEnrs = newSeq[enr.Record](),
|
bootstrapEnrs = newSeq[enr.Record](),
|
||||||
enrAutoUpdate = false,
|
enrAutoUpdate = false,
|
||||||
privateKey: keys.PrivateKey,
|
privateKey: keys.PrivateKey,
|
||||||
flags: WakuEnrBitfield,
|
flags: CapabilitiesBitfield,
|
||||||
multiaddrs = newSeq[MultiAddress](),
|
multiaddrs = newSeq[MultiAddress](),
|
||||||
rng: ref HmacDrbgContext,
|
rng: ref HmacDrbgContext,
|
||||||
discv5Config: protocol.DiscoveryConfig = protocol.defaultDiscoveryConfig): T =
|
discv5Config: protocol.DiscoveryConfig = protocol.defaultDiscoveryConfig): T =
|
||||||
## TODO: consider loading from a configurable bootstrap file
|
## TODO: consider loading from a configurable bootstrap file
|
||||||
|
|
||||||
## We always add the waku field as specified
|
## We always add the waku field as specified
|
||||||
var enrInitFields = @[(WAKU_ENR_FIELD, @[flags.byte])]
|
var enrInitFields = @[(CapabilitiesEnrField, @[flags.byte])]
|
||||||
|
|
||||||
## Add multiaddresses to ENR
|
## Add multiaddresses to ENR
|
||||||
if multiaddrs.len > 0:
|
if multiaddrs.len > 0:
|
||||||
|
@ -151,7 +151,7 @@ proc new*(T: type WakuDiscoveryV5,
|
||||||
bootstrapNodes: seq[string],
|
bootstrapNodes: seq[string],
|
||||||
enrAutoUpdate = false,
|
enrAutoUpdate = false,
|
||||||
privateKey: keys.PrivateKey,
|
privateKey: keys.PrivateKey,
|
||||||
flags: WakuEnrBitfield,
|
flags: CapabilitiesBitfield,
|
||||||
multiaddrs = newSeq[MultiAddress](),
|
multiaddrs = newSeq[MultiAddress](),
|
||||||
rng: ref HmacDrbgContext,
|
rng: ref HmacDrbgContext,
|
||||||
discv5Config: protocol.DiscoveryConfig = protocol.defaultDiscoveryConfig): T =
|
discv5Config: protocol.DiscoveryConfig = protocol.defaultDiscoveryConfig): T =
|
||||||
|
|
|
@ -19,14 +19,17 @@ import
|
||||||
export enr, crypto, multiaddress, net
|
export enr, crypto, multiaddress, net
|
||||||
|
|
||||||
const
|
const
|
||||||
MULTIADDR_ENR_FIELD* = "multiaddrs"
|
MultiaddrEnrField* = "multiaddrs"
|
||||||
WAKU_ENR_FIELD* = "waku2"
|
CapabilitiesEnrField* = "waku2"
|
||||||
|
|
||||||
|
|
||||||
|
## Capabilities
|
||||||
|
|
||||||
type
|
type
|
||||||
## 8-bit flag field to indicate Waku capabilities.
|
## 8-bit flag field to indicate Waku capabilities.
|
||||||
## Only the 4 LSBs are currently defined according
|
## Only the 4 LSBs are currently defined according
|
||||||
## to RFC31 (https://rfc.vac.dev/spec/31/).
|
## to RFC31 (https://rfc.vac.dev/spec/31/).
|
||||||
WakuEnrBitfield* = uint8
|
CapabilitiesBitfield* = distinct uint8
|
||||||
|
|
||||||
## See: https://rfc.vac.dev/spec/31/#waku2-enr-key
|
## See: https://rfc.vac.dev/spec/31/#waku2-enr-key
|
||||||
## each enum numbers maps to a bit (where 0 is the LSB)
|
## each enum numbers maps to a bit (where 0 is the LSB)
|
||||||
|
@ -34,7 +37,59 @@ type
|
||||||
Relay = 0,
|
Relay = 0,
|
||||||
Store = 1,
|
Store = 1,
|
||||||
Filter = 2,
|
Filter = 2,
|
||||||
Lightpush = 3,
|
Lightpush = 3
|
||||||
|
|
||||||
|
|
||||||
|
func init*(T: type CapabilitiesBitfield, lightpush, filter, store, relay: bool): T =
|
||||||
|
## Creates an waku2 ENR flag bit field according to RFC 31 (https://rfc.vac.dev/spec/31/)
|
||||||
|
var bitfield: uint8
|
||||||
|
if relay: bitfield.setBit(0)
|
||||||
|
if store: bitfield.setBit(1)
|
||||||
|
if filter: bitfield.setBit(2)
|
||||||
|
if lightpush: bitfield.setBit(3)
|
||||||
|
CapabilitiesBitfield(bitfield)
|
||||||
|
|
||||||
|
func init*(T: type CapabilitiesBitfield, caps: varargs[Capabilities]): T =
|
||||||
|
## Creates an waku2 ENR flag bit field according to RFC 31 (https://rfc.vac.dev/spec/31/)
|
||||||
|
var bitfield: uint8
|
||||||
|
for cap in caps:
|
||||||
|
bitfield.setBit(ord(cap))
|
||||||
|
CapabilitiesBitfield(bitfield)
|
||||||
|
|
||||||
|
converter toCapabilitiesBitfield*(field: uint8): CapabilitiesBitfield =
|
||||||
|
CapabilitiesBitfield(field)
|
||||||
|
|
||||||
|
proc supportsCapability*(bitfield: CapabilitiesBitfield, cap: Capabilities): bool =
|
||||||
|
testBit(bitfield.uint8, ord(cap))
|
||||||
|
|
||||||
|
func toCapabilities*(bitfield: CapabilitiesBitfield): seq[Capabilities] =
|
||||||
|
toSeq(Capabilities.low..Capabilities.high).filterIt(supportsCapability(bitfield, it))
|
||||||
|
|
||||||
|
|
||||||
|
func toFieldPair*(caps: CapabilitiesBitfield): FieldPair =
|
||||||
|
toFieldPair(CapabilitiesEnrField, @[caps.uint8])
|
||||||
|
|
||||||
|
proc getCapabilitiesField*(r: Record): EnrResult[CapabilitiesBitfield] =
|
||||||
|
let field = ?r.get(CapabilitiesEnrField, seq[uint8])
|
||||||
|
ok(CapabilitiesBitfield(field[0]))
|
||||||
|
|
||||||
|
|
||||||
|
proc supportsCapability*(r: Record, cap: Capabilities): bool =
|
||||||
|
let bitfield = getCapabilitiesField(r)
|
||||||
|
if bitfield.isErr():
|
||||||
|
return false
|
||||||
|
|
||||||
|
bitfield.value.supportsCapability(cap)
|
||||||
|
|
||||||
|
proc getCapabilities*(r: Record): seq[Capabilities] =
|
||||||
|
let bitfield = getCapabilitiesField(r)
|
||||||
|
if bitfield.isErr():
|
||||||
|
return @[]
|
||||||
|
|
||||||
|
bitfield.value.toCapabilities()
|
||||||
|
|
||||||
|
|
||||||
|
## Multiaddress
|
||||||
|
|
||||||
func getRawField*(multiaddrs: seq[MultiAddress]): seq[byte] =
|
func getRawField*(multiaddrs: seq[MultiAddress]): seq[byte] =
|
||||||
var fieldRaw: seq[byte]
|
var fieldRaw: seq[byte]
|
||||||
|
@ -93,28 +148,6 @@ func readBytes(rawBytes: seq[byte], numBytes: int, pos: var int = 0): Result[seq
|
||||||
|
|
||||||
return ok(slicedSeq)
|
return ok(slicedSeq)
|
||||||
|
|
||||||
################
|
|
||||||
# Public utils #
|
|
||||||
################
|
|
||||||
|
|
||||||
func initWakuFlags*(lightpush, filter, store, relay: bool): WakuEnrBitfield =
|
|
||||||
## Creates an waku2 ENR flag bit field according to RFC 31 (https://rfc.vac.dev/spec/31/)
|
|
||||||
var v = 0b0000_0000'u8
|
|
||||||
if lightpush: v.setBit(3)
|
|
||||||
if filter: v.setBit(2)
|
|
||||||
if store: v.setBit(1)
|
|
||||||
if relay: v.setBit(0)
|
|
||||||
|
|
||||||
# TODO: With the changes in this PR, this can be refactored? Using the enum?
|
|
||||||
# Perhaps refactor to:
|
|
||||||
# WaKuEnr.enr.Record.init(..., capabilities=[Store, Lightpush])
|
|
||||||
# WaKuEnr.enr.Record.init(..., capabilities=[Store, Lightpush, Relay, Filter])
|
|
||||||
|
|
||||||
# Safer also since we dont inject WakuEnrBitfield, and we let this package
|
|
||||||
# handle the bits according to the capabilities
|
|
||||||
|
|
||||||
return v.WakuEnrBitfield
|
|
||||||
|
|
||||||
func toMultiAddresses*(multiaddrsField: seq[byte]): seq[MultiAddress] =
|
func toMultiAddresses*(multiaddrsField: seq[byte]): seq[MultiAddress] =
|
||||||
## Parses a `multiaddrs` ENR field according to
|
## Parses a `multiaddrs` ENR field according to
|
||||||
## https://rfc.vac.dev/spec/31/
|
## https://rfc.vac.dev/spec/31/
|
||||||
|
@ -147,11 +180,16 @@ func toMultiAddresses*(multiaddrsField: seq[byte]): seq[MultiAddress] =
|
||||||
|
|
||||||
return multiaddrs
|
return multiaddrs
|
||||||
|
|
||||||
|
|
||||||
|
## ENR
|
||||||
|
|
||||||
func init*(T: type enr.Record,
|
func init*(T: type enr.Record,
|
||||||
|
seqNum: uint64,
|
||||||
privateKey: crypto.PrivateKey,
|
privateKey: crypto.PrivateKey,
|
||||||
enrIp: Option[ValidIpAddress],
|
enrIp = none(ValidIpAddress),
|
||||||
enrTcpPort, enrUdpPort: Option[Port],
|
enrTcpPort = none(Port),
|
||||||
wakuFlags = none(WakuEnrBitfield),
|
enrUdpPort = none(Port),
|
||||||
|
wakuFlags = none(CapabilitiesBitfield),
|
||||||
multiaddrs: seq[MultiAddress] = @[]): T =
|
multiaddrs: seq[MultiAddress] = @[]): T =
|
||||||
|
|
||||||
assert privateKey.scheme == PKScheme.Secp256k1
|
assert privateKey.scheme == PKScheme.Secp256k1
|
||||||
|
@ -160,27 +198,22 @@ func init*(T: type enr.Record,
|
||||||
var wakuEnrFields: seq[FieldPair]
|
var wakuEnrFields: seq[FieldPair]
|
||||||
|
|
||||||
# `waku2` field
|
# `waku2` field
|
||||||
if wakuFlags.isSome:
|
if wakuFlags.isSome():
|
||||||
wakuEnrFields.add(toFieldPair(WAKU_ENR_FIELD, @[wakuFlags.get().byte]))
|
wakuEnrFields.add(toFieldPair(wakuFlags.get()))
|
||||||
|
|
||||||
# `multiaddrs` field
|
# `multiaddrs` field
|
||||||
if multiaddrs.len > 0:
|
if multiaddrs.len > 0:
|
||||||
wakuEnrFields.add(multiaddrs.stripPeerIds().toFieldPair)
|
wakuEnrFields.add(multiaddrs.stripPeerIds().toFieldPair())
|
||||||
|
|
||||||
let
|
let
|
||||||
rawPk = privateKey.getRawBytes().expect("Private key is valid")
|
rawPk = privateKey.getRawBytes().expect("Private key is valid")
|
||||||
pk = keys.PrivateKey.fromRaw(rawPk).expect("Raw private key is of valid length")
|
pk = keys.PrivateKey.fromRaw(rawPk).expect("Raw private key is of valid length")
|
||||||
enr = enr.Record.init(1, pk,
|
|
||||||
enrIp, enrTcpPort, enrUdpPort,
|
|
||||||
wakuEnrFields).expect("Record within size limits")
|
|
||||||
|
|
||||||
return enr
|
enr.Record.init(
|
||||||
|
seqNum=seqNum,
|
||||||
proc supportsCapability*(r: Record, capability: Capabilities): bool =
|
pk=pk,
|
||||||
let enrCapabilities = r.get(WAKU_ENR_FIELD, seq[byte])
|
ip=enrIp,
|
||||||
if enrCapabilities.isOk():
|
tcpPort=enrTcpPort,
|
||||||
return testBit(enrCapabilities.get()[0], capability.ord)
|
udpPort=enrUdpPort,
|
||||||
return false
|
extraFields=wakuEnrFields
|
||||||
|
).expect("Record within size limits")
|
||||||
proc getCapabilities*(r: Record): seq[Capabilities] =
|
|
||||||
return toSeq(Capabilities.low..Capabilities.high).filterIt(r.supportsCapability(it))
|
|
||||||
|
|
Loading…
Reference in New Issue