Skip to content

Commit

Permalink
Merge branch 'transfer-impl' of https://github.com/ComposableFi/emula…
Browse files Browse the repository at this point in the history
…ted-light-client into transfer-impl
  • Loading branch information
dhruvja committed Nov 20, 2023
2 parents a5ca435 + ed5a0d0 commit 038ef23
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 59 deletions.
2 changes: 1 addition & 1 deletion common/sealable-trie/src/trie/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn make_trie_impl<'a>(
want: Option<(&str, usize)>,
) -> TestTrie {
let keys = keys.into_iter();
let count = keys.size_hint().1.unwrap_or(1000).saturating_mul(4);
let count = keys.size_hint().1.unwrap_or(1000).saturating_mul(4).max(100);
let mut trie = TestTrie::new(count);
for key in keys {
set(&mut trie, key)
Expand Down
48 changes: 31 additions & 17 deletions solana/solana-ibc/programs/solana-ibc/src/execution_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use ibc::core::events::IbcEvent;
use ibc::core::ics02_client::error::ClientError;
use ibc::core::ics02_client::ClientExecutionContext;
use ibc::core::ics03_connection::connection::ConnectionEnd;
use ibc::core::ics03_connection::error::ConnectionError;
use ibc::core::ics04_channel::channel::ChannelEnd;
use ibc::core::ics04_channel::commitment::{
AcknowledgementCommitment, PacketCommitment,
Expand All @@ -25,7 +26,7 @@ use lib::hash::CryptoHash;
use crate::client_state::AnyClientState;
use crate::consensus_state::AnyConsensusState;
use crate::storage::trie_key::TrieKey;
use crate::storage::{self, IbcStorage, IbcStorageInner};
use crate::storage::{self, ids, IbcStorage, IbcStorageInner};

type Result<T = (), E = ibc::core::ContextError> = core::result::Result<T, E>;

Expand Down Expand Up @@ -146,13 +147,34 @@ impl ExecutionContext for IbcStorage<'_, '_, '_> {
path: &ConnectionPath,
connection_end: ConnectionEnd,
) -> Result {
use core::cmp::Ordering;

msg!("store_connection({}, {:?})", path, connection_end);
self.borrow_mut().store_serialised_proof(
|private| &mut private.connections,
path.0.to_string(),
&TrieKey::from(path),
&connection_end,
)
let connection = ids::ConnectionIdx::try_from(&path.0)?;
let serialised = storage::Serialised::new(&connection_end)?;
let hash = serialised.digest();

let mut store = self.borrow_mut();

let connections = &mut store.private.connections;
let index = usize::from(connection);
match index.cmp(&connections.len()) {
Ordering::Less => connections[index] = serialised,
Ordering::Equal => connections.push(serialised),
Ordering::Greater => {
return Err(ConnectionError::ConnectionNotFound {
connection_id: path.0.clone(),
}
.into())
}
}

store
.provable
.set(&TrieKey::for_connection(connection), &hash)
.map_err(error)?;

Ok(())
}

fn store_connection_to_client(
Expand All @@ -161,21 +183,13 @@ impl ExecutionContext for IbcStorage<'_, '_, '_> {
conn_id: ConnectionId,
) -> Result {
msg!("store_connection_to_client({}, {:?})", path, conn_id);
let conn_id = ids::ConnectionIdx::try_from(&conn_id)?;
self.borrow_mut().private.client_mut(&path.0, false)?.connection_id =
Some(conn_id);
Ok(())
}

fn increase_connection_counter(&mut self) -> Result {
let mut store = self.borrow_mut();
store.private.connection_counter =
store.private.connection_counter.checked_add(1).unwrap();
msg!(
"connection_counter has increased to: {}",
store.private.connection_counter
);
Ok(())
}
fn increase_connection_counter(&mut self) -> Result { Ok(()) }

fn store_packet_commitment(
&mut self,
Expand Down
18 changes: 9 additions & 9 deletions solana/solana-ibc/programs/solana-ibc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,15 +203,15 @@ pub struct Chain<'info> {
sender: Signer<'info>,

/// The guest blockchain data.
#[account(init_if_needed, payer = sender, seeds = [CHAIN_SEED], bump, space = 10000)]
#[account(init_if_needed, payer = sender, seeds = [CHAIN_SEED], bump, space = 10240)]
chain: Account<'info, chain::ChainData>,

/// The account holding the trie which corresponds to guest blockchain’s
/// state root.
///
/// CHECK: Account’s owner is checked by [`storage::get_provable_from`]
/// function.
#[account(init_if_needed, payer = sender, seeds = [TRIE_SEED], bump, space = 10000)]
#[account(init_if_needed, payer = sender, seeds = [TRIE_SEED], bump, space = 10240)]
trie: UncheckedAccount<'info>,

system_program: Program<'info, System>,
Expand All @@ -223,15 +223,15 @@ pub struct ChainWithVerifier<'info> {
sender: Signer<'info>,

/// The guest blockchain data.
#[account(init_if_needed, payer = sender, seeds = [CHAIN_SEED], bump, space = 10000)]
#[account(init_if_needed, payer = sender, seeds = [CHAIN_SEED], bump, space = 10240)]
chain: Account<'info, chain::ChainData>,

/// The account holding the trie which corresponds to guest blockchain’s
/// state root.
///
/// CHECK: Account’s owner is checked by [`storage::get_provable_from`]
/// function.
#[account(init_if_needed, payer = sender, seeds = [TRIE_SEED], bump, space = 10000)]
#[account(init_if_needed, payer = sender, seeds = [TRIE_SEED], bump, space = 10240)]
trie: UncheckedAccount<'info>,

#[account(address = solana_program::sysvar::instructions::ID)]
Expand All @@ -247,22 +247,22 @@ pub struct Deliver<'info> {
sender: Signer<'info>,

/// The account holding private IBC storage.
#[account(init_if_needed, payer = sender, seeds = [SOLANA_IBC_STORAGE_SEED], bump, space = 10000)]
#[account(init_if_needed, payer = sender, seeds = [SOLANA_IBC_STORAGE_SEED], bump, space = 10240)]
storage: Account<'info, storage::PrivateStorage>,

/// The account holding provable IBC storage, i.e. the trie.
///
/// CHECK: Account’s owner is checked by [`storage::get_provable_from`]
/// function.
#[account(init_if_needed, payer = sender, seeds = [TRIE_SEED], bump, space = 10000)]
#[account(init_if_needed, payer = sender, seeds = [TRIE_SEED], bump, space = 10240)]
trie: UncheckedAccount<'info>,

/// The account holding packets.
#[account(init_if_needed, payer = sender, seeds = [PACKET_SEED], bump, space = 1000)]
#[account(init_if_needed, payer = sender, seeds = [PACKET_SEED], bump, space = 10240)]
packets: Account<'info, storage::IbcPackets>,

// /// The guest blockchain data.
#[account(init_if_needed, payer = sender, seeds = [CHAIN_SEED], bump, space = 10000)]
/// The guest blockchain data.
#[account(init_if_needed, payer = sender, seeds = [CHAIN_SEED], bump, space = 10240)]
chain: Box<Account<'info, chain::ChainData>>,
system_program: Program<'info, System>,
}
Expand Down
20 changes: 13 additions & 7 deletions solana/solana-ibc/programs/solana-ibc/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::consensus_state::AnyConsensusState;
mod ibc {
pub use ibc::core::ics02_client::error::ClientError;
pub use ibc::core::ics03_connection::connection::ConnectionEnd;
pub use ibc::core::ics03_connection::error::ConnectionError;
pub use ibc::core::ics04_channel::channel::ChannelEnd;
pub use ibc::core::ics04_channel::msgs::PacketMsg;
pub use ibc::core::ics04_channel::packet::Sequence;
Expand All @@ -25,7 +26,6 @@ pub(crate) mod ids;
pub(crate) mod trie_key;

pub(crate) type SolanaTimestamp = u64;
pub(crate) type InnerConnectionId = String;
pub(crate) type InnerPortId = String;
pub(crate) type InnerChannelId = String;

Expand Down Expand Up @@ -86,7 +86,7 @@ impl SequenceTriple {
#[derive(Clone, Debug, borsh::BorshSerialize, borsh::BorshDeserialize)]
pub(crate) struct ClientStore {
pub client_id: ibc::ClientId,
pub connection_id: Option<ibc::ConnectionId>,
pub connection_id: Option<ids::ConnectionIdx>,

pub client_state: Serialised<AnyClientState>,
pub consensus_states: BTreeMap<ibc::Height, Serialised<AnyConsensusState>>,
Expand Down Expand Up @@ -141,14 +141,20 @@ pub struct IbcPackets(pub Vec<ibc::PacketMsg>);

#[account]
#[derive(Debug)]
/// All the structs from IBC are stored as String since they dont implement
/// AnchorSerialize and AnchorDeserialize
/// The private IBC storage, i.e. data which doesn’t require proofs.
pub(crate) struct PrivateStorage {
/// Per-client information.
///
/// Entry at index `N` corresponds to the client with IBC identifier
/// `client-<N>`.
clients: Vec<ClientStore>,

pub connection_counter: u64,
pub connections:
BTreeMap<InnerConnectionId, Serialised<ibc::ConnectionEnd>>,
/// Information about the counterparty on given connection.
///
/// Entry at index `N` corresponds to the connection with IBC identifier
/// `connection-<N>`.
pub connections: Vec<Serialised<ibc::ConnectionEnd>>,

pub channel_ends:
BTreeMap<(InnerPortId, InnerChannelId), Serialised<ibc::ChannelEnd>>,
pub channel_counter: u64,
Expand Down
81 changes: 75 additions & 6 deletions solana/solana-ibc/programs/solana-ibc/src/storage/ids.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/// Prefix of IBC connection ids.
///
/// Note: We’re not using ConnectionId::prefix() because it returns the prefix
/// without trailing `-` which we want included to simplify stripping of the
/// prefix.
pub(super) const CONNECTION_ID_PREFIX: &str = "connection-";
use anchor_lang::prelude::borsh;

use super::ibc;

type Result<T, E = ibc::ClientError> = core::result::Result<T, E>;


/// Prefix of IBC channel ids.
///
Expand All @@ -12,6 +12,7 @@ pub(super) const CONNECTION_ID_PREFIX: &str = "connection-";
/// prefix.
pub(super) const CHANNEL_ID_PREFIX: &str = "channel-";


/// An index used as unique identifier for a client.
///
/// IBC client id uses `<client-type>-<counter>` format. This index is
Expand Down Expand Up @@ -51,3 +52,71 @@ impl PartialEq<usize> for ClientIdx {
u32::try_from(*rhs).ok().filter(|rhs| self.0 == *rhs).is_some()
}
}


/// An internal connection identifier.
///
/// The identifier is build from IBC identifiers which are of the form
/// `connection-<number>`. Rather than treating the identifier as a string,
/// we’re parsing the number out and keep only that.
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
borsh::BorshSerialize,
borsh::BorshDeserialize,
derive_more::From,
derive_more::Into,
)]
pub struct ConnectionIdx(u32);

impl ConnectionIdx {
/// Prefix of IBC connection ids.
///
/// Note: We’re not using ConnectionId::prefix() because it returns the
/// prefix without trailing `-` which we want included to simplify stripping
/// of the prefix.
const IBC_PREFIX: &'static str = "connection-";
}

impl From<ConnectionIdx> for usize {
#[inline]
fn from(index: ConnectionIdx) -> usize { index.0 as usize }
}

impl TryFrom<ibc::ConnectionId> for ConnectionIdx {
type Error = ibc::ConnectionError;

fn try_from(id: ibc::ConnectionId) -> Result<Self, Self::Error> {
match parse_sans_prefix(Self::IBC_PREFIX, id.as_str()) {
Some(num) => Ok(Self(num)),
None => Err(ibc::ConnectionError::ConnectionNotFound {
connection_id: id,
}),
}
}
}

impl TryFrom<&ibc::ConnectionId> for ConnectionIdx {
type Error = ibc::ConnectionError;

fn try_from(id: &ibc::ConnectionId) -> Result<Self, Self::Error> {
match parse_sans_prefix(Self::IBC_PREFIX, id.as_str()) {
Some(num) => Ok(Self(num)),
None => Err(ibc::ConnectionError::ConnectionNotFound {
connection_id: id.clone(),
}),
}
}
}


/// Strips `prefix` from `data` and parses it to get `u32`. Panics if data
/// doesn’t start with the prefix or parsing fails.
fn parse_sans_prefix(prefix: &'static str, data: &str) -> Option<u32> {
data.strip_prefix(prefix)
.and_then(|index| index.parse().ok())
.filter(|index| usize::try_from(*index).is_ok())
}
33 changes: 18 additions & 15 deletions solana/solana-ibc/programs/solana-ibc/src/storage/trie_key.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use ibc::core::ics04_channel::packet::Sequence;
use ibc::core::ics24_host::identifier::{ChannelId, PortId};
use ibc::core::ics24_host::path::{
AckPath, ChannelEndPath, CommitmentPath, ConnectionPath, ReceiptPath,
SeqAckPath, SeqRecvPath, SeqSendPath,
AckPath, ChannelEndPath, CommitmentPath, ReceiptPath, SeqAckPath,
SeqRecvPath, SeqSendPath,
};

use crate::storage::ids::{ClientIdx, CHANNEL_ID_PREFIX, CONNECTION_ID_PREFIX};
use crate::storage::ids;

/// A key used for indexing entries in the provable storage.
///
Expand Down Expand Up @@ -60,16 +60,24 @@ macro_rules! new_key_impl {
impl TrieKey {
/// Constructs a new key for a client state path for client with given
/// counter.
pub fn for_client_state(client: ClientIdx) -> Self {
pub fn for_client_state(client: ids::ClientIdx) -> Self {
new_key_impl!(Tag::ClientState, client)
}

/// Constructs a new key for a consensus state path for client with given
/// counter and specified height.
pub fn for_consensus_state(client: ClientIdx, height: ibc::Height) -> Self {
pub fn for_consensus_state(
client: ids::ClientIdx,
height: ibc::Height,
) -> Self {
new_key_impl!(Tag::ConsensusState, client, height)
}

/// Constructs a new key for a connection end path.
pub fn for_connection(connection: ids::ConnectionIdx) -> Self {
new_key_impl!(Tag::Connection, connection)
}

/// Constructs a new key for a `(port_id, channel_id)` path.
///
/// Panics if `channel_id` is invalid.
Expand Down Expand Up @@ -99,12 +107,6 @@ impl core::ops::Deref for TrieKey {
fn deref(&self) -> &[u8] { self.0.as_slice() }
}

impl From<&ConnectionPath> for TrieKey {
fn from(path: &ConnectionPath) -> Self {
new_key_impl!(Tag::Connection, path.0)
}
}

impl From<&ChannelEndPath> for TrieKey {
fn from(path: &ChannelEndPath) -> Self {
Self::from_channel_path(Tag::ChannelEnd, &path.0, &path.1)
Expand Down Expand Up @@ -197,17 +199,17 @@ trait AsComponent {
fn append_into(&self, dest: &mut Vec<u8>);
}

impl AsComponent for ClientIdx {
impl AsComponent for ids::ClientIdx {
fn key_len(&self) -> usize { 0_u32.key_len() }
fn append_into(&self, dest: &mut Vec<u8>) {
u32::from(*self).append_into(dest)
}
}

impl AsComponent for ibc::core::ics24_host::identifier::ConnectionId {
impl AsComponent for ids::ConnectionIdx {
fn key_len(&self) -> usize { 0_u32.key_len() }
fn append_into(&self, dest: &mut Vec<u8>) {
parse_sans_prefix(CONNECTION_ID_PREFIX, self.as_str()).append_into(dest)
u32::from(*self).append_into(dest)
}
}

Expand All @@ -223,7 +225,8 @@ impl AsComponent for ibc::core::ics24_host::identifier::PortId {
impl AsComponent for ibc::core::ics24_host::identifier::ChannelId {
fn key_len(&self) -> usize { 0_u32.key_len() }
fn append_into(&self, dest: &mut Vec<u8>) {
parse_sans_prefix(CHANNEL_ID_PREFIX, self.as_str()).append_into(dest)
parse_sans_prefix(ids::CHANNEL_ID_PREFIX, self.as_str())
.append_into(dest)
}
}

Expand Down
Loading

0 comments on commit 038ef23

Please sign in to comment.