Skip to content

Conversation

@thlorenz
Copy link
Collaborator

@thlorenz thlorenz commented Dec 22, 2025

Summary

Optimize fetching accounts for transactions by skipping account ensure operations for noop system transfer
transactions (where from == to).

This prevents unnecessary account cloning and processing overhead for self-transfer
transactions, which are no-ops that waste transaction fees without meaningful state changes.

Details

A new filter module has been added to magicblock-chainlink to detect noop system transfers
with O(1) performance characteristics.

is_noop_system_transfer filter

The filter identifies transactions that consist of a single system program transfer instruction
where the sender and recipient are the same account. This is detected by:

  1. Verifying the transaction has exactly one instruction
  2. Confirming the instruction is a system program transfer
  3. Checking that the from and to account pubkeys are identical

When detected, the chainlink processor skips the account ensure operation, avoiding unnecessary
account fetches for these no-op transactions.

The implementation includes comprehensive unit tests covering:

  • Self-transfer detection (noop case)
  • Different sender/recipient accounts (normal case)
  • Multiple instructions in a transaction
  • Empty transactions
  • Non-system program instructions

Summary by CodeRabbit

  • New Features
    • Short-circuits no-op system transfers so self-transfers are handled more efficiently, avoiding unnecessary work.
  • Bug Fixes
    • Prevents noop transactions from triggering downstream account-processing logic.
  • Tests
    • Added unit tests covering noop and non-noop transfer scenarios.
  • Chores
    • Repository ownership mappings cleaned up (CODEOWNERS cleared).

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions
Copy link

github-actions bot commented Dec 22, 2025

Manual Deploy Available

You can trigger a manual deploy of this PR branch to testnet:

Deploy to Testnet 🚀

Alternative: Comment /deploy on this PR to trigger deployment directly.

⚠️ Note: Manual deploy requires authorization. Only authorized users can trigger deployments.

Comment updated automatically when the PR is synchronized.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

📝 Walkthrough

Walkthrough

Adds a new filters submodule (declared in lib.rs) containing a crate-visible is_noop_system_transfer function (filters/noop_system_transfer.rs) with unit tests. Re-exports is_noop_system_transfer inside filters. Updates chainlink::ensure_transaction_accounts to call is_noop_system_transfer and early-return a default FetchAndCloneResult with a trace log when a transaction is a noop system transfer. Also removes all entries from .github/CODEOWNERS.


📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3606a4b and 3ad5c9f.

📒 Files selected for processing (1)
  • magicblock-chainlink/src/filters/noop_system_transfer.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • magicblock-chainlink/src/filters/noop_system_transfer.rs
⏰ 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: Build Project
  • GitHub Check: run_make_ci_lint
  • GitHub Check: run_make_ci_test

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
magicblock-chainlink/src/filters/noop_system_transfer.rs (1)

33-36: Consider avoiding the Vec allocation.

The code collects all instructions into a Vec just to check the length. For better performance, consider checking the iterator directly without collecting.

🔎 Proposed optimization
-    let instructions = message.program_instructions_iter().collect::<Vec<_>>();
-    if instructions.len() != 1 {
+    let mut instructions = message.program_instructions_iter();
+    let Some(first) = instructions.next() else {
         return false;
-    }
+    };
+    if instructions.next().is_some() {
+        return false;
+    }

-    let (program_id, instruction) = instructions[0];
+    let (program_id, instruction) = first;
magicblock-chainlink/src/chainlink/mod.rs (1)

290-296: Consider adding metrics tracking for skipped noop transfers.

While the optimization logic is correct, tracking how often this code path is taken would provide valuable insights into the optimization's impact.

🔎 Suggested metric addition
     ) -> ChainlinkResult<FetchAndCloneResult> {
         if is_noop_system_transfer(tx) {
             trace!(
                 "Skipping account ensure for noop system transfer transaction {}",
                 tx.signature()
             );
+            magicblock_metrics::metrics::inc_noop_system_transfer_skipped();
             return Ok(Default::default());
         }

Note: You'll need to add the corresponding metric function in the magicblock-metrics crate.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5cac28b and c04ae15.

📒 Files selected for processing (4)
  • magicblock-chainlink/src/chainlink/mod.rs
  • magicblock-chainlink/src/filters/mod.rs
  • magicblock-chainlink/src/filters/noop_system_transfer.rs
  • magicblock-chainlink/src/lib.rs
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-12-03T09:36:01.527Z
Learnt from: Dodecahedr0x
Repo: magicblock-labs/magicblock-validator PR: 639
File: magicblock-chainlink/src/remote_account_provider/mod.rs:1350-1353
Timestamp: 2025-12-03T09:36:01.527Z
Learning: Repo: magicblock-labs/magicblock-validator
File: magicblock-chainlink/src/remote_account_provider/mod.rs
Context: consolidate_fetched_remote_accounts
Learning: For unexpected result counts (>2), the project prefers logging an error and returning an empty Vec over panicking; acceptable during development per maintainer (Dodecahedr0x).

Applied to files:

  • magicblock-chainlink/src/chainlink/mod.rs
  • magicblock-chainlink/src/lib.rs
📚 Learning: 2025-11-19T09:34:37.917Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 621
File: test-integration/test-chainlink/tests/ix_remote_account_provider.rs:62-63
Timestamp: 2025-11-19T09:34:37.917Z
Learning: In test-integration/test-chainlink/tests/ix_remote_account_provider.rs and similar test files, the `_fwd_rx` receiver returned by `init_remote_account_provider()` is intentionally kept alive (but unused) to prevent "receiver dropped" errors on the sender side. The pattern `let (remote_account_provider, _fwd_rx) = init_remote_account_provider().await;` should NOT be changed to `let (remote_account_provider, _) = ...` because dropping the receiver would cause send() operations to fail.

Applied to files:

  • magicblock-chainlink/src/chainlink/mod.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-chainlink/src/lib.rs
🧬 Code graph analysis (3)
magicblock-chainlink/src/filters/noop_system_transfer.rs (2)
magicblock-chainlink/src/chainlink/mod.rs (2)
  • tx (298-303)
  • tx (520-524)
magicblock-committor-program/src/state/changeset.rs (1)
  • account_keys (255-257)
magicblock-chainlink/src/filters/mod.rs (1)
magicblock-chainlink/src/filters/noop_system_transfer.rs (1)
  • is_noop_system_transfer (29-79)
magicblock-chainlink/src/chainlink/mod.rs (1)
magicblock-chainlink/src/filters/noop_system_transfer.rs (1)
  • is_noop_system_transfer (29-79)
⏰ 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). (4)
  • GitHub Check: Build Project
  • GitHub Check: run_make_ci_lint
  • GitHub Check: run_make_ci_format
  • GitHub Check: run_make_ci_test
🔇 Additional comments (7)
magicblock-chainlink/src/filters/noop_system_transfer.rs (4)

4-28: LGTM!

The documentation is comprehensive, clearly explaining the function's purpose, performance characteristics, arguments, and return value.


48-52: LGTM!

The deserialization and pattern matching correctly identifies only Transfer instructions, filtering out other system instruction types.


56-78: LGTM!

The account validation and bounds checking are correctly implemented. The safe use of get() prevents potential panics from out-of-bounds access.


81-179: LGTM!

The test suite provides comprehensive coverage of the main scenarios: self-transfer detection, different sender/recipient, multiple instructions, empty transactions, and non-system instructions.

magicblock-chainlink/src/filters/mod.rs (1)

1-2: LGTM!

The module structure correctly declares and re-exports the is_noop_system_transfer function with appropriate crate-level visibility.

magicblock-chainlink/src/chainlink/mod.rs (1)

27-27: LGTM!

The import is correctly added to bring in the is_noop_system_transfer function.

magicblock-chainlink/src/lib.rs (1)

10-10: LGTM!

The module declaration correctly introduces the filters module as a private crate-level module, consistent with the pub(crate) visibility of is_noop_system_transfer.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
magicblock-chainlink/src/filters/noop_system_transfer.rs (3)

10-19: Clarify performance claim regarding line 33.

The documentation states "Single iteration through at most 1 instruction (bounded to 1)" but line 33 collects all instructions into a Vec, which is O(n) in the number of instructions. While Solana transactions have bounded instruction counts (making this effectively constant-time in practice), the documentation could be more precise.

🔎 Consider rewording the performance notes
 /// # Performance Notes
 ///
-/// This function is O(1) in terms of iterations:
+/// This function has bounded complexity due to Solana's instruction limits:
 /// - Early return after checking instruction count (constant time)
-/// - Single iteration through at most 1 instruction (bounded to 1)
+/// - Collects all instructions (bounded by Solana's max instructions per transaction)
 /// - Account key lookup is O(1) array indexing
 /// - System instruction deserialization is O(1) for fixed-size data

Alternatively, to make it truly O(1) without allocations, you could avoid the collect():

let mut instructions = message.program_instructions_iter();
let Some((program_id, instruction)) = instructions.next() else {
    return false;
};
if instructions.next().is_some() {
    return false;
}
// ... rest of the logic

32-36: Consider avoiding Vec allocation.

The current implementation collects all instructions into a Vec, which creates an unnecessary allocation. You can check for exactly one instruction more efficiently using iterator methods.

🔎 More efficient alternative
-    // Early exit: Must have exactly 1 instruction
-    let instructions = message.program_instructions_iter().collect::<Vec<_>>();
-    if instructions.len() != 1 {
+    // Early exit: Must have exactly 1 instruction
+    let mut instructions = message.program_instructions_iter();
+    let Some((program_id, instruction)) = instructions.next() else {
         return false;
-    }
+    };
+    if instructions.next().is_some() {
+        return false;
+    }

-    let (program_id, instruction) = instructions[0];
-
     // Check if this is the system program instruction

This avoids the Vec allocation while maintaining the same logic.


81-180: Excellent test coverage!

The test suite comprehensively covers the key scenarios:

  • Positive case: self-transfer detection
  • Different sender/recipient accounts
  • Multiple instructions
  • Empty transactions
  • Non-system program instructions
Optional: Consider additional edge case tests

While the current coverage is sufficient, you could add tests for:

#[test]
fn test_non_transfer_system_instruction() {
    // Test that other SystemInstructions (e.g., Allocate) with same account are not detected
    let payer = Keypair::new();
    let account = Keypair::new();
    let allocate_ix = system_instruction::allocate(&account.pubkey(), 1024);
    
    let message = Message::new(&[allocate_ix], Some(&payer.pubkey()));
    let tx = Transaction::new_unsigned(message);
    let sanitized_tx = SanitizedTransaction::from_transaction_for_tests(tx);
    
    assert!(!is_noop_system_transfer(&sanitized_tx));
}

#[test]
fn test_transfer_with_wrong_account_count() {
    // Test Transfer instruction with incorrect number of accounts
    // (though this would be caught by Solana runtime, it's good to verify the filter behavior)
}

These are optional as the current tests already provide strong coverage.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c04ae15 and 3606a4b.

📒 Files selected for processing (2)
  • .github/CODEOWNERS
  • magicblock-chainlink/src/filters/noop_system_transfer.rs
💤 Files with no reviewable changes (1)
  • .github/CODEOWNERS
⏰ 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 (3)
magicblock-chainlink/src/filters/noop_system_transfer.rs (3)

1-3: LGTM!

The imports are minimal and appropriate for the functionality.


46-58: LGTM!

The instruction parsing and validation logic is correct:

  • Proper error handling for deserialization failures
  • Correctly filters for Transfer variant only
  • Appropriate validation that Transfer instructions have exactly 2 accounts

60-79: LGTM!

The account resolution and comparison logic is robust:

  • Safe casting of account indices
  • Proper bounds checking with Option pattern prevents potential panics
  • Correct pubkey comparison

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants