Skip to content

Commit 9341a25

Browse files
authored
Feat/memory improvements2 (#76)
1 parent c179599 commit 9341a25

File tree

6 files changed

+313
-88
lines changed

6 files changed

+313
-88
lines changed

solana-programs/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

solana-programs/programs/tuktuk/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tuktuk"
3-
version = "0.2.5"
3+
version = "0.2.6"
44
description = "Created with Anchor"
55
edition = "2021"
66

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use anchor_lang::prelude::*;
22

3-
use crate::state::{TaskQueueAuthorityV0, TaskQueueV0, TaskV0};
3+
use crate::state::{TaskQueueAuthorityV0, TaskQueueDataWrapper, TaskV0};
44

55
#[derive(Accounts)]
66
pub struct DequeuetaskV0<'info> {
@@ -12,21 +12,23 @@ pub struct DequeuetaskV0<'info> {
1212
seeds = [b"task_queue_authority", task_queue.key().as_ref(), queue_authority.key().as_ref()],
1313
bump = task_queue_authority.bump_seed,
1414
)]
15-
pub task_queue_authority: Box<Account<'info, TaskQueueAuthorityV0>>,
15+
pub task_queue_authority: Account<'info, TaskQueueAuthorityV0>,
16+
/// CHECK: We manually deserialize this using TaskQueueDataWrapper for memory efficiency
1617
#[account(mut)]
17-
pub task_queue: Box<Account<'info, TaskQueueV0>>,
18+
pub task_queue: UncheckedAccount<'info>,
1819
#[account(
1920
mut,
2021
close = rent_refund,
2122
has_one = rent_refund,
2223
has_one = task_queue,
2324
)]
24-
pub task: Box<Account<'info, TaskV0>>,
25+
pub task: Account<'info, TaskV0>,
2526
}
2627

2728
pub fn handler(ctx: Context<DequeuetaskV0>) -> Result<()> {
28-
ctx.accounts
29-
.task_queue
30-
.set_task_exists(ctx.accounts.task.id, false);
29+
let task_queue_account_info = ctx.accounts.task_queue.to_account_info();
30+
let mut task_queue_data = task_queue_account_info.try_borrow_mut_data()?;
31+
let mut task_queue = TaskQueueDataWrapper::new(*task_queue_data)?;
32+
task_queue.set_task_exists(ctx.accounts.task.id, false);
3133
Ok(())
3234
}

solana-programs/programs/tuktuk/src/instructions/queue_task_v0.rs

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ use anchor_lang::{
55

66
use crate::{
77
error::ErrorCode,
8-
resize_to_fit::resize_to_fit,
9-
state::{TaskQueueAuthorityV0, TaskQueueV0, TaskV0, TransactionSourceV0, TriggerV0},
8+
state::{TaskQueueAuthorityV0, TaskQueueDataWrapper, TaskV0, TransactionSourceV0, TriggerV0},
109
};
1110

1211
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Default)]
@@ -34,25 +33,39 @@ pub struct QueueTaskV0<'info> {
3433
seeds = [b"task_queue_authority", task_queue.key().as_ref(), queue_authority.key().as_ref()],
3534
bump = task_queue_authority.bump_seed,
3635
)]
37-
pub task_queue_authority: Box<Account<'info, TaskQueueAuthorityV0>>,
36+
pub task_queue_authority: Account<'info, TaskQueueAuthorityV0>,
37+
/// CHECK: We manually deserialize this using TaskQueueDataWrapper for memory efficiency
3838
#[account(mut)]
39-
pub task_queue: Box<Account<'info, TaskQueueV0>>,
39+
pub task_queue: UncheckedAccount<'info>,
4040
#[account(
4141
init,
4242
payer = payer,
43-
space = 8 + std::mem::size_of::<TaskV0>() + 60 + args.description.len(),
44-
constraint = !task_queue.task_exists(args.id) @ ErrorCode::TaskAlreadyExists,
45-
constraint = args.id < task_queue.capacity,
43+
space = 8 + std::mem::size_of::<TaskV0>() + args.transaction.size() + 4 + args.description.len() + 60,
4644
seeds = [b"task".as_ref(), task_queue.key().as_ref(), &args.id.to_le_bytes()[..]],
4745
bump,
4846
)]
49-
pub task: Box<Account<'info, TaskV0>>,
47+
pub task: Account<'info, TaskV0>,
5048
pub system_program: Program<'info, System>,
5149
}
5250

