From 4435c76bbe195275c7416c8e5e82c99561245c02 Mon Sep 17 00:00:00 2001 From: febo Date: Mon, 21 Oct 2024 10:09:27 +0100 Subject: [PATCH] Use lazy entrypoint --- Cargo.lock | 15 +++--- cpi/pinocchio/Cargo.toml | 4 +- cpi/pinocchio/src/lib.rs | 52 +++++++++---------- transfer-lamports/pinocchio/Cargo.toml | 2 +- transfer-lamports/pinocchio/src/entrypoint.rs | 26 +++++++--- transfer-lamports/pinocchio/src/lib.rs | 1 - transfer-lamports/pinocchio/src/processor.rs | 29 ----------- 7 files changed, 53 insertions(+), 76 deletions(-) delete mode 100644 transfer-lamports/pinocchio/src/processor.rs diff --git a/Cargo.lock b/Cargo.lock index c471bc4..5e58212 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2533,15 +2533,13 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pinocchio" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4205e6f0d6f9155ece9e9cff154192a8e36c2c987ce3143f50b5fbea46e7d2fa" +version = "0.5.0" +source = "git+https://github.com/febo/pinocchio.git?branch=create-pda-unchecked#a22cc1861d5666c4aa977dfb25c7b5b33bacc34b" [[package]] name = "pinocchio-pubkey" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2826006b44e26d8db9cf1f9ead4e43f01a36fa5f59d032cf9fdb5d118356249" +version = "0.2.0" +source = "git+https://github.com/febo/pinocchio.git?branch=create-pda-unchecked#a22cc1861d5666c4aa977dfb25c7b5b33bacc34b" dependencies = [ "five8_const", "pinocchio", @@ -2568,9 +2566,8 @@ dependencies = [ [[package]] name = "pinocchio-system" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "906738307ebf61b4a3751f756ee5635018b20a9151564c265ed84982e63d4323" +version = "0.1.3" +source = "git+https://github.com/febo/pinocchio.git?branch=create-pda-unchecked#a22cc1861d5666c4aa977dfb25c7b5b33bacc34b" dependencies = [ "pinocchio", "pinocchio-pubkey", diff --git a/cpi/pinocchio/Cargo.toml b/cpi/pinocchio/Cargo.toml index 12ce2bc..ed7c134 100644 --- a/cpi/pinocchio/Cargo.toml +++ b/cpi/pinocchio/Cargo.toml @@ -7,8 +7,8 @@ edition = "2021" test-sbf = [] [dependencies] -pinocchio = "0.4" -pinocchio-system = "0.1" +pinocchio = { version = "0.5", git = "https://github.com/febo/pinocchio.git", branch = "create-pda-unchecked" } +pinocchio-system = { version="0.1", git = "https://github.com/febo/pinocchio.git", branch = "create-pda-unchecked" } [dev-dependencies] solana-program-test = "2.0.3" diff --git a/cpi/pinocchio/src/lib.rs b/cpi/pinocchio/src/lib.rs index a686162..46fdac0 100644 --- a/cpi/pinocchio/src/lib.rs +++ b/cpi/pinocchio/src/lib.rs @@ -2,30 +2,33 @@ #![deny(missing_docs)] use pinocchio::{ - account_info::AccountInfo, - entrypoint, - entrypoint::ProgramResult, - instruction::{Account, AccountMeta, Instruction, Seed, Signer}, + instruction::{Account, AccountMeta, Instruction}, + lazy_entrypoint::InstructionContext, program::invoke_signed_unchecked, program_error::ProgramError, - pubkey::{create_program_address, Pubkey}, + pubkey::create_program_address, + signer, ProgramResult, }; -pinocchio::entrypoint!(process_instruction); +// Since this is a single instruction program, we use the "lazy" variation +// of the entrypoint. +pinocchio::lazy_entrypoint!(process_instruction); /// Amount of bytes of account data to allocate pub const SIZE: usize = 42; -/// Instruction processor -pub fn process_instruction( - program_id: &Pubkey, - accounts: &[AccountInfo], - instruction_data: &[u8], -) -> ProgramResult { - // Account info to allocate abd for the program being invoked - let [allocated_info, _system_program_info] = accounts else { - return Err(ProgramError::NotEnoughAccountKeys); - }; +/// Instruction processor. +unsafe fn process_instruction(mut context: InstructionContext) -> ProgramResult { + // Account info to allocate and for the program being invoked. Here we are + // optimizing for CU, so we are not checking that the accounts are present + // ('unchecked' method will panic if the account is duplicated or UB if the + // account is missing). + let allocated_info = context.next_account_unchecked(); + let _system_program_info = context.next_account_unchecked(); + + // Again, we are not checking that all accounts have been consumed (we assume + // that we got only the 2 accounts we expected). + let (instruction_data, program_id) = context.instruction_data_unchecked(); let expected_allocated_key = create_program_address(&[b"You pass butter", &[instruction_data[0]]], program_id)?; @@ -45,16 +48,13 @@ pub fn process_instruction( data: &data, }; - unsafe { - invoke_signed_unchecked( - &instruction, - &[Account::from(allocated_info)], - &[Signer::from(&[ - Seed::from(b"You pass butter"), - Seed::from(&[instruction_data[0]]), - ])], - ); - } + // Invoke the system program with the 'unchcked' function. This is safe since + // we know the accounts are not borrowed elsewhere. + invoke_signed_unchecked( + &instruction, + &[Account::from(&allocated_info)], + &[signer!(b"You pass butter", &[instruction_data[0]])], + ); Ok(()) } diff --git a/transfer-lamports/pinocchio/Cargo.toml b/transfer-lamports/pinocchio/Cargo.toml index 098b177..a8b7898 100644 --- a/transfer-lamports/pinocchio/Cargo.toml +++ b/transfer-lamports/pinocchio/Cargo.toml @@ -8,7 +8,7 @@ no-entrypoint = [] test-sbf = [] [dependencies] -pinocchio = "0.4" +pinocchio = { version = "0.5", git = "https://github.com/febo/pinocchio.git", branch = "create-pda-unchecked" } [dev-dependencies] solana-program-test = "2.0.3" diff --git a/transfer-lamports/pinocchio/src/entrypoint.rs b/transfer-lamports/pinocchio/src/entrypoint.rs index 6b746ce..b4f4cce 100644 --- a/transfer-lamports/pinocchio/src/entrypoint.rs +++ b/transfer-lamports/pinocchio/src/entrypoint.rs @@ -2,14 +2,24 @@ #![cfg(not(feature = "no-entrypoint"))] -use pinocchio::{account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, pubkey::Pubkey}; +use pinocchio::{lazy_entrypoint::InstructionContext, ProgramResult}; -pinocchio::entrypoint!(process_instruction); +// Since this is a single instruction program, we use the "lazy" variation +// of the entrypoint. +pinocchio::lazy_entrypoint!(process_instruction); -fn process_instruction( - program_id: &Pubkey, - accounts: &[AccountInfo], - instruction_data: &[u8], -) -> ProgramResult { - crate::processor::process_instruction(program_id, accounts, instruction_data) +#[inline] +unsafe fn process_instruction(mut context: InstructionContext) -> ProgramResult { + // Account infos used in the transfer. Here we are optimizing for CU, so we + // are not checking that the accounts are present ('unchecked' method will panic + // if the account is duplicated or UB if the account is missing). + let source_info = context.next_account_unchecked(); + let destination_info = context.next_account_unchecked(); + + // Transfer five lamports from the source to the destination using 'unchecked' + // borrowing. This is safe since we know the lamports are not borrowed elsewhere. + *source_info.borrow_mut_lamports_unchecked() -= 5; // withdraw five lamports + *destination_info.borrow_mut_lamports_unchecked() += 5; // deposit five lamports + + Ok(()) } diff --git a/transfer-lamports/pinocchio/src/lib.rs b/transfer-lamports/pinocchio/src/lib.rs index 5c1c835..4f5bd25 100644 --- a/transfer-lamports/pinocchio/src/lib.rs +++ b/transfer-lamports/pinocchio/src/lib.rs @@ -2,4 +2,3 @@ #![deny(missing_docs)] mod entrypoint; -pub mod processor; diff --git a/transfer-lamports/pinocchio/src/processor.rs b/transfer-lamports/pinocchio/src/processor.rs deleted file mode 100644 index eb8b543..0000000 --- a/transfer-lamports/pinocchio/src/processor.rs +++ /dev/null @@ -1,29 +0,0 @@ -#![allow(clippy::arithmetic_side_effects)] -//! Program instruction processor - -use pinocchio::{ - account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, - pubkey::Pubkey, -}; - -/// Instruction processor -pub fn process_instruction( - _program_id: &Pubkey, - accounts: &[AccountInfo], - _instruction_data: &[u8], -) -> ProgramResult { - // As part of the program specification the first account is the source - // account and the second is the destination account - let [source_info, destination_info] = accounts else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - unsafe { - // Withdraw five lamports from the source - *source_info.borrow_mut_lamports_unchecked() -= 5; - // Deposit five lamports into the destination - *destination_info.borrow_mut_lamports_unchecked() += 5; - } - - Ok(()) -}