nim-libp2p-experimental/libp2p/routing_record.nim

96 lines
2.4 KiB
Nim

# Nim-Libp2p
# Copyright (c) 2023 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
# at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.
## This module implements Routing Records.
{.push raises: [].}
import std/[sequtils, times]
import pkg/stew/results
import
multiaddress,
multicodec,
peerid,
protobuf/minprotobuf,
signed_envelope
export peerid, multiaddress, signed_envelope
type
AddressInfo* = object
address*: MultiAddress
PeerRecord* = object
peerId*: PeerId
seqNo*: uint64
addresses*: seq[AddressInfo]
proc decode*(
T: typedesc[PeerRecord],
buffer: seq[byte]): Result[PeerRecord, ProtoError] =
let pb = initProtoBuffer(buffer)
var record = PeerRecord()
? pb.getRequiredField(1, record.peerId)
? pb.getRequiredField(2, record.seqNo)
var addressInfos: seq[seq[byte]]
if ? pb.getRepeatedField(3, addressInfos):
for address in addressInfos:
var addressInfo = AddressInfo()
let subProto = initProtoBuffer(address)
let f = subProto.getField(1, addressInfo.address)
if f.get(false):
record.addresses &= addressInfo
if record.addresses.len == 0:
return err(ProtoError.RequiredFieldMissing)
ok(record)
proc encode*(record: PeerRecord): seq[byte] =
var pb = initProtoBuffer()
pb.write(1, record.peerId)
pb.write(2, record.seqNo)
for address in record.addresses:
var addrPb = initProtoBuffer()
addrPb.write(1, address.address)
pb.write(3, addrPb)
pb.finish()
pb.buffer
proc init*(T: typedesc[PeerRecord],
peerId: PeerId,
addresses: seq[MultiAddress],
seqNo = getTime().toUnix().uint64 # follows the recommended implementation, using unix epoch as seq no.
): T =
PeerRecord(
peerId: peerId,
seqNo: seqNo,
addresses: addresses.mapIt(AddressInfo(address: it))
)
## Functions related to signed peer records
type SignedPeerRecord* = SignedPayload[PeerRecord]
proc payloadDomain*(T: typedesc[PeerRecord]): string = $multiCodec("libp2p-peer-record")
proc payloadType*(T: typedesc[PeerRecord]): seq[byte] = @[(byte) 0x03, (byte) 0x01]
proc checkValid*(spr: SignedPeerRecord): Result[void, EnvelopeError] =
if not spr.data.peerId.match(spr.envelope.publicKey):
err(EnvelopeInvalidSignature)
else:
ok()