Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Spammer #2821

Draft
wants to merge 5 commits into
base: rlnv2-only
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions apps/wakunode2/spammer.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
when (NimMajor, NimMinor) < (1, 4):
{.push raises: [Defect].}
else:
{.push raises: [].}

import
chronos,
chronicles,
stew/[byteutils, results],
std/times,
libp2p/protocols/pubsub/gossipsub,
strutils

import
../../waku/factory/waku,
../../waku/factory/external_config,
../../waku/waku_core,
../../waku/waku_relay,
../../waku/node/waku_node,
../../waku/node/peer_manager/peer_manager,
../../waku/waku_rln_relay/rln_relay,
../../tests/waku_rln_relay/rln/waku_rln_relay_utils

proc send(
waku: Waku, contentTopic: ContentTopic
): Future[Result[void, string]] {.async.} =
var ephemeral = true

var message = WakuMessage(
payload: toBytes("Hello World!" & intToStr(int(getTime().toUnix()))),
contentTopic: contentTopic,
# meta: metaBytes,
version: 2,
timestamp: getNanosecondTime(getTime().toUnixFloat()),
ephemeral: ephemeral,
)

let rlnRes =
waku.node.wakuRlnRelay.appendRLNProof(message, float64(getTime().toUnix()))
if rlnRes.isOk:
let pubRes = await waku.node.publish(none(PubsubTopic), message)
if pubRes.isErr():
error "failed to publish", msg = pubRes.error
return err(pubRes.error)
else:
error "failed to append RLNProof", err = rlnRes.error
return err(rlnRes.error)

return ok()

proc burstPublish(
waku: Waku, conf: WakuNodeConf, contentTopic: ContentTopic
) {.async.} =
var futures: seq[Future[Result[void, string]]]
var i: uint64 = 0
var start = getTime().toUnixFloat()

while i < conf.rlnRelayUserMessageLimit:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe i not needed?
and here
for i in conf.rlnRelayUserMessageLimit

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not how Nim works:-P There is a function I could use to turn the msg limit into iterator, but I am not sure it is worth searching for it:D

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yeah my bad. gues for i in 0..<conf.rlnRelayUserMessageLimit
no big deal tho

futures.add(send(waku, contentTopic))
inc i

let results = await allFinished(futures)

var current = getTime().toUnixFloat()
var tillNextBurst =
int(int64(conf.rlnEpochSizeSec * 1000) - int64((current - start) * 1000))
info "Published messages",
sleep = tillNextBurst, msgCount = conf.rlnRelayUserMessageLimit

await sleepAsync(tillNextBurst)

proc iterativePublish(
waku: Waku, conf: WakuNodeConf, contentTopic: ContentTopic
) {.async.} =
var start = getTime().toUnixFloat()

(await send(waku, contentTopic)).isOkOr:
error "Failed to publish", err = error

#echo await (waku.node.isReady())
var current = getTime().toUnixFloat()
var tillNextMsg = int(int64(conf.spammerDelay) - int64((current - start) * 1000))
info "Published message", sleep = tillNextMsg

await sleepAsync(tillNextMsg)

proc runSpammer*(
waku: Waku, conf: WakuNodeConf, contentTopic: ContentTopic = "/spammer/0/test/plain"
) {.async.} =
if not conf.spammerEnable:
return

if not conf.rlnRelay:
error "RLN not configured!"
quit(QuitFailure)

while true:
var (inRelayPeers, outRelayPeers) =
waku.node.peerManager.connectedPeers(WakuRelayCodec)

var numPeers = len(inRelayPeers) + len(outRelayPeers)
if numPeers > 0:
break
info "Waiting for peers", numPeers = numPeers
await sleepAsync(1000)

#var rate = int(float(1000) / float(conf.msgRate))
#var delayBetweenMsg =
# float(conf.rlnEpochSizeSec * 1000) /
# (float(conf.rlnRelayUserMessageLimit) * conf.msgRateMultiplier)

info "Sending message with delay", delay = conf.spammerDelay

