From e9e18ae8e7276ec9bf7a820d254470292e177359 Mon Sep 17 00:00:00 2001 From: dhruvja Date: Wed, 18 Oct 2023 18:31:08 +0530 Subject: [PATCH] storing data in trie in execution context --- .../solana-ibc/src/execution_context.rs | 153 +++++++++++++++++- .../solana-ibc/programs/solana-ibc/src/lib.rs | 56 ++++--- 2 files changed, 181 insertions(+), 28 deletions(-) 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 7be79cad..034717fe 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/execution_context.rs @@ -32,6 +32,12 @@ use crate::{ type Result = core::result::Result; +const CONNECTION_ID_PREFIX: &str = "connection-"; +const CHANNEL_ID_PREFIX: &str = "channel-"; + +const DEFAULT_PORT_ID: &str = "defaultPort"; +const TRANSFER_PORT_ID: &str = "transfer"; + impl ClientExecutionContext for SolanaIbcStorage<'_, '_> { type ClientValidationContext = Self; type AnyClientState = AnyClientState; @@ -84,6 +90,21 @@ impl ClientExecutionContext for SolanaIbcStorage<'_, '_> { ); let serialized_consensus_state = serde_json::to_string(&consensus_state).unwrap(); + + let consensus_state_trie_key = &TrieKey::ConsensusState { + client_id: consensus_state_path.client_id.to_string(), + height: consensus_state_path.height, + epoch: consensus_state_path.epoch, + }.to_vec(); + let trie = self.trie.as_mut().unwrap(); + let consensus_state_hash = + borsh::to_vec(&serialized_consensus_state).unwrap(); + trie.set( + &consensus_state_trie_key, + &lib::hash::CryptoHash::digest(&consensus_state_hash), + ) + .unwrap(); + self.consensus_states .insert(consensus_state_key, serialized_consensus_state); self.height.0 = consensus_state_path.epoch; @@ -183,9 +204,26 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { connection_path, connection_end ); + + let serialized_connection_end = + serde_json::to_string(&connection_end).unwrap(); + let connection_prefix_length = CONNECTION_ID_PREFIX.len(); + let connection_id = &connection_path.0.to_string()[connection_prefix_length..]; + let consensus_state_trie_key = &TrieKey::Connection { + connection_id: connection_id.parse().unwrap(), + }.to_vec(); + let trie = self.trie.as_mut().unwrap(); + let consensus_state_hash = + borsh::to_vec(&serialized_connection_end).unwrap(); + trie.set( + &consensus_state_trie_key, + &lib::hash::CryptoHash::digest(&consensus_state_hash), + ) + .unwrap(); + self.connections.insert( connection_path.0.to_string(), - serde_json::to_string(&connection_end).unwrap(), + serialized_connection_end ); Ok(()) } @@ -224,6 +262,21 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { commitment_path, commitment ); + let channel_prefix_length = CHANNEL_ID_PREFIX.len(); + let channel_id = &commitment_path.channel_id.to_string()[channel_prefix_length..]; + + let commitment_trie_key = &TrieKey::Commitment { + port_id: commitment_path.port_id.clone().to_string(), + channel_id: channel_id.parse().unwrap(), + sequence: u64::from(commitment_path.sequence) + }.to_vec(); + let trie = self.trie.as_mut().unwrap(); + trie.set( + &commitment_trie_key, + &lib::hash::CryptoHash::digest(&commitment.into_vec()), + ) + .unwrap(); + record_packet_sequence( &mut self.packet_commitment_sequence_sets, &commitment_path.port_id, @@ -262,6 +315,19 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { receipt_path, receipt ); + let channel_prefix_length = CHANNEL_ID_PREFIX.len(); + let channel_id = &receipt_path.channel_id.to_string()[channel_prefix_length..]; + + let receipt_trie_key = &TrieKey::Receipts { + port_id: receipt_path.port_id.clone().to_string(), + channel_id: channel_id.parse().unwrap(), + sequence: u64::from(receipt_path.sequence) + }.to_vec(); + let trie = self.trie.as_mut().unwrap(); + trie.set( + &receipt_trie_key, + &lib::hash::CryptoHash::DEFAULT, + ).unwrap(); record_packet_sequence( &mut self.packet_receipt_sequence_sets, &receipt_path.port_id, @@ -281,6 +347,20 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { ack_path, ack_commitment ); + let channel_prefix_length = CHANNEL_ID_PREFIX.len(); + let channel_id = &ack_path.channel_id.to_string()[channel_prefix_length..]; + + let ack_commitment_trie_key = &TrieKey::Acks { + port_id: ack_path.port_id.clone().to_string(), + channel_id: channel_id.parse().unwrap(), + sequence: u64::from(ack_path.sequence) + }.to_vec(); + let trie = self.trie.as_mut().unwrap(); + trie.set( + &ack_commitment_trie_key, + &lib::hash::CryptoHash::digest(&ack_commitment.into_vec()), + ) + .unwrap(); record_packet_sequence( &mut self.packet_acknowledgement_sequence_sets, &ack_path.port_id, @@ -317,6 +397,25 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { channel_end_path.0.clone().to_string(), channel_end_path.1.clone().to_string(), )); + + let serialized_channel_end = + serde_json::to_string(&channel_end).unwrap(); + let channel_prefix_length = CHANNEL_ID_PREFIX.len(); + let channel_id = &channel_end_path.1.to_string()[channel_prefix_length..]; + + let channel_end_trie_key = &TrieKey::ChannelEnd { + port_id: channel_end_path.0.clone().to_string(), + channel_id: channel_id.parse().unwrap(), + }.to_vec(); + let trie = self.trie.as_mut().unwrap(); + let channel_end_hash = + borsh::to_vec(&serialized_channel_end).unwrap(); + trie.set( + &channel_end_trie_key, + &lib::hash::CryptoHash::digest(&channel_end_hash), + ) + .unwrap(); + self.channel_ends.insert( (channel_end_path.0.to_string(), channel_end_path.1.to_string()), serde_json::to_string(&channel_end).unwrap(), @@ -336,6 +435,24 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { ); let seq_send_key = (seq_send_path.0.to_string(), seq_send_path.1.to_string()); + + let channel_prefix_length = CHANNEL_ID_PREFIX.len(); + let channel_id = &seq_send_path.1.to_string()[channel_prefix_length..]; + + let next_seq_send_trie_key = &TrieKey::NextSequenceSend { + port_id: seq_send_path.0.clone().to_string(), + channel_id: channel_id.parse().unwrap(), + }.to_vec(); + let trie = self.trie.as_mut().unwrap(); + let seq_in_u64: u64 = seq.into(); + let seq_in_bytes = seq_in_u64.to_be_bytes(); + + trie.set( + &next_seq_send_trie_key, + &lib::hash::CryptoHash::digest(&seq_in_bytes), + ) + .unwrap(); + self.next_sequence_send.insert(seq_send_key, u64::from(seq)); Ok(()) } @@ -351,7 +468,23 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { seq ); let seq_recv_key = - (seq_recv_path.0.to_string(), seq_recv_path.1.to_string()); + (seq_recv_path.0.to_string(), seq_recv_path.1.to_string()); + let channel_prefix_length = CHANNEL_ID_PREFIX.len(); + let channel_id = &seq_recv_path.1.to_string()[channel_prefix_length..]; + + let next_seq_recv_trie_key = &TrieKey::NextSequenceRecv { + port_id: seq_recv_path.0.clone().to_string(), + channel_id: channel_id.parse().unwrap(), + }.to_vec(); + let trie = self.trie.as_mut().unwrap(); + let seq_in_u64: u64 = seq.into(); + let seq_in_bytes = seq_in_u64.to_be_bytes(); + + trie.set( + &next_seq_recv_trie_key, + &lib::hash::CryptoHash::digest(&seq_in_bytes), + ) + .unwrap(); self.next_sequence_recv.insert(seq_recv_key, u64::from(seq)); Ok(()) } @@ -364,6 +497,22 @@ impl ExecutionContext for SolanaIbcStorage<'_, '_> { msg!("store_next_sequence_ack: path: {}, seq: {:?}", seq_ack_path, seq); let seq_ack_key = (seq_ack_path.0.to_string(), seq_ack_path.1.to_string()); + let channel_prefix_length = CHANNEL_ID_PREFIX.len(); + let channel_id = &seq_ack_path.1.to_string()[channel_prefix_length..]; + + let next_seq_ack_trie_key = &TrieKey::NextSequenceAck { + port_id: seq_ack_path.0.clone().to_string(), + channel_id: channel_id.parse().unwrap(), + }.to_vec(); + let trie = self.trie.as_mut().unwrap(); + let seq_in_u64: u64 = seq.into(); + let seq_in_bytes = seq_in_u64.to_be_bytes(); + + trie.set( + &next_seq_ack_trie_key, + &lib::hash::CryptoHash::digest(&seq_in_bytes), + ) + .unwrap(); self.next_sequence_ack.insert(seq_ack_key, u64::from(seq)); Ok(()) } diff --git a/solana/solana-ibc/programs/solana-ibc/src/lib.rs b/solana/solana-ibc/programs/solana-ibc/src/lib.rs index e20b1543..87217864 100644 --- a/solana/solana-ibc/programs/solana-ibc/src/lib.rs +++ b/solana/solana-ibc/programs/solana-ibc/src/lib.rs @@ -230,15 +230,15 @@ pub struct Deliver<'info> { pub enum TrieKey { ClientState { client_id: String }, - ConsensusState { client_id: String, height: u64 }, + ConsensusState { client_id: String, epoch: u64, height: u64 }, Connection { connection_id: u32 }, - ChannelEnd { port_id: u32, channel_id: u32 }, - NextSequenceSend { port_id: u32, channel_id: u32 }, - NextSequenceRecv { port_id: u32, channel_id: u32 }, - NextSequenceAck { port_id: u32, channel_id: u32 }, - Commitment { port_id: u32, channel_id: u32, sequence: u64 }, - Receipts { port_id: u32, channel_id: u32, sequence: u64 }, - Acks { port_id: u32, channel_id: u32, sequence: u64 }, + ChannelEnd { port_id: String, channel_id: u32 }, + NextSequenceSend { port_id: String, channel_id: u32 }, + NextSequenceRecv { port_id: String, channel_id: u32 }, + NextSequenceAck { port_id: String, channel_id: u32 }, + Commitment { port_id: String, channel_id: u32, sequence: u64 }, + Receipts { port_id: String, channel_id: u32, sequence: u64 }, + Acks { port_id: String, channel_id: u32, sequence: u64 }, } #[repr(u8)] @@ -261,30 +261,30 @@ impl TrieKey { size_of::() + match self { TrieKey::ClientState { client_id } => client_id.len(), - TrieKey::ConsensusState { client_id, height } => { - client_id.len() + size_of::() + TrieKey::ConsensusState { client_id, epoch: u64, height } => { + client_id.len() + size_of::() + size_of::() } TrieKey::Connection { connection_id } => size_of::(), TrieKey::ChannelEnd { port_id, channel_id } => { - size_of::() + size_of::() + port_id.len() + size_of::() } TrieKey::NextSequenceSend { port_id, channel_id } => { - size_of::() + size_of::() + port_id.len() + size_of::() } TrieKey::NextSequenceRecv { port_id, channel_id } => { - size_of::() + size_of::() + port_id.len() + size_of::() } TrieKey::NextSequenceAck { port_id, channel_id } => { - size_of::() + size_of::() + port_id.len() + size_of::() } TrieKey::Commitment { port_id, channel_id, sequence } => { - size_of::() + size_of::() + size_of::() + port_id.len() + size_of::() + size_of::() } TrieKey::Receipts { port_id, channel_id, sequence } => { - size_of::() + size_of::() + size_of::() + port_id.len() + size_of::() + size_of::() } TrieKey::Acks { port_id, channel_id, sequence } => { - size_of::() + size_of::() + size_of::() + port_id.len() + size_of::() + size_of::() } } } @@ -298,9 +298,13 @@ impl TrieKey { buf.push(TrieKeyWithoutFields::ClientState as u8); buf.extend(client_id.as_bytes()); } - TrieKey::ConsensusState { client_id, height } => { + TrieKey::ConsensusState { client_id, epoch, height } => { buf.push(TrieKeyWithoutFields::ConsensusState as u8); - buf.extend(height.to_be_bytes()) + buf.extend(client_id.as_bytes()); + buf.push(TrieKeyWithoutFields::ConsensusState as u8); + buf.extend(height.to_be_bytes()); + buf.push(TrieKeyWithoutFields::ConsensusState as u8); + buf.extend(epoch.to_be_bytes()) } TrieKey::Connection { connection_id } => { buf.push(TrieKeyWithoutFields::Connection as u8); @@ -308,31 +312,31 @@ impl TrieKey { } TrieKey::ChannelEnd { port_id, channel_id } => { buf.push(TrieKeyWithoutFields::ChannelEnd as u8); - buf.extend(port_id.to_be_bytes()); + buf.extend(port_id.as_bytes()); buf.push(TrieKeyWithoutFields::ChannelEnd as u8); buf.extend(channel_id.to_be_bytes()); } TrieKey::NextSequenceSend { port_id, channel_id } => { buf.push(TrieKeyWithoutFields::NextSequenceSend as u8); - buf.extend(port_id.to_be_bytes()); + buf.extend(port_id.as_bytes()); buf.push(TrieKeyWithoutFields::NextSequenceSend as u8); buf.extend(channel_id.to_be_bytes()); } TrieKey::NextSequenceRecv { port_id, channel_id } => { buf.push(TrieKeyWithoutFields::NextSequenceRecv as u8); - buf.extend(port_id.to_be_bytes()); + buf.extend(port_id.as_bytes()); buf.push(TrieKeyWithoutFields::NextSequenceRecv as u8); buf.extend(channel_id.to_be_bytes()); } TrieKey::NextSequenceAck { port_id, channel_id } => { buf.push(TrieKeyWithoutFields::NextSequenceAck as u8); - buf.extend(port_id.to_be_bytes()); + buf.extend(port_id.as_bytes()); buf.push(TrieKeyWithoutFields::NextSequenceAck as u8); buf.extend(channel_id.to_be_bytes()); } TrieKey::Commitment { port_id, channel_id, sequence } => { buf.push(TrieKeyWithoutFields::Commitment as u8); - buf.extend(port_id.to_be_bytes()); + buf.extend(port_id.as_bytes()); buf.push(TrieKeyWithoutFields::Commitment as u8); buf.extend(channel_id.to_be_bytes()); buf.push(TrieKeyWithoutFields::Commitment as u8); @@ -340,7 +344,7 @@ impl TrieKey { } TrieKey::Receipts { port_id, channel_id, sequence } => { buf.push(TrieKeyWithoutFields::Receipts as u8); - buf.extend(port_id.to_be_bytes()); + buf.extend(port_id.as_bytes()); buf.push(TrieKeyWithoutFields::Receipts as u8); buf.extend(channel_id.to_be_bytes()); buf.push(TrieKeyWithoutFields::Receipts as u8); @@ -348,7 +352,7 @@ impl TrieKey { } TrieKey::Acks { port_id, channel_id, sequence } => { buf.push(TrieKeyWithoutFields::Acks as u8); - buf.extend(port_id.to_be_bytes()); + buf.extend(port_id.as_bytes()); buf.push(TrieKeyWithoutFields::Acks as u8); buf.extend(channel_id.to_be_bytes()); buf.push(TrieKeyWithoutFields::Acks as u8);