[message-buffer 14/x] - Message buffer/zero copy fixes (#811)

* test(message-buffer): add rust integration tests

add rust-toolchain.toml to pin rust version, add integration tests, update cpi caller auth seeds

* refactor(message-buffer): remove unused test ix

* chore(message-buffer): clean up

* refactor(message-buffer): simple refactor

* test(message-buffer): refactor integration test structure

* refactor(message-buffer): rename

* fix(message-buffer): fix min size check when shrinking msg buffer

* chore(message-buffer): cleanup

* fix(message-buffer): resize borrow bug fix

* test(message-buffer): refactor test util methods into MessageBufferTestContext for less duplication

* test(message-buffer): resolve merge conflicts from repo restructure

* chore(message-buffer): delete commented out code

* feat(message-buffer): use AccountLoader for zero-copy for resize/delete & put_all

* chore(message-buffer): clean up

* style(message-buffer): clean up

* fix(message-buffer): address PR feedback

revert to old put_all impl of using bytemuck for deserializing header, update tests add back old
check

* chore(message-buffer): clean up
This commit is contained in:
swimricky 2023-05-09 17:18:40 -04:00 committed by GitHub
parent 2e32a22725
commit 78d3c5c4ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 273 additions and 260 deletions

View File

@ -76,7 +76,6 @@ pub fn create_buffer<'info>(
}
loader.exit(&crate::ID)?;
} else {
// FIXME: change this to be emit!(Event)
msg!("Buffer account already initialized");
}

View File

@ -1,51 +1,21 @@
use {
crate::{
state::*,
MessageBufferError,
MESSAGE,
},
crate::state::*,
anchor_lang::prelude::*,
};
pub fn delete_buffer<'info>(
ctx: Context<'_, '_, '_, 'info, DeleteBuffer<'info>>,
allowed_program_auth: Pubkey,
base_account_key: Pubkey,
bump: u8,
_base_account_key: Pubkey,
) -> Result<()> {
let message_buffer_account_info = ctx
.remaining_accounts
.first()
.ok_or(MessageBufferError::MessageBufferNotProvided)?;
ctx.accounts
.whitelist
.is_allowed_program_auth(&allowed_program_auth)?;
MessageBuffer::check_discriminator(message_buffer_account_info)?;
let expected_key = Pubkey::create_program_address(
&[
allowed_program_auth.as_ref(),
MESSAGE.as_bytes(),
base_account_key.as_ref(),
&[bump],
],
&crate::ID,
)
.map_err(|_| MessageBufferError::InvalidPDA)?;
require_keys_eq!(
message_buffer_account_info.key(),
expected_key,
MessageBufferError::InvalidPDA
);
let loader = AccountLoader::<MessageBuffer>::try_from(message_buffer_account_info)?;
loader.close(ctx.accounts.admin.to_account_info())?;
Ok(())
}
#[derive(Accounts)]
#[instruction(allowed_program_auth: Pubkey, base_account_key: Pubkey)]
pub struct DeleteBuffer<'info> {
#[account(
seeds = [b"message".as_ref(), b"whitelist".as_ref()],
@ -57,5 +27,12 @@ pub struct DeleteBuffer<'info> {
// Also the recipient of the lamports from closing the buffer account
#[account(mut)]
pub admin: Signer<'info>,
// remaining_account: - [AccumulatorInput PDA]
#[account(
mut,
close = admin,
seeds = [allowed_program_auth.as_ref(), b"message".as_ref(), base_account_key.as_ref()],
bump = message_buffer.load()?.bump,
)]
pub message_buffer: AccountLoader<'info, MessageBuffer>,
}

View File

