Repository: cloudflare/daphne
Pull request #351 (2023-06-20 14:53:43)

Break compatibility with draft 04
Partially addresses #350.

cjpatton: > This is a kv breaking change at least, right? What else could this possibly break?

This is a breaking change for draft-04 of the spec only; draft-02 is not impacted.
cjpatton: Fixed clippy

Patch:
diff --git a/daphne/src/constants.rs b/daphne/src/constants.rs
index 20af4d9..50926d3 100644
--- a/daphne/src/constants.rs
+++ b/daphne/src/constants.rs
@@ -68,30 +68,30 @@ impl DapMediaType {
     pub fn from_str_for_version(version: DapVersion, content_type: Option<&str>) -> Self {
         match (version, content_type) {
             (DapVersion::Draft02, Some(DRAFT02_MEDIA_TYPE_AGG_CONT_REQ))
-            | (DapVersion::Draft04, Some(MEDIA_TYPE_AGG_JOB_CONT_REQ)) => {
+            | (DapVersion::Draft05, Some(MEDIA_TYPE_AGG_JOB_CONT_REQ)) => {
                 Self::AggregationJobContinueReq
             }
             (DapVersion::Draft02, Some(DRAFT02_MEDIA_TYPE_AGG_CONT_RESP)) => {
                 Self::Draft02AggregateContinueResp
             }
             (DapVersion::Draft02, Some(DRAFT02_MEDIA_TYPE_AGG_INIT_REQ))
-            | (DapVersion::Draft04, Some(MEDIA_TYPE_AGG_JOB_INIT_REQ)) => {
+            | (DapVersion::Draft05, Some(MEDIA_TYPE_AGG_JOB_INIT_REQ)) => {
                 Self::AggregationJobInitReq
             }
             (DapVersion::Draft02, Some(DRAFT02_MEDIA_TYPE_AGG_INIT_RESP))
-            | (DapVersion::Draft04, Some(MEDIA_TYPE_AGG_JOB_RESP)) => Self::AggregationJobResp,
+            | (DapVersion::Draft05, Some(MEDIA_TYPE_AGG_JOB_RESP)) => Self::AggregationJobResp,
             (DapVersion::Draft02, Some(DRAFT02_MEDIA_TYPE_AGG_SHARE_RESP))
-            | (DapVersion::Draft04, Some(MEDIA_TYPE_AGG_SHARE)) => Self::AggregateShare,
+            | (DapVersion::Draft05, Some(MEDIA_TYPE_AGG_SHARE)) => Self::AggregateShare,
             (DapVersion::Draft02, Some(DRAFT02_MEDIA_TYPE_COLLECT_RESP))
-            | (DapVersion::Draft04, Some(MEDIA_TYPE_COLLECTION)) => Self::Collection,
+            | (DapVersion::Draft05, Some(MEDIA_TYPE_COLLECTION)) => Self::Collection,
             (DapVersion::Draft02, Some(DRAFT02_MEDIA_TYPE_HPKE_CONFIG))
-            | (DapVersion::Draft04, Some(MEDIA_TYPE_HPKE_CONFIG_LIST)) => Self::HpkeConfigList,
+            | (DapVersion::Draft05, Some(MEDIA_TYPE_HPKE_CONFIG_LIST)) => Self::HpkeConfigList,
             (DapVersion::Draft02, Some(MEDIA_TYPE_AGG_SHARE_REQ))
-            | (DapVersion::Draft04, Some(MEDIA_TYPE_AGG_SHARE_REQ)) => Self::AggregateShareReq,
+            | (DapVersion::Draft05, Some(MEDIA_TYPE_AGG_SHARE_REQ)) => Self::AggregateShareReq,
             (DapVersion::Draft02, Some(MEDIA_TYPE_COLLECT_REQ))
-            | (DapVersion::Draft04, Some(MEDIA_TYPE_COLLECT_REQ)) => Self::CollectReq,
+            | (DapVersion::Draft05, Some(MEDIA_TYPE_COLLECT_REQ)) => Self::CollectReq,
             (DapVersion::Draft02, Some(MEDIA_TYPE_REPORT))
-            | (DapVersion::Draft04, Some(MEDIA_TYPE_REPORT)) => Self::Report,
+            | (DapVersion::Draft05, Some(MEDIA_TYPE_REPORT)) => Self::Report,
             (_, Some(content_type)) => Self::Invalid(content_type.to_string()),
             (_, None) => Self::Missing,
         }
@@ -103,15 +103,15 @@ impl DapMediaType {
             (DapVersion::Draft02, Self::AggregationJobInitReq) => {
                 Some(DRAFT02_MEDIA_TYPE_AGG_INIT_REQ)
             }
-            (DapVersion::Draft04, Self::AggregationJobInitReq) => Some(MEDIA_TYPE_AGG_JOB_INIT_REQ),
+            (DapVersion::Draft05, Self::AggregationJobInitReq) => Some(MEDIA_TYPE_AGG_JOB_INIT_REQ),
             (DapVersion::Draft02, Self::AggregationJobResp) => {
                 Some(DRAFT02_MEDIA_TYPE_AGG_INIT_RESP)
             }
-            (DapVersion::Draft04, Self::AggregationJobResp) => Some(MEDIA_TYPE_AGG_JOB_RESP),
+            (DapVersion::Draft05, Self::AggregationJobResp) => Some(MEDIA_TYPE_AGG_JOB_RESP),
             (DapVersion::Draft02, Self::AggregationJobContinueReq) => {
                 Some(DRAFT02_MEDIA_TYPE_AGG_CONT_REQ)
             }
-            (DapVersion::Draft04, Self::AggregationJobContinueReq) => {
+            (DapVersion::Draft05, Self::AggregationJobContinueReq) => {
                 Some(MEDIA_TYPE_AGG_JOB_CONT_REQ)
             }
             (DapVersion::Draft02, Self::Draft02AggregateContinueResp) => {
@@ -119,17 +119,17 @@ impl DapMediaType {
             }
             (_, Self::Draft02AggregateContinueResp) => None,
             (DapVersion::Draft02, Self::AggregateShareReq)
-            | (DapVersion::Draft04, Self::AggregateShareReq) => Some(MEDIA_TYPE_AGG_SHARE_REQ),
+            | (DapVersion::Draft05, Self::AggregateShareReq) => Some(MEDIA_TYPE_AGG_SHARE_REQ),
             (DapVersion::Draft02, Self::AggregateShare) => Some(DRAFT02_MEDIA_TYPE_AGG_SHARE_RESP),
-            (DapVersion::Draft04, Self::AggregateShare) => Some(MEDIA_TYPE_AGG_SHARE),
-            (DapVersion::Draft02, Self::CollectReq) | (DapVersion::Draft04, Self::CollectReq) => {
+            (DapVersion::Draft05, Self::AggregateShare) => Some(MEDIA_TYPE_AGG_SHARE),
+            (DapVersion::Draft02, Self::CollectReq) | (DapVersion::Draft05, Self::CollectReq) => {
                 Some(MEDIA_TYPE_COLLECT_REQ)
             }
             (DapVersion::Draft02, Self::Collection) => Some(DRAFT02_MEDIA_TYPE_COLLECT_RESP),
-            (DapVersion::Draft04, Self::Collection) => Some(MEDIA_TYPE_COLLECTION),
+            (DapVersion::Draft05, Self::Collection) => Some(MEDIA_TYPE_COLLECTION),
             (DapVersion::Draft02, Self::HpkeConfigList) => Some(DRAFT02_MEDIA_TYPE_HPKE_CONFIG),
-            (DapVersion::Draft04, Self::HpkeConfigList) => Some(MEDIA_TYPE_HPKE_CONFIG_LIST),
-            (DapVersion::Draft02, Self::Report) | (DapVersion::Draft04, Self::Report) => {
+            (DapVersion::Draft05, Self::HpkeConfigList) => Some(MEDIA_TYPE_HPKE_CONFIG_LIST),
+            (DapVersion::Draft02, Self::Report) | (DapVersion::Draft05, Self::Report) => {
                 Some(MEDIA_TYPE_REPORT)
             }
             (_, Self::Invalid(ref content_type)) => Some(content_type),
@@ -143,7 +143,7 @@ impl DapMediaType {
     pub(crate) fn agg_job_cont_resp_for_version(version: DapVersion) -> Self {
         match version {
             DapVersion::Draft02 => Self::Draft02AggregateContinueResp,
-            DapVersion::Draft04 => Self::AggregationJobResp,
+            DapVersion::Draft05 => Self::AggregationJobResp,
             _ => unreachable!("unhandled version {version:?}"),
         }
     }
diff --git a/daphne/src/lib.rs b/daphne/src/lib.rs
index 687d8ba..1204ff7 100644
--- a/daphne/src/lib.rs
+++ b/daphne/src/lib.rs
@@ -9,7 +9,9 @@
 //! PPM working group of the IETF. See [`VdafConfig`] for a listing of supported
 //! [VDAFs](https://github.com/cfrg/draft-irtf-cfrg-vdaf).
 //!
-//! Daphne implements draft-ietf-ppm-dap-02 and draft-ietf-ppm-dap-03.
+//! Daphne implements draft-ietf-ppm-dap-02 and draft-ietf-ppm-dap-05.
+//!
+//! **WARNING:** draft 05 is a work-in-progress. We are not yet compatible.
 //!
 //! Daphne does not provide the complete, end-to-end functionality of any party in the protocol.
 //! Instead, it defines traits for the functionalities that a concrete instantiation of the
@@ -73,8 +75,8 @@ pub enum DapVersion {
     #[serde(rename = "v02")]
     Draft02,
 
-    #[serde(rename = "v04")]
-    Draft04,
+    #[serde(rename = "v05")]
+    Draft05,
 
     #[serde(other)]
     #[serde(rename = "unknown_version")]
@@ -86,7 +88,7 @@ impl From<&str> for DapVersion {
     fn from(version: &str) -> Self {
         match version {
             "v02" => DapVersion::Draft02,
-            "v04" => DapVersion::Draft04,
+            "v05" => DapVersion::Draft05,
             _ => DapVersion::Unknown,
         }
     }
@@ -96,8 +98,8 @@ impl AsRef<str> for DapVersion {
     fn as_ref(&self) -> &str {
         match self {
             DapVersion::Draft02 => "v02",
-            DapVersion::Draft04 => "v04",
-            _ => panic!("tried to construct string from unknown DAP version"),
+            DapVersion::Draft05 => "v05",
+            _ => unreachable!("tried to construct string from unknown DAP version"),
         }
     }
 }
@@ -842,13 +844,13 @@ pub struct DapLeaderProcessTelemetry {
 }
 
 /// draft02 compatibility: A logical aggregation job ID. In the latest draft, this is a 32-byte
-/// string included in the HTTP request payload; in draft04, this is a 16-byte string included in
+/// string included in the HTTP request payload; in draft05, this is a 16-byte string included in
 /// the HTTP request path. This type unifies these into one type so that any protocol logic that
 /// is agnostic to these details can use the same object.
 #[derive(Clone, Debug)]
 pub enum MetaAggregationJobId<'a> {
     Draft02(Cow<'a, Draft02AggregationJobId>),
-    Draft04(Cow<'a, AggregationJobId>),
+    Draft05(Cow<'a, AggregationJobId>),
 }
 
 impl MetaAggregationJobId<'_> {
@@ -857,7 +859,7 @@ impl MetaAggregationJobId<'_> {
         let mut rng = thread_rng();
         match version {
             DapVersion::Draft02 => Self::Draft02(Cow::Owned(Draft02AggregationJobId(rng.gen()))),
-            DapVersion::Draft04 => Self::Draft04(Cow::Owned(AggregationJobId(rng.gen()))),
+            DapVersion::Draft05 => Self::Draft05(Cow::Owned(AggregationJobId(rng.gen()))),
             DapVersion::Unknown => unreachable!("unhandled version {version:?}"),
         }
     }
@@ -867,7 +869,7 @@ impl MetaAggregationJobId<'_> {
     pub(crate) fn for_request_payload(&self) -> Option<Draft02AggregationJobId> {
         match self {
             Self::Draft02(agg_job_id) => Some(agg_job_id.clone().into_owned()),
-            Self::Draft04(..) => None,
+            Self::Draft05(..) => None,
         }
     }
 
@@ -877,7 +879,7 @@ impl MetaAggregationJobId<'_> {
         match self {
             // In draft02, the aggregation job ID is not determined until the payload is parsed.
             Self::Draft02(..) => DapResource::Undefined,
-            Self::Draft04(agg_job_id) => {
+            Self::Draft05(agg_job_id) => {
                 DapResource::AggregationJob(agg_job_id.clone().into_owned())
             }
         }
@@ -887,7 +889,7 @@ impl MetaAggregationJobId<'_> {
     pub fn to_hex(&self) -> String {
         match self {
             Self::Draft02(agg_job_id) => agg_job_id.to_hex(),
-            Self::Draft04(agg_job_id) => agg_job_id.to_hex(),
+            Self::Draft05(agg_job_id) => agg_job_id.to_hex(),
         }
     }
 
@@ -895,7 +897,7 @@ impl MetaAggregationJobId<'_> {
     pub fn to_base64url(&self) -> String {
         match self {
             Self::Draft02(agg_job_id) => agg_job_id.to_base64url(),
-            Self::Draft04(agg_job_id) => agg_job_id.to_base64url(),
+            Self::Draft05(agg_job_id) => agg_job_id.to_base64url(),
         }
     }
 }
diff --git a/daphne/src/messages/mod.rs b/daphne/src/messages/mod.rs
index 233a029..1ac6e7b 100644
--- a/daphne/src/messages/mod.rs
+++ b/daphne/src/messages/mod.rs
@@ -95,11 +95,11 @@ id_struct!(TaskId, 32, "Task ID");
 impl TaskId {
     /// draft02 compatibility: Convert the task ID to the field that would be added to the DAP
     /// request for the given version. In draft02, the task ID is generally included in the HTTP
-    /// request payload; in draft04, the task ID is included in the HTTP request path.
+    /// request payload; in draft05, the task ID is included in the HTTP request path.
     pub fn for_request_payload(&self, version: &DapVersion) -> Option<TaskId> {
         match version {
             DapVersion::Draft02 => Some(self.clone()),
-            DapVersion::Draft04 => None,
+            DapVersion::Draft05 => None,
             DapVersion::Unknown => unreachable!("unhandled version {version:?}"),
         }
     }
@@ -424,7 +424,7 @@ impl ParameterizedEncode<DapVersion> for AggregationJobInitReq {
                     .encode(bytes);
                 encode_u16_bytes(bytes, &self.agg_param);
             }
-            DapVersion::Draft04 => encode_u32_bytes(bytes, &self.agg_param),
+            DapVersion::Draft05 => encode_u32_bytes(bytes, &self.agg_param),
             DapVersion::Unknown => unreachable!("unhandled version {version:?}"),
         };
         self.part_batch_sel.encode(bytes);
@@ -443,7 +443,7 @@ impl ParameterizedDecode<DapVersion> for AggregationJobInitReq {
                 Some(Draft02AggregationJobId::decode(bytes)?),
                 decode_u16_bytes(bytes)?,
             ),
-            DapVersion::Draft04 => (None, None, decode_u32_bytes(bytes)?),
+            DapVersion::Draft05 => (None, None, decode_u32_bytes(bytes)?),
             DapVersion::Unknown => unreachable!("unhandled version {version:?}"),
         };
 
@@ -479,10 +479,10 @@ impl ParameterizedEncode<DapVersion> for AggregationJobContinueReq {
                     .expect("draft02: missing aggregation job ID")
                     .encode(bytes);
             }
-            DapVersion::Draft04 => {
+            DapVersion::Draft05 => {
                 self.round
                     .as_ref()
-                    .expect("draft04: missing round")
+                    .expect("draft05: missing round")
                     .encode(bytes);
             }
             DapVersion::Unknown => unreachable!("unhandled version {version:?}"),
@@ -502,7 +502,7 @@ impl ParameterizedDecode<DapVersion> for AggregationJobContinueReq {
                 Some(Draft02AggregationJobId::decode(bytes)?),
                 None,
             ),
-            DapVersion::Draft04 => (None, None, Some(u16::decode(bytes)?)),
+            DapVersion::Draft05 => (None, None, Some(u16::decode(bytes)?)),
             DapVersion::Unknown => unreachable!("unhandled version {version:?}"),
         };
         Ok(Self {
@@ -517,7 +517,7 @@ impl ParameterizedDecode<DapVersion> for AggregationJobContinueReq {
 /// Transition message. This conveyes a message sent from one Aggregator to another during the
 /// preparation phase of VDAF evaluation.
 //
-// TODO Consider renaming this to `PrepareStep` to align with draft04.
+// TODO Consider renaming this to `PrepareStep` to align with draft05.
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct Transition {
     pub report_id: ReportId,
@@ -785,13 +785,13 @@ impl ParameterizedEncode<DapVersion> for CollectionReq {
                     .expect("draft02: missing task ID")
                     .encode(bytes);
             }
-            DapVersion::Draft04 => {}
+            DapVersion::Draft05 => {}
             DapVersion::Unknown => unreachable!("unhandled version {version:?}"),
         }
         self.query.encode_with_param(version, bytes);
         match version {
             DapVersion::Draft02 => encode_u16_bytes(bytes, &self.agg_param),
-            DapVersion::Draft04 => encode_u32_bytes(bytes, &self.agg_param),
+            DapVersion::Draft05 => encode_u32_bytes(bytes, &self.agg_param),
             _ => panic!("unimplemented DapVersion"),
         };
     }
@@ -804,7 +804,7 @@ impl ParameterizedDecode<DapVersion> for CollectionReq {
     ) -> Result<Self, CodecError> {
         let draft02_task_id = match version {
             DapVersion::Draft02 => Some(TaskId::decode(bytes)?),
-            DapVersion::Draft04 => None,
+            DapVersion::Draft05 => None,
             DapVersion::Unknown => unreachable!("unhandled version {version:?}"),
         };
         Ok(Self {
@@ -812,7 +812,7 @@ impl ParameterizedDecode<DapVersion> for CollectionReq {
             query: Query::decode_with_param(version, bytes)?,
             agg_param: match version {
                 DapVersion::Draft02 => decode_u16_bytes(bytes)?,
-                DapVersion::Draft04 => decode_u32_bytes(bytes)?,
+                DapVersion::Draft05 => decode_u32_bytes(bytes)?,
                 _ => panic!("unimplemented DapVersion"),
             },
         })
@@ -836,10 +836,10 @@ impl ParameterizedEncode<DapVersion> for Collection {
         self.report_count.encode(bytes);
         match version {
             DapVersion::Draft02 => {}
-            DapVersion::Draft04 => {
+            DapVersion::Draft05 => {
                 self.interval
                     .as_ref()
-                    .expect("draft04: missing interval")
+                    .expect("draft05: missing interval")
                     .encode(bytes);
             }
             DapVersion::Unknown => unreachable!("unhandled version {version:?}"),
@@ -858,7 +858,7 @@ impl ParameterizedDecode<DapVersion> for Collection {
             report_count: u64::decode(bytes)?,
             interval: match version {
                 DapVersion::Draft02 => None,
-                DapVersion::Draft04 => Some(Interval::decode(bytes)?),
+                DapVersion::Draft05 => Some(Interval::decode(bytes)?),
                 _ => panic!("unimplemented DapVersion"),
             },
             encrypted_agg_shares: decode_u32_items(&(), bytes)?,
@@ -889,7 +889,7 @@ impl ParameterizedEncode<DapVersion> for AggregateShareReq {
                 self.batch_sel.encode_with_param(version, bytes);
                 encode_u16_bytes(bytes, &self.agg_param);
             }
-            DapVersion::Draft04 => {
+            DapVersion::Draft05 => {
                 self.batch_sel.encode_with_param(version, bytes);
                 encode_u32_bytes(bytes, &self.agg_param);
             }
@@ -911,7 +911,7 @@ impl ParameterizedDecode<DapVersion> for AggregateShareReq {
                 BatchSelector::decode_with_param(version, bytes)?,
                 decode_u16_bytes(bytes)?,
             ),
-            DapVersion::Draft04 => (
+            DapVersion::Draft05 => (
                 None,
                 BatchSelector::decode_with_param(version, bytes)?,
                 decode_u32_bytes(bytes)?,
diff --git a/daphne/src/roles.rs b/daphne/src/roles.rs
index 18131da..7bfa3da 100644
--- a/daphne/src/roles.rs
+++ b/daphne/src/roles.rs
@@ -187,7 +187,7 @@ pub trait DapAggregator<S>: HpkeDecrypter + DapReportInitializer + Sized {
 
         let payload = match req.version {
             DapVersion::Draft02 => hpke_config.as_ref().get_encoded(),
-            DapVersion::Draft04 => {
+            DapVersion::Draft05 => {
                 let hpke_config_list = HpkeConfigList {
                     hpke_configs: vec![hpke_config.as_ref().clone()],
                 };
@@ -451,10 +451,10 @@ pub trait DapLeader<S>: DapAuthorizedSender<S> + DapAggregator<S> {
         // from the request path.
         let collect_job_id = match (req.version, &req.resource) {
             (DapVersion::Draft02, DapResource::Undefined) => None,
-            (DapVersion::Draft04, DapResource::CollectionJob(ref collect_job_id)) => {
+            (DapVersion::Draft05, DapResource::CollectionJob(ref collect_job_id)) => {
                 Some(collect_job_id.clone())
             }
-            (DapVersion::Draft04, DapResource::Undefined) => {
+            (DapVersion::Draft05, DapResource::Undefined) => {
                 return Err(DapAbort::BadRequest("undefined resource".into()));
             }
             _ => unreachable!("unhandled resource {:?}", req.resource),
@@ -644,11 +644,11 @@ pub trait DapLeader<S>: DapAuthorizedSender<S> + DapAggregator<S> {
         );
         let agg_share_resp = AggregateShare::get_decoded(&resp.payload)
             .map_err(|e| DapAbort::from_codec_error(e, task_id.clone()))?;
-        // For draft04 and later, the Collection message includes the smallest quantized time
+        // For draft05 and later, the Collection message includes the smallest quantized time
         // interval containing all reports in the batch.
         let interval = match task_config.version {
             DapVersion::Draft02 => None,
-            DapVersion::Draft04 => {
+            DapVersion::Draft05 => {
                 let low = task_config.quantized_time_lower_bound(leader_agg_share.min_time);
                 let high = task_config.quantized_time_upper_bound(leader_agg_share.max_time);
                 Some(Interval {
@@ -847,10 +847,10 @@ pub trait DapHelper<S>: DapAggregator<S> {
                     (DapVersion::Draft02, DapResource::Undefined, Some(ref agg_job_id)) => {
                         MetaAggregationJobId::Draft02(Cow::Borrowed(agg_job_id))
                     }
-                    (DapVersion::Draft04, DapResource::AggregationJob(ref agg_job_id), None) => {
-                        MetaAggregationJobId::Draft04(Cow::Borrowed(agg_job_id))
+                    (DapVersion::Draft05, DapResource::AggregationJob(ref agg_job_id), None) => {
+                        MetaAggregationJobId::Draft05(Cow::Borrowed(agg_job_id))
                     }
-                    (DapVersion::Draft04, DapResource::Undefined, None) => {
+                    (DapVersion::Draft05, DapResource::Undefined, None) => {
                         return Err(DapAbort::BadRequest("undefined resource".into()));
                     }
                     _ => unreachable!("unhandled resource {:?}", req.resource),
@@ -944,10 +944,10 @@ pub trait DapHelper<S>: DapAggregator<S> {
                     (DapVersion::Draft02, DapResource::Undefined, Some(ref agg_job_id)) => {
                         MetaAggregationJobId::Draft02(Cow::Borrowed(agg_job_id))
                     }
-                    (DapVersion::Draft04, DapResource::AggregationJob(ref agg_job_id), None) => {
-                        MetaAggregationJobId::Draft04(Cow::Borrowed(agg_job_id))
+                    (DapVersion::Draft05, DapResource::AggregationJob(ref agg_job_id), None) => {
+                        MetaAggregationJobId::Draft05(Cow::Borrowed(agg_job_id))
                     }
-                    (DapVersion::Draft04, DapResource::Undefined, None) => {
+                    (DapVersion::Draft05, DapResource::Undefined, None) => {
                         return Err(DapAbort::BadRequest("undefined resource".into()));
                     }
                     _ => unreachable!("unhandled resource {:?}", req.resource),
diff --git a/daphne/src/vdaf/mod.rs b/daphne/src/vdaf/mod.rs
index 207199b..b84c579 100644
--- a/daphne/src/vdaf/mod.rs
+++ b/daphne/src/vdaf/mod.rs
@@ -45,9 +45,9 @@ use std::{borrow::Cow, collections::HashSet, convert::TryInto};
 use self::{prio2::prio2_decode_prepare_state, prio3::prio3_decode_prepare_state};
 
 const CTX_INPUT_SHARE_DRAFT02: &[u8] = b"dap-02 input share";
-const CTX_INPUT_SHARE_DRAFT04: &[u8] = b"dap-04 input share";
+const CTX_INPUT_SHARE_DRAFT05: &[u8] = b"dap-05 input share";
 const CTX_AGG_SHARE_DRAFT02: &[u8] = b"dap-02 aggregate share";
-const CTX_AGG_SHARE_DRAFT04: &[u8] = b"dap-04 aggregate share";
+const CTX_AGG_SHARE_DRAFT05: &[u8] = b"dap-05 aggregate share";
 const CTX_ROLE_COLLECTOR: u8 = 0;
 const CTX_ROLE_CLIENT: u8 = 1;
 const CTX_ROLE_LEADER: u8 = 2;
@@ -122,7 +122,7 @@ impl<'req> EarlyReportStateConsumed<'req> {
 
         let input_share_text = match task_config.version {
             DapVersion::Draft02 => CTX_INPUT_SHARE_DRAFT02,
-            DapVersion::Draft04 => CTX_INPUT_SHARE_DRAFT04,
+            DapVersion::Draft05 => CTX_INPUT_SHARE_DRAFT05,
             _ => return Err(unimplemented_version()),
         };
         let n: usize = input_share_text.len();
@@ -159,7 +159,7 @@ impl<'req> EarlyReportStateConsumed<'req> {
                 extensions: vec![],
                 payload: encoded_input_share,
             },
-            DapVersion::Draft04 => match PlaintextInputShare::get_decoded(&encoded_input_share) {
+            DapVersion::Draft05 => match PlaintextInputShare::get_decoded(&encoded_input_share) {
                 Ok(input_share) => input_share,
                 Err(..) => {
                     return Ok(Self::Rejected {
@@ -532,7 +532,7 @@ impl VdafConfig {
 
         let input_share_text = match version {
             DapVersion::Draft02 => CTX_INPUT_SHARE_DRAFT02,
-            DapVersion::Draft04 => CTX_INPUT_SHARE_DRAFT04,
+            DapVersion::Draft05 => CTX_INPUT_SHARE_DRAFT05,
             _ => return Err(unimplemented_version()),
         };
         let n: usize = input_share_text.len();
@@ -1200,7 +1200,7 @@ impl VdafConfig {
     ) -> Result<DapAggregateResult, DapError> {
         let agg_share_text = match version {
             DapVersion::Draft02 => CTX_AGG_SHARE_DRAFT02,
-            DapVersion::Draft04 => CTX_AGG_SHARE_DRAFT04,
+            DapVersion::Draft05 => CTX_AGG_SHARE_DRAFT05,
             _ => return Err(unimplemented_version()),
         };
         let n: usize = agg_share_text.len();
@@ -1262,7 +1262,7 @@ fn produce_encrypted_agg_share(
 
     let agg_share_text = match version {
         DapVersion::Draft02 => CTX_AGG_SHARE_DRAFT02,
-        DapVersion::Draft04 => CTX_AGG_SHARE_DRAFT04,
+        DapVersion::Draft05 => CTX_AGG_SHARE_DRAFT05,
         _ => return Err(unimplemented_version_abort()),
     };
     let n: usize = agg_share_text.len();
diff --git a/daphne_worker/src/config.rs b/daphne_worker/src/config.rs
index c30591d..558873e 100644
--- a/daphne_worker/src/config.rs
+++ b/daphne_worker/src/config.rs
@@ -1109,7 +1109,7 @@ impl<'srv> DaphneWorker<'srv> {
                 let mut r = Cursor::new(payload.as_ref());
                 (TaskId::decode(&mut r).ok(), DapResource::Undefined)
             }
-            DapVersion::Draft04 => {
+            DapVersion::Draft05 => {
                 let task_id = ctx.param("task_id").and_then(TaskId::try_from_base64url);
                 let resource = match media_type {
                     DapMediaType::AggregationJobInitReq
diff --git a/daphne_worker/src/dap.rs b/daphne_worker/src/dap.rs
index 1c21d6d..8357f29 100644
--- a/daphne_worker/src/dap.rs
+++ b/daphne_worker/src/dap.rs
@@ -892,7 +892,7 @@ impl<'srv> DapLeader<DaphneWorkerAuth> for DaphneWorker<'srv> {
 
         let url = task_config.as_ref().leader_url.clone();
 
-        // Note that we always return the draft02 URI, but draft04 and later ignore it.
+        // Note that we always return the draft02 URI, but draft05 and later ignore it.
         let collect_uri = url
             .join(&format!(
                 "collect/task/{}/req/{}",
diff --git a/daphne_worker/src/durable/reports_pending.rs b/daphne_worker/src/durable/reports_pending.rs
index 1dd8b11..93e1edf 100644
--- a/daphne_worker/src/durable/reports_pending.rs
+++ b/daphne_worker/src/durable/reports_pending.rs
@@ -46,7 +46,7 @@ impl PendingReport {
     pub(crate) fn report_id_hex(&self) -> Option<&str> {
         match self.version {
             DapVersion::Draft02 if self.report_hex.len() >= 96 => Some(&self.report_hex[64..96]),
-            DapVersion::Draft04 if self.report_hex.len() >= 32 => Some(&self.report_hex[..32]),
+            DapVersion::Draft05 if self.report_hex.len() >= 32 => Some(&self.report_hex[..32]),
             DapVersion::Unknown => unreachable!("unhandled version {:?}", self.version),
             _ => None,
         }
diff --git a/docker/wrangler.toml b/docker/wrangler.toml
index b7423d4..74da5e6 100644
--- a/docker/wrangler.toml
+++ b/docker/wrangler.toml
@@ -54,7 +54,7 @@ DAP_TASKPROV_LEADER_AUTH = """{
 DAP_TASKPROV_COLLECTOR_AUTH = """{
   "bearer_token": "I am the collector!"
 }""" # SECRET
-DAP_DEFAULT_VERSION = "v04"
+DAP_DEFAULT_VERSION = "v05"
 DAP_TRACING = "debug"
 
 [env.leader.durable_objects]
@@ -131,7 +131,7 @@ DAP_TASKPROV_VDAF_VERIFY_KEY_INIT = "b029a72fa327931a5cb643dcadcaafa098fcbfac07d
 DAP_TASKPROV_LEADER_AUTH = """{
   "bearer_token": "I am the leader!"
 }""" # SECRET
-DAP_DEFAULT_VERSION = "v04"
+DAP_DEFAULT_VERSION = "v05"
 DAP_TRACING = "debug"
 
 [env.helper.durable_objects]


Test patch:
diff --git a/daphne/src/constants_test.rs b/daphne/src/constants_test.rs
index cdebc2f..e088aae 100644
--- a/daphne/src/constants_test.rs
+++ b/daphne/src/constants_test.rs
@@ -70,70 +70,70 @@ fn from_str_for_version() {
         DapMediaType::Collection,
     );
 
-    // draft04, Section 8.1
+    // draft05, Section 8.1
     assert_eq!(
         DapMediaType::from_str_for_version(
-            DapVersion::Draft04,
+            DapVersion::Draft05,
             Some("application/dap-hpke-config-list")
         ),
         DapMediaType::HpkeConfigList
     );
     assert_eq!(
         DapMediaType::from_str_for_version(
-            DapVersion::Draft04,
+            DapVersion::Draft05,
             Some("application/dap-aggregation-job-init-req")
         ),
         DapMediaType::AggregationJobInitReq,
     );
     assert_eq!(
         DapMediaType::from_str_for_version(
-            DapVersion::Draft04,
+            DapVersion::Draft05,
             Some("application/dap-aggregation-job-resp")
         ),
         DapMediaType::AggregationJobResp,
     );
     assert_eq!(
         DapMediaType::from_str_for_version(
-            DapVersion::Draft04,
+            DapVersion::Draft05,
             Some("application/dap-aggregation-job-continue-req")
         ),
         DapMediaType::AggregationJobContinueReq,
     );
     assert_eq!(
         DapMediaType::from_str_for_version(
-            DapVersion::Draft04,
+            DapVersion::Draft05,
             Some("application/dap-aggregate-share-req")
         ),
         DapMediaType::AggregateShareReq,
     );
     assert_eq!(
         DapMediaType::from_str_for_version(
-            DapVersion::Draft04,
+            DapVersion::Draft05,
             Some("application/dap-aggregate-share")
         ),
         DapMediaType::AggregateShare,
     );
     assert_eq!(
         DapMediaType::from_str_for_version(
-            DapVersion::Draft04,
+            DapVersion::Draft05,
             Some("application/dap-collect-req")
         ),
         DapMediaType::CollectReq,
     );
     assert_eq!(
-        DapMediaType::from_str_for_version(DapVersion::Draft04, Some("application/dap-collection")),
+        DapMediaType::from_str_for_version(DapVersion::Draft05, Some("application/dap-collection")),
         DapMediaType::Collection,
     );
 
     // Invalid media type
     assert_eq!(
-        DapMediaType::from_str_for_version(DapVersion::Draft04, Some("blah-blah-blah")),
+        DapMediaType::from_str_for_version(DapVersion::Draft05, Some("blah-blah-blah")),
         DapMediaType::Invalid("blah-blah-blah".into()),
     );
 
     // Missing media type
     assert_eq!(
-        DapMediaType::from_str_for_version(DapVersion::Draft04, None),
+        DapMediaType::from_str_for_version(DapVersion::Draft05, None),
         DapMediaType::Missing,
     );
 }
@@ -142,27 +142,27 @@ fn from_str_for_version() {
 fn round_trip() {
     for (version, media_type) in [
         (DapVersion::Draft02, DapMediaType::AggregationJobInitReq),
-        (DapVersion::Draft04, DapMediaType::AggregationJobInitReq),
+        (DapVersion::Draft05, DapMediaType::AggregationJobInitReq),
         (DapVersion::Draft02, DapMediaType::AggregationJobResp),
-        (DapVersion::Draft04, DapMediaType::AggregationJobResp),
+        (DapVersion::Draft05, DapMediaType::AggregationJobResp),
         (DapVersion::Draft02, DapMediaType::AggregationJobContinueReq),
-        (DapVersion::Draft04, DapMediaType::AggregationJobContinueReq),
+        (DapVersion::Draft05, DapMediaType::AggregationJobContinueReq),
         (
             DapVersion::Draft02,
             DapMediaType::Draft02AggregateContinueResp,
         ),
         (DapVersion::Draft02, DapMediaType::AggregateShareReq),
-        (DapVersion::Draft04, DapMediaType::AggregateShareReq),
+        (DapVersion::Draft05, DapMediaType::AggregateShareReq),
         (DapVersion::Draft02, DapMediaType::AggregateShare),
-        (DapVersion::Draft04, DapMediaType::AggregateShare),
+        (DapVersion::Draft05, DapMediaType::AggregateShare),
         (DapVersion::Draft02, DapMediaType::CollectReq),
-        (DapVersion::Draft04, DapMediaType::CollectReq),
+        (DapVersion::Draft05, DapMediaType::CollectReq),
         (DapVersion::Draft02, DapMediaType::Collection),
-        (DapVersion::Draft04, DapMediaType::Collection),
+        (DapVersion::Draft05, DapMediaType::Collection),
         (DapVersion::Draft02, DapMediaType::HpkeConfigList),
-        (DapVersion::Draft04, DapMediaType::HpkeConfigList),
+        (DapVersion::Draft05, DapMediaType::HpkeConfigList),
         (DapVersion::Draft02, DapMediaType::Report),
-        (DapVersion::Draft04, DapMediaType::Report),
+        (DapVersion::Draft05, DapMediaType::Report),
     ] {
         assert_eq!(
             DapMediaType::from_str_for_version(version, media_type.as_str_for_version(version)),
@@ -183,6 +183,6 @@ fn media_type_for_agg_cont_req() {
 
     assert_eq!(
         DapMediaType::AggregationJobResp,
-        DapMediaType::agg_job_cont_resp_for_version(DapVersion::Draft04)
+        DapMediaType::agg_job_cont_resp_for_version(DapVersion::Draft05)
     );
 }
diff --git a/daphne/src/messages/mod_test.rs b/daphne/src/messages/mod_test.rs
index 38fdaff..0e3452d 100644
--- a/daphne/src/messages/mod_test.rs
+++ b/daphne/src/messages/mod_test.rs
@@ -172,8 +172,8 @@ fn read_agg_job_init_req() {
     };
 
     let got = AggregationJobInitReq::get_decoded_with_param(
-        &DapVersion::Draft04,
-        &want.get_encoded_with_param(&DapVersion::Draft04),
+        &DapVersion::Draft05,
+        &want.get_encoded_with_param(&DapVersion::Draft05),
     )
     .unwrap();
     assert_eq!(got, want);
@@ -225,8 +225,8 @@ fn read_agg_job_cont_req() {
     };
 
     let got = AggregationJobContinueReq::get_decoded_with_param(
-        &DapVersion::Draft04,
-        &want.get_encoded_with_param(&DapVersion::Draft04),
+        &DapVersion::Draft05,
+        &want.get_encoded_with_param(&DapVersion::Draft05),
     )
     .unwrap();
     assert_eq!(got, want);
@@ -261,8 +261,8 @@ fn read_agg_share_req() {
         checksum: [0; 32],
     };
     let got = AggregateShareReq::get_decoded_with_param(
-        &DapVersion::Draft04,
-        &want.get_encoded_with_param(&DapVersion::Draft04),
+        &DapVersion::Draft05,
+        &want.get_encoded_with_param(&DapVersion::Draft05),
     )
     .unwrap();
     assert_eq!(got, want);
diff --git a/daphne/src/roles_test.rs b/daphne/src/roles_test.rs
index 2141386..53eb720 100644
--- a/daphne/src/roles_test.rs
+++ b/daphne/src/roles_test.rs
@@ -635,7 +635,7 @@ async fn handle_agg_job_req_bad_round(version: DapVersion) {
     // Test wrong round
     let req = t
         .gen_test_agg_job_cont_req_with_round(
-            &MetaAggregationJobId::Draft04(Cow::Borrowed(&agg_job_id)),
+            &MetaAggregationJobId::Draft05(Cow::Borrowed(&agg_job_id)),
             Vec::default(),
             Some(2),
         )
@@ -683,7 +683,7 @@ async fn handle_agg_job_req_zero_round(version: DapVersion) {
     // Test wrong round
     let req = t
         .gen_test_agg_job_cont_req_with_round(
-            &MetaAggregationJobId::Draft04(Cow::Borrowed(&agg_job_id)),
+            &MetaAggregationJobId::Draft05(Cow::Borrowed(&agg_job_id)),
             Vec::default(),
             Some(0),
         )
diff --git a/daphne/src/testing.rs b/daphne/src/testing.rs
index 9895666..a0e0f4c 100644
--- a/daphne/src/testing.rs
+++ b/daphne/src/testing.rs
@@ -29,7 +29,7 @@ use prio::codec::Encode;
 use rand::{thread_rng, Rng};
 use serde::{Deserialize, Serialize};
 use std::{
-    borrow::{Borrow, Cow},
+    borrow::Cow,
     collections::{HashMap, HashSet, VecDeque},
     hash::Hash,
     ops::DerefMut,
@@ -44,7 +44,7 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub(crate) enum MetaAggregationJobIdOwned {
     Draft02(Draft02AggregationJobId),
-    Draft04(AggregationJobId),
+    Draft05(AggregationJobId),
 }
 
 impl From<&MetaAggregationJobId<'_>> for MetaAggregationJobIdOwned {
@@ -53,8 +53,8 @@ impl From<&MetaAggregationJobId<'_>> for MetaAggregationJobIdOwned {
             MetaAggregationJobId::Draft02(agg_job_id) => {
                 Self::Draft02(agg_job_id.clone().into_owned())
             }
-            MetaAggregationJobId::Draft04(agg_job_id) => {
-                Self::Draft04(agg_job_id.clone().into_owned())
+            MetaAggregationJobId::Draft05(agg_job_id) => {
+                Self::Draft05(agg_job_id.clone().into_owned())
             }
         }
     }
@@ -679,7 +679,7 @@ impl DapLeader<BearerToken> for MockAggregator {
 
         // Check whether Report has been collected or replayed.
         if let Some(transition_failure) = self
-            .check_report_early_fail(task_id, bucket.borrow(), &report.report_metadata)
+            .check_report_early_fail(task_id, &bucket, &report.report_metadata)
             .await
         {
             return Err(DapError::Transition(transition_failure));
@@ -981,7 +981,7 @@ pub(crate) struct AggStore {
 //
 // and
 //
-//     something_draft04
+//     something_draft05
 //
 // that called something(version) with the appropriate version.
 //
@@ -1005,7 +1005,7 @@ macro_rules! test_versions {
     ($($fname:ident),*) => {
         $(
             test_version! { $fname, Draft02 }
-            test_version! { $fname, Draft04 }
+            test_version! { $fname, Draft05 }
         )*
     };
 }
@@ -1027,7 +1027,7 @@ macro_rules! async_test_versions {
     ($($fname:ident),*) => {
         $(
             async_test_version! { $fname, Draft02 }
-            async_test_version! { $fname, Draft04 }
+            async_test_version! { $fname, Draft05 }
         )*
     };
 }
diff --git a/daphne_worker_test/tests/e2e.rs b/daphne_worker_test/tests/e2e.rs
index d9b3ef6..ba215ca 100644
--- a/daphne_worker_test/tests/e2e.rs
+++ b/daphne_worker_test/tests/e2e.rs
@@ -90,7 +90,7 @@ async fn e2e_leader_endpoint_for_task(version: DapVersion, want_prefix: bool) {
     let expected = if want_prefix {
         format!("/{}/", version.as_ref())
     } else {
-        String::from("/v04/") // Must match DAP_DEFAULT_VERSION
+        String::from("/v05/") // Must match DAP_DEFAULT_VERSION
     };
     assert_eq!(res.endpoint.unwrap(), expected);
 }
@@ -131,7 +131,7 @@ async fn e2e_helper_endpoint_for_task(version: DapVersion, want_prefix: bool) {
     let expected = if want_prefix {
         format!("/{}/", version.as_ref())
     } else {
-        String::from("/v04/") // Must match DAP_DEFAULT_VERSION
+        String::from("/v05/") // Must match DAP_DEFAULT_VERSION
     };
     assert_eq!(res.endpoint.unwrap(), expected);
 }
@@ -317,7 +317,7 @@ async fn e2e_leader_upload(version: DapVersion) {
     );
     let builder = match t.version {
         DapVersion::Draft02 => client.post(url.as_str()),
-        DapVersion::Draft04 => client.put(url.as_str()),
+        DapVersion::Draft05 => client.put(url.as_str()),
         _ => unreachable!("unhandled version {}", t.version),
     };
     let resp = builder
@@ -1154,7 +1154,7 @@ async fn e2e_fixed_size(version: DapVersion, use_current: bool) {
     if version == DapVersion::Draft02 && use_current {
         // The "current batch" isn't a feature in Draft02, but we allow it
         // and immediately return for testing flexibility, as this allows us
-        // to not have a test coverage regression if we add a Draft04 in
+        // to not have a test coverage regression if we add a Draft05 in
         // the future.
         return;
     }
diff --git a/daphne_worker_test/tests/test_runner.rs b/daphne_worker_test/tests/test_runner.rs
index 1273be3..b9f7ed2 100644
--- a/daphne_worker_test/tests/test_runner.rs
+++ b/daphne_worker_test/tests/test_runner.rs
@@ -85,7 +85,7 @@ impl TestRunner {
         // aggregator URL with 127.0.0.1.
         let version_path = match version {
             DapVersion::Draft02 => "v02",
-            DapVersion::Draft04 => "v04",
+            DapVersion::Draft05 => "v05",
             _ => panic!("unimplemented DapVersion"),
         };
         let mut leader_url = Url::parse(&format!("http://leader:8787/{}/", version_path)).unwrap();
@@ -597,7 +597,7 @@ impl TestRunner {
         client: &reqwest::Client,
         report_sel: &DaphneWorkerReportSelector,
     ) -> DapLeaderProcessTelemetry {
-        // Replace path "/v04" with "/internal/process".
+        // Replace path "/v05" with "/internal/process".
         let mut url = self.leader_url.clone();
         url.set_path("internal/process");
 
@@ -628,7 +628,7 @@ impl TestRunner {
         } else {
             self.helper_url.clone()
         };
-        url.set_path(path); // Overwrites the version path (i.e., "/v04")
+        url.set_path(path); // Overwrites the version path (i.e., "/v05")
         let resp = client
             .post(url.clone())
             .json(data)
@@ -691,7 +691,7 @@ impl TestRunner {
     pub fn upload_path_for_task(&self, id: &TaskId) -> String {
         match self.version {
             DapVersion::Draft02 => "upload".to_string(),
-            DapVersion::Draft04 => format!("tasks/{}/reports", id.to_base64url()),
+            DapVersion::Draft05 => format!("tasks/{}/reports", id.to_base64url()),
             _ => unreachable!("unknown version"),
         }
     }
@@ -792,7 +792,7 @@ async fn post_internal_delete_all(
     base_url: &Url,
     batch_interval: &Interval,
 ) {
-    // Replace path "/v04" with "/internal/delete_all".
+    // Replace path "/v05" with "/internal/delete_all".
     let mut url = base_url.clone();
     url.set_path("internal/delete_all");
 
diff --git a/daphne_worker_test/wrangler.toml b/daphne_worker_test/wrangler.toml
index 338a0f2..4d334f8 100644
--- a/daphne_worker_test/wrangler.toml
+++ b/daphne_worker_test/wrangler.toml
@@ -54,7 +54,7 @@ DAP_TASKPROV_LEADER_AUTH = """{
 DAP_TASKPROV_COLLECTOR_AUTH = """{
   "bearer_token": "I am the collector!"
 }""" # SECRET
-DAP_DEFAULT_VERSION = "v04"
+DAP_DEFAULT_VERSION = "v05"
 DAP_TRACING = "debug"
 
 [env.leader.durable_objects]
@@ -131,7 +131,7 @@ DAP_TASKPROV_VDAF_VERIFY_KEY_INIT = "b029a72fa327931a5cb643dcadcaafa098fcbfac07d
 DAP_TASKPROV_LEADER_AUTH = """{
   "bearer_token": "I am the leader!"
 }""" # SECRET
-DAP_DEFAULT_VERSION = "v04"
+DAP_DEFAULT_VERSION = "v05"
 DAP_TRACING = "debug"
 
 [env.helper.durable_objects]