mirror of
https://github.com/vacp2p/linea-monorepo.git
synced 2026-01-08 03:43:56 -05:00
[Chore] - 498 v5 techdebt cleanup (#613)
* initial V5 removal before main coordinator adjust * fix build issue * default to V6 and remove V5 references * force Web3JLineaRollupSmartContractClientReadOnly * fix test reference * remove V5 references
This commit is contained in:
6
Makefile
6
Makefile
@@ -86,13 +86,9 @@ deploy-linea-rollup:
|
||||
LINEA_ROLLUP_GENESIS_TIMESTAMP=1683325137 \
|
||||
npx ts-node local-deployments-artifacts/deployPlonkVerifierAndLineaRollupV$(L1_CONTRACT_VERSION).ts
|
||||
|
||||
deploy-linea-rollup-v5:
|
||||
$(MAKE) deploy-linea-rollup L1_CONTRACT_VERSION=5
|
||||
|
||||
deploy-linea-rollup-v6:
|
||||
$(MAKE) deploy-linea-rollup L1_CONTRACT_VERSION=6
|
||||
|
||||
|
||||
deploy-l2messageservice:
|
||||
# WARNING: FOR LOCAL DEV ONLY - DO NOT REUSE THESE KEYS ELSEWHERE
|
||||
cd contracts/; \
|
||||
@@ -243,7 +239,7 @@ testnet-start-l2:
|
||||
testnet-start-l2-traces-node-only:
|
||||
docker compose -f docker/compose.yml -f docker/compose-testnet-sync.overries.yml up traces-node -d
|
||||
|
||||
testnet-start: start-l1 deploy-linea-rollup-v5 testnet-start-l2
|
||||
testnet-start: start-l1 deploy-linea-rollup-v6 testnet-start-l2
|
||||
testnet-restart-l2-keep-state:
|
||||
docker compose -f docker/compose.yml -f docker/compose-testnet-sync.overrides.yml rm -f -s -v sequencer traces-node coordinator
|
||||
make testnet-start-l2
|
||||
|
||||
@@ -110,11 +110,11 @@ finalized-block-tag="latest"
|
||||
# reset this once we know what to do on dev/UAT
|
||||
earliest-block=0
|
||||
genesis-state-root-hash="0x072ead6777750dc20232d1cee8dc9a395c2d350df4bbaa5096c6f59b214dcecd"
|
||||
# shnarf for contract V5
|
||||
# shnarf for contract V6
|
||||
# Keccak256(parentShnarf="0x00...00", snarkHash="0x00...00",
|
||||
# parentStateRootHash="0x072ead6777750dc20232d1cee8dc9a395c2d350df4bbaa5096c6f59b214dcecd",
|
||||
# evaludationClaim="0x00...00", evaludationPoint="0x00...00")
|
||||
genesis-shnarf-v5="0x47452a1b9ebadfe02bdd02f580fa1eba17680d57eec968a591644d05d78ee84f"
|
||||
genesis-shnarf-v6="0x47452a1b9ebadfe02bdd02f580fa1eba17680d57eec968a591644d05d78ee84f"
|
||||
|
||||
[l2]
|
||||
rpc-endpoint="http://sequencer:8545"
|
||||
|
||||
@@ -111,7 +111,7 @@ The L2MessageService deploy uses nonce 2 as the following are deployed beforehan
|
||||
|
||||
**Deploying the L1 contracts**
|
||||
```
|
||||
# This will deploy the Linea Rollup that is currently deployed on Mainnet - the current version is the LineaRollupV5.
|
||||
# This will deploy the Linea Rollup that is currently deployed on Mainnet - the current version is the LineaRollupV6.
|
||||
# Some end to end tests will test future upgrades to validate the stack remains functional.
|
||||
|
||||
# Note: By default a test/placeholder verifier contract is used `IntegrationTestTrueVerifier` if you wish to use a proper verifier, adjust the
|
||||
@@ -119,10 +119,7 @@ The L2MessageService deploy uses nonce 2 as the following are deployed beforehan
|
||||
|
||||
# Be sure to check the parameter values in the Makefile before executing the command.
|
||||
|
||||
# Deploy v5
|
||||
make deploy-linea-rollup-v5
|
||||
|
||||
# Or deploy v6
|
||||
# deploy v6
|
||||
make deploy-linea-rollup-v6
|
||||
|
||||
make deploy-token-bridge-l1
|
||||
@@ -145,7 +142,7 @@ make deploy-contracts
|
||||
|
||||
The above command will trigger the following commands to deploy:
|
||||
|
||||
- deploy-linea-rollup-v5
|
||||
- deploy-linea-rollup-v6
|
||||
- deploy-token-bridge-l1
|
||||
- deploy-l1-test-erc20
|
||||
- deploy-l2messageservice
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,73 +0,0 @@
|
||||
import { DeployFunction } from "hardhat-deploy/types";
|
||||
import { HardhatRuntimeEnvironment } from "hardhat/types";
|
||||
import { deployUpgradableFromFactory } from "../scripts/hardhat/utils";
|
||||
import {
|
||||
LogContractDeployment,
|
||||
getDeployedContractAddress,
|
||||
getRequiredEnvVar,
|
||||
tryStoreAddress,
|
||||
tryVerifyContract,
|
||||
} from "contracts/common/helpers";
|
||||
|
||||
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
||||
const { deployments } = hre;
|
||||
|
||||
const contractName = "LineaRollupV5";
|
||||
const verifierName = "PlonkVerifier";
|
||||
const existingContractAddress = await getDeployedContractAddress(contractName, deployments);
|
||||
let verifierAddress = await getDeployedContractAddress(verifierName, deployments);
|
||||
if (verifierAddress === undefined) {
|
||||
if (process.env["PLONKVERIFIER_ADDRESS"] !== undefined) {
|
||||
console.log(`Using environment variable for PlonkVerifier , ${process.env["PLONKVERIFIER_ADDRESS"]}`);
|
||||
verifierAddress = process.env["PLONKVERIFIER_ADDRESS"];
|
||||
} else {
|
||||
throw "Missing PLONKVERIFIER_ADDRESS environment variable";
|
||||
}
|
||||
} else {
|
||||
console.log(`Using deployed variable for PlonkVerifier , ${verifierAddress}`);
|
||||
}
|
||||
|
||||
// LineaRollup DEPLOYED AS UPGRADEABLE PROXY
|
||||
const LineaRollup_initialStateRootHash = getRequiredEnvVar("LINEA_ROLLUP_INITIAL_STATE_ROOT_HASH");
|
||||
const LineaRollup_initialL2BlockNumber = getRequiredEnvVar("LINEA_ROLLUP_INITIAL_L2_BLOCK_NUMBER");
|
||||
const LineaRollup_securityCouncil = getRequiredEnvVar("LINEA_ROLLUP_SECURITY_COUNCIL");
|
||||
const LineaRollup_operators = getRequiredEnvVar("LINEA_ROLLUP_OPERATORS");
|
||||
const LineaRollup_rateLimitPeriodInSeconds = getRequiredEnvVar("LINEA_ROLLUP_RATE_LIMIT_PERIOD");
|
||||
const LineaRollup_rateLimitAmountInWei = getRequiredEnvVar("LINEA_ROLLUP_RATE_LIMIT_AMOUNT");
|
||||
const LineaRollup_genesisTimestamp = getRequiredEnvVar("LINEA_ROLLUP_GENESIS_TIMESTAMP");
|
||||
|
||||
console.log(`Setting operators ${LineaRollup_operators}`);
|
||||
|
||||
if (existingContractAddress === undefined) {
|
||||
console.log(`Deploying initial version, NB: the address will be saved if env SAVE_ADDRESS=true.`);
|
||||
} else {
|
||||
console.log(`Deploying new version, NB: ${existingContractAddress} will be overwritten if env SAVE_ADDRESS=true.`);
|
||||
}
|
||||
const contract = await deployUpgradableFromFactory(
|
||||
"LineaRollupV5",
|
||||
[
|
||||
LineaRollup_initialStateRootHash,
|
||||
LineaRollup_initialL2BlockNumber,
|
||||
verifierAddress,
|
||||
LineaRollup_securityCouncil,
|
||||
LineaRollup_operators?.split(","),
|
||||
LineaRollup_rateLimitPeriodInSeconds,
|
||||
LineaRollup_rateLimitAmountInWei,
|
||||
LineaRollup_genesisTimestamp,
|
||||
],
|
||||
{
|
||||
initializer: "initialize(bytes32,uint256,address,address,address[],uint256,uint256,uint256)",
|
||||
unsafeAllow: ["constructor"],
|
||||
},
|
||||
);
|
||||
|
||||
await LogContractDeployment(contractName, contract);
|
||||
const contractAddress = await contract.getAddress();
|
||||
|
||||
await tryStoreAddress(hre.network.name, contractName, contractAddress, contract.deploymentTransaction()!.hash);
|
||||
|
||||
await tryVerifyContract(contractAddress);
|
||||
};
|
||||
|
||||
export default func;
|
||||
func.tags = ["LineaRollupV5"];
|
||||
@@ -1,114 +0,0 @@
|
||||
import { ethers } from "ethers";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import * as dotenv from "dotenv";
|
||||
import { abi as LineaRollupV5Abi, bytecode as LineaRollupV5Bytecode } from "./dynamic-artifacts/LineaRollupV5.json";
|
||||
import {
|
||||
contractName as ProxyAdminContractName,
|
||||
abi as ProxyAdminAbi,
|
||||
bytecode as ProxyAdminBytecode,
|
||||
} from "./static-artifacts/ProxyAdmin.json";
|
||||
import {
|
||||
abi as TransparentUpgradeableProxyAbi,
|
||||
bytecode as TransparentUpgradeableProxyBytecode,
|
||||
} from "./static-artifacts/TransparentUpgradeableProxy.json";
|
||||
import { getRequiredEnvVar } from "../common/helpers/environment";
|
||||
import { deployContractFromArtifacts, getInitializerData } from "../common/helpers/deployments";
|
||||
import { get1559Fees } from "../scripts/utils";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
function findContractArtifacts(
|
||||
folderPath: string,
|
||||
contractName: string,
|
||||
): { abi: ethers.InterfaceAbi; bytecode: ethers.BytesLike } {
|
||||
const files = fs.readdirSync(folderPath);
|
||||
|
||||
const foundFile = files.find((file) => file === `${contractName}.json`);
|
||||
|
||||
if (!foundFile) {
|
||||
// Throw an error if the file is not found
|
||||
throw new Error(`Contract "${contractName}" not found in folder "${folderPath}"`);
|
||||
}
|
||||
|
||||
// Construct the full file path
|
||||
const filePath = path.join(folderPath, foundFile);
|
||||
|
||||
// Read the file content
|
||||
const fileContent = fs.readFileSync(filePath, "utf-8").trim();
|
||||
const parsedContent = JSON.parse(fileContent);
|
||||
return parsedContent;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const verifierName = getRequiredEnvVar("VERIFIER_CONTRACT_NAME");
|
||||
const lineaRollupInitialStateRootHash = getRequiredEnvVar("LINEA_ROLLUP_INITIAL_STATE_ROOT_HASH");
|
||||
const lineaRollupInitialL2BlockNumber = getRequiredEnvVar("LINEA_ROLLUP_INITIAL_L2_BLOCK_NUMBER");
|
||||
const lineaRollupSecurityCouncil = getRequiredEnvVar("LINEA_ROLLUP_SECURITY_COUNCIL");
|
||||
const lineaRollupOperators = getRequiredEnvVar("LINEA_ROLLUP_OPERATORS").split(",");
|
||||
const lineaRollupRateLimitPeriodInSeconds = getRequiredEnvVar("LINEA_ROLLUP_RATE_LIMIT_PERIOD");
|
||||
const lineaRollupTateLimitAmountInWei = getRequiredEnvVar("LINEA_ROLLUP_RATE_LIMIT_AMOUNT");
|
||||
const lineaRollupGenesisTimestamp = getRequiredEnvVar("LINEA_ROLLUP_GENESIS_TIMESTAMP");
|
||||
const lineaRollupName = "LineaRollupV5";
|
||||
const lineaRollupImplementationName = "LineaRollupV5Implementation";
|
||||
const verifierArtifacts = findContractArtifacts(path.join(__dirname, "./dynamic-artifacts"), verifierName);
|
||||
|
||||
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
|
||||
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
|
||||
|
||||
const { gasPrice } = await get1559Fees(provider);
|
||||
|
||||
let walletNonce;
|
||||
|
||||
if (!process.env.L1_NONCE) {
|
||||
walletNonce = await wallet.getNonce();
|
||||
} else {
|
||||
walletNonce = parseInt(process.env.L1_NONCE);
|
||||
}
|
||||
|
||||
const [verifier, lineaRollupImplementation, proxyAdmin] = await Promise.all([
|
||||
deployContractFromArtifacts(verifierName, verifierArtifacts.abi, verifierArtifacts.bytecode, wallet, {
|
||||
nonce: walletNonce,
|
||||
gasPrice,
|
||||
}),
|
||||
deployContractFromArtifacts(lineaRollupImplementationName, LineaRollupV5Abi, LineaRollupV5Bytecode, wallet, {
|
||||
nonce: walletNonce + 1,
|
||||
gasPrice,
|
||||
}),
|
||||
deployContractFromArtifacts(ProxyAdminContractName, ProxyAdminAbi, ProxyAdminBytecode, wallet, {
|
||||
nonce: walletNonce + 2,
|
||||
gasPrice,
|
||||
}),
|
||||
]);
|
||||
|
||||
const proxyAdminAddress = await proxyAdmin.getAddress();
|
||||
const verifierAddress = await verifier.getAddress();
|
||||
const lineaRollupImplementationAddress = await lineaRollupImplementation.getAddress();
|
||||
|
||||
const initializer = getInitializerData(LineaRollupV5Abi, "initialize", [
|
||||
lineaRollupInitialStateRootHash,
|
||||
lineaRollupInitialL2BlockNumber,
|
||||
verifierAddress,
|
||||
lineaRollupSecurityCouncil,
|
||||
lineaRollupOperators,
|
||||
lineaRollupRateLimitPeriodInSeconds,
|
||||
lineaRollupTateLimitAmountInWei,
|
||||
lineaRollupGenesisTimestamp,
|
||||
]);
|
||||
|
||||
await deployContractFromArtifacts(
|
||||
lineaRollupName,
|
||||
TransparentUpgradeableProxyAbi,
|
||||
TransparentUpgradeableProxyBytecode,
|
||||
wallet,
|
||||
lineaRollupImplementationAddress,
|
||||
proxyAdminAddress,
|
||||
initializer,
|
||||
{ gasPrice },
|
||||
);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -1,14 +0,0 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0
|
||||
pragma solidity 0.8.24;
|
||||
|
||||
import { LineaRollupV5 } from "../../integration/LineaRollupV5.sol";
|
||||
|
||||
contract TestLineaRollupV5 is LineaRollupV5 {
|
||||
function setDefaultShnarfExistValue(bytes32 _shnarf) external {
|
||||
shnarfFinalBlockNumbers[_shnarf] = 1;
|
||||
}
|
||||
|
||||
function setRollingHash(uint256 _messageNumber, bytes32 _rollingHash) external {
|
||||
rollingHashes[_messageNumber] = _rollingHash;
|
||||
}
|
||||
}
|
||||
@@ -19,28 +19,29 @@
|
||||
pragma solidity 0.8.26;
|
||||
|
||||
contract TestPlonkVerifierForDataAggregation {
|
||||
|
||||
uint256 private constant R_MOD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||
uint256 private constant R_MOD_MINUS_ONE = 21888242871839275222246405745257275088548364400416034343698204186575808495616;
|
||||
uint256 private constant R_MOD_MINUS_ONE =
|
||||
21888242871839275222246405745257275088548364400416034343698204186575808495616;
|
||||
uint256 private constant P_MOD = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||
|
||||
|
||||
uint256 private constant G2_SRS_0_X_0 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
|
||||
uint256 private constant G2_SRS_0_X_1 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
|
||||
uint256 private constant G2_SRS_0_Y_0 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
|
||||
uint256 private constant G2_SRS_0_Y_1 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
|
||||
|
||||
|
||||
uint256 private constant G2_SRS_1_X_0 = 15805639136721018565402881920352193254830339253282065586954346329754995870280;
|
||||
uint256 private constant G2_SRS_1_X_1 = 19089565590083334368588890253123139704298730990782503769911324779715431555531;
|
||||
uint256 private constant G2_SRS_1_Y_0 = 9779648407879205346559610309258181044130619080926897934572699915909528404984;
|
||||
uint256 private constant G2_SRS_1_Y_1 = 6779728121489434657638426458390319301070371227460768374343986326751507916979;
|
||||
|
||||
|
||||
uint256 private constant G1_SRS_X = 14312776538779914388377568895031746459131577658076416373430523308756343304251;
|
||||
uint256 private constant G1_SRS_Y = 11763105256161367503191792604679297387056316997144156930871823008787082098465;
|
||||
|
||||
// ----------------------- vk ---------------------
|
||||
uint256 private constant VK_NB_PUBLIC_INPUTS = 1;
|
||||
uint256 private constant VK_DOMAIN_SIZE = 16;
|
||||
uint256 private constant VK_INV_DOMAIN_SIZE = 20520227692349320520856005386178695395514091625390032197217066424914820464641;
|
||||
uint256 private constant VK_INV_DOMAIN_SIZE =
|
||||
20520227692349320520856005386178695395514091625390032197217066424914820464641;
|
||||
uint256 private constant VK_OMEGA = 14940766826517323942636479241147756311199852622225275649687664389641784935947;
|
||||
uint256 private constant VK_QL_COM_X = 3767637989833674092151354229632559107224950590673664856842061399469467338879;
|
||||
uint256 private constant VK_QL_COM_Y = 18545409996679466114224178746162553880737296402729089689774308937082946761979;
|
||||
@@ -52,23 +53,21 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
uint256 private constant VK_QO_COM_Y = 10782414695040549646706468913781794882209258381887890407509684555513355143197;
|
||||
uint256 private constant VK_QK_COM_X = 309591480144351325314158474719361148480191595146291661238142838254651436989;
|
||||
uint256 private constant VK_QK_COM_Y = 12063173869829536468830946547606069911666129778788708678515573607390482939756;
|
||||
|
||||
|
||||
uint256 private constant VK_S1_COM_X = 12287072751694848944507699577006619791724925439540371477056092891137357229312;
|
||||
uint256 private constant VK_S1_COM_Y = 2469356406782415219782253630635766217009619642857495098799013714324696399305;
|
||||
|
||||
|
||||
uint256 private constant VK_S2_COM_X = 17261757720471042341269061128759148572672168808566386603388432325173708264418;
|
||||
uint256 private constant VK_S2_COM_Y = 20976565876611279190744172824963243461988367679364518747954008723085439460611;
|
||||
|
||||
|
||||
uint256 private constant VK_S3_COM_X = 18758025488249277181117376239193628449359868741625564388668468130204669284937;
|
||||
uint256 private constant VK_S3_COM_Y = 15566903578741238761792344329051427316196307361197991677131114502821508927172;
|
||||
|
||||
|
||||
uint256 private constant VK_COSET_SHIFT = 5;
|
||||
|
||||
|
||||
|
||||
uint256 private constant VK_QCP_0_X = 4559262075452024065272338216146989708834054079507534161096300708463935456394;
|
||||
uint256 private constant VK_QCP_0_Y = 1898950104727986554890445533779776634695458253078091580309593009754027486622;
|
||||
|
||||
|
||||
|
||||
uint256 private constant VK_INDEX_COMMIT_API_0 = 5;
|
||||
uint256 private constant VK_NB_CUSTOM_GATES = 1;
|
||||
|
||||
@@ -78,7 +77,7 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
uint256 private constant FIXED_PROOF_SIZE = 0x300;
|
||||
|
||||
// offset proof
|
||||
|
||||
|
||||
uint256 private constant PROOF_L_COM_X = 0x0;
|
||||
uint256 private constant PROOF_L_COM_Y = 0x20;
|
||||
uint256 private constant PROOF_R_COM_X = 0x40;
|
||||
@@ -122,7 +121,7 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
// -------- offset state
|
||||
|
||||
// challenges to check the claimed quotient
|
||||
|
||||
|
||||
uint256 private constant STATE_ALPHA = 0x0;
|
||||
uint256 private constant STATE_BETA = 0x20;
|
||||
uint256 private constant STATE_GAMMA = 0x40;
|
||||
@@ -153,15 +152,13 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
// -------- errors
|
||||
uint256 private constant ERROR_STRING_ID = 0x08c379a000000000000000000000000000000000000000000000000000000000; // selector for function Error(string)
|
||||
|
||||
|
||||
// -------- utils (for hash_fr)
|
||||
uint256 private constant HASH_FR_BB = 340282366920938463463374607431768211456; // 2**128
|
||||
uint256 private constant HASH_FR_ZERO_UINT256 = 0;
|
||||
uint8 private constant HASH_FR_LEN_IN_BYTES = 48;
|
||||
uint8 private constant HASH_FR_SIZE_DOMAIN = 11;
|
||||
uint8 private constant HASH_FR_ONE = 1;
|
||||
uint8 private constant HASH_FR_TWO = 2;
|
||||
|
||||
uint256 private constant HASH_FR_BB = 340282366920938463463374607431768211456; // 2**128
|
||||
uint256 private constant HASH_FR_ZERO_UINT256 = 0;
|
||||
uint8 private constant HASH_FR_LEN_IN_BYTES = 48;
|
||||
uint8 private constant HASH_FR_SIZE_DOMAIN = 11;
|
||||
uint8 private constant HASH_FR_ONE = 1;
|
||||
uint8 private constant HASH_FR_TWO = 2;
|
||||
|
||||
// -------- precompiles
|
||||
uint8 private constant SHA2 = 0x2;
|
||||
@@ -169,17 +166,14 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
uint8 private constant EC_ADD = 0x6;
|
||||
uint8 private constant EC_MUL = 0x7;
|
||||
uint8 private constant EC_PAIR = 0x8;
|
||||
|
||||
|
||||
/// Verify a Plonk proof.
|
||||
/// Reverts if the proof or the public inputs are malformed.
|
||||
/// @param proof serialised plonk proof (using gnark's MarshalSolidity)
|
||||
/// @param public_inputs (must be reduced)
|
||||
/// @return success true if the proof passes false otherwise
|
||||
function Verify(bytes calldata proof, uint256[] calldata public_inputs)
|
||||
public view returns(bool success) {
|
||||
|
||||
function Verify(bytes calldata proof, uint256[] calldata public_inputs) public view returns (bool success) {
|
||||
assembly {
|
||||
|
||||
let mem := mload(0x40)
|
||||
let freeMem := add(mem, STATE_LAST_MEM)
|
||||
|
||||
@@ -311,20 +305,23 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
// end errors -------------------------------------------------
|
||||
|
||||
// Beginning checks -------------------------------------------------
|
||||
|
||||
|
||||
/// @param s actual number of public inputs
|
||||
function check_number_of_public_inputs(s) {
|
||||
if iszero(eq(s, VK_NB_PUBLIC_INPUTS)) {
|
||||
error_nb_public_inputs()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Checks that the public inputs are < R_MOD.
|
||||
/// @param s number of public inputs
|
||||
/// @param p pointer to the public inputs array
|
||||
function check_inputs_size(s, p) {
|
||||
for {let i} lt(i, s) {i:=add(i,1)}
|
||||
{
|
||||
for {
|
||||
let i
|
||||
} lt(i, s) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
if gt(calldataload(p), R_MOD_MINUS_ONE) {
|
||||
error_inputs_size()
|
||||
}
|
||||
@@ -335,17 +332,16 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// Checks if the proof is of the correct size
|
||||
/// @param actual_proof_size size of the proof (not the expected size)
|
||||
function check_proof_size(actual_proof_size) {
|
||||
let expected_proof_size := add(FIXED_PROOF_SIZE, mul(VK_NB_CUSTOM_GATES,0x60))
|
||||
let expected_proof_size := add(FIXED_PROOF_SIZE, mul(VK_NB_CUSTOM_GATES, 0x60))
|
||||
if iszero(eq(actual_proof_size, expected_proof_size)) {
|
||||
error_proof_size()
|
||||
error_proof_size()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Checks if the multiple openings of the polynomials are < R_MOD.
|
||||
/// @param aproof pointer to the beginning of the proof
|
||||
/// @dev the 'a' prepending proof is to have a local name
|
||||
function check_proof_openings_size(aproof) {
|
||||
|
||||
// PROOF_L_AT_ZETA
|
||||
let p := add(aproof, PROOF_L_AT_ZETA)
|
||||
if gt(calldataload(p), R_MOD_MINUS_ONE) {
|
||||
@@ -369,7 +365,7 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
if gt(calldataload(p), R_MOD_MINUS_ONE) {
|
||||
error_proof_openings_size()
|
||||
}
|
||||
|
||||
|
||||
// PROOF_S2_AT_ZETA
|
||||
p := add(aproof, PROOF_S2_AT_ZETA)
|
||||
if gt(calldataload(p), R_MOD_MINUS_ONE) {
|
||||
@@ -383,16 +379,18 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
}
|
||||
|
||||
// PROOF_OPENING_QCP_AT_ZETA
|
||||
|
||||
|
||||
p := add(aproof, PROOF_OPENING_QCP_AT_ZETA)
|
||||
for {let i:=0} lt(i, VK_NB_CUSTOM_GATES) {i:=add(i,1)}
|
||||
{
|
||||
for {
|
||||
let i := 0
|
||||
} lt(i, VK_NB_CUSTOM_GATES) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
if gt(calldataload(p), R_MOD_MINUS_ONE) {
|
||||
error_proof_openings_size()
|
||||
}
|
||||
p := add(p, 0x20)
|
||||
}
|
||||
|
||||
}
|
||||
// end checks -------------------------------------------------
|
||||
|
||||
@@ -414,34 +412,32 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// and is encoded as a uint256 number n. In basis b = 256, the number looks like this
|
||||
/// [0 0 0 .. 0x67 0x61 0x6d, 0x6d, 0x61]. The first non zero entry is at position 27=0x1b
|
||||
/// Gamma reduced (the actual challenge) is stored at add(state, state_gamma)
|
||||
function derive_gamma(aproof, nb_pi, pi)->gamma_not_reduced {
|
||||
|
||||
function derive_gamma(aproof, nb_pi, pi) -> gamma_not_reduced {
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(state, STATE_LAST_MEM)
|
||||
|
||||
mstore(mPtr, FS_GAMMA) // "gamma"
|
||||
|
||||
|
||||
mstore(add(mPtr, 0x20), VK_S1_COM_X)
|
||||
mstore(add(mPtr, 0x40), VK_S1_COM_Y)
|
||||
mstore(add(mPtr, 0x60), VK_S2_COM_X)
|
||||
mstore(add(mPtr, 0x80), VK_S2_COM_Y)
|
||||
mstore(add(mPtr, 0xa0), VK_S3_COM_X)
|
||||
mstore(add(mPtr, 0xc0), VK_S3_COM_Y)
|
||||
mstore(add(mPtr, 0xe0), VK_QL_COM_X)
|
||||
mstore(add(mPtr, 0x100), VK_QL_COM_Y)
|
||||
mstore(add(mPtr, 0x120), VK_QR_COM_X)
|
||||
mstore(add(mPtr, 0x140), VK_QR_COM_Y)
|
||||
mstore(add(mPtr, 0x160), VK_QM_COM_X)
|
||||
mstore(add(mPtr, 0x180), VK_QM_COM_Y)
|
||||
mstore(add(mPtr, 0x1a0), VK_QO_COM_X)
|
||||
mstore(add(mPtr, 0x1c0), VK_QO_COM_Y)
|
||||
mstore(add(mPtr, 0x1e0), VK_QK_COM_X)
|
||||
mstore(add(mPtr, 0x200), VK_QK_COM_Y)
|
||||
|
||||
mstore(add(mPtr, 0x220), VK_QCP_0_X)
|
||||
mstore(add(mPtr, 0x240), VK_QCP_0_Y)
|
||||
|
||||
mstore(add(mPtr, 0x20), VK_S1_COM_X)
|
||||
mstore(add(mPtr, 0x40), VK_S1_COM_Y)
|
||||
mstore(add(mPtr, 0x60), VK_S2_COM_X)
|
||||
mstore(add(mPtr, 0x80), VK_S2_COM_Y)
|
||||
mstore(add(mPtr, 0xa0), VK_S3_COM_X)
|
||||
mstore(add(mPtr, 0xc0), VK_S3_COM_Y)
|
||||
mstore(add(mPtr, 0xe0), VK_QL_COM_X)
|
||||
mstore(add(mPtr, 0x100), VK_QL_COM_Y)
|
||||
mstore(add(mPtr, 0x120), VK_QR_COM_X)
|
||||
mstore(add(mPtr, 0x140), VK_QR_COM_Y)
|
||||
mstore(add(mPtr, 0x160), VK_QM_COM_X)
|
||||
mstore(add(mPtr, 0x180), VK_QM_COM_Y)
|
||||
mstore(add(mPtr, 0x1a0), VK_QO_COM_X)
|
||||
mstore(add(mPtr, 0x1c0), VK_QO_COM_Y)
|
||||
mstore(add(mPtr, 0x1e0), VK_QK_COM_X)
|
||||
mstore(add(mPtr, 0x200), VK_QK_COM_Y)
|
||||
|
||||
mstore(add(mPtr, 0x220), VK_QCP_0_X)
|
||||
mstore(add(mPtr, 0x240), VK_QCP_0_Y)
|
||||
|
||||
// public inputs
|
||||
let _mPtr := add(mPtr, 0x260)
|
||||
let size_pi_in_bytes := mul(nb_pi, 0x20)
|
||||
@@ -458,7 +454,7 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
// + nb_public_inputs*0x20
|
||||
// + nb_custom gates*0x40
|
||||
let size := add(0x2c5, size_pi_in_bytes)
|
||||
|
||||
|
||||
size := add(size, mul(VK_NB_CUSTOM_GATES, 0x40))
|
||||
let l_success := staticcall(gas(), SHA2, add(mPtr, 0x1b), size, mPtr, 0x20) //0x1b -> 000.."gamma"
|
||||
if iszero(l_success) {
|
||||
@@ -473,8 +469,7 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// @return beta_not_reduced the next challenge, beta, not reduced
|
||||
/// @notice the transcript consists of the previous challenge only.
|
||||
/// The reduced version of beta is stored at add(state, state_beta)
|
||||
function derive_beta(gamma_not_reduced)->beta_not_reduced{
|
||||
|
||||
function derive_beta(gamma_not_reduced) -> beta_not_reduced {
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
|
||||
@@ -495,9 +490,8 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// @return alpha_not_reduced the next challenge, alpha, not reduced
|
||||
/// @notice the transcript consists of the previous challenge (beta)
|
||||
/// not reduced, the commitments to the wires associated to the QCP_i,
|
||||
/// and the commitment to the grand product polynomial
|
||||
function derive_alpha(aproof, beta_not_reduced)->alpha_not_reduced {
|
||||
|
||||
/// and the commitment to the grand product polynomial
|
||||
function derive_alpha(aproof, beta_not_reduced) -> alpha_not_reduced {
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
let full_size := 0x65 // size("alpha") + 0x20 (previous challenge)
|
||||
@@ -507,14 +501,14 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
let _mPtr := add(mPtr, 0x20)
|
||||
mstore(_mPtr, beta_not_reduced)
|
||||
_mPtr := add(_mPtr, 0x20)
|
||||
|
||||
|
||||
// Bsb22Commitments
|
||||
let proof_bsb_commitments := add(aproof, PROOF_BSB_COMMITMENTS)
|
||||
let size_bsb_commitments := mul(0x40, VK_NB_CUSTOM_GATES)
|
||||
calldatacopy(_mPtr, proof_bsb_commitments, size_bsb_commitments)
|
||||
_mPtr := add(_mPtr, size_bsb_commitments)
|
||||
full_size := add(full_size, size_bsb_commitments)
|
||||
|
||||
|
||||
// [Z], the commitment to the grand product polynomial
|
||||
calldatacopy(_mPtr, add(aproof, PROOF_GRAND_PRODUCT_COMMITMENT_X), 0x40)
|
||||
let l_success := staticcall(gas(), SHA2, add(mPtr, 0x1b), full_size, mPtr, 0x20)
|
||||
@@ -532,7 +526,6 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// The transcript consists of the previous challenge and the commitment to
|
||||
/// the quotient polynomial h.
|
||||
function derive_zeta(aproof, alpha_not_reduced) {
|
||||
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
|
||||
@@ -557,8 +550,7 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// @param n number of public inputs
|
||||
/// @param mPtr free memory
|
||||
/// @return pi_wo_commit public inputs contribution (except the public inputs coming from the custom gate)
|
||||
function sum_pi_wo_api_commit(ins, n, mPtr)->pi_wo_commit {
|
||||
|
||||
function sum_pi_wo_api_commit(ins, n, mPtr) -> pi_wo_commit {
|
||||
let state := mload(0x40)
|
||||
let z := mload(add(state, STATE_ZETA))
|
||||
let zpnmo := mload(add(state, STATE_ZETA_POWER_N_MINUS_ONE))
|
||||
@@ -567,14 +559,16 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
batch_compute_lagranges_at_z(z, zpnmo, n, li)
|
||||
|
||||
let tmp := 0
|
||||
for {let i:=0} lt(i,n) {i:=add(i,1)}
|
||||
{
|
||||
for {
|
||||
let i := 0
|
||||
} lt(i, n) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
tmp := mulmod(mload(li), calldataload(ins), R_MOD)
|
||||
pi_wo_commit := addmod(pi_wo_commit, tmp, R_MOD)
|
||||
li := add(li, 0x20)
|
||||
ins := add(ins, 0x20)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// batch_compute_lagranges_at_z computes [L_0(z), .., L_{n-1}(z)]
|
||||
@@ -583,27 +577,32 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// @param n_pub number of public inputs (number of Lagranges to compute)
|
||||
/// @param mPtr pointer to which the results are stored
|
||||
function batch_compute_lagranges_at_z(z, zpnmo, n_pub, mPtr) {
|
||||
|
||||
let zn := mulmod(zpnmo, VK_INV_DOMAIN_SIZE, R_MOD) // 1/n * (ζⁿ - 1)
|
||||
|
||||
|
||||
let _w := 1
|
||||
let _mPtr := mPtr
|
||||
for {let i:=0} lt(i,n_pub) {i:=add(i,1)}
|
||||
{
|
||||
mstore(_mPtr, addmod(z,sub(R_MOD, _w), R_MOD))
|
||||
for {
|
||||
let i := 0
|
||||
} lt(i, n_pub) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
mstore(_mPtr, addmod(z, sub(R_MOD, _w), R_MOD))
|
||||
_w := mulmod(_w, VK_OMEGA, R_MOD)
|
||||
_mPtr := add(_mPtr, 0x20)
|
||||
}
|
||||
batch_invert(mPtr, n_pub, _mPtr)
|
||||
_mPtr := mPtr
|
||||
_w := 1
|
||||
for {let i:=0} lt(i,n_pub) {i:=add(i,1)}
|
||||
{
|
||||
mstore(_mPtr, mulmod(mulmod(mload(_mPtr), zn , R_MOD), _w, R_MOD))
|
||||
for {
|
||||
let i := 0
|
||||
} lt(i, n_pub) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
mstore(_mPtr, mulmod(mulmod(mload(_mPtr), zn, R_MOD), _w, R_MOD))
|
||||
_mPtr := add(_mPtr, 0x20)
|
||||
_w := mulmod(_w, VK_OMEGA, R_MOD)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @notice Montgomery trick for batch inversion mod R_MOD
|
||||
/// @param ins pointer to the data to batch invert
|
||||
@@ -612,8 +611,11 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
function batch_invert(ins, nb_ins, mPtr) {
|
||||
mstore(mPtr, 1)
|
||||
let offset := 0
|
||||
for {let i:=0} lt(i, nb_ins) {i:=add(i,1)}
|
||||
{
|
||||
for {
|
||||
let i := 0
|
||||
} lt(i, nb_ins) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
let prev := mload(add(mPtr, offset))
|
||||
let cur := mload(add(ins, offset))
|
||||
cur := mulmod(prev, cur, R_MOD)
|
||||
@@ -622,9 +624,12 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
}
|
||||
ins := add(ins, sub(offset, 0x20))
|
||||
mPtr := add(mPtr, offset)
|
||||
let inv := pow(mload(mPtr), sub(R_MOD,2), add(mPtr, 0x20))
|
||||
for {let i:=0} lt(i, nb_ins) {i:=add(i,1)}
|
||||
{
|
||||
let inv := pow(mload(mPtr), sub(R_MOD, 2), add(mPtr, 0x20))
|
||||
for {
|
||||
let i := 0
|
||||
} lt(i, nb_ins) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
mPtr := sub(mPtr, 0x20)
|
||||
let tmp := mload(ins)
|
||||
let cur := mulmod(inv, mload(mPtr), R_MOD)
|
||||
@@ -634,14 +639,12 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Public inputs (the ones coming from the custom gate) contribution
|
||||
/// @param aproof pointer to the proof
|
||||
/// @param nb_public_inputs number of public inputs
|
||||
/// @param mPtr pointer to free memory
|
||||
/// @return pi_commit custom gate public inputs contribution
|
||||
function sum_pi_commit(aproof, nb_public_inputs, mPtr)->pi_commit {
|
||||
|
||||
function sum_pi_commit(aproof, nb_public_inputs, mPtr) -> pi_commit {
|
||||
let state := mload(0x40)
|
||||
let z := mload(add(state, STATE_ZETA))
|
||||
let zpnmo := mload(add(state, STATE_ZETA_POWER_N_MINUS_ONE))
|
||||
@@ -649,14 +652,10 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
let p := add(aproof, PROOF_BSB_COMMITMENTS)
|
||||
|
||||
let h_fr, ith_lagrange
|
||||
|
||||
|
||||
|
||||
h_fr := hash_fr(calldataload(p), calldataload(add(p, 0x20)), mPtr)
|
||||
ith_lagrange := compute_ith_lagrange_at_z(z, zpnmo, add(nb_public_inputs, VK_INDEX_COMMIT_API_0), mPtr)
|
||||
pi_commit := addmod(pi_commit, mulmod(h_fr, ith_lagrange, R_MOD), R_MOD)
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// Computes L_i(zeta) = ωⁱ/n * (ζⁿ-1)/(ζ-ωⁱ) where:
|
||||
@@ -664,16 +663,14 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// @param zpmno ζⁿ-1
|
||||
/// @param i i-th lagrange
|
||||
/// @param mPtr free memory
|
||||
/// @return res = ωⁱ/n * (ζⁿ-1)/(ζ-ωⁱ)
|
||||
function compute_ith_lagrange_at_z(z, zpnmo, i, mPtr)->res {
|
||||
|
||||
/// @return res = ωⁱ/n * (ζⁿ-1)/(ζ-ωⁱ)
|
||||
function compute_ith_lagrange_at_z(z, zpnmo, i, mPtr) -> res {
|
||||
let w := pow(VK_OMEGA, i, mPtr) // w**i
|
||||
i := addmod(z, sub(R_MOD, w), R_MOD) // z-w**i
|
||||
w := mulmod(w, VK_INV_DOMAIN_SIZE, R_MOD) // w**i/n
|
||||
i := pow(i, sub(R_MOD,2), mPtr) // (z-w**i)**-1
|
||||
i := pow(i, sub(R_MOD, 2), mPtr) // (z-w**i)**-1
|
||||
w := mulmod(w, i, R_MOD) // w**i/n*(z-w)**-1
|
||||
res := mulmod(w, zpnmo, R_MOD)
|
||||
|
||||
}
|
||||
|
||||
/// @dev https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-5.2
|
||||
@@ -681,15 +678,14 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// @param y y coordinate of a point on Bn254(𝔽_p)
|
||||
/// @param mPtr free memory
|
||||
/// @return res an element mod R_MOD
|
||||
function hash_fr(x, y, mPtr)->res {
|
||||
|
||||
function hash_fr(x, y, mPtr) -> res {
|
||||
// [0x00, .. , 0x00 || x, y, || 0, 48, 0, dst, HASH_FR_SIZE_DOMAIN]
|
||||
// <- 64 bytes -> <-64b -> <- 1 bytes each ->
|
||||
|
||||
// [0x00, .., 0x00] 64 bytes of zero
|
||||
mstore(mPtr, HASH_FR_ZERO_UINT256)
|
||||
mstore(add(mPtr, 0x20), HASH_FR_ZERO_UINT256)
|
||||
|
||||
|
||||
// msg = x || y , both on 32 bytes
|
||||
mstore(add(mPtr, 0x40), x)
|
||||
mstore(add(mPtr, 0x60), y)
|
||||
@@ -725,7 +721,7 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
// [b0 || one || dst || HASH_FR_SIZE_DOMAIN]
|
||||
// <-64bytes -> <- 1 byte each ->
|
||||
mstore8(add(mPtr, 0x20), HASH_FR_ONE) // 1
|
||||
|
||||
|
||||
mstore8(add(mPtr, 0x21), 0x42) // dst
|
||||
mstore8(add(mPtr, 0x22), 0x53)
|
||||
mstore8(add(mPtr, 0x23), 0x42)
|
||||
@@ -777,9 +773,8 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
res := mulmod(mload(mPtr), HASH_FR_BB, R_MOD) // <- res = 2**128 * mPtr[:32]
|
||||
let b1 := shr(128, mload(add(mPtr, 0x20))) // b1 <- [0, 0, .., 0 || b2[:16] ]
|
||||
res := addmod(res, b1, R_MOD)
|
||||
|
||||
}
|
||||
|
||||
|
||||
// END compute_pi -------------------------------------------------
|
||||
|
||||
/// @notice compute α² * 1/n * (ζ{n}-1)/(ζ - 1) where
|
||||
@@ -787,7 +782,7 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// * n = vk_domain_size
|
||||
/// * ω = vk_omega (generator of the multiplicative cyclic group of order n in (ℤ/rℤ)*)
|
||||
/// * ζ = zeta (challenge derived with Fiat Shamir)
|
||||
function compute_alpha_square_lagrange_0() {
|
||||
function compute_alpha_square_lagrange_0() {
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
|
||||
@@ -827,7 +822,7 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
mstore(add(mPtr, 0x100), mload(add(state, STATE_ZETA)))
|
||||
mstore(add(mPtr, 0x120), mload(add(state, STATE_GAMMA_KZG)))
|
||||
let random := staticcall(gas(), SHA2, mPtr, 0x140, mPtr, 0x20)
|
||||
if iszero(random){
|
||||
if iszero(random) {
|
||||
error_random_generation()
|
||||
}
|
||||
random := mod(mload(mPtr), R_MOD) // use the same variable as we are one variable away from getting stack-too-deep error...
|
||||
@@ -876,18 +871,18 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
mstore(folded_quotients_y, sub(P_MOD, mload(folded_quotients_y)))
|
||||
|
||||
mstore(mPtr, mload(folded_digests))
|
||||
|
||||
mstore(add(mPtr, 0x20), mload(add(folded_digests, 0x20)))
|
||||
mstore(add(mPtr, 0x40), G2_SRS_0_X_0) // the 4 lines are the canonical G2 point on BN254
|
||||
mstore(add(mPtr, 0x60), G2_SRS_0_X_1)
|
||||
mstore(add(mPtr, 0x80), G2_SRS_0_Y_0)
|
||||
mstore(add(mPtr, 0xa0), G2_SRS_0_Y_1)
|
||||
mstore(add(mPtr, 0xc0), mload(folded_quotients))
|
||||
mstore(add(mPtr, 0xe0), mload(add(folded_quotients, 0x20)))
|
||||
mstore(add(mPtr, 0x100), G2_SRS_1_X_0)
|
||||
mstore(add(mPtr, 0x120), G2_SRS_1_X_1)
|
||||
mstore(add(mPtr, 0x140), G2_SRS_1_Y_0)
|
||||
mstore(add(mPtr, 0x160), G2_SRS_1_Y_1)
|
||||
|
||||
mstore(add(mPtr, 0x20), mload(add(folded_digests, 0x20)))
|
||||
mstore(add(mPtr, 0x40), G2_SRS_0_X_0) // the 4 lines are the canonical G2 point on BN254
|
||||
mstore(add(mPtr, 0x60), G2_SRS_0_X_1)
|
||||
mstore(add(mPtr, 0x80), G2_SRS_0_Y_0)
|
||||
mstore(add(mPtr, 0xa0), G2_SRS_0_Y_1)
|
||||
mstore(add(mPtr, 0xc0), mload(folded_quotients))
|
||||
mstore(add(mPtr, 0xe0), mload(add(folded_quotients, 0x20)))
|
||||
mstore(add(mPtr, 0x100), G2_SRS_1_X_0)
|
||||
mstore(add(mPtr, 0x120), G2_SRS_1_X_1)
|
||||
mstore(add(mPtr, 0x140), G2_SRS_1_Y_0)
|
||||
mstore(add(mPtr, 0x160), G2_SRS_1_Y_1)
|
||||
check_pairing_kzg(mPtr)
|
||||
}
|
||||
|
||||
@@ -912,7 +907,6 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// @param aproof pointer to the proof
|
||||
/// acc_gamma stores the γⁱ
|
||||
function fold_state(aproof) {
|
||||
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
let mPtr20 := add(mPtr, 0x20)
|
||||
@@ -949,15 +943,14 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
point_acc_mul(state_folded_digests, mPtr, acc_gamma, mPtr40)
|
||||
fr_acc_mul_calldata(add(state, STATE_FOLDED_CLAIMED_VALUES), add(aproof, PROOF_S2_AT_ZETA), acc_gamma)
|
||||
let poqaz := add(aproof, PROOF_OPENING_QCP_AT_ZETA)
|
||||
|
||||
|
||||
acc_gamma := mulmod(acc_gamma, l_gamma_kzg, R_MOD)
|
||||
mstore(mPtr, VK_QCP_0_X)
|
||||
mstore(mPtr20, VK_QCP_0_Y)
|
||||
point_acc_mul(state_folded_digests, mPtr, acc_gamma, mPtr40)
|
||||
fr_acc_mul_calldata(add(state, STATE_FOLDED_CLAIMED_VALUES), poqaz, acc_gamma)
|
||||
poqaz := add(poqaz, 0x20)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// @notice generate the challenge (using Fiat Shamir) to fold the opening proofs
|
||||
/// at ζ.
|
||||
@@ -975,23 +968,22 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// * Z(ζω)
|
||||
/// @param aproof pointer to the proof
|
||||
function compute_gamma_kzg(aproof) {
|
||||
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
mstore(mPtr, FS_GAMMA_KZG) // "gamma"
|
||||
mstore(add(mPtr, 0x20), mload(add(state, STATE_ZETA)))
|
||||
mstore(add(mPtr,0x40), mload(add(state, STATE_LINEARISED_POLYNOMIAL_X)))
|
||||
mstore(add(mPtr,0x60), mload(add(state, STATE_LINEARISED_POLYNOMIAL_Y)))
|
||||
mstore(add(mPtr, 0x40), mload(add(state, STATE_LINEARISED_POLYNOMIAL_X)))
|
||||
mstore(add(mPtr, 0x60), mload(add(state, STATE_LINEARISED_POLYNOMIAL_Y)))
|
||||
calldatacopy(add(mPtr, 0x80), add(aproof, PROOF_L_COM_X), 0xc0)
|
||||
mstore(add(mPtr,0x140), VK_S1_COM_X)
|
||||
mstore(add(mPtr,0x160), VK_S1_COM_Y)
|
||||
mstore(add(mPtr,0x180), VK_S2_COM_X)
|
||||
mstore(add(mPtr,0x1a0), VK_S2_COM_Y)
|
||||
|
||||
mstore(add(mPtr, 0x140), VK_S1_COM_X)
|
||||
mstore(add(mPtr, 0x160), VK_S1_COM_Y)
|
||||
mstore(add(mPtr, 0x180), VK_S2_COM_X)
|
||||
mstore(add(mPtr, 0x1a0), VK_S2_COM_Y)
|
||||
|
||||
let offset := 0x1c0
|
||||
|
||||
mstore(add(mPtr,offset), VK_QCP_0_X)
|
||||
mstore(add(mPtr,add(offset, 0x20)), VK_QCP_0_Y)
|
||||
|
||||
mstore(add(mPtr, offset), VK_QCP_0_X)
|
||||
mstore(add(mPtr, add(offset, 0x20)), VK_QCP_0_Y)
|
||||
offset := add(offset, 0x40)
|
||||
mstore(add(mPtr, offset), mload(add(state, STATE_OPENING_LINEARISED_POLYNOMIAL_ZETA)))
|
||||
mstore(add(mPtr, add(offset, 0x20)), calldataload(add(aproof, PROOF_L_AT_ZETA)))
|
||||
@@ -1002,18 +994,23 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
|
||||
let _mPtr := add(mPtr, add(offset, 0xc0))
|
||||
|
||||
|
||||
let _poqaz := add(aproof, PROOF_OPENING_QCP_AT_ZETA)
|
||||
calldatacopy(_mPtr, _poqaz, mul(VK_NB_CUSTOM_GATES, 0x20))
|
||||
_mPtr := add(_mPtr, mul(VK_NB_CUSTOM_GATES, 0x20))
|
||||
|
||||
|
||||
mstore(_mPtr, calldataload(add(aproof, PROOF_GRAND_PRODUCT_AT_ZETA_OMEGA)))
|
||||
|
||||
let start_input := 0x1b // 00.."gamma"
|
||||
let size_input := add(0x14, mul(VK_NB_CUSTOM_GATES,3)) // number of 32bytes elmts = 0x14 (zeta+3*6 for the digests+openings) + 3*VK_NB_CUSTOM_GATES (for the commitments of the selectors) + 1 (opening of Z at ζω)
|
||||
let size_input := add(0x14, mul(VK_NB_CUSTOM_GATES, 3)) // number of 32bytes elmts = 0x14 (zeta+3*6 for the digests+openings) + 3*VK_NB_CUSTOM_GATES (for the commitments of the selectors) + 1 (opening of Z at ζω)
|
||||
size_input := add(0x5, mul(size_input, 0x20)) // size in bytes: 15*32 bytes + 5 bytes for gamma
|
||||
let check_staticcall := staticcall(gas(), SHA2, add(mPtr,start_input), size_input, add(state, STATE_GAMMA_KZG), 0x20)
|
||||
let check_staticcall := staticcall(
|
||||
gas(),
|
||||
SHA2,
|
||||
add(mPtr, start_input),
|
||||
size_input,
|
||||
add(state, STATE_GAMMA_KZG),
|
||||
0x20
|
||||
)
|
||||
if iszero(check_staticcall) {
|
||||
error_verify()
|
||||
}
|
||||
@@ -1021,7 +1018,6 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
}
|
||||
|
||||
function compute_commitment_linearised_polynomial_ec(aproof, s1, s2) {
|
||||
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
|
||||
@@ -1066,7 +1062,6 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
add(mPtr, 0x40)
|
||||
)
|
||||
|
||||
|
||||
let qcp_opening_at_zeta := add(aproof, PROOF_OPENING_QCP_AT_ZETA)
|
||||
let bsb_commitments := add(aproof, PROOF_BSB_COMMITMENTS)
|
||||
for {
|
||||
@@ -1085,7 +1080,6 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
qcp_opening_at_zeta := add(qcp_opening_at_zeta, 0x20)
|
||||
bsb_commitments := add(bsb_commitments, 0x40)
|
||||
}
|
||||
|
||||
|
||||
mstore(mPtr, VK_S3_COM_X)
|
||||
mstore(add(mPtr, 0x20), VK_S3_COM_Y)
|
||||
@@ -1096,10 +1090,11 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
point_acc_mul(add(state, STATE_LINEARISED_POLYNOMIAL_X), mPtr, s2, add(mPtr, 0x40))
|
||||
|
||||
point_add(
|
||||
add(state, STATE_LINEARISED_POLYNOMIAL_X),
|
||||
add(state, STATE_LINEARISED_POLYNOMIAL_X),
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
mPtr)
|
||||
add(state, STATE_LINEARISED_POLYNOMIAL_X),
|
||||
add(state, STATE_LINEARISED_POLYNOMIAL_X),
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
mPtr
|
||||
)
|
||||
}
|
||||
|
||||
/// @notice Compute the commitment to the linearized polynomial equal to
|
||||
@@ -1166,10 +1161,25 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
let zeta_power_n_plus_two := pow(mload(add(state, STATE_ZETA)), n_plus_two, mPtr)
|
||||
point_mul_calldata(add(state, STATE_FOLDED_H_X), add(aproof, PROOF_H_2_COM_X), zeta_power_n_plus_two, mPtr)
|
||||
point_add_calldata(add(state, STATE_FOLDED_H_X), add(state, STATE_FOLDED_H_X), add(aproof, PROOF_H_1_COM_X), mPtr)
|
||||
point_add_calldata(
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
add(aproof, PROOF_H_1_COM_X),
|
||||
mPtr
|
||||
)
|
||||
point_mul(add(state, STATE_FOLDED_H_X), add(state, STATE_FOLDED_H_X), zeta_power_n_plus_two, mPtr)
|
||||
point_add_calldata(add(state, STATE_FOLDED_H_X), add(state, STATE_FOLDED_H_X), add(aproof, PROOF_H_0_COM_X), mPtr)
|
||||
point_mul(add(state, STATE_FOLDED_H_X), add(state, STATE_FOLDED_H_X), mload(add(state, STATE_ZETA_POWER_N_MINUS_ONE)), mPtr)
|
||||
point_add_calldata(
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
add(aproof, PROOF_H_0_COM_X),
|
||||
mPtr
|
||||
)
|
||||
point_mul(
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
mload(add(state, STATE_ZETA_POWER_N_MINUS_ONE)),
|
||||
mPtr
|
||||
)
|
||||
let folded_h_y := mload(add(state, STATE_FOLDED_H_Y))
|
||||
folded_h_y := sub(P_MOD, folded_h_y)
|
||||
mstore(add(state, STATE_FOLDED_H_Y), folded_h_y)
|
||||
@@ -1179,7 +1189,6 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// - [ PI(ζ) - α²*L₁(ζ) + α(l(ζ)+β*s1(ζ)+γ)(r(ζ)+β*s2(ζ)+γ)(o(ζ)+γ)*z(ωζ) ]
|
||||
/// @param aproof pointer to the proof
|
||||
function compute_opening_linearised_polynomial(aproof) {
|
||||
|
||||
let state := mload(0x40)
|
||||
|
||||
// (l(ζ)+β*s1(ζ)+γ)
|
||||
@@ -1215,7 +1224,7 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
}
|
||||
|
||||
// BEGINNING utils math functions -------------------------------------------------
|
||||
|
||||
|
||||
/// @param dst pointer storing the result
|
||||
/// @param p pointer to the first point
|
||||
/// @param q pointer to the second point
|
||||
@@ -1225,7 +1234,7 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
mstore(add(mPtr, 0x20), mload(add(p, 0x20)))
|
||||
mstore(add(mPtr, 0x40), mload(q))
|
||||
mstore(add(mPtr, 0x60), mload(add(q, 0x20)))
|
||||
let l_success := staticcall(gas(),EC_ADD,mPtr,0x80,dst,0x40)
|
||||
let l_success := staticcall(gas(), EC_ADD, mPtr, 0x80, dst, 0x40)
|
||||
if iszero(l_success) {
|
||||
error_ec_op()
|
||||
}
|
||||
@@ -1250,11 +1259,11 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// @param src pointer to a point on Bn254(𝔽_p)
|
||||
/// @param s scalar
|
||||
/// @param mPtr free memory
|
||||
function point_mul(dst,src,s, mPtr) {
|
||||
mstore(mPtr,mload(src))
|
||||
mstore(add(mPtr,0x20),mload(add(src,0x20)))
|
||||
mstore(add(mPtr,0x40),s)
|
||||
let l_success := staticcall(gas(),EC_MUL,mPtr,0x60,dst,0x40)
|
||||
function point_mul(dst, src, s, mPtr) {
|
||||
mstore(mPtr, mload(src))
|
||||
mstore(add(mPtr, 0x20), mload(add(src, 0x20)))
|
||||
mstore(add(mPtr, 0x40), s)
|
||||
let l_success := staticcall(gas(), EC_MUL, mPtr, 0x60, dst, 0x40)
|
||||
if iszero(l_success) {
|
||||
error_ec_op()
|
||||
}
|
||||
@@ -1279,14 +1288,14 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// @param src pointer to the point to multiply and add
|
||||
/// @param s scalar
|
||||
/// @param mPtr free memory
|
||||
function point_acc_mul(dst,src,s, mPtr) {
|
||||
mstore(mPtr,mload(src))
|
||||
mstore(add(mPtr,0x20),mload(add(src,0x20)))
|
||||
mstore(add(mPtr,0x40),s)
|
||||
let l_success := staticcall(gas(),7,mPtr,0x60,mPtr,0x40)
|
||||
mstore(add(mPtr,0x40),mload(dst))
|
||||
mstore(add(mPtr,0x60),mload(add(dst,0x20)))
|
||||
l_success := and(l_success, staticcall(gas(),EC_ADD,mPtr,0x80,dst, 0x40))
|
||||
function point_acc_mul(dst, src, s, mPtr) {
|
||||
mstore(mPtr, mload(src))
|
||||
mstore(add(mPtr, 0x20), mload(add(src, 0x20)))
|
||||
mstore(add(mPtr, 0x40), s)
|
||||
let l_success := staticcall(gas(), 7, mPtr, 0x60, mPtr, 0x40)
|
||||
mstore(add(mPtr, 0x40), mload(dst))
|
||||
mstore(add(mPtr, 0x60), mload(add(dst, 0x20)))
|
||||
l_success := and(l_success, staticcall(gas(), EC_ADD, mPtr, 0x80, dst, 0x40))
|
||||
if iszero(l_success) {
|
||||
error_ec_op()
|
||||
}
|
||||
@@ -1315,7 +1324,7 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// @param src pointer to the scalar to multiply and add (on calldata)
|
||||
/// @param s scalar
|
||||
function fr_acc_mul_calldata(dst, src, s) {
|
||||
let tmp := mulmod(calldataload(src), s, R_MOD)
|
||||
let tmp := mulmod(calldataload(src), s, R_MOD)
|
||||
mstore(dst, addmod(mload(dst), tmp, R_MOD))
|
||||
}
|
||||
|
||||
@@ -1323,16 +1332,16 @@ contract TestPlonkVerifierForDataAggregation {
|
||||
/// @param e exponent
|
||||
/// @param mPtr free memory
|
||||
/// @return res x ** e mod r
|
||||
function pow(x, e, mPtr)->res {
|
||||
function pow(x, e, mPtr) -> res {
|
||||
mstore(mPtr, 0x20)
|
||||
mstore(add(mPtr, 0x20), 0x20)
|
||||
mstore(add(mPtr, 0x40), 0x20)
|
||||
mstore(add(mPtr, 0x60), x)
|
||||
mstore(add(mPtr, 0x80), e)
|
||||
mstore(add(mPtr, 0xa0), R_MOD)
|
||||
let check_staticcall := staticcall(gas(),MOD_EXP,mPtr,0xc0,mPtr,0x20)
|
||||
let check_staticcall := staticcall(gas(), MOD_EXP, mPtr, 0xc0, mPtr, 0x20)
|
||||
if eq(check_staticcall, 0) {
|
||||
error_mod_exp()
|
||||
error_mod_exp()
|
||||
}
|
||||
res := mload(mPtr)
|
||||
}
|
||||
|
||||
@@ -19,28 +19,29 @@
|
||||
pragma solidity 0.8.26;
|
||||
|
||||
contract PlonkVerifierForDataAggregation {
|
||||
|
||||
uint256 private constant R_MOD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||
uint256 private constant R_MOD_MINUS_ONE = 21888242871839275222246405745257275088548364400416034343698204186575808495616;
|
||||
uint256 private constant R_MOD_MINUS_ONE =
|
||||
21888242871839275222246405745257275088548364400416034343698204186575808495616;
|
||||
uint256 private constant P_MOD = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||
|
||||
|
||||
uint256 private constant G2_SRS_0_X_0 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
|
||||
uint256 private constant G2_SRS_0_X_1 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
|
||||
uint256 private constant G2_SRS_0_Y_0 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
|
||||
uint256 private constant G2_SRS_0_Y_1 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
|
||||
|
||||
|
||||
uint256 private constant G2_SRS_1_X_0 = 15805639136721018565402881920352193254830339253282065586954346329754995870280;
|
||||
uint256 private constant G2_SRS_1_X_1 = 19089565590083334368588890253123139704298730990782503769911324779715431555531;
|
||||
uint256 private constant G2_SRS_1_Y_0 = 9779648407879205346559610309258181044130619080926897934572699915909528404984;
|
||||
uint256 private constant G2_SRS_1_Y_1 = 6779728121489434657638426458390319301070371227460768374343986326751507916979;
|
||||
|
||||
|
||||
uint256 private constant G1_SRS_X = 14312776538779914388377568895031746459131577658076416373430523308756343304251;
|
||||
uint256 private constant G1_SRS_Y = 11763105256161367503191792604679297387056316997144156930871823008787082098465;
|
||||
|
||||
// ----------------------- vk ---------------------
|
||||
uint256 private constant VK_NB_PUBLIC_INPUTS = 1;
|
||||
uint256 private constant VK_DOMAIN_SIZE = 16;
|
||||
uint256 private constant VK_INV_DOMAIN_SIZE = 20520227692349320520856005386178695395514091625390032197217066424914820464641;
|
||||
uint256 private constant VK_INV_DOMAIN_SIZE =
|
||||
20520227692349320520856005386178695395514091625390032197217066424914820464641;
|
||||
uint256 private constant VK_OMEGA = 14940766826517323942636479241147756311199852622225275649687664389641784935947;
|
||||
uint256 private constant VK_QL_COM_X = 3767637989833674092151354229632559107224950590673664856842061399469467338879;
|
||||
uint256 private constant VK_QL_COM_Y = 18545409996679466114224178746162553880737296402729089689774308937082946761979;
|
||||
@@ -52,23 +53,21 @@ contract PlonkVerifierForDataAggregation {
|
||||
uint256 private constant VK_QO_COM_Y = 10782414695040549646706468913781794882209258381887890407509684555513355143197;
|
||||
uint256 private constant VK_QK_COM_X = 309591480144351325314158474719361148480191595146291661238142838254651436989;
|
||||
uint256 private constant VK_QK_COM_Y = 12063173869829536468830946547606069911666129778788708678515573607390482939756;
|
||||
|
||||
|
||||
uint256 private constant VK_S1_COM_X = 12287072751694848944507699577006619791724925439540371477056092891137357229312;
|
||||
uint256 private constant VK_S1_COM_Y = 2469356406782415219782253630635766217009619642857495098799013714324696399305;
|
||||
|
||||
|
||||
uint256 private constant VK_S2_COM_X = 17261757720471042341269061128759148572672168808566386603388432325173708264418;
|
||||
uint256 private constant VK_S2_COM_Y = 20976565876611279190744172824963243461988367679364518747954008723085439460611;
|
||||
|
||||
|
||||
uint256 private constant VK_S3_COM_X = 18758025488249277181117376239193628449359868741625564388668468130204669284937;
|
||||
uint256 private constant VK_S3_COM_Y = 15566903578741238761792344329051427316196307361197991677131114502821508927172;
|
||||
|
||||
|
||||
uint256 private constant VK_COSET_SHIFT = 5;
|
||||
|
||||
|
||||
|
||||
uint256 private constant VK_QCP_0_X = 4559262075452024065272338216146989708834054079507534161096300708463935456394;
|
||||
uint256 private constant VK_QCP_0_Y = 1898950104727986554890445533779776634695458253078091580309593009754027486622;
|
||||
|
||||
|
||||
|
||||
uint256 private constant VK_INDEX_COMMIT_API_0 = 5;
|
||||
uint256 private constant VK_NB_CUSTOM_GATES = 1;
|
||||
|
||||
@@ -78,7 +77,7 @@ contract PlonkVerifierForDataAggregation {
|
||||
uint256 private constant FIXED_PROOF_SIZE = 0x300;
|
||||
|
||||
// offset proof
|
||||
|
||||
|
||||
uint256 private constant PROOF_L_COM_X = 0x0;
|
||||
uint256 private constant PROOF_L_COM_Y = 0x20;
|
||||
uint256 private constant PROOF_R_COM_X = 0x40;
|
||||
@@ -122,7 +121,7 @@ contract PlonkVerifierForDataAggregation {
|
||||
// -------- offset state
|
||||
|
||||
// challenges to check the claimed quotient
|
||||
|
||||
|
||||
uint256 private constant STATE_ALPHA = 0x0;
|
||||
uint256 private constant STATE_BETA = 0x20;
|
||||
uint256 private constant STATE_GAMMA = 0x40;
|
||||
@@ -153,15 +152,13 @@ contract PlonkVerifierForDataAggregation {
|
||||
// -------- errors
|
||||
uint256 private constant ERROR_STRING_ID = 0x08c379a000000000000000000000000000000000000000000000000000000000; // selector for function Error(string)
|
||||
|
||||
|
||||
// -------- utils (for hash_fr)
|
||||
uint256 private constant HASH_FR_BB = 340282366920938463463374607431768211456; // 2**128
|
||||
uint256 private constant HASH_FR_ZERO_UINT256 = 0;
|
||||
uint8 private constant HASH_FR_LEN_IN_BYTES = 48;
|
||||
uint8 private constant HASH_FR_SIZE_DOMAIN = 11;
|
||||
uint8 private constant HASH_FR_ONE = 1;
|
||||
uint8 private constant HASH_FR_TWO = 2;
|
||||
|
||||
uint256 private constant HASH_FR_BB = 340282366920938463463374607431768211456; // 2**128
|
||||
uint256 private constant HASH_FR_ZERO_UINT256 = 0;
|
||||
uint8 private constant HASH_FR_LEN_IN_BYTES = 48;
|
||||
uint8 private constant HASH_FR_SIZE_DOMAIN = 11;
|
||||
uint8 private constant HASH_FR_ONE = 1;
|
||||
uint8 private constant HASH_FR_TWO = 2;
|
||||
|
||||
// -------- precompiles
|
||||
uint8 private constant SHA2 = 0x2;
|
||||
@@ -169,17 +166,14 @@ contract PlonkVerifierForDataAggregation {
|
||||
uint8 private constant EC_ADD = 0x6;
|
||||
uint8 private constant EC_MUL = 0x7;
|
||||
uint8 private constant EC_PAIR = 0x8;
|
||||
|
||||
|
||||
/// Verify a Plonk proof.
|
||||
/// Reverts if the proof or the public inputs are malformed.
|
||||
/// @param proof serialised plonk proof (using gnark's MarshalSolidity)
|
||||
/// @param public_inputs (must be reduced)
|
||||
/// @return success true if the proof passes false otherwise
|
||||
function Verify(bytes calldata proof, uint256[] calldata public_inputs)
|
||||
public view returns(bool success) {
|
||||
|
||||
function Verify(bytes calldata proof, uint256[] calldata public_inputs) public view returns (bool success) {
|
||||
assembly {
|
||||
|
||||
let mem := mload(0x40)
|
||||
let freeMem := add(mem, STATE_LAST_MEM)
|
||||
|
||||
@@ -311,20 +305,23 @@ contract PlonkVerifierForDataAggregation {
|
||||
// end errors -------------------------------------------------
|
||||
|
||||
// Beginning checks -------------------------------------------------
|
||||
|
||||
|
||||
/// @param s actual number of public inputs
|
||||
function check_number_of_public_inputs(s) {
|
||||
if iszero(eq(s, VK_NB_PUBLIC_INPUTS)) {
|
||||
error_nb_public_inputs()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Checks that the public inputs are < R_MOD.
|
||||
/// @param s number of public inputs
|
||||
/// @param p pointer to the public inputs array
|
||||
function check_inputs_size(s, p) {
|
||||
for {let i} lt(i, s) {i:=add(i,1)}
|
||||
{
|
||||
for {
|
||||
let i
|
||||
} lt(i, s) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
if gt(calldataload(p), R_MOD_MINUS_ONE) {
|
||||
error_inputs_size()
|
||||
}
|
||||
@@ -335,17 +332,16 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// Checks if the proof is of the correct size
|
||||
/// @param actual_proof_size size of the proof (not the expected size)
|
||||
function check_proof_size(actual_proof_size) {
|
||||
let expected_proof_size := add(FIXED_PROOF_SIZE, mul(VK_NB_CUSTOM_GATES,0x60))
|
||||
let expected_proof_size := add(FIXED_PROOF_SIZE, mul(VK_NB_CUSTOM_GATES, 0x60))
|
||||
if iszero(eq(actual_proof_size, expected_proof_size)) {
|
||||
error_proof_size()
|
||||
error_proof_size()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Checks if the multiple openings of the polynomials are < R_MOD.
|
||||
/// @param aproof pointer to the beginning of the proof
|
||||
/// @dev the 'a' prepending proof is to have a local name
|
||||
function check_proof_openings_size(aproof) {
|
||||
|
||||
// PROOF_L_AT_ZETA
|
||||
let p := add(aproof, PROOF_L_AT_ZETA)
|
||||
if gt(calldataload(p), R_MOD_MINUS_ONE) {
|
||||
@@ -369,7 +365,7 @@ contract PlonkVerifierForDataAggregation {
|
||||
if gt(calldataload(p), R_MOD_MINUS_ONE) {
|
||||
error_proof_openings_size()
|
||||
}
|
||||
|
||||
|
||||
// PROOF_S2_AT_ZETA
|
||||
p := add(aproof, PROOF_S2_AT_ZETA)
|
||||
if gt(calldataload(p), R_MOD_MINUS_ONE) {
|
||||
@@ -383,16 +379,18 @@ contract PlonkVerifierForDataAggregation {
|
||||
}
|
||||
|
||||
// PROOF_OPENING_QCP_AT_ZETA
|
||||
|
||||
|
||||
p := add(aproof, PROOF_OPENING_QCP_AT_ZETA)
|
||||
for {let i:=0} lt(i, VK_NB_CUSTOM_GATES) {i:=add(i,1)}
|
||||
{
|
||||
for {
|
||||
let i := 0
|
||||
} lt(i, VK_NB_CUSTOM_GATES) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
if gt(calldataload(p), R_MOD_MINUS_ONE) {
|
||||
error_proof_openings_size()
|
||||
}
|
||||
p := add(p, 0x20)
|
||||
}
|
||||
|
||||
}
|
||||
// end checks -------------------------------------------------
|
||||
|
||||
@@ -414,34 +412,32 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// and is encoded as a uint256 number n. In basis b = 256, the number looks like this
|
||||
/// [0 0 0 .. 0x67 0x61 0x6d, 0x6d, 0x61]. The first non zero entry is at position 27=0x1b
|
||||
/// Gamma reduced (the actual challenge) is stored at add(state, state_gamma)
|
||||
function derive_gamma(aproof, nb_pi, pi)->gamma_not_reduced {
|
||||
|
||||
function derive_gamma(aproof, nb_pi, pi) -> gamma_not_reduced {
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(state, STATE_LAST_MEM)
|
||||
|
||||
mstore(mPtr, FS_GAMMA) // "gamma"
|
||||
|
||||
|
||||
mstore(add(mPtr, 0x20), VK_S1_COM_X)
|
||||
mstore(add(mPtr, 0x40), VK_S1_COM_Y)
|
||||
mstore(add(mPtr, 0x60), VK_S2_COM_X)
|
||||
mstore(add(mPtr, 0x80), VK_S2_COM_Y)
|
||||
mstore(add(mPtr, 0xa0), VK_S3_COM_X)
|
||||
mstore(add(mPtr, 0xc0), VK_S3_COM_Y)
|
||||
mstore(add(mPtr, 0xe0), VK_QL_COM_X)
|
||||
mstore(add(mPtr, 0x100), VK_QL_COM_Y)
|
||||
mstore(add(mPtr, 0x120), VK_QR_COM_X)
|
||||
mstore(add(mPtr, 0x140), VK_QR_COM_Y)
|
||||
mstore(add(mPtr, 0x160), VK_QM_COM_X)
|
||||
mstore(add(mPtr, 0x180), VK_QM_COM_Y)
|
||||
mstore(add(mPtr, 0x1a0), VK_QO_COM_X)
|
||||
mstore(add(mPtr, 0x1c0), VK_QO_COM_Y)
|
||||
mstore(add(mPtr, 0x1e0), VK_QK_COM_X)
|
||||
mstore(add(mPtr, 0x200), VK_QK_COM_Y)
|
||||
|
||||
mstore(add(mPtr, 0x220), VK_QCP_0_X)
|
||||
mstore(add(mPtr, 0x240), VK_QCP_0_Y)
|
||||
|
||||
mstore(add(mPtr, 0x20), VK_S1_COM_X)
|
||||
mstore(add(mPtr, 0x40), VK_S1_COM_Y)
|
||||
mstore(add(mPtr, 0x60), VK_S2_COM_X)
|
||||
mstore(add(mPtr, 0x80), VK_S2_COM_Y)
|
||||
mstore(add(mPtr, 0xa0), VK_S3_COM_X)
|
||||
mstore(add(mPtr, 0xc0), VK_S3_COM_Y)
|
||||
mstore(add(mPtr, 0xe0), VK_QL_COM_X)
|
||||
mstore(add(mPtr, 0x100), VK_QL_COM_Y)
|
||||
mstore(add(mPtr, 0x120), VK_QR_COM_X)
|
||||
mstore(add(mPtr, 0x140), VK_QR_COM_Y)
|
||||
mstore(add(mPtr, 0x160), VK_QM_COM_X)
|
||||
mstore(add(mPtr, 0x180), VK_QM_COM_Y)
|
||||
mstore(add(mPtr, 0x1a0), VK_QO_COM_X)
|
||||
mstore(add(mPtr, 0x1c0), VK_QO_COM_Y)
|
||||
mstore(add(mPtr, 0x1e0), VK_QK_COM_X)
|
||||
mstore(add(mPtr, 0x200), VK_QK_COM_Y)
|
||||
|
||||
mstore(add(mPtr, 0x220), VK_QCP_0_X)
|
||||
mstore(add(mPtr, 0x240), VK_QCP_0_Y)
|
||||
|
||||
// public inputs
|
||||
let _mPtr := add(mPtr, 0x260)
|
||||
let size_pi_in_bytes := mul(nb_pi, 0x20)
|
||||
@@ -458,7 +454,7 @@ contract PlonkVerifierForDataAggregation {
|
||||
// + nb_public_inputs*0x20
|
||||
// + nb_custom gates*0x40
|
||||
let size := add(0x2c5, size_pi_in_bytes)
|
||||
|
||||
|
||||
size := add(size, mul(VK_NB_CUSTOM_GATES, 0x40))
|
||||
let l_success := staticcall(gas(), SHA2, add(mPtr, 0x1b), size, mPtr, 0x20) //0x1b -> 000.."gamma"
|
||||
if iszero(l_success) {
|
||||
@@ -473,8 +469,7 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// @return beta_not_reduced the next challenge, beta, not reduced
|
||||
/// @notice the transcript consists of the previous challenge only.
|
||||
/// The reduced version of beta is stored at add(state, state_beta)
|
||||
function derive_beta(gamma_not_reduced)->beta_not_reduced{
|
||||
|
||||
function derive_beta(gamma_not_reduced) -> beta_not_reduced {
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
|
||||
@@ -495,9 +490,8 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// @return alpha_not_reduced the next challenge, alpha, not reduced
|
||||
/// @notice the transcript consists of the previous challenge (beta)
|
||||
/// not reduced, the commitments to the wires associated to the QCP_i,
|
||||
/// and the commitment to the grand product polynomial
|
||||
function derive_alpha(aproof, beta_not_reduced)->alpha_not_reduced {
|
||||
|
||||
/// and the commitment to the grand product polynomial
|
||||
function derive_alpha(aproof, beta_not_reduced) -> alpha_not_reduced {
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
let full_size := 0x65 // size("alpha") + 0x20 (previous challenge)
|
||||
@@ -507,14 +501,14 @@ contract PlonkVerifierForDataAggregation {
|
||||
let _mPtr := add(mPtr, 0x20)
|
||||
mstore(_mPtr, beta_not_reduced)
|
||||
_mPtr := add(_mPtr, 0x20)
|
||||
|
||||
|
||||
// Bsb22Commitments
|
||||
let proof_bsb_commitments := add(aproof, PROOF_BSB_COMMITMENTS)
|
||||
let size_bsb_commitments := mul(0x40, VK_NB_CUSTOM_GATES)
|
||||
calldatacopy(_mPtr, proof_bsb_commitments, size_bsb_commitments)
|
||||
_mPtr := add(_mPtr, size_bsb_commitments)
|
||||
full_size := add(full_size, size_bsb_commitments)
|
||||
|
||||
|
||||
// [Z], the commitment to the grand product polynomial
|
||||
calldatacopy(_mPtr, add(aproof, PROOF_GRAND_PRODUCT_COMMITMENT_X), 0x40)
|
||||
let l_success := staticcall(gas(), SHA2, add(mPtr, 0x1b), full_size, mPtr, 0x20)
|
||||
@@ -532,7 +526,6 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// The transcript consists of the previous challenge and the commitment to
|
||||
/// the quotient polynomial h.
|
||||
function derive_zeta(aproof, alpha_not_reduced) {
|
||||
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
|
||||
@@ -557,8 +550,7 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// @param n number of public inputs
|
||||
/// @param mPtr free memory
|
||||
/// @return pi_wo_commit public inputs contribution (except the public inputs coming from the custom gate)
|
||||
function sum_pi_wo_api_commit(ins, n, mPtr)->pi_wo_commit {
|
||||
|
||||
function sum_pi_wo_api_commit(ins, n, mPtr) -> pi_wo_commit {
|
||||
let state := mload(0x40)
|
||||
let z := mload(add(state, STATE_ZETA))
|
||||
let zpnmo := mload(add(state, STATE_ZETA_POWER_N_MINUS_ONE))
|
||||
@@ -567,14 +559,16 @@ contract PlonkVerifierForDataAggregation {
|
||||
batch_compute_lagranges_at_z(z, zpnmo, n, li)
|
||||
|
||||
let tmp := 0
|
||||
for {let i:=0} lt(i,n) {i:=add(i,1)}
|
||||
{
|
||||
for {
|
||||
let i := 0
|
||||
} lt(i, n) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
tmp := mulmod(mload(li), calldataload(ins), R_MOD)
|
||||
pi_wo_commit := addmod(pi_wo_commit, tmp, R_MOD)
|
||||
li := add(li, 0x20)
|
||||
ins := add(ins, 0x20)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// batch_compute_lagranges_at_z computes [L_0(z), .., L_{n-1}(z)]
|
||||
@@ -583,27 +577,32 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// @param n_pub number of public inputs (number of Lagranges to compute)
|
||||
/// @param mPtr pointer to which the results are stored
|
||||
function batch_compute_lagranges_at_z(z, zpnmo, n_pub, mPtr) {
|
||||
|
||||
let zn := mulmod(zpnmo, VK_INV_DOMAIN_SIZE, R_MOD) // 1/n * (ζⁿ - 1)
|
||||
|
||||
|
||||
let _w := 1
|
||||
let _mPtr := mPtr
|
||||
for {let i:=0} lt(i,n_pub) {i:=add(i,1)}
|
||||
{
|
||||
mstore(_mPtr, addmod(z,sub(R_MOD, _w), R_MOD))
|
||||
for {
|
||||
let i := 0
|
||||
} lt(i, n_pub) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
mstore(_mPtr, addmod(z, sub(R_MOD, _w), R_MOD))
|
||||
_w := mulmod(_w, VK_OMEGA, R_MOD)
|
||||
_mPtr := add(_mPtr, 0x20)
|
||||
}
|
||||
batch_invert(mPtr, n_pub, _mPtr)
|
||||
_mPtr := mPtr
|
||||
_w := 1
|
||||
for {let i:=0} lt(i,n_pub) {i:=add(i,1)}
|
||||
{
|
||||
mstore(_mPtr, mulmod(mulmod(mload(_mPtr), zn , R_MOD), _w, R_MOD))
|
||||
for {
|
||||
let i := 0
|
||||
} lt(i, n_pub) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
mstore(_mPtr, mulmod(mulmod(mload(_mPtr), zn, R_MOD), _w, R_MOD))
|
||||
_mPtr := add(_mPtr, 0x20)
|
||||
_w := mulmod(_w, VK_OMEGA, R_MOD)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @notice Montgomery trick for batch inversion mod R_MOD
|
||||
/// @param ins pointer to the data to batch invert
|
||||
@@ -612,8 +611,11 @@ contract PlonkVerifierForDataAggregation {
|
||||
function batch_invert(ins, nb_ins, mPtr) {
|
||||
mstore(mPtr, 1)
|
||||
let offset := 0
|
||||
for {let i:=0} lt(i, nb_ins) {i:=add(i,1)}
|
||||
{
|
||||
for {
|
||||
let i := 0
|
||||
} lt(i, nb_ins) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
let prev := mload(add(mPtr, offset))
|
||||
let cur := mload(add(ins, offset))
|
||||
cur := mulmod(prev, cur, R_MOD)
|
||||
@@ -622,9 +624,12 @@ contract PlonkVerifierForDataAggregation {
|
||||
}
|
||||
ins := add(ins, sub(offset, 0x20))
|
||||
mPtr := add(mPtr, offset)
|
||||
let inv := pow(mload(mPtr), sub(R_MOD,2), add(mPtr, 0x20))
|
||||
for {let i:=0} lt(i, nb_ins) {i:=add(i,1)}
|
||||
{
|
||||
let inv := pow(mload(mPtr), sub(R_MOD, 2), add(mPtr, 0x20))
|
||||
for {
|
||||
let i := 0
|
||||
} lt(i, nb_ins) {
|
||||
i := add(i, 1)
|
||||
} {
|
||||
mPtr := sub(mPtr, 0x20)
|
||||
let tmp := mload(ins)
|
||||
let cur := mulmod(inv, mload(mPtr), R_MOD)
|
||||
@@ -634,14 +639,12 @@ contract PlonkVerifierForDataAggregation {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Public inputs (the ones coming from the custom gate) contribution
|
||||
/// @param aproof pointer to the proof
|
||||
/// @param nb_public_inputs number of public inputs
|
||||
/// @param mPtr pointer to free memory
|
||||
/// @return pi_commit custom gate public inputs contribution
|
||||
function sum_pi_commit(aproof, nb_public_inputs, mPtr)->pi_commit {
|
||||
|
||||
function sum_pi_commit(aproof, nb_public_inputs, mPtr) -> pi_commit {
|
||||
let state := mload(0x40)
|
||||
let z := mload(add(state, STATE_ZETA))
|
||||
let zpnmo := mload(add(state, STATE_ZETA_POWER_N_MINUS_ONE))
|
||||
@@ -649,14 +652,10 @@ contract PlonkVerifierForDataAggregation {
|
||||
let p := add(aproof, PROOF_BSB_COMMITMENTS)
|
||||
|
||||
let h_fr, ith_lagrange
|
||||
|
||||
|
||||
|
||||
h_fr := hash_fr(calldataload(p), calldataload(add(p, 0x20)), mPtr)
|
||||
ith_lagrange := compute_ith_lagrange_at_z(z, zpnmo, add(nb_public_inputs, VK_INDEX_COMMIT_API_0), mPtr)
|
||||
pi_commit := addmod(pi_commit, mulmod(h_fr, ith_lagrange, R_MOD), R_MOD)
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// Computes L_i(zeta) = ωⁱ/n * (ζⁿ-1)/(ζ-ωⁱ) where:
|
||||
@@ -664,16 +663,14 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// @param zpmno ζⁿ-1
|
||||
/// @param i i-th lagrange
|
||||
/// @param mPtr free memory
|
||||
/// @return res = ωⁱ/n * (ζⁿ-1)/(ζ-ωⁱ)
|
||||
function compute_ith_lagrange_at_z(z, zpnmo, i, mPtr)->res {
|
||||
|
||||
/// @return res = ωⁱ/n * (ζⁿ-1)/(ζ-ωⁱ)
|
||||
function compute_ith_lagrange_at_z(z, zpnmo, i, mPtr) -> res {
|
||||
let w := pow(VK_OMEGA, i, mPtr) // w**i
|
||||
i := addmod(z, sub(R_MOD, w), R_MOD) // z-w**i
|
||||
w := mulmod(w, VK_INV_DOMAIN_SIZE, R_MOD) // w**i/n
|
||||
i := pow(i, sub(R_MOD,2), mPtr) // (z-w**i)**-1
|
||||
i := pow(i, sub(R_MOD, 2), mPtr) // (z-w**i)**-1
|
||||
w := mulmod(w, i, R_MOD) // w**i/n*(z-w)**-1
|
||||
res := mulmod(w, zpnmo, R_MOD)
|
||||
|
||||
}
|
||||
|
||||
/// @dev https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-5.2
|
||||
@@ -681,15 +678,14 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// @param y y coordinate of a point on Bn254(𝔽_p)
|
||||
/// @param mPtr free memory
|
||||
/// @return res an element mod R_MOD
|
||||
function hash_fr(x, y, mPtr)->res {
|
||||
|
||||
function hash_fr(x, y, mPtr) -> res {
|
||||
// [0x00, .. , 0x00 || x, y, || 0, 48, 0, dst, HASH_FR_SIZE_DOMAIN]
|
||||
// <- 64 bytes -> <-64b -> <- 1 bytes each ->
|
||||
|
||||
// [0x00, .., 0x00] 64 bytes of zero
|
||||
mstore(mPtr, HASH_FR_ZERO_UINT256)
|
||||
mstore(add(mPtr, 0x20), HASH_FR_ZERO_UINT256)
|
||||
|
||||
|
||||
// msg = x || y , both on 32 bytes
|
||||
mstore(add(mPtr, 0x40), x)
|
||||
mstore(add(mPtr, 0x60), y)
|
||||
@@ -725,7 +721,7 @@ contract PlonkVerifierForDataAggregation {
|
||||
// [b0 || one || dst || HASH_FR_SIZE_DOMAIN]
|
||||
// <-64bytes -> <- 1 byte each ->
|
||||
mstore8(add(mPtr, 0x20), HASH_FR_ONE) // 1
|
||||
|
||||
|
||||
mstore8(add(mPtr, 0x21), 0x42) // dst
|
||||
mstore8(add(mPtr, 0x22), 0x53)
|
||||
mstore8(add(mPtr, 0x23), 0x42)
|
||||
@@ -777,9 +773,8 @@ contract PlonkVerifierForDataAggregation {
|
||||
res := mulmod(mload(mPtr), HASH_FR_BB, R_MOD) // <- res = 2**128 * mPtr[:32]
|
||||
let b1 := shr(128, mload(add(mPtr, 0x20))) // b1 <- [0, 0, .., 0 || b2[:16] ]
|
||||
res := addmod(res, b1, R_MOD)
|
||||
|
||||
}
|
||||
|
||||
|
||||
// END compute_pi -------------------------------------------------
|
||||
|
||||
/// @notice compute α² * 1/n * (ζ{n}-1)/(ζ - 1) where
|
||||
@@ -787,7 +782,7 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// * n = vk_domain_size
|
||||
/// * ω = vk_omega (generator of the multiplicative cyclic group of order n in (ℤ/rℤ)*)
|
||||
/// * ζ = zeta (challenge derived with Fiat Shamir)
|
||||
function compute_alpha_square_lagrange_0() {
|
||||
function compute_alpha_square_lagrange_0() {
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
|
||||
@@ -827,7 +822,7 @@ contract PlonkVerifierForDataAggregation {
|
||||
mstore(add(mPtr, 0x100), mload(add(state, STATE_ZETA)))
|
||||
mstore(add(mPtr, 0x120), mload(add(state, STATE_GAMMA_KZG)))
|
||||
let random := staticcall(gas(), SHA2, mPtr, 0x140, mPtr, 0x20)
|
||||
if iszero(random){
|
||||
if iszero(random) {
|
||||
error_random_generation()
|
||||
}
|
||||
random := mod(mload(mPtr), R_MOD) // use the same variable as we are one variable away from getting stack-too-deep error...
|
||||
@@ -876,18 +871,18 @@ contract PlonkVerifierForDataAggregation {
|
||||
mstore(folded_quotients_y, sub(P_MOD, mload(folded_quotients_y)))
|
||||
|
||||
mstore(mPtr, mload(folded_digests))
|
||||
|
||||
mstore(add(mPtr, 0x20), mload(add(folded_digests, 0x20)))
|
||||
mstore(add(mPtr, 0x40), G2_SRS_0_X_0) // the 4 lines are the canonical G2 point on BN254
|
||||
mstore(add(mPtr, 0x60), G2_SRS_0_X_1)
|
||||
mstore(add(mPtr, 0x80), G2_SRS_0_Y_0)
|
||||
mstore(add(mPtr, 0xa0), G2_SRS_0_Y_1)
|
||||
mstore(add(mPtr, 0xc0), mload(folded_quotients))
|
||||
mstore(add(mPtr, 0xe0), mload(add(folded_quotients, 0x20)))
|
||||
mstore(add(mPtr, 0x100), G2_SRS_1_X_0)
|
||||
mstore(add(mPtr, 0x120), G2_SRS_1_X_1)
|
||||
mstore(add(mPtr, 0x140), G2_SRS_1_Y_0)
|
||||
mstore(add(mPtr, 0x160), G2_SRS_1_Y_1)
|
||||
|
||||
mstore(add(mPtr, 0x20), mload(add(folded_digests, 0x20)))
|
||||
mstore(add(mPtr, 0x40), G2_SRS_0_X_0) // the 4 lines are the canonical G2 point on BN254
|
||||
mstore(add(mPtr, 0x60), G2_SRS_0_X_1)
|
||||
mstore(add(mPtr, 0x80), G2_SRS_0_Y_0)
|
||||
mstore(add(mPtr, 0xa0), G2_SRS_0_Y_1)
|
||||
mstore(add(mPtr, 0xc0), mload(folded_quotients))
|
||||
mstore(add(mPtr, 0xe0), mload(add(folded_quotients, 0x20)))
|
||||
mstore(add(mPtr, 0x100), G2_SRS_1_X_0)
|
||||
mstore(add(mPtr, 0x120), G2_SRS_1_X_1)
|
||||
mstore(add(mPtr, 0x140), G2_SRS_1_Y_0)
|
||||
mstore(add(mPtr, 0x160), G2_SRS_1_Y_1)
|
||||
check_pairing_kzg(mPtr)
|
||||
}
|
||||
|
||||
@@ -912,7 +907,6 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// @param aproof pointer to the proof
|
||||
/// acc_gamma stores the γⁱ
|
||||
function fold_state(aproof) {
|
||||
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
let mPtr20 := add(mPtr, 0x20)
|
||||
@@ -949,15 +943,14 @@ contract PlonkVerifierForDataAggregation {
|
||||
point_acc_mul(state_folded_digests, mPtr, acc_gamma, mPtr40)
|
||||
fr_acc_mul_calldata(add(state, STATE_FOLDED_CLAIMED_VALUES), add(aproof, PROOF_S2_AT_ZETA), acc_gamma)
|
||||
let poqaz := add(aproof, PROOF_OPENING_QCP_AT_ZETA)
|
||||
|
||||
|
||||
acc_gamma := mulmod(acc_gamma, l_gamma_kzg, R_MOD)
|
||||
mstore(mPtr, VK_QCP_0_X)
|
||||
mstore(mPtr20, VK_QCP_0_Y)
|
||||
point_acc_mul(state_folded_digests, mPtr, acc_gamma, mPtr40)
|
||||
fr_acc_mul_calldata(add(state, STATE_FOLDED_CLAIMED_VALUES), poqaz, acc_gamma)
|
||||
poqaz := add(poqaz, 0x20)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// @notice generate the challenge (using Fiat Shamir) to fold the opening proofs
|
||||
/// at ζ.
|
||||
@@ -975,23 +968,22 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// * Z(ζω)
|
||||
/// @param aproof pointer to the proof
|
||||
function compute_gamma_kzg(aproof) {
|
||||
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
mstore(mPtr, FS_GAMMA_KZG) // "gamma"
|
||||
mstore(add(mPtr, 0x20), mload(add(state, STATE_ZETA)))
|
||||
mstore(add(mPtr,0x40), mload(add(state, STATE_LINEARISED_POLYNOMIAL_X)))
|
||||
mstore(add(mPtr,0x60), mload(add(state, STATE_LINEARISED_POLYNOMIAL_Y)))
|
||||
mstore(add(mPtr, 0x40), mload(add(state, STATE_LINEARISED_POLYNOMIAL_X)))
|
||||
mstore(add(mPtr, 0x60), mload(add(state, STATE_LINEARISED_POLYNOMIAL_Y)))
|
||||
calldatacopy(add(mPtr, 0x80), add(aproof, PROOF_L_COM_X), 0xc0)
|
||||
mstore(add(mPtr,0x140), VK_S1_COM_X)
|
||||
mstore(add(mPtr,0x160), VK_S1_COM_Y)
|
||||
mstore(add(mPtr,0x180), VK_S2_COM_X)
|
||||
mstore(add(mPtr,0x1a0), VK_S2_COM_Y)
|
||||
|
||||
mstore(add(mPtr, 0x140), VK_S1_COM_X)
|
||||
mstore(add(mPtr, 0x160), VK_S1_COM_Y)
|
||||
mstore(add(mPtr, 0x180), VK_S2_COM_X)
|
||||
mstore(add(mPtr, 0x1a0), VK_S2_COM_Y)
|
||||
|
||||
let offset := 0x1c0
|
||||
|
||||
mstore(add(mPtr,offset), VK_QCP_0_X)
|
||||
mstore(add(mPtr,add(offset, 0x20)), VK_QCP_0_Y)
|
||||
|
||||
mstore(add(mPtr, offset), VK_QCP_0_X)
|
||||
mstore(add(mPtr, add(offset, 0x20)), VK_QCP_0_Y)
|
||||
offset := add(offset, 0x40)
|
||||
mstore(add(mPtr, offset), mload(add(state, STATE_OPENING_LINEARISED_POLYNOMIAL_ZETA)))
|
||||
mstore(add(mPtr, add(offset, 0x20)), calldataload(add(aproof, PROOF_L_AT_ZETA)))
|
||||
@@ -1002,18 +994,23 @@ contract PlonkVerifierForDataAggregation {
|
||||
|
||||
let _mPtr := add(mPtr, add(offset, 0xc0))
|
||||
|
||||
|
||||
let _poqaz := add(aproof, PROOF_OPENING_QCP_AT_ZETA)
|
||||
calldatacopy(_mPtr, _poqaz, mul(VK_NB_CUSTOM_GATES, 0x20))
|
||||
_mPtr := add(_mPtr, mul(VK_NB_CUSTOM_GATES, 0x20))
|
||||
|
||||
|
||||
mstore(_mPtr, calldataload(add(aproof, PROOF_GRAND_PRODUCT_AT_ZETA_OMEGA)))
|
||||
|
||||
let start_input := 0x1b // 00.."gamma"
|
||||
let size_input := add(0x14, mul(VK_NB_CUSTOM_GATES,3)) // number of 32bytes elmts = 0x14 (zeta+3*6 for the digests+openings) + 3*VK_NB_CUSTOM_GATES (for the commitments of the selectors) + 1 (opening of Z at ζω)
|
||||
let size_input := add(0x14, mul(VK_NB_CUSTOM_GATES, 3)) // number of 32bytes elmts = 0x14 (zeta+3*6 for the digests+openings) + 3*VK_NB_CUSTOM_GATES (for the commitments of the selectors) + 1 (opening of Z at ζω)
|
||||
size_input := add(0x5, mul(size_input, 0x20)) // size in bytes: 15*32 bytes + 5 bytes for gamma
|
||||
let check_staticcall := staticcall(gas(), SHA2, add(mPtr,start_input), size_input, add(state, STATE_GAMMA_KZG), 0x20)
|
||||
let check_staticcall := staticcall(
|
||||
gas(),
|
||||
SHA2,
|
||||
add(mPtr, start_input),
|
||||
size_input,
|
||||
add(state, STATE_GAMMA_KZG),
|
||||
0x20
|
||||
)
|
||||
if iszero(check_staticcall) {
|
||||
error_verify()
|
||||
}
|
||||
@@ -1021,7 +1018,6 @@ contract PlonkVerifierForDataAggregation {
|
||||
}
|
||||
|
||||
function compute_commitment_linearised_polynomial_ec(aproof, s1, s2) {
|
||||
|
||||
let state := mload(0x40)
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
|
||||
@@ -1066,7 +1062,6 @@ contract PlonkVerifierForDataAggregation {
|
||||
add(mPtr, 0x40)
|
||||
)
|
||||
|
||||
|
||||
let qcp_opening_at_zeta := add(aproof, PROOF_OPENING_QCP_AT_ZETA)
|
||||
let bsb_commitments := add(aproof, PROOF_BSB_COMMITMENTS)
|
||||
for {
|
||||
@@ -1085,7 +1080,6 @@ contract PlonkVerifierForDataAggregation {
|
||||
qcp_opening_at_zeta := add(qcp_opening_at_zeta, 0x20)
|
||||
bsb_commitments := add(bsb_commitments, 0x40)
|
||||
}
|
||||
|
||||
|
||||
mstore(mPtr, VK_S3_COM_X)
|
||||
mstore(add(mPtr, 0x20), VK_S3_COM_Y)
|
||||
@@ -1096,10 +1090,11 @@ contract PlonkVerifierForDataAggregation {
|
||||
point_acc_mul(add(state, STATE_LINEARISED_POLYNOMIAL_X), mPtr, s2, add(mPtr, 0x40))
|
||||
|
||||
point_add(
|
||||
add(state, STATE_LINEARISED_POLYNOMIAL_X),
|
||||
add(state, STATE_LINEARISED_POLYNOMIAL_X),
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
mPtr)
|
||||
add(state, STATE_LINEARISED_POLYNOMIAL_X),
|
||||
add(state, STATE_LINEARISED_POLYNOMIAL_X),
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
mPtr
|
||||
)
|
||||
}
|
||||
|
||||
/// @notice Compute the commitment to the linearized polynomial equal to
|
||||
@@ -1166,10 +1161,25 @@ contract PlonkVerifierForDataAggregation {
|
||||
let mPtr := add(mload(0x40), STATE_LAST_MEM)
|
||||
let zeta_power_n_plus_two := pow(mload(add(state, STATE_ZETA)), n_plus_two, mPtr)
|
||||
point_mul_calldata(add(state, STATE_FOLDED_H_X), add(aproof, PROOF_H_2_COM_X), zeta_power_n_plus_two, mPtr)
|
||||
point_add_calldata(add(state, STATE_FOLDED_H_X), add(state, STATE_FOLDED_H_X), add(aproof, PROOF_H_1_COM_X), mPtr)
|
||||
point_add_calldata(
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
add(aproof, PROOF_H_1_COM_X),
|
||||
mPtr
|
||||
)
|
||||
point_mul(add(state, STATE_FOLDED_H_X), add(state, STATE_FOLDED_H_X), zeta_power_n_plus_two, mPtr)
|
||||
point_add_calldata(add(state, STATE_FOLDED_H_X), add(state, STATE_FOLDED_H_X), add(aproof, PROOF_H_0_COM_X), mPtr)
|
||||
point_mul(add(state, STATE_FOLDED_H_X), add(state, STATE_FOLDED_H_X), mload(add(state, STATE_ZETA_POWER_N_MINUS_ONE)), mPtr)
|
||||
point_add_calldata(
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
add(aproof, PROOF_H_0_COM_X),
|
||||
mPtr
|
||||
)
|
||||
point_mul(
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
add(state, STATE_FOLDED_H_X),
|
||||
mload(add(state, STATE_ZETA_POWER_N_MINUS_ONE)),
|
||||
mPtr
|
||||
)
|
||||
let folded_h_y := mload(add(state, STATE_FOLDED_H_Y))
|
||||
folded_h_y := sub(P_MOD, folded_h_y)
|
||||
mstore(add(state, STATE_FOLDED_H_Y), folded_h_y)
|
||||
@@ -1179,7 +1189,6 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// - [ PI(ζ) - α²*L₁(ζ) + α(l(ζ)+β*s1(ζ)+γ)(r(ζ)+β*s2(ζ)+γ)(o(ζ)+γ)*z(ωζ) ]
|
||||
/// @param aproof pointer to the proof
|
||||
function compute_opening_linearised_polynomial(aproof) {
|
||||
|
||||
let state := mload(0x40)
|
||||
|
||||
// (l(ζ)+β*s1(ζ)+γ)
|
||||
@@ -1215,7 +1224,7 @@ contract PlonkVerifierForDataAggregation {
|
||||
}
|
||||
|
||||
// BEGINNING utils math functions -------------------------------------------------
|
||||
|
||||
|
||||
/// @param dst pointer storing the result
|
||||
/// @param p pointer to the first point
|
||||
/// @param q pointer to the second point
|
||||
@@ -1225,7 +1234,7 @@ contract PlonkVerifierForDataAggregation {
|
||||
mstore(add(mPtr, 0x20), mload(add(p, 0x20)))
|
||||
mstore(add(mPtr, 0x40), mload(q))
|
||||
mstore(add(mPtr, 0x60), mload(add(q, 0x20)))
|
||||
let l_success := staticcall(gas(),EC_ADD,mPtr,0x80,dst,0x40)
|
||||
let l_success := staticcall(gas(), EC_ADD, mPtr, 0x80, dst, 0x40)
|
||||
if iszero(l_success) {
|
||||
error_ec_op()
|
||||
}
|
||||
@@ -1250,11 +1259,11 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// @param src pointer to a point on Bn254(𝔽_p)
|
||||
/// @param s scalar
|
||||
/// @param mPtr free memory
|
||||
function point_mul(dst,src,s, mPtr) {
|
||||
mstore(mPtr,mload(src))
|
||||
mstore(add(mPtr,0x20),mload(add(src,0x20)))
|
||||
mstore(add(mPtr,0x40),s)
|
||||
let l_success := staticcall(gas(),EC_MUL,mPtr,0x60,dst,0x40)
|
||||
function point_mul(dst, src, s, mPtr) {
|
||||
mstore(mPtr, mload(src))
|
||||
mstore(add(mPtr, 0x20), mload(add(src, 0x20)))
|
||||
mstore(add(mPtr, 0x40), s)
|
||||
let l_success := staticcall(gas(), EC_MUL, mPtr, 0x60, dst, 0x40)
|
||||
if iszero(l_success) {
|
||||
error_ec_op()
|
||||
}
|
||||
@@ -1279,14 +1288,14 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// @param src pointer to the point to multiply and add
|
||||
/// @param s scalar
|
||||
/// @param mPtr free memory
|
||||
function point_acc_mul(dst,src,s, mPtr) {
|
||||
mstore(mPtr,mload(src))
|
||||
mstore(add(mPtr,0x20),mload(add(src,0x20)))
|
||||
mstore(add(mPtr,0x40),s)
|
||||
let l_success := staticcall(gas(),7,mPtr,0x60,mPtr,0x40)
|
||||
mstore(add(mPtr,0x40),mload(dst))
|
||||
mstore(add(mPtr,0x60),mload(add(dst,0x20)))
|
||||
l_success := and(l_success, staticcall(gas(),EC_ADD,mPtr,0x80,dst, 0x40))
|
||||
function point_acc_mul(dst, src, s, mPtr) {
|
||||
mstore(mPtr, mload(src))
|
||||
mstore(add(mPtr, 0x20), mload(add(src, 0x20)))
|
||||
mstore(add(mPtr, 0x40), s)
|
||||
let l_success := staticcall(gas(), 7, mPtr, 0x60, mPtr, 0x40)
|
||||
mstore(add(mPtr, 0x40), mload(dst))
|
||||
mstore(add(mPtr, 0x60), mload(add(dst, 0x20)))
|
||||
l_success := and(l_success, staticcall(gas(), EC_ADD, mPtr, 0x80, dst, 0x40))
|
||||
if iszero(l_success) {
|
||||
error_ec_op()
|
||||
}
|
||||
@@ -1315,7 +1324,7 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// @param src pointer to the scalar to multiply and add (on calldata)
|
||||
/// @param s scalar
|
||||
function fr_acc_mul_calldata(dst, src, s) {
|
||||
let tmp := mulmod(calldataload(src), s, R_MOD)
|
||||
let tmp := mulmod(calldataload(src), s, R_MOD)
|
||||
mstore(dst, addmod(mload(dst), tmp, R_MOD))
|
||||
}
|
||||
|
||||
@@ -1323,16 +1332,16 @@ contract PlonkVerifierForDataAggregation {
|
||||
/// @param e exponent
|
||||
/// @param mPtr free memory
|
||||
/// @return res x ** e mod r
|
||||
function pow(x, e, mPtr)->res {
|
||||
function pow(x, e, mPtr) -> res {
|
||||
mstore(mPtr, 0x20)
|
||||
mstore(add(mPtr, 0x20), 0x20)
|
||||
mstore(add(mPtr, 0x40), 0x20)
|
||||
mstore(add(mPtr, 0x60), x)
|
||||
mstore(add(mPtr, 0x80), e)
|
||||
mstore(add(mPtr, 0xa0), R_MOD)
|
||||
let check_staticcall := staticcall(gas(),MOD_EXP,mPtr,0xc0,mPtr,0x20)
|
||||
let check_staticcall := staticcall(gas(), MOD_EXP, mPtr, 0xc0, mPtr, 0x20)
|
||||
if eq(check_staticcall, 0) {
|
||||
error_mod_exp()
|
||||
error_mod_exp()
|
||||
}
|
||||
res := mload(mPtr)
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ import { loadFixture, time as networkTime } from "@nomicfoundation/hardhat-netwo
|
||||
import { expect } from "chai";
|
||||
import { config, ethers, upgrades } from "hardhat";
|
||||
import { HardhatNetworkHDAccountsConfig } from "hardhat/types";
|
||||
import { BaseContract, Contract, HDNodeWallet, Transaction, Wallet, ZeroAddress } from "ethers";
|
||||
import { CallForwardingProxy, TestLineaRollup, TestLineaRollupV5 } from "../../../typechain-types";
|
||||
import { BaseContract, Contract, HDNodeWallet, Transaction, Wallet } from "ethers";
|
||||
import { CallForwardingProxy, TestLineaRollup } from "../../../typechain-types";
|
||||
import calldataAggregatedProof1To155 from "../_testData/compressedData/aggregatedProof-1-155.json";
|
||||
import blobAggregatedProof1To155 from "../_testData/compressedDataEip4844/aggregatedProof-1-155.json";
|
||||
import blobMultipleAggregatedProof1To81 from "../_testData/compressedDataEip4844/multipleProofs/aggregatedProof-1-81.json";
|
||||
@@ -32,20 +32,9 @@ import {
|
||||
CALLDATA_SUBMISSION_PAUSE_TYPE,
|
||||
BLOB_SUBMISSION_PAUSE_TYPE,
|
||||
FINALIZATION_PAUSE_TYPE,
|
||||
PAUSE_ALL_ROLE,
|
||||
DEFAULT_ADMIN_ROLE,
|
||||
UNPAUSE_ALL_ROLE,
|
||||
PAUSE_BLOB_SUBMISSION_ROLE,
|
||||
UNPAUSE_BLOB_SUBMISSION_ROLE,
|
||||
PAUSE_FINALIZATION_ROLE,
|
||||
UNPAUSE_FINALIZATION_ROLE,
|
||||
DEFAULT_LAST_FINALIZED_TIMESTAMP,
|
||||
SIX_MONTHS_IN_SECONDS,
|
||||
USED_RATE_LIMIT_RESETTER_ROLE,
|
||||
PAUSE_L1_L2_ROLE,
|
||||
PAUSE_L2_L1_ROLE,
|
||||
UNPAUSE_L1_L2_ROLE,
|
||||
UNPAUSE_L2_L1_ROLE,
|
||||
LINEA_ROLLUP_INITIALIZE_SIGNATURE,
|
||||
} from "../common/constants";
|
||||
import { deployUpgradableFromFactory } from "../common/deployment";
|
||||
@@ -66,9 +55,7 @@ import {
|
||||
generateParentShnarfData,
|
||||
generateBlobDataSubmission,
|
||||
generateBlobParentShnarfData,
|
||||
convertStringToPaddedHexBytes,
|
||||
calculateLastFinalizedState,
|
||||
expectEvents,
|
||||
expectEventDirectFromReceiptData,
|
||||
generateBlobDataSubmissionFromFile,
|
||||
} from "../common/helpers";
|
||||
@@ -88,7 +75,6 @@ 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;
|
||||
@@ -164,7 +150,7 @@ describe("Linea Rollup contract", () => {
|
||||
|
||||
before(async () => {
|
||||
[admin, securityCouncil, operator, nonAuthorizedAccount] = await ethers.getSigners();
|
||||
const securityCouncilAddress = securityCouncil.address;
|
||||
const securityCouncilAddress = await securityCouncil.getAddress();
|
||||
|
||||
roleAddresses = generateRoleAssignments(LINEA_ROLLUP_ROLES, securityCouncilAddress, [
|
||||
{
|
||||
@@ -2257,6 +2243,69 @@ describe("Linea Rollup contract", () => {
|
||||
const args = [OPERATOR_ROLE, operator.address, operator.address];
|
||||
expectEvent(lineaRollup, renounceCall, "RoleRevoked", args);
|
||||
});
|
||||
|
||||
it("Should fail to accept ETH on the CallForwardingProxy receive function", async () => {
|
||||
await deployCallForwardingProxy(await lineaRollup.getAddress());
|
||||
const forwardingProxyAddress = await callForwardingProxy.getAddress();
|
||||
|
||||
const tx = {
|
||||
to: forwardingProxyAddress,
|
||||
value: ethers.parseEther("0.1"),
|
||||
};
|
||||
|
||||
await expectRevertWithReason(admin.sendTransaction(tx), "ETH not accepted");
|
||||
});
|
||||
|
||||
it("Should be able to submit blobs and finalize via callforwarding proxy", async () => {
|
||||
await deployCallForwardingProxy(await lineaRollup.getAddress());
|
||||
const forwardingProxyAddress = await callForwardingProxy.getAddress();
|
||||
|
||||
expect(await lineaRollup.currentL2BlockNumber()).to.equal(0);
|
||||
|
||||
// Deploy new LineaRollup implementation
|
||||
const newLineaRollupFactory = await ethers.getContractFactory(
|
||||
"src/_testing/unit/rollup/TestLineaRollup.sol:TestLineaRollup",
|
||||
);
|
||||
const newLineaRollup = await upgrades.upgradeProxy(lineaRollup, newLineaRollupFactory, {
|
||||
unsafeAllowRenames: true,
|
||||
});
|
||||
|
||||
const upgradedContract = await newLineaRollup.waitForDeployment();
|
||||
|
||||
await upgradedContract.reinitializeLineaRollupV6(
|
||||
[],
|
||||
LINEA_ROLLUP_PAUSE_TYPES_ROLES,
|
||||
LINEA_ROLLUP_UNPAUSE_TYPES_ROLES,
|
||||
forwardingProxyAddress,
|
||||
);
|
||||
|
||||
// Grants deployed callforwarding proxy as operator
|
||||
await networkTime.increase(SIX_MONTHS_IN_SECONDS);
|
||||
await expectEvent(
|
||||
upgradedContract,
|
||||
upgradedContract.setFallbackOperator(0n, HASH_ZERO, DEFAULT_LAST_FINALIZED_TIMESTAMP),
|
||||
"FallbackOperatorRoleGranted",
|
||||
[admin.address, forwardingProxyAddress],
|
||||
);
|
||||
|
||||
// Submit 2 blobs
|
||||
await sendBlobTransactionViaCallForwarder(upgradedContract, 0, 2, forwardingProxyAddress);
|
||||
// Submit another 2 blobs
|
||||
await sendBlobTransactionViaCallForwarder(upgradedContract, 2, 4, forwardingProxyAddress);
|
||||
|
||||
// Finalize 4 blobs
|
||||
await expectSuccessfulFinalizeViaCallForwarder(
|
||||
blobAggregatedProof1To155,
|
||||
4,
|
||||
fourthCompressedDataContent.finalStateRootHash,
|
||||
generateBlobParentShnarfData,
|
||||
false,
|
||||
HASH_ZERO,
|
||||
0n,
|
||||
forwardingProxyAddress,
|
||||
upgradedContract,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
async function sendBlobTransaction(startIndex: number, finalIndex: number, isMultiple: boolean = false) {
|
||||
@@ -2597,322 +2646,4 @@ describe("Linea Rollup contract", () => {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
describe("LineaRollup Upgradeable Tests", () => {
|
||||
let newRoleAddresses: { addressWithRole: string; role: string }[];
|
||||
|
||||
async function deployLineaRollupFixture() {
|
||||
const plonkVerifierFactory = await ethers.getContractFactory("TestPlonkVerifierForDataAggregation");
|
||||
const plonkVerifier = await plonkVerifierFactory.deploy();
|
||||
await plonkVerifier.waitForDeployment();
|
||||
|
||||
verifier = await plonkVerifier.getAddress();
|
||||
|
||||
const lineaRollup = (await deployUpgradableFromFactory(
|
||||
"src/_testing/unit/rollup/TestLineaRollupV5.sol:TestLineaRollupV5",
|
||||
[
|
||||
parentStateRootHash,
|
||||
0,
|
||||
verifier,
|
||||
securityCouncil.address,
|
||||
[operator.address],
|
||||
ONE_DAY_IN_SECONDS,
|
||||
INITIAL_WITHDRAW_LIMIT,
|
||||
DEFAULT_LAST_FINALIZED_TIMESTAMP,
|
||||
],
|
||||
{
|
||||
initializer: "initialize(bytes32,uint256,address,address,address[],uint256,uint256,uint256)",
|
||||
unsafeAllow: ["constructor"],
|
||||
},
|
||||
)) as unknown as TestLineaRollupV5;
|
||||
|
||||
return lineaRollup;
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
const securityCouncilAddress = securityCouncil.address;
|
||||
|
||||
newRoleAddresses = [
|
||||
{ addressWithRole: securityCouncilAddress, role: USED_RATE_LIMIT_RESETTER_ROLE },
|
||||
{ addressWithRole: securityCouncilAddress, role: VERIFIER_UNSETTER_ROLE },
|
||||
{ addressWithRole: securityCouncilAddress, role: PAUSE_ALL_ROLE },
|
||||
{ addressWithRole: securityCouncilAddress, role: PAUSE_L1_L2_ROLE },
|
||||
{ addressWithRole: securityCouncilAddress, role: PAUSE_L2_L1_ROLE },
|
||||
{ addressWithRole: securityCouncilAddress, role: UNPAUSE_ALL_ROLE },
|
||||
{ addressWithRole: securityCouncilAddress, role: UNPAUSE_L1_L2_ROLE },
|
||||
{ addressWithRole: securityCouncilAddress, role: UNPAUSE_L2_L1_ROLE },
|
||||
{ addressWithRole: securityCouncilAddress, role: PAUSE_BLOB_SUBMISSION_ROLE },
|
||||
{ addressWithRole: securityCouncilAddress, role: UNPAUSE_BLOB_SUBMISSION_ROLE },
|
||||
{ addressWithRole: securityCouncilAddress, role: PAUSE_FINALIZATION_ROLE },
|
||||
{ addressWithRole: securityCouncilAddress, role: UNPAUSE_FINALIZATION_ROLE },
|
||||
];
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
lineaRollupV5 = await loadFixture(deployLineaRollupFixture);
|
||||
|
||||
// we need to set a non-zero value for the genesis shnarf else it will break on blob submission.
|
||||
const { parentShnarf, snarkHash, finalStateRootHash, dataEvaluationPoint, dataEvaluationClaim } =
|
||||
generateParentShnarfData(0);
|
||||
const genesisShnarf = generateKeccak256(
|
||||
["bytes32", "bytes32", "bytes32", "bytes32", "bytes32"],
|
||||
[parentShnarf, snarkHash, finalStateRootHash, dataEvaluationPoint, dataEvaluationClaim],
|
||||
);
|
||||
|
||||
await lineaRollupV5.setDefaultShnarfExistValue(genesisShnarf);
|
||||
});
|
||||
|
||||
it("Should revert if fallback operator has address zero", async () => {
|
||||
expect(await lineaRollupV5.currentL2BlockNumber()).to.equal(0);
|
||||
|
||||
// Deploy new implementation
|
||||
const newLineaRollupFactory = await ethers.getContractFactory(
|
||||
"src/_testing/unit/rollup/TestLineaRollup.sol:TestLineaRollup",
|
||||
);
|
||||
const newLineaRollup = await upgrades.upgradeProxy(lineaRollupV5, newLineaRollupFactory, {
|
||||
unsafeAllowRenames: true,
|
||||
});
|
||||
const upgradedContract = await newLineaRollup.waitForDeployment();
|
||||
|
||||
expectRevertWithCustomError(
|
||||
upgradedContract,
|
||||
upgradedContract.reinitializeLineaRollupV6(
|
||||
newRoleAddresses,
|
||||
LINEA_ROLLUP_PAUSE_TYPES_ROLES,
|
||||
LINEA_ROLLUP_UNPAUSE_TYPES_ROLES,
|
||||
ADDRESS_ZERO,
|
||||
),
|
||||
"ZeroAddressNotAllowed",
|
||||
);
|
||||
});
|
||||
|
||||
it("Should fail to accept ETH on the CallForwardingProxy receive function", async () => {
|
||||
await deployCallForwardingProxy(await lineaRollupV5.getAddress());
|
||||
const forwardingProxyAddress = await callForwardingProxy.getAddress();
|
||||
|
||||
const tx = {
|
||||
to: forwardingProxyAddress,
|
||||
value: ethers.parseEther("0.1"),
|
||||
};
|
||||
|
||||
await expectRevertWithReason(admin.sendTransaction(tx), "ETH not accepted");
|
||||
});
|
||||
|
||||
it("Should be able to submit blobs and finalize via callforwarding proxy", async () => {
|
||||
// Deploy callforwarding proxy
|
||||
await deployCallForwardingProxy(await lineaRollupV5.getAddress());
|
||||
const forwardingProxyAddress = await callForwardingProxy.getAddress();
|
||||
|
||||
expect(await lineaRollupV5.currentL2BlockNumber()).to.equal(0);
|
||||
|
||||
// Deploy new LineaRollup implementation
|
||||
const newLineaRollupFactory = await ethers.getContractFactory(
|
||||
"src/_testing/unit/rollup/TestLineaRollup.sol:TestLineaRollup",
|
||||
);
|
||||
const newLineaRollup = await upgrades.upgradeProxy(lineaRollupV5, newLineaRollupFactory, {
|
||||
unsafeAllowRenames: true,
|
||||
});
|
||||
|
||||
const upgradedContract = await newLineaRollup.waitForDeployment();
|
||||
|
||||
await upgradedContract.reinitializeLineaRollupV6(
|
||||
newRoleAddresses,
|
||||
LINEA_ROLLUP_PAUSE_TYPES_ROLES,
|
||||
LINEA_ROLLUP_UNPAUSE_TYPES_ROLES,
|
||||
forwardingProxyAddress,
|
||||
);
|
||||
|
||||
// Grants deployed callforwarding proxy as operator
|
||||
await networkTime.increase(SIX_MONTHS_IN_SECONDS);
|
||||
await expectEvent(
|
||||
upgradedContract,
|
||||
upgradedContract.setFallbackOperator(0n, HASH_ZERO, DEFAULT_LAST_FINALIZED_TIMESTAMP),
|
||||
"FallbackOperatorRoleGranted",
|
||||
[admin.address, forwardingProxyAddress],
|
||||
);
|
||||
|
||||
// Submit 2 blobs
|
||||
await sendBlobTransactionViaCallForwarder(upgradedContract, 0, 2, forwardingProxyAddress);
|
||||
// Submit another 2 blobs
|
||||
await sendBlobTransactionViaCallForwarder(upgradedContract, 2, 4, forwardingProxyAddress);
|
||||
|
||||
// Finalize 4 blobs
|
||||
await expectSuccessfulFinalizeViaCallForwarder(
|
||||
blobAggregatedProof1To155,
|
||||
4,
|
||||
fourthCompressedDataContent.finalStateRootHash,
|
||||
generateBlobParentShnarfData,
|
||||
false,
|
||||
HASH_ZERO,
|
||||
0n,
|
||||
forwardingProxyAddress,
|
||||
upgradedContract,
|
||||
);
|
||||
});
|
||||
|
||||
it("Should deploy and upgrade the LineaRollup contract expecting LineaRollupVersionChanged", async () => {
|
||||
expect(await lineaRollupV5.currentL2BlockNumber()).to.equal(0);
|
||||
|
||||
// Deploy new implementation
|
||||
const newLineaRollupFactory = await ethers.getContractFactory("src/rollup/LineaRollup.sol:LineaRollup");
|
||||
const newLineaRollup = await upgrades.upgradeProxy(lineaRollupV5, newLineaRollupFactory, {
|
||||
unsafeAllowRenames: true,
|
||||
});
|
||||
const upgradedContract = await newLineaRollup.waitForDeployment();
|
||||
|
||||
const upgradeCall = upgradedContract.reinitializeLineaRollupV6(
|
||||
newRoleAddresses,
|
||||
LINEA_ROLLUP_PAUSE_TYPES_ROLES,
|
||||
LINEA_ROLLUP_UNPAUSE_TYPES_ROLES,
|
||||
fallbackoperatorAddress,
|
||||
);
|
||||
|
||||
const expectedVersion5Bytes8 = convertStringToPaddedHexBytes("5.0", 8);
|
||||
const expectedVersion6Bytes8 = convertStringToPaddedHexBytes("6.0", 8);
|
||||
|
||||
await expectEvent(upgradedContract, upgradeCall, "LineaRollupVersionChanged", [
|
||||
expectedVersion5Bytes8,
|
||||
expectedVersion6Bytes8,
|
||||
]);
|
||||
});
|
||||
|
||||
it("Should upgrade the LineaRollup contract expecting FallbackOperatorAddressSet", async () => {
|
||||
expect(await lineaRollupV5.currentL2BlockNumber()).to.equal(0);
|
||||
|
||||
// Deploy new implementation
|
||||
const newLineaRollupFactory = await ethers.getContractFactory("src/rollup/LineaRollup.sol:LineaRollup");
|
||||
const newLineaRollup = await upgrades.upgradeProxy(lineaRollupV5, newLineaRollupFactory, {
|
||||
unsafeAllowRenames: true,
|
||||
});
|
||||
const upgradedContract = await newLineaRollup.waitForDeployment();
|
||||
const upgradeCall = upgradedContract.reinitializeLineaRollupV6(
|
||||
newRoleAddresses,
|
||||
LINEA_ROLLUP_PAUSE_TYPES_ROLES,
|
||||
LINEA_ROLLUP_UNPAUSE_TYPES_ROLES,
|
||||
fallbackoperatorAddress,
|
||||
);
|
||||
|
||||
await expectEvent(upgradedContract, upgradeCall, "FallbackOperatorAddressSet", [
|
||||
admin.address,
|
||||
fallbackoperatorAddress,
|
||||
]);
|
||||
});
|
||||
|
||||
it("Should not be able to call reinitializeLineaRollupV6 when upgraded.", async () => {
|
||||
expect(await lineaRollupV5.currentL2BlockNumber()).to.equal(0);
|
||||
|
||||
// Deploy new implementation
|
||||
const newLineaRollupFactory = await ethers.getContractFactory("src/rollup/LineaRollup.sol:LineaRollup");
|
||||
const newLineaRollup = await upgrades.upgradeProxy(lineaRollupV5, newLineaRollupFactory, {
|
||||
unsafeAllowRenames: true,
|
||||
});
|
||||
const upgradedContract = await newLineaRollup.waitForDeployment();
|
||||
await upgradedContract.reinitializeLineaRollupV6(
|
||||
newRoleAddresses,
|
||||
LINEA_ROLLUP_PAUSE_TYPES_ROLES,
|
||||
LINEA_ROLLUP_UNPAUSE_TYPES_ROLES,
|
||||
fallbackoperatorAddress,
|
||||
);
|
||||
|
||||
const secondCall = upgradedContract.reinitializeLineaRollupV6(
|
||||
newRoleAddresses,
|
||||
LINEA_ROLLUP_PAUSE_TYPES_ROLES,
|
||||
LINEA_ROLLUP_UNPAUSE_TYPES_ROLES,
|
||||
fallbackoperatorAddress,
|
||||
);
|
||||
|
||||
await expectRevertWithReason(secondCall, "Initializable: contract is already initialized");
|
||||
});
|
||||
|
||||
it("Should revert with ZeroAddressNotAllowed when addressWithRole is zero address in reinitializeLineaRollupV6", async () => {
|
||||
// Deploy new implementation
|
||||
const newLineaRollupFactory = await ethers.getContractFactory("src/rollup/LineaRollup.sol:LineaRollup");
|
||||
const newLineaRollup = await upgrades.upgradeProxy(lineaRollupV5, newLineaRollupFactory, {
|
||||
unsafeAllowRenames: true,
|
||||
});
|
||||
const upgradedContract = await newLineaRollup.waitForDeployment();
|
||||
const roleAddresses = [{ addressWithRole: ZeroAddress, role: DEFAULT_ADMIN_ROLE }, ...newRoleAddresses.slice(1)];
|
||||
|
||||
await expectRevertWithCustomError(
|
||||
upgradedContract,
|
||||
upgradedContract.reinitializeLineaRollupV6(
|
||||
roleAddresses,
|
||||
LINEA_ROLLUP_PAUSE_TYPES_ROLES,
|
||||
LINEA_ROLLUP_UNPAUSE_TYPES_ROLES,
|
||||
fallbackoperatorAddress,
|
||||
),
|
||||
"ZeroAddressNotAllowed",
|
||||
);
|
||||
});
|
||||
|
||||
it("Should set all permissions", async () => {
|
||||
// Deploy new implementation
|
||||
const newLineaRollupFactory = await ethers.getContractFactory("src/rollup/LineaRollup.sol:LineaRollup");
|
||||
const newLineaRollup = await upgrades.upgradeProxy(lineaRollupV5, newLineaRollupFactory, {
|
||||
unsafeAllowRenames: true,
|
||||
});
|
||||
const upgradedContract = await newLineaRollup.waitForDeployment();
|
||||
|
||||
await upgradedContract.reinitializeLineaRollupV6(
|
||||
newRoleAddresses,
|
||||
LINEA_ROLLUP_PAUSE_TYPES_ROLES,
|
||||
LINEA_ROLLUP_UNPAUSE_TYPES_ROLES,
|
||||
fallbackoperatorAddress,
|
||||
);
|
||||
|
||||
for (const { role, addressWithRole } of newRoleAddresses) {
|
||||
expect(await upgradedContract.hasRole(role, addressWithRole)).to.be.true;
|
||||
}
|
||||
});
|
||||
|
||||
it("Should set all pause types and unpause types in mappings and emit events", async () => {
|
||||
// Deploy new implementation
|
||||
const newLineaRollupFactory = await ethers.getContractFactory("src/rollup/LineaRollup.sol:LineaRollup");
|
||||
const newLineaRollup = await upgrades.upgradeProxy(lineaRollupV5, newLineaRollupFactory, {
|
||||
unsafeAllowRenames: true,
|
||||
});
|
||||
const upgradedContract = await newLineaRollup.waitForDeployment();
|
||||
|
||||
const reinitializePromise = upgradedContract.reinitializeLineaRollupV6(
|
||||
newRoleAddresses,
|
||||
LINEA_ROLLUP_PAUSE_TYPES_ROLES,
|
||||
LINEA_ROLLUP_UNPAUSE_TYPES_ROLES,
|
||||
fallbackoperatorAddress,
|
||||
);
|
||||
|
||||
await Promise.all([
|
||||
expectEvents(
|
||||
upgradedContract,
|
||||
reinitializePromise,
|
||||
LINEA_ROLLUP_PAUSE_TYPES_ROLES.map(({ pauseType, role }) => ({
|
||||
name: "PauseTypeRoleSet",
|
||||
args: [pauseType, role],
|
||||
})),
|
||||
),
|
||||
expectEvents(
|
||||
upgradedContract,
|
||||
reinitializePromise,
|
||||
LINEA_ROLLUP_UNPAUSE_TYPES_ROLES.map(({ pauseType, role }) => ({
|
||||
name: "UnPauseTypeRoleSet",
|
||||
args: [pauseType, role],
|
||||
})),
|
||||
),
|
||||
]);
|
||||
|
||||
const pauseTypeRolesMappingSlot = 219;
|
||||
const unpauseTypeRolesMappingSlot = 220;
|
||||
|
||||
for (const { pauseType, role } of LINEA_ROLLUP_PAUSE_TYPES_ROLES) {
|
||||
const slot = generateKeccak256(["uint8", "uint256"], [pauseType, pauseTypeRolesMappingSlot]);
|
||||
const roleInMapping = await ethers.provider.getStorage(upgradedContract.getAddress(), slot);
|
||||
expect(roleInMapping).to.equal(role);
|
||||
}
|
||||
|
||||
for (const { pauseType, role } of LINEA_ROLLUP_UNPAUSE_TYPES_ROLES) {
|
||||
const slot = generateKeccak256(["uint8", "uint256"], [pauseType, unpauseTypeRolesMappingSlot]);
|
||||
const roleInMapping = await ethers.provider.getStorage(upgradedContract.getAddress(), slot);
|
||||
expect(roleInMapping).to.equal(role);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -446,7 +446,7 @@ class L1DependentApp(
|
||||
|
||||
private val genesisStateProvider = GenesisStateProvider(
|
||||
configs.l1.genesisStateRootHash,
|
||||
configs.l1.genesisShnarfV5
|
||||
configs.l1.genesisShnarfV6
|
||||
)
|
||||
|
||||
private val blobCompressionProofCoordinator = run {
|
||||
|
||||
@@ -278,15 +278,15 @@ data class L1Config(
|
||||
val blockTime: Duration = Duration.parse("PT12S"),
|
||||
@ConfigAlias("eth-fee-history-endpoint") private val _ethFeeHistoryEndpoint: URL?,
|
||||
@ConfigAlias("genesis-state-root-hash") private val _genesisStateRootHash: String,
|
||||
@ConfigAlias("genesis-shnarf-v5") private val _genesisShnarfV5: String
|
||||
@ConfigAlias("genesis-shnarf-v6") private val _genesisShnarfV6: String
|
||||
) {
|
||||
val ethFeeHistoryEndpoint: URL
|
||||
get() = _ethFeeHistoryEndpoint ?: rpcEndpoint
|
||||
|
||||
val genesisStateRootHash: ByteArray
|
||||
get() = _genesisStateRootHash.decodeHex().assertIs32Bytes("genesisStateRootHash")
|
||||
val genesisShnarfV5: ByteArray
|
||||
get() = _genesisShnarfV5.decodeHex().assertIs32Bytes("genesisShnarfV5")
|
||||
val genesisShnarfV6: ByteArray
|
||||
get() = _genesisShnarfV6.decodeHex().assertIs32Bytes("genesisShnarfV6")
|
||||
|
||||
val l1QueryBlockTag: BlockParameter.Tag
|
||||
get() = BlockParameter.Tag.fromString(_l1QueryBlockTag)
|
||||
|
||||
@@ -209,7 +209,7 @@ class CoordinatorConfigTest {
|
||||
blockRangeLoopLimit = 500U,
|
||||
_ethFeeHistoryEndpoint = null,
|
||||
_genesisStateRootHash = "0x072ead6777750dc20232d1cee8dc9a395c2d350df4bbaa5096c6f59b214dcecd",
|
||||
_genesisShnarfV5 = "0x47452a1b9ebadfe02bdd02f580fa1eba17680d57eec968a591644d05d78ee84f"
|
||||
_genesisShnarfV6 = "0x47452a1b9ebadfe02bdd02f580fa1eba17680d57eec968a591644d05d78ee84f"
|
||||
)
|
||||
|
||||
private val l2Config = L2Config(
|
||||
|
||||
@@ -110,11 +110,11 @@ finalized-block-tag="latest"
|
||||
# reset this once we know what to do on dev/UAT
|
||||
earliest-block=0
|
||||
genesis-state-root-hash="0x072ead6777750dc20232d1cee8dc9a395c2d350df4bbaa5096c6f59b214dcecd"
|
||||
# shnarf for contract V5
|
||||
# shnarf for contract V6
|
||||
# Keccak256(parentShnarf="0x00...00", snarkHash="0x00...00",
|
||||
# parentStateRootHash="0x072ead6777750dc20232d1cee8dc9a395c2d350df4bbaa5096c6f59b214dcecd",
|
||||
# evaludationClaim="0x00...00", evaludationPoint="0x00...00")
|
||||
genesis-shnarf-v5="0x47452a1b9ebadfe02bdd02f580fa1eba17680d57eec968a591644d05d78ee84f"
|
||||
genesis-shnarf-v6="0x47452a1b9ebadfe02bdd02f580fa1eba17680d57eec968a591644d05d78ee84f"
|
||||
|
||||
[l2]
|
||||
rpc-endpoint="http://sequencer:8545"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.consensys.linea.contract
|
||||
|
||||
import build.linea.contract.LineaRollupV5
|
||||
import build.linea.contract.LineaRollupV6
|
||||
import net.consensys.linea.web3j.AtomicContractEIP1559GasProvider
|
||||
import net.consensys.linea.web3j.EIP1559GasFees
|
||||
import net.consensys.linea.web3j.SmartContractErrors
|
||||
@@ -28,7 +28,7 @@ class LineaRollupAsyncFriendly(
|
||||
private val asyncTransactionManager: AsyncFriendlyTransactionManager,
|
||||
contractGasProvider: ContractGasProvider,
|
||||
private val smartContractErrors: SmartContractErrors
|
||||
) : LineaRollupV5(
|
||||
) : LineaRollupV6(
|
||||
contractAddress,
|
||||
web3j,
|
||||
asyncTransactionManager,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.consensys.linea.contract.l1
|
||||
|
||||
import build.linea.contract.LineaRollupV5
|
||||
import build.linea.contract.LineaRollupV6
|
||||
import net.consensys.linea.contract.AsyncFriendlyTransactionManager
|
||||
import net.consensys.linea.contract.Web3JContractAsyncHelper
|
||||
import org.web3j.abi.datatypes.Function
|
||||
@@ -16,7 +16,7 @@ internal class LineaRollupEnhancedWrapper(
|
||||
asyncTransactionManager: AsyncFriendlyTransactionManager,
|
||||
contractGasProvider: ContractGasProvider,
|
||||
val helper: Web3JContractAsyncHelper
|
||||
) : LineaRollupV5(
|
||||
) : LineaRollupV6(
|
||||
contractAddress,
|
||||
web3j,
|
||||
asyncTransactionManager,
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
package net.consensys.linea.contract.l1
|
||||
|
||||
import build.linea.contract.LineaRollupV5
|
||||
import build.linea.contract.LineaRollupV5.BlobSubmissionData
|
||||
import net.consensys.toBigInteger
|
||||
import net.consensys.zkevm.domain.BlobRecord
|
||||
import net.consensys.zkevm.domain.ProofToFinalize
|
||||
import org.web3j.abi.TypeReference
|
||||
import org.web3j.abi.datatypes.DynamicArray
|
||||
import org.web3j.abi.datatypes.DynamicBytes
|
||||
import org.web3j.abi.datatypes.Function
|
||||
import org.web3j.abi.datatypes.Type
|
||||
import org.web3j.abi.datatypes.generated.Bytes32
|
||||
import org.web3j.abi.datatypes.generated.Uint256
|
||||
import java.math.BigInteger
|
||||
import java.util.Arrays
|
||||
|
||||
internal fun buildSubmitBlobsFunction(
|
||||
blobs: List<BlobRecord>
|
||||
): Function {
|
||||
val blobsSubmissionData = blobs.map { blob ->
|
||||
val blobCompressionProof = blob.blobCompressionProof!!
|
||||
val supportingSubmissionData = LineaRollupV5.SupportingSubmissionDataV2(
|
||||
/*finalStateRootHash*/ blobCompressionProof.finalStateRootHash,
|
||||
/*firstBlockInData*/ blob.startBlockNumber.toBigInteger(),
|
||||
/*finalBlockInData*/ blob.endBlockNumber.toBigInteger(),
|
||||
/*snarkHash*/ blobCompressionProof.snarkHash
|
||||
)
|
||||
|
||||
BlobSubmissionData(
|
||||
/*submissionData*/ supportingSubmissionData,
|
||||
/*dataEvaluationClaim*/ BigInteger(blobCompressionProof.expectedY),
|
||||
/*kzgCommitment*/ blobCompressionProof.commitment,
|
||||
/*kzgProof*/ blobCompressionProof.kzgProofContract
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* function submitBlobs(
|
||||
* BlobSubmissionData[] calldata _blobSubmissionData,
|
||||
* bytes32 _parentShnarf,
|
||||
* bytes32 _finalBlobShnarf
|
||||
* ) external;
|
||||
*/
|
||||
return Function(
|
||||
LineaRollupV5.FUNC_SUBMITBLOBS,
|
||||
Arrays.asList<Type<*>>(
|
||||
DynamicArray(BlobSubmissionData::class.java, blobsSubmissionData),
|
||||
Bytes32(blobs.first().blobCompressionProof!!.prevShnarf),
|
||||
Bytes32(blobs.last().blobCompressionProof!!.expectedShnarf)
|
||||
),
|
||||
emptyList<TypeReference<*>>()
|
||||
)
|
||||
}
|
||||
|
||||
internal fun buildFinalizeBlobsFunction(
|
||||
aggregationProof: ProofToFinalize,
|
||||
aggregationLastBlob: BlobRecord,
|
||||
parentShnarf: ByteArray,
|
||||
parentL1RollingHash: ByteArray,
|
||||
parentL1RollingHashMessageNumber: Long
|
||||
): Function {
|
||||
val aggregationEndBlobInfo = LineaRollupV5.ShnarfData(
|
||||
/*parentShnarf*/ aggregationLastBlob.blobCompressionProof!!.prevShnarf,
|
||||
/*snarkHash*/ aggregationLastBlob.blobCompressionProof!!.snarkHash,
|
||||
/*finalStateRootHash*/ aggregationLastBlob.blobCompressionProof!!.finalStateRootHash,
|
||||
/*dataEvaluationPoint*/ aggregationLastBlob.blobCompressionProof!!.expectedX,
|
||||
/*dataEvaluationClaim*/ aggregationLastBlob.blobCompressionProof!!.expectedY
|
||||
)
|
||||
|
||||
val finalizationData = LineaRollupV5.FinalizationDataV2(
|
||||
/*parentStateRootHash*/ aggregationProof.parentStateRootHash,
|
||||
/*lastFinalizedShnarf*/ parentShnarf,
|
||||
/*finalBlockInData*/ aggregationProof.finalBlockNumber.toBigInteger(),
|
||||
/*shnarfData*/ aggregationEndBlobInfo,
|
||||
/*lastFinalizedTimestamp*/ aggregationProof.parentAggregationLastBlockTimestamp.epochSeconds.toBigInteger(),
|
||||
/*finalTimestamp*/ aggregationProof.finalTimestamp.epochSeconds.toBigInteger(),
|
||||
/*lastFinalizedL1RollingHash*/ parentL1RollingHash,
|
||||
/*l1RollingHash*/ aggregationProof.l1RollingHash,
|
||||
/*lastFinalizedL1RollingHashMessageNumber*/ parentL1RollingHashMessageNumber.toBigInteger(),
|
||||
/*l1RollingHashMessageNumber*/ aggregationProof.l1RollingHashMessageNumber.toBigInteger(),
|
||||
/*l2MerkleTreesDepth*/ aggregationProof.l2MerkleTreesDepth.toBigInteger(),
|
||||
/*l2MerkleRoots*/ aggregationProof.l2MerkleRoots,
|
||||
/*l2MessagingBlocksOffsets*/ aggregationProof.l2MessagingBlocksOffsets
|
||||
)
|
||||
|
||||
/**
|
||||
* function finalizeBlocksWithProof(
|
||||
* bytes calldata _aggregatedProof,
|
||||
* uint256 _aggregatedVerifierIndex,
|
||||
* FinalizationData calldata _finalizationData
|
||||
* ) external;
|
||||
*/
|
||||
val function = Function(
|
||||
LineaRollupV5.FUNC_FINALIZEBLOCKSWITHPROOF,
|
||||
Arrays.asList<Type<*>>(
|
||||
DynamicBytes(aggregationProof.aggregatedProof),
|
||||
Uint256(aggregationProof.aggregatedVerifierIndex.toLong()),
|
||||
finalizationData
|
||||
),
|
||||
emptyList<TypeReference<*>>()
|
||||
)
|
||||
return function
|
||||
}
|
||||
@@ -20,7 +20,6 @@ internal fun buildSubmitBlobsFunction(
|
||||
blobs: List<BlobRecord>
|
||||
): Function {
|
||||
return when (version) {
|
||||
LineaContractVersion.V5 -> buildSubmitBlobsFunction(blobs)
|
||||
LineaContractVersion.V6 -> buildSubmitBlobsFunctionV6(blobs)
|
||||
}
|
||||
}
|
||||
@@ -63,21 +62,10 @@ fun buildFinalizeBlocksFunction(
|
||||
version: LineaContractVersion,
|
||||
aggregationProof: ProofToFinalize,
|
||||
aggregationLastBlob: BlobRecord,
|
||||
parentShnarf: ByteArray,
|
||||
parentL1RollingHash: ByteArray,
|
||||
parentL1RollingHashMessageNumber: Long
|
||||
): Function {
|
||||
when (version) {
|
||||
LineaContractVersion.V5 -> {
|
||||
return buildFinalizeBlobsFunction(
|
||||
aggregationProof,
|
||||
aggregationLastBlob,
|
||||
parentShnarf,
|
||||
parentL1RollingHash,
|
||||
parentL1RollingHashMessageNumber
|
||||
)
|
||||
}
|
||||
|
||||
LineaContractVersion.V6 -> {
|
||||
return buildFinalizeBlockFunctionV6(
|
||||
aggregationProof,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.consensys.linea.contract.l1
|
||||
|
||||
import build.linea.contract.LineaRollupV5
|
||||
import build.linea.contract.LineaRollupV6
|
||||
import build.linea.contract.l1.Web3JLineaRollupSmartContractClientReadOnly
|
||||
import net.consensys.linea.contract.AsyncFriendlyTransactionManager
|
||||
import net.consensys.linea.contract.Web3JContractAsyncHelper
|
||||
@@ -37,7 +37,7 @@ class Web3JLineaRollupSmartContractClient internal constructor(
|
||||
contractGasProvider,
|
||||
smartContractErrors
|
||||
),
|
||||
private val web3jLineaClient: LineaRollupV5 = LineaRollupEnhancedWrapper(
|
||||
private val web3jLineaClient: LineaRollupV6 = LineaRollupEnhancedWrapper(
|
||||
contractAddress,
|
||||
web3j,
|
||||
asyncTransactionManager,
|
||||
@@ -155,7 +155,6 @@ class Web3JLineaRollupSmartContractClient internal constructor(
|
||||
version,
|
||||
aggregation,
|
||||
aggregationLastBlob,
|
||||
parentShnarf,
|
||||
parentL1RollingHash,
|
||||
parentL1RollingHashMessageNumber
|
||||
)
|
||||
@@ -180,7 +179,6 @@ class Web3JLineaRollupSmartContractClient internal constructor(
|
||||
version,
|
||||
aggregation,
|
||||
aggregationLastBlob,
|
||||
parentShnarf,
|
||||
parentL1RollingHash,
|
||||
parentL1RollingHashMessageNumber
|
||||
)
|
||||
|
||||
@@ -70,7 +70,7 @@ class BlobAndAggregationFinalizationIntTest : CleanDbTestSuiteParallel() {
|
||||
vertx: Vertx,
|
||||
smartContractVersion: LineaContractVersion
|
||||
) {
|
||||
if (listOf(LineaContractVersion.V5, LineaContractVersion.V6).contains(smartContractVersion).not()) {
|
||||
if (listOf(LineaContractVersion.V6).contains(smartContractVersion).not()) {
|
||||
// V6 with prover V3 is soon comming, so we will need to update/extend this test setup
|
||||
throw IllegalArgumentException("unsupported contract version=$smartContractVersion!")
|
||||
}
|
||||
@@ -99,13 +99,13 @@ class BlobAndAggregationFinalizationIntTest : CleanDbTestSuiteParallel() {
|
||||
)
|
||||
aggregationsRepository = AggregationsRepositoryImpl(PostgresAggregationsDao(sqlClient, fakeClock))
|
||||
|
||||
val lineaRollupContractForDataSubmissionV5 = rollupDeploymentResult.rollupOperatorClient
|
||||
val lineaRollupContractForDataSubmissionV6 = rollupDeploymentResult.rollupOperatorClient
|
||||
|
||||
val acceptedBlobEndBlockNumberConsumer = Consumer<ULong> { acceptedBlob = it }
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
val alreadySubmittedBlobFilter = L1ShnarfBasedAlreadySubmittedBlobsFilter(
|
||||
lineaRollup = lineaRollupContractForDataSubmissionV5,
|
||||
lineaRollup = lineaRollupContractForDataSubmissionV6,
|
||||
acceptedBlobEndBlockNumberConsumer = acceptedBlobEndBlockNumberConsumer
|
||||
)
|
||||
val blobSubmittedEventConsumers = mapOf(
|
||||
@@ -123,7 +123,7 @@ class BlobAndAggregationFinalizationIntTest : CleanDbTestSuiteParallel() {
|
||||
),
|
||||
blobsRepository = blobsRepository,
|
||||
aggregationsRepository = aggregationsRepository,
|
||||
lineaSmartContractClient = lineaRollupContractForDataSubmissionV5,
|
||||
lineaSmartContractClient = lineaRollupContractForDataSubmissionV6,
|
||||
alreadySubmittedBlobsFilter = alreadySubmittedBlobFilter,
|
||||
gasPriceCapProvider = FakeGasPriceCapProvider(),
|
||||
blobSubmittedEventDispatcher = EventDispatcher(blobSubmittedEventConsumers),
|
||||
@@ -208,15 +208,6 @@ class BlobAndAggregationFinalizationIntTest : CleanDbTestSuiteParallel() {
|
||||
}.whenException(testContext::failNow)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Timeout(3, timeUnit = TimeUnit.MINUTES)
|
||||
fun `submission works with contract V5`(
|
||||
vertx: Vertx,
|
||||
testContext: VertxTestContext
|
||||
) {
|
||||
testSubmission(vertx, testContext, LineaContractVersion.V5)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Timeout(3, timeUnit = TimeUnit.MINUTES)
|
||||
fun `submission works with contract V6`(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.consensys.zkevm.ethereum.coordination.messageanchoring
|
||||
|
||||
import build.linea.contract.LineaRollupV5
|
||||
import build.linea.contract.LineaRollupV6
|
||||
import build.linea.contract.l1.LineaContractVersion
|
||||
import io.vertx.core.Vertx
|
||||
import io.vertx.junit5.Timeout
|
||||
@@ -37,7 +37,7 @@ class L1EventQuerierIntegrationTest {
|
||||
@BeforeEach
|
||||
fun beforeEach() {
|
||||
val deploymentResult = ContractsManager.get()
|
||||
.deployLineaRollup(contractVersion = LineaContractVersion.V5)
|
||||
.deployLineaRollup(contractVersion = LineaContractVersion.V6)
|
||||
.get()
|
||||
testLineaRollupContractAddress = deploymentResult.contractAddress
|
||||
web3Client = Web3jClientManager.l1Client
|
||||
@@ -82,9 +82,9 @@ class L1EventQuerierIntegrationTest {
|
||||
contract.sendMessage(it.recipient, it.fee, it.calldata, it.value).sendAsync()
|
||||
.thenApply { receipt ->
|
||||
Pair(
|
||||
LineaRollupV5.getMessageSentEventFromLog(
|
||||
LineaRollupV6.getMessageSentEventFromLog(
|
||||
receipt.logs.first { log ->
|
||||
log.topics.contains(EventEncoder.encode(LineaRollupV5.MESSAGESENT_EVENT))
|
||||
log.topics.contains(EventEncoder.encode(LineaRollupV6.MESSAGESENT_EVENT))
|
||||
}
|
||||
),
|
||||
receipt
|
||||
@@ -103,9 +103,9 @@ class L1EventQuerierIntegrationTest {
|
||||
contract.sendMessage(it.recipient, it.fee, it.calldata, it.value).sendAsync()
|
||||
.thenApply { receipt ->
|
||||
Pair(
|
||||
LineaRollupV5.getMessageSentEventFromLog(
|
||||
LineaRollupV6.getMessageSentEventFromLog(
|
||||
receipt.logs.first { log ->
|
||||
log.topics.contains(EventEncoder.encode(LineaRollupV5.MESSAGESENT_EVENT))
|
||||
log.topics.contains(EventEncoder.encode(LineaRollupV6.MESSAGESENT_EVENT))
|
||||
}
|
||||
),
|
||||
receipt
|
||||
@@ -159,10 +159,10 @@ class L1EventQuerierIntegrationTest {
|
||||
contract.sendMessage(it.recipient, it.fee, it.calldata, it.value).sendAsync()
|
||||
.thenApply { receipt ->
|
||||
Pair(
|
||||
LineaRollupV5.staticExtractEventParameters(
|
||||
LineaRollupV5.MESSAGESENT_EVENT,
|
||||
LineaRollupV6.staticExtractEventParameters(
|
||||
LineaRollupV6.MESSAGESENT_EVENT,
|
||||
receipt.logs.first { log ->
|
||||
log.topics.contains(EventEncoder.encode(LineaRollupV5.MESSAGESENT_EVENT))
|
||||
log.topics.contains(EventEncoder.encode(LineaRollupV6.MESSAGESENT_EVENT))
|
||||
}
|
||||
),
|
||||
receipt
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.consensys.zkevm.ethereum.coordination.messageanchoring
|
||||
|
||||
import build.linea.contract.LineaRollupV5
|
||||
import build.linea.contract.LineaRollupV6
|
||||
import build.linea.contract.l1.LineaContractVersion
|
||||
import io.vertx.core.Vertx
|
||||
import io.vertx.junit5.Timeout
|
||||
@@ -49,7 +49,7 @@ class MessageServiceIntegrationTest {
|
||||
|
||||
private fun deployContracts() {
|
||||
val l1RollupDeploymentResult = ContractsManager.get()
|
||||
.deployLineaRollup(contractVersion = LineaContractVersion.V5)
|
||||
.deployLineaRollup(contractVersion = LineaContractVersion.V6)
|
||||
.get()
|
||||
@Suppress("DEPRECATION")
|
||||
l1ContractLegacyClient = l1RollupDeploymentResult.rollupOperatorClientLegacy
|
||||
@@ -202,10 +202,10 @@ class MessageServiceIntegrationTest {
|
||||
.toSafeFuture()
|
||||
.thenApply { transactionReceipt ->
|
||||
log.debug("Message has been sent in block {}", transactionReceipt.blockNumber)
|
||||
val eventValues = LineaRollupV5.staticExtractEventParameters(
|
||||
LineaRollupV5.MESSAGESENT_EVENT,
|
||||
val eventValues = LineaRollupV6.staticExtractEventParameters(
|
||||
LineaRollupV6.MESSAGESENT_EVENT,
|
||||
transactionReceipt.logs.first { log ->
|
||||
log.topics.contains(EventEncoder.encode(LineaRollupV5.MESSAGESENT_EVENT))
|
||||
log.topics.contains(EventEncoder.encode(LineaRollupV6.MESSAGESENT_EVENT))
|
||||
}
|
||||
)
|
||||
MessageSentResult(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.consensys.zkevm.ethereum.coordination.messageanchoring
|
||||
|
||||
import build.linea.contract.LineaRollupV5
|
||||
import build.linea.contract.LineaRollupV6
|
||||
import io.vertx.core.Vertx
|
||||
import net.consensys.linea.async.toSafeFuture
|
||||
import net.consensys.toULong
|
||||
@@ -24,10 +24,10 @@ class L1EventQuerierImpl(
|
||||
private val l1Web3jClient: Web3j
|
||||
) : L1EventQuerier {
|
||||
companion object {
|
||||
val encodedMessageSentEvent: String = EventEncoder.encode(LineaRollupV5.MESSAGESENT_EVENT)
|
||||
val encodedMessageSentEvent: String = EventEncoder.encode(LineaRollupV6.MESSAGESENT_EVENT)
|
||||
|
||||
fun parseMessageSentEventLogs(log: Log): SendMessageEvent {
|
||||
val messageSentEvent = LineaRollupV5.getMessageSentEventFromLog(log)
|
||||
val messageSentEvent = LineaRollupV6.getMessageSentEventFromLog(log)
|
||||
return SendMessageEvent(
|
||||
Bytes32.wrap(messageSentEvent._messageHash),
|
||||
messageSentEvent._nonce.toULong(),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.consensys.zkevm.ethereum.coordination.messageanchoring
|
||||
|
||||
import build.linea.contract.LineaRollupV5
|
||||
import build.linea.contract.LineaRollupV6
|
||||
import io.vertx.core.Vertx
|
||||
import io.vertx.junit5.Timeout
|
||||
import io.vertx.junit5.VertxExtension
|
||||
@@ -603,7 +603,7 @@ class L1EventQuerierImplTest {
|
||||
|
||||
private fun createRandomSendEvent(blockNumber: String, logIndex: String): LogResult<Log> {
|
||||
val log = Log()
|
||||
val eventSignature: String = EventEncoder.encode(LineaRollupV5.MESSAGESENT_EVENT)
|
||||
val eventSignature: String = EventEncoder.encode(LineaRollupV6.MESSAGESENT_EVENT)
|
||||
val messageHashValue = Bytes32.random()
|
||||
val messageHash = org.web3j.abi.datatypes.generated.Bytes32(messageHashValue.toArray())
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ interface ContractsManager {
|
||||
fun deployRollupAndL2MessageService(
|
||||
dataCompressionAndProofAggregationMigrationBlock: ULong = 1000UL,
|
||||
numberOfOperators: Int = 1,
|
||||
l1ContractVersion: LineaContractVersion = LineaContractVersion.V5
|
||||
l1ContractVersion: LineaContractVersion = LineaContractVersion.V6
|
||||
): SafeFuture<ContactsDeploymentResult>
|
||||
|
||||
fun connectToLineaRollupContract(
|
||||
|
||||
@@ -77,7 +77,6 @@ fun makeDeployLineaRollup(
|
||||
)
|
||||
deploymentPrivateKey?.let { env["DEPLOYMENT_PRIVATE_KEY"] = it }
|
||||
val command = when (contractVersion) {
|
||||
LineaContractVersion.V5 -> "make deploy-linea-rollup-v5"
|
||||
LineaContractVersion.V6 -> "make deploy-linea-rollup-v6"
|
||||
else -> throw IllegalArgumentException("Unsupported contract version: $contractVersion")
|
||||
}
|
||||
@@ -118,7 +117,7 @@ fun main() {
|
||||
makeDeployLineaRollup(
|
||||
L1AccountManager.generateAccount().privateKey,
|
||||
listOf("03dfa322A95039BB679771346Ee2dBfEa0e2B773"),
|
||||
LineaContractVersion.V5
|
||||
LineaContractVersion.V6
|
||||
),
|
||||
makeDeployL2MessageService(
|
||||
L2AccountManager.generateAccount().privateKey,
|
||||
|
||||
@@ -52,8 +52,8 @@ class MakefileContractDeploymentHelperKtTest {
|
||||
assertThat(
|
||||
getDeployedAddress(
|
||||
listOf(
|
||||
"LineaRollupV5.2.1 artifact has been deployed in 1.855172125s ",
|
||||
"contract=LineaRollupV5.2.1 deployed: address=0x8613180dF1485B8b87DEE3BCf31896659eb1a092 blockNumber=1414",
|
||||
"LineaRollup6.2.1 artifact has been deployed in 1.855172125s ",
|
||||
"contract=LineaRollupV6.2.1 deployed: address=0x8613180dF1485B8b87DEE3BCf31896659eb1a092 blockNumber=1414",
|
||||
""
|
||||
),
|
||||
lineaRollupAddressPattern
|
||||
|
||||
@@ -4,7 +4,6 @@ import net.consensys.linea.BlockParameter
|
||||
import tech.pegasys.teku.infrastructure.async.SafeFuture
|
||||
|
||||
enum class LineaContractVersion : Comparable<LineaContractVersion> {
|
||||
V5, // "EIP4844 multiple blobs per tx support - version in all networks"
|
||||
V6 // more efficient data submission and new events for state recovery
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package build.linea.contract.l1
|
||||
|
||||
import build.linea.contract.LineaRollupV5
|
||||
import build.linea.contract.LineaRollupV6
|
||||
import net.consensys.encodeHex
|
||||
import net.consensys.linea.BlockParameter
|
||||
@@ -34,8 +33,8 @@ open class Web3JLineaRollupSmartContractClientReadOnly(
|
||||
private val log: Logger = LogManager.getLogger(Web3JLineaRollupSmartContractClientReadOnly::class.java)
|
||||
) : LineaRollupSmartContractClientReadOnly {
|
||||
|
||||
protected fun contractClientAtBlock(blockParameter: BlockParameter): LineaRollupV5 {
|
||||
return contractClientAtBlock(blockParameter, LineaRollupV5::class.java)
|
||||
protected fun contractClientAtBlock(blockParameter: BlockParameter): LineaRollupV6 {
|
||||
return contractClientAtBlock(blockParameter, LineaRollupV6::class.java)
|
||||
}
|
||||
|
||||
protected fun <T : Contract> contractClientAtBlock(blockParameter: BlockParameter, contract: Class<T>): T {
|
||||
@@ -49,16 +48,6 @@ open class Web3JLineaRollupSmartContractClientReadOnly(
|
||||
).apply {
|
||||
this.setDefaultBlockParameter(blockParameter.toWeb3j())
|
||||
}
|
||||
|
||||
LineaRollupV5::class.java.isAssignableFrom(contract) -> LineaRollupV5.load(
|
||||
contractAddress,
|
||||
web3j,
|
||||
fakeCredentials,
|
||||
StaticGasProvider(BigInteger.ZERO, BigInteger.ZERO)
|
||||
).apply {
|
||||
this.setDefaultBlockParameter(blockParameter.toWeb3j())
|
||||
}
|
||||
|
||||
else -> throw IllegalArgumentException("Unsupported contract type: ${contract::class.java}")
|
||||
} as T
|
||||
}
|
||||
@@ -101,7 +90,7 @@ open class Web3JLineaRollupSmartContractClientReadOnly(
|
||||
if (error.cause is ContractCallException) {
|
||||
// means that contract does not have CONTRACT_VERSION method available yet
|
||||
// so it is still V5, so defaulting to V5
|
||||
SafeFuture.completedFuture(LineaContractVersion.V5)
|
||||
SafeFuture.completedFuture(LineaContractVersion.V6)
|
||||
} else {
|
||||
SafeFuture.failedFuture(error)
|
||||
}
|
||||
@@ -134,10 +123,10 @@ open class Web3JLineaRollupSmartContractClientReadOnly(
|
||||
override fun isBlobShnarfPresent(blockParameter: BlockParameter, shnarf: ByteArray): SafeFuture<Boolean> {
|
||||
return getVersion()
|
||||
.thenCompose { version ->
|
||||
if (version == LineaContractVersion.V5) {
|
||||
contractClientAtBlock(blockParameter, LineaRollupV5::class.java).shnarfFinalBlockNumbers(shnarf)
|
||||
} else {
|
||||
contractClientAtBlock(blockParameter, LineaRollupV6::class.java).blobShnarfExists(shnarf)
|
||||
when (version!!) {
|
||||
LineaContractVersion.V6 -> contractClientAtBlock(blockParameter, LineaRollupV6::class.java).blobShnarfExists(
|
||||
shnarf
|
||||
)
|
||||
}
|
||||
.sendAsync()
|
||||
.thenApply { it != BigInteger.ZERO }
|
||||
|
||||
@@ -20,11 +20,9 @@ dependencies {
|
||||
web3jContractWrappers {
|
||||
def contractsDir = layout.buildDirectory.dir("${rootProject.projectDir}/contracts/abi").get()
|
||||
def contractV6Abi = contractsDir.file("LineaRollupV6.0.abi").asFile.absolutePath
|
||||
def contractV5Abi = contractsDir.file("LineaRollupV5.0.abi").asFile.absolutePath
|
||||
|
||||
contractsPackage = "build.linea.contract"
|
||||
contracts = [
|
||||
"$contractV5Abi": "LineaRollupV5",
|
||||
"$contractV6Abi": "LineaRollupV6"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user