Skip to content

Commit

Permalink
refactor: tlsn-core (#333)
Browse files Browse the repository at this point in the history
* refactor: use RangeSet

* bump tlsn-utils commit

* add RedactedTranscript

* fix return type in TranscriptSlice::data

* simplify openings

* mark Commitment non_exhaustive

* add commitment id, session data builder

* move fixtures into tlsn-fixtures

* encapsulate more into tlsn-core

* fix tlsn-core api test

* clean up unused imports

* update tlsn-prover

* wip

* restructuring exports, and documentation

* more work on docs

* improve substrings errors

* implement opaque debug for substringsproof

* clean up substringsproof verify

* readd merkle test

* bump tlsn-utils version

* fix dependents

* add getter for substrings commitments

* fix RedactedTranscript constructor

* introduce bimap and info types

* clean up error types

* add panic if duplicate ids

* remove tracing dep

* move SubstringsOpeningError

* check range bound

* remove transcript error

* fix panic

* flatten commitment types

* fix import in example

* delete old substrings module

* transcript commitment builder

* hide constructor for builder

* remove dead code

* Apply suggestions from code review

Co-authored-by: dan <[email protected]>

* Update tlsn/tlsn-core/src/proof.rs

Co-authored-by: th4s <[email protected]>

* Update tlsn/tlsn-core/src/commitment/builder.rs

Co-authored-by: dan <[email protected]>

* Update tlsn/tlsn-core/src/merkle.rs

Co-authored-by: dan <[email protected]>

* fix transcript name

* update fn name

* into -> to

* ensure transcript slices are sorted and disjoint

---------

Co-authored-by: dan <[email protected]>
Co-authored-by: th4s <[email protected]>
  • Loading branch information
3 people authored Sep 18, 2023
1 parent 7826e6a commit 2f0666f
Show file tree
Hide file tree
Showing 56 changed files with 1,207 additions and 1,532 deletions.
4 changes: 3 additions & 1 deletion tlsn/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ members = [
"tlsn-core",
"tlsn-notary",
"tlsn-prover",
"tlsn-fixtures",
"tests-integration",
"examples",
]
Expand All @@ -12,6 +13,7 @@ resolver = "2"
tlsn-core = { path = "tlsn-core" }
tlsn-prover = { path = "tlsn-prover" }
tlsn-notary = { path = "tlsn-notary" }
tlsn-fixtures = { path = "tlsn-fixtures" }

tlsn-tls-core = { path = "../components/tls/tls-core" }
tlsn-tls-mpc = { path = "../components/tls/tls-mpc" }
Expand All @@ -20,7 +22,7 @@ tlsn-tls-client-async = { path = "../components/tls/tls-client-async" }
tls-server-fixture = { path = "../components/tls/tls-server-fixture" }
uid-mux = { path = "../components/uid-mux" }

tlsn-utils = { git = "https://github.com/tlsnotary/tlsn-utils", rev = "b182066" }
tlsn-utils = { git = "https://github.com/tlsnotary/tlsn-utils", rev = "8ac9156" }
tlsn-utils-aio = { git = "https://github.com/tlsnotary/tlsn-utils", rev = "b182066" }

mpz-core = { git = "https://github.com/privacy-scaling-explorations/mpz", rev = "76ed767" }
Expand Down
36 changes: 24 additions & 12 deletions tlsn/examples/simple_prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,22 +117,34 @@ async fn main() {
],
);

// Commit to each range of the outbound data which we want to disclose
for range in public_ranges.iter() {
prover.add_commitment_sent(range.clone()).unwrap();
}
let recv_len = prover.recv_transcript().data().len();

let builder = prover.commitment_builder();

// Commit to each range of the public outbound data which we want to disclose
let sent_commitments: Vec<_> = public_ranges
.iter()
.map(|r| builder.commit_sent(r.clone()).unwrap())
.collect();

// Commit to all inbound data in one shot, as we don't need to redact anything in it
let recv_len = prover.recv_transcript().data().len();
prover.add_commitment_recv(0..recv_len as u32).unwrap();
let recv_commitment = builder.commit_recv(0..recv_len).unwrap();

// Finalize, returning the notarized session
let notarized_session = prover.finalize().await.unwrap();

// Create a proof for all committed data in this session
let session_proof = notarized_session.session_proof();
let ids = (0..notarized_session.data().commitments().len()).collect();
let substrings_proof = notarized_session.generate_substring_proof(ids).unwrap();

let mut proof_builder = notarized_session.data().build_substrings_proof();

// Reveal all the public ranges
for commitment_id in sent_commitments {
proof_builder.reveal(commitment_id).unwrap();
}
proof_builder.reveal(recv_commitment).unwrap();

