Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Chore] - Add beta v1 proof verification test #508

Merged
merged 6 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions contracts/contracts/test-contracts/TestLineaRollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,8 @@ contract TestLineaRollup is LineaRollup {
function setShnarfFinalBlockNumber(bytes32 _shnarf, uint256 _finalBlockNumber) external {
blobShnarfExists[_shnarf] = _finalBlockNumber;
}

function setLastFinalizedState(uint256 _messageNumber, bytes32 _rollingHash, uint256 _timestamp) external {
currentFinalizedState = _computeLastFinalizedState(_messageNumber, _rollingHash, _timestamp);
}
}
184 changes: 184 additions & 0 deletions contracts/test/LineaRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import firstCompressedDataContent from "./testData/compressedData/blocks-1-46.js
import secondCompressedDataContent from "./testData/compressedData/blocks-47-81.json";
import fourthCompressedDataContent from "./testData/compressedData/blocks-115-155.json";
import fourthMultipleCompressedDataContent from "./testData/compressedData/multipleProofs/blocks-120-153.json";

import betaV1FinalizationData from "./testData/betaV1/proof/7027059-7042723-d2221f5035e3dcbbc46e8a6130fef34fdec33c252b7d31fb8afa6848660260ba-getZkAggregatedProof.json";

import {
ADDRESS_ZERO,
GENERAL_PAUSE_TYPE,
Expand Down Expand Up @@ -68,6 +71,7 @@ import {
calculateLastFinalizedState,
expectEvents,
expectEventDirectFromReceiptData,
generateBlobDataSubmissionFromFile,
} from "./common/helpers";
import { CalldataSubmissionData, ShnarfDataGenerator } from "./common/types";
import aggregatedProof1To81 from "./testData/compressedData/multipleProofs/aggregatedProof-1-81.json";
Expand All @@ -79,13 +83,15 @@ import {
LINEA_ROLLUP_UNPAUSE_TYPES_ROLES,
} from "contracts/common/constants";
import { generateRoleAssignments } from "contracts/common/helpers";
import * as fs from "fs";

kzg.loadTrustedSetup(`${__dirname}/testData/trusted_setup.txt`);

describe("Linea Rollup contract", () => {
let lineaRollup: TestLineaRollup;
let lineaRollupV5: TestLineaRollupV5;
let revertingVerifier: string;
let sepoliaFullVerifier: string;
let callForwardingProxy: CallForwardingProxy;

// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -109,6 +115,13 @@ describe("Linea Rollup contract", () => {
revertingVerifier = await verifier.getAddress();
}

async function deployPlonkVerifierSepoliaFull() {
const plonkVerifierSepoliaFull = await ethers.getContractFactory("PlonkVerifierSepoliaFull");
const verifier = await plonkVerifierSepoliaFull.deploy();
await verifier.waitForDeployment();
sepoliaFullVerifier = await verifier.getAddress();
}

async function deployCallForwardingProxy(target: string) {
const callForwardingProxyFactory = await ethers.getContractFactory("CallForwardingProxy");
callForwardingProxy = await callForwardingProxyFactory.deploy(target);
Expand Down Expand Up @@ -160,6 +173,8 @@ describe("Linea Rollup contract", () => {
addresses: [operator.address],
},
]);

await deployPlonkVerifierSepoliaFull();
});

beforeEach(async () => {
Expand Down Expand Up @@ -1537,6 +1552,132 @@ describe("Linea Rollup contract", () => {
await expectRevertWithCustomError(lineaRollup, finalizeCall, "FinalBlockStateEqualsZeroHash");
});
});

