Skip to content

Commit

Permalink
chore: deprecating protected topics in favor of protected shards (#2983)
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielmer committed Aug 19, 2024
1 parent 6743905 commit e51ffe0
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 81 deletions.
106 changes: 56 additions & 50 deletions tests/wakunode2/test_validators.nim
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ suite "WakuNode2 - Validators":
newTestWakuNode(generateSecp256k1Key(), parseIpAddress("0.0.0.0"), Port(0))
)

# Protected topic and key to sign
let spamProtectedTopic = PubSubTopic("some-spam-protected-topic")
# Protected shard and key to sign
let spamProtectedShard = RelayShard(clusterId: 0, shardId: 7)
let secretKey = SkSecretKey
.fromHex("5526a8990317c9b7b58d07843d270f9cd1d9aaee129294c1c478abf7261dd9e6")
.expect("valid key")
let publicKey = secretKey.toPublicKey()
let topicsPrivateKeys = {spamProtectedTopic: secretKey}.toTable
let topicsPublicKeys = {spamProtectedTopic: publicKey}.toTable
let shardsPrivateKeys = {spamProtectedShard: secretKey}.toTable
let shardsPublicKeys = {spamProtectedShard: publicKey}.toTable

# Start all the nodes and mount relay with protected topic
await allFutures(nodes.mapIt(it.start()))
Expand All @@ -48,10 +48,12 @@ suite "WakuNode2 - Validators":

# Add signed message validator to all nodes. They will only route signed messages
for node in nodes:
var signedTopics: seq[ProtectedTopic]
for topic, publicKey in topicsPublicKeys:
signedTopics.add(ProtectedTopic(topic: topic, key: publicKey))
node.wakuRelay.addSignedTopicsValidator(signedTopics)
var signedShards: seq[ProtectedShard]
for shard, publicKey in shardsPublicKeys:
signedShards.add(ProtectedShard(shard: shard.shardId, key: publicKey))
node.wakuRelay.addSignedShardsValidator(
signedShards, spamProtectedShard.clusterId
)

# Connect the nodes in a full mesh
for i in 0 ..< 5:
Expand All @@ -72,25 +74,25 @@ suite "WakuNode2 - Validators":

# Subscribe all nodes to the same topic/handler
for node in nodes:
discard node.wakuRelay.subscribe(spamProtectedTopic, handler)
discard node.wakuRelay.subscribe($spamProtectedShard, handler)
await sleepAsync(500.millis)

# Each node publishes 10 signed messages
for i in 0 ..< 5:
for j in 0 ..< 10:
var msg = WakuMessage(
payload: urandom(1 * (10 ^ 3)),
contentTopic: spamProtectedTopic,
contentTopic: spamProtectedShard,
version: 2,
timestamp: now(),
ephemeral: true,
)

# Include signature
msg.meta =
secretKey.sign(SkMessage(spamProtectedTopic.msgHash(msg))).toRaw()[0 .. 63]
secretKey.sign(SkMessage(spamProtectedShard.msgHash(msg))).toRaw()[0 .. 63]

discard await nodes[i].publish(some(spamProtectedTopic), msg)
discard await nodes[i].publish(some($spamProtectedShard), msg)

# Wait for gossip
await sleepAsync(2.seconds)
Expand All @@ -103,7 +105,7 @@ suite "WakuNode2 - Validators":
for i in 0 ..< 5:
for k, v in nodes[i].wakuRelay.peerStats.mpairs:
check:
v.topicInfos[spamProtectedTopic].invalidMessageDeliveries == 0.0
v.topicInfos[spamProtectedShard].invalidMessageDeliveries == 0.0

# Stop all nodes
await allFutures(nodes.mapIt(it.stop()))
Expand All @@ -114,14 +116,14 @@ suite "WakuNode2 - Validators":
newTestWakuNode(generateSecp256k1Key(), parseIpAddress("0.0.0.0"), Port(0))
)

# Protected topic and key to sign
let spamProtectedTopic = PubSubTopic("some-spam-protected-topic")
# Protected shard and key to sign
let spamProtectedShard = RelayShard(clusterId: 0, shardId: 7)
let secretKey = SkSecretKey
.fromHex("5526a8990317c9b7b58d07843d270f9cd1d9aaee129294c1c478abf7261dd9e6")
.expect("valid key")
let publicKey = secretKey.toPublicKey()
let topicsPrivateKeys = {spamProtectedTopic: secretKey}.toTable
let topicsPublicKeys = {spamProtectedTopic: publicKey}.toTable
let shardsPrivateKeys = {spamProtectedShard: secretKey}.toTable
let shardsPublicKeys = {spamProtectedShard: publicKey}.toTable

