Skip to main content
Technical proposal SIMD-0558 Draft

Leader Info Syscall

  1. Idea
  2. Draft
  3. Review
  4. Accept
  5. Implement
  6. Active

Decision brief

Why this proposal matters

Create a new syscall that returns the leader for the current & the next slot. fn sol_get_leader(result: *mut u8) -> u64

Source-backed reading aid · source language: EN

Proposal at a glance

What changes

  • The program was loaded by a loader that does not enforce aligned accesses. The error is SyscallError::UnalignedPointer. This is the same guard the sysvar getter syscalls use. LeaderInfo is a #[repr(C)] struct of four pubkeys, so its alignment is 1. When the loader does enforce alignment, the address is not rejected for being unaligned.
  • result >= 0x4_0000_0000 (MM_INPUT_START, the input region). The error is SyscallError::InvalidPointer. This syscall rejects an input-region destination directly, the same way a sysvar getter does. The check does not depend on SIMD-0459 being active.
  • Any byte in [result, result + 128) is not writable. That includes an unmapped address, a read-only region, and a range that crosses a region boundary. This is an access violation. Address 0 fails here; there is no separate null check.

Stakeholder map

Who is affected

Builders & client teams Medium impact

Programs such as market makers may now use this syscall to better update quotes based on specific and undesirable leader characteristics. This will further improve the robustness of Solana's market-making environment.

Action requirement unknown
Validators & operators Medium impact

The leader_identity and leader_vote fields must be the block producer's identity pubkey and vote account pubkey for the current slot. The next_leader_identity and next_leader_vote fields must be the block producer's identity pubkey and vote account pubkey for slot current_slot + 1.

Action may be required
Users & stakers Impact unknown

No proposal-specific evidence was found for this group.

Action requirement unknown
Governance & ecosystem Impact unknown

No proposal-specific evidence was found for this group.

Action requirement unknown

Exact source revision

Full proposal document

Source-language document. Technical identifiers and evidence remain unchanged. eac20f2994dd

Summary

Create a new syscall that returns the leader for the current & the next slot.

fn sol_get_leader(result: *mut u8) -> u64

Motivation

Currently it is not possible to identify the leader for a given slot fully onchain. This information is needed for market makers to update quotes based on swaps coming in on specific leaders (e.g. a leader is malicious, very remote, or has historically unreliable scheduling characteristics).

New Terminology

No new terminology is introduced by this proposal.

Detailed Design

result is a virtual address. On success the syscall writes 128 bytes of LeaderInfo to [result, result + 128).

Compute units are consumed first. If that exceeds the budget, the virtual machine aborts and no bytes are written.

Otherwise the syscall aborts the virtual machine, without returning to the caller and without writing LeaderInfo, when any of the following are true. The checks run in this order:

  1. The program was loaded by a loader that does not enforce aligned accesses. The error is SyscallError::UnalignedPointer. This is the same guard the sysvar getter syscalls use. LeaderInfo is a #[repr(C)] struct of four pubkeys, so its alignment is 1. When the loader does enforce alignment, the address is not rejected for being unaligned.

  2. result >= 0x4_0000_0000 (MM_INPUT_START, the input region). The error is SyscallError::InvalidPointer. This syscall rejects an input-region destination directly, the same way a sysvar getter does. The check does not depend on SIMD-0459 being active.

  3. Any byte in [result, result + 128) is not writable. That includes an unmapped address, a read-only region, and a range that crosses a region boundary. This is an access violation. Address 0 fails here; there is no separate null check.

If every check passes, the syscall writes LeaderInfo and returns 0.

Returned Result

#[repr(C)]
pub struct LeaderInfo {
    pub leader_identity: Pubkey,
    pub leader_vote: Pubkey,
    pub next_leader_identity: Pubkey,
    pub next_leader_vote: Pubkey
}

The LeaderInfo struct is written to the result formal by the syscall.

The leader_identity and leader_vote fields must be the block producer's identity pubkey and vote account pubkey for the current slot. The next_leader_identity and next_leader_vote fields must be the block producer's identity pubkey and vote account pubkey for slot current_slot + 1.

Returned Value

The syscall itself returns 0 on success. If any validation condition fails, the syscall aborts VM execution without returning to the calling program.

Program Access

Programs may access the LeaderInfo information via the sol_get_leader syscall.

No sysvar is introduced.

CU Cost

The sol_get_leader syscall CU cost is defined as:

$$ \mathtt{sysvar\_base\_cost} + \max \left( \mathtt{mem\_op\_base\_cost}, \left\lfloor \frac{\mathit{sizeof}(\mathtt{LeaderInfo)}} {\mathtt{cpi\_bytes\_per\_unit}} \right\rfloor \right) $$

As of mainnet epoch 1036, this is 110 CU, which matches sol_get_sysvar:

$$ 100 + \max \left( \left\lfloor \frac{128}{250} \right\rfloor, 10 \right) = 110 $$

Leader & Vote Pubkeys

For the duration of an epoch, the leader_identity, leader_vote, next_leader_identity, and next_leader_vote fields must correspond to the canonical leader schedule generated for that epoch. This is to address mid-epoch UpdateValidatorIdentity changes and the fact that multiple vote accounts may correspond to the same identity.

