Skip to content

Commit fc55615

Browse files
authored
feat: add new zkevm verifier for Feynman upgrade (#123)
1 parent 95113a0 commit fc55615

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity =0.8.24;
4+
5+
import {IZkEvmVerifierV2} from "./IZkEvmVerifier.sol";
6+
7+
// solhint-disable no-inline-assembly
8+
9+
contract ZkEvmVerifierPostFeynman is IZkEvmVerifierV2 {
10+
/**********
11+
* Errors *
12+
**********/
13+
14+
/// @dev Thrown when bundle recursion zk proof verification is failed.
15+
error VerificationFailed();
16+
17+
/*************
18+
* Constants *
19+
*************/
20+
21+
/// @notice The address of highly optimized plonk verifier contract.
22+
address public immutable plonkVerifier;
23+
24+
/// @notice A predetermined digest for the `plonkVerifier`.
25+
bytes32 public immutable verifierDigest1;
26+
27+
/// @notice A predetermined digest for the `plonkVerifier`.
28+
bytes32 public immutable verifierDigest2;
29+
30+
/// @notice The version of the protocol.
31+
uint256 public immutable protocolVersion;
32+
33+
/***************
34+
* Constructor *
35+
***************/
36+
37+
constructor(
38+
address _verifier,
39+
bytes32 _verifierDigest1,
40+
bytes32 _verifierDigest2,
41+
uint256 _protocolVersion
42+
) {
43+
plonkVerifier = _verifier;
44+
verifierDigest1 = _verifierDigest1;
45+
verifierDigest2 = _verifierDigest2;
46+
protocolVersion = _protocolVersion;
47+
}
48+
49+
/*************************
50+
* Public View Functions *
51+
*************************/
52+
53+
/// @inheritdoc IZkEvmVerifierV2
54+
///
55+
/// @dev Encoding for `publicInput`. And this is exactly the same as `ZkEvmVerifierV2`.
56+
/// ```text
57+
/// | layer2ChainId | numBatches | prevStateRoot | prevBatchHash | postStateRoot | batchHash | withdrawRoot |
58+
/// | 8 bytes | 4 bytes | 32 bytes | 32 bytes | 32 bytes | 32 bytes | 32 bytes |
59+
/// ```
60+
function verify(bytes calldata bundleProof, bytes calldata publicInput) external view override {
61+
address _verifier = plonkVerifier;
62+
bytes32 _verifierDigest1 = verifierDigest1;
63+
bytes32 _verifierDigest2 = verifierDigest2;
64+
bytes32 publicInputHash = keccak256(abi.encodePacked(protocolVersion, publicInput));
65+
bool success;
66+
67+
// 1. the first 12 * 32 (0x180) bytes of `bundleProof` is `accumulator`
68+
// 2. the rest bytes of `bundleProof` is the actual `bundle_proof`
69+
// 3. Inserted between `accumulator` and `bundle_proof` are
70+
// 32 * 34 (0x440) bytes, such that:
71+
// | start | end | field |
72+
// |---------------|---------------|-------------------------|
73+
// | 0x00 | 0x180 | bundleProof[0x00:0x180] |
74+
// | 0x180 | 0x180 + 0x20 | verifierDigest1 |
75+
// | 0x180 + 0x20 | 0x180 + 0x40 | verifierDigest2 |
76+
// | 0x180 + 0x40 | 0x180 + 0x60 | publicInputHash[0] |
77+
// | 0x180 + 0x60 | 0x180 + 0x80 | publicInputHash[1] |
78+
// ...
79+
// | 0x180 + 0x420 | 0x180 + 0x440 | publicInputHash[31] |
80+
// | 0x180 + 0x440 | dynamic | bundleProof[0x180:] |
81+
assembly {
82+
let p := mload(0x40)
83+
// 1. copy the accumulator's 0x180 bytes
84+
calldatacopy(p, bundleProof.offset, 0x180)
85+
// 2. insert the public input's 0x440 bytes
86+
mstore(add(p, 0x180), _verifierDigest1) // verifierDigest1
87+
mstore(add(p, 0x1a0), _verifierDigest2) // verifierDigest2
88+
for {
89+
let i := 0
90+
} lt(i, 0x400) {
91+
i := add(i, 0x20)
92+
} {
93+
mstore(add(p, sub(0x5a0, i)), and(publicInputHash, 0xff))
94+
publicInputHash := shr(8, publicInputHash)
95+
}
96+
// 3. copy all remaining bytes from bundleProof
97+
calldatacopy(add(p, 0x5c0), add(bundleProof.offset, 0x180), sub(bundleProof.length, 0x180))
98+
// 4. call plonk verifier
99+
success := staticcall(gas(), _verifier, p, add(bundleProof.length, 0x440), 0x00, 0x00)
100+
}
101+
if (!success) {
102+
revert VerificationFailed();
103+
}
104+
}
105+
}

0 commit comments

Comments
 (0)