it("Can submit blobs and finalize with Prover Beta V1", async () => {
const blobFiles = getBetaV1BlobFiles();
const finalBlobFile = JSON.parse(
fs.readFileSync(`${__dirname}/testData/betaV1/${blobFiles.slice(-1)[0]}`, "utf-8"),
);

const initializationData = {
initialStateRootHash: betaV1FinalizationData.parentStateRootHash,
initialL2BlockNumber: betaV1FinalizationData.lastFinalizedBlockNumber,
genesisTimestamp: betaV1FinalizationData.parentAggregationLastBlockTimestamp,
defaultVerifier: sepoliaFullVerifier,
rateLimitPeriodInSeconds: ONE_DAY_IN_SECONDS,
rateLimitAmountInWei: INITIAL_WITHDRAW_LIMIT,
roleAddresses,
pauseTypeRoles: LINEA_ROLLUP_PAUSE_TYPES_ROLES,
unpauseTypeRoles: LINEA_ROLLUP_UNPAUSE_TYPES_ROLES,
fallbackOperator: fallbackoperatorAddress,
defaultAdmin: securityCouncil.address,
};

const betaV1LineaRollup = (await deployUpgradableFromFactory("TestLineaRollup", [initializationData], {
initializer: LINEA_ROLLUP_INITIALIZE_SIGNATURE,
unsafeAllow: ["constructor"],
})) as unknown as TestLineaRollup;

await betaV1LineaRollup.setupParentShnarf(betaV1FinalizationData.parentAggregationFinalShnarf);
await betaV1LineaRollup.setLastFinalizedShnarf(betaV1FinalizationData.parentAggregationFinalShnarf);

for (let i = 0; i < blobFiles.length; i++) {
await sendBlobTransactionFromFile(blobFiles[i], betaV1LineaRollup);
}

const finalizationData = await generateFinalizationData({
l1RollingHash: betaV1FinalizationData.l1RollingHash,
l1RollingHashMessageNumber: BigInt(betaV1FinalizationData.l1RollingHashMessageNumber),
lastFinalizedTimestamp: BigInt(betaV1FinalizationData.parentAggregationLastBlockTimestamp),
endBlockNumber: BigInt(betaV1FinalizationData.finalBlockNumber),
parentStateRootHash: betaV1FinalizationData.parentStateRootHash,
finalTimestamp: BigInt(betaV1FinalizationData.finalTimestamp),
l2MerkleRoots: betaV1FinalizationData.l2MerkleRoots,
l2MerkleTreesDepth: BigInt(betaV1FinalizationData.l2MerkleTreesDepth),
l2MessagingBlocksOffsets: betaV1FinalizationData.l2MessagingBlocksOffsets,
aggregatedProof: betaV1FinalizationData.aggregatedProof,
shnarfData: {
parentShnarf: finalBlobFile.prevShnarf,
snarkHash: finalBlobFile.snarkHash,
finalStateRootHash: finalBlobFile.finalStateRootHash,
dataEvaluationPoint: finalBlobFile.expectedX,
dataEvaluationClaim: finalBlobFile.expectedY,
},
});

finalizationData.lastFinalizedL1RollingHash = betaV1FinalizationData.parentAggregationLastL1RollingHash;
finalizationData.lastFinalizedL1RollingHashMessageNumber = BigInt(
betaV1FinalizationData.parentAggregationLastL1RollingHashMessageNumber,
);

await betaV1LineaRollup.setLastFinalizedState(
betaV1FinalizationData.parentAggregationLastL1RollingHashMessageNumber,
betaV1FinalizationData.parentAggregationLastL1RollingHash,
betaV1FinalizationData.parentAggregationLastBlockTimestamp,
);
await betaV1LineaRollup.setRollingHash(
betaV1FinalizationData.l1RollingHashMessageNumber,
betaV1FinalizationData.l1RollingHash,
);

const finalizeCompressedCall = betaV1LineaRollup
.connect(operator)
.finalizeBlocks(betaV1FinalizationData.aggregatedProof, TEST_PUBLIC_VERIFIER_INDEX, finalizationData);

const eventArgs = [
BigInt(betaV1FinalizationData.lastFinalizedBlockNumber) + 1n,
finalizationData.endBlockNumber,
betaV1FinalizationData.finalShnarf,
finalizationData.parentStateRootHash,
finalBlobFile.finalStateRootHash,
];

await expectEvent(betaV1LineaRollup, finalizeCompressedCall, "DataFinalizedV3", eventArgs);

const [expectedFinalStateRootHash, lastFinalizedBlockNumber, lastFinalizedState] = await Promise.all([
betaV1LineaRollup.stateRootHashes(finalizationData.endBlockNumber),
betaV1LineaRollup.currentL2BlockNumber(),
betaV1LineaRollup.currentFinalizedState(),
]);

expect(expectedFinalStateRootHash).to.equal(finalizationData.shnarfData.finalStateRootHash);
expect(lastFinalizedBlockNumber).to.equal(finalizationData.endBlockNumber);
expect(lastFinalizedState).to.equal(
generateKeccak256(
["uint256", "bytes32", "uint256"],
[
finalizationData.l1RollingHashMessageNumber,
finalizationData.l1RollingHash,
finalizationData.finalTimestamp,
],
),
);
});