@ -1,53 +1,40 @@
use {
crate::{
state::*,
MessageBufferError,
},
crate::state::*,
anchor_lang::prelude::*,
std::mem,
};
pub fn put_all<'info>(
ctx: Context<'_, '_, '_, 'info, PutAll<'info>>,
base_account_key: Pubkey,
_base_account_key: Pubkey,
messages: Vec<Vec<u8>>,
) -> Result<()> {
let cpi_caller_auth = ctx.accounts.whitelist_verifier.is_allowed()?;
let message_buffer_account_info = ctx
.remaining_accounts
.first()
.ok_or(MessageBufferError::MessageBufferNotProvided)?;
ctx.accounts.whitelist_verifier.is_allowed()?;
MessageBuffer::check_discriminator(message_buffer_account_info)?;
let account_data = &mut message_buffer_account_info.try_borrow_mut_data()?;
let header_end_index = mem::size_of::<MessageBuffer>() + 8;
let msg_buffer_ai = ctx.accounts.message_buffer.to_account_info();
let account_data = &mut msg_buffer_ai.try_borrow_mut_data()?;
let header_end_index = MessageBuffer::HEADER_LEN as usize;
let (header_bytes, body_bytes) = account_data.split_at_mut(header_end_index);
let message_buffer: &mut MessageBuffer = bytemuck::from_bytes_mut(&mut header_bytes[8..]);
message_buffer.validate(
message_buffer_account_info.key(),
cpi_caller_auth,
base_account_key,
)?;
message_buffer.refresh_header();
let (num_msgs, num_bytes) = message_buffer.put_all_in_buffer(body_bytes, &messages);
if num_msgs != messages.len() {
msg!("unable to fit all messages in MessageBuffer account. Wrote {}/{} messages and {} bytes", num_msgs, messages.len(), num_bytes);
}
Ok(())
}
#[derive(Accounts)]
#[instruction( base_account_key: Pubkey)]
#[instruction(base_account_key: Pubkey)]
pub struct PutAll<'info> {
pub whitelist_verifier: WhitelistVerifier<'info>,
// remaining_accounts: - [AccumulatorInput PDA]
#[account(
mut,
seeds = [whitelist_verifier.cpi_caller_auth.key().as_ref(), b"message".as_ref(), base_account_key.as_ref()],
bump = message_buffer.load()?.bump,
)]
pub message_buffer: AccountLoader<'info, MessageBuffer>,
}

View File

@ -2,112 +2,35 @@ use {
crate::{
state::*,
MessageBufferError,
MESSAGE,
},
anchor_lang::{
prelude::*,
solana_program::entrypoint::MAX_PERMITTED_DATA_INCREASE,
system_program::{
self,
Transfer,
},
},
anchor_lang::prelude::*,
};
pub fn resize_buffer<'info>(
ctx: Context<'_, '_, '_, 'info, ResizeBuffer<'info>>,
allowed_program_auth: Pubkey,
base_account_key: Pubkey,
buffer_bump: u8,
_base_account_key: Pubkey,
target_size: u32,
) -> Result<()> {
let message_buffer_account_info = ctx
.remaining_accounts
.first()
.ok_or(MessageBufferError::MessageBufferNotProvided)?;
ctx.accounts
.whitelist
.is_allowed_program_auth(&allowed_program_auth)?;
MessageBuffer::check_discriminator(message_buffer_account_info)?;
let target_size = target_size as usize;
let current_account_size = message_buffer_account_info.data_len();
let target_size_delta = target_size.saturating_sub(current_account_size);
let message_buffer = &ctx.accounts.message_buffer.load()?;
let max_end_offset = message_buffer.end_offsets.iter().max().unwrap();
let minimum_size = max_end_offset + message_buffer.header_len;
require_gte!(
MAX_PERMITTED_DATA_INCREASE,
target_size_delta,
MessageBufferError::TargetSizeDeltaExceeded
target_size as usize,
minimum_size as usize,
MessageBufferError::MessageBufferTooSmall
);
let expected_key = Pubkey::create_program_address(
&[
allowed_program_auth.as_ref(),
MESSAGE.as_bytes(),
base_account_key.as_ref(),
&[buffer_bump],
],
&crate::ID,
)
.map_err(|_| MessageBufferError::InvalidPDA)?;
require_keys_eq!(
message_buffer_account_info.key(),
expected_key,
MessageBufferError::InvalidPDA
);
// allow for target_size == account_size in case Rent requirements have changed
// and additional lamports need to be transferred.
// the realloc step will be a no-op in this case.
if target_size >= current_account_size {
let target_rent = Rent::get()?.minimum_balance(target_size);
if message_buffer_account_info.lamports() < target_rent {
system_program::transfer(
CpiContext::new(
ctx.accounts.system_program.to_account_info(),
Transfer {
from: ctx.accounts.admin.to_account_info(),
to: message_buffer_account_info.to_account_info(),
},
),
target_rent - message_buffer_account_info.lamports(),
)?;
}
message_buffer_account_info
.realloc(target_size, false)
.map_err(|_| MessageBufferError::ReallocFailed)?;
} else {
// Check that account doesn't get resized to smaller than the amount of
// data it is currently holding (if any)
{
let account_data = &message_buffer_account_info.try_borrow_data()?;
let header_end_index = std::mem::size_of::<MessageBuffer>() + 8;
let (header_bytes, _) = account_data.split_at(header_end_index);
let message_buffer: &MessageBuffer = bytemuck::from_bytes(&header_bytes[8..]);
let max_end_offset = message_buffer.end_offsets.iter().max().unwrap();
let minimum_size = max_end_offset + message_buffer.header_len;
require_gte!(
target_size,
minimum_size as usize,
MessageBufferError::MessageBufferTooSmall
);
}
// Not transferring excess lamports back to admin.
// Account will retain more lamports than necessary.
message_buffer_account_info.realloc(target_size, false)?;
}
Ok(())
}
#[derive(Accounts)]
#[instruction(
allowed_program_auth: Pubkey, base_account_key: Pubkey,
buffer_bump: u8, target_size: u32
allowed_program_auth: Pubkey, base_account_key: Pubkey, target_size: u32
)]
pub struct ResizeBuffer<'info> {
#[account(
@ -122,5 +45,18 @@ pub struct ResizeBuffer<'info> {
pub admin: Signer<'info>,
pub system_program: Program<'info, System>,
// remaining_accounts: - [AccumulatorInput PDA]
/// If decreasing, Anchor will automatically check
/// if target_size is too small and if so,then load() will fail.
/// If increasing, Anchor also automatically checks if target_size delta
/// exceeds MAX_PERMITTED_DATA_INCREASE
#[account(
mut,
realloc = target_size as usize,
realloc::zero = false,
realloc::payer = admin,
seeds = [allowed_program_auth.as_ref(), b"message".as_ref(), base_account_key.as_ref()],
bump = message_buffer.load()?.bump,
)]
pub message_buffer: AccountLoader<'info, MessageBuffer>,
}

View File

@ -112,21 +112,13 @@ pub mod message_buffer {
/// *`target_size` - Size to re-allocate for the
/// `MessageBuffer` PDA. If increasing the size,
/// max delta of current_size & target_size is 10240
/// *`buffer_bump` - Bump seed for the `MessageBuffer` PDA
pub fn resize_buffer<'info>(
ctx: Context<'_, '_, '_, 'info, ResizeBuffer<'info>>,
allowed_program_auth: Pubkey,
base_account_key: Pubkey,
buffer_bump: u8,
target_size: u32,
) -> Result<()> {
instructions::resize_buffer(
ctx,
allowed_program_auth,
base_account_key,
buffer_bump,
target_size,
)
instructions::resize_buffer(ctx, allowed_program_auth, base_account_key, target_size)
}
/// Closes the buffer account and transfers the remaining lamports to the
@ -138,14 +130,12 @@ pub mod message_buffer {
/// * `base_account_key` - Pubkey of the original account the
/// `MessageBuffer` is derived from
/// (e.g. pyth price account)
/// *`buffer_bump` - Bump seed for the `MessageBuffer` PDA
pub fn delete_buffer<'info>(
ctx: Context<'_, '_, '_, 'info, DeleteBuffer<'info>>,
allowed_program_auth: Pubkey,
base_account_key: Pubkey,
buffer_bump: u8,
) -> Result<()> {
instructions::delete_buffer(ctx, allowed_program_auth, base_account_key, buffer_bump)
instructions::delete_buffer(ctx, allowed_program_auth, base_account_key)
}
}

View File

