@@ -57,13 +57,17 @@ abstract contract LCPClientBase is ILightClient, ILCPClientErrors {
5757
5858 // --------------------- Storage fields ---------------------
5959
60+ /// @dev clientId => client storage
6061 mapping (string => ClientStorage) internal clientStorages;
6162
62- // rootCA 's public key parameters
63+ /// @dev RootCA 's public key parameters
6364 AVRValidator.RSAParams internal verifiedRootCAParams;
64- // keccak256(signingCert) => RSAParams of signing public key
65+ /// @dev keccak256(signingCert) => RSAParams of signing public key
6566 mapping (bytes32 => AVRValidator.RSAParams) internal verifiedSigningRSAParams;
6667
68+ /// @dev Reserved storage space to allow for layout changes in the future
69+ uint256 [50 ] private __gap;
70+
6771 // --------------------- Constructor ---------------------
6872
6973 /// @custom:oz-upgrades-unsafe-allow constructor
@@ -100,7 +104,8 @@ abstract contract LCPClientBase is ILightClient, ILCPClientErrors {
100104 /**
101105 * @dev initializeClient initializes a new client with the given state.
102106 * If succeeded, it returns heights at which the consensus state are stored.
103- * The function must be only called by IBCHandler.
107+ * This function is guaranteed by the IBC contract to be called only once for each `clientId`.
108+ * @param clientId the client identifier which is unique within the IBC handler
104109 */
105110 function initializeClient (
106111 string calldata clientId ,
@@ -164,12 +169,18 @@ abstract contract LCPClientBase is ILightClient, ILCPClientErrors {
164169
165170 // set allowed quote status and advisories
166171 for (uint256 i = 0 ; i < clientState.allowed_quote_statuses.length ; i++ ) {
167- clientStorage.allowedStatuses.allowedQuoteStatuses[clientState.allowed_quote_statuses[i]] =
168- AVRValidator.FLAG_ALLOWED;
172+ string memory allowedQuoteStatus = clientState.allowed_quote_statuses[i];
173+ if (bytes (allowedQuoteStatus).length == 0 ) {
174+ revert LCPClientClientStateInvalidAllowedQuoteStatus ();
175+ }
176+ clientStorage.allowedStatuses.allowedQuoteStatuses[allowedQuoteStatus] = AVRValidator.FLAG_ALLOWED;
169177 }
170178 for (uint256 i = 0 ; i < clientState.allowed_advisory_ids.length ; i++ ) {
171- clientStorage.allowedStatuses.allowedAdvisories[clientState.allowed_advisory_ids[i]] =
172- AVRValidator.FLAG_ALLOWED;
179+ string memory allowedAdvisoryId = clientState.allowed_advisory_ids[i];
180+ if (bytes (allowedAdvisoryId).length == 0 ) {
181+ revert LCPClientClientStateInvalidAllowedAdvisoryId ();
182+ }
183+ clientStorage.allowedStatuses.allowedAdvisories[allowedAdvisoryId] = AVRValidator.FLAG_ALLOWED;
173184 }
174185
175186 return clientState.latest_height;
@@ -433,16 +444,22 @@ abstract contract LCPClientBase is ILightClient, ILCPClientErrors {
433444
434445 LCPCommitment.validationContextEval (pmsg.context, block .timestamp * 1e9 );
435446
436- uint128 latestHeight = clientState.latest_height.toUint128 ();
437447 uint128 postHeight = pmsg.postHeight.toUint128 ();
438- if (latestHeight < postHeight) {
439- clientState.latest_height = pmsg.postHeight;
440- }
441-
442448 consensusState = clientStorage.consensusStates[postHeight];
449+ if (consensusState.stateId != bytes32 (0 )) {
450+ if (consensusState.stateId != pmsg.postStateId || consensusState.timestamp != uint64 (pmsg.timestamp)) {
451+ revert LCPClientUpdateStateInconsistentConsensusState ();
452+ }
453+ // return empty heights if the consensus state is already stored
454+ return heights;
455+ }
443456 consensusState.stateId = pmsg.postStateId;
444457 consensusState.timestamp = uint64 (pmsg.timestamp);
445458
459+ uint128 latestHeight = clientState.latest_height.toUint128 ();
460+ if (latestHeight < postHeight) {
461+ clientState.latest_height = pmsg.postHeight;
462+ }
446463 heights = new Height.Data [](1 );
447464 heights[0 ] = pmsg.postHeight;
448465 return heights;
@@ -639,14 +656,6 @@ abstract contract LCPClientBase is ILightClient, ILCPClientErrors {
639656 }
640657 }
641658
642- function verifyECDSASignature (bytes32 commitment , bytes memory signature , address signer )
643- internal
644- pure
645- returns (bool )
646- {
647- return verifyECDSASignature (commitment, signature) == signer;
648- }
649-
650659 function verifyECDSASignature (bytes32 commitment , bytes memory signature ) internal pure returns (address ) {
651660 if (uint8 (signature[64 ]) < 27 ) {
652661 signature[64 ] = bytes1 (uint8 (signature[64 ]) + 27 );
0 commit comments