fix(send): gate SKDM redistribution on the primary device (WA Web parity) - #872
Conversation
…ity) During a retry storm (mass PN->LID migration) each retrying device is marked has_key=false individually, but the SKDM filter redistributed the sender key to ALL of that user's devices via a per-user is_user_forgotten clause, including devices that already hold the key. That is extra outbound SKDM volume during the storms that risk AccountLocked, and it diverges from WhatsApp Web. Match WA Web's getGroupSenderKeyListFromParticipantRecord (ParticipantStore.js): a device is warm (skip SKDM) only when both it AND its primary device (device 0) hold the key. The filter predicate becomes "needs SKDM iff the device is cold OR its primary is cold", replacing is_user_forgotten with a primary-device gate. A cold companion now redistributes only itself; a cold primary redistributes the whole user. This is exact WA Web parity, unlike the old over-broad behavior or a naive per-device check (which would drop an SKDM to a warm companion when the primary is cold). The now-dead forgotten_users set and is_user_forgotten method are removed.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughSummary by CodeRabbit
Walkthrough
ChangesSKDM Primary-Device Gate Refactor
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📦 Binary size report
.text per crate
Top movers (cargo-bloat attribution)
Baseline: |
Problem
During a retry storm (mass PN->LID migration), each retrying device is marked has_key=false individually, but the SKDM filter redistributed the sender key to ALL of that user's devices via a per-user
is_user_forgottenclause, including devices that already hold the key. That is extra outbound SKDM volume during exactly the storms that risk AccountLocked, and it diverges from WhatsApp Web.Fix
Match WA Web's getGroupSenderKeyListFromParticipantRecord (ParticipantStore.js): a device is warm (skip SKDM) only when both it AND its primary device (device 0) hold the key. The filter predicate becomes "needs SKDM iff the device is cold OR its primary is cold", replacing the per-user
is_user_forgottenclause with a primary-device gate.Strictly more correct than both the old behavior and a naive per-device check:
is_user_forgotten): a single cold companion redistributed the whole user. Broader than WA Web.The now-dead
forgotten_usersset andis_user_forgottenmethod are removed.Tests
filter_skdm_targets_uses_primary_device_gatedrives the real filter across the three distinguishing cases (cold companion + warm primary => only companion; cold primary + warm companion => whole user; warm companion + absent primary => companion). It fails for both the old over-broad and the naive under-broad behaviors.Verify
cargo fmt --all,cargo clippy --all-targets -- -D warningsclean.cargo test -p whatsapp-rust --lib(827 tests) pass.Notes (pre-existing, out of scope)
SenderKeyDeviceMapindexes by user (not server+user). Safe in practice (PN and LID user-id spaces are disjoint, and a single send resolves one namespace).sender_key_devicesrows. The retry path self-heals (a re-added device fails, gets marked cold, next send redistributes). Worth a separate look.