Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions deploy-config/hardhat.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,5 @@
"multiproofGenesisOutputRoot": "0x0000000000000000000000000000000000000000000000000000000000000001",
"multiproofGenesisBlockNumber": 0,
"multiproofBlockInterval": 100,
"multiproofIntermediateBlockInterval": 10,
"multiproofProofThreshold": 1
"multiproofIntermediateBlockInterval": 10
}
1 change: 0 additions & 1 deletion deploy-config/sepolia.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@
"multiproofGenesisBlockNumber": 37223829,
"multiproofBlockInterval": 600,
"multiproofIntermediateBlockInterval": 30,
"multiproofProofThreshold": 1,
"risc0VerifierRouter": "0xb121b667dd2cf27f95f9f5107137696f56f188f6",
"risc0SetBuilderImageId": "0x70909b25db0db00f1d4b4016aeb876f53568a3e5a8e6397cb562d79947a02cc9"
}
3 changes: 3 additions & 0 deletions interfaces/multiproof/IVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ interface IVerifier {
/// @dev Should only occur if a soundness issue is found.
/// @dev Should only be callable by a proper dispute game.
function nullify() external;

/// @notice Whether this verifier has been nullified.
function nullified() external view returns (bool);
}
1 change: 0 additions & 1 deletion scripts/deploy/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@ contract Deploy is Deployer {
l2ChainID: cfg.l2ChainID(),
multiproofBlockInterval: cfg.multiproofBlockInterval(),
multiproofIntermediateBlockInterval: cfg.multiproofIntermediateBlockInterval(),
multiproofProofThreshold: cfg.multiproofProofThreshold(),
protocolVersionsProxy: IProtocolVersions(artifacts.mustGetAddress("ProtocolVersionsProxy")),
superchainConfigProxy: superchainConfigProxy,
superchainProxyAdmin: superchainProxyAdmin,
Expand Down
2 changes: 0 additions & 2 deletions scripts/deploy/DeployConfig.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ contract DeployConfig is Script {
uint256 public multiproofGenesisBlockNumber;
uint256 public multiproofBlockInterval;
uint256 public multiproofIntermediateBlockInterval;
uint256 public multiproofProofThreshold;

// RISC Zero / NitroEnclaveVerifier Configuration (reference values; DeployRiscZeroStack takes these as CLI args)
bytes32 public risc0SetBuilderImageId;
Expand Down Expand Up @@ -227,7 +226,6 @@ contract DeployConfig is Script {
multiproofGenesisBlockNumber = _readOr(_json, "$.multiproofGenesisBlockNumber", 0);
multiproofBlockInterval = _readOr(_json, "$.multiproofBlockInterval", 100);
multiproofIntermediateBlockInterval = _readOr(_json, "$.multiproofIntermediateBlockInterval", 10);
multiproofProofThreshold = _readOr(_json, "$.multiproofProofThreshold", 1);

risc0SetBuilderImageId = bytes32(_readOr(_json, "$.risc0SetBuilderImageId", 0));
nitroRootCert = bytes32(_readOr(_json, "$.nitroRootCert", 0));
Expand Down
4 changes: 1 addition & 3 deletions scripts/deploy/DeployImplementations.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ contract DeployImplementations is Script {
uint256 l2ChainID;
uint256 multiproofBlockInterval;
uint256 multiproofIntermediateBlockInterval;
uint256 multiproofProofThreshold;
// Outputs from DeploySuperchain.s.sol.
ISuperchainConfig superchainConfigProxy;
IProtocolVersions protocolVersionsProxy;
Expand Down Expand Up @@ -740,8 +739,7 @@ contract DeployImplementations is Script {
_input.multiproofConfigHash,
_input.l2ChainID,
_input.multiproofBlockInterval,
_input.multiproofIntermediateBlockInterval,
_input.multiproofProofThreshold
_input.multiproofIntermediateBlockInterval
)
)
);
Expand Down
4 changes: 1 addition & 3 deletions scripts/multiproof/DeployDevNoNitro.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ import { MockDelayedWETH } from "./mocks/MockDelayedWETH.sol";
contract DeployDevNoNitro is Script {
uint256 public constant BLOCK_INTERVAL = 100;
uint256 public constant INTERMEDIATE_BLOCK_INTERVAL = 10;
uint256 public constant PROOF_THRESHOLD = 1;
uint256 public constant INIT_BOND = 0.001 ether;

DeployConfig public constant cfg =
Expand Down Expand Up @@ -183,8 +182,7 @@ contract DeployDevNoNitro is Script {
cfg.multiproofConfigHash(),
cfg.l2ChainID(),
BLOCK_INTERVAL,
INTERMEDIATE_BLOCK_INTERVAL,
PROOF_THRESHOLD
INTERMEDIATE_BLOCK_INTERVAL
)
);

Expand Down
4 changes: 1 addition & 3 deletions scripts/multiproof/DeployDevWithNitro.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ import { MockDelayedWETH } from "./mocks/MockDelayedWETH.sol";
contract DeployDevWithNitro is Script {
uint256 public constant BLOCK_INTERVAL = 600;
uint256 public constant INTERMEDIATE_BLOCK_INTERVAL = 30;
uint256 public constant PROOF_THRESHOLD = 1;
uint256 public constant INIT_BOND = 0.00001 ether;

DeployConfig public constant cfg =
Expand Down Expand Up @@ -178,8 +177,7 @@ contract DeployDevWithNitro is Script {
cfg.multiproofConfigHash(),
cfg.l2ChainID(),
BLOCK_INTERVAL,
INTERMEDIATE_BLOCK_INTERVAL,
PROOF_THRESHOLD
INTERMEDIATE_BLOCK_INTERVAL
)
);

Expand Down
14 changes: 7 additions & 7 deletions snapshots/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -232,24 +232,24 @@
"sourceCodeHash": "0x955bd0c9b47e43219865e4e92abf28d916c96de20cbdf2f94c8ab14d02083759"
},
"src/multiproof/AggregateVerifier.sol:AggregateVerifier": {
"initCodeHash": "0x54168f8e087c104e6bcc532d2d323327205a14b4ad3597d14d6cadcc1924543b",
"sourceCodeHash": "0x36342bdca5dd7c41f408216377b4b0e1a6d076df6396c77a6350d5d67e499ebe"
"initCodeHash": "0x10bb6a60f21de103d1da9ff310a38f571c53a8113d04a029087648debf3f0341",
"sourceCodeHash": "0xcd4c508223b9b461ec230bde03c1630fe68cd00b82ee84c39b93d9f3c0d71d37"
},
"src/multiproof/tee/NitroEnclaveVerifier.sol:NitroEnclaveVerifier": {
"initCodeHash": "0x100364f9b0c63a61538386ba91e73dcffba22d3f6dfe8efdbbf5ff347b6fce47",
"sourceCodeHash": "0xed5d92ee1f32f2fde5e89ba278f3142c8113c774f6ce7bd831781a8abe7bddf3"
"sourceCodeHash": "0xbedb66738a0ab18600b2ed21de51d552a210c4cc71b2c971440e325791dc3ce7"
},
"src/multiproof/tee/TEEProverRegistry.sol:TEEProverRegistry": {
"initCodeHash": "0xfd1942e1c2f59b0aa72b33d698a948a53b6e4cf1040106f173fb5d89f63f57b0",
"sourceCodeHash": "0xf1ec1f02f540da659a204b26acf986fdce7d7d63bba67a87923f52453fb92ccb"
},
"src/multiproof/tee/TEEVerifier.sol:TEEVerifier": {
"initCodeHash": "0x9f65f2d6e2c43512594f7a08fc0ea475d06f48d230690c3c85cc85dee3a9679a",
"initCodeHash": "0x655576cc21cc5c603d55fb4dd2a2f0ef57b11deeaabd3e539b0a70a5f7e2c9af",
"sourceCodeHash": "0xd5e01b4f4e69313e56e51f2f46b7bbe699ef8dc24b8a6385b8ebac4162e05353"
},
"src/multiproof/zk/ZKVerifier.sol:ZkVerifier": {
"initCodeHash": "0xb50364a38af3ef7dbfab9a84210d08c5f61105638326e6a442828dfa5afc924d",
"sourceCodeHash": "0x0ffc935dbd768b4aad6c35e2d6826c556191cc5e8f20737045d1bc196b13e19f"
"initCodeHash": "0xcdc5bd5fa8ffad76358b8f34a53b8c0cb36540176c31f82d52546373d0bd5245",
"sourceCodeHash": "0xdb3774707dc5fa59c32636ab896eba284bb6466568bd04583d9767112857d405"
},
"src/revenue-share/FeeDisburser.sol:FeeDisburser": {
"initCodeHash": "0x1278027e3756e2989e80c0a7b513e221a5fe0d3dbd9ded108375a29b2c1f3d57",
Expand Down Expand Up @@ -299,4 +299,4 @@
"initCodeHash": "0x2bfce526f82622288333d53ca3f43a0a94306ba1bab99241daa845f8f4b18bd4",
"sourceCodeHash": "0xf49d7b0187912a6bb67926a3222ae51121e9239495213c975b3b4b217ee57a1b"
}
}
}
37 changes: 24 additions & 13 deletions src/multiproof/AggregateVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ contract AggregateVerifier is Clone, ReentrancyGuard, ISemver {

/// @notice The maximum number of blocks that EIP-2935 can look back (~8192).
uint256 public constant EIP2935_WINDOW = 8191;

/// @notice The minimum number of proofs required to resolve the game.
uint256 public constant PROOF_THRESHOLD = 1;
////////////////////////////////////////////////////////////////
// Immutables //
////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -109,9 +112,6 @@ contract AggregateVerifier is Clone, ReentrancyGuard, ISemver {
/// @notice The game type ID.
GameType internal immutable GAME_TYPE;

/// @notice The minimum number of proofs required to resolve the game.
uint256 public immutable PROOF_THRESHOLD;

////////////////////////////////////////////////////////////////
// State Vars //
////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -261,7 +261,6 @@ contract AggregateVerifier is Clone, ReentrancyGuard, ISemver {
/// @param l2ChainId The chain ID of the L2 network.
/// @param blockInterval The block interval.
/// @param intermediateBlockInterval The intermediate block interval.
/// @param proofThreshold The minimum number of proofs required to resolve the game.
constructor(
GameType gameType_,
IAnchorStateRegistry anchorStateRegistry_,
Expand All @@ -273,17 +272,13 @@ contract AggregateVerifier is Clone, ReentrancyGuard, ISemver {
bytes32 configHash,
uint256 l2ChainId,
uint256 blockInterval,
uint256 intermediateBlockInterval,
uint256 proofThreshold
uint256 intermediateBlockInterval
) {
// Block interval and intermediate block interval must be positive and divisible.
if (blockInterval == 0 || intermediateBlockInterval == 0 || blockInterval % intermediateBlockInterval != 0) {
revert InvalidBlockInterval(blockInterval, intermediateBlockInterval);
}

// Proof threshold must be between 1 and 2.
if (proofThreshold != 1 && proofThreshold != 2) revert InvalidProofThreshold();

// Set up initial game state.
GAME_TYPE = gameType_;
ANCHOR_STATE_REGISTRY = anchorStateRegistry_;
Expand All @@ -298,7 +293,6 @@ contract AggregateVerifier is Clone, ReentrancyGuard, ISemver {
L2_CHAIN_ID = l2ChainId;
BLOCK_INTERVAL = blockInterval;
INTERMEDIATE_BLOCK_INTERVAL = intermediateBlockInterval;
PROOF_THRESHOLD = proofThreshold;

INITIALIZE_CALLDATA_SIZE = 0x8E + 0x20 * intermediateOutputRootsCount();
}
Expand Down Expand Up @@ -454,6 +448,9 @@ contract AggregateVerifier is Clone, ReentrancyGuard, ISemver {
status = GameStatus.CHALLENGER_WINS;
} else {
// Game must be completed with a valid proof and enough proofs.
if (_updateProofCount()) {
return status;
}
if (!gameOver()) revert GameNotOver();
if (proofCount < PROOF_THRESHOLD) revert NotEnoughProofs();

Expand Down Expand Up @@ -592,9 +589,6 @@ contract AggregateVerifier is Clone, ReentrancyGuard, ISemver {

// Nullify the verifier to prevent further proof verification.
if (proofType == ProofType.ZK) {
// Delete the challenged intermediate root if one existed.
delete counteredByIntermediateRootIndexPlusOne;

IVerifier(ZK_VERIFIER).nullify();
} else if (proofType == ProofType.TEE) {
IVerifier(TEE_VERIFIER).nullify();
Expand Down Expand Up @@ -787,6 +781,10 @@ contract AggregateVerifier is Clone, ReentrancyGuard, ISemver {
/// @dev Should only occur if challenged or nullified.
function _proofRefutedUpdate(ProofType proofType) internal {
delete proofTypeToProver[proofType];
// A ZK challenge is recorded in `counteredByIntermediateRootIndexPlusOne`; dropping the ZK proof clears it.
if (proofType == ProofType.ZK) {
delete counteredByIntermediateRootIndexPlusOne;
}

// Should not be possible, but just in case.
if (proofCount == 0) revert NotEnoughProofs();
Expand All @@ -812,6 +810,19 @@ contract AggregateVerifier is Clone, ReentrancyGuard, ISemver {
expectedResolution = Timestamp.wrap(uint64(block.timestamp) + delay);
}

/// @notice Updates the proof count and returns true if a proof was nullified.
function _updateProofCount() internal returns (bool) {
if (proofTypeToProver[ProofType.TEE] != address(0) && TEE_VERIFIER.nullified()) {
_proofRefutedUpdate(ProofType.TEE);
return true;
}
if (proofTypeToProver[ProofType.ZK] != address(0) && ZK_VERIFIER.nullified()) {
_proofRefutedUpdate(ProofType.ZK);
return true;
}
return false;
}

function _getDelay() internal view returns (uint64) {
if (proofCount >= 2) {
return FAST_FINALIZATION_DELAY;
Expand Down
6 changes: 4 additions & 2 deletions src/multiproof/Verifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ abstract contract Verifier is IVerifier {

/// @notice Nullifies the verifier to prevent further proof verification.
/// @dev Should only occur if a soundness issue is found.
/// @dev Should only be callable by a proper dispute game.
/// @dev Should only be callable by a registered, respected, not blacklisted, not retired dispute game.
function nullify() external override {
if (
!ANCHOR_STATE_REGISTRY.isGameProper(IDisputeGame(msg.sender))
!ANCHOR_STATE_REGISTRY.isGameRegistered(IDisputeGame(msg.sender))
|| !ANCHOR_STATE_REGISTRY.isGameRespected(IDisputeGame(msg.sender))
|| ANCHOR_STATE_REGISTRY.isGameBlacklisted(IDisputeGame(msg.sender))
|| ANCHOR_STATE_REGISTRY.isGameRetired(IDisputeGame(msg.sender))
) revert NotProperGame();
nullified = true;

Expand Down
7 changes: 5 additions & 2 deletions src/multiproof/tee/NitroEnclaveVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -591,8 +591,11 @@ contract NitroEnclaveVerifier is Ownable, INitroEnclaveVerifier, ISemver {
* 5. Caches newly discovered certificates for future use
*
* The timestamp validation converts milliseconds to seconds and checks:
* - Attestation is not too old (timestamp + maxTimeDiff >= block.timestamp)
* - Attestation is not from the future (timestamp <= block.timestamp)
* - Attestation is not too old (timestamp + maxTimeDiff > block.timestamp)
* - Attestation is not from the future (timestamp < block.timestamp)
* Note that due to truncating timestamp from milliseconds, to seconds,
* some valid attestations may be rejected. However, this ensures all invalid
* timestamps are rejected.
*/
function _verifyJournal(VerifierJournal memory journal) internal returns (VerifierJournal memory) {
if (journal.result != VerificationResult.Success) {
Expand Down
3 changes: 0 additions & 3 deletions src/multiproof/zk/ZKVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ contract ZkVerifier is Verifier {
/// @notice The SP1 verifier gateway contract.
ISP1Verifier public immutable SP1_VERIFIER;

/// @notice Thrown when SP1 proof verification reverts.
error SP1VerificationFailed();

/// @param sp1Verifier The deployed SP1 verifier gateway address.
/// @param anchorStateRegistry The anchor state registry for nullification checks.
constructor(ISP1Verifier sp1Verifier, IAnchorStateRegistry anchorStateRegistry) Verifier(anchorStateRegistry) {
Expand Down
45 changes: 3 additions & 42 deletions test/multiproof/AggregateVerifier.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -375,8 +375,7 @@ contract AggregateVerifierTest is BaseTest {
CONFIG_HASH,
L2_CHAIN_ID,
0,
INTERMEDIATE_BLOCK_INTERVAL,
PROOF_THRESHOLD
INTERMEDIATE_BLOCK_INTERVAL
);

// Case 2: INTERMEDIATE_BLOCK_INTERVAL is 0
Expand All @@ -392,8 +391,7 @@ contract AggregateVerifierTest is BaseTest {
CONFIG_HASH,
L2_CHAIN_ID,
BLOCK_INTERVAL,
0,
PROOF_THRESHOLD
0
);

// Case 3: BLOCK_INTERVAL is not divisible by INTERMEDIATE_BLOCK_INTERVAL
Expand All @@ -409,44 +407,7 @@ contract AggregateVerifierTest is BaseTest {
CONFIG_HASH,
L2_CHAIN_ID,
3,
2,
PROOF_THRESHOLD
);
}

function testDeployWithInvalidProofThreshold() public {
// Case 1: PROOF_THRESHOLD is 0
vm.expectRevert(abi.encodeWithSelector(AggregateVerifier.InvalidProofThreshold.selector));
new AggregateVerifier(
AGGREGATE_VERIFIER_GAME_TYPE,
IAnchorStateRegistry(address(anchorStateRegistry)),
IDelayedWETH(payable(address(delayedWETH))),
IVerifier(address(teeVerifier)),
IVerifier(address(zkVerifier)),
TEE_IMAGE_HASH,
AggregateVerifier.ZkHashes(ZK_RANGE_HASH, ZK_AGGREGATE_HASH),
CONFIG_HASH,
L2_CHAIN_ID,
BLOCK_INTERVAL,
INTERMEDIATE_BLOCK_INTERVAL,
0
);

// Case 2: PROOF_THRESHOLD is > 2
vm.expectRevert(abi.encodeWithSelector(AggregateVerifier.InvalidProofThreshold.selector));
new AggregateVerifier(
AGGREGATE_VERIFIER_GAME_TYPE,
IAnchorStateRegistry(address(anchorStateRegistry)),
IDelayedWETH(payable(address(delayedWETH))),
IVerifier(address(teeVerifier)),
IVerifier(address(zkVerifier)),
TEE_IMAGE_HASH,
AggregateVerifier.ZkHashes(ZK_RANGE_HASH, ZK_AGGREGATE_HASH),
CONFIG_HASH,
L2_CHAIN_ID,
BLOCK_INTERVAL,
INTERMEDIATE_BLOCK_INTERVAL,
3
2
);
}
}
4 changes: 1 addition & 3 deletions test/multiproof/BaseTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ contract BaseTest is Test {
uint256 public constant DELAYED_WETH_DELAY = 1 days;
// Finality delay handled by the AggregateVerifier
uint256 public constant FINALITY_DELAY = 0 days;
uint256 public constant PROOF_THRESHOLD = 1;

uint256 public currentL2BlockNumber = 0;

Expand Down Expand Up @@ -136,8 +135,7 @@ contract BaseTest is Test {
CONFIG_HASH,
L2_CHAIN_ID,
BLOCK_INTERVAL,
INTERMEDIATE_BLOCK_INTERVAL,
PROOF_THRESHOLD
INTERMEDIATE_BLOCK_INTERVAL
);

// Set the implementation for the aggregate verifier
Expand Down
Loading
Loading