Skip to content

Commit 03eccc4

Browse files
(wip): sketch implementation
1 parent 4cc978c commit 03eccc4

File tree

6 files changed

+443
-143
lines changed

6 files changed

+443
-143
lines changed

notary/src/errors.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,6 @@ pub enum NotaryServerError {
9090
#[error(transparent)]
9191
ProofError(#[from] ProofError),
9292

93-
// TODO: Update to contain feedback
94-
#[error("Manifest-request mismatch")]
95-
ManifestRequestMismatch,
96-
97-
// TODO: Update to contain feedback
98-
#[error("Manifest-response mismatch")]
99-
ManifestResponseMismatch,
100-
10193
#[error("Manifest is missing")]
10294
ManifestMissing,
10395

notary/src/tee.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,8 @@ pub fn create_tee_proof(
244244
response: &NotaryResponse,
245245
State(state): State<Arc<SharedState>>,
246246
) -> Result<TeeProof, NotaryServerError> {
247-
let values = get_legal_notarization_values(manifest, request, response)?;
248247
// TODO(#543): Use these values in the proof
249-
debug!("Extracted values for notarization={:?}", values);
248+
let result = get_legal_notarization_values(manifest, request, response)?;
250249

251250
let manifest_hash = manifest.to_keccak_digest()?;
252251
let to_sign = VerifyOutput {
@@ -268,14 +267,13 @@ fn get_legal_notarization_values(
268267
request: &ManifestRequest,
269268
response: &NotaryResponse,
270269
) -> Result<ExtractionValues, NotaryServerError> {
271-
// Validate manifest first
272-
manifest.validate()?;
270+
let result = manifest.validate_with(request, response)?;
273271

274-
// Check if request matches manifest requirements
275-
if !manifest.request.is_subset_of(request) {
276-
return Err(NotaryServerError::ManifestRequestMismatch);
272+
if !result.is_success() {
273+
info!("Manifest validation failed: {:?}", result.errors());
277274
}
278275

279-
// Check if response matches manifest and extract values
280-
response.match_and_extract(&manifest.response)?.ok_or(NotaryServerError::ManifestResponseMismatch)
276+
info!("Extracted values for notarization={:?}", result.values());
277+
278+
Ok(result.values())
281279
}

web-prover-core/src/http.rs

Lines changed: 115 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ pub use web_proof_circuits_witness_generator::json::JsonKey;
2121

2222
use crate::{
2323
errors::ManifestError,
24-
parser::{DataFormat, ExtractionValues, ExtractorConfig},
24+
manifest::ManifestValidationResult,
25+
parser::{DataFormat, ExtractionResult, ExtractorConfig},
2526
template,
2627
template::TemplateVar,
2728
};
@@ -154,27 +155,29 @@ impl NotaryResponse {
154155
pub fn match_and_extract(
155156
&self,
156157
other: &ManifestResponse,
157-
) -> Result<Option<ExtractionValues>, ManifestError> {
158+
) -> Result<ExtractionResult, ManifestError> {
159+
let mut result = ExtractionResult::default();
160+
158161
// Check basic response properties
159-
if self.response.status != other.status
160-
|| self.response.version != other.version
161-
|| self.response.message != other.message
162-
{
163-
debug!("Exact matches for status, version, or message do not match");
164-
return Ok(None);
162+
if self.response.status != other.status {
163+
result.report_error(&format!(
164+
"Status mismatch: expected={}, actual={}",
165+
other.status, self.response.status
166+
));
165167
}
166-
167-
// Check headers
168-
if !self.headers_match(other) {
169-
return Ok(None);
168+
if self.response.version != other.version {
169+
result.report_error(&format!(
170+
"Version mismatch: expected={}, actual={}",
171+
other.version, self.response.version
172+
));
173+
}
174+
if self.response.message != other.message {
175+
result.report_error(&format!(
176+
"Message mismatch: expected={}, actual={}",
177+
other.version, self.response.version
178+
));
170179
}
171180

172-
// Check body
173-
self.body_matches(other)
174-
}
175-
176-
/// Helper method to check if headers match
177-
fn headers_match(&self, other: &ManifestResponse) -> bool {
178181
for (key, other_value) in &other.headers {
179182
match self
180183
.response
@@ -184,51 +187,58 @@ impl NotaryResponse {
184187
{
185188
Some(actual_value) if actual_value.to_lowercase() == other_value.to_lowercase() => continue,
186189
Some(actual_value) => {
187-
debug!(
188-
"Header mismatch for key: {}: expected={}, actual={}",
189-
key, other_value, actual_value
190-
);
191-
return false;
190+
result.report_error(&format!(
191+
"Header mismatch: expected={}, actual={}",
192+
other_value, actual_value
193+
));
192194
},
193195
None => {
194-
debug!("Header key not present in self: {}", key);
195-
return false;
196+
result.report_error(&format!("Header missing: {}", key));
196197
},
197198
}
198199
}
199-
true
200+
201+
// Check body
202+
let body_result = self.body_matches(other)?;
203+
result.merge(body_result);
204+
205+
// Return combined result
206+
Ok(result)
200207
}
201208

202209
/// Helper method to check if body matches and extract values
203-
fn body_matches(
204-
&self,
205-
other: &ManifestResponse,
206-
) -> Result<Option<ExtractionValues>, ManifestError> {
210+
fn body_matches(&self, other: &ManifestResponse) -> Result<ExtractionResult, ManifestError> {
207211
match &self.notary_response_body.body {
208212
Some(body) => {
209-
let result = other.body.0.extract_and_validate(body)?;
213+
let mut body_result = other.body.0.extract_and_validate(body)?;
210214

211-
if !result.errors.is_empty() {
212-
debug!("Response body does not match: {:?}", result.errors);
213-
return Ok(None);
215+
if !body_result.errors.is_empty() {
216+
debug!("Response body does not match: {:?}", body_result.errors);
217+
body_result.report_error("Response body does not match");
218+
return Ok(body_result);
214219
}
215220

216-
if result.values.len() != other.body.0.extractors.len() {
221+
if body_result.values.len() != other.body.0.extractors.len() {
217222
debug!("Not all extractors were matched");
218-
return Ok(None);
223+
body_result.report_error("Not all extractors were matched");
224+
return Ok(body_result);
219225
}
220226

221227
debug!("Client response matches");
222-
Ok(Some(result.values))
228+
Ok(body_result)
223229
},
224230
None if other.body.0.extractors.is_empty() => {
225231
// If we get here, there was a match but no data
226232
debug!("Client response matches (no data in response body)");
227-
Ok(Some(HashMap::new()))
233+
let mut result = ExtractionResult::default();
234+
result.report_error("No data in response body");
235+
Ok(result)
228236
},
229237
None => {
230238
debug!("No data to match against");
231-
Ok(None)
239+
let mut result = ExtractionResult::default();
240+
result.report_error("No data to match against");
241+
Ok(result)
232242
},
233243
}
234244
}
@@ -502,34 +512,60 @@ impl ManifestRequest {
502512
/// - All headers in `self` must exist in `other` with matching values.
503513
/// - All vars in `self` must exist in `other` with matching constraints.
504514
/// - All remaining fields like `method`, `url`, and `body` must also match.
505-
pub fn is_subset_of(&self, other: &ManifestRequest) -> bool {
515+
pub fn is_subset_of(
516+
&self,
517+
other: &ManifestRequest,
518+
) -> Result<ManifestValidationResult, ManifestError> {
519+
let mut result = ManifestValidationResult::default();
520+
506521
// Check if all headers in `self` exist in `other` with the same value
507522
for (key, value) in &self.headers {
508523
let expected_header =
509524
other.headers.get(key).or_else(|| other.headers.get(&key.to_lowercase()));
510525
if expected_header != Some(value) {
511-
return false;
526+
result.report_error(&format!("Header mismatch: expected={}, actual={}", value, key));
512527
}
513528
}
514529

515-
// TODO: Not sure how to handle `vars` now, so disabling this
516-
// Check if all vars in `self` exist in `other` with the same or compatible constraints
517-
// for (key, var) in &self.vars {
518-
// match other.vars.get(key) {
519-
// Some(other_var) =>
520-
// if var != other_var {
521-
// return false;
522-
// },
523-
// None => {
524-
// return false;
525-
// },
526-
// }
527-
// }
528-
529-
// TODO: Notice that we match body exactly below
530-
// TODO: What to do with the body? Ominous
531-
// self.method == other.method && self.url == other.url && self.body == other.body
532-
self.method == other.method && self.url == other.url
530+
for (key, var) in &self.vars {
531+
match other.vars.get(key) {
532+
Some(other_var) =>
533+
if var != other_var {
534+
result.report_error(&format!("Var mismatch: expected={}, actual={}", var, key));
535+
},
536+
None => {
537+
result.report_error(&format!("Var missing: {}", key));
538+
},
539+
}
540+
}
541+
542+
if self.method != other.method {
543+
result.report_error(&format!(
544+
"Method mismatch: expected={}, actual={}",
545+
other.method, self.method
546+
));
547+
}
548+
549+
if self.url != other.url {
550+
result.report_error(&format!("URL mismatch: expected={}, actual={}", other.url, self.url));
551+
}
552+
553+
if self.version != other.version {
554+
result.report_error(&format!(
555+
"Version mismatch: expected={}, actual={}",
556+
other.version, self.version
557+
));
558+
}
559+
560+
if self.body != other.body {
561+
result.report_error(&format!(
562+
"Body mismatch: expected={:?}, actual={:?}",
563+
other.body.clone(),
564+
self.body.clone()
565+
));
566+
}
567+
568+
Ok(result)
533569
}
534570
}
535571

@@ -553,7 +589,7 @@ pub mod tests {
553589
url: "https://example.com".to_string(),
554590
version: "HTTP/1.1".to_string(),
555591
headers: std::collections::HashMap::from([
556-
("Authorization".to_string(), "Bearer <TOKEN>".to_string()),
592+
("Authorization".to_string(), "Bearer <%TOKEN%>".to_string()),
557593
("User-Agent".to_string(), "test-agent".to_string()),
558594
]),
559595
body: None,
@@ -590,7 +626,20 @@ pub mod tests {
590626
headers: std::collections::HashMap::from([
591627
("Content-Type".to_string(), "application/json".to_string())
592628
]),
593-
body: ManifestResponseBody::default(),
629+
body: ManifestResponseBody {
630+
0: ExtractorConfig {
631+
format: DataFormat::Json,
632+
extractors: vec![crate::parser::Extractor {
633+
id: "dummy".to_string(),
634+
description: "Dummy extractor".to_string(),
635+
selector: vec![],
636+
extractor_type: crate::parser::ExtractorType::String,
637+
required: true,
638+
predicates: vec![],
639+
attribute: None,
640+
}],
641+
},
642+
},
594643
};
595644

596645
// Override default fields with provided arguments
@@ -664,12 +713,12 @@ pub mod tests {
664713

665714
// Is a perfect match with itself
666715
let matching_result = notary_response.match_and_extract(&response).unwrap();
667-
assert!(matching_result.is_some());
668-
assert_eq!(matching_result.unwrap().get("testKey").unwrap(), &json!(3));
716+
assert!(matching_result.is_success());
717+
assert_eq!(matching_result.values.get("testKey").unwrap(), &json!(3));
669718

670719
// Fails if it doesn't match directly
671720
let non_matching_response = response!(status: "201".to_string());
672-
assert!(notary_response.match_and_extract(&non_matching_response).unwrap().is_none());
721+
assert!(!notary_response.match_and_extract(&non_matching_response).unwrap().is_success());
673722

674723
// Superset case
675724
let response_superset = {
@@ -683,7 +732,7 @@ pub mod tests {
683732
));
684733
res
685734
};
686-
assert!(response_superset.match_and_extract(&response).unwrap().is_some());
735+
assert!(response_superset.match_and_extract(&response).unwrap().is_success());
687736
}
688737

689738
#[test]
@@ -786,7 +835,7 @@ pub mod tests {
786835
)],
787836
})
788837
);
789-
assert!(!base_response.match_and_extract(&other_response).unwrap().is_some());
838+
assert!(!base_response.match_and_extract(&other_response).unwrap().is_success());
790839
}
791840

792841
#[test]

0 commit comments

Comments
 (0)