Skip to content

Commit

Permalink
feat(executor): add blob linear hash and commitment to calldata (#221)
Browse files Browse the repository at this point in the history
  • Loading branch information
koloz193 authored Feb 23, 2024
1 parent 25e84e0 commit df3cc42
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 7 deletions.
12 changes: 11 additions & 1 deletion l1-contracts/contracts/zksync/facets/Executor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,17 @@ contract ExecutorFacet is Base, IExecutor {
blobCommitments = _verifyBlobInformation(_newBatch.pubdataCommitments[1:], blobHashes);
} else if (pubdataSource == uint8(PubdataSource.Calldata)) {
// In this scenario pubdataCommitments is actual pubdata consisting of l2 to l1 logs, l2 to l1 message, compressed smart contract bytecode, and compressed state diffs
require(logOutput.pubdataHash == keccak256(_newBatch.pubdataCommitments[1:]), "wp");
require(
logOutput.pubdataHash ==
keccak256(_newBatch.pubdataCommitments[1:_newBatch.pubdataCommitments.length - 32]),
"wp"
);
blobHashes[0] = logOutput.blob1Hash;
blobCommitments[0] = bytes32(
_newBatch.pubdataCommitments[_newBatch.pubdataCommitments.length - 32:_newBatch
.pubdataCommitments
.length]
);
}

require(_previousBatch.batchHash == logOutput.previousBatchHash, "l");
Expand Down
5 changes: 4 additions & 1 deletion l1-contracts/contracts/zksync/interfaces/IExecutor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,11 @@ interface IExecutor is IBase {
/// @param pubdataCommitments Packed pubdata commitments/data.
/// @dev pubdataCommitments format: This will always start with a 1 byte pubdataSource flag. Current allowed values are 0 (calldata) or 1 (blobs)
/// kzg: list of: opening point (16 bytes) || claimed value (32 bytes) || commitment (48 bytes) || proof (48 bytes) = 144 bytes
/// calldata: pubdataCommitments.length - 1 bytes of pubdata
/// calldata: pubdataCommitments.length - 1 - 32 bytes of pubdata
/// and 32 bytes appended to serve as the blob commitment part for the aux output part of the batch commitment
/// @dev For 2 blobs we will be sending 288 bytes of calldata instead of the full amount for pubdata.
/// @dev When using calldata, we only need to send one blob commitment since the max number of bytes in calldata fits in a single blob and we can pull the
/// linear hash from the system logs
struct CommitBatchInfo {
uint64 batchNumber;
uint64 timestamp;
Expand Down
25 changes: 25 additions & 0 deletions l1-contracts/test/foundry/unit/concrete/Executor/Committing.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,32 @@ contract CommittingTest is ExecutorTest {
uint256(SystemLogKey.PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY),
Utils.packBatchTimestampAndBlockTimestamp(currentTimestamp, currentTimestamp)
);
correctL2Logs[uint256(SystemLogKey.BLOB_ONE_HASH_KEY)] = Utils.constructL2Log(
true,
L2_PUBDATA_CHUNK_PUBLISHER_ADDR,
uint256(SystemLogKey.BLOB_ONE_HASH_KEY),
0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563
);

IExecutor.CommitBatchInfo memory correctNewCommitBatchInfo = newCommitBatchInfo;
correctNewCommitBatchInfo.systemLogs = Utils.encodePacked(correctL2Logs);
correctNewCommitBatchInfo.pubdataCommitments = abi.encodePacked(
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
bytes32(uint256(0xbeef))
);

bytes32[] memory blobHashes = new bytes32[](2);
blobHashes[0] = 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563;

bytes32[] memory blobCommitments = new bytes32[](2);
blobCommitments[0] = bytes32(uint256(0xbeef));

bytes32 expectedBatchCommitment = Utils.createBatchCommitment(
correctNewCommitBatchInfo,
bytes32(""),
blobCommitments,
blobHashes
);

IExecutor.CommitBatchInfo[] memory correctCommitBatchInfoArray = new IExecutor.CommitBatchInfo[](1);
correctCommitBatchInfoArray[0] = correctNewCommitBatchInfo;
Expand All @@ -336,6 +359,8 @@ contract CommittingTest is ExecutorTest {
assertEq(entries.length, 1);
assertEq(entries[0].topics[0], keccak256("BlockCommit(uint256,bytes32,bytes32)"));
assertEq(entries[0].topics[1], bytes32(uint256(1))); // batchNumber
assertEq(entries[0].topics[2], correctNewCommitBatchInfo.newStateRoot); // batchHash
assertEq(entries[0].topics[3], expectedBatchCommitment); // commitment

uint256 totalBatchesCommitted = getters.getTotalBatchesCommitted();
assertEq(totalBatchesCommitted, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ contract ExecutorTest is Test {
bootloaderHeapInitialContentsHash: Utils.randomBytes32("bootloaderHeapInitialContentsHash"),
eventsQueueStateHash: Utils.randomBytes32("eventsQueueStateHash"),
systemLogs: l2Logs,
pubdataCommitments: "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
pubdataCommitments: "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
});
}
}
57 changes: 57 additions & 0 deletions l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,61 @@ library Utils {
selectors[5] = MailboxFacet.l2TransactionBaseCost.selector;
return selectors;
}

function createBatchCommitment(
IExecutor.CommitBatchInfo calldata _newBatchData,
bytes32 _stateDiffHash,
bytes32[] memory _blobCommitments,
bytes32[] memory _blobHashes
) public pure returns (bytes32) {
bytes32 passThroughDataHash = keccak256(_batchPassThroughData(_newBatchData));
bytes32 metadataHash = keccak256(_batchMetaParameters());
bytes32 auxiliaryOutputHash = keccak256(
_batchAuxiliaryOutput(_newBatchData, _stateDiffHash, _blobCommitments, _blobHashes)
);

return keccak256(abi.encode(passThroughDataHash, metadataHash, auxiliaryOutputHash));
}

function _batchPassThroughData(IExecutor.CommitBatchInfo calldata _batch) internal pure returns (bytes memory) {
return
abi.encodePacked(
_batch.indexRepeatedStorageChanges,
_batch.newStateRoot,
uint64(0), // index repeated storage changes in zkPorter
bytes32(0) // zkPorter batch hash
);
}

function _batchMetaParameters() internal pure returns (bytes memory) {
// Used in __Executor_Shared.t.sol
bytes8 dummyHash = 0x1234567890123456;
return abi.encodePacked(false, bytes32(dummyHash), bytes32(dummyHash));
}

function _batchAuxiliaryOutput(
IExecutor.CommitBatchInfo calldata _batch,
bytes32 _stateDiffHash,
bytes32[] memory _blobCommitments,
bytes32[] memory _blobHashes
) internal pure returns (bytes memory) {
bytes32 l2ToL1LogsHash = keccak256(_batch.systemLogs);

return
abi.encode(
l2ToL1LogsHash,
_stateDiffHash,
_batch.bootloaderHeapInitialContentsHash,
_batch.eventsQueueStateHash,
// for each blob we have:
// linear hash (hash of preimage from system logs) and
// output hash of blob commitments: keccak(versioned hash || opening point || evaluation value)
// These values will all be bytes32(0) when we submit pubdata via calldata instead of blobs.
// If we only utilize a single blob, _blobHash[1] and _blobCommitments[1] will be bytes32(0)
_blobHashes[0],
_blobCommitments[0],
_blobHashes[1],
_blobCommitments[1]
);
}
}
2 changes: 1 addition & 1 deletion l1-contracts/test/unit_tests/executor_proof.spec.ts

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ async function buildCommitBatchInfo(
numberOfLayer1Txs: 0,
priorityOperationsHash: EMPTY_STRING_KECCAK,
systemLogs: ethers.utils.hexConcat(systemLogs),
pubdataCommitments: `${ethers.constants.HashZero}00`,
pubdataCommitments: `0x${"0".repeat(130)}`,
bootloaderHeapInitialContentsHash: ethers.utils.randomBytes(32),
eventsQueueStateHash: ethers.utils.randomBytes(32),
...info,
Expand All @@ -746,7 +746,7 @@ async function buildCommitBatchInfoWithCustomLogs(
numberOfLayer1Txs: 0,
priorityOperationsHash: EMPTY_STRING_KECCAK,
systemLogs: ethers.utils.hexConcat(systemLogs),
pubdataCommitments: `${ethers.constants.HashZero}00`,
pubdataCommitments: `0x${"0".repeat(130)}`,
bootloaderHeapInitialContentsHash: ethers.utils.randomBytes(32),
eventsQueueStateHash: ethers.utils.randomBytes(32),
...info,
Expand Down
3 changes: 2 additions & 1 deletion l1-contracts/test/unit_tests/validator_timelock_test.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ describe("ValidatorTimelock tests", function () {
bootloaderHeapInitialContentsHash: ethers.utils.randomBytes(32),
eventsQueueStateHash: ethers.utils.randomBytes(32),
systemLogs: [],
pubdataCommitments: "0x00290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563",
pubdataCommitments:
"0x00290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
};
}

Expand Down

0 comments on commit df3cc42

Please sign in to comment.