From 1a661093324e6fe594bb241350e49e74a21c6ea7 Mon Sep 17 00:00:00 2001 From: Michael de Hoog Date: Mon, 9 Dec 2024 14:53:29 -1000 Subject: [PATCH] Implement ability to switch TEE proofs on after genesis --- script/DeploySystem.s.sol | 2 +- src/DeployChain.sol | 10 ++++++---- src/OutputOracle.sol | 39 +++++++++++++++++++++++++++------------ 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/script/DeploySystem.s.sol b/script/DeploySystem.s.sol index 4f0d539..0311ffd 100644 --- a/script/DeploySystem.s.sol +++ b/script/DeploySystem.s.sol @@ -313,7 +313,7 @@ contract DeploySystem is Deploy { _upgradeAndCallViaSafe({ _proxy: payable(l2OutputOracleProxy), _implementation: l2OutputOracle, - _innerCallData: abi.encodeCall(OutputOracle.initialize, (SystemConfigOwnable(systemConfigProxy), 0, 0)) + _innerCallData: abi.encodeCall(OutputOracle.initialize, (SystemConfigOwnable(systemConfigProxy), 0, 0, false)) }); OutputOracle oracle = OutputOracle(l2OutputOracleProxy); diff --git a/src/DeployChain.sol b/src/DeployChain.sol index 6460dfd..89b57bd 100644 --- a/src/DeployChain.sol +++ b/src/DeployChain.sol @@ -116,7 +116,8 @@ contract DeployChain { uint256 chainID, GenesisConfiguration memory genesisConfig, GasConfiguration memory gasConfig, - AddressConfiguration memory addressConfig + AddressConfiguration memory addressConfig, + bool proofsEnabled ) external { DeployAddresses memory addresses = setupProxies(chainID); @@ -124,7 +125,7 @@ contract DeployChain { address batchInbox = calculateBatchInbox(chainID); - initializeProxies(gasConfig, addressConfig, batchInbox, hashes, addresses); + initializeProxies(gasConfig, addressConfig, batchInbox, hashes, addresses, proofsEnabled); emit Deploy({ chainID: chainID, @@ -205,10 +206,11 @@ contract DeployChain { AddressConfiguration memory addressConfig, address batchInbox, Hashes memory hashes, - DeployAddresses memory addresses + DeployAddresses memory addresses, + bool proofsEnabled ) internal { OutputOracle(addresses.l2OutputOracle).initialize( - SystemConfigOwnable(addresses.systemConfig), hashes.configHash, hashes.genesisOutputRoot + SystemConfigOwnable(addresses.systemConfig), hashes.configHash, hashes.genesisOutputRoot, proofsEnabled ); Portal(payable(addresses.optimismPortal)).initialize( diff --git a/src/OutputOracle.sol b/src/OutputOracle.sol index c36116a..4fe1b11 100644 --- a/src/OutputOracle.sol +++ b/src/OutputOracle.sol @@ -42,6 +42,9 @@ contract OutputOracle is Initializable, ISemver { /// @notice An array of L2 output proposals. Types.OutputProposal[] internal l2Outputs; + /// @notice Whether or not TEE proofs are enabled. + bool public proofsEnabled; + /// @notice Pointer inside l2Outputs to the latest submitted output. uint256 public latestOutputIndex; @@ -65,14 +68,16 @@ contract OutputOracle is Initializable, ISemver { constructor(SystemConfigGlobal _systemConfigGlobal, uint256 _maxOutputCount) { systemConfigGlobal = _systemConfigGlobal; maxOutputCount = _maxOutputCount; - initialize(SystemConfigOwnable(address(0)), 0, 0); + initialize(SystemConfigOwnable(address(0)), 0, 0, false); } /// @notice Initializer. - function initialize(SystemConfigOwnable _systemConfig, bytes32 _configHash, bytes32 _genesisOutputRoot) - public - initializer - { + function initialize( + SystemConfigOwnable _systemConfig, + bytes32 _configHash, + bytes32 _genesisOutputRoot, + bool _proofsEnabled + ) public initializer { systemConfig = _systemConfig; configHash = _configHash; l2Outputs.push( @@ -82,13 +87,21 @@ contract OutputOracle is Initializable, ISemver { l2BlockNumber: uint128(0) }) ); + proofsEnabled = _proofsEnabled; } + /// @notice Returns the proposer address. function proposer() public view returns (address) { address _proposer = address(systemConfig) != address(0) ? systemConfig.proposer() : address(0); return _proposer != address(0) ? _proposer : systemConfigGlobal.proposer(); } + /// @notice Enables TEE proofs for output proposals. This is a one-way function. + function enableProofs() external { + require(msg.sender == proposer(), "OutputOracle: only the proposer address can enable proofs"); + proofsEnabled = true; + } + /// @notice Accepts an outputRoot of the corresponding L2 block. /// @param _outputRoot The L2 output of the checkpoint block. /// @param _l2BlockNumber The L2 block number that resulted in _outputRoot. @@ -107,14 +120,16 @@ contract OutputOracle is Initializable, ISemver { require(_outputRoot != bytes32(0), "OutputOracle: L2 output proposal cannot be the zero hash"); - bytes32 _blockHash = blockhash(_l1BlockNumber); - require(_blockHash != bytes32(0), "OutputOracle: blockhash not available"); + if (proofsEnabled) { + bytes32 _blockHash = blockhash(_l1BlockNumber); + require(_blockHash != bytes32(0), "OutputOracle: blockhash not available"); - bytes32 previousOutputRoot = l2Outputs[latestOutputIndex].outputRoot; - address signer = ECDSA.recover( - keccak256(abi.encodePacked(configHash, _blockHash, previousOutputRoot, _outputRoot)), _signature - ); - require(systemConfigGlobal.validSigners(signer), "OutputOracle: invalid signature"); + bytes32 previousOutputRoot = l2Outputs[latestOutputIndex].outputRoot; + address signer = ECDSA.recover( + keccak256(abi.encodePacked(configHash, _blockHash, previousOutputRoot, _outputRoot)), _signature + ); + require(systemConfigGlobal.validSigners(signer), "OutputOracle: invalid signature"); + } latestOutputIndex = nextOutputIndex(); emit OutputProposed(_outputRoot, latestOutputIndex, _l2BlockNumber, block.timestamp);