You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Every native node draws the same radio noise, so every node's fast_rng is seeded identically #720
Found while tracing #712. The identity was a different fault (the bridge's 32-bit strtoul), but the hypothesis in that issue, "the startup is passing the same noise to each node", is true of everything except the identity.
Since MeshBench/meshcore-native 0f43543 the native binary runs MeshCore's own CustomSX1262 over RadioLib over the vendored virtual-sx1262 model, linked into the process. randomByte() is RadioLib's real SX126x::randomByte(), and the model answers it from refreshNoise(): splitmix64 over noiseSeed_ + K * (++noiseCounter_). noiseSeed_ defaults to 0 and nothing in meshcore-native ever calls setNoiseSeed / vsx_set_noise_seed. There is no --noise-seed flag and no MESHBENCH_NOISE_SEED read (bridge/main.cpp accepts --bridge --seed --sf --bw-khz --cr --stuck-irq-ms --print-airtime).
So every native node runs the identical noise stream from counter 0, and because boot is deterministic they read the same bytes at the same points. The identity survives because the host variant bypasses the radio there (radio_new_identity() uses HostRNG(g_identity_seed)). What does not survive:
simple_repeater/main.cpp:68 does fast_rng.begin(radio_driver.getRngSeed()), and RadioLibWrappers.cpp:46-48 implements that as _radio->random(0x7FFFFFFF): four randomByte() calls, 32 reads of the noise register. Every native node's StdRNG is seeded identically. That is CSMA backoff, advert jitter, retry timing: the things whose independence between nodes the channel model depends on.
This is the native-side instance of #556, which gave the emulated chip a per-node noise stream (internal/firmware/emulated/noiseseed.go, MESHBENCH_NOISE_SEED, FNV-1a over run seed + name + board + position).
What would fix it
meshcore-native: --noise-seed N in bridge/main.cpp, calling sim_hal.chip().setNoiseSeed(N) before setup().
MeshBench: send it from internal/firmware/native/native.go, derived the way noiseSeedFor already does for emulated nodes rather than from the node index.
Needs a meshcore-native release, so it is not in the #712 fix. Until then, native nodes' backoff and jitter are correlated across the whole mesh, and any result that depends on two nodes not choosing the same slot is optimistic or pessimistic in a way nobody has measured.
Fixed in MeshBench/meshcore-native#23 (merged): the bridge sets the chip model's noise seed, defaulting to the node's identity seed - which the simulator makes distinct per node - so every native node draws its own receiver-noise stream and its RNG, CSMA backoff and advert jitter are no longer correlated across the mesh. Shipped in v0.0.11: all native firmware releases were rebuilt and their assets replaced, and the rebuilt binaries carry the --noise-seed argument. Two Fife fixtures pass with the noise-fixed binaries.
Activity
bridge: each node draws its own receiver noise (#23)
A13xB0 commentedon Sep 9, 2026
Fixed in MeshBench/meshcore-native#23 (merged): the bridge sets the chip model's noise seed, defaulting to the node's identity seed - which the simulator makes distinct per node - so every native node draws its own receiver-noise stream and its RNG, CSMA backoff and advert jitter are no longer correlated across the mesh. Shipped in v0.0.11: all native firmware releases were rebuilt and their assets replaced, and the rebuilt binaries carry the
--noise-seedargument. Two Fife fixtures pass with the noise-fixed binaries.