-
Notifications
You must be signed in to change notification settings - Fork 55
/
routing_record.nim
90 lines (70 loc) · 2.39 KB
/
routing_record.nim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# 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()