chunk_loader/instructions/
load_chunk.rs

1use crate::{state::*, utils::*};
2use anchor_lang::{prelude::*, Discriminator};
3
4#[derive(Accounts)]
5#[instruction(chunk_holder_id: u32)]
6pub struct LoadChunk<'info> {
7    #[account(mut)]
8    owner: Signer<'info>,
9    /// CHECK: it's handled in the function body
10    #[account(
11        mut,
12        seeds = [b"CHUNK_HOLDER", &owner.key().to_bytes(), &chunk_holder_id.to_le_bytes()],
13        bump,
14    )]
15    chunk_holder: AccountInfo<'info>,
16    system_program: Program<'info, System>,
17}
18
19pub fn load_chunk(ctx: Context<LoadChunk>, chunk_holder_id: u32, chunk: Chunk) -> Result<()> {
20    let owner = &ctx.accounts.owner;
21    let chunk_holder = &ctx.accounts.chunk_holder;
22
23    let (space, data) = if chunk_holder.data_is_empty() {
24        (
25            1 + ChunkHolder::INIT_SPACE + chunk.self_space(),
26            ChunkHolder {
27                owner: owner.key(),
28                chunks: vec![chunk],
29            },
30        )
31    } else {
32        let data = chunk_holder.try_borrow_data()?;
33        let Some(rest_data) = data.strip_prefix(ChunkHolder::DISCRIMINATOR) else {
34            return err!(ErrorCode::AccountDiscriminatorMismatch);
35        };
36        let space = chunk_holder.data_len() + chunk.self_space();
37        let mut data = ChunkHolder::deserialize(&mut &rest_data[..])?;
38        data.chunks.push(chunk);
39        (space, data)
40    };
41
42    init_or_realloc_with_admin(
43        chunk_holder,
44        space,
45        owner.key(),
46        &data,
47        owner.to_account_info(),
48        &[&[
49            b"CHUNK_HOLDER",
50            &owner.key().to_bytes(),
51            &chunk_holder_id.to_le_bytes(),
52            &[ctx.bumps.chunk_holder],
53        ]],
54        false,
55    )?;
56
57    Ok(())
58}