# Non whitelisted secret key
let wrongSecretKey = SkSecretKey
Expand All @@ -136,10 +138,12 @@ suite "WakuNode2 - Validators":

# Add signed message validator to all nodes. They will only route signed messages
for node in nodes:
var signedTopics: seq[ProtectedTopic]
for topic, publicKey in topicsPublicKeys:
signedTopics.add(ProtectedTopic(topic: topic, key: publicKey))
node.wakuRelay.addSignedTopicsValidator(signedTopics)
var signedShards: seq[ProtectedShard]
for shard, publicKey in shardsPublicKeys:
signedShards.add(ProtectedShard(shard: shard.shardId, key: publicKey))
node.wakuRelay.addSignedShardsValidator(
signedShards, spamProtectedShard.clusterId
)

# Connect the nodes in a full mesh
for i in 0 ..< 5:
Expand All @@ -160,76 +164,76 @@ suite "WakuNode2 - Validators":

# Subscribe all nodes to the same topic/handler
for node in nodes:
discard node.wakuRelay.subscribe(spamProtectedTopic, handler)
discard node.wakuRelay.subscribe($spamProtectedShard, handler)
await sleepAsync(500.millis)

# Each node sends 5 messages, signed but with a non-whitelisted key (total = 25)
for i in 0 ..< 5:
for j in 0 ..< 5:
var msg = WakuMessage(
payload: urandom(1 * (10 ^ 3)),
contentTopic: spamProtectedTopic,
contentTopic: spamProtectedShard,
version: 2,
timestamp: now(),
ephemeral: true,
)

# Sign the message with a wrong key
msg.meta = wrongSecretKey.sign(SkMessage(spamProtectedTopic.msgHash(msg))).toRaw()[
msg.meta = wrongSecretKey.sign(SkMessage(spamProtectedShard.msgHash(msg))).toRaw()[
0 .. 63
]

discard await nodes[i].publish(some(spamProtectedTopic), msg)
discard await nodes[i].publish(some($spamProtectedShard), msg)

# Each node sends 5 messages that are not signed (total = 25)
for i in 0 ..< 5:
for j in 0 ..< 5:
let unsignedMessage = WakuMessage(
payload: urandom(1 * (10 ^ 3)),
contentTopic: spamProtectedTopic,
contentTopic: spamProtectedShard,
version: 2,
timestamp: now(),
ephemeral: true,
)
discard await nodes[i].publish(some(spamProtectedTopic), unsignedMessage)
discard await nodes[i].publish(some($spamProtectedShard), unsignedMessage)

# Each node sends 5 messages that dont contain timestamp (total = 25)
for i in 0 ..< 5:
for j in 0 ..< 5:
let unsignedMessage = WakuMessage(
payload: urandom(1 * (10 ^ 3)),
contentTopic: spamProtectedTopic,
contentTopic: spamProtectedShard,
version: 2,
timestamp: 0,
ephemeral: true,
)
discard await nodes[i].publish(some(spamProtectedTopic), unsignedMessage)
discard await nodes[i].publish(some($spamProtectedShard), unsignedMessage)

# Each node sends 5 messages way BEFORE than the current timestmap (total = 25)
for i in 0 ..< 5:
for j in 0 ..< 5:
let beforeTimestamp = now() - getNanosecondTime(6 * 60)
let unsignedMessage = WakuMessage(
payload: urandom(1 * (10 ^ 3)),
contentTopic: spamProtectedTopic,
contentTopic: spamProtectedShard,
version: 2,
timestamp: beforeTimestamp,
ephemeral: true,
)
discard await nodes[i].publish(some(spamProtectedTopic), unsignedMessage)
discard await nodes[i].publish(some($spamProtectedShard), unsignedMessage)

# Each node sends 5 messages way LATER than the current timestmap (total = 25)
for i in 0 ..< 5:
for j in 0 ..< 5:
let afterTimestamp = now() - getNanosecondTime(6 * 60)
let unsignedMessage = WakuMessage(
payload: urandom(1 * (10 ^ 3)),
contentTopic: spamProtectedTopic,
contentTopic: spamProtectedShard,
version: 2,
timestamp: afterTimestamp,
ephemeral: true,
)
discard await nodes[i].publish(some(spamProtectedTopic), unsignedMessage)
discard await nodes[i].publish(some($spamProtectedShard), unsignedMessage)

# Since we have a full mesh with 5 nodes and each one publishes 25+25+25+25+25 msgs
# there are 625 messages being sent.
Expand All @@ -243,7 +247,7 @@ suite "WakuNode2 - Validators":
msgRejected = 0
for i in 0 ..< 5:
for k, v in nodes[i].wakuRelay.peerStats.mpairs:
msgRejected += v.topicInfos[spamProtectedTopic].invalidMessageDeliveries.int
msgRejected += v.topicInfos[spamProtectedShard].invalidMessageDeliveries.int

if msgReceived == 125 and msgRejected == 500:
break
Expand All @@ -262,14 +266,14 @@ suite "WakuNode2 - Validators":
newTestWakuNode(generateSecp256k1Key(), parseIpAddress("0.0.0.0"), Port(0))
)

