From 82d509266b11d3911569689f961c1320d44e27b1 Mon Sep 17 00:00:00 2001 From: yuroitaki <25913766+yuroitaki@users.noreply.github.com> Date: Wed, 8 Oct 2025 10:13:07 +0800 Subject: [PATCH] feat: add blake3 transcript commitment (#1000) * Add blake3. * Update mpz version. --------- Co-authored-by: yuroitaki <> --- Cargo.lock | 43 +++++++++++++++-------------- Cargo.toml | 26 ++++++++--------- crates/core/src/transcript/proof.rs | 13 ++++++--- crates/tlsn/src/commit/hash.rs | 31 +++++++++++++++++++-- 4 files changed, 72 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db21af1ce..9842b75c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2010,7 +2010,7 @@ checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "clmul" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "bytemuck", "cfg-if", @@ -4205,7 +4205,7 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "matrix-transpose" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "thiserror 1.0.69", ] @@ -4261,7 +4261,7 @@ dependencies = [ [[package]] name = "mpz-circuits" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "bincode 1.3.3", "itybity 0.3.1", @@ -4277,7 +4277,7 @@ dependencies = [ [[package]] name = "mpz-cointoss" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "futures", "mpz-cointoss-core", @@ -4290,7 +4290,7 @@ dependencies = [ [[package]] name = "mpz-cointoss-core" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "mpz-core", "opaque-debug", @@ -4301,7 +4301,7 @@ dependencies = [ [[package]] name = "mpz-common" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "async-trait", "bytes", @@ -4321,7 +4321,7 @@ dependencies = [ [[package]] name = "mpz-core" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "aes 0.9.0-rc.1", "bcs", @@ -4347,7 +4347,7 @@ dependencies = [ [[package]] name = "mpz-fields" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "ark-ff 0.4.2", "ark-secp256r1", @@ -4367,7 +4367,7 @@ dependencies = [ [[package]] name = "mpz-garble" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "async-trait", "derive_builder 0.11.2", @@ -4393,7 +4393,7 @@ dependencies = [ [[package]] name = "mpz-garble-core" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "aes 0.9.0-rc.1", "bitvec", @@ -4424,8 +4424,9 @@ dependencies = [ [[package]] name = "mpz-hash" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ + "blake3", "itybity 0.3.1", "mpz-circuits", "mpz-core", @@ -4436,7 +4437,7 @@ dependencies = [ [[package]] name = "mpz-memory-core" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "blake3", "futures", @@ -4451,7 +4452,7 @@ dependencies = [ [[package]] name = "mpz-ole" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "async-trait", "futures", @@ -4469,7 +4470,7 @@ dependencies = [ [[package]] name = "mpz-ole-core" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "hybrid-array", "itybity 0.3.1", @@ -4485,7 +4486,7 @@ dependencies = [ [[package]] name = "mpz-ot" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "async-trait", "cfg-if", @@ -4508,7 +4509,7 @@ dependencies = [ [[package]] name = "mpz-ot-core" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "aes 0.9.0-rc.1", "blake3", @@ -4539,7 +4540,7 @@ dependencies = [ [[package]] name = "mpz-share-conversion" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "async-trait", "mpz-common", @@ -4555,7 +4556,7 @@ dependencies = [ [[package]] name = "mpz-share-conversion-core" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "mpz-common", "mpz-core", @@ -4569,7 +4570,7 @@ dependencies = [ [[package]] name = "mpz-vm-core" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "async-trait", "futures", @@ -4582,7 +4583,7 @@ dependencies = [ [[package]] name = "mpz-zk" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "async-trait", "blake3", @@ -4600,7 +4601,7 @@ dependencies = [ [[package]] name = "mpz-zk-core" version = "0.1.0-alpha.3" -source = "git+https://github.com/privacy-ethereum/mpz?rev=3d90b6c#3d90b6cd5ec34f51735d4cebe7988d259d4dc528" +source = "git+https://github.com/privacy-ethereum/mpz?rev=8dce54e#8dce54ed9a136bdb8f9624b9d1fad00625b6ff02" dependencies = [ "blake3", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 73e23cdb1..c0514a3f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,19 +66,19 @@ tlsn-harness-runner = { path = "crates/harness/runner" } tlsn-wasm = { path = "crates/wasm" } tlsn = { path = "crates/tlsn" } -mpz-circuits = { git = "https://github.com/privacy-ethereum/mpz", rev = "3d90b6c" } -mpz-memory-core = { git = "https://github.com/privacy-ethereum/mpz", rev = "3d90b6c" } -mpz-common = { git = "https://github.com/privacy-ethereum/mpz", rev = "3d90b6c" } -mpz-core = { git = "https://github.com/privacy-ethereum/mpz", rev = "3d90b6c" } -mpz-vm-core = { git = "https://github.com/privacy-ethereum/mpz", rev = "3d90b6c" } -mpz-garble = { git = "https://github.com/privacy-ethereum/mpz", rev = "3d90b6c" } -mpz-garble-core = { git = "https://github.com/privacy-ethereum/mpz", rev = "3d90b6c" } -mpz-ole = { git = "https://github.com/privacy-ethereum/mpz", rev = "3d90b6c" } -mpz-ot = { git = "https://github.com/privacy-ethereum/mpz", rev = "3d90b6c" } -mpz-share-conversion = { git = "https://github.com/privacy-ethereum/mpz", rev = "3d90b6c" } -mpz-fields = { git = "https://github.com/privacy-ethereum/mpz", rev = "3d90b6c" } -mpz-zk = { git = "https://github.com/privacy-ethereum/mpz", rev = "3d90b6c" } -mpz-hash = { git = "https://github.com/privacy-ethereum/mpz", rev = "3d90b6c" } +mpz-circuits = { git = "https://github.com/privacy-ethereum/mpz", rev = "8dce54e" } +mpz-memory-core = { git = "https://github.com/privacy-ethereum/mpz", rev = "8dce54e" } +mpz-common = { git = "https://github.com/privacy-ethereum/mpz", rev = "8dce54e" } +mpz-core = { git = "https://github.com/privacy-ethereum/mpz", rev = "8dce54e" } +mpz-vm-core = { git = "https://github.com/privacy-ethereum/mpz", rev = "8dce54e" } +mpz-garble = { git = "https://github.com/privacy-ethereum/mpz", rev = "8dce54e" } +mpz-garble-core = { git = "https://github.com/privacy-ethereum/mpz", rev = "8dce54e" } +mpz-ole = { git = "https://github.com/privacy-ethereum/mpz", rev = "8dce54e" } +mpz-ot = { git = "https://github.com/privacy-ethereum/mpz", rev = "8dce54e" } +mpz-share-conversion = { git = "https://github.com/privacy-ethereum/mpz", rev = "8dce54e" } +mpz-fields = { git = "https://github.com/privacy-ethereum/mpz", rev = "8dce54e" } +mpz-zk = { git = "https://github.com/privacy-ethereum/mpz", rev = "8dce54e" } +mpz-hash = { git = "https://github.com/privacy-ethereum/mpz", rev = "8dce54e" } rangeset = { version = "0.2" } serio = { version = "0.2" } diff --git a/crates/core/src/transcript/proof.rs b/crates/core/src/transcript/proof.rs index 3d6fa9b8e..999925f84 100644 --- a/crates/core/src/transcript/proof.rs +++ b/crates/core/src/transcript/proof.rs @@ -22,6 +22,9 @@ const DEFAULT_COMMITMENT_KINDS: &[TranscriptCommitmentKind] = &[ TranscriptCommitmentKind::Hash { alg: HashAlgId::SHA256, }, + TranscriptCommitmentKind::Hash { + alg: HashAlgId::BLAKE3, + }, TranscriptCommitmentKind::Encoding, ]; @@ -637,7 +640,9 @@ mod tests { } #[rstest] - fn test_reveal_with_hash_commitment() { + #[case::sha256(HashAlgId::SHA256)] + #[case::blake3(HashAlgId::BLAKE3)] + fn test_reveal_with_hash_commitment(#[case] alg: HashAlgId) { let mut rng = rand::rngs::StdRng::seed_from_u64(0); let provider = HashProvider::default(); let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON); @@ -645,7 +650,6 @@ mod tests { let direction = Direction::Sent; let idx = RangeSet::from(0..10); let blinder: Blinder = rng.random(); - let alg = HashAlgId::SHA256; let hasher = provider.get(&alg).unwrap(); let commitment = PlaintextHash { @@ -683,7 +687,9 @@ mod tests { } #[rstest] - fn test_reveal_with_inconsistent_hash_commitment() { + #[case::sha256(HashAlgId::SHA256)] + #[case::blake3(HashAlgId::BLAKE3)] + fn test_reveal_with_inconsistent_hash_commitment(#[case] alg: HashAlgId) { let mut rng = rand::rngs::StdRng::seed_from_u64(0); let provider = HashProvider::default(); let transcript = Transcript::new(GET_WITH_HEADER, OK_JSON); @@ -691,7 +697,6 @@ mod tests { let direction = Direction::Sent; let idx = RangeSet::from(0..10); let blinder: Blinder = rng.random(); - let alg = HashAlgId::SHA256; let hasher = provider.get(&alg).unwrap(); let commitment = PlaintextHash { diff --git a/crates/tlsn/src/commit/hash.rs b/crates/tlsn/src/commit/hash.rs index eefeb00f5..b8c93a95d 100644 --- a/crates/tlsn/src/commit/hash.rs +++ b/crates/tlsn/src/commit/hash.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use mpz_core::bitvec::BitVec; -use mpz_hash::sha256::Sha256; +use mpz_hash::{blake3::Blake3, sha256::Sha256}; use mpz_memory_core::{ DecodeFutureTyped, MemoryExt, Vector, binary::{Binary, U8}, @@ -107,6 +107,12 @@ pub(crate) fn verify_hash( Ok(HashCommitFuture { futs }) } +#[derive(Clone)] +enum Hasher { + Sha256(Sha256), + Blake3(Blake3), +} + /// Commit plaintext hashes of the transcript. #[allow(clippy::type_complexity)] fn hash_commit_inner( @@ -135,11 +141,11 @@ fn hash_commit_inner( let hash = match alg { HashAlgId::SHA256 => { - let mut hasher = if let Some(hasher) = hashers.get(&alg).cloned() { + let mut hasher = if let Some(Hasher::Sha256(hasher)) = hashers.get(&alg).cloned() { hasher } else { let hasher = Sha256::new_with_init(vm).map_err(HashCommitError::hasher)?; - hashers.insert(alg, hasher.clone()); + hashers.insert(alg, Hasher::Sha256(hasher.clone())); hasher }; @@ -149,6 +155,25 @@ fn hash_commit_inner( hasher.update(&blinder); hasher.finalize(vm).map_err(HashCommitError::hasher)? } + HashAlgId::BLAKE3 => { + let mut hasher = if let Some(Hasher::Blake3(hasher)) = hashers.get(&alg).cloned() { + hasher + } else { + let hasher = Blake3::new(vm).map_err(HashCommitError::hasher)?; + hashers.insert(alg, Hasher::Blake3(hasher.clone())); + hasher + }; + + for plaintext in refs.get(direction, &idx).expect("plaintext refs are valid") { + hasher + .update(vm, &plaintext) + .map_err(HashCommitError::hasher)?; + } + hasher + .update(vm, &blinder) + .map_err(HashCommitError::hasher)?; + hasher.finalize(vm).map_err(HashCommitError::hasher)? + } alg => { return Err(HashCommitError::unsupported_alg(alg)); }