diff --git a/README.md b/README.md
index 1a693af3..46584365 100644
--- a/README.md
+++ b/README.md
@@ -5,12 +5,13 @@
- Create Solana programs with no dependencies attached.
+ Create Solana programs with no dependencies* attached.
+
@@ -23,25 +24,20 @@
There are no dependencies on me
-## Overview
-
-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. Since the communication between a program and SVM loader — either at the first time the program is called or when one program invokes the instructions of another program — is done via a byte array, a program can define its own types. This completely eliminates the dependency on the `solana-program` crate, which in turn mitigates dependency issues by having a crate specifically designed to create on-chain programs.
+
+* It includes only dependencies to Solana SDK types — i.e., no external dependencies.
+
-As a result, Pinocchio can be used as a replacement for [`solana-program`](https://crates.io/crates/solana-program) to write on-chain programs, which are optimized in terms of both compute units consumption and binary size.
+## Overview
-The library defines:
-* program entrypoint
-* core data types
-* logging macros
-* `syscall` functions
-* access to system accounts (`sysvars`)
-* cross-program invocation
+Pinocchio is a *no-external* dependencies library to create Solana programs in Rust. The only dependencies are types from the Solana SDK specifically designed for on-chain programs. This mitigates dependency issues and offers an efficient zero-copy library to write programs, optimized in terms of both compute units consumption and binary size.
## Features
-* Zero dependencies and `no_std` crate
-* Efficient `entrypoint!` macro – no copies or allocations
-* Improved CU consumption of cross-program invocations
+* `no_std` crate
+* no-external dependencies
+* efficient `program_entrypoint!` macro – no copies or allocations
+* lightweight `lazy_program_entrypoint` providing more control over how the input is parsed
## Getting started
@@ -57,21 +53,21 @@ This will add `pinocchio` as a dependency to your project.
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](https://doc.rust-lang.org/stable/core/alloc/trait.GlobalAlloc.html) and [custom panic hook](https://github.com/anza-xyz/rust/blob/2830febbc59d44bdd7ad2c3b81731f1d08b96eba/library/std/src/sys/pal/sbf/mod.rs#L49) using the [default_allocator!](https://docs.rs/pinocchio/latest/pinocchio/macro.default_allocator.html) and [default_panic_handler!](https://docs.rs/pinocchio/latest/pinocchio/macro.default_panic_handler.html) macros.
-The [`entrypoint!`](https://docs.rs/pinocchio/latest/pinocchio/macro.entrypoint.html) is a convenience macro that invokes three other macros to set all symbols required for a program execution:
+The [`entrypoint!`](https://docs.rs/pinocchio/latest/pinocchio/macro.entrypoint.html) is a convenience macro that invokes three other macros to set all components required for a program execution:
* [`program_entrypoint!`](https://docs.rs/pinocchio/latest/pinocchio/macro.program_entrypoint.html): declares the program entrypoint
* [`default_allocator!`](https://docs.rs/pinocchio/latest/pinocchio/macro.default_allocator.html): declares the default (bump) global allocator
* [`default_panic_handler!`](https://docs.rs/pinocchio/latest/pinocchio/macro.default_panic_handler.html): declares the default panic handler
-If all dependencies are `no_std`, you should append [`nostd_panic_handler!`](https://docs.rs/pinocchio/latest/pinocchio/macro.nostd_panic_handler.html) to declare a rust runtime panic handler. There's no need to do this if any dependency is `std` since rust compiler will emit std panic handler.
+When all dependencies are `no_std`, you should use [`nostd_panic_handler!`](https://docs.rs/pinocchio/latest/pinocchio/macro.nostd_panic_handler.html) instead of `default_panic_handler!` to declare a rust runtime panic handler. There's no need to do this when any dependency is `std` since rust compiler will emit a panic handler.
To use the `entrypoint!` macro, use the following in your entrypoint definition:
```rust
use pinocchio::{
account::AccountView,
+ Address,
entrypoint,
- ProgramResult,
- Address
+ ProgramResult
};
entrypoint!(process_instruction);
@@ -91,17 +87,17 @@ The information from the input is parsed into their own entities:
* `accounts`: the accounts received
* `instruction_data`: data for the instruction
-`pinocchio` also offers variations of the program entrypoint (`lazy_program_allocator`) 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:
+`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:
```rust
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.
+Any of these macros can be replaced by alternative implementations.
📌 [`lazy_program_entrypoint!`](https://docs.rs/pinocchio/latest/pinocchio/macro.lazy_program_entrypoint.html)
-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!`](https://docs.rs/pinocchio/latest/pinocchio/macro.lazy_program_entrypoint.html) macro. This macro only wraps the program input and provides methods to parse the input on demand.
+The `entrypoint!` macro looks similar to the "standard" one found in [`solana-program-entrypoint`](https://docs.rs/solana-program-entrypoint/latest/solana_program_entrypoint/macro.entrypoint.html). 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!`](https://docs.rs/pinocchio/latest/pinocchio/macro.lazy_program_entrypoint.html) macro. This macro only wraps the program input and provides methods to parse the input on demand.
The `lazy_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!`](https://docs.rs/pinocchio/latest/pinocchio/macro.program_entrypoint.html) will likely be easier and more efficient to use.
@@ -166,7 +162,21 @@ pub fn process_instruction(
> ⚠️ **Note:**
> The `no_allocator!` macro can also be used in combination with the `lazy_program_entrypoint!`.
-## Crate feature: `alloc`
+Since the `no_allocator!` macro does not allocate memory, the `32kb` memory region reserved for the heap remains unused. To take advantage of this, the `no_allocator!` macro emits an `allocate_unchecked` helper function that allows you to manually reserve memory for a type at compile time.
+
+```rust
+/// static allocation:
+/// - 0 is the offset when the type will be allocated
+/// - `allocate_unchecked` returns a mutable reference to the allocated type
+let lamports = allocate_unchecked::(0);
+*lamports = 1_000_000_000;
+```
+
+Note that it is the developer's responsibility to ensure that types do not overlap in memory — the `offset + ` of different types must not overlap.
+
+## Crate features
+
+### `alloc`
The `alloc` feature is enabled by default and it uses the [`alloc`](https://doc.rust-lang.org/alloc/) crate. This provides access to dynamic memory allocation in combination with the `default_allocator`, e.g., required to use `String` and `Vec` in a program. Helpers that need to allocate memory, such as fetching `SlotHashes` sysvar data, are also available.
@@ -179,9 +189,17 @@ pinocchio = { version = "0.10.0", default-features = false }
> ⚠️ **Note:**
> The `default_allocator` macro is not available when disabling the `alloc` feature.
+### `cpi`
+
+The `cpi` feature enables the cross-program invocation helpers, as well as types to define instructions and signer information.
+
+```
+pinocchio = { version = "0.10.0", features = ["cpi"] }
+```
+
## Advance 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](https://doc.rust-lang.org/cargo/reference/features.html) in your program crate to conditionally enable the module that includes the `entrypoint!` macro invocation. The convention is to name the feature `bpf-entrypoint`.
+The components 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](https://doc.rust-lang.org/cargo/reference/features.html) in your program crate to conditionally enable the module that includes the `entrypoint!` macro invocation. The convention is to name the feature `bpf-entrypoint`.
```rust
#[cfg(feature = "bpf-entrypoint")]
diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml
index a6cf88fd..778fbe86 100644
--- a/sdk/Cargo.toml
+++ b/sdk/Cargo.toml
@@ -8,13 +8,17 @@ readme = "./README.md"
repository = { workspace = true }
rust-version = { workspace = true }
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+all-features = true
+rustdoc-args = ["--cfg=docsrs"]
+
[lib]
crate-type = ["rlib"]
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = [
'cfg(target_os, values("solana"))',
- 'cfg(target_feature, values("static-syscalls"))',
] }
[features]
diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs
index 7aa54f4d..0cddda12 100644
--- a/sdk/src/lib.rs
+++ b/sdk/src/lib.rs
@@ -1,18 +1,10 @@
-//! # Pinocchio
+//! # A library to create Solana programs in Rust
//!
-//! Pinocchio is a "no-external" dependencies library to create Solana programs
-//! in Rust, which means that the only dependencies are from the Solana SDK. This
-//! reduces the chance of dependency conflicts when compiling the program.
-//!
-//! 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 use 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 [`solana-sdk`] crates.
-//!
-//! [`solana-sdk`]: https://docs.rs/solana-sdk/latest/solana_sdk/
+//! Pinocchio is a *no-external* dependencies library to create Solana programs
+//! in Rust. The only dependencies are types from the Solana SDK specifically
+//! designed for on-chain programs. This mitigates dependency issues and offers
+//! an efficient zero-copy library to write programs, optimized in terms of both
+//! compute units consumption and binary size.
//!
//! ## Defining the program entrypoint
//!
@@ -23,17 +15,23 @@
//! and [panic handler](https://doc.rust-lang.org/nomicon/panic-handler.html) 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:
+//! The [`entrypoint!`](https://docs.rs/pinocchio/latest/pinocchio/macro.entrypoint.html)
+//! is a convenience macro that invokes three other macros to set all components
+//! required for a program execution:
//!
//! * [`program_entrypoint!`]: declares the program entrypoint
//! * [`default_allocator!`]: declares the default (bump) global allocator
//! * [`default_panic_handler!`]: declares the default panic handler
//!
+//! When all dependencies are `no_std`, you should use [`nostd_panic_handler!`](https://docs.rs/pinocchio/latest/pinocchio/macro.nostd_panic_handler.html)
+//! instead of `default_panic_handler!` to declare a rust runtime panic handler.
+//! There's no need to do this when any dependency is `std` since rust compiler will
+//! emit a panic handler.
+//!
//! To use the `entrypoint!` macro, use the following in your entrypoint definition:
//! ```ignore
//! use pinocchio::{
-//! AccountView,
+//! account::AccountView,
//! Address,
//! entrypoint,
//! ProgramResult
@@ -56,18 +54,16 @@
//! * `accounts`: the accounts received
//! * `instruction_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:
+//! `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:
//! ```ignore
//! 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.
+//! Any of these macros can be replaced by alternative implementations.
//!
//! ### [`lazy_program_entrypoint!`]
//!
@@ -160,16 +156,44 @@
//! 💡 The [`no_allocator!`] macro can also be used in combination with the
//! [`lazy_program_entrypoint!`].
//!
-//! ## `std` crate feature
+//! Since the `no_allocator!` macro does not allocate memory, the `32kb` memory region
+//! reserved for the heap remains unused. To take advantage of this, the `no_allocator!`
+//! macro emits an `allocate_unchecked` helper function that allows you to manually
+//! reserve memory for a type at compile time.
+//! ```ignore
+//! /// static allocation:
+//! /// - 0 is the offset when the type will be allocated
+//! /// - `allocate_unchecked` returns a mutable reference to the allocated type
+//! let lamports = allocate_unchecked::(0);
+//! *lamports = 1_000_000_000;
+//! ```
+//!
+//! Note that it is the developer's responsibility to ensure that types do not overlap
+//! in memory - the `offset + ` of different types must not overlap.
+//!
+//! ## Crate features
+//!
+//! ### `alloc`
+//!
+//! The `alloc` feature is enabled by default and it uses the [`alloc`](https://doc.rust-lang.org/alloc/)
+//! crate. This provides access to dynamic memory allocation in combination with the
+//! [`default_allocator!`], e.g., required to use `String` and `Vec` in a program.
+//! Helpers that need to allocate memory, such as fetching [`crate::sysvars::slot_hashes::SlotHashes::fetch`]
+//! sysvar data, are also available.
+//!
+//! When no allocation is needed or desired, the feature can be disabled:
+//!
+//! ```ignore
+//! pinocchio = { version = "0.10.0", default-features = false }
+//! ```
+//!
+//! ### `cpi`
+//!
+//! The `cpi` feature enables the cross-program invocation helpers, as well as types
+//! to define instructions and signer information.
//!
-//! 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. Helpers that need to
-//! allocate memory, such as fetching `SlotHashes` sysvar, are not available. To
-//! enable these helpers, the `alloc` feature must be enabled when adding Pinocchio
-//! as a dependency:
//! ```ignore
-//! pinocchio = { version = "0.10.0", features = ["alloc"] }
+//! pinocchio = { version = "0.10.0", features = ["cpi"] }
//! ```
//!
//! ## Advanced entrypoint configuration
@@ -185,7 +209,7 @@
//! #[cfg(feature = "bpf-entrypoint")]
//! mod entrypoint {
//! use pinocchio::{
-//! AccountView,
+//! account::AccountView,
//! Address,
//! entrypoint,
//! ProgramResult