# Protected topic and key to sign
let spamProtectedTopic = PubSubTopic("some-spam-protected-topic")
# Protected shard and key to sign
let spamProtectedShard = RelayShard(clusterId: 0, shardId: 7)
let secretKey = SkSecretKey
.fromHex("5526a8990317c9b7b58d07843d270f9cd1d9aaee129294c1c478abf7261dd9e6")
.expect("valid key")
let publicKey = secretKey.toPublicKey()
let topicsPrivateKeys = {spamProtectedTopic: secretKey}.toTable
let topicsPublicKeys = {spamProtectedTopic: publicKey}.toTable
let shardsPrivateKeys = {spamProtectedShard: secretKey}.toTable
let shardsPublicKeys = {spamProtectedShard: publicKey}.toTable

# Non whitelisted secret key
let wrongSecretKey = SkSecretKey
Expand All @@ -288,15 +292,17 @@ suite "WakuNode2 - Validators":

# Subscribe all nodes to the same topic/handler
for node in nodes:
discard node.wakuRelay.subscribe(spamProtectedTopic, handler)
discard node.wakuRelay.subscribe($spamProtectedShard, handler)
await sleepAsync(500.millis)

# Add signed message validator to all nodes. They will only route signed messages
for node in nodes:
var signedTopics: seq[ProtectedTopic]
for topic, publicKey in topicsPublicKeys:
signedTopics.add(ProtectedTopic(topic: topic, key: publicKey))
node.wakuRelay.addSignedTopicsValidator(signedTopics)
var signedShards: seq[ProtectedShard]
for shard, publicKey in shardsPublicKeys:
signedShards.add(ProtectedShard(shard: shard.shardId, key: publicKey))
node.wakuRelay.addSignedShardsValidator(
signedShards, spamProtectedShard.clusterId
)

# nodes[0] is connected only to nodes[1]
let connOk1 = await nodes[0].peerManager.connectRelay(
Expand All @@ -321,26 +327,26 @@ suite "WakuNode2 - Validators":
for j in 0 ..< 50:
let unsignedMessage = WakuMessage(
payload: urandom(1 * (10 ^ 3)),
contentTopic: spamProtectedTopic,
contentTopic: spamProtectedShard,
version: 2,
timestamp: now(),
ephemeral: true,
)
discard await nodes[0].publish(some(spamProtectedTopic), unsignedMessage)
discard await nodes[0].publish(some($spamProtectedShard), unsignedMessage)

# nodes[0] spams 50 wrongly signed messages (nodes[0] just knows of nodes[1])
for j in 0 ..< 50:
var msg = WakuMessage(
payload: urandom(1 * (10 ^ 3)),
contentTopic: spamProtectedTopic,
contentTopic: spamProtectedShard,
version: 2,
timestamp: now(),
ephemeral: true,
)
# Sign the message with a wrong key
msg.meta =
wrongSecretKey.sign(SkMessage(spamProtectedTopic.msgHash(msg))).toRaw()[0 .. 63]
discard await nodes[0].publish(some(spamProtectedTopic), msg)
wrongSecretKey.sign(SkMessage(spamProtectedShard.msgHash(msg))).toRaw()[0 .. 63]
discard await nodes[0].publish(some($spamProtectedShard), msg)

# Wait for gossip
await sleepAsync(2.seconds)
Expand All @@ -353,7 +359,7 @@ suite "WakuNode2 - Validators":
# peer1 got invalid messages from peer0
let p0Id = nodes[0].peerInfo.peerId
check:
nodes[1].wakuRelay.peerStats[p0Id].topicInfos[spamProtectedTopic].invalidMessageDeliveries ==
nodes[1].wakuRelay.peerStats[p0Id].topicInfos[spamProtectedShard].invalidMessageDeliveries ==
100.0

# peer1 did not gossip further, so no other node rx invalid messages
Expand All @@ -362,7 +368,7 @@ suite "WakuNode2 - Validators":
if k == p0Id and i == 1:
continue
check:
v.topicInfos[spamProtectedTopic].invalidMessageDeliveries == 0.0
v.topicInfos[spamProtectedShard].invalidMessageDeliveries == 0.0

# Stop all nodes
await allFutures(nodes.mapIt(it.stop()))
Expand Down
Loading

0 comments on commit e51ffe0

Please sign in to comment.