Architecture · Explanation
SVM accounts and deployed SBF programs
The SVM surface gives programs an account-and-instruction model: a signed message declares accounts, signer and writable privileges, and ordered instructions. Native processors and deployed SBF bytecode share this envelope but execute through different machinery.
Native programs are chain-maintained Rust consensus code. Deployed SBF programs are untrusted ELF bytecode executed by the canonical BPFCC GPU VM. Familiar Solana message formats do not imply that the node runs Agave or that every Solana program is compatible.
Account declarations are capabilities
An instruction selects its program and account inputs by indices into the message account list. The message header establishes signer/writable privileges, including loaded addresses for version-0 messages. Those declarations serve both scheduling and authorization.
Two transactions sharing only reads may run independently. A shared key with a writer creates a dependency. Programs that can access dynamic shared state require a more conservative execution path; see execution scheduling.
Within a transaction, a child receives only accounts and privileges allowed by its caller and the authenticated transaction scope. invoke_signed may add signer authority for a program-derived address using the calling program's identity. It cannot turn an arbitrary caller-supplied public key into a signer. Duplicate account aliases represent one account, not independent balances.
An implicit runtime read still matters to scheduling. The executable program, sysvars, and a loader-derived ProgramData account are not free of dependencies merely because they are absent from a guest's ordinary account array.
Dispatch follows program identity and loader state
Known IDs route to native System, Token, loaders, Stake/Vote, address lookup tables, cryptographic handlers, or cross-VM/product processors. Unknown IDs do not become successful no-ops. An executable, supported loader-owned account is resolved to SBF code; unsupported/non-executable accounts fail.
The same transaction journal makes a successful earlier instruction's effects visible to later instructions. Final publication still belongs to the outer transaction. The Instructions sysvar is transaction-scoped metadata, not an account to persist as ordinary application state.
| Loader layout | How executable bytes are resolved |
|---|---|
| BPF Loader v1 | Inline ELF in the executable program account |
| Upgradeable Loader v3 | Program account identifies a canonical ProgramData PDA; owner and non-executable ProgramData state are checked |
| Loader v4 | Inline code after the loader header; lifecycle must allow execution |
All supported layouts converge on a sealed BPFCC artifact. A loader selects code layout and lifecycle, not a local CPU/GPU preference. ProgramData is an authenticated loader-derived read; clients do not need to pass it as a guest AccountInfo. Resolver, loader authentication.
Validate the actual ELF and engine
To inspect an existing artifact locally, follow check a program before deployment. That task checks the CLI header boundary; the engine checks described here establish a broader execution boundary.
Native admission parses, verifies, and compiles ELF into the canonical artifact before execution. Current ELF flags accept zero as SBPF v1 and EF_SBPF_V2 as v2. Other encodings, including v3 and some newer toolchain numeric version flags, reject. Targeting “Solana” in a build command is insufficient to establish this format match. ELF acceptance.
The artifact binds the program bytes, descriptor, generated PTX, read-only data, and code-generation version. Cache warmth may affect latency but must not change this identity or the result. BPFCC emits the ABI-v3 path with deterministic compiled-block selection and interpreter handling; NVIDIA then compiles the resulting PTX for the device.
The solana_rbpf interpreter and x86 JIT are test/oracle mechanisms behind tests or rbpf-oracle. They are not a production fallback when CUDA is unavailable. Historical tier names and SVM_BPF_JIT controls in the oracle module must not be presented as current validator engine selection. Artifact construction, oracle gating.
Executing node roles must pass the GPU and chain-adapter startup checks. A read-only replica applies replicated state and has a different requirement. Node startup.
CPI suspends execution across a checked host boundary
Cross-program invocation, or CPI, uses typed host requests for the C and Rust invocation ABIs. The host owns decoding, PDA derivation, privilege checks, alias reconciliation, child dispatch, and caller-memory refresh. A deployed child executes recursively on the canonical GPU path; a native child uses its explicit processor.
Children return staged images and cannot commit directly. A catchable child error leaves no partial child writes. A canonical transport/engine defect cannot be converted into an ordinary program error that the caller catches and ignores. CPI ownership.
The current CPI limits are depth 4 beyond the top-level frame, 255 account metas, 255 account infos, 10 KiB instruction data, 16 signer groups, 16 seeds per signer, and 32 bytes per seed. These are this implementation's limits, not promises about every upstream version. Constants.
GPU output must prove an authorized account change
A successful GPU terminal is not sufficient to write shared state. The host compares unique account post-images with authenticated input images. It checks unchanged identity and privilege metadata, writable permission, bounded growth, ownership, permitted lamport debits, and conservation.
Data/owner changes must belong to the current program or match an authorized CPI result. A System CPI that assigns an account to the caller can authorize subsequent initialization by that caller; comparing only against the entry owner would incorrectly reject this useful pattern. Account growth is capped at 10 KiB per permitted increase.
The runtime validates total lamports across unique changed accounts and prevents aliases from multiplying value. An execution-wide rollback guard remains armed through registration, host resumptions, and output validation. Failed validation restores the shared journal/proof context instead of leaking a partially accepted child. Post-image authorization, rollback guard.
Compute and compatibility
Compute-budget instructions are parsed as transaction metadata before normal dispatch. Guest instructions, host services, and recursive children consume the remaining allowance. Omitting diagnostic per-charge rows does not disable metering.
Without an explicit limit, the built-in execution allowance is 1.4 million CU per non-budget instruction, capped at the transaction ceiling. Priority-fee pricing without an explicit limit uses a separate 200,000-CU basis. Heap requests span 32–256 KiB; loaded-account data is capped at 64 MiB. Process-level compute overrides are consensus-relevant and require coordinated values across validators. Compute contract, fee details.
A practical compatibility check covers the emitted ELF flags, loader lifecycle, syscall imports, builtin instructions, CPI topology, compute behavior, and state/log/error outputs. Anchor compilation alone proves none of those runtime observations.
Focused evidence includes loader resolver tests, guest-memory/CPI adversarial tests, ABI continuation tests, instruction-level differential fixtures, and bpfcc_anchor_state_oracle. Compare failures, return data, logs, compute, and account metadata as well as successful balances. These suites were inspected during generation; use validation strategy for the relevant artifact and GPU prerequisites.