Skip to content

Commit

Permalink
solana-ibc: added send_packet method (#132)
Browse files Browse the repository at this point in the history
Allows us to send packets given that we already have the client,
connection and channels set up. This is different from
send_transfer and no transfer takes place in this method. It
accepts a packet and stores it.

This method was added in IBC v0.30.0

* added send_packet method

* better retuning error

* merged with master

* merged with master

* fmt

* added tests

* fmt
  • Loading branch information
dhruvja authored Nov 29, 2023
1 parent 6b303a1 commit 05c9a38
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 8 deletions.
49 changes: 49 additions & 0 deletions solana/solana-ibc/programs/solana-ibc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,32 @@ pub mod solana_ibc {
#[cfg(not(feature = "mocks"))]
panic!("This method is only for mocks");
}

/// Should be called after setting up client, connection and channels.
pub fn send_packet(
ctx: Context<SendPacket>,
packet: ibc::Packet,
) -> Result<()> {
let private: &mut storage::PrivateStorage = &mut ctx.accounts.storage;
let provable = storage::get_provable_from(&ctx.accounts.trie, "trie")?;
let host_head = host::Head::get()?;

// Before anything else, try generating a new guest block. However, if
// that fails it’s not an error condition. We do this at the beginning
// of any request.
ctx.accounts.chain.maybe_generate_block(&provable, Some(host_head))?;

let mut store = storage::IbcStorage::new(storage::IbcStorageInner {
private,
provable,
accounts: Vec::new(), // We are not doing any transfers so no point of having accounts
host_head,
});

::ibc::core::channel::handler::send_packet(&mut store, packet)
.map_err(error::Error::ContextError)
.map_err(|err| error!((&err)))
}
}

#[derive(Accounts)]
Expand Down Expand Up @@ -283,6 +309,29 @@ pub struct MockDeliver<'info> {
system_program: Program<'info, System>,
}

/// Has the same structure as `Deliver` though we expect for accounts to be already initialized here.
#[derive(Accounts)]
pub struct SendPacket<'info> {
#[account(mut)]
sender: Signer<'info>,

/// The account holding private IBC storage.
#[account(mut, seeds = [SOLANA_IBC_STORAGE_SEED], bump)]
storage: Account<'info, storage::PrivateStorage>,

/// The account holding provable IBC storage, i.e. the trie.
///
/// CHECK: Account’s owner is checked by [`storage::get_provable_from`]
/// function.
#[account(mut, seeds = [TRIE_SEED], bump)]
trie: UncheckedAccount<'info>,

/// The guest blockchain data.
#[account(mut, seeds = [CHAIN_SEED], bump)]
chain: Box<Account<'info, chain::ChainData>>,
system_program: Program<'info, System>,
}

impl ibc::Router for storage::IbcStorage<'_, '_, '_> {
//
fn get_route(&self, module_id: &ibc::ModuleId) -> Option<&dyn ibc::Module> {
Expand Down
18 changes: 12 additions & 6 deletions solana/solana-ibc/programs/solana-ibc/src/mocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,21 @@ pub fn mock_deliver_impl(
)
.unwrap();

let counterparty = ibc::chan::Counterparty::new(
let channel_id_on_a = ibc::ChannelId::new(0);
let channel_id_on_b = ibc::ChannelId::new(1);
let counterparty_for_a = ibc::chan::Counterparty::new(
port_id.clone(),
Some(channel_id_on_b.clone()),
);
let counterparty_for_b = ibc::chan::Counterparty::new(
port_id.clone(),
Some(ibc::ChannelId::new(0)),
Some(channel_id_on_a.clone()),
);

let channel_end_on_a = ibc::ChannelEnd::new(
ibc::chan::State::Open,
ibc::chan::Order::Unordered,
counterparty.clone(),
counterparty_for_a.clone(),
vec![connection_id_on_a.clone()],
ibc::chan::Version::new(
ibc::apps::transfer::types::VERSION.to_string(),
Expand All @@ -96,15 +103,14 @@ pub fn mock_deliver_impl(
let channel_end_on_b = ibc::ChannelEnd::new(
ibc::chan::State::Open,
ibc::chan::Order::Unordered,
counterparty,
counterparty_for_b.clone(),
vec![connection_id_on_b.clone()],
ibc::chan::Version::new(
ibc::apps::transfer::types::VERSION.to_string(),
),
)
.unwrap();
let channel_id_on_a = ibc::ChannelId::new(0);
let channel_id_on_b = ibc::ChannelId::new(1);


// For Client on Chain A
store
Expand Down
40 changes: 38 additions & 2 deletions solana/solana-ibc/programs/solana-ibc/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,8 +449,8 @@ fn anchor_test_deliver() -> Result<()> {
let packet = construct_packet_from_denom(
port_id.clone(),
channel_id_on_b.clone(),
channel_id_on_a,
channel_id_on_b,
channel_id_on_a.clone(),
channel_id_on_b.clone(),
2,
sender_token_address,
receiver_token_address,
Expand Down Expand Up @@ -506,6 +506,42 @@ fn anchor_test_deliver() -> Result<()> {
TRANSFER_AMOUNT
);

/*
*
* Send Packets
*
*/

let packet = construct_packet_from_denom(
port_id.clone(),
channel_id_on_a.clone(),
channel_id_on_a.clone(),
channel_id_on_b.clone(),
1,
sender_token_address,
receiver_token_address,
String::from("Just a packet"),
);

let sig = program
.request()
.accounts(accounts::SendPacket {
sender: authority.pubkey(),
storage,
trie,
chain: chain.clone(),
system_program: system_program::ID,
})
.args(instruction::SendPacket { packet })
.payer(authority.clone())
.signer(&*authority)
.send_with_spinner_and_config(RpcSendTransactionConfig {
skip_preflight: true,
..RpcSendTransactionConfig::default()
})?; // ? gives us the log messages on the why the tx did fail ( better than unwrap )

println!("signature for sending packet: {sig}");

Ok(())
}

Expand Down

0 comments on commit 05c9a38

Please sign in to comment.