Allow application-supplied ENR fields in discv5

This commit is contained in:
Zahary Karadjov 2020-04-15 05:32:52 +03:00
parent 8f3bf36054
commit 6513cd9eff
No known key found for this signature in database
GPG Key ID: C8936F8A3073D609
3 changed files with 22 additions and 13 deletions

View File

@ -13,11 +13,13 @@ const
minRlpListLen = 4 # for signature, seqId, "id" key, id minRlpListLen = 4 # for signature, seqId, "id" key, id
type type
FieldPair* = (string, Field)
Record* = object Record* = object
seqNum*: uint64 seqNum*: uint64
# signature: seq[byte] # signature: seq[byte]
raw*: seq[byte] # RLP encoded record raw*: seq[byte] # RLP encoded record
pairs: seq[(string, Field)] # sorted list of all key/value pairs pairs: seq[FieldPair] # sorted list of all key/value pairs
EnrUri* = distinct string EnrUri* = distinct string
@ -101,25 +103,31 @@ macro initRecord*(seqNum: uint64, pk: PrivateKey, pairs: untyped{nkTableConstr})
result = quote do: result = quote do:
makeEnrAux(`seqNum`, `pk`, `pairs`) makeEnrAux(`seqNum`, `pk`, `pairs`)
template toFieldPair*(key: string, value: auto): FieldPair =
(key, toField(value))
proc init*(T: type Record, seqNum: uint64, proc init*(T: type Record, seqNum: uint64,
pk: PrivateKey, pk: PrivateKey,
ip: Option[IpAddress], ip: Option[IpAddress],
tcpPort, udpPort: Port): T = tcpPort, udpPort: Port,
extraFields: openarray[FieldPair] = []): T =
var fields = newSeq[FieldPair]()
if ip.isSome(): if ip.isSome():
let let
ipExt = ip.get() ipExt = ip.get()
isV6 = ipExt.family == IPv6 isV6 = ipExt.family == IPv6
ipField = if isV6: ("ip6", ipExt.address_v6.toField)
else: ("ip", ipExt.address_v4.toField)
tcpField = ((if isV6: "tcp6" else: "tcp"), tcpPort.uint16.toField)
udpField = ((if isV6: "udp6" else: "udp"), udpPort.uint16.toField)
makeEnrAux(seqNum, pk, [ipField, tcpField, udpField]) fields.add(if isV6: ("ip6", ipExt.address_v6.toField)
else: ("ip", ipExt.address_v4.toField))
fields.add(((if isV6: "tcp6" else: "tcp"), tcpPort.uint16.toField))
fields.add(((if isV6: "udp6" else: "udp"), udpPort.uint16.toField))
else: else:
let fields.add(("tcp", tcpPort.uint16.toField))
tcpField = ("tcp", tcpPort.uint16.toField) fields.add(("udp", udpPort.uint16.toField))
udpField = ("udp", udpPort.uint16.toField)
makeEnrAux(seqNum, pk, [tcpField, udpField]) fields.add extraFields
makeEnrAux(seqNum, pk, fields)
proc getField(r: Record, name: string, field: var Field): bool = proc getField(r: Record, name: string, field: var Field): bool =
# It might be more correct to do binary search, # It might be more correct to do binary search,

View File

@ -476,12 +476,13 @@ proc lookupLoop(d: Protocol) {.async.} =
proc newProtocol*(privKey: PrivateKey, db: Database, proc newProtocol*(privKey: PrivateKey, db: Database,
externalIp: Option[IpAddress], tcpPort, udpPort: Port, externalIp: Option[IpAddress], tcpPort, udpPort: Port,
localEnrFields: openarray[FieldPair],
bootstrapRecords: openarray[Record] = []): Protocol = bootstrapRecords: openarray[Record] = []): Protocol =
let let
a = Address(ip: externalIp.get(IPv4_any()), a = Address(ip: externalIp.get(IPv4_any()),
tcpPort: tcpPort, udpPort: udpPort) tcpPort: tcpPort, udpPort: udpPort)
enode = ENode(pubkey: privKey.toPublicKey().tryGet(), address: a) enode = ENode(pubkey: privKey.toPublicKey().tryGet(), address: a)
enrRec = enr.Record.init(1, privKey, externalIp, tcpPort, udpPort) enrRec = enr.Record.init(1, privKey, externalIp, tcpPort, udpPort, localEnrFields)
node = newNode(enode, enrRec) node = newNode(enode, enrRec)
result = Protocol( result = Protocol(

View File

@ -35,7 +35,7 @@ suite "ENR":
let let
keys = KeyPair.random()[] keys = KeyPair.random()[]
ip = parseIpAddress("10.20.30.40") ip = parseIpAddress("10.20.30.40")
enr = Record.init(100, keys.seckey, some(ip), Port(9000), Port(9000)) enr = Record.init(100, keys.seckey, some(ip), Port(9000), Port(9000), @[])
typedEnr = get enr.toTypedRecord() typedEnr = get enr.toTypedRecord()
check: check: