antegen_fiber_program/instructions/
create.rs1use crate::constants::*;
2use crate::errors::AntegenFiberError;
3use crate::state::*;
4use anchor_lang::prelude::*;
5use anchor_lang::solana_program::instruction::Instruction;
6use anchor_lang::solana_program::program::invoke_signed;
7use anchor_lang::solana_program::system_instruction;
8
9#[derive(Accounts)]
12#[instruction(fiber_index: u8)]
13pub struct Create<'info> {
14 pub thread: Signer<'info>,
16
17 #[account(mut)]
19 pub fiber: UncheckedAccount<'info>,
20
21 pub system_program: Program<'info, System>,
22}
23
24pub fn create(
25 ctx: Context<Create>,
26 fiber_index: u8,
27 instruction: Instruction,
28 priority_fee: u64,
29 lookup_tables: Vec<Pubkey>,
30) -> Result<()> {
31 require!(
32 lookup_tables.len() <= MAX_LOOKUP_TABLES_PER_FIBER,
33 AntegenFiberError::LookupTablesExceedMax
34 );
35
36 let thread_key = ctx.accounts.thread.key();
37 let fiber_info = ctx.accounts.fiber.to_account_info();
38
39 if fiber_info.data_len() == 0 {
40 initialize_fiber(
41 &ctx.accounts.fiber,
42 &ctx.accounts.system_program,
43 &thread_key,
44 fiber_index,
45 &instruction,
46 priority_fee,
47 lookup_tables,
48 )
49 } else {
50 let compiled = compile_instruction(instruction)?;
54 let compiled_bytes = borsh::to_vec(&compiled)?;
55
56 let fiber_read = {
57 let data = fiber_info.try_borrow_data()?;
58 Fiber::try_deserialize(&mut &data[..])?
59 };
60
61 match fiber_read {
62 Fiber::Legacy(mut state) => {
63 require!(
64 lookup_tables.is_empty(),
65 AntegenFiberError::LegacyFiberLookupTablesUnsupported
66 );
67 state.thread = thread_key;
68 state.compiled_instruction = compiled_bytes;
69 state.priority_fee = priority_fee;
70 state.last_executed = 0;
71 state.exec_count = 0;
72 write_legacy(&fiber_info, &state)?;
73 }
74 Fiber::V1(mut state) => {
75 state.version = CURRENT_FIBER_VERSION;
76 state.thread = thread_key;
77 state.compiled_instruction = compiled_bytes;
78 state.priority_fee = priority_fee;
79 state.last_executed = 0;
80 state.exec_count = 0;
81 state.lookup_tables = lookup_tables;
82 write_versioned(&fiber_info, &state)?;
83 }
84 }
85
86 Ok(())
87 }
88}
89
90pub fn initialize_fiber<'info>(
94 fiber: &UncheckedAccount<'info>,
95 system_program: &Program<'info, System>,
96 thread_key: &Pubkey,
97 fiber_index: u8,
98 instruction: &Instruction,
99 priority_fee: u64,
100 lookup_tables: Vec<Pubkey>,
101) -> Result<()> {
102 require!(
103 lookup_tables.len() <= MAX_LOOKUP_TABLES_PER_FIBER,
104 AntegenFiberError::LookupTablesExceedMax
105 );
106
107 let fiber_info = fiber.to_account_info();
108
109 let (expected_pda, bump) = Pubkey::find_program_address(
110 &[SEED_THREAD_FIBER, thread_key.as_ref(), &[fiber_index]],
111 &crate::ID,
112 );
113 require!(
114 expected_pda.eq(&fiber.key()),
115 AntegenFiberError::InvalidFiberPDA
116 );
117
118 let space = 8 + FiberVersionedState::INIT_SPACE;
119 let rent = Rent::get()?;
120 let min_lamports = rent.minimum_balance(space);
121 require!(
122 fiber_info.lamports().ge(&min_lamports),
123 AntegenFiberError::InsufficientRent
124 );
125
126 let seeds: &[&[u8]] = &[
127 SEED_THREAD_FIBER,
128 thread_key.as_ref(),
129 &[fiber_index],
130 &[bump],
131 ];
132
133 invoke_signed(
134 &system_instruction::allocate(&fiber.key(), space as u64),
135 &[fiber_info.clone(), system_program.to_account_info()],
136 &[seeds],
137 )?;
138
139 invoke_signed(
140 &system_instruction::assign(&fiber.key(), &crate::ID),
141 &[fiber_info.clone(), system_program.to_account_info()],
142 &[seeds],
143 )?;
144
145 let compiled = compile_instruction(instruction.clone())?;
146 let compiled_bytes = borsh::to_vec(&compiled)?;
147
148 let state = FiberVersionedState {
149 version: CURRENT_FIBER_VERSION,
150 thread: *thread_key,
151 compiled_instruction: compiled_bytes,
152 priority_fee,
153 last_executed: 0,
154 exec_count: 0,
155 lookup_tables,
156 };
157
158 write_versioned(&fiber_info, &state)
159}
160
161pub(crate) fn write_versioned(fiber_info: &AccountInfo, state: &FiberVersionedState) -> Result<()> {
162 let mut data = fiber_info.try_borrow_mut_data()?;
163 data[..8].copy_from_slice(FiberVersionedState::DISCRIMINATOR);
164 let state_bytes = borsh::to_vec(state)?;
165 data[8..8 + state_bytes.len()].copy_from_slice(&state_bytes);
166 Ok(())
167}
168
169pub(crate) fn write_legacy(fiber_info: &AccountInfo, state: &FiberState) -> Result<()> {
170 let mut data = fiber_info.try_borrow_mut_data()?;
171 data[..8].copy_from_slice(FiberState::DISCRIMINATOR);
172 let state_bytes = borsh::to_vec(state)?;
173 data[8..8 + state_bytes.len()].copy_from_slice(&state_bytes);
174 Ok(())
175}