Skip to content

Commit

Permalink
solana-ibc: serialise ConnectionEnd and ChannelEnd w/ borsh i/o serde
Browse files Browse the repository at this point in the history
Issue: #46
  • Loading branch information
mina86 committed Nov 2, 2023
1 parent 42b01ca commit d7f0e5e
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 96 deletions.
103 changes: 50 additions & 53 deletions solana/solana-ibc/programs/solana-ibc/src/execution_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,13 @@ impl ClientExecutionContext for IbcStorage<'_, '_> {
client_state: Self::AnyClientState,
) -> Result {
msg!("store_client_state({path}, {client_state:?})");
let key = path.0.to_string();
let serialized = borsh::to_vec(&client_state).map_err(|err| {
ClientError::Other { description: err.to_string() }
})?;
let hash = lib::hash::CryptoHash::digest(&serialized);
msg!("This is serialized client state {hash}");

let mut store = self.borrow_mut();
store.provable.set(&TrieKey::from(&path), &hash).unwrap();
let serialized = store_serialised_proof(
&mut store.provable,
&TrieKey::from(&path),
&client_state,
)?;
let key = path.0.to_string();
store.private.clients.insert(key.clone(), serialized);
store.private.client_id_set.push(key);
Ok(())
Expand Down Expand Up @@ -191,30 +189,17 @@ impl ExecutionContext for IbcStorage<'_, '_> {

fn store_connection(
&mut self,
connection_path: &ConnectionPath,
path: &ConnectionPath,
connection_end: ConnectionEnd,
) -> Result {
msg!(
"store_connection: path: {}, connection_end: {:?}",
connection_path,
connection_end
);

msg!("store_connection({path}, {connection_end:?})");
let mut store = self.borrow_mut();
let serialized_connection_end =
serde_json::to_string(&connection_end).unwrap();
let connection_trie_key = TrieKey::from(connection_path);
let trie = &mut store.provable;
trie.set(
&connection_trie_key,
&CryptoHash::digest(serialized_connection_end.as_bytes()),
)
.unwrap();

store
.private
.connections
.insert(connection_path.0.to_string(), serialized_connection_end);
let serialized = store_serialised_proof(
&mut store.provable,
&TrieKey::from(path),
&connection_end,
)?;
store.private.connections.insert(path.0.to_string(), serialized);
Ok(())
}

Expand Down Expand Up @@ -303,33 +288,19 @@ impl ExecutionContext for IbcStorage<'_, '_> {

fn store_channel(
&mut self,
channel_end_path: &ChannelEndPath,
path: &ChannelEndPath,
channel_end: ChannelEnd,
) -> Result {
msg!(
"store_channel: path: {}, channel_end: {:?}",
channel_end_path,
channel_end
);
msg!("store_channel({path}, {channel_end:?})");
let mut store = self.borrow_mut();
store.private.port_channel_id_set.push((
channel_end_path.0.to_string(),
channel_end_path.1.to_string(),
));

let serialized_channel_end = borsh::to_vec(&channel_end).unwrap();
let channel_end_trie_key = TrieKey::from(channel_end_path);
let trie = &mut &mut store.provable;
trie.set(
&channel_end_trie_key,
&CryptoHash::digest(&serialized_channel_end),
)
.unwrap();

store.private.channel_ends.insert(
(channel_end_path.0.to_string(), channel_end_path.1.to_string()),
serde_json::to_string(&channel_end).unwrap(),
);
let serialized = store_serialised_proof(
&mut store.provable,
&TrieKey::from(path),
&channel_end,
)?;
let key = (path.0.to_string(), path.1.to_string());
store.private.channel_ends.insert(key.clone(), serialized);
store.private.port_channel_id_set.push(key);
Ok(())
}

Expand Down Expand Up @@ -426,3 +397,29 @@ impl crate::storage::IbcStorageInner<'_, '_> {
Ok(())
}
}

/// Serialises value and stores its hash in trie under given key. Returns the
/// serialised value.
fn store_serialised_proof(
trie: &mut crate::storage::AccountTrie<'_, '_>,
key: &TrieKey,
value: &impl borsh::BorshSerialize,
) -> Result<Vec<u8>> {
fn store_impl(
trie: &mut crate::storage::AccountTrie<'_, '_>,
key: &TrieKey,
value: borsh::maybestd::io::Result<Vec<u8>>,
) -> Result<Vec<u8>> {
value
.map_err(|err| err.to_string())
.and_then(|value| {
let hash = lib::hash::CryptoHash::digest(&value);
trie.set(key, &hash)
.map(|()| value)
.map_err(|err| err.to_string())
})
.map_err(|description| ClientError::Other { description })
.map_err(ContextError::ClientError)
}
store_impl(trie, key, borsh::to_vec(value))
}
4 changes: 2 additions & 2 deletions solana/solana-ibc/programs/solana-ibc/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ pub(crate) type InnerPortId = String;
pub(crate) type InnerChannelId = String;
pub(crate) type InnerIbcEvent = Vec<u8>;
pub(crate) type InnerClient = Vec<u8>; // Serialized
pub(crate) type InnerConnectionEnd = String; // Serialized
pub(crate) type InnerChannelEnd = String; // Serialized
pub(crate) type InnerConnectionEnd = Vec<u8>; // Serialized
pub(crate) type InnerChannelEnd = Vec<u8>; // Serialized
pub(crate) type InnerConsensusState = String; // Serialized

/// A triple of send, receive and acknowledge sequences.
Expand Down
78 changes: 37 additions & 41 deletions solana/solana-ibc/programs/solana-ibc/src/validation_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,13 @@ impl ValidationContext for IbcStorage<'_, '_> {
&self,
client_id: &ClientId,
) -> Result<Self::AnyClientState> {
let store = self.borrow();
let state =
store.private.clients.get(client_id.as_str()).ok_or_else(|| {
ClientError::ClientStateNotFound {
client_id: client_id.clone(),
}
})?;
let state =
borsh::BorshDeserialize::try_from_slice(state).map_err(|err| {
ClientError::Other { description: err.to_string() }
})?;
Ok(state)
deserialise(
self.borrow().private.clients.get(client_id.as_str()),
|| ClientError::ClientStateNotFound {
client_id: client_id.clone(),
},
|description| ClientError::Other { description },
)
}

fn decode_client_state(
Expand Down Expand Up @@ -116,19 +111,13 @@ impl ValidationContext for IbcStorage<'_, '_> {
}

fn connection_end(&self, conn_id: &ConnectionId) -> Result<ConnectionEnd> {
let store = self.borrow();
match store.private.connections.get(conn_id.as_str()) {
Some(data) => {
let connection: ConnectionEnd =
serde_json::from_str(data).unwrap();
Ok(connection)
}
None => Err(ContextError::ConnectionError(
ConnectionError::ConnectionNotFound {
connection_id: conn_id.clone(),
},
)),
}
deserialise(
self.borrow().private.connections.get(conn_id.as_str()),
|| ConnectionError::ConnectionNotFound {
connection_id: conn_id.clone(),
},
|description| ConnectionError::Other { description },
)
}

fn validate_self_client(
Expand Down Expand Up @@ -157,22 +146,16 @@ impl ValidationContext for IbcStorage<'_, '_> {
&self,
channel_end_path: &ChannelEndPath,
) -> Result<ChannelEnd> {
let channel_end_key =
&(channel_end_path.0.to_string(), channel_end_path.1.to_string());
let store = self.borrow();
match store.private.channel_ends.get(channel_end_key) {
Some(data) => {
let channel_end: ChannelEnd =
serde_json::from_str(data).unwrap();
Ok(channel_end)
}
None => {
Err(ContextError::ChannelError(ChannelError::ChannelNotFound {
port_id: channel_end_path.0.clone(),
channel_id: channel_end_path.1.clone(),
}))
}
}
let key =
(channel_end_path.0.to_string(), channel_end_path.1.to_string());
deserialise(
self.borrow().private.channel_ends.get(&key),
|| ChannelError::ChannelNotFound {
port_id: channel_end_path.0.clone(),
channel_id: channel_end_path.1.clone(),
},
|description| ChannelError::Other { description },
)
}

fn get_next_sequence_send(&self, path: &SeqSendPath) -> Result<Sequence> {
Expand Down Expand Up @@ -389,3 +372,16 @@ fn calculate_block_delay(
max_expected_time_per_block.as_secs_f64();
delay.ceil() as u64
}

fn deserialise<V: borsh::BorshDeserialize, E: Into<ContextError>>(
serialised: Option<&Vec<u8>>,
not_found: impl FnOnce() -> E,
borsh_err: impl FnOnce(String) -> E,
) -> Result<V> {
match serialised.map(|data| V::try_from_slice(data)) {
Some(Ok(value)) => Ok(value),
Some(Err(err)) => Err(borsh_err(err.to_string())),
None => Err(not_found()),
}
.map_err(|err| err.into())
}

0 comments on commit d7f0e5e

Please sign in to comment.