Draft: draft-ietf-ppm-dap

Commentary: Introduces the field to and discusses how aggregators should recover from round skew . 
 Nobody 's asked for any changes on this for about week , so let 's merge it !
Paragraph (version A):
The sequence of report shares to aggregate.  The
"encrypted_input_share" field of the report share is the
"HpkeCiphertext" whose index in "Report.encrypted_input_shares" is
equal to the index of the aggregator in the task's
"aggregator_endpoints" to which the AggregateInitializeReq is
being sent.
Paragraph (version A):
Let "{aggregator}" denote the helper's API endpoint.  The leader
sends a PUT request to "{aggregator}/tasks/{task-
id}/aggregation_jobs/{aggregation-job-id}" with its
"AggregationJobInitReq" message as the payload.  The media type is
"application/dap-aggregation-job-init-req".
Paragraph (version B):
The sequence of report shares to aggregate.  The
"encrypted_input_share" field of the report share is the
"HpkeCiphertext" whose index in "Report.encrypted_input_shares" is
equal to the index of the aggregator in the task's
"aggregator_endpoints" to which the "AggregationJobInitReq" is
being sent.
Paragraph (version B):
Let "{aggregator}" denote the Helper's API endpoint.  The Leader
sends a PUT request to "{aggregator}/tasks/{task-
id}/aggregation_jobs/{aggregation-job-id}" with its
"AggregationJobInitReq" message as the payload.  The media type is
"application/dap-aggregation-job-init-req".  The Leader's aggregation
job is now in round 0.
Paragraph (version B):
The Helper's response will be an "AggregationJobResp" message (see
aggregation-helper-init, which the Leader validates according to the
criteria in aggregation-job-validation.  If the message is valid, the
Leader moves to the aggregation job continuation phase with the
enclosed prepare steps, as described in agg-continue-flow.
Otherwise, the Leader should abandon the aggregation job entirely.
Paragraph (version A):
The message is a sequence of PrepareStep values, the order of which
matches that of the ReportShare values in
"AggregationJobInitReq.report_shares".  Each report that was marked
as invalid is assigned the "PrepareStepState" "failed".  Otherwise,
the "PrepareStep" is either marked as continued with the output
"prep_msg", or is marked as finished if the VDAF preparation process
is finished for the report share.
Paragraph (version A):
On success, the helper responds to the leader with HTTP status code
201 Created and a body consisting of the "AggregationJob", with media
type "application/dap-aggregation-job".
Paragraph (version A):
Upon receipt of a helper's "AggregationJob" message, the leader
checks that the sequence of "PrepareStep" messages corresponds to the
"ReportShare" sequence of the "AggregationJobInitReq".  If any
message appears out of order, is missing, has an unrecognized report
ID, or if two messages have the same report ID, then the leader MUST
abort with error "unrecognizedMessage".
Paragraph (version B):
The message is a sequence of PrepareStep values, the order of which
matches that of the ReportShare values in
"AggregationJobInitReq.report_shares".  Each report that was marked
as invalid is assigned the "PrepareStepState" "failed".  Otherwise,
the "PrepareStep" is either marked as continued with the output
"prep_msg", or is marked as finished if the VDAF preparation process
is finished for the report share.  The Helper's aggregation job is
now in round 0.
Paragraph (version B):
On success, the helper responds to the leader with HTTP status code
201 Created and a body consisting of the "AggregationJobResp", with
media type "application/dap-aggregation-job-resp".
Paragraph (version B):
During the aggregation job initialization (leader-init) or
continuation (agg-continue-flow) phases, the Leader will receive an
"AggregationJobResp" message from the Helper, which should be
validated before the Leader can move to the next phase of the
aggregation protocol.
Paragraph (version B):
The Helper's "prepare_steps" MUST include exactly the same report
IDs in the same order as either the "report_shares" in the
Leader's "AggregationJobInitReq" (if this is the first round of
continuation) or the "prepare_steps" in the Leader's
"AggregationJobContinueReq" (if this is a subsequent round).
Paragraph (version A):
If the error is "ReportShareError.report_too_early", then the
leader MAY try to re-send the report in a later
"AggregateInitializeReq".
Paragraph (version B):
If the error is "ReportShareError.report_too_early", then the
leader MAY try to re-send the report in a later
"AggregationJobInitReq".
Paragraph (version A):
where [leader_outbound, helper_outbound] is a vector of two elements.
If either of these operations fails, then the leader marks the report
as invalid.  Otherwise it interprets "out" as follows: If this is the
last round of the VDAF, then "out" is the aggregator's output share,
in which case the aggregator finishes and stores its output share for
further processing as described in collect-flow.  Otherwise, "out" is
the pair "(new_state, prep_msg)", where "new_state" is its updated
state and "prep_msg" is its next VDAF message (which will be
"leader_outbound" in the next round of continuation).  For the latter
case, the helper sets "prep_state" to "new_state".
Paragraph (version A):
The Leader then sends a POST request to the aggregation job URI used
during initialization (see leader-init).  The body is an
"AggregationJob" message (see aggregation-helper-init) containing the
"PrepareStep"s.  The media type is set to "application/dap-
aggregation-job".
Paragraph (version B):
where "[leader_outbound, helper_outbound]" is a vector of two
elements.  If either of these operations fails, then the leader marks
the report as invalid.  Otherwise it interprets "out" as follows: If
this is the last round of the VDAF, then "out" is the aggregator's
output share, in which case the aggregator finishes and stores its
output share for further processing as described in collect-flow.
Otherwise, "out" is the pair "(new_state, prep_msg)", where
"new_state" is its updated state and "prep_msg" is its next VDAF
message (which will be "leader_outbound" in the next round of
continuation).  For the latter case, the helper sets "prep_state" to
"new_state".
Paragraph (version B):
The "round" field is the round of VDAF preparation that the Leader
just reached and wants the Helper to advance to.
Paragraph (version B):
The "prepare_steps" field MUST be a sequence of "PrepareStep"s in the
"continued" state containing the corresponding "inbound" prepare
message.  The media type is set to "application/dap-aggregation-job-
continue-req".
Paragraph (version B):
The Helper's response will be an "AggregationJobResp" message (see
aggregation-helper-init), which the Leader validates according to the
criteria in aggregation-job-validation.  If the message is valid, the
Leader moves to the next round of continuation with the enclosed
prepare steps.  Otherwise, the Leader should abandon the aggregation
job entirely.
Paragraph (version A):
If this is the last round of VDAF preparation phase, then "out" is
the helper's output share, in which case the helper stores the
output share for future collection.
Paragraph (version A):
Otherwise, the helper interprets "out" as the tuple "(new_state,
prep_msg)", where "new_state" is its updated preparation state and
"prep_msg" is its next VDAF message.
Paragraph (version A):
If successful, the helper responds to the leader with HTTP status 200
OK, media type "application/dap-aggregation-job" and a body
consisting of an "AggregationJob" (see aggregation-helper-init)
compiled from the stepped "PrepareStep"s.  The order of the steps
MUST match that of the "PrepareStep" values in the leader's
"AggregationJob".  The helper then awaits the next message from the
leader.
Paragraph (version B):
An error, in which case the report share is marked as failed and
the Helper replies to the Leader with a "PrepareStep" in the
"failed" state.
Paragraph (version B):
An output share, in which case the Helper stores the output share
for future collection as described in collect-flow and replies to
the Leader with a "PrepareStep" in the "finished" state.
Paragraph (version B):
An updated VDAF state and preparation message, denoted
"(prep_state, prep_msg)", in which case the Helper replies to the
Leader with a "PrepareStep" in the "continued" state containing
"prep_msg".
Paragraph (version B):
After stepping each state, the Helper advances its aggregation job to
the Leader's "AggregationJobContinueReq.round".
Paragraph (version B):
If the "round" in the Leader's request is equal to the Helper's
current round (i.e., this is not the first time the Leader has sent
this request), then the Helper responds with the current round's
prepare messages.  The Helper SHOULD verify that the contents of the
"AggregationJobContinueReq" are identical to the previous message
(see aggregation-round-skew-recovery).
Paragraph (version B):
If the Leader's "round" is behind or more than one round ahead of the
Helper's current round, then the Helper MUST abort with an error of
type "roundMismatch".
Paragraph (version B):
If successful, the Helper responds to the Leader with HTTP status 200
OK, media type "application/dap-aggregation-job-resp" and a body
consisting of an "AggregationJobResp" (see aggregation-helper-init)
compiled from the stepped "PrepareStep"s.
Paragraph (version B):
"AggregationJobContinueReq" messages contain a "round" field,
allowing Aggregators to ensure that their peer is on an expected
round of the VDAF preparation algorithm.  In particular, the intent
is to allow recovery from a scenario where the Helper successfully
advances from round "n" to "n+1", but its "AggregationJobResp"
response to the Leader gets dropped due to something like a transient
network failure.  The Leader could then resend the request to have
the Helper advance to round "n+1" and the Helper should be able to
retransmit the "AggregationJobContinueReq" that was previously
dropped.  To make that kind of recovery possible, Aggregator
implementations SHOULD checkpoint the most recent round's preparation
state and messages to durable storage such that Leaders can re-
construct continuation requests and Helpers can re-construct
continuation responses as needed.
Paragraph (version B):
When implementing a round skew recovery strategy, Helpers SHOULD
ensure that the Leader's "AggregationJobContinueReq" message did not
change when it was re-sent (i.e., the two messages must contain the
same set of report IDs and prepare messages).  This prevents the
Leader from re-winding an aggregation job and re-running a round with
different parameters.
Paragraph (version B):
One way a Helper could address this would be to store a digest of the
Leader's request, indexed by aggregation job ID and round, and refuse
to service a request for a given aggregation job round unless it
matches the previously seen request (if any).
Paragraph (version A):
The opaque aggregation parameter for the VDAF being executed.
This value MUST match the same value in the the
"AggregateInitializeReq" message sent in at least one run of the
aggregate sub-protocol.  (See leader-init). and in "CollectReq"
(see collect-init).
Paragraph (version B):
The opaque aggregation parameter for the VDAF being executed.
This value MUST match the same value in the the
"AggregationJobInitReq" message sent in at least one run of the
aggregate sub-protocol.  (See leader-init). and in "CollectReq"
(see collect-init).
Paragraph (version A):
For an AggregateShareReq, the Helper checks that the batch ID
provided by the Leader corresponds to a batch ID used in a
previous AggregateInitializeReq for the task.
Paragraph (version B):
For an AggregateShareReq, the Helper checks that the batch ID
provided by the Leader corresponds to a batch ID used in a
previous "AggregationJobInitReq" for the task.