diff --git a/README.md b/README.md index 7d53df1e94..5338581edb 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ [![Solidity](https://github.com/taikoxyz/taiko-mono/actions/workflows/solidity.yml/badge.svg)](https://github.com/taikoxyz/taiko-mono/actions/workflows/solidity.yml) [![Protocol](https://codecov.io/gh/taikoxyz/taiko-mono/branch/main/graph/badge.svg?token=E468X2PTJC&flag=protocol)](https://codecov.io/gh/taikoxyz/taiko-mono) -[![Golang](https://github.com/taikoxyz/taiko-mono/actions/workflows/golang.yml/badge.svg)](https://github.com/taikoxyz/taiko-mono/actions/workflows/golang.yml) [![Relayer](https://codecov.io/gh/taikoxyz/taiko-mono/branch/main/graph/badge.svg?token=E468X2PTJC&flag=relayer)](https://codecov.io/gh/taikoxyz/taiko-mono) +[![Golang](https://github.com/taikoxyz/taiko-mono/actions/workflows/golang.yml/badge.svg)](https://github.com/taikoxyz/taiko-mono/actions/workflows/golang.yml) +[![Relayer](https://codecov.io/gh/taikoxyz/taiko-mono/branch/main/graph/badge.svg?token=E468X2PTJC&flag=relayer)](https://codecov.io/gh/taikoxyz/taiko-mono)
diff --git a/codecov.yml b/codecov.yml index 6446305235..d1c7aa69fe 100644 --- a/codecov.yml +++ b/codecov.yml @@ -3,6 +3,20 @@ coverage: - "packages/relayer/contracts/**/*" - "packages/relayer/mock/**/*" - "packages/relayer/cmd/**/*" + status: + project: off + patch: off + +flag_management: + default_rules: + carryforward: true + individual_flags: + - name: protocol + paths: + - packages/protocol/**/* + - name: relayer + paths: + - packages/relayer/**/* comment: - show_carryforward_flags: true \ No newline at end of file + show_carryforward_flags: true diff --git a/packages/protocol/contracts/L1/LibData.sol b/packages/protocol/contracts/L1/LibData.sol index 5b22387b9f..04c6f6aafb 100644 --- a/packages/protocol/contracts/L1/LibData.sol +++ b/packages/protocol/contracts/L1/LibData.sol @@ -43,6 +43,7 @@ library LibData { // block id => parent hash => fork choice mapping(uint256 => mapping(bytes32 => ForkChoice)) forkChoices; mapping(bytes32 => uint256) commits; + mapping(address => bool) provers; // Whitelisted provers uint64 genesisHeight; uint64 latestFinalizedHeight; uint64 latestFinalizedId; diff --git a/packages/protocol/contracts/L1/TaikoL1.sol b/packages/protocol/contracts/L1/TaikoL1.sol index c038ae4401..2d4a8e7513 100644 --- a/packages/protocol/contracts/L1/TaikoL1.sol +++ b/packages/protocol/contracts/L1/TaikoL1.sol @@ -28,7 +28,7 @@ contract TaikoL1 is EssentialContract, IHeaderSync, V1Events { using SafeCastUpgradeable for uint256; LibData.State public state; - uint256[45] private __gap; + uint256[44] private __gap; function init( address _addressManager, @@ -134,6 +134,29 @@ contract TaikoL1 is EssentialContract, IHeaderSync, V1Events { ); } + /** + * Add or remove a prover from the whitelist. + * + * @param prover The prover to be added or removed. + * @param whitelisted True to add; remove otherwise. + */ + function whitelistProver( + address prover, + bool whitelisted + ) public onlyOwner { + V1Proving.whitelistProver(state, prover, whitelisted); + } + + /** + * Return whether a prover is whitelisted. + * + * @param prover The prover. + * @return True if the prover is whitelisted, false otherwise. + */ + function isProverWhitelisted(address prover) public view returns (bool) { + return V1Proving.isProverWhitelisted(state, prover); + } + /// @notice Finalize up to N blocks. /// @param maxBlocks Max number of blocks to finalize. function finalizeBlocks(uint256 maxBlocks) external nonReentrant { diff --git a/packages/protocol/contracts/L1/v1/V1Events.sol b/packages/protocol/contracts/L1/v1/V1Events.sol index e870d63ed9..90f0ca94c3 100644 --- a/packages/protocol/contracts/L1/v1/V1Events.sol +++ b/packages/protocol/contracts/L1/v1/V1Events.sol @@ -27,4 +27,6 @@ abstract contract V1Events { uint64 provenAt, address prover ); + + event ProverWhitelisted(address indexed prover, bool whitelisted); } diff --git a/packages/protocol/contracts/L1/v1/V1Proving.sol b/packages/protocol/contracts/L1/v1/V1Proving.sol index 85fb5ad74d..0be26baf0e 100644 --- a/packages/protocol/contracts/L1/v1/V1Proving.sol +++ b/packages/protocol/contracts/L1/v1/V1Proving.sol @@ -46,12 +46,21 @@ library V1Proving { address prover ); + event ProverWhitelisted(address indexed prover, bool whitelisted); + + modifier onlyWhitelistedProver(LibData.State storage s) { + if (LibConstants.K_WHITELIST_PROVERS) { + require(s.provers[msg.sender], "L1:whitelist"); + } + _; + } + function proveBlock( LibData.State storage s, AddressResolver resolver, uint256 blockIndex, bytes[] calldata inputs - ) public { + ) public onlyWhitelistedProver(s) { // Check and decode inputs require(inputs.length == 3, "L1:inputs:size"); Evidence memory evidence = abi.decode(inputs[0], (Evidence)); @@ -126,7 +135,7 @@ library V1Proving { AddressResolver resolver, uint256 blockIndex, bytes[] calldata inputs - ) public { + ) public onlyWhitelistedProver(s) { // Check and decode inputs require(inputs.length == 3, "L1:inputs:size"); Evidence memory evidence = abi.decode(inputs[0], (Evidence)); @@ -182,6 +191,29 @@ library V1Proving { ); } + function whitelistProver( + LibData.State storage s, + address prover, + bool enabled + ) public { + require(LibConstants.K_WHITELIST_PROVERS, "L1:featureDisabled"); + require( + prover != address(0) && s.provers[prover] != enabled, + "L1:precondition" + ); + + s.provers[prover] = enabled; + emit ProverWhitelisted(prover, enabled); + } + + function isProverWhitelisted( + LibData.State storage s, + address prover + ) public view returns (bool) { + require(LibConstants.K_WHITELIST_PROVERS, "L1:featureDisabled"); + return s.provers[prover]; + } + function _proveBlock( LibData.State storage s, AddressResolver resolver, diff --git a/packages/protocol/contracts/libs/LibConstants.sol b/packages/protocol/contracts/libs/LibConstants.sol index 98593758d6..870c512288 100644 --- a/packages/protocol/contracts/libs/LibConstants.sol +++ b/packages/protocol/contracts/libs/LibConstants.sol @@ -31,4 +31,6 @@ library LibConstants { bytes32 public constant V1_INVALIDATE_BLOCK_LOG_TOPIC = keccak256("BlockInvalidated(bytes32)"); + + bool public constant K_WHITELIST_PROVERS = false; } diff --git a/packages/protocol/contracts/test/bridge/libs/TestBadReceiver.sol b/packages/protocol/contracts/test/bridge/libs/TestBadReceiver.sol index 0ed64f9bc8..2a050934a0 100644 --- a/packages/protocol/contracts/test/bridge/libs/TestBadReceiver.sol +++ b/packages/protocol/contracts/test/bridge/libs/TestBadReceiver.sol @@ -8,7 +8,6 @@ // ╱╱╰╯╰╯╰┻┻╯╰┻━━╯╰━━━┻╯╰┻━━┻━━╯ pragma solidity ^0.8.9; - contract TestBadReceiver { receive() external payable { revert("can not send to this contract"); diff --git a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeRetry.sol b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeRetry.sol index 512a4efd18..8de54c2eaf 100644 --- a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeRetry.sol +++ b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeRetry.sol @@ -21,10 +21,10 @@ contract TestLibBridgeRetry is EssentialContract { EssentialContract._init(_addressManager); } - function retryMessage(IBridge.Message calldata message, bool lastAttempt) - public - payable - { + function retryMessage( + IBridge.Message calldata message, + bool lastAttempt + ) public payable { LibBridgeRetry.retryMessage( state, AddressResolver(this), diff --git a/packages/protocol/contracts/test/thirdparty/TestMessageSender.sol b/packages/protocol/contracts/test/thirdparty/TestMessageSender.sol index 0a907dea5c..a5fd7697b4 100644 --- a/packages/protocol/contracts/test/thirdparty/TestMessageSender.sol +++ b/packages/protocol/contracts/test/thirdparty/TestMessageSender.sol @@ -4,8 +4,8 @@ pragma solidity ^0.8.9; import "../../bridge/IBridge.sol"; contract TestMessageSender { - - bytes32 signal = 0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abab; + bytes32 signal = + 0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abab; function sendMessage( IBridge.Message calldata message