antegen_thread_program/instructions/
fiber_create.rs

1use crate::{errors::*, state::compile_instruction, *};
2use anchor_lang::{prelude::*, solana_program::instruction::Instruction};
3
4/// Accounts required by the `fiber_create` instruction.
5#[derive(Accounts)]
6#[instruction(fiber_index: u8)]
7pub struct FiberCreate<'info> {
8    /// The authority of the thread or the thread itself
9    #[account(
10        constraint = authority.key().eq(&thread.authority) || authority.key().eq(&thread.key())
11    )]
12    pub authority: Signer<'info>,
13
14    /// The payer for account initializations
15    #[account(mut)]
16    pub payer: Signer<'info>,
17
18    /// The thread to add the fiber to
19    #[account(
20        mut,
21        seeds = [
22            SEED_THREAD,
23            thread.authority.as_ref(),
24            thread.id.as_slice(),
25        ],
26        bump = thread.bump,
27    )]
28    pub thread: Account<'info, Thread>,
29
30    /// The fiber account to create
31    #[account(
32        init,
33        seeds = [
34            SEED_THREAD_FIBER,
35            thread.key().as_ref(),
36            &[fiber_index],
37        ],
38        bump,
39        payer = payer,
40        space = 8 + FiberState::INIT_SPACE
41    )]
42    pub fiber: Account<'info, FiberState>,
43
44    #[account(address = anchor_lang::system_program::ID)]
45    pub system_program: Program<'info, System>,
46}
47
48pub fn fiber_create(
49    ctx: Context<FiberCreate>,
50    fiber_index: u8,
51    instruction: Instruction,
52    signer_seeds: Vec<Vec<Vec<u8>>>,
53    priority_fee: u64,
54) -> Result<()> {
55    // Validate fiber_index matches fiber_next_id (enforces sequential creation)
56    let thread = &mut ctx.accounts.thread;
57    require!(
58        fiber_index == thread.fiber_next_id,
59        AntegenThreadError::InvalidFiberIndex
60    );
61
62    // Prevent thread_delete instructions in fibers
63    if instruction.program_id.eq(&crate::ID)
64        && instruction.data.len().ge(&8)
65        && instruction.data[..8].eq(crate::instruction::DeleteThread::DISCRIMINATOR)
66    {
67        return Err(AntegenThreadError::InvalidInstruction.into());
68    }
69
70    let fiber = &mut ctx.accounts.fiber;
71
72    // Compile the instruction
73    let compiled = compile_instruction(instruction, signer_seeds)?;
74    let compiled_bytes = compiled.try_to_vec()?;
75
76    // Initialize the fiber
77    fiber.thread = thread.key();
78    fiber.fiber_index = fiber_index;
79    fiber.compiled_instruction = compiled_bytes;
80    fiber.priority_fee = priority_fee;
81    fiber.last_executed = 0;
82    fiber.exec_count = 0;
83
84    // Update thread's fiber_ids and increment fiber_next_id
85    if !thread.fiber_ids.contains(&fiber_index) {
86        thread.fiber_ids.push(fiber_index);
87        thread.fiber_ids.sort();
88    }
89    thread.fiber_next_id = thread.fiber_next_id.saturating_add(1);
90
91    Ok(())
92}