Skip to content

Commit b23d31b

Browse files
eigenmikemypatil12
authored andcommitted
feat: bn254 certificate verifier (#1431)
**Motivation:** A BN254 certificate verifier is needed for multichain functionality **Modifications:** New core contract: `BN254CertificateVerifier`. It stores operatorTables and verifies certificates against them. **Result:** Core part of multichain release
1 parent 6c47b77 commit b23d31b

File tree

5 files changed

+1274
-1
lines changed

5 files changed

+1274
-1
lines changed

src/contracts/interfaces/IBN254CertificateVerifier.sol

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,18 @@ interface IBN254CertificateVerifierEvents is IBN254CertificateVerifierTypes {
4141
event TableUpdated(OperatorSet operatorSet, uint32 referenceTimestamp, BN254OperatorSetInfo operatorSetInfo);
4242
}
4343

44+
interface IBN254CertificateVerifierErrors {
45+
///@notice thrown when operator index provided in certificate is invalid
46+
error InvalidOperatorIndex();
47+
}
48+
4449
/// @notice An interface for verifying BN254 certificates
4550
/// @notice This implements the base `IBaseCertificateVerifier` interface
46-
interface IBN254CertificateVerifier is IBN254CertificateVerifierEvents, IBaseCertificateVerifier {
51+
interface IBN254CertificateVerifier is
52+
IBN254CertificateVerifierEvents,
53+
IBaseCertificateVerifier,
54+
IBN254CertificateVerifierErrors
55+
{
4756
/**
4857
* @notice updates the operator table
4958
* @param operatorSet the operatorSet to update the operator table for

src/contracts/libraries/Merkle.sol

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,70 @@ library Merkle {
164164
//the first node in the layer is the root
165165
return layer[0];
166166
}
167+
168+
/**
169+
* @notice this function returns the merkle root of a tree created from a set of leaves using keccak as its hash function
170+
* @param leaves the leaves of the merkle tree
171+
* @return The computed Merkle root of the tree.
172+
*/
173+
function merkleizeKeccak(
174+
bytes32[] memory leaves
175+
) internal pure returns (bytes32) {
176+
// TODO: very inefficient, use ZERO_HASHES
177+
// pad to the next power of 2
178+
uint256 numNodesInLayer = 1;
179+
while (numNodesInLayer < leaves.length) {
180+
numNodesInLayer *= 2;
181+
}
182+
bytes32[] memory layer = new bytes32[](numNodesInLayer);
183+
for (uint256 i = 0; i < leaves.length; i++) {
184+
layer[i] = leaves[i];
185+
}
186+
187+
//while we haven't computed the root
188+
while (numNodesInLayer != 1) {
189+
uint256 numNodesInNextLayer = numNodesInLayer / 2;
190+
//overwrite the first numNodesInLayer nodes in layer with the pairwise hashes of their children
191+
for (uint256 i = 0; i < numNodesInNextLayer; i++) {
192+
layer[i] = keccak256(abi.encodePacked(layer[2 * i], layer[2 * i + 1]));
193+
}
194+
//the next layer above has half as many nodes
195+
numNodesInLayer = numNodesInNextLayer;
196+
}
197+
//the first node in the layer is the root
198+
return layer[0];
199+
}
200+
201+
function getProofKeccak(bytes32[] memory leaves, uint256 index) internal pure returns (bytes memory proof) {
202+
// TODO: very inefficient, use ZERO_HASHES
203+
// pad to the next power of 2
204+
uint256 numNodesInLayer = 1;
205+
while (numNodesInLayer < leaves.length) {
206+
numNodesInLayer *= 2;
207+
}
208+
bytes32[] memory layer = new bytes32[](numNodesInLayer);
209+
for (uint256 i = 0; i < leaves.length; i++) {
210+
layer[i] = leaves[i];
211+
}
212+
213+
//while we haven't computed the root
214+
while (numNodesInLayer != 1) {
215+
//overwrite the first numNodesInLayer nodes in layer with the pairwise hashes of their children
216+
for (uint256 i = 0; i < layer.length; i++) {
217+
if (i == index) {
218+
uint256 siblingIndex = i + 1 - 2 * (i % 2);
219+
proof = abi.encodePacked(proof, layer[siblingIndex]);
220+
index /= 2;
221+
}
222+
}
223+
224+
uint256 numNodesInNextLayer = numNodesInLayer / 2;
225+
//overwrite the first numNodesInLayer nodes in layer with the pairwise hashes of their children
226+
for (uint256 i = 0; i < numNodesInNextLayer; i++) {
227+
layer[i] = keccak256(abi.encodePacked(layer[2 * i], layer[2 * i + 1]));
228+
}
229+
//the next layer above has half as many nodes
230+
numNodesInLayer = numNodesInNextLayer;
231+
}
232+
}
167233
}

0 commit comments

Comments
 (0)