Compare commits

...

3 Commits

Author SHA1 Message Date
dan
51dd59e282 update tlsn-wasm 2025-12-09 11:13:37 +02:00
dan
21e803b214 chore: adapt for rangeset 0.4 2025-12-09 10:23:50 +02:00
dan
f7d70b285d chore: adapt for rangeset 0.3 2025-12-04 14:51:55 +02:00
20 changed files with 588 additions and 594 deletions

977
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -82,11 +82,11 @@ mpz-zk = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-hash = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
mpz-ideal-vm = { git = "https://github.com/privacy-ethereum/mpz", rev = "9c343f8" }
rangeset = { version = "0.2" }
rangeset = { version = "0.4" }
serio = { version = "0.2" }
spansy = { git = "https://github.com/tlsnotary/tlsn-utils", rev = "6168663" }
spansy = { git = "https://github.com/tlsnotary/tlsn-utils", rev = "6f1a934" }
uid-mux = { version = "0.2" }
websocket-relay = { git = "https://github.com/tlsnotary/tlsn-utils", rev = "6168663" }
websocket-relay = { git = "https://github.com/tlsnotary/tlsn-utils", rev = "6f1a934" }
aead = { version = "0.4" }
aes = { version = "0.8" }

View File

@@ -15,7 +15,7 @@ use mpz_vm_core::{
memory::{binary::Binary, DecodeFuture, Memory, Repr, Slice, View},
Call, Callable, Execute, Vm, VmError,
};
use rangeset::{Difference, RangeSet, UnionMut};
use rangeset::{ops::Set, set::RangeSet};
use tokio::sync::{Mutex, MutexGuard, OwnedMutexGuard};
type Error = DeapError;
@@ -210,10 +210,12 @@ where
}
fn commit_raw(&mut self, slice: Slice) -> Result<(), VmError> {
let slice_range = slice.to_range();
// Follower's private inputs are not committed in the ZK VM until finalization.
let input_minus_follower = slice.to_range().difference(&self.follower_input_ranges);
let input_minus_follower = slice_range.difference(&self.follower_input_ranges);
let mut zk = self.zk.try_lock().unwrap();
for input in input_minus_follower.iter_ranges() {
for input in input_minus_follower {
zk.commit_raw(
self.memory_map
.try_get(Slice::from_range_unchecked(input))?,
@@ -266,7 +268,7 @@ where
mpc.mark_private_raw(slice)?;
// Follower's private inputs will become public during finalization.
zk.mark_public_raw(self.memory_map.try_get(slice)?)?;
self.follower_input_ranges.union_mut(&slice.to_range());
self.follower_input_ranges.union_mut(slice.to_range());
self.follower_inputs.push(slice);
}
}
@@ -282,7 +284,7 @@ where
mpc.mark_blind_raw(slice)?;
// Follower's private inputs will become public during finalization.
zk.mark_public_raw(self.memory_map.try_get(slice)?)?;
self.follower_input_ranges.union_mut(&slice.to_range());
self.follower_input_ranges.union_mut(slice.to_range());
self.follower_inputs.push(slice);
}
Role::Follower => {

View File

@@ -1,7 +1,7 @@
use std::ops::Range;
use mpz_vm_core::{memory::Slice, VmError};
use rangeset::Subset;
use rangeset::ops::Set;
/// A mapping between the memories of the MPC and ZK VMs.
#[derive(Debug, Default)]

View File

@@ -59,5 +59,7 @@ generic-array = { workspace = true }
bincode = { workspace = true }
hex = { workspace = true }
rstest = { workspace = true }
tlsn-core = { workspace = true, features = ["fixtures"] }
tlsn-attestation = { workspace = true, features = ["fixtures"] }
tlsn-data-fixtures = { workspace = true }
webpki-root-certs = { workspace = true }

View File

@@ -1,6 +1,6 @@
//! Proving configuration.
use rangeset::{RangeSet, ToRangeSet, UnionMut};
use rangeset::set::{RangeSet, ToRangeSet};
use serde::{Deserialize, Serialize};
use crate::transcript::{Direction, Transcript, TranscriptCommitConfig, TranscriptCommitRequest};

View File

@@ -1,11 +1,11 @@
use rangeset::RangeSet;
use rangeset::set::RangeSet;
pub(crate) struct FmtRangeSet<'a>(pub &'a RangeSet<usize>);
impl<'a> std::fmt::Display for FmtRangeSet<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("{")?;
for range in self.0.iter_ranges() {
for range in self.0.iter() {
write!(f, "{}..{}", range.start, range.end)?;
if range.end < self.0.end().unwrap_or(0) {
f.write_str(", ")?;

View File

@@ -26,7 +26,11 @@ mod tls;
use std::{fmt, ops::Range};
use rangeset::{Difference, IndexRanges, RangeSet, Union};
use rangeset::{
iter::RangeIterator,
ops::{Index, Set},
set::RangeSet,
};
use serde::{Deserialize, Serialize};
use crate::connection::TranscriptLength;
@@ -106,7 +110,7 @@ impl Transcript {
}
Some(
Subsequence::new(idx.clone(), data.index_ranges(idx))
Subsequence::new(idx.clone(), data.index(idx).flatten().copied().collect())
.expect("data is same length as index"),
)
}
@@ -129,11 +133,11 @@ impl Transcript {
let mut sent = vec![0; self.sent.len()];
let mut received = vec![0; self.received.len()];
for range in sent_idx.iter_ranges() {
for range in sent_idx.iter() {
sent[range.clone()].copy_from_slice(&self.sent[range]);
}
for range in recv_idx.iter_ranges() {
for range in recv_idx.iter() {
received[range.clone()].copy_from_slice(&self.received[range]);
}
@@ -188,10 +192,16 @@ impl From<PartialTranscript> for CompressedPartialTranscript {
Self {
sent_authed: uncompressed
.sent
.index_ranges(&uncompressed.sent_authed_idx),
.index(&uncompressed.sent_authed_idx)
.flatten()
.copied()
.collect(),
received_authed: uncompressed
.received
.index_ranges(&uncompressed.received_authed_idx),
.index(&uncompressed.received_authed_idx)
.flatten()
.copied()
.collect(),
sent_idx: uncompressed.sent_authed_idx,
recv_idx: uncompressed.received_authed_idx,
sent_total: uncompressed.sent.len(),
@@ -207,7 +217,7 @@ impl From<CompressedPartialTranscript> for PartialTranscript {
let mut offset = 0;
for range in compressed.sent_idx.iter_ranges() {
for range in compressed.sent_idx.iter() {
sent[range.clone()]
.copy_from_slice(&compressed.sent_authed[offset..offset + range.len()]);
offset += range.len();
@@ -215,7 +225,7 @@ impl From<CompressedPartialTranscript> for PartialTranscript {
let mut offset = 0;
for range in compressed.recv_idx.iter_ranges() {
for range in compressed.recv_idx.iter() {
received[range.clone()]
.copy_from_slice(&compressed.received_authed[offset..offset + range.len()]);
offset += range.len();
@@ -304,12 +314,16 @@ impl PartialTranscript {
/// Returns the index of sent data which haven't been authenticated.
pub fn sent_unauthed(&self) -> RangeSet<usize> {
(0..self.sent.len()).difference(&self.sent_authed_idx)
(0..self.sent.len())
.difference(&self.sent_authed_idx)
.into_set()
}
/// Returns the index of received data which haven't been authenticated.
pub fn received_unauthed(&self) -> RangeSet<usize> {
(0..self.received.len()).difference(&self.received_authed_idx)
(0..self.received.len())
.difference(&self.received_authed_idx)
.into_set()
}
/// Returns an iterator over the authenticated data in the transcript.
@@ -319,7 +333,7 @@ impl PartialTranscript {
Direction::Received => (&self.received, &self.received_authed_idx),
};
authed.iter().map(|i| data[i])
authed.iter_values().map(move |i| data[i])
}
/// Unions the authenticated data of this transcript with another.
@@ -339,24 +353,20 @@ impl PartialTranscript {
"received data are not the same length"
);
for range in other
.sent_authed_idx
.difference(&self.sent_authed_idx)
.iter_ranges()
{
for range in other.sent_authed_idx.difference(&self.sent_authed_idx) {
self.sent[range.clone()].copy_from_slice(&other.sent[range]);
}
for range in other
.received_authed_idx
.difference(&self.received_authed_idx)
.iter_ranges()
{
self.received[range.clone()].copy_from_slice(&other.received[range]);
}
self.sent_authed_idx = self.sent_authed_idx.union(&other.sent_authed_idx);
self.received_authed_idx = self.received_authed_idx.union(&other.received_authed_idx);
self.sent_authed_idx.union_mut(&other.sent_authed_idx);
self.received_authed_idx
.union_mut(&other.received_authed_idx);
}
/// Unions an authenticated subsequence into this transcript.
@@ -368,11 +378,11 @@ impl PartialTranscript {
match direction {
Direction::Sent => {
seq.copy_to(&mut self.sent);
self.sent_authed_idx = self.sent_authed_idx.union(&seq.idx);
self.sent_authed_idx.union_mut(&seq.idx);
}
Direction::Received => {
seq.copy_to(&mut self.received);
self.received_authed_idx = self.received_authed_idx.union(&seq.idx);
self.received_authed_idx.union_mut(&seq.idx);
}
}
}
@@ -383,10 +393,10 @@ impl PartialTranscript {
///
/// * `value` - The value to set the unauthenticated bytes to
pub fn set_unauthed(&mut self, value: u8) {
for range in self.sent_unauthed().iter_ranges() {
for range in self.sent_unauthed().iter() {
self.sent[range].fill(value);
}
for range in self.received_unauthed().iter_ranges() {
for range in self.received_unauthed().iter() {
self.received[range].fill(value);
}
}
@@ -401,13 +411,13 @@ impl PartialTranscript {
pub fn set_unauthed_range(&mut self, value: u8, direction: Direction, range: Range<usize>) {
match direction {
Direction::Sent => {
for range in range.difference(&self.sent_authed_idx).iter_ranges() {
self.sent[range].fill(value);
for r in range.difference(&self.sent_authed_idx) {
self.sent[r].fill(value);
}
}
Direction::Received => {
for range in range.difference(&self.received_authed_idx).iter_ranges() {
self.received[range].fill(value);
for r in range.difference(&self.received_authed_idx) {
self.received[r].fill(value);
}
}
}
@@ -485,7 +495,7 @@ impl Subsequence {
/// Panics if the subsequence ranges are out of bounds.
pub(crate) fn copy_to(&self, dest: &mut [u8]) {
let mut offset = 0;
for range in self.idx.iter_ranges() {
for range in self.idx.iter() {
dest[range.clone()].copy_from_slice(&self.data[offset..offset + range.len()]);
offset += range.len();
}
@@ -610,12 +620,7 @@ mod validation {
mut partial_transcript: CompressedPartialTranscriptUnchecked,
) {
// Change the total to be less than the last range's end bound.
let end = partial_transcript
.sent_idx
.iter_ranges()
.next_back()
.unwrap()
.end;
let end = partial_transcript.sent_idx.iter().next_back().unwrap().end;
partial_transcript.sent_total = end - 1;

View File

@@ -2,7 +2,7 @@
use std::{collections::HashSet, fmt};
use rangeset::{ToRangeSet, UnionMut};
use rangeset::set::ToRangeSet;
use serde::{Deserialize, Serialize};
use crate::{

View File

@@ -1,6 +1,6 @@
use std::{collections::HashMap, fmt};
use rangeset::{RangeSet, UnionMut};
use rangeset::set::RangeSet;
use serde::{Deserialize, Serialize};
use crate::{
@@ -103,7 +103,7 @@ impl EncodingProof {
}
expected_leaf.clear();
for range in idx.iter_ranges() {
for range in idx.iter() {
encoder.encode_data(*direction, range.clone(), &data[range], &mut expected_leaf);
}
expected_leaf.extend_from_slice(blinder.as_bytes());

View File

@@ -1,7 +1,7 @@
use std::collections::HashMap;
use bimap::BiMap;
use rangeset::{RangeSet, UnionMut};
use rangeset::set::RangeSet;
use serde::{Deserialize, Serialize};
use crate::{
@@ -99,7 +99,7 @@ impl EncodingTree {
let blinder: Blinder = rand::random();
encoding.clear();
for range in idx.iter_ranges() {
for range in idx.iter() {
provider
.provide_encoding(direction, range, &mut encoding)
.map_err(|_| EncodingTreeError::MissingEncoding { index: idx.clone() })?;

View File

@@ -1,6 +1,10 @@
//! Transcript proofs.
use rangeset::{Cover, Difference, Subset, ToRangeSet, UnionMut};
use rangeset::{
iter::RangeIterator,
ops::{Cover, Set},
set::ToRangeSet,
};
use serde::{Deserialize, Serialize};
use std::{collections::HashSet, fmt};
@@ -144,7 +148,7 @@ impl TranscriptProof {
}
buffer.clear();
for range in idx.iter_ranges() {
for range in idx.iter() {
buffer.extend_from_slice(&plaintext[range]);
}
@@ -366,7 +370,7 @@ impl<'a> TranscriptProofBuilder<'a> {
if idx.is_subset(committed) {
self.query_idx.union(&direction, &idx);
} else {
let missing = idx.difference(committed);
let missing = idx.difference(committed).into_set();
return Err(TranscriptProofBuilderError::new(
BuilderErrorKind::MissingCommitment,
format!(
@@ -582,7 +586,7 @@ impl fmt::Display for TranscriptProofBuilderError {
#[cfg(test)]
mod tests {
use rand::{Rng, SeedableRng};
use rangeset::RangeSet;
use rangeset::prelude::*;
use rstest::rstest;
use tlsn_data_fixtures::http::{request::GET_WITH_HEADER, response::OK_JSON};

View File

@@ -1,7 +1,7 @@
use std::ops::Range;
use mpz_memory_core::{Vector, binary::U8};
use rangeset::RangeSet;
use rangeset::set::RangeSet;
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct RangeMap<T> {
@@ -77,7 +77,7 @@ where
pub(crate) fn index(&self, idx: &RangeSet<usize>) -> Option<Self> {
let mut map = Vec::new();
for idx in idx.iter_ranges() {
for idx in idx.iter() {
let pos = match self.map.binary_search_by(|(base, _)| base.cmp(&idx.start)) {
Ok(i) => i,
Err(0) => return None,

View File

@@ -2,7 +2,7 @@ use mpc_tls::SessionKeys;
use mpz_common::Context;
use mpz_memory_core::binary::Binary;
use mpz_vm_core::Vm;
use rangeset::{RangeSet, UnionMut};
use rangeset::set::RangeSet;
use tlsn_core::{
ProverOutput,
config::prove::ProveConfig,

View File

@@ -12,7 +12,7 @@ use mpz_memory_core::{
binary::{Binary, U8},
};
use mpz_vm_core::{Call, CallableExt, Vm};
use rangeset::{Difference, RangeSet, Union};
use rangeset::{iter::RangeIterator, ops::Set, set::RangeSet};
use tlsn_core::transcript::Record;
use crate::transcript_internal::ReferenceMap;
@@ -32,7 +32,7 @@ pub(crate) fn prove_plaintext<'a>(
commit.clone()
} else {
// The plaintext is only partially revealed, so we need to authenticate in ZK.
commit.union(reveal)
commit.union(reveal).into_set()
};
let plaintext_refs = alloc_plaintext(vm, &alloc_ranges)?;
@@ -49,7 +49,7 @@ pub(crate) fn prove_plaintext<'a>(
vm.commit(*slice).map_err(PlaintextAuthError::vm)?;
}
} else {
let private = commit.difference(reveal);
let private = commit.difference(reveal).into_set();
for (_, slice) in plaintext_refs
.index(&private)
.expect("all ranges are allocated")
@@ -98,7 +98,7 @@ pub(crate) fn verify_plaintext<'a>(
commit.clone()
} else {
// The plaintext is only partially revealed, so we need to authenticate in ZK.
commit.union(reveal)
commit.union(reveal).into_set()
};
let plaintext_refs = alloc_plaintext(vm, &alloc_ranges)?;
@@ -123,7 +123,7 @@ pub(crate) fn verify_plaintext<'a>(
ciphertext,
})
} else {
let private = commit.difference(reveal);
let private = commit.difference(reveal).into_set();
for (_, slice) in plaintext_refs
.index(&private)
.expect("all ranges are allocated")
@@ -175,15 +175,13 @@ fn alloc_plaintext(
let plaintext = vm.alloc_vec::<U8>(len).map_err(PlaintextAuthError::vm)?;
let mut pos = 0;
Ok(ReferenceMap::from_iter(ranges.iter_ranges().map(
move |range| {
let chunk = plaintext
.get(pos..pos + range.len())
.expect("length was checked");
pos += range.len();
(range.start, chunk)
},
)))
Ok(ReferenceMap::from_iter(ranges.iter().map(move |range| {
let chunk = plaintext
.get(pos..pos + range.len())
.expect("length was checked");
pos += range.len();
(range.start, chunk)
})))
}
fn alloc_ciphertext<'a>(
@@ -212,15 +210,13 @@ fn alloc_ciphertext<'a>(
let ciphertext: Vector<U8> = vm.call(call).map_err(PlaintextAuthError::vm)?;
let mut pos = 0;
Ok(ReferenceMap::from_iter(ranges.iter_ranges().map(
move |range| {
let chunk = ciphertext
.get(pos..pos + range.len())
.expect("length was checked");
pos += range.len();
(range.start, chunk)
},
)))
Ok(ReferenceMap::from_iter(ranges.iter().map(move |range| {
let chunk = ciphertext
.get(pos..pos + range.len())
.expect("length was checked");
pos += range.len();
(range.start, chunk)
})))
}
fn alloc_keystream<'a>(
@@ -233,7 +229,7 @@ fn alloc_keystream<'a>(
let mut keystream = Vec::new();
let mut pos = 0;
let mut range_iter = ranges.iter_ranges();
let mut range_iter = ranges.iter();
let mut current_range = range_iter.next();
for record in records {
let mut explicit_nonce = None;
@@ -508,7 +504,7 @@ mod tests {
for record in records {
let mut record_keystream = vec![0u8; record.len];
aes_ctr_apply_keystream(&key, &iv, &record.explicit_nonce, &mut record_keystream);
for mut range in ranges.iter_ranges() {
for mut range in ranges.iter() {
range.start = range.start.max(pos);
range.end = range.end.min(pos + record.len);
if range.start < range.end {

View File

@@ -9,7 +9,7 @@ use mpz_memory_core::{
correlated::{Delta, Key, Mac},
};
use rand::Rng;
use rangeset::RangeSet;
use rangeset::set::RangeSet;
use serde::{Deserialize, Serialize};
use serio::{SinkExt, stream::IoStreamExt};
use tlsn_core::{

View File

@@ -9,7 +9,7 @@ use mpz_memory_core::{
binary::{Binary, U8},
};
use mpz_vm_core::{Vm, VmError, prelude::*};
use rangeset::RangeSet;
use rangeset::set::RangeSet;
use tlsn_core::{
hash::{Blinder, Hash, HashAlgId, TypedHash},
transcript::{
@@ -155,7 +155,7 @@ fn hash_commit_inner(
Direction::Received => &refs.recv,
};
for range in idx.iter_ranges() {
for range in idx.iter() {
hasher.update(&refs.get(range).expect("plaintext refs are valid"));
}
@@ -176,7 +176,7 @@ fn hash_commit_inner(
Direction::Received => &refs.recv,
};
for range in idx.iter_ranges() {
for range in idx.iter() {
hasher
.update(vm, &refs.get(range).expect("plaintext refs are valid"))
.map_err(HashCommitError::hasher)?;
@@ -201,7 +201,7 @@ fn hash_commit_inner(
Direction::Received => &refs.recv,
};
for range in idx.iter_ranges() {
for range in idx.iter() {
hasher
.update(vm, &refs.get(range).expect("plaintext refs are valid"))
.map_err(HashCommitError::hasher)?;

View File

@@ -2,7 +2,7 @@ use mpc_tls::SessionKeys;
use mpz_common::Context;
use mpz_memory_core::binary::Binary;
use mpz_vm_core::Vm;
use rangeset::{RangeSet, UnionMut};
use rangeset::set::RangeSet;
use tlsn_core::{
VerifierOutput,
config::prove::ProveRequest,

View File

@@ -1,5 +1,5 @@
use futures::{AsyncReadExt, AsyncWriteExt};
use rangeset::RangeSet;
use rangeset::set::RangeSet;
use tlsn::{
config::{
prove::ProveConfig,
@@ -51,19 +51,11 @@ async fn test() {
assert_eq!(server_name.as_str(), SERVER_DOMAIN);
assert!(!partial_transcript.is_complete());
assert_eq!(
partial_transcript
.sent_authed()
.iter_ranges()
.next()
.unwrap(),
partial_transcript.sent_authed().iter().next().unwrap(),
0..10
);
assert_eq!(
partial_transcript
.received_authed()
.iter_ranges()
.next()
.unwrap(),
partial_transcript.received_authed().iter().next().unwrap(),
0..10
);

View File

@@ -151,9 +151,9 @@ impl From<tlsn::transcript::PartialTranscript> for PartialTranscript {
fn from(value: tlsn::transcript::PartialTranscript) -> Self {
Self {
sent: value.sent_unsafe().to_vec(),
sent_authed: value.sent_authed().iter_ranges().collect(),
sent_authed: value.sent_authed().iter().collect(),
recv: value.received_unsafe().to_vec(),
recv_authed: value.received_authed().iter_ranges().collect(),
recv_authed: value.received_authed().iter().collect(),
}
}
}