Epoch Boundaries

On the last slot of an epoch, when the next leader is in epoch current_epoch + 1, the next_leader value represents the first leader of the next epoch. This value comes from the next epoch's leader schedule.

Alternatives Considered

  • Add fields to the current Clock. This was rejected as many programs assert invariants like clock.data().len() == 40, so adding fields would break these programs.
  • Only include the current leader. We opted to include both current and next because knowledge of the next leader enables programs to compensate for, for example, the next leader having a history of outright censorship. A program can then take actions to ensure that its state remains valid even if it is censored for the entire next leader window. Even though the current / next leader will usually be the same it is only 110 CU total and other schemes for counting the next leader (i.e, the actual next non-current leader) seemed to have awkward semantics or would exhibit odd behavior on single-node clusters. The % of time that these fields are the same will also decrease as we shorten leader windows.
  • A full LeaderSchedule sysvar containing the entire schedule for the current epoch. This was rejected to avoid variable-length sysvars and because the account would be well over 200,000 bytes. Additionally, getting the current slot from Clock and indexing by window offset makes the current-leader lookup cost O(500) CU instead of O(110) CU here.

Impact

Programs such as market makers may now use this syscall to better update quotes based on specific and undesirable leader characteristics. This will further improve the robustness of Solana's market-making environment.

Programs will need to be recompiled and redeployed to adopt this feature.

Similar to the Clock, programs relying on this syscall may exhibit different behavior if simulated and executed at different slots.

Security Considerations

None

Backwards Compatibility

Programs accessing this syscall could not be used on Solana versions which do not implement it. Existing programs that do not use this syscall are not impacted. Therefore, a feature gate should be used to enable this feature when the majority of the cluster is using the required version.

Evidence graph

Related proposals and rollout

One or more sources are unavailable.

Upstream review record

Upstream discussion & review

GitHub review is editorial context, not evidence of on-chain support, voting, or outcome.

PR #621 · merged SIMD-0558 - Leader Info Syscall 29 comments and reviews · Oct 27, 2026
@buffalojoec

nit: I'm assuming this 100 is sysvarbasecost? This isn't a sysvar, so I wouldn't price it like one. I'd use the variable name syscallbasecost (which is also 100) here instead, in case we ever change syscallbasecost.

GitHub ↗
@soundsonacid

I think this SIMD is now in a much better shape than the original version, but I don't think it makes any sense to have merged it while it is proposing a new syscall instead of using the existing solgetsysvar. Is there some reason why we thought that was a good idea?

GitHub ↗
@buffalojoec

I guess linking back to the discussion I can see why this was framed this way. If we want to make this call available via Static Sysvars, then maybe the framing is okay. I would have liked to hash this out a bit, though.

GitHub ↗
@bw-solana

@buffalojoec that's my fault. I thought we already had SME review on this one for some reason ☠️ let's not let my process fuckup leave us with a suboptimal design. if we just need to tweak things, let's open a PR to amend. if there are big disagreements on the design, let's hash those out in the discussion, abandon this, and re-create

GitHub ↗
@deanmlittle

@buffalojoec that's my fault. I thought we already had SME review on this one for some reason ☠️ let's not let my process fuckup leave us with a suboptimal design. if we just need to tweak things, let's open a PR to amend. if there are big disagreements on the design, let's hash those out in the discussion, abandon this, and re-create No need to abandon. Let's nail it down here and PR later. It's almost there imo. It is my strong preference that we put this in the sysvar cache and use solgetsysvar, and as Trent suggested, not assign it an address or an account. It does not make sense to have a special behavior just for handling this one thing. If we migrate to static sysvars later, not havin

GitHub ↗
@soundsonacid

@buffalojoec that's my fault. I thought we already had SME review on this one for some reason ☠️ let's not let my process fuckup leave us with a suboptimal design. if we just need to tweak things, let's open a PR to amend. if there are big disagreements on the design, let's hash those out in the discussion, abandon this, and re-create No need to abandon. Let's nail it down here and PR later. It's almost there imo. It is my strong preference that we put this in the sysvar cache and use solgetsysvar, and as Trent suggested, not assign it an address or an account. It does not make sense to have a special behavior just for handling this one thing. If we migrate to static sysvars later, not havin

GitHub ↗
@buffalojoec

I'm on board for solgetsysvar as well. @soundsonacid if you don't mind PR'ing an amendment that would be great.

GitHub ↗
@apfitzge

🫠 this is annoying for lookup. See people discussing SIMD-558 - i type issues/558 into github and get led to something that's wrong

GitHub ↗

simd.watch community discussion · SIMD-0558

Powered by Giscus · Sign in with GitHub to comment

Community comments load when this section approaches the viewport.

Provenance

Evidence & technical details

Rollout or chain data, source revisions, freshness and integrity.
2

SIMD

Deployment Status

Document lifecycleDraft
CategoryCore protocol

Feature Gate not yet created

Exact source revision

Sources & integrity

  • Proposal document pinned_commit_blob
    eac20f2994dd064482d96f178a4bbc0f4e358fd0
  • simd-document document · stale · Oct 27, 2026
    eac20f2994dd064482d96f178a4bbc0f4e358fd0

One or more sources are unavailable.