Skip to content

Commit

Permalink
added trie key and impl for ser and de
Browse files Browse the repository at this point in the history
  • Loading branch information
dhruvja committed Oct 18, 2023
1 parent b1d7b5f commit c9492ee
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::BTreeMap;

use anchor_lang::emit;
use anchor_lang::prelude::borsh;
use anchor_lang::solana_program::msg;
use ibc::core::events::IbcEvent;
use ibc::core::ics02_client::ClientExecutionContext;
Expand All @@ -26,7 +27,7 @@ use crate::client_state::AnyClientState;
use crate::consensus_state::AnyConsensusState;
use crate::{
EmitIBCEvent, HostHeight, InnerChannelId, InnerHeight, InnerPortId,
InnerSequence, SolanaIbcStorage, SolanaTimestamp,
InnerSequence, SolanaIbcStorage, SolanaTimestamp, TrieKey
};

type Result<T = (), E = ibc::core::ContextError> = core::result::Result<T, E>;
Expand All @@ -49,6 +50,12 @@ 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 client_state_trie_key = &TrieKey::ClientState { client_id: client_state_path.0.to_string() }.to_vec();
let trie = self.trie.as_mut().unwrap();
let client_state_hash = borsh::to_vec(&serialized_client_state).unwrap();
trie.set(&client_state_trie_key, &lib::hash::CryptoHash::digest(&client_state_hash)).unwrap();

self.clients.insert(client_state_key, serialized_client_state);
Ok(())
}
Expand Down
245 changes: 215 additions & 30 deletions solana/solana-ibc/programs/solana-ibc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#![allow(clippy::result_large_err)]

use std::collections::BTreeMap;
use std::mem::size_of;

use anchor_lang::prelude::*;
use borsh::{BorshDeserialize, BorshSerialize};
Expand Down Expand Up @@ -32,6 +33,8 @@ mod magic {
pub(crate) const TRIE_ROOT: u32 = 1;
}



