lang: Reduce compute unit consumption of loader accounts (#1134)
This commit is contained in:
parent
a7e80079da
commit
a3c8d20352
|
@ -258,7 +258,7 @@ jobs:
|
|||
path: tests/cashiers-check
|
||||
- cmd: cd tests/typescript && anchor test
|
||||
path: tests/typescript
|
||||
- cmd: cd tests/zero-copy && anchor test
|
||||
- cmd: cd tests/zero-copy && anchor test && cd programs/zero-copy && cargo test-bpf
|
||||
path: tests/zero-copy
|
||||
- cmd: cd tests/chat && anchor test
|
||||
path: tests/chat
|
||||
|
|
|
@ -212,6 +212,7 @@ dependencies = [
|
|||
"anchor-attribute-program",
|
||||
"anchor-attribute-state",
|
||||
"anchor-derive-accounts",
|
||||
"arrayref",
|
||||
"base64 0.13.0",
|
||||
"bincode",
|
||||
"borsh",
|
||||
|
|
|
@ -33,6 +33,7 @@ anchor-attribute-state = { path = "./attribute/state", version = "0.19.0" }
|
|||
anchor-attribute-interface = { path = "./attribute/interface", version = "0.19.0" }
|
||||
anchor-attribute-event = { path = "./attribute/event", version = "0.19.0" }
|
||||
anchor-derive-accounts = { path = "./derive/accounts", version = "0.19.0" }
|
||||
arrayref = "0.3.6"
|
||||
base64 = "0.13.0"
|
||||
borsh = "0.9"
|
||||
bytemuck = "1.4.0"
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::{
|
|||
Accounts, AccountsClose, AccountsExit, Key, ToAccountInfo, ToAccountInfos, ToAccountMetas,
|
||||
ZeroCopy,
|
||||
};
|
||||
use arrayref::array_ref;
|
||||
use solana_program::account_info::AccountInfo;
|
||||
use solana_program::entrypoint::ProgramResult;
|
||||
use solana_program::instruction::AccountMeta;
|
||||
|
@ -62,9 +63,8 @@ impl<'info, T: ZeroCopy> Loader<'info, T> {
|
|||
}
|
||||
let data: &[u8] = &acc_info.try_borrow_data()?;
|
||||
// Discriminator must match.
|
||||
let mut disc_bytes = [0u8; 8];
|
||||
disc_bytes.copy_from_slice(&data[..8]);
|
||||
if disc_bytes != T::discriminator() {
|
||||
let disc_bytes = array_ref![data, 0, 8];
|
||||
if disc_bytes != &T::discriminator() {
|
||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||
}
|
||||
|
||||
|
@ -89,9 +89,8 @@ impl<'info, T: ZeroCopy> Loader<'info, T> {
|
|||
pub fn load(&self) -> Result<Ref<T>, ProgramError> {
|
||||
let data = self.acc_info.try_borrow_data()?;
|
||||
|
||||
let mut disc_bytes = [0u8; 8];
|
||||
disc_bytes.copy_from_slice(&data[..8]);
|
||||
if disc_bytes != T::discriminator() {
|
||||
let disc_bytes = array_ref![data, 0, 8];
|
||||
if disc_bytes != &T::discriminator() {
|
||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||
}
|
||||
|
||||
|
@ -109,9 +108,8 @@ impl<'info, T: ZeroCopy> Loader<'info, T> {
|
|||
|
||||
let data = self.acc_info.try_borrow_mut_data()?;
|
||||
|
||||
let mut disc_bytes = [0u8; 8];
|
||||
disc_bytes.copy_from_slice(&data[..8]);
|
||||
if disc_bytes != T::discriminator() {
|
||||
let disc_bytes = array_ref![data, 0, 8];
|
||||
if disc_bytes != &T::discriminator() {
|
||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::{
|
|||
Accounts, AccountsClose, AccountsExit, Key, Owner, ToAccountInfo, ToAccountInfos,
|
||||
ToAccountMetas, ZeroCopy,
|
||||
};
|
||||
use arrayref::array_ref;
|
||||
use solana_program::account_info::AccountInfo;
|
||||
use solana_program::entrypoint::ProgramResult;
|
||||
use solana_program::instruction::AccountMeta;
|
||||
|
@ -58,9 +59,8 @@ impl<'info, T: ZeroCopy + Owner> AccountLoader<'info, T> {
|
|||
}
|
||||
let data: &[u8] = &acc_info.try_borrow_data()?;
|
||||
// Discriminator must match.
|
||||
let mut disc_bytes = [0u8; 8];
|
||||
disc_bytes.copy_from_slice(&data[..8]);
|
||||
if disc_bytes != T::discriminator() {
|
||||
let disc_bytes = array_ref![data, 0, 8];
|
||||
if disc_bytes != &T::discriminator() {
|
||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||
}
|
||||
|
||||
|
@ -83,9 +83,8 @@ impl<'info, T: ZeroCopy + Owner> AccountLoader<'info, T> {
|
|||
pub fn load(&self) -> Result<Ref<T>, ProgramError> {
|
||||
let data = self.acc_info.try_borrow_data()?;
|
||||
|
||||
let mut disc_bytes = [0u8; 8];
|
||||
disc_bytes.copy_from_slice(&data[..8]);
|
||||
if disc_bytes != T::discriminator() {
|
||||
let disc_bytes = array_ref![data, 0, 8];
|
||||
if disc_bytes != &T::discriminator() {
|
||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||
}
|
||||
|
||||
|
@ -102,9 +101,8 @@ impl<'info, T: ZeroCopy + Owner> AccountLoader<'info, T> {
|
|||
|
||||
let data = self.acc_info.try_borrow_mut_data()?;
|
||||
|
||||
let mut disc_bytes = [0u8; 8];
|
||||
disc_bytes.copy_from_slice(&data[..8]);
|
||||
if disc_bytes != T::discriminator() {
|
||||
let disc_bytes = array_ref![data, 0, 8];
|
||||
if disc_bytes != &T::discriminator() {
|
||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
|
|||
|
||||
quote! {
|
||||
// TODO: remove once we allow segmented paths in `Accounts` structs.
|
||||
use #mod_name::*;
|
||||
use self::#mod_name::*;
|
||||
|
||||
#entry
|
||||
#dispatch
|
||||
|
|
|
@ -13,6 +13,12 @@ no-entrypoint = []
|
|||
no-idl = []
|
||||
cpi = ["no-entrypoint"]
|
||||
default = []
|
||||
test-bpf = []
|
||||
|
||||
[dependencies]
|
||||
anchor-lang = { path = "../../../../lang" }
|
||||
|
||||
[dev-dependencies]
|
||||
anchor-client = { path = "../../../../client", features = ["debug"] }
|
||||
bytemuck = "1.4.0"
|
||||
solana-program-test = "1.8.0"
|
||||
|
|
|
@ -11,8 +11,6 @@ declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
|||
|
||||
#[program]
|
||||
pub mod zero_copy {
|
||||
use std::str::FromStr;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub fn create_foo(ctx: Context<CreateFoo>) -> ProgramResult {
|
||||
|
@ -140,6 +138,7 @@ pub struct UpdateLargeAccount<'info> {
|
|||
}
|
||||
|
||||
#[account(zero_copy)]
|
||||
#[derive(Default)]
|
||||
pub struct Foo {
|
||||
pub authority: Pubkey,
|
||||
pub data: u64,
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
#![cfg(feature = "test-bpf")]
|
||||
|
||||
use {
|
||||
anchor_client::{
|
||||
anchor_lang::Discriminator,
|
||||
solana_sdk::{
|
||||
account::Account,
|
||||
commitment_config::CommitmentConfig,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, Signer},
|
||||
transaction::Transaction,
|
||||
},
|
||||
Client, Cluster,
|
||||
},
|
||||
solana_program_test::{tokio, ProgramTest},
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn update_foo() {
|
||||
let authority = Keypair::new();
|
||||
let foo_pubkey = Pubkey::new_unique();
|
||||
let foo_account = {
|
||||
let mut foo_data = Vec::new();
|
||||
foo_data.extend_from_slice(&zero_copy::Foo::discriminator());
|
||||
foo_data.extend_from_slice(bytemuck::bytes_of(&zero_copy::Foo {
|
||||
authority: authority.pubkey(),
|
||||
..zero_copy::Foo::default()
|
||||
}));
|
||||
|
||||
Account {
|
||||
lamports: 1,
|
||||
data: foo_data,
|
||||
owner: zero_copy::id(),
|
||||
..Account::default()
|
||||
}
|
||||
};
|
||||
|
||||
let mut pt = ProgramTest::new("zero_copy", zero_copy::id(), None);
|
||||
pt.add_account(foo_pubkey, foo_account);
|
||||
pt.set_bpf_compute_max_units(2077);
|
||||
let (mut banks_client, payer, recent_blockhash) = pt.start().await;
|
||||
|
||||
let client = Client::new_with_options(
|
||||
Cluster::Debug,
|
||||
Keypair::new(),
|
||||
CommitmentConfig::processed(),
|
||||
);
|
||||
let program = client.program(zero_copy::id());
|
||||
let update_ix = program
|
||||
.request()
|
||||
.accounts(zero_copy::accounts::UpdateFoo {
|
||||
foo: foo_pubkey,
|
||||
authority: authority.pubkey(),
|
||||
})
|
||||
.args(zero_copy::instruction::UpdateFoo { data: 1u64 })
|
||||
.instructions()
|
||||
.unwrap()
|
||||
.pop()
|
||||
.unwrap();
|
||||
|
||||
let transaction = Transaction::new_signed_with_payer(
|
||||
&[update_ix],
|
||||
Some(&payer.pubkey()),
|
||||
&[&payer, &authority],
|
||||
recent_blockhash,
|
||||
);
|
||||
|
||||
banks_client.process_transaction(transaction).await.unwrap();
|
||||
}
|
Loading…
Reference in New Issue