From 583708dc0a6bdedd6bc159caaddfbcdaefa7048b Mon Sep 17 00:00:00 2001 From: Dhruv D Jain Date: Fri, 20 Oct 2023 02:27:36 +0530 Subject: [PATCH] Fix Router by implementing on storage instead on seperate module (#38) * impl router on storage instead of another struct * impl router on storage instead of another struct * rm module holder * rm unneccesary logs * fixed merge conflicts * fixed storing client counter * rm unneccesary commented code * added comments * impl storing seq on inner type * fmt * fmt * use btreemap from alloc * fmt * fix borrow * fmt --------- Co-authored-by: Michal Nazarewicz --- common/sealable-trie/src/trie.rs | 1 + .../programs/solana-ibc/src/client_state.rs | 12 +- .../solana-ibc/src/execution_context.rs | 146 +++++++---- .../solana-ibc/programs/solana-ibc/src/lib.rs | 235 ++++-------------- .../programs/solana-ibc/src/module_holder.rs | 22 -- .../programs/solana-ibc/src/transfer/impls.rs | 126 +--------- .../programs/solana-ibc/src/transfer/mod.rs | 44 +++- .../programs/solana-ibc/src/trie.rs | 3 +- .../solana-ibc/src/validation_context.rs | 65 +++-- 9 files changed, 261 insertions(+), 393 deletions(-) delete mode 100644 solana/solana-ibc/programs/solana-ibc/src/module_holder.rs diff --git a/common/sealable-trie/src/trie.rs b/common/sealable-trie/src/trie.rs index 2257bc5b..aaaf582b 100644 --- a/common/sealable-trie/src/trie.rs +++ b/common/sealable-trie/src/trie.rs @@ -59,6 +59,7 @@ pub const EMPTY_TRIE_ROOT: CryptoHash = CryptoHash::DEFAULT; /// a single value at a key whose length is withing 36 bytes has a single /// node however if that key is longer than 36 bytes the trie needs at least /// two nodes. +#[derive(Debug)] pub struct Trie { /// Pointer to the root node. `None` if the trie is empty or the root node /// has been sealed. diff --git a/solana/solana-ibc/programs/solana-ibc/src/client_state.rs b/solana/solana-ibc/programs/solana-ibc/src/client_state.rs index ecfbe51e..fbcd8aa5 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/client_state.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/client_state.rs @@ -416,7 +416,11 @@ impl ibc::clients::ics07_tendermint::ValidationContext height: &Height, ) -> Result, ContextError> { let end_height = (height.revision_number() + 1, 1); - match self.consensus_states.get(&(client_id.to_string(), end_height)) { + let solana_ibc_store = &self.0.borrow().solana_ibc_store; + match solana_ibc_store + .consensus_states + .get(&(client_id.to_string(), end_height)) + { Some(data) => { let result: Self::AnyConsensusState = serde_json::from_str(data).unwrap(); @@ -434,7 +438,11 @@ impl ibc::clients::ics07_tendermint::ValidationContext height: &Height, ) -> Result, ContextError> { let end_height = (height.revision_number(), 1); - match self.consensus_states.get(&(client_id.to_string(), end_height)) { + let solana_ibc_store = &self.0.borrow().solana_ibc_store; + match solana_ibc_store + .consensus_states + .get(&(client_id.to_string(), end_height)) + { Some(data) => { let result: Self::AnyConsensusState = serde_json::from_str(data).unwrap(); 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 37943143..30ca38e7 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs @@ -20,7 +20,7 @@ use ibc::core::ics24_host::path::{ SeqRecvPath, SeqSendPath, }; use ibc::core::timestamp::Timestamp; -use ibc::core::{ExecutionContext, ValidationContext}; +use ibc::core::{ContextError, ExecutionContext}; use ibc::Height; use crate::client_state::AnyClientState; @@ -28,6 +28,7 @@ use crate::consensus_state::AnyConsensusState; use crate::trie_key::TrieKey; use crate::{ EmitIBCEvent, InnerChannelId, InnerPortId, InnerSequence, SolanaIbcStorage, + SolanaIbcStorageTest, }; type Result = core::result::Result; @@ -50,9 +51,10 @@ impl ClientExecutionContext for SolanaIbcStorage<'_, '_> { let client_state_key = client_state_path.0.to_string(); let serialized_client_state = serde_json::to_string(&client_state).unwrap(); - + let mut store = self.0.borrow_mut(); + // let mut solana_ibc_store = &store.solana_ibc_store; let client_state_trie_key = TrieKey::from(&client_state_path); - let trie = self.trie.as_mut().unwrap(); + let trie = &mut store.trie; msg!( "THis is serialized client state {}", &lib::hash::CryptoHash::digest(serialized_client_state.as_bytes()) @@ -62,8 +64,14 @@ impl ClientExecutionContext for SolanaIbcStorage<'_, '_> { &lib::hash::CryptoHash::digest(serialized_client_state.as_bytes()), ) .unwrap(); - self.clients.insert(client_state_key, serialized_client_state); - self.client_id_set.push(client_state_path.0.to_string()); + store + .solana_ibc_store + .clients + .insert(client_state_key, serialized_client_state); + store + .solana_ibc_store + .client_id_set + .push(client_state_path.0.to_string()); Ok(()) } @@ -81,11 +89,12 @@ impl ClientExecutionContext for SolanaIbcStorage<'_, '_> { consensus_state_path.client_id.to_string(), (consensus_state_path.epoch, consensus_state_path.height), ); + let mut store = self.0.borrow_mut(); let serialized_consensus_state = serde_json::to_string(&consensus_state).unwrap(); let consensus_state_trie_key = TrieKey::from(&consensus_state_path); - let trie = self.trie.as_mut().unwrap(); + let trie = &mut store.trie; trie.set( &consensus_state_trie_key, &lib::hash::CryptoHash::digest( @@ -94,18 +103,25 @@ impl ClientExecutionContext for SolanaIbcStorage<'_, '_> { ) .unwrap(); - self.consensus_states + store + .solana_ibc_store + .consensus_states .insert(consensus_state_key, serialized_consensus_state); - self.height.0 = consensus_state_path.epoch; - self.height.1 = consensus_state_path.height; + store.solana_ibc_store.height.0 = consensus_state_path.epoch; + store.solana_ibc_store.height.1 = consensus_state_path.height; Ok(()) } } impl ExecutionContext for SolanaIbcStorage<'_, '_> { fn increase_client_counter(&mut self) -> Result { - self.client_counter.checked_add(1).unwrap(); - msg!("client_counter has increased to: {}", self.client_counter); + let mut store = self.0.borrow_mut(); + store.solana_ibc_store.client_counter = + store.solana_ibc_store.client_counter.checked_add(1).unwrap(); + msg!( + "client_counter has increased to: {}", + store.solana_ibc_store.client_counter + ); Ok(()) } @@ -121,7 +137,10 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { height, timestamp ); - self.client_processed_times + let mut store = self.0.borrow_mut(); + store + .solana_ibc_store + .client_processed_times .entry(client_id.to_string()) .or_default() .insert( @@ -144,7 +163,10 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { height, host_height ); - self.client_processed_heights + let mut store = self.0.borrow_mut(); + store + .solana_ibc_store + .client_processed_heights .entry(client_id.to_string()) .or_default() .insert( @@ -165,10 +187,11 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { connection_end ); + let mut store = self.0.borrow_mut(); let serialized_connection_end = serde_json::to_string(&connection_end).unwrap(); let connection_trie_key = TrieKey::from(connection_path); - let trie = self.trie.as_mut().unwrap(); + let trie = &mut store.trie; trie.set( &connection_trie_key, &lib::hash::CryptoHash::digest( @@ -177,7 +200,9 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { ) .unwrap(); - self.connections + store + .solana_ibc_store + .connections .insert(connection_path.0.to_string(), serialized_connection_end); Ok(()) } @@ -192,16 +217,21 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { client_connection_path, conn_id ); - self.connection_to_client + let mut store = self.0.borrow_mut(); + store + .solana_ibc_store + .connection_to_client .insert(conn_id.to_string(), client_connection_path.0.to_string()); Ok(()) } fn increase_connection_counter(&mut self) -> Result { - self.connection_counter.checked_add(1).unwrap(); + let mut store = self.0.borrow_mut(); + store.solana_ibc_store.connection_counter = + store.solana_ibc_store.connection_counter.checked_add(1).unwrap(); msg!( "connection_counter has increased to: {}", - self.connection_counter + store.solana_ibc_store.connection_counter ); Ok(()) } @@ -216,8 +246,9 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { commitment_path, commitment ); + let mut store = self.0.borrow_mut(); let commitment_trie_key = TrieKey::from(commitment_path); - let trie = self.trie.as_mut().unwrap(); + let trie = &mut store.trie; trie.set( &commitment_trie_key, &lib::hash::CryptoHash::digest(&commitment.into_vec()), @@ -225,7 +256,7 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { .unwrap(); record_packet_sequence( - &mut self.packet_commitment_sequence_sets, + &mut store.solana_ibc_store.packet_commitment_sequence_sets, &commitment_path.port_id, &commitment_path.channel_id, &commitment_path.sequence, @@ -238,10 +269,12 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { commitment_path: &CommitmentPath, ) -> Result { msg!("delete_packet_commitment: path: {}", commitment_path); - let sequences = self.packet_commitment_sequence_sets.get_mut(&( - commitment_path.port_id.clone().to_string(), - commitment_path.channel_id.clone().to_string(), - )); + let mut store = self.0.borrow_mut(); + let sequences = + store.solana_ibc_store.packet_commitment_sequence_sets.get_mut(&( + commitment_path.port_id.clone().to_string(), + commitment_path.channel_id.clone().to_string(), + )); if let Some(sequences) = sequences { let index = sequences .iter() @@ -262,12 +295,13 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { receipt_path, receipt ); + let mut store = self.0.borrow_mut(); let receipt_trie_key = TrieKey::from(receipt_path); - let trie = self.trie.as_mut().unwrap(); + let trie = &mut store.trie; trie.set(&receipt_trie_key, &lib::hash::CryptoHash::DEFAULT).unwrap(); trie.seal(&receipt_trie_key).unwrap(); record_packet_sequence( - &mut self.packet_receipt_sequence_sets, + &mut store.solana_ibc_store.packet_receipt_sequence_sets, &receipt_path.port_id, &receipt_path.channel_id, &receipt_path.sequence, @@ -285,15 +319,16 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { ack_path, ack_commitment ); + let mut store = self.0.borrow_mut(); let ack_commitment_trie_key = TrieKey::from(ack_path); - let trie = self.trie.as_mut().unwrap(); + let trie = &mut store.trie; trie.set( &ack_commitment_trie_key, &lib::hash::CryptoHash::digest(&ack_commitment.into_vec()), ) .unwrap(); record_packet_sequence( - &mut self.packet_acknowledgement_sequence_sets, + &mut store.solana_ibc_store.packet_acknowledgement_sequence_sets, &ack_path.port_id, &ack_path.channel_id, &ack_path.sequence, @@ -303,10 +338,14 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { fn delete_packet_acknowledgement(&mut self, ack_path: &AckPath) -> Result { msg!("delete_packet_acknowledgement: path: {}", ack_path,); - let sequences = self.packet_acknowledgement_sequence_sets.get_mut(&( - ack_path.port_id.clone().to_string(), - ack_path.channel_id.clone().to_string(), - )); + let mut store = self.0.borrow_mut(); + let sequences = store + .solana_ibc_store + .packet_acknowledgement_sequence_sets + .get_mut(&( + ack_path.port_id.clone().to_string(), + ack_path.channel_id.clone().to_string(), + )); if let Some(sequences) = sequences { let sequence_as_u64: u64 = ack_path.sequence.into(); sequences.remove(sequence_as_u64 as usize); @@ -324,21 +363,22 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { channel_end_path, channel_end ); - self.port_channel_id_set.push(( + let mut store = self.0.borrow_mut(); + store.solana_ibc_store.port_channel_id_set.push(( channel_end_path.0.clone().to_string(), channel_end_path.1.clone().to_string(), )); let serialized_channel_end = borsh::to_vec(&channel_end).unwrap(); let channel_end_trie_key = TrieKey::from(channel_end_path); - let trie = self.trie.as_mut().unwrap(); + let trie = &mut &mut store.trie; trie.set( &channel_end_trie_key, &lib::hash::CryptoHash::digest(&serialized_channel_end), ) .unwrap(); - self.channel_ends.insert( + store.solana_ibc_store.channel_ends.insert( (channel_end_path.0.to_string(), channel_end_path.1.to_string()), serde_json::to_string(&channel_end).unwrap(), ); @@ -351,7 +391,8 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { seq: Sequence, ) -> Result { msg!("store_next_sequence_send: path: {path}, seq: {seq}"); - self.store_next_sequence( + let store: &mut SolanaIbcStorageTest<'_, '_> = &mut self.0.borrow_mut(); + store.store_next_sequence( path.into(), super::SequenceTripleIdx::Send, seq, @@ -364,7 +405,8 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { seq: Sequence, ) -> Result { msg!("store_next_sequence_recv: path: {path}, seq: {seq}"); - self.store_next_sequence( + let store: &mut SolanaIbcStorageTest<'_, '_> = &mut self.0.borrow_mut(); + store.store_next_sequence( path.into(), super::SequenceTripleIdx::Recv, seq, @@ -377,7 +419,8 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { seq: Sequence, ) -> Result { msg!("store_next_sequence_ack: path: {path}, seq: {seq}"); - self.store_next_sequence( + let store: &mut SolanaIbcStorageTest<'_, '_> = &mut self.0.borrow_mut(); + store.store_next_sequence( path.into(), super::SequenceTripleIdx::Ack, seq, @@ -385,17 +428,29 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { } fn increase_channel_counter(&mut self) -> Result { - self.channel_counter += 1; - msg!("channel_counter has increased to: {}", self.channel_counter); + let mut store = self.0.borrow_mut(); + store.solana_ibc_store.channel_counter += 1; + msg!( + "channel_counter has increased to: {}", + store.solana_ibc_store.channel_counter + ); Ok(()) } fn emit_ibc_event(&mut self, event: IbcEvent) -> Result { - let host_height = self.host_height().unwrap(); + let mut store = self.0.borrow_mut(); + let host_height = ibc::Height::new( + store.solana_ibc_store.height.0, + store.solana_ibc_store.height.1, + ) + .map_err(ContextError::ClientError) + .unwrap(); let event_in_bytes: Vec = bincode::serialize(&event).unwrap(); let inner_host_height = (host_height.revision_height(), host_height.revision_number()); - self.ibc_events_history + store + .solana_ibc_store + .ibc_events_history .entry(inner_host_height) .or_default() .push(event_in_bytes.clone()); @@ -411,19 +466,20 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { fn get_client_execution_context(&mut self) -> &mut Self::E { self } } -impl SolanaIbcStorage<'_, '_> { +impl SolanaIbcStorageTest<'_, '_> { fn store_next_sequence( &mut self, path: crate::trie_key::SequencePath<'_>, index: super::SequenceTripleIdx, seq: Sequence, ) -> Result { + let trie = &mut self.trie; + let next_seq = &mut self.solana_ibc_store.next_sequence; let map_key = (path.port_id.to_string(), path.channel_id.to_string()); - let triple = self.next_sequence.entry(map_key).or_default(); + let triple = next_seq.entry(map_key).or_default(); triple.set(index, seq); let trie_key = TrieKey::from(path); - let trie = self.trie.as_mut().unwrap(); trie.set(&trie_key, &triple.to_hash()).unwrap(); Ok(()) diff --git a/solana/solana-ibc/programs/solana-ibc/src/lib.rs b/solana/solana-ibc/programs/solana-ibc/src/lib.rs index 9ae5de0a..4c70d724 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/lib.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/lib.rs @@ -1,16 +1,17 @@ // anchor_lang::error::Error and anchor_lang::Result is ≥ 160 bytes and there’s // not much we can do about it. #![allow(clippy::result_large_err)] +extern crate alloc; -use core::borrow::Borrow; -use std::collections::BTreeMap; +use alloc::collections::BTreeMap; +use alloc::rc::Rc; +use core::cell::RefCell; use anchor_lang::prelude::*; use borsh::{BorshDeserialize, BorshSerialize}; use ibc::core::ics04_channel::packet::Sequence; use ibc::core::ics24_host::identifier::PortId; use ibc::core::router::{Module, ModuleId, Router}; -use module_holder::ModuleHolder; const SOLANA_IBC_STORAGE_SEED: &[u8] = b"solana_ibc_storage"; const TEST_TRIE_SEED: &[u8] = b"test_trie"; @@ -22,7 +23,6 @@ declare_id!("EnfDJsAK7BGgetnmKzBx86CsgC5kfSPcsktFCQ4YLC81"); mod client_state; mod consensus_state; mod execution_context; -mod module_holder; #[cfg(test)] mod tests; mod transfer; @@ -67,93 +67,23 @@ pub mod solana_ibc { let trie = trie::AccountTrie::new(account.try_borrow_mut_data()?) .ok_or(ProgramError::InvalidAccountData)?; - msg!("Before trie {:?}", trie.hash()); - - let mut solana_real_storage = SolanaIbcStorage { - height: solana_ibc_store.height, - module_holder: solana_ibc_store.module_holder.clone(), - clients: solana_ibc_store.clients.clone(), - client_id_set: solana_ibc_store.client_id_set.clone(), - client_counter: solana_ibc_store.client_counter, - client_processed_times: solana_ibc_store - .client_processed_times - .clone(), - client_processed_heights: solana_ibc_store - .client_processed_heights - .clone(), - consensus_states: solana_ibc_store.consensus_states.clone(), - client_consensus_state_height_sets: solana_ibc_store - .client_consensus_state_height_sets - .clone(), - connection_id_set: solana_ibc_store.connection_id_set.clone(), - connection_counter: solana_ibc_store.connection_counter, - connections: solana_ibc_store.connections.clone(), - channel_ends: solana_ibc_store.channel_ends.clone(), - connection_to_client: solana_ibc_store.connection_to_client.clone(), - port_channel_id_set: solana_ibc_store.port_channel_id_set.clone(), - channel_counter: solana_ibc_store.channel_counter, - next_sequence: solana_ibc_store.next_sequence.clone(), - packet_commitment_sequence_sets: solana_ibc_store - .packet_commitment_sequence_sets - .clone(), - packet_receipt_sequence_sets: solana_ibc_store - .packet_receipt_sequence_sets - .clone(), - packet_acknowledgement_sequence_sets: solana_ibc_store - .packet_acknowledgement_sequence_sets - .clone(), - ibc_events_history: solana_ibc_store.ibc_events_history.clone(), - trie: Some(trie), + let solana_real_storage = SolanaIbcStorageTest { + solana_ibc_store: solana_ibc_store.clone(), + trie, }; - let mut solana_real_storage_another = SolanaIbcStorage { - height: solana_ibc_store.height, - module_holder: solana_ibc_store.module_holder.clone(), - clients: solana_ibc_store.clients.clone(), - client_id_set: solana_ibc_store.client_id_set.clone(), - client_counter: solana_ibc_store.client_counter, - client_processed_times: solana_ibc_store - .client_processed_times - .clone(), - client_processed_heights: solana_ibc_store - .client_processed_heights - .clone(), - consensus_states: solana_ibc_store.consensus_states.clone(), - client_consensus_state_height_sets: solana_ibc_store - .client_consensus_state_height_sets - .clone(), - connection_id_set: solana_ibc_store.connection_id_set.clone(), - connection_counter: solana_ibc_store.connection_counter, - connections: solana_ibc_store.connections.clone(), - channel_ends: solana_ibc_store.channel_ends.clone(), - connection_to_client: solana_ibc_store.connection_to_client.clone(), - port_channel_id_set: solana_ibc_store.port_channel_id_set.clone(), - channel_counter: solana_ibc_store.channel_counter, - next_sequence: solana_ibc_store.next_sequence.clone(), - packet_commitment_sequence_sets: solana_ibc_store - .packet_commitment_sequence_sets - .clone(), - packet_receipt_sequence_sets: solana_ibc_store - .packet_receipt_sequence_sets - .clone(), - packet_acknowledgement_sequence_sets: solana_ibc_store - .packet_acknowledgement_sequence_sets - .clone(), - ibc_events_history: solana_ibc_store.ibc_events_history.clone(), - trie: None, - }; - - let router = &mut solana_real_storage_another; + let mut store = + SolanaIbcStorage(Rc::>::new( + solana_real_storage.into(), + )); + let mut router = store.clone(); let errors = all_messages.into_iter().fold(vec![], |mut errors, msg| { match ibc::core::MsgEnvelope::try_from(msg) { Ok(msg) => { - match ibc::core::dispatch( - &mut solana_real_storage, - router, - msg, - ) { + match ibc::core::dispatch(&mut store, &mut router, msg) + { Ok(()) => (), Err(e) => errors.push(e), } @@ -163,43 +93,37 @@ pub mod solana_ibc { errors }); - solana_ibc_store.height = solana_real_storage.height; - solana_ibc_store.module_holder = - solana_real_storage.module_holder.clone(); - solana_ibc_store.clients = solana_real_storage.clients.clone(); - solana_ibc_store.client_id_set = - solana_real_storage.client_id_set.clone(); - solana_ibc_store.client_counter = solana_real_storage.client_counter; + let sol_store = &store.0.borrow_mut().solana_ibc_store; + solana_ibc_store.height = sol_store.height; + solana_ibc_store.clients = sol_store.clients.clone(); + solana_ibc_store.client_id_set = sol_store.client_id_set.clone(); + solana_ibc_store.client_counter = sol_store.client_counter; solana_ibc_store.client_processed_times = - solana_real_storage.client_processed_times.clone(); + sol_store.client_processed_times.clone(); solana_ibc_store.client_processed_heights = - solana_real_storage.client_processed_heights.clone(); - solana_ibc_store.consensus_states = - solana_real_storage.consensus_states.clone(); + sol_store.client_processed_heights.clone(); + solana_ibc_store.consensus_states = sol_store.consensus_states.clone(); solana_ibc_store.client_consensus_state_height_sets = - solana_real_storage.client_consensus_state_height_sets.clone(); + sol_store.client_consensus_state_height_sets.clone(); solana_ibc_store.connection_id_set = - solana_real_storage.connection_id_set.clone(); - solana_ibc_store.connection_counter = - solana_real_storage.connection_counter; - solana_ibc_store.connections = solana_real_storage.connections.clone(); - solana_ibc_store.channel_ends = - solana_real_storage.channel_ends.clone(); + sol_store.connection_id_set.clone(); + solana_ibc_store.connection_counter = sol_store.connection_counter; + solana_ibc_store.connections = sol_store.connections.clone(); + solana_ibc_store.channel_ends = sol_store.channel_ends.clone(); solana_ibc_store.connection_to_client = - solana_real_storage.connection_to_client.clone(); + sol_store.connection_to_client.clone(); solana_ibc_store.port_channel_id_set = - solana_real_storage.port_channel_id_set.clone(); - solana_ibc_store.channel_counter = solana_real_storage.channel_counter; - solana_ibc_store.next_sequence = - solana_real_storage.next_sequence.clone(); + sol_store.port_channel_id_set.clone(); + solana_ibc_store.channel_counter = sol_store.channel_counter; + solana_ibc_store.next_sequence = sol_store.next_sequence.clone(); solana_ibc_store.packet_commitment_sequence_sets = - solana_real_storage.packet_commitment_sequence_sets.clone(); + sol_store.packet_commitment_sequence_sets.clone(); solana_ibc_store.packet_receipt_sequence_sets = - solana_real_storage.packet_receipt_sequence_sets.clone(); + sol_store.packet_receipt_sequence_sets.clone(); solana_ibc_store.packet_acknowledgement_sequence_sets = - solana_real_storage.packet_acknowledgement_sequence_sets.clone(); + sol_store.packet_acknowledgement_sequence_sets.clone(); solana_ibc_store.ibc_events_history = - solana_real_storage.ibc_events_history.clone(); + sol_store.ibc_events_history.clone(); msg!("These are errors {:?}", errors); msg!("This is final structure {:?}", solana_ibc_store); @@ -304,8 +228,6 @@ impl InnerSequenceTriple { /// All the structs from IBC are stored as String since they dont implement AnchorSerialize and AnchorDeserialize pub struct SolanaIbcStorageTemp { pub height: InnerHeight, - /// To support the mutable borrow in `Router::get_route_mut`. - pub module_holder: ModuleHolder, pub clients: BTreeMap, /// The client ids of the clients. pub client_id_set: Vec, @@ -353,76 +275,21 @@ pub struct SolanaIbcStorageTemp { } /// All the structs from IBC are stored as String since they dont implement AnchorSerialize and AnchorDeserialize -pub struct SolanaIbcStorage<'a, 'b> { - pub height: InnerHeight, - /// To support the mutable borrow in `Router::get_route_mut`. - pub module_holder: ModuleHolder, - pub clients: BTreeMap, - /// The client ids of the clients. - pub client_id_set: Vec, - pub client_counter: u64, - pub client_processed_times: - BTreeMap>, - pub client_processed_heights: - BTreeMap>, - pub consensus_states: - BTreeMap<(InnerClientId, InnerHeight), InnerConsensusState>, - /// This collection contains the heights corresponding to all consensus states of - /// all clients stored in the contract. - pub client_consensus_state_height_sets: - BTreeMap>, - /// The connection ids of the connections. - pub connection_id_set: Vec, - pub connection_counter: u64, - pub connections: BTreeMap, - pub channel_ends: BTreeMap<(InnerPortId, InnerChannelId), InnerChannelEnd>, - // Contains the client id corresponding to the connectionId - pub connection_to_client: BTreeMap, - /// The port and channel id tuples of the channels. - pub port_channel_id_set: Vec<(InnerPortId, InnerChannelId)>, - pub channel_counter: u64, - - /// Next send, receive and ack sequence for given (port, channel). - /// - /// We’re storing all three sequences in a single object to reduce amount of - /// 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), InnerSequenceTriple>, - - /// The sequence numbers of the packet commitments. - pub packet_commitment_sequence_sets: - BTreeMap<(InnerPortId, InnerChannelId), Vec>, - /// The sequence numbers of the packet receipts. - pub packet_receipt_sequence_sets: - BTreeMap<(InnerPortId, InnerChannelId), Vec>, - /// The sequence numbers of the packet acknowledgements. - pub packet_acknowledgement_sequence_sets: - BTreeMap<(InnerPortId, InnerChannelId), Vec>, - /// The history of IBC events. - pub ibc_events_history: BTreeMap>, - pub trie: Option>, +#[derive(Debug)] +pub struct SolanaIbcStorageTest<'a, 'b> { + pub solana_ibc_store: SolanaIbcStorageTemp, + pub trie: trie::AccountTrie<'a, 'b>, } -pub trait SolanaIbcStorageHost { - /// - fn get_solana_ibc_store( - _account: Pubkey, - ) -> SolanaIbcStorage<'static, 'static> { - // Unpack the account - todo!() - } - /// - fn set_solana_ibc_store(_store: &SolanaIbcStorage) { todo!() } -} +#[derive(Debug, Clone)] +struct SolanaIbcStorage<'a, 'b>(Rc>>); impl Router for SolanaIbcStorage<'_, '_> { // fn get_route(&self, module_id: &ModuleId) -> Option<&dyn Module> { - match module_id.borrow() { - ibc::applications::transfer::MODULE_ID_STR => { - Some(&self.module_holder) - } + let module_id = core::borrow::Borrow::borrow(module_id); + match module_id { + ibc::applications::transfer::MODULE_ID_STR => Some(self), _ => None, } } @@ -431,15 +298,19 @@ impl Router for SolanaIbcStorage<'_, '_> { &mut self, module_id: &ModuleId, ) -> Option<&mut dyn Module> { - match module_id.borrow() { - ibc::applications::transfer::MODULE_ID_STR => { - Some(&mut self.module_holder) - } + let module_id = core::borrow::Borrow::borrow(module_id); + match module_id { + ibc::applications::transfer::MODULE_ID_STR => Some(self), _ => None, } } // fn lookup_module(&self, port_id: &PortId) -> Option { - self.module_holder.get_module_id(port_id) + match port_id.as_str() { + ibc::applications::transfer::PORT_ID_STR => Some(ModuleId::new( + ibc::applications::transfer::MODULE_ID_STR.to_string(), + )), + _ => None, + } } } diff --git a/solana/solana-ibc/programs/solana-ibc/src/module_holder.rs b/solana/solana-ibc/programs/solana-ibc/src/module_holder.rs deleted file mode 100644 index 391c42a5..00000000 --- a/solana/solana-ibc/programs/solana-ibc/src/module_holder.rs +++ /dev/null @@ -1,22 +0,0 @@ -use anchor_lang::prelude::*; -use ibc::core::ics24_host::identifier::PortId; -use ibc::core::router::ModuleId; - -/// A simple struct for supporting the mutable borrow in `Router::get_route_mut`. -#[derive(Debug, Clone, AnchorSerialize, AnchorDeserialize, PartialEq)] -pub struct ModuleHolder { - pub account: Pubkey, -} - -impl ModuleHolder { - pub fn new(account: Pubkey) -> Self { Self { account } } - /// - pub fn get_module_id(&self, port_id: &PortId) -> Option { - match port_id.as_str() { - ibc::applications::transfer::PORT_ID_STR => Some(ModuleId::new( - ibc::applications::transfer::MODULE_ID_STR.to_string(), - )), - _ => None, - } - } -} diff --git a/solana/solana-ibc/programs/solana-ibc/src/transfer/impls.rs b/solana/solana-ibc/programs/solana-ibc/src/transfer/impls.rs index a643a718..70ab4ffe 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/transfer/impls.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/transfer/impls.rs @@ -4,28 +4,13 @@ use ibc::applications::transfer::context::{ }; use ibc::applications::transfer::error::TokenTransferError; use ibc::applications::transfer::PrefixedCoin; -use ibc::core::ics03_connection::connection::ConnectionEnd; -use ibc::core::ics04_channel::channel::ChannelEnd; -use ibc::core::ics04_channel::commitment::PacketCommitment; -use ibc::core::ics04_channel::context::{ - SendPacketExecutionContext, SendPacketValidationContext, -}; -use ibc::core::ics04_channel::packet::Sequence; -use ibc::core::ics24_host::identifier::{ - ChannelId, ClientId, ConnectionId, PortId, -}; -use ibc::core::ics24_host::path::{ - ChannelEndPath, ClientConsensusStatePath, CommitmentPath, SeqSendPath, -}; -use ibc::core::{ContextError, ExecutionContext, ValidationContext}; +use ibc::core::ics24_host::identifier::{ChannelId, PortId}; use ibc::Signer; -use crate::client_state::AnyClientState; -use crate::consensus_state::AnyConsensusState; -use crate::module_holder::ModuleHolder; -use crate::{SolanaIbcStorage, SolanaIbcStorageHost}; +// use crate::module_holder::SolanaIbcStorage<'_,'_>; +use crate::SolanaIbcStorage; -impl TokenTransferExecutionContext for ModuleHolder { +impl TokenTransferExecutionContext for SolanaIbcStorage<'_, '_> { fn send_coins_execute( &mut self, _from: &Self::AccountId, @@ -71,7 +56,7 @@ impl TokenTransferExecutionContext for ModuleHolder { } } -impl TokenTransferValidationContext for ModuleHolder { +impl TokenTransferValidationContext for SolanaIbcStorage<'_, '_> { type AccountId = Signer; fn get_port(&self) -> Result { @@ -123,104 +108,3 @@ impl TokenTransferValidationContext for ModuleHolder { Ok(()) } } - -impl SendPacketValidationContext for ModuleHolder { - type ClientValidationContext = SolanaIbcStorage<'static, 'static>; - - type E = SolanaIbcStorage<'static, 'static>; - - type AnyConsensusState = AnyConsensusState; - - type AnyClientState = AnyClientState; - - fn channel_end( - &self, - channel_end_path: &ChannelEndPath, - ) -> Result { - let store = Self::get_solana_ibc_store(self.account); - ValidationContext::channel_end(&store, channel_end_path) - } - - fn connection_end( - &self, - connection_id: &ConnectionId, - ) -> Result { - let store = Self::get_solana_ibc_store(self.account); - ValidationContext::connection_end(&store, connection_id) - } - - fn client_state( - &self, - client_id: &ClientId, - ) -> Result { - let store = Self::get_solana_ibc_store(self.account); - ValidationContext::client_state(&store, client_id) - } - - fn client_consensus_state( - &self, - client_cons_state_path: &ClientConsensusStatePath, - ) -> Result { - let store = Self::get_solana_ibc_store(self.account); - ValidationContext::consensus_state(&store, client_cons_state_path) - } - - fn get_next_sequence_send( - &self, - seq_send_path: &SeqSendPath, - ) -> Result { - let store = Self::get_solana_ibc_store(self.account); - ValidationContext::get_next_sequence_send(&store, seq_send_path) - } - - fn get_client_validation_context(&self) -> &Self::ClientValidationContext { - todo!() - } -} - -impl SendPacketExecutionContext for ModuleHolder { - fn store_packet_commitment( - &mut self, - commitment_path: &CommitmentPath, - commitment: PacketCommitment, - ) -> Result<(), ContextError> { - let mut store = Self::get_solana_ibc_store(self.account); - let result = ExecutionContext::store_packet_commitment( - &mut store, - commitment_path, - commitment, - ); - Self::set_solana_ibc_store(&store); - result - } - - fn store_next_sequence_send( - &mut self, - seq_send_path: &SeqSendPath, - seq: Sequence, - ) -> Result<(), ContextError> { - let mut store = Self::get_solana_ibc_store(self.account); - let result = ExecutionContext::store_next_sequence_send( - &mut store, - seq_send_path, - seq, - ); - Self::set_solana_ibc_store(&store); - result - } - - fn emit_ibc_event( - &mut self, - event: ibc::core::events::IbcEvent, - ) -> Result<(), ContextError> { - let mut store = Self::get_solana_ibc_store(self.account); - let result = ExecutionContext::emit_ibc_event(&mut store, event); - Self::set_solana_ibc_store(&store); - result - } - - fn log_message(&mut self, message: String) -> Result<(), ContextError> { - msg!(&message); - Ok(()) - } -} diff --git a/solana/solana-ibc/programs/solana-ibc/src/transfer/mod.rs b/solana/solana-ibc/programs/solana-ibc/src/transfer/mod.rs index 796a1a44..c4ed0dce 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/transfer/mod.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/transfer/mod.rs @@ -13,14 +13,11 @@ use ibc::Signer; use ibc_proto::ibc::apps::transfer::v2::FungibleTokenPacketData; use serde::{Deserialize, Serialize}; -use crate::module_holder::ModuleHolder; -use crate::SolanaIbcStorageHost; +use crate::SolanaIbcStorage; mod impls; -impl SolanaIbcStorageHost for ModuleHolder {} - -impl Module for ModuleHolder { +impl Module for SolanaIbcStorage<'_, '_> { fn on_chan_open_init_validate( &self, order: Order, @@ -257,6 +254,43 @@ impl Module for ModuleHolder { }), ) } + + fn on_chan_open_ack_execute( + &mut self, + _port_id: &PortId, + _channel_id: &ChannelId, + _counterparty_version: &Version, + ) -> Result { + // TODO(#35): Verify port_id is valid. + Ok(ModuleExtras::empty()) + } + + fn on_chan_open_confirm_execute( + &mut self, + _port_id: &PortId, + _channel_id: &ChannelId, + ) -> Result { + // TODO(#35): Verify port_id is valid. + Ok(ModuleExtras::empty()) + } + + fn on_chan_close_init_execute( + &mut self, + _port_id: &PortId, + _channel_id: &ChannelId, + ) -> Result { + // TODO(#35): Verify port_id is valid. + Ok(ModuleExtras::empty()) + } + + fn on_chan_close_confirm_execute( + &mut self, + _port_id: &PortId, + _channel_id: &ChannelId, + ) -> Result { + // TODO(#35): Verify port_id is valid. + Ok(ModuleExtras::empty()) + } } #[derive(Serialize, Deserialize, Clone)] diff --git a/solana/solana-ibc/programs/solana-ibc/src/trie.rs b/solana/solana-ibc/programs/solana-ibc/src/trie.rs index d7598476..2fdb8f74 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/trie.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/trie.rs @@ -14,7 +14,7 @@ type DataRef<'a, 'b> = RefMut<'a, &'b mut [u8]>; const SZ: usize = sealable_trie::nodes::RawNode::SIZE; /// Trie stored in a Solana account. -// #[account] +#[derive(Debug)] pub struct AccountTrie<'a, 'b>( core::mem::ManuallyDrop>>, ); @@ -128,6 +128,7 @@ impl Header { } } +#[derive(Debug)] pub struct Allocator<'a, 'b> { /// Pool of memory to allocate blocks in. /// diff --git a/solana/solana-ibc/programs/solana-ibc/src/validation_context.rs b/solana/solana-ibc/programs/solana-ibc/src/validation_context.rs index e48a0f34..4de0cec9 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/validation_context.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/validation_context.rs @@ -35,7 +35,8 @@ impl ValidationContext for SolanaIbcStorage<'_, '_> { &self, client_id: &ClientId, ) -> std::result::Result { - match self.clients.get(client_id.as_str()) { + let store = self.0.borrow(); + match store.solana_ibc_store.clients.get(client_id.as_str()) { Some(data) => { let client: AnyClientState = serde_json::from_str(data).unwrap(); @@ -64,7 +65,8 @@ impl ValidationContext for SolanaIbcStorage<'_, '_> { client_cons_state_path.client_id.to_string(), (client_cons_state_path.epoch, client_cons_state_path.height), ); - match self.consensus_states.get(consensus_state_key) { + let store = self.0.borrow(); + match store.solana_ibc_store.consensus_states.get(consensus_state_key) { Some(data) => { let result: Self::AnyConsensusState = serde_json::from_str(data).unwrap(); @@ -83,8 +85,12 @@ impl ValidationContext for SolanaIbcStorage<'_, '_> { } fn host_height(&self) -> std::result::Result { - ibc::Height::new(self.height.0, self.height.1) - .map_err(ContextError::ClientError) + let store = self.0.borrow(); + ibc::Height::new( + store.solana_ibc_store.height.0, + store.solana_ibc_store.height.1, + ) + .map_err(ContextError::ClientError) } fn host_timestamp(&self) -> std::result::Result { @@ -105,14 +111,16 @@ impl ValidationContext for SolanaIbcStorage<'_, '_> { } fn client_counter(&self) -> std::result::Result { - Ok(self.client_counter) + let store = self.0.borrow(); + Ok(store.solana_ibc_store.client_counter) } fn connection_end( &self, conn_id: &ConnectionId, ) -> std::result::Result { - match self.connections.get(conn_id.as_str()) { + let store = self.0.borrow(); + match store.solana_ibc_store.connections.get(conn_id.as_str()) { Some(data) => { let connection: ConnectionEnd = serde_json::from_str(data).unwrap(); @@ -144,7 +152,8 @@ impl ValidationContext for SolanaIbcStorage<'_, '_> { } fn connection_counter(&self) -> std::result::Result { - Ok(self.connection_counter) + let store = self.0.borrow(); + Ok(store.solana_ibc_store.connection_counter) } fn channel_end( @@ -153,7 +162,8 @@ impl ValidationContext for SolanaIbcStorage<'_, '_> { ) -> std::result::Result { let channel_end_key = &(channel_end_path.0.to_string(), channel_end_path.1.to_string()); - match self.channel_ends.get(channel_end_key) { + let store = self.0.borrow(); + match store.solana_ibc_store.channel_ends.get(channel_end_key) { Some(data) => { let channel_end: ChannelEnd = serde_json::from_str(data).unwrap(); @@ -215,7 +225,12 @@ impl ValidationContext for SolanaIbcStorage<'_, '_> { commitment_path.port_id.to_string(), commitment_path.channel_id.to_string(), ); - match self.packet_acknowledgement_sequence_sets.get(&commitment_key) { + let store = self.0.borrow(); + match store + .solana_ibc_store + .packet_acknowledgement_sequence_sets + .get(&commitment_key) + { Some(data) => { let data_in_u8: Vec = data.iter().map(|x| *x as u8).collect(); @@ -237,7 +252,12 @@ impl ValidationContext for SolanaIbcStorage<'_, '_> { receipt_path.port_id.to_string(), receipt_path.channel_id.to_string(), ); - match self.packet_acknowledgement_sequence_sets.get(&receipt_key) { + let store = self.0.borrow(); + match store + .solana_ibc_store + .packet_acknowledgement_sequence_sets + .get(&receipt_key) + { Some(data) => { match data.binary_search(&u64::from(receipt_path.sequence)) { Ok(_) => Ok(Receipt::Ok), @@ -262,7 +282,12 @@ impl ValidationContext for SolanaIbcStorage<'_, '_> { ) -> std::result::Result { let ack_key = (ack_path.port_id.to_string(), ack_path.channel_id.to_string()); - match self.packet_acknowledgement_sequence_sets.get(&ack_key) { + let store = self.0.borrow(); + match store + .solana_ibc_store + .packet_acknowledgement_sequence_sets + .get(&ack_key) + { Some(data) => { let data_in_u8: Vec = data.iter().map(|x| *x as u8).collect(); @@ -281,7 +306,10 @@ impl ValidationContext for SolanaIbcStorage<'_, '_> { client_id: &ClientId, height: &Height, ) -> std::result::Result { - self.client_processed_times + let store = self.0.borrow(); + store + .solana_ibc_store + .client_processed_times .get(client_id.as_str()) .and_then(|processed_times| { processed_times @@ -304,7 +332,10 @@ impl ValidationContext for SolanaIbcStorage<'_, '_> { client_id: &ClientId, height: &Height, ) -> std::result::Result { - self.client_processed_heights + let store = self.0.borrow(); + store + .solana_ibc_store + .client_processed_heights .get(client_id.as_str()) .and_then(|processed_heights| { processed_heights @@ -325,7 +356,8 @@ impl ValidationContext for SolanaIbcStorage<'_, '_> { } fn channel_counter(&self) -> std::result::Result { - Ok(self.channel_counter) + let store = self.0.borrow(); + Ok(store.solana_ibc_store.channel_counter) } fn max_expected_time_per_block(&self) -> Duration { @@ -389,7 +421,10 @@ impl SolanaIbcStorage<'_, '_> { ibc::core::ics24_host::identifier::ChannelId, ), > { - self.next_sequence + let store = self.0.borrow(); + store + .solana_ibc_store + .next_sequence .get(&(path.port_id.to_string(), path.channel_id.to_string())) .and_then(|triple| triple.get(index)) .ok_or_else(|| (path.port_id.clone(), path.channel_id.clone()))