#[anchor_lang::program]
pub mod solana_ibc {
use super::*;
Expand All @@ -42,8 +45,8 @@ pub mod solana_ibc {
) -> Result<()> {
msg!("Called deliver method");
let _sender = ctx.accounts.sender.to_account_info();
let solana_ibc_store: &SolanaIbcStorageTemp =
&ctx.accounts.storage;
let mut solana_ibc_store: &mut SolanaIbcStorageTemp =
&mut ctx.accounts.storage;
msg!("This is solana_ibc_store {:?}", solana_ibc_store);

let all_messages = messages
Expand All @@ -55,7 +58,6 @@ pub mod solana_ibc {
.collect::<Vec<_>>();

msg!("These are messages {:?}", all_messages);


let account = &ctx.accounts.trie;
let mut trie = trie::AccountTrie::new(account.try_borrow_mut_data()?)
Expand All @@ -67,10 +69,16 @@ pub mod solana_ibc {
clients: solana_ibc_store.clients.clone(),
client_id_set: solana_ibc_store.client_id_set.clone(),
client_counter: solana_ibc_store.client_counter.clone(),
client_processed_times: solana_ibc_store.client_processed_times.clone(),
client_processed_heights: solana_ibc_store.client_processed_heights.clone(),
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(),
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.clone(),
connections: solana_ibc_store.connections.clone(),
Expand All @@ -81,11 +89,17 @@ pub mod solana_ibc {
next_sequence_send: solana_ibc_store.next_sequence_send.clone(),
next_sequence_recv: solana_ibc_store.next_sequence_recv.clone(),
next_sequence_ack: solana_ibc_store.next_sequence_ack.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(),
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)
trie: Some(trie),
};

let mut solana_real_storage_another = SolanaIbcStorage {
Expand All @@ -94,10 +108,16 @@ pub mod solana_ibc {
clients: solana_ibc_store.clients.clone(),
client_id_set: solana_ibc_store.client_id_set.clone(),
client_counter: solana_ibc_store.client_counter.clone(),
client_processed_times: solana_ibc_store.client_processed_times.clone(),
client_processed_heights: solana_ibc_store.client_processed_heights.clone(),
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(),
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.clone(),
connections: solana_ibc_store.connections.clone(),
Expand All @@ -108,9 +128,15 @@ pub mod solana_ibc {
next_sequence_send: solana_ibc_store.next_sequence_send.clone(),
next_sequence_recv: solana_ibc_store.next_sequence_recv.clone(),
next_sequence_ack: solana_ibc_store.next_sequence_ack.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(),
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,
};
Expand All @@ -121,8 +147,11 @@ pub mod solana_ibc {
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 solana_real_storage,
router,
msg,
) {
Ok(()) => (),
Err(e) => errors.push(e),
}
Expand All @@ -132,12 +161,59 @@ 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.clone();
solana_ibc_store.client_processed_times =
solana_real_storage.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();
solana_ibc_store.client_consensus_state_height_sets =
solana_real_storage.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.clone();
solana_ibc_store.connections = solana_real_storage.connections.clone();
solana_ibc_store.channel_ends =
solana_real_storage.channel_ends.clone();
solana_ibc_store.connection_to_client =
solana_real_storage.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.clone();
solana_ibc_store.next_sequence_send =
solana_real_storage.next_sequence_send.clone();
solana_ibc_store.next_sequence_recv =
solana_real_storage.next_sequence_recv.clone();
solana_ibc_store.next_sequence_ack =
solana_real_storage.next_sequence_ack.clone();
solana_ibc_store.packet_commitment_sequence_sets =
solana_real_storage.packet_commitment_sequence_sets.clone();
solana_ibc_store.packet_receipt_sequence_sets =
solana_real_storage.packet_receipt_sequence_sets.clone();
solana_ibc_store.packet_acknowledgement_sequence_sets =
solana_real_storage.packet_acknowledgement_sequence_sets.clone();
solana_ibc_store.ibc_events_history =
solana_real_storage.ibc_events_history.clone();

trie = solana_real_storage.trie.unwrap();

msg!("These are errors {:?}", errors);
msg!("This is final structure {:?}", solana_ibc_store);

// msg!("this is length {}", TrieKey::ClientState{ client_id: String::from("hello")}.into());

Ok(())
}

}

#[derive(Accounts)]
Expand All @@ -152,7 +228,125 @@ pub struct Deliver<'info> {
pub system_program: Program<'info, System>,
}

pub struct MyTrie {}
pub enum TrieKey {
ClientState { client_id: String },
ConsensusState { client_id: String, 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 },
}

#[repr(u8)]
pub enum TrieKeyWithoutFields {
ClientState = 1,
ConsensusState = 2,
Connection = 3,
ChannelEnd = 4,
NextSequenceSend = 5,
NextSequenceRecv = 6,
NextSequenceAck = 7,
Commitment = 8,
Receipts = 9,
Acks = 10,
}


impl TrieKey {
pub fn len(&self) -> usize {
size_of::<u8>() + match self {
TrieKey::ClientState { client_id } => client_id.len(),
TrieKey::ConsensusState { client_id, height } => client_id.len() + size_of::<u64>(),
TrieKey::Connection { connection_id } => size_of::<u32>(),
TrieKey::ChannelEnd { port_id, channel_id } => size_of::<u32>() + size_of::<u32>(),
TrieKey::NextSequenceSend { port_id, channel_id } => size_of::<u32>() + size_of::<u32>(),
TrieKey::NextSequenceRecv { port_id, channel_id } => size_of::<u32>() + size_of::<u32>(),
TrieKey::NextSequenceAck { port_id, channel_id } => size_of::<u32>() + size_of::<u32>(),
TrieKey::Commitment { port_id, channel_id, sequence } => size_of::<u32>() + size_of::<u32>() + size_of::<u64>(),
TrieKey::Receipts { port_id, channel_id, sequence } => size_of::<u32>() + size_of::<u32>()+ size_of::<u64>(),
TrieKey::Acks { port_id, channel_id, sequence } => size_of::<u32>() + size_of::<u32>()+ size_of::<u64>(),
}
}

pub fn append_into(&self, buf: &mut Vec<u8>) {
let expected_len = self.len();
let start_len = buf.len();
buf.reserve(self.len());
match self {
TrieKey::ClientState { client_id } => {
buf.push(TrieKeyWithoutFields::ClientState as u8);
buf.extend(client_id.as_bytes());
},
TrieKey::ConsensusState { client_id, height } => {
buf.push(TrieKeyWithoutFields::ConsensusState as u8);
buf.extend(height.to_be_bytes())
},
TrieKey::Connection { connection_id } => {
buf.push(TrieKeyWithoutFields::Connection as u8);
buf.extend(connection_id.to_be_bytes())
},
TrieKey::ChannelEnd { port_id, channel_id } => {
buf.push(TrieKeyWithoutFields::ChannelEnd as u8);
buf.extend(port_id.to_be_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.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.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.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.push(TrieKeyWithoutFields::Commitment as u8);
buf.extend(channel_id.to_be_bytes());
buf.push(TrieKeyWithoutFields::Commitment as u8);
buf.extend(sequence.to_be_bytes());
},
TrieKey::Receipts { port_id, channel_id, sequence } => {
buf.push(TrieKeyWithoutFields::Receipts as u8);
buf.extend(port_id.to_be_bytes());
buf.push(TrieKeyWithoutFields::Receipts as u8);
buf.extend(channel_id.to_be_bytes());
buf.push(TrieKeyWithoutFields::Receipts as u8);
buf.extend(sequence.to_be_bytes());
},
TrieKey::Acks { port_id, channel_id, sequence } => {
buf.push(TrieKeyWithoutFields::Acks as u8);
buf.extend(port_id.to_be_bytes());
buf.push(TrieKeyWithoutFields::Acks as u8);
buf.extend(channel_id.to_be_bytes());
buf.push(TrieKeyWithoutFields::Acks as u8);
buf.extend(sequence.to_be_bytes());
},
}
debug_assert_eq!(expected_len, buf.len() - start_len);
}

pub fn to_vec(&self) -> Vec<u8> {
let mut buf = Vec::with_capacity(self.len());
self.append_into(&mut buf);
buf
}
}

#[event]
pub struct EmitIBCEvent {
Expand All @@ -179,15 +373,6 @@ pub type InnerConnectionEnd = String; // Serialized
pub type InnerChannelEnd = String; // Serialized
pub type InnerConsensusState = String; // Serialized

// #[derive(Debug, Clone, AnchorSerialize, AnchorDeserialize, PartialEq)]
// pub struct InnerHeight {
// /// Previously known as "epoch"
// revision_number: u64,

// /// The height of a block
// revision_height: u64,
// }

#[account]
#[derive(Debug)]
/// All the structs from IBC are stored as String since they dont implement AnchorSerialize and AnchorDeserialize
Expand Down Expand Up @@ -327,4 +512,4 @@ impl Router for SolanaIbcStorage<'_, '_> {
fn lookup_module(&self, port_id: &PortId) -> Option<ModuleId> {
self.module_holder.get_module_id(port_id)
}
}
}
11 changes: 6 additions & 5 deletions solana/solana-ibc/programs/solana-ibc/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ use ibc::mock::header::MockHeader;
use ibc::Any;
use ibc_proto::protobuf::Protobuf;

use crate::trie::AccountTrie;
use crate::{
accounts, instruction, AnyCheck, SolanaIbcStorage, ID,
SOLANA_IBC_STORAGE_SEED, TEST_TRIE_SEED,
SOLANA_IBC_STORAGE_SEED, TEST_TRIE_SEED, SolanaIbcStorageTemp,
};

const TYPE_URL: &str = "/ibc.core.client.v1.MsgCreateClient";
Expand Down Expand Up @@ -99,11 +100,11 @@ fn anchor_test_deliver() -> Result<()> {

println!("demo sig: {sig}");

// // Retrieve and validate state
// let solana_ibc_storage_account: SolanaIbcStorage =
// program.account(solana_ibc_storage).unwrap();
// Retrieve and validate state
let solana_ibc_storage_account: SolanaIbcStorageTemp =
program.account(solana_ibc_storage).unwrap();

// println!("This is solana storage account {:?}", solana_ibc_storage_account);
println!("This is solana storage account {:?}", solana_ibc_storage_account);

Ok(())
}
Expand Down

0 comments on commit c9492ee

Please sign in to comment.