Converted verifier-rs into a test

This commit is contained in:
Hendrik Eeckhaut
2025-09-19 17:00:55 +02:00
parent c5f752041b
commit 6021db998c
6 changed files with 92 additions and 72 deletions

View File

@@ -39,3 +39,7 @@ tlsn = { git = "https://github.com/tlsnotary/tlsn.git", branch = "dev" }
spansy = { git = "https://github.com/tlsnotary/tlsn-utils", package = "spansy", branch = "dev" }
rangeset = "0.2.0"
tower-util = "0.3.1"
[dev-dependencies]
rustls = "0.23"
webpki-roots = "0.26"

View File

@@ -34,6 +34,7 @@ use tracing::{debug, error, info};
use ws_stream_tungstenite::WsStream;
mod axum_websocket;
pub mod verifier;
// Maximum number of bytes that can be sent from prover to server
const MAX_SENT_DATA: usize = 2048;

View File

@@ -1,5 +1,3 @@
use std::thread::panicking;
use async_tungstenite::{tokio::connect_async_with_config, tungstenite::protocol::WebSocketConfig};
use eyre::eyre;
use tlsn::{
@@ -10,32 +8,16 @@ use tlsn::{
use tokio::io::{AsyncRead, AsyncWrite};
use tokio_util::compat::TokioAsyncReadCompatExt;
use tracing::{debug, info};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
use uuid;
use ws_stream_tungstenite::WsStream;
const TRACING_FILTER: &str = "INFO";
const PROVER_HOST: &str = "localhost";
const PROVER_PORT: u16 = 9816;
// Maximum number of bytes that can be sent from prover to server
const MAX_SENT_DATA: usize = 2048;
// Maximum number of bytes that can be received by prover from server
const MAX_RECV_DATA: usize = 4096;
/// Make sure the following url's domain is the same as SERVER_DOMAIN on the prover side
const SERVER_DOMAIN: &str = "raw.githubusercontent.com";
#[tokio::main]
async fn main() {
tracing_subscriber::registry()
.with(EnvFilter::try_from_default_env().unwrap_or_else(|_| TRACING_FILTER.into()))
.with(tracing_subscriber::fmt::layer())
.init();
run_verifier(PROVER_HOST, PROVER_PORT, SERVER_DOMAIN).await;
}
async fn run_verifier(prover_host: &str, prover_port: u16, server_domain: &str) {
/// Connect to prover via websocket and run verification
pub async fn run_verifier_test(prover_host: &str, prover_port: u16, server_domain: &str) -> Result<(), eyre::ErrReport> {
info!("Sending websocket request to prover...");
let request = http::Request::builder()
.uri(format!("ws://{prover_host}:{prover_port}/prove"))
@@ -50,18 +32,20 @@ async fn run_verifier(prover_host: &str, prover_port: u16, server_domain: &str)
let (prover_ws_stream, _) =
connect_async_with_config(request, Some(WebSocketConfig::default()))
.await
.unwrap();
.map_err(|e| eyre!("Failed to connect to prover: {}", e))?;
info!("Websocket connection established with prover!");
let prover_ws_socket = WsStream::new(prover_ws_stream);
verifier(prover_ws_socket, server_domain).await;
verify_prover_connection(prover_ws_socket, server_domain).await?;
info!("Verification is successful!");
Ok(())
}
async fn verifier<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(
/// Core verifier logic that validates the TLS proof
pub async fn verify_prover_connection<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(
socket: T,
server_domain: &str,
) {
) -> Result<(), eyre::ErrReport> {
debug!("Starting verification...");
// Setup Verifier.
@@ -87,10 +71,10 @@ async fn verifier<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(
} = verifier
.verify(socket.compat(), &VerifyConfig::default())
.await
.unwrap();
.map_err(|e| eyre!("Verification failed: {}", e))?;
let server_name = server_name.expect("prover should have revealed server name");
let transcript = transcript.expect("prover should have revealed transcript data");
let server_name = server_name.ok_or_else(|| eyre!("prover should have revealed server name"))?;
let transcript = transcript.ok_or_else(|| eyre!("prover should have revealed transcript data"))?;
// Check sent data: check host.
debug!("Starting sent data verification...");
@@ -98,8 +82,7 @@ async fn verifier<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(
let sent_data = String::from_utf8(sent.clone()).expect("Verifier expected sent data");
sent_data
.find(server_domain)
.ok_or_else(|| eyre!("Verification failed: Expected host {}", server_domain))
.unwrap();
.ok_or_else(|| eyre!("Verification failed: Expected host {}", server_domain))?;
// Check received data: check json and version number.
debug!("Starting received data verification...");
@@ -109,24 +92,24 @@ async fn verifier<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(
debug!("Received data: {:?}", response);
response
.find("123 Elm Street")
.ok_or_else(|| eyre!("Verification failed: missing data in received data"))
.unwrap();
.ok_or_else(|| eyre!("Verification failed: missing data in received data"))?;
// Check Session info: server name.
let ServerName::Dns(dns_name) = server_name;
if dns_name.as_str() != server_domain {
panic!("Verification failed: server name mismatches");
// return Err(eyre!("Verification failed: server name mismatches"));
return Err(eyre!("Verification failed: server name mismatches"));
}
let sent_string = bytes_to_redacted_string(&sent).unwrap();
let received_string = bytes_to_redacted_string(&received).unwrap();
let sent_string = bytes_to_redacted_string(&sent)?;
let received_string = bytes_to_redacted_string(&received)?;
info!("============================================");
info!("Verification successful!");
info!("============================================");
info!("Sent data: {:?}", sent_string);
info!("Received data: {:?}", received_string);
Ok(())
}
/// Render redacted bytes as `🙈`.
@@ -134,4 +117,4 @@ fn bytes_to_redacted_string(bytes: &[u8]) -> Result<String, eyre::ErrReport> {
Ok(String::from_utf8(bytes.to_vec())
.map_err(|err| eyre!("Failed to parse bytes to redacted string: {err}"))?
.replace('\0', "🙈"))
}
}

View File

@@ -0,0 +1,67 @@
use std::time::Duration;
use tokio::time::timeout;
use interactive_networked_prover::{run_server, verifier::run_verifier_test};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
const TRACING_FILTER: &str = "INFO";
const PROVER_HOST: &str = "127.0.0.1";
const PROVER_PORT: u16 = 9817; // Use different port to avoid conflicts
const SERVER_DOMAIN: &str = "raw.githubusercontent.com";
const SERVER_URL: &str = "https://raw.githubusercontent.com/tlsnotary/tlsn/refs/tags/v0.1.0-alpha.12/crates/server-fixture/server/src/data/1kb.json";
#[tokio::test]
async fn test_prover_verifier_integration() {
// Initialize tracing for test output
let _ = tracing_subscriber::registry()
.with(EnvFilter::try_from_default_env().unwrap_or_else(|_| TRACING_FILTER.into()))
.with(tracing_subscriber::fmt::layer())
.try_init();
// Start prover server in background task
let server_task = tokio::spawn(async move {
run_server(PROVER_HOST, PROVER_PORT, SERVER_URL)
.await
.expect("Server should start successfully")
});
// Wait for server to start up
tokio::time::sleep(Duration::from_millis(500)).await;
// Run verifier test with timeout
let verification_result = timeout(
Duration::from_secs(60), // Generous timeout for network operations
run_verifier_test(PROVER_HOST, PROVER_PORT, SERVER_DOMAIN)
).await;
// Clean up server task
server_task.abort();
// Assert verification succeeded
match verification_result {
Ok(Ok(())) => {
println!("✅ Integration test passed: Prover-Verifier communication successful");
}
Ok(Err(e)) => {
panic!("❌ Verification failed: {}", e);
}
Err(_) => {
panic!("❌ Verification timed out after 60 seconds");
}
}
}
#[tokio::test]
async fn test_verifier_connection_failure() {
// Test that verifier handles connection failure gracefully
let result = timeout(
Duration::from_secs(5),
run_verifier_test("127.0.0.1", 9999, SERVER_DOMAIN) // Non-existent port
).await;
// Should either timeout or return an error
match result {
Ok(Ok(())) => panic!("Should not succeed when connecting to non-existent server"),
Ok(Err(_)) => println!("✅ Correctly failed to connect to non-existent server"),
Err(_) => println!("✅ Correctly timed out when connecting to non-existent server"),
}
}

View File

@@ -1,26 +0,0 @@
[package]
name = "interactive-networked-verifier"
version = "0.1.0"
edition = "2021"
[dependencies]
async-tungstenite = { version = "0.25", features = ["tokio-runtime"] }
eyre = "0.6.12"
http = "1.1"
tokio = { version = "1", features = [
"rt",
"rt-multi-thread",
"macros",
"net",
"io-std",
"fs",
] }
tokio-util = { version = "0.7", features = ["compat"] }
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
uuid = { version = "1.4.1", features = ["v4", "fast-rng"] }
ws_stream_tungstenite = { version = "0.13", features = ["tokio_io"] }
tlsn = { git = "https://github.com/tlsnotary/tlsn.git", branch = "dev" }
rustls = "0.23"
webpki-roots = "0.26"

View File

@@ -1,9 +0,0 @@
## Interactive Prover
An implementation of the interactive prover in Rust.
## Running the prover
1. Configure this prover setting via the global variables defined in [main.rs](./src/main.rs) — please ensure that the hardcoded `SERVER_URL` is the same on the verifier side.
2. Start the prover by running the following in a terminal at the root of this crate.
```bash
cargo run --release
```