fix(serdes): decode usize as u64 on 32-bit targets (wasm32 verifier)#328
fix(serdes): decode usize as u64 on 32-bit targets (wasm32 verifier)#328pauldelucia wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Code Review
This pull request replaces the macro-based serialization for usize with a manual implementation to ensure it always serializes as a fixed-width 64-bit integer, which enables cross-platform compatibility between 64-bit provers and 32-bit WASM verifiers. A review comment suggests simplifying this manual implementation by delegating to the existing u64 serialization logic to improve idiomaticity and reduce code duplication.
| fn serialize_into<W: Write>(&self, mut writer: W) -> SerdeResult<()> { | ||
| writer.write_all(&(*self as u64).to_le_bytes())?; | ||
| Ok(()) | ||
| } | ||
| fn deserialize_from<R: Read>(mut reader: R) -> SerdeResult<Self> { | ||
| let mut buffer = [0u8; 8]; | ||
| reader.read_exact(&mut buffer)?; | ||
| let v = u64::from_le_bytes(buffer); | ||
| usize::try_from(v).map_err(|_| SerdeError::DeserializeError) | ||
| } |
There was a problem hiding this comment.
The manual implementation of ExpSerde for usize can be simplified by delegating to the u64 implementation. This is more idiomatic, reduces code duplication, and matches the pattern used for the bool implementation later in this file. It correctly preserves the 8-byte wire format and the try_from check for 32-bit targets.
fn serialize_into<W: Write>(&self, writer: W) -> SerdeResult<()> {
(*self as u64).serialize_into(writer)
}
fn deserialize_from<R: Read>(reader: R) -> SerdeResult<Self> {
let v = u64::deserialize_from(reader)?;
usize::try_from(v).map_err(|_| SerdeError::DeserializeError)
}The `exp_serde_for_number!(usize, 8)` macro expands to a `usize::from_le_bytes([u8; 8])` call that fails on wasm32 (and any other 32-bit target) where `usize::from_le_bytes` takes `[u8; 4]`. Proofs are produced on 64-bit hosts, so the wire format already stores usize as 8 bytes; this change just makes the verifier decode them correctly on 32-bit targets by reading a u64 and try_from-ing to usize. Values above `usize::MAX` on 32-bit (4 GiB) decode to `SerdeError::DeserializeError`. Unblocks WASM verifier builds — the verifier needs to deserialize `Circuit<C>` and `Proof` on wasm32-unknown-unknown for browser/mobile full-GKR verification.
709ab24 to
6a9e39e
Compare
Problem
exp_serde_for_number!(usize, 8)expands to ausize::from_le_bytes([u8; 8])call. On 32-bit targets (wasm32-unknown-unknown,wasm32-wasi)usize::from_le_bytestakes[u8; 4], so the macro fails to compile.Fix
Replace the macro call for
usizewith a hand-writtenExpSerdeimpl that:u64, thentry_from-ing tousize. Values aboveusize::MAXon 32-bit (4 GiB) returnSerdeError::DeserializeError.Why
Proofs are produced on 64-bit hosts; the wire format already stores
usizeas 8 bytes. This is purely a 32-bit-decode fix — no change to what 64-bit consumers see.Motivation: unblocks browser / mobile WASM verifier builds that need to deserialize
Circuit<C>andProofonwasm32-unknown-unknown.Scope
serdes/src/serdes.rs.