Solana signing: introduction
Solana is a high-performance blockchain that relies on cryptographic digital signatures to authorize transactions. Signing proves that the holder of a private key explicitly approves the transaction’s actions. Without valid signatures, the network rejects the transaction. Solana uses the Ed25519 signature scheme (an EdDSA construction on a twisted Edwards curve, standardized in RFC 8032). It is fast, secure, and compact:| Artifact | Size |
|---|---|
| Public key (account address) | 32 bytes |
| Private key (secret scalar / seed handling is implementation-defined) | 32 bytes |
| Signature | 64 bytes |
Ed25519 in one mathematical picture (high level)
Ed25519 signs a message (here, the serialized transaction Message bytes). Write for a private key and for the matching public key. The signer produces a 64-byte signature ; verifiers run a deterministic check: Internally, Ed25519 operates on the twisted Edwards curve Curve25519 in Edwards form over a prime field (with a specific cofactor-aware encoding). You do not need the curve equations to use Solana safely—audited SDKs implement RFC 8032—but the usual Edwards shape is: for fixed curve parameters . Scalar multiplication and hashing inside Sign / Verify are defined by the standard; never reimplement them in application code.1. Keypairs and accounts
Every Solana account that can sign transactions is controlled by an Ed25519 keypair:- The public key is the account address (often base58-encoded, e.g.
7EcDhS…). - The private key is used only for signing — never shared.
- Accounts without a private key (Program Derived Addresses, PDAs) cannot sign directly; they are controlled by programs via seeds and CPI rules.
@solana/web3.js in JavaScript or solana-sdk in Rust); the wire format uses the raw 32-byte keys as in the protocol.
2. Transaction structure
A Solana transaction is not signed as an opaque whole. It has two main parts:- An array of signatures (64 bytes each, Ed25519).
- A Message — the payload that signers actually approve.
Wire layout (conceptual)
Serialized transaction format (compact binary on the wire):num_signatures(compact-u16) — number of signatures.signatures— array of 64-byte Ed25519 signatures (order must match signer order in the message).Message— header + account keys + recent blockhash + instructions (+ versioned extras as applicable).
Why “message first, signatures in front” is easy to get wrong
Every required signer signs the same . The signature vector is prepended to the serialized message for broadcast; verification recomputes checks over , not over the signatures.3. The Message (what gets signed)
The Message is serialized to bytes and signed. It contains everything the cluster needs to enforce permissions and execute programs:| Field | Size | Role |
|---|---|---|
| Header | 3 bytes | num_required_signatures (u8), num_readonly_signed_accounts (u8), num_readonly_unsigned_accounts (u8) |
| Account keys | variable | Compact list of 32-byte public keys, in a fixed order (signer+writable → signer+readonly → non-signer+writable → non-signer+readonly) |
| Recent blockhash | 32 bytes | Binds the tx to a short-lived fork context; mitigates replay within the validity window (~150 slots is a common rule of thumb, not a substitute for reading current RPC/cluster policy) |
| Instructions | variable | Compiled instructions: program id index, account indices, opaque data |
Message composition (ordering matters)
4. How signing works (step-by-step)
-
Build the unsigned Message
Create instructions (e.g. transfer SOL, invoke a program), collect all accounts, attach a recent blockhash from RPC, then serialize to bytes . -
Identify signers
Any account marked signer (including the fee payer) must supply a signature. The fee payer is the first account inaccount_keysand typically signs first in the signature list. -
Sign
For each signer in account key order among signers, compute: Pseudocode: -
Assemble
Prepend the signature array (fee payer first, then other signers in the order required by the message). Full wire transaction: signatures + serialized Message. -
Submit
Send to an RPC (e.g.sendTransaction); the leader may include it in a block.
Multi-signer vs single-message
5. How verification works (network side)
When a validator receives the transaction:-
Signature verification (SigVerify)
For each signature slot , take the public key from the ordered account list and check: Implementations batch and parallelize these checks; Ed25519 verification is fast. -
Runtime checks
Enforce that the number of signatures matchesnum_required_signatures, and that writable / signer flags are consistent with the header. Invalid signature → drop before program execution. -
Execution
Only if all checks pass does the transaction proceed to scheduling and program execution.
6. Special cases and advanced topics
- Partial signing — Wallets can add one signature at a time (
partialSign, pass-around flows). Same , signatures accumulated until complete.
- Versioned transactions (v0) — Address Lookup Tables (ALTs) shrink on-chain address lists; signing still binds to the resolved message your SDK builds—always sign what your stack serializes.
- Durable nonces — Alternative to recent blockhash for long-lived or offline signing; semantics differ; use current docs for nonce accounts and danger zones.
- Off-chain message signing — Login / airdrops / proofs: arbitrary bytes with a Solana-specific domain separation; still Ed25519, not the same bytes as a transaction .
- Ed25519 program — On-chain verification of external Ed25519 signatures via the built-in program is a different path from native transaction SigVerify.
7. Practical example (JavaScript-style pseudocode)
Lifecycle and operations (agents / backends)
- Blockhash freshness — Retry with a new blockhash when RPC reports expiry or “blockhash not found”.
- Account order and writable flags — Must match program expectations; silent reordering invalidates signatures or instruction checks.
- Fee payer vs authority — Sponsorship separates who pays rent/fee from who authorizes program logic; govern with policy.
- Simulation — Signature validity does not imply program success; preflight when stakes are high.
Summary
- Signing is Ed25519 over the serialized Message : .
- The Message is the semantic commitment; signatures are proofs prepended on the wire.
- The design favors fast parallel verification and multiple signers per transaction, aligned with Solana’s execution model.
@solana/web3.js, solana-program, Rust solana-sdk, etc.) so serialization and signing stay consensus-compatible.
See also
- Signing overview — Solana next to EVM, Bitcoin, Morpheum
- Solana Transaction Structure — protocol-level reference (official docs)
- Ethereum (EVM) signatures — contrast with ECDSA / digest-first EVM flows
- Morpheum x402 — products that may combine multiple signing contexts
- Agent wallet — wallet patterns for automated signers