Skip to content

Commit

Permalink
sdk: Improve comments (#64)
Browse files Browse the repository at this point in the history
* [wip]: Add new scripts

* [wip]: Use matric strategy

* [wip]: Fix members parsing

* [wip]: Add CI env variables

* [wip]: Remove nothrow

* [wip]: Filter changes

* [wip]: Add audit step

* [wip]: Add semver checks

* [wip]: Refactor publish workflow

* [wip]: Refactor

* [wip]: Fix commands

* Fix formatting

* Remove detect changes step

* Review comments

* Fix lint comments

* Expand crate comment

* Ignore crate comment tests

* Add missing docs

* More missing docs

* Add missing release component

* Pin cargo-release version

* Fix merge

* Review comments
  • Loading branch information
febo authored Feb 14, 2025
1 parent f2a765b commit 5f33c92
Show file tree
Hide file tree
Showing 15 changed files with 333 additions and 47 deletions.
2 changes: 1 addition & 1 deletion .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ runs:
- name: Install 'cargo-release'
if: ${{ contains(inputs.components, 'release') }}
shell: bash
run: cargo install cargo-release
run: cargo install cargo-release@0.25.15

- name: Install 'cargo-semver-checks'
if: ${{ contains(inputs.components, 'semver-checks') }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
with:
cargo-cache-key: cargo-publish
toolchain: test
components: semver-checks
components: release, semver-checks
solana: true

- name: Build
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

## Overview

Pinocchio is a zero-dependency library to create Solana programs in Rust. It takes advantage of the way SBF 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 SBF 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.
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.

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.

Expand Down
9 changes: 8 additions & 1 deletion sdk/pinocchio/src/account_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ use crate::{program_error::ProgramError, pubkey::Pubkey, ProgramResult};
/// single realloc.
pub const MAX_PERMITTED_DATA_INCREASE: usize = 1_024 * 10;

/// Returns the account info at the given index.
///
/// This macro validates that the index is within the bounds of the accounts.
#[macro_export]
macro_rules! get_account_info {
( $accounts:ident, $index:expr ) => {{
Expand Down Expand Up @@ -465,6 +468,7 @@ pub struct Ref<'a, T: ?Sized> {
}

impl<'a, T: ?Sized> Ref<'a, T> {
/// Maps a reference to a new type.
#[inline]
pub fn map<U: ?Sized, F>(orig: Ref<'a, T>, f: F) -> Ref<'a, U>
where
Expand All @@ -481,6 +485,7 @@ impl<'a, T: ?Sized> Ref<'a, T> {
}
}

/// Filters and maps a reference to a new type.
#[inline]
pub fn filter_map<U: ?Sized, F>(orig: Ref<'a, T>, f: F) -> Result<Ref<'a, U>, Self>
where
Expand Down Expand Up @@ -534,6 +539,7 @@ pub struct RefMut<'a, T: ?Sized> {
}

impl<'a, T: ?Sized> RefMut<'a, T> {
/// Maps a mutable reference to a new type.
#[inline]
pub fn map<U: ?Sized, F>(orig: RefMut<'a, T>, f: F) -> RefMut<'a, U>
where
Expand All @@ -550,6 +556,7 @@ impl<'a, T: ?Sized> RefMut<'a, T> {
}
}

/// Filters and maps a mutable reference to a new type.
#[inline]
pub fn filter_map<U: ?Sized, F>(orig: RefMut<'a, T>, f: F) -> Result<RefMut<'a, U>, Self>
where
Expand Down Expand Up @@ -586,8 +593,8 @@ impl<T: ?Sized> core::ops::DerefMut for RefMut<'_, T> {
}

impl<T: ?Sized> Drop for RefMut<'_, T> {
// unset the mutable borrow flag
fn drop(&mut self) {
// unset the mutable borrow flag
unsafe { *self.state.as_mut() &= self.borrow_mask };
}
}
Expand Down
11 changes: 7 additions & 4 deletions sdk/pinocchio/src/entrypoint/lazy.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
//! Defines the lazy program entrypoint and the context to access the
//! input buffer.
use crate::{
account_info::{Account, AccountInfo, MAX_PERMITTED_DATA_INCREASE},
program_error::ProgramError,
pubkey::Pubkey,
BPF_ALIGN_OF_U128, NON_DUP_MARKER,
};

/// Declare the program entrypoint.
/// Declare the lazy program entrypoint.
///
/// Use the `lazy_program_entrypoint!` macro instead.
#[deprecated(
Expand All @@ -19,15 +22,15 @@ macro_rules! lazy_entrypoint {
};
}

/// Declare the program entrypoint.
/// Declare the lazy program entrypoint.
///
/// This entrypoint is defined as *lazy* because it does not read the accounts upfront.
/// Instead, it provides an [`InstructionContext`] to the access input information on demand.
/// This is useful when the program needs more control over the compute units it uses.
/// The trade-off is that the program is responsible for managing potential duplicated
/// accounts and set up a `global allocator` and `panic handler`.
///
/// The usual use-case for a [`lazy_program_entrypoint!`] is small programs with a single
/// The usual use-case for a [`crate::lazy_program_entrypoint!`] is small programs with a single
/// instruction. For most use-cases, it is recommended to use the [`crate::program_entrypoint!`]
/// macro instead.
///
Expand Down Expand Up @@ -161,7 +164,7 @@ impl InstructionContext {

/// Returns the number of remaining accounts.
///
/// This value is decremented each time [`next_account`] is called.
/// This value is decremented each time [`Self::next_account`] is called.
#[inline(always)]
pub fn remaining(&self) -> u64 {
self.remaining
Expand Down
4 changes: 2 additions & 2 deletions sdk/pinocchio/src/entrypoint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ pub const SUCCESS: u64 = super::SUCCESS;
/// provided function to process the program instruction supplied by the runtime, and reporting
/// its result to the runtime.
///
/// It also sets up a [global allocator] and [panic handler], using the [`default_allocator!`]
/// and [`default_panic_handler!`] macros.
/// It also sets up a [global allocator] and [panic handler], using the [`crate::default_allocator!`]
/// and [`crate::default_panic_handler!`] macros.
///
/// The first argument is the name of a function with this type signature:
///
Expand Down
16 changes: 13 additions & 3 deletions sdk/pinocchio/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,18 @@ impl<'a> From<&'a AccountInfo> for Account<'a> {
#[repr(C)]
#[derive(Debug, Clone)]
pub struct AccountMeta<'a> {
// Public key of the account.
/// Public key of the account.
pub pubkey: &'a Pubkey,

// Indicates whether the account is writable or not.
/// Indicates whether the account is writable or not.
pub is_writable: bool,

// Indicates whether the account signed the instruction or not.
/// Indicates whether the account signed the instruction or not.
pub is_signer: bool,
}

impl<'a> AccountMeta<'a> {
/// Creates a new `AccountMeta`.
#[inline(always)]
pub fn new(pubkey: &'a Pubkey, is_writable: bool, is_signer: bool) -> Self {
Self {
Expand All @@ -130,21 +131,25 @@ impl<'a> AccountMeta<'a> {
}
}

/// Creates a new readonly `AccountMeta`.
#[inline(always)]
pub fn readonly(pubkey: &'a Pubkey) -> Self {
Self::new(pubkey, false, false)
}

/// Creates a new writable `AccountMeta`.
#[inline(always)]
pub fn writable(pubkey: &'a Pubkey) -> Self {
Self::new(pubkey, true, false)
}

/// Creates a new readonly and signer `AccountMeta`.
#[inline(always)]
pub fn readonly_signer(pubkey: &'a Pubkey) -> Self {
Self::new(pubkey, false, true)
}

/// Creates a new writable and signer `AccountMeta`.
#[inline(always)]
pub fn writable_signer(pubkey: &'a Pubkey) -> Self {
Self::new(pubkey, true, true)
Expand All @@ -157,6 +162,11 @@ impl<'a> From<&'a AccountInfo> for AccountMeta<'a> {
}
}

/// Represents a signer seed.
///
/// This struct contains the same information as a `[u8]`, but
/// has the memory layout as expected by `sol_invoke_signed_c`
/// syscall.
#[repr(C)]
#[derive(Debug, Clone)]
pub struct Seed<'a> {
Expand Down
Loading

0 comments on commit 5f33c92

Please sign in to comment.