polygon cdk 查看最新提交L1batch num
通过RPC
curl http://L2RPC访问地址/ \
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"zkevm_virtualBatchNumber","params":[],"id":1,"jsonrpc":"2.0"}'
例如返回
curl http://172.18.39.103:8123/ \
> -X POST \
> -H "Content-Type: application/json" \
> --data '{"method":"zkevm_virtualBatchNumber","params":[],"id":1,"jsonrpc":"2.0"}'
{"jsonrpc":"2.0","id":1,"result":"0x52"}
0x52对应10进制为82
https://tool.lu/hexconvert/
合约逻辑
function sequenceBatchesValidium(
ValidiumBatchData[] calldata batches,
uint32 l1InfoTreeLeafCount,
uint64 maxSequenceTimestamp,
bytes32 expectedFinalAccInputHash,
address l2Coinbase,
bytes calldata dataAvailabilityMessage
) external onlyTrustedSequencer {
uint256 batchesNum = batches.length;
if (batchesNum == 0) {
revert SequenceZeroBatches();
}
if (batchesNum > _MAX_VERIFY_BATCHES) {
revert ExceedMaxVerifyBatches();
}
// Check max sequence timestamp inside of range
if (
uint256(maxSequenceTimestamp) > (block.timestamp + TIMESTAMP_RANGE)
) {
revert MaxTimestampSequenceInvalid();
}
// Update global exit root if there are new deposits
bridgeAddress.updateGlobalExitRoot();
// Get global batch variables
bytes32 l1InfoRoot = globalExitRootManager.l1InfoRootMap(
l1InfoTreeLeafCount
);
if (l1InfoRoot == bytes32(0)) {
revert L1InfoTreeLeafCountInvalid();
}
// Store storage variables in memory, to save gas, because will be overrided multiple times
uint64 currentLastForceBatchSequenced = lastForceBatchSequenced;
bytes32 currentAccInputHash = lastAccInputHash;
// Store in a temporal variable, for avoid access again the storage slot
uint64 initLastForceBatchSequenced = currentLastForceBatchSequenced;
for (uint256 i = 0; i < batchesNum; i++) {
// Load current sequence
ValidiumBatchData memory currentBatch = batches[i];
// Check if it's a forced batch
if (currentBatch.forcedTimestamp > 0) {
currentLastForceBatchSequenced++;
// Check forced data matches
bytes32 hashedForcedBatchData = keccak256(
abi.encodePacked(
currentBatch.transactionsHash,
currentBatch.forcedGlobalExitRoot,
currentBatch.forcedTimestamp,
currentBatch.forcedBlockHashL1
)
);
if (
hashedForcedBatchData !=
forcedBatches[currentLastForceBatchSequenced]
) {
revert ForcedDataDoesNotMatch();
}
// Calculate next accumulated input hash
currentAccInputHash = keccak256(
abi.encodePacked(
currentAccInputHash,
currentBatch.transactionsHash,
currentBatch.forcedGlobalExitRoot,
currentBatch.forcedTimestamp,
l2Coinbase,
currentBatch.forcedBlockHashL1
)
);
// Delete forceBatch data since won't be used anymore
delete forcedBatches[currentLastForceBatchSequenced];
} else {
// Note that forcedGlobalExitRoot and forcedBlockHashL1 remain unused and unchecked in this path
// The synchronizer should be aware of that
// Calculate next accumulated input hash
currentAccInputHash = keccak256(
abi.encodePacked(
currentAccInputHash,
currentBatch.transactionsHash,
l1InfoRoot,
maxSequenceTimestamp,
l2Coinbase,
bytes32(0)
)
);
}
}
// Sanity check, should be unreachable
if (currentLastForceBatchSequenced > lastForceBatch) {
revert ForceBatchesOverflow();
}
// Store back the storage variables
lastAccInputHash = currentAccInputHash;
uint256 nonForcedBatchesSequenced = batchesNum;
// Check if there has been forced batches
if (currentLastForceBatchSequenced != initLastForceBatchSequenced) {
uint64 forcedBatchesSequenced = currentLastForceBatchSequenced -
initLastForceBatchSequenced;
// substract forced batches
nonForcedBatchesSequenced -= forcedBatchesSequenced;
// Transfer pol for every forced batch submitted
pol.safeTransfer(
address(rollupManager),
calculatePolPerForceBatch() * (forcedBatchesSequenced)
);
// Store new last force batch sequenced
lastForceBatchSequenced = currentLastForceBatchSequenced;
}
// Pay collateral for every non-forced batch submitted
if (nonForcedBatchesSequenced != 0) {
pol.safeTransferFrom(
msg.sender,
address(rollupManager),
rollupManager.getBatchFee() * nonForcedBatchesSequenced
);
// Validate that the data availability protocol accepts the dataAvailabilityMessage
// note This is a view function, so there's not much risk even if this contract was vulnerable to reentrant attacks
dataAvailabilityProtocol.verifyMessage(
expectedFinalAccInputHash,
dataAvailabilityMessage
);
}
uint64 currentBatchSequenced = rollupManager.onSequenceBatches(
uint64(batchesNum),
currentAccInputHash
);
// Check expectedFinalAccInputHash
if (currentAccInputHash != expectedFinalAccInputHash) {
revert FinalAccInputHashDoesNotMatch();
}
emit SequenceBatches(currentBatchSequenced, l1InfoRoot);
}
查看举例交易:https://sepolia.etherscan.io/tx/0xdb8636d8853348d4d48df1d602a3ce6fe8c37c6be3c30ea9d83f2568e7562fa1#eventlog
对应事件:SequenceBatches
最新提交batch num: 82 与RPC 查询数据一致