let substrings_proof = proof_builder.build().unwrap();

// Write the proof to a file in the format expected by `simple_verifier.rs`
let mut file = tokio::fs::File::create("proof.json").await.unwrap();
Expand Down Expand Up @@ -270,12 +282,12 @@ async fn connect_to_notary() -> (TlsStream<TcpStream>, String) {
/// Find the ranges of the public and private parts of a sequence.
///
/// Returns a tuple of `(public, private)` ranges.
fn find_ranges(seq: &[u8], private_seq: &[&[u8]]) -> (Vec<Range<u32>>, Vec<Range<u32>>) {
fn find_ranges(seq: &[u8], private_seq: &[&[u8]]) -> (Vec<Range<usize>>, Vec<Range<usize>>) {
let mut private_ranges = Vec::new();
for s in private_seq {
for (idx, w) in seq.windows(s.len()).enumerate() {
if w == *s {
private_ranges.push(idx as u32..(idx + w.len()) as u32);
private_ranges.push(idx..(idx + w.len()));
}
}
}
Expand All @@ -292,8 +304,8 @@ fn find_ranges(seq: &[u8], private_seq: &[&[u8]]) -> (Vec<Range<u32>>, Vec<Range
last_end = r.end;
}

if last_end < seq.len() as u32 {
public_ranges.push(last_end..seq.len() as u32);
if last_end < seq.len() {
public_ranges.push(last_end..seq.len());
}

(public_ranges, private_ranges)
Expand Down
8 changes: 3 additions & 5 deletions tlsn/examples/simple_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use tls_core::{
dns::ServerName,
verify::ServerCertVerifier,
};
use tlsn_core::{signature::Signature, substrings::proof::SubstringsProof, SessionProof};
use tlsn_core::{proof::SubstringsProof, SessionProof, Signature};

/// A simple verifier which reads a proof generated by `simple_prover.rs` from "proof.json", verifies
/// it and prints the verified data to the console.
Expand Down Expand Up @@ -59,14 +59,12 @@ fn main() {
// to disclose with 'X'
let mut transcript_tx = vec![b'X'; header.sent_len() as usize];
for slice in sent_slices {
transcript_tx[slice.range().start as usize..slice.range().end as usize]
.copy_from_slice(slice.data())
transcript_tx[slice.range()].copy_from_slice(slice.data())
}

let mut transcript_rx = vec![b'X'; header.recv_len() as usize];
for slice in recv_slices {
transcript_rx[slice.range().start as usize..slice.range().end as usize]
.copy_from_slice(slice.data())
transcript_rx[slice.range()].copy_from_slice(slice.data())
}

println!("-------------------------------------------------------------------");
Expand Down
17 changes: 10 additions & 7 deletions tlsn/examples/twitter_dm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,14 +264,17 @@ async fn main() {
],
);

let recv_len = prover.recv_transcript().data().len();

let builder = prover.commitment_builder();

// Commit to the outbound transcript, isolating the data that contain secrets
for range in public_ranges.iter().chain(private_ranges.iter()) {
prover.add_commitment_sent(range.clone()).unwrap();
builder.commit_sent(range.clone()).unwrap();
}

// Commit to the full received transcript in one shot, as we don't need to redact anything
let recv_len = prover.recv_transcript().data().len();
prover.add_commitment_recv(0..recv_len as u32).unwrap();
builder.commit_recv(0..recv_len).unwrap();

// Finalize, returning the notarized session
let notarized_session = prover.finalize().await.unwrap();
Expand All @@ -292,12 +295,12 @@ async fn main() {
/// Find the ranges of the public and private parts of a sequence.
///
/// Returns a tuple of `(public, private)` ranges.
fn find_ranges(seq: &[u8], sub_seq: &[&[u8]]) -> (Vec<Range<u32>>, Vec<Range<u32>>) {
fn find_ranges(seq: &[u8], sub_seq: &[&[u8]]) -> (Vec<Range<usize>>, Vec<Range<usize>>) {
let mut private_ranges = Vec::new();
for s in sub_seq {
for (idx, w) in seq.windows(s.len()).enumerate() {
if w == *s {
private_ranges.push(idx as u32..(idx + w.len()) as u32);
private_ranges.push(idx..(idx + w.len()));
}
}
}
Expand All @@ -314,8 +317,8 @@ fn find_ranges(seq: &[u8], sub_seq: &[&[u8]]) -> (Vec<Range<u32>>, Vec<Range<u32
last_end = r.end;
}

if last_end < seq.len() as u32 {
public_ranges.push(last_end..seq.len() as u32);
if last_end < seq.len() {
public_ranges.push(last_end..seq.len());
}

(public_ranges, private_ranges)
Expand Down
6 changes: 4 additions & 2 deletions tlsn/tests-integration/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,10 @@ async fn prover<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(notary_socke
let sent_len = prover.sent_transcript().data().len();
let recv_len = prover.recv_transcript().data().len();

prover.add_commitment_sent(0..sent_len as u32).unwrap();
prover.add_commitment_recv(0..recv_len as u32).unwrap();
let builder = prover.commitment_builder();

builder.commit_sent(0..sent_len).unwrap();
builder.commit_recv(0..recv_len).unwrap();

_ = prover.finalize().await.unwrap();
}
Expand Down
9 changes: 5 additions & 4 deletions tlsn/tlsn-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ edition = "2021"

[features]
default = []
fixtures = ["dep:hex"]
tracing = ["dep:tracing"]

[dependencies]
tlsn-tls-core = { workspace = true, features = ["serde"] }
Expand All @@ -30,9 +28,13 @@ rs_merkle.workspace = true
rstest = { workspace = true, optional = true }
hex = { workspace = true, optional = true }
bytes = { workspace = true, features = ["serde"] }
tracing = { workspace = true, optional = true }
opaque-debug.workspace = true

bimap = { version = "0.6.3", features = ["serde"] }

[dev-dependencies]
tlsn-fixtures.workspace = true

rstest.workspace = true
hex.workspace = true
rand_core.workspace = true
Expand All @@ -41,4 +43,3 @@ bincode.workspace = true

[[test]]
name = "api"
required-features = ["fixtures"]
36 changes: 0 additions & 36 deletions tlsn/tlsn-core/src/commitment.rs

This file was deleted.

105 changes: 105 additions & 0 deletions tlsn/tlsn-core/src/commitment/blake3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use crate::commitment::{Commitment, CommitmentOpening};
use mpz_core::{
commit::{Decommitment, HashCommit, Nonce},
hash::Hash,
};
use mpz_garble_core::{encoding_state, encoding_state::Full, EncodedValue};
use serde::{Deserialize, Serialize};

/// A Blake3 commitment to the encodings of the substrings of a [`Transcript`](crate::Transcript).
#[derive(Clone, Copy, Serialize, Deserialize)]
pub struct Blake3Commitment {
hash: Hash,
nonce: Nonce,
}

opaque_debug::implement!(Blake3Commitment);

impl Blake3Commitment {
/// Creates a new Blake3 commitment
pub fn new(encodings: &[EncodedValue<encoding_state::Active>]) -> Self {
let (decommitment, hash) = encodings.hash_commit();

Self {
hash,
nonce: *decommitment.nonce(),
}
}

/// Returns the hash of this commitment
pub fn hash(&self) -> &Hash {
&self.hash
}

/// Returns the nonce of this commitment
pub fn nonce(&self) -> &Nonce {
&self.nonce
}

/// Opens this commitment
pub fn open(&self, data: Vec<u8>) -> Blake3Opening {
Blake3Opening::new(data, self.nonce)
}
}

impl From<Blake3Commitment> for Commitment {
fn from(value: Blake3Commitment) -> Self {
Self::Blake3(value)
}
}

/// A substring opening using Blake3
#[derive(Serialize, Deserialize, Clone)]
pub struct Blake3Opening {
data: Vec<u8>,
nonce: Nonce,
}

impl Blake3Opening {
pub(crate) fn new(data: Vec<u8>, nonce: Nonce) -> Self {
Self { data, nonce }
}

/// Recovers the expected commitment from this opening.
///
/// # Panics
///
/// - If the number of encodings does not match the number of bytes in the opening.
/// - If an encoding is not for a u8.
pub fn recover(&self, encodings: &[EncodedValue<Full>]) -> Blake3Commitment {
assert_eq!(
encodings.len(),
self.data.len(),
"encodings and data must have the same length"
);

let encodings = encodings
.iter()
.zip(&self.data)
.map(|(encoding, data)| encoding.select(*data).expect("encoding is for a u8"))
.collect::<Vec<_>>();

let hash = Decommitment::new_with_nonce(encodings, self.nonce).commit();

Blake3Commitment {
hash,
nonce: self.nonce,
}
}

/// Returns the transcript data corresponding to this opening
pub fn data(&self) -> &[u8] {
&self.data
}

/// Returns the transcript data corresponding to this opening
pub fn into_data(self) -> Vec<u8> {
self.data
}
}

impl From<Blake3Opening> for CommitmentOpening {
fn from(value: Blake3Opening) -> Self {
Self::Blake3(value)
}
}
Loading

0 comments on commit 2f0666f

Please sign in to comment.