Skip to content

Commit

Permalink
solana-ibc: introduce Serialised wrapper in storage (#101)
Browse files Browse the repository at this point in the history
Rather than using untyped `Vec<u8>` for places where serialised
objects are kept in storage, introduce a `Serialised<T>` wrapper
which allows typing the stored object.
  • Loading branch information
mina86 authored Nov 18, 2023
1 parent 8b9c065 commit dac30e2
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 150 deletions.
7 changes: 2 additions & 5 deletions solana/solana-ibc/programs/solana-ibc/src/client_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,11 +544,8 @@ impl IbcStorage<'_, '_> {
let store = self.borrow();
let mut range = store.private.consensus_states.range(range);
if dir == Direction::Next { range.next() } else { range.next_back() }
.map(|(_, data)| borsh::BorshDeserialize::try_from_slice(data))
.map(|(_, data)| data.get())
.transpose()
.map_err(|err| err.to_string())
.map_err(|description| {
ContextError::from(ClientError::ClientSpecific { description })
})
.map_err(|err| err.into())
}
}
117 changes: 50 additions & 67 deletions solana/solana-ibc/programs/solana-ibc/src/execution_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,40 +37,30 @@ impl ClientExecutionContext for IbcStorage<'_, '_> {
fn store_client_state(
&mut self,
path: ClientStatePath,
client_state: Self::AnyClientState,
state: Self::AnyClientState,
) -> Result {
msg!("store_client_state({}, {:?})", path, client_state);
let mut store = self.borrow_mut();
let serialized = store_serialised_proof(
&mut store.provable,
msg!("store_client_state({}, {:?})", path, state);
self.borrow_mut().store_serialised_proof(
|private| &mut private.clients,
path.0.to_string(),
&TrieKey::from(&path),
&client_state,
)?;
let key = path.0.to_string();
store.private.clients.insert(key.clone(), serialized);
Ok(())
&state,
)
}

fn store_consensus_state(
&mut self,
path: ClientConsensusStatePath,
consensus_state: Self::AnyConsensusState,
state: Self::AnyConsensusState,
) -> Result {
msg!(
"store_consensus_state - path: {}, consensus_state: {:?}",
path,
consensus_state
);
let mut store = self.borrow_mut();
let serialized = store_serialised_proof(
&mut store.provable,
&TrieKey::from(&path),
&consensus_state,
)?;
msg!("store_consensus_state({}, {:?})", path, state);
let height = Height::new(path.epoch, path.height)?;
let key = (path.client_id.to_string(), height);
store.private.consensus_states.insert(key, serialized);
Ok(())
self.borrow_mut().store_serialised_proof(
|private| &mut private.consensus_states,
(path.client_id.to_string(), height),
&TrieKey::from(&path),
&state,
)
}

fn delete_consensus_state(
Expand Down Expand Up @@ -164,14 +154,12 @@ impl ExecutionContext for IbcStorage<'_, '_> {
connection_end: ConnectionEnd,
) -> Result {
msg!("store_connection({}, {:?})", path, connection_end);
let mut store = self.borrow_mut();
let serialized = store_serialised_proof(
&mut store.provable,
self.borrow_mut().store_serialised_proof(
|private| &mut private.connections,
path.0.to_string(),
&TrieKey::from(path),
&connection_end,
)?;
store.private.connections.insert(path.0.to_string(), serialized);
Ok(())
)
}

fn store_connection_to_client(
Expand Down Expand Up @@ -289,15 +277,12 @@ impl ExecutionContext for IbcStorage<'_, '_> {
channel_end: ChannelEnd,
) -> Result {
msg!("store_channel({}, {:?})", path, channel_end);
let mut store = self.borrow_mut();
let serialized = store_serialised_proof(
&mut store.provable,
self.borrow_mut().store_serialised_proof(
|private| &mut private.channel_ends,
(path.0.to_string(), path.1.to_string()),
&TrieKey::from(path),
&channel_end,
)?;
let key = (path.0.to_string(), path.1.to_string());
store.private.channel_ends.insert(key.clone(), serialized);
Ok(())
)
}

fn store_next_sequence_send(
Expand All @@ -308,7 +293,7 @@ impl ExecutionContext for IbcStorage<'_, '_> {
msg!("store_next_sequence_send: path: {}, seq: {}", path, seq);
self.borrow_mut().store_next_sequence(
path.into(),
crate::storage::SequenceTripleIdx::Send,
storage::SequenceTripleIdx::Send,
seq,
)
}
Expand All @@ -321,7 +306,7 @@ impl ExecutionContext for IbcStorage<'_, '_> {
msg!("store_next_sequence_recv: path: {}, seq: {}", path, seq);
self.borrow_mut().store_next_sequence(
path.into(),
crate::storage::SequenceTripleIdx::Recv,
storage::SequenceTripleIdx::Recv,
seq,
)
}
Expand All @@ -334,7 +319,7 @@ impl ExecutionContext for IbcStorage<'_, '_> {
msg!("store_next_sequence_ack: path: {}, seq: {}", path, seq);
self.borrow_mut().store_next_sequence(
path.into(),
crate::storage::SequenceTripleIdx::Ack,
storage::SequenceTripleIdx::Ack,
seq,
)
}
Expand Down Expand Up @@ -362,11 +347,11 @@ impl ExecutionContext for IbcStorage<'_, '_> {
fn get_client_execution_context(&mut self) -> &mut Self::E { self }
}

impl crate::storage::IbcStorageInner<'_, '_> {
impl storage::IbcStorageInner<'_, '_> {
fn store_next_sequence(
&mut self,
path: crate::trie_key::SequencePath<'_>,
index: crate::storage::SequenceTripleIdx,
index: storage::SequenceTripleIdx,
seq: Sequence,
) -> Result {
let trie = &mut self.provable;
Expand All @@ -380,32 +365,30 @@ 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)
/// Serialises `value` and stores it in private storage along with its
/// commitment in provable storage.
///
/// Serialises `value` and a) stores hash of the serialised object (i.e. its
/// commitment) in the provable storage under key `trie_key` and b) stores
/// the serialised object itself in map returned my `get_map` under the key
/// `key`.
fn store_serialised_proof<K: Ord, V: borsh::BorshSerialize>(
&mut self,
get_map: impl FnOnce(
&mut storage::PrivateStorage,
) -> &mut BTreeMap<K, storage::Serialised<V>>,
key: K,
trie_key: &TrieKey,
value: &V,
) -> Result {
let serialised = storage::Serialised::new(value)?;
self.provable
.set(trie_key, &serialised.digest())
.map_err(|e| ClientError::Other { description: e.to_string() })?;
get_map(self.private).insert(key, serialised);
Ok(())
}
store_impl(trie, key, borsh::to_vec(value))
}

type SequencesMap =
Expand Down
6 changes: 2 additions & 4 deletions solana/solana-ibc/programs/solana-ibc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ const TRIE_SEED: &[u8] = b"trie";
const CONNECTION_ID_PREFIX: &str = "connection-";
const CHANNEL_ID_PREFIX: &str = "channel-";

use crate::storage::IBCPackets;

declare_id!("EnfDJsAK7BGgetnmKzBx86CsgC5kfSPcsktFCQ4YLC81");

mod chain;
Expand Down Expand Up @@ -122,7 +120,7 @@ pub mod solana_ibc {
let private: &mut storage::PrivateStorage = &mut ctx.accounts.storage;
msg!("This is private: {:?}", private);
let provable = storage::get_provable_from(&ctx.accounts.trie, "trie")?;
let packets: &mut IBCPackets = &mut ctx.accounts.packets;
let packets = &mut ctx.accounts.packets;
let host_head = host::Head::get()?;

// Before anything else, try generating a new guest block. However, if
Expand Down Expand Up @@ -227,7 +225,7 @@ pub struct Deliver<'info> {

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

/// The guest blockchain data.
#[account(init_if_needed, payer = sender, seeds = [CHAIN_SEED], bump, space = 10000)]
Expand Down
Loading

0 comments on commit dac30e2

Please sign in to comment.