Skip to content

Commit

Permalink
Merge pull request #25 from NethermindEth/anshu/task-manager-block-pr…
Browse files Browse the repository at this point in the history
…oposal

Add block proposals and lookahead posting
  • Loading branch information
smartprogrammer93 authored Jul 3, 2024
2 parents 739fc68 + d81b7c6 commit 577c576
Show file tree
Hide file tree
Showing 7 changed files with 599 additions and 17 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
[submodule "SmartContracts/lib/openzeppelin-contracts-upgradeable"]
path = SmartContracts/lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
[submodule "SmartContracts/lib/openzeppelin-contracts"]
path = SmartContracts/lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
1 change: 1 addition & 0 deletions SmartContracts/lib/openzeppelin-contracts
Submodule openzeppelin-contracts added at 54b3f1
1 change: 1 addition & 0 deletions SmartContracts/remappings.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
eigenlayer-middleware/=lib/eigenlayer-middleware/src
forge-std/=lib/forge-std/src/
openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts
openzeppelin-contracts/=lib/openzeppelin-contracts/contracts
406 changes: 406 additions & 0 deletions SmartContracts/src/avs/PreconfTaskManager.sol

Large diffs are not rendered by default.

96 changes: 79 additions & 17 deletions SmartContracts/src/interfaces/IPreconfTaskManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
pragma solidity 0.8.25;

