From 3b738c949475ec0b801ed0ec51f51630314eea79 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 13 Mar 2025 16:04:35 +0100
Subject: [PATCH 1/4] fix: fix broken fixtures
---
fixture/client.html.tee.json | 84 +++++++++++++++++
fixture/client.html.tee_tcp_local.json | 92 -------------------
...ient.proxy.json => client.json.proxy.json} | 88 +++++++-----------
notary/src/proxy.rs | 28 ++++--
tests/src/lib.rs | 2 +-
5 files changed, 138 insertions(+), 156 deletions(-)
create mode 100644 fixture/client.html.tee.json
delete mode 100644 fixture/client.html.tee_tcp_local.json
rename fixture/{client.proxy.json => client.json.proxy.json} (54%)
diff --git a/fixture/client.html.tee.json b/fixture/client.html.tee.json
new file mode 100644
index 000000000..29f9e0118
--- /dev/null
+++ b/fixture/client.html.tee.json
@@ -0,0 +1,84 @@
+{
+ "mode": "TEE",
+ "notary_host": "localhost",
+ "notary_port": 7443,
+ "notary_ca_cert": "MIIFszCCA5ugAwIBAgIUeXLQmnjeXsHpGji7xA8oJjjw7WwwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0bzEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRowGAYDVQQDDBFMb2NhbGhvc3QgUm9vdCBDQTAeFw0yNDA2MDcyMjUyNDBaFw0yOTA2MDYyMjUyNDBaMGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlQYWxvIEFsdG8xFTATBgNVBAoMDE9yZ2FuaXphdGlvbjEaMBgGA1UEAwwRTG9jYWxob3N0IFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDIHMEL9gVSxT/J0qS4xDkDZs1d1UG0+z6NFLLsGdV7gu0ZJbDPlNd0kpjWsisVNB7TcqWoq5ROK5CR+6lZxXC8nbqr2YAJ2O8mHIXcYv7msAN3UYxtM6v1M7K+vNMJdDjZVAxcOKq5R7uUDUPw1weePz6eVEjntAW8mUjqkfnCqYml943Ud3724SkI5wyUT9rKS3bk6hvneq1ah/b1zRGDF2gp+T/oNe4ieS/LGoIUluE2csGRXtt542gpJnw5L54JASmGgt6hunUSWtoaht7Qxv6hYpieu4iHqZY1kfcFDjDH2WI16g1YqrWHzk1l7vWNLVDEcK3kdSQ1GmYAij8ZjAi0LJizLwtN//EkfxiOPlV435itK3uugY+etxrk77BeA6PmVcpZeLLXYuKSrzfaBh0ifP2p0uRlShURi5Rz4IE0I7wHkZ44x9MKYv8YzXK7O29HD158tgorxqwwKmkHqSxWpp7SRKvNnMulHN/el+IKDrPeBhVXsSSkd6U+/H61q7i0SY9TqqhdiMQLW/efK9LkVRen5myhwqogwiF/42Jp2nrCeuzv5YDsAFSrQ0lukW+Hz7FXV+0axnKeXZ08Nd+IS1BhGyMgHo6PWMP1fWyfO0DJVUfIqrHqvBy8bW0yNOuhiyU2oeyDRKv75OMxpIrUeX3qvmrVcYUPvfXsVQIDAQABo1MwUTAdBgNVHQ4EFgQUlro6UuKRY+lHZ3T4FQMhoQAJ2a8wHwYDVR0jBBgwFoAUlro6UuKRY+lHZ3T4FQMhoQAJ2a8wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEARliSCLdjNI5fFkNwXDK6k6jN5hITrY07XIawUIEwinjQqgLkYFvzXbMtfLwsWmxMPjDVYYDa5Y2NAGcH08b//2z9EuHxMOTOFTKr59BEcVxV1cxV+lspAunH8DLSlLJhf/EeR+MhIIHAfhlE8V7lvlE1EbM+Uj5JYIeefV/4omsGrphyHD3oSJAQDae0su200I/i2yAaTrwXLZ4HtaXsnxKZ4PMPFWaLvMQ8DsLgx2VB3/vQJn74Xepau6mYEWlRnUu90mj79gJOnwBKPlLojF6dJOMIJ2YHr9fI8sUfkVwPFVlkDKJcr0ll5RL3O/naNlLQZuOgijOM5YF5iTrefliVodEHpBPID2mhtq/E+ZIQWLpik8ulsJ8ufN9YfrbjbsiC/KeoMqoFCImRSyMGQDMADo4EV3DNfDFvfrHx0qBMmJ0nkhuGobphegMPCjZ3axvQwQulKuHXmFpAvGYcpK/twBMC1MJkV04tIwVEDZG6id5oKYtrIXHdSFshf6r3z4bbgq6kJnOxZ8Vo4cEw/dgc3hRivr+HnxOJcEk2CTQlCVOiCQAg64OqDEOoswVg6nzoO3RJhFatu+abO22MIXPNGma02zBoQZLYpGzL9z6pMnPKjL15G9H1SYVSTGhmq+GVtdRibg8rLBciSm3ERd7gNRqvYP5GrjCtUIbOTEc=",
+ "target_method": "GET",
+ "target_url": "https://en.wikipedia.org/wiki/Claude_Shannon",
+ "target_headers": {},
+ "target_body": "",
+ "max_sent_data": 10000,
+ "max_recv_data": 10000,
+ "manifest": {
+ "manifestVersion": "1",
+ "id": "wikipedia-claude-shannon",
+ "title": "Wikipedia Claude Shannon",
+ "description": "Generate a proof that you have visited the Claude Shannon Wikipedia page",
+ "prepareUrl": "https://en.wikipedia.org/wiki/Claude_Shannon",
+ "request": {
+ "method": "GET",
+ "version": "HTTP/1.1",
+ "url": "https://en.wikipedia.org/wiki/Claude_Shannon",
+ "headers": {}
+ },
+ "response": {
+ "status": "200",
+ "version": "HTTP/1.1",
+ "message": "OK",
+ "headers": {
+ "Content-Type": "text/html; charset=UTF-8"
+ },
+ "body": {
+ "format": "html",
+ "extractors": [
+ {
+ "id": "pageTitle",
+ "description": "Extract the page title",
+ "selector": [
+ "title"
+ ],
+ "type": "string",
+ "predicates": [
+ {
+ "type": "value",
+ "comparison": "contains",
+ "value": "Claude Shannon"
+ }
+ ]
+ },
+ {
+ "id": "roles",
+ "description": "Extract his professional roles",
+ "selector": [
+ "div#mw-content-text",
+ "div.mw-parser-output",
+ "p",
+ "a"
+ ],
+ "type": "array",
+ "predicates": [
+ {
+ "type": "value",
+ "comparison": "contains",
+ "value": "mathematician",
+ "case_sensitive": false
+ },
+ {
+ "type": "value",
+ "comparison": "contains",
+ "value": "electrical engineer",
+ "case_sensitive": false
+ },
+ {
+ "type": "value",
+ "comparison": "contains",
+ "value": "cryptographer",
+ "case_sensitive": false
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/fixture/client.html.tee_tcp_local.json b/fixture/client.html.tee_tcp_local.json
deleted file mode 100644
index 41555a9da..000000000
--- a/fixture/client.html.tee_tcp_local.json
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "mode": "TEE",
- "notary_host": "localhost",
- "notary_port": 7443,
- "notary_ca_cert": "MIIFszCCA5ugAwIBAgIUeXLQmnjeXsHpGji7xA8oJjjw7WwwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0bzEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRowGAYDVQQDDBFMb2NhbGhvc3QgUm9vdCBDQTAeFw0yNDA2MDcyMjUyNDBaFw0yOTA2MDYyMjUyNDBaMGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlQYWxvIEFsdG8xFTATBgNVBAoMDE9yZ2FuaXphdGlvbjEaMBgGA1UEAwwRTG9jYWxob3N0IFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDIHMEL9gVSxT/J0qS4xDkDZs1d1UG0+z6NFLLsGdV7gu0ZJbDPlNd0kpjWsisVNB7TcqWoq5ROK5CR+6lZxXC8nbqr2YAJ2O8mHIXcYv7msAN3UYxtM6v1M7K+vNMJdDjZVAxcOKq5R7uUDUPw1weePz6eVEjntAW8mUjqkfnCqYml943Ud3724SkI5wyUT9rKS3bk6hvneq1ah/b1zRGDF2gp+T/oNe4ieS/LGoIUluE2csGRXtt542gpJnw5L54JASmGgt6hunUSWtoaht7Qxv6hYpieu4iHqZY1kfcFDjDH2WI16g1YqrWHzk1l7vWNLVDEcK3kdSQ1GmYAij8ZjAi0LJizLwtN//EkfxiOPlV435itK3uugY+etxrk77BeA6PmVcpZeLLXYuKSrzfaBh0ifP2p0uRlShURi5Rz4IE0I7wHkZ44x9MKYv8YzXK7O29HD158tgorxqwwKmkHqSxWpp7SRKvNnMulHN/el+IKDrPeBhVXsSSkd6U+/H61q7i0SY9TqqhdiMQLW/efK9LkVRen5myhwqogwiF/42Jp2nrCeuzv5YDsAFSrQ0lukW+Hz7FXV+0axnKeXZ08Nd+IS1BhGyMgHo6PWMP1fWyfO0DJVUfIqrHqvBy8bW0yNOuhiyU2oeyDRKv75OMxpIrUeX3qvmrVcYUPvfXsVQIDAQABo1MwUTAdBgNVHQ4EFgQUlro6UuKRY+lHZ3T4FQMhoQAJ2a8wHwYDVR0jBBgwFoAUlro6UuKRY+lHZ3T4FQMhoQAJ2a8wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEARliSCLdjNI5fFkNwXDK6k6jN5hITrY07XIawUIEwinjQqgLkYFvzXbMtfLwsWmxMPjDVYYDa5Y2NAGcH08b//2z9EuHxMOTOFTKr59BEcVxV1cxV+lspAunH8DLSlLJhf/EeR+MhIIHAfhlE8V7lvlE1EbM+Uj5JYIeefV/4omsGrphyHD3oSJAQDae0su200I/i2yAaTrwXLZ4HtaXsnxKZ4PMPFWaLvMQ8DsLgx2VB3/vQJn74Xepau6mYEWlRnUu90mj79gJOnwBKPlLojF6dJOMIJ2YHr9fI8sUfkVwPFVlkDKJcr0ll5RL3O/naNlLQZuOgijOM5YF5iTrefliVodEHpBPID2mhtq/E+ZIQWLpik8ulsJ8ufN9YfrbjbsiC/KeoMqoFCImRSyMGQDMADo4EV3DNfDFvfrHx0qBMmJ0nkhuGobphegMPCjZ3axvQwQulKuHXmFpAvGYcpK/twBMC1MJkV04tIwVEDZG6id5oKYtrIXHdSFshf6r3z4bbgq6kJnOxZ8Vo4cEw/dgc3hRivr+HnxOJcEk2CTQlCVOiCQAg64OqDEOoswVg6nzoO3RJhFatu+abO22MIXPNGma02zBoQZLYpGzL9z6pMnPKjL15G9H1SYVSTGhmq+GVtdRibg8rLBciSm3ERd7gNRqvYP5GrjCtUIbOTEc=",
- "target_method": "GET",
- "target_url": "https://en.wikipedia.org/wiki/Claude_Shannon",
- "target_headers": {},
- "target_body": "",
- "max_sent_data": 10000,
- "max_recv_data": 10000,
- "proving": {
- "manifest": {
- "manifestVersion": "2",
- "id": "wikipedia-claude-shannon",
- "title": "Wikipedia Claude Shannon",
- "description": "Generate a proof that you have visited the Claude Shannon Wikipedia page",
- "prepareUrl": "https://en.wikipedia.org/wiki/Claude_Shannon",
- "request": {
- "method": "GET",
- "version": "HTTP/1.1",
- "url": "https://en.wikipedia.org/wiki/Claude_Shannon",
- "headers": {
- "accept-encoding": "identity",
- "host": "en.wikipedia.org",
- "connection": "close",
- "accept": "*/*",
- "authorization": "Bearer <% accessToken %>"
- },
- "vars": {
- "accessToken": {
- "description": "Spotify access token",
- "required": true,
- "pattern": "^[A-Za-z0-9_-]+$"
- }
- }
- },
- "response": {
- "status": "200",
- "version": "HTTP/1.1",
- "message": "OK",
- "headers": {
- "Content-Type": "text/html; charset=UTF-8"
- },
- "body": {
- "format": "html",
- "extractors": [
- {
- "id": "pageTitle",
- "description": "Extract the page title",
- "selector": ["title"],
- "type": "string",
- "predicates": [
- {
- "type": "value",
- "comparison": "contains",
- "value": "Claude Shannon"
- }
- ]
- },
- {
- "id": "roles",
- "description": "Extract his professional roles",
- "selector": ["div#mw-content-text", "div.mw-parser-output", "p", "a"],
- "type": "array",
- "predicates": [
- {
- "type": "value",
- "comparison": "contains",
- "value": "mathematician",
- "case_sensitive": false
- },
- {
- "type": "value",
- "comparison": "contains",
- "value": "electrical engineer",
- "case_sensitive": false
- },
- {
- "type": "value",
- "comparison": "contains",
- "value": "cryptographer",
- "case_sensitive": false
- }
- ]
- }
- ]
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/fixture/client.proxy.json b/fixture/client.json.proxy.json
similarity index 54%
rename from fixture/client.proxy.json
rename to fixture/client.json.proxy.json
index 4b387f458..b5803d462 100644
--- a/fixture/client.proxy.json
+++ b/fixture/client.json.proxy.json
@@ -3,62 +3,40 @@
"notary_port": 7443,
"notary_ca_cert": "MIIFszCCA5ugAwIBAgIUeXLQmnjeXsHpGji7xA8oJjjw7WwwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0bzEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRowGAYDVQQDDBFMb2NhbGhvc3QgUm9vdCBDQTAeFw0yNDA2MDcyMjUyNDBaFw0yOTA2MDYyMjUyNDBaMGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlQYWxvIEFsdG8xFTATBgNVBAoMDE9yZ2FuaXphdGlvbjEaMBgGA1UEAwwRTG9jYWxob3N0IFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDIHMEL9gVSxT/J0qS4xDkDZs1d1UG0+z6NFLLsGdV7gu0ZJbDPlNd0kpjWsisVNB7TcqWoq5ROK5CR+6lZxXC8nbqr2YAJ2O8mHIXcYv7msAN3UYxtM6v1M7K+vNMJdDjZVAxcOKq5R7uUDUPw1weePz6eVEjntAW8mUjqkfnCqYml943Ud3724SkI5wyUT9rKS3bk6hvneq1ah/b1zRGDF2gp+T/oNe4ieS/LGoIUluE2csGRXtt542gpJnw5L54JASmGgt6hunUSWtoaht7Qxv6hYpieu4iHqZY1kfcFDjDH2WI16g1YqrWHzk1l7vWNLVDEcK3kdSQ1GmYAij8ZjAi0LJizLwtN//EkfxiOPlV435itK3uugY+etxrk77BeA6PmVcpZeLLXYuKSrzfaBh0ifP2p0uRlShURi5Rz4IE0I7wHkZ44x9MKYv8YzXK7O29HD158tgorxqwwKmkHqSxWpp7SRKvNnMulHN/el+IKDrPeBhVXsSSkd6U+/H61q7i0SY9TqqhdiMQLW/efK9LkVRen5myhwqogwiF/42Jp2nrCeuzv5YDsAFSrQ0lukW+Hz7FXV+0axnKeXZ08Nd+IS1BhGyMgHo6PWMP1fWyfO0DJVUfIqrHqvBy8bW0yNOuhiyU2oeyDRKv75OMxpIrUeX3qvmrVcYUPvfXsVQIDAQABo1MwUTAdBgNVHQ4EFgQUlro6UuKRY+lHZ3T4FQMhoQAJ2a8wHwYDVR0jBBgwFoAUlro6UuKRY+lHZ3T4FQMhoQAJ2a8wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEARliSCLdjNI5fFkNwXDK6k6jN5hITrY07XIawUIEwinjQqgLkYFvzXbMtfLwsWmxMPjDVYYDa5Y2NAGcH08b//2z9EuHxMOTOFTKr59BEcVxV1cxV+lspAunH8DLSlLJhf/EeR+MhIIHAfhlE8V7lvlE1EbM+Uj5JYIeefV/4omsGrphyHD3oSJAQDae0su200I/i2yAaTrwXLZ4HtaXsnxKZ4PMPFWaLvMQ8DsLgx2VB3/vQJn74Xepau6mYEWlRnUu90mj79gJOnwBKPlLojF6dJOMIJ2YHr9fI8sUfkVwPFVlkDKJcr0ll5RL3O/naNlLQZuOgijOM5YF5iTrefliVodEHpBPID2mhtq/E+ZIQWLpik8ulsJ8ufN9YfrbjbsiC/KeoMqoFCImRSyMGQDMADo4EV3DNfDFvfrHx0qBMmJ0nkhuGobphegMPCjZ3axvQwQulKuHXmFpAvGYcpK/twBMC1MJkV04tIwVEDZG6id5oKYtrIXHdSFshf6r3z4bbgq6kJnOxZ8Vo4cEw/dgc3hRivr+HnxOJcEk2CTQlCVOiCQAg64OqDEOoswVg6nzoO3RJhFatu+abO22MIXPNGma02zBoQZLYpGzL9z6pMnPKjL15G9H1SYVSTGhmq+GVtdRibg8rLBciSm3ERd7gNRqvYP5GrjCtUIbOTEc=",
"target_body": "",
- "proving": {
- "manifest": {
- "manifestVersion": "1",
- "id": "reddit-user-karma",
- "title": "Total Reddit Karma",
- "description": "Generate a proof that you have a certain amount of karma",
- "prepareUrl": "https://www.reddit.com/login/",
- "request": {
- "method": "GET",
- "version": "HTTP/1.1",
- "url": "https://gist.githubusercontent.com/mattes/23e64faadb5fd4b5112f379903d2572e/raw/74e517a60c21a5c11d94fec8b572f68addfade39/example.json",
- "headers": {
- },
- "body": {
- "userId": "<% userId %>"
- },
- "vars": {
- "userId": {
- "description": "Reddit username",
- "required": true,
- "pattern": "^[A-Za-z0-9_-]{3,20}$"
- },
- "authToken": {
- "description": "Authentication token",
- "required": false,
- "default": "abcdef1234567890abcdef1234567890",
- "pattern": "^[A-Za-z0-9]{32}$"
- }
- },
- "extra": {
- "headers": {
- "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36",
- "Content-Type": "application/json"
- }
- }
+ "target_method": "GET",
+ "target_url": "https://gist.githubusercontent.com/mattes/23e64faadb5fd4b5112f379903d2572e/raw/74e517a60c21a5c11d94fec8b572f68addfade39/example.json",
+ "target_headers": {},
+ "manifest": {
+ "manifestVersion": "1",
+ "id": "hello-world",
+ "title": "Hello World example",
+ "description": "Prove that a gist contains a hello world message",
+ "prepareUrl": "https://gist.githubusercontent.com/mattes/23e64faadb5fd4b5112f379903d2572e/raw/74e517a60c21a5c11d94fec8b572f68addfade39/example.json",
+ "request": {
+ "method": "GET",
+ "version": "HTTP/1.1",
+ "url": "https://gist.githubusercontent.com/mattes/23e64faadb5fd4b5112f379903d2572e/raw/74e517a60c21a5c11d94fec8b572f68addfade39/example.json",
+ "headers": {}
+ },
+ "response": {
+ "status": "200",
+ "version": "HTTP/1.1",
+ "message": "OK",
+ "headers": {
+ "Content-Type": "text/plain; charset=utf-8"
},
- "response": {
- "status": "200",
- "version": "HTTP/1.1",
- "message": "OK",
- "headers": {
- "Content-Type": "text/plain; charset=utf-8"
- },
- "body": {
- "format": "json",
- "extractors": [
- {
- "id": "helloValue",
- "description": "Extract the hello value",
- "selector": [
- "hello"
- ],
- "type": "string"
- }
- ]
- }
+ "body": {
+ "format": "json",
+ "extractors": [
+ {
+ "id": "helloValue",
+ "description": "Extract the hello value",
+ "selector": [
+ "hello"
+ ],
+ "type": "string"
+ }
+ ]
}
}
}
diff --git a/notary/src/proxy.rs b/notary/src/proxy.rs
index 3f24c2847..76a0c8a98 100644
--- a/notary/src/proxy.rs
+++ b/notary/src/proxy.rs
@@ -7,7 +7,7 @@ use axum::{
use reqwest::{Request, Response};
use serde::Deserialize;
use serde_json::Value;
-use tracing::info;
+use tracing::{debug, info};
use uuid::Uuid;
use web_prover_core::{
hash::keccak_digest,
@@ -19,10 +19,11 @@ use web_prover_core::{
};
use crate::{
- error::NotaryServerError,
+ error::{NotaryServerError, ProxyError},
verifier::{sign_verification, VerifyOutput},
SharedState,
};
+
#[derive(Deserialize)]
pub struct NotarizeQuery {
session_id: Uuid,
@@ -54,7 +55,7 @@ pub async fn proxy(
let request = from_reqwest_request(&reqwest_request);
// debug!("{:?}", request);
- let response = from_reqwest_response(reqwest_response).await;
+ let response = from_reqwest_response(reqwest_response).await?;
// debug!("{:?}", response);
let tee_proof = create_tee_proof(&payload.manifest, &request, &response, State(state))?;
@@ -64,7 +65,7 @@ pub async fn proxy(
// TODO: This, similarly to other from_* methods, should be a trait
// Requires adding reqwest to proofs crate
-async fn from_reqwest_response(response: Response) -> NotaryResponse {
+async fn from_reqwest_response(response: Response) -> Result {
let status = response.status().as_u16().to_string();
let version = format!("{:?}", response.version());
let message = response.status().canonical_reason().unwrap_or("").to_string();
@@ -73,8 +74,17 @@ async fn from_reqwest_response(response: Response) -> NotaryResponse {
.iter()
.map(|(k, v)| (capitalize_header(k.as_ref()), v.to_str().unwrap_or("").to_string()))
.collect();
- let json = response.json().await.ok();
- NotaryResponse {
+ let body = response
+ .bytes()
+ .await
+ .map_err(|_| {
+ NotaryServerError::ProxyError(ProxyError::Io(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ "Failed to read response body",
+ )))
+ })?
+ .to_vec();
+ Ok(NotaryResponse {
response: ManifestResponse {
status,
version,
@@ -83,8 +93,9 @@ async fn from_reqwest_response(response: Response) -> NotaryResponse {
// TODO: This makes me think that perhaps this should be an optional field or something else
body: ManifestResponseBody::default(),
},
- notary_response_body: NotaryResponseBody { body: json },
- }
+ // TODO: Should we remove Option<_> on body?
+ notary_response_body: NotaryResponseBody { body: Some(body) },
+ })
}
fn from_reqwest_request(request: &Request) -> ManifestRequest {
@@ -142,6 +153,7 @@ fn validate_notarization_legal(
request: &ManifestRequest,
response: &NotaryResponse,
) -> Result {
+ debug!("Validating manifest");
let result = manifest.validate_with(request, response)?;
if !result.is_success() {
info!("Manifest validation failed: {:?}", result.errors());
diff --git a/tests/src/lib.rs b/tests/src/lib.rs
index 6af5fced7..3df20d2fb 100644
--- a/tests/src/lib.rs
+++ b/tests/src/lib.rs
@@ -146,7 +146,7 @@ impl TestSetup {
Command::new("cargo")
.args(["run", "-p", "client", "--"])
.arg("--config")
- .arg(workspace_root.join("fixture/client.proxy.json"))
+ .arg(workspace_root.join("../../fixture/client.json.proxy.json"))
.env("RUST_LOG", "DEBUG")
.current_dir(&workspace_root)
.stdout(Stdio::piped())
From 8c3ee5cfad9322a10f3c5d5e5b13300e4c70ab6d Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 13 Mar 2025 22:12:33 +0100
Subject: [PATCH 2/4] (wip): refactor into consts
---
tests/src/lib.rs | 75 +++++++++++++++++++++++++++++-------------------
1 file changed, 45 insertions(+), 30 deletions(-)
diff --git a/tests/src/lib.rs b/tests/src/lib.rs
index 3df20d2fb..71fbc2618 100644
--- a/tests/src/lib.rs
+++ b/tests/src/lib.rs
@@ -12,6 +12,25 @@ use std::{
use tokio::time::{sleep, timeout};
+// File paths
+const NOTARY_CONFIG_PATH: &str = "fixture/notary-config.toml";
+const CLIENT_CONFIG_PATH: &str = "fixture/client.proxy.json";
+const RELEASE_DIR: &str = "target/release";
+
+// Binary names
+const NOTARY_BIN: &str = "web-prover-notary";
+const CLIENT_BIN: &str = "web-prover-client";
+
+// Timeouts and delays
+const NOTARY_READY_TIMEOUT: Duration = Duration::from_secs(60);
+const PROVING_TIMEOUT: Duration = Duration::from_secs(60);
+const NOTARY_STARTUP_DELAY: Duration = Duration::from_secs(5);
+const POLL_INTERVAL: Duration = Duration::from_millis(100);
+
+// Log messages
+const NOTARY_READY_MSG: &str = "Listening on https://0.0.0.0:7443";
+const PROVING_SUCCESS_MSG: &str = "Proving Successful";
+
struct TestSetup {
notary: Child,
client: Child,
@@ -37,14 +56,14 @@ impl TestSetup {
println!("Workspace root: {:?}", workspace_root);
// Check for pre-built binaries in target/release
- let notary_bin = workspace_root.join("target/release/notary");
- let client_bin = workspace_root.join("target/release/client");
+ let notary_bin = workspace_root.join(RELEASE_DIR).join(NOTARY_BIN);
+ let client_bin = workspace_root.join(RELEASE_DIR).join(CLIENT_BIN);
let use_prebuilt = notary_bin.exists() && client_bin.exists();
println!("Using pre-built binaries: {}", use_prebuilt);
// Print the config file content for debugging
- let notary_config_path = workspace_root.join("fixture/notary-config.toml");
+ let notary_config_path = workspace_root.join(NOTARY_CONFIG_PATH);
if notary_config_path.exists() {
match std::fs::read_to_string(¬ary_config_path) {
Ok(content) => println!("Notary config content:\n{}", content),
@@ -54,15 +73,14 @@ impl TestSetup {
println!("Notary config file not found at {:?}", notary_config_path);
}
- // This matches exactly what worked in your shell script
+ // Start notary
let mut notary = if use_prebuilt {
- // Change directory to workspace root first
std::env::set_current_dir(&workspace_root).unwrap();
println!("Current directory: {:?}", std::env::current_dir().unwrap());
- let cmd = Command::new("./target/release/notary")
+ let cmd = Command::new(format!("./{}/{}", RELEASE_DIR, NOTARY_BIN))
.arg("--config")
- .arg("./fixture/notary-config.toml")
+ .arg(format!("./{}", NOTARY_CONFIG_PATH))
.env("RUST_LOG", "DEBUG")
.stdout(Stdio::piped())
.stderr(Stdio::piped())
@@ -73,7 +91,7 @@ impl TestSetup {
cmd
} else {
Command::new("cargo")
- .args(["run", "-p", "notary", "--release", "--"])
+ .args(["run", "-p", NOTARY_BIN, "--release", "--"])
.arg("--config")
.arg(notary_config_path)
.env("RUST_LOG", "DEBUG")
@@ -100,7 +118,7 @@ impl TestSetup {
for line in stdout_reader.lines().chain(stderr_reader.lines()) {
if let Ok(line) = line {
println!("Notary: {}", line);
- if line.contains("Listening on https://0.0.0.0:7443") {
+ if line.contains(NOTARY_READY_MSG) {
ready_flag_clone.store(true, Ordering::SeqCst);
break;
}
@@ -109,13 +127,11 @@ impl TestSetup {
});
// Wait for notary to be ready with a timeout, or sleep 10 seconds like the original workflow
- match timeout(Duration::from_secs(60), async {
+ match timeout(NOTARY_READY_TIMEOUT, async {
while !ready_flag.load(Ordering::SeqCst) {
- sleep(Duration::from_millis(100)).await;
+ sleep(POLL_INTERVAL).await;
}
-
- // Add extra delay to match original workflow
- sleep(Duration::from_secs(5)).await;
+ sleep(NOTARY_STARTUP_DELAY).await;
})
.await
{
@@ -126,14 +142,13 @@ impl TestSetup {
},
}
- // Start client with exact same pattern as the working workflow
+ // Start client
let client = if use_prebuilt {
- // We're already in workspace_root directory
println!("Current directory before client: {:?}", std::env::current_dir().unwrap());
- let cmd = Command::new("./target/release/client")
+ let cmd = Command::new(format!("./{}/{}", RELEASE_DIR, CLIENT_BIN))
.arg("--config")
- .arg("./fixture/client.proxy.json")
+ .arg(format!("./{}", CLIENT_CONFIG_PATH))
.env("RUST_LOG", "DEBUG")
.stdout(Stdio::piped())
.stderr(Stdio::piped())
@@ -144,9 +159,9 @@ impl TestSetup {
cmd
} else {
Command::new("cargo")
- .args(["run", "-p", "client", "--"])
+ .args(["run", "-p", CLIENT_BIN, "--"])
.arg("--config")
- .arg(workspace_root.join("../../fixture/client.json.proxy.json"))
+ .arg(workspace_root.join(CLIENT_CONFIG_PATH))
.env("RUST_LOG", "DEBUG")
.current_dir(&workspace_root)
.stdout(Stdio::piped())
@@ -173,35 +188,35 @@ async fn test_proving_successful() {
let stdout = BufReader::new(setup.client.stdout.take().unwrap());
let stderr = BufReader::new(setup.client.stderr.take().unwrap());
- // Wait for proving successful with timeout
- let result = timeout(Duration::from_secs(60), async {
+ let result = timeout(PROVING_TIMEOUT, async {
let mut stdout_lines = stdout.lines();
let mut stderr_lines = stderr.lines();
loop {
- // Check stdout
if let Some(Ok(line)) = stdout_lines.next() {
println!("Client stdout: {}", line);
- if line.contains("Proving Successful") {
+ if line.contains(PROVING_SUCCESS_MSG) {
return true;
}
}
- // Check stderr
if let Some(Ok(line)) = stderr_lines.next() {
println!("Client stderr: {}", line);
- if line.contains("Proving Successful") {
+ if line.contains(PROVING_SUCCESS_MSG) {
return true;
}
}
- // Small sleep to avoid busy waiting
- sleep(Duration::from_millis(10)).await;
+ sleep(POLL_INTERVAL).await;
}
})
.await;
match result {
- Ok(found) => assert!(found, "Did not find 'Proving Successful' in output"),
- Err(_) => panic!("Timed out waiting for 'Proving Successful' after 60 seconds"),
+ Ok(found) => assert!(found, "Did not find '{}' in output", PROVING_SUCCESS_MSG),
+ Err(_) => panic!(
+ "Timed out waiting for '{}' after {} seconds",
+ PROVING_SUCCESS_MSG,
+ PROVING_TIMEOUT.as_secs()
+ ),
}
}
From ee12dfd227fcec10e1467cfa23c4bdeeab961ab1 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Fri, 14 Mar 2025 08:50:22 +0100
Subject: [PATCH 3/4] (wip): test works
---
tests/src/lib.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/src/lib.rs b/tests/src/lib.rs
index 71fbc2618..1b541e60c 100644
--- a/tests/src/lib.rs
+++ b/tests/src/lib.rs
@@ -14,7 +14,7 @@ use tokio::time::{sleep, timeout};
// File paths
const NOTARY_CONFIG_PATH: &str = "fixture/notary-config.toml";
-const CLIENT_CONFIG_PATH: &str = "fixture/client.proxy.json";
+const CLIENT_CONFIG_PATH: &str = "fixture/client.json.proxy.json";
const RELEASE_DIR: &str = "target/release";
// Binary names
From d349e6fbfc23bec2fa9a53f2f3301778097890b9 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Fri, 14 Mar 2025 09:55:41 +0100
Subject: [PATCH 4/4] feat!: return notary errors to client
---
client/src/lib.rs | 10 +++++-----
client/src/main.rs | 10 ++++++++--
core/src/proof.rs | 6 ++++++
notary/src/proxy.rs | 44 ++++++++++++++++++++------------------------
tests/src/lib.rs | 15 +++++++++++----
5 files changed, 50 insertions(+), 35 deletions(-)
diff --git a/client/src/lib.rs b/client/src/lib.rs
index 69ec1cb45..7700822fd 100644
--- a/client/src/lib.rs
+++ b/client/src/lib.rs
@@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
use tracing::debug;
use web_prover_core::{
manifest::Manifest,
- proof::{SignedVerificationReply, TeeProof},
+ proof::{NotarizationResult, SignedVerificationReply},
};
use crate::error::WebProverClientError;
@@ -21,7 +21,7 @@ pub struct ProxyConfig {
pub manifest: Manifest,
}
-pub async fn proxy(config: config::Config) -> Result {
+pub async fn proxy(config: config::Config) -> Result {
let session_id = config.session_id.clone();
let url = format!(
@@ -50,8 +50,8 @@ pub async fn proxy(config: config::Config) -> Result().await?;
- Ok(tee_proof)
+ let notarization_result = response.json::().await?;
+ Ok(notarization_result)
}
pub async fn verify(
@@ -75,7 +75,7 @@ pub async fn verify(
};
let response = client.post(url).json(&verify_body).send().await?;
- assert!(response.status() == hyper::StatusCode::OK, "response={:?}", response);
+ assert_eq!(response.status(), hyper::StatusCode::OK, "response={:?}", response);
let verify_response = response.json::().await?;
debug!("\n{:?}\n\n", verify_response.clone());
diff --git a/client/src/main.rs b/client/src/main.rs
index 9c828f96b..5155b023e 100644
--- a/client/src/main.rs
+++ b/client/src/main.rs
@@ -32,8 +32,14 @@ async fn main() -> Result<(), WebProverClientError> {
let mut config: Config = serde_json::from_str(&config_json)?;
config.set_session_id();
- let proof = web_prover_client::proxy(config).await?;
- let proof_json = serde_json::to_string_pretty(&proof)?;
+ let result = web_prover_client::proxy(config).await?;
+
+ if result.errors.is_some() {
+ println!("Proving Failed: {:?}", result.errors);
+ return Ok(());
+ }
+
+ let proof_json = serde_json::to_string_pretty(&result.tee_proof)?;
println!("Proving Successful: proof_len={:?}", proof_json.len());
Ok(())
}
diff --git a/core/src/proof.rs b/core/src/proof.rs
index 33d8b5986..4fe12a475 100644
--- a/core/src/proof.rs
+++ b/core/src/proof.rs
@@ -35,3 +35,9 @@ impl TryFrom for Vec {
pub struct TeeProofData {
pub manifest_hash: Vec,
}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct NotarizationResult {
+ pub tee_proof: Option,
+ pub errors: Option>,
+}
diff --git a/notary/src/proxy.rs b/notary/src/proxy.rs
index 76a0c8a98..77f43ee1a 100644
--- a/notary/src/proxy.rs
+++ b/notary/src/proxy.rs
@@ -14,8 +14,8 @@ use web_prover_core::{
http::{
ManifestRequest, ManifestResponse, ManifestResponseBody, NotaryResponse, NotaryResponseBody,
},
- manifest::{Manifest, ManifestValidationResult},
- proof::{TeeProof, TeeProofData},
+ manifest::Manifest,
+ proof::{NotarizationResult, TeeProof, TeeProofData},
};
use crate::{
@@ -33,7 +33,7 @@ pub async fn proxy(
query: Query,
State(state): State>,
extract::Json(payload): extract::Json,
-) -> Result, NotaryServerError> {
+) -> Result, NotaryServerError> {
let session_id = query.session_id;
info!("Starting proxy with ID: {}", session_id);
@@ -58,9 +58,9 @@ pub async fn proxy(
let response = from_reqwest_response(reqwest_response).await?;
// debug!("{:?}", response);
- let tee_proof = create_tee_proof(&payload.manifest, &request, &response, State(state))?;
+ let notarization_result = create_tee_proof(&payload.manifest, &request, &response, State(state))?;
- Ok(Json(tee_proof))
+ Ok(Json(notarization_result))
}
// TODO: This, similarly to other from_* methods, should be a trait
@@ -124,13 +124,21 @@ fn capitalize_header(header: &str) -> String {
.join("-")
}
+/// Check if `manifest`, `request`, and `response` all fulfill requirements necessary for
+/// a proof to be created.
pub fn create_tee_proof(
manifest: &Manifest,
request: &ManifestRequest,
response: &NotaryResponse,
State(state): State>,
-) -> Result {
- let validation_result = validate_notarization_legal(manifest, request, response)?;
+) -> Result {
+ debug!("Validating manifest");
+ let validation_result = manifest.validate_with(request, response)?;
+ if !validation_result.is_success() {
+ info!("Manifest validation failed: {:?}", validation_result.errors());
+ return Ok(NotarizationResult { tee_proof: None, errors: Some(validation_result.errors()) });
+ }
+ info!("Manifest returned values: {:?}", validation_result.values());
let manifest_hash = manifest.to_keccak_digest()?;
let extraction_hash = validation_result.extraction_keccak_digest()?;
@@ -142,22 +150,10 @@ pub fn create_tee_proof(
};
let signature = sign_verification(to_sign, State(state))?;
let data = TeeProofData { manifest_hash: manifest_hash.to_vec() };
+ let proof = TeeProof { data, signature };
+ debug!("Created proof: {:?}", proof);
- Ok(TeeProof { data, signature })
-}
-
-/// Check if `manifest`, `request`, and `response` all fulfill requirements necessary for
-/// a proof to be created
-fn validate_notarization_legal(
- manifest: &Manifest,
- request: &ManifestRequest,
- response: &NotaryResponse,
-) -> Result {
- debug!("Validating manifest");
- let result = manifest.validate_with(request, response)?;
- if !result.is_success() {
- info!("Manifest validation failed: {:?}", result.errors());
- }
- info!("Manifest returned values: {:?}", result.values());
- Ok(result)
+ let notarization_result =
+ NotarizationResult { tee_proof: Some(proof), errors: Some(validation_result.errors()) };
+ Ok(notarization_result)
}
diff --git a/tests/src/lib.rs b/tests/src/lib.rs
index 1b541e60c..d6c1e74f2 100644
--- a/tests/src/lib.rs
+++ b/tests/src/lib.rs
@@ -195,14 +195,20 @@ async fn test_proving_successful() {
if let Some(Ok(line)) = stdout_lines.next() {
println!("Client stdout: {}", line);
if line.contains(PROVING_SUCCESS_MSG) {
- return true;
+ return Ok(());
+ }
+ if line.contains("Proving Failed") {
+ return Err(line);
}
}
if let Some(Ok(line)) = stderr_lines.next() {
println!("Client stderr: {}", line);
if line.contains(PROVING_SUCCESS_MSG) {
- return true;
+ return Ok(());
+ }
+ if line.contains("Proving Failed") {
+ return Err(line);
}
}
@@ -212,9 +218,10 @@ async fn test_proving_successful() {
.await;
match result {
- Ok(found) => assert!(found, "Did not find '{}' in output", PROVING_SUCCESS_MSG),
+ Ok(Ok(())) => (),
+ Ok(Err(failed_msg)) => panic!("Proving failed: {}", failed_msg),
Err(_) => panic!(
- "Timed out waiting for '{}' after {} seconds",
+ "Timed out waiting for '{}' or 'Proving Failed' after {} seconds",
PROVING_SUCCESS_MSG,
PROVING_TIMEOUT.as_secs()
),