5351
pub fn handler(ctx: Context<QueueTaskV0>, args: QueueTaskArgsV0) -> Result<()> {
52+
// Use memory-efficient wrapper to avoid deserializing the entire task queue
53+
let task_queue_account_info = ctx.accounts.task_queue.to_account_info();
54+
let mut task_queue_data = task_queue_account_info.try_borrow_mut_data()?;
55+
let mut task_queue = TaskQueueDataWrapper::new(*task_queue_data)?;
56+
57+
// Validate constraints that were removed from the account struct
58+
require!(
59+
!task_queue.task_exists(args.id),
60+
ErrorCode::TaskAlreadyExists
61+
);
62+
require!(
63+
args.id < task_queue.header().capacity,
64+
ErrorCode::InvalidTaskId
65+
);
66+
5467
require_gte!(
55-
ctx.accounts.task_queue.capacity,
68+
task_queue.header().capacity,
5669
(args.free_tasks + 1) as u16,
5770
ErrorCode::FreeTasksGreaterThanCapacity
5871
);
@@ -63,15 +76,14 @@ pub fn handler(ctx: Context<QueueTaskV0>, args: QueueTaskArgsV0) -> Result<()> {
6376
);
6477
let crank_reward = args
6578
.crank_reward
66-
.unwrap_or(ctx.accounts.task_queue.min_crank_reward);
67-
require_gte!(crank_reward, ctx.accounts.task_queue.min_crank_reward);
79+
.unwrap_or(task_queue.header().min_crank_reward);
80+
require_gte!(crank_reward, task_queue.header().min_crank_reward);
6881

69-
let mut transaction = args.transaction.clone();
70-
if let TransactionSourceV0::CompiledV0(mut compiled_tx) = transaction {
82+
let mut transaction = args.transaction;
83+
if let TransactionSourceV0::CompiledV0(ref mut compiled_tx) = transaction {
7184
compiled_tx
7285
.accounts
7386
.extend(ctx.remaining_accounts.iter().map(|a| a.key()));
74-
transaction = TransactionSourceV0::CompiledV0(compiled_tx);
7587
}
7688
ctx.accounts.task.set_inner(TaskV0 {
7789
free_tasks: args.free_tasks,
@@ -86,14 +98,14 @@ pub fn handler(ctx: Context<QueueTaskV0>, args: QueueTaskArgsV0) -> Result<()> {
8698
bump_seed: ctx.bumps.task,
8799
queued_at: Clock::get()?.unix_timestamp,
88100
});
89-
ctx.accounts.task_queue.set_task_exists(args.id, true);
90-
ctx.accounts.task_queue.updated_at = Clock::get()?.unix_timestamp;
91101

92-
resize_to_fit(
93-
&ctx.accounts.payer.to_account_info(),
94-
&ctx.accounts.system_program.to_account_info(),
95-
&ctx.accounts.task,
96-
)?;
102+
// Update the task queue bitmap and metadata
103+
task_queue.set_task_exists(args.id, true);
104+
task_queue.header_mut().updated_at = Clock::get()?.unix_timestamp;
105+
task_queue.save()?;
106+
107+
// Drop the borrow
108+
drop(task_queue_data);
97109

98110
let rented_amount = ctx.accounts.task.to_account_info().lamports();
99111
ctx.accounts.task.rent_amount = rented_amount;

0 commit comments

Comments
 (0)