Component: pallets/exodus @ 0162da46, src/types/packages.rs:105-112 (PackageContext holds only authority_index + network_curve), src/lib.rs:901-950 (register_round0_package), src/lib.rs:2669-2700 (validate_round0_package_size), src/lib.rs:3760-3766 (offchain skip), src/types/dkg.rs:236-239 (restart increments the index).
Description: Every sr25519-signed DkgPackage (Rounds 0-6) binds only (authority_index, network_curve), with no dkg_index/generation. After restart_dkg()/new_dkg (phase returns to Round0, bitmap nullified), anyone (permissionless, unsigned tx, Pays::No) can replay a stale register_round0_package extrinsic from validator V from the previous generation: all checks pass (verify on verbatim replayed bytes is still valid). Consequences: (1) Round0Packages[V] is filled with a stale hash and the bitmap marks V as registered; (2) V’s real round-1 package is rejected (Round1PackageBadHash, lib.rs:978-980); (3) V’s own offchain worker skips submission because Round0Packages::contains_key (lib.rs:3760-3766): the victim is unaware and does not retry. A “franken-DKG” variant (also replaying a stale Round1 package so old key material mixes into the new group key) is HYPOTHESIS (needs further review).
Impact: Selective censorship/DoS of a validator’s DKG participation; if more than n - threshold validators are censored, DKG misses quorum and loops on restart. Permissionless and cheap.
Reproduction: Static reproduction: (1) capture validator V’s register_round0_package extrinsic from generation N; (2) wait for generation N+1 to enter the Round0 phase; (3) re-submit as an unsigned tx: it is accepted. Full code rationale above; executable PoC not yet run.
Severity: Medium. Reason: the mechanism is fully present in code and cheap, but taking down DKG entirely needs noisy mass censorship; single censorship is only degradation. Not High (no proven fund loss).
Recommendation: Bind dkg_index into the signed payload (add it to PackageContext or to each package) and reject packages whose dkg_index differs from QualificationDkgState.get_dkg_index() during validation.
Verification: VERIFIED (static analysis).