Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add getLatestInfo function to ILightClient #257

Merged
merged 2 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
IBCMockAppTest:testHandshake() (gas: 3433206)
IBCMockAppTest:testHandshakeBetweenDifferentPorts() (gas: 2539275)
IBCMockAppTest:testPacketRelay() (gas: 9485102)
IBCMockAppTest:testPacketTimeout() (gas: 2906505)
IBCMockAppTest:testPacketRelay() (gas: 9417242)
IBCMockAppTest:testPacketTimeout() (gas: 2899060)
IBCTest:testBenchmarkCreateMockClient() (gas: 209365)
IBCTest:testBenchmarkLCUpdateMockClient() (gas: 39945)
IBCTest:testBenchmarkRecvPacket() (gas: 129941)
IBCTest:testBenchmarkSendPacket() (gas: 84051)
IBCTest:testBenchmarkSendPacket() (gas: 81008)
IBCTest:testBenchmarkUpdateMockClient() (gas: 137373)
IBCTest:testToUint128((uint64,uint64)) (runs: 256, μ: 947, ~: 947)
TestICS02:testCreateClient() (gas: 23157317)
TestICS02:testInvalidCreateClient() (gas: 23006914)
TestICS02:testInvalidUpdateClient() (gas: 23008761)
TestICS02:testRegisterClient() (gas: 22751790)
TestICS02:testRegisterClientDuplicatedClientType() (gas: 22735015)
TestICS02:testRegisterClientInvalidClientType() (gas: 22719144)
TestICS02:testUpdateClient() (gas: 23174313)
TestICS02:testCreateClient() (gas: 23141284)
TestICS02:testInvalidCreateClient() (gas: 22990881)
TestICS02:testInvalidUpdateClient() (gas: 22992728)
TestICS02:testRegisterClient() (gas: 22735757)
TestICS02:testRegisterClientDuplicatedClientType() (gas: 22718982)
TestICS02:testRegisterClientInvalidClientType() (gas: 22703111)
TestICS02:testUpdateClient() (gas: 23158280)
TestICS03Handshake:testConnOpenAck() (gas: 1631720)
TestICS03Handshake:testConnOpenConfirm() (gas: 1766228)
TestICS03Handshake:testConnOpenInit() (gas: 1279055)
Expand All @@ -40,12 +40,12 @@ TestICS04Handshake:testInvalidChanOpenConfirm() (gas: 2116580)
TestICS04Handshake:testInvalidChanOpenInit() (gas: 1275939)
TestICS04Handshake:testInvalidChanOpenTry() (gas: 1352198)
TestICS04Packet:testAcknowledgementPacket() (gas: 2276942)
TestICS04Packet:testInvalidSendPacket() (gas: 2274601)
TestICS04Packet:testInvalidSendPacket() (gas: 2274365)
TestICS04Packet:testRecvPacket() (gas: 7645640)
TestICS04Packet:testRecvPacketTimeoutHeight() (gas: 2320869)
TestICS04Packet:testRecvPacketTimeoutTimestamp() (gas: 2319828)
TestICS04Packet:testSendPacket() (gas: 5067297)
TestICS04Packet:testTimeoutOnClose() (gas: 2539008)
TestICS04Packet:testRecvPacketTimeoutHeight() (gas: 2314783)
TestICS04Packet:testRecvPacketTimeoutTimestamp() (gas: 2313742)
TestICS04Packet:testSendPacket() (gas: 5018609)
TestICS04Packet:testTimeoutOnClose() (gas: 2532922)
TestICS20:testAddressToHex(address) (runs: 256, μ: 22676, ~: 22804)
TestICS20:testHexToAddress(string) (runs: 256, μ: 4776, ~: 4734)
TestICS20:testIsEscapedString() (gas: 48979)
Expand Down
31 changes: 22 additions & 9 deletions contracts/clients/IBFT2Client.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ contract IBFT2Client is ILightClient, ILightClientErrors {
string calldata clientId,
bytes calldata protoClientState,
bytes calldata protoConsensusState
) external override onlyIBC returns (Height.Data memory height) {
) public override onlyIBC returns (Height.Data memory height) {
ClientState.Data memory clientState = unmarshalClientState(protoClientState);
ConsensusState.Data memory consensusState = unmarshalConsensusState(protoConsensusState);
if (clientState.ibc_store_address.length != 20) {
Expand All @@ -103,7 +103,7 @@ contract IBFT2Client is ILightClient, ILightClientErrors {
* The light client encodes a client message as ethereum ABI.
*/
function routeUpdateClient(string calldata clientId, bytes calldata protoClientMessage)
external
public
pure
virtual
override
Expand All @@ -118,7 +118,7 @@ contract IBFT2Client is ILightClient, ILightClientErrors {
* The timestamp is nanoseconds since unix epoch.
*/
function getTimestampAtHeight(string calldata clientId, Height.Data calldata height)
external
public
view
override
returns (uint64)
Expand All @@ -134,7 +134,7 @@ contract IBFT2Client is ILightClient, ILightClientErrors {
/**
* @dev getLatestHeight returns the latest height of the client state corresponding to `clientId`.
*/
function getLatestHeight(string calldata clientId) external view override returns (Height.Data memory) {
function getLatestHeight(string calldata clientId) public view override returns (Height.Data memory) {
ClientState.Data storage clientState = clientStates[clientId];
if (clientState.latest_height.revision_height == 0) {
revert ClientStateNotFound(clientId);
Expand All @@ -145,10 +145,23 @@ contract IBFT2Client is ILightClient, ILightClientErrors {
/**
* @dev getStatus returns the status of the client corresponding to `clientId`.
*/
function getStatus(string calldata) external pure override returns (ILightClient.ClientStatus) {
function getStatus(string calldata) public pure override returns (ILightClient.ClientStatus) {
return ILightClient.ClientStatus.Active;
}

/**
* @dev getLatestInfo returns the latest height, timestamp and status of the client corresponding to `clientId`.
*/
function getLatestInfo(string calldata clientId)
public
view
returns (Height.Data memory latestHeight, uint64 latestTimestamp, ClientStatus status)
{
latestHeight = getLatestHeight(clientId);
latestTimestamp = consensusStates[clientId][latestHeight.toUint128()].timestamp;
status = ILightClient.ClientStatus.Active;
}

/**
* @dev updateClient updates the client with the given header
*/
Expand Down Expand Up @@ -204,7 +217,7 @@ contract IBFT2Client is ILightClient, ILightClientErrors {
bytes memory prefix,
bytes memory path,
bytes calldata value
) external view override returns (bool) {
) public view override returns (bool) {
if (!validateArgsAndDelayPeriod(clientId, height, delayTimePeriod, delayBlockPeriod, prefix, proof)) {
return false;
}
Expand Down Expand Up @@ -232,7 +245,7 @@ contract IBFT2Client is ILightClient, ILightClientErrors {
bytes calldata proof,
bytes calldata prefix,
bytes calldata path
) external view override returns (bool) {
) public view override returns (bool) {
if (!validateArgsAndDelayPeriod(clientId, height, delayTimePeriod, delayBlockPeriod, prefix, proof)) {
return false;
}
Expand Down Expand Up @@ -493,7 +506,7 @@ contract IBFT2Client is ILightClient, ILightClientErrors {
* @dev getClientState returns the clientState corresponding to `clientId`.
* If it's not found, the function returns false.
*/
function getClientState(string calldata clientId) external view returns (bytes memory clientStateBytes, bool) {
function getClientState(string calldata clientId) public view returns (bytes memory clientStateBytes, bool) {
ClientState.Data storage clientState = clientStates[clientId];
if (clientState.latest_height.revision_height == 0) {
return (clientStateBytes, false);
Expand All @@ -506,7 +519,7 @@ contract IBFT2Client is ILightClient, ILightClientErrors {
* If it's not found, the function returns false.
*/
function getConsensusState(string calldata clientId, Height.Data calldata height)
external
public
view
returns (bytes memory consensusStateBytes, bool)
{
Expand Down
10 changes: 10 additions & 0 deletions contracts/clients/LocalhostClient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,16 @@ contract LocalhostClient is ILightClient, ILightClientErrors {
return ClientStatus.Active;
}

function getLatestInfo(string calldata clientId)
public
view
returns (Height.Data memory latestHeight, uint64 latestTimestamp, ClientStatus status)
{
latestHeight = getLatestHeight(clientId);
latestTimestamp = uint64(block.timestamp);
status = ILightClient.ClientStatus.Active;
}

/**
* @dev verifyMembership is a generic proof verification method which verifies a proof of the existence of a value at a given CommitmentPath at the specified height.
* The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
Expand Down
33 changes: 23 additions & 10 deletions contracts/clients/MockClient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ contract MockClient is Ownable, ILightClient, ILightClientErrors {
string calldata clientId,
bytes calldata protoClientState,
bytes calldata protoConsensusState
) external virtual override onlyIBC returns (Height.Data memory height) {
) public virtual override onlyIBC returns (Height.Data memory height) {
ClientState.Data memory clientState = unmarshalClientState(protoClientState);
ConsensusState.Data memory consensusState = unmarshalConsensusState(protoConsensusState);
if (clientState.latest_height.revision_number != 0 || clientState.latest_height.revision_height == 0) {
Expand All @@ -70,7 +70,7 @@ contract MockClient is Ownable, ILightClient, ILightClientErrors {
* The light client encodes a client message as ethereum ABI.
*/
function routeUpdateClient(string calldata clientId, bytes calldata protoClientMessage)
external
public
pure
virtual
override
Expand All @@ -92,7 +92,7 @@ contract MockClient is Ownable, ILightClient, ILightClientErrors {
* The timestamp is nanoseconds since unix epoch.
*/
function getTimestampAtHeight(string calldata clientId, Height.Data calldata height)
external
public
view
virtual
override
Expand All @@ -108,7 +108,7 @@ contract MockClient is Ownable, ILightClient, ILightClientErrors {
/**
* @dev getLatestHeight returns the latest height of the client state corresponding to `clientId`.
*/
function getLatestHeight(string calldata clientId) external view virtual override returns (Height.Data memory) {
function getLatestHeight(string calldata clientId) public view virtual override returns (Height.Data memory) {
ClientState.Data storage clientState = clientStates[clientId];
if (clientState.latest_height.revision_height == 0) {
revert ClientStateNotFound(clientId);
Expand All @@ -119,14 +119,27 @@ contract MockClient is Ownable, ILightClient, ILightClientErrors {
/**
* @dev getStatus returns the status of the client corresponding to `clientId`.
*/
function getStatus(string calldata clientId) external view virtual override returns (ClientStatus) {
function getStatus(string calldata clientId) public view virtual override returns (ClientStatus) {
return statuses[clientId];
}

/**
* @dev getLatestInfo returns the latest height, the latest timestamp, and the status of the client corresponding to `clientId`.
*/
function getLatestInfo(string calldata clientId)
public
view
returns (Height.Data memory latestHeight, uint64 latestTimestamp, ClientStatus status)
{
latestHeight = getLatestHeight(clientId);
latestTimestamp = consensusStates[clientId][latestHeight.toUint128()].timestamp;
status = statuses[clientId];
}
/**
* @dev setStatus sets the status of the client corresponding to `clientId`.
*/
function setStatus(string calldata clientId, ClientStatus status) external virtual onlyOwner {

function setStatus(string calldata clientId, ClientStatus status) public virtual onlyOwner {
statuses[clientId] = status;
}

Expand Down Expand Up @@ -165,7 +178,7 @@ contract MockClient is Ownable, ILightClient, ILightClientErrors {
bytes memory prefix,
bytes memory path,
bytes calldata value
) external view virtual override returns (bool) {
) public view virtual override returns (bool) {
if (consensusStates[clientId][height.toUint128()].timestamp == 0) {
revert ConsensusStateNotFound(clientId, height);
}
Expand All @@ -191,7 +204,7 @@ contract MockClient is Ownable, ILightClient, ILightClientErrors {
bytes calldata proof,
bytes memory prefix,
bytes memory path
) external view virtual override returns (bool) {
) public view virtual override returns (bool) {
if (consensusStates[clientId][height.toUint128()].timestamp == 0) {
revert ConsensusStateNotFound(clientId, height);
}
Expand All @@ -208,7 +221,7 @@ contract MockClient is Ownable, ILightClient, ILightClientErrors {
* If it's not found, the function returns false.
*/
function getClientState(string calldata clientId)
external
public
view
virtual
returns (bytes memory clientStateBytes, bool)
Expand All @@ -225,7 +238,7 @@ contract MockClient is Ownable, ILightClient, ILightClientErrors {
* If it's not found, the function returns false.
*/
function getConsensusState(string calldata clientId, Height.Data calldata height)
external
public
view
virtual
returns (bytes memory consensusStateBytes, bool)
Expand Down
8 changes: 8 additions & 0 deletions contracts/core/02-client/ILightClient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ interface ILightClient {
*/
function getStatus(string calldata clientId) external view returns (ClientStatus);

/**
* @dev getLatestInfo returns the latest height, the latest timestamp, and the status of the client corresponding to `clientId`.
*/
function getLatestInfo(string calldata clientId)
external
view
returns (Height.Data memory latestHeight, uint64 latestTimestamp, ClientStatus status);

/**
* @dev verifyMembership is a generic proof verification method which verifies a proof of the existence of a value at a given CommitmentPath at the specified height.
* The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
Expand Down
11 changes: 3 additions & 8 deletions contracts/core/04-channel/IBCChannelPacketSendRecv.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,14 @@ contract IBCChannelPacketSendRecv is
{
// NOTE: We can assume here that the connection state is OPEN because the channel state is OPEN
ConnectionEnd.Data storage connection = connections[channel.connection_hops[0]];
ILightClient client = ILightClient(clientImpls[connection.client_id]);
if (address(client) == address(0)) {
revert IBCHostClientNotFound(connection.client_id);
}
if (client.getStatus(connection.client_id) != ILightClient.ClientStatus.Active) {
(Height.Data memory latestHeight, uint64 latestTimestamp, ILightClient.ClientStatus status) =
ILightClient(clientImpls[connection.client_id]).getLatestInfo(connection.client_id);
if (status != ILightClient.ClientStatus.Active) {
revert IBCClientNotActiveClient(connection.client_id);
}

Height.Data memory latestHeight = client.getLatestHeight(connection.client_id);
if (!timeoutHeight.isZero() && latestHeight.gte(timeoutHeight)) {
revert IBCChannelPastPacketTimeoutHeight(timeoutHeight, latestHeight);
}
uint64 latestTimestamp = client.getTimestampAtHeight(connection.client_id, latestHeight);
if (timeoutTimestamp != 0 && latestTimestamp >= timeoutTimestamp) {
revert IBCChannelPastPacketTimeoutTimestamp(timeoutTimestamp, latestTimestamp);
}
Expand Down
Loading
Loading