while true:
if conf.spammerBurst:
await burstPublish(waku, conf, contentTopic)
else:
await iterativePublish(waku, conf, contentTopic)
5 changes: 5 additions & 0 deletions apps/wakunode2/wakunode2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import
system/ansi_c,
libp2p/crypto/crypto
import
./spammer,
../../tools/rln_keystore_generator/rln_keystore_generator,
../../tools/rln_db_inspector/rln_db_inspector,
../../waku/common/logging,
Expand Down Expand Up @@ -52,6 +53,8 @@ when isMainModule:
of inspectRlnDb:
doInspectRlnDb(conf)
of noCommand:
if conf.spammerEnable:
doRlnKeystoreGenerator(conf, false)
# NOTE: {.threadvar.} is used to make the global variable GC safe for the closure uses it
# It will always be called from main thread anyway.
# Ref: https://nim-lang.org/docs/manual.html#threads-gc-safety
Expand Down Expand Up @@ -132,4 +135,6 @@ when isMainModule:

info "Node setup complete"

asyncSpawn runSpammer(waku, conf)

runForever()
9 changes: 5 additions & 4 deletions tools/rln_keystore_generator/rln_keystore_generator.nim
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import
logScope:
topics = "rln_keystore_generator"

proc doRlnKeystoreGenerator*(conf: WakuNodeConf) =
proc doRlnKeystoreGenerator*(conf: WakuNodeConf, quitOnSucces: bool = true) =
# 1. load configuration
trace "configuration", conf = $conf

Expand All @@ -42,7 +42,7 @@ proc doRlnKeystoreGenerator*(conf: WakuNodeConf) =
idSecretHash = credential.idSecretHash.inHex(),
idCommitment = credential.idCommitment.inHex()

if not conf.execute:
if quitOnSucces and not conf.execute:
info "not executing, exiting"
quit(0)

Expand Down Expand Up @@ -91,7 +91,6 @@ proc doRlnKeystoreGenerator*(conf: WakuNodeConf) =
userMessageLimit: conf.rlnRelayUserMessageLimit,
)


let persistRes = addMembershipCredentials(
conf.rlnRelayCredPath, keystoreCred, conf.rlnRelayCredPassword, RLNAppInfo
)
Expand All @@ -106,4 +105,6 @@ proc doRlnKeystoreGenerator*(conf: WakuNodeConf) =
except CatchableError:
error "failure while stopping OnchainGroupManager", error = getCurrentExceptionMsg()
quit(0) # 0 because we already registered on-chain
quit(0)

if quitOnSucces:
quit(0)
25 changes: 25 additions & 0 deletions waku/factory/external_config.nim
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,31 @@ type WakuNodeConf* = object
name: "request-rate-period"
.}: int64

spammerEnable* {.desc: "Enable spammer", defaultValue: false, name: "spammer".}:
bool
# msgRate* {.
# desc: "Number of messages published per epoch",
# defaultValue: 10,
# name: "spammer-msg-rate"
# .}: int

# msgRateMultiplier* {.
# desc: "Multiply max message per epoch to publish spam",
# defaultValue: 1,
# name: "spammer-msg-multiplier"
# .}: float
spammerDelay* {.
desc: "Delay between spawning a publish method (in miliseconds)",
defaultValue: 0,
name: "spammer-delay-between-msg"
.}: int

spammerBurst* {.
desc: "Send messages in burst instead of one by one",
defaultValue: false,
name: "spammer-burst"
.}: bool

## Parsing

# NOTE: Keys are different in nim-libp2p
Expand Down
18 changes: 10 additions & 8 deletions waku/waku_rln_relay/nonce_manager.nim
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,16 @@ proc getNonce*(n: NonceManager): NonceManagerResult[Nonce] =

n.nextNonce = retNonce + 1

# This is modified for spam testing purposes, once the limit is reached the nonce value is reset to 0
if retNonce >= n.nonceLimit:
return err(
NonceManagerError(
kind: NonceLimitReached,
error:
"Nonce limit reached. Please wait for the next epoch. requested nonce: " &
$retNonce & " & nonceLimit: " & $n.nonceLimit,
)
)
retNonce = 0
# return err(
# NonceManagerError(
# kind: NonceLimitReached,
# error:
# "Nonce limit reached. Please wait for the next epoch. requested nonce: " &
# $retNonce & " & nonceLimit: " & $n.nonceLimit,
# )
# )

return ok(retNonce)
Loading