Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(protocol): add preconfirmation support [helder] #17654

Closed
wants to merge 49 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
e69e360
make block metadata predictable longer + sequencer registry
Brechtpd Jun 23, 2024
f27e0b7
feedback
Brechtpd Jun 24, 2024
ee84153
order alphabetically
Brechtpd Jun 24, 2024
d59db31
Allow proposer to also choose the timestamp
Brechtpd Jun 25, 2024
fac9ba8
fix issue with difficulty not being independent of L1 slot or proposing
Brechtpd Jun 25, 2024
6ef1726
fix timestamp range check
Brechtpd Jun 25, 2024
de08795
fix ci
Brechtpd Jun 27, 2024
b5036c3
Merge remote-tracking branch 'origin/helder' into preconfirmations
Brechtpd Jun 27, 2024
3e0c74c
forge fmt & update contract layout table
Brechtpd Jun 27, 2024
015ed34
increase allowed L1 data window
Brechtpd Jun 28, 2024
23351f8
comment out some checks/unused functionality to make TaikoL1 deployable
Brechtpd Jun 29, 2024
d021b0d
forge fmt & update contract layout table
Brechtpd Jun 29, 2024
9e97bbf
add back simplified EOA check for now
Brechtpd Jun 30, 2024
507149b
Merge remote-tracking branch 'origin/preconfirmations' into preconfir…
Brechtpd Jun 30, 2024
4bbe16e
fix check
Brechtpd Jun 30, 2024
c29759f
nevermind disable check again to keep tests running
Brechtpd Jun 30, 2024
a68a163
enable check (I can't read)
Brechtpd Jun 30, 2024
d9fbe44
set proving window to 0 so anybody can prove blocks directly (with TKO)
Brechtpd Jul 1, 2024
0986e22
deploy and register sequencer registry
cyberhorsey Jul 2, 2024
3628ae7
forge fmt & update contract layout table
cyberhorsey Jul 2, 2024
ed709d7
.
cyberhorsey Jul 2, 2024
999e5d4
.
cyberhorsey Jul 2, 2024
0a89fa0
forge fmt & update contract layout table
cyberhorsey Jul 2, 2024
6a0f394
rm unused stuff
cyberhorsey Jul 3, 2024
f4e602a
forge fmt & update contract layout table
cyberhorsey Jul 3, 2024
63ba193
rm bridge copy
cyberhorsey Jul 3, 2024
2052946
Merge branch 'preconfirmations' of github.com:taikoxyz/taiko-mono int…
cyberhorsey Jul 3, 2024
967f7ee
forge fmt & update contract layout table
cyberhorsey Jul 3, 2024
5962ba9
calldata check fix
cyberhorsey Jul 5, 2024
157cd13
feat(protocol): allow contracts to propose (#17744)
cyberhorsey Jul 5, 2024
7451a5a
feat(protocol): propose multiple blocks in one call (#17787)
cyberhorsey Jul 13, 2024
c00bfb5
conversion fix
cyberhorsey Jul 13, 2024
8439b00
lint
cyberhorsey Jul 13, 2024
d1ecef2
forge fmt & update contract layout table
cyberhorsey Jul 13, 2024
4699f96
.
cyberhorsey Jul 13, 2024
14f5b94
forge fmt & update contract layout table
cyberhorsey Jul 13, 2024
0b2a987
feat(taiko-client): updates for protocol preconfirmation changes (#17…
davidtaikocha Jul 16, 2024
c4fe319
.
cyberhorsey Jul 16, 2024
73048c2
proposeBlocks as well as proposeBlock
cyberhorsey Jul 16, 2024
4205b96
lint
cyberhorsey Jul 16, 2024
c0f3b38
rm prove/verify block for code size temporarily, not being used
cyberhorsey Jul 16, 2024
0e03c3c
forge fmt & update contract layout table
cyberhorsey Jul 16, 2024
b38bd37
update taikoevents
cyberhorsey Jul 16, 2024
1b6fd86
Merge branch 'preconfirmations' of github.com:taikoxyz/taiko-mono int…
cyberhorsey Jul 16, 2024
a383b19
add offset/len
cyberhorsey Jul 17, 2024
1d1c41f
.
cyberhorsey Jul 17, 2024
284ef1a
feat(taiko-client): preconfirmation indexing (#17866)
cyberhorsey Aug 12, 2024
6579417
proposeblocks api fix
cyberhorsey Aug 14, 2024
915f888
log
cyberhorsey Aug 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions packages/protocol/contracts/L1/ISequencerRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

/// @title ISequencerRegistry
/// @custom:security-contact [email protected]
interface ISequencerRegistry {
/// @notice Return true if the specified address can propose blocks, false otherwise
/// @param _proposer The address proposing a block
function isEligibleSigner(address _proposer) external returns (bool);
}
44 changes: 44 additions & 0 deletions packages/protocol/contracts/L1/SequencerRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import "../common/EssentialContract.sol";
import "./ISequencerRegistry.sol";

/// @title SequencerRegistry
/// A dummy implementation that only whitelist some trusted addresses. A real
/// implementation would only allow a single proposer address to propose a block
/// using some selection mechanism.
/// @custom:security-contact [email protected]
contract SequencerRegistry is EssentialContract, ISequencerRegistry {
dantaik marked this conversation as resolved.
Show resolved Hide resolved
/// @notice Whitelisted sequencers
mapping(address sequencer => bool enabled) public sequencers;

uint256[49] private __gap;

/// @notice Initializes the contract with the provided address manager.
/// @param _owner The address of the owner.
function init(address _owner) external initializer {
__Essential_init(_owner);
}

/// @notice Sets/unsets an the imageId as trusted entity
/// @param _sequencers The list of sequencers
/// @param _enabled The corresponing list of the new status of the sequencers

Check warning on line 26 in packages/protocol/contracts/L1/SequencerRegistry.sol

View workflow job for this annotation

GitHub Actions / check-for-typos

"corresponing" should be "corresponding".
function setSequencers(
address[] memory _sequencers,
bool[] memory _enabled
)
external
onlyOwner
{
require(_sequencers.length == _enabled.length, "invalid input data");
for (uint256 i = 0; i < _sequencers.length; i++) {
sequencers[_sequencers[i]] = _enabled[i];
Brechtpd marked this conversation as resolved.
Show resolved Hide resolved
}
}

/// @inheritdoc ISequencerRegistry
function isEligibleSigner(address _proposer) external view returns (bool) {
return sequencers[_proposer];
}
}
4 changes: 3 additions & 1 deletion packages/protocol/contracts/L1/TaikoData.sol
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ library TaikoData {
bytes32 parentMetaHash;
HookCall[] hookCalls; // DEPRECATED, value ignored.
bytes signature;
uint32 l1StateBlockNumber;
dantaik marked this conversation as resolved.
Show resolved Hide resolved
Brechtpd marked this conversation as resolved.
Show resolved Hide resolved
}

/// @dev Struct containing data only required for proving a block
Expand Down Expand Up @@ -124,6 +125,7 @@ library TaikoData {
// this block is not verified as the last block in a batch, verifiedTransitionId
// will remain zero.
uint32 verifiedTransitionId;
uint64 l1StateBlockNumber;
dantaik marked this conversation as resolved.
Show resolved Hide resolved
dantaik marked this conversation as resolved.
Show resolved Hide resolved
}

/// @dev Struct representing an Ethereum deposit.
Expand Down Expand Up @@ -167,7 +169,7 @@ library TaikoData {
mapping(
uint64 blockId_mod_blockRingBufferSize
=> mapping(uint32 transitionId => TransitionState ts)
) transitions;
) transitions;
// Ring buffer for Ether deposits
bytes32 __reserve1;
SlotA slotA; // slot 5
Expand Down
1 change: 1 addition & 0 deletions packages/protocol/contracts/L1/TaikoErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ abstract contract TaikoErrors {
error L1_TRANSITION_NOT_FOUND();
error L1_UNEXPECTED_PARENT();
error L1_UNEXPECTED_TRANSITION_ID();
error L1_INVALID_PROPOSER();
dantaik marked this conversation as resolved.
Show resolved Hide resolved
}
11 changes: 11 additions & 0 deletions packages/protocol/contracts/L1/TaikoL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import "./libs/LibVerifying.sol";
import "./ITaikoL1.sol";
import "./TaikoErrors.sol";
import "./TaikoEvents.sol";
import "./ISequencerRegistry.sol";

/// @title TaikoL1
/// @notice This contract serves as the "base layer contract" of the Taiko protocol, providing
Expand Down Expand Up @@ -78,6 +79,16 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents, TaikoErrors {
emitEventForClient
returns (TaikoData.BlockMetadata memory meta_, TaikoData.EthDeposit[] memory deposits_)
{
// If there's a sequencer registry, check if the block can be proposed by the current
// proposer
ISequencerRegistry sequencerRegistry =
ISequencerRegistry(resolve(LibStrings.B_SEQUENCER_REGISTRY, true));
if (sequencerRegistry != ISequencerRegistry(address(0))) {
if (!sequencerRegistry.isEligibleSigner(msg.sender)) {
revert L1_INVALID_PROPOSER();
}
}

TaikoData.Config memory config = getConfig();
TaikoToken tko = TaikoToken(resolve(LibStrings.B_TAIKO_TOKEN, false));

Expand Down
36 changes: 26 additions & 10 deletions packages/protocol/contracts/L1/libs/LibProposing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ library LibProposing {
error L1_LIVENESS_BOND_NOT_RECEIVED();
error L1_TOO_MANY_BLOCKS();
error L1_UNEXPECTED_PARENT();
error L1_INVALID_L1_STATE_BLOCK();

/// @dev Proposes a Taiko L2 block.
/// @param _state Current TaikoData.State.
Expand Down Expand Up @@ -74,35 +75,47 @@ library LibProposing {
revert L1_TOO_MANY_BLOCKS();
}

bytes32 parentMetaHash =
_state.blocks[(b.numBlocks - 1) % _config.blockRingBufferSize].metaHash;
// assert(parentMetaHash != 0);
TaikoData.Block storage parentBlock =
_state.blocks[(b.numBlocks - 1) % _config.blockRingBufferSize];

// Check if parent block has the right meta hash. This is to allow the proposer to make sure
// the block builds on the expected latest chain state.
if (params.parentMetaHash != 0 && parentMetaHash != params.parentMetaHash) {
if (params.parentMetaHash != 0 && parentBlock.metaHash != params.parentMetaHash) {
revert L1_UNEXPECTED_PARENT();
}

// Verify the passed in L1 state block number.
// We only allow the L1 block to be 2 epochs old.
dantaik marked this conversation as resolved.
Show resolved Hide resolved
// The other constraint is that the L1 block number needs to be larger than or equal the one
// in the previous block.
if (
dantaik marked this conversation as resolved.
Show resolved Hide resolved
params.l1StateBlockNumber < block.number - 64
Brechtpd marked this conversation as resolved.
Show resolved Hide resolved
|| params.l1StateBlockNumber >= block.number
dantaik marked this conversation as resolved.
Show resolved Hide resolved
|| params.l1StateBlockNumber < parentBlock.l1StateBlockNumber
) {
revert L1_INVALID_L1_STATE_BLOCK();
}

// Initialize metadata to compute a metaHash, which forms a part of
// the block data to be stored on-chain for future integrity checks.
// If we choose to persist all data fields in the metadata, it will
// require additional storage slots.
unchecked {
meta_ = TaikoData.BlockMetadata({
l1Hash: blockhash(block.number - 1),
l1Hash: blockhash(params.l1StateBlockNumber),
dantaik marked this conversation as resolved.
Show resolved Hide resolved
difficulty: 0, // to be initialized below
blobHash: 0, // to be initialized below
extraData: params.extraData,
depositsHash: _EMPTY_ETH_DEPOSIT_HASH,
coinbase: params.coinbase,
id: b.numBlocks,
gasLimit: _config.blockMaxGasLimit,
timestamp: uint64(block.timestamp),
l1Height: uint64(block.number - 1),
// Use the timestamp of the L1 state block
timestamp: uint64(block.timestamp - 12 * (block.number - params.l1StateBlockNumber)),
dantaik marked this conversation as resolved.
Show resolved Hide resolved
l1Height: uint64(params.l1StateBlockNumber),
minTier: 0, // to be initialized below
blobUsed: _txList.length == 0,
parentMetaHash: parentMetaHash,
parentMetaHash: parentBlock.metaHash,
sender: msg.sender
});
}
Expand Down Expand Up @@ -137,7 +150,9 @@ library LibProposing {
// of multiple Taiko blocks being proposed within a single
// Ethereum block, we choose to introduce a salt to this random
// number as the L2 mixHash.
meta_.difficulty = keccak256(abi.encodePacked(block.prevrandao, b.numBlocks, block.number));
meta_.difficulty = keccak256(
abi.encodePacked(blockhash(params.l1StateBlockNumber), b.numBlocks, block.number)
);

{
ITierRouter tierRouter = ITierRouter(_resolver.resolve(LibStrings.B_TIER_ROUTER, false));
Expand All @@ -161,7 +176,8 @@ library LibProposing {
// For a new block, the next transition ID is always 1, not 0.
nextTransitionId: 1,
// For unverified block, its verifiedTransitionId is always 0.
verifiedTransitionId: 0
verifiedTransitionId: 0,
l1StateBlockNumber: params.l1StateBlockNumber
});

// Store the block in the ring buffer
Expand Down
1 change: 1 addition & 0 deletions packages/protocol/contracts/common/LibStrings.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ library LibStrings {
bytes32 internal constant H_RETURN_LIVENESS_BOND = keccak256("RETURN_LIVENESS_BOND");
bytes32 internal constant H_SIGNAL_ROOT = keccak256("SIGNAL_ROOT");
bytes32 internal constant H_STATE_ROOT = keccak256("STATE_ROOT");
bytes32 internal constant B_SEQUENCER_REGISTRY = bytes32("sequencer_registry");
}
2 changes: 1 addition & 1 deletion packages/protocol/test/L1/TaikoL1.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ contract TaikoL1Test is TaikoL1TestBase {
vm.prank(proposer, proposer);
vm.expectRevert(revertReason);
L1.proposeBlock{ value: msgValue }(
abi.encode(TaikoData.BlockParams(address(0), address(0), 0, 0, hookcalls, "")),
abi.encode(TaikoData.BlockParams(address(0), address(0), 0, 0, hookcalls, "", 0)),
new bytes(txListSize)
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/test/L1/TaikoL1TestBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ abstract contract TaikoL1TestBase is TaikoTest {
TaikoData.HookCall[] memory hookcalls = new TaikoData.HookCall[](0);
vm.prank(proposer, proposer);
(meta, ethDeposits) = L1.proposeBlock{ value: msgValue }(
abi.encode(TaikoData.BlockParams(address(0), address(0), 0, 0, hookcalls, "")),
abi.encode(TaikoData.BlockParams(address(0), address(0), 0, 0, hookcalls, "", 0)),
new bytes(txListSize)
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/test/L1/TaikoL1TestGroupBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ abstract contract TaikoL1TestGroupBase is TaikoL1TestBase {
vm.prank(proposer);
if (revertReason != "") vm.expectRevert(revertReason);
(meta,) = L1.proposeBlock{ value: 3 ether }(
abi.encode(TaikoData.BlockParams(address(0), address(0), 0, 0, hookcalls, eoaSig)),
abi.encode(TaikoData.BlockParams(address(0), address(0), 0, 0, hookcalls, eoaSig, 0)),
txList
);
}
Expand Down
Loading