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): emit blob hashes in event and split meta into 2 structs #18817

Merged
merged 24 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
12 changes: 7 additions & 5 deletions packages/protocol/contracts/layer1/based/ITaikoInbox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ interface ITaikoInbox {
}

struct BatchMetadata {
bytes32 txListHash;
bytes32 txsHash;
bytes32[] blobHashes;
uint32 blobByteOffset;
uint32 blobByteSize;
bytes32 extraData;
address coinbase;
uint64 batchId;
Expand All @@ -70,7 +73,6 @@ interface ITaikoInbox {
bytes32[] signalSlots;
bytes32 anchorInput;
BlockParams[] blocks;
BlobParams blobParams;
LibSharedData.BaseFeeConfig baseFeeConfig;
}

Expand Down Expand Up @@ -209,9 +211,9 @@ interface ITaikoInbox {

/// @notice Emitted when a batch is proposed.
/// @param meta The metadata of the proposed batch.
/// @param calldataUsed Whether calldata is used for txList DA.
/// @param txListInCalldata The tx list in calldata.
event BatchProposed(BatchMetadata meta, bool calldataUsed, bytes txListInCalldata);
/// @param txList The tx list in calldata.
/// @param blobHashes The blob hashes.
event BatchProposed(BatchMetadata meta, bytes txList, bytes32[] blobHashes);

/// @notice Emitted when multiple transitions are proved.
/// @param verifier The address of the verifier.
Expand Down
72 changes: 41 additions & 31 deletions packages/protocol/contracts/layer1/based/TaikoInbox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -113,31 +113,37 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork {
// use
// the following approach to calculate a block's difficulty:
// `keccak256(abi.encode("TAIKO_DIFFICULTY", block.number))`

meta_ = BatchMetadata({
txListHash: calldataUsed ? keccak256(_txList) : _calcTxListHash(params.blobParams),
extraData: bytes32(uint256(config.baseFeeConfig.sharingPctg)),
coinbase: params.coinbase,
batchId: stats2.numBatches,
gasLimit: config.blockMaxGasLimit,
lastBlockTimestamp: lastBlockTimestamp,
parentMetaHash: lastBatch.metaHash,
proposer: params.proposer,
livenessBond: config.livenessBondBase
+ config.livenessBondPerBlock * uint96(params.blocks.length),
proposedAt: uint64(block.timestamp),
proposedIn: uint64(block.number),
anchorBlockId: anchorBlockId,
anchorBlockHash: blockhash(anchorBlockId),
signalSlots: params.signalSlots,
blocks: params.blocks,
anchorInput: params.anchorInput,
blobParams: params.blobParams,
baseFeeConfig: config.baseFeeConfig
});
{
(bytes32 txsHash, bytes32[] memory blobHashes) =
_calculateTxsHash(keccak256(_txList), params.blobParams);

meta_ = BatchMetadata({
txsHash: txsHash,
blobHashes: blobHashes,
blobByteOffset: params.blobParams.byteOffset,
blobByteSize: params.blobParams.byteSize,
extraData: bytes32(uint256(config.baseFeeConfig.sharingPctg)),
coinbase: params.coinbase,
batchId: stats2.numBatches,
gasLimit: config.blockMaxGasLimit,
lastBlockTimestamp: lastBlockTimestamp,
parentMetaHash: lastBatch.metaHash,
proposer: params.proposer,
livenessBond: config.livenessBondBase
+ config.livenessBondPerBlock * uint96(params.blocks.length),
proposedAt: uint64(block.timestamp),
proposedIn: uint64(block.number),
anchorBlockId: anchorBlockId,
anchorBlockHash: blockhash(anchorBlockId),
signalSlots: params.signalSlots,
blocks: params.blocks,
anchorInput: params.anchorInput,
baseFeeConfig: config.baseFeeConfig
});
emit BatchProposed(meta_, _txList, blobHashes);
}

require(meta_.anchorBlockHash != 0, ZeroAnchorBlockHash());
require(meta_.txListHash != 0, BlobNotFound());
bytes32 metaHash = keccak256(abi.encode(meta_));

Batch storage batch = state.batches[stats2.numBatches % config.batchRingBufferSize];
Expand Down Expand Up @@ -168,7 +174,6 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork {
stats2.lastProposedIn = uint56(block.number);

_debitBond(params.proposer, meta_.livenessBond);
emit BatchProposed(meta_, calldataUsed, _txList);
} // end-of-unchecked

_verifyBatches(config, stats2, 1);
Expand Down Expand Up @@ -515,18 +520,23 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork {
state.stats2.paused = true;
}

function _calcTxListHash(BlobParams memory _blobParams)
function _calculateTxsHash(
bytes32 _txListHash,
BlobParams memory _blobParams
)
internal
view
virtual
returns (bytes32)
returns (bytes32 hash_, bytes32[] memory blobHashes_)
{
bytes32[] memory blobHashes = new bytes32[](_blobParams.numBlobs);
for (uint256 i; i < _blobParams.numBlobs; ++i) {
blobHashes[i] = blobhash(_blobParams.firstBlobIndex + i);
require(blobHashes[i] != 0, BlobNotFound());
unchecked {
blobHashes_ = new bytes32[](_blobParams.numBlobs);
for (uint256 i; i < _blobParams.numBlobs; ++i) {
blobHashes_[i] = blobhash(_blobParams.firstBlobIndex + i);
require(blobHashes_[i] != 0, BlobNotFound());
}
hash_ = keccak256(abi.encode(_txListHash, blobHashes_));
}
return keccak256(abi.encode(blobHashes));
}

// Private functions -----------------------------------------------------------------------
Expand Down
12 changes: 10 additions & 2 deletions packages/protocol/test/layer1/Layer1Test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,16 @@ contract ConfigurableInbox is TaikoInbox {
return __config;
}

function _calcTxListHash(BlobParams memory) internal pure override returns (bytes32) {
return keccak256("BLOB");
function _calculateTxsHash(
bytes32,
BlobParams memory _blobParams
)
internal
pure
override
returns (bytes32, bytes32[] memory)
{
return (keccak256("BLOB"), new bytes32[](_blobParams.numBlobs));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ contract InboxTest_CalldataForTxList is InboxTestBase {

for (uint256 i; i < batchIds.length; ++i) {
ITaikoInbox.BatchMetadata memory meta = _loadMetadata(batchIds[i]);
assertEq(meta.txListHash, expectedHash);
assertEq(meta.txsHash, expectedHash);
}

vm.prank(Alice);
Expand Down Expand Up @@ -93,7 +93,7 @@ contract InboxTest_CalldataForTxList is InboxTestBase {

// With empty txList
ITaikoInbox.BatchMetadata memory meta = inbox.proposeBatch(abi.encode(params), "");
assertTrue(meta.txListHash != 0, "txListHash should not be zero for valid blobIndex");
assertTrue(meta.txsHash != 0, "txsHash should not be zero for valid blobIndex");

_saveMetadata(meta);

Expand All @@ -120,12 +120,12 @@ contract InboxTest_CalldataForTxList is InboxTestBase {
vm.prank(Alice);
uint64[] memory batchIds1 = _proposeBatchesWithDefaultParameters(1, txList1);
ITaikoInbox.BatchMetadata memory meta1 = _loadMetadata(batchIds1[0]);
assertEq(meta1.txListHash, expectedHash1, "txListHash mismatch for block 1");
assertEq(meta1.txsHash, expectedHash1, "txsHash mismatch for block 1");

vm.prank(Alice);
uint64[] memory batchIds2 = _proposeBatchesWithDefaultParameters(1, txList2);
ITaikoInbox.BatchMetadata memory meta2 = _loadMetadata(batchIds2[0]);
assertEq(meta2.txListHash, expectedHash2, "txListHash mismatch for block 2");
assertEq(meta2.txsHash, expectedHash2, "txsHash mismatch for block 2");

vm.prank(Alice);
_proveBatchesWithCorrectTransitions(batchIds2);
Expand Down Expand Up @@ -153,14 +153,14 @@ contract InboxTest_CalldataForTxList is InboxTestBase {

// Attempt to prove the block with the incorrect txList
ITaikoInbox.BatchMetadata memory meta = _loadMetadata(batchIds[0]);
meta.txListHash = incorrectHash;
meta.txsHash = incorrectHash;

ITaikoInbox.BatchMetadata[] memory metas = new ITaikoInbox.BatchMetadata[](batchIds.length);
ITaikoInbox.Transition[] memory transitions = new ITaikoInbox.Transition[](batchIds.length);

for (uint256 i; i < batchIds.length; ++i) {
metas[i] = _loadMetadata(batchIds[i]);
metas[i].txListHash = incorrectHash;
metas[i].txsHash = incorrectHash;
transitions[i].parentHash = correctBlockhash(batchIds[i] - 1);
transitions[i].blockHash = correctBlockhash(batchIds[i]);
transitions[i].stateRoot = correctStateRoot(batchIds[i]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ contract MockTaikoInbox is EssentialContract {

// Create metadata with minimal required fields for testing
meta_ = ITaikoInbox.BatchMetadata({
txListHash: keccak256(_txList),
txsHash: keccak256(_txList),
extraData: bytes32(0),
coinbase: params.coinbase == address(0) ? params.proposer : params.coinbase,
batchId: 0, // Mock value
Expand All @@ -41,7 +41,9 @@ contract MockTaikoInbox is EssentialContract {
signalSlots: params.signalSlots,
blocks: params.blocks,
anchorInput: params.anchorInput,
blobParams: params.blobParams,
blobHashes: new bytes32[](0),
blobByteOffset: 0,
blobByteSize: 0,
baseFeeConfig: LibSharedData.BaseFeeConfig({
adjustmentQuotient: 0,
sharingPctg: 0,
Expand Down
Loading