Skip to content

Commit

Permalink
fix(examples): fix examples for alpha.7 release (#603)
Browse files Browse the repository at this point in the history
* doc: Fix examples for alpha7 release

+ Use secp256k1 key for notary server fixture
+ fix tower issue
+ Fixed doctes issues (Avoid doc test failures when ignored tests are run)
+ Run wasm tests in incognitto mode to avoid chromiumoxide ws errors

* Added comment

* minor improvements

* formatting

* polish attestation example

* use shorthand fs write

* clean

* simplify discord example

---------

Co-authored-by: sinu <[email protected]>
  • Loading branch information
heeckhau and sinui0 authored Oct 3, 2024
1 parent 6e20930 commit dfc1629
Show file tree
Hide file tree
Showing 22 changed files with 408 additions and 570 deletions.
2 changes: 1 addition & 1 deletion crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
//! ```no_run
//! # use tlsn_core::transcript::{TranscriptCommitConfigBuilder, Transcript, Direction};
//! # use tlsn_core::hash::HashAlgId;
//! # fn main() -> Result<(), Box<dyn std::error::Error> {
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # let transcript: Transcript = unimplemented!();
//! let (sent_len, recv_len) = transcript.len();
//!
Expand Down
26 changes: 26 additions & 0 deletions crates/core/src/transcript/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,32 @@ impl<'a> TranscriptProofBuilder<'a> {
self.reveal_with_kind(ranges, direction, self.default_kind)
}

/// Reveals the given ranges in the sent transcript using the default kind
/// of commitment.
///
/// # Arguments
///
/// * `ranges` - The ranges to reveal.
pub fn reveal_sent(
&mut self,
ranges: &dyn ToRangeSet<usize>,
) -> Result<&mut Self, TranscriptProofBuilderError> {
self.reveal(ranges, Direction::Sent)
}

/// Reveals the given ranges in the received transcript using the default
/// kind of commitment.
///
/// # Arguments
///
/// * `ranges` - The ranges to reveal.
pub fn reveal_recv(
&mut self,
ranges: &dyn ToRangeSet<usize>,
) -> Result<&mut Self, TranscriptProofBuilderError> {
self.reveal(ranges, Direction::Received)
}

/// Builds the transcript proof.
pub fn build(self) -> Result<TranscriptProof, TranscriptProofBuilderError> {
let encoding_proof = if !self.encoding_proof_idxs.is_empty() {
Expand Down
2 changes: 1 addition & 1 deletion crates/data-fixtures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ macro_rules! define_fixture {
($name:ident, $doc:tt, $path:tt) => {
#[doc = $doc]
///
/// ```ignore
/// ```text
#[doc = include_str!($path)]
/// ```
pub const $name: &[u8] = include_bytes!($path);
Expand Down
2 changes: 2 additions & 0 deletions crates/examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Ignore files from examples.
*.tlsn
20 changes: 12 additions & 8 deletions crates/examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ notary-client = { workspace = true }
tlsn-common = { workspace = true }
tlsn-core = { workspace = true }
tlsn-prover = { workspace = true }
tlsn-utils = { workspace = true }
tlsn-verifier = { workspace = true }
tlsn-formats = { workspace = true }

bincode = { workspace = true }
chrono = { workspace = true }
dotenv = { version = "0.15.0" }
elliptic-curve = { workspace = true, features = ["pkcs8"] }
futures = { workspace = true }
http-body-util = { workspace = true }
hex = { workspace = true }
hyper = { workspace = true, features = ["client", "http1"] }
hyper-util = { workspace = true, features = ["full"] }
k256 = { workspace = true, features = ["ecdsa"] }
Expand All @@ -35,12 +39,16 @@ tracing = { workspace = true }
tracing-subscriber = { workspace = true }

[[example]]
name = "attestation_prover"
path = "attestation/prover.rs"
name = "attestation_prove"
path = "attestation/prove.rs"

[[example]]
name = "attestation_verifier"
path = "attestation/verifier.rs"
name = "attestation_present"
path = "attestation/present.rs"

[[example]]
name = "attestation_verify"
path = "attestation/verify.rs"

[[example]]
name = "interactive"
Expand All @@ -49,7 +57,3 @@ path = "interactive/interactive.rs"
[[example]]
name = "discord_dm"
path = "discord/discord_dm.rs"

[[example]]
name = "discord_dm_verifier"
path = "discord/discord_dm_verifier.rs"
77 changes: 31 additions & 46 deletions crates/examples/attestation/README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
## Simple Example: Notarize Public Data from example.com (Rust) <a name="rust-simple"></a>
## Simple Attestation Example: Notarize Public Data from example.com (Rust) <a name="rust-simple"></a>

This example demonstrates the simplest possible use case for TLSNotary:
1. Notarize: Fetch <https://example.com/> and create a proof of its content.
2. Verify the proof.

Next, we will redact the content and verify it again:
1. Redact the `USER_AGENT` and titles.
2. Verify the redacted proof.
1. Fetch <https://example.com/> and acquire an attestation of its content.
2. Create a verifiable presentation using the attestation, while redacting the value of a header.
3. Verify the presentation.

### 1. Notarize <https://example.com/>

Run a simple prover:
Run the `prove` binary.

```shell
cargo run --release --example simple_prover
cargo run --release --example attestation_prove
```

If the notarization was successful, you should see this output in the console:
Expand All @@ -22,66 +19,54 @@ If the notarization was successful, you should see this output in the console:
Starting an MPC TLS connection with the server
Got a response from the server
Notarization completed successfully!
The proof has been written to `simple_proof.json`
The attestation has been written to `example.attestation.tlsn` and the corresponding secrets to `example.secrets.tlsn`.
```

⚠️ In this simple example the `Notary` server is automatically started in the background. Note that this is for demonstration purposes only. In a real work example, the notary should be run by a neutral party or the verifier of the proofs. Consult the [Notary Server Docs](https://docs.tlsnotary.org/developers/notary_server.html) for more details on how to run a notary server.
⚠️ In this simple example the `Notary` server is automatically started in the background. Note that this is for demonstration purposes only. In a real world example, the notary should be run by a trusted party. Consult the [Notary Server Docs](https://docs.tlsnotary.org/developers/notary_server.html) for more details on how to run a notary server.

### 2. Build a verifiable presentation

### 2. Verify the Proof
This will build a verifiable presentation with the `User-Agent` header redacted from the request. This presentation can be shared with any verifier you wish to present the data to.

When you open `simple_proof.json` in an editor, you will see a JSON file with lots of non-human-readable byte arrays. You can decode this file by running:
Run the `present` binary.

```shell
cargo run --release --example simple_verifier
cargo run --release --example attestation_present
```

This will output the TLS-transaction in clear text:
If successful, you should see this output in the console:

```log
Successfully verified that the bytes below came from a session with Dns("example.com") at 2023-11-03 08:48:20 UTC.
Note that the bytes which the Prover chose not to disclose are shown as X.
Bytes sent:
...
```

### 3. Redact Information

Open `simple_prover.rs` and locate the line with:

```rust
let redact = false;
Presentation built successfully!
The presentation has been written to `example.presentation.tlsn`.
```

and change it to:
### 3. Verify the presentation

```rust
let redact = true;
```
This will read the presentation from the previous step, verify it, and print the disclosed data to console.

Next, if you run the `simple_prover` and `simple_verifier` again, you'll notice redacted `X`'s in the output:
Run the `verify` binary.

```shell
cargo run --release --example simple_prover
cargo run --release --example simple_verifier
cargo run --release --example attestation_verify
```

If successful, you should see this output in the console:

```log
<!doctype html>
<html>
<head>
<title>XXXXXXXXXXXXXX</title>
...
```
Verifying presentation with {key algorithm} key: { hex encoded key }
You can also use <https://explorer.tlsnotary.org/> to inspect your proofs. Simply drag and drop `simple_proof.json` from your file explorer into the drop zone. Redacted bytes are marked with X characters. [Notary public key](../../notary/server/fixture/notary/notary.pub)
**Ask yourself, do you trust this key?**
### (Optional) Extra Experiments
-------------------------------------------------------------------
Successfully verified that the data below came from a session with example.com at 2024-10-03 03:01:40 UTC.
Note that the data which the Prover chose not to disclose are shown as X.
Feel free to try these extra challenges:
Data sent:
...
```

- [ ] Modify the `server_name` (or any other data) in `simple_proof.json` and verify that the proof is no longer valid.
- [ ] Modify the `build_proof_with_redactions` function in `simple_prover.rs` to redact more or different data.
⚠️ Notice that the presentation comes with a "verifying key". This is the key the Notary used when issuing the attestation that the presentation was built from. If you trust the Notary, or more specifically the verifying key, then you can trust that the presented data is authentic.

### Next steps

Expand Down
61 changes: 61 additions & 0 deletions crates/examples/attestation/present.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// This example demonstrates how to build a verifiable presentation from an
// attestation and the corresponding connection secrets. See the `prove.rs`
// example to learn how to acquire an attestation from a Notary.

use tlsn_core::{attestation::Attestation, presentation::Presentation, CryptoProvider, Secrets};
use tlsn_formats::http::HttpTranscript;

fn main() -> Result<(), Box<dyn std::error::Error>> {
// Read attestation from disk.
let attestation: Attestation =
bincode::deserialize(&std::fs::read("example.attestation.tlsn")?)?;

// Read secrets from disk.
let secrets: Secrets = bincode::deserialize(&std::fs::read("example.secrets.tlsn")?)?;

// Parse the HTTP transcript.
let transcript = HttpTranscript::parse(secrets.transcript())?;

// Build a transcript proof.
let mut builder = secrets.transcript_proof_builder();

let request = &transcript.requests[0];
// Reveal the structure of the request without the headers or body.
builder.reveal_sent(&request.without_data())?;
// Reveal the request target.
builder.reveal_sent(&request.request.target)?;
// Reveal all headers except the value of the User-Agent header.
for header in &request.headers {
if !header.name.as_str().eq_ignore_ascii_case("User-Agent") {
builder.reveal_sent(header)?;
} else {
builder.reveal_sent(&header.without_value())?;
}
}
// Reveal the entire response.
builder.reveal_recv(&transcript.responses[0])?;

let transcript_proof = builder.build()?;

// Use default crypto provider to build the presentation.
let provider = CryptoProvider::default();

let mut builder = attestation.presentation_builder(&provider);

builder
.identity_proof(secrets.identity_proof())
.transcript_proof(transcript_proof);

let presentation: Presentation = builder.build()?;

// Write the presentation to disk.
std::fs::write(
"example.presentation.tlsn",
bincode::serialize(&presentation)?,
)?;

println!("Presentation built successfully!");
println!("The presentation has been written to `example.presentation.tlsn`.");

Ok(())
}
Loading

1 comment on commit dfc1629

@maceip
Copy link
Collaborator

@maceip maceip commented on dfc1629 Oct 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♥️

Please sign in to comment.