Skip to content
This repository has been archived by the owner on Nov 29, 2024. It is now read-only.

Commit

Permalink
imp: added interface contract and natspec linter (#92)
Browse files Browse the repository at this point in the history
* fix: justfile

* deps(contracts): ran 'bun update'

* imp: improved lint

* deps: added 'natspec-smells'

* just: added linter

* refactor: fixing linter complaints

* imp: all linting done

* imp: removed rust-toolchain
  • Loading branch information
srdtrk authored Aug 13, 2024
1 parent f3a6849 commit 618f9e4
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 71 deletions.
Binary file modified bun.lockb
Binary file not shown.
39 changes: 39 additions & 0 deletions contracts/src/ISP1ICS07Tendermint.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.25;

import { ILightClient } from "solidity-ibc/interfaces/ILightClient.sol";
import { IICS07TendermintMsgs } from "../src/msgs/IICS07TendermintMsgs.sol";
import { ISP1Verifier } from "@sp1-contracts/ISP1Verifier.sol";

/// @title ISP1ICS07Tendermint
/// @notice ISP1ICS07Tendermint is the interface for the ICS07 Tendermint light client
interface ISP1ICS07Tendermint is ILightClient {
/// @notice Immutable update client program verification key.
/// @return The verification key for the update client program.
function UPDATE_CLIENT_PROGRAM_VKEY() external view returns (bytes32);

/// @notice Immutable membership program verification key.
/// @return The verification key for the membership program.
function MEMBERSHIP_PROGRAM_VKEY() external view returns (bytes32);

/// @notice Immutable update client and membership program verification key.
/// @return The verification key for the update client and membership program.
function UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY() external view returns (bytes32);

/// @notice Immutable SP1 verifier contract address.
/// @return The SP1 verifier contract.
function VERIFIER() external view returns (ISP1Verifier);

/// @notice Constant allowed clock drift in seconds.
/// @return The allowed clock drift in seconds.
function ALLOWED_SP1_CLOCK_DRIFT() external view returns (uint16);

/// @notice Returns the client state.
/// @return The client state.
function getClientState() external view returns (IICS07TendermintMsgs.ClientState memory);

/// @notice Returns the consensus state keccak256 hash at the given revision height.
/// @param revisionHeight The revision height.
/// @return The consensus state at the given revision height.
function getConsensusStateHash(uint32 revisionHeight) external view returns (bytes32);
}
49 changes: 33 additions & 16 deletions contracts/src/SP1ICS07Tendermint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IMembershipMsgs } from "./msgs/IMembershipMsgs.sol";
import { IUpdateClientAndMembershipMsgs } from "./msgs/IUcAndMembershipMsgs.sol";
import { ISP1Verifier } from "@sp1-contracts/ISP1Verifier.sol";
import { ISP1ICS07TendermintErrors } from "./errors/ISP1ICS07TendermintErrors.sol";
import { ISP1ICS07Tendermint } from "./ISP1ICS07Tendermint.sol";
import { ILightClientMsgs } from "solidity-ibc/msgs/ILightClientMsgs.sol";
import { ILightClient } from "solidity-ibc/interfaces/ILightClient.sol";

Expand All @@ -21,23 +22,24 @@ contract SP1ICS07Tendermint is
IUpdateClientAndMembershipMsgs,
ISP1ICS07TendermintErrors,
ILightClientMsgs,
ILightClient
ISP1ICS07Tendermint
{
/// @notice The verification key for the update client program.
/// @inheritdoc ISP1ICS07Tendermint
bytes32 public immutable UPDATE_CLIENT_PROGRAM_VKEY;
/// @notice The verification key for the verify (non)membership program.
/// @inheritdoc ISP1ICS07Tendermint
bytes32 public immutable MEMBERSHIP_PROGRAM_VKEY;
/// @notice The verification key for the update client and membership program.
/// @inheritdoc ISP1ICS07Tendermint
bytes32 public immutable UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY;
/// @notice The SP1 verifier contract.
/// @inheritdoc ISP1ICS07Tendermint
ISP1Verifier public immutable VERIFIER;

/// @notice The ICS07Tendermint client state
ClientState private clientState;
/// @notice The mapping from height to consensus state keccak256 hashes.
mapping(uint32 height => bytes32 hash) private consensusStateHashes;

/// Allowed clock drift in seconds
/// @notice Allowed clock drift in seconds.
/// @inheritdoc ISP1ICS07Tendermint
uint16 public constant ALLOWED_SP1_CLOCK_DRIFT = 3000; // 3000 seconds

/// @notice The constructor sets the program verification key and the initial client and consensus states.
Expand All @@ -64,15 +66,12 @@ contract SP1ICS07Tendermint is
consensusStateHashes[clientState.latestHeight.revisionHeight] = _consensusState;
}

/// @notice Returns the client state.
/// @return The client state.
/// @inheritdoc ISP1ICS07Tendermint
function getClientState() public view returns (ClientState memory) {
return clientState;
}

/// @notice Returns the consensus state keccak256 hash at the given revision height.
/// @param revisionHeight The revision height.
/// @return The consensus state at the given revision height.
/// @inheritdoc ISP1ICS07Tendermint
function getConsensusStateHash(uint32 revisionHeight) public view returns (bytes32) {
bytes32 hash = consensusStateHashes[revisionHeight];
if (hash == 0) {
Expand All @@ -85,6 +84,7 @@ contract SP1ICS07Tendermint is
/// @dev This function verifies the public values and forwards the proof to the SP1 verifier.
/// @param updateMsg The encoded update message.
/// @return The result of the update.
/// @inheritdoc ILightClient
function updateClient(bytes calldata updateMsg) public returns (UpdateResult) {
MsgUpdateClient memory msgUpdateClient = abi.decode(updateMsg, (MsgUpdateClient));
if (msgUpdateClient.sp1Proof.vKey != UPDATE_CLIENT_PROGRAM_VKEY) {
Expand Down Expand Up @@ -116,6 +116,7 @@ contract SP1ICS07Tendermint is
/// @notice The entrypoint for verifying (non)membership proof.
/// @param msgMembership The membership message.
/// @return timestamp The timestamp of the trusted consensus state.
/// @inheritdoc ILightClient
function membership(MsgMembership calldata msgMembership) public returns (uint256 timestamp) {
MembershipProof memory membershipProof = abi.decode(msgMembership.proof, (MembershipProof));
if (membershipProof.proofType == MembershipProofType.SP1MembershipProof) {
Expand All @@ -132,17 +133,25 @@ contract SP1ICS07Tendermint is
}

/// @notice The entrypoint for misbehaviour.
/// TODO: Not yet implemented. (#56)
/// @inheritdoc ILightClient
function misbehaviour(bytes calldata) public pure {
// TODO: Not yet implemented. (#56)
revert FeatureNotSupported();
}

/// @notice The entrypoint for upgrading the client.
/// TODO: Not yet implemented. (#78)
/// @inheritdoc ILightClient
function upgradeClient(bytes calldata) public pure {
// TODO: Not yet implemented. (#78)
revert FeatureNotSupported();
}

/// @notice Handles the `SP1MembershipProof` proof type.
/// @param proofHeight The height of the proof.
/// @param proofBytes The encoded proof.
/// @param kvPath The path of the key-value pair.
/// @param kvValue The value of the key-value pair.
/// @return The timestamp of the trusted consensus state.
function handleSP1MembershipProof(
Height memory proofHeight,
bytes memory proofBytes,
Expand Down Expand Up @@ -199,7 +208,7 @@ contract SP1ICS07Tendermint is
return proof.trustedConsensusState.timestamp;
}

/// @notice The entrypoint for updating the client and membership proof.
/// @notice The entrypoint for handling the `SP1MembershipAndUpdateClientProof` proof type.
/// @dev This function verifies the public values and forwards the proof to the SP1 verifier.
/// @param proofHeight The height of the proof.
/// @param proofBytes The encoded proof.
Expand Down Expand Up @@ -351,13 +360,13 @@ contract SP1ICS07Tendermint is
/// @dev This function checks if the consensus state at the new height is different than the one in the mapping.
/// @dev This function does not check timestamp misbehaviour (a niche case).
/// @param output The public values of the update client program.
/// @return The result of the update.
function checkUpdateResult(UpdateClientOutput memory output) private view returns (UpdateResult) {
bytes32 consensusStateHash = consensusStateHashes[output.newHeight.revisionHeight];
if (consensusStateHash == bytes32(0)) {
// No consensus state at the new height, so no misbehaviour
return UpdateResult.Update;
}
if (consensusStateHash != keccak256(abi.encode(output.newConsensusState))) {
} else if (consensusStateHash != keccak256(abi.encode(output.newConsensusState))) {
// The consensus state at the new height is different than the one in the mapping
return UpdateResult.Misbehaviour;
} else {
Expand All @@ -366,11 +375,19 @@ contract SP1ICS07Tendermint is
}
}

/// @notice Verifies the SP1 proof.
/// @param proof The SP1 proof.
function verifySP1Proof(SP1Proof memory proof) private view {
VERIFIER.verifyProof(proof.vKey, proof.publicValues, proof.proof);
}

/// @notice A dummy function to generate the ABI for the parameters.
/// @param o1 The MembershipOutput.
/// @param o2 The UcAndMembershipOutput.
/// @param o3 The MsgUpdateClient.
/// @param o4 The MembershipProof.
/// @param o5 The SP1MembershipProof.
/// @param o6 The SP1MembershipAndUpdateClientProof.
function abiPublicTypes(
MembershipOutput memory o1,
UcAndMembershipOutput memory o2,
Expand Down
30 changes: 15 additions & 15 deletions contracts/src/msgs/IICS07TendermintMsgs.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,39 @@ import { IICS02ClientMsgs } from "solidity-ibc/msgs/IICS02ClientMsgs.sol";
/// @author srdtrk
/// @notice Defines shared types for ICS07Tendermint implementations.
interface IICS07TendermintMsgs is IICS02ClientMsgs {
/// Fraction of validator overlap needed to update header
/// @notice Fraction of validator overlap needed to update header
/// @param numerator Numerator of the fraction
/// @param denominator Denominator of the fraction
struct TrustThreshold {
/// Numerator of the fraction
uint8 numerator;
/// Denominator of the fraction
uint8 denominator;
}

/// @notice Defines the ICS07Tendermint ClientState for ibc-lite
/// @param chainId Chain ID
/// @param trustLevel Fraction of validator overlap needed to update header
/// @param latestHeight Latest height the client was updated to
/// @param trustingPeriod duration of the period since the LatestTimestamp during which the
/// submitted headers are valid for upgrade in seconds.
/// @param unbondingPeriod duration of the staking unbonding period in seconds
/// @param isFrozen whether or not client is frozen (due to misbehavior)
struct ClientState {
/// Chain ID
string chainId;
/// Fraction of validator overlap needed to update header
TrustThreshold trustLevel;
/// Latest height the client was updated to
Height latestHeight;
/// duration of the period since the LatestTimestamp during which the
/// submitted headers are valid for upgrade in seconds
uint32 trustingPeriod;
/// duration of the staking unbonding period in seconds
uint32 unbondingPeriod;
/// whether or not client is frozen (due to misbehavior)
bool isFrozen;
}

/// Defines the Tendermint light client's consensus state at some height.
/// @notice Defines the Tendermint light client's consensus state at some height.
/// @param timestamp timestamp that corresponds to the counterparty block height
/// in which the ConsensusState was generated.
/// @param root commitment root (i.e app hash)
/// @param nextValidatorsHash next validators hash
struct ConsensusState {
/// timestamp that corresponds to the block height in which the ConsensusState
/// was stored.
uint64 timestamp;
/// commitment root (i.e app hash)
bytes32 root;
/// next validators hash
bytes32 nextValidatorsHash;
}
}
30 changes: 15 additions & 15 deletions contracts/src/msgs/IMembershipMsgs.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,40 @@ import { IICS07TendermintMsgs } from "./IICS07TendermintMsgs.sol";
/// @notice Defines shared types for the verify (non)membership program.
interface IMembershipMsgs is ISP1Msgs {
/// @notice The key-value pair used in the verify (non)membership program.
/// @param path The path of the value in the key-value store.
/// @param value The value of the key-value pair.
struct KVPair {
/// The path of the value in the key-value store.
bytes path;
/// The value of the key-value pair.
bytes value;
}

/// @notice The public value output for the sp1 verify (non)membership program.
/// @param commitmentRoot The app hash of the header.
/// @param kvPairs The key-value pairs verified by the program.
struct MembershipOutput {
/// The app hash of the header.
bytes32 commitmentRoot;
/// The key-value pairs verified by the program.
KVPair[] kvPairs;
}

/// @notice The membership proof that can be submitted to the SP1Verifier contract.
/// @param proofType The type of the membership proof.
/// @param proof The membership proof.
struct MembershipProof {
MembershipProofType proofType;
bytes proof;
}

/// @notice The membership proof for the sp1 verify (non)membership program.
/// @param sp1Proof The sp1 proof for the membership program.
/// @param trustedConsensusState The trusted consensus state that the proof is based on.
struct SP1MembershipProof {
/// The sp1 proof for the membership program.
SP1Proof sp1Proof;
/// The trusted consensus state that the proof is based on.
IICS07TendermintMsgs.ConsensusState trustedConsensusState;
}

/// @notice The membership proof for the sp1 verify (non)membership and update client program.
/// @param sp1Proof The sp1 proof for the membership and update client program.
struct SP1MembershipAndUpdateClientProof {
/// The sp1 proof for the membership and update client program.
SP1Proof sp1Proof;
}

Expand All @@ -45,12 +53,4 @@ interface IMembershipMsgs is ISP1Msgs {
/// The proof is for the verify membership and update client program.
SP1MembershipAndUpdateClientProof
}

/// @notice The membership proof that can be submitted to the SP1Verifier contract.
struct MembershipProof {
/// The type of the membership proof.
MembershipProofType proofType;
/// The membership proof.
bytes proof;
}
}
6 changes: 3 additions & 3 deletions contracts/src/msgs/ISP1Msgs.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ pragma solidity >=0.8.25;
/// @title SP1 Messages
interface ISP1Msgs {
/// @notice The SP1 proof that can be submitted to the SP1Verifier contract.
/// @param vKey The verification key for the program.
/// @param publicValues The public values for the program.
/// @param proof The proof for the program.
struct SP1Proof {
/// The verification key for the program.
bytes32 vKey;
/// The public values for the program.
bytes publicValues;
/// The proof for the program.
bytes proof;
}
}
4 changes: 2 additions & 2 deletions contracts/src/msgs/IUcAndMembershipMsgs.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import { IMembershipMsgs } from "./IMembershipMsgs.sol";
/// @notice Defines shared types for the update client and membership program.
interface IUpdateClientAndMembershipMsgs is IUpdateClientMsgs {
/// @notice The public value output for the sp1 update client and membership program.
/// @param updateClientOutput The output of the update client program.
/// @param kvPairs The key-value pairs verified by the membership program in the proposed header.
struct UcAndMembershipOutput {
/// Update client program output.
UpdateClientOutput updateClientOutput;
/// The key-value pairs verified by the membership program in the proposed header.
IMembershipMsgs.KVPair[] kvPairs;
}
}
22 changes: 11 additions & 11 deletions contracts/src/msgs/IUpdateClientMsgs.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,35 @@ import { ISP1Msgs } from "./ISP1Msgs.sol";
/// @notice Defines shared types for the update client program.
interface IUpdateClientMsgs is IICS07TendermintMsgs, ISP1Msgs {
/// @notice The message that is submitted to the updateClient function.
/// @param sp1Proof The SP1 proof for updating the client.
struct MsgUpdateClient {
/// SP1 proof for updating the client.
SP1Proof sp1Proof;
}

/// @notice The public value output for the sp1 update client program.
/// @param trustedConsensusState The trusted consensus state.
/// @param newConsensusState The new consensus state with the verified header.
/// @param env The validation environment.
/// @param trustedHeight The trusted height.
/// @param newHeight The new height.
struct UpdateClientOutput {
/// The trusted consensus state.
ConsensusState trustedConsensusState;
/// The new consensus state with the verified header.
ConsensusState newConsensusState;
/// The validation environment.
Env env;
/// trusted height
Height trustedHeight;
/// new height
Height newHeight;
}

/// @notice The environment output for the sp1 program.
/// @param chainId The chain ID of the chain that the client is tracking.
/// @param trustThreshold Fraction of validator overlap needed to update header
/// @param trustingPeriod Duration of the period since the `LatestTimestamp` during which the
/// submitted headers are valid for upgrade in seconds.
/// @param now Timestamp in seconds.
struct Env {
/// The chain ID of the chain that the client is tracking.
string chainId;
/// Fraction of validator overlap needed to update header
TrustThreshold trustThreshold;
/// Duration of the period since the `LatestTimestamp` during which the
/// submitted headers are valid for upgrade in seconds.
uint32 trustingPeriod;
/// Timestamp in seconds
uint64 now;
}
}
Loading

0 comments on commit 618f9e4

Please sign in to comment.