The home for Hyperlane core contracts, sdk packages, and other infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
hyperlane-monorepo/rust/sealevel/programs/mailbox-test/src/utils.rs

202 lines
6.3 KiB

use hyperlane_core::{Encode, HyperlaneMessage, H256};
use solana_program::{
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
system_program,
};
use solana_program_test::*;
use solana_sdk::{
signature::{Signature, Signer},
signer::keypair::Keypair,
transaction::Transaction,
};
use hyperlane_sealevel_mailbox::{
accounts::{
DispatchedMessage, DispatchedMessageAccount, Inbox, InboxAccount, Outbox, OutboxAccount,
ProcessedMessage, ProcessedMessageAccount,
},
instruction::{Instruction as MailboxInstruction, OutboxDispatch},
mailbox_dispatched_message_pda_seeds, mailbox_processed_message_pda_seeds,
};
use hyperlane_test_utils::MailboxAccounts;
pub async fn dispatch_from_payer(
banks_client: &mut BanksClient,
payer: &Keypair,
mailbox_accounts: &MailboxAccounts,
outbox_dispatch: OutboxDispatch,
) -> Result<(Signature, Keypair, Pubkey), BanksClientError> {
let unique_message_account_keypair = Keypair::new();
let (dispatched_message_account_key, _dispatched_message_bump) = Pubkey::find_program_address(
mailbox_dispatched_message_pda_seeds!(&unique_message_account_keypair.pubkey()),
&mailbox_accounts.program,
);
let instruction = Instruction {
program_id: mailbox_accounts.program,
data: MailboxInstruction::OutboxDispatch(outbox_dispatch)
.into_instruction_data()
.unwrap(),
accounts: vec![
// 0. [writeable] Outbox PDA.
// 1. [signer] Message sender signer.
// 2. [executable] System program.
// 3. [executable] SPL Noop program.
// 4. [signer] Payer.
// 5. [signer] Unique message account.
// 6. [writeable] Dispatched message PDA. An empty message PDA relating to the seeds
// `mailbox_dispatched_message_pda_seeds` where the message contents will be stored.
AccountMeta::new(mailbox_accounts.outbox, false),
AccountMeta::new(payer.pubkey(), true),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(spl_noop::id(), false),
AccountMeta::new(payer.pubkey(), true),
AccountMeta::new(unique_message_account_keypair.pubkey(), true),
AccountMeta::new(dispatched_message_account_key, false),
],
};
let recent_blockhash = banks_client.get_latest_blockhash().await.unwrap();
let transaction = Transaction::new_signed_with_payer(
&[instruction],
Some(&payer.pubkey()),
&[payer, &unique_message_account_keypair],
recent_blockhash,
);
let tx_signature = transaction.signatures[0];
banks_client.process_transaction(transaction).await?;
Ok((
tx_signature,
unique_message_account_keypair,
dispatched_message_account_key,
))
}
pub async fn assert_dispatched_message(
banks_client: &mut BanksClient,
dispatch_tx_signature: Signature,
dispatch_unique_account_pubkey: Pubkey,
dispatched_message_account_key: Pubkey,
expected_message: &HyperlaneMessage,
) {
// Get the slot of the tx
let dispatch_tx_status = banks_client
.get_transaction_status(dispatch_tx_signature)
.await
.unwrap()
.unwrap();
let dispatch_slot = dispatch_tx_status.slot;
// Get the dispatched message account
let dispatched_message_account = banks_client
.get_account(dispatched_message_account_key)
.await
.unwrap()
.unwrap();
let dispatched_message =
DispatchedMessageAccount::fetch(&mut &dispatched_message_account.data[..])
.unwrap()
.into_inner();
assert_eq!(
*dispatched_message,
DispatchedMessage::new(
expected_message.nonce,
dispatch_slot,
dispatch_unique_account_pubkey,
expected_message.to_vec(),
),
);
}
pub async fn assert_outbox(
banks_client: &mut BanksClient,
outbox_pubkey: Pubkey,
expected_outbox: Outbox,
) {
// Check that the outbox account was updated.
let outbox_account = banks_client
.get_account(outbox_pubkey)
.await
.unwrap()
.unwrap();
let outbox = OutboxAccount::fetch(&mut &outbox_account.data[..])
.unwrap()
.into_inner();
assert_eq!(*outbox, expected_outbox,);
}
pub async fn assert_inbox(
banks_client: &mut BanksClient,
inbox_pubkey: Pubkey,
expected_inbox: Inbox,
) {
// Check that the inbox account was updated.
let inbox_account = banks_client
.get_account(inbox_pubkey)
.await
.unwrap()
.unwrap();
let inbox = InboxAccount::fetch(&mut &inbox_account.data[..])
.unwrap()
.into_inner();
assert_eq!(*inbox, expected_inbox,);
}
pub async fn assert_processed_message(
banks_client: &mut BanksClient,
process_tx_signature: Signature,
processed_message_account_key: Pubkey,
expected_message: &HyperlaneMessage,
expected_sequence: u64,
) {
// Get the slot of the tx
let process_tx_status = banks_client
.get_transaction_status(process_tx_signature)
.await
.unwrap()
.unwrap();
let process_slot = process_tx_status.slot;
// Get the processed message account
let processed_message_account = banks_client
.get_account(processed_message_account_key)
.await
.unwrap()
.unwrap();
let processed_message =
ProcessedMessageAccount::fetch(&mut &processed_message_account.data[..])
.unwrap()
.into_inner();
assert_eq!(
*processed_message,
ProcessedMessage::new(expected_sequence, expected_message.id(), process_slot,),
);
}
pub async fn assert_message_not_processed(
banks_client: &mut BanksClient,
mailbox_accounts: &MailboxAccounts,
message_id: H256,
) {
let (processed_message_account_key, _processed_message_account_bump) =
Pubkey::find_program_address(
mailbox_processed_message_pda_seeds!(&message_id),
&mailbox_accounts.program,
);
// Get the processed message account
let processed_message_account = banks_client
.get_account(processed_message_account_key)
.await
.unwrap();
assert!(processed_message_account.is_none());
}