I want to use zero copy in an anchor program, but I don't have a clear path on how can I do that. Is there any guide or example program that does this?
2 Answers
This is how you use the account(zero). It will allow you to create data accounts of a size up to 10 MB.
In your context you wrap the account in an AccountLoader and add the #[account(zero)] decorator.
#[account(zero)]
pub my_account: AccountLoader<'info, MyAccount>
In your account struct you need to add the #[account(zero_copy)] decorator as well.
#[account(zero_copy)]
pub struct MyAccount {...}
to load your account if you have just initialized it
let my_account = &mut ctx.accounts.my_account.load_init()?;
or if you want to borrow as mut
let mut my_account = ctx.accounts.my_account.load_mut()?;
In your javascript test you first generate a keypair for the zero account. Then you can call the program instruction that takes the zero account together with an additional instruction that will create the account for you. The createInstruction will first be executed followed by the someInstruction that will change the owner of the myAccount to the program account.
const myAccount = anchor.web3.Keypair.generate();
const tx = await program.rpc.someInstruction(
...,
{
accounts: {
...
},
instructions: [
await program.account.myAccount.createInstruction(myAccount),
],
signers: [myAccount],
}
);
At the time where we zero an account the ownership is transferred from user to program. You can only change an account's owning program once, from the system program to some other program. So when the program is owned by your program you can't change the owner again.
-
1You can also add
#[account(mut)]
instead of#[account(zero)]
above theAccountLoader
if you want useinit
,space
,payer
. Only the#[account(zero_copy)]
would be enough. Commented Oct 19, 2022 at 5:00 -
1How to use dynamic size of account. e.g.
MyAccount { users: Vec<Pubkey> }
. zero_copy doesn't seem to allow dynamic size of vector. We can adjust the size of account in prior creating account instruction. but I wasn't able to use it asload_init()
occurred errorpanicked at 'range end index 320040 out of range for slice of length 3264', src/accounts/account_loader.rs:212:43
in case of smaller size of account than initial struct size. I setMyAccount {users: [Pubkey; 10000]}
– JulbhCommented Mar 7 at 10:15
pda accounts have a restricted size of 10 kb
zero is a attribute you use when you create an account outside a cpi and want to initialize it, anchor skips discriminator checking on accounts with zero attribute anchor ref : Use this constraint if you want to create an account in a previous instruction and then initialize it in your instruction instead of using init. This is necessary for accounts that are larger than 10 Kibibyte because those accounts cannot be created via a CPI (which is what init would do).
Anchor adds internal data to the account when using zero just like it does with init which is why zero implies mut.
-
So how do we create an account in previous instruction do you have any code Commented Aug 1, 2022 at 12:10
-
What are you quoting? Please add a link to your answer.– mikemaccana ♦Commented Aug 1, 2022 at 12:20