Specify the REQUEST_SYNC responder budget

AGENTS.md requires protocol and security changes to update the relevant
specification. sync.md already carries the receiver-side DoS rules — the
filter-length cap and the malformed-payload rejections — but says nothing
about how often a request may be serviced or how much it may pull, which
is the gap this branch closes in the Android client.

Record it where the other receiver limits live, including why the budget
cannot be keyed on the sender ID: REQUEST_SYNC carries no signature that
receivers verify, so that field is free to rotate. Other implementations
need some equivalent even if they pick different numbers.
This commit is contained in:
Taksh 2026-08-16 09:41:08 +05:30
parent 3c126b20db
commit 2d80548ddb

View File

@ -71,6 +71,8 @@ Sender behavior:
Receiver behavior:
- Decode the REQUEST_SYNC payload and reconstruct the sorted set of mapped values using the provided P, M, and bitstream.
- Admit the request against the per-ingress budget described under “Validation and limits” before
decoding anything; drop it otherwise.
- For each locally stored public packet ID:
- Compute h64(ID) % M and check if it is in the reconstructed set; if NOT present, send the original packet back with `ttl=0` to the requester only.
- For announcements, send only the latest announcement per (sender peerID).
@ -143,6 +145,22 @@ Validation and limits (recommended):
- Reject malformed REQUEST_SYNC payloads (e.g., P < 1, M <= 0, or data length too large for local limits).
- Practical bounds: data length in [0, 1024]; P in [1, 24]; M up to 2^32‑1.
- Rate-limit how often a REQUEST_SYNC is serviced, and bound how many packets one requester can
pull. A filter that claims to hold nothing is a few bytes, and answering it costs a filter
decode, a packet-ID hash over every stored candidate, and up to “max packets per sync”
transmissions — so an unbounded responder amplifies a trivial request into the whole retention
set, repeatedly. The admission check MUST run before decoding or hashing, so a shed request
costs only the check.
- Key that budget on a **locally-assigned ingress identity** (the link or connection the request
arrived on), never on the sender ID in the packet. REQUEST_SYNC carries no signature that
receivers verify, so the sender ID is free to rotate: budgeting by it lets one neighbor mint a
fresh allowance per request, and lets it spend another peer's. Bookkeeping keyed on anything
taken from the wire MUST itself be bounded, or the limiter becomes a memory-exhaustion vector.
- Suggested shape (Android): one serviced request per 5s with a burst of 2, so the scheduled
first sync and a periodic one both land, plus a response allowance refilling to “max packets
per sync” over the 30s periodic interval — the most a peer can legitimately be missing in one
round. These are local policy; they need no cross-implementation agreement, but every
implementation needs some equivalent.
Versioning: