Skip to content

Commit

Permalink
Fix CkbClient
Browse files Browse the repository at this point in the history
* Return same client state as MockClient

* Comment out verifyClientState for now
  • Loading branch information
blckngm committed Dec 21, 2023
1 parent 3ae160a commit c43a5ad
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 59 deletions.
166 changes: 136 additions & 30 deletions contracts/clients/CkbClient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,58 @@ pragma solidity ^0.8.9;
import "../core/02-client/ILightClient.sol";
import "../core/02-client/IBCHeight.sol";
import "../proto/Client.sol";
import {IbcLightclientsMockV1ClientState as ClientState, IbcLightclientsMockV1ConsensusState as ConsensusState, IbcLightclientsMockV1Header as Header} from "../proto/MockClient.sol";
import {GoogleProtobufAny as Any} from "../proto/GoogleProtobufAny.sol";
import "solidity-bytes-utils/contracts/BytesLib.sol";
import "./CkbProof.sol";

// MokkClient implements https://github.com/datachainlab/ibc-mock-client
// WARNING: This client is intended to be used for testing purpose. Therefore, it is not generally available in a production, except in a fully trusted environment.
contract CkbClient is ILightClient {
using CkbProof for *;
uint64 private constant MAX_UINT64 = 18446744073709551615;
constructor() {}
using BytesLib for bytes;
using IBCHeight for Height.Data;

string private constant HEADER_TYPE_URL =
"/ibc.lightclients.mock.v1.Header";
string private constant CLIENT_STATE_TYPE_URL =
"/ibc.lightclients.mock.v1.ClientState";
string private constant CONSENSUS_STATE_TYPE_URL =
"/ibc.lightclients.mock.v1.ConsensusState";

bytes32 private constant HEADER_TYPE_URL_HASH =
keccak256(abi.encodePacked(HEADER_TYPE_URL));
bytes32 private constant CLIENT_STATE_TYPE_URL_HASH =
keccak256(abi.encodePacked(CLIENT_STATE_TYPE_URL));
bytes32 private constant CONSENSUS_STATE_TYPE_URL_HASH =
keccak256(abi.encodePacked(CONSENSUS_STATE_TYPE_URL));

// mapping(string => ClientState.Data) internal clientStates;
mapping(string => bytes) internal clientStates;
// mapping(string => mapping(uint128 => ConsensusState.Data))
// internal consensusStates;
mapping(string => bytes) internal consensusStates;

/**
* @dev createClient creates a new client with the given state
*/
function createClient(string calldata, bytes calldata, bytes calldata)
external pure override returns (bytes32 clientStateCommitment, ConsensusStateUpdate memory update, bool ok)
function createClient(
string calldata clientId,
bytes calldata clientStateBytes,
bytes calldata consensusStateBytes
)
external
override
returns (
bytes32 clientStateCommitment,
ConsensusStateUpdate memory update,
bool ok
)
{
clientStates[clientId] = clientStateBytes;
consensusStates[clientId] = consensusStateBytes;
return (
bytes32(""),
keccak256(clientStateBytes),
ConsensusStateUpdate({
consensusStateCommitment: bytes32(""),
height: Height.Data({revisionNumber: 0, revisionHeight: MAX_UINT64})
consensusStateCommitment: bytes32(0),
height: Height.Data({revisionNumber: 0, revisionHeight: 9999})
}),
true
);
Expand All @@ -32,17 +64,20 @@ contract CkbClient is ILightClient {
/**
* @dev getTimestampAtHeight returns the timestamp of the consensus state at the given height.
*/
function getTimestampAtHeight(string calldata, Height.Data calldata)
external pure override returns (uint64, bool)
{
return (MAX_UINT64, true);
function getTimestampAtHeight(
string calldata clientId,
Height.Data calldata height
) external view override returns (uint64, bool) {
return (9223372036854775807, true);
}

/**
* @dev getLatestHeight returns the latest height of the client state corresponding to `clientId`.
*/
function getLatestHeight(string calldata) external pure override returns (Height.Data memory, bool) {
return (Height.Data({revisionNumber: 0, revisionHeight: MAX_UINT64}), true);
function getLatestHeight(
string calldata clientId
) external pure override returns (Height.Data memory, bool) {
return (Height.Data({revisionNumber: 0, revisionHeight: 9999}), true);
}

/**
Expand All @@ -53,8 +88,17 @@ contract CkbClient is ILightClient {
* 4. update state(s) with the client message
* 5. persist the state(s) on the host
*/
function updateClient(string calldata, bytes calldata)
external pure override returns (bytes32 clientStateCommitment, ConsensusStateUpdate[] memory updates, bool ok)
function updateClient(
string calldata clientId,
bytes calldata clientMessageBytes
)
external
override
returns (
bytes32 clientStateCommitment,
ConsensusStateUpdate[] memory updates,
bool ok
)
{
return (bytes32(0), new ConsensusStateUpdate[](0), true);
}
Expand All @@ -64,8 +108,8 @@ contract CkbClient is ILightClient {
* The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
*/
function verifyMembership(
string calldata,
Height.Data calldata,
string calldata clientId,
Height.Data calldata height,
uint64,
uint64,
bytes calldata proof,
Expand All @@ -81,14 +125,14 @@ contract CkbClient is ILightClient {
* The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
*/
function verifyNonMembership(
string calldata,
Height.Data calldata,
string calldata clientId,
Height.Data calldata height,
uint64,
uint64,
bytes calldata,
bytes calldata proof,
bytes memory,
bytes memory
) external pure override returns (bool) {
) external view override returns (bool) {
return true;
}

Expand All @@ -98,18 +142,80 @@ contract CkbClient is ILightClient {
* @dev getClientState returns the clientState corresponding to `clientId`.
* If it's not found, the function returns false.
*/
function getClientState(string calldata) external pure returns (bytes memory clientStateBytes, bool) {
return (bytes(""), true);
function getClientState(
string calldata clientId
) external view returns (bytes memory clientStateBytes, bool) {
string memory result = string.concat(
clientId,
"|",
string(clientStates[clientId])
);
return (bytes(result), true);
}

/**
* @dev getConsensusState returns the consensusState corresponding to `clientId` and `height`.
* If it's not found, the function returns false.
*/
function getConsensusState(string calldata, Height.Data calldata)
external pure returns (bytes memory consensusStateBytes, bool)
{
return (bytes(""), true);
function getConsensusState(
string calldata clientId,
Height.Data calldata height
) external view returns (bytes memory consensusStateBytes, bool) {
string memory result = string.concat(
clientId,
"|",
string(consensusStates[clientId])
);
return (bytes(result), true);
}

/* Internal functions */

function parseHeader(
bytes memory bz
) internal pure returns (Height.Data memory, uint64) {
Any.Data memory any = Any.decode(bz);
require(
keccak256(abi.encodePacked(any.typeUrl)) == HEADER_TYPE_URL_HASH,
"invalid header type"
);
Header.Data memory header = Header.decode(any.value);
require(
header.height.revisionNumber == 0 &&
header.height.revisionHeight != 0 &&
header.timestamp != 0,
"invalid header"
);
return (header.height, header.timestamp);
}

function unmarshalClientState(
bytes calldata bz
) internal pure returns (ClientState.Data memory clientState, bool ok) {
Any.Data memory anyClientState = Any.decode(bz);
if (
keccak256(abi.encodePacked(anyClientState.typeUrl)) !=
CLIENT_STATE_TYPE_URL_HASH
) {
return (clientState, false);
}
return (ClientState.decode(anyClientState.value), true);
}

function unmarshalConsensusState(
bytes calldata bz
)
internal
pure
returns (ConsensusState.Data memory consensusState, bool ok)
{
Any.Data memory anyConsensusState = Any.decode(bz);
if (
keccak256(abi.encodePacked(anyConsensusState.typeUrl)) !=
CONSENSUS_STATE_TYPE_URL_HASH
) {
return (consensusState, false);
}
return (ConsensusState.decode(anyConsensusState.value), true);
}
}
42 changes: 22 additions & 20 deletions contracts/core/03-connection/IBCConnection.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,17 @@ contract IBCConnection is IBCStore, IIBCConnectionHandshake {
),
"failed to verify connection state"
);
require(
verifyClientState(
connection,
msg_.proofHeight,
IBCCommitment.clientStatePath(connection.counterparty.clientId),
msg_.proofClient,
msg_.clientState
),
"failed to verify clientState"
);
// TODO: verify client state.
// require(
// verifyClientState(
// connection,
// msg_.proofHeight,
// IBCCommitment.clientStatePath(connection.counterparty.clientId),
// msg_.proofClient,
// msg_.clientState
// ),
// "failed to verify clientState"
// );
// TODO we should also verify a consensus state

updateConnectionCommitment(connectionId);
Expand Down Expand Up @@ -145,16 +146,17 @@ contract IBCConnection is IBCStore, IIBCConnectionHandshake {
),
"failed to verify connection state"
);
require(
verifyClientState(
connection,
msg_.proofHeight,
IBCCommitment.clientStatePath(connection.counterparty.clientId),
msg_.proofClient,
msg_.clientState
),
"failed to verify clientState"
);
// TODO: verify client state.
// require(
// verifyClientState(
// connection,
// msg_.proofHeight,
// IBCCommitment.clientStatePath(connection.counterparty.clientId),
// msg_.proofClient,
// msg_.clientState
// ),
// "failed to verify clientState"
// );
// TODO we should also verify a consensus state

connection.state = ConnectionEnd.State.Open;
Expand Down
18 changes: 9 additions & 9 deletions migrations/1_deploy_contracts.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,11 @@ module.exports = async function (deployer, network) {
await deployer.deploy(MockClient);
await deployer.deploy(MockModule);

const molecule = await Molecule.new();
const ckbLightClient = await CkbLightClient.new();
CkbProof.link(molecule);
CkbProof.link(ckbLightClient);
const ckbProof = await CkbProof.new();
CkbClient.link(ckbProof);
await deployer.deploy(CkbClient);

const ibcClient = await IBCClient.deployed();
const ibcPacket = await IBCPacket.deployed();
const ibcConnection = await IBCConnection.deployed();
const ibcChannel = await IBCChannel.deployed();
const mockClient = await MockClient.deployed();
const ckbClient = await CkbClient.deployed();

// 2. deploy IBCMockHandler
let IBCHandler = undefined;
Expand All @@ -55,6 +46,15 @@ module.exports = async function (deployer, network) {
);
ibcHandler = await IBCHandler.deployed();

const molecule = await Molecule.new();
const ckbLightClient = await CkbLightClient.new();
CkbProof.link(molecule);
CkbProof.link(ckbLightClient);
const ckbProof = await CkbProof.new();
CkbClient.link(ckbProof);
await deployer.deploy(CkbClient);
const ckbClient = await CkbClient.deployed();

// 3. register Client
const axonClientType = "07-axon";
await ibcHandler.registerClient(axonClientType, mockClient.address);
Expand Down

0 comments on commit c43a5ad

Please sign in to comment.