From 6051af38dfd4b7586f25089edaef6ba762dfb5dd Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 9 Nov 2023 16:25:00 +0100 Subject: [PATCH] solana-ibc: refactor events handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Firstly, remove ibc_events_history from the storage. The field only ever grows which isn’t sustainable. The contract has no use for the field and off-chain customers should look at history of Solana logs rather than looking at the field. Secondly, encode the IBC event directly in an event struct rather than first borsh serialising it and then emitting that. Since emitting causes another borsh serialisation this leads to somewhat awkward and unnecessary double serialisation. Lastly, use Solana logging directly rather than using Anchor’s logging infrastructure. Anchor really doesn’t give us much as far as I can tell and having an enum with all possible events which is serialised is just as if not more convenient. --- .../solana-ibc/programs/solana-ibc/Cargo.toml | 1 + .../programs/solana-ibc/src/events.rs | 29 +++++++++++++++++++ .../solana-ibc/src/execution_context.rs | 20 ++----------- .../solana-ibc/programs/solana-ibc/src/lib.rs | 6 +--- .../programs/solana-ibc/src/storage.rs | 4 --- 5 files changed, 33 insertions(+), 27 deletions(-) create mode 100644 solana/solana-ibc/programs/solana-ibc/src/events.rs diff --git a/solana/solana-ibc/programs/solana-ibc/Cargo.toml b/solana/solana-ibc/programs/solana-ibc/Cargo.toml index 5508b968..73886b13 100644 --- a/solana/solana-ibc/programs/solana-ibc/Cargo.toml +++ b/solana/solana-ibc/programs/solana-ibc/Cargo.toml @@ -19,6 +19,7 @@ mocks = ["ibc/mocks", "ibc/std"] anchor-lang.workspace = true base64.workspace = true bytemuck.workspace = true +derive_more.workspace = true ibc-proto.workspace = true ibc.workspace = true serde.workspace = true diff --git a/solana/solana-ibc/programs/solana-ibc/src/events.rs b/solana/solana-ibc/programs/solana-ibc/src/events.rs new file mode 100644 index 00000000..2c9c1866 --- /dev/null +++ b/solana/solana-ibc/programs/solana-ibc/src/events.rs @@ -0,0 +1,29 @@ +use anchor_lang::prelude::borsh; +use anchor_lang::solana_program; + +/// Possible events emitted by the smart contract. +/// +/// The events are logged in their borsh-serialised form. +#[derive( + Clone, + PartialEq, + Eq, + borsh::BorshSerialize, + borsh::BorshDeserialize, + derive_more::From, +)] +pub enum Event { + IBCEvent(ibc::core::events::IbcEvent), +} + +impl Event { + pub fn emit(&self) -> Result<(), String> { + borsh::BorshSerialize::try_to_vec(self) + .map(|data| solana_program::log::sol_log_data(&[data.as_slice()])) + .map_err(|err| err.to_string()) + } +} + +pub fn emit(event: impl Into) -> Result<(), String> { + event.into().emit() +} diff --git a/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs b/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs index 7bc677da..405eb1ca 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs @@ -1,6 +1,5 @@ use alloc::collections::BTreeMap; -use anchor_lang::emit; use anchor_lang::prelude::borsh; use anchor_lang::solana_program::msg; use ibc::core::events::IbcEvent; @@ -27,7 +26,6 @@ use crate::client_state::AnyClientState; use crate::consensus_state::AnyConsensusState; use crate::storage::{self, IbcStorage}; use crate::trie_key::TrieKey; -use crate::EmitIBCEvent; type Result = core::result::Result; @@ -382,22 +380,8 @@ impl ExecutionContext for IbcStorage<'_, '_> { } fn emit_ibc_event(&mut self, event: IbcEvent) -> Result { - let mut store = self.borrow_mut(); - let host_height = - ibc::Height::new(store.private.height.0, store.private.height.1)?; - let ibc_event = borsh::to_vec(&event).map_err(|err| { - ClientError::Other { description: err.to_string() } - })?; - let inner_host_height = - (host_height.revision_height(), host_height.revision_number()); - store - .private - .ibc_events_history - .entry(inner_host_height) - .or_default() - .push(ibc_event.clone()); - emit!(EmitIBCEvent { ibc_event }); - Ok(()) + crate::events::emit(event) + .map_err(|description| ClientError::Other { description }.into()) } fn log_message(&mut self, message: String) -> Result { diff --git a/solana/solana-ibc/programs/solana-ibc/src/lib.rs b/solana/solana-ibc/programs/solana-ibc/src/lib.rs index c73d4364..0496a611 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/lib.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/lib.rs @@ -21,6 +21,7 @@ declare_id!("EnfDJsAK7BGgetnmKzBx86CsgC5kfSPcsktFCQ4YLC81"); mod client_state; mod consensus_state; mod ed25519; +mod events; mod execution_context; mod storage; #[cfg(test)] @@ -132,11 +133,6 @@ impl From> for u32 { } } -#[event] -pub struct EmitIBCEvent { - pub ibc_event: Vec, -} - impl Router for storage::IbcStorage<'_, '_> { // fn get_route(&self, module_id: &ModuleId) -> Option<&dyn Module> { diff --git a/solana/solana-ibc/programs/solana-ibc/src/storage.rs b/solana/solana-ibc/programs/solana-ibc/src/storage.rs index 8ec71d82..9add9d0c 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/storage.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/storage.rs @@ -13,7 +13,6 @@ pub(crate) type InnerClientId = String; pub(crate) type InnerConnectionId = String; pub(crate) type InnerPortId = String; pub(crate) type InnerChannelId = String; -pub(crate) type InnerIbcEvent = Vec; pub(crate) type InnerClient = Vec; // Serialized pub(crate) type InnerConnectionEnd = Vec; // Serialized pub(crate) type InnerChannelEnd = Vec; // Serialized @@ -120,9 +119,6 @@ pub(crate) struct PrivateStorage { /// different maps we need to maintain. This saves us on the amount of /// trie nodes we need to maintain. pub next_sequence: BTreeMap<(InnerPortId, InnerChannelId), SequenceTriple>, - - /// The history of IBC events. - pub ibc_events_history: BTreeMap>, } /// Provable storage, i.e. the trie, held in an account.