Skip to content

Commit 9d89b2c

Browse files
committed
chore: replace minprotobuf with nim-protobuf-serialization
* convert all codecs except sds_persistency to proto2 * add common/protobuf_ext.nim: generic array[N,byte] protobuf extension * encode PeerId and MultiAddress via libp2p extensions * encode PublicKey as seq[byte] * change encode() to return seq[byte] and update all .encode().buffer call sites * reduce common/protobuf.nim to ProtobufError/ProtobufResult * add wire-format tests for message, filter v2, lightpush v3/legacy, rln proof * adapt chat2, chat2mix, chat2bridge, wakustealthcommitments * delete tests/common/test_protobuf_validation * add protobuf_serialization to logos_delivery.nimble
1 parent ce918b0 commit 9d89b2c

70 files changed

Lines changed: 1197 additions & 1149 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/chat2/chat2.nim

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,12 @@ import
2727
peerinfo,
2828
# manage the information of a peer, such as peer ID and public / private key
2929
peerid, # Implement how peers interact
30-
protobuf/minprotobuf, # message serialisation/deserialisation from and to protobufs
3130
nameresolving/dnsresolver,
3231
] # define DNS resolution
32+
import protobuf_serialization, protobuf_serialization/pkg/results
3333
import
3434
logos_delivery/waku/[
35+
common/protobuf,
3536
waku_core,
3637
waku_lightpush_legacy/common,
3738
waku_lightpush_legacy/rpc,
@@ -87,27 +88,36 @@ type
8788
nick*: string
8889
payload*: seq[byte]
8990

90-
proc init*(T: type Chat2Message, buffer: seq[byte]): ProtoResult[T] =
91-
var msg = Chat2Message()
92-
let pb = initProtoBuffer(buffer)
91+
type Chat2MessagePB {.proto2.} = object
92+
timestamp {.fieldNumber: 1, pint.}: Opt[uint64]
93+
nick {.fieldNumber: 2.}: Opt[string]
94+
payload {.fieldNumber: 3.}: Opt[seq[byte]]
9395

94-
var timestamp: uint64
95-
discard ?pb.getField(1, timestamp)
96-
msg.timestamp = int64(timestamp)
97-
98-
discard ?pb.getField(2, msg.nick)
99-
discard ?pb.getField(3, msg.payload)
100-
101-
ok(msg)
102-
103-
proc encode*(message: Chat2Message): ProtoBuffer =
104-
var serialised = initProtoBuffer()
96+
proc decodeChat2Message(buffer: seq[byte]): ProtobufResult[Chat2Message] =
97+
var pb: Chat2MessagePB
98+
try:
99+
pb = Protobuf.decode(buffer, Chat2MessagePB)
100+
except SerializationError:
101+
return err(protobuf.ProtobufError(kind: ProtobufErrorKind.DecodeFailure))
102+
ok(
103+
Chat2Message(
104+
timestamp: int64(pb.timestamp.get(0'u64)),
105+
nick: pb.nick.get(""),
106+
payload: pb.payload.get(@[]),
107+
)
108+
)
105109

106-
serialised.write(1, uint64(message.timestamp))
107-
serialised.write(2, message.nick)
108-
serialised.write(3, message.payload)
110+
proc init*(T: type Chat2Message, buffer: seq[byte]): ProtobufResult[T] =
111+
decodeChat2Message(buffer)
109112

110-
return serialised
113+
proc encode*(message: Chat2Message): seq[byte] =
114+
Protobuf.encode(
115+
Chat2MessagePB(
116+
timestamp: Opt.some(uint64(message.timestamp)),
117+
nick: Opt.some(message.nick),
118+
payload: Opt.some(message.payload),
119+
)
120+
)
111121

112122
proc toString*(message: Chat2Message): string =
113123
# Get message date and timestamp in local time
@@ -183,7 +193,7 @@ proc publish(c: Chat, line: string) =
183193
trace "lightpush response received", response = response
184194

185195
var message = WakuMessage(
186-
payload: chat2pb.buffer,
196+
payload: chat2pb,
187197
contentTopic: c.contentTopic,
188198
version: 0,
189199
timestamp: getNanosecondTime(time),

apps/chat2bridge/chat2bridge.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ proc toWakuMessage(
8989
payload: msgFields["text"].getStr().toBytes(),
9090
).encode()
9191

92-
WakuMessage(payload: chat2pb.buffer, contentTopic: cmb.contentTopic, version: 0)
92+
WakuMessage(payload: chat2pb, contentTopic: cmb.contentTopic, version: 0)
9393

9494
proc toChat2(cmb: Chat2MatterBridge, jsonNode: JsonNode) {.async.} =
9595
let msg = cmb.toWakuMessage(jsonNode)

apps/chat2mix/chat2mix.nim

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@ import
2727
peerinfo,
2828
# manage the information of a peer, such as peer ID and public / private key
2929
peerid, # Implement how peers interact
30-
protobuf/minprotobuf, # message serialisation/deserialisation from and to protobufs
3130
protocols/kademlia/types,
3231
protocols/service_discovery/types as sd_types,
3332
nameresolving/dnsresolver,
3433
] # define DNS resolution
3534
import libp2p_mix/[curve25519, mix_protocol]
35+
import protobuf_serialization, protobuf_serialization/pkg/results
3636
import
3737
logos_delivery/waku/[
38+
common/protobuf,
3839
waku_core,
3940
waku_core/peers,
4041
waku_lightpush/common,
@@ -108,27 +109,36 @@ proc getPubsubTopic*(
108109
return "" #TODO: fix this.
109110
return $RelayShard(clusterId: conf.clusterId, shardId: shard.shardId)
110111

111-
proc init*(T: type Chat2Message, buffer: seq[byte]): ProtoResult[T] =
112-
var msg = Chat2Message()
113-
let pb = initProtoBuffer(buffer)
112+
type Chat2MessagePB {.proto2.} = object
113+
timestamp {.fieldNumber: 1, pint.}: Opt[uint64]
114+
nick {.fieldNumber: 2.}: Opt[string]
115+
payload {.fieldNumber: 3.}: Opt[seq[byte]]
114116

115-
var timestamp: uint64
116-
discard ?pb.getField(1, timestamp)
117-
msg.timestamp = int64(timestamp)
118-
119-
discard ?pb.getField(2, msg.nick)
120-
discard ?pb.getField(3, msg.payload)
121-
122-
ok(msg)
123-
124-
proc encode*(message: Chat2Message): ProtoBuffer =
125-
var serialised = initProtoBuffer()
117+
proc decodeChat2Message(buffer: seq[byte]): ProtobufResult[Chat2Message] =
118+
var pb: Chat2MessagePB
119+
try:
120+
pb = Protobuf.decode(buffer, Chat2MessagePB)
121+
except SerializationError:
122+
return err(protobuf.ProtobufError(kind: ProtobufErrorKind.DecodeFailure))
123+
ok(
124+
Chat2Message(
125+
timestamp: int64(pb.timestamp.get(0'u64)),
126+
nick: pb.nick.get(""),
127+
payload: pb.payload.get(@[]),
128+
)
129+
)
126130

127-
serialised.write(1, uint64(message.timestamp))
128-
serialised.write(2, message.nick)
129-
serialised.write(3, message.payload)
131+
proc init*(T: type Chat2Message, buffer: seq[byte]): ProtobufResult[T] =
132+
decodeChat2Message(buffer)
130133

131-
return serialised
134+
proc encode*(message: Chat2Message): seq[byte] =
135+
Protobuf.encode(
136+
Chat2MessagePB(
137+
timestamp: Opt.some(uint64(message.timestamp)),
138+
nick: Opt.some(message.nick),
139+
payload: Opt.some(message.payload),
140+
)
141+
)
132142

133143
proc `$`*(message: Chat2Message): string =
134144
# Get message date and timestamp in local time
@@ -203,7 +213,7 @@ proc publish(c: Chat, line: string) {.async.} =
203213
trace "lightpush response received", response = response
204214

205215
var message = WakuMessage(
206-
payload: chat2pb.buffer,
216+
payload: chat2pb,
207217
contentTopic: c.contentTopic,
208218
version: 0,
209219
timestamp: getNanosecondTime(time),

examples/wakustealthcommitments/wire_spec.nim

Lines changed: 46 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import std/times
22
import confutils, chronicles, chronos, results
3+
import protobuf_serialization, protobuf_serialization/pkg/results
34

45
import logos_delivery/waku/[waku_core, common/protobuf]
5-
import libp2p/protobuf/minprotobuf
66

7-
export times, confutils, chronicles, chronos, results, waku_core, protobuf, minprotobuf
7+
export times, confutils, chronicles, chronos, results, waku_core, protobuf
88

99
type SerializedKey* = seq[byte]
1010

@@ -16,57 +16,47 @@ type WakuStealthCommitmentMsg* = object
1616
stealthCommitment*: Opt[SerializedKey]
1717
viewTag*: Opt[uint64]
1818

19-
proc decode*(T: type WakuStealthCommitmentMsg, buffer: seq[byte]): ProtoResult[T] =
19+
type WakuStealthCommitmentMsgPB {.proto2.} = object
20+
request {.fieldNumber: 1, pint.}: Opt[uint64]
21+
spendingPubKey {.fieldNumber: 2.}: Opt[seq[byte]]
22+
viewingPubKey {.fieldNumber: 3.}: Opt[seq[byte]]
23+
stealthCommitment {.fieldNumber: 4.}: Opt[seq[byte]]
24+
ephemeralPubKey {.fieldNumber: 5.}: Opt[seq[byte]]
25+
viewTag {.fieldNumber: 6, pint.}: Opt[uint64]
26+
27+
proc nonEmptyKey(o: Opt[seq[byte]]): Opt[SerializedKey] =
28+
if o.isSome() and o.get().len > 0:
29+
o
30+
else:
31+
Opt.none(SerializedKey)
32+
33+
proc decode*(T: type WakuStealthCommitmentMsg, buffer: seq[byte]): ProtobufResult[T] =
34+
var pb: WakuStealthCommitmentMsgPB
35+
try:
36+
pb = Protobuf.decode(buffer, WakuStealthCommitmentMsgPB)
37+
except SerializationError:
38+
return err(protobuf.ProtobufError(kind: ProtobufErrorKind.DecodeFailure))
39+
2040
var msg = WakuStealthCommitmentMsg()
21-
let pb = initProtoBuffer(buffer)
22-
23-
var request: uint64
24-
discard ?pb.getField(1, request)
25-
msg.request = request == 1
26-
var spendingPubKey = newSeq[byte]()
27-
discard ?pb.getField(2, spendingPubKey)
28-
msg.spendingPubKey =
29-
if spendingPubKey.len > 0:
30-
Opt.some(spendingPubKey)
31-
else:
32-
Opt.none(SerializedKey)
33-
var viewingPubKey = newSeq[byte]()
34-
discard ?pb.getField(3, viewingPubKey)
35-
msg.viewingPubKey =
36-
if viewingPubKey.len > 0:
37-
Opt.some(viewingPubKey)
38-
else:
39-
Opt.none(SerializedKey)
41+
msg.request = pb.request.get(0'u64) == 1
42+
msg.spendingPubKey = nonEmptyKey(pb.spendingPubKey)
43+
msg.viewingPubKey = nonEmptyKey(pb.viewingPubKey)
4044

4145
if msg.spendingPubKey.isSome() and msg.viewingPubKey.isSome():
4246
msg.stealthCommitment = Opt.none(SerializedKey)
4347
msg.viewTag = Opt.none(uint64)
4448
return ok(msg)
4549
if msg.spendingPubKey.isSome() and msg.viewingPubKey.isNone():
46-
return err(ProtoError.RequiredFieldMissing)
50+
return err(protobuf.ProtobufError(kind: ProtobufErrorKind.DecodeFailure))
4751
if msg.spendingPubKey.isNone() and msg.viewingPubKey.isSome():
48-
return err(ProtoError.RequiredFieldMissing)
52+
return err(protobuf.ProtobufError(kind: ProtobufErrorKind.DecodeFailure))
4953
if msg.request == true and msg.spendingPubKey.isNone() and msg.viewingPubKey.isNone():
50-
return err(ProtoError.RequiredFieldMissing)
51-
52-
var stealthCommitment = newSeq[byte]()
53-
discard ?pb.getField(4, stealthCommitment)
54-
msg.stealthCommitment =
55-
if stealthCommitment.len > 0:
56-
Opt.some(stealthCommitment)
57-
else:
58-
Opt.none(SerializedKey)
54+
return err(protobuf.ProtobufError(kind: ProtobufErrorKind.DecodeFailure))
5955

60-
var ephemeralPubKey = newSeq[byte]()
61-
discard ?pb.getField(5, ephemeralPubKey)
62-
msg.ephemeralPubKey =
63-
if ephemeralPubKey.len > 0:
64-
Opt.some(ephemeralPubKey)
65-
else:
66-
Opt.none(SerializedKey)
56+
msg.stealthCommitment = nonEmptyKey(pb.stealthCommitment)
57+
msg.ephemeralPubKey = nonEmptyKey(pb.ephemeralPubKey)
6758

68-
var viewTag: uint64
69-
discard ?pb.getField(6, viewTag)
59+
let viewTag = pb.viewTag.get(0'u64)
7060
msg.viewTag =
7161
if viewTag != 0:
7262
Opt.some(viewTag)
@@ -75,37 +65,31 @@ proc decode*(T: type WakuStealthCommitmentMsg, buffer: seq[byte]): ProtoResult[T
7565

7666
if msg.stealthCommitment.isNone() and msg.viewTag.isNone() and
7767
msg.ephemeralPubKey.isNone():
78-
return err(ProtoError.RequiredFieldMissing)
68+
return err(protobuf.ProtobufError(kind: ProtobufErrorKind.DecodeFailure))
7969

8070
if msg.stealthCommitment.isSome() and msg.viewTag.isNone():
81-
return err(ProtoError.RequiredFieldMissing)
71+
return err(protobuf.ProtobufError(kind: ProtobufErrorKind.DecodeFailure))
8272

8373
if msg.stealthCommitment.isNone() and msg.viewTag.isSome():
84-
return err(ProtoError.RequiredFieldMissing)
74+
return err(protobuf.ProtobufError(kind: ProtobufErrorKind.DecodeFailure))
8575

8676
if msg.stealthCommitment.isSome() and msg.viewTag.isSome():
8777
msg.spendingPubKey = Opt.none(SerializedKey)
8878
msg.viewingPubKey = Opt.none(SerializedKey)
8979

9080
ok(msg)
9181

92-
proc encode*(msg: WakuStealthCommitmentMsg): ProtoBuffer =
93-
var serialised = initProtoBuffer()
94-
95-
serialised.write(1, uint64(msg.request))
96-
97-
if msg.spendingPubKey.isSome():
98-
serialised.write(2, msg.spendingPubKey.get())
99-
if msg.viewingPubKey.isSome():
100-
serialised.write(3, msg.viewingPubKey.get())
101-
if msg.stealthCommitment.isSome():
102-
serialised.write(4, msg.stealthCommitment.get())
103-
if msg.ephemeralPubKey.isSome():
104-
serialised.write(5, msg.ephemeralPubKey.get())
105-
if msg.viewTag.isSome():
106-
serialised.write(6, msg.viewTag.get())
107-
108-
return serialised
82+
proc encode*(msg: WakuStealthCommitmentMsg): seq[byte] =
83+
Protobuf.encode(
84+
WakuStealthCommitmentMsgPB(
85+
request: Opt.some(uint64(msg.request)),
86+
spendingPubKey: msg.spendingPubKey,
87+
viewingPubKey: msg.viewingPubKey,
88+
stealthCommitment: msg.stealthCommitment,
89+
ephemeralPubKey: msg.ephemeralPubKey,
90+
viewTag: msg.viewTag,
91+
)
92+
)
10993

11094
func toByteSeq*(str: string): seq[byte] {.inline.} =
11195
## Converts a string to the corresponding byte sequence.

logos_delivery.nimble

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ requires "nim >= 2.2.4",
2626
"serialization",
2727
"json_serialization",
2828
"toml_serialization",
29+
"protobuf_serialization",
2930
"faststreams",
3031
# Networking & P2P
3132
"https://github.com/vacp2p/nim-libp2p.git#v2.0.0",
Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
# Extensions for libp2p's protobuf library implementation
1+
# Waku protobuf result/error types.
22

33
{.push raises: [].}
44

5-
import results, libp2p/protobuf/minprotobuf, libp2p/varint
6-
7-
export minprotobuf, varint
5+
import results
6+
export results
87

98
## Custom errors
109

@@ -17,48 +16,23 @@ type
1716
ProtobufError* = object
1817
case kind*: ProtobufErrorKind
1918
of DecodeFailure:
20-
error*: minprotobuf.ProtoError
19+
discard
2120
of MissingRequiredField, InvalidLengthField:
2221
field*: string
2322

2423
ProtobufResult*[T] = Result[T, ProtobufError]
2524

26-
converter toProtobufError*(err: minprotobuf.ProtoError): ProtobufError =
27-
case err
28-
of minprotobuf.ProtoError.RequiredFieldMissing:
29-
ProtobufError(kind: ProtobufErrorKind.MissingRequiredField, field: "unknown")
30-
else:
31-
ProtobufError(kind: ProtobufErrorKind.DecodeFailure, error: err)
32-
3325
proc missingRequiredField*(T: type ProtobufError, field: string): T =
3426
ProtobufError(kind: ProtobufErrorKind.MissingRequiredField, field: field)
3527

3628
proc invalidLengthField*(T: type ProtobufError, field: string): T =
3729
ProtobufError(kind: ProtobufErrorKind.InvalidLengthField, field: field)
3830

39-
## Extension methods
40-
41-
proc write3*(proto: var ProtoBuffer, field: int, value: auto) =
42-
when value is Opt:
43-
if value.isSome():
44-
proto.write(field, value.get())
45-
else:
46-
proto.write(field, value)
47-
48-
proc finish3*(proto: var ProtoBuffer) =
49-
if proto.buffer.len > 0:
50-
proto.finish()
51-
else:
52-
proto.offset = 0
53-
54-
proc `==`*(a: zint64, b: zint64): bool =
55-
int64(a) == int64(b)
56-
5731
proc `$`*(err: ProtobufError): string =
5832
case err.kind
5933
of DecodeFailure:
60-
return $err.error ## assume that ProtoError is pure
34+
"DecodeFailure"
6135
of MissingRequiredField:
62-
return "MissingRequiredField " & err.field
36+
"MissingRequiredField " & err.field
6337
of InvalidLengthField:
64-
return "InvalidLengthField " & err.field
38+
"InvalidLengthField " & err.field

0 commit comments

Comments
 (0)