Skip to content

Commit

Permalink
feat(protocol): add a batch proposing block function (#17864)
Browse files Browse the repository at this point in the history
Co-authored-by: d1onys1us <13951458+d1onys1us@users.noreply.github.com>
  • Loading branch information
dantaik and dionysuzx authored Jul 30, 2024
1 parent a962b06 commit 3649785
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 18 deletions.
13 changes: 12 additions & 1 deletion packages/protocol/contracts/L1/ITaikoL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface ITaikoL1 {
returns (TaikoData.BlockMetadata memory meta_, TaikoData.EthDeposit[] memory deposits_);

/// @notice Proposes a Taiko L2 block (version 2)
/// @param _params Block parameters, currently an encoded BlockParams object.
/// @param _params Block parameters, an encoded BlockParamsV2 object.
/// @param _txList txList data if calldata is used for DA.
/// @return meta_ The metadata of the proposed L2 block.
function proposeBlockV2(
Expand All @@ -30,6 +30,17 @@ interface ITaikoL1 {
external
returns (TaikoData.BlockMetadataV2 memory meta_);

/// @notice Proposes a Taiko L2 block (version 2)
/// @param _paramsArr A list of encoded BlockParamsV2 objects.
/// @param _txListArr A list of txList.
/// @return metaArr_ The metadata objects of the proposed L2 blocks.
function proposeBlocksV2(
bytes[] calldata _paramsArr,
bytes[] calldata _txListArr
)
external
returns (TaikoData.BlockMetadataV2[] memory metaArr_);

/// @notice Proves or contests a block transition.
/// @param _blockId The index of the block to prove. This is also used to
/// select the right implementation version.
Expand Down
53 changes: 47 additions & 6 deletions packages/protocol/contracts/L1/TaikoL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents {
uint256[50] private __gap;

error L1_FORK_ERROR();
error L1_INVALID_PARAMS();
error L1_RECEIVE_DISABLED();

modifier whenProvingNotPaused() {
Expand All @@ -37,6 +38,11 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents {
emit StateVariablesUpdated(state.slotB);
}

modifier onlyRegisteredProposer() {
LibProposing.checkProposerPermission(this);
_;
}

/// @dev Allows for receiving Ether from Hooks
receive() external payable {
if (!inNonReentrant()) revert L1_RECEIVE_DISABLED();
Expand Down Expand Up @@ -76,6 +82,7 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents {
)
external
payable
onlyRegisteredProposer
whenNotPaused
nonReentrant
emitEventForClient
Expand All @@ -96,18 +103,36 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents {
bytes calldata _txList
)
external
onlyRegisteredProposer
whenNotPaused
nonReentrant
emitEventForClient
returns (TaikoData.BlockMetadataV2 memory meta_)
returns (TaikoData.BlockMetadataV2 memory)
{
TaikoData.Config memory config = getConfig();
return _proposeBlock(_params, _txList, getConfig());
}

(, meta_,) = LibProposing.proposeBlock(state, config, this, _params, _txList);
if (meta_.id < config.ontakeForkHeight) revert L1_FORK_ERROR();
/// @inheritdoc ITaikoL1
function proposeBlocksV2(
bytes[] calldata _paramsArr,
bytes[] calldata _txListArr
)
external
onlyRegisteredProposer
whenNotPaused
nonReentrant
emitEventForClient
returns (TaikoData.BlockMetadataV2[] memory metaArr_)
{
if (_paramsArr.length == 0 || _paramsArr.length != _txListArr.length) {
revert L1_INVALID_PARAMS();
}

if (LibUtils.shouldVerifyBlocks(config, meta_.id, true) && !state.slotB.provingPaused) {
LibVerifying.verifyBlocks(state, config, this, config.maxBlocksToVerify);
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);
}
}

Expand Down Expand Up @@ -276,6 +301,22 @@ 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);
}
}

/// @dev chain_pauser is supposed to be a cold wallet.
function _authorizePause(
address,
Expand Down
19 changes: 9 additions & 10 deletions packages/protocol/contracts/L1/libs/LibProposing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ library LibProposing {
struct Local {
TaikoData.SlotB b;
TaikoData.BlockParamsV2 params;
address proposerAccess;
ITierProvider tierProvider;
bytes32 parentMetaHash;
bool postFork;
Expand Down Expand Up @@ -82,15 +81,6 @@ library LibProposing {
{
// Checks proposer access.
Local memory local;

local.proposerAccess = _resolver.resolve(LibStrings.B_PROPOSER_ACCESS, true);
if (
local.proposerAccess != address(0)
&& !IProposerAccess(local.proposerAccess).isProposerEligible(msg.sender)
) {
revert L1_INVALID_PROPOSER();
}

local.b = _state.slotB;
local.postFork = local.b.numBlocks >= _config.ontakeForkHeight;

Expand Down Expand Up @@ -263,4 +253,13 @@ library LibProposing {
});
}
}

function checkProposerPermission(IAddressResolver _resolver) internal view {
address proposerAccess = _resolver.resolve(LibStrings.B_PROPOSER_ACCESS, true);
if (proposerAccess == address(0)) return;

if (!IProposerAccess(proposerAccess).isProposerEligible(msg.sender)) {
revert L1_INVALID_PROPOSER();
}
}
}
2 changes: 1 addition & 1 deletion packages/protocol/contracts/L1/libs/LibProving.sol
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ library LibProving {
uint64 _blockId,
bytes calldata _input
)
internal
public
{
Local memory local;

Expand Down

0 comments on commit 3649785

Please sign in to comment.