feat: allow msgIdProvider to fail (#688)
* feat: allow msgIdProvider to fail Closes: #642. Changes the return type of the msgIdProvider to `Result[MessageID, string]` so that message id generation can fail. String error type was chosen as this `msgIdProvider` mainly because the failed message id generation drops the message and logs the error provided. Because `msgIdProvider` can be externally provided by library consumers, an enum didn’t make sense and a object seemed to be overkill. Exceptions could have been used as well, however, in this case, Result ergonomics were warranted and prevented wrapping quite a large block of code in try/except. The `defaultMsgIdProvider` function previously allowed message id generation to fail silently for use in the tests: when seqno or source peerid were not valid, the message id generated was based on a hash of the message data and topic ids. The silent failing was moved to the `defaultMsgIdProvider` used only in the tests so that it could not fail silently in applications. Unit tests were added for the `defaultMsgIdProvider`. * Change MsgIdProvider error type to ValidationResult
This commit is contained in:
parent
9a7e3bda3c
commit
3b718baa97
|
@ -0,0 +1,6 @@
|
||||||
|
# this module will be further extended in PR
|
||||||
|
# https://github.com/status-im/nim-libp2p/pull/107/
|
||||||
|
|
||||||
|
type
|
||||||
|
ValidationResult* {.pure.} = enum
|
||||||
|
Accept, Reject, Ignore
|
|
@ -96,7 +96,14 @@ method rpcHandler*(f: FloodSub,
|
||||||
f.handleSubscribe(peer, sub.topic, sub.subscribe)
|
f.handleSubscribe(peer, sub.topic, sub.subscribe)
|
||||||
|
|
||||||
for msg in rpcMsg.messages: # for every message
|
for msg in rpcMsg.messages: # for every message
|
||||||
let msgId = f.msgIdProvider(msg)
|
let msgIdResult = f.msgIdProvider(msg)
|
||||||
|
if msgIdResult.isErr:
|
||||||
|
debug "Dropping message due to failed message id generation",
|
||||||
|
error = msgIdResult.error
|
||||||
|
# TODO: descore peers due to error during message validation (malicious?)
|
||||||
|
continue
|
||||||
|
|
||||||
|
let msgId = msgIdResult.get
|
||||||
|
|
||||||
if f.addSeen(msgId):
|
if f.addSeen(msgId):
|
||||||
trace "Dropping already-seen message", msgId, peer
|
trace "Dropping already-seen message", msgId, peer
|
||||||
|
@ -184,7 +191,14 @@ method publish*(f: FloodSub,
|
||||||
Message.init(none(PeerInfo), data, topic, none(uint64), false)
|
Message.init(none(PeerInfo), data, topic, none(uint64), false)
|
||||||
else:
|
else:
|
||||||
Message.init(some(f.peerInfo), data, topic, some(f.msgSeqno), f.sign)
|
Message.init(some(f.peerInfo), data, topic, some(f.msgSeqno), f.sign)
|
||||||
msgId = f.msgIdProvider(msg)
|
msgIdResult = f.msgIdProvider(msg)
|
||||||
|
|
||||||
|
if msgIdResult.isErr:
|
||||||
|
trace "Error generating message id, skipping publish",
|
||||||
|
error = msgIdResult.error
|
||||||
|
return 0
|
||||||
|
|
||||||
|
let msgId = msgIdResult.get
|
||||||
|
|
||||||
trace "Created new message",
|
trace "Created new message",
|
||||||
msg = shortLog(msg), peers = peers.len, topic, msgId
|
msg = shortLog(msg), peers = peers.len, topic, msgId
|
||||||
|
|
|
@ -362,8 +362,16 @@ method rpcHandler*(g: GossipSub,
|
||||||
|
|
||||||
for i in 0..<rpcMsg.messages.len(): # for every message
|
for i in 0..<rpcMsg.messages.len(): # for every message
|
||||||
template msg: untyped = rpcMsg.messages[i]
|
template msg: untyped = rpcMsg.messages[i]
|
||||||
|
let msgIdResult = g.msgIdProvider(msg)
|
||||||
|
|
||||||
|
if msgIdResult.isErr:
|
||||||
|
debug "Dropping message due to failed message id generation",
|
||||||
|
error = msgIdResult.error
|
||||||
|
# TODO: descore peers due to error during message validation (malicious?)
|
||||||
|
continue
|
||||||
|
|
||||||
let
|
let
|
||||||
msgId = g.msgIdProvider(msg)
|
msgId = msgIdResult.get
|
||||||
msgIdSalted = msgId & g.seenSalt
|
msgIdSalted = msgId & g.seenSalt
|
||||||
|
|
||||||
# addSeen adds salt to msgId to avoid
|
# addSeen adds salt to msgId to avoid
|
||||||
|
@ -505,7 +513,15 @@ method publish*(g: GossipSub,
|
||||||
Message.init(none(PeerInfo), data, topic, none(uint64), false)
|
Message.init(none(PeerInfo), data, topic, none(uint64), false)
|
||||||
else:
|
else:
|
||||||
Message.init(some(g.peerInfo), data, topic, some(g.msgSeqno), g.sign)
|
Message.init(some(g.peerInfo), data, topic, some(g.msgSeqno), g.sign)
|
||||||
msgId = g.msgIdProvider(msg)
|
msgIdResult = g.msgIdProvider(msg)
|
||||||
|
|
||||||
|
if msgIdResult.isErr:
|
||||||
|
trace "Error generating message id, skipping publish",
|
||||||
|
error = msgIdResult.error
|
||||||
|
libp2p_gossipsub_failed_publish.inc()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
let msgId = msgIdResult.get
|
||||||
|
|
||||||
logScope: msgId = shortLog(msgId)
|
logScope: msgId = shortLog(msgId)
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
|
|
||||||
import std/[tables, sequtils, sets, strutils]
|
import std/[tables, sequtils, sets, strutils]
|
||||||
import chronos, chronicles, metrics, bearssl
|
import chronos, chronicles, metrics, bearssl
|
||||||
import ./pubsubpeer,
|
import ./errors as pubsub_errors,
|
||||||
|
./pubsubpeer,
|
||||||
./rpc/[message, messages, protobuf],
|
./rpc/[message, messages, protobuf],
|
||||||
../../switch,
|
../../switch,
|
||||||
../protocol,
|
../protocol,
|
||||||
|
@ -76,16 +77,13 @@ type
|
||||||
TopicHandler* = proc(topic: string,
|
TopicHandler* = proc(topic: string,
|
||||||
data: seq[byte]): Future[void] {.gcsafe, raises: [Defect].}
|
data: seq[byte]): Future[void] {.gcsafe, raises: [Defect].}
|
||||||
|
|
||||||
ValidationResult* {.pure.} = enum
|
|
||||||
Accept, Reject, Ignore
|
|
||||||
|
|
||||||
ValidatorHandler* = proc(topic: string,
|
ValidatorHandler* = proc(topic: string,
|
||||||
message: Message): Future[ValidationResult] {.gcsafe, raises: [Defect].}
|
message: Message): Future[ValidationResult] {.gcsafe, raises: [Defect].}
|
||||||
|
|
||||||
TopicPair* = tuple[topic: string, handler: TopicHandler]
|
TopicPair* = tuple[topic: string, handler: TopicHandler]
|
||||||
|
|
||||||
MsgIdProvider* =
|
MsgIdProvider* =
|
||||||
proc(m: Message): MessageID {.noSideEffect, raises: [Defect], gcsafe.}
|
proc(m: Message): Result[MessageID, ValidationResult] {.noSideEffect, raises: [Defect], gcsafe.}
|
||||||
|
|
||||||
SubscriptionValidator* =
|
SubscriptionValidator* =
|
||||||
proc(topic: string): bool {.raises: [Defect], gcsafe.}
|
proc(topic: string): bool {.raises: [Defect], gcsafe.}
|
||||||
|
|
|
@ -16,9 +16,10 @@ import ./messages,
|
||||||
../../../peerid,
|
../../../peerid,
|
||||||
../../../peerinfo,
|
../../../peerinfo,
|
||||||
../../../crypto/crypto,
|
../../../crypto/crypto,
|
||||||
../../../protobuf/minprotobuf
|
../../../protobuf/minprotobuf,
|
||||||
|
../../../protocols/pubsub/errors
|
||||||
|
|
||||||
export messages
|
export errors, messages
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "pubsubmessage"
|
topics = "pubsubmessage"
|
||||||
|
@ -28,16 +29,12 @@ const PubSubPrefix = toBytes("libp2p-pubsub:")
|
||||||
declareCounter(libp2p_pubsub_sig_verify_success, "pubsub successfully validated messages")
|
declareCounter(libp2p_pubsub_sig_verify_success, "pubsub successfully validated messages")
|
||||||
declareCounter(libp2p_pubsub_sig_verify_failure, "pubsub failed validated messages")
|
declareCounter(libp2p_pubsub_sig_verify_failure, "pubsub failed validated messages")
|
||||||
|
|
||||||
func defaultMsgIdProvider*(m: Message): MessageID =
|
func defaultMsgIdProvider*(m: Message): Result[MessageID, ValidationResult] =
|
||||||
let mid =
|
if m.seqno.len > 0 and m.fromPeer.data.len > 0:
|
||||||
if m.seqno.len > 0 and m.fromPeer.data.len > 0:
|
let mid = byteutils.toHex(m.seqno) & $m.fromPeer
|
||||||
byteutils.toHex(m.seqno) & $m.fromPeer
|
ok mid.toBytes()
|
||||||
else:
|
else:
|
||||||
# This part is irrelevant because it's not standard,
|
err ValidationResult.Reject
|
||||||
# We use it exclusively for testing basically and users should
|
|
||||||
# implement their own logic in the case they use anonymization
|
|
||||||
$m.data.hash & $m.topicIDs.hash
|
|
||||||
mid.toBytes()
|
|
||||||
|
|
||||||
proc sign*(msg: Message, privateKey: PrivateKey): CryptoResult[seq[byte]] =
|
proc sign*(msg: Message, privateKey: PrivateKey): CryptoResult[seq[byte]] =
|
||||||
ok((? privateKey.sign(PubSubPrefix & encodeMessage(msg, false))).getBytes())
|
ok((? privateKey.sign(PubSubPrefix & encodeMessage(msg, false))).getBytes())
|
||||||
|
|
|
@ -20,6 +20,7 @@ import utils,
|
||||||
protocols/pubsub/floodsub,
|
protocols/pubsub/floodsub,
|
||||||
protocols/pubsub/rpc/messages,
|
protocols/pubsub/rpc/messages,
|
||||||
protocols/pubsub/peertable]
|
protocols/pubsub/peertable]
|
||||||
|
import ../../libp2p/protocols/pubsub/errors as pubsub_errors
|
||||||
|
|
||||||
import ../helpers
|
import ../helpers
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,8 @@ proc randomPeerId(): PeerId =
|
||||||
except CatchableError as exc:
|
except CatchableError as exc:
|
||||||
raise newException(Defect, exc.msg)
|
raise newException(Defect, exc.msg)
|
||||||
|
|
||||||
|
const MsgIdFail = "msg id gen failure"
|
||||||
|
|
||||||
suite "GossipSub internal":
|
suite "GossipSub internal":
|
||||||
teardown:
|
teardown:
|
||||||
checkTrackers()
|
checkTrackers()
|
||||||
|
@ -308,7 +310,7 @@ suite "GossipSub internal":
|
||||||
conn.peerId = peerId
|
conn.peerId = peerId
|
||||||
inc seqno
|
inc seqno
|
||||||
let msg = Message.init(peerId, ("HELLO" & $i).toBytes(), topic, some(seqno))
|
let msg = Message.init(peerId, ("HELLO" & $i).toBytes(), topic, some(seqno))
|
||||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
gossipSub.mcache.put(gossipSub.msgIdProvider(msg).expect(MsgIdFail), msg)
|
||||||
|
|
||||||
check gossipSub.fanout[topic].len == 15
|
check gossipSub.fanout[topic].len == 15
|
||||||
check gossipSub.mesh[topic].len == 15
|
check gossipSub.mesh[topic].len == 15
|
||||||
|
@ -355,7 +357,7 @@ suite "GossipSub internal":
|
||||||
conn.peerId = peerId
|
conn.peerId = peerId
|
||||||
inc seqno
|
inc seqno
|
||||||
let msg = Message.init(peerId, ("HELLO" & $i).toBytes(), topic, some(seqno))
|
let msg = Message.init(peerId, ("HELLO" & $i).toBytes(), topic, some(seqno))
|
||||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
gossipSub.mcache.put(gossipSub.msgIdProvider(msg).expect(MsgIdFail), msg)
|
||||||
|
|
||||||
let peers = gossipSub.getGossipPeers()
|
let peers = gossipSub.getGossipPeers()
|
||||||
check peers.len == gossipSub.parameters.d
|
check peers.len == gossipSub.parameters.d
|
||||||
|
@ -396,7 +398,7 @@ suite "GossipSub internal":
|
||||||
conn.peerId = peerId
|
conn.peerId = peerId
|
||||||
inc seqno
|
inc seqno
|
||||||
let msg = Message.init(peerId, ("HELLO" & $i).toBytes(), topic, some(seqno))
|
let msg = Message.init(peerId, ("HELLO" & $i).toBytes(), topic, some(seqno))
|
||||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
gossipSub.mcache.put(gossipSub.msgIdProvider(msg).expect(MsgIdFail), msg)
|
||||||
|
|
||||||
let peers = gossipSub.getGossipPeers()
|
let peers = gossipSub.getGossipPeers()
|
||||||
check peers.len == gossipSub.parameters.d
|
check peers.len == gossipSub.parameters.d
|
||||||
|
@ -437,7 +439,7 @@ suite "GossipSub internal":
|
||||||
conn.peerId = peerId
|
conn.peerId = peerId
|
||||||
inc seqno
|
inc seqno
|
||||||
let msg = Message.init(peerId, ("bar" & $i).toBytes(), topic, some(seqno))
|
let msg = Message.init(peerId, ("bar" & $i).toBytes(), topic, some(seqno))
|
||||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
gossipSub.mcache.put(gossipSub.msgIdProvider(msg).expect(MsgIdFail), msg)
|
||||||
|
|
||||||
let peers = gossipSub.getGossipPeers()
|
let peers = gossipSub.getGossipPeers()
|
||||||
check peers.len == 0
|
check peers.len == 0
|
||||||
|
|
|
@ -24,6 +24,7 @@ import utils, ../../libp2p/[errors,
|
||||||
protocols/pubsub/peertable,
|
protocols/pubsub/peertable,
|
||||||
protocols/pubsub/timedcache,
|
protocols/pubsub/timedcache,
|
||||||
protocols/pubsub/rpc/messages]
|
protocols/pubsub/rpc/messages]
|
||||||
|
import ../../libp2p/protocols/pubsub/errors as pubsub_errors
|
||||||
import ../helpers
|
import ../helpers
|
||||||
|
|
||||||
proc `$`(peer: PubSubPeer): string = shortLog(peer)
|
proc `$`(peer: PubSubPeer): string = shortLog(peer)
|
||||||
|
|
|
@ -5,19 +5,21 @@ import stew/byteutils
|
||||||
import ../../libp2p/[peerid,
|
import ../../libp2p/[peerid,
|
||||||
crypto/crypto,
|
crypto/crypto,
|
||||||
protocols/pubsub/mcache,
|
protocols/pubsub/mcache,
|
||||||
protocols/pubsub/rpc/message,
|
|
||||||
protocols/pubsub/rpc/messages]
|
protocols/pubsub/rpc/messages]
|
||||||
|
import ./utils
|
||||||
|
|
||||||
var rng = newRng()
|
var rng = newRng()
|
||||||
|
|
||||||
proc randomPeerId(): PeerId =
|
proc randomPeerId(): PeerId =
|
||||||
PeerId.init(PrivateKey.random(ECDSA, rng[]).get()).get()
|
PeerId.init(PrivateKey.random(ECDSA, rng[]).get()).get()
|
||||||
|
|
||||||
|
const MsgIdGenFail = "msg id gen failure"
|
||||||
|
|
||||||
suite "MCache":
|
suite "MCache":
|
||||||
test "put/get":
|
test "put/get":
|
||||||
var mCache = MCache.init(3, 5)
|
var mCache = MCache.init(3, 5)
|
||||||
var msg = Message(fromPeer: randomPeerId(), seqno: "12345".toBytes())
|
var msg = Message(fromPeer: randomPeerId(), seqno: "12345".toBytes())
|
||||||
let msgId = defaultMsgIdProvider(msg)
|
let msgId = defaultMsgIdProvider(msg).expect(MsgIdGenFail)
|
||||||
mCache.put(msgId, msg)
|
mCache.put(msgId, msg)
|
||||||
check mCache.get(msgId).isSome and mCache.get(msgId).get() == msg
|
check mCache.get(msgId).isSome and mCache.get(msgId).get() == msg
|
||||||
|
|
||||||
|
@ -28,13 +30,13 @@ suite "MCache":
|
||||||
var msg = Message(fromPeer: randomPeerId(),
|
var msg = Message(fromPeer: randomPeerId(),
|
||||||
seqno: "12345".toBytes(),
|
seqno: "12345".toBytes(),
|
||||||
topicIDs: @["foo"])
|
topicIDs: @["foo"])
|
||||||
mCache.put(defaultMsgIdProvider(msg), msg)
|
mCache.put(defaultMsgIdProvider(msg).expect(MsgIdGenFail), msg)
|
||||||
|
|
||||||
for i in 0..<5:
|
for i in 0..<5:
|
||||||
var msg = Message(fromPeer: randomPeerId(),
|
var msg = Message(fromPeer: randomPeerId(),
|
||||||
seqno: "12345".toBytes(),
|
seqno: "12345".toBytes(),
|
||||||
topicIDs: @["bar"])
|
topicIDs: @["bar"])
|
||||||
mCache.put(defaultMsgIdProvider(msg), msg)
|
mCache.put(defaultMsgIdProvider(msg).expect(MsgIdGenFail), msg)
|
||||||
|
|
||||||
var mids = mCache.window("foo")
|
var mids = mCache.window("foo")
|
||||||
check mids.len == 3
|
check mids.len == 3
|
||||||
|
@ -49,7 +51,7 @@ suite "MCache":
|
||||||
var msg = Message(fromPeer: randomPeerId(),
|
var msg = Message(fromPeer: randomPeerId(),
|
||||||
seqno: "12345".toBytes(),
|
seqno: "12345".toBytes(),
|
||||||
topicIDs: @["foo"])
|
topicIDs: @["foo"])
|
||||||
mCache.put(defaultMsgIdProvider(msg), msg)
|
mCache.put(defaultMsgIdProvider(msg).expect(MsgIdGenFail), msg)
|
||||||
|
|
||||||
mCache.shift()
|
mCache.shift()
|
||||||
check mCache.window("foo").len == 0
|
check mCache.window("foo").len == 0
|
||||||
|
@ -58,7 +60,7 @@ suite "MCache":
|
||||||
var msg = Message(fromPeer: randomPeerId(),
|
var msg = Message(fromPeer: randomPeerId(),
|
||||||
seqno: "12345".toBytes(),
|
seqno: "12345".toBytes(),
|
||||||
topicIDs: @["bar"])
|
topicIDs: @["bar"])
|
||||||
mCache.put(defaultMsgIdProvider(msg), msg)
|
mCache.put(defaultMsgIdProvider(msg).expect(MsgIdGenFail), msg)
|
||||||
|
|
||||||
mCache.shift()
|
mCache.shift()
|
||||||
check mCache.window("bar").len == 0
|
check mCache.window("bar").len == 0
|
||||||
|
@ -67,7 +69,7 @@ suite "MCache":
|
||||||
var msg = Message(fromPeer: randomPeerId(),
|
var msg = Message(fromPeer: randomPeerId(),
|
||||||
seqno: "12345".toBytes(),
|
seqno: "12345".toBytes(),
|
||||||
topicIDs: @["baz"])
|
topicIDs: @["baz"])
|
||||||
mCache.put(defaultMsgIdProvider(msg), msg)
|
mCache.put(defaultMsgIdProvider(msg).expect(MsgIdGenFail), msg)
|
||||||
|
|
||||||
mCache.shift()
|
mCache.shift()
|
||||||
check mCache.window("baz").len == 0
|
check mCache.window("baz").len == 0
|
||||||
|
@ -79,19 +81,19 @@ suite "MCache":
|
||||||
var msg = Message(fromPeer: randomPeerId(),
|
var msg = Message(fromPeer: randomPeerId(),
|
||||||
seqno: "12345".toBytes(),
|
seqno: "12345".toBytes(),
|
||||||
topicIDs: @["foo"])
|
topicIDs: @["foo"])
|
||||||
mCache.put(defaultMsgIdProvider(msg), msg)
|
mCache.put(defaultMsgIdProvider(msg).expect(MsgIdGenFail), msg)
|
||||||
|
|
||||||
for i in 0..<3:
|
for i in 0..<3:
|
||||||
var msg = Message(fromPeer: randomPeerId(),
|
var msg = Message(fromPeer: randomPeerId(),
|
||||||
seqno: "12345".toBytes(),
|
seqno: "12345".toBytes(),
|
||||||
topicIDs: @["bar"])
|
topicIDs: @["bar"])
|
||||||
mCache.put(defaultMsgIdProvider(msg), msg)
|
mCache.put(defaultMsgIdProvider(msg).expect(MsgIdGenFail), msg)
|
||||||
|
|
||||||
for i in 0..<3:
|
for i in 0..<3:
|
||||||
var msg = Message(fromPeer: randomPeerId(),
|
var msg = Message(fromPeer: randomPeerId(),
|
||||||
seqno: "12345".toBytes(),
|
seqno: "12345".toBytes(),
|
||||||
topicIDs: @["baz"])
|
topicIDs: @["baz"])
|
||||||
mCache.put(defaultMsgIdProvider(msg), msg)
|
mCache.put(defaultMsgIdProvider(msg).expect(MsgIdGenFail), msg)
|
||||||
|
|
||||||
mCache.shift()
|
mCache.shift()
|
||||||
check mCache.window("foo").len == 0
|
check mCache.window("foo").len == 0
|
||||||
|
|
|
@ -3,8 +3,10 @@ import unittest2
|
||||||
{.used.}
|
{.used.}
|
||||||
|
|
||||||
import options
|
import options
|
||||||
|
import stew/byteutils
|
||||||
import ../../libp2p/[peerid, peerinfo,
|
import ../../libp2p/[peerid, peerinfo,
|
||||||
crypto/crypto,
|
crypto/crypto,
|
||||||
|
protocols/pubsub/errors,
|
||||||
protocols/pubsub/rpc/message,
|
protocols/pubsub/rpc/message,
|
||||||
protocols/pubsub/rpc/messages]
|
protocols/pubsub/rpc/messages]
|
||||||
|
|
||||||
|
@ -18,3 +20,56 @@ suite "Message":
|
||||||
msg = Message.init(some(peer), @[], "topic", some(seqno), sign = true)
|
msg = Message.init(some(peer), @[], "topic", some(seqno), sign = true)
|
||||||
|
|
||||||
check verify(msg)
|
check verify(msg)
|
||||||
|
|
||||||
|
test "defaultMsgIdProvider success":
|
||||||
|
let
|
||||||
|
seqno = 11'u64
|
||||||
|
pkHex =
|
||||||
|
"""08011240B9EA7F0357B5C1247E4FCB5AD09C46818ECB07318CA84711875F4C6C
|
||||||
|
E6B946186A4EB44E0D714B2A2D48263D75CF52D30BEF9D9AE2A9FEB7DAF1775F
|
||||||
|
E731065A"""
|
||||||
|
seckey = PrivateKey.init(fromHex(stripSpaces(pkHex)))
|
||||||
|
.expect("invalid private key bytes")
|
||||||
|
peer = PeerInfo.new(seckey)
|
||||||
|
msg = Message.init(some(peer), @[], "topic", some(seqno), sign = true)
|
||||||
|
msgIdResult = msg.defaultMsgIdProvider()
|
||||||
|
|
||||||
|
check:
|
||||||
|
msgIdResult.isOk
|
||||||
|
string.fromBytes(msgIdResult.get) ==
|
||||||
|
"000000000000000b12D3KooWGyLzSt9g4U9TdHYDvVWAs5Ht4WrocgoyqPxxvnqAL8qw"
|
||||||
|
|
||||||
|
test "defaultMsgIdProvider error - no source peer id":
|
||||||
|
let
|
||||||
|
seqno = 11'u64
|
||||||
|
pkHex =
|
||||||
|
"""08011240B9EA7F0357B5C1247E4FCB5AD09C46818ECB07318CA84711875F4C6C
|
||||||
|
E6B946186A4EB44E0D714B2A2D48263D75CF52D30BEF9D9AE2A9FEB7DAF1775F
|
||||||
|
E731065A"""
|
||||||
|
seckey = PrivateKey.init(fromHex(stripSpaces(pkHex)))
|
||||||
|
.expect("invalid private key bytes")
|
||||||
|
peer = PeerInfo.new(seckey)
|
||||||
|
|
||||||
|
var msg = Message.init(peer.some, @[], "topic", some(seqno), sign = true)
|
||||||
|
msg.fromPeer = PeerId()
|
||||||
|
let msgIdResult = msg.defaultMsgIdProvider()
|
||||||
|
|
||||||
|
check:
|
||||||
|
msgIdResult.isErr
|
||||||
|
msgIdResult.error == ValidationResult.Reject
|
||||||
|
|
||||||
|
test "defaultMsgIdProvider error - no source seqno":
|
||||||
|
let
|
||||||
|
pkHex =
|
||||||
|
"""08011240B9EA7F0357B5C1247E4FCB5AD09C46818ECB07318CA84711875F4C6C
|
||||||
|
E6B946186A4EB44E0D714B2A2D48263D75CF52D30BEF9D9AE2A9FEB7DAF1775F
|
||||||
|
E731065A"""
|
||||||
|
seckey = PrivateKey.init(fromHex(stripSpaces(pkHex)))
|
||||||
|
.expect("invalid private key bytes")
|
||||||
|
peer = PeerInfo.new(seckey)
|
||||||
|
msg = Message.init(some(peer), @[], "topic", uint64.none, sign = true)
|
||||||
|
msgIdResult = msg.defaultMsgIdProvider()
|
||||||
|
|
||||||
|
check:
|
||||||
|
msgIdResult.isErr
|
||||||
|
msgIdResult.error == ValidationResult.Reject
|
||||||
|
|
|
@ -4,24 +4,37 @@ const
|
||||||
libp2p_pubsub_verify {.booldefine.} = true
|
libp2p_pubsub_verify {.booldefine.} = true
|
||||||
libp2p_pubsub_anonymize {.booldefine.} = false
|
libp2p_pubsub_anonymize {.booldefine.} = false
|
||||||
|
|
||||||
import random, tables
|
import hashes, random, tables
|
||||||
import chronos
|
import chronos, stew/[byteutils, results]
|
||||||
import ../../libp2p/[builders,
|
import ../../libp2p/[builders,
|
||||||
|
protocols/pubsub/errors,
|
||||||
protocols/pubsub/pubsub,
|
protocols/pubsub/pubsub,
|
||||||
protocols/pubsub/gossipsub,
|
protocols/pubsub/gossipsub,
|
||||||
protocols/pubsub/floodsub,
|
protocols/pubsub/floodsub,
|
||||||
|
protocols/pubsub/rpc/messages,
|
||||||
protocols/secure/secure]
|
protocols/secure/secure]
|
||||||
|
|
||||||
export builders
|
export builders
|
||||||
|
|
||||||
randomize()
|
randomize()
|
||||||
|
|
||||||
|
func defaultMsgIdProvider*(m: Message): Result[MessageID, ValidationResult] =
|
||||||
|
let mid =
|
||||||
|
if m.seqno.len > 0 and m.fromPeer.data.len > 0:
|
||||||
|
byteutils.toHex(m.seqno) & $m.fromPeer
|
||||||
|
else:
|
||||||
|
# This part is irrelevant because it's not standard,
|
||||||
|
# We use it exclusively for testing basically and users should
|
||||||
|
# implement their own logic in the case they use anonymization
|
||||||
|
$m.data.hash & $m.topicIDs.hash
|
||||||
|
ok mid.toBytes()
|
||||||
|
|
||||||
proc generateNodes*(
|
proc generateNodes*(
|
||||||
num: Natural,
|
num: Natural,
|
||||||
secureManagers: openArray[SecureProtocol] = [
|
secureManagers: openArray[SecureProtocol] = [
|
||||||
SecureProtocol.Noise
|
SecureProtocol.Noise
|
||||||
],
|
],
|
||||||
msgIdProvider: MsgIdProvider = nil,
|
msgIdProvider: MsgIdProvider = defaultMsgIdProvider,
|
||||||
gossip: bool = false,
|
gossip: bool = false,
|
||||||
triggerSelf: bool = false,
|
triggerSelf: bool = false,
|
||||||
verifySignature: bool = libp2p_pubsub_verify,
|
verifySignature: bool = libp2p_pubsub_verify,
|
||||||
|
|
Loading…
Reference in New Issue