From 4fde49665ac61ada6a6f82b2492148502b3f23a4 Mon Sep 17 00:00:00 2001 From: QUAQ Date: Mon, 4 Nov 2024 17:51:46 -0600 Subject: [PATCH] batched verify blob --- .../src/libraries/EigenDARollupUtils.sol | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/contracts/src/libraries/EigenDARollupUtils.sol b/contracts/src/libraries/EigenDARollupUtils.sol index 4cab6b28a5..e89819e0e9 100644 --- a/contracts/src/libraries/EigenDARollupUtils.sol +++ b/contracts/src/libraries/EigenDARollupUtils.sol @@ -97,6 +97,84 @@ library EigenDARollupUtils { ); } + /** + * @notice Verifies the inclusion of a blob within a batch confirmed in `eigenDAServiceManager` and its trust assumptions + * @param blobHeaders the headers of the blobs containing relevant attributes of the blobs + * @param eigenDAServiceManager the contract in which the batch was confirmed + * @param blobVerificationProofs the relevant data needed to prove inclusion of the blobs and that the trust assumptions were as expected + */ + function verifyBlobs( + IEigenDAServiceManager.BlobHeader[] calldata blobHeaders, + IEigenDAServiceManager eigenDAServiceManager, + BlobVerificationProof[] calldata blobVerificationProofs + ) external view { + require(blobHeaders.length == blobVerificationProofs.length, "EigenDARollupUtils.verifyBlobs: blobHeaders and blobVerificationProofs must have the same length"); + + bytes memory quorumAdversaryThresholdPercentages = eigenDAServiceManager.quorumAdversaryThresholdPercentages(); + uint256 quorumNumbersRequiredBitmap = BitmapUtils.orderedBytesArrayToBitmap(eigenDAServiceManager.quorumNumbersRequired()); + + for (uint i = 0; i < blobHeaders.length; i++) { + require( + EigenDAHasher.hashBatchMetadata(blobVerificationProofs[i].batchMetadata) + == eigenDAServiceManager.batchIdToBatchMetadataHash(blobVerificationProofs[i].batchId), + "EigenDARollupUtils.verifyBlob: batchMetadata does not match stored metadata" + ); + + require( + Merkle.verifyInclusionKeccak( + blobVerificationProofs[i].inclusionProof, + blobVerificationProofs[i].batchMetadata.batchHeader.blobHeadersRoot, + keccak256(abi.encodePacked(EigenDAHasher.hashBlobHeader(blobHeaders[i]))), + blobVerificationProofs[i].blobIndex + ), + "EigenDARollupUtils.verifyBlob: inclusion proof is invalid" + ); + + // bitmap of quorum numbers in all quorumBlobParams + uint256 confirmedQuorumsBitmap; + + // require that the security param in each blob is met + for (uint j = 0; i < blobHeaders[i].quorumBlobParams.length; j++) { + // make sure that the quorumIndex matches the given quorumNumber + require(uint8(blobVerificationProofs[i].batchMetadata.batchHeader.quorumNumbers[uint8(blobVerificationProofs[i].quorumIndices[i])]) == blobHeaders[i].quorumBlobParams[i].quorumNumber, + "EigenDARollupUtils.verifyBlob: quorumNumber does not match" + ); + + // make sure that the adversaryThresholdPercentage is less than the given confirmationThresholdPercentage + require(blobHeaders[i].quorumBlobParams[i].adversaryThresholdPercentage + < blobHeaders[i].quorumBlobParams[i].confirmationThresholdPercentage, + "EigenDARollupUtils.verifyBlob: adversaryThresholdPercentage is not valid" + ); + + // make sure that the adversaryThresholdPercentage is at least the given quorumAdversaryThresholdPercentage + uint8 _adversaryThresholdPercentage = uint8(quorumAdversaryThresholdPercentages[blobHeaders[i].quorumBlobParams[j].quorumNumber]); + if(_adversaryThresholdPercentage > 0){ + require(blobHeaders[i].quorumBlobParams[j].adversaryThresholdPercentage >= _adversaryThresholdPercentage, + "EigenDARollupUtils.verifyBlob: adversaryThresholdPercentage is not met" + ); + } + + // make sure that the stake signed for is greater than the given confirmationThresholdPercentage + require(uint8(blobVerificationProofs[i].batchMetadata.batchHeader.signedStakeForQuorums[uint8(blobVerificationProofs[i].quorumIndices[j])]) + >= blobHeaders[i].quorumBlobParams[j].confirmationThresholdPercentage, + "EigenDARollupUtils.verifyBlob: confirmationThresholdPercentage is not met" + ); + + // mark confirmed quorum in the bitmap + confirmedQuorumsBitmap = BitmapUtils.setBit(confirmedQuorumsBitmap, blobHeaders[i].quorumBlobParams[j].quorumNumber); + } + + // check that required quorums are a subset of the confirmed quorums + require( + BitmapUtils.isSubsetOf( + quorumNumbersRequiredBitmap, + confirmedQuorumsBitmap + ), + "EigenDARollupUtils.verifyBlob: required quorums are not a subset of the confirmed quorums" + ); + } + } + /** * @notice gets the adversary threshold percentage for a given quorum * @param eigenDAServiceManager the contract in which the batch was confirmed