Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
72bf945
fix: gate non-primary RPC writes
thlorenz May 19, 2026
4b71387
fix: gate chainlink remote sync by mode
thlorenz May 19, 2026
05eeac0
fix: reset bank only before primary
thlorenz May 19, 2026
8c41d84
fix: demote before standby setup
thlorenz May 19, 2026
8412815
feat: add chainlink lifecycle hooks
thlorenz May 19, 2026
9b3c745
test: cover replica RPC side effects
thlorenz May 19, 2026
9d9f7dc
test: cover chainlink replica gating
thlorenz May 19, 2026
98076aa
Merge branch 'master' into thlorenz/replica-aware-chainlink
thlorenz May 20, 2026
7df33b5
test: add replication lifecycle ordering coverage
thlorenz May 20, 2026
59ea8d0
docs: clarify chainlink lifecycle cleanup
thlorenz May 20, 2026
fc9b68b
fix: reject replica transaction simulations
thlorenz May 20, 2026
5e4dd23
chore: simplify step implementations in replicator
thlorenz May 20, 2026
b4102fd
Merge branch 'master' into thlorenz/replica-aware-chainlink
thlorenz May 20, 2026
286fee4
feat: add chainlink lifecycle runtime state
thlorenz May 20, 2026
d170473
feat: add chainlink runtime introspection APIs
thlorenz May 20, 2026
59987ed
feat: add remote account provider shutdown
thlorenz May 20, 2026
8ef9a13
feat: expose deterministic pubsub shutdown
thlorenz May 20, 2026
6b6d810
feat: add fetch cloner shutdown
thlorenz May 20, 2026
f3d5ebc
feat(chainlink): disable runtime asynchronously
thlorenz May 20, 2026
0eb21d3
feat(chainlink): store runtime build config
thlorenz May 20, 2026
75cf215
feat(chainlink): enable primary runtime startup
thlorenz May 20, 2026
69a28af
feat(chainlink): defer endpoint runtime construction
thlorenz May 20, 2026
3832a29
feat(api): publish standalone primary after chainlink readiness
thlorenz May 20, 2026
1bf8b77
feat(replicator): reorder chainlink role transitions
thlorenz May 20, 2026
5e16b20
test(chainlink): cover lifecycle shutdown transitions
thlorenz May 20, 2026
ac87aef
test(chainlink): cover lower-layer shutdown
thlorenz May 20, 2026
9cd44d2
test(lifecycle): cover promotion failure ordering
thlorenz May 20, 2026
2832242
test(chainlink): cover non-primary remote resources
thlorenz May 20, 2026
15a3aff
refactor(chainlink): remove defensive remote sync gates
thlorenz May 20, 2026
7946cc0
test(chainlink): remove obsolete non-primary gate coverage
thlorenz May 20, 2026
0ef111c
fix(chainlink): avoid runtime lock when disabled
thlorenz May 20, 2026
4a9a695
test(chainlink): apply non-primary startup modes
thlorenz May 20, 2026
915ac37
fix: integration tests
thlorenz May 20, 2026
6e995e6
fix: stop deferred pubsub on shutdown
thlorenz May 20, 2026
e00e015
test: cover deferred pubsub shutdown
thlorenz May 20, 2026
7bbc994
chore: simplify primary startup sequence
thlorenz May 21, 2026
67db4fa
fix: propagate scheduler mode send failures
thlorenz May 21, 2026
0ad4ee9
chore: simplify primary readiness sequence
thlorenz May 21, 2026
c8cbea0
fix: roll back primary enable on scheduler failure
thlorenz May 21, 2026
00e9092
Merge branch 'master' into thlorenz/replica-aware-chainlink
thlorenz May 21, 2026
a661b78
feat: add Chainlink lifecycle APIs
thlorenz May 21, 2026
f4bd5ed
feat: wire real Chainlink lifecycle into replication
thlorenz May 21, 2026
bf7793a
feat: gate stubbed Chainlink lifecycle
thlorenz May 21, 2026
dc95c1e
test: add replication readiness ordering coverage
thlorenz May 21, 2026
13dae9f
test: add Chainlink enablement guard coverage
thlorenz May 21, 2026
91cd8d0
feat: add chainlink readiness
thlorenz May 21, 2026
0bd8750
feat: add aperture routing decisions
thlorenz May 21, 2026
2edcee2
feat: fail closed for unready primary reads
thlorenz May 21, 2026
d2200ea
chore: format chainlink readiness
thlorenz May 21, 2026
d488381
feat: gate transaction writes on chainlink readiness
thlorenz May 21, 2026
7cf56a2
feat: wire replication to real chainlink runtime
thlorenz May 21, 2026
6581ed5
test: add primary readiness ordering regressions
thlorenz May 21, 2026
1cb408d
chore: remove duplicate aperture primary gate
thlorenz May 21, 2026
fb0cfef
feat: add chainlink primary readiness outcomes
thlorenz May 21, 2026
a4a5dd3
feat: route replication through primary chainlink
thlorenz May 21, 2026
dde9fb3
feat: centralize aperture readiness routing
thlorenz May 21, 2026
53d1653
test: add aperture readiness routing coverage
thlorenz May 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions magicblock-aperture/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ magicblock-version = { workspace = true }
agave-geyser-plugin-interface = { workspace = true }
solana-account = { workspace = true }
solana-account-decoder = { workspace = true }
solana-commitment-config = { workspace = true }
solana-feature-set = { workspace = true }
solana-fee-structure = { workspace = true }
solana-keypair = { workspace = true }
Expand Down
11 changes: 11 additions & 0 deletions magicblock-aperture/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use solana_transaction_error::TransactionError;

