-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for public extensions in Reports. #754
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we're missing one feature: we need to resolve repeated extensions across the public and private extension fields.
So the spec says:
Which I take to mean a conflict between the public and private extensions is allowed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not even a nit, just a comment. I don't have a preference but instead of Vec::new()
you can write vec![]
The intent of the text is: "if the same extension appears twice, then the report MUST be rejected - regardless of what fields the extensions appear in." In particular, if the taskprov extension appears in the public and private fields, then reject. |
692eb78
to
eda9b3c
Compare
eda9b3c
to
5078b99
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks largely correct, though I have some suggestions for behavior changes. I think the tests need a bit of work. Also, I have some suggestions for making the code a little cleaner/easier to read.
@@ -533,6 +537,150 @@ async fn leader_upload_taskprov_wrong_version(version: DapVersion) { | |||
|
|||
async_test_versions!(leader_upload_taskprov_wrong_version); | |||
|
|||
#[tokio::test] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the test coverage in the daphne::roles
module is high enough that we could just as easily move theses tests there. You can call leader::handle_upload_req()
on the mock aggregator, just as you already do in a new test in that module.
Any code path that can be tested without the e2e setup ought to be moved to a unit test, since unit tests are easier to run.
task_id: &TaskId, | ||
unknown_extensions: &[u16], | ||
) -> Result<Self, DapError> { | ||
let detail = serde_json::to_string(&unknown_extensions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary reference
let detail = serde_json::to_string(&unknown_extensions); | |
let detail = serde_json::to_string(unknown_extensions); |
detail: s, | ||
task_id: *task_id, | ||
}), | ||
Err(x) => Err(fatal_error!(err = %x,)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Err(x) => Err(fatal_error!(err = %x,)), | |
Err(x) => Err(fatal_error!(err = %x)), |
task_id: &TaskId, | ||
unknown_extensions: &[u16], | ||
) -> Result<Self, DapError> { | ||
let detail = serde_json::to_string(&unknown_extensions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More Rusty
let detail = serde_json::to_string(&unknown_extensions); | |
let detail = serde_json::to_string(&unknown_extensions).map_err(|e| fatal_error!(err = e))?; |
public_extensions: match version { | ||
DapVersion::Draft09 => None, | ||
DapVersion::Latest => Some(Vec::new()), | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the extensions are replicated between the Leader and Helper, perhaps it makes more sense to include them in the public extensions field rather than in the private extension fields.
If you take this suggestion, let's also rename extensions
to public_extensions
.
} | ||
); | ||
} | ||
test_versions! {handle_unknown_public_extensions_in_report} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: This creates the test for all versions of DAP, including draft 09.
) { | ||
(Some(extensions), DapVersion::Latest) => { | ||
let mut unknown_extensions = Vec::<u16>::new(); | ||
if crate::protocol::no_duplicates(extensions.iter()).is_err() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And use crate::protocol;
. Also, we should rename no_duplicates
to something more distinctive.
if crate::protocol::no_duplicates(extensions.iter()).is_err() { | |
if protocol::no_duplicates(extensions.iter()).is_err() { |
@@ -223,6 +223,47 @@ pub async fn handle_upload_req<A: DapLeader>( | |||
.into()); | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment here telling the reader what's going on.
(Some(_), DapVersion::Draft09) => { | ||
return Err(DapError::Abort(DapAbort::version_mismatch( | ||
DapVersion::Draft09, | ||
DapVersion::Latest, | ||
))) | ||
} | ||
(None, DapVersion::Latest) => { | ||
return Err(DapError::Abort(DapAbort::version_mismatch( | ||
DapVersion::Latest, | ||
DapVersion::Draft09, | ||
))) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure either of these arms could ever be reached, assuming the code that sets public_extensions
is correct. If I were you, I would use the public_extension.is_some()
to deduce which version was negotiated. Tnen we could replace this big ugly match
with:
if let Some(public_extensions) = &report.report_metadata.public_extensions {
... // check for duplicates, unorecgonized values, and so on
}
@@ -1348,6 +1496,116 @@ async fn leader_selected() { | |||
.unwrap(); | |||
} | |||
|
|||
#[tokio::test] | |||
async fn leader_collect_taskprov_repeated_abort() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this new test do?
Draft 13 adds mandatory support for public extensions in the ReportMetadata, but doesn't define any (Taskprov is (for now) a private extension). This PR adds support for rejecting unknown extensions, which is all of them.