Ultra low-latency delivery of media is defined here as having a glass-to-glass delay target under one second. <del> This level of latency is sometimes necessary for real-time interactive applications such as video conferencing, operation of remote control devices or vehicles, or remotely hosted real-time gaming systems.  Some media content providers aim to achieve this level of latency for live media events involving sports, but have usually so far been unsuccessful over the internet at scale, though it is often possible within a localized environment with a controlled network, such as inside a specific venue connected to the event. Applications operating in this domain that encounter transient network events such as loss or reordering of some packets often experience user-visible artifacts in the media. </del>  Applications requiring ultra low latency for media delivery are usually tightly constrained on the available choices for media other protocols necessary for safe operation in browsers. Worth noting is that many applications for ultra low-latency delivery <del> do not need to scale to more than one user at a time, which </del>  simplifies many delivery considerations relative to other use cases. <del> For applications that need to replicate streams to multiple users, especially at a scale exceeding tens of users, this level of latency has historically been nearly impossible to achieve except with the use of multicast or planned provisioning in controlled networks. </del> Recommended reading for applications adopting an RTP-based approach also includes RFC7656.  For increasing the robustness of the playback 7. <del> This document requires no actions from IANA. </del>  8. <del> This document introduces no new security issues. </del>  9.  Thanks to Alexandre Gouaillard, Aaron Falk, Dave Oran, Glenn Deen, Kyle Rose, Leslie Daigle, Lucas Pardue, Mark Nottingham, Matt Stock, Mike English, Roni Even, and Will Law for very helpful suggestions, (If we missed your name, please let us know!) <del> 10.  References </del>  <del> 10.1.  URIs </del>  [1] https://github.com/ietf-wg-mops/draft-ietf-mops-streaming-opcons

Yes, lets add it. Well, I really don't want to imply that right provisioning requires QoS or at least some DSCP marking. Yes, to many, the answer could be just providing enough bandwidth for others, it could be a bit more complicated. If you have seen my recent ANRW talk, I refer to the "QoS" as the first camp (slide 5) and many efforts to date simply failed in that aspect. Paper: URL Slides: URL
I like this text. I have thoughts. Do we need a reference for "bufferbloat"? We haven't used that term in the document yet, and I agree with using it here. I note . I agree with "the right provisioning", but for someone not skilled in the art, that may be like "and then a miracle occurs", and I suspect a lot of people still assume "the right provisioning" means something like "the right bandwidth provisioning", which isn't what we mean at all, is it? ISTM that we might (1) mention DSCP, (2) mention URL as something to be aware of.

Ultra low-latency delivery of media is defined here as having a glass-to-glass delay target under one second.  <ins> Some media content providers aim to achieve this level of latency for live media events.  This introduces new challenges relative to less- restricted levels of latency requirements because this latency is the same scale as commonly observed end-to-end network latency variation (for example, due to effects such as bufferbloat, Wi-Fi error correction, or packet reordering).  These effects can make it difficult to achieve this level of latency for the general case, and may require tradeoffs in relatively frequent user-visible media artifacts.  However, for controlled environments or targeted networks that provide mitigations against such effects, this level of latency is potentially achievable with the right provisioning. </ins> Applications requiring ultra low latency for media delivery are usually tightly constrained on the available choices for media other protocols necessary for safe operation in browsers. Worth noting is that many applications for ultra low-latency delivery  <ins> do not need to scale to more than a few users at a time, which </ins> simplifies many delivery considerations relative to other use cases.  Recommended reading for applications adopting an RTP-based approach also includes RFC7656.  For increasing the robustness of the playback 7.  <ins> Editor's note: This section is to be kept in a living document where future references, links and/or updates to the existing references will be reflected.  That living document is likely to be an IETF- owned Wiki: https://tinyurl.com/streaming-opcons-reading 7.1. SVA Glossary: https://glossary.streamingvideoalliance.org/ Datazoom Video Player Data Dictionary: https://help.datazoom.io/hc/en-us/articles/360031323311 Datazoom Video Metrics Encyclopedia: https://help.datazoom.io/hc/ en-us/articles/360046177191 7.2. 7.2.1. The following papers describe how video is encoded, different video encoding standards and tradeoffs in selecting encoding parameters. Overview of the Versatile Video Coding (VVC) Standard and its Applications (https://ieeexplore.ieee.org/document/9503377) Video Compression - From Concepts to the H.264/AVC Standard (https://ieeexplore.ieee.org/document/1369695) Developments in International Video Coding Standardization After AVC, With an Overview of Versatile Video Coding (VVC) (https://ieeexplore.ieee.org/document/9328514) A Technical Overview of AV1 (https://ieeexplore.ieee.org/ document/9363937) CTU Depth Decision Algorithms for HEVC: A Survey (https://arxiv.org/abs/2104.08328) 7.2.2. The following papers summarize the methods for selecting packaging configurations such as the resolution-bitrate pairs, segment durations, use of constant vs. variable-duration segments, etc. Deep Reinforced Bitrate Ladders for Adaptive Video Streaming (https://dl.acm.org/doi/10.1145/3458306.3458873) Comparing Fixed and Variable Segment Durations for Adaptive Video Streaming: a Holistic Analysis (https://dl.acm.org/ doi/10.1145/3339825.3391858) 7.2.3. The following links describe some of the issues and solutions regarding the interconnecting of the content delivery networks. Open Caching: Open standards for Caching in ISP Networks: https://www.streamingvideoalliance.org/working-group/open-caching/ Netflix Open Connect: https://openconnect.netflix.com 7.2.4. The two surveys describe and compare different rate-adaptation algorithms in terms of different metrics like achieved bitrate/ quality, stall rate/duration, bitrate switching frequency, fairness, network utilization, etc. A Survey on Bitrate Adaptation Schemes for Streaming Media Over HTTP (https://ieeexplore.ieee.org/document/8424813) A Survey of Rate Adaptation Techniques for Dynamic Adaptive Streaming Over HTTP (https://ieeexplore.ieee.org/document/7884970) Low-Latency Live Streaming: The following papers describe the peculiarities of adaptive streaming in low-latency live streaming scenarios. Catching the Moment with LoL+ in Twitch-like Low-latency Live Streaming Platforms (https://ieeexplore.ieee.org/document/9429986) Data-driven Bandwidth Prediction Models and Automated Model Selection for Low Latency (https://ieeexplore.ieee.org/ document/9154522) Performance Analysis of ACTE: A Bandwidth Prediction Method for Low-latency Chunked Streaming (https://dl.acm.org/ doi/10.1145/3387921) Online Learning for Low-latency Adaptive Streaming (https://dl.acm.org/doi/10.1145/3339825.3397042) Tightrope Walking in Low-latency Live Streaming: Optimal Joint Adaptation of Video Rate and Playback Speed (https://dl.acm.org/ doi/10.1145/3458305.3463382) Content-aware Playback Speed Control for Low-latency Live Streaming of Sports (https://dl.acm.org/ doi/10.1145/3458305.3478437) 7.2.5. The following papers explain the benefits of server and network assistance in client-driven streaming systems.  There is also a good reference about how congestion affects video quality and how rate control works in streaming applications. Manus Manum Lavat: Media Clients and Servers Cooperating with Common Media Client/Server Data (https://dl.acm.org/ doi/10.1145/3472305.3472886) Common media client data (CMCD): initial findings (https://dl.acm.org/doi/10.1145/3458306.3461444) SDNDASH: Improving QoE of HTTP Adaptive Streaming Using Software Defined Networking (https://dl.acm.org/ doi/10.1145/2964284.2964332) Caching in HTTP Adaptive Streaming: Friend or Foe? (https://dl.acm.org/doi/10.1145/2578260.2578270) A Survey on Multi-Access Edge Computing Applied to Video Streaming: Some Research Issues and Challenges (https://ieeexplore.ieee.org/document/9374553) The Ultimate Guide to Internet Congestion Control (https://www.compiralabs.com/ultimate-guide-congestion-control) 7.2.6. The following papers describe various QoE metrics one can use in streaming applications. QoE Management of Multimedia Streaming Services in Future Networks: a Tutorial and Survey (https://ieeexplore.ieee.org/ document/8930519) A Survey on Quality of Experience of HTTP Adaptive Streaming (https://ieeexplore.ieee.org/document/6913491) QoE Modeling for HTTP Adaptive Video Streaming-A Survey and Open Challenges (https://ieeexplore.ieee.org/document/8666971) 7.2.7. The following papers explain the latest developments in the immersive media domain (for video and audio) and the developing standards for such media. A Survey on Adaptive 360o Video Streaming: Solutions, Challenges and Opportunities (https://ieeexplore.ieee.org/document/9133103) MPEG Immersive Video Coding Standard (https://ieeexplore.ieee.org/ document/9374648) Emerging MPEG Standards for Point Cloud Compression (https://ieeexplore.ieee.org/document/8571288) Compression of Sparse and Dense Dynamic Point Clouds--Methods and Standards (https://ieeexplore.ieee.org/document/9457097) MPEG Standards for Compressed Representation of Immersive Audio (https://ieeexplore.ieee.org/document/9444109) An Overview of Omnidirectional MediA Format (OMAF) (https://ieeexplore.ieee.org/document/9380215) From Capturing to Rendering: Volumetric Media Delivery with Six Degrees of Freedom (https://ieeexplore.ieee.org/document/9247522) 7.3. 5G-MA: https://www.5g-mag.com/reference-tools dash.js: http://reference.dashif.org/dash.js/latest/samples/ DASH-IF Conformance: https://conformance.dashif.org ExoPlayer: https://github.com/google/ExoPlayer FFmpeg: https://www.ffmpeg.org/ GPAC: https://gpac.wp.imt.fr/ hls.js: https://github.com/video-dev/hls.js OBS Studio: https://obsproject.com/ Shaka Player: https://github.com/google/shaka-player Shaka Packager: https://github.com/google/shaka-packager Traffic Control CDN: https://trafficcontrol.incubator.apache.org VideoLAN: https://www.videolan.org/projects/ video.js: https://github.com/videojs/video.js 7.4. ACM Mile High Video (MHV): https://mile-high.video/ ACM Multimedia Systems (MMSys): https://acmmmsys.org ACM Multimedia (MM): https://acmmm.org ACM NOSSDAV: https://www.nossdav.org/ ACM Packet Video: https://packet.video/ Demuxed and meetups: https://demuxed.com/ and https://demuxed.com/ events/ DVB World: https://www.dvbworld.org EBU BroadThinking: https://tech.ebu.ch/events/broadthinking2021 IBC Conference: https://show.ibc.org/conference/ibc-conference IEEE Int. Conf. on Multimedia and Expo (ICME) Media Web Symposium: https://www.fokus.fraunhofer.de/de/go/mws Live Video Stack: https://sh2021.livevideostack.com Picture Coding Symp.  (PCS) SCTE Expo: https://expo.scte.org/ 7.5. 3GPP SA4: https://www.3gpp.org/specifications-groups/sa-plenary/ sa4-codec 5G-MAG: https://www.5g-mag.com/ AOM: http://aomedia.org/ ATSC: https://www.atsc.org/ CTA WAVE: https://cta.tech/Resources/Standards/WAVE-Project DASH Industry Forum: https://dashif.org/ DVB: https://dvb.org/ HbbTV: https://www.hbbtv.org/ HESP Alliance: https://www.hespalliance.org/ IAB: https://www.iab.com/ MPEG: https://www.mpegstandards.org/ Streaming Video Alliance: https://www.streamingvideoalliance.org/ SCTE: https://www.scte.org/ SMPTE: https://www.smpte.org/ SRT Alliance: https://www.srtalliance.org/ Video Services Forum: https://vsf.tv/ VQEG: https://www.its.bldrdoc.gov/vqeg/vqeg-home.aspx W3C: https://www.w3.org/ 7.6. 7.6.1. 5G new radio and systems technologies provide new functionalities for video distribution. 5G targets not only smartphones, but also new devices such as augmented reality glasses or automotive receivers. Higher bandwidth, lower latencies, edge and cloud computing functionalities, service-based architectures, low power consumption, broadcast/multicast functionalities and other network functions come hand in hand with new media formats and processing capabilities promising better and more consistent quality for traditional video streaming services as well as enabling new experiences such as immersive media and augmented realities. 5G Multimedia Standardization (https://www.riverpublishers.com/ journal_read_html_article.php?j=JICTS/6/1/8) 7.6.2. Ads can be inserted at different stages in the streaming workflow, on the server side or client side.  The DASH-IF guidelines detail server-side ad-insertion with period replacements based on manipulating the manifest.  HLS interstitials provide a similar approach.  The idea is that the manifest can be changed and point to a sub-playlist of segments, possibly located on a different location. This approach results in efficient resource usage in the network, as duplicate caching is avoided, but some intelligence at the player is needed to deal with content transitions (e.g., codec changes, timeline gaps, etc.).  Player support for such content is gradually maturing.  Other important technologies for ad insertion include signalling of ads and breaks that is still typically based on SCTE-35 for HLS and SCTE-214 for DASH.  Such signals provide useful information for scheduling the ads and contacting ad servers.  The usage of SCTE-35 for ad insertion is popular in the broadcast industry, while the exact usage in the OTT space is still being discussed in SCTE.  Another important technology is identification of ads, such as based on ad-id or other commercial entities that provide such services.  The identification of the ad in a manifest or stream is usually standardized by SMPTE.  Other key technologies for ad insertion include tracking of viewer impressions, usually based on Video Ad Serving Template (VAST) defined by IAB. DASH-IF Ad Insertion Guidelines: https://dashif.org/docs/CR-Ad- Insertion-r7.pdf SCTE-214-1: https://www.scte.org/standards-development/library/ standards-catalog/ansiscte-214-1-2016/ RP 2092-1:2015 - SMPTE Recommended Practice - Advertising Digital Identifier (Ad-ID) Representations: https://ieeexplore.ieee.org/ document/7291518 IAB Tech Lab Digital Video Studio: https://iabtechlab.com/audio- video/tech-lab-digital-video-suite/ 7.6.3. There are different contribution and ingest specifications dealing with different use cases.  A common case is contribution that previously happened over satellite to a broadcast or streaming headend.  RIST and SRT are examples of such contribution protocols. Within a streaming headend the encoder and packager/CDN may have an ingest/contribution interface as well.  This is specified by the DASH-IF Ingest. DASH-IF Ingest: https://github.com/Dash-Industry-Forum/Ingest RIST: https://www.rist.tv/ SRT: https://github.com/Haivision/srt 7.6.4. Practical streaming headends need redundant encoders and packagers to operate without glitches and blackouts.  The redundant operation requires synchronization between two or more encoders and also between two or more packagers that possibly handle different inputs and outputs, generating compatible inter-changeable output representations.  This problem is important for anyone developing a streaming headend at scale, and the synchronization problem is currently under discussion in the wider community.  Follow the developments at: https://sites.google.com/view/encodersyncworkshop/ home 7.6.5. WebRTC is increasingly being used for streaming of time-sensitive content such as live sporting events.  Innovations in cloud computing allow implementers to efficiently scale delivery of content using WebRTC.  Support for WebRTC communication is available on all modern web browsers and is available on native clients for all major platforms. DASH-IF WebRTC Discussions: https://dashif.org/webRTC/ Overview of WebRTC: https://webrtc.org/ </ins> 8.  <ins> This document requires no actions from IANA. </ins> 9. <ins> This document introduces no new security issues. 10. </ins> Thanks to Alexandre Gouaillard, Aaron Falk, Dave Oran, Glenn Deen, Kyle Rose, Leslie Daigle, Lucas Pardue, Mark Nottingham, Matt Stock, Mike English, Roni Even, and Will Law for very helpful suggestions, (If we missed your name, please let us know!)  <ins> 11.  References </ins>  <ins> 11.1.  URIs </ins> [1] https://github.com/ietf-wg-mops/draft-ietf-mops-streaming-opcons


