Skip to content

Commit

Permalink
feat(protocol): sync state root rather than signal service's storage …
Browse files Browse the repository at this point in the history
…root (#15671)

Co-authored-by: Keszey Dániel <[email protected]>
Co-authored-by: Brecht Devos <[email protected]>
  • Loading branch information
3 people authored Feb 10, 2024
1 parent 6e2771c commit ea33e65
Show file tree
Hide file tree
Showing 27 changed files with 222 additions and 290 deletions.
4 changes: 2 additions & 2 deletions packages/protocol/contracts/L1/TaikoData.sol
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ library TaikoData {
struct Transition {
bytes32 parentHash;
bytes32 blockHash;
bytes32 signalRoot;
bytes32 stateRoot;
bytes32 graffiti;
}

Expand All @@ -128,7 +128,7 @@ library TaikoData {
struct TransitionState {
bytes32 key; // slot 1, only written/read for the 1st state transition.
bytes32 blockHash; // slot 2
bytes32 signalRoot; // slot 3
bytes32 stateRoot; // slot 3
address prover; // slot 4
uint96 validityBond;
address contester; // slot 5
Expand Down
4 changes: 2 additions & 2 deletions packages/protocol/contracts/L1/TaikoEvents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ abstract contract TaikoEvents {
/// @param prover The prover whose transition is used for verifing the
/// block.
/// @param blockHash The hash of the verified block.
/// @param signalRoot The latest value of the signal service storage.
/// @param stateRoot The block's state root.
/// @param tier The tier ID of the proof.
/// @param contestations Number of total contestations.
event BlockVerified(
uint256 indexed blockId,
address indexed assignedProver,
address indexed prover,
bytes32 blockHash,
bytes32 signalRoot,
bytes32 stateRoot,
uint16 tier,
uint8 contestations
);
Expand Down
3 changes: 3 additions & 0 deletions packages/protocol/contracts/L1/TaikoL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ contract TaikoL1 is
}

/// @inheritdoc ICrossChainSync
/// @notice Important: as this contract doesn't send each block's state root as a signal when
/// the block is verified, bridging developers should subscribe to CrossChainSynced events
/// to ensure all synced state roots are verifiable using merkle proofs.
function getSyncedSnippet(uint64 blockId)
public
view
Expand Down
14 changes: 7 additions & 7 deletions packages/protocol/contracts/L1/libs/LibProving.sol
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ library LibProving {
{
// Make sure parentHash is not zero
// To contest an existing transition, simply use any non-zero value as
// the blockHash and signalRoot.
if (tran.parentHash == 0 || tran.blockHash == 0 || tran.signalRoot == 0) {
// the blockHash and stateRoot.
if (tran.parentHash == 0 || tran.blockHash == 0 || tran.stateRoot == 0) {
revert L1_INVALID_TRANSITION();
}

Expand All @@ -110,7 +110,7 @@ library LibProving {
}

// Each transition is uniquely identified by the parentHash, with the
// blockHash and signalRoot open for later updates as higher-tier proofs
// blockHash and stateRoot open for later updates as higher-tier proofs
// become available. In cases where a transition with the specified
// parentHash does not exist, the transition ID (tid) will be set to 0.
(uint32 tid, TaikoData.TransitionState storage ts) =
Expand Down Expand Up @@ -183,7 +183,7 @@ library LibProving {
}
}

bool sameTransition = tran.blockHash == ts.blockHash && tran.signalRoot == ts.signalRoot;
bool sameTransition = tran.blockHash == ts.blockHash && tran.stateRoot == ts.stateRoot;

if (proof.tier > ts.tier) {
// Handles the case when an incoming tier is higher than the current transition's tier.
Expand All @@ -210,7 +210,7 @@ library LibProving {

ts.prover = msg.sender;
ts.blockHash = tran.blockHash;
ts.signalRoot = tran.signalRoot;
ts.stateRoot = tran.stateRoot;

emit TransitionProved({
blockId: blk.blockId,
Expand Down Expand Up @@ -283,7 +283,7 @@ library LibProving {
// below.
ts = state.transitions[slot][tid];
ts.blockHash = 0;
ts.signalRoot = 0;
ts.stateRoot = 0;
ts.validityBond = 0;
ts.contester = address(0);
ts.contestBond = 1; // to save gas
Expand Down Expand Up @@ -376,7 +376,7 @@ library LibProving {

if (!sameTransition) {
ts.blockHash = tran.blockHash;
ts.signalRoot = tran.signalRoot;
ts.stateRoot = tran.stateRoot;
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/contracts/L1/libs/LibUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ library LibUtils {
remoteBlockId: blockId,
syncedInBlock: blk.proposedIn,
blockHash: transition.blockHash,
signalRoot: transition.signalRoot
stateRoot: transition.stateRoot
});
}

Expand Down
22 changes: 13 additions & 9 deletions packages/protocol/contracts/L1/libs/LibVerifying.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ library LibVerifying {
address indexed assignedProver,
address indexed prover,
bytes32 blockHash,
bytes32 signalRoot,
bytes32 stateRoot,
uint16 tier,
uint8 contestations
);

event CrossChainSynced(
uint64 indexed syncedInBlock, uint64 indexed blockId, bytes32 blockHash, bytes32 signalRoot
uint64 indexed syncedInBlock, uint64 indexed blockId, bytes32 blockHash, bytes32 stateRoot
);

// Warning: Any errors defined here must also be defined in TaikoErrors.sol.
Expand Down Expand Up @@ -78,7 +78,7 @@ library LibVerifying {
assignedProver: address(0),
prover: address(0),
blockHash: genesisBlockHash,
signalRoot: 0,
stateRoot: 0,
tier: 0,
contestations: 0
});
Expand Down Expand Up @@ -135,7 +135,7 @@ library LibVerifying {
// The `blockHash` variable represents the most recently trusted
// blockHash on L2.
bytes32 blockHash = state.transitions[slot][tid].blockHash;
bytes32 signalRoot;
bytes32 stateRoot;
uint64 processed;
address tierProvider;

Expand Down Expand Up @@ -185,7 +185,7 @@ library LibVerifying {

// Update variables
blockHash = ts.blockHash;
signalRoot = ts.signalRoot;
stateRoot = ts.stateRoot;

// We consistently return the liveness bond and the validity
// bond to the actual prover of the transition utilized for
Expand Down Expand Up @@ -222,7 +222,7 @@ library LibVerifying {
assignedProver: blk.assignedProver,
prover: ts.prover,
blockHash: blockHash,
signalRoot: signalRoot,
stateRoot: stateRoot,
tier: ts.tier,
contestations: ts.contestations
});
Expand All @@ -237,12 +237,16 @@ library LibVerifying {
// Update protocol level state variables
state.slotB.lastVerifiedBlockId = lastVerifiedBlockId;

// Store the L2's signal root as a signal to the local signal
// Store the L2's state root as a signal to the local signal
// service to allow for multi-hop bridging.
ISignalService(resolver.resolve("signal_service", false)).sendSignal(signalRoot);
//
// This also means if we verified more than one block, only the last one's stateRoot
// is sent as a signal and verifiable with merkle proofs, all other blocks'
// stateRoot are not.
ISignalService(resolver.resolve("signal_service", false)).sendSignal(stateRoot);

emit CrossChainSynced(
uint64(block.number), lastVerifiedBlockId, blockHash, signalRoot
uint64(block.number), lastVerifiedBlockId, blockHash, stateRoot
);
}
}
Expand Down
19 changes: 11 additions & 8 deletions packages/protocol/contracts/L2/TaikoL2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,22 +100,24 @@ contract TaikoL2 is CrossChainOwned, ICrossChainSync {
/// message verification.
/// @param l1BlockHash The latest L1 block hash when this block was
/// proposed.
/// @param l1SignalRoot The latest value of the L1 signal root.
/// @param l1StateRoot The latest L1 block's state root.
/// @param l1Height The latest L1 block height when this block was proposed.
/// @param parentGasUsed The gas used in the parent block.
function anchor(
bytes32 l1BlockHash,
bytes32 l1SignalRoot,
bytes32 l1StateRoot,
uint64 l1Height,
uint32 parentGasUsed
)
external
nonReentrant
{
if (
l1BlockHash == 0 || l1SignalRoot == 0 || l1Height == 0
l1BlockHash == 0 || l1StateRoot == 0 || l1Height == 0
|| (block.number != 1 && parentGasUsed == 0)
) revert L2_INVALID_PARAM();
) {
revert L2_INVALID_PARAM();
}

if (msg.sender != GOLDEN_TOUCH_ADDRESS) revert L2_INVALID_SENDER();

Expand All @@ -139,18 +141,19 @@ contract TaikoL2 is CrossChainOwned, ICrossChainSync {
revert L2_BASEFEE_MISMATCH();
}

// Store the L1's signal root as a signal to the local signal service to
// Store the L1's state root as a signal to the local signal service to
// allow for multi-hop bridging.
ISignalService(resolve("signal_service", false)).sendSignal(l1SignalRoot);
emit CrossChainSynced(uint64(block.number), l1Height, l1BlockHash, l1SignalRoot);
ISignalService(resolve("signal_service", false)).sendSignal(l1StateRoot);

emit CrossChainSynced(uint64(block.number), l1Height, l1BlockHash, l1StateRoot);

// Update state variables
l2Hashes[parentId] = blockhash(parentId);
snippets[l1Height] = ICrossChainSync.Snippet({
remoteBlockId: l1Height,
syncedInBlock: uint64(block.number),
blockHash: l1BlockHash,
signalRoot: l1SignalRoot
stateRoot: l1StateRoot
});
publicInputHash = publicInputHashNew;
latestSyncedL1Height = l1Height;
Expand Down
9 changes: 4 additions & 5 deletions packages/protocol/contracts/common/ICrossChainSync.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,17 @@ interface ICrossChainSync {
uint64 remoteBlockId;
uint64 syncedInBlock;
bytes32 blockHash;
bytes32 signalRoot;
bytes32 stateRoot;
}

/// @dev Emitted when a block has been synced across chains.
/// @param syncedInBlock The ID of this chain's block where the sync
/// happened.
/// @param blockId The ID of the remote block whose block hash and
/// signal root are synced.
/// @param blockId The ID of the remote block whose block hash are synced.
/// @param blockHash The hash of the synced block.
/// @param signalRoot The root hash representing cross-chain signals.
/// @param stateRoot The block's state root.
event CrossChainSynced(
uint64 indexed syncedInBlock, uint64 indexed blockId, bytes32 blockHash, bytes32 signalRoot
uint64 indexed syncedInBlock, uint64 indexed blockId, bytes32 blockHash, bytes32 stateRoot
);

/// @notice Fetches the hash of a block from the opposite chain.
Expand Down
Loading

0 comments on commit ea33e65

Please sign in to comment.