diff --git a/packages/protocol/contract_layout.md b/packages/protocol/contract_layout.md index de7f9bb4b8..12028cfa30 100644 --- a/packages/protocol/contract_layout.md +++ b/packages/protocol/contract_layout.md @@ -599,6 +599,25 @@ | __gap | uint256[50] | 251 | 0 | 1600 | contracts/verifiers/compose/ZkAnyVerifier.sol:ZkAnyVerifier | | __gap | uint256[50] | 301 | 0 | 1600 | contracts/verifiers/compose/ZkAnyVerifier.sol:ZkAnyVerifier | +## ZkAndTeeVerifier +| Name | Type | Slot | Offset | Bytes | Contract | +|----------------|-------------|------|--------|-------|-------------------------------------------------------------------| +| _initialized | uint8 | 0 | 0 | 1 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| _initializing | bool | 0 | 1 | 1 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| __gap | uint256[50] | 1 | 0 | 1600 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| _owner | address | 51 | 0 | 20 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| __gap | uint256[49] | 52 | 0 | 1568 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| _pendingOwner | address | 101 | 0 | 20 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| __gap | uint256[49] | 102 | 0 | 1568 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| addressManager | address | 151 | 0 | 20 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| __gap | uint256[49] | 152 | 0 | 1568 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| __reentry | uint8 | 201 | 0 | 1 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| __paused | uint8 | 201 | 1 | 1 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| lastUnpausedAt | uint64 | 201 | 2 | 8 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| __gap | uint256[49] | 202 | 0 | 1568 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| __gap | uint256[50] | 251 | 0 | 1600 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | +| __gap | uint256[50] | 301 | 0 | 1600 | contracts/verifiers/compose/ZkAndTeeVerifier.sol:ZkAndTeeVerifier | + ## HeklaTaikoL1 | Name | Type | Slot | Offset | Bytes | Contract | |----------------|------------------------|------|--------|-------|-----------------------------------------------| @@ -834,6 +853,63 @@ | addressRegistered | mapping(address => bool) | 253 | 0 | 32 | contracts/mainnet/rollup/verifiers/MainnetSgxVerifier.sol:MainnetSgxVerifier | | __gap | uint256[47] | 254 | 0 | 1504 | contracts/mainnet/rollup/verifiers/MainnetSgxVerifier.sol:MainnetSgxVerifier | +## MainnetTeeAnyVerifier +| Name | Type | Slot | Offset | Bytes | Contract | +|----------------|-------------|------|--------|-------|------------------------------------------------------------------------------------| +| _initialized | uint8 | 0 | 0 | 1 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| _initializing | bool | 0 | 1 | 1 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| __gap | uint256[50] | 1 | 0 | 1600 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| _owner | address | 51 | 0 | 20 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| __gap | uint256[49] | 52 | 0 | 1568 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| _pendingOwner | address | 101 | 0 | 20 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| __gap | uint256[49] | 102 | 0 | 1568 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| addressManager | address | 151 | 0 | 20 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| __gap | uint256[49] | 152 | 0 | 1568 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| __reentry | uint8 | 201 | 0 | 1 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| __paused | uint8 | 201 | 1 | 1 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| lastUnpausedAt | uint64 | 201 | 2 | 8 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| __gap | uint256[49] | 202 | 0 | 1568 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| __gap | uint256[50] | 251 | 0 | 1600 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | +| __gap | uint256[50] | 301 | 0 | 1600 | contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol:MainnetTeeAnyVerifier | + +## MainnetZkAnyVerifier +| Name | Type | Slot | Offset | Bytes | Contract | +|----------------|-------------|------|--------|-------|----------------------------------------------------------------------------------| +| _initialized | uint8 | 0 | 0 | 1 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| _initializing | bool | 0 | 1 | 1 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| __gap | uint256[50] | 1 | 0 | 1600 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| _owner | address | 51 | 0 | 20 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| __gap | uint256[49] | 52 | 0 | 1568 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| _pendingOwner | address | 101 | 0 | 20 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| __gap | uint256[49] | 102 | 0 | 1568 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| addressManager | address | 151 | 0 | 20 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| __gap | uint256[49] | 152 | 0 | 1568 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| __reentry | uint8 | 201 | 0 | 1 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| __paused | uint8 | 201 | 1 | 1 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| lastUnpausedAt | uint64 | 201 | 2 | 8 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| __gap | uint256[49] | 202 | 0 | 1568 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| __gap | uint256[50] | 251 | 0 | 1600 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | +| __gap | uint256[50] | 301 | 0 | 1600 | contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol:MainnetZkAnyVerifier | + +## MainnetZkAndTeeVerifier +| Name | Type | Slot | Offset | Bytes | Contract | +|----------------|-------------|------|--------|-------|----------------------------------------------------------------------------------------| +| _initialized | uint8 | 0 | 0 | 1 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| _initializing | bool | 0 | 1 | 1 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| __gap | uint256[50] | 1 | 0 | 1600 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| _owner | address | 51 | 0 | 20 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| __gap | uint256[49] | 52 | 0 | 1568 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| _pendingOwner | address | 101 | 0 | 20 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| __gap | uint256[49] | 102 | 0 | 1568 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| addressManager | address | 151 | 0 | 20 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| __gap | uint256[49] | 152 | 0 | 1568 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| __reentry | uint8 | 201 | 0 | 1 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| __paused | uint8 | 201 | 1 | 1 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| lastUnpausedAt | uint64 | 201 | 2 | 8 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| __gap | uint256[49] | 202 | 0 | 1568 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| __gap | uint256[50] | 251 | 0 | 1600 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | +| __gap | uint256[50] | 301 | 0 | 1600 | contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol:MainnetZkAndTeeVerifier | + ## MainnetSharedAddressManager | Name | Type | Slot | Offset | Bytes | Contract | |----------------|-------------------------------------------------|------|--------|-------|--------------------------------------------------------------------------------------| diff --git a/packages/protocol/contracts/L1/ITaikoL1.sol b/packages/protocol/contracts/L1/ITaikoL1.sol index 3a66ba2a4d..114579f0ea 100644 --- a/packages/protocol/contracts/L1/ITaikoL1.sol +++ b/packages/protocol/contracts/L1/ITaikoL1.sol @@ -48,11 +48,18 @@ interface ITaikoL1 { /// TaikoData.TierProof) tuple. function proveBlock(uint64 _blockId, bytes calldata _input) external; - /// @notice Proves or contests multiple block transitions. + /// @notice Proves or contests multiple block transitions (version 2) /// @param _blockIds The indices of the blocks to prove. - /// @param _inputArr An list of abi-encoded (TaikoData.BlockMetadata, TaikoData.Transition, + /// @param _inputs An list of abi-encoded (TaikoData.BlockMetadata, TaikoData.Transition, /// TaikoData.TierProof) tuples. - function proveBlocks(uint64[] calldata _blockIds, bytes[] calldata _inputArr) external; + /// @param _batchProof An abi-encoded TaikoData.TierProof that contains the batch/aggregated + /// proof for the given blocks. + function proveBlocks( + uint64[] calldata _blockIds, + bytes[] calldata _inputs, + bytes calldata _batchProof + ) + external; /// @notice Verifies up to a certain number of blocks. /// @param _maxBlocksToVerify Max number of blocks to verify. diff --git a/packages/protocol/contracts/L1/TaikoData.sol b/packages/protocol/contracts/L1/TaikoData.sol index f45eac37b4..7e85ebcf70 100644 --- a/packages/protocol/contracts/L1/TaikoData.sol +++ b/packages/protocol/contracts/L1/TaikoData.sol @@ -6,7 +6,7 @@ pragma solidity 0.8.24; /// protocol. /// @custom:security-contact security@taiko.xyz library TaikoData { - /// @dev Struct that represneds L2 basefee configurations + /// @dev Struct that represents L2 basefee configurations struct BaseFeeConfig { uint8 adjustmentQuotient; uint8 sharingPctg; diff --git a/packages/protocol/contracts/L1/TaikoL1.sol b/packages/protocol/contracts/L1/TaikoL1.sol index 3fedb0fbaf..bf7921276e 100644 --- a/packages/protocol/contracts/L1/TaikoL1.sol +++ b/packages/protocol/contracts/L1/TaikoL1.sol @@ -78,13 +78,9 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents { returns (TaikoData.BlockMetadata memory meta_, TaikoData.EthDeposit[] memory deposits_) { TaikoData.Config memory config = getConfig(); - - (meta_,, deposits_) = LibProposing.proposeBlock(state, config, this, _params, _txList); + (meta_,) = LibProposing.proposeBlock(state, config, this, _params, _txList); if (meta_.id >= config.ontakeForkHeight) revert L1_FORK_ERROR(); - - if (LibUtils.shouldVerifyBlocks(config, meta_.id, true) && !state.slotB.provingPaused) { - LibVerifying.verifyBlocks(state, config, this, config.maxBlocksToVerify); - } + deposits_ = new TaikoData.EthDeposit[](0); } function proposeBlockV2( @@ -96,9 +92,11 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents { whenNotPaused nonReentrant emitEventForClient - returns (TaikoData.BlockMetadataV2 memory) + returns (TaikoData.BlockMetadataV2 memory meta_) { - return _proposeBlock(_params, _txList, getConfig()); + TaikoData.Config memory config = getConfig(); + (, meta_) = LibProposing.proposeBlock(state, config, this, _params, _txList); + if (meta_.id < config.ontakeForkHeight) revert L1_FORK_ERROR(); } /// @inheritdoc ITaikoL1 @@ -113,15 +111,10 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents { emitEventForClient returns (TaikoData.BlockMetadataV2[] memory metaArr_) { - if (_paramsArr.length == 0 || _paramsArr.length != _txListArr.length) { - revert L1_INVALID_PARAMS(); - } - - metaArr_ = new TaikoData.BlockMetadataV2[](_paramsArr.length); TaikoData.Config memory config = getConfig(); - - for (uint256 i; i < _paramsArr.length; ++i) { - metaArr_[i] = _proposeBlock(_paramsArr[i], _txListArr[i], config); + (, metaArr_) = LibProposing.proposeBlocks(state, config, this, _paramsArr, _txListArr); + for (uint256 i; i < metaArr_.length; ++i) { + if (metaArr_[i].id < config.ontakeForkHeight) revert L1_FORK_ERROR(); } } @@ -136,14 +129,14 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents { nonReentrant emitEventForClient { - TaikoData.Config memory config = getConfig(); - _proveBlock(_blockId, _input, config); + LibProving.proveBlock(state, getConfig(), this, _blockId, _input); } /// @inheritdoc ITaikoL1 function proveBlocks( uint64[] calldata _blockIds, - bytes[] calldata _inputArr + bytes[] calldata _inputs, + bytes calldata _batchProof ) external whenNotPaused @@ -151,21 +144,11 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents { nonReentrant emitEventForClient { - if (_blockIds.length == 0 || _blockIds.length != _inputArr.length) { - revert L1_INVALID_PARAMS(); - } - - TaikoData.Config memory config = getConfig(); - - for (uint256 i; i < _blockIds.length; ++i) { - _proveBlock(_blockIds[i], _inputArr[i], config); - } + LibProving.proveBlocks(state, getConfig(), this, _blockIds, _inputs, _batchProof); } /// @inheritdoc ITaikoL1 - function verifyBlocks( - uint64 _maxBlocksToVerify - ) + function verifyBlocks(uint64 _maxBlocksToVerify) external whenNotPaused whenProvingNotPaused @@ -315,36 +298,6 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents { }); } - function _proposeBlock( - bytes calldata _params, - bytes calldata _txList, - TaikoData.Config memory _config - ) - internal - returns (TaikoData.BlockMetadataV2 memory meta_) - { - (, meta_,) = LibProposing.proposeBlock(state, _config, this, _params, _txList); - if (meta_.id < _config.ontakeForkHeight) revert L1_FORK_ERROR(); - - if (LibUtils.shouldVerifyBlocks(_config, meta_.id, true) && !state.slotB.provingPaused) { - LibVerifying.verifyBlocks(state, _config, this, _config.maxBlocksToVerify); - } - } - - function _proveBlock( - uint64 _blockId, - bytes calldata _input, - TaikoData.Config memory _config - ) - internal - { - LibProving.proveBlock(state, _config, this, _blockId, _input); - - if (LibUtils.shouldVerifyBlocks(_config, _blockId, false)) { - LibVerifying.verifyBlocks(state, _config, this, _config.maxBlocksToVerify); - } - } - /// @dev chain_pauser is supposed to be a cold wallet. function _authorizePause( address, diff --git a/packages/protocol/contracts/L1/libs/LibData.sol b/packages/protocol/contracts/L1/libs/LibData.sol index df5ffe0df8..98e3fc2f12 100644 --- a/packages/protocol/contracts/L1/libs/LibData.sol +++ b/packages/protocol/contracts/L1/libs/LibData.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.24; import "../TaikoData.sol"; +import "../../verifiers/IVerifier.sol"; /// @title LibData /// @notice A library that offers helper functions. @@ -11,9 +12,7 @@ library LibData { bytes32 internal constant EMPTY_ETH_DEPOSIT_HASH = 0x569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd; - function blockParamsV1ToV2( - TaikoData.BlockParams memory _v1 - ) + function blockParamsV1ToV2(TaikoData.BlockParams memory _v1) internal pure returns (TaikoData.BlockParamsV2 memory) @@ -29,9 +28,7 @@ library LibData { }); } - function blockMetadataV2toV1( - TaikoData.BlockMetadataV2 memory _v2 - ) + function blockMetadataV2toV1(TaikoData.BlockMetadataV2 memory _v2) internal pure returns (TaikoData.BlockMetadata memory) @@ -54,9 +51,7 @@ library LibData { }); } - function blockMetadataV1toV2( - TaikoData.BlockMetadata memory _v1 - ) + function blockMetadataV1toV2(TaikoData.BlockMetadata memory _v1) internal pure returns (TaikoData.BlockMetadataV2 memory) @@ -85,9 +80,7 @@ library LibData { }); } - function blockV2toV1( - TaikoData.BlockV2 memory _v2 - ) + function blockV2toV1(TaikoData.BlockV2 memory _v2) internal pure returns (TaikoData.Block memory) @@ -103,4 +96,20 @@ library LibData { verifiedTransitionId: _v2.verifiedTransitionId }); } + + function verifierContextV2toV1(IVerifier.ContextV2 memory _v2) + internal + pure + returns (IVerifier.Context memory) + { + return IVerifier.Context({ + metaHash: _v2.metaHash, + blobHash: _v2.blobHash, + prover: _v2.prover, + blockId: _v2.blockId, + isContesting: _v2.isContesting, + blobUsed: _v2.blobUsed, + msgSender: _v2.msgSender + }); + } } diff --git a/packages/protocol/contracts/L1/libs/LibProposing.sol b/packages/protocol/contracts/L1/libs/LibProposing.sol index b9b7802077..296af4fb6c 100644 --- a/packages/protocol/contracts/L1/libs/LibProposing.sol +++ b/packages/protocol/contracts/L1/libs/LibProposing.sol @@ -6,6 +6,7 @@ import "../../libs/LibNetwork.sol"; import "./LibBonds.sol"; import "./LibData.sol"; import "./LibUtils.sol"; +import "./LibVerifying.sol"; /// @title LibProposing /// @notice A library for handling block proposals in the Taiko protocol. @@ -50,34 +51,91 @@ library LibProposing { error L1_BLOB_NOT_AVAILABLE(); error L1_BLOB_NOT_FOUND(); error L1_INVALID_ANCHOR_BLOCK(); + error L1_INVALID_PARAMS(); error L1_INVALID_PROPOSER(); error L1_INVALID_TIMESTAMP(); error L1_LIVENESS_BOND_NOT_RECEIVED(); error L1_TOO_MANY_BLOCKS(); error L1_UNEXPECTED_PARENT(); - /// @dev Proposes a Taiko L2 block. - /// @param _state Current TaikoData.State. - /// @param _config Actual TaikoData.Config. - /// @param _resolver Address resolver interface. - /// @param _data Encoded data bytes containing the block params. + /// @notice Proposes multiple Taiko L2 blocks. + /// @param _state The current state of the Taiko protocol. + /// @param _config The configuration parameters for the Taiko protocol. + /// @param _resolver The address resolver interface. + /// @param _paramsArr An array of encoded data bytes containing the block parameters. + /// @param _txListArr An array of transaction list bytes (if not blob). + /// @return metaV1s_ An array of metadata objects for the proposed L2 blocks (version 1). + /// @return metas_ An array of metadata objects for the proposed L2 blocks (version 2). + function proposeBlocks( + TaikoData.State storage _state, + TaikoData.Config memory _config, + IAddressResolver _resolver, + bytes[] calldata _paramsArr, + bytes[] calldata _txListArr + ) + public + returns ( + TaikoData.BlockMetadata[] memory metaV1s_, + TaikoData.BlockMetadataV2[] memory metas_ + ) + { + if (_paramsArr.length == 0 || _paramsArr.length != _txListArr.length) { + revert L1_INVALID_PARAMS(); + } + + metaV1s_ = new TaikoData.BlockMetadata[](_paramsArr.length); + metas_ = new TaikoData.BlockMetadataV2[](_paramsArr.length); + + for (uint256 i; i < _paramsArr.length; ++i) { + (metaV1s_[i], metas_[i]) = + _proposeBlock(_state, _config, _resolver, _paramsArr[i], _txListArr[i]); + } + + if (!_state.slotB.provingPaused) { + for (uint256 i; i < _paramsArr.length; ++i) { + if (LibUtils.shouldVerifyBlocks(_config, metas_[i].id, false)) { + LibVerifying.verifyBlocks(_state, _config, _resolver, _config.maxBlocksToVerify); + } + } + } + } + + /// @notice Proposes a single Taiko L2 block. + /// @param _state The current state of the Taiko protocol. + /// @param _config The configuration parameters for the Taiko protocol. + /// @param _resolver The address resolver interface. + /// @param _params Encoded data bytes containing the block parameters. /// @param _txList Transaction list bytes (if not blob). - /// @return metaV1_ The constructed block's metadata v1. - /// @return meta_ The constructed block's metadata v2. - /// @return deposits_ An empty ETH deposit array. + /// @return metaV1_ The metadata of the proposed block (version 1). + /// @return meta_ The metadata of the proposed block (version 2). function proposeBlock( TaikoData.State storage _state, TaikoData.Config memory _config, IAddressResolver _resolver, - bytes calldata _data, + bytes calldata _params, bytes calldata _txList ) public - returns ( - TaikoData.BlockMetadata memory metaV1_, - TaikoData.BlockMetadataV2 memory meta_, - TaikoData.EthDeposit[] memory deposits_ - ) + returns (TaikoData.BlockMetadata memory metaV1_, TaikoData.BlockMetadataV2 memory meta_) + { + (metaV1_, meta_) = _proposeBlock(_state, _config, _resolver, _params, _txList); + + if (!_state.slotB.provingPaused) { + if (LibUtils.shouldVerifyBlocks(_config, meta_.id, false)) { + LibVerifying.verifyBlocks(_state, _config, _resolver, _config.maxBlocksToVerify); + } + } + } + + function _proposeBlock( + TaikoData.State storage _state, + TaikoData.Config memory _config, + IAddressResolver _resolver, + bytes calldata _params, + bytes calldata _txList + ) + private + returns (TaikoData.BlockMetadata memory metaV1_, TaikoData.BlockMetadataV2 memory meta_) { // Checks proposer access. Local memory local; @@ -91,12 +149,12 @@ library LibProposing { } if (local.postFork) { - if (_data.length != 0) { - local.params = abi.decode(_data, (TaikoData.BlockParamsV2)); + if (_params.length != 0) { + local.params = abi.decode(_params, (TaikoData.BlockParamsV2)); // otherwise use a default BlockParamsV2 with 0 values } } else { - TaikoData.BlockParams memory paramsV1 = abi.decode(_data, (TaikoData.BlockParams)); + TaikoData.BlockParams memory paramsV1 = abi.decode(_params, (TaikoData.BlockParams)); local.params = LibData.blockParamsV1ToV2(paramsV1); local.extraData = paramsV1.extraData; } @@ -244,8 +302,6 @@ library LibProposing { address(block.coinbase).sendEtherAndVerify(msg.value); } - deposits_ = new TaikoData.EthDeposit[](0); - if (local.postFork) { emit BlockProposedV2(meta_.id, meta_); } else { @@ -254,14 +310,12 @@ library LibProposing { assignedProver: msg.sender, livenessBond: _config.livenessBond, meta: metaV1_, - depositsProcessed: deposits_ + depositsProcessed: new TaikoData.EthDeposit[](0) }); } } - function _encodeBaseFeeConfig( - TaikoData.BaseFeeConfig memory _baseFeeConfig - ) + function _encodeBaseFeeConfig(TaikoData.BaseFeeConfig memory _baseFeeConfig) private pure returns (bytes32) diff --git a/packages/protocol/contracts/L1/libs/LibProving.sol b/packages/protocol/contracts/L1/libs/LibProving.sol index 7ed20e21cb..14e02fe51e 100644 --- a/packages/protocol/contracts/L1/libs/LibProving.sol +++ b/packages/protocol/contracts/L1/libs/LibProving.sol @@ -5,6 +5,7 @@ import "../../verifiers/IVerifier.sol"; import "./LibBonds.sol"; import "./LibData.sol"; import "./LibUtils.sol"; +import "./LibVerifying.sol"; /// @title LibProving /// @notice A library for handling block contestation and proving in the Taiko @@ -18,6 +19,8 @@ library LibProving { TaikoData.SlotB b; ITierProvider.Tier tier; ITierProvider.Tier minTier; + TaikoData.BlockMetadataV2 meta; + TaikoData.TierProof proof; bytes32 metaHash; address assignedProver; bytes32 stateRoot; @@ -101,6 +104,8 @@ library LibProving { error L1_ALREADY_PROVED(); error L1_BLOCK_MISMATCH(); error L1_CANNOT_CONTEST(); + error L1_DIFF_VERIFIER(); + error L1_INVALID_PARAMS(); error L1_INVALID_PAUSE_STATUS(); error L1_INVALID_TIER(); error L1_INVALID_TRANSITION(); @@ -120,7 +125,67 @@ library LibProving { emit ProvingPaused(_pause); } - /// @dev Proves or contests a block transition. + /// @dev Proves or contests multiple Taiko L2 blocks. + /// @param _state Current TaikoData.State. + /// @param _config Actual TaikoData.Config. + /// @param _resolver Address resolver interface. + /// @param _blockIds The index of the block to prove. This is also used to + /// select the right implementation version. + /// @param _inputs An abi-encoded (TaikoData.BlockMetadata, TaikoData.Transition, + /// TaikoData.TierProof) tuple. + /// @param _batchProof An abi-encoded TaikoData.TierProof that contains the batch/aggregated + /// proof for the given blocks. + function proveBlocks( + TaikoData.State storage _state, + TaikoData.Config memory _config, + IAddressResolver _resolver, + uint64[] calldata _blockIds, + bytes[] calldata _inputs, + bytes calldata _batchProof + ) + public + { + if (_blockIds.length == 0 || _blockIds.length != _inputs.length) { + revert L1_INVALID_PARAMS(); + } + + TaikoData.TierProof memory batchProof; + if (_batchProof.length != 0) { + batchProof = abi.decode(_batchProof, (TaikoData.TierProof)); + if (batchProof.tier == 0) revert L1_INVALID_TIER(); + } + + IVerifier.ContextV2[] memory ctxs = new IVerifier.ContextV2[](_blockIds.length); + bytes32 batchVerifierName; + bool batchVerifierNameSet; + + // This loop iterates over each block ID in the _blockIds array. + // For each block ID, it calls the _proveBlock function to get the context and verifier. + for (uint256 i; i < _blockIds.length; ++i) { + bytes32 _verifierName; + (ctxs[i], _verifierName) = + _proveBlock(_state, _config, _resolver, _blockIds[i], _inputs[i], batchProof); + + // Verify that if batchProof is used, the verifier is the same for all blocks. + if (batchProof.tier != 0) { + if (!batchVerifierNameSet) { + batchVerifierNameSet = true; + batchVerifierName = _verifierName; + } else if (batchVerifierName != _verifierName) { + revert L1_DIFF_VERIFIER(); + } + } + } + + // If batch verifier name is not empty, verify the batch proof. + if (batchVerifierName != "") { + IVerifier(_resolver.resolve(batchVerifierName, false)).verifyBatchProof( + ctxs, batchProof + ); + } + } + + /// @dev Proves or contests a single Taiko L2 block. /// @param _state Current TaikoData.State. /// @param _config Actual TaikoData.Config. /// @param _resolver Address resolver interface. @@ -137,59 +202,77 @@ library LibProving { ) public { - Local memory local; + TaikoData.TierProof memory noBatchProof; + _proveBlock(_state, _config, _resolver, _blockId, _input, noBatchProof); + } + function _proveBlock( + TaikoData.State storage _state, + TaikoData.Config memory _config, + IAddressResolver _resolver, + uint64 _blockId, + bytes calldata _input, + TaikoData.TierProof memory _batchProof + ) + private + returns (IVerifier.ContextV2 memory ctx_, bytes32 verifierName_) + { + Local memory local; local.b = _state.slotB; local.blockId = _blockId; local.postFork = _blockId >= _config.ontakeForkHeight; - TaikoData.BlockMetadataV2 memory meta; - TaikoData.Transition memory tran; - TaikoData.TierProof memory proof; - if (local.postFork) { - (meta, tran, proof) = abi.decode( - _input, (TaikoData.BlockMetadataV2, TaikoData.Transition, TaikoData.TierProof) - ); + if (_batchProof.tier == 0) { + // No batch proof is available, each transition is proving using a separate proof. + (local.meta, ctx_.tran, local.proof) = abi.decode( + _input, (TaikoData.BlockMetadataV2, TaikoData.Transition, TaikoData.TierProof) + ); + } else { + // All transitions are proving using the batch proof. + (local.meta, ctx_.tran) = + abi.decode(_input, (TaikoData.BlockMetadataV2, TaikoData.Transition)); + local.proof = _batchProof; + } } else { TaikoData.BlockMetadata memory metaV1; - - (metaV1, tran, proof) = abi.decode( + (metaV1, ctx_.tran, local.proof) = abi.decode( _input, (TaikoData.BlockMetadata, TaikoData.Transition, TaikoData.TierProof) ); - meta = LibData.blockMetadataV1toV2(metaV1); + local.meta = LibData.blockMetadataV1toV2(metaV1); } - if (_blockId != meta.id) revert LibUtils.L1_INVALID_BLOCK_ID(); + if (_blockId != local.meta.id) revert LibUtils.L1_INVALID_BLOCK_ID(); // Make sure parentHash is not zero // To contest an existing transition, simply use any non-zero value as // the blockHash and stateRoot. - if (tran.parentHash == 0 || tran.blockHash == 0 || tran.stateRoot == 0) { + if (ctx_.tran.parentHash == 0 || ctx_.tran.blockHash == 0 || ctx_.tran.stateRoot == 0) { revert L1_INVALID_TRANSITION(); } // Check that the block has been proposed but has not yet been verified. - if (meta.id <= local.b.lastVerifiedBlockId || meta.id >= local.b.numBlocks) { + if (local.meta.id <= local.b.lastVerifiedBlockId || local.meta.id >= local.b.numBlocks) { revert LibUtils.L1_INVALID_BLOCK_ID(); } - local.slot = meta.id % _config.blockRingBufferSize; + local.slot = local.meta.id % _config.blockRingBufferSize; TaikoData.BlockV2 storage blk = _state.blocks[local.slot]; - local.proposedAt = local.postFork ? meta.proposedAt : blk.proposedAt; + local.proposedAt = local.postFork ? local.meta.proposedAt : blk.proposedAt; if (LibUtils.shouldSyncStateRoot(_config.stateRootSyncInternal, local.blockId)) { - local.stateRoot = tran.stateRoot; + local.stateRoot = ctx_.tran.stateRoot; } local.assignedProver = blk.assignedProver; if (local.assignedProver == address(0)) { - local.assignedProver = meta.proposer; + local.assignedProver = local.meta.proposer; } if (!blk.livenessBondReturned) { - local.livenessBond = meta.livenessBond == 0 ? blk.livenessBond : meta.livenessBond; + local.livenessBond = + local.meta.livenessBond == 0 ? blk.livenessBond : local.meta.livenessBond; } local.metaHash = blk.metaHash; @@ -198,8 +281,8 @@ library LibProving { // caution. { bytes32 metaHash = local.postFork - ? keccak256(abi.encode(meta)) - : keccak256(abi.encode(LibData.blockMetadataV2toV1(meta))); + ? keccak256(abi.encode(local.meta)) + : keccak256(abi.encode(LibData.blockMetadataV2toV1(local.meta))); if (local.metaHash != metaHash) revert L1_BLOCK_MISMATCH(); } @@ -209,11 +292,14 @@ library LibProving { // become available. In cases where a transition with the specified // parentHash does not exist, the transition ID (tid) will be set to 0. TaikoData.TransitionState memory ts; - (local.tid, ts) = _fetchOrCreateTransition(_state, blk, tran, local); + (local.tid, ts) = _fetchOrCreateTransition(_state, blk, ctx_.tran, local); // The new proof must meet or exceed the minimum tier required by the // block or the previous proof; it cannot be on a lower tier. - if (proof.tier == 0 || proof.tier < meta.minTier || proof.tier < ts.tier) { + if ( + local.proof.tier == 0 || local.proof.tier < local.meta.minTier + || local.proof.tier < ts.tier + ) { revert L1_INVALID_TIER(); } @@ -223,8 +309,8 @@ library LibProving { ITierRouter tierRouter = ITierRouter(_resolver.resolve(LibStrings.B_TIER_ROUTER, false)); ITierProvider tierProvider = ITierProvider(tierRouter.getProvider(local.blockId)); - local.tier = tierProvider.getTier(proof.tier); - local.minTier = tierProvider.getTier(meta.minTier); + local.tier = tierProvider.getTier(local.proof.tier); + local.minTier = tierProvider.getTier(local.meta.minTier); } local.inProvingWindow = !LibUtils.isPostDeadline({ @@ -257,49 +343,55 @@ library LibProving { // It's obvious that proof verification is entirely decoupled from // Taiko's core protocol. if (local.tier.verifierName != "") { - address verifier = _resolver.resolve(local.tier.verifierName, false); - bool isContesting = proof.tier == ts.tier && local.tier.contestBond != 0; - - IVerifier.Context memory ctx = IVerifier.Context({ + ctx_ = IVerifier.ContextV2({ metaHash: local.metaHash, - blobHash: meta.blobHash, + blobHash: local.meta.blobHash, // Separate msgSender to allow the prover to be any address in the future. prover: msg.sender, msgSender: msg.sender, blockId: local.blockId, - isContesting: isContesting, - blobUsed: meta.blobUsed + isContesting: local.proof.tier == ts.tier && local.tier.contestBond != 0, + blobUsed: local.meta.blobUsed, + tran: ctx_.tran }); - IVerifier(verifier).verifyProof(ctx, tran, proof); + verifierName_ = local.tier.verifierName; + + if (_batchProof.tier == 0) { + // In the case of per-transition proof, we verify the proof. + IVerifier(_resolver.resolve(local.tier.verifierName, false)).verifyProof( + LibData.verifierContextV2toV1(ctx_), ctx_.tran, local.proof + ); + } } local.isTopTier = local.tier.contestBond == 0; - local.sameTransition = tran.blockHash == ts.blockHash && local.stateRoot == ts.stateRoot; + local.sameTransition = + ctx_.tran.blockHash == ts.blockHash && local.stateRoot == ts.stateRoot; - if (proof.tier > ts.tier) { + if (local.proof.tier > ts.tier) { // Handles the case when an incoming tier is higher than the current transition's tier. // Reverts when the incoming proof tries to prove the same transition // (L1_ALREADY_PROVED). - _overrideWithHigherProof(_state, _resolver, blk, ts, tran, proof, local); + _overrideWithHigherProof(_state, _resolver, blk, ts, ctx_.tran, local.proof, local); if (local.postFork) { emit TransitionProvedV2({ blockId: local.blockId, - tran: tran, + tran: ctx_.tran, prover: msg.sender, validityBond: local.tier.validityBond, - tier: proof.tier, - proposedIn: meta.proposedIn + tier: local.proof.tier, + proposedIn: local.meta.proposedIn }); } else { emit TransitionProved({ blockId: local.blockId, - tran: tran, + tran: ctx_.tran, prover: msg.sender, validityBond: local.tier.validityBond, - tier: proof.tier + tier: local.proof.tier }); } } else { @@ -313,25 +405,25 @@ library LibProving { assert(ts.validityBond == 0 && ts.contester == address(0)); ts.prover = msg.sender; - ts.blockHash = tran.blockHash; + ts.blockHash = ctx_.tran.blockHash; ts.stateRoot = local.stateRoot; if (local.postFork) { emit TransitionProvedV2({ blockId: local.blockId, - tran: tran, + tran: ctx_.tran, prover: msg.sender, validityBond: 0, - tier: proof.tier, - proposedIn: meta.proposedIn + tier: local.proof.tier, + proposedIn: local.meta.proposedIn }); } else { emit TransitionProved({ blockId: local.blockId, - tran: tran, + tran: ctx_.tran, prover: msg.sender, validityBond: 0, - tier: proof.tier + tier: local.proof.tier }); } } else { @@ -364,19 +456,19 @@ library LibProving { if (local.postFork) { emit TransitionContestedV2({ blockId: local.blockId, - tran: tran, + tran: ctx_.tran, contester: msg.sender, contestBond: local.tier.contestBond, - tier: proof.tier, - proposedIn: meta.proposedIn + tier: local.proof.tier, + proposedIn: local.meta.proposedIn }); } else { emit TransitionContested({ blockId: local.blockId, - tran: tran, + tran: ctx_.tran, contester: msg.sender, contestBond: local.tier.contestBond, - tier: proof.tier + tier: local.proof.tier }); } } @@ -384,6 +476,12 @@ library LibProving { ts.timestamp = uint64(block.timestamp); _state.transitions[local.slot][local.tid] = ts; + + if ( + !_state.slotB.provingPaused && LibUtils.shouldVerifyBlocks(_config, local.meta.id, true) + ) { + LibVerifying.verifyBlocks(_state, _config, _resolver, _config.maxBlocksToVerify); + } } /// @dev Handle the transition initialization logic diff --git a/packages/protocol/contracts/L1/provers/GuardianProver.sol b/packages/protocol/contracts/L1/provers/GuardianProver.sol index a86f820719..6e25b39859 100644 --- a/packages/protocol/contracts/L1/provers/GuardianProver.sol +++ b/packages/protocol/contracts/L1/provers/GuardianProver.sol @@ -238,6 +238,19 @@ contract GuardianProver is IVerifier, EssentialContract { if (_ctx.msgSender != address(this)) revert GV_PERMISSION_DENIED(); } + /// @inheritdoc IVerifier + function verifyBatchProof( + ContextV2[] calldata _ctxs, + TaikoData.TierProof calldata /*_proof*/ + ) + external + view + { + for (uint256 i; i < _ctxs.length; ++i) { + if (_ctxs[i].msgSender != address(this)) revert GV_PERMISSION_DENIED(); + } + } + /// @notice Returns the number of guardians /// @return The number of guardians function numGuardians() public view returns (uint256) { diff --git a/packages/protocol/contracts/L1/tiers/LibTiers.sol b/packages/protocol/contracts/L1/tiers/LibTiers.sol index 28c9c5f757..5a27302f1f 100644 --- a/packages/protocol/contracts/L1/tiers/LibTiers.sol +++ b/packages/protocol/contracts/L1/tiers/LibTiers.sol @@ -26,6 +26,9 @@ library LibTiers { /// @notice Any ZKVM proof uint16 public constant TIER_ZKVM_ANY = 290; + /// @notice Any ZKVM+TEE proof + uint16 public constant TIER_ZKVM_AND_TEE = 300; + /// @notice Guardian tier ID with minority approval. uint16 public constant TIER_GUARDIAN_MINORITY = 900; diff --git a/packages/protocol/contracts/L1/tiers/TierProviderBase.sol b/packages/protocol/contracts/L1/tiers/TierProviderBase.sol index fbccae3cee..1e2ca26a29 100644 --- a/packages/protocol/contracts/L1/tiers/TierProviderBase.sol +++ b/packages/protocol/contracts/L1/tiers/TierProviderBase.sol @@ -35,11 +35,18 @@ abstract contract TierProviderBase is ITierProvider { if (_tierId == LibTiers.TIER_ZKVM_SP1) return _buildZkTier(LibStrings.B_TIER_ZKVM_SP1); if (_tierId == LibTiers.TIER_ZKVM_ANY) return _buildZkTier(LibStrings.B_TIER_ZKVM_ANY); + // ZKVM+TEE Tier + if (_tierId == LibTiers.TIER_ZKVM_AND_TEE) { + return _buildTier(LibStrings.B_TIER_ZKVM_AND_TEE, BOND_UNIT * 4, 1440, 180); + } + + // Guardian Minority Tiers if (_tierId == LibTiers.TIER_GUARDIAN_MINORITY) { // cooldownWindow is 240 minutes and provingWindow is 2880 minutes return _buildTier(LibStrings.B_TIER_GUARDIAN_MINORITY, BOND_UNIT * 4, 240, 2880); } + // Guardian Major Tiers if (_tierId == LibTiers.TIER_GUARDIAN) { // cooldownWindow is 1440 minutes and provingWindow is 2880 minutes return _buildTier(LibStrings.B_TIER_GUARDIAN, 0, 1440, 2880); @@ -51,9 +58,7 @@ abstract contract TierProviderBase is ITierProvider { /// @dev Builds a TEE tier with a specific verifier name. /// @param _verifierName The name of the verifier. /// @return A Tier struct with predefined parameters for TEE. - function _buildTeeTier( - bytes32 _verifierName - ) + function _buildTeeTier(bytes32 _verifierName) private pure returns (ITierProvider.Tier memory) diff --git a/packages/protocol/contracts/L2/TaikoL2.sol b/packages/protocol/contracts/L2/TaikoL2.sol index 498cf07143..149a735a3c 100644 --- a/packages/protocol/contracts/L2/TaikoL2.sol +++ b/packages/protocol/contracts/L2/TaikoL2.sol @@ -111,12 +111,11 @@ contract TaikoL2 is EssentialContract { /// @dev This function can be called freely as the golden touch private key is publicly known, /// but the Taiko node guarantees the first transaction of each block is always this anchor /// transaction, and any subsequent calls will revert with L2_PUBLIC_INPUT_HASH_MISMATCH. - /// @param _l1BlockHash The `anchorBlockHash` value in this block's metadata. /// @param _l1StateRoot The state root for the L1 block with id equals `_anchorBlockId` /// @param _l1BlockId The `anchorBlockId` value in this block's metadata. /// @param _parentGasUsed The gas used in the parent block. function anchor( - bytes32 _l1BlockHash, + bytes32, /*_l1BlockHash*/ bytes32 _l1StateRoot, uint64 _l1BlockId, uint32 _parentGasUsed @@ -355,9 +354,7 @@ contract TaikoL2 is EssentialContract { ); } - function _calcPublicInputHash( - uint256 _blockId - ) + function _calcPublicInputHash(uint256 _blockId) private view returns (bytes32 publicInputHashOld, bytes32 publicInputHashNew) diff --git a/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol b/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol index 59dbea343d..900ade3600 100644 --- a/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol +++ b/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol @@ -132,9 +132,7 @@ contract AutomataDcapV3Attestation is IAttestation, EssentialContract { emit TcbInfoJsonConfigured(fmspc, tcbInfoInput); } - function configureQeIdentityJson( - EnclaveIdStruct.EnclaveId calldata qeIdentityInput - ) + function configureQeIdentityJson(EnclaveIdStruct.EnclaveId calldata qeIdentityInput) external onlyOwner { @@ -148,9 +146,7 @@ contract AutomataDcapV3Attestation is IAttestation, EssentialContract { emit LocalReportCheckToggled(checkLocalEnclaveReport); } - function _attestationTcbIsValid( - TCBInfoStruct.TCBStatus status - ) + function _attestationTcbIsValid(TCBInfoStruct.TCBStatus status) internal pure virtual @@ -199,9 +195,7 @@ contract AutomataDcapV3Attestation is IAttestation, EssentialContract { return _verifyParsedQuote(parsedV3Quote); } - function _verifyQEReportWithIdentity( - V3Struct.EnclaveReport memory quoteEnclaveReport - ) + function _verifyQEReportWithIdentity(V3Struct.EnclaveReport memory quoteEnclaveReport) private view returns (bool, EnclaveIdStruct.EnclaveIdStatus status) @@ -274,9 +268,7 @@ contract AutomataDcapV3Attestation is IAttestation, EssentialContract { return true; } - function _verifyCertChain( - IPEMCertChainLib.ECSha256Certificate[] memory certs - ) + function _verifyCertChain(IPEMCertChainLib.ECSha256Certificate[] memory certs) private view returns (bool) @@ -383,9 +375,7 @@ contract AutomataDcapV3Attestation is IAttestation, EssentialContract { /// @dev For all valid quote verification, returns the following data: /// (_attestationTcbIsValid()) /// @dev exitCode is defined in the {{ TCBInfoStruct.TCBStatus }} enum - function verifyParsedQuote( - V3Struct.ParsedV3QuoteStruct calldata v3quote - ) + function verifyParsedQuote(V3Struct.ParsedV3QuoteStruct calldata v3quote) external view override @@ -394,9 +384,7 @@ contract AutomataDcapV3Attestation is IAttestation, EssentialContract { return _verifyParsedQuote(v3quote); } - function _verifyParsedQuote( - V3Struct.ParsedV3QuoteStruct memory v3quote - ) + function _verifyParsedQuote(V3Struct.ParsedV3QuoteStruct memory v3quote) internal view returns (bool, bytes memory) diff --git a/packages/protocol/contracts/automata-attestation/interfaces/IAttestation.sol b/packages/protocol/contracts/automata-attestation/interfaces/IAttestation.sol index f731e98f5f..7f918de6e2 100644 --- a/packages/protocol/contracts/automata-attestation/interfaces/IAttestation.sol +++ b/packages/protocol/contracts/automata-attestation/interfaces/IAttestation.sol @@ -7,9 +7,7 @@ import { V3Struct } from "../lib/QuoteV3Auth/V3Struct.sol"; /// @custom:security-contact security@taiko.xyz interface IAttestation { function verifyAttestation(bytes calldata data) external returns (bool); - function verifyParsedQuote( - V3Struct.ParsedV3QuoteStruct calldata v3quote - ) + function verifyParsedQuote(V3Struct.ParsedV3QuoteStruct calldata v3quote) external returns (bool success, bytes memory retData); } diff --git a/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol b/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol index ad0fa277db..f69c3e0200 100644 --- a/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol +++ b/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol @@ -213,9 +213,7 @@ contract PEMCertChainLib is IPEMCertChainLib { success = true; } - function _removeHeadersAndFooters( - string memory pemData - ) + function _removeHeadersAndFooters(string memory pemData) private pure returns (bool success, bytes memory extracted, uint256 endIndex) diff --git a/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol b/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol index 9e810961db..4e574b7eec 100644 --- a/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol +++ b/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol @@ -68,9 +68,7 @@ library V3Parser { success = true; } - function validateParsedInput( - V3Struct.ParsedV3QuoteStruct memory v3Quote - ) + function validateParsedInput(V3Struct.ParsedV3QuoteStruct memory v3Quote) internal pure returns ( @@ -149,9 +147,7 @@ library V3Parser { authDataV3 = v3Quote.v3AuthData; } - function parseEnclaveReport( - bytes memory rawEnclaveReport - ) + function parseEnclaveReport(bytes memory rawEnclaveReport) internal pure returns (V3Struct.EnclaveReport memory enclaveReport) @@ -183,9 +179,7 @@ library V3Parser { } } - function parseAndVerifyHeader( - bytes memory rawHeader - ) + function parseAndVerifyHeader(bytes memory rawHeader) private pure returns (bool success, V3Struct.Header memory header) @@ -264,9 +258,7 @@ library V3Parser { /// in bytes should be in big endian according to Intel spec. /// @param enclaveReport enclave report /// @return packedQEReport enclave report in bytes - function packQEReport( - V3Struct.EnclaveReport memory enclaveReport - ) + function packQEReport(V3Struct.EnclaveReport memory enclaveReport) internal pure returns (bytes memory packedQEReport) diff --git a/packages/protocol/contracts/bridge/Bridge.sol b/packages/protocol/contracts/bridge/Bridge.sol index 305cc01402..9fd7f4d580 100644 --- a/packages/protocol/contracts/bridge/Bridge.sol +++ b/packages/protocol/contracts/bridge/Bridge.sol @@ -126,9 +126,7 @@ contract Bridge is EssentialContract, IBridge { } /// @inheritdoc IBridge - function sendMessage( - Message calldata _message - ) + function sendMessage(Message calldata _message) external payable override @@ -355,9 +353,7 @@ contract Bridge is EssentialContract, IBridge { } /// @inheritdoc IBridge - function failMessage( - Message calldata _message - ) + function failMessage(Message calldata _message) external sameChain(_message.destChainId) diffChain(_message.srcChainId) @@ -433,9 +429,7 @@ contract Bridge is EssentialContract, IBridge { /// @param _chainId The destination chain ID. /// @return enabled_ True if the destination chain is enabled. /// @return destBridge_ The bridge of the destination chain. - function isDestChainEnabled( - uint64 _chainId - ) + function isDestChainEnabled(uint64 _chainId) public view returns (bool enabled_, address destBridge_) diff --git a/packages/protocol/contracts/bridge/IBridge.sol b/packages/protocol/contracts/bridge/IBridge.sol index bfd57ebc78..99af78b249 100644 --- a/packages/protocol/contracts/bridge/IBridge.sol +++ b/packages/protocol/contracts/bridge/IBridge.sol @@ -76,9 +76,7 @@ interface IBridge { /// @param _message The message to be sent. /// @return msgHash_ The hash of the sent message. /// @return message_ The updated message sent. - function sendMessage( - Message calldata _message - ) + function sendMessage(Message calldata _message) external payable returns (bytes32 msgHash_, Message memory message_); diff --git a/packages/protocol/contracts/common/LibStrings.sol b/packages/protocol/contracts/common/LibStrings.sol index e171cc22a4..324318c506 100644 --- a/packages/protocol/contracts/common/LibStrings.sol +++ b/packages/protocol/contracts/common/LibStrings.sol @@ -32,6 +32,7 @@ library LibStrings { bytes32 internal constant B_TIER_ZKVM_RISC0 = bytes32("tier_zkvm_risc0"); bytes32 internal constant B_TIER_ZKVM_SP1 = bytes32("tier_zkvm_sp1"); bytes32 internal constant B_TIER_ZKVM_ANY = bytes32("tier_zkvm_any"); + bytes32 internal constant B_TIER_ZKVM_AND_TEE = bytes32("tier_zkvm_and_tee"); bytes32 internal constant B_RISCZERO_GROTH16_VERIFIER = bytes32("risc0_groth16_verifier"); bytes32 internal constant B_WITHDRAWER = bytes32("withdrawer"); bytes32 internal constant H_RETURN_LIVENESS_BOND = keccak256("RETURN_LIVENESS_BOND"); diff --git a/packages/protocol/contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol b/packages/protocol/contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol index 5b47d3cd98..6ead5e10f4 100644 --- a/packages/protocol/contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol +++ b/packages/protocol/contracts/mainnet/rollup/verifiers/MainnetTeeAnyVerifier.sol @@ -5,6 +5,8 @@ import "../../../verifiers/compose/TeeAnyVerifier.sol"; import "../../addrcache/RollupAddressCache.sol"; /// @title MainnetTeeAnyVerifier +/// @dev This contract shall be deployed to replace its parent contract on Ethereum for Taiko +/// mainnet to reduce gas cost. /// @custom:security-contact security@taiko.xyz contract MainnetTeeAnyVerifier is TeeAnyVerifier, RollupAddressCache { function _getAddress(uint64 _chainId, bytes32 _name) internal view override returns (address) { diff --git a/packages/protocol/contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol b/packages/protocol/contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol new file mode 100644 index 0000000000..6e85de06e5 --- /dev/null +++ b/packages/protocol/contracts/mainnet/rollup/verifiers/MainnetZkAndTeeVerifier.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import "../../../verifiers/compose/ZkAndTeeVerifier.sol"; +import "../../addrcache/RollupAddressCache.sol"; + +/// @title MainnetZkAndTeeVerifier +/// @dev This contract shall be deployed to replace its parent contract on Ethereum for Taiko +/// mainnet to reduce gas cost. +/// @custom:security-contact security@taiko.xyz +contract MainnetZkAndTeeVerifier is ZkAndTeeVerifier, RollupAddressCache { + function _getAddress(uint64 _chainId, bytes32 _name) internal view override returns (address) { + return getAddress(_chainId, _name, super._getAddress); + } +} diff --git a/packages/protocol/contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol b/packages/protocol/contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol index 225016f93c..eff4d81926 100644 --- a/packages/protocol/contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol +++ b/packages/protocol/contracts/mainnet/rollup/verifiers/MainnetZkAnyVerifier.sol @@ -5,6 +5,8 @@ import "../../../verifiers/compose/ZkAnyVerifier.sol"; import "../../addrcache/RollupAddressCache.sol"; /// @title MainnetZkAnyVerifier +/// @dev This contract shall be deployed to replace its parent contract on Ethereum for Taiko +/// mainnet to reduce gas cost. /// @custom:security-contact security@taiko.xyz contract MainnetZkAnyVerifier is ZkAnyVerifier, RollupAddressCache { function _getAddress(uint64 _chainId, bytes32 _name) internal view override returns (address) { diff --git a/packages/protocol/contracts/tko/BridgedTaikoToken.sol b/packages/protocol/contracts/tko/BridgedTaikoToken.sol index 1a30448697..092d89c2a9 100644 --- a/packages/protocol/contracts/tko/BridgedTaikoToken.sol +++ b/packages/protocol/contracts/tko/BridgedTaikoToken.sol @@ -32,9 +32,7 @@ contract BridgedTaikoToken is TaikoTokenBase, IBridgedERC20 { _mint(_account, _amount); } - function burn( - uint256 _amount - ) + function burn(uint256 _amount) external override whenNotPaused diff --git a/packages/protocol/contracts/tokenvault/BridgedERC20.sol b/packages/protocol/contracts/tokenvault/BridgedERC20.sol index ee69dc472f..d263f50133 100644 --- a/packages/protocol/contracts/tokenvault/BridgedERC20.sol +++ b/packages/protocol/contracts/tokenvault/BridgedERC20.sol @@ -172,9 +172,7 @@ contract BridgedERC20 is return super._beforeTokenTransfer(_from, _to, _amount); } - function _authorizedMintBurn( - address addr - ) + function _authorizedMintBurn(address addr) private onlyFromOwnerOrNamed(LibStrings.B_ERC20_VAULT) { } diff --git a/packages/protocol/contracts/tokenvault/BridgedERC721.sol b/packages/protocol/contracts/tokenvault/BridgedERC721.sol index e39e320a1f..672bc55782 100644 --- a/packages/protocol/contracts/tokenvault/BridgedERC721.sol +++ b/packages/protocol/contracts/tokenvault/BridgedERC721.sol @@ -62,9 +62,7 @@ contract BridgedERC721 is } /// @inheritdoc IBridgedERC721 - function burn( - uint256 _tokenId - ) + function burn(uint256 _tokenId) external whenNotPaused onlyFromNamed(LibStrings.B_ERC721_VAULT) diff --git a/packages/protocol/contracts/tokenvault/ERC1155Vault.sol b/packages/protocol/contracts/tokenvault/ERC1155Vault.sol index 4f918ee912..3712356a3d 100644 --- a/packages/protocol/contracts/tokenvault/ERC1155Vault.sol +++ b/packages/protocol/contracts/tokenvault/ERC1155Vault.sol @@ -31,9 +31,7 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable { /// @param _op Option for sending the ERC1155 token. /// @return message_ The constructed message. - function sendToken( - BridgeTransferOp calldata _op - ) + function sendToken(BridgeTransferOp calldata _op) external payable whenNotPaused @@ -186,9 +184,7 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable { /// @dev See {BaseVault-supportsInterface}. /// @param _interfaceId The interface identifier. /// @return true if supports, else otherwise. - function supportsInterface( - bytes4 _interfaceId - ) + function supportsInterface(bytes4 _interfaceId) public view override(BaseVault, ERC1155ReceiverUpgradeable) @@ -235,9 +231,7 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable { /// @param _op BridgeTransferOp data. /// @return msgData_ Encoded message data. /// @return ctoken_ The canonical token. - function _handleMessage( - BridgeTransferOp calldata _op - ) + function _handleMessage(BridgeTransferOp calldata _op) private returns (bytes memory msgData_, CanonicalNFT memory ctoken_) { @@ -275,9 +269,7 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable { /// @dev Retrieve or deploy a bridged ERC1155 token contract. /// @param _ctoken CanonicalNFT data. /// @return btoken_ Address of the bridged token contract. - function _getOrDeployBridgedToken( - CanonicalNFT memory _ctoken - ) + function _getOrDeployBridgedToken(CanonicalNFT memory _ctoken) private returns (address btoken_) { diff --git a/packages/protocol/contracts/tokenvault/ERC20Vault.sol b/packages/protocol/contracts/tokenvault/ERC20Vault.sol index 3e99020d8d..830ebf48b5 100644 --- a/packages/protocol/contracts/tokenvault/ERC20Vault.sol +++ b/packages/protocol/contracts/tokenvault/ERC20Vault.sol @@ -239,9 +239,7 @@ contract ERC20Vault is BaseVault { /// invoking the message call. /// @param _op Option for sending ERC20 tokens. /// @return message_ The constructed message. - function sendToken( - BridgeTransferOp calldata _op - ) + function sendToken(BridgeTransferOp calldata _op) external payable whenNotPaused @@ -377,9 +375,7 @@ contract ERC20Vault is BaseVault { /// @return balanceChange_ User token balance actual change after the token /// transfer. This value is calculated so we do not assume token balance /// change is the amount of token transferred away. - function _handleMessage( - BridgeTransferOp calldata _op - ) + function _handleMessage(BridgeTransferOp calldata _op) private returns (bytes memory msgData_, CanonicalERC20 memory ctoken_, uint256 balanceChange_) { @@ -419,9 +415,7 @@ contract ERC20Vault is BaseVault { /// @dev Retrieve or deploy a bridged ERC20 token contract. /// @param ctoken CanonicalERC20 data. /// @return btoken Address of the bridged token contract. - function _getOrDeployBridgedToken( - CanonicalERC20 memory ctoken - ) + function _getOrDeployBridgedToken(CanonicalERC20 memory ctoken) private returns (address btoken) { diff --git a/packages/protocol/contracts/tokenvault/ERC721Vault.sol b/packages/protocol/contracts/tokenvault/ERC721Vault.sol index b07406cf89..812d9f4492 100644 --- a/packages/protocol/contracts/tokenvault/ERC721Vault.sol +++ b/packages/protocol/contracts/tokenvault/ERC721Vault.sol @@ -30,9 +30,7 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver { /// by invoking the message call. /// @param _op Option for sending the ERC721 token. /// @return message_ The constructed message. - function sendToken( - BridgeTransferOp calldata _op - ) + function sendToken(BridgeTransferOp calldata _op) external payable whenNotPaused @@ -83,9 +81,7 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver { } /// @inheritdoc IMessageInvocable - function onMessageInvocation( - bytes calldata _data - ) + function onMessageInvocation(bytes calldata _data) external payable whenNotPaused @@ -194,9 +190,7 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver { /// @param _op BridgeTransferOp data. /// @return msgData_ Encoded message data. /// @return ctoken_ The canonical token. - function _handleMessage( - BridgeTransferOp calldata _op - ) + function _handleMessage(BridgeTransferOp calldata _op) private returns (bytes memory msgData_, CanonicalNFT memory ctoken_) { @@ -230,9 +224,7 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver { /// @dev Retrieve or deploy a bridged ERC721 token contract. /// @param _ctoken CanonicalNFT data. /// @return btoken_ Address of the bridged token contract. - function _getOrDeployBridgedToken( - CanonicalNFT memory _ctoken - ) + function _getOrDeployBridgedToken(CanonicalNFT memory _ctoken) private returns (address btoken_) { diff --git a/packages/protocol/contracts/verifiers/IVerifier.sol b/packages/protocol/contracts/verifiers/IVerifier.sol index a3e0091fcd..1af91d9ca5 100644 --- a/packages/protocol/contracts/verifiers/IVerifier.sol +++ b/packages/protocol/contracts/verifiers/IVerifier.sol @@ -17,6 +17,17 @@ interface IVerifier { address msgSender; } + struct ContextV2 { + bytes32 metaHash; + bytes32 blobHash; + address prover; + uint64 blockId; + bool isContesting; + bool blobUsed; + address msgSender; + TaikoData.Transition tran; + } + /// @notice Verifies a proof. /// @param _ctx The context of the proof verification. /// @param _tran The transition to verify. @@ -27,4 +38,13 @@ interface IVerifier { TaikoData.TierProof calldata _proof ) external; + + /// @notice Verifies multiple proofs. + /// @param _ctxs The array of contexts for the proof verifications. + /// @param _proof The batch proof to verify. + function verifyBatchProof( + ContextV2[] calldata _ctxs, + TaikoData.TierProof calldata _proof + ) + external; } diff --git a/packages/protocol/contracts/verifiers/Risc0Verifier.sol b/packages/protocol/contracts/verifiers/Risc0Verifier.sol index 92b9ec9e02..037f22d6c1 100644 --- a/packages/protocol/contracts/verifiers/Risc0Verifier.sol +++ b/packages/protocol/contracts/verifiers/Risc0Verifier.sol @@ -78,6 +78,16 @@ contract Risc0Verifier is EssentialContract, IVerifier { } } + /// @inheritdoc IVerifier + function verifyBatchProof( + ContextV2[] calldata, /*_ctxs*/ + TaikoData.TierProof calldata /*_proof*/ + ) + external + pure + notImplemented + { } + function taikoChainId() internal view virtual returns (uint64) { return ITaikoL1(resolve(LibStrings.B_TAIKO, false)).getConfig().chainId; } diff --git a/packages/protocol/contracts/verifiers/SP1Verifier.sol b/packages/protocol/contracts/verifiers/SP1Verifier.sol index 90b627d78c..07b84c61d6 100644 --- a/packages/protocol/contracts/verifiers/SP1Verifier.sol +++ b/packages/protocol/contracts/verifiers/SP1Verifier.sol @@ -76,6 +76,16 @@ contract SP1Verifier is EssentialContract, IVerifier { } } + /// @inheritdoc IVerifier + function verifyBatchProof( + ContextV2[] calldata, /*_ctxs*/ + TaikoData.TierProof calldata /*_proof*/ + ) + external + pure + notImplemented + { } + function taikoChainId() internal view virtual returns (uint64) { return ITaikoL1(resolve(LibStrings.B_TAIKO, false)).getConfig().chainId; } diff --git a/packages/protocol/contracts/verifiers/SgxVerifier.sol b/packages/protocol/contracts/verifiers/SgxVerifier.sol index 9dd5cc7526..6de0560219 100644 --- a/packages/protocol/contracts/verifiers/SgxVerifier.sol +++ b/packages/protocol/contracts/verifiers/SgxVerifier.sol @@ -88,9 +88,7 @@ contract SgxVerifier is EssentialContract, IVerifier { /// @notice Adds trusted SGX instances to the registry. /// @param _instances The address array of trusted SGX instances. /// @return The respective instanceId array per addresses. - function addInstances( - address[] calldata _instances - ) + function addInstances(address[] calldata _instances) external onlyOwner returns (uint256[] memory) @@ -100,9 +98,7 @@ contract SgxVerifier is EssentialContract, IVerifier { /// @notice Deletes SGX instances from the registry. /// @param _ids The ids array of SGX instances. - function deleteInstances( - uint256[] calldata _ids - ) + function deleteInstances(uint256[] calldata _ids) external onlyFromOwnerOrNamed(LibStrings.B_SGX_WATCHDOG) { @@ -120,9 +116,7 @@ contract SgxVerifier is EssentialContract, IVerifier { /// @notice Adds an SGX instance after the attestation is verified /// @param _attestation The parsed attestation quote. /// @return The respective instanceId - function registerInstance( - V3Struct.ParsedV3QuoteStruct calldata _attestation - ) + function registerInstance(V3Struct.ParsedV3QuoteStruct calldata _attestation) external returns (uint256) { @@ -175,6 +169,17 @@ contract SgxVerifier is EssentialContract, IVerifier { } } + /// @inheritdoc IVerifier + function verifyBatchProof( + ContextV2[] calldata, /*_ctxs*/ + TaikoData.TierProof calldata /*_proof*/ + ) + external + view + notImplemented + onlyFromNamedEither(LibStrings.B_TAIKO, LibStrings.B_TIER_TEE_ANY) + { } + function taikoChainId() internal view virtual returns (uint64) { return ITaikoL1(resolve(LibStrings.B_TAIKO, false)).getConfig().chainId; } diff --git a/packages/protocol/contracts/verifiers/compose/ComposeVerifier.sol b/packages/protocol/contracts/verifiers/compose/ComposeVerifier.sol index dac33e9077..e7f3ecce5b 100644 --- a/packages/protocol/contracts/verifiers/compose/ComposeVerifier.sol +++ b/packages/protocol/contracts/verifiers/compose/ComposeVerifier.sol @@ -25,6 +25,11 @@ abstract contract ComposeVerifier is EssentialContract, IVerifier { error CV_INVALID_SUBPROOF_LENGTH(); error CV_SUB_VERIFIER_NOT_FOUND(); + modifier onlyAuthorizedCaller() { + if (!isCallerAuthorized(msg.sender)) revert CV_INVALID_CALLER(); + _; + } + /// @notice Initializes the contract. /// @param _owner The owner of this contract. msg.sender will be used if this value is zero. /// @param _rollupAddressManager The address of the {AddressManager} contract. @@ -32,17 +37,14 @@ abstract contract ComposeVerifier is EssentialContract, IVerifier { __Essential_init(_owner, _rollupAddressManager); } - /// @notice Verifies one or more sub-proofs. - /// @param _ctx The context of the proof verification. - /// @param _tran The transition to verify. - /// @param _proof The proof to verify. + /// @inheritdoc IVerifier function verifyProof( Context calldata _ctx, TaikoData.Transition calldata _tran, TaikoData.TierProof calldata _proof ) external - onlyFromNamed(LibStrings.B_TAIKO) + onlyAuthorizedCaller nonReentrant { (address[] memory verifiers, uint256 numSubProofs_) = getSubVerifiersAndThreshold(); @@ -70,6 +72,40 @@ abstract contract ComposeVerifier is EssentialContract, IVerifier { } } + /// @inheritdoc IVerifier + function verifyBatchProof( + ContextV2[] calldata _ctxs, + TaikoData.TierProof calldata _proof + ) + external + onlyFromNamed(LibStrings.B_TAIKO) + nonReentrant + { + (address[] memory verifiers, uint256 numSubProofs_) = getSubVerifiersAndThreshold(); + + SubProof[] memory subProofs = abi.decode(_proof.data, (SubProof[])); + if (subProofs.length != numSubProofs_) revert CV_INVALID_SUBPROOF_LENGTH(); + + for (uint256 i; i < subProofs.length; ++i) { + if (subProofs[i].verifier == address(0)) revert CV_DUPLICATE_SUBPROOF(); + + // find the verifier + bool verifierFound; + for (uint256 j; j < verifiers.length; ++j) { + if (verifiers[j] == subProofs[i].verifier) { + verifierFound = true; + verifiers[j] = address(0); + } + } + + if (!verifierFound) revert CV_SUB_VERIFIER_NOT_FOUND(); + + IVerifier(subProofs[i].verifier).verifyBatchProof( + _ctxs, TaikoData.TierProof(_proof.tier, subProofs[i].proof) + ); + } + } + /// @notice Returns the list of sub-verifiers and calculates the threshold. /// @return verifiers_ An array of addresses of sub-verifiers. /// @return numSubProofs_ The number of sub proofs required. @@ -78,4 +114,11 @@ abstract contract ComposeVerifier is EssentialContract, IVerifier { view virtual returns (address[] memory verifiers_, uint256 numSubProofs_); + + /// @notice Checks if the caller is authorized. + /// @param _caller The address of the caller to be checked. + /// @return A boolean value indicating whether the caller is authorized. + function isCallerAuthorized(address _caller) public view virtual returns (bool) { + return _caller == resolve(LibStrings.B_TAIKO, false); + } } diff --git a/packages/protocol/contracts/verifiers/compose/TeeAnyVerifier.sol b/packages/protocol/contracts/verifiers/compose/TeeAnyVerifier.sol index ab9c8590b0..668ff60780 100644 --- a/packages/protocol/contracts/verifiers/compose/TeeAnyVerifier.sol +++ b/packages/protocol/contracts/verifiers/compose/TeeAnyVerifier.sol @@ -5,12 +5,16 @@ import "../../common/LibStrings.sol"; import "./ComposeVerifier.sol"; /// @title TeeAnyVerifier -/// @notice This contract is a verifier for the Mainnet TEE proofs that composes SGX and TDX -/// Verifiers. /// @custom:security-contact security@taiko.xyz contract TeeAnyVerifier is ComposeVerifier { uint256[50] private __gap; + /// @inheritdoc ComposeVerifier + function isCallerAuthorized(address _caller) public view override returns (bool) { + return _caller == resolve(LibStrings.B_TAIKO, false) + || _caller == resolve(LibStrings.B_TIER_ZKVM_AND_TEE, true); + } + /// @inheritdoc ComposeVerifier function getSubVerifiersAndThreshold() public @@ -19,8 +23,8 @@ contract TeeAnyVerifier is ComposeVerifier { returns (address[] memory verifiers_, uint256 numSubProofs_) { verifiers_ = new address[](2); - verifiers_[0] = resolve(LibStrings.B_TIER_SGX, false); - verifiers_[1] = resolve(LibStrings.B_TIER_TDX, false); + verifiers_[0] = resolve(LibStrings.B_TIER_SGX, true); + verifiers_[1] = resolve(LibStrings.B_TIER_TDX, true); numSubProofs_ = 1; } } diff --git a/packages/protocol/contracts/verifiers/compose/ZkAndTeeVerifier.sol b/packages/protocol/contracts/verifiers/compose/ZkAndTeeVerifier.sol new file mode 100644 index 0000000000..c4c3b928d8 --- /dev/null +++ b/packages/protocol/contracts/verifiers/compose/ZkAndTeeVerifier.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import "../../common/LibStrings.sol"; +import "./ComposeVerifier.sol"; + +/// @title ZkAndTeeVerifier +/// @custom:security-contact security@taiko.xyz +contract ZkAndTeeVerifier is ComposeVerifier { + uint256[50] private __gap; + + /// @inheritdoc ComposeVerifier + function getSubVerifiersAndThreshold() + public + view + override + returns (address[] memory verifiers_, uint256 numSubProofs_) + { + verifiers_ = new address[](2); + verifiers_[0] = resolve(LibStrings.B_TIER_TEE_ANY, false); + verifiers_[1] = resolve(LibStrings.B_TIER_ZKVM_ANY, false); + numSubProofs_ = 2; + } +} diff --git a/packages/protocol/contracts/verifiers/compose/ZkAnyVerifier.sol b/packages/protocol/contracts/verifiers/compose/ZkAnyVerifier.sol index d574ca086f..c77e09c3db 100644 --- a/packages/protocol/contracts/verifiers/compose/ZkAnyVerifier.sol +++ b/packages/protocol/contracts/verifiers/compose/ZkAnyVerifier.sol @@ -5,12 +5,16 @@ import "../../common/LibStrings.sol"; import "./ComposeVerifier.sol"; /// @title ZkAnyVerifier -/// @notice This contract is a verifier for the Mainnet ZkVM that composes RiscZero and SP1 -/// Verifiers. /// @custom:security-contact security@taiko.xyz contract ZkAnyVerifier is ComposeVerifier { uint256[50] private __gap; + /// @inheritdoc ComposeVerifier + function isCallerAuthorized(address _caller) public view override returns (bool) { + return _caller == resolve(LibStrings.B_TAIKO, false) + || _caller == resolve(LibStrings.B_TIER_ZKVM_AND_TEE, true); + } + /// @inheritdoc ComposeVerifier function getSubVerifiersAndThreshold() public @@ -19,8 +23,8 @@ contract ZkAnyVerifier is ComposeVerifier { returns (address[] memory verifiers_, uint256 numSubProofs_) { verifiers_ = new address[](2); - verifiers_[0] = resolve(LibStrings.B_TIER_ZKVM_RISC0, false); - verifiers_[1] = resolve(LibStrings.B_TIER_ZKVM_SP1, false); + verifiers_[0] = resolve(LibStrings.B_TIER_ZKVM_RISC0, true); + verifiers_[1] = resolve(LibStrings.B_TIER_ZKVM_SP1, true); numSubProofs_ = 1; } } diff --git a/packages/protocol/deployments/gen-layouts.sh b/packages/protocol/deployments/gen-layouts.sh index 4070e434cc..98ff08392f 100755 --- a/packages/protocol/deployments/gen-layouts.sh +++ b/packages/protocol/deployments/gen-layouts.sh @@ -28,6 +28,7 @@ contracts=( "ComposeVerifier" "TeeAnyVerifier" "ZkAnyVerifier" + "ZkAndTeeVerifier" # Hekla contracts "HeklaTaikoL1" # Mainnet contracts @@ -41,6 +42,9 @@ contracts=( "MainnetSP1Verifier" "MainnetRollupAddressManager" "MainnetSgxVerifier" + "MainnetTeeAnyVerifier" + "MainnetZkAnyVerifier" + "MainnetZkAndTeeVerifier" "MainnetSharedAddressManager" "MainnetSignalService" "MainnetTaikoL1" diff --git a/packages/protocol/test/automata-attestation/utils/DcapTestUtils.t.sol b/packages/protocol/test/automata-attestation/utils/DcapTestUtils.t.sol index 26c4d0cdcb..a859d73a30 100644 --- a/packages/protocol/test/automata-attestation/utils/DcapTestUtils.t.sol +++ b/packages/protocol/test/automata-attestation/utils/DcapTestUtils.t.sol @@ -13,9 +13,7 @@ contract DcapTestUtils { uint256 constant INDEX_ERROR = type(uint256).max; - function parseTcbInfoJson( - string memory tcbInfoJsonStr - ) + function parseTcbInfoJson(string memory tcbInfoJsonStr) internal pure returns (bool success, TCBInfoStruct.TCBInfo memory tcbInfo) @@ -80,9 +78,7 @@ contract DcapTestUtils { bool tcbLevelsFound; } - function parseEnclaveIdentityJson( - string memory enclaveIdJsonStr - ) + function parseEnclaveIdentityJson(string memory enclaveIdJsonStr) internal pure returns (bool success, EnclaveIdStruct.EnclaveId memory enclaveId) diff --git a/packages/protocol/test/automata-attestation/utils/V3QuoteParseUtils.t.sol b/packages/protocol/test/automata-attestation/utils/V3QuoteParseUtils.t.sol index b52725b643..83b7e9a24a 100644 --- a/packages/protocol/test/automata-attestation/utils/V3QuoteParseUtils.t.sol +++ b/packages/protocol/test/automata-attestation/utils/V3QuoteParseUtils.t.sol @@ -80,9 +80,7 @@ contract V3QuoteParseUtils { ECDSAQuoteV3AuthDataHelper v3AuthData; } - function parseV3QuoteJson( - bytes memory v3QuotePacked - ) + function parseV3QuoteJson(bytes memory v3QuotePacked) internal pure returns (bool success, V3Struct.ParsedV3QuoteStruct memory v3quote) diff --git a/packages/protocol/test/thirdparty/Multicall3.sol b/packages/protocol/test/thirdparty/Multicall3.sol index 6861cb2e5b..e96d0d2d2b 100644 --- a/packages/protocol/test/thirdparty/Multicall3.sol +++ b/packages/protocol/test/thirdparty/Multicall3.sol @@ -42,9 +42,7 @@ contract Multicall3 { /// @param calls An array of Call structs /// @return blockNumber The block number where the calls were executed /// @return returnData An array of bytes containing the responses - function aggregate( - Call[] calldata calls - ) + function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) @@ -116,9 +114,7 @@ contract Multicall3 { /// @return blockNumber The block number where the calls were executed /// @return blockHash The hash of the block where the calls were executed /// @return returnData An array of Result structs - function blockAndAggregate( - Call[] calldata calls - ) + function blockAndAggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) @@ -129,9 +125,7 @@ contract Multicall3 { /// @notice Aggregate calls, ensuring each returns success if required /// @param calls An array of Call3 structs /// @return returnData An array of Result structs - function aggregate3( - Call3[] calldata calls - ) + function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) @@ -168,9 +162,7 @@ contract Multicall3 { /// @notice Reverts if msg.value is less than the sum of the call values /// @param calls An array of Call3Value structs /// @return returnData An array of Result structs - function aggregate3Value( - Call3Value[] calldata calls - ) + function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) diff --git a/packages/protocol/test/tokenvault/ERC1155Vault.t.sol b/packages/protocol/test/tokenvault/ERC1155Vault.t.sol index 6f8fe4daba..c7a4853e66 100644 --- a/packages/protocol/test/tokenvault/ERC1155Vault.t.sol +++ b/packages/protocol/test/tokenvault/ERC1155Vault.t.sol @@ -34,9 +34,7 @@ contract PrankDestBridge { destERC1155Vault = ERC1155Vault(addr); } - function sendMessage( - IBridge.Message memory message - ) + function sendMessage(IBridge.Message memory message) external payable returns (bytes32 msgHash, IBridge.Message memory _message) diff --git a/packages/protocol/test/tokenvault/ERC20Vault.t.sol b/packages/protocol/test/tokenvault/ERC20Vault.t.sol index 9d567bd30e..e2079cfc5d 100644 --- a/packages/protocol/test/tokenvault/ERC20Vault.t.sol +++ b/packages/protocol/test/tokenvault/ERC20Vault.t.sol @@ -416,9 +416,7 @@ contract TestERC20Vault is TaikoTest { assertEq(bridgedERC20.balanceOf(Bob), amount); } - function erc20ToCanonicalERC20( - uint64 chainId - ) + function erc20ToCanonicalERC20(uint64 chainId) internal view returns (ERC20Vault.CanonicalERC20 memory) diff --git a/packages/protocol/test/tokenvault/ERC721Vault.t.sol b/packages/protocol/test/tokenvault/ERC721Vault.t.sol index 375c20b0ae..c43ed5fde0 100644 --- a/packages/protocol/test/tokenvault/ERC721Vault.t.sol +++ b/packages/protocol/test/tokenvault/ERC721Vault.t.sol @@ -50,9 +50,7 @@ contract PrankDestBridge { destERC721Vault = ERC721Vault(addr); } - function sendMessage( - IBridge.Message memory message - ) + function sendMessage(IBridge.Message memory message) external payable returns (bytes32 msgHash, IBridge.Message memory _message) diff --git a/packages/protocol/test/verifiers/compose/ComposeVerifeir.t.sol b/packages/protocol/test/verifiers/compose/ComposeVerifeir.t.sol index 0b6b9949e6..b403cb5dcf 100644 --- a/packages/protocol/test/verifiers/compose/ComposeVerifeir.t.sol +++ b/packages/protocol/test/verifiers/compose/ComposeVerifeir.t.sol @@ -51,6 +51,17 @@ contract MockVerifier is IVerifier { revert("MockVerifier: Verification failed"); } } + + function verifyBatchProof( + ContextV2[] calldata, + TaikoData.TierProof calldata + ) + external + pure + override + { + revert("NOT_IMPLEMENTED"); + } } contract ComposeVerifierTest is TaikoTest {