@@ -8,14 +8,22 @@ type MemoryPointer is uint256;
88/// @notice This contract provides a thin wrapper around the Halo2 verifier
99/// outputted by `snark-verifier`, exposing a more user-friendly interface.
1010contract OpenVmHalo2Verifier is AxiomV2QueryVerifier {
11+ /// @dev Invalid partial proof length
1112 error InvalidPartialProofLength ();
13+
14+ /// @dev Invalid guest PVs length
1215 error InvalidGuestPvsLength ();
16+
17+ /// @dev Proof verification failed
1318 error ProofVerificationFailed ();
1419
20+ /// @dev The length of the partial proof, in bytes
1521 uint256 private constant PARTIAL_PROOF_LENGTH = (12 + 43 ) * 32 ;
1622
23+ /// @dev The length of the guest PVs, in bytes. This value is set by OpenVM.
1724 uint256 private constant GUEST_PVS_LENGTH = 32 ;
1825
26+ /// @dev The length of the full proof, in bytes
1927 uint256 private constant FULL_PROOF_LENGTH = (12 + 2 + GUEST_PVS_LENGTH + 43 ) * 32 ;
2028
2129 /// @notice A wrapper that constructs the proof into the right format for
@@ -28,22 +36,21 @@ contract OpenVmHalo2Verifier is AxiomV2QueryVerifier {
2836 /// proof[..12 * 32]: KZG accumulators
2937 /// proof[12 * 32..13 * 32]: app exe commit
3038 /// proof[13 * 32..14 * 32]: leaf exe commit
31- /// proof[14 * 32..46 * 32]: guestPvsHash [0..GUEST_PVS_LENGTH]
32- /// proof[46 * 32..]: Guest PVs Suffix
39+ /// proof[14 * 32..(14 + GUEST_PVS_LENGTH) * 32]: guestPvs [0..GUEST_PVS_LENGTH]
40+ /// proof[(14 + GUEST_PVS_LENGTH) * 32..]: Guest PVs Suffix
3341 ///
3442 /// Or with hex offsets
3543 ///
3644 /// proof[..0x180]: KZG accumulators
3745 /// proof[0x180..0x1a0]: app exe commit
3846 /// proof[0x1a0..0x1c0]: leaf exe commit
39- /// proof[0x1c0..0x5c0 ]: guestPvsHash [0..GUEST_PVS_LENGTH]
40- /// proof[0x5c0 ..]: Guest PVs Suffix
47+ /// proof[0x1c0..(0x1c0 + GUEST_PVS_LENGTH * 32) ]: guestPvs [0..GUEST_PVS_LENGTH]
48+ /// proof[(0x1c0 + GUEST_PVS_LENGTH * 32) ..]: Guest PVs Suffix
4149 ///
4250 /// @param partialProof All components of the proof except the Guest PVs,
4351 /// leaf and app exe commits. The expected format is:
4452 /// `abi.encodePacked(KZG accumulators, Guest PVs Suffix)`
45- /// @param guestPvs The PVs revealed by the OpenVM guest program. This
46- /// contract is only compatible with a reveal of exactly 32 bytes.
53+ /// @param guestPvs The PVs revealed by the OpenVM guest program.
4754 /// @param appExeCommit The commitment to the RISC-V executable whose execution
4855 /// is being verified.
4956 /// @param leafExeCommit The commitment to the leaf verifier.
@@ -53,8 +60,8 @@ contract OpenVmHalo2Verifier is AxiomV2QueryVerifier {
5360 bytes32 appExeCommit ,
5461 bytes32 leafExeCommit
5562 ) external view {
56- // We will format the pvsHash and construct the full proof payload
57- // below for submission to the verifier .
63+ // We will format the public values and construct the full proof payload
64+ // below.
5865
5966 MemoryPointer proofPtr = _constructProof (guestPvs, partialProof, appExeCommit, leafExeCommit);
6067
@@ -80,14 +87,13 @@ contract OpenVmHalo2Verifier is AxiomV2QueryVerifier {
8087 // The assembly code should perform the same function as the following
8188 // solidity code:
8289 //
83- // bytes memory guestPvsPayload = new bytes(GUEST_PVS_LENGTH * 32);
84- // for (uint256 i = 0; i < GUEST_PVS_LENGTH; ++i) {
85- // bytes1 pvsByte = guestPvs[i];
86- // guestPvsPayload = bytes.concat(guestPvsPayload, bytes32(uint256(uint8(pvsByte))));
87- // }
88- //
90+ // ```solidity
8991 // bytes memory proof =
9092 // abi.encodePacked(partialProof[0:0x180], appExeCommit, leafExeCommit, guestPvsPayload, partialProof[0x180:]);
93+ // ```
94+ //
95+ // where `guestPvsPayload` is a memory payload with each byte in
96+ // `guestPvs` separated into its own word.
9197
9298 uint256 fullProofLength = FULL_PROOF_LENGTH;
9399
@@ -107,20 +113,15 @@ contract OpenVmHalo2Verifier is AxiomV2QueryVerifier {
107113
108114 // Copy the Guest PVs Suffix (length 43 * 32 = 0x560) into the
109115 // end of the memory buffer, leaving GUEST_PVS_LENGTH words in
110- // between for the guestPvsHash .
116+ // between for the guestPvsPayload .
111117 //
112118 // Begin copying from the end of the KZG accumulators in the
113119 // calldata buffer (0x180)
114120 let suffixProofOffset := add (0x1c0 , shl (5 , GUEST_PVS_LENGTH))
115121 calldatacopy (add (proofPtr, suffixProofOffset), add (partialProof.offset, 0x180 ), 0x560 )
116122
117- // Copy each byte of the guestPvsHash into the proof. It copies the
118- // most significant bytes of guestPvsHash first.
119-
120- // Begin by loading 32-byte segments and copying each byte of each
121- // segment into its own memory slot.
122- let wordCount := div (GUEST_PVS_LENGTH, 32 )
123-
123+ // Copy each byte of the guestPvs into the proof. It copies the
124+ // most significant bytes of guestPvs first.
124125 let guestPvsMemOffset := add (proofPtr, 0x1c0 )
125126 for { let i := 0 } lt (i, GUEST_PVS_LENGTH) { i := add (i, 1 ) } {
126127 calldatacopy (add (guestPvsMemOffset, add (shl (5 , i), 0x1f )), add (guestPvs.offset, i), 0x01 )
0 commit comments