interface IPreconfTaskManager {
event LookaheadUpdated(bytes lookahead);
event ProvedIncorrectPreconfirmation(address indexed preconfer, uint256 indexed blockId, address indexed disputer);
event ProvedIncorrectLookahead(address indexed poster, uint256 indexed slot, address indexed disputer);

struct LookaheadEntry {
// The timestamp of the slot
uint256 timestamp;
// The id of the AVS operator who is also the L1 validator for the slot
uint256 validatorId;
struct ProposedBlock {
// Proposer of the L2 block
address proposer;
// L1 block timestamp
uint96 timestamp;
// Keccak hash of the RLP transaction list of the block
bytes32 txListHash;
}

struct PreconfirmationHeader {
Expand All @@ -22,31 +20,95 @@ interface IPreconfTaskManager {
bytes32 txListHash;
}

struct LookaheadEntry {
// Timestamp of the slot at which the provided preconfer is the L1 validator
uint48 timestamp;
// Timestamp of the last slot that had a valid preconfer
uint48 prevTimestamp;
// Address of the preconfer who is also the L1 validator
// The preconfer will have rights to propose a block in the range (prevTimestamp, timestamp]
address preconfer;
}

struct LookaheadSetParam {
// The timestamp of the slot
uint256 timestamp;
// The AVS operator who is also the L1 validator for the slot and will preconf L2 transactions
address preconfer;
}

event LookaheadUpdated(LookaheadSetParam[]);
event ProvedIncorrectPreconfirmation(address indexed preconfer, uint256 indexed blockId, address indexed disputer);
event ProvedIncorrectLookahead(address indexed poster, uint256 indexed timestamp, address indexed disputer);

/// @dev The block proposer is not the randomly chosen fallback preconfer for the current slot/timestamp
error SenderIsNotTheFallbackPreconfer();
/// @dev The current (or provided) timestamp does not fall in the range provided by the lookahead pointer
error InvalidLookaheadPointer();
/// @dev The block proposer is not the assigned preconfer for the current slot/timestamp
error SenderIsNotThePreconfer();
/// @dev The preconfer in the lookahead set params is not registered in the AVS
error EntryNotRegisteredInAVS();
/// @dev The sender is not registered in the AVS
error SenderNotRegisteredInAVS();
/// @dev The timestamp in the lookahead is not of a valid future slot in the present epoch
error InvalidSlotTimestamp();
/// @dev The chain id on which the preconfirmation was signed is different from the current chain's id
error PreconfirmationChainIdMismatch();
/// @dev The dispute window for proving incorretc lookahead or preconfirmation is over
error MissedDisputeWindow();
/// @dev The disputed preconfirmation is correct
error PreconfirmationIsCorrect();
/// @dev The preconfer is yet to register the hash tree root of their consensus BLS pub key
error ConsensusBLSPubKeyHashTreeRootNotRegistered();
/// @dev The preconfer has already registered the hash tree root of their consensus BLS pub key
error ConsensusBLSPubKeyHashTreeRootAlreadyRegistered();
/// @dev The expected validator has been slashed on CL
error ExpectedValidatorMustNotBeSlashed();
/// @dev The lookahead poster for the epoch has already been slashed
error PosterAlreadySlashedForTheEpoch();
/// @dev The registered hash tree root of preconfer's consensus BLS pub key does not match with expected validator
error ExpectedValidatorIsIncorrect();
/// @dev The validator list indices for both expected and actual validators are same
error ExpectedAndActualValidatorAreSame();
/// @dev The proof that the expected validator is a part of the validator list is invalid.
error ValidatorProofFailed();
/// @dev The proof that the validator list is a part of the beacon state is invalid.
error BeaconStateProofFailed();
/// @dev The proof that the beacon state is a part of the beacon block is invalid.
error BeaconBlockProofForStateFailed();
/// @dev The proof that the actual validator index is a part of the beacon is invalid.
error BeaconBlockProofForProposerIndex();

/// @dev Accepts block proposal by an operator and forwards it to TaikoL1 contract
function newBlockProposal(
bytes calldata blockParams,
bytes calldata txList,
LookaheadEntry[] calldata lookaheadEntries
) external;
uint256 lookaheadHint,
LookaheadSetParam[] calldata lookaheadSetParams
) external payable;

/// @dev Slashes a preconfer if the txn and ordering in a signed preconf does not match the actual block
function proveIncorrectPreconfirmation(PreconfirmationHeader memory header, bytes memory signature) external;

/// @dev Slashes a preconfer if the validator lookahead pushed by them has an incorrect entry
function proveIncorrectLookahead(
uint256 offset,
bytes32[] memory expectedValidator,
uint256 lookaheadPointer,
uint256 slotTimestamp,
bytes32[8] memory expectedValidator,
uint256 expectedValidatorIndex,
bytes32[] memory expectedValidatorProof,
bytes32[] memory actualValidator,
uint256 actualValidatorIndex,
bytes32[] memory actualValidatorProof,
bytes32 validatorsRoot,
uint256 nr_validators,
bytes32[] memory beaconStateProof,
bytes32 beaconStateRoot,
bytes32[] memory beaconBlockProof
bytes32[] memory beaconBlockProofForState,
bytes32[] memory beaconBlockProofForProposerIndex
) external;

function isLookaheadRequired() external view returns (bool);
/// @dev Records the hash tree root of the BLS pub key that the preconfer uses on the consensus layer
function registerConsensusBLSPubKeyHashTreeRoot(bytes32 consensusBLSPubKeyHashTreeRoot) external;

function isLookaheadRequired(uint256 epochTimestamp) external view returns (bool);
}
32 changes: 32 additions & 0 deletions SmartContracts/src/interfaces/taiko/ITaikoL1.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.25;

interface ITaikoL1 {
struct BlockMetadata {
bytes32 l1Hash;
bytes32 difficulty;
bytes32 blobHash;
bytes32 extraData;
bytes32 depositsHash;
address coinbase;
uint64 id;
uint32 gasLimit;
uint64 timestamp;
uint64 l1Height;
uint16 minTier;
bool blobUsed;
bytes32 parentMetaHash;
address sender;
}

struct EthDeposit {
address recipient;
uint96 amount;
uint64 id;
}

function proposeBlock(bytes calldata _params, bytes calldata _txList)
external
payable
returns (BlockMetadata memory meta_, EthDeposit[] memory deposits_);
}
77 changes: 77 additions & 0 deletions SmartContracts/src/libraries/MerkleUtils.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.25;

library MerkleUtils {
uint256 internal constant CHUNKS_LENGTH = 8;
uint256 internal constant TMP_LENGTH = 4;

function hash(bytes32 a, bytes32 b) internal pure returns (bytes32) {
return sha256(abi.encodePacked(a, b));
}

function merkleize(bytes32[CHUNKS_LENGTH] memory chunks) internal pure returns (bytes32) {
bytes32[] memory tmp = new bytes32[](TMP_LENGTH);

for (uint256 i; i < CHUNKS_LENGTH; ++i) {
merge(tmp, i, chunks[i]);
}

return tmp[TMP_LENGTH - 1];
}

function merge(bytes32[] memory tmp, uint256 index, bytes32 chunk) internal pure {
bytes32 h = chunk;
uint256 j = 0;
while (true) {
if (index & 1 << j == 0) {
break;
} else {
h = hash(tmp[j], h);
}
j += 1;
}
tmp[j] = h;
}

function verifyProof(bytes32[] memory proof, bytes32 root, bytes32 leaf, uint256 leafIndex)
internal
pure
returns (bool)
{
bytes32 h = leaf;
uint256 index = leafIndex;

for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];

if (index % 2 == 0) {
h = sha256(bytes.concat(h, proofElement));
} else {
h = sha256(bytes.concat(proofElement, h));
}

index = index / 2;
}

return h == root;
}

function toLittleEndian(uint256 n) public pure returns (bytes32) {
uint256 v = n;
v = ((v & 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >> 8)
| ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8);
v = ((v & 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >> 16)
| ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16);
v = ((v & 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >> 32)
| ((v & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32);
v = ((v & 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >> 64)
| ((v & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) << 64);
v = (v >> 128) | (v << 128);
return bytes32(v);
}

function mixInLength(bytes32 root, uint256 length) public pure returns (bytes32) {
bytes32 littleEndianLength = toLittleEndian(length);
return sha256(abi.encodePacked(root, littleEndianLength));
}
}

0 comments on commit 577c576

Please sign in to comment.