Skip to content

Commit

Permalink
solana-ibc: add guest client and consensus states (#390)
Browse files Browse the repository at this point in the history
Adding guest client and consensus states so that the solana-ibc on the
rollup can store them. The guest client and consensus state was previous
removed since we used to store the wasm wrapped guest states. It was
removed here
#255 and now
its added again.
  • Loading branch information
dhruvja authored Oct 15, 2024
1 parent ca9dadb commit 13be90d
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 43 deletions.
66 changes: 46 additions & 20 deletions solana/solana-ibc/programs/solana-ibc/src/client_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub enum AnyClientState {
Tendermint(ibc::tm::ClientState),
Wasm(ibc::wasm::ClientState),
Rollup(cf_solana::ClientState),
Guest(cf_guest::ClientState<sigverify::ed25519::PubKey>),
#[cfg(any(test, feature = "mocks"))]
Mock(ibc::mock::MockClientState),
}
Expand All @@ -28,6 +29,7 @@ enum AnyClientStateTag {
Tendermint = 0,
Wasm = 1,
Rollup = 2,
Guest = 3,
#[cfg(any(test, feature = "mocks"))]
Mock = 255,
}
Expand All @@ -40,6 +42,7 @@ impl AnyClientStateTag {
AnyClientState::TENDERMINT_TYPE => Some(Self::Tendermint),
AnyClientState::WASM_TYPE => Some(Self::Wasm),
AnyClientState::ROLLUP_TYPE => Some(Self::Rollup),
AnyClientState::GUEST_TYPE => Some(Self::Guest),
#[cfg(any(test, feature = "mocks"))]
AnyClientState::MOCK_TYPE => Some(Self::Mock),
_ => None,
Expand All @@ -56,6 +59,8 @@ impl AnyClientState {
/// Protobuf type URL for Rollup client state used in Any message.
const ROLLUP_TYPE: &'static str =
cf_solana::proto::ClientState::IBC_TYPE_URL;
/// Protobuf type URL for Guest client state used in Any message.
const GUEST_TYPE: &'static str = cf_guest::proto::ClientState::IBC_TYPE_URL;
#[cfg(any(test, feature = "mocks"))]
/// Protobuf type URL for Mock client state used in Any message.
const MOCK_TYPE: &'static str = ibc::mock::MOCK_CLIENT_STATE_TYPE_URL;
Expand Down Expand Up @@ -89,6 +94,11 @@ impl AnyClientState {
Self::ROLLUP_TYPE,
Protobuf::<cf_solana::proto::ClientState>::encode_vec(state),
),
Self::Guest(state) => (
AnyClientStateTag::Guest,
Self::GUEST_TYPE,
Protobuf::<cf_guest::proto::ClientState>::encode_vec(state),
),
#[cfg(any(test, feature = "mocks"))]
Self::Mock(state) => (
AnyClientStateTag::Mock,
Expand Down Expand Up @@ -119,6 +129,11 @@ impl AnyClientState {
.map_err(|err| err.to_string())
.map(Self::Rollup)
}
AnyClientStateTag::Guest => {
Protobuf::<cf_guest::proto::ClientState>::decode_vec(&value)
.map_err(|err| err.to_string())
.map(Self::Guest)
}
#[cfg(any(test, feature = "mocks"))]
AnyClientStateTag::Mock => {
Protobuf::<ibc::mock::ClientStatePB>::decode_vec(&value)
Expand All @@ -135,21 +150,6 @@ impl From<ibc::tm::types::ClientState> for AnyClientState {
}
}

impl<PK: guestchain::PubKey> From<cf_guest::ClientState<PK>>
for AnyClientState
{
fn from(state: cf_guest::ClientState<PK>) -> Self {
Self::from(ibc::wasm::ClientState {
data: prost::Message::encode_to_vec(&cf_guest::proto::Any::from(
&state,
)),
checksum: Default::default(),
latest_height: ibc::Height::new(1, u64::from(state.latest_height))
.unwrap(),
})
}
}

impl From<AnyClientState> for ibc::Any {
fn from(value: AnyClientState) -> Self {
let (_, type_url, value) = value.into_any();
Expand Down Expand Up @@ -231,11 +231,30 @@ impl ibc::tm::CommonContext for IbcStorage<'_, '_> {
impl cf_guest::CommonContext<sigverify::ed25519::PubKey>
for IbcStorage<'_, '_>
{
type ConversionError = cf_guest::DecodeError;
type ConversionError = &'static str;
type AnyClientState = AnyClientState;
type AnyConsensusState = AnyConsensusState;

fn host_metadata(&self) -> Result<(ibc::Timestamp, ibc::Height)> {
#[cfg(feature = "witness")]
{
let clock =
anchor_lang::solana_program::sysvar::clock::Clock::get()
.map_err(|e| ibc::ClientError::ClientSpecific {
description: e.to_string(),
})?;

let slot = clock.slot;
let timestamp_sec = clock.unix_timestamp as u64;

let timestamp =
ibc::Timestamp::from_nanoseconds(timestamp_sec * 10u64.pow(9))
.map_err(|e| ibc::ClientError::ClientSpecific {
description: e.to_string(),
})?;
let height = ibc::Height::new(1, slot)?;
return Ok((timestamp, height));
}
let timestamp = self.borrow().chain.head()?.timestamp_ns.get();
let timestamp =
ibc::Timestamp::from_nanoseconds(timestamp).map_err(|err| {
Expand Down Expand Up @@ -331,11 +350,18 @@ impl cf_guest::CommonContext<sigverify::ed25519::PubKey>
impl guestchain::Verifier<sigverify::ed25519::PubKey> for IbcStorage<'_, '_> {
fn verify(
&self,
_message: &[u8],
_pubkey: &sigverify::ed25519::PubKey,
_signature: &sigverify::ed25519::Signature,
message: &[u8],
pubkey: &sigverify::ed25519::PubKey,
signature: &sigverify::ed25519::Signature,
) -> bool {
unimplemented!()
let pubkey = pubkey.as_ref();
let sig = signature.as_ref();
if let Some(verifier) = crate::global().verifier() {
if verifier.verify(message, pubkey, sig).unwrap_or(false) {
return true;
}
}
false
}
}

Expand Down
12 changes: 12 additions & 0 deletions solana/solana-ibc/programs/solana-ibc/src/client_state/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ macro_rules! delegate {
AnyClientState::Tendermint(cs) => cs.$name($($arg),*),
AnyClientState::Wasm(_) => unimplemented!(),
AnyClientState::Rollup(cs) => cs.$name($($arg),*),
AnyClientState::Guest(cs) => cs.$name($($arg),*),
#[cfg(any(test, feature = "mocks"))]
AnyClientState::Mock(cs) => cs.$name($($arg),*),
}
Expand Down Expand Up @@ -55,6 +56,7 @@ impl ibc::ClientStateCommon for AnyClientState {
}
AnyClientState::Wasm(_) => unimplemented!(),
AnyClientState::Rollup(_) => unimplemented!(),
AnyClientState::Guest(_) => unimplemented!(),
#[cfg(any(test, feature = "mocks"))]
AnyClientState::Mock(cs) => cs.verify_upgrade_client(
upgraded_client_state,
Expand Down Expand Up @@ -89,6 +91,9 @@ impl ibc::ClientStateCommon for AnyClientState {
AnyClientState::Rollup(cs) => {
cs.verify_membership(prefix, proof, root, path, value)
}
AnyClientState::Guest(cs) => {
cs.verify_membership(prefix, proof, root, path, value)
}
#[cfg(any(test, feature = "mocks"))]
AnyClientState::Mock(cs) => {
cs.verify_membership(prefix, proof, root, path, value)
Expand All @@ -115,6 +120,9 @@ impl ibc::ClientStateCommon for AnyClientState {
AnyClientState::Rollup(cs) => {
cs.verify_non_membership(prefix, proof, root, path)
}
AnyClientState::Guest(cs) => {
cs.verify_non_membership(prefix, proof, root, path)
}
#[cfg(any(test, feature = "mocks"))]
AnyClientState::Mock(cs) => {
cs.verify_non_membership(prefix, proof, root, path)
Expand Down Expand Up @@ -143,6 +151,9 @@ impl<'a, 'b> ibc::ClientStateValidation<IbcStorage<'a, 'b>> for AnyClientState {
AnyClientState::Rollup(cs) => {
cs.verify_client_message(ctx, client_id, client_message)
}
AnyClientState::Guest(cs) => {
cs.verify_client_message(ctx, client_id, client_message)
}
#[cfg(any(test, feature = "mocks"))]
AnyClientState::Mock(cs) => {
cs.verify_client_message(ctx, client_id, client_message)
Expand All @@ -167,6 +178,7 @@ impl<'a, 'b> ibc::ClientStateValidation<IbcStorage<'a, 'b>> for AnyClientState {
}
AnyClientState::Wasm(_) => unimplemented!(),
AnyClientState::Rollup(_) => unimplemented!(),
AnyClientState::Guest(_) => unimplemented!(),
#[cfg(any(test, feature = "mocks"))]
AnyClientState::Mock(_) => unimplemented!(),
}
Expand Down
39 changes: 16 additions & 23 deletions solana/solana-ibc/programs/solana-ibc/src/consensus_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub enum AnyConsensusState {
Tendermint(ibc::tm::ConsensusState),
Wasm(ibc::wasm::ConsensusState),
Rollup(cf_solana::ConsensusState),
Guest(cf_guest::ConsensusState),
#[cfg(any(test, feature = "mocks"))]
Mock(ibc::mock::MockConsensusState),
}
Expand All @@ -27,6 +28,7 @@ enum AnyConsensusStateTag {
Tendermint = 0,
Wasm = 1,
Rollup = 2,
Guest = 3,
#[cfg(any(test, feature = "mocks"))]
Mock = 255,
}
Expand All @@ -39,6 +41,7 @@ impl AnyConsensusStateTag {
AnyConsensusState::TENDERMINT_TYPE => Some(Self::Tendermint),
AnyConsensusState::WASM_TYPE => Some(Self::Wasm),
AnyConsensusState::ROLLUP_TYPE => Some(Self::Rollup),
AnyConsensusState::GUEST_TYPE => Some(Self::Guest),
#[cfg(any(test, feature = "mocks"))]
AnyConsensusState::MOCK_TYPE => Some(Self::Mock),
_ => None,
Expand All @@ -55,6 +58,9 @@ impl AnyConsensusState {
/// Protobuf type URL for Rollup consensus state used in Any message.
const ROLLUP_TYPE: &'static str =
cf_solana::proto::ConsensusState::IBC_TYPE_URL;
/// Protobuf type URL for Guest consensus state used in Any message.
const GUEST_TYPE: &'static str =
cf_guest::proto::ConsensusState::IBC_TYPE_URL;
#[cfg(any(test, feature = "mocks"))]
/// Protobuf type URL for Mock consensus state used in Any message.
const MOCK_TYPE: &'static str = ibc::mock::MOCK_CONSENSUS_STATE_TYPE_URL;
Expand Down Expand Up @@ -88,6 +94,11 @@ impl AnyConsensusState {
Self::ROLLUP_TYPE,
Protobuf::<cf_solana::proto::ConsensusState>::encode_vec(state),
),
AnyConsensusState::Guest(state) => (
AnyConsensusStateTag::Guest,
Self::GUEST_TYPE,
Protobuf::<cf_guest::proto::ConsensusState>::encode_vec(state),
),
#[cfg(any(test, feature = "mocks"))]
AnyConsensusState::Mock(state) => (
AnyConsensusStateTag::Mock,
Expand Down Expand Up @@ -118,6 +129,11 @@ impl AnyConsensusState {
.map_err(|err| err.to_string())
.map(Self::Rollup)
}
AnyConsensusStateTag::Guest => {
Protobuf::<cf_guest::proto::ConsensusState>::decode_vec(&value)
.map_err(|err| err.to_string())
.map(Self::Guest)
}
#[cfg(any(test, feature = "mocks"))]
AnyConsensusStateTag::Mock => {
Protobuf::<ibc::mock::ConsensusStatePB>::decode_vec(&value)
Expand All @@ -128,35 +144,12 @@ impl AnyConsensusState {
}
}


impl From<ibc::tm::types::ConsensusState> for AnyConsensusState {
fn from(state: ibc::tm::types::ConsensusState) -> Self {
Self::Tendermint(state.into())
}
}

impl From<cf_guest::ConsensusState> for AnyConsensusState {
fn from(state: cf_guest::ConsensusState) -> Self {
Self::from(ibc::wasm::ConsensusState {
data: prost::Message::encode_to_vec(&cf_guest::proto::Any::from(
&state,
)),
timestamp_ns: state.timestamp_ns.get(),
})
}
}

impl TryFrom<AnyConsensusState> for cf_guest::ConsensusState {
type Error = cf_guest::DecodeError;
fn try_from(state: AnyConsensusState) -> Result<Self, Self::Error> {
use prost::Message;
let state = ibc::wasm::ConsensusState::try_from(state)
.map_err(|_| cf_guest::DecodeError::BadMessage)?;
let any = cf_guest::proto::Any::decode(state.data.as_slice())?;
cf_guest::ConsensusState::try_from(any)
}
}

impl Protobuf<ibc::Any> for AnyConsensusState {}

impl TryFrom<ibc::Any> for AnyConsensusState {
Expand Down

0 comments on commit 13be90d

Please sign in to comment.