mirror of
https://github.com/scroll-tech/scroll.git
synced 2026-01-13 07:57:58 -05:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d667f9353 | ||
|
|
57a058c516 |
@@ -22,7 +22,7 @@ func NewL2CrossMsgOrm(db *sqlx.DB) L2CrossMsgOrm {
|
||||
|
||||
func (l *l2CrossMsgOrm) GetL2CrossMsgByHash(l2Hash common.Hash) (*CrossMsg, error) {
|
||||
result := &CrossMsg{}
|
||||
row := l.db.QueryRowx(`SELECT * FROM l2_cross_message WHERE layer2_hash = $1 AND NOT is_deleted;`, l2Hash.String())
|
||||
row := l.db.QueryRowx(`SELECT * FROM cross_message WHERE layer2_hash = $1 AND NOT is_deleted;`, l2Hash.String())
|
||||
if err := row.StructScan(result); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
var tag = "v3.3.6"
|
||||
var tag = "v3.3.7"
|
||||
|
||||
var commit = func() string {
|
||||
if info, ok := debug.ReadBuildInfo(); ok {
|
||||
|
||||
118
contracts/src/L1/rollup/MultipleVersionRollupVerifier.sol
Normal file
118
contracts/src/L1/rollup/MultipleVersionRollupVerifier.sol
Normal file
@@ -0,0 +1,118 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
||||
|
||||
import {IRollupVerifier} from "../../libraries/verifier/IRollupVerifier.sol";
|
||||
import {IZkEvmVerifier} from "../../libraries/verifier/IZkEvmVerifier.sol";
|
||||
|
||||
contract MultipleVersionRollupVerifier is IRollupVerifier, Ownable {
|
||||
/**********
|
||||
* Events *
|
||||
**********/
|
||||
|
||||
/// @notice Emitted when the address of verifier is updated.
|
||||
/// @param startBatchIndex The start batch index when the verifier will be used.
|
||||
/// @param verifier The address of new verifier.
|
||||
event UpdateVerifier(uint256 startBatchIndex, address verifier);
|
||||
|
||||
/***********
|
||||
* Structs *
|
||||
***********/
|
||||
|
||||
struct Verifier {
|
||||
// The start batch index for the verifier.
|
||||
uint64 startBatchIndex;
|
||||
// The address of zkevm verifier.
|
||||
address verifier;
|
||||
}
|
||||
|
||||
/*************
|
||||
* Variables *
|
||||
*************/
|
||||
|
||||
/// @notice The list of legacy zkevm verifier, sorted by batchIndex in increasing order.
|
||||
Verifier[] public legacyVerifiers;
|
||||
|
||||
/// @notice The lastest used zkevm verifier.
|
||||
Verifier public latestVerifier;
|
||||
|
||||
/***************
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
constructor(address _verifier) {
|
||||
require(_verifier != address(0), "zero verifier address");
|
||||
|
||||
latestVerifier.verifier = _verifier;
|
||||
}
|
||||
|
||||
/*************************
|
||||
* Public View Functions *
|
||||
*************************/
|
||||
|
||||
/// @notice Return the number of legacy verifiers.
|
||||
function legacyVerifiersLength() external view returns (uint256) {
|
||||
return legacyVerifiers.length;
|
||||
}
|
||||
|
||||
/// @notice Compute the verifier should be used for specific batch.
|
||||
/// @param _batchIndex The batch index to query.
|
||||
function getVerifier(uint256 _batchIndex) public view returns (address) {
|
||||
// Normally, we will use the latest verifier.
|
||||
Verifier memory _verifier = latestVerifier;
|
||||
|
||||
if (_verifier.startBatchIndex > _batchIndex) {
|
||||
uint256 _length = legacyVerifiers.length;
|
||||
// In most case, only last few verifier will be used by `ScrollChain`.
|
||||
// So, we use linear search instead of binary search.
|
||||
unchecked {
|
||||
for (uint256 i = _length; i > 0; --i) {
|
||||
_verifier = legacyVerifiers[i - 1];
|
||||
if (_verifier.startBatchIndex <= _batchIndex) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _verifier.verifier;
|
||||
}
|
||||
|
||||
/*****************************
|
||||
* Public Mutating Functions *
|
||||
*****************************/
|
||||
|
||||
/// @inheritdoc IRollupVerifier
|
||||
function verifyAggregateProof(
|
||||
uint256 _batchIndex,
|
||||
bytes calldata _aggrProof,
|
||||
bytes32 _publicInputHash
|
||||
) external view override {
|
||||
address _verifier = getVerifier(_batchIndex);
|
||||
|
||||
IZkEvmVerifier(_verifier).verify(_aggrProof, _publicInputHash);
|
||||
}
|
||||
|
||||
/************************
|
||||
* Restricted Functions *
|
||||
************************/
|
||||
|
||||
/// @notice Update the address of zkevm verifier.
|
||||
/// @param _startBatchIndex The start batch index when the verifier will be used.
|
||||
/// @param _verifier The address of new verifier.
|
||||
function updateVerifier(uint64 _startBatchIndex, address _verifier) external onlyOwner {
|
||||
Verifier memory _latestVerifier = latestVerifier;
|
||||
require(_startBatchIndex >= _latestVerifier.startBatchIndex, "start batch index too small");
|
||||
require(_verifier != address(0), "zero verifier address");
|
||||
|
||||
if (_latestVerifier.startBatchIndex < _startBatchIndex) {
|
||||
legacyVerifiers.push(_latestVerifier);
|
||||
_latestVerifier.startBatchIndex = _startBatchIndex;
|
||||
}
|
||||
_latestVerifier.verifier = _verifier;
|
||||
|
||||
latestVerifier = _latestVerifier;
|
||||
|
||||
emit UpdateVerifier(_startBatchIndex, _verifier);
|
||||
}
|
||||
}
|
||||
@@ -308,7 +308,7 @@ contract ScrollChain is OwnableUpgradeable, IScrollChain {
|
||||
);
|
||||
|
||||
// verify batch
|
||||
IRollupVerifier(verifier).verifyAggregateProof(_aggrProof, _publicInputHash);
|
||||
IRollupVerifier(verifier).verifyAggregateProof(_batchIndex, _aggrProof, _publicInputHash);
|
||||
|
||||
// check and update lastFinalizedBatchIndex
|
||||
unchecked {
|
||||
|
||||
@@ -4,7 +4,12 @@ pragma solidity ^0.8.0;
|
||||
|
||||
interface IRollupVerifier {
|
||||
/// @notice Verify aggregate zk proof.
|
||||
/// @param batchIndex The batch index to verify.
|
||||
/// @param aggrProof The aggregated proof.
|
||||
/// @param publicInputHash The public input hash.
|
||||
function verifyAggregateProof(bytes calldata aggrProof, bytes32 publicInputHash) external view;
|
||||
function verifyAggregateProof(
|
||||
uint256 batchIndex,
|
||||
bytes calldata aggrProof,
|
||||
bytes32 publicInputHash
|
||||
) external view;
|
||||
}
|
||||
|
||||
10
contracts/src/libraries/verifier/IZkEvmVerifier.sol
Normal file
10
contracts/src/libraries/verifier/IZkEvmVerifier.sol
Normal file
@@ -0,0 +1,10 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
interface IZkEvmVerifier {
|
||||
/// @notice Verify aggregate zk proof.
|
||||
/// @param aggrProof The aggregated proof.
|
||||
/// @param publicInputHash The public input hash.
|
||||
function verify(bytes calldata aggrProof, bytes32 publicInputHash) external view;
|
||||
}
|
||||
105
contracts/src/test/MultipleVersionRollupVerifier.t.sol
Normal file
105
contracts/src/test/MultipleVersionRollupVerifier.t.sol
Normal file
@@ -0,0 +1,105 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import {DSTestPlus} from "solmate/test/utils/DSTestPlus.sol";
|
||||
|
||||
import {L1MessageQueue} from "../L1/rollup/L1MessageQueue.sol";
|
||||
import {MultipleVersionRollupVerifier} from "../L1/rollup/MultipleVersionRollupVerifier.sol";
|
||||
|
||||
import {MockZkEvmVerifier} from "./mocks/MockZkEvmVerifier.sol";
|
||||
|
||||
contract MultipleVersionRollupVerifierTest is DSTestPlus {
|
||||
// from MultipleVersionRollupVerifier
|
||||
event UpdateVerifier(uint256 startBatchIndex, address verifier);
|
||||
|
||||
MultipleVersionRollupVerifier private verifier;
|
||||
MockZkEvmVerifier private v0;
|
||||
MockZkEvmVerifier private v1;
|
||||
MockZkEvmVerifier private v2;
|
||||
|
||||
function setUp() external {
|
||||
v0 = new MockZkEvmVerifier();
|
||||
v1 = new MockZkEvmVerifier();
|
||||
v2 = new MockZkEvmVerifier();
|
||||
|
||||
verifier = new MultipleVersionRollupVerifier(address(v0));
|
||||
}
|
||||
|
||||
function testUpdateVerifier(address _newVerifier) external {
|
||||
hevm.assume(_newVerifier != address(0));
|
||||
|
||||
// set by non-owner, should revert
|
||||
hevm.startPrank(address(1));
|
||||
hevm.expectRevert("Ownable: caller is not the owner");
|
||||
verifier.updateVerifier(0, address(0));
|
||||
hevm.stopPrank();
|
||||
|
||||
// zero verifier address, revert
|
||||
hevm.expectRevert("zero verifier address");
|
||||
verifier.updateVerifier(0, address(0));
|
||||
|
||||
// change to random operator
|
||||
assertEq(verifier.legacyVerifiersLength(), 0);
|
||||
verifier.updateVerifier(uint64(100), _newVerifier);
|
||||
assertEq(verifier.legacyVerifiersLength(), 1);
|
||||
(uint64 _startBatchIndex, address _verifier) = verifier.latestVerifier();
|
||||
assertEq(_startBatchIndex, uint64(100));
|
||||
assertEq(_verifier, _newVerifier);
|
||||
(_startBatchIndex, _verifier) = verifier.legacyVerifiers(0);
|
||||
assertEq(_startBatchIndex, uint64(0));
|
||||
assertEq(_verifier, address(v0));
|
||||
|
||||
// change to same batch index
|
||||
verifier.updateVerifier(uint64(100), address(v1));
|
||||
(_startBatchIndex, _verifier) = verifier.latestVerifier();
|
||||
assertEq(_startBatchIndex, uint64(100));
|
||||
assertEq(_verifier, address(v1));
|
||||
(_startBatchIndex, _verifier) = verifier.legacyVerifiers(0);
|
||||
assertEq(_startBatchIndex, uint64(0));
|
||||
assertEq(_verifier, address(v0));
|
||||
|
||||
// start batch index too small, revert
|
||||
hevm.expectRevert("start batch index too small");
|
||||
verifier.updateVerifier(99, _newVerifier);
|
||||
}
|
||||
|
||||
function testGetVerifier() external {
|
||||
verifier.updateVerifier(100, address(v1));
|
||||
verifier.updateVerifier(300, address(v2));
|
||||
|
||||
assertEq(verifier.getVerifier(0), address(v0));
|
||||
assertEq(verifier.getVerifier(1), address(v0));
|
||||
assertEq(verifier.getVerifier(99), address(v0));
|
||||
assertEq(verifier.getVerifier(100), address(v1));
|
||||
assertEq(verifier.getVerifier(101), address(v1));
|
||||
assertEq(verifier.getVerifier(299), address(v1));
|
||||
assertEq(verifier.getVerifier(300), address(v2));
|
||||
assertEq(verifier.getVerifier(301), address(v2));
|
||||
assertEq(verifier.getVerifier(10000), address(v2));
|
||||
}
|
||||
|
||||
function testVerifyAggregateProof() external {
|
||||
verifier.updateVerifier(100, address(v1));
|
||||
verifier.updateVerifier(300, address(v2));
|
||||
|
||||
hevm.expectRevert(abi.encode(address(v0)));
|
||||
verifier.verifyAggregateProof(0, new bytes(0), bytes32(0));
|
||||
hevm.expectRevert(abi.encode(address(v0)));
|
||||
verifier.verifyAggregateProof(1, new bytes(0), bytes32(0));
|
||||
hevm.expectRevert(abi.encode(address(v0)));
|
||||
verifier.verifyAggregateProof(99, new bytes(0), bytes32(0));
|
||||
hevm.expectRevert(abi.encode(address(v1)));
|
||||
verifier.verifyAggregateProof(100, new bytes(0), bytes32(0));
|
||||
hevm.expectRevert(abi.encode(address(v1)));
|
||||
verifier.verifyAggregateProof(101, new bytes(0), bytes32(0));
|
||||
hevm.expectRevert(abi.encode(address(v1)));
|
||||
verifier.verifyAggregateProof(299, new bytes(0), bytes32(0));
|
||||
hevm.expectRevert(abi.encode(address(v2)));
|
||||
verifier.verifyAggregateProof(300, new bytes(0), bytes32(0));
|
||||
hevm.expectRevert(abi.encode(address(v2)));
|
||||
verifier.verifyAggregateProof(301, new bytes(0), bytes32(0));
|
||||
hevm.expectRevert(abi.encode(address(v2)));
|
||||
verifier.verifyAggregateProof(10000, new bytes(0), bytes32(0));
|
||||
}
|
||||
}
|
||||
@@ -6,5 +6,9 @@ import {IRollupVerifier} from "../../libraries/verifier/IRollupVerifier.sol";
|
||||
|
||||
contract MockRollupVerifier is IRollupVerifier {
|
||||
/// @inheritdoc IRollupVerifier
|
||||
function verifyAggregateProof(bytes calldata, bytes32) external view {}
|
||||
function verifyAggregateProof(
|
||||
uint256,
|
||||
bytes calldata,
|
||||
bytes32
|
||||
) external view {}
|
||||
}
|
||||
|
||||
14
contracts/src/test/mocks/MockZkEvmVerifier.sol
Normal file
14
contracts/src/test/mocks/MockZkEvmVerifier.sol
Normal file
@@ -0,0 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import {IZkEvmVerifier} from "../../libraries/verifier/IZkEvmVerifier.sol";
|
||||
|
||||
contract MockZkEvmVerifier is IZkEvmVerifier {
|
||||
event Called(address);
|
||||
|
||||
/// @inheritdoc IZkEvmVerifier
|
||||
function verify(bytes calldata, bytes32) external view {
|
||||
revert(string(abi.encode(address(this))));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user