// Function to extract range from the file name
function extractBlockRangeFromFileName(fileName: string): [number, number] | null {
thedarkjester marked this conversation as resolved.
Show resolved Hide resolved
const rangeRegex = /(\d+)-(\d+)-/;
const match = fileName.match(rangeRegex);
if (match && match.length >= 3) {
return [parseInt(match[1], 10), parseInt(match[2], 10)];
}
return null;
}

function getBetaV1BlobFiles(): string[] {
// Read all files in the folder
const files = fs.readdirSync(`${__dirname}/testData/betaV1`);

// Map files to their ranges and filter invalid ones
const filesWithRanges = files
.map((fileName) => {
const range = extractBlockRangeFromFileName(fileName);
return range ? { fileName, range } : null;
})
.filter(Boolean) as { fileName: string; range: [number, number] }[];

return filesWithRanges.sort((a, b) => a.range[0] - b.range[0]).map((f) => f.fileName);
}
});

describe("Compressed data finalization with proof", () => {
Expand Down Expand Up @@ -2166,6 +2307,49 @@ describe("Linea Rollup contract", () => {
expectEventDirectFromReceiptData(lineaRollup as BaseContract, receipt!, "DataSubmittedV3", expectedEventArgs);
}

async function sendBlobTransactionFromFile(filePath: string, betaV1LineaRollup: TestLineaRollup) {
const operatorHDSigner = getWalletForIndex(2);
const lineaRollupAddress = await betaV1LineaRollup.getAddress();

const {
blobDataSubmission: blobSubmission,
compressedBlobs: compressedBlobs,
parentShnarf: parentShnarf,
finalShnarf: finalShnarf,
} = generateBlobDataSubmissionFromFile(`${__dirname}/testData/betaV1/${filePath}`);

const encodedCall = lineaRollup.interface.encodeFunctionData("submitBlobs", [
blobSubmission,
parentShnarf,
finalShnarf,
]);

const { maxFeePerGas, maxPriorityFeePerGas } = await ethers.provider.getFeeData();
const nonce = await operatorHDSigner.getNonce();

const transaction = Transaction.from({
data: encodedCall,
maxPriorityFeePerGas: maxPriorityFeePerGas!,
maxFeePerGas: maxFeePerGas!,
to: lineaRollupAddress,
chainId: (await ethers.provider.getNetwork()).chainId,
type: 3,
nonce: nonce,
value: 0,
gasLimit: 5_000_000,
kzg,
maxFeePerBlobGas: 1n,
blobs: compressedBlobs,
});

const signedTx = await operatorHDSigner.signTransaction(transaction);
const txResponse = await ethers.provider.broadcastTransaction(signedTx);
const receipt = await ethers.provider.getTransactionReceipt(txResponse.hash);
const expectedEventArgs = [parentShnarf, finalShnarf, blobSubmission[blobSubmission.length - 1].finalStateRootHash];

expectEventDirectFromReceiptData(lineaRollup as BaseContract, receipt!, "DataSubmittedV3", expectedEventArgs);
}

async function sendBlobTransactionViaCallForwarder(
lineaRollupUpgraded: Contract,
startIndex: number,
Expand Down
33 changes: 33 additions & 0 deletions contracts/test/common/helpers/dataGeneration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from "../types";
import { generateRandomBytes, range } from "./general";
import { generateKeccak256 } from "./hashing";
import * as fs from "fs";

export const generateL2MessagingBlocksOffsets = (start: number, end: number) =>
`0x${range(start, end)
Expand Down Expand Up @@ -87,6 +88,38 @@ export function generateBlobDataSubmission(
};
}

export function generateBlobDataSubmissionFromFile(filePath: string): {
blobDataSubmission: BlobSubmission[];
compressedBlobs: string[];
parentShnarf: string;
finalShnarf: string;
} {
const fileContents = JSON.parse(fs.readFileSync(filePath, "utf-8"));

const compressedBlobs: string[] = [];
const parentShnarf = fileContents.prevShnarf;
const finalShnarf = fileContents.expectedShnarf;

compressedBlobs.push(ethers.hexlify(ethers.decodeBase64(fileContents.compressedData)));

const blobDataSubmission = [
{
dataEvaluationClaim: fileContents.expectedY,
kzgCommitment: fileContents.commitment,
kzgProof: fileContents.kzgProofContract,
finalStateRootHash: fileContents.finalStateRootHash,
snarkHash: fileContents.snarkHash,
},
];

return {
compressedBlobs,
blobDataSubmission,
parentShnarf,
finalShnarf,
};
}

export function generateParentShnarfData(index: number, multiple?: boolean): ShnarfData {
if (index === 0) {
return {
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"finalShnarf": "0x7a136069d307ccefc5b6717ea36f57cb2b84a46252f5187eb33b97293014817b",
"parentAggregationFinalShnarf": "0x96753ec2fed56f5b394eb094eb5730e0f177f2a8da6b316c0d9af5a2922fb432",
"aggregatedProof": "0x177a72544b7f9a348229134444086a9aebb4ceb7926d9294c6a6ada22f60c70d04edba6b21762652bb0b6a9dc35a44aa9ce824ca5f070ab513cdc03de4820046138498bb54786094bd48356dd2cfa3f0818b773c20db2a88f139c4cb160893ab28ce46438d707c965f3c3e071ebea4bea19d756a991d017d1654e3fc3800501420e4cf7591a3440103081d56cdc4431cca7d6f3b6e06dca8fbfda2320ae3ab7c2fae1d18b54685fb34fae08b57cb965134f0ba722111405cc138932328e9c09225be749d7e2740523ba91f0654c201bdff05bc175c4794ddf24b3d0d59dd29bc076ea535bfff5d31e02d8281d520d74dd6a4161cee29fd0d9d2e1cff776607ce1403e48ada601a75f6ffbf3bdbab44b0e1790b896b09f749227837c23624f0b2159cb20de349abb2e12f9e735271035884b37365cafc1da5ff27586b7691cb9a1c52b1cc618d25a9bad94742a18b4ba68cbf2b557d84bb54f28c7ce5792a16e328937347a214a077b859d13f2a244d92723de8aa6fc517c7d1ff44d5a378bdcd1283e29f2abc87e8fb7034169da9633a4f92058b4f70ec99f1e7e46a518519c91dac2b9158394e406141bd1f0040b664d972db9485e708e8e5980ac15bffe52c272bb71f5930b8aad319eb59ca7af7dae0485c6afdc1e7070ab5add93d6ea3951fc29fcb36bcca011a1ec93cb9254491f9238d4be9fb59366bdb54a7919491be1d3fbd72d22998c3aace2cddb352117f06e6c5347d99fabd5addfcb33f81362d21b720f44db8d9e990b5ad01a31ea3f81ff37b0af83843d66f41e25af125b01e05ae002683c453bbb9a7fe339e5b1dfa386be40313ad4b54577d09f714228d721193128e34077f0405bf0f0463e534c62b1dd38fdaa62fba7e9cebd3489736391235753f7a90175c3d274533185b7a28cc817910c9d827c820063260c1d1c9251dbc882318ae3eb556e929643a6dad978cf03b184f1d42f3eab6d0761b7ad0492896d01258aa58caf3789c9a13c510ac60322b2aa07475644bf5b7d54065c037232af7903687bf08c04303b4fb58dbcc6469a7c044e37e2c696f354678aad0c2053c174b7040bb89c8e0909238880f0d11334c48d1343a51f8fbd492edfd32e105803424d34e8a8aaccca2bb811287951bd2f531d97f861a8a448e22d3af151014c155aafb33938fc4fc9bd1112195cd6992786cbbd29ae2a80e06bdbbd133fd",
"aggregatedProverVersion": "4.0.0",
"aggregatedVerifierIndex": 1,
"aggregatedProofPublicInput": "0x2bf2182cedb120b0498f6f5c21d3fded5814d1baaaaf0ad0095c4af66aa43760",
"dataHashes": [
"0x017f997a65f5d76eb8729f2fb93a478b5b8c10c6b003acabe75a7ed65e8acf20",
"0x0110077374a890c15cfe3d1491a72360ff0c183caaba0d12218bbac2a6a116a7",
"0x01d141651c5c3dccf00d6c32b1fd89ecb6c7009a150ff67bbbb88c43c63e9b14",
"0x01c17239b3e2855e2f10133585471aee626d5ceefdba469bae01aacd3f949546",
"0x01778fe64db2d70511d98fd140fe49a75380f8e5bd583f83071ea095886e1c1d",
"0x017230c9a2f7630fb4ea3fe14dc1892dcf8409a5133c940f264432df916ce0c2",
"0x010ff5be097add0e119a32274fcef7d40c17db5dc23c20932555e5ffcccd6f46",
"0x010f56b1437003d53dc7c51b3f5c40b013aeac059c2973dca3a98864a63a9e64",
"0x01dca3dfbda6b0ef522f961069a84476d2e535959036e3bb3cd7ba9586f7182e",
"0x01ae24d234d79c4de14ab5805b5753fa45c989b2055445cd362a4b076bf437db",
"0x01a14e692b8e2bf0128193d650c90adbb27454673f332a77a4aa8a17e65cc636",
"0x015fff3b4f7518f743cdfa4031d81cc075b861f7da29e691c20a827fe7c6c0c3",
"0x013741185351b9e8eff5f79c32147b2dc83f75847fb8a32835982dba31c00c12",
"0x016555b059ec3538a6a00afc7ae260c95fdcc3d153b77f7588cdbc78555a8934",
"0x017575773df1d87e8653a9e8e74883d554a6afdf4d62610440f0f0a97f12114b",
"0x01608e7c9e0ce75d08f922fcd5ef1d0bcd21471fbfae9417e6afd041af54678c",
"0x01648df253736fcf9fdd37a201dcd042981b23b52668b4b85aded31a42578183",
"0x01f0d0cf21203028993fc3295afc8b260da193d262c38157b69952bd1f490b1d",
"0x018bdd0c24a95eac0097a84efef9d0993aff3fb102835372f23ed9243c3ed85f",
"0x01cac918ec2270b71a0418002087191cdb9fbad9d0ba19ad726f79b473627866",
"0x01eae3119c1c2cdc7c7a5d17d89a183a30f0dc07886d5d432984bdbce0573e84",
"0x01c7a9c2c30db9310853bc15b380d14224577bd35785f359e7087e3da79617fa",
"0x01957c9b3489688a4c1694cac06ea71598cea989b954a3599e70ac65b7dcdbf3",
"0x01f94c9515f7e5a6dbc0db1c179dc2f4e78ff5a9766f38ed8f0c52fc86ecfb6e",
"0x0153dd977839136be4f0bc5c94e26bfc966e1ff6a7cfc1ff1c165ea4d099b311",
"0x01e539e95eb6b3b4a51af356bca0c9fd0258946e9eb85219904f33558319d080",
"0x012fb46b48563443d95bf4201a6f206f77254ffa6c4ed8ae26d68352ea3cd52f",
"0x017e6ffb3b771e6c0457b97eed0e0c18407f24042f9e0048bffe2f9d66835e7d",
"0x01a299166adb39150b4510e6e46c72d0df1067d632c7a6402799910de1cdef83",
"0x01d2792b5df71881e644faa99fcd47cbad583a2bdece69c2293880c2a24e7b6a",
"0x01a3425716e60db7eb1f2eead49a788e59bdc21da75711c52d1508d52ec592e2",
"0x013202aa697c795b44af46712115cffc3580721d0c62f68714f5f0b8a5cffa10",
"0x016c67d093861515ffe38f32de3507282edac3067f4652ee7e229bffcfccd5d9",
"0x010ca6e792aafa1d1e644294f115e4e7eca67730911fd06474eab50f3df44e8b",
"0x013bc4e57a468d8e5668be245f9ec1c7064c652284219dbe4a35a96f772151cf"
],
"dataParentHash": "0x016241c7d4fa854e828a519465d1438d63bea65cdf71cdfd109aebff6822c50b",
"parentStateRootHash": "0x07ad7d1132d84f9e6c4ee40c18c61be4352d38fdc761a1b0eb2a3731f8b9d8ce",
"parentAggregationLastBlockTimestamp": 1734008807,
"lastFinalizedBlockNumber": 7027058,
"finalTimestamp": 1734047084,
"finalBlockNumber": 7042723,
"l1RollingHash": "0xfc35a07760a5ea43ffe2a084344049a53c1c4b2ccc3d6c3ff4b1f7c931962b5b",
"l1RollingHashMessageNumber": 17492,
"l2MerkleRoots": [
"0xc43b869dba160a6b870cf62697079fd2fb32bcfb54826112bd4bd53ff4662aa0"
],
"l2MerkleTreesDepth": 5,
"l2MessagingBlocksOffsets": "0x020e046f04bb0f0f0f370f6b0f890f9e0fe61002101a107f1090109f10ad10b510e710fd110f111c1323153d17902a103385388138c4",
"parentAggregationLastL1RollingHashMessageNumber": 16998,
"parentAggregationLastL1RollingHash": "0x14a65384fef7a424e59359ffdf2bdb6c6f1cdf077518136f02822188d95836e1"
}
Loading