@ -1,13 +1,9 @@
use {
crate::{
accumulator_input_seeds,
instructions,
MessageBufferError,
},
anchor_lang::{
prelude::*,
Discriminator,
},
anchor_lang::prelude::*,
};
/// A MessageBuffer will have the following structure
@ -78,6 +74,7 @@ impl MessageBuffer {
self.end_offsets = [0u16; u8::MAX as usize];
}
/// `put_all` writes all the messages to the `AccumulatorInput` account
/// and updates the `end_offsets` array.
///
@ -131,28 +128,6 @@ impl MessageBuffer {
require_keys_eq!(expected_key, key);
Ok(())
}
/// Verify message buffer account is initialized and has the correct discriminator.
///
/// Note: manually checking because using anchor's `AccountLoader.load()`
/// will panic since the `AccountInfo.data_len()` will not match the
/// size of the `MessageBuffer` since the `MessageBuffer` struct does not
/// include the messages.
pub fn check_discriminator(message_buffer_account_info: &AccountInfo) -> Result<()> {
if instructions::is_uninitialized_account(message_buffer_account_info) {
return err!(MessageBufferError::MessageBufferUninitialized);
}
let data = message_buffer_account_info.try_borrow_data()?;
if data.len() < MessageBuffer::discriminator().len() {
return Err(ErrorCode::AccountDiscriminatorNotFound.into());
}
let disc_bytes = &data[0..8];
if disc_bytes != &MessageBuffer::discriminator() {
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
}
Ok(())
}
}
#[cfg(test)]
@ -222,16 +197,11 @@ mod test {
let header_len = MessageBuffer::HEADER_LEN as usize;
let (header_bytes, body_bytes) = account_info_data.split_at_mut(header_len);
let message_buffer: &mut MessageBuffer = bytemuck::from_bytes_mut(&mut header_bytes[8..]);
let (num_msgs, num_bytes) = message_buffer.put_all_in_buffer(body_bytes, &data_bytes);
let message_buffer: &MessageBuffer =
bytemuck::from_bytes(&account_info_data.as_slice()[8..header_len]);
assert_eq!(num_msgs, 2);
assert_eq!(num_bytes, 5);
@ -239,6 +209,8 @@ mod test {
assert_eq!(message_buffer.end_offsets[0], 2);
assert_eq!(message_buffer.end_offsets[1], 5);
let message_buffer: &MessageBuffer =
bytemuck::from_bytes(&account_info_data.as_slice()[8..header_len]);
let iter = message_buffer.end_offsets.iter().take_while(|x| **x != 0);
let mut start = header_len;
@ -258,6 +230,7 @@ mod test {
}
}
#[test]
fn test_put_all_exceed_max() {
let data = vec![vec![0u8; 9_718 - 2], vec![0u8], vec![0u8; 2]];
@ -269,20 +242,24 @@ mod test {
let header_len = MessageBuffer::HEADER_LEN as usize;
let (header_bytes, body_bytes) = account_info_data.split_at_mut(header_len);
let message_buffer: &mut MessageBuffer = bytemuck::from_bytes_mut(&mut header_bytes[8..]);
let (num_msgs, num_bytes) = message_buffer.put_all_in_buffer(body_bytes, &data_bytes);
let message_buffer: &MessageBuffer =
bytemuck::from_bytes(&account_info_data.as_slice()[8..header_len]);
assert_eq!(num_msgs, 2);
assert_eq!(
num_bytes,
data_bytes[0..2].iter().map(|x| x.len()).sum::<usize>() as u16
);
assert_eq!(message_buffer.end_offsets[0], 9_718 - 2);
assert_eq!(message_buffer.end_offsets[1], 9_718 - 1);
let message_buffer: &MessageBuffer =
bytemuck::from_bytes(&account_info_data.as_slice()[8..header_len]);
let iter = message_buffer.end_offsets.iter().take_while(|x| **x != 0);
let mut start = header_len;
@ -298,7 +275,6 @@ mod test {
assert_eq!(message_buffer.end_offsets[2], 0);
}
#[test]
fn test_put_all_long_vec() {
let data = vec![
@ -315,17 +291,12 @@ mod test {
let header_len = MessageBuffer::HEADER_LEN as usize;
let (header_bytes, body_bytes) = account_info_data.split_at_mut(header_len);
let message_buffer: &mut MessageBuffer = bytemuck::from_bytes_mut(&mut header_bytes[8..]);
let (num_msgs, num_bytes) = message_buffer.put_all_in_buffer(body_bytes, &data_bytes);
let message_buffer: &MessageBuffer =
bytemuck::from_bytes(&account_info_data.as_slice()[8..header_len]);
assert_eq!(num_msgs, 3);
assert_eq!(
num_bytes,
@ -333,6 +304,9 @@ mod test {
);
let message_buffer: &MessageBuffer =
bytemuck::from_bytes(&account_info_data.as_slice()[8..header_len]);
let iter = message_buffer.end_offsets.iter().take_while(|x| **x != 0);
let mut start = header_len;
let mut data_iter = data_bytes.iter();
@ -368,13 +342,9 @@ mod test {
let message_buffer: &mut MessageBuffer = bytemuck::from_bytes_mut(&mut header_bytes[8..]);
let (num_msgs, num_bytes) = message_buffer.put_all_in_buffer(body_bytes, &data_bytes);
assert_eq!(num_msgs, 2);
assert_eq!(num_bytes, 5);
let message_buffer: &MessageBuffer =
bytemuck::from_bytes(&account_info_data.as_slice()[8..header_len]);
assert_eq!(message_buffer.end_offsets[0], 2);
assert_eq!(message_buffer.end_offsets[1], 5);

View File

@ -58,10 +58,10 @@ pub struct WhitelistVerifier<'info> {
}
impl<'info> WhitelistVerifier<'info> {
pub fn is_allowed(&self) -> Result<Pubkey> {
pub fn is_allowed(&self) -> Result<()> {
let auth = self.cpi_caller_auth.key();
let whitelist = &self.whitelist;
whitelist.is_allowed_program_auth(&auth)?;
Ok(auth)
Ok(())
}
}

View File

@ -90,6 +90,7 @@ async fn test_multiple_resize_buffer_ixs_in_same_txn() {
}
#[tokio::test]
#[should_panic]
async fn fail_resize_buffer_invalid_increase() {
let mut context = MessageBufferTestContext::initialize_with_default_test_buffer(
false,
@ -111,7 +112,6 @@ async fn fail_resize_buffer_invalid_increase() {
let resize_ix = resize_msg_buffer_ix(
cpi_caller_auth,
pyth_price_acct,
msg_buffer_bump,
target_size,
whitelist,
admin.pubkey(),
@ -125,16 +125,173 @@ async fn fail_resize_buffer_invalid_increase() {
let err: ProgramError = res.unwrap_err().into();
assert_eq!(
err,
ProgramError::Custom(MessageBufferError::TargetSizeDeltaExceeded.into())
ProgramError::Custom(anchor_lang::error::ErrorCode::AccountReallocExceedsLimit.into())
);
// shrink buffer size to less than minimum allowed
let target_size = 1;
let msg_buffer_account_data = context
.fetch_msg_buffer_account_data(&msg_buffer_pda)
.await
.unwrap();
assert_eq!(
msg_buffer_account_data.len(),
MessageBufferTestContext::DEFAULT_TARGET_SIZE as usize
);
let (bump, _version, _header_len, end_offsets) =
deserialize_msg_buffer_header(&msg_buffer_account_data);
assert_eq!(bump, msg_buffer_bump);
assert_eq!(end_offsets, [0u16; 255]);
// shrink buffer size to less than MessageBuffer::HEADER_LEN
let target_size = 15;
let resize_ix = resize_msg_buffer_ix(
cpi_caller_auth,
pyth_price_acct,
target_size,
whitelist,
admin.pubkey(),
msg_buffer_pda,
);
// a target_size less than the MessageBuffer::HEADER_LEN
// will result in a `ProgramFailedToComplete` (or AccountDiscriminatorNotFound
// if target_size < 8) since after the realloc,
// the AccountLoadder.load/load_mut() calls will fail
context
.process_ixs(&[resize_ix], vec![&admin])
.await
.unwrap();
}
#[tokio::test]
async fn test_resize_initialized_buffer() {
let mut context = MessageBufferTestContext::initialize_with_default_test_buffer(
false,
MessageBufferTestContext::DEFAULT_TARGET_SIZE,
)
.await
.unwrap();
let payer = context.payer.pubkey();
let whitelist = context.whitelist();
let cpi_caller_auth = MessageBufferTestContext::get_mock_cpi_auth();
let (msg_buffer_pda, msg_buffer_bump) = MessageBufferTestContext::default_msg_buffer();
let add_price_params = MessageBufferTestContext::DEFAULT_ADD_PRICE_PARAMS;
context
.add_price(add_price_params, payer, whitelist, cpi_caller_auth)
.await
.unwrap();
let (id, price, price_expo, ema, ema_expo) = add_price_params;
let msg_buffer_account_data = context
.fetch_msg_buffer_account_data(&msg_buffer_pda)
.await
.unwrap();
let (bump, _version, header_len, end_offsets) =
deserialize_msg_buffer_header(&msg_buffer_account_data);
assert_eq!(bump, msg_buffer_bump);
// size_of(price::MessageHeader) + FullPriceMessage::SIZE
let msg_size_0 = 7 + 40;
assert_eq!(&end_offsets[0], &msg_size_0);
// size_of(price::MessageHeader) + CompactPriceMessage::SIZE
let msg_size_1 = 7 + 24;
assert_eq!(&end_offsets[1], &(msg_size_0 + msg_size_1));
assert_eq!(&end_offsets[2..], &[0u16; 253]);
let msgs = extract_msg_buffer_messages(header_len, end_offsets, &msg_buffer_account_data);
validate_price_msgs(id, price, price_expo, ema, ema_expo, &msgs).unwrap();
// increase buffer size should not edit the original data
let target_size = MessageBufferTestContext::DEFAULT_TARGET_SIZE + 10240;
let target_sizes = vec![target_size];
context
.resize_msg_buffer(
MessageBufferTestContext::DEFAULT_TEST_PRICE_ID,
target_sizes,
)
.await
.unwrap();
let msg_buffer_account_data = context
.fetch_msg_buffer_account_data(&msg_buffer_pda)
.await
.unwrap();
let (bump, _version, header_len, end_offsets) =
deserialize_msg_buffer_header(&msg_buffer_account_data);
assert_eq!(bump, msg_buffer_bump);
// size_of(price::MessageHeader) + FullPriceMessage::SIZE
let msg_size_0 = 7 + 40;
assert_eq!(&end_offsets[0], &msg_size_0);
// size_of(price::MessageHeader) + CompactPriceMessage::SIZE
let msg_size_1 = 7 + 24;
assert_eq!(&end_offsets[1], &(msg_size_0 + msg_size_1));
assert_eq!(&end_offsets[2..], &[0u16; 253]);
let msgs = extract_msg_buffer_messages(header_len, end_offsets, &msg_buffer_account_data);
validate_price_msgs(id, price, price_expo, ema, ema_expo, &msgs).unwrap();
}
#[tokio::test]
async fn fail_resize_initialized_buffer() {
let mut context = MessageBufferTestContext::initialize_with_default_test_buffer(
false,
MessageBufferTestContext::DEFAULT_TARGET_SIZE,
)
.await
.unwrap();
let payer = context.payer.pubkey();
let admin = context.default_admin();
let pyth_price_acct = MessageBufferTestContext::default_pyth_price_account();
let whitelist = context.whitelist();
let cpi_caller_auth = MessageBufferTestContext::get_mock_cpi_auth();
let (msg_buffer_pda, _msg_buffer_bump) = MessageBufferTestContext::default_msg_buffer();
let add_price_params = MessageBufferTestContext::DEFAULT_ADD_PRICE_PARAMS;
context
.add_price(add_price_params, payer, whitelist, cpi_caller_auth)
.await
.unwrap();
let msg_buffer_account_data = context
.fetch_msg_buffer_account_data(&msg_buffer_pda)
.await
.unwrap();
let (_, _version, header_len, end_offsets) =
deserialize_msg_buffer_header(&msg_buffer_account_data);
let max_end_offset = end_offsets.iter().max().unwrap();
let min_size = header_len + max_end_offset;
// decrease buffer size to less than something that can fit the current messages
let target_size = (min_size as u32) - 1;
let resize_ix = resize_msg_buffer_ix(
cpi_caller_auth,
pyth_price_acct,
msg_buffer_bump,
target_size,
whitelist,
admin.pubkey(),
@ -144,13 +301,32 @@ async fn fail_resize_buffer_invalid_increase() {
let res = context.process_ixs(&[resize_ix], vec![&admin]).await;
assert!(res.is_err());
let err: ProgramError = res.unwrap_err().into();
assert_eq!(
err,
ProgramError::Custom(MessageBufferError::MessageBufferTooSmall.into())
);
}
#[tokio::test]
async fn test_resize_initialized_buffer() {
let target_size = (min_size as u32) + 1;
let resize_ix = resize_msg_buffer_ix(
cpi_caller_auth,
pyth_price_acct,
target_size,
whitelist,
admin.pubkey(),
msg_buffer_pda,
);
let res = context.process_ixs(&[resize_ix], vec![&admin]).await;
assert!(res.is_ok());
let msg_buffer_account_data = context
.fetch_msg_buffer_account_data(&msg_buffer_pda)
.await
.unwrap();
assert_eq!(msg_buffer_account_data.len(), target_size as usize);
}

View File

@ -192,7 +192,10 @@ impl MessageBufferTestContext {
let e = Custom(error_code);
Err(e.into())
}
Err(_) => panic!("Unexpected error"),
Err(e) => {
println!("proces_ixs Error: {:?}", e);
panic!("Non Custom Ix Error in process_ixs{:?}", e);
}
Ok(_) => Ok(()),
}
}
@ -287,14 +290,13 @@ impl MessageBufferTestContext {
pub async fn delete_buffer(&mut self, id: u64) -> anchor_lang::Result<()> {
let pyth_price_account = Self::get_mock_pyth_price_account(id);
let (msg_buffer_pda, msg_buffer_bump) =
let (msg_buffer_pda, _) =
find_msg_buffer_pda(Self::get_mock_cpi_auth(), pyth_price_account);
let admin = self.admin.as_ref().unwrap().insecure_clone();
let delete_ix = delete_msg_buffer_ix(
Self::get_mock_cpi_auth(),
pyth_price_account,
msg_buffer_bump,
self.whitelist(),
admin.pubkey(),
msg_buffer_pda,
@ -310,7 +312,7 @@ impl MessageBufferTestContext {
target_sizes: Vec<u32>,
) -> anchor_lang::Result<()> {
let pyth_price_account = Self::get_mock_pyth_price_account(id);
let (msg_buffer_pda, msg_buffer_bump) =
let (msg_buffer_pda, _) =
find_msg_buffer_pda(Self::get_mock_cpi_auth(), pyth_price_account);
let resize_ixs = &mut vec![];
@ -322,7 +324,6 @@ impl MessageBufferTestContext {
let resize_ix = resize_msg_buffer_ix(
Self::get_mock_cpi_auth(),
pyth_price_account,
msg_buffer_bump,
target_size,
self.whitelist(),
admin.pubkey(),
@ -430,7 +431,6 @@ pub fn create_msg_buffer_ix(
pub fn resize_msg_buffer_ix(
cpi_caller_auth: Pubkey,
pyth_price_acct: Pubkey,
msg_buffer_bump: u8,
target_size: u32,
whitelist: Pubkey,
admin: Pubkey,
@ -444,7 +444,6 @@ pub fn resize_msg_buffer_ix(
resize_ix_disc,
cpi_caller_auth,
pyth_price_acct,
msg_buffer_bump,
target_size,
),
vec![
@ -460,7 +459,6 @@ pub fn resize_msg_buffer_ix(
pub fn delete_msg_buffer_ix(
cpi_caller_auth: Pubkey,
pyth_price_acct: Pubkey,
msg_buffer_bump: u8,
whitelist: Pubkey,
admin: Pubkey,
msg_buffer_pda: Pubkey,
@ -469,12 +467,7 @@ pub fn delete_msg_buffer_ix(
Instruction::new_with_borsh(
::message_buffer::id(),
&(
delete_ix_disc,
cpi_caller_auth,
pyth_price_acct,
msg_buffer_bump,
),
&(delete_ix_disc, cpi_caller_auth, pyth_price_acct),
vec![
AccountMeta::new_readonly(whitelist, false),
AccountMeta::new(admin, true),

View File

@ -65,7 +65,7 @@ const [messageBufferPda2, messageBufferBump2] =
messageBufferProgram.programId
);
const accumulatorPdaMeta2 = {
const messageBufferPdaMeta2 = {
pubkey: messageBufferPda2,
isSigner: false,
isWritable: true,
@ -144,7 +144,7 @@ describe("message_buffer", () => {
});
it("Creates a buffer", async () => {
const accumulatorPdaMetas = [
const msgBufferPdaMetas = [
{
pubkey: messageBufferPda,
isSigner: false,
@ -160,7 +160,7 @@ describe("message_buffer", () => {
systemProgram: anchor.web3.SystemProgram.programId,
})
.signers([whitelistAdmin])
.remainingAccounts(accumulatorPdaMetas)
.remainingAccounts(msgBufferPdaMetas)
.rpc({ skipPreflight: true });
const messageBufferAccountData = await getMessageBuffer(
@ -206,7 +206,7 @@ describe("message_buffer", () => {
systemProgram: anchor.web3.SystemProgram.programId,
})
.signers([whitelistAdmin])
.remainingAccounts([accumulatorPdaMeta2])
.remainingAccounts([messageBufferPdaMeta2])
.rpc({ skipPreflight: true });
const messageBufferAccountData = await getMessageBuffer(
@ -560,19 +560,13 @@ describe("message_buffer", () => {
);
const targetSize = 10 * 1024;
await messageBufferProgram.methods
.resizeBuffer(
mockCpiCallerAuth,
pythPriceAccountPk2,
messageBufferBump2,
targetSize
)
.resizeBuffer(mockCpiCallerAuth, pythPriceAccountPk2, targetSize)
.accounts({
whitelist: whitelistPubkey,
admin: whitelistAdmin.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
})
.signers([whitelistAdmin])
.remainingAccounts([accumulatorPdaMeta2])
.rpc({ skipPreflight: true });
const whitelistAuthorityBalanceAfter = await provider.connection.getBalance(
@ -606,19 +600,14 @@ describe("message_buffer", () => {
it("Resizes a buffer to a smaller size", async () => {
const targetSize = 4 * 1024;
await messageBufferProgram.methods
.resizeBuffer(
mockCpiCallerAuth,
pythPriceAccountPk2,
messageBufferBump2,
targetSize
)
.resizeBuffer(mockCpiCallerAuth, pythPriceAccountPk2, targetSize)
.accounts({
whitelist: whitelistPubkey,
admin: whitelistAdmin.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
messageBuffer: messageBufferPda2,
})
.signers([whitelistAdmin])
.remainingAccounts([accumulatorPdaMeta2])
.rpc({ skipPreflight: true });
const messageBufferAccountData = await getMessageBuffer(
@ -635,19 +624,14 @@ describe("message_buffer", () => {
let errorThrown = false;
try {
await messageBufferProgram.methods
.resizeBuffer(
mockCpiCallerAuth,
pythPriceAccountPk2,
messageBufferBump2,
testCase
)
.resizeBuffer(mockCpiCallerAuth, pythPriceAccountPk2, testCase)
.accounts({
whitelist: whitelistPubkey,
admin: whitelistAdmin.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
messageBuffer: messageBufferPda2,
})
.signers([whitelistAdmin])
.remainingAccounts([accumulatorPdaMeta2])
.rpc({ skipPreflight: true });
} catch (_err) {
errorThrown = true;
@ -658,13 +642,14 @@ describe("message_buffer", () => {
it("Deletes a buffer", async () => {
await messageBufferProgram.methods
.deleteBuffer(mockCpiCallerAuth, pythPriceAccountPk2, messageBufferBump2)
.deleteBuffer(mockCpiCallerAuth, pythPriceAccountPk2)
.accounts({
whitelist: whitelistPubkey,
admin: whitelistAdmin.publicKey,
messageBuffer: messageBufferPda2,
})
.signers([whitelistAdmin])
.remainingAccounts([accumulatorPdaMeta2])
.remainingAccounts([messageBufferPdaMeta2])
.rpc({ skipPreflight: true });
const messageBufferAccountData = await getMessageBuffer(
@ -697,7 +682,7 @@ describe("message_buffer", () => {
systemProgram: anchor.web3.SystemProgram.programId,
})
.signers([whitelistAdmin])
.remainingAccounts([accumulatorPdaMeta2])
.remainingAccounts([messageBufferPdaMeta2])
.rpc({ skipPreflight: true });
const messageBufferAccountData = await getMessageBuffer(