Expand description
§Pinocchio
Pinocchio is a zero-dependency library to create Solana programs in Rust. It takes advantage of the way SVM loaders serialize the program input parameters into a byte array that is then passed to the program’s entrypoint to define zero-copy types to read the input – these types are defined in an efficient way taking into consideration that they will be used in on-chain programs.
It is intended to be used by on-chain programs only; for off-chain programs,
use instead the solana-sdk
crate.
§Defining the program entrypoint
A Solana program needs to define an entrypoint, which will be called by the
runtime to begin the program execution. The entrypoint!
macro emits the common
boilerplate to set up the program entrypoint. The macro will also set up global
allocator
and panic handler using
the default_allocator!
and default_panic_handler!
macros.
The entrypoint!
is a convenience macro that invokes three other macros to set
all symbols required for a program execution:
program_entrypoint!
: declares the program entrypointdefault_allocator!
: declares the default (bump) global allocatordefault_panic_handler!
: declares the default panic handler
To use the entrypoint!
macro, use the following in your entrypoint definition:
use pinocchio::{
account_info::AccountInfo,
entrypoint,
msg,
ProgramResult,
pubkey::Pubkey
};
entrypoint!(process_instruction);
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
msg!("Hello from my program!");
Ok(())
}
The information from the input is parsed into their own entities:
program_id
: theID
of the program being calledaccounts
: the accounts receivedinstruction_data
: data for the instruction
Pinocchio also offers variations of the program entrypoint
(lazy_program_entrypoint
) and global allocator (no_allocator
). In
order to use these, the program needs to specify the program entrypoint,
global allocator and panic handler individually. The entrypoint!
macro
is equivalent to writing:
program_entrypoint!(process_instruction);
default_allocator!();
default_panic_handler!();
Any of these macros can be replaced by other implementations and Pinocchio offers a couple of variants for this.
§lazy_program_entrypoint!
The entrypoint!
macro looks similar to the “standard” one found in
solana-program
.
It parses the whole input and provides the program_id
, accounts
and
instruction_data
separately. This consumes compute units before the program
begins its execution. In some cases, it is beneficial for a program to have
more control when the input parsing is happening, even whether the parsing
is needed or not — this is the purpose of the lazy_program_entrypoint!
macro. This macro only wraps the program input and provides methods to parse
the input on-demand.
The lazy_program_entrypoint
is suitable for programs that have a single
or very few instructions, since it requires the program to handle the parsing,
which can become complex as the number of instructions increases. For larger
programs, the program_entrypoint!
will likely be easier and more efficient
to use.
To use the lazy_program_entrypoint!
macro, use the following in your
entrypoint definition:
use pinocchio::{
default_allocator,
default_panic_handler,
entrypoint::InstructionContext,
lazy_program_entrypoint,
msg,
ProgramResult
};
lazy_program_entrypoint!(process_instruction);
default_allocator!();
default_panic_handler!();
pub fn process_instruction(
mut context: InstructionContext
) -> ProgramResult {
msg!("Hello from my lazy program!");
Ok(())
}
The InstructionContext
provides on-demand
access to the information of the input:
available()
: number of available accounts.next_account()
: parses the next available account (can be used as many times as accounts available).instruction_data()
: parses the instruction data.program_id()
: parses the program id.
💡 The lazy_program_entrypoint!
does not set up a global allocator nor a panic
handler. A program should explicitly use one of the provided macros to set them
up or include its own implementation.
§no_allocator!
When writing programs, it can be useful to make sure the program does not attempt
to make any allocations. For this cases, Pinocchio includes a no_allocator!
macro that set a global allocator just panics at any attempt to allocate memory.
To use the no_allocator!
macro, use the following in your entrypoint definition:
use pinocchio::{
account_info::AccountInfo,
default_panic_handler,
msg,
no_allocator,
program_entrypoint,
ProgramResult,
pubkey::Pubkey
};
program_entrypoint!(process_instruction);
default_panic_handler!();
no_allocator!();
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
msg!("Hello from `no_std` program!");
Ok(())
}
💡 The no_allocator!
macro can also be used in combination with the
lazy_program_entrypoint!
.
§std
crate feature
By default, Pinocchio is a no_std
crate. This means that it does not use any
code from the standard (std
) library. While this does not affect how Pinocchio
is used, there is a one particular apparent difference. In a no_std
environment,
the msg!
macro does not provide any formatting options since the format!
macro
requires the std
library. In order to use msg!
with formatting, the std
feature should be enable when adding Pinocchio as a dependency:
pinocchio = { version = "0.7.0", features = ["std"] }
Instead of enabling the std
feature to be able to format log messages with msg!
,
it is recommented to use the pinocchio-log
crate. This crate provides a lightweight log!
macro with better compute units
consumption than the standard format!
macro without requiring the std
library.
§Advanced entrypoint configuration
The symbols emitted by the entrypoint macros — program entrypoint, global
allocator and default panic handler — can only be defined once globally. If
the program crate is also intended to be used as a library, it is common practice
to define a Cargo feature
in your program crate to conditionally enable the module that includes the entrypoint!
macro invocation. The convention is to name the feature bpf-entrypoint
.
#[cfg(feature = "bpf-entrypoint")]
mod entrypoint {
use pinocchio::{
account_info::AccountInfo,
entrypoint,
msg,
ProgramResult,
pubkey::Pubkey
};
entrypoint!(process_instruction);
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
msg!("Hello from my program!");
Ok(())
}
}
When building the program binary, you must enable the bpf-entrypoint
feature:
cargo build-sbf --features bpf-entrypoint
Re-exports§
pub use entrypoint::lazy as lazy_entrypoint;
Modules§
- account_
info - Data structures to represent account information.
- cpi
- Cross-program invocation helpers.
- entrypoint
- Macros and functions for defining the program entrypoint and setting up global handlers.
- instruction
- Instruction types.
- log
- Logging utilities for Rust-based Solana programs.
- memory
- Basic low-level memory operations.
- program
Deprecated - program_
error - Errors generated by programs.
- pubkey
- Public key type and functions.
- syscalls
- Syscall functions.
- sysvars
- Provides access to cluster system accounts.
Macros§
- default_
allocator - Default global allocator.
- default_
panic_ handler - Default panic hook.
- entrypoint
- Declare the program entrypoint and set up global handlers.
- impl_
sysvar_ get - Implements the
Sysvar::get
method for both SBF and host targets. - lazy_
entrypoint Deprecated - Declare the lazy program entrypoint.
- lazy_
program_ entrypoint - Declare the lazy program entrypoint.
- msg
- Print a message to the log.
- no_
allocator - A global allocator that does not allocate memory.
- nostd_
panic_ handler - A global
#[panic_handler]
forno_std
programs. - program_
entrypoint - Declare the program entrypoint.
- seeds
- Convenience macro for constructing a
[Seed; N]
array from a list of seeds. - signer
Deprecated - Convenience macro for constructing a
Signer
from a list of seeds represented as byte slices.
Constants§
- MAX_
TX_ ACCOUNTS - Maximum number of accounts that a transaction may process.
- SUCCESS
- Return value for a successful program execution.
Type Aliases§
- Program
Result - The result of a program execution.