acknowledged at the connection level with a DATA_ACK.  Further details are in sec_close. <del> There is an additional method of connecton closure, referred to as </del>  "Fast Close", which is analogous to closing a single-path TCP connection with a RST signal.  The MP_FASTCLOSE signal is used to indicate to the peer that the connection will be abruptly closed and the MPTCP connection would continue to provide a regular TCP service. Since key generation is implementation-specific, there is no <del> requirement that they be simply random numbers.  An implemention is </del>  free to exchange cryptographic material out-of-band and generate these keys from this, in order to provide additional mechanisms by which to verify the identity of the communicating entities.  For numbers is not required, then an implementation MAY include just the lower 32 bits of the data sequence number in the data sequence mapping and/or Data ACK as an optimization, and an implementation can <del> make this choice independently for each packet.  An implementaton </del>  MUST be able to receive and process both 64-bit or 32-bit sequence number values, but it is not required that an implementation is able to send both. can be altered by a middlebox without affecting MPTCP, as the data stream is equivalent to a regular, legacy TCP session.  The MP_FAIL signal affects only one direction of traffic.  It is not mandatory <del> for the reciever of an MP_FAIL to also respond with an MP_FAIL, since </del>  the paths may only be damaged in one direction.  However, implementations MAY choose to send a MP_FAIL in the reverse direction and entirely revert to a regular TCP session. that can be applied here.  Furthermore, an on-path attacker would have access to the raw data, negating any other TCP-level security mechanisms.  Also a change from RFC6824 has removed the subflow <del> identifer from the MP_PRIO option (sec_policy), to remove the </del>  theoretical attack where a subflow could be placed in "backup" mode by an attacker.

Reading through the draft I noticed a few typos so I wanted to propose a small change to fix.

acknowledged at the connection level with a DATA_ACK.  Further details are in sec_close.  <ins> There is an additional method of connection closure, referred to as </ins> "Fast Close", which is analogous to closing a single-path TCP connection with a RST signal.  The MP_FASTCLOSE signal is used to indicate to the peer that the connection will be abruptly closed and the MPTCP connection would continue to provide a regular TCP service. Since key generation is implementation-specific, there is no  <ins> requirement that they be simply random numbers.  An implementation is </ins> free to exchange cryptographic material out-of-band and generate these keys from this, in order to provide additional mechanisms by which to verify the identity of the communicating entities.  For numbers is not required, then an implementation MAY include just the lower 32 bits of the data sequence number in the data sequence mapping and/or Data ACK as an optimization, and an implementation can  <ins> make this choice independently for each packet.  An implementation </ins> MUST be able to receive and process both 64-bit or 32-bit sequence number values, but it is not required that an implementation is able to send both. can be altered by a middlebox without affecting MPTCP, as the data stream is equivalent to a regular, legacy TCP session.  The MP_FAIL signal affects only one direction of traffic.  It is not mandatory  <ins> for the receiver of an MP_FAIL to also respond with an MP_FAIL, since </ins> the paths may only be damaged in one direction.  However, implementations MAY choose to send a MP_FAIL in the reverse direction and entirely revert to a regular TCP session. that can be applied here.  Furthermore, an on-path attacker would have access to the raw data, negating any other TCP-level security mechanisms.  Also a change from RFC6824 has removed the subflow  <ins> identifier from the MP_PRIO option (sec_policy), to remove the </ins> theoretical attack where a subflow could be placed in "backup" mode by an attacker.


"helper_url": The helper's endpoint URL. "collector_config": The HPKE configuration of the collector <del> (described in key-config).  [OPEN ISSUE: Maybe the collector's HPKE config should be carried by the collect request?] </del>  "batch_size": The batch size, i.e., the minimum number of reports that are aggregated into an output. same PPM task.  [[OPEN ISSUE: And the same batch, right?]] Let "[helper]" denote "Param.helper_url", where "Param" is the PPM <del> parameters structure associated with"AggregateReq.task.id".  The </del>  leader sends a POST request to "[helper]/aggregate" with the following message: out-of-order sub-requests by ignoring any sub-request that does not follow the previous one (See anti-replay.) <del> The response consists of the helper's updated state and a sequence of </del>  , where the i-th sub-response corresponds to the i-th sub-request for each i.  The structure of each sub-response is specific to the PPM public key: where "pk" is the HPKE public key encoded by the collector's HPKE key <del> configuration and "output_share" is its serialized output share. This encryption prevents the leader from learning the actual result, as it only has its own share and not the helper's share, which is encrypted for the collector. </del>  <del> It responds with the following message: </del>  The leader uses the helper's output share response to respond to the collector's collect request (see pa-collect). leader may already have computed the results and can return them immediately.  In either case, once the leader has obtained the helper's encrypted output share for the batch, it responds to the <del> collector's request with the CollectResp message: </del>  [[OPEN ISSUE: What happens if this all takes a really long time.]] [TODO: Decide if and how the collector's request is authenticated.] <del> [[TODO: Define the fields]] </del>  <del> [[OPEN ISSUE: change this to just have a list of shares </del>  https://github.com/abetterinternet/prio-documents/issues/112]] [OPEN ISSUE: Describe how intra-protocol errors yield collect errors participants know that at least one aggregator is defective, and it may be possible to identify the defector (i.e., if a majority of runs agree, and a single aggregator appears in every run that disagrees). <del> See #22 [1] for discussion. </del>  6.7. 10.1.  URIs <del> [1] https://github.com/abetterinternet/prio-documents/issues/22 </del>

Removes some TODOs, clarifies why we have HpkeConfig collectorconfigstruct PPMParamUrl collectorurl, and amends collect protocol so that leader output shares are encrypted to collector's HPKE config. Several response structures no longer have or fields if the appropriate task (and hence and hence ) can be inferred from the request.
I want to address in this PR as well, so downgrading to draft for now.
NAME NAME This is ready; please review at your convenience.
Thank you for the review, NAME This picked up some merge conflicts so I will wait for all of NAME changes to land and then rebase.
You should be able to rebase now. I am mostly done.
Rebased, reordered, ready for re-review
This seems to be a dupe fo -- can we close?
Per discussion in the call today, I think this issue is about updating the various PDU definitions to allow for multiple helpers. For instance, currently has fields and , but it should instead have . is the more complex problem of extending the protocol to handle >1 helper, which probably involves more rounds of communication. I'm going to grab this issue because I ran into which I think is related, so I'll fix both.
Right now only the helper's output share for a batch of reports is encrypted to the collector. We previously agreed that all input shares should be encrypted to the corresponding aggregator (URL). It makes sense to encrypt the leader's output share for the same reasons we discussed there. Along the way, the message format should be made to accommodate multiple helpers, as we did for the input shares.
Fixed in . Making "the message format [...] accommodate multiple helpers" is specifically tracked in and resolved by .

"helper_url": The helper's endpoint URL. "collector_config": The HPKE configuration of the collector  <ins> (described in key-config).  Putting the collector's HPKE configuration directly in "struct PPMParam" absolves collectors of the burden of operating an HTTP server.  See #102 [1] for discussion. </ins> "batch_size": The batch size, i.e., the minimum number of reports that are aggregated into an output. same PPM task.  [[OPEN ISSUE: And the same batch, right?]] Let "[helper]" denote "Param.helper_url", where "Param" is the PPM  <ins> parameters structure associated with "AggregateReq.task.id".  The </ins> leader sends a POST request to "[helper]/aggregate" with the following message: out-of-order sub-requests by ignoring any sub-request that does not follow the previous one (See anti-replay.)  <ins> The response is an HTTP 200 OK with a body consisting of the helper's updated state and a sequence of </ins> , where the i-th sub-response corresponds to the i-th sub-request for each i.  The structure of each sub-response is specific to the PPM public key: where "pk" is the HPKE public key encoded by the collector's HPKE key  <ins> configuration, "server_role" is the role of the server ("0x01" for the leader and "0x00" for the helper) and "output_share" is the serialized "OutputShare".  "task_id", "batch_start" and "batch_end" are obtained from the "OutputShareReq".  This encryption prevents the leader from learning the actual result, as it only has its own share and not the helper's share, which is encrypted for the collector. The helper response to the collector with HTTP status 200 OK and a body consisting of the following structure: </ins>  <ins> "collector_hpke_config_id" is "collector_config.id" from the "Param" corresponding to "CollectReq.task_id". "enc" is the encapsulated HPKE context, used by the collector to decrypt the output share. "encrypted_output_share" is an encrypted "OutputShare", whose structure is given below. </ins> The leader uses the helper's output share response to respond to the collector's collect request (see pa-collect). leader may already have computed the results and can return them immediately.  In either case, once the leader has obtained the helper's encrypted output share for the batch, it responds to the  <ins> collector's request with HTTP status 200 and a body consisting of a CollectResp message: </ins> [[OPEN ISSUE: What happens if this all takes a really long time.]] [TODO: Decide if and how the collector's request is authenticated.]  <ins> "leader_share" and "helper_share" are "EncryptedOutputShare"s as described in output-share-request, except that the "task_id", "batch_start", and "batch_end" used to encrypt the "OutputShare" are obtained from the "CollectReq". </ins>  <ins> [[OPEN ISSUE: change CollectResp to just have a list of shares </ins> https://github.com/abetterinternet/prio-documents/issues/112]] [OPEN ISSUE: Describe how intra-protocol errors yield collect errors participants know that at least one aggregator is defective, and it may be possible to identify the defector (i.e., if a majority of runs agree, and a single aggregator appears in every run that disagrees).  <ins> See #22 [2] for discussion. </ins> 6.7. 10.1.  URIs  <ins> [1] https://github.com/abetterinternet/prio-documents/issues/102 [2] https://github.com/abetterinternet/prio-documents/issues/22 </ins>


4.2.3. <del> Each PAUploadReq carries a list of extensions that clients may use to </del>  convey additional, authenticated information in the report.  Each extension is a tag-length encoded value of the following form:

NAME I'm struggling with Github here and can't figure out what change you want.
Thanks.
Disregard, I found it and pushed myself.

4.2.3.  <ins> Each UploadReq carries a list of extensions that clients may use to </ins> convey additional, authenticated information in the report.  Each extension is a tag-length encoded value of the following form:


3.1. <del> [[OPEN ISSUE: Align this with best practice, cribbing from ACME.]] Errors SHOULD be reported in PPM at the HTTP layer, using an HTTP response code of 400.  The response payload is a Alert structure: where "task_id" is the associated PPM task (this value is always known, see task-configuration) and "payload" contains a string indicating the error that occurred.  When sent by an aggregator in response to an HTTP request, the response status is 400.  When sent in a request to an aggregator, the URL is always "[aggregator]/error", where "[aggregator]" is the URL of the aggregator endpoint. [[OPEN ISSUE: What is the URL? https://github.com/abetterinternet/ prio-documents/issues/108]] The following list defines a set of common errors. The message type for the payload of each request and response is unique for a given URL.  If ever a client, aggregator, or collector receives a request or response to a request with a malformed payload, then the receiver aborts and alerts the peer with "unrecognized message". Each POST request to an aggregator contains a "TaskID".  If the aggregator does not recognize the task, i.e., it can't find a "Param" for which the derived task ID matches the "TaskID", then it aborts and alerts the peer with "unrecognized task". [[TODO: Add error table here.]] </del>  This document uses the verbs "abort" and "alert with "[some error message]"" to describe how protocol participants react to various [TODO: define how we want to structure this registry when the time comes]  8. The text in message-transport is based extensively on

ACME has a pretty well defined error structure, including RFC 8707 problem documents. We should look at adopting that.
Fixed by

3.1.  <ins> Errors can be reported in PPM both at the HTTP layer and within challenge objects as defined in iana-considerations.  PPM servers can return responses with an HTTP error response code (4XX or 5XX).  For example, if the client submits a request using a method not allowed in this document, then the server MAY return status code 405 (Method Not Allowed). When the server responds with an error status, it SHOULD provide additional information using a problem document RFC7807.  To facilitate automatic response to errors, this document defines the following standard tokens for use in the "type" field (within the PPM URN namespace "urn:ietf:ppm:acme:error:"): This list is not exhaustive.  The server MAY return errors set to a URI other than those defined above.  Servers MUST NOT use the PPM URN namespace for errors not listed in the appropriate IANA registry (see ppm-urn-space).  Clients SHOULD display the "detail" field of all errors.  The "instance" value MUST be the endpoint to which the request was targeted.  The problem document MUST also include a "taskid" member which contains the associated PPM task ID (this value is always known, see task-configuration). In the remainder of this document, we use the tokens in the table above to refer to error types, rather than the full URNs.  For example, an "error of type 'unrecognizedMessage'" refers to an error document with "type" value "urn:ietf:params:acme:error:unrecognizedMessage". </ins> This document uses the verbs "abort" and "alert with "[some error message]"" to describe how protocol participants react to various [TODO: define how we want to structure this registry when the time comes] <ins> 7.2. The following value [will be/has been] registered in the "IETF URN Sub- namespace for Registered Protocol Parameter Identifiers" registry, following the template in RFC3553: Initial contents: The types and descriptions in the table in errors above, with the Reference field set to point to this specification. </ins> 8. The text in message-transport is based extensively on


BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. <del> [[TODO: Clean up this glossary]] </del> The following terms are used: <del> Aggregation function: The function computed over the users' inputs. Aggregator: An endpoint that runs the input-validation protocol and accumulates input shares. Batch: A set of reports that are aggregated into an output. Batch size: The minimum number of reports in a batch. Batch window: The minimum time difference between the oldest and newest report in a batch (in seconds). Client: The endpoint from which a user sends data to be aggregated, e.g., a web browser. Collector: The endpoint that receives the output of the aggregation function.  It also specifies the parameters of the protocol. False input: An input that is valid, but incorrect.  For example, if the data being gathered is whether or not users have clicked on a particular button, a client could report clicks when none occurred. Input: The measurement (or measurements) emitted by a client, before any encryption or secret sharing scheme is applied. Input share: one of the shares output by feeding an input into a secret sharing scheme.  Each share is to be transmitted to one of the participating aggregators. Input validation protocol: The protocol executed by the client and aggregators in order to validate the client's input without leaking its value to the aggregators. Invalid input: An input for which the input validation protocol fails.  For example, if the input is meant to be a bit vectors, then "[2, 1, 0]" is invalid. Measurement: A single value (e.g., a count) being reported by a client.  Multiple measurements may be grouped into a single protocol input. Leader: A distinguished aggregator that coordinates input validation and data collection. Output: A reduction over the inputs, for instance a statistical aggregation, which is of interest to a collector.  This is the output of the aggregation function. Output share: The share of an output emitted by an aggregator. Output shares can be reassembled by the leader into the final output. Prio v1: Mozilla's Origin Telemetry project [1]. Prio v2: Contact tracing project by Apple, Google, and ISRG. Proof: A value generated by the client and used by the aggregators to verify the client's input. Proof share: A share of a proof, used by an aggregator during the input-validation protocol. Report: Uploaded to the leader from the client.  A report contains the secret-shared and encrypted input and proof. Server: An aggregator or collector. </del> This document uses the protocol definition language of RFC8446. 2. participants know that at least one aggregator is defective, and it may be possible to identify the defector (i.e., if a majority of runs agree, and a single aggregator appears in every run that disagrees). <del> See #22 [2] for discussion. </del>  6.7. 13.1.  URIs <del> [1] https://blog.mozilla.org/security/2019/06/06/next-steps-in- privacy-preserving-telemetry-with-prio/ [2] https://github.com/abetterinternet/prio-documents/issues/22 </del>

This is just converting to defn. list format. I'm going to submit a separate PR to clean up the contents.

BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here.  The following terms are used:  This document uses the protocol definition language of RFC8446. 2. participants know that at least one aggregator is defective, and it may be possible to identify the defector (i.e., if a majority of runs agree, and a single aggregator appears in every run that disagrees).  <ins> See #22 [1] for discussion. </ins> 6.7. 13.1.  URIs  <ins> [1] https://github.com/abetterinternet/prio-documents/issues/22 </ins>


by refusing to emit output shares. Input validity proof forging.  Any aggregator can collude with a <del> malicious client to craft a proof share that will fool honest </del>  aggregators into accepting invalid input. 6.1.2.3. aggregating invalid inputs. This capability is no stronger than any aggregator's ability to <del> forge validity proof shares in collusion with a malicious client. </del>  Relaying messages between aggregators.  The leader can compromise availability by dropping messages. [TODO: Decide how to provide mutual authentication in leader-to- helper and collector-to-leader connections.  One option is to use client certificates for TLS; another is to have the leader sign its <del> messages directly, as in Prio v2.  For collector-to-leader connections, we may just have this be up to deployment.  (For instance, the collector might authenticate themselves by logging into a website that has some trust relationship with the leader.)] </del>  11. faster implementations?]] The table below lists parameters that meet these criteria at various <del> levels of security.  (Note that #1 is the field used in "Prio v2".) The "size" column indicates the number of bits required to represent elements of the field. </del>  [TODO: Choose new parameters for 2, 3, and 5 so that p is as close to 2^size as possible without going over. (4 is already close enough; 1

Remove terms which are infrequently used (and in a few cases, remove the unnecessary references) Clean up a few terms which appear to be defined incorrectly.

by refusing to emit output shares. Input validity proof forging.  Any aggregator can collude with a  <ins> malicious client to craft a proof that will fool honest </ins> aggregators into accepting invalid input. 6.1.2.3. aggregating invalid inputs. This capability is no stronger than any aggregator's ability to  <ins> forge validity proof in collusion with a malicious client. </ins> Relaying messages between aggregators.  The leader can compromise availability by dropping messages. [TODO: Decide how to provide mutual authentication in leader-to- helper and collector-to-leader connections.  One option is to use client certificates for TLS; another is to have the leader sign its  <ins> messages directly.  For collector-to-leader connections, we may just have this be up to deployment.  (For instance, the collector might authenticate themselves by logging into a website that has some trust relationship with the leader.)] </ins> 11. faster implementations?]] The table below lists parameters that meet these criteria at various  <ins> levels of security.  The "size" column indicates the number of bits required to represent elements of the field. </ins> [TODO: Choose new parameters for 2, 3, and 5 so that p is as close to 2^size as possible without going over. (4 is already close enough; 1


Each endpoint in the system must agree on the configuration for each task, which is defined using the Param structure: <del> "nonce": A unique sequence of bytes used to ensure that two </del>  otherwise identical "Param" instances will have distinct "TaskID"s.  It is RECOMMENDED that this be set to a random 16-byte string derived from a cryptographically secure pseudorandom number

Apply to clean up some other whitespace stuff, too.
Because you'll also want a "jitter buffer" on the receiver side and that means something different. Instead of having a random value, why not just have time be to a nanosecond clock and then lexically sort between collisions?
Which will also help one remove duplicates.
Yeah, this is a bad name :)

Each endpoint in the system must agree on the configuration for each task, which is defined using the Param structure:  <ins> "uuid": A unique sequence of bytes used to ensure that two </ins> otherwise identical "Param" instances will have distinct "TaskID"s.  It is RECOMMENDED that this be set to a random 16-byte string derived from a cryptographically secure pseudorandom number


7.1.  This document requests creation of a new registry for extensions to the Upload protocol.  This registry should contain the following columns: [TODO: define how we want to structure this registry when the time comes] <del> 7.2. </del>  The following value [will be/has been] registered in the "IETF URN Sub- namespace for Registered Protocol Parameter Identifiers"

NAME -- is it better practice to define media types per protocol message, or to define a single media type for all protocol messages?
Generally, if they're different formats -- e.g., they have different schema, or just different syntax -- they need different media types (or an explicitly generic one like ). If it's one format that has different uses, you can give it a single media type and then switch contexts based upon internal flags. The real question, though, is whether you have any potential for use cases where it's important for generic software that's handling these messages to do different things based upon the media type.
I don't think there'd ever be generic software using these types (beyond the HpkeConfig?). Most messages are meant to be consumed by PPM and PPM alone. I moved protocol messages to the "message" registry space and kept the HpkeConfig in the application type space, and also left all intended usage fields as COMMON. I also added an open issue to have someone more familiar with these registries give these allocation requests a review. NAME this should be good to go based on the above.
Currently, DAP uses the following media types (defined in section 7.1): Note that the first uses the top-level type, while the remainder use the top-level type. For consistency, I suggest we use the same top-level type for all messages. Which type is more appropriate? Per : is for "either uninterpreted binary data or information to be processed by an application" is for "an encapsulated message"; all of the motivating examples (see section 5.2) are around encaspulating one message format inside another, or fragmenting a message into multiple chunks. provides further guidance that "multipart and message are composite types; that is, they provide a means of encapsulating zero or more objects, each one a separate media type." Given that DAP messages are not a method of encapsulating a message of a different type, I suggest that is the more appropriate top-level type to use. This is also supported by the rather large number of media types vs the relatively tiny number of media types in . (this issue fell out of discussion on URL)
Agreed, seems better.
The types were chosen in PR on a tentative basis, and marked with "OPEN ISSUE: Solicit review of these allocations from domain experts." Based on the encapsulation reasoning, I agree that be most appropriate for our media types.
LGTM except for the hed.

7.1. <ins> This specification defines the following protocol messages, along with their corresponding media types types: HpkeConfig task-configuration: "application/ppm-hpke-config" Report upload-request: "message/ppm-report" AggregateReq aggregate-request: "message/ppm-aggregate-req" AggregateResp aggregate-request: "message/ppm-aggregate-resp" OutputShareReq output-share-request: "message/ppm-output-share- req" OutputShareResp output-share-request: "message/ppm-output-share- resp" CollectReq pa-collect: "message/ppm-collect-req" CollectResp pa-collect: "message/ppm-collect-req" The definition for each media type is in the following subsections. Protocol message format evolution is supported through the definition of new formats that are identified by new media types. IANA [shall update / has updated] the "Media Types" registry at https://www.iana.org/assignments/media-types with the registration information in this section for all media types listed above. [OPEN ISSUE: Solicit review of these allocations from domain experts.] 7.1.1. 7.1.2. 7.1.3. 7.1.4. 7.1.5. 7.1.6. 7.1.7. 7.1.8. 7.2. </ins> This document requests creation of a new registry for extensions to the Upload protocol.  This registry should contain the following columns: [TODO: define how we want to structure this registry when the time comes]  <ins> 7.3. </ins> The following value [will be/has been] registered in the "IETF URN Sub- namespace for Registered Protocol Parameter Identifiers"


is derived from the PPM parameters as: <del> Where param is just the serialization of Param. </del>  4.2. Config.  The aggregator responds to well-formed requests with status 200 and an "HpkeConfig" value: <del> [TODO: Decide whether to use the same config structure as OHTTP/ECH. This would add support for multiple cipher suites.] </del>  The client issues a key configuration request to "Param.leader_url" and "Param.helper_url".  It aborts if any of the following happen for the key config specifies a KEM, KDF, or AEAD algorithm the client doesn't recognize.  Clients SHOULD follow the usual HTTP caching RFC7234 semantics for <del> key configurations.  Aggregators SHOULD favor long cache lifetimes to avoid frequent cache revalidation. </del>  Note: Long cache lifetimes may result in clients using stale HPKE keys; aggregators SHOULD continue to accept reports with old keys for <del> a reasonable period after key changes in order to avoid rejecting reports.  [[OPEN ISSUE: https://github.com/abetterinternet/prio- documents/issues/106]] </del>  4.2.2. value in more than one report if the leader responds with status 200 and an empty body.  4.2.3. Each UploadReq carries a list of extensions that clients may use to

It seems silly to have clients revalidating the HPKE key for each request, so we probably want some kind of caching. I'm not sure HTTP Caching is quite what we want, but something... NAME NAME recommendations?
I'm going to need a little more context to provide good advice. If we don't need key consistency (it doesn't appear so) and you only need correctness, then the client should just be able to talk directly to the collector and get keys periodically. HTTP caching works fine for that purpose. This would also need a rejection message so that the collector (or the leader on their behalf - the leader is more likely to learn about bad key identifiers before clients) can reject an out-of-date key in case the cache needs to be invalidated.
We do not need key consistency. The rejection message seems like a good idea.

is derived from the PPM parameters as:  <ins> Where param is the serialization of Param. </ins> 4.2. Config.  The aggregator responds to well-formed requests with status 200 and an "HpkeConfig" value:  <ins> [OPEN ISSUE: Decide whether to expand the width of the id, or support multiple cipher suites (a la OHTTP/ECH).] </ins> The client issues a key configuration request to "Param.leader_url" and "Param.helper_url".  It aborts if any of the following happen for the key config specifies a KEM, KDF, or AEAD algorithm the client doesn't recognize. <ins> Aggregators SHOULD use HTTP caching to permit client-side caching of this resource RFC5861.  Aggregators SHOULD favor long cache lifetimes to avoid frequent cache revalidation, e.g., on the order of days. Aggregators can control this cached lifetime with the Cache-Control header, as follows: </ins> Clients SHOULD follow the usual HTTP caching RFC7234 semantics for  <ins> key configurations. </ins> Note: Long cache lifetimes may result in clients using stale HPKE keys; aggregators SHOULD continue to accept reports with old keys for  <ins> at least twice the cache lifetime in order to avoid rejecting reports. </ins> 4.2.2. value in more than one report if the leader responds with status 200 and an empty body. <ins> The leader responds to requests with out-of-date "HpkeConfig.id" values, indicated by "EncryptedInputShare.config_id", with status 400 and an error of type 'outdatedConfig'.  Clients SHOULD invalidate any cached aggregator "HpkeConfig" and retry with a freshly generated Report.  If this retried report does not succeed, clients MUST abort and discontinue retrying. </ins> 4.2.3. Each UploadReq carries a list of extensions that clients may use to


Privacy Preserving Measurement <del> draft-pda-protocol-latest </del>  Abstract

The draft name still has the acronym "pda" in it. Let's kill this for good.
You also need to fix URL I believe
nice catch, NAME

Privacy Preserving Measurement  <ins> draft-ppm-protocol-latest </ins> Abstract


malicious client to craft a proof that will fool honest aggregators into accepting invalid input.  6.1.2.3. The linear secret sharing scheme employed by the client ensures shares reveal nothing about either the inputs or the participating clients.  6.1.3. The leader is also an aggregator, and so all the assets, capabilities

Aggregators merely counting the number of input shares could compromise user privacy in some circumstances (namely, it can break differential privacy if the number of records per user is not constant). This attack only applies to aggregators who can count the number of shares, so any protection still holds on the collector side. To address this attack, there are two possible mitigations, which both involve adding noise to the total number of input shares. This should be possible to do with "null" shares that don't affect aggregate output (i.e. inserting 0 into sums).
Specifically, this is about being able to count the number of contributions from an individual client, right? If so, this would also be mitigated by putting an anonymizing proxy between clients and the leader which would scrub identifying information from reports.
An anonymizing proxy mitigates attacks but not in the worst case. I didn't mention in the PR (I could if it is necessary), but the worst case attack involves the attackers having some side knowledge (e.g. via client collusion) such that if N reports arrive, then Tim did not contribute to this batch, and if N+1 reports arrive, then Tim did contribute to the batch. This is related to the Sybil style attacks which do the same thing but with the value embedded in the report. In these kinds of attacks, no auxiliary information in the report (like IP, etc) is needed. In practice, I don't believe this attack does much to meaningfully reduce user privacy. However, I think calling it out is important if we want to make differential privacy claims since DP requires us to think through worst-case attacks.
No this is not what I am talking about. This issue is not necessarily about attacks on , but rather about attacks on revealing to the helpers. In some settings, could be just as sensitive as . In your example you are using some local noise for each input (just one possible way of implementing DP). I don't think we would need this to protect . However, to protect we would only need to add false shares that truly sum to 0 (i.e. no noise embedded in them at all). So that is hard to learn from the total # of input records. Great question. Let's simplify this and say that you know for a fact that the true dataset contains either: records summing to , OR records summing to i.e. each record will always just have value 1. Also let's say that we've properly hidden directly, and the adversary wants to learn from . I think it should be clear that if we can protect the true value of , we can protect the true value of as they are the same. True, will be close to N or N+1, but the noise added to the sum will be enough that both cases are reasonably probable, protecting both and . For example (with Laplace noise with epsilon ln2): () -
Sharpening this a bit more: The concern is not whether the collector learns but whether the aggregators learn . The clients can add bogus reports to hide from the aggregators, or the leader can add bogus reports to hide from the helper. Is that right? This would be a tad inconsistent with the current threat model, which assumes the collector may collude with an aggregator and, in particular, provide it with the final output. That said, I'm fine with adding it as a security consideration. We just want to make it clear that it only appears to be achievable under stronger non-collusion assumptions. I see, thanks for clarifying. I think we need to be careful about what we mean when we say that the number of real (i.e., non-bogus) inputs is "protected". The output of the distributed aggregation function may be differentially private, but it doesn't hide the number of real inputs.
Yes that's right The collector colluding with an aggregator and providing the final output should be OK (similarly, the aggregators providing the noisy count of raw records to the collector). In this case, the adversary has 2 views of the data (noisy count and noisy output). You should still be able to prove DP protections in this case if each view is protected with DP (this comes from the fact that DP composes well: URL). Yes, this is exactly the purpose of this PR. By default, we can't protect from the aggregators unless we add the bogus records. However, if we can directly hide the number of real records (by adding bogus ones), and also_ ensure is DP, we can hide the true values of both and .
NAME take another look. I've tried to keep this short + sweet but let me know if you think it can be compressed further.
This should be ready to go
On the last design call (2021/08/04) we decided to split our work into two (sets of) documents: one for the "core" cryptographic protocols (Prio, Hits, ...) and another for the "wrapper" protocol (basically the protocol bits we've been working on so far). The next step is to specify the "interface" between these (sets of) documents. This is our goal for this issue. So far we've been reasoning about this core-wrapper interface by analogy of HPKE and its applications (ECH, OHTTP, etc.), which may indeed be an apt analogy, but it falls short of a precise definition. To that end, I'd like to suggest that the interface needs to accomplish two things. (1) Specify the syntax of every PDA protocol. The syntax should cover: (1a) generation of input shares from a measurement; (1b) the state machine of the leader and helper and how they respond to messages (in the core protocol); (1c) accumulation of input shares into an output share; and (1d) combination of output shares into the output. (2) Specify the security requirements of every PDA protocol. This has three main components: (2a) The expected communication model, which determines how much control over the network the adversary has. (This may be different from the communication model of the wrapper protocol, as discussed below.) (2b) A baseline notion of privacy in the expected communication model that allows any number of clients and all but one aggregator to be corrupted. (2c) A baseline notion of robustness in the expected communication that allows any number of corrupt clients to be corrupted, but requires all aggregators to be honest. Much of what we need is already worked out, but there are some gaps that require us to make some decisions. Two such gaps are discussed below. As observed in , we've been considering attacks outside the formal model of either Prio or Hits (specifically Sybil and replay attacks). The communication model for the core protocol may therefore differ from (i.e., make stronger assumptions about the adversary than) the communication model for the wrapper protocol. I would argue that this is perfectly reasonable. In fact, the main job of the wrapper protocol should be to "emulate" whatever communication model is expected by the core protocol. We are already well on our way here. The following mechanisms are used to provide properties that are implicit in the communication models of the papers: HPKE encryption creates a confidential channel between the client and each honest aggregator. The report's timestamp and jitter fields define a total ordering on reports, which the aggregators can use to ensure each report is counted in at most one batch. Some bits are still missing, however: Who manages the report queue? It seems simplest if the core protocol can assume in-order, non-repeated reports. The wrapper protocol can then do this enforcement. How are messages authenticated? Currently, the adversary can impersonate the leader since leader->helper messages are not leader authenticated. This may lead to an attack on robustness. We should probably address this in the wrapper protocol such that the core protocol can assume these messages are authenticated. In Prio, the adversary learns nothing beyond the aggregate of the honest clients' inputs. In contrast, in Hits, the adversary doesn't just learn the heavy hitters (HHs); it may also learn the frequency of non-HH inputs that share a common prefix of a non-HH input with some HH. This leakage is inevitable because the aggregators learn each intermediate set of candidate prefixes at the start of each collect request. We've observed that we can mitigate this leakage somewhat . Thus, one way to address this gap between Prio and Hits may be to require that each PDA protocol provide DP. This is probably too high a cost, however, given that not all PDA tasks need it. A simpler alternative might be to limit the syntax so that a single collect request is in scope. This seems natural, since a single round of Hits provides basically the same security properties as Prio. DP could still be added, but this would merely augment whatever the baseline privacy goal aims to provide.
Left a couple of suggestions that I don't think should block merging. NAME let us know when you've rebased or otherwise finished with this and we can merge it for you.

malicious client to craft a proof that will fool honest aggregators into accepting invalid input. <ins> Aggregators can count the total number of input shares, which could compromise user privacy (and differential privacy dp) if the presence or absence of a share for a given user is sensitive. </ins> 6.1.2.3. The linear secret sharing scheme employed by the client ensures shares reveal nothing about either the inputs or the participating clients. <ins> Clients can ensure that aggregate counts are non-sensitive by generating input independently of user behavior.  For example, a client should periodically upload a report even if the event that the task is tracking has not occurred, so that the absence of reports cannot be distinguished from their presence. Bogus inputs can be generated that encode "null" shares that do not affect the aggregate output, but mask the total number of true inputs. Either leaders or clients can generate these inputs to mask the total number from non-leader aggregators or all the aggregators, respectively. In either case, care must be taken to ensure that bogus inputs are indistinguishable from true inputs (metadata, etc), especially when constructing timestamps on reports. [OPEN ISSUE: Define what "null" shares are.  They should be defined such that inserting null shares into an aggregation is effectively a no-op.  See issue#98.] </ins> 6.1.3. The leader is also an aggregator, and so all the assets, capabilities


The overall system architecture is shown in pa-topology. [[OPEN ISSUE: This shows two helpers, but the document only allows <del> one for now.  https://github.com/abetterinternet/prio-documents/ </del>  issues/117]] The main participants in the protocol are as follows: 10.1.  URIs <del> [1] https://github.com/abetterinternet/prio-documents/issues/102 </del>  <del> [2] https://github.com/abetterinternet/prio-documents/issues/22 </del>

The repo was renamed to "ppm-specification". This commit replaces various occurences of the old repo's name, and also updated URL to reflect the current name of the protocol.

The overall system architecture is shown in pa-topology. [[OPEN ISSUE: This shows two helpers, but the document only allows  <ins> one for now.  https://github.com/abetterinternet/ppm-specification/ </ins> issues/117]] The main participants in the protocol are as follows: 10.1.  URIs  <ins> [1] https://github.com/abetterinternet/ppm-specification/issues/102 </ins>  <ins> [2] https://github.com/abetterinternet/ppm-specification/issues/22 </ins>


4.3.1.1. The leader is required to issue aggregate requests in order, but <del> reports are likely to arrive out-of-order.  The leader SHOULD buffer </del>  reports for a time period proportional to the batch window before <del> issuing the first aggregate request.  Failure to do so will result in out-of-order reports being dropped by the helper. </del>  4.3.1.2. 4.4.2. <del> Using a report multiple times within a single batch, or using the same report in multiple batches, is considered a privacy violation. To prevent such replay attacks, this specification defines a total ordering on reports that aggregators can use to ensure that reports are aggregated once. </del>  Aggregate requests are ordered as follows: We say that a report "R2" follows report "R1" if either "R2.time > R1.time" or "R2.time ==

As previously written, the timing of report aggregations would allow aggregation of reports with timestamps far into the future, which would allow a single client reporting a timestamp of INT_MAX to DOS the aggregation system due to the way timestamps are used in the anti-replay mechanism. Given the severity of not following this portion of the specification, I upgrade the SHOULD to a MUST as well.
At a high level, there are two ways for this to work: The leader and the helper agree precisely on which reports are acceptable, in which case (a) they need to have agreement on how much slack there is and (b) have precisely synchronized clocks. If the leader sends the helper an invalid share, then this can be a fatal error. The leader and the helper. In this case, they do not need to have agreement on slack or have synchronized clocks, but we then need to deal with the situation in which some shares are unacceptable. This requires a way for the helper to report that and then to know how the leader handles that.
I took another look at the spec and I think we can actually get away without any new agreed-upon parameters, nor synchronized clocks; nor is there a requirement for (new) agreement on shares being unacceptable. (Sorry, I should have caught this during the discussion yesterday.) With the changes in this PR, the leader now needs to know two new parameters: (a) how long into the past to keep reports before including them in an aggregate request, (b) how far into the future a client-provided timestamp can be. The leader uses these parameters to decide, respectively, (a) which client reports to include in a given aggregate request, and (b) which client reports to drop at time of reception. It is capable of performing both of these functions on its own, without need for communication/coordination with the helper. The helper's function for this part of the protocol is to receive aggregate requests, perform the existing anti-replay mechanism (based on ordering of ) to avoid the leader being able to replay reports, then do whatever aggregation is necessary based on the VDAF in use. The helper does not actually need to know the parameters the leader is using to perform client report selection/filtering, nor does it need to have a clock synchronized with the leader (unless the VDAF needs a clock, I suppose the helper does not need a clock at all for the aggregation portion of the protocol!). Malformed aggregation requests, including (by my reading) those that trigger the anti-replay mechanism, . [edit: actually, currently out-of-order reports are silently dropped: "[The helper] then filters out out-of-order sub-requests by ignoring any sub-request that does not follow the previous one (See Section 4.4.2.)"]
There was some discussion of whether we need to accept client reports timestamped in the future during yesterday's meeting. I wanted to circle back on this. First: an implementation can choose not to accept client timestamps that are in the future. The tradeoff is that clients whose clocks have skewed even a small amount of time into the future will no longer be able to provide reports. For that reason, I think implementations should accept reports timestamped into the future, for a time period on the order of "minutes" or "hours" (but perhaps not "days" or "weeks"?). The leader does have to store these reports -- but since the leader already has to store all reports for some time to allow reports to arrive out-of-order, this is not a totally new requirement. The text in the PR suggests accepting reports timestamped into the future up to a "time proportional to the batch window size"; to be honest, I simply copied forward the previous text's suggestion here. Perhaps there is a better suggestion to be made?
Based on last week's discussion, I dropped the behavior from a to a . Please note this now-allowed bad behavior, copied from the commit message: I don't think this caveat is bad enough to be worthy of specifying gracewindow with a MUST, I only note it for posterity.
I won't have time to look at this by noon, so please merge without my approval.
LGTM! I'll merge at noon unless someone adds a review asking for more changes.
I'd like to look first.
Clients in the PPM send a client-generated tuple with their upload requests, and encrypt their reports using a nonce that is derived from this tuple. [section 4.2.2] The aggregators use the tuple as a unique identifier for an individual report, to enable an "anti-replay" mechanism described in section 4.4.2. The reasoning for this anti-replay mechanism is described as: I argue that this mechanism does not practically stop any of the actors from submitting some arbitrary report multiple times in a single batch (i.e. "ballot-stuffing"): malicious clients can effectively replay any of their reports by re-submitting the report content re-encrypted with a new tuple; malicious servers can effectively pose as a client and perform the described "malicious client" attack themselves. But per discussion with timgNAME the purpose of the anti-replay mechanism is not to stop a malicious client/server from doing arbitrary ballot-stuffing; it is to protect a malicious leader from using the same legitimate client-provided report multiple times, which could enable certain attacks on client privacy. Separately, there is currently nothing in the spec placing any requirements or server validations on the timestamp value. A misconfigured or malicious client could send a "poisoned" report with a timestamp of . As the leader must send reports to the helper ordered by [sections 4.3.1, 4.4.2], once this report was sent to the helper as part of an aggregation request the leader would no longer be able to submit any additional reports (and if it tried, the helper would silently filter them). Separately (again), message deduplication based on a total ordering of message timestamps will lead to messages that are received in a delayed fashion being dropped, since the leader will no longer be able to include them in aggregation requests. (The same effect would be seen if a misconfigured/malicious client sent a message timestamped forward to the end of the current batch; this is very similar to the "poisoned report" issue above, but somewhat more inherent to the ordering-based deduplication mechanism.) Proposals: Update the explanation of the anti-replay mechanism to describe the intended protection more explicitly, i.e. that it covers only replay of messages sent by a client, with replay attempted by the server (I think). Think through and add server validation on the client-submitted timestamp. For example, we might decide that only reports in the current batch, or a previous batch falling within a "grace window", are allowed. (I am unsure if this would be acceptable for Heavy Hitters or other PPM algorithms that require a more "online" query capability.) Consider switching away from an ordering-based deduplication system entirely, as it depends on ordering information that cannot be reliably provided by the clients & because it will cause delayed messages to be dropped. Whatever replaces the ordering-based deduplication mechanism will likely require more storage than the ordering-based mechanism, but this might be mitigated by bounding what reports can be accepted by a time or window. Consider switching clients from reporting a timestamp to reporting a counter. The current timestamp-based report could be mapped to a batch ID by something like (though using a counter opens up the possibility of other methods of determining the current ). Reports should still be deduplicated by the tuple. (The ordering-based deduplication mechanism would no longer work.)
I like how the linked PR solves this. Before closing this issue, however, we might consider being a bit more prescriptive, along the lines of URL (thanks NAME for the link)

4.3.1.1. The leader is required to issue aggregate requests in order, but  <ins> reports are likely to arrive out-of-order.  The leader SHOULD store </ins> reports for a time period proportional to the batch window before  <ins> including them in an aggregate request.  Failure to do so may result in out-of-order reports being dropped by the helper.  The leader MUST NOT accept reports whose timestamps are in the future.  Implementors MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew. </ins> 4.3.1.2. 4.4.2.  <ins> Using a client-provided report multiple times within a single batch, or using the same report in multiple batches, may allow a server to learn information about the client's measurement, violating the privacy property of PPM.  To prevent such replay attacks, this specification defines a total ordering on reports that aggregators can use to ensure that reports are aggregated once. </ins> Aggregate requests are ordered as follows: We say that a report "R2" follows report "R1" if either "R2.time > R1.time" or "R2.time ==


input share uploaded by the client.  At the end of the computation, each aggregator is in posession of either an "output share" that is ready to be aggregated or an indication that a valid output share <del> could not be recovered. </del>  To facilitiate this computation, the input shares generated by the client include information used by the aggregators during aggregation <del> in order to validate their recovered output shares.  For example, </del>  "prio3" includes a distributed zero-knowledge proof of the input's validity BBCGGI19 which the aggregators can jointly verify and reject the report if it cannot be verified.  However, they do not learn

What PPM calls an "output share" is called an "aggregate share" in the VDAF draft. Furthermore, in the VDAF draft, an "output share" is what an aggregator recovers from running the MPC with its peers. This change fixes this ambiguity without changing the PPM protocol itself (modulo changing the info string for HPKE).
Squashed.
Thanks fellas!
Generally looks good. I would change the "agg" in the label if you can as it is confusing.LGTM, modulo typos

input share uploaded by the client.  At the end of the computation, each aggregator is in posession of either an "output share" that is ready to be aggregated or an indication that a valid output share  <ins> could not be computed. </ins> To facilitiate this computation, the input shares generated by the client include information used by the aggregators during aggregation  <ins> in order to validate their corresponding output shares.  For example, </ins> "prio3" includes a distributed zero-knowledge proof of the input's validity BBCGGI19 which the aggregators can jointly verify and reject the report if it cannot be verified.  However, they do not learn


First the aggregator checks that the request's batch interval respects the boundaries defined by the PPM task's parameters. Namely, it checks that both "batch_interval.start" and <del> "batch_interval.end" are divisible by "min_batch_duration" and that "batch_interval.end - batch_interval.start >= min_batch_duration". Unless both these conditions are true, it aborts and alerts the peer with "invalid batch interval". </del>  Next, the aggregator checks that the request respects the generic privacy parameters of the PPM task.  Let "X" denote the set of

While reviewing , NAME and I figured out a way to redefine so that invalid values cannot be represented[1]. The existing representation contains and , which means an interval could be defined with , which is invalid. Redefining as a start instant and a duration makes it impossible to represent invalid s (since is an unsigned integer). Additionally, this implicitly fixes a bug in the batch interval validation logic: we asserted that should be divisible by , but since is excluded from the , I think that was incorrect. Instead, should be divisible by . In any case, this is simpler with the new definition of : needs to be a multiple of . [1]: URL
Nice!

First the aggregator checks that the request's batch interval respects the boundaries defined by the PPM task's parameters. Namely, it checks that both "batch_interval.start" and  <ins> "batch_interval.duration" are divisible by "min_batch_duration" and that "batch_interval.duration >= min_batch_duration".  Unless both these conditions are true, it aborts and alerts the peer with "invalid batch interval". </ins> Next, the aggregator checks that the request respects the generic privacy parameters of the PPM task.  Let "X" denote the set of


"[leader]/collect", where "[leader]" is the leader's endpoint URL. The body of the request is structured as follows:  The named parameters are: "task_id", the PPM task ID. "agg_param", an aggregation parameter for the VDAF being executed. Depending on the VDAF scheme and how the leader is configured, the <del> collect request may cause the leader to send a series of aggregate requests to the helpers in order to compute their share of the aggregate.  Alternately, the leader may already have made these requests and can respond immediately.  In either case it responds to the collector's request as follows. It begins by checking that the request meets the requirements of the batch parameters using the procedure in batch-parameter-validation. If so, it obtains the helper's encrypted aggregate share for the batch interval by sending an AggregateShareReq to the helper as described in aggregate-share-request.  (This request may too have been made in advance.) Next, the leader computes its own aggregate share by aggregating all of the verified output shares that fall within the batch interval. Finally, it responds with HTTP status 200 and a body consisting of a CollectResp message: [OPEN ISSUE: What happens if this all takes a really long time.] [TODO: Decide if and how the collector's request is authenticated.] </del>  "shares" is a vector of "EncryptedAggregateShare"s, as described in aggregate-share-request, except that for the leader's share, the "task_id" and "batch_interval" used to encrypt the "AggregateShare" are obtained from the "CollectReq".  [OPEN ISSUE: Describe how intra-protocol errors yield collect errors (see issue#57).  For example, how does a leader respond to a collect request if the helper drops out?] CollectReq pa-collect: "message/ppm-collect-req" <del> CollectResp pa-collect: "message/ppm-collect-req" </del>  The definition for each media type is in the following subsections.

Make the handling of collect requests on the leader asynchronous, since servicing a collect request could entail running the preparation protocol over all the reports that fall into the batch interval, especially in VDAFs like poplar1 where the aggregation parameter is not available until the collector provides it. I've only made the collect request handling asynchronous. My reasoning is that handling other requests synchronously should be feasible: upload requests should only contain shares of a single report and thus never be all that big. Additionally, the client needs an explicit acknowledgement from the aggregator that the uploaded report was accepted and has been persisted. the requests in the aggregation/preparation sub-protocol should also never get that big: even when preparing a large number of reports, the leader can choose to carve that work up into any number of aggregation jobs, each of which covers a small enough number of reports that the message sizes and processing times should be reasonable to handle in synchronous request/response exchanges.
With this change, we will have two differing definitions of structs named . My understanding is that clients will know which one to expect based on the URL of the request, and the status code in the response. (they will receive a URL from /collect on success, and the URL will return a URL with status code 202, or shares with status code 200) I think we should change one of these for clarity to the reader, i.e. or .
It's easy to imagine that a request will take a long time, especially if you are using Collect and that has to trigger a bunch of work from the leader. We need some way of handling this.
This intersects with something we were discussing last week, which is whether or not should have in it, or a URL from which collector config can be fetched dynamically. We decided on the former to spare collectors of running an online HTTP server. However, if we adopt an asynchronous model for collect requests, then we might need collectors to be an HTTP server anyway so that the leader can notify them that a collect request is complete, in which case we should make collectors have a endpoint like the other servers.
NAME and I were talking about this today. We agree that / definitely needs to be made asynchronous since in the case, servicing a will definitely incur lots of expensive work between the aggregators (this is less likely in the case because the aggregators aren't blocked on obtaining the aggregation parameter from the collector in that VDAF). What I'm not sure if is whether we should make all the interactions between the aggregators during preparation and verification asynchronous, and I'm not sure how to decide. It seems like it should be possible for leaders to scope each aggregate requests to a small enough number of shares that each one can reasonably be serviced synchronously.
For collect requests, I'd also note here that asynchronicity is probably going to be important for , as it's possible that the aggregation flow will fall behind the upload flow. (Imagine the helper can only handle 1000 reports/sec, but the clients are uploading 1million reports/sec.) As for aggregate requests, I would expect these to be able to be completed fairly quickly (in a matter of seconds, in the worst case). Based on our experience so far, the most expensive part appears to be interacting with long-term storage, which is required for anti-replay and, if we take , looking up report shares. I think we can hold off on making these requests asynchronous until we've gotten enough deployment experience to determine if this is going to be a problem.
NAME provided some interesting prior art that we should rely on when addressing this: URL
Nicely done. Hi Tim, Maybe this might help you: URL (URIs, not UUIDs) You might also find this informative: URL You are probably familiar with how ACME does asynchronous processing, which is largely OK. This probably comes down to preference at some level. However, asynchronous interactions are a fair bit more complex than synchronous ones, so avoiding that complexity is good. Keep in mind that modern HTTP versions aren't stalled if there are a handful of long-running requests, so unless you are talking a fairly significant time, it might be cleaner and easier to just have the client wait on hold. Asynchronous requests do come with some benefits to go with the complexity. For instance, robustness can be improved if the initial request creates resources that can be referred to later on a different connection without having to rely on the connection remaining viable. RFC 7240 does suggest that you might offer both, but I would only go that far if you thought that implementations would consistently use both options.

"[leader]/collect", where "[leader]" is the leader's endpoint URL. The body of the request is structured as follows: <ins> [OPEN ISSUE: Decide if and how the collector's request is authenticated.  If not, then we need to ensure that collect job URIs are resistant to enumeration attacks.] ~~~ struct { TaskID task_id; Interval batch_interval; opaque agg_param<0..2^16-1>; // VDAF aggregation parameter } CollectReq; ~~~ </ins> The named parameters are: "task_id", the PPM task ID. "agg_param", an aggregation parameter for the VDAF being executed. Depending on the VDAF scheme and how the leader is configured, the  <ins> leader and helper may already have prepared all the reports falling within "batch_interval" and be ready to return the aggregate shares right away, but this cannot be guaranteed.  In fact, for some VDAFs, it is not be possible to begin preparing inputs until the collector provides the aggregation parameter in the "CollectReq".  For these reasons, collect requests are handled asynchronously. Upon receipt of a "CollectReq", the leader begins by checking that the request meets the requirements of the batch parameters using the procedure in batch-parameter-validation.  If so, it immediately sends the collector a response with HTTP status 303 See Other and a Location header containing a URI identifying the collect job that can be polled by the collector, called the "collect job URI". The leader then begins working with the helper to prepare the shares falling into "CollectReq.batch_interval" (or continues this process, depending on the VDAF) as described in pa-aggregate. After receiving the response to its CollectReq, the collector makes an HTTP GET request to the collect job URI to check on the status of the collect job and eventually obtain the result.  If the collect job is not finished yet, the leader responds with HTTP status 202 Accepted.  The response MAY include a Retry-After header field to suggest a pulling interval to the collector. Once all the necessary reports have been prepared, the leader obtains the helper's encrypted aggregate share for the batch interval by sending an "AggregateShareReq" to the helper as described in aggregate-share-request.  The leader then computes its own aggregate share by aggregating all of the prepared output shares that fall within the batch interval. When both aggregators' shares are successfully obtained, the leader responds to subsequent HTTP GET requests to the collect job's URI with HTTP status 200 OK and a body consisting of a "CollectResult": </ins> "shares" is a vector of "EncryptedAggregateShare"s, as described in aggregate-share-request, except that for the leader's share, the "task_id" and "batch_interval" used to encrypt the "AggregateShare" are obtained from the "CollectReq". <ins> If obtaining aggregate shares fails, then the leader responds to subsequent HTTP GET requests to the collect job URI with an HTTP error status and a problem document as described in errors. The leader MUST retain a collect job's results until the collector sends an HTTP DELETE request to the collect job URI, in which case the leader responds with HTTP status 204 No Content. [OPEN ISSUE: Allow the leader to drop aggregate shares after some reasonable amount of time has passed, but it's not clear how to specify that.  ACME doesn't bother to say anything at all about this when describing how subscribers should fetch certificates: https://datatracker.ietf.org/doc/html/rfc8555#section-7.4.2] </ins> [OPEN ISSUE: Describe how intra-protocol errors yield collect errors (see issue#57).  For example, how does a leader respond to a collect request if the helper drops out?] CollectReq pa-collect: "message/ppm-collect-req"  <ins> CollectResult pa-collect: "message/ppm-collect-result" </ins> The definition for each media type is in the following subsections.


extracting its aggregate share from its state and encrypting it under the collector's HPKE public key. <del> For each aggregator endpoint "[aggregator]" in the parameters </del>  associated with "CollectReq.task_id" (see pa-collect) except its own, the leader sends a POST request to "[aggregator]/aggregate_share" with the following message: "batch_interval" is the batch interval of the request.  "helper_state" is the helper's state, which is carried across requests from the leader. To respond to an AggregateShareReq message, the helper first looks up the PPM parameters associated with task "task_id".  Then, using the procedure in batch-parameter-validation, it ensures that the request <del> meets the requirements of the batch parameters.  If so, it aggregates all valid output shares that fall in the batch interval into an aggregate share.  The response contains an opaque, VDAF-specific message: </del>  Next, the helper encrypts the aggregate share "agg_share" under the collector's public key as follows:

This is intended to allow PPM implementations to discover if the leader & helper(s) have fallen out-of-sync in their views of what shares are included in the aggregation. Notes: it would be trivial for an adversary to generate sets of nonces that collide with one another. Since the goal is to provide a check against server malfunction, rather than a security check against malicious clients or other actors in the system, I think this is acceptable. I evaluated a number of collision-resistant multiset-hash constructions[1], but none of them were currently standardized & specifying them would be more effort than seems necessary given the goals of this checksum.
The hash function wouldn't matter in that setting, as the attacker could generate a pool of a few hundred/thousand nonces and their hashes, fix one set of nonces, and use a system of equations over GF(2)^(digest length) to determine what the other set of nonces should be to match the checksum. Equivalently, they could start with generating a pool of nonces and hashes, treat them as vectors in GF(2)^(digest length), put them in a matrix, and find the kernel of that matrix. Pick two unique vectors that are in the kernel and have the same Hamming weight, then each entry determines whether the corresponding nonce from the pool should be included. These two vectors will give you two unique sets of nonces from the pool, such that they form two batches of the same size with the same checksum. Using a MAC would require sorting at some point, and would preclude accumulating the checksum as each prepare request comes in, like with LtHash or this XOR construction. Long term, we need to more rigorously handle ordering of prepare and collect interactions, gracefully handling communication failures and retries between the leader and helper, and agreement on reports to be collected, but I agree this is fine for now as an error heuristic.
I think any hash function would permit an attacker to create a collision. Treating the hash function as a random oracle, the attacker could try random nonces until they find hash values that produce a basis for (where is the output size of the hash in bits). I think this is expected to take right around hash computations if I remember my linear algebra correctly. Then they can use this basis to select a set of nonces producing any desired checksum value. By repeating the process and finding a different basis, they can then produce a distinct set of nonces producing any desired checksum value. (I think this is similar to/the same as David's argument above.) Swapping out SHA256 for HMAC-SHA256 with the key kept secret by the aggregators would fix that particular issue since clients could no longer predict how a given nonce would contribute to the checksum; but as far as I'm aware there are no security proofs for this construction so there may be other attacks. The lack of collision-resistance may be acceptable for two reasons IMO: (a) there are other mechanisms in PPM to make sure the aggregators are aggregating the same set of client reports, this is intended as a check against server malfunction/distributed systems errors; (b) since we are currently implementing the client-uploads-to-leader-only model, clients can't provide different sets of nonces to different aggregators. I'm still not entirely happy with it, however. I added an OPEN ISSUE and I think we should revisit this later.
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 .
I agree that we don't care about a malicious aggregator here, but we do care about malicious clients. We need to think through what an attacker can do if it controls a subset of the clients and can disrupt the transmission of messages between the aggregators. Specifically, suppose the leader has computed the checksum and the helper has computed the checksum where and are distinct sets of nonces (i.e., they differ by at least one element). Suppose further that the attacker controls the values of the nonces. The attacker's goal is to choose the nonce sets so that . Thus the question is what we need to assume about to ensure that this is hard. It's not clear to me that this amounts to a standard assumption about cryptographic hash functions like SHA256. We might be better off using a MAC here instead. That said, I think it would be best to keep this change as simple as possible. I would be OK with merging as-is, so long as we add a note about the attack above in an "OPEN ISSUE" in the text.LGTM at least provisionally.This would This LGTM, though I'm eager to hear what NAME thinks about using XORed SHA256 here.

extracting its aggregate share from its state and encrypting it under the collector's HPKE public key.  <ins> [OPEN ISSUE: consider updating the "checksum" algorithm to not permit collisions] First, the leader computes a checksum over the set of output shares included in the batch window.  The checksum is computed by taking the SHA256 hash of each nonce from the client reports included in the aggregation, then combining the hash values with a bitwise-XOR operation. Then, for each aggregator endpoint "[aggregator]" in the parameters </ins> associated with "CollectReq.task_id" (see pa-collect) except its own, the leader sends a POST request to "[aggregator]/aggregate_share" with the following message: "batch_interval" is the batch interval of the request. <ins> "report_count" is the number of reports included in the aggregation. "checksum" is the checksum computed over the set of client reports, computed as described above. </ins> "helper_state" is the helper's state, which is carried across requests from the leader. To respond to an AggregateShareReq message, the helper first looks up the PPM parameters associated with task "task_id".  Then, using the procedure in batch-parameter-validation, it ensures that the request  <ins> meets the requirements of the batch parameters.  It also computes a checksum based on its view of the output shares included in the batch window, and checks that the "report_count" and "checksum" included in the request match its computed values.  If so, it aggregates all valid output shares that fall in the batch interval into an aggregate share.  The response contains an opaque, VDAF-specific message: </ins> Next, the helper encrypts the aggregate share "agg_share" under the collector's public key as follows:


The following terms are used: <del> This document uses the protocol definition language of RFC8446. </del>  2. "HpkeConfig" is the key config of the aggregator receiving the input share. <del> "enc" is the encapsulated HPKE context, used by the aggregator to </del>  decrypt its input share. "payload" is the encrypted input share. where "pk" is the aggregator's public key, "task_id" is "Report.task_id" and "server_role" is a byte whose value is "0x01" if the aggregator is the leader and "0x00" if the aggregator is the <del> helper. "enc" is the encapsulated HPKE context and "context" is the HPKE context used by the client for encryption.  The payload is encrypted as </del>  where "input_share" is the aggregator's input share and "nonce" and "extensions" are the corresponding fields of "Report". "collector_hpke_config_id" is "collector_config.id" from the task parameters corresponding to "CollectReq.task_id". <del> "enc" is the encapsulated HPKE context, used by the collector to </del>  decrypt the aggregate share. "payload" is an encrypted "AggregateShare". 7.3. The following value [will be/has been] registered in the "IETF URN <del> Sub- namespace for Registered Protocol Parameter Identifiers" </del>  registry, following the template in RFC3553: Initial contents: The types and descriptions in the table in errors

Here are a few small editorial changes: Refer to TLS's "presentation language", per section 3 of the RFC. The output from the HPKE setup function is an encapsulated key, not an encapsulated context. The term context is defined as "A context is an implementation-specific structure...", whereas is alternately described as "an encapsulated KEM shared secret", an "encapsulated key", or a "KEM encapsulated key". Remove stray whitespace from a hyphenated word.
One non-blocking comment.

The following terms are used:  <ins> This document uses the presentation language of RFC8446. </ins> 2. "HpkeConfig" is the key config of the aggregator receiving the input share.  <ins> "enc" is the HPKE encapsulated key, used by the aggregator to </ins> decrypt its input share. "payload" is the encrypted input share. where "pk" is the aggregator's public key, "task_id" is "Report.task_id" and "server_role" is a byte whose value is "0x01" if the aggregator is the leader and "0x00" if the aggregator is the  <ins> helper. "enc" is the HPKE encapsulated key and "context" is the HPKE context used by the client for encryption.  The payload is encrypted as </ins> where "input_share" is the aggregator's input share and "nonce" and "extensions" are the corresponding fields of "Report". "collector_hpke_config_id" is "collector_config.id" from the task parameters corresponding to "CollectReq.task_id".  <ins> "enc" is the HPKE encapsulated key, used by the collector to </ins> decrypt the aggregate share. "payload" is an encrypted "AggregateShare". 7.3. The following value [will be/has been] registered in the "IETF URN  <ins> Sub-namespace for Registered Protocol Parameter Identifiers" </ins> registry, following the template in RFC3553: Initial contents: The types and descriptions in the table in errors


(see issue#57).  For example, how does a leader respond to a collect request if the helper drops out?]  4.4.1. Before an aggregator responds to a collect request or aggregate-share

The info strings used in HPKE context construction used the prefix "pda", referring to the old "Private Data Aggregation" name of this protocol. This commit also adds text instructing the collector how to decrypt the aggregate shares it receives and to use the VDAF's unsharding algorithm to obtain aggregate results.
Question for the reviewers: VDAF defines labels like (). Should we include the draft version number in info strings like this? e.g. ?

(see issue#57).  For example, how does a leader respond to a collect request if the helper drops out?] <ins> The collector then decrypts each aggregate share "share" using the following procedure: where "sk" is the HPKE secret key, "task_id" is "AggregateReq.task_id" and "server_role" is the role of the server that send the aggregate share ("0x01" for the leader and "0x00" for the helper). "batch_interval" is the "Interval" from the "CollectReq".  The collector then unshards the aggregate shares into an aggregate result using the VDAF's "agg_shares_to_result" algorithm. </ins> 4.4.1. Before an aggregator responds to a collect request or aggregate-share


When both aggregators' shares are successfully obtained, the leader responds to subsequent HTTP GET requests to the collect job's URI <del> with HTTP status 200 OK and a body consisting of a "CollectResult": </del>  "shares" is a vector of "EncryptedAggregateShare"s, as described in aggregate-share-request, except that for the leader's share, CollectReq pa-collect: "message/ppm-collect-req" <del> CollectResult pa-collect: "message/ppm-collect-result" </del>  The definition for each media type is in the following subsections.

CollectResp is paired with CollectReq; naming things this way matches other {Req, Resp} message pairs.

When both aggregators' shares are successfully obtained, the leader responds to subsequent HTTP GET requests to the collect job's URI  <ins> with HTTP status 200 OK and a body consisting of a "CollectResp": </ins> "shares" is a vector of "EncryptedAggregateShare"s, as described in aggregate-share-request, except that for the leader's share, CollectReq pa-collect: "message/ppm-collect-req"  <ins> CollectResp pa-collect: "message/ppm-collect-resp" </ins> The definition for each media type is in the following subsections.