Skip to content

Commit 8b26e13

Browse files
ggonzalez94Gustavo Gonzalezclaudecursoragentdantaik
authored
feat(protocol): integrate signal service with shasta (#20270)
Co-authored-by: Gustavo Gonzalez <gustavo@taiko.xyz> Co-authored-by: ggonzalez94 <17907743+ggonzalez94@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Daniel Wang <99078276+dantaik@users.noreply.github.com> Co-authored-by: David <david@taiko.xyz>
1 parent 8c800ff commit 8b26e13

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2940
-3557
lines changed

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@
1111
"packages/taiko-client-rs": "2.0.0",
1212
"packages/taikoon-ui": "1.3.0",
1313
"packages/ui-lib": "1.0.0"
14-
}
14+
}

packages/protocol/CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ See inline comments for specific safety justifications on each unchecked block.
210210
Due to aggressive use of unchecked blocks throughout these contracts, developers **MUST** explicitly cast values to their proper types before performing mathematical operations when mixing different numeric types. Without explicit casts, Solidity may perform implicit conversions that could lead to unexpected results within unchecked blocks.
211211

212212
**Example:**
213+
213214
```solidity
214215
// ✅ CORRECT - Explicit casting
215216
uint256(uint48Value) + uint256(anotherUint48)

packages/protocol/contracts/layer1/shasta/iface/IInbox.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ interface IInbox {
1515
address codec;
1616
/// @notice The token used for bonds
1717
address bondToken;
18+
/// @notice The signal service contract address
19+
address signalService;
1820
/// @notice The proof verifier contract
1921
address proofVerifier;
2022
/// @notice The proposer checker contract
@@ -38,8 +40,6 @@ interface IInbox {
3840
uint16 forcedInclusionDelay;
3941
/// @notice The fee for forced inclusions in Gwei
4042
uint64 forcedInclusionFeeInGwei;
41-
/// @notice The maximum number of checkpoints to store in ring buffer
42-
uint16 maxCheckpointHistory;
4343
/// @notice The minimum delay between checkpoints in seconds
4444
/// @dev Must be less than or equal to finalization grace period
4545
uint16 minCheckpointDelay;

packages/protocol/contracts/layer1/shasta/impl/Inbox.sol

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ import { LibBlobs } from "../libs/LibBlobs.sol";
1313
import { LibBonds } from "src/shared/shasta/libs/LibBonds.sol";
1414
import { LibBondsL1 } from "../libs/LibBondsL1.sol";
1515
import { LibForcedInclusion } from "../libs/LibForcedInclusion.sol";
16-
import { LibCheckpointStore } from "src/shared/shasta/libs/LibCheckpointStore.sol";
1716
import { LibHashSimple } from "../libs/LibHashSimple.sol";
18-
import { ICheckpointStore } from "src/shared/shasta/iface/ICheckpointStore.sol";
1917
import { LibMath } from "src/shared/libs/LibMath.sol";
18+
import { ICheckpointStore } from "src/shared/shasta/iface/ICheckpointStore.sol";
2019

2120
/// @title Inbox
2221
/// @notice Core contract for managing L2 proposals, proofs, verification and forced inclusion in
@@ -28,7 +27,7 @@ import { LibMath } from "src/shared/libs/LibMath.sol";
2827
/// - Bond instruction processing for economic security
2928
/// - Finalization of proven proposals with checkpoint rate limiting
3029
/// @custom:security-contact security@taiko.xyz
31-
contract Inbox is IInbox, IForcedInclusionStore, ICheckpointStore, EssentialContract {
30+
contract Inbox is IInbox, IForcedInclusionStore, EssentialContract {
3231
using LibAddress for address;
3332
using LibMath for uint48;
3433
using LibMath for uint256;
@@ -90,9 +89,6 @@ contract Inbox is IInbox, IForcedInclusionStore, ICheckpointStore, EssentialCont
9089
/// @notice The fee for forced inclusions in Gwei.
9190
uint64 internal immutable _forcedInclusionFeeInGwei;
9291

93-
/// @notice The maximum number of checkpoints to store in ring buffer.
94-
uint16 internal immutable _maxCheckpointHistory;
95-
9692
/// @notice The minimum delay between checkpoints in seconds.
9793
uint16 internal immutable _minCheckpointDelay;
9894

@@ -133,9 +129,8 @@ contract Inbox is IInbox, IForcedInclusionStore, ICheckpointStore, EssentialCont
133129
/// @dev 2 slots used
134130
LibForcedInclusion.Storage private _forcedInclusionStorage;
135131

136-
/// @dev Storage for checkpoint management
137-
/// @dev 2 slots used
138-
LibCheckpointStore.Storage private _checkpointStorage;
132+
/// @notice Signal service responsible for checkpoints
133+
ICheckpointStore public immutable signalService;
139134

140135
uint256[37] private __gap;
141136

@@ -146,13 +141,14 @@ contract Inbox is IInbox, IForcedInclusionStore, ICheckpointStore, EssentialCont
146141
/// @notice Initializes the Inbox contract
147142
/// @param _config Configuration struct containing all constructor parameters
148143
constructor(IInbox.Config memory _config) {
149-
require(_config.maxCheckpointHistory != 0, LibCheckpointStore.InvalidMaxCheckpointHistory());
144+
require(_config.signalService != address(0), ZERO_ADDRESS());
150145
require(_config.ringBufferSize != 0, RingBufferSizeZero());
151146

152147
_codec = _config.codec;
153148
_bondToken = IERC20(_config.bondToken);
154149
_proofVerifier = IProofVerifier(_config.proofVerifier);
155150
_proposerChecker = IProposerChecker(_config.proposerChecker);
151+
signalService = ICheckpointStore(_config.signalService);
156152
_provingWindow = _config.provingWindow;
157153
_extendedProvingWindow = _config.extendedProvingWindow;
158154
_maxFinalizationCount = _config.maxFinalizationCount;
@@ -162,7 +158,6 @@ contract Inbox is IInbox, IForcedInclusionStore, ICheckpointStore, EssentialCont
162158
_minForcedInclusionCount = _config.minForcedInclusionCount;
163159
_forcedInclusionDelay = _config.forcedInclusionDelay;
164160
_forcedInclusionFeeInGwei = _config.forcedInclusionFeeInGwei;
165-
_maxCheckpointHistory = _config.maxCheckpointHistory;
166161
_minCheckpointDelay = _config.minCheckpointDelay;
167162
_permissionlessInclusionMultiplier = _config.permissionlessInclusionMultiplier;
168163
_compositeKeyVersion = _config.compositeKeyVersion;
@@ -331,6 +326,7 @@ contract Inbox is IInbox, IForcedInclusionStore, ICheckpointStore, EssentialCont
331326
config_ = IInbox.Config({
332327
codec: _codec,
333328
bondToken: address(_bondToken),
329+
signalService: address(signalService),
334330
proofVerifier: address(_proofVerifier),
335331
proposerChecker: address(_proposerChecker),
336332
provingWindow: _provingWindow,
@@ -342,28 +338,12 @@ contract Inbox is IInbox, IForcedInclusionStore, ICheckpointStore, EssentialCont
342338
minForcedInclusionCount: _minForcedInclusionCount,
343339
forcedInclusionDelay: _forcedInclusionDelay,
344340
forcedInclusionFeeInGwei: _forcedInclusionFeeInGwei,
345-
maxCheckpointHistory: _maxCheckpointHistory,
346341
minCheckpointDelay: _minCheckpointDelay,
347342
permissionlessInclusionMultiplier: _permissionlessInclusionMultiplier,
348343
compositeKeyVersion: _compositeKeyVersion
349344
});
350345
}
351346

352-
/// @inheritdoc ICheckpointStore
353-
function getCheckpoint(uint48 _offset) external view returns (Checkpoint memory) {
354-
return LibCheckpointStore.getCheckpoint(_checkpointStorage, _offset, _maxCheckpointHistory);
355-
}
356-
357-
/// @inheritdoc ICheckpointStore
358-
function getLatestCheckpointBlockNumber() external view returns (uint48) {
359-
return LibCheckpointStore.getLatestCheckpointBlockNumber(_checkpointStorage);
360-
}
361-
362-
/// @inheritdoc ICheckpointStore
363-
function getNumberOfCheckpoints() external view returns (uint48) {
364-
return LibCheckpointStore.getNumberOfCheckpoints(_checkpointStorage);
365-
}
366-
367347
// ---------------------------------------------------------------
368348
// Internal Functions
369349
// ---------------------------------------------------------------
@@ -945,9 +925,7 @@ contract Inbox is IInbox, IForcedInclusionStore, ICheckpointStore, EssentialCont
945925
bytes32 checkpointHash = _hashCheckpoint(_checkpoint);
946926
require(checkpointHash == _expectedCheckpointHash, CheckpointMismatch());
947927

948-
LibCheckpointStore.saveCheckpoint(
949-
_checkpointStorage, _checkpoint, _maxCheckpointHistory
950-
);
928+
signalService.saveCheckpoint(_checkpoint);
951929
_coreState.lastCheckpointTimestamp = uint48(block.timestamp);
952930
} else {
953931
require(

packages/protocol/contracts/layer1/shasta/impl/ShastaDevnetInbox.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ contract ShastaDevnetInbox is InboxOptimized2 {
2323
/// = (86400 * 2) / 12 / 6
2424
/// = 2400
2525
uint64 private constant _RING_BUFFER_SIZE = 2400;
26-
uint16 private constant _MAX_CHECKPOINT_HISTORY = 256;
2726

2827
// ---------------------------------------------------------------
2928
// Constructor
@@ -33,11 +32,13 @@ contract ShastaDevnetInbox is InboxOptimized2 {
3332
address _codec,
3433
address _proofVerifier,
3534
address _proposerChecker,
36-
address _taikoToken
35+
address _taikoToken,
36+
address _signalService
3737
)
3838
InboxOptimized2(
3939
IInbox.Config({
4040
bondToken: _taikoToken,
41+
signalService: _signalService,
4142
codec: _codec,
4243
proofVerifier: _proofVerifier,
4344
proposerChecker: _proposerChecker,
@@ -50,7 +51,6 @@ contract ShastaDevnetInbox is InboxOptimized2 {
5051
minForcedInclusionCount: 1,
5152
forcedInclusionDelay: 0,
5253
forcedInclusionFeeInGwei: 10_000_000, // 0.01 ETH
53-
maxCheckpointHistory: _MAX_CHECKPOINT_HISTORY,
5454
minCheckpointDelay: 384 seconds, // 1 epoch
5555
permissionlessInclusionMultiplier: 5,
5656
compositeKeyVersion: 1

packages/protocol/contracts/layer1/shasta/impl/ShastaMainnetInbox.sol

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ contract ShastaMainnetInbox is InboxOptimized2 {
2525
/// = 2400
2626
uint64 private constant _RING_BUFFER_SIZE = 2400;
2727

28-
uint16 private constant _MAX_CHECKPOINT_HISTORY = 256;
29-
3028
// ---------------------------------------------------------------
3129
// Constructor
3230
// ---------------------------------------------------------------
@@ -39,6 +37,7 @@ contract ShastaMainnetInbox is InboxOptimized2 {
3937
InboxOptimized2(
4038
IInbox.Config({
4139
bondToken: LibL1Addrs.TAIKO_TOKEN,
40+
signalService: LibL1Addrs.SIGNAL_SERVICE,
4241
codec: _codec,
4342
proofVerifier: _proofVerifier,
4443
proposerChecker: _proposerChecker,
@@ -51,7 +50,6 @@ contract ShastaMainnetInbox is InboxOptimized2 {
5150
minForcedInclusionCount: 1,
5251
forcedInclusionDelay: 100,
5352
forcedInclusionFeeInGwei: 10_000_000, // 0.01 ETH
54-
maxCheckpointHistory: _MAX_CHECKPOINT_HISTORY,
5553
minCheckpointDelay: 384 seconds, // 1 epoch
5654
permissionlessInclusionMultiplier: 5,
5755
compositeKeyVersion: 1

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

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ pragma solidity ^0.8.24;
33

44
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
55
import { PacayaAnchor } from "./PacayaAnchor.sol";
6-
import { LibCheckpointStore } from "src/shared/shasta/libs/LibCheckpointStore.sol";
76
import { ICheckpointStore } from "src/shared/shasta/iface/ICheckpointStore.sol";
7+
import { ISignalServiceShasta } from "src/shared/shasta/iface/ISignalServiceShasta.sol";
88
import { IBondManager as IShastaBondManager } from "./IBondManager.sol";
99
import { LibBonds } from "src/shared/shasta/libs/LibBonds.sol";
1010

@@ -18,7 +18,7 @@ import { LibBonds } from "src/shared/shasta/libs/LibBonds.sol";
1818
/// - State tracking for multi-block proposals
1919
/// - Checkpoint storage for L1 block data
2020
/// @custom:security-contact security@taiko.xyz
21-
abstract contract ShastaAnchor is PacayaAnchor, ICheckpointStore {
21+
abstract contract ShastaAnchor is PacayaAnchor {
2222
// ---------------------------------------------------------------
2323
// Structs
2424
// ---------------------------------------------------------------
@@ -59,9 +59,6 @@ abstract contract ShastaAnchor is PacayaAnchor, ICheckpointStore {
5959
/// @notice Contract managing bond deposits, withdrawals, and transfers.
6060
IShastaBondManager public immutable bondManager;
6161

62-
/// @notice Maximum number of checkpoints to store in ring buffer.
63-
uint16 public immutable maxCheckpointHistory;
64-
6562
// ---------------------------------------------------------------
6663
// State variables
6764
// ---------------------------------------------------------------
@@ -73,12 +70,8 @@ abstract contract ShastaAnchor is PacayaAnchor, ICheckpointStore {
7370
mapping(uint256 blockId => uint256 endOfSubmissionWindowTimestamp) public
7471
blockIdToEndOfSubmissionWindowTimeStamp;
7572

76-
/// @dev Storage for checkpoint management
77-
/// @dev 2 slots used
78-
LibCheckpointStore.Storage internal _checkpointStorage;
79-
8073
/// @notice Storage gap for upgrade safety.
81-
uint256[44] private __gap;
74+
uint256[46] private __gap;
8275

8376
// ---------------------------------------------------------------
8477
// Constructor
@@ -90,27 +83,23 @@ abstract contract ShastaAnchor is PacayaAnchor, ICheckpointStore {
9083
/// @param _signalService The address of the signal service.
9184
/// @param _pacayaForkHeight The block height at which the Pacaya fork is activated.
9285
/// @param _shastaForkHeight The block height at which the Shasta fork is activated.
93-
/// @param _maxCheckpointHistory The maximum number of checkpoints to store.
9486
/// @param _bondManager The address of the bond manager.
9587
constructor(
9688
uint48 _livenessBondGwei,
9789
uint48 _provabilityBondGwei,
9890
address _signalService,
9991
uint64 _pacayaForkHeight,
10092
uint64 _shastaForkHeight,
101-
uint16 _maxCheckpointHistory,
10293
IShastaBondManager _bondManager
10394
)
10495
PacayaAnchor(_signalService, _pacayaForkHeight, _shastaForkHeight)
10596
{
10697
require(
10798
_shastaForkHeight == 0 || _shastaForkHeight > _pacayaForkHeight, InvalidForkHeight()
10899
);
109-
require(_maxCheckpointHistory != 0, LibCheckpointStore.InvalidMaxCheckpointHistory());
110100

111101
livenessBondGwei = _livenessBondGwei;
112102
provabilityBondGwei = _provabilityBondGwei;
113-
maxCheckpointHistory = _maxCheckpointHistory;
114103
bondManager = _bondManager;
115104
}
116105

@@ -186,15 +175,13 @@ abstract contract ShastaAnchor is PacayaAnchor, ICheckpointStore {
186175

187176
// Process new L1 anchor data
188177
if (_anchorBlockNumber > previousState_.anchorBlockNumber) {
189-
// Save L1 block data
190-
LibCheckpointStore.saveCheckpoint(
191-
_checkpointStorage,
178+
// Save L1 block data to signal service
179+
ISignalServiceShasta(address(signalService)).saveCheckpoint(
192180
ICheckpointStore.Checkpoint({
193181
blockNumber: _anchorBlockNumber,
194182
blockHash: _anchorBlockHash,
195183
stateRoot: _anchorStateRoot
196-
}),
197-
maxCheckpointHistory
184+
})
198185
);
199186

200187
// Update state atomically
@@ -237,21 +224,6 @@ abstract contract ShastaAnchor is PacayaAnchor, ICheckpointStore {
237224
return _getDesignatedProver(_proposalId, _proposer, _proverAuth);
238225
}
239226

240-
/// @inheritdoc ICheckpointStore
241-
function getCheckpoint(uint48 _offset) external view returns (Checkpoint memory) {
242-
return LibCheckpointStore.getCheckpoint(_checkpointStorage, _offset, maxCheckpointHistory);
243-
}
244-
245-
/// @inheritdoc ICheckpointStore
246-
function getLatestCheckpointBlockNumber() external view returns (uint48) {
247-
return LibCheckpointStore.getLatestCheckpointBlockNumber(_checkpointStorage);
248-
}
249-
250-
/// @inheritdoc ICheckpointStore
251-
function getNumberOfCheckpoints() external view returns (uint48) {
252-
return LibCheckpointStore.getNumberOfCheckpoints(_checkpointStorage);
253-
}
254-
255227
// ---------------------------------------------------------------
256228
// Private functions
257229
// ---------------------------------------------------------------

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ contract TaikoAnchor is ShastaAnchor {
2323
address _signalService,
2424
uint64 _pacayaForkHeight,
2525
uint64 _shastaForkHeight,
26-
uint16 _maxCheckpointHistory,
2726
address _bondManager
2827
)
2928
ShastaAnchor(
@@ -32,7 +31,6 @@ contract TaikoAnchor is ShastaAnchor {
3231
_signalService,
3332
_pacayaForkHeight,
3433
_shastaForkHeight,
35-
_maxCheckpointHistory,
3634
IShastaBondManager(_bondManager)
3735
)
3836
{ }

packages/protocol/contracts/shared/shasta/iface/ICheckpointStore.sol

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface ICheckpointStore {
1111

1212
/// @notice Represents a synced checkpoint
1313
struct Checkpoint {
14+
/// @notice The block number associated with the checkpoint.
1415
uint48 blockNumber;
1516
/// @notice The block hash for the end (last) L2 block in this proposal.
1617
bytes32 blockHash;
@@ -32,17 +33,12 @@ interface ICheckpointStore {
3233
// External Functions
3334
// ---------------------------------------------------------------
3435

35-
/// @notice Gets a checkpoint by index
36-
/// @param _offset The offset of the checkpoint. Use 0 for the last checkpoint, 1 for the
37-
/// second last, etc.
38-
/// @return _ The checkpoint
39-
function getCheckpoint(uint48 _offset) external view returns (Checkpoint memory);
40-
41-
/// @notice Gets the latest checkpoint number
42-
/// @return _ The latest checkpoint number
43-
function getLatestCheckpointBlockNumber() external view returns (uint48);
36+
/// @notice Saves a checkpoint
37+
/// @param _checkpoint The checkpoint data to persist
38+
function saveCheckpoint(Checkpoint calldata _checkpoint) external;
4439

45-
/// @notice Gets the number of checkpoints
46-
/// @return _ The number of checkpoints
47-
function getNumberOfCheckpoints() external view returns (uint48);
40+
/// @notice Gets a checkpoint by its block number
41+
/// @param _blockNumber The block number associated with the checkpoint
42+
/// @return _ The checkpoint
43+
function getCheckpoint(uint48 _blockNumber) external view returns (Checkpoint memory);
4844
}

0 commit comments

Comments
 (0)