pub(crate) const TRANSACTION_SIMULATION: i16 = -32002;
pub(crate) const TRANSACTION_VERIFICATION: i16 = -32003;
#[allow(dead_code)]
pub(crate) const TEMPORARILY_UNAVAILABLE: i16 = -32004;
pub(crate) const BLOCK_NOT_FOUND: i16 = -32009;
pub(crate) const INVALID_REQUEST: i16 = -32600;
pub(crate) const INVALID_PARAMS: i16 = -32602;
Expand Down Expand Up @@ -145,6 +147,15 @@ impl RpcError {
}
}

#[allow(dead_code)]
pub(crate) fn temporarily_unavailable<E: Display>(error: E) -> Self {
Self {
code: TEMPORARILY_UNAVAILABLE,
message: format!("temporarily unavailable: {error}"),
http_status: 503,
}
}

pub(crate) fn invalid_request<E: Display>(error: E) -> Self {
Self {
code: INVALID_REQUEST,
Expand Down
4 changes: 2 additions & 2 deletions magicblock-aperture/src/requests/http/get_account_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ impl HttpDispatcher {

// `read_account_with_ensure` guarantees the account is clone from chain if not in database.
let account = self
.read_account_with_ensure(&pubkey)
.await
.read_account_with_ensure("getAccountInfo", &pubkey)
.await?
.filter(|acc| !Self::account_should_render_as_null(acc))
// `LockedAccount` provides a race-free read of the account data before encoding.
.map(|acc| {
Expand Down
4 changes: 2 additions & 2 deletions magicblock-aperture/src/requests/http/get_balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ impl HttpDispatcher {
let pubkey = some_or_err!(pubkey_bytes);

let balance = self
.read_account_with_ensure(&pubkey)
.await
.read_account_with_ensure("getBalance", &pubkey)
.await?
.map(|a| a.lamports())
.unwrap_or_default(); // Default to 0 if account not found

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ impl HttpDispatcher {

// Ensure the account is present in the local AccountsDb, cloning it
// from the reference cluster if necessary.
let account = self.read_account_with_ensure(&pubkey).await;
let account = self
.read_account_with_ensure("getDelegationStatus", &pubkey)
.await?;

let is_delegated =
account.as_ref().map(|acc| acc.delegated()).unwrap_or(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ impl HttpDispatcher {
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Base58);
let slice = config.data_slice;

let ensured_accounts = self
.read_accounts_with_ensure("getMultipleAccounts", &pubkeys)
.await?;
let accounts = pubkeys
.iter()
.zip(self.read_accounts_with_ensure(&pubkeys).await.into_iter())
.zip(ensured_accounts.into_iter())
.map(|(pubkey, acc)| {
acc.filter(|account| {
!Self::account_should_render_as_null(account)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ impl HttpDispatcher {

// Fetch the target token account.
let token_account: AccountSharedData = some_or_err!(
self.read_account_with_ensure(&pubkey).await,
self.read_account_with_ensure("getTokenAccountBalance", &pubkey)
.await?,
"token account not found or is not a token account"
);

Expand All @@ -42,7 +43,11 @@ impl HttpDispatcher {

// Fetch the mint account to get the token's decimals.
let mint_account: AccountSharedData = some_or_err!(
self.read_account_with_ensure(&mint_pubkey).await,
self.read_account_with_ensure(
"getTokenAccountBalance",
&mint_pubkey
)
.await?,
"mint account not found"
);
let decimals =
Expand Down
Loading
Loading