Change:
For privacy reasons, leaders should not be allowed to replay a given report more than once within the context of a single batch. The current verify+collect model runs in a "streaming mode," wherein the leader sends slices of batch shares to helpers for verification and aggregation. If we changed this to require the leader to send all batch shares in a single verify+collect flow, then replay prevention would be simpler: just scan the list and check for dupes. If we stick with the current model, then the helper must necessarily store some state (on the leader, most likely) representing the shares processed. This state could then be consulted when asked to verify+collect any new share. (We can probably spell out a number of ways to do store this state, but ideally it should not be linear in the number of shares collected so far.) We'd likely also need a way for the leader to request that the helper produce the final aggregate output once the batch is "done" being verified and collected.
One downside to this approach is that it requires the leader to queue up the entire batch of reports before sending the first aggregate request to the helper. This may be OK for some deployments, but it might not be workable for all. I think this is worth pursuing. This is already in the protocol. (See "output share request".)
We could require that the leader feed the helper reports with monotonically increasing timestamps, such that the helper can simply maintain a single timestamp and reject any report older than that. However I'm not sure if that's practical given that clients may submit reports out of order.
One intermediate option would be to maintain a jitter buffer on the leader, so that they keep reports for a few minutes and then feed them out in order. You would still lose some reports, but not too many.
I have a few questions but nothing blocking.

Discussion:
Each task has a unique _task ID_ derived from the PDA parameters: <del> The task ID of a "PDAParam" `is derived using the following procedure: </del> <ins> The task ID of a "PDAParam" is derived using the following procedure: </ins> Where "SHA-256" is as specified in FIPS180-4.

"[leader]" is the leader's endpoint URL.  The payload is structured as follows: <del> We sometimes refer to this message as the _report_. The message contains the "task_id" of the previous request.  It also includes the time at which the report was generated.  This field is present to ensure that each report is included in at most one batch.  The rest of the message consists of the encrypted input shares, each of which has the following structure: </del> <ins> This message is called the client's _report_. It contains the following fields: "task_id" is the task ID of the task for which the report is intended. "time" is the time at which the report was generated.  This field is used by the aggregators to ensure the report appears in at most one batch.  (See anti-replay.) "jitter" is a random number chosen by the client generating the report.  This and the timestamp field are used by the aggregators to ensure that each report appears at most once in a batch.  (See anti-replay.) "encrypted_input_shares" contains the encrypted input shares of each of the aggregators. Encrypted input shares are structured as follows: </ins> "config_id" is equal to "HpkeConfig.id", where "HpkeConfig" is the aggregator's key config.

encrypt an input share, the client first generates an HPKE I-D.irtf- cfrg-hpke context for the aggregator by running <del> where "pk" is the aggregator's public key. "enc" is the encapsulate HPKE context and "context" is the HPKE context used by the client for encryption.  The payload is encrypted as </del> <ins> where "pk" is the aggregator's public key and "server_role" is a byte whose value is "0x01" if the aggregator is the leader and "0x00" if the aggregator is the helper. "enc" is the encapsulate HPKE context and "context" is the HPKE context used by the client for encryption. The payload is encrypted as </ins> <del> where "input_share" is the aggregator's input share. [TODO: Fully specify encryption of the shares.  We need to make sure we authenticate things like the PDA parameters and the report timestamp.  We need to decide what the info string for SetupBaseS() will be, as well as the aad for context.Seal().  The aad might be the entire "transcript" between the client and aggregator.] </del> <ins> where "input_share" is the aggregator's input share and "task_id", "time", and "jitter" are the fields of "PDAReport". </ins> The leader responds to well-formed requests to "[leader]/upload" with status 200 and an empty body.  Malformed requests are handled as

corresponding to a unique client report.  Sub-requests are structured as follows: <del> The "helper_share" field is the helper's encrypted input share as it appeared in the report uploaded by the client.  [OPEN ISSUE: We usually only need to send this in the first aggregate request.  Shall we exclude it in subsequent requests somehow?]  The "time" field should match the timestamp of the corresponding report.  The </del> <ins> The "time" and "jitter" fields have the same value as those in the report uploaded by the client.  Similarly, the "helper_share" field is the helper's encrypted input share as it appeared in the report. [OPEN ISSUE: We usually only need to send this in the first aggregate request.  Shall we exclude it in subsequent requests somehow?]  The </ins> remainder of the structure is dedicated to the protocol-specific <del> helper share and request parameters used for the current round. </del> <ins> request parameters. In order to provide replay protection, the leader is required to send aggregate sub-requests in ascending order, where the ordering on sub- requests is determined by the algorithm defined in anti-replay. Specifically, the leader constructs its request such that: * each sub-request follows the previous sub-request; and * the first sub- request follows the last sub-request in the previous aggregate request. </ins> The helper handles well-formed requests as follows.  (As usual, malformed requests are handled as described in pa-error-common- aborts.)  It first looks for the PDA parameters "PDAParam" for which "PDAAggregateReq.task_id" is equal to the task ID derived from <del> "PDAParam". </del> <ins> "PDAParam".  It then filters out out-of-order sub-requests by ignoring any sub-request that does not follow the previous one (See anti-replay.) </ins> The response consists of the helper's updated state and a sequence of _sub-responses_, where the i-th sub-response corresponds to the sub-

Next, it attempts to decrypt the payload with the following procedure: <del> where "sk" is the HPKE secret key.  If decryption fails, then the sub-response consists of a "decryption error" alert.  [See issue#57.] Otherwise, the helper handles the request for its plaintext input share "input_share" and updates its state as specified by the PDA protocol. </del> <ins> where "sk" is the HPKE secret key and "server_role" is the role of the server ("0x01" for the leader and "0x00" for the helper).  If decryption fails, then the sub-response consists of a "decryption error" alert.  [See issue#57.]  Otherwise, the helper handles the request for its plaintext input share "input_share" and updates its state as specified by the PDA protocol. </ins> After processing all of the sub-requests, the helper encrypts its updated state and constructs its response to the aggregate request. 3.4.2.1.1. <ins> The leader is required to issue aggregate requests in order, but reports are likely to arrive out-of-order.  The leader SHOULD buffer reports for a time period proportional to the batch window before issuing the first aggregate request.  Failure to do so will result in out-of-order reports being dropped by the helper. 3.4.2.1.2. </ins> The helper state is an optional parameter of an aggregate request that the can helper use to carry state across requests.  At least part of the state will usually need to be encrypted in order to

cloud vendor would be able to reassemble all the input shares and defeat privacy. <ins> 8.6.1. Using a report in multiple batches, or multiple times within a single batch, is considered a privacy violation, since it may leak more information about that report than intended by the PDA protocol.  For example, this may violate differential privacy.  To mitigate this issue, the core specification imposes an ordering on reports so that aggregators can cheaply prevent replays attacks. Aggregate requests are ordered as follows: We say that a report "R2" _follows_ report "R1" if either "R2.time > R1.time" or "R2.time == R1.time" and "R2.jitter > R1.jitter".  If "R2.time < R1.time", or "R2.time == R1.time" but "R2.jitter <= R1.jitter", then we say that "R2" _does not follow_ "R1". To prevent replay attacks, it suffices for each aggregator to ensure that each report it consumes follows the previous one it consumed. To prevent the adversary from tampering with the ordering of reports, honest clients incorporate the ordering-sensitive parameters "(time, jitter)" into the AAD for HPKE encryption. Note that this strategy may result in dropping reports that happen to have the same timestamp and jitter value. </ins> 8.7. 8.7.1.