jiebi/TextFlow huggingface dataset:
Original text:
given task.  If the leader receives a report from a client whose nonce is in this set, it simply ignores it.  A helper who receives an encrypted input share whose nonce is in this set replies to the <del> leader with an error as described in collect-flow. </del>  [OPEN ISSUE: This has the potential to require aggreagtors to store nonce sests indefinitely.  See issue#180.]

Reviewer comments:
This fixes a reference that was pointing at the wrong section. The behavior relating to is under "Input Share Validation".

Revised text:
given task.  If the leader receives a report from a client whose nonce is in this set, it simply ignores it.  A helper who receives an encrypted input share whose nonce is in this set replies to the  <ins> leader with an error as described in input-share-batch-validation. </ins> [OPEN ISSUE: This has the potential to require aggreagtors to store nonce sests indefinitely.  See issue#180.]
Original text:
(described in hpke-config); see compliance for information about the HPKE configuration algorithms. <del> "vdaf_verify_param": The aggregator's VDAF verification parameter output by the setup algorithm computed jointly by the aggregators before the start of the DAP protocol VDAF).  [OPEN ISSUE: This is yet to be specified.  See issue#161.] </del>  The helper stores a bearer token used to authenticate HTTP requests from the leader.  Likewise, the leader stores a bearer token to Each aggregator runs this procedure for a given input share with corresponding nonce as follows: <del> "vdaf_verify_param" is the public VDAF parameter, and "agg_param" is the opaque aggregation parameter.  If either step fails, the aggregator marks the report as invalid with error "vdaf-prep-error". </del>  <del> Otherwise, the value "out" is interpreted as follows.  If this is the last round of the VDAF, then "out" is the aggregator's output share. Otherwise, "out" is the pair "(prep_state, prep_msg)". </del>  4.3.2. each share in the candidate report set until the underlying VDAF moves into a terminal state, yielding an output share for all aggregators or an error.  This phase may involve multiple rounds of <del> interaction depending on the underlying VDAF parameters.  Each round trip is initiated by the leader. </del>  4.3.2.1.

Reviewer comments:
The next VDAF draft is out. It includes some minor changes that we'll need to adopt here. URL

Revised text:
(described in hpke-config); see compliance for information about the HPKE configuration algorithms.  <ins> "vdaf_verify_key": The VDAF verification key shared by the aggregators.  This key is used in the aggregation sub-protocol (aggregate-flow).  [OPEN ISSUE: The manner in which this key is distributed may be relevant to the VDAF's security.  See issue#161.] </ins> The helper stores a bearer token used to authenticate HTTP requests from the leader.  Likewise, the leader stores a bearer token to Each aggregator runs this procedure for a given input share with corresponding nonce as follows:  <ins> "vdaf_verify_key" is the VDAF verification key shared by the aggregators; "agg_id" is the aggregator ID ("0x00" for the Leader and "0x01" for the helper); and "agg_param" is the opaque aggregation parameter distributed to the aggregtors by the collector. </ins>  <ins> If either step fails, the aggregator marks the report as invalid with error "vdaf-prep-error".  Otherwise, the value "out" is interpreted as follows.  If this is the last round of the VDAF, then "out" is the aggregator's output share.  Otherwise, "out" is the pair "(prep_state, prep_msg)". </ins> 4.3.2. each share in the candidate report set until the underlying VDAF moves into a terminal state, yielding an output share for all aggregators or an error.  This phase may involve multiple rounds of  <ins> interaction depending on the underlying VDAF.  Each round trip is initiated by the leader. </ins> 4.3.2.1.
Original text:
HTTP GET requests to the collect job's URI with HTTP status code 200 OK and a body consisting of a "CollectResp": <del> The "encrypted_agg_shares" field is the vector of encrypted aggregate shares.  They MUST appear in the same order as the aggregator endpoints list of the task parameters. </del>  If obtaining aggregate shares fails, then the leader responds to subsequent HTTP GET requests to the collect job URI with an HTTP

Reviewer comments:
This adds a field to collect responses with the number of reports that contributed to the aggregation. Collectors will likely want this count to aid in the interpretation of aggregate results. (see ) There is also a change in draft-irtf-cfrg-vdaf-02 that opens the door for VDAFs that would require the report count during unsharding. (see cfrg/draft-irtf-cfrg-vdaf) Note that while this field is not part of the adjacent s, it will be protected by to the confidentiality of HTTPS and the leader-collector bearer token authentication.
I'm open to pushing it into the ciphertext, but my thinking was that a tampered reportcount would only affect robustness, not privacy, and thus we only need to arrive at the correct reportcount when all aggregators follow the protocol.
NAME can you please rebase? Sorry!
Collectors will want to know how many inputs are included in the aggregations they receive, for a number of reasons: they may wish to compute a mean over a privately aggregated sum, or track metrics on how many clients are providing inputs. struct should include a count of how many contributions went into an aggregation.
The linked PR only added a to the structure, which communicates it to the helper. I'm reopening this issue because the collector does not yet receive this information. In addition to the statistics-related motivation above, a recent PR to the VDAF spec, cfrg/draft-irtf-cfrg-vdaf, expects the number of reports to be available when unsharding.
This was completed in .
OK, seems reasonable to me.

Revised text:
HTTP GET requests to the collect job's URI with HTTP status code 200 OK and a body consisting of a "CollectResp":  <ins> "report_count" is the number of reports included in the aggregation. "encrypted_agg_shares" is the vector of encrypted aggregate shares.  They MUST appear in the same order as the aggregator endpoints list of the task parameters. </ins> If obtaining aggregate shares fails, then the leader responds to subsequent HTTP GET requests to the collect job URI with an HTTP
Original text:
Aggregators can control this cached lifetime with the Cache-Control header, as follows: <del> Clients SHOULD follow the usual HTTP caching RFC7234 semantics for </del>  key configurations. Note: Long cache lifetimes may result in clients using stale HPKE

Reviewer comments:
I-D Nits complains of outdated reference for: ** Obsolete normative reference: RFC 7234 (Obsoleted by RFC 9111) We should update tit.
Thanks!

Revised text:
Aggregators can control this cached lifetime with the Cache-Control header, as follows:  <ins> Clients SHOULD follow the usual HTTP caching RFC9111 semantics for </ins> key configurations. Note: Long cache lifetimes may result in clients using stale HPKE
Original text:
The time-interval query type is described in time-interval-query; the fixed-size query type is described in fixed-size-query.  Future specifications can introduce new query types as needed (see query- <del> type-reg.  A query includes parameters used by the Aggregators to </del>  select a batch of reports specific to the given query type.  A query is defined as follows:

Reviewer comments:
NAME I think we should wait for one of NAME or NAME before merging.
s4.1 includes the following: Future specifications can introduce new query types as needed. That means this I-D needs an IANA consideration to address registering a query type.

Revised text:
The time-interval query type is described in time-interval-query; the fixed-size query type is described in fixed-size-query.  Future specifications can introduce new query types as needed (see query-  <ins> type-reg).  A query includes parameters used by the Aggregators to </ins> select a batch of reports specific to the given query type.  A query is defined as follows:
Original text:
This message is called the Client's report.  It consists of the task ID, report metadata, the "public share" output by the VDAF's input- distribution algorithm, and the encrypted input share of each of the <del> Aggregators.  The metadata consists of the following fields: </del>  A timestamp representing the time at which the report was generated.  Specifically, the "time" field is set to the number of

Reviewer comments:
cc/ NAME
The presentation syntax is: opaque public_share; Are there ever going to be no public shares in a Report?
EDITED: Yes, Prio3 has an empty public share. This is mainly needed for Poplar1. From the :
NAME if you want, we can add text that makes sure your question is answered. Otherwise I don't think there's any action to take here.
I think the answer should be: "Yes, Prio3 doesn't need public shares."
Thanks for the update.

Revised text:
This message is called the Client's report.  It consists of the task ID, report metadata, the "public share" output by the VDAF's input- distribution algorithm, and the encrypted input share of each of the  <ins> Aggregators.  (Note that the public share might be empty, depending on the VDAF.  For example, Prio3 has an empty public share, but Poplar1 does not.  See VDAF.)  The header consists of the task ID and report "metadata".  The metadata consists of the following fields: </ins> A timestamp representing the time at which the report was generated.  Specifically, the "time" field is set to the number of
Original text:
"(prep_state, prep_msg)". To carry out this step, for each PrepareStep in <del> AggregateContinueReq.prepare_shares received from the leader, the </del>  helper performs the following check to determine if the report share should continue being prepared: "prep_msg" is its next VDAF message. This output message for each report in <del> AggregateContinueReq.prepare_shares is then sent to the leader in an </del>  AggregateContinueResp message, structured as follows: <del> The order of AggregateContinueResp.prepare_shares MUST match that of the PrepareStep values in "AggregateContinueReq.prepare_shares".  The </del>  helper's response to the leader is an HTTP status code 200 OK whose body is the AggregateContinueResp and media type is "message/dap- aggregate-continue-resp".  The helper then awaits the next message

Reviewer comments:
The prepare_shares fields were always of type PrepareStep. To match the convention used for most other field names, I change the name of the field to match its type. (There is no "PrepareShare" type.)

Revised text:
"(prep_state, prep_msg)". To carry out this step, for each PrepareStep in  <ins> AggregateContinueReq.prepare_steps received from the leader, the </ins> helper performs the following check to determine if the report share should continue being prepared: "prep_msg" is its next VDAF message. This output message for each report in  <ins> AggregateContinueReq.prepare_steps is then sent to the leader in an </ins> AggregateContinueResp message, structured as follows:  <ins> The order of AggregateContinueResp.prepare_steps MUST match that of the PrepareStep values in "AggregateContinueReq.prepare_steps".  The </ins> helper's response to the leader is an HTTP status code 200 OK whose body is the AggregateContinueResp and media type is "message/dap- aggregate-continue-resp".  The helper then awaits the next message
Original text:
The collector decrypts these aggregate shares using the opposite process.  Specifically, given an encrypted input share, denoted <del> "enc_share", for a given batch interval, denoted "batch_interval", </del>  decryption works as follows: where "sk" is the HPKE secret key, "task_id" is the task ID for the

Reviewer comments:
The Aggregate Share Encryption section still had a few references to "batch interval", but the encryption process now uses the "batch selector".

Revised text:
The collector decrypts these aggregate shares using the opposite process.  Specifically, given an encrypted input share, denoted  <ins> "enc_share", for a given batch selector, denoted "batch_selector", </ins> decryption works as follows: where "sk" is the HPKE secret key, "task_id" is the task ID for the
Original text:
too many times.  This is determined by the maximum number of times a batch can be queried, "max_batch_query_count".  Unless the query has been issued less than "max_batch_query_count" times, the Aggregator <del> MUST abort with error of type "batchLifetimeExceeded". </del>  Finally, the Aggregator checks that the batch does not contain a report that was included in any previous batch.  If this batch

Reviewer comments:
NAME please have another look
This seems useful, since it disambiguates "tasklifetime" and "batchlifetime". The former, as i understand it, is a timestamp; and the latter is a number of queries. cc/ NAME for thoughtful review here

Revised text:
too many times.  This is determined by the maximum number of times a batch can be queried, "max_batch_query_count".  Unless the query has been issued less than "max_batch_query_count" times, the Aggregator  <ins> MUST abort with error of type "batchQueriedTooManyTimes". </ins> Finally, the Aggregator checks that the batch does not contain a report that was included in any previous batch.  If this batch
Original text:
Let "[aggregator]" denote the helper's API endpoint.  The leader sends a POST request to "[aggregator]/aggregate" with its AggregateInitializeReq message as the payload.  The media type is <del> "message/dap-aggregate-initialize-req". </del>  4.4.1.2. is finished for the report share. The helper's response to the leader is an HTTP status code 200 OK <del> whose body is the AggregateInitializeResp and media type is "message/ dap-aggregate-initialize-resp". </del>  Upon receipt of a helper's AggregateInitializeResp message, the leader checks that the sequence of PrepareStep messages corresponds "AggregateContinueReq.task_id"'s parameters except its own, the leader sends a POST request to "[aggregator]/aggregate" with AggregateContinueReq as the payload and the media type set to <del> "message/dap-aggregate-continue-req". </del>  4.4.2.2. The order of AggregateContinueResp.prepare_steps MUST match that of the PrepareStep values in "AggregateContinueReq.prepare_steps".  The helper's response to the leader is an HTTP status code 200 OK whose <del> body is the AggregateContinueResp and media type is "message/dap- </del>  aggregate-continue-resp".  The helper then awaits the next message from the leader.

Reviewer comments:
In IANA all media types seem to be of "application" type instead of "message" type, this PR is to align the mismatch in the protocol description and adapt to the media types specified in IANA.
Nice catch!

Revised text:
Let "[aggregator]" denote the helper's API endpoint.  The leader sends a POST request to "[aggregator]/aggregate" with its AggregateInitializeReq message as the payload.  The media type is  <ins> "application/dap-aggregate-initialize-req". </ins> 4.4.1.2. is finished for the report share. The helper's response to the leader is an HTTP status code 200 OK  <ins> whose body is the AggregateInitializeResp and media type is "application/dap-aggregate-initialize-resp". </ins> Upon receipt of a helper's AggregateInitializeResp message, the leader checks that the sequence of PrepareStep messages corresponds "AggregateContinueReq.task_id"'s parameters except its own, the leader sends a POST request to "[aggregator]/aggregate" with AggregateContinueReq as the payload and the media type set to  <ins> "application/dap-aggregate-continue-req". </ins> 4.4.2.2. The order of AggregateContinueResp.prepare_steps MUST match that of the PrepareStep values in "AggregateContinueReq.prepare_steps".  The helper's response to the leader is an HTTP status code 200 OK whose  <ins> body is the AggregateContinueResp and media type is "application/dap- </ins> aggregate-continue-resp".  The helper then awaits the next message from the leader.
Original text:
where "pk" is the aggregator's public key; "server_role" is the Role of the intended recipient ("0x02" for the leader and "0x03" for the helper), "task_id" is the task ID, "metadata" is the report metadata, <del> and "input_share" is the Aggregator's input share. </del>  The order of the encrypted input shares appear MUST match the order of the task's "aggregator_endpoints".  That is, the first share the aggregator ("0x02" for the leader and "0x03" for the helper).  If decryption fails, the aggregator marks the report share as invalid with the error "hpke_decrypt_error".  Otherwise, it outputs the <del> resulting "input_share". </del>  4.4.1.4. where "pk" is the HPKE public key encoded by the collector's HPKE key, "server_role" is "0x02" for the leader and "0x03" for a helper.  The collector decrypts these aggregate shares using the opposite process.  Specifically, given an encrypted input share, denoted For fixed_size tasks, the batch selector is the batch ID assigned sent in the response.  4.5.5. Collect sub-protocol messages must be confidential and mutually

Reviewer comments:
I only tried searching for it, but all I found were places that it was used. This makes it difficult to determine which inputs are which. Which is the AAD, which is the plaintext, and which is the nonce? Please also describe the inputs in text. Note that at least one of the code blocks that use this is too wide at 76 characters.
SealBase() and SealOpen() refer to the "single-shot APIs" from URL I notice that we don't reference this explicitly. Would a reference suffice?

Revised text:
where "pk" is the aggregator's public key; "server_role" is the Role of the intended recipient ("0x02" for the leader and "0x03" for the helper), "task_id" is the task ID, "metadata" is the report metadata,  <ins> and "input_share" is the Aggregator's input share.  The "SealBase()" function is as specified in HPKE for the ciphersuite indicated by the HPKE configuration. </ins> The order of the encrypted input shares appear MUST match the order of the task's "aggregator_endpoints".  That is, the first share the aggregator ("0x02" for the leader and "0x03" for the helper).  If decryption fails, the aggregator marks the report share as invalid with the error "hpke_decrypt_error".  Otherwise, it outputs the  <ins> resulting "input_share".  The "OpenBase()" function is as specified in HPKE for the ciphersuite indicated by the HPKE configuration. </ins> 4.4.1.4. where "pk" is the HPKE public key encoded by the collector's HPKE key, "server_role" is "0x02" for the leader and "0x03" for a helper. <ins> The "SealBase()" function is as specified in HPKE for the ciphersuite indicated by the HPKE configuration. </ins> The collector decrypts these aggregate shares using the opposite process.  Specifically, given an encrypted input share, denoted For fixed_size tasks, the batch selector is the batch ID assigned sent in the response. <ins> The "OpenBase()" function is as specified in HPKE for the ciphersuite indicated by the HPKE configuration. </ins> 4.5.5. Collect sub-protocol messages must be confidential and mutually
Original text:
rejects a report for this reason, it SHOULD abort the upload protocol and alert the client with error "reportTooEarly". <del> If the Report contains an unrecognized extension, then the Leader MAY abort the upload request with error "unrecognizedMessage".  Note that this behavior is not mandatory because it requires the Leader to decrypt its input share. </del>  4.3.3. If so, then the Aggregator MUST mark the input share as invalid with error "unrecognized_message".  Finally, if an Aggregator cannot determine if an input share is <del> valid. it MUST mark the input share as invalid with error </del>  "report_dropped".  This situation arises if, for example, the Aggregator has evicted from long-term storage the state required to perform the check.  (See reducing-storage-requirements for

Reviewer comments:
Based on (merge that first).
As noted by NAME in URL, we need to decide how to handle duplicate extensions. One simple idea is to treat duplicate extensions as decoding failures, i.e., abort with "unrecognizedMessage".

Revised text:
rejects a report for this reason, it SHOULD abort the upload protocol and alert the client with error "reportTooEarly".  <ins> If the Report contains an unrecognized extension, or of two extensions have the same ExtensionType, then the Leader MAY abort the upload request with error "unrecognizedMessage".  Note that this behavior is not mandatory because it requires the Leader to decrypt its input share. </ins> 4.3.3. If so, then the Aggregator MUST mark the input share as invalid with error "unrecognized_message". <ins> Check if the ExtensionType of any two extensions in PlaintextInputShare is the same.  If so, then the Aggregator MUST mark the input share as invalid with error "unrecognized_message". </ins> Finally, if an Aggregator cannot determine if an input share is  <ins> valid, it MUST mark the input share as invalid with error </ins> "report_dropped".  This situation arises if, for example, the Aggregator has evicted from long-term storage the state required to perform the check.  (See reducing-storage-requirements for
Original text:
the aggregator ("0x02" for the leader and "0x03" for the helper). The "OpenBase()" function is as specified in HPKE for the ciphersuite indicated by the HPKE configuration.  If the leader supports multiple <del> HPKE configurations, it can use trial decryption with each configuration.  If decryption fails, the aggregator marks the report share as invalid with the error "hpke_decrypt_error".  Otherwise, the aggregator outputs the resulting PlaintextInputShare "plaintext_input_share". </del>  4.4.1.4.

Reviewer comments:
The server only supplies one config, so what happens if the server would support X22519 and P-256? We can fix this by having the server supply multiple configs.
This is probably a good idea. We could just change the payload of the response to to a sequence of messages rather than one.
As mentioned in URL, it might be useful to allow the client to advertise which algorithms it supports. This would increase the likelihood of successfully negotiating an a HPKE suite that both parties support.
NAME should we try to tackle this in DAP-03?
I'm game. One minor editorial nit.

Revised text:
the aggregator ("0x02" for the leader and "0x03" for the helper). The "OpenBase()" function is as specified in HPKE for the ciphersuite indicated by the HPKE configuration.  If the leader supports multiple  <ins> HPKE configurations with non-distinct configuration identifiers, it can use trial decryption with each configuration.  If decryption fails, the aggregator marks the report share as invalid with the error "hpke_decrypt_error".  Otherwise, the aggregator outputs the resulting PlaintextInputShare "plaintext_input_share". </ins> 4.4.1.4.