@@ -20,45 +20,51 @@ pragma solidity 0.8.15;
20
20
import {Ics23Proof} from "../interfaces/IProofVerifier.sol " ;
21
21
import {ISignatureVerifier} from "../interfaces/ISignatureVerifier.sol " ;
22
22
import {ILightClient, LightClientType} from "../interfaces/ILightClient.sol " ;
23
+ import {L1Block} from "optimism/L2/L1Block.sol " ;
23
24
24
25
/**
25
- * @title SubfinalityLightClient
26
+ * @title SequencerSoloClient
26
27
* @author Polymer Labs
27
- * @dev This specific light client implementation uses the same client that is used in the op-stack
28
+ * @dev This light client implementation verifies a single signature by the polymer p2p-signer, and updates the light
29
+ * client if valid signatures are provided.
28
30
*/
29
31
contract SequencerSoloClient is ILightClient {
30
32
LightClientType public constant LIGHT_CLIENT_TYPE = LightClientType.SequencerLightClient; // Stored as a constant
31
33
// for cheap on-chain use
34
+
35
+ ISignatureVerifier public immutable verifier;
36
+ L1Block public immutable l1BlockProvider;
37
+
32
38
uint8 private _LightClientType = uint8 (LIGHT_CLIENT_TYPE); // Also redundantly stored as a private mutable type in
33
39
// case it needs to be accessed in any proofs
34
40
35
- // consensusStates maps from the height to the appHash.
41
+ // consensusStates maps from the height to the appHash, and is modified during state updates if it is a valid state
42
+ // update.
36
43
mapping (uint256 => uint256 ) public consensusStates;
37
44
38
- ISignatureVerifier public immutable verifier;
39
-
40
- error CannotUpdatePendingOptimisticConsensusState ();
45
+ error InvalidL1Origin ();
46
+ error CannotUpdateClientWithDifferentAppHash ();
41
47
error AppHashHasNotPassedFraudProofWindow ();
42
48
error NonMembershipProofsNotYetImplemented ();
43
49
error NoConsensusStateAtHeight (uint256 height );
44
50
45
- constructor (ISignatureVerifier verifier_ ) {
51
+ constructor (ISignatureVerifier verifier_ , L1Block _l1BlockProvider ) {
46
52
verifier = verifier_;
53
+ l1BlockProvider = _l1BlockProvider;
47
54
}
48
55
49
56
/**
50
57
* @inheritdoc ILightClient
51
58
* @param proof An array of bytes that contain the l1blockhash and the sequencer's signature. The first 32 bytes of
52
- * this argument should be
53
- * the l1BlockHash, and the remaining bytes should be the sequencer signature which attests to the peptide AppHash
59
+ * this argument should be the l1BlockHash, and the remaining bytes should be the sequencer signature which attests
60
+ * to the peptide AppHash
54
61
* for that l1BlockHash
55
62
*/
56
63
function updateClient (bytes calldata proof , uint256 peptideHeight , uint256 peptideAppHash ) external override {
57
- if (consensusStates[peptideHeight] != 0 ) {
58
- return ;
64
+ if (l1BlockProvider. hash () != bytes32 (proof[: 32 ]) ) {
65
+ revert InvalidL1Origin () ;
59
66
}
60
- verifier.verifyStateUpdate (peptideHeight, bytes32 (peptideAppHash), bytes32 (proof[:32 ]), proof[32 :]);
61
- consensusStates[peptideHeight] = peptideAppHash;
67
+ _updateClient (proof, peptideHeight, peptideAppHash);
62
68
}
63
69
64
70
/**
@@ -67,10 +73,10 @@ contract SequencerSoloClient is ILightClient {
67
73
function getState (uint256 height ) external view returns (uint256 appHash ) {
68
74
return _getState (height);
69
75
}
76
+
70
77
/**
71
78
* @inheritdoc ILightClient
72
79
*/
73
-
74
80
function verifyMembership (Ics23Proof calldata proof , bytes calldata key , bytes calldata expectedValue )
75
81
external
76
82
view
@@ -88,6 +94,20 @@ contract SequencerSoloClient is ILightClient {
88
94
revert NonMembershipProofsNotYetImplemented ();
89
95
}
90
96
97
+ function _updateClient (bytes calldata proof , uint256 peptideHeight , uint256 peptideAppHash ) internal {
98
+ if (consensusStates[peptideHeight] != 0 ) {
99
+ // Note: we don't cache consensusStates[peptideHeight] in mem for gas savings here because this if statement
100
+ // would not be triggered too often, and would make the more frequent branch more expensive due to mem
101
+ // allocation.
102
+ if (consensusStates[peptideHeight] != peptideAppHash) {
103
+ revert CannotUpdateClientWithDifferentAppHash ();
104
+ }
105
+ return ;
106
+ }
107
+ verifier.verifyStateUpdate (peptideHeight, bytes32 (peptideAppHash), bytes32 (proof[:32 ]), proof[32 :]);
108
+ consensusStates[peptideHeight] = peptideAppHash;
109
+ }
110
+
91
111
/**
92
112
* @dev Returns the internal state of the light client at a given height.
93
113
*/
0 commit comments