Skip to content

Commit 10e6770

Browse files
dantaiklinoscope
andauthored
feat(protocol): enforce tail-only anchoring (#19475)
Co-authored-by: Lin Oshitani <[email protected]>
1 parent 973929b commit 10e6770

File tree

3 files changed

+31
-15
lines changed

3 files changed

+31
-15
lines changed

packages/protocol/contracts/layer1/based/ITaikoInbox.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ interface ITaikoInbox is IBondManager, IProveBatches {
5454
address proposer;
5555
address coinbase;
5656
bytes32 parentMetaHash;
57+
// anchorBlockId is used only by the anchor transaction in the last block in the batch.
5758
uint64 anchorBlockId;
5859
uint64 lastBlockTimestamp;
5960
bool revertIfNotFirstProposal;

packages/protocol/contracts/layer2/based/anchor/ShastaAnchor.sol

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import "./PacayaAnchor.sol";
99
/// @custom:security-contact [email protected]
1010
abstract contract ShastaAnchor is PacayaAnchor {
1111
error InvalidForkHeight();
12+
error NonZeroAnchorStateRoot();
13+
error ZeroAnchorStateRoot();
1214

1315
// The v4Anchor's transaction gas limit, this value must be enforced by the node and prover.
1416
// When there are 16 signals in v4Anchor's parameter, the estimated gas cost is actually
@@ -30,17 +32,19 @@ abstract contract ShastaAnchor is PacayaAnchor {
3032
shastaForkHeight = _shastaForkHeight;
3133
}
3234

33-
/// @notice Anchors the latest L1 block details to L2 for cross-layer
35+
/// @notice This function anchors the latest L1 block details to L2, enabling cross-layer
3436
/// message verification.
35-
/// @dev The gas limit for this transaction must be set to 1,000,000 gas.
36-
/// @dev This function can be called freely as the golden touch private key is publicly known,
37-
/// but the Taiko node guarantees the first transaction of each block is always this anchor
38-
/// transaction, and any subsequent calls will revert with L2_PUBLIC_INPUT_HASH_MISMATCH.
39-
/// @param _anchorBlockId The `anchorBlockId` value in this block's metadata.
40-
/// @param _anchorStateRoot The state root for the L1 block with id equals `_anchorBlockId`.
41-
/// @param _parentGasUsed The gas used in the parent block.
42-
/// @param _baseFeeConfig The base fee configuration.
43-
/// @param _signalSlots The signal slots to mark as received.
37+
/// @dev The gas limit for this transaction is required to be set to 1,000,000 gas.
38+
/// @dev Although this function can be invoked freely due to the public availability of the
39+
/// golden touch private key,
40+
/// the Taiko node ensures that the first transaction of each block is always this anchor
41+
/// transaction. Any subsequent calls will be reverted with L2_PUBLIC_INPUT_HASH_MISMATCH.
42+
/// @param _anchorBlockId This is the `anchorBlockId` value in the metadata of this block.
43+
/// @param _anchorStateRoot This is the state root for the L1 block with an id equal to
44+
/// `_anchorBlockId`.
45+
/// @param _parentGasUsed This is the amount of gas used in the parent block.
46+
/// @param _baseFeeConfig This is the configuration for the base fee.
47+
/// @param _signalSlots These are the signal slots to be marked as received.
4448
function v4Anchor(
4549
uint64 _anchorBlockId,
4650
bytes32 _anchorStateRoot,
@@ -50,8 +54,6 @@ abstract contract ShastaAnchor is PacayaAnchor {
5054
bytes32[] calldata _signalSlots
5155
)
5256
external
53-
nonZeroBytes32(_anchorStateRoot)
54-
nonZeroValue(_anchorBlockId)
5557
nonZeroValue(_baseFeeConfig.gasIssuancePerSecond)
5658
nonZeroValue(_baseFeeConfig.adjustmentQuotient)
5759
onlyGoldenTouch
@@ -62,10 +64,20 @@ abstract contract ShastaAnchor is PacayaAnchor {
6264
uint256 parentId = block.number - 1;
6365
_verifyAndUpdatePublicInputHash(parentId);
6466
_verifyBaseFeeAndUpdateGasExcess(_parentGasUsed, _baseFeeConfig);
65-
_syncChainData(_anchorBlockId, _anchorStateRoot);
6667
_updateParentHashAndTimestamp(parentId);
6768

68-
signalService.receiveSignals(_signalSlots);
69+
if (_anchorBlockId == 0) {
70+
// This block must not be the last block in the batch.
71+
require(_anchorStateRoot == 0, NonZeroAnchorStateRoot());
72+
} else {
73+
// This block must be the last block in the batch.
74+
require(_anchorStateRoot != 0, ZeroAnchorStateRoot());
75+
_syncChainData(_anchorBlockId, _anchorStateRoot);
76+
}
77+
78+
if (_signalSlots.length != 0) {
79+
signalService.receiveSignals(_signalSlots);
80+
}
6981

7082
// We need to add one SSTORE from non-zero to non-zero (5000), one addition (3), and one
7183
// subtraction (3).

packages/protocol/contracts/layer2/based/anchor/TaikoAnchor.sol

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import "./ShastaAnchor.sol";
88
/// verification and manages EIP-1559 gas pricing for Layer 2 (L2) operations.
99
/// It is used to anchor the latest L1 block details to L2 for cross-layer
1010
/// communication, manage EIP-1559 parameters for gas pricing, and store
11-
/// verified L1 block information
11+
/// verified L1 block information.
12+
///
13+
/// This contract receives a portion of L2 base fees, while the remainder is directed to
14+
/// L2 block's coinbase address.
1215
/// @custom:security-contact [email protected]
1316
contract TaikoAnchor is ShastaAnchor {
1417
constructor(

0 commit comments

Comments
 (0)