Skip to content

fix: disable Chainlink for replicas#1238

Open
thlorenz wants to merge 28 commits into
masterfrom
thlorenz/replica-chainlink-simple
Open

fix: disable Chainlink for replicas#1238
thlorenz wants to merge 28 commits into
masterfrom
thlorenz/replica-chainlink-simple

Conversation

@thlorenz
Copy link
Copy Markdown
Collaborator

@thlorenz thlorenz commented May 22, 2026

Summary

Disable Chainlink-dependent behavior when the validator runs as a replica, while keeping Chainlink enabled for standalone and primary modes.

CLOSES: #1203

NOTE: this does not disable the comittor service in those replica modes, but it totally could. That part could be done in a follow up PR if we want to implement it.

Details

Chainlink

Adds a replication-mode-aware Chainlink wrapper that can run either with the full Chainlink stack or in a disabled mode for replicas. Disabled mode avoids remote account fetching and subscriptions while preserving the account-bank reset behavior needed during replication startup.

Aperture RPC

Gates RPC paths that require on-chain interaction so replicas serve local account reads but reject primary-only transaction flows with a clear error. This prevents replica nodes from attempting Chainlink-backed fetches or transaction account preparation.

Validator and replication services

Initializes disabled Chainlink for replica mode and passes a reset-capable Chainlink handle into replication instead of relying on a Chainlink-shaped stub. Replication services are made generic over the account-bank resetter interface so they only depend on the cleanup behavior they need.

Tests

Adds coverage for mode-aware Chainlink behavior, replica RPC gating, validator replication-mode selection, and the resetter plumbing used by replication services.

Summary by CodeRabbit

  • New Features

    • RPCs now enforce coordination mode: sendTransaction and simulateTransaction only run in primary mode.
    • Account reads and ensure flows can bypass on-chain interactions and return local account data when on-chain actions are disallowed.
  • Bug Fixes

    • Chainlink behaviour is replication-mode aware: non-primary modes disable on-chain operations and produce safe defaults or explicit errors.
  • Tests

    • Added/updated tests for primary-only RPC enforcement and disabled-mode chainlink behavior.

Review Change Stack

bmuddha and others added 22 commits May 21, 2026 14:48
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

This PR makes chainlink replication-mode aware by adding ReplicationModeAwareChainlink (enabled/disabled variants), introduces production type aliases (ProdInnerChainlink/ProdChainlink), and a new AccountsBankResetter trait. RPC handlers are gated by CoordinationMode (require_primary_rpc_method/needs_onchain_interactions) to reject primary-only operations in replica mode. The replicator and related contexts are generalized to accept an AccountsBankResetter and invoke reset during role transitions. Tests and test setups are updated to construct InnerChainlink and wrap it as enabled where appropriate.

Assessment against linked issues

Objective Addressed Explanation
Disable chainlink outside of primary mode [#1203]
Prevent on-chain operations in non-primary modes [#1203]
Mode-aware committor service [#1203]
Introduce CoordinationMode awareness [#1203]

Suggested reviewers

  • GabrielePicco
  • snawaz
  • bmuddha
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch thlorenz/replica-chainlink-simple

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
Copy Markdown
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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
magicblock-api/src/magic_validator.rs (2)

236-246: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Replace the startup .expect() with a typed error.

Line 238 will panic the validator if replication_messages was already taken or not initialized. Please return an ApiError here instead of aborting startup.

As per coding guidelines, "Treat any usage of .unwrap() or .expect() in production Rust code as a MAJOR issue."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@magicblock-api/src/magic_validator.rs` around lines 236 - 246, The code
currently calls dispatch.replication_messages.take().expect(...) which can
panic; replace this .expect() with a typed ApiError return so startup fails
gracefully. Update the block constructing ReplicationService (where you access
dispatch.replication_messages and call ReplicationService::new) to call
dispatch.replication_messages.take().ok_or_else(|| ApiError::new("...")) or
map_err to convert the None case into an ApiError and propagate it (using ?),
ensuring the enclosing function's signature returns Result<..., ApiError> so the
error is returned instead of panicking. Ensure the ApiError includes a clear
message like "replication channel missing or already taken" and adjust any call
sites to handle the propagated error.

216-218: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Replica mode still eagerly boots the commit pipeline.

init_committor_service still always starts CommittorService, and scheduled_commits_processor is still built from it, so ReplicationMode::Replica keeps the primary-only commit path alive even though this PR disables Chainlink/RPC on replicas. Please gate both on the same replica-only predicate used for Chainlink, or make the replica-safe invariant explicit and tested.

Also applies to: 293-300, 450-468

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@magicblock-api/src/magic_validator.rs` around lines 216 - 218, The code
currently always starts the CommittorService via
Self::init_committor_service(...) and constructs scheduled_commits_processor
even when running in ReplicationMode::Replica; gate both the CommittorService
startup and any construction/use of scheduled_commits_processor behind the same
replica predicate used for Chainlink/RPC (i.e., only start when NOT
ReplicationMode::Replica) or make an explicit replica-safe invariant with tests;
update the call sites that invoke init_committor_service and build
scheduled_commits_processor (including the other occurrences noted around
init_committor_service/CommittorService usage) to check the replication
mode/config before initializing the service or processor, and add a
unit/integration test that verifies replicas do not start the commit pipeline.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@magicblock-api/src/magic_validator.rs`:
- Around line 236-246: The code currently calls
dispatch.replication_messages.take().expect(...) which can panic; replace this
.expect() with a typed ApiError return so startup fails gracefully. Update the
block constructing ReplicationService (where you access
dispatch.replication_messages and call ReplicationService::new) to call
dispatch.replication_messages.take().ok_or_else(|| ApiError::new("...")) or
map_err to convert the None case into an ApiError and propagate it (using ?),
ensuring the enclosing function's signature returns Result<..., ApiError> so the
error is returned instead of panicking. Ensure the ApiError includes a clear
message like "replication channel missing or already taken" and adjust any call
sites to handle the propagated error.
- Around line 216-218: The code currently always starts the CommittorService via
Self::init_committor_service(...) and constructs scheduled_commits_processor
even when running in ReplicationMode::Replica; gate both the CommittorService
startup and any construction/use of scheduled_commits_processor behind the same
replica predicate used for Chainlink/RPC (i.e., only start when NOT
ReplicationMode::Replica) or make an explicit replica-safe invariant with tests;
update the call sites that invoke init_committor_service and build
scheduled_commits_processor (including the other occurrences noted around
init_committor_service/CommittorService usage) to check the replication
mode/config before initializing the service or processor, and add a
unit/integration test that verifies replicas do not start the commit pipeline.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9a5500b7-ffec-40c0-a4bb-d7a76c9e0a02

📥 Commits

Reviewing files that changed from the base of the PR and between e054070 and 9ba4d74.

📒 Files selected for processing (17)
  • magicblock-accounts/src/scheduled_commits_processor.rs
  • magicblock-aperture/src/requests/http/mod.rs
  • magicblock-aperture/src/requests/http/send_transaction.rs
  • magicblock-aperture/src/requests/http/simulate_transaction.rs
  • magicblock-aperture/src/state/mod.rs
  • magicblock-aperture/src/tests.rs
  • magicblock-aperture/tests/setup.rs
  • magicblock-api/src/magic_validator.rs
  • magicblock-chainlink/src/chainlink/errors.rs
  • magicblock-chainlink/src/chainlink/mod.rs
  • magicblock-chainlink/tests/utils/test_context.rs
  • magicblock-replicator/src/service/context.rs
  • magicblock-replicator/src/service/mod.rs
  • magicblock-replicator/src/service/primary.rs
  • magicblock-replicator/src/service/replica.rs
  • test-integration/test-chainlink/src/ixtest_context.rs
  • test-integration/test-chainlink/src/test_context.rs

@thlorenz
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@thlorenz
Copy link
Copy Markdown
Collaborator Author

@CodeRabbit resume

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

✅ Actions performed

Reviews resumed.

@thlorenz thlorenz marked this pull request as ready for review May 22, 2026 08:18
Base automatically changed from bmuddha/fix/disable-auto-failover to master May 26, 2026 07:51
thlorenz added 2 commits May 27, 2026 14:11
* master:
  fix: replication protocol  (#1247)
  fix: delegated account evictions (#1216)
  fix(replicator): disable automatic failover (#1228)
  Fix same-slot account refetch (#1242)
  fix: onchain startup setup (#1244)
  fix: prohobit commits of confined & ephemeral accs via IntentBundles (#1236)
  fix: reset owner to default when closing buffer accounts (#1241)
  Fix eATA projection min-context refetch (#1240)
  Stop RPC servers promptly on shutdown (#1237)
  fix: validate min_interval (#1234)
  feat: derive crank signer from task authority (#1188)
  feat: batch cranks (#1190)
* master:
  fix: various correctness related enhancements  (#1248)
// Magic Router compatibility methods.
pub(crate) mod get_delegation_status;

#[cfg(test)]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

these tests verify something which is obvious from reading the code, they are overly verbose and add very little value, if you think they are absolutely necessary, then please add a proper full coverage in tests directory to respective modules

if Self::replication_mode_uses_disabled_chainlink(
&config.validator.replication_mode,
) {
return ChainlinkImpl::disabled(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

arguably could've just used Option to indicate disabled state


/// Shared state for both primary and replica roles.
pub struct ReplicationContext {
pub struct ReplicationContext<R>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

please remove the generic, it's no longer needed, as we do not perform the reset

pub enum Service {
Primary(Primary),
Replica(Replica),
pub enum Service<R>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

ditto, no generic needed, master code doesn't perform the reset or transitions between modes


use std::time::Duration;

use magicblock_chainlink::AccountsBankResetter;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

ditto: no need for the trait

bytes = { workspace = true }
futures = { workspace = true }
magicblock-accounts-db = { workspace = true }
magicblock-chainlink = { workspace = true }
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

no need for the dependency

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.

bug: disable chainlink and committor service outside of primary mode

2 participants