Skip to content
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a29bff2
spec: port jolt-transcript to spongefish
shreyas-londhe Apr 21, 2026
848ebb1
spec: narrow scope to crates/jolt-transcript internal port
shreyas-londhe Apr 22, 2026
d7cf298
spec: narrow jolt-transcript port to crate-only with compat layer
Vishalkulkarni45 May 5, 2026
d90cda5
spec: resolve implementation ambiguities found in analyze-spec review
shreyas-londhe May 5, 2026
4654db8
feat(jolt-transcript): port internals to spongefish 0.7
shreyas-londhe May 12, 2026
042f00c
feat(jolt-eval): add transcript_prover_verifier_consistency invariant
shreyas-londhe May 12, 2026
d387b06
spec: mark jolt-transcript-spongefish status implemented
shreyas-londhe May 12, 2026
5590acc
Merge upstream/main into spec/jolt-transcript-spongefish
shreyas-londhe May 12, 2026
2125d8f
fix(ci): rustfmt, taplo, and pin generic-array 0.14.7
shreyas-londhe May 12, 2026
a68ed76
fix(jolt-transcript): generic FieldEl and guard BytesMsg length overflow
shreyas-londhe May 13, 2026
f824065
perf(jolt-transcript): drop per-op peek_state cache in SpongeTranscript
shreyas-londhe May 13, 2026
ddb62ed
docs(jolt-transcript): note compat challenge() vs OptimizedChallenge …
shreyas-londhe May 13, 2026
40b940a
fix(jolt-transcript): drop Encoding impl on FieldElOptimized to block…
shreyas-londhe May 13, 2026
334c78f
refactor(jolt-transcript): drop Clone bound from compat::Transcript
shreyas-londhe May 19, 2026
4833a93
refactor(jolt-transcript): drop FieldElOptimized, use spongefish u128…
shreyas-londhe May 19, 2026
eec24ad
refactor(jolt-transcript): rename `compat` module to `legacy`
shreyas-londhe May 19, 2026
dfb7ce9
feat(jolt-transcript): native construction API — prover_transcript / …
shreyas-londhe May 19, 2026
b82947c
docs(jolt-transcript): check_eof contract + regression tests
shreyas-londhe May 19, 2026
1e623e6
chore(jolt-transcript): rename PROTOCOL_ID to drop "spongefish"
shreyas-londhe May 19, 2026
2f1215f
refactor(jolt-transcript): drop FieldEl, use spongefish ark-ff codec
shreyas-londhe May 19, 2026
981aa57
Merge remote-tracking branch 'upstream/main' into spec/jolt-transcrip…
shreyas-londhe May 19, 2026
67a1a3c
chore: apply rustfmt and taplo after merge
shreyas-londhe May 20, 2026
b8f4b23
refactor(jolt-transcript): use dot-call syntax in tests per mmaker fe…
shreyas-londhe May 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
406 changes: 327 additions & 79 deletions Cargo.lock

Large diffs are not rendered by default.

17 changes: 10 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,12 @@ lto = "fat"
strip = false
codegen-units = 1

[patch.crates-io]
ark-bn254 = { git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" }
ark-ff = { git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" }
ark-ec = { git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" }
ark-serialize = { git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" }
allocative = { git = "https://github.com/facebookexperimental/allocative", rev = "85b773d85d526d068ce94724ff7a7b81203fc95e" }
[replace]
"ark-bn254:0.5.0" = { git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" }
"ark-ff:0.5.0" = { git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" }
"ark-ec:0.5.0" = { git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" }
"ark-serialize:0.5.0" = { git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" }
"allocative:0.3.4" = { git = "https://github.com/facebookexperimental/allocative", rev = "85b773d85d526d068ce94724ff7a7b81203fc95e" }

[workspace.metadata.cargo-machete]
ignored = ["jolt-sdk"]
Expand Down Expand Up @@ -249,11 +249,14 @@ ark-secp256r1 = { git = "https://github.com/a16z/arkworks-algebra", branch = "de
ark-serialize-derive = { version = "0.5.0", default-features = false }
ark-std = { version = "0.5.0", default-features = false }
sha2 = "0.11"
sha3 = "0.11"
sha3 = "=0.11.0-rc.9"
blake2 = "0.11.0-rc.6"
blake3 = { version = "1.8.5" }
light-poseidon = "0.4"
digest = "0.11"
spongefish = { version = "0.6.1", default-features = false, features = [
"sha3",
] }
jolt-optimizations = { git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" }
dory = { package = "dory-pcs", version = "0.3.0", features = [
"backends",
Expand Down
29 changes: 11 additions & 18 deletions crates/jolt-transcript/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,21 @@ categories = ["cryptography", "no-std"]
[lints]
workspace = true

[features]
default = ["transcript-blake2b", "transcript-keccak", "transcript-poseidon"]
transcript-blake2b = ["spongefish/blake2"]
transcript-keccak = ["spongefish/keccak"]
transcript-poseidon = ["dep:light-poseidon"]

[dependencies]
blake2.workspace = true
digest.workspace = true
sha3.workspace = true
ark-bn254 = { workspace = true, optional = true }
ark-ff = { workspace = true, optional = true }
ark-serialize = { workspace = true, optional = true }
ark-bn254.workspace = true
ark-ff.workspace = true
light-poseidon = { workspace = true, optional = true }
jolt-field = { path = "../jolt-field", default-features = false }

[features]
default = ["poseidon"]
poseidon = [
"dep:ark-bn254",
"dep:ark-ff",
"dep:ark-serialize",
"dep:light-poseidon",
"jolt-field/bn254",
]
spongefish = { workspace = true, features = ["ark-ff"] }
jolt-field = { path = "../jolt-field", features = ["bn254"] }
rand.workspace = true

[dev-dependencies]
jolt-field = { path = "../jolt-field", features = ["bn254"] }
num-traits = { workspace = true }
criterion = { workspace = true }

Expand Down
13 changes: 0 additions & 13 deletions crates/jolt-transcript/src/blake2b.rs

This file was deleted.

16 changes: 0 additions & 16 deletions crates/jolt-transcript/src/blanket.rs

This file was deleted.

97 changes: 97 additions & 0 deletions crates/jolt-transcript/src/codec.rs
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Instead of implementing these traits for ark_bn254::Fr, can we do a blanket implementation over F: jolt_field::CanonicalBytes like we had in blanket.rs?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done — FieldEl<F> / FieldElOptimized<F> now generic with per-impl bounds (CanonicalBytes for Encoding, ReducingBytes/FromPrimitiveInt for Decoding). 64-byte uniform constant stays hardcoded with a doc note (BN254-tuned; sound for any ≤254-bit field).

Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//! Local codecs for absorbing / decoding Jolt-native messages over a
//! byte-oriented spongefish sponge.
//!
//! Field-element codecs come from spongefish's `ark-ff` feature
//! (`spongefish::Encoding<[u8]>` is implemented for every `ark_ff::Fp<C, N>`
//! using big-endian canonical encoding per RFC8017). 128-bit-truncated
//! challenges decode through spongefish's built-in `u128` codec directly;
//! see [`crate::prover::OptimizedChallenge`].
//!
//! This module keeps only `BytesMsg`, the length-prefixed byte string
//! framing that spongefish 0.6 does not provide.

use spongefish::{Encoding, NargDeserialize, VerificationError, VerificationResult};

/// Length-prefixed byte string. 8-byte LE length keeps `BytesMsg(a) ; BytesMsg(b)`
/// distinguishable from `BytesMsg(a||b)`.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BytesMsg(pub Vec<u8>);
Comment on lines +15 to +18
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we implement Encoding and NargDeserialize for Vec<u8> upstream, so we can get rid of this wrapper?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Upstream = external spongefish crate. Wrapper enforces an 8-byte LE u64 length prefix so BytesMsg(a); BytesMsg(b)BytesMsg(a‖b) — a jolt-side choice.

@mmaker — thoughts on adding Encoding<[u8]> + NargDeserialize for Vec<u8> upstream?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I agree with you and @moodlezoup. This wrapper should be in spongefish and derive(Encoding) should work for Vec<u8>.


impl BytesMsg {
/// Returns the inner bytes.
pub fn as_slice(&self) -> &[u8] {
&self.0
}
}

impl From<Vec<u8>> for BytesMsg {
fn from(v: Vec<u8>) -> Self {
Self(v)
}
}

impl Encoding<[u8]> for BytesMsg {
fn encode(&self) -> impl AsRef<[u8]> {
let mut out = Vec::with_capacity(8 + self.0.len());
out.extend_from_slice(&(self.0.len() as u64).to_le_bytes());
out.extend_from_slice(&self.0);
out
}
}

impl NargDeserialize for BytesMsg {
fn deserialize_from_narg(buf: &mut &[u8]) -> VerificationResult<Self> {
if buf.len() < 8 {
return Err(VerificationError);
}
let mut len_bytes = [0u8; 8];
len_bytes.copy_from_slice(&buf[..8]);
let len = u64::from_le_bytes(len_bytes) as usize;
let total = 8usize.checked_add(len).ok_or(VerificationError)?;
if buf.len() < total {
return Err(VerificationError);
}
let body = buf[8..total].to_vec();
*buf = &buf[total..];
Ok(BytesMsg(body))
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn bytes_msg_is_length_prefixed() {
let m = BytesMsg(vec![1, 2, 3, 4]);
let enc = m.encode();
let bytes = enc.as_ref();
assert_eq!(bytes.len(), 8 + 4);
assert_eq!(&bytes[..8], &4u64.to_le_bytes());
assert_eq!(&bytes[8..], &[1, 2, 3, 4]);
}

#[test]
fn bytes_msg_narg_rejects_truncation() {
let m = BytesMsg(vec![9, 8, 7]);
let mut narg: Vec<u8> = Vec::new();
narg.extend_from_slice(m.encode().as_ref());
let _ = narg.pop();
let mut cursor: &[u8] = &narg;
let before = cursor.len();
let result = BytesMsg::deserialize_from_narg(&mut cursor);
assert!(result.is_err());
assert_eq!(cursor.len(), before, "cursor must not advance on error");
}

#[test]
fn bytes_msg_narg_rejects_oversized_length() {
let mut narg = Vec::new();
narg.extend_from_slice(&u64::MAX.to_le_bytes());
let mut cursor: &[u8] = &narg;
let before = cursor.len();
let result = BytesMsg::deserialize_from_narg(&mut cursor);
assert!(result.is_err());
assert_eq!(cursor.len(), before, "cursor must not advance on error");
}
}
182 changes: 0 additions & 182 deletions crates/jolt-transcript/src/digest.rs

This file was deleted.

Loading