-
Notifications
You must be signed in to change notification settings - Fork 21
feat: replace task context with thread-local storage #614
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
This stash can be used for communication between magic program and the rest of the validator, as a more performant and easier to use alternative to Context accounts.
Manual Deploy AvailableYou can trigger a manual deploy of this PR branch to testnet: Alternative: Comment
Comment updated automatically when the PR is synchronized. |
WalkthroughRefactors task scheduling from on-chain TaskContext and ticker polling to an event-driven design: removes TaskContext and ProcessTasks, adds TLS-based ExecutionTlsStash and TaskRequest types, wires ScheduledTasks channels through core/link into executor/validator, and replaces the tick-based TaskSchedulerService with a channel-driven service. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Proc as Transaction Processor
participant TLS as ExecutionTlsStash
participant Chan as ScheduledTasksTx (tasks_tx)
participant Sched as TaskSchedulerService
rect rgb(200,220,240)
note over Proc,Sched: Old flow (removed)
Proc->>OnChain: write TaskContext account
Sched->>OnChain: periodic ticker reads TaskContext
Sched->>Sched: deserialize/process requests
end
rect rgb(220,240,200)
note over Proc,Sched: New flow (event-driven)
Proc->>TLS: register_task (during instruction)
Proc->>TLS: after commit drain -> for each TaskRequest
TLS->>Chan: send(TaskRequest)
Chan->>Sched: receive(TaskRequest)
Sched->>Sched: process immediately (schedule/cancel)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Areas requiring extra attention:
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
programs/magicblock/src/schedule_task/process_schedule_task.rs (1)
42-49: Update the out-of-date error text.
This log still references the old task-context account even though the instruction no longer requires it, which will mislead operators debugging failures.Apply this diff to keep the message accurate:
- "ScheduleTask ERR: not enough accounts to schedule task ({}), need payer, signing program and task context", + "ScheduleTask ERR: not enough accounts to schedule task ({}), need payer and signing program accounts",magicblock-task-scheduler/src/service.rs (1)
234-237: Cancellation currently ignored for freshly scheduled tasksNewly scheduled tasks never record their
DelayQueuekey, soremove_task_from_queuecannot pull them out if a cancel request arrives before the first execution—cancellations silently fail and the task still runs. Please stash the key when inserting (and clear any existing entry) so we can honor cancel requests.self.db.insert_task(&db_task)?; - self.task_queue - .insert(db_task.clone(), Duration::from_millis(0)); + self.remove_task_from_queue(task.id); + let key = self + .task_queue + .insert(db_task.clone(), Duration::from_millis(0)); + self.task_queue_keys.insert(task.id, key);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (3)
Cargo.lockis excluded by!**/*.lockprograms/elfs/guinea.sois excluded by!**/*.sotest-integration/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (46)
magicblock-api/src/fund_account.rs(1 hunks)magicblock-api/src/magic_validator.rs(8 hunks)magicblock-chainlink/src/chainlink/blacklisted_accounts.rs(0 hunks)magicblock-committor-program/Cargo.toml(1 hunks)magicblock-config/src/lib.rs(4 hunks)magicblock-config/src/task_scheduler.rs(1 hunks)magicblock-config/tests/fixtures/11_everything-defined.toml(0 hunks)magicblock-config/tests/parse_config.rs(1 hunks)magicblock-config/tests/read_config.rs(1 hunks)magicblock-core/src/link.rs(6 hunks)magicblock-core/src/link/transactions.rs(3 hunks)magicblock-magic-program-api/src/args.rs(1 hunks)magicblock-magic-program-api/src/instruction.rs(0 hunks)magicblock-magic-program-api/src/lib.rs(1 hunks)magicblock-magic-program-api/src/tls.rs(1 hunks)magicblock-processor/Cargo.toml(1 hunks)magicblock-processor/src/executor/mod.rs(3 hunks)magicblock-processor/src/executor/processing.rs(4 hunks)magicblock-processor/src/scheduler/state.rs(2 hunks)magicblock-task-scheduler/Cargo.toml(1 hunks)magicblock-task-scheduler/src/service.rs(6 hunks)magicblock-task-scheduler/tests/service.rs(1 hunks)programs/guinea/Cargo.toml(1 hunks)programs/guinea/src/lib.rs(5 hunks)programs/magicblock/src/lib.rs(0 hunks)programs/magicblock/src/magicblock_processor.rs(1 hunks)programs/magicblock/src/schedule_task/mod.rs(1 hunks)programs/magicblock/src/schedule_task/process_cancel_task.rs(5 hunks)programs/magicblock/src/schedule_task/process_process_tasks.rs(0 hunks)programs/magicblock/src/schedule_task/process_schedule_task.rs(6 hunks)programs/magicblock/src/schedule_task/utils.rs(0 hunks)programs/magicblock/src/task_context.rs(0 hunks)programs/magicblock/src/utils/instruction_utils.rs(2 hunks)test-integration/configs/schedule-task.ephem.toml(0 hunks)test-integration/programs/flexi-counter/src/instruction.rs(0 hunks)test-integration/programs/flexi-counter/src/processor.rs(2 hunks)test-integration/programs/schedulecommit/Cargo.toml(1 hunks)test-integration/test-ledger-restore/src/lib.rs(1 hunks)test-integration/test-task-scheduler/src/lib.rs(1 hunks)test-integration/test-task-scheduler/tests/test_cancel_ongoing_task.rs(1 hunks)test-integration/test-task-scheduler/tests/test_reschedule_task.rs(1 hunks)test-integration/test-task-scheduler/tests/test_schedule_error.rs(1 hunks)test-integration/test-task-scheduler/tests/test_schedule_task.rs(1 hunks)test-integration/test-task-scheduler/tests/test_schedule_task_signed.rs(1 hunks)test-integration/test-task-scheduler/tests/test_unauthorized_reschedule.rs(1 hunks)test-kit/src/lib.rs(3 hunks)
💤 Files with no reviewable changes (9)
- programs/magicblock/src/lib.rs
- programs/magicblock/src/schedule_task/utils.rs
- programs/magicblock/src/schedule_task/process_process_tasks.rs
- magicblock-magic-program-api/src/instruction.rs
- magicblock-config/tests/fixtures/11_everything-defined.toml
- test-integration/programs/flexi-counter/src/instruction.rs
- programs/magicblock/src/task_context.rs
- magicblock-chainlink/src/chainlink/blacklisted_accounts.rs
- test-integration/configs/schedule-task.ephem.toml
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-10-21T14:00:54.642Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579
Applied to files:
magicblock-magic-program-api/src/lib.rsprograms/guinea/src/lib.rsmagicblock-api/src/fund_account.rsprograms/magicblock/src/schedule_task/process_schedule_task.rstest-integration/programs/flexi-counter/src/processor.rsprograms/magicblock/src/schedule_task/process_cancel_task.rs
📚 Learning: 2025-11-04T10:53:50.922Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: magicblock-processor/src/scheduler/locks.rs:110-122
Timestamp: 2025-11-04T10:53:50.922Z
Learning: In magicblock-processor, the TransactionScheduler runs in a single, dedicated thread and will always remain single-threaded. The `next_transaction_id()` function in scheduler/locks.rs uses `unsafe static mut` which is safe given this architectural guarantee.
Applied to files:
magicblock-core/src/link/transactions.rsmagicblock-processor/src/executor/mod.rsmagicblock-core/src/link.rsmagicblock-processor/src/scheduler/state.rsprograms/magicblock/src/schedule_task/process_schedule_task.rsmagicblock-task-scheduler/src/service.rstest-kit/src/lib.rsmagicblock-api/src/magic_validator.rs
📚 Learning: 2025-10-14T09:56:14.047Z
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 564
File: test-integration/programs/flexi-counter/src/processor/call_handler.rs:122-125
Timestamp: 2025-10-14T09:56:14.047Z
Learning: The file test-integration/programs/flexi-counter/src/processor/call_handler.rs contains a test smart contract used for integration testing, not production code.
Applied to files:
test-integration/test-task-scheduler/tests/test_unauthorized_reschedule.rsmagicblock-processor/src/executor/processing.rsmagicblock-task-scheduler/tests/service.rstest-integration/test-ledger-restore/src/lib.rsprograms/magicblock/src/schedule_task/process_schedule_task.rstest-integration/programs/flexi-counter/src/processor.rstest-integration/test-task-scheduler/tests/test_schedule_task_signed.rstest-integration/test-task-scheduler/tests/test_schedule_error.rstest-kit/src/lib.rstest-integration/test-task-scheduler/tests/test_reschedule_task.rstest-integration/test-task-scheduler/tests/test_schedule_task.rstest-integration/test-task-scheduler/tests/test_cancel_ongoing_task.rsprograms/magicblock/src/schedule_task/process_cancel_task.rs
📚 Learning: 2025-10-21T10:34:59.140Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-accounts-db/src/lib.rs:63-72
Timestamp: 2025-10-21T10:34:59.140Z
Learning: In magicblock-validator, the AccountsDb "stop-the-world" synchronizer is managed at the processor/executor level, not at the AccountsDb API level. Transaction executors in magicblock-processor hold a read lock (sync.read()) for the duration of each slot and release it only at slot boundaries, ensuring all account writes happen under the read lock. Snapshot operations acquire a write lock, blocking until all executors release their read locks. This pattern ensures mutual exclusion between writes and snapshots without requiring read guards in AccountsDb write APIs.
Applied to files:
magicblock-api/src/fund_account.rsmagicblock-processor/src/scheduler/state.rs
📚 Learning: 2025-11-04T10:48:00.070Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: magicblock-processor/src/scheduler/mod.rs:217-219
Timestamp: 2025-11-04T10:48:00.070Z
Learning: In magicblock-validator, the codebase uses a pattern where types containing non-Send/non-Sync fields (like Rc<RefCell<...>>) are marked with unsafe impl Send when they are guaranteed to be confined to a single thread through careful API design and thread spawning patterns.
Applied to files:
magicblock-task-scheduler/src/service.rs
🧬 Code graph analysis (7)
magicblock-processor/src/executor/processing.rs (1)
magicblock-magic-program-api/src/tls.rs (2)
next_task(22-24)clear(26-31)
programs/magicblock/src/magicblock_processor.rs (4)
programs/magicblock/src/utils/instruction_utils.rs (1)
schedule_task(200-209)programs/magicblock/src/schedule_task/process_cancel_task.rs (1)
process_cancel_task(13-52)test-integration/programs/flexi-counter/src/processor.rs (2)
process_cancel_task(458-485)process_schedule_task(401-456)programs/magicblock/src/schedule_task/process_schedule_task.rs (1)
process_schedule_task(18-123)
magicblock-task-scheduler/tests/service.rs (1)
test-kit/src/lib.rs (3)
new(83-85)default(67-69)get_account(281-291)
programs/magicblock/src/schedule_task/process_schedule_task.rs (2)
programs/magicblock/src/utils/accounts.rs (1)
get_instruction_pubkey_with_idx(94-102)magicblock-magic-program-api/src/tls.rs (1)
register_task(17-20)
magicblock-task-scheduler/src/service.rs (4)
magicblock-core/src/link.rs (1)
link(60-89)magicblock-task-scheduler/src/db.rs (2)
new(50-89)path(46-48)magicblock-api/src/magic_validator.rs (1)
start(635-711)magicblock-magic-program-api/src/args.rs (1)
id(142-147)
programs/magicblock/src/schedule_task/process_cancel_task.rs (2)
programs/magicblock/src/utils/accounts.rs (1)
get_instruction_pubkey_with_idx(94-102)magicblock-magic-program-api/src/tls.rs (1)
register_task(17-20)
magicblock-api/src/magic_validator.rs (4)
magicblock-core/src/link.rs (1)
link(60-89)magicblock-task-scheduler/src/db.rs (1)
path(46-48)magicblock-task-scheduler/src/service.rs (1)
new(58-91)magicblock-processor/src/executor/mod.rs (1)
new(68-110)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: run_make_ci_test
- GitHub Check: run_make_ci_lint
- GitHub Check: Build Project
🔇 Additional comments (43)
programs/guinea/Cargo.toml (1)
19-19: Dependency is properly used and necessary.The verification confirms that
magicblock-magic-program-apiis actively imported and used in the guinea crate (programs/guinea/src/lib.rs:4with usages at lines 109 and 130). The dependency addition is justified and follows the existing workspace dependency pattern used throughout the Cargo.toml file.magicblock-task-scheduler/Cargo.toml (1)
32-38: All dev-dependencies are valid and properly used in tests.Verification confirms:
- All 6 crates are defined in the workspace root
Cargo.toml- Test file
magicblock-task-scheduler/tests/service.rsuses guinea, test-kit, magicblock-magic-program-api, and solana-account directly; solana-pubkey and solana-signature are transitively integrated through test-kit- Two integration tests exercise task scheduling functionality (schedule and cancel operations)
magicblock-committor-program/Cargo.toml (1)
32-33: Clarify the purpose and necessity of these feature flags for the PR objective.The addition of
custom-heapandcustom-panicfeatures across multiple crates appears unrelated to the stated PR objective of replacing ticker-based task scheduling with thread-local storage. These features should either be:
- Documented with a clear explanation of their necessity, or
- Moved to a separate PR if they're orthogonal to this refactoring.
Provide clarification on:
- Why are
custom-heapandcustom-panicfeatures required for the TLS task scheduling refactoring?- Are these features documented in an RFC or design document?
- Are they gated by conditional compilation logic that ties to the scheduler changes?
If these features are preparatory/future work, consider extracting them to a separate infrastructure improvement PR to keep this PR focused on the task scheduling objective.
magicblock-processor/Cargo.toml (1)
21-21: Remove unused dependency or add integration code.The workspace dependency is properly configured; however,
magicblock-magic-program-apiis not imported or used anywhere in the magicblock-processor codebase. Either remove this dependency frommagicblock-processor/Cargo.tomlline 21, or add the code that integrates it (if this PR is incomplete).⛔ Skipped due to learnings
Learnt from: taco-paco Repo: magicblock-labs/magicblock-validator PR: 564 File: test-integration/programs/flexi-counter/src/processor/call_handler.rs:122-125 Timestamp: 2025-10-14T09:56:14.047Z Learning: The file test-integration/programs/flexi-counter/src/processor/call_handler.rs contains a test smart contract used for integration testing, not production code.programs/magicblock/src/utils/instruction_utils.rs (2)
240-251: Verification confirmed: No issues found.The
CancelTaskinstruction change has been properly implemented end-to-end:
- The processor (
process_cancel_task.rs) expects only one account (the authority at index 0), with no references toTASK_CONTEXT_PUBKEY.- The instruction builder (
cancel_task_instruction) creates a single-account instruction matching the processor's expectation.- All callsites—including internal tests and external programs (guinea, flexi-counter)—pass only the authority account.
- Tests verify the correct behavior: authority must be a signer, unsigned attempts fail appropriately.
The breaking change has been consistently applied throughout the codebase.
211-226: No verification required—changes are properly coordinated.The removal of
TASK_CONTEXT_PUBKEYis correctly implemented across the codebase:
process_schedule_task()expects accounts:[payer (idx 0), ...instruction_accounts (idx 1+)]✓process_cancel_task()expects accounts:[authority (idx 0)]✓- All instruction builders match these expectations ✓
- All callsites are compatible ✓
Minor note: The error message in
process_schedule_taskstill mentions "task context," which is outdated documentation but doesn't affect functionality. Consider updating to reflect the current channel-based architecture.programs/guinea/src/lib.rs (4)
4-6: LGTM!The imports are properly organized and all are necessary for the cross-program invocation functionality.
Also applies to: 12-12, 14-14
27-31: LGTM!The new instruction variants are well-defined and appropriately typed for the task scheduling functionality.
67-75: LGTM!The increment function follows the existing patterns in the file and includes proper error handling.
160-168: LGTM!The instruction handling in the match statement is properly implemented and follows the existing patterns.
test-integration/test-task-scheduler/tests/test_schedule_error.rs (2)
3-3: LGTM!The import change from TASK_CONTEXT_PUBKEY to MAGIC_PROGRAM_ID aligns with the PR's refactoring objective to remove TaskContext-based scheduling.
43-51: LGTM!The instruction constructor calls are properly updated to use MAGIC_PROGRAM_ID, maintaining consistency with the API refactoring.
Also applies to: 128-132
test-kit/src/lib.rs (3)
40-41: LGTM!The NOOP_PROGRAM_ID constant is properly defined with compile-time validation.
127-127: LGTM!The
tasks_txchannel integration is essential for the new event-driven task scheduling architecture.
138-143: NOOP program binary verified — code is ready.The NOOP program binary exists at the specified path. The code follows the established test program initialization pattern.
test-integration/test-task-scheduler/tests/test_reschedule_task.rs (2)
3-3: LGTM!The import change is consistent with the broader refactoring to remove TaskContext-based scheduling.
42-50: LGTM!All instruction constructor calls are consistently updated to use MAGIC_PROGRAM_ID.
Also applies to: 77-85, 168-172
test-integration/test-task-scheduler/src/lib.rs (1)
46-46: LGTM!The TaskSchedulerConfig simplification is consistent with the shift to event-driven task scheduling.
test-integration/test-ledger-restore/src/lib.rs (1)
155-155: LGTM!The formatting change improves code conciseness without affecting functionality.
programs/magicblock/src/magicblock_processor.rs (2)
8-8: LGTM!The removal of
process_process_tasksimport is consistent with the elimination of the ProcessTasks instruction path.
68-73: ProcessTasks removal verified complete.The MagicBlockInstruction enum and match statement in magicblock_processor.rs have been properly updated. ProcessTasks has been completely removed from the codebase with no remaining references, and the ScheduleTask and CancelTask instruction variants are correctly handled. The event-driven scheduling refactoring is complete.
magicblock-config/tests/parse_config.rs (1)
285-285: Verified: TaskSchedulerConfig correctly refactored for event-driven scheduling.The struct definition confirms that
millis_per_tickhas been removed and only theresetfield remains, exactly as shown in the test at line 285. The initializationTaskSchedulerConfig { reset: true }is correct.magicblock-config/src/lib.rs (1)
271-271: LGTM! Tests updated consistently with the new TaskSchedulerConfig API.All test cases correctly reflect the removal of
millis_per_tickfrom the public TaskSchedulerConfig struct, using only theresetfield.Also applies to: 356-356, 438-438, 513-513
test-integration/test-task-scheduler/tests/test_unauthorized_reschedule.rs (1)
3-3: LGTM! Instruction builder correctly updated to remove TaskContext dependency.The removal of
TASK_CONTEXT_PUBKEYfrom both the import and thecreate_schedule_task_ixcalls aligns with the PR's objective to replace task context with thread-local storage.Also applies to: 47-55, 82-90
magicblock-magic-program-api/src/lib.rs (1)
3-3: LGTM! TLS module addition aligns with the event-driven architecture.The new
tlsmodule introduces thread-local storage for task scheduling, replacing the previous TaskContext-based polling approach.magicblock-config/src/task_scheduler.rs (1)
7-24: LGTM! Simplified configuration aligns with the new event-driven architecture.Removing
millis_per_tickis consistent with eliminating ticker-based polling in favor of direct channel-based task notification. The derivedDefaultimplementation simplifies the code.magicblock-config/tests/read_config.rs (1)
204-204: LGTM! Test correctly updated for the new TaskSchedulerConfig API.The test configuration construction is consistent with the removal of
millis_per_tick.test-integration/programs/flexi-counter/src/processor.rs (2)
451-451: LGTM! Correctly removed task_context_info from schedule task invocation.The
invoke_signedcall now correctly omits thetask_context_infoaccount, aligning with the shift to TLS-based task scheduling.
479-482: LGTM! Correctly removed task_context_info from cancel task flow.Both the
AccountMetavector and theinvokecall have been updated to excludetask_context_info, consistent with the removal of TaskContext-based task management.programs/magicblock/src/schedule_task/mod.rs (1)
1-5: LGTM! Module structure simplified by removing ProcessTasks pathway.The removal of
process_process_tasksandutilsmodules aligns with eliminating ticker-based task polling. Only the essential schedule and cancel operations remain, consistent with the new event-driven architecture.magicblock-processor/src/scheduler/state.rs (1)
6-8: LGTM! New task channel properly initialized across all construction sites.The
tasks_txfield successfully introduces event-driven task scheduling by replacing ticker-based polling. Verification confirms the channel is properly initialized in both known construction sites (test-kit and magicblock-api), consistently sourced fromvalidator_channels.tasks_service.magicblock-processor/src/executor/processing.rs (1)
98-99: LGTM: Proper stash cleanup.The unconditional clearing of ExecutionTlsStash after transaction processing (lines 98-99) and in the simulate path (lines 145-147) correctly prevents task leakage between transactions and ensures simulations don't interfere with actual executions.
Also applies to: 145-147
test-integration/test-task-scheduler/tests/test_schedule_task.rs (1)
3-3: LGTM: Test updated to match new instruction signatures.The test correctly updates to use
MAGIC_PROGRAM_IDinstead ofTASK_CONTEXT_PUBKEY, aligning with the removal of TaskContext-based scheduling. The test logic remains functionally equivalent.Also applies to: 42-50, 133-137
magicblock-api/src/fund_account.rs (1)
6-6: LGTM: Simplified account funding aligns with TaskContext removal.The removal of
fund_task_contextand related TaskContext handling is consistent with the architectural shift to TLS-based task scheduling. The code correctly retains only the MagicContext initialization.Also applies to: 74-87
magicblock-processor/src/executor/mod.rs (1)
8-8: LGTM: Clean channel integration.The addition of the
tasks_txchannel toTransactionExecutoris properly wired through initialization and aligns with the new task scheduling architecture.Also applies to: 53-54, 105-105
magicblock-core/src/link/transactions.rs (1)
34-37: Verify unbounded channel choice for scheduled tasks.The use of
UnboundedSender/UnboundedReceivermeans tasks will accumulate in memory without backpressure if the task scheduler service falls behind or hangs. While the send-side error handling (in processing.rs line 89) logs warnings on failure, an unbounded channel can still lead to memory growth.Consider whether a bounded channel with appropriate capacity would provide better resource management, or confirm that unbounded semantics are intentional for the "fire-and-forget" task scheduling model.
programs/magicblock/src/schedule_task/process_cancel_task.rs (2)
3-6: LGTM: Clean migration to TLS-based task cancellation.The refactor from TaskContext manipulation to ExecutionTlsStash registration is clean and correct. Signer validation is properly maintained, and the cancel request is correctly queued for processing.
Also applies to: 36-43
76-79: LGTM: Test updates aligned with TaskContext removal.The tests correctly simplify to only require the payer account, removing the now-unnecessary TaskContext account handling. Test expectations remain functionally equivalent.
Also applies to: 101-104
test-integration/test-task-scheduler/tests/test_schedule_task_signed.rs (1)
2-2: LGTM: Test updated consistently with instruction signature changes.The test correctly updates to use
MAGIC_PROGRAM_IDinstead ofTASK_CONTEXT_PUBKEY, maintaining consistency with other test updates in this PR.Also applies to: 38-46
magicblock-magic-program-api/src/tls.rs (1)
1-32: LGTM: Well-designed thread-local task stash.The implementation correctly uses thread-local storage with interior mutability for per-executor-thread task queuing. Key design points:
- FIFO ordering (push_back/pop_front) is appropriate for task queue semantics
- No size limits on the queues is acceptable because the caller (processing.rs) clears unconditionally after each transaction (line 99) and in simulate paths (line 147), preventing unbounded accumulation
- Thread-local isolation ensures tasks don't leak between executor threads
magicblock-core/src/link.rs (1)
65-86: Task channel wiring LGTM.
Channel creation and hand-off mirror the existing pattern for other endpoints, and wrapping the dispatch receiver inOptionlets downstream consumerstake()ownership safely.magicblock-magic-program-api/src/args.rs (1)
119-148: TaskRequest shape is clean.
The enum plusid()helper keep schedule/cancel aligned and make downstream code straightforward to match on identifiers.magicblock-api/src/magic_validator.rs (1)
332-343: Task scheduler initialization looks solid.
Passing ownership of the dispatchtasks_servicereceiver intoTaskSchedulerService::newhere completes the new TLS-driven flow without leaving dangling consumers.
| let _ = self.tasks_tx.send(task).inspect_err(|_| | ||
| warn!("Scheduled tasks service has hung up and longer running") | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in warning message.
Line 90: "and longer running" should be "is no longer running" for grammatical correctness.
Apply this diff:
- let _ = self.tasks_tx.send(task).inspect_err(|_|
- warn!("Scheduled tasks service has hung up and longer running")
- );
+ let _ = self.tasks_tx.send(task).inspect_err(|_|
+ warn!("Scheduled tasks service has hung up and is no longer running")
+ );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let _ = self.tasks_tx.send(task).inspect_err(|_| | |
| warn!("Scheduled tasks service has hung up and longer running") | |
| ); | |
| let _ = self.tasks_tx.send(task).inspect_err(|_| | |
| warn!("Scheduled tasks service has hung up and is no longer running") | |
| ); |
🤖 Prompt for AI Agents
In magicblock-processor/src/executor/processing.rs around lines 89 to 91, the
warn! message contains a typo "and longer running"; change the log string to
read "is no longer running" for correct grammar. Update the closure passed to
inspect_err so the warn! call prints "Scheduled tasks service has hung up and is
no longer running" (preserving surrounding code and punctuation).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed in b282868
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Dodecahedr0x, thank you for fixing the typo! 🎉
🧠 Learnings used
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: magicblock-processor/src/scheduler/locks.rs:110-122
Timestamp: 2025-11-04T10:53:50.922Z
Learning: In magicblock-processor, the TransactionScheduler runs in a single, dedicated thread and will always remain single-threaded. The `next_transaction_id()` function in scheduler/locks.rs uses `unsafe static mut` which is safe given this architectural guarantee.
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: test-kit/src/lib.rs:275-0
Timestamp: 2025-11-07T13:09:52.253Z
Learning: In test-kit, the transaction scheduler in ExecutionTestEnv is not expected to shut down during tests. Therefore, using `.unwrap()` in test helper methods like `schedule_transaction` is acceptable and will not cause issues in the test environment.
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 596
File: magicblock-processor/src/scheduler.rs:1-1
Timestamp: 2025-10-28T13:15:42.706Z
Learning: In magicblock-processor, transaction indexes were always set to 0 even before the changes in PR #596. The proper transaction indexing within slots will be addressed during the planned ledger rewrite.
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/http/get_program_accounts.rs:17-25
Timestamp: 2025-10-21T13:06:38.900Z
Learning: The magicblock validator does not support ledger forking, so commitment-based state queries (processed/confirmed/finalized) are not applicable. RPC methods can safely ignore commitment and minContextSlot parameters from Solana RPC config objects.
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 587
File: test-manual/Cargo.toml:0-0
Timestamp: 2025-10-26T16:54:39.084Z
Learning: In the magicblock-validator repository, use git branch references (not commit hashes or tags) for the helius-laserstream dependency to allow automatic updates when the branch is pushed to.
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: magicblock-aperture/src/requests/http/get_fee_for_message.rs:25-31
Timestamp: 2025-11-04T13:22:38.811Z
Learning: In magicblock-aperture, request size validation (including limits on message size) is enforced at the request ingestion layer, before handlers like get_fee_for_message are invoked. Therefore, handlers do not need additional size guards on decoded data.
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/encoder.rs:176-187
Timestamp: 2025-10-21T11:00:18.396Z
Learning: In the magicblock validator, the current slot is always the root slot. The SlotEncoder in magicblock-aperture/src/encoder.rs correctly sets `root: slot` because there is no lag between current and root slots in this architecture.
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: magicblock-processor/src/scheduler/mod.rs:217-219
Timestamp: 2025-11-04T10:48:00.070Z
Learning: In magicblock-validator, the codebase uses a pattern where types containing non-Send/non-Sync fields (like Rc<RefCell<...>>) are marked with unsafe impl Send when they are guaranteed to be confined to a single thread through careful API design and thread spawning patterns.
If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
magicblock-processor/src/executor/processing.rs (1)
54-60: Critical: ExecutionTlsStash not cleared on early return.When a transaction fails to load, the function returns early without clearing the ExecutionTlsStash. Any tasks added during the failed execution will leak into the next transaction, potentially causing incorrect task scheduling.
Apply this diff to clear the stash before the early return:
if let Err(err) = result { let status = Err(err); self.commit_failed_transaction(txn, status.clone()); FAILED_TRANSACTIONS_COUNT.inc(); + ExecutionTlsStash::clear(); tx.map(|tx| tx.send(status)); return; }
♻️ Duplicate comments (2)
magicblock-task-scheduler/tests/service.rs (1)
74-87: Remove redundant sleep before polling loop.The fixed 10ms sleep at line 75 is unnecessary because the polling loop (lines 78-84) immediately follows and will efficiently wait for the account mutation. The polling loop already handles the timing correctly with its 20ms interval and 1-second timeout.
Apply this diff to remove the redundant sleep:
- // Wait the task scheduler to receive the task - tokio::time::sleep(Duration::from_millis(10)).await; - // Wait until the task scheduler actually mutates the account (with an upper bound to avoid hangs) tokio::time::timeout(Duration::from_secs(1), async {magicblock-processor/src/executor/processing.rs (1)
89-91: Already flagged: Typo in warning message + optional improvement.The typo "and longer running" → "is no longer running" was already flagged in a previous review.
Additionally, the error is not captured in the closure, so the actual error details aren't logged. Consider capturing and logging it for better diagnostics.
Apply this diff to fix both issues:
- let _ = self.tasks_tx.send(task).inspect_err(|_| - warn!("Scheduled tasks service has hung up and is longer running") + let _ = self.tasks_tx.send(task).inspect_err(|e| + warn!("Scheduled tasks service has hung up and is no longer running: {e}") );
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
magicblock-processor/src/executor/processing.rs(4 hunks)magicblock-task-scheduler/tests/service.rs(1 hunks)programs/guinea/src/lib.rs(5 hunks)programs/magicblock/src/validator.rs(1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-11-07T13:09:52.253Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: test-kit/src/lib.rs:275-0
Timestamp: 2025-11-07T13:09:52.253Z
Learning: In test-kit, the transaction scheduler in ExecutionTestEnv is not expected to shut down during tests. Therefore, using `.unwrap()` in test helper methods like `schedule_transaction` is acceptable and will not cause issues in the test environment.
Applied to files:
magicblock-processor/src/executor/processing.rsmagicblock-task-scheduler/tests/service.rs
📚 Learning: 2025-11-07T13:20:13.793Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: magicblock-processor/src/scheduler/coordinator.rs:227-238
Timestamp: 2025-11-07T13:20:13.793Z
Learning: In magicblock-processor's ExecutionCoordinator (scheduler/coordinator.rs), the `account_contention` HashMap intentionally does not call `shrink_to_fit()`. Maintaining slack capacity is beneficial for performance by avoiding frequent reallocations during high transaction throughput. As long as empty entries are removed from the map (which `clear_account_contention` does), the capacity overhead is acceptable.
Applied to files:
magicblock-processor/src/executor/processing.rsprograms/guinea/src/lib.rsmagicblock-task-scheduler/tests/service.rs
📚 Learning: 2025-10-21T14:00:54.642Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579
Applied to files:
programs/guinea/src/lib.rs
📚 Learning: 2025-11-07T14:20:31.425Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 621
File: magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs:457-495
Timestamp: 2025-11-07T14:20:31.425Z
Learning: In magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs, the unsubscribe closure returned by PubSubConnection::account_subscribe(...) resolves to () (unit), not a Result. Downstream code should not attempt to inspect an unsubscribe result and can optionally wrap it in a timeout to guard against hangs.
Applied to files:
programs/guinea/src/lib.rsmagicblock-task-scheduler/tests/service.rs
📚 Learning: 2025-10-14T09:56:14.047Z
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 564
File: test-integration/programs/flexi-counter/src/processor/call_handler.rs:122-125
Timestamp: 2025-10-14T09:56:14.047Z
Learning: The file test-integration/programs/flexi-counter/src/processor/call_handler.rs contains a test smart contract used for integration testing, not production code.
Applied to files:
magicblock-task-scheduler/tests/service.rs
🧬 Code graph analysis (2)
magicblock-processor/src/executor/processing.rs (1)
magicblock-magic-program-api/src/tls.rs (2)
next_task(22-24)clear(26-31)
magicblock-task-scheduler/tests/service.rs (2)
programs/magicblock/src/validator.rs (1)
init_validator_authority_if_needed(54-62)test-kit/src/lib.rs (1)
new(83-85)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: run_make_ci_lint
- GitHub Check: run_make_ci_test
- GitHub Check: Build Project
🔇 Additional comments (15)
magicblock-task-scheduler/tests/service.rs (9)
1-18: LGTM!The imports are well-organized and all appear necessary for the integration tests.
19-45: LGTM! Test setup is thorough.The test properly initializes the execution environment, validator authority, and task scheduler service. The use of
expecton the ledger parent path and tasks service is acceptable in test code.
47-72: LGTM! Task scheduling logic is correct.The test correctly constructs a ScheduleTask instruction with a single Increment instruction and properly asserts the transaction execution succeeds.
77-87: LGTM! Polling loop properly addresses past flakiness concerns.The bounded retry with timeout and polling correctly replaces the previous fixed sleep, making the test resilient to scheduler timing variations. The 20ms poll interval and 1-second timeout are reasonable values.
89-92: LGTM! Cleanup is correct.Canceling the token and awaiting the handle ensures proper shutdown of the task scheduler service.
Based on learnings
151-166: LGTM! Polling loop properly addresses past flakiness concerns.The bounded retry correctly waits until at least 5 executions are observed before proceeding with cancellation. The 20ms poll interval and 2-second timeout are appropriate for this test.
168-183: LGTM! Task cancellation logic is correct.The test properly constructs and executes the CancelTask instruction.
196-209: LGTM! Cancellation verification is thorough.The test correctly waits for multiple intervals after cancellation and verifies that the account value remains unchanged, confirming that the scheduler stopped executing the task.
211-214: LGTM! Cleanup is correct.Canceling the token and awaiting the handle ensures proper shutdown of the task scheduler service.
Based on learnings
magicblock-processor/src/executor/processing.rs (2)
98-99: LGTM: Unconditional stash clearing.The stash is correctly cleared after transaction processing, ensuring no tasks leak between transactions (once the early-return issue at line 60 is fixed).
145-147: LGTM: Simulation stash clearing.Correctly clears the stash after simulation without draining tasks, preventing simulations from scheduling actual tasks or interfering with real execution.
programs/guinea/src/lib.rs (4)
4-14: LGTM! Imports are appropriate for CPI.All new imports (
ScheduleTaskArgs,MagicBlockInstruction,AccountMeta,Instruction,invoke) are properly used in the new task scheduling functions.
23-32: LGTM! New instruction variants are well-defined.The
Increment,ScheduleTask, andCancelTaskvariants are properly typed and consistent with the existing enum style.
104-114: Good! Past review feedback has been addressed.The previous review flagged that
_magic_program_infowas extracted but never validated. The current implementation correctly:
- Removes the underscore prefix (line 104)
- Validates the program ID matches
magicblock_magic_program_api::ID(lines 108-110)- Validates the payer is a signer (lines 112-114)
176-184: LGTM! Instruction routing is correct.The new instruction variants are properly routed to their respective handler functions with appropriate error propagation.
| self.commit_accounts(feepayer, &processed, is_replay); | ||
|
|
||
| // And commit transaction to the ledger | ||
| // Commit transaction to the ledger and schedule tasks and intents (if any) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment mentions intents but code doesn't process them.
The comment references scheduling intents, but the code at lines 86-92 only drains and sends tasks. Intents are cleared at line 99 but never processed.
If intents are not yet implemented or handled elsewhere, consider updating the comment for clarity.
Apply this diff if intents are not handled here:
- // Commit transaction to the ledger and schedule tasks and intents (if any)
+ // Commit transaction to the ledger and schedule tasks (if any)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Commit transaction to the ledger and schedule tasks and intents (if any) | |
| // Commit transaction to the ledger and schedule tasks (if any) |
🤖 Prompt for AI Agents
magicblock-processor/src/executor/processing.rs around line 80: the inline
comment mentions "schedule tasks and intents" but the surrounding code only
drains and schedules tasks and then clears intents without processing them;
either update the comment to remove or clarify the intents part if intent
handling is implemented elsewhere, or implement intent processing here (drain
intents like tasks, schedule/send them appropriately before clearing, and handle
errors/metrics similarly to tasks). Ensure the final comment accurately reflects
the implemented behavior.
| #[tokio::test] | ||
| pub async fn test_cancel_task() -> TaskSchedulerResult<()> { | ||
| let mut env = ExecutionTestEnv::new(); | ||
| let account = | ||
| env.create_account_with_config(LAMPORTS_PER_SOL, 1, guinea::ID); | ||
|
|
||
| init_validator_authority_if_needed(env.payer.insecure_clone()); | ||
|
|
||
| let token = CancellationToken::new(); | ||
| let task_scheduler_db_path = SchedulerDatabase::path( | ||
| env.ledger | ||
| .ledger_path() | ||
| .parent() | ||
| .expect("ledger_path didn't have a parent, should never happen"), | ||
| ); | ||
| let handle = TaskSchedulerService::new( | ||
| &task_scheduler_db_path, | ||
| &TaskSchedulerConfig::default(), | ||
| env.transaction_scheduler.clone(), | ||
| env.dispatch | ||
| .tasks_service | ||
| .take() | ||
| .expect("Tasks service should be initialized"), | ||
| env.ledger.latest_block().clone(), | ||
| token.clone(), | ||
| )? | ||
| .start()?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider extracting common setup into a helper function.
The setup code (lines 97-121) is nearly identical to lines 21-45 in test_schedule_task. Extracting the common initialization logic into a helper function would reduce duplication and improve maintainability.
Example helper function:
async fn setup_test_env_with_scheduler(
) -> TaskSchedulerResult<(
ExecutionTestEnv,
Signer,
tokio::task::JoinHandle<TaskSchedulerResult<()>>,
CancellationToken,
)> {
let mut env = ExecutionTestEnv::new();
let account = env.create_account_with_config(LAMPORTS_PER_SOL, 1, guinea::ID);
init_validator_authority_if_needed(env.payer.insecure_clone());
let token = CancellationToken::new();
let task_scheduler_db_path = SchedulerDatabase::path(
env.ledger
.ledger_path()
.parent()
.expect("ledger_path didn't have a parent, should never happen"),
);
let handle = TaskSchedulerService::new(
&task_scheduler_db_path,
&TaskSchedulerConfig::default(),
env.transaction_scheduler.clone(),
env.dispatch
.tasks_service
.take()
.expect("Tasks service should be initialized"),
env.ledger.latest_block().clone(),
token.clone(),
)?
.start()?;
Ok((env, account, handle, token))
}🤖 Prompt for AI Agents
In magicblock-task-scheduler/tests/service.rs around lines 95 to 121, the test
setup (creating ExecutionTestEnv, account, initializing validator authority,
creating CancellationToken, resolving SchedulerDatabase.path, and starting
TaskSchedulerService) is duplicated from test_schedule_task; extract this
sequence into a single helper function (e.g., setup_test_env_with_scheduler)
that returns the env, account/signers, the started TaskSchedulerService handle,
and the token, replace the duplicated lines in both tests with a call to that
helper, and update imports and return types to use TaskSchedulerResult as
needed.
| let value_at_cancel = env | ||
| .get_account(account.pubkey()) | ||
| .data() | ||
| .first() | ||
| .copied() | ||
| .unwrap_or_default(); | ||
| assert!( | ||
| value_at_cancel >= executed_before_cancel, | ||
| "value regressed before cancellation" | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Clarify assertion message.
The assertion checks that the value at cancellation time is at least as large as the value observed when we detected 5 executions. However, the message "value regressed before cancellation" is slightly misleading—this assertion fires when the value at cancel time is LESS than expected, which would actually be impossible given that time has passed and the scheduler may have executed more iterations. Consider a more descriptive message.
Apply this diff to clarify the assertion:
assert!(
value_at_cancel >= executed_before_cancel,
- "value regressed before cancellation"
+ "unexpected: value at cancellation ({}) < value when 5 executions were observed ({})",
+ value_at_cancel,
+ executed_before_cancel
);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let value_at_cancel = env | |
| .get_account(account.pubkey()) | |
| .data() | |
| .first() | |
| .copied() | |
| .unwrap_or_default(); | |
| assert!( | |
| value_at_cancel >= executed_before_cancel, | |
| "value regressed before cancellation" | |
| ); | |
| let value_at_cancel = env | |
| .get_account(account.pubkey()) | |
| .data() | |
| .first() | |
| .copied() | |
| .unwrap_or_default(); | |
| assert!( | |
| value_at_cancel >= executed_before_cancel, | |
| "unexpected: value at cancellation ({}) < value when 5 executions were observed ({})", | |
| value_at_cancel, | |
| executed_before_cancel | |
| ); |
🤖 Prompt for AI Agents
In magicblock-task-scheduler/tests/service.rs around lines 185 to 194, the
assertion message "value regressed before cancellation" is misleading; change it
to a clearer message that indicates the observed value at cancellation is
unexpectedly lower than the value recorded when we detected 5 executions (e.g.,
"value at cancellation is less than value observed at 5 executions" or "value
decreased between detection and cancellation"). Replace the assertion's message
string with one of these clearer, more descriptive messages so future failures
show the precise expectation.
| fn increment(accounts: slice::Iter<AccountInfo>) -> ProgramResult { | ||
| for a in accounts { | ||
| let mut data = a.try_borrow_mut_data()?; | ||
| let first = | ||
| data.first_mut().ok_or(ProgramError::AccountDataTooSmall)?; | ||
| *first += 1; | ||
| } | ||
| Ok(()) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider overflow behavior in increment operation.
The increment operation on line 72 will wrap around when the byte value reaches 255 (wrapping to 0). If this wrapping behavior is unintended, consider adding an overflow check:
- *first += 1;
+ *first = first.checked_add(1).ok_or(ProgramError::ArithmeticOverflow)?;However, for a test program like guinea, the wrapping behavior may be acceptable or even intentional.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In programs/guinea/src/lib.rs around lines 67 to 75, the byte increment at line
72 will wrap from 255 to 0; if that is unintended, replace the direct addition
with a checked add and return an error when overflow would occur (e.g., use
u8::checked_add on *first and map None to an appropriate ProgramError or custom
error), or explicitly document the wrapping behavior if intentional. Ensure you
borrow_mut, perform the checked add, set the byte only on success, and return a
clear error when overflow is detected.
| let ix = Instruction::new_with_bincode( | ||
| magicblock_magic_program_api::ID, | ||
| &MagicBlockInstruction::ScheduleTask(args), | ||
| vec![ | ||
| AccountMeta::new(*payer_info.key, true), | ||
| AccountMeta::new(*counter_pda_info.key, false), | ||
| ], | ||
| ); | ||
|
|
||
| invoke(&ix, &[payer_info.clone(), counter_pda_info.clone()])?; | ||
|
|
||
| Ok(()) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include the magic program account in the CPI invoke call.
While the magic_program_info is correctly validated (lines 108-110), it should also be included in the invoke call on line 125. In Solana CPI, passing the program account to invoke is a standard practice that allows the runtime to verify the program is executable and matches the expected program ID.
Apply this diff:
- invoke(&ix, &[payer_info.clone(), counter_pda_info.clone()])?;
+ invoke(
+ &ix,
+ &[
+ magic_program_info.clone(),
+ payer_info.clone(),
+ counter_pda_info.clone(),
+ ],
+ )?;🤖 Prompt for AI Agents
In programs/guinea/src/lib.rs around lines 116 to 128, the CPI invoke call omits
the validated magic_program_info account; add magic_program_info.clone() to the
slice of account infos passed to invoke so the runtime can verify the program
account (e.g. invoke(&ix, &[payer_info.clone(), counter_pda_info.clone(),
magic_program_info.clone()])?), keeping the Instruction as-is since the program
ID was already set to magicblock_magic_program_api::ID and ensuring the added
account is the same magic_program_info validated on lines ~108-110.
| if magic_program_info.key != &magicblock_magic_program_api::ID { | ||
| return Err(ProgramError::InvalidAccountData); | ||
| } | ||
|
|
||
| if !payer_info.is_signer { | ||
| return Err(ProgramError::MissingRequiredSignature); | ||
| } | ||
|
|
||
| let ix = Instruction::new_with_bincode( | ||
| magicblock_magic_program_api::ID, | ||
| &MagicBlockInstruction::CancelTask { task_id }, | ||
| vec![AccountMeta::new(*payer_info.key, true)], | ||
| ); | ||
|
|
||
| invoke(&ix, &[payer_info.clone()])?; | ||
|
|
||
| Ok(()) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include the magic program account in the CPI invoke call.
Similar to schedule_task, the magic_program_info should be included in the invoke call on line 151 for proper CPI execution.
Apply this diff:
- invoke(&ix, &[payer_info.clone()])?;
+ invoke(&ix, &[magic_program_info.clone(), payer_info.clone()])?;🤖 Prompt for AI Agents
In programs/guinea/src/lib.rs around lines 137 to 154, the CPI invoke call only
passes payer_info but must include the magic program account as well; update the
invoke call to pass both payer_info.clone() and magic_program_info.clone() (in
the same order expected by the callee) so the CPI has the program account
available during execution.
| pub fn init_validator_authority_if_needed(keypair: Keypair) { | ||
| let mut validator_authority_lock = VALIDATOR_AUTHORITY | ||
| .write() | ||
| .expect("RwLock VALIDATOR_AUTHORITY poisoned"); | ||
| if validator_authority_lock.as_ref().is_some() { | ||
| return; | ||
| } | ||
| validator_authority_lock.replace(keypair); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
LGTM! Idempotent initialization pattern is correct and aligns with PR objectives.
The function correctly implements idempotent initialization by acquiring a write lock, checking if the authority is already set, and returning early if so. This enables stable initialization without panics, supporting the task scheduler refactor.
Optional: Consider reducing code duplication.
Lines 55-57 and 58-60 are duplicated across three initialization functions (init_validator_authority, init_validator_authority_if_needed, and generate_validator_authority_if_needed). Consider extracting a helper function to reduce duplication:
fn with_validator_authority_lock<F>(f: F)
where
F: FnOnce(&mut Option<Keypair>),
{
let mut lock = VALIDATOR_AUTHORITY
.write()
.expect("RwLock VALIDATOR_AUTHORITY poisoned");
f(&mut lock);
}Optional: Add logging or return value to indicate initialization state.
The function silently does nothing if the authority is already set. While the _if_needed naming makes this clear, consider logging when initialization is skipped or returning a bool to indicate whether initialization occurred. This can help with debugging and prevent subtle bugs where a caller expects to set a specific keypair but a different one was already set.
🤖 Prompt for AI Agents
programs/magicblock/src/validator.rs around lines 54 to 62, duplicate
lock-and-init logic appears in init_validator_authority,
init_validator_authority_if_needed, and generate_validator_authority_if_needed;
extract a small helper that acquires the VALIDATOR_AUTHORITY write lock and
invokes a closure with &mut Option<Keypair> to centralize the lock handling and
mutation, then refactor the three functions to call that helper instead of
repeating the lock/replace pattern; additionally consider changing the
_if_needed variant to return a bool indicating whether it performed
initialization (or emit a debug log when initialization is skipped or performed)
so callers can observe the outcome.
Fix #523
This PR is a draft based on #608, which is also currently a draft. It reduces overhead by receiving new tasks instead of periodically deserializing the task context. It also introduces new task scheduler tests using
test-kitSummary by CodeRabbit
New Features
Bug Fixes / Behavior
Tests
Chores