diff --git a/Cargo.lock b/Cargo.lock index 73ed8c5e..4a1ce8de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,7 +36,8 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" name = "pinocchio" version = "0.8.0" dependencies = [ - "solana-address", + "solana-account-view", + "solana-address 0.0.0 (git+https://github.com/febo/solana-sdk.git?branch=solana-address)", "solana-program-error", ] @@ -69,7 +70,7 @@ name = "pinocchio-pubkey" version = "0.2.4" dependencies = [ "five8_const", - "solana-address", + "solana-address 0.0.0 (git+https://github.com/febo/solana-sdk.git?branch=solana-address)", ] [[package]] @@ -135,15 +136,35 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "solana-account-view" +version = "0.0.0" +source = "git+https://github.com/febo/solana-sdk.git?branch=account-view#67740223b05b3146d03eb8b1d4c57a22380366b0" +dependencies = [ + "solana-address 0.0.0 (git+https://github.com/febo/solana-sdk.git?branch=account-view)", + "solana-define-syscall 2.2.1 (git+https://github.com/febo/solana-sdk.git?branch=account-view)", + "solana-program-error", +] + +[[package]] +name = "solana-address" +version = "0.0.0" +source = "git+https://github.com/febo/solana-sdk.git?branch=account-view#67740223b05b3146d03eb8b1d4c57a22380366b0" + [[package]] name = "solana-address" version = "0.0.0" source = "git+https://github.com/febo/solana-sdk.git?branch=solana-address#626d9c0d25da15cd2b0a53a37edf510d4e5ea430" dependencies = [ - "solana-define-syscall", + "solana-define-syscall 2.2.1 (git+https://github.com/febo/solana-sdk.git?branch=solana-address)", "solana-program-error", ] +[[package]] +name = "solana-define-syscall" +version = "2.2.1" +source = "git+https://github.com/febo/solana-sdk.git?branch=account-view#67740223b05b3146d03eb8b1d4c57a22380366b0" + [[package]] name = "solana-define-syscall" version = "2.2.1" diff --git a/Cargo.toml b/Cargo.toml index a56ed3c5..f77e038c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ pinocchio-pubkey = { path = "sdk/pubkey", version = "0.2" } pinocchio-log-macro = { version = "0.4", path = "sdk/log/macro" } quote = "1.0" regex = "1" +solana-account-view = { version = "0.0.0", git = "https://github.com/febo/solana-sdk.git", branch = "account-view" } solana-address = { version = "0.0.0", git = "https://github.com/febo/solana-sdk.git", branch = "solana-address" } syn = "1.0" diff --git a/README.md b/README.md index b5b0ea91..bcc0739f 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ If all dependencies are `no_std`, you should append [`nostd_panic_handler!`](htt To use the `entrypoint!` macro, use the following in your entrypoint definition: ```rust use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, entrypoint, msg, ProgramResult, @@ -79,7 +79,7 @@ entrypoint!(process_instruction); pub fn process_instruction( program_id: &Address, - accounts: &[AccountInfo], + accounts: &[AccountView], instruction_data: &[u8], ) -> ProgramResult { msg!("Hello from my program!"); @@ -147,7 +147,7 @@ When writing programs, it can be useful to make sure the program does not attemp To use the `no_allocator!` macro, use the following in your entrypoint definition: ```rust use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, default_panic_handler, msg, no_allocator, @@ -162,7 +162,7 @@ no_allocator!(); pub fn process_instruction( program_id: &Address, - accounts: &[AccountInfo], + accounts: &[AccountView], instruction_data: &[u8], ) -> ProgramResult { msg!("Hello from `no_std` program!"); @@ -189,7 +189,7 @@ The symbols emitted by the entrypoint macros — program entrypoint, global #[cfg(feature = "bpf-entrypoint")] mod entrypoint { use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, entrypoint, msg, ProgramResult, @@ -200,7 +200,7 @@ mod entrypoint { pub fn process_instruction( program_id: &Address, - accounts: &[AccountInfo], + accounts: &[AccountView], instruction_data: &[u8], ) -> ProgramResult { msg!("Hello from my program!"); diff --git a/programs/associated-token-account/src/instructions/create.rs b/programs/associated-token-account/src/instructions/create.rs index 3c2eeecd..e3dd6ebc 100644 --- a/programs/associated-token-account/src/instructions/create.rs +++ b/programs/associated-token-account/src/instructions/create.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -17,17 +17,17 @@ use pinocchio::{ /// 5. `[]` SPL Token program pub struct Create<'a> { /// Funding account (must be a system account) - pub funding_account: &'a AccountInfo, + pub funding_account: &'a AccountView, /// Associated token account address to be created - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Wallet address for the new associated token account - pub wallet: &'a AccountInfo, + pub wallet: &'a AccountView, /// The token mint for the new associated token account - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// System program - pub system_program: &'a AccountInfo, + pub system_program: &'a AccountView, /// SPL Token program - pub token_program: &'a AccountInfo, + pub token_program: &'a AccountView, } impl Create<'_> { diff --git a/programs/associated-token-account/src/instructions/create_idempotent.rs b/programs/associated-token-account/src/instructions/create_idempotent.rs index b88d1853..4bd50f19 100644 --- a/programs/associated-token-account/src/instructions/create_idempotent.rs +++ b/programs/associated-token-account/src/instructions/create_idempotent.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -18,17 +18,17 @@ use pinocchio::{ /// 5. `[]` SPL Token program pub struct CreateIdempotent<'a> { /// Funding account (must be a system account) - pub funding_account: &'a AccountInfo, + pub funding_account: &'a AccountView, /// Associated token account address to be created - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Wallet address for the new associated token account - pub wallet: &'a AccountInfo, + pub wallet: &'a AccountView, /// The token mint for the new associated token account - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// System program - pub system_program: &'a AccountInfo, + pub system_program: &'a AccountView, /// SPL Token program - pub token_program: &'a AccountInfo, + pub token_program: &'a AccountView, } impl CreateIdempotent<'_> { diff --git a/programs/associated-token-account/src/instructions/recover_nested.rs b/programs/associated-token-account/src/instructions/recover_nested.rs index 003dfc7f..d859b012 100644 --- a/programs/associated-token-account/src/instructions/recover_nested.rs +++ b/programs/associated-token-account/src/instructions/recover_nested.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -26,19 +26,19 @@ use pinocchio::{ /// 6. `[]` SPL Token program pub struct RecoverNested<'a> { /// Nested associated token account, must be owned by `owner_associated_token_account` - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Token mint for the nested associated token account - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Wallet's associated token account - pub destination_account: &'a AccountInfo, + pub destination_account: &'a AccountView, /// Owner associated token account address, must be owned by `wallet_account` - pub owner_account: &'a AccountInfo, + pub owner_account: &'a AccountView, /// Token mint for the owner associated token account - pub owner_mint: &'a AccountInfo, + pub owner_mint: &'a AccountView, /// Wallet address for the owner associated token account - pub wallet: &'a AccountInfo, + pub wallet: &'a AccountView, /// SPL Token program - pub token_program: &'a AccountInfo, + pub token_program: &'a AccountView, } impl RecoverNested<'_> { diff --git a/programs/system/src/instructions/advance_nonce_account.rs b/programs/system/src/instructions/advance_nonce_account.rs index b40d2fe0..3de15a36 100644 --- a/programs/system/src/instructions/advance_nonce_account.rs +++ b/programs/system/src/instructions/advance_nonce_account.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -13,13 +13,13 @@ use pinocchio::{ /// 2. `[SIGNER]` Nonce authority pub struct AdvanceNonceAccount<'a> { /// Nonce account. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// RecentBlockhashes sysvar. - pub recent_blockhashes_sysvar: &'a AccountInfo, + pub recent_blockhashes_sysvar: &'a AccountView, /// Nonce authority. - pub authority: &'a AccountInfo, + pub authority: &'a AccountView, } impl AdvanceNonceAccount<'_> { diff --git a/programs/system/src/instructions/allocate.rs b/programs/system/src/instructions/allocate.rs index 0a857cd4..acb3a2ce 100644 --- a/programs/system/src/instructions/allocate.rs +++ b/programs/system/src/instructions/allocate.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -11,7 +11,7 @@ use pinocchio::{ /// 0. `[WRITE, SIGNER]` New account pub struct Allocate<'a> { /// Account to be assigned. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Number of bytes of memory to allocate. pub space: u64, diff --git a/programs/system/src/instructions/allocate_with_seed.rs b/programs/system/src/instructions/allocate_with_seed.rs index c1acccba..6a6bb033 100644 --- a/programs/system/src/instructions/allocate_with_seed.rs +++ b/programs/system/src/instructions/allocate_with_seed.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, Address, ProgramResult, @@ -13,14 +13,14 @@ use pinocchio::{ /// 1. `[SIGNER]` Base account pub struct AllocateWithSeed<'a, 'b, 'c> { /// Allocated account. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Base account. /// /// The account matching the base address below must be provided as /// a signer, but may be the same as the funding account and provided /// as account 0. - pub base: &'a AccountInfo, + pub base: &'a AccountView, /// String of ASCII chars, no longer than [MAX_SEED_LEN](https://docs.rs/solana-address/latest/solana_address/constant.MAX_SEED_LEN.html). pub seed: &'b str, diff --git a/programs/system/src/instructions/assign.rs b/programs/system/src/instructions/assign.rs index 9824cd53..d22a967e 100644 --- a/programs/system/src/instructions/assign.rs +++ b/programs/system/src/instructions/assign.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, Address, ProgramResult, @@ -11,7 +11,7 @@ use pinocchio::{ /// 0. `[WRITE, SIGNER]` Assigned account address pub struct Assign<'a, 'b> { /// Account to be assigned. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Program account to assign as owner. pub owner: &'b Address, diff --git a/programs/system/src/instructions/assign_with_seed.rs b/programs/system/src/instructions/assign_with_seed.rs index 1000d7fb..dac544c3 100644 --- a/programs/system/src/instructions/assign_with_seed.rs +++ b/programs/system/src/instructions/assign_with_seed.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, Address, ProgramResult, @@ -12,14 +12,14 @@ use pinocchio::{ /// 1. `[SIGNER]` Base account pub struct AssignWithSeed<'a, 'b, 'c> { /// Allocated account. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Base account. /// /// The account matching the base `Address` below must be provided as /// a signer, but may be the same as the funding account and provided /// as account 0. - pub base: &'a AccountInfo, + pub base: &'a AccountView, /// String of ASCII chars, no longer than [MAX_SEED_LEN](https://docs.rs/solana-address/latest/solana_address/constant.MAX_SEED_LEN.html). pub seed: &'b str, diff --git a/programs/system/src/instructions/authorize_nonce_account.rs b/programs/system/src/instructions/authorize_nonce_account.rs index 50b90a54..faaf7137 100644 --- a/programs/system/src/instructions/authorize_nonce_account.rs +++ b/programs/system/src/instructions/authorize_nonce_account.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, Address, ProgramResult, @@ -14,10 +14,10 @@ use pinocchio::{ /// 1. `[SIGNER]` Nonce authority pub struct AuthorizeNonceAccount<'a, 'b> { /// Nonce account. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Nonce authority. - pub authority: &'a AccountInfo, + pub authority: &'a AccountView, /// New entity authorized to execute nonce instructions on the account. pub new_authority: &'b Address, diff --git a/programs/system/src/instructions/create_account.rs b/programs/system/src/instructions/create_account.rs index c07ce69c..42a5a8f9 100644 --- a/programs/system/src/instructions/create_account.rs +++ b/programs/system/src/instructions/create_account.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, Address, ProgramResult, @@ -12,10 +12,10 @@ use pinocchio::{ /// 1. `[WRITE, SIGNER]` New account pub struct CreateAccount<'a> { /// Funding account. - pub from: &'a AccountInfo, + pub from: &'a AccountView, /// New account. - pub to: &'a AccountInfo, + pub to: &'a AccountView, /// Number of lamports to transfer to the new account. pub lamports: u64, diff --git a/programs/system/src/instructions/create_account_with_seed.rs b/programs/system/src/instructions/create_account_with_seed.rs index 7ca43e9d..be9d9d99 100644 --- a/programs/system/src/instructions/create_account_with_seed.rs +++ b/programs/system/src/instructions/create_account_with_seed.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, Address, ProgramResult, @@ -14,17 +14,17 @@ use pinocchio::{ /// provided as a signer, but may be the same as the funding account pub struct CreateAccountWithSeed<'a, 'b, 'c> { /// Funding account. - pub from: &'a AccountInfo, + pub from: &'a AccountView, /// New account. - pub to: &'a AccountInfo, + pub to: &'a AccountView, /// Base account. /// /// The account matching the base [`Address`] below must be provided as /// a signer, but may be the same as the funding account and provided /// as account 0. - pub base: Option<&'a AccountInfo>, + pub base: Option<&'a AccountView>, /// String of ASCII chars, no longer than [MAX_SEED_LEN](https://docs.rs/solana-address/latest/solana_address/constant.MAX_SEED_LEN.html). pub seed: &'b str, diff --git a/programs/system/src/instructions/initialize_nonce_account.rs b/programs/system/src/instructions/initialize_nonce_account.rs index 33fa3a45..7dc16058 100644 --- a/programs/system/src/instructions/initialize_nonce_account.rs +++ b/programs/system/src/instructions/initialize_nonce_account.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, Address, ProgramResult, @@ -19,13 +19,13 @@ use pinocchio::{ /// 2. `[]` Rent sysvar pub struct InitializeNonceAccount<'a, 'b> { /// Nonce account. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// RecentBlockhashes sysvar. - pub recent_blockhashes_sysvar: &'a AccountInfo, + pub recent_blockhashes_sysvar: &'a AccountView, /// Rent sysvar. - pub rent_sysvar: &'a AccountInfo, + pub rent_sysvar: &'a AccountView, /// Lamports to withdraw. /// diff --git a/programs/system/src/instructions/transfer.rs b/programs/system/src/instructions/transfer.rs index d62a7740..57999a37 100644 --- a/programs/system/src/instructions/transfer.rs +++ b/programs/system/src/instructions/transfer.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -12,10 +12,10 @@ use pinocchio::{ /// 1. `[WRITE]` Recipient account pub struct Transfer<'a> { /// Funding account. - pub from: &'a AccountInfo, + pub from: &'a AccountView, /// Recipient account. - pub to: &'a AccountInfo, + pub to: &'a AccountView, /// Amount of lamports to transfer. pub lamports: u64, diff --git a/programs/system/src/instructions/transfer_with_seed.rs b/programs/system/src/instructions/transfer_with_seed.rs index 59ac9922..5db332e6 100644 --- a/programs/system/src/instructions/transfer_with_seed.rs +++ b/programs/system/src/instructions/transfer_with_seed.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, Address, ProgramResult, @@ -13,17 +13,17 @@ use pinocchio::{ /// 2. `[WRITE]` Recipient account pub struct TransferWithSeed<'a, 'b, 'c> { /// Funding account. - pub from: &'a AccountInfo, + pub from: &'a AccountView, /// Base account. /// /// The account matching the base [`Address`] below must be provided as /// a signer, but may be the same as the funding account and provided /// as account 0. - pub base: &'a AccountInfo, + pub base: &'a AccountView, /// Recipient account. - pub to: &'a AccountInfo, + pub to: &'a AccountView, /// Amount of lamports to transfer. pub lamports: u64, diff --git a/programs/system/src/instructions/update_nonce_account.rs b/programs/system/src/instructions/update_nonce_account.rs index b890c8c2..fba6ddc5 100644 --- a/programs/system/src/instructions/update_nonce_account.rs +++ b/programs/system/src/instructions/update_nonce_account.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -12,7 +12,7 @@ use pinocchio::{ /// 0. `[WRITE]` Nonce account pub struct UpdateNonceAccount<'a> { /// Nonce account. - pub account: &'a AccountInfo, + pub account: &'a AccountView, } impl UpdateNonceAccount<'_> { diff --git a/programs/system/src/instructions/withdraw_nonce_account.rs b/programs/system/src/instructions/withdraw_nonce_account.rs index e45185e6..dbb1f772 100644 --- a/programs/system/src/instructions/withdraw_nonce_account.rs +++ b/programs/system/src/instructions/withdraw_nonce_account.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -18,19 +18,19 @@ use pinocchio::{ /// 4. `[SIGNER]` Nonce authority pub struct WithdrawNonceAccount<'a> { /// Nonce account. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Recipient account. - pub recipient: &'a AccountInfo, + pub recipient: &'a AccountView, /// RecentBlockhashes sysvar. - pub recent_blockhashes_sysvar: &'a AccountInfo, + pub recent_blockhashes_sysvar: &'a AccountView, /// Rent sysvar. - pub rent_sysvar: &'a AccountInfo, + pub rent_sysvar: &'a AccountView, /// Nonce authority. - pub authority: &'a AccountInfo, + pub authority: &'a AccountView, /// Lamports to withdraw. /// diff --git a/programs/token/src/instructions/approve.rs b/programs/token/src/instructions/approve.rs index 80355a7d..d5730cd9 100644 --- a/programs/token/src/instructions/approve.rs +++ b/programs/token/src/instructions/approve.rs @@ -1,7 +1,7 @@ use core::slice::from_raw_parts; use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -17,11 +17,11 @@ use crate::{write_bytes, UNINIT_BYTE}; /// 2. `[SIGNER]` The source account owner. pub struct Approve<'a> { /// Source Account. - pub source: &'a AccountInfo, + pub source: &'a AccountView, /// Delegate Account - pub delegate: &'a AccountInfo, + pub delegate: &'a AccountView, /// Source Owner Account - pub authority: &'a AccountInfo, + pub authority: &'a AccountView, /// Amount pub amount: u64, } diff --git a/programs/token/src/instructions/approve_checked.rs b/programs/token/src/instructions/approve_checked.rs index 9c924936..8b4f643c 100644 --- a/programs/token/src/instructions/approve_checked.rs +++ b/programs/token/src/instructions/approve_checked.rs @@ -1,7 +1,7 @@ use core::slice::from_raw_parts; use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -18,13 +18,13 @@ use crate::{write_bytes, UNINIT_BYTE}; /// 3. `[SIGNER]` The source account owner. pub struct ApproveChecked<'a> { /// Source Account. - pub source: &'a AccountInfo, + pub source: &'a AccountView, /// Mint Account. - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Delegate Account. - pub delegate: &'a AccountInfo, + pub delegate: &'a AccountView, /// Source Owner Account. - pub authority: &'a AccountInfo, + pub authority: &'a AccountView, /// Amount. pub amount: u64, /// Decimals. diff --git a/programs/token/src/instructions/burn.rs b/programs/token/src/instructions/burn.rs index d379faf1..5f4a6f8b 100644 --- a/programs/token/src/instructions/burn.rs +++ b/programs/token/src/instructions/burn.rs @@ -1,7 +1,7 @@ use core::slice::from_raw_parts; use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -17,11 +17,11 @@ use crate::{write_bytes, UNINIT_BYTE}; /// 2. `[SIGNER]` The account's owner/delegate. pub struct Burn<'a> { /// Source of the Burn Account - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Mint Account - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Owner of the Token Account - pub authority: &'a AccountInfo, + pub authority: &'a AccountView, /// Amount pub amount: u64, } diff --git a/programs/token/src/instructions/burn_checked.rs b/programs/token/src/instructions/burn_checked.rs index cd316644..c5781811 100644 --- a/programs/token/src/instructions/burn_checked.rs +++ b/programs/token/src/instructions/burn_checked.rs @@ -2,7 +2,7 @@ use core::slice::from_raw_parts; use crate::{write_bytes, UNINIT_BYTE}; use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -16,11 +16,11 @@ use pinocchio::{ /// 2. `[SIGNER]` The account's owner/delegate. pub struct BurnChecked<'a> { /// Source of the Burn Account - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Mint Account - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Owner of the Token Account - pub authority: &'a AccountInfo, + pub authority: &'a AccountView, /// Amount pub amount: u64, /// Decimals diff --git a/programs/token/src/instructions/close_account.rs b/programs/token/src/instructions/close_account.rs index 0d6d6947..e3ae50b0 100644 --- a/programs/token/src/instructions/close_account.rs +++ b/programs/token/src/instructions/close_account.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -13,11 +13,11 @@ use pinocchio::{ /// 2. `[SIGNER]` The account's owner. pub struct CloseAccount<'a> { /// Token Account. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Destination Account - pub destination: &'a AccountInfo, + pub destination: &'a AccountView, /// Owner Account - pub authority: &'a AccountInfo, + pub authority: &'a AccountView, } impl CloseAccount<'_> { diff --git a/programs/token/src/instructions/freeze_account.rs b/programs/token/src/instructions/freeze_account.rs index 3cf2fb55..973494a1 100644 --- a/programs/token/src/instructions/freeze_account.rs +++ b/programs/token/src/instructions/freeze_account.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -13,11 +13,11 @@ use pinocchio::{ /// 2. `[SIGNER]` The mint freeze authority. pub struct FreezeAccount<'a> { /// Token Account to freeze. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Mint Account. - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Mint Freeze Authority Account - pub freeze_authority: &'a AccountInfo, + pub freeze_authority: &'a AccountView, } impl FreezeAccount<'_> { diff --git a/programs/token/src/instructions/initialize_account.rs b/programs/token/src/instructions/initialize_account.rs index cd608146..d03ce6d7 100644 --- a/programs/token/src/instructions/initialize_account.rs +++ b/programs/token/src/instructions/initialize_account.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -14,13 +14,13 @@ use pinocchio::{ /// 3. `[]` Rent sysvar pub struct InitializeAccount<'a> { /// New Account. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Mint Account. - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Owner of the new Account. - pub owner: &'a AccountInfo, + pub owner: &'a AccountView, /// Rent Sysvar Account - pub rent_sysvar: &'a AccountInfo, + pub rent_sysvar: &'a AccountView, } impl InitializeAccount<'_> { diff --git a/programs/token/src/instructions/initialize_account_2.rs b/programs/token/src/instructions/initialize_account_2.rs index 14f8ca2b..397ccf32 100644 --- a/programs/token/src/instructions/initialize_account_2.rs +++ b/programs/token/src/instructions/initialize_account_2.rs @@ -1,7 +1,7 @@ use core::slice::from_raw_parts; use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, Address, ProgramResult, @@ -17,11 +17,11 @@ use crate::{write_bytes, UNINIT_BYTE}; /// 3. `[]` Rent sysvar pub struct InitializeAccount2<'a> { /// New Account. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Mint Account. - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Rent Sysvar Account - pub rent_sysvar: &'a AccountInfo, + pub rent_sysvar: &'a AccountView, /// Owner of the new Account. pub owner: &'a Address, } diff --git a/programs/token/src/instructions/initialize_account_3.rs b/programs/token/src/instructions/initialize_account_3.rs index b7651d68..a7d98c1d 100644 --- a/programs/token/src/instructions/initialize_account_3.rs +++ b/programs/token/src/instructions/initialize_account_3.rs @@ -1,7 +1,7 @@ use core::slice::from_raw_parts; use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, Address, ProgramResult, @@ -16,9 +16,9 @@ use crate::{write_bytes, UNINIT_BYTE}; /// 1. `[]` The mint this account will be associated with. pub struct InitializeAccount3<'a> { /// New Account. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Mint Account. - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Owner of the new Account. pub owner: &'a Address, } diff --git a/programs/token/src/instructions/initialize_mint.rs b/programs/token/src/instructions/initialize_mint.rs index 11148504..100e15f9 100644 --- a/programs/token/src/instructions/initialize_mint.rs +++ b/programs/token/src/instructions/initialize_mint.rs @@ -1,7 +1,7 @@ use core::slice::from_raw_parts; use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, Address, ProgramResult, @@ -16,9 +16,9 @@ use crate::{write_bytes, UNINIT_BYTE}; /// 1. `[]` Rent sysvar pub struct InitializeMint<'a> { /// Mint Account. - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Rent sysvar Account. - pub rent_sysvar: &'a AccountInfo, + pub rent_sysvar: &'a AccountView, /// Decimals. pub decimals: u8, /// Mint Authority. diff --git a/programs/token/src/instructions/initialize_mint_2.rs b/programs/token/src/instructions/initialize_mint_2.rs index 800609bc..005a7970 100644 --- a/programs/token/src/instructions/initialize_mint_2.rs +++ b/programs/token/src/instructions/initialize_mint_2.rs @@ -1,7 +1,7 @@ use core::slice::from_raw_parts; use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, Address, ProgramResult, @@ -15,7 +15,7 @@ use crate::{write_bytes, UNINIT_BYTE}; /// 0. `[WRITABLE]` Mint account pub struct InitializeMint2<'a> { /// Mint Account. - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Decimals. pub decimals: u8, /// Mint Authority. diff --git a/programs/token/src/instructions/mint_to.rs b/programs/token/src/instructions/mint_to.rs index 91ce6f90..e6f0bad3 100644 --- a/programs/token/src/instructions/mint_to.rs +++ b/programs/token/src/instructions/mint_to.rs @@ -1,7 +1,7 @@ use core::slice::from_raw_parts; use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -18,11 +18,11 @@ use crate::{write_bytes, UNINIT_BYTE}; /// pub struct MintTo<'a> { /// Mint Account. - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Token Account. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Mint Authority - pub mint_authority: &'a AccountInfo, + pub mint_authority: &'a AccountView, /// Amount pub amount: u64, } diff --git a/programs/token/src/instructions/mint_to_checked.rs b/programs/token/src/instructions/mint_to_checked.rs index 9496932c..58e81a68 100644 --- a/programs/token/src/instructions/mint_to_checked.rs +++ b/programs/token/src/instructions/mint_to_checked.rs @@ -1,7 +1,7 @@ use core::slice::from_raw_parts; use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -18,11 +18,11 @@ use crate::{write_bytes, UNINIT_BYTE}; /// pub struct MintToChecked<'a> { /// Mint Account. - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Token Account. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Mint Authority - pub mint_authority: &'a AccountInfo, + pub mint_authority: &'a AccountView, /// Amount pub amount: u64, /// Decimals diff --git a/programs/token/src/instructions/revoke.rs b/programs/token/src/instructions/revoke.rs index cbb4c815..ba61e6bc 100644 --- a/programs/token/src/instructions/revoke.rs +++ b/programs/token/src/instructions/revoke.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -12,9 +12,9 @@ use pinocchio::{ /// 1. `[SIGNER]` The source account owner. pub struct Revoke<'a> { /// Source Account. - pub source: &'a AccountInfo, + pub source: &'a AccountView, /// Source Owner Account. - pub authority: &'a AccountInfo, + pub authority: &'a AccountView, } impl Revoke<'_> { diff --git a/programs/token/src/instructions/set_authority.rs b/programs/token/src/instructions/set_authority.rs index 216685e7..2972fec9 100644 --- a/programs/token/src/instructions/set_authority.rs +++ b/programs/token/src/instructions/set_authority.rs @@ -1,7 +1,7 @@ use core::slice::from_raw_parts; use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, Address, ProgramResult, @@ -25,10 +25,10 @@ pub enum AuthorityType { /// 1. `[SIGNER]` The current authority of the mint or account. pub struct SetAuthority<'a> { /// Account (Mint or Token) - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Authority of the Account. - pub authority: &'a AccountInfo, + pub authority: &'a AccountView, /// The type of authority to update. pub authority_type: AuthorityType, diff --git a/programs/token/src/instructions/sync_native.rs b/programs/token/src/instructions/sync_native.rs index b6ea680c..5c31d34b 100644 --- a/programs/token/src/instructions/sync_native.rs +++ b/programs/token/src/instructions/sync_native.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -13,7 +13,7 @@ use pinocchio::{ /// lamports. pub struct SyncNative<'a> { /// Native Token Account - pub native_token: &'a AccountInfo, + pub native_token: &'a AccountView, } impl SyncNative<'_> { diff --git a/programs/token/src/instructions/thaw_account.rs b/programs/token/src/instructions/thaw_account.rs index 1ffacf92..e036fe84 100644 --- a/programs/token/src/instructions/thaw_account.rs +++ b/programs/token/src/instructions/thaw_account.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -13,11 +13,11 @@ use pinocchio::{ /// 2. `[SIGNER]` The mint freeze authority. pub struct ThawAccount<'a> { /// Token Account to thaw. - pub account: &'a AccountInfo, + pub account: &'a AccountView, /// Mint Account. - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Mint Freeze Authority Account - pub freeze_authority: &'a AccountInfo, + pub freeze_authority: &'a AccountView, } impl ThawAccount<'_> { diff --git a/programs/token/src/instructions/transfer.rs b/programs/token/src/instructions/transfer.rs index 389b0c23..a93d5247 100644 --- a/programs/token/src/instructions/transfer.rs +++ b/programs/token/src/instructions/transfer.rs @@ -1,7 +1,7 @@ use core::slice::from_raw_parts; use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -17,11 +17,11 @@ use crate::{write_bytes, UNINIT_BYTE}; /// 2. `[SIGNER]` Authority account pub struct Transfer<'a> { /// Sender account. - pub from: &'a AccountInfo, + pub from: &'a AccountView, /// Recipient account. - pub to: &'a AccountInfo, + pub to: &'a AccountView, /// Authority account. - pub authority: &'a AccountInfo, + pub authority: &'a AccountView, /// Amount of microtokens to transfer. pub amount: u64, } diff --git a/programs/token/src/instructions/transfer_checked.rs b/programs/token/src/instructions/transfer_checked.rs index a7db7b6e..7f8a39f4 100644 --- a/programs/token/src/instructions/transfer_checked.rs +++ b/programs/token/src/instructions/transfer_checked.rs @@ -1,7 +1,7 @@ use core::slice::from_raw_parts; use pinocchio::{ - account_info::AccountInfo, + account_view::AccountView, instruction::{AccountMeta, Instruction, Signer}, program::invoke_signed, ProgramResult, @@ -18,13 +18,13 @@ use crate::{write_bytes, UNINIT_BYTE}; /// 3. `[SIGNER]` The source account's owner/delegate. pub struct TransferChecked<'a> { /// Sender account. - pub from: &'a AccountInfo, + pub from: &'a AccountView, /// Mint Account - pub mint: &'a AccountInfo, + pub mint: &'a AccountView, /// Recipient account. - pub to: &'a AccountInfo, + pub to: &'a AccountView, /// Authority account. - pub authority: &'a AccountInfo, + pub authority: &'a AccountView, /// Amount of microtokens to transfer. pub amount: u64, /// Decimal for the Token diff --git a/programs/token/src/state/mint.rs b/programs/token/src/state/mint.rs index cff6c485..7c2eca37 100644 --- a/programs/token/src/state/mint.rs +++ b/programs/token/src/state/mint.rs @@ -1,5 +1,5 @@ use pinocchio::{ - account_info::{AccountInfo, Ref}, + account_view::{AccountView, Ref}, program_error::ProgramError, Address, }; @@ -40,10 +40,10 @@ impl Mint { /// Return a `Mint` from the given account info. /// - /// This method performs owner and length validation on `AccountInfo`, safe borrowing + /// This method performs owner and length validation on `AccountView`, safe borrowing /// the account data. #[inline] - pub fn from_account_info(account_info: &AccountInfo) -> Result, ProgramError> { + pub fn from_account_info(account_info: &AccountView) -> Result, ProgramError> { if account_info.data_len() != Self::LEN { return Err(ProgramError::InvalidAccountData); } @@ -57,7 +57,7 @@ impl Mint { /// Return a `Mint` from the given account info. /// - /// This method performs owner and length validation on `AccountInfo`, but does not + /// This method performs owner and length validation on `AccountView`, but does not /// perform the borrow check. /// /// # Safety @@ -66,7 +66,7 @@ impl Mint { /// no mutable borrows of the account data. #[inline] pub unsafe fn from_account_info_unchecked( - account_info: &AccountInfo, + account_info: &AccountView, ) -> Result<&Self, ProgramError> { if account_info.data_len() != Self::LEN { return Err(ProgramError::InvalidAccountData); diff --git a/programs/token/src/state/token.rs b/programs/token/src/state/token.rs index 1ebb0c73..8d302930 100644 --- a/programs/token/src/state/token.rs +++ b/programs/token/src/state/token.rs @@ -1,6 +1,6 @@ use super::AccountState; use pinocchio::{ - account_info::{AccountInfo, Ref}, + account_view::{AccountView, Ref}, program_error::ProgramError, Address, }; @@ -53,11 +53,11 @@ impl TokenAccount { /// Return a `TokenAccount` from the given account info. /// - /// This method performs owner and length validation on `AccountInfo`, safe borrowing + /// This method performs owner and length validation on `AccountView`, safe borrowing /// the account data. #[inline] pub fn from_account_info( - account_info: &AccountInfo, + account_info: &AccountView, ) -> Result, ProgramError> { if account_info.data_len() != Self::LEN { return Err(ProgramError::InvalidAccountData); @@ -72,7 +72,7 @@ impl TokenAccount { /// Return a `TokenAccount` from the given account info. /// - /// This method performs owner and length validation on `AccountInfo`, but does not + /// This method performs owner and length validation on `AccountView`, but does not /// perform the borrow check. /// /// # Safety @@ -81,7 +81,7 @@ impl TokenAccount { /// no mutable borrows of the account data. #[inline] pub unsafe fn from_account_info_unchecked( - account_info: &AccountInfo, + account_info: &AccountView, ) -> Result<&TokenAccount, ProgramError> { if account_info.data_len() != Self::LEN { return Err(ProgramError::InvalidAccountData); diff --git a/sdk/pinocchio/Cargo.toml b/sdk/pinocchio/Cargo.toml index e7031691..5e25b222 100644 --- a/sdk/pinocchio/Cargo.toml +++ b/sdk/pinocchio/Cargo.toml @@ -20,5 +20,6 @@ unexpected_cfgs = { level = "warn", check-cfg = [ std = ["solana-program-error/std"] [dependencies] +solana-account-view = { workspace = true } solana-address = { workspace = true, features = ["syscalls"] } solana-program-error = { version = "2.2.1", git = "https://github.com/kevinheavey/solana-sdk.git", branch = "program-error-pinocchio-compat" } diff --git a/sdk/pinocchio/src/account_info.rs b/sdk/pinocchio/src/account_info.rs deleted file mode 100644 index c4b60f86..00000000 --- a/sdk/pinocchio/src/account_info.rs +++ /dev/null @@ -1,779 +0,0 @@ -//! Data structures to represent account information. -use core::{ - marker::PhantomData, - mem::ManuallyDrop, - ptr::NonNull, - slice::{from_raw_parts, from_raw_parts_mut}, -}; - -#[cfg(target_os = "solana")] -use crate::syscalls::sol_memset_; - -use crate::{program_error::ProgramError, ProgramResult}; -use solana_address::Address; - -/// Maximum number of bytes a program may add to an account during a -/// single top-level instruction. -pub const MAX_PERMITTED_DATA_INCREASE: usize = 1_024 * 10; - -/// Raw account data. -/// -/// This data is wrapped in an `AccountInfo` struct, which provides safe access -/// to the data. -#[repr(C)] -#[derive(Clone, Copy, Default)] -pub(crate) struct Account { - /// Borrow state of the account data. - /// - /// 0) We reuse the duplicate flag for this. We set it to 0b0000_0000. - /// 1) We use the first four bits to track state of lamport borrow - /// 2) We use the second four bits to track state of data borrow - /// - /// 4 bit state: [1 bit mutable borrow flag | u3 immmutable borrow flag] - /// This gives us up to 7 immutable borrows. Note that does not mean 7 - /// duplicate account infos, but rather 7 calls to borrow lamports or - /// borrow data across all duplicate account infos. - pub(crate) borrow_state: u8, - - /// Indicates whether the transaction was signed by this account. - is_signer: u8, - - /// Indicates whether the account is writable. - is_writable: u8, - - /// Indicates whether this account represents a program. - executable: u8, - - /// Account's original data length when it was serialized for the - /// current program invocation. - /// - /// The value of this field is lazily initialized to the current data length - /// and the [`SET_LEN_MASK`] flag on first access. When reading this field, - /// the flag is cleared to retrieve the original data length by using the - /// [`GET_LEN_MASK`] mask. - /// - /// Currently, this value is only used for `realloc` to determine if the - /// account data length has changed from the original serialized length beyond - /// the maximum permitted data increase. - original_data_len: u32, - - /// Address of the account. - key: Address, - - /// Program that owns this account. Modifiable by programs. - owner: Address, - - /// The lamports in the account. Modifiable by programs. - lamports: u64, - - /// Length of the data. Modifiable by programs. - pub(crate) data_len: u64, -} - -/// Mask to indicate the original data length has been set. -/// -/// This takes advantage of the fact that the original data length will not -/// be greater than 10_000_000 bytes, so we can use the most significant bit -/// as a flag to indicate that the original data length has been set and lazily -/// initialize its value. -const SET_LEN_MASK: u32 = 1 << 31; - -/// Mask to retrieve the original data length. -/// -/// This mask is used to retrieve the original data length from the `original_data_len` -/// by clearing the flag that indicates the original data length has been set. -const GET_LEN_MASK: u32 = !SET_LEN_MASK; - -/// Wrapper struct for an `Account`. -/// -/// This struct provides safe access to the data in an `Account`. It is also -/// used to track borrows of the account data and lamports, given that an -/// account can be "shared" across multiple `AccountInfo` instances. -#[repr(C)] -#[derive(Clone, PartialEq, Eq)] -pub struct AccountInfo { - /// Raw (pointer to) account data. - /// - /// Note that this is a pointer can be shared across multiple `AccountInfo`. - pub(crate) raw: *mut Account, -} - -impl AccountInfo { - /// Address of the account. - #[inline(always)] - pub fn key(&self) -> &Address { - unsafe { &(*self.raw).key } - } - - /// Program that owns this account. - /// - /// # Safety - /// - /// A reference returned by this method is invalidated when [`Self::assign`] - /// is called. - #[inline(always)] - pub unsafe fn owner(&self) -> &Address { - &(*self.raw).owner - } - - /// Indicates whether the transaction was signed by this account. - #[inline(always)] - pub fn is_signer(&self) -> bool { - unsafe { (*self.raw).is_signer != 0 } - } - - /// Indicates whether the account is writable. - #[inline(always)] - pub fn is_writable(&self) -> bool { - unsafe { (*self.raw).is_writable != 0 } - } - - /// Indicates whether this account represents a program. - /// - /// Program accounts are always read-only. - #[inline(always)] - pub fn executable(&self) -> bool { - unsafe { (*self.raw).executable != 0 } - } - - /// Returns the size of the data in the account. - #[inline(always)] - pub fn data_len(&self) -> usize { - unsafe { (*self.raw).data_len as usize } - } - - /// Returns the lamports in the account. - #[inline(always)] - pub fn lamports(&self) -> u64 { - unsafe { (*self.raw).lamports } - } - - /// Indicates whether the account data is empty. - /// - /// An account is considered empty if the data length is zero. - #[inline(always)] - pub fn data_is_empty(&self) -> bool { - self.data_len() == 0 - } - - /// Checks if the account is owned by the given program. - #[inline(always)] - pub fn is_owned_by(&self, program: &Address) -> bool { - unsafe { &(*self.raw).owner == program } - } - - /// Changes the owner of the account. - /// - /// # Safety - /// - /// Using this method invalidates any reference returned by [`Self::owner`]. - #[inline(always)] - pub unsafe fn assign(&self, new_owner: &Address) { - #[allow(invalid_reference_casting)] - core::ptr::write_volatile(&(*self.raw).owner as *const _ as *mut Address, *new_owner); - } - - /// Returns a read-only reference to the lamports in the account. - /// - /// # Safety - /// - /// This method is unsafe because it does not return a `Ref`, thus leaving the borrow - /// flag untouched. Useful when an instruction has verified non-duplicate accounts. - #[inline(always)] - pub unsafe fn borrow_lamports_unchecked(&self) -> &u64 { - &(*self.raw).lamports - } - - /// Returns a mutable reference to the lamports in the account. - /// - /// # Safety - /// - /// This method is unsafe because it does not return a `Ref`, thus leaving the borrow - /// flag untouched. Useful when an instruction has verified non-duplicate accounts. - #[allow(clippy::mut_from_ref)] - #[inline(always)] - pub unsafe fn borrow_mut_lamports_unchecked(&self) -> &mut u64 { - &mut (*self.raw).lamports - } - - /// Returns a read-only reference to the data in the account. - /// - /// # Safety - /// - /// This method is unsafe because it does not return a `Ref`, thus leaving the borrow - /// flag untouched. Useful when an instruction has verified non-duplicate accounts. - #[inline(always)] - pub unsafe fn borrow_data_unchecked(&self) -> &[u8] { - core::slice::from_raw_parts(self.data_ptr(), self.data_len()) - } - - /// Returns a mutable reference to the data in the account. - /// - /// # Safety - /// - /// This method is unsafe because it does not return a `Ref`, thus leaving the borrow - /// flag untouched. Useful when an instruction has verified non-duplicate accounts. - #[allow(clippy::mut_from_ref)] - #[inline(always)] - pub unsafe fn borrow_mut_data_unchecked(&self) -> &mut [u8] { - core::slice::from_raw_parts_mut(self.data_ptr(), self.data_len()) - } - - /// Tries to get a read-only reference to the lamport field, failing if the - /// field is already mutable borrowed or if 7 borrows already exist. - pub fn try_borrow_lamports(&self) -> Result, ProgramError> { - // check if the account lamports are already borrowed - self.check_borrow_lamports()?; - - let borrow_state = unsafe { &mut (*self.raw).borrow_state }; - // increment the immutable borrow count - *borrow_state += 1 << LAMPORTS_SHIFT; - - // return the reference to lamports - Ok(Ref { - value: unsafe { NonNull::from(&(*self.raw).lamports) }, - state: unsafe { NonNull::new_unchecked(borrow_state) }, - borrow_shift: LAMPORTS_SHIFT, - marker: PhantomData, - }) - } - - /// Tries to get a read only reference to the lamport field, failing if the field - /// is already borrowed in any form. - pub fn try_borrow_mut_lamports(&self) -> Result, ProgramError> { - // check if the account lamports are already borrowed - self.check_borrow_mut_lamports()?; - - let borrow_state = unsafe { &mut (*self.raw).borrow_state }; - // set the mutable lamport borrow flag - *borrow_state |= 0b_1000_0000; - - // return the mutable reference to lamports - Ok(RefMut { - value: unsafe { NonNull::from(&mut (*self.raw).lamports) }, - state: unsafe { NonNull::new_unchecked(borrow_state) }, - borrow_mask: LAMPORTS_MASK, - marker: PhantomData, - }) - } - - /// Checks if it is possible to get a read-only reference to the lamport field, - /// failing if the field is already mutable borrowed or if 7 borrows already exist. - #[inline(always)] - pub fn check_borrow_lamports(&self) -> Result<(), ProgramError> { - let borrow_state = unsafe { (*self.raw).borrow_state }; - - // check if mutable borrow is already taken - if borrow_state & 0b_1000_0000 != 0 { - return Err(ProgramError::AccountBorrowFailed); - } - - // check if we have reached the max immutable borrow count - if borrow_state & 0b_0111_0000 == 0b_0111_0000 { - return Err(ProgramError::AccountBorrowFailed); - } - - Ok(()) - } - - /// Checks if it is possible to get a mutable reference to the lamport field, - /// failing if the field is already borrowed in any form. - #[inline(always)] - pub fn check_borrow_mut_lamports(&self) -> Result<(), ProgramError> { - let borrow_state = unsafe { (*self.raw).borrow_state }; - - // check if any borrow (mutable or immutable) is already taken for lamports - if borrow_state & 0b_1111_0000 != 0 { - return Err(ProgramError::AccountBorrowFailed); - } - - Ok(()) - } - - /// Tries to get a read-only reference to the data field, failing if the field - /// is already mutable borrowed or if 7 borrows already exist. - pub fn try_borrow_data(&self) -> Result, ProgramError> { - // check if the account data is already borrowed - self.check_borrow_data()?; - - let borrow_state = unsafe { &mut (*self.raw).borrow_state }; - // increment the immutable data borrow count - *borrow_state += 1; - - // return the reference to data - Ok(Ref { - value: unsafe { NonNull::from(from_raw_parts(self.data_ptr(), self.data_len())) }, - state: unsafe { NonNull::new_unchecked(borrow_state) }, - borrow_shift: DATA_SHIFT, - marker: PhantomData, - }) - } - - /// Tries to get a mutable reference to the data field, failing if the field - /// is already borrowed in any form. - pub fn try_borrow_mut_data(&self) -> Result, ProgramError> { - // check if the account data is already borrowed - self.check_borrow_mut_data()?; - - let borrow_state = unsafe { &mut (*self.raw).borrow_state }; - // set the mutable data borrow flag - *borrow_state |= 0b_0000_1000; - - // return the mutable reference to data - Ok(RefMut { - value: unsafe { NonNull::from(from_raw_parts_mut(self.data_ptr(), self.data_len())) }, - state: unsafe { NonNull::new_unchecked(borrow_state) }, - borrow_mask: DATA_MASK, - marker: PhantomData, - }) - } - - /// Checks if it is possible to get a read-only reference to the data field, failing - /// if the field is already mutable borrowed or if 7 borrows already exist. - #[inline(always)] - pub fn check_borrow_data(&self) -> Result<(), ProgramError> { - let borrow_state = unsafe { (*self.raw).borrow_state }; - - // check if mutable data borrow is already taken (most significant bit - // of the data_borrow_state) - if borrow_state & 0b_0000_1000 != 0 { - return Err(ProgramError::AccountBorrowFailed); - } - - // check if we have reached the max immutable data borrow count (7) - if borrow_state & 0b_0111 == 0b0111 { - return Err(ProgramError::AccountBorrowFailed); - } - - Ok(()) - } - - /// Checks if it is possible to get a mutable reference to the data field, failing - /// if the field is already borrowed in any form. - #[inline(always)] - pub fn check_borrow_mut_data(&self) -> Result<(), ProgramError> { - let borrow_state = unsafe { (*self.raw).borrow_state }; - - // check if any borrow (mutable or immutable) is already taken for data - if borrow_state & 0b_0000_1111 != 0 { - return Err(ProgramError::AccountBorrowFailed); - } - - Ok(()) - } - - /// Realloc the account's data and optionally zero-initialize the new - /// memory. - /// - /// Note: Account data can be increased within a single call by up to - /// [`MAX_PERMITTED_DATA_INCREASE`] bytes. - /// - /// Note: Memory used to grow is already zero-initialized upon program - /// entrypoint and re-zeroing it wastes compute units. If within the same - /// call a program reallocs from larger to smaller and back to larger again - /// the new space could contain stale data. Pass `true` for `zero_init` in - /// this case, otherwise compute units will be wasted re-zero-initializing. - /// - /// # Safety - /// - /// This method makes assumptions about the layout and location of memory - /// referenced by `AccountInfo` fields. It should only be called for - /// instances of `AccountInfo` that were created by the runtime and received - /// in the `process_instruction` entrypoint of a program. - pub fn realloc(&self, new_len: usize, zero_init: bool) -> Result<(), ProgramError> { - let mut data = self.try_borrow_mut_data()?; - let current_len = data.len(); - - // return early if length hasn't changed - if new_len == current_len { - return Ok(()); - } - - let original_len = { - let length = unsafe { (*self.raw).original_data_len }; - - if length & SET_LEN_MASK == SET_LEN_MASK { - (length & GET_LEN_MASK) as usize - } else { - // lazily initialize the original data length and sets the flag - unsafe { - (*self.raw).original_data_len = (current_len as u32) | SET_LEN_MASK; - } - current_len - } - }; - - // return early if the length increase from the original serialized data - // length is too large and would result in an out of bounds allocation - if new_len.saturating_sub(original_len) > MAX_PERMITTED_DATA_INCREASE { - return Err(ProgramError::InvalidRealloc); - } - - // realloc - unsafe { - let data_ptr = data.as_mut_ptr(); - // set new length in the serialized data - (*self.raw).data_len = new_len as u64; - // recreate the local slice with the new length - data.value = NonNull::from(from_raw_parts_mut(data_ptr, new_len)); - } - - if zero_init { - let len_increase = new_len.saturating_sub(current_len); - if len_increase > 0 { - unsafe { - #[cfg(target_os = "solana")] - sol_memset_( - &mut data[current_len..] as *mut _ as *mut u8, - 0, - len_increase as u64, - ); - #[cfg(not(target_os = "solana"))] - core::ptr::write_bytes(data.as_mut_ptr().add(current_len), 0, len_increase); - } - } - } - - Ok(()) - } - - /// Zero out the the account's data length, lamports and owner fields, effectively - /// closing the account. - /// - /// This doesn't protect against future reinitialization of the account - /// since the account data will need to be zeroed out as well; otherwise the lenght, - /// lamports and owner can be set again before the data is wiped out from - /// the ledger using the keypair of the account being closed. - /// - /// # Important - /// - /// The lamports must be moved from the account prior to closing it to prevent - /// an unbalanced instruction error. - #[inline] - pub fn close(&self) -> ProgramResult { - // make sure the account is not borrowed since we are about to - // resize the data to zero - self.check_borrow_mut_data()?; - - unsafe { - self.close_unchecked(); - } - - Ok(()) - } - - /// Zero out the the account's data length, lamports and owner fields, effectively - /// closing the account. - /// - /// This doesn't protect against future reinitialization of the account - /// since the account data will need to be zeroed out as well; otherwise the lenght, - /// lamports and owner can be set again before the data is wiped out from - /// the ledger using the keypair of the account being closed. - /// - /// # Important - /// - /// The lamports must be moved from the account prior to closing it to prevent - /// an unbalanced instruction error. - /// - /// # Safety - /// - /// This method is unsafe because it does not check if the account data is already - /// borrowed. It should only be called when the account is not being used. - /// - /// It also makes assumptions about the layout and location of memory - /// referenced by `AccountInfo` fields. It should only be called for - /// instances of `AccountInfo` that were created by the runtime and received - /// in the `process_instruction` entrypoint of a program. - #[inline(always)] - pub unsafe fn close_unchecked(&self) { - // We take advantage that the 48 bytes before the account data are: - // - 32 bytes for the owner - // - 8 bytes for the lamports - // - 8 bytes for the data_len - // - // So we can zero out them directly. - #[cfg(target_os = "solana")] - sol_memset_(self.data_ptr().sub(48), 0, 48); - } - - /// Returns the memory address of the account data. - fn data_ptr(&self) -> *mut u8 { - unsafe { (self.raw as *const _ as *mut u8).add(core::mem::size_of::()) } - } -} - -/// Bytes to shift to get to the borrow state of lamports. -const LAMPORTS_SHIFT: u8 = 4; - -/// Bytes to shift to get to the borrow state of data. -const DATA_SHIFT: u8 = 0; - -/// Reference to account data or lamports with checked borrow rules. -pub struct Ref<'a, T: ?Sized> { - value: NonNull, - state: NonNull, - /// Indicates the type of borrow (lamports or data) by representing the - /// shift amount. - borrow_shift: u8, - /// The `value` raw pointer is only valid while the `&'a T` lives so we claim - /// to hold a reference to it. - marker: PhantomData<&'a T>, -} - -impl<'a, T: ?Sized> Ref<'a, T> { - /// Maps a reference to a new type. - #[inline] - pub fn map(orig: Ref<'a, T>, f: F) -> Ref<'a, U> - where - F: FnOnce(&T) -> &U, - { - // Avoid decrementing the borrow flag on Drop. - let orig = ManuallyDrop::new(orig); - - Ref { - value: NonNull::from(f(&*orig)), - state: orig.state, - borrow_shift: orig.borrow_shift, - marker: PhantomData, - } - } - - /// Filters and maps a reference to a new type. - #[inline] - pub fn filter_map(orig: Ref<'a, T>, f: F) -> Result, Self> - where - F: FnOnce(&T) -> Option<&U>, - { - // Avoid decrementing the borrow flag on Drop. - let orig = ManuallyDrop::new(orig); - - match f(&*orig) { - Some(value) => Ok(Ref { - value: NonNull::from(value), - state: orig.state, - borrow_shift: orig.borrow_shift, - marker: PhantomData, - }), - None => Err(ManuallyDrop::into_inner(orig)), - } - } -} - -impl core::ops::Deref for Ref<'_, T> { - type Target = T; - fn deref(&self) -> &Self::Target { - unsafe { self.value.as_ref() } - } -} - -impl Drop for Ref<'_, T> { - // decrement the immutable borrow count - fn drop(&mut self) { - unsafe { *self.state.as_mut() -= 1 << self.borrow_shift }; - } -} - -/// Mask representing the mutable borrow flag for lamports. -const LAMPORTS_MASK: u8 = 0b_0111_1111; - -/// Mask representing the mutable borrow flag for data. -const DATA_MASK: u8 = 0b_1111_0111; - -/// Mutable reference to account data or lamports with checked borrow rules. -pub struct RefMut<'a, T: ?Sized> { - value: NonNull, - state: NonNull, - /// Indicates the type of borrow (lamports or data) by representing the - /// mutable borrow mask. - borrow_mask: u8, - /// The `value` raw pointer is only valid while the `&'a T` lives so we claim - /// to hold a reference to it. - marker: PhantomData<&'a mut T>, -} - -impl<'a, T: ?Sized> RefMut<'a, T> { - /// Maps a mutable reference to a new type. - #[inline] - pub fn map(orig: RefMut<'a, T>, f: F) -> RefMut<'a, U> - where - F: FnOnce(&mut T) -> &mut U, - { - // Avoid decrementing the borrow flag on Drop. - let mut orig = ManuallyDrop::new(orig); - - RefMut { - value: NonNull::from(f(&mut *orig)), - state: orig.state, - borrow_mask: orig.borrow_mask, - marker: PhantomData, - } - } - - /// Filters and maps a mutable reference to a new type. - #[inline] - pub fn filter_map(orig: RefMut<'a, T>, f: F) -> Result, Self> - where - F: FnOnce(&mut T) -> Option<&mut U>, - { - // Avoid decrementing the mutable borrow flag on Drop. - let mut orig = ManuallyDrop::new(orig); - - match f(&mut *orig) { - Some(value) => { - let value = NonNull::from(value); - Ok(RefMut { - value, - state: orig.state, - borrow_mask: orig.borrow_mask, - marker: PhantomData, - }) - } - None => Err(ManuallyDrop::into_inner(orig)), - } - } -} - -impl core::ops::Deref for RefMut<'_, T> { - type Target = T; - fn deref(&self) -> &Self::Target { - unsafe { self.value.as_ref() } - } -} -impl core::ops::DerefMut for RefMut<'_, T> { - fn deref_mut(&mut self) -> &mut ::Target { - unsafe { self.value.as_mut() } - } -} - -impl Drop for RefMut<'_, T> { - fn drop(&mut self) { - // unset the mutable borrow flag - unsafe { *self.state.as_mut() &= self.borrow_mask }; - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_data_ref() { - let data: [u8; 4] = [0, 1, 2, 3]; - let state = 1 << DATA_SHIFT; - - let ref_data = Ref { - value: NonNull::from(&data), - borrow_shift: DATA_SHIFT, - state: NonNull::from(&state), - marker: PhantomData, - }; - - let new_ref = Ref::map(ref_data, |data| &data[1]); - - assert_eq!(state, 1 << DATA_SHIFT); - assert_eq!(*new_ref, 1); - - let Ok(new_ref) = Ref::filter_map(new_ref, |_| Some(&3)) else { - unreachable!() - }; - - assert_eq!(state, 1 << DATA_SHIFT); - assert_eq!(*new_ref, 3); - - let new_ref = Ref::filter_map(new_ref, |_| Option::<&u8>::None); - - assert_eq!(state, 1 << DATA_SHIFT); - assert!(new_ref.is_err()); - - drop(new_ref); - - assert_eq!(state, 0 << DATA_SHIFT); - } - - #[test] - fn test_lamports_ref() { - let lamports: u64 = 10000; - let state = 1 << LAMPORTS_SHIFT; - - let ref_lamports = Ref { - value: NonNull::from(&lamports), - borrow_shift: LAMPORTS_SHIFT, - state: NonNull::from(&state), - marker: PhantomData, - }; - - let new_ref = Ref::map(ref_lamports, |_| &1000); - - assert_eq!(state, 1 << LAMPORTS_SHIFT); - assert_eq!(*new_ref, 1000); - - let Ok(new_ref) = Ref::filter_map(new_ref, |_| Some(&2000)) else { - unreachable!() - }; - - assert_eq!(state, 1 << LAMPORTS_SHIFT); - assert_eq!(*new_ref, 2000); - - let new_ref = Ref::filter_map(new_ref, |_| Option::<&i32>::None); - - assert_eq!(state, 1 << LAMPORTS_SHIFT); - assert!(new_ref.is_err()); - - drop(new_ref); - - assert_eq!(state, 0 << LAMPORTS_SHIFT); - } - - #[test] - fn test_data_ref_mut() { - let data: [u8; 4] = [0, 1, 2, 3]; - let state = 0b_0000_1000; - - let ref_data = RefMut { - value: NonNull::from(&data), - borrow_mask: DATA_MASK, - state: NonNull::from(&state), - marker: PhantomData, - }; - - let Ok(mut new_ref) = RefMut::filter_map(ref_data, |data| data.get_mut(0)) else { - unreachable!() - }; - - *new_ref = 4; - - assert_eq!(state, 8); - assert_eq!(*new_ref, 4); - - drop(new_ref); - - assert_eq!(data, [4, 1, 2, 3]); - assert_eq!(state, 0); - } - - #[test] - fn test_lamports_ref_mut() { - let lamports: u64 = 10000; - let state = 0b_1000_0000; - - let ref_lamports = RefMut { - value: NonNull::from(&lamports), - borrow_mask: LAMPORTS_MASK, - state: NonNull::from(&state), - marker: PhantomData, - }; - - let new_ref = RefMut::map(ref_lamports, |lamports| { - *lamports = 200; - lamports - }); - - assert_eq!(state, 128); - assert_eq!(*new_ref, 200); - - drop(new_ref); - - assert_eq!(lamports, 200); - assert_eq!(state, 0); - } -} diff --git a/sdk/pinocchio/src/cpi.rs b/sdk/pinocchio/src/cpi.rs index 2ec15132..a63be9bd 100644 --- a/sdk/pinocchio/src/cpi.rs +++ b/sdk/pinocchio/src/cpi.rs @@ -3,11 +3,11 @@ use core::{mem::MaybeUninit, ops::Deref}; use crate::{ - account_info::AccountInfo, instruction::{Account, AccountMeta, Instruction, Signer}, program_error::ProgramError, ProgramResult, }; +use solana_account_view::AccountView; use solana_address::Address; /// Maximum number of accounts that can be passed to a cross-program invocation. @@ -60,19 +60,19 @@ impl<'a> From<&Instruction<'a, '_, '_, '_>> for CInstruction<'a> { #[inline(always)] pub fn invoke( instruction: &Instruction, - account_infos: &[&AccountInfo; ACCOUNTS], + account_infos: &[&AccountView; ACCOUNTS], ) -> ProgramResult { invoke_signed(instruction, account_infos, &[]) } -/// Invoke a cross-program instruction from a slice of `AccountInfo`s. +/// Invoke a cross-program instruction from a slice of `AccountView`s. /// /// # Important /// /// The accounts on the `account_infos` slice must be in the same order as the /// `accounts` field of the `instruction`. #[inline(always)] -pub fn slice_invoke(instruction: &Instruction, account_infos: &[&AccountInfo]) -> ProgramResult { +pub fn slice_invoke(instruction: &Instruction, account_infos: &[&AccountView]) -> ProgramResult { slice_invoke_signed(instruction, account_infos, &[]) } @@ -84,7 +84,7 @@ pub fn slice_invoke(instruction: &Instruction, account_infos: &[&AccountInfo]) - /// `accounts` field of the `instruction`. pub fn invoke_signed( instruction: &Instruction, - account_infos: &[&AccountInfo; ACCOUNTS], + account_infos: &[&AccountView; ACCOUNTS], signers_seeds: &[Signer], ) -> ProgramResult { if instruction.accounts.len() < ACCOUNTS { @@ -125,7 +125,7 @@ pub fn invoke_signed( } /// Invoke a cross-program instruction with signatures from a slice of -/// `AccountInfo`s. +/// `AccountView`s. /// /// # Important /// @@ -133,7 +133,7 @@ pub fn invoke_signed( /// `accounts` field of the `instruction`. pub fn slice_invoke_signed( instruction: &Instruction, - account_infos: &[&AccountInfo], + account_infos: &[&AccountView], signers_seeds: &[Signer], ) -> ProgramResult { if instruction.accounts.len() < account_infos.len() { diff --git a/sdk/pinocchio/src/entrypoint/lazy.rs b/sdk/pinocchio/src/entrypoint/lazy.rs index 78bbe5fd..8ab2eea1 100644 --- a/sdk/pinocchio/src/entrypoint/lazy.rs +++ b/sdk/pinocchio/src/entrypoint/lazy.rs @@ -1,13 +1,11 @@ //! 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, - BPF_ALIGN_OF_U128, NON_DUP_MARKER, -}; +use solana_account_view::{Account, AccountView, MAX_PERMITTED_DATA_INCREASE}; use solana_address::Address; +use crate::{program_error::ProgramError, BPF_ALIGN_OF_U128, NON_DUP_MARKER}; + /// Declare the lazy program entrypoint. /// /// Use the `lazy_program_entrypoint!` macro instead. @@ -124,7 +122,7 @@ impl InstructionContext { /// Reads the next account for the instruction. /// /// The account is represented as a [`MaybeAccount`], since it can either - /// represent and [`AccountInfo`] or the index of a duplicated account. It is up to the + /// represent and [`AccountView`] or the index of a duplicated account. It is up to the /// caller to handle the mapping back to the source account. /// /// # Error @@ -225,23 +223,23 @@ impl InstructionContext { } } -/// Wrapper type around an [`AccountInfo`] that may be a duplicate. +/// Wrapper type around an [`AccountView`] that may be a duplicate. pub enum MaybeAccount { - /// An [`AccountInfo`] that is not a duplicate. - Account(AccountInfo), + /// An [`AccountView`] that is not a duplicate. + Account(AccountView), /// The index of the original account that was duplicated. Duplicated(u8), } impl MaybeAccount { - /// Extracts the wrapped [`AccountInfo`]. + /// Extracts the wrapped [`AccountView`]. /// /// It is up to the caller to guarantee that the [`MaybeAccount`] really is in an /// [`MaybeAccount::Account`]. Calling this method when the variant is a /// [`MaybeAccount::Duplicated`] will result in a panic. #[inline(always)] - pub fn assume_account(self) -> AccountInfo { + pub fn assume_account(self) -> AccountView { let MaybeAccount::Account(account) = self else { panic!("Duplicated account") }; @@ -268,7 +266,7 @@ unsafe fn read_account(input: *mut u8, offset: &mut usize) -> MaybeAccount { *offset += (*offset as *const u8).align_offset(BPF_ALIGN_OF_U128); *offset += core::mem::size_of::(); - MaybeAccount::Account(AccountInfo { raw: account }) + MaybeAccount::Account(account.into()) } else { *offset += core::mem::size_of::(); //the caller will handle the mapping to the original account diff --git a/sdk/pinocchio/src/entrypoint/mod.rs b/sdk/pinocchio/src/entrypoint/mod.rs index e874c7af..644e050e 100644 --- a/sdk/pinocchio/src/entrypoint/mod.rs +++ b/sdk/pinocchio/src/entrypoint/mod.rs @@ -7,12 +7,11 @@ pub use lazy::{InstructionContext, MaybeAccount}; #[cfg(target_os = "solana")] pub use alloc::BumpAllocator; -use crate::{ - account_info::{Account, AccountInfo, MAX_PERMITTED_DATA_INCREASE}, - BPF_ALIGN_OF_U128, NON_DUP_MARKER, -}; +use solana_account_view::{Account, AccountView, MAX_PERMITTED_DATA_INCREASE}; use solana_address::Address; +use crate::{BPF_ALIGN_OF_U128, NON_DUP_MARKER}; + /// Start address of the memory region used for program heap. pub const HEAP_START_ADDRESS: u64 = 0x300000000; @@ -47,7 +46,7 @@ pub const SUCCESS: u64 = super::SUCCESS; /// ```ignore /// fn process_instruction( /// program_id: &Address, // Address of the account the program was loaded into -/// accounts: &[AccountInfo], // All accounts required to process the instruction +/// accounts: &[AccountView], // All accounts required to process the instruction /// instruction_data: &[u8], // Serialized instruction-specific data /// ) -> ProgramResult; /// ``` @@ -69,7 +68,7 @@ pub const SUCCESS: u64 = super::SUCCESS; /// pub mod entrypoint { /// /// use pinocchio::{ -/// account_info::AccountInfo, +/// AccountView, /// entrypoint, /// msg, /// Address::Address, @@ -80,7 +79,7 @@ pub const SUCCESS: u64 = super::SUCCESS; /// /// pub fn process_instruction( /// program_id: &Address, -/// accounts: &[AccountInfo], +/// accounts: &[AccountView], /// instruction_data: &[u8], /// ) -> ProgramResult { /// msg!("Hello from my program!"); @@ -115,8 +114,8 @@ macro_rules! program_entrypoint { /// Program entrypoint. #[no_mangle] pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 { - const UNINIT: core::mem::MaybeUninit<$crate::account_info::AccountInfo> = - core::mem::MaybeUninit::<$crate::account_info::AccountInfo>::uninit(); + const UNINIT: core::mem::MaybeUninit<$crate::account_view::AccountView> = + core::mem::MaybeUninit::<$crate::account_view::AccountView>::uninit(); // Create an array of uninitialized account infos. let mut accounts = [UNINIT; $maximum]; @@ -124,7 +123,7 @@ macro_rules! program_entrypoint { $crate::entrypoint::deserialize::<$maximum>(input, &mut accounts); // Call the program's entrypoint passing `count` account infos; we know that - // they are initialized so we cast the pointer to a slice of `[AccountInfo]`. + // they are initialized so we cast the pointer to a slice of `[AccountView]`. match $process_instruction( &program_id, core::slice::from_raw_parts(accounts.as_ptr() as _, count), @@ -145,7 +144,7 @@ macro_rules! program_entrypoint { #[inline(always)] pub unsafe fn deserialize<'a, const MAX_ACCOUNTS: usize>( input: *mut u8, - accounts: &mut [core::mem::MaybeUninit], + accounts: &mut [core::mem::MaybeUninit], ) -> (&'a Address, usize, &'a [u8]) { let mut offset: usize = 0; @@ -158,26 +157,26 @@ pub unsafe fn deserialize<'a, const MAX_ACCOUNTS: usize>( let processed = core::cmp::min(total_accounts, MAX_ACCOUNTS); for i in 0..processed { - let account_info: *mut Account = input.add(offset) as *mut _; + let account: *mut Account = input.add(offset) as *mut _; - if (*account_info).borrow_state == NON_DUP_MARKER { + if (*account).borrow_state == NON_DUP_MARKER { // repurpose the borrow state to track borrows - (*account_info).borrow_state = 0b_0000_0000; + (*account).borrow_state = 0b_0000_0000; offset += core::mem::size_of::(); - offset += (*account_info).data_len as usize; + offset += (*account).data_len as usize; offset += MAX_PERMITTED_DATA_INCREASE; offset += (offset as *const u8).align_offset(BPF_ALIGN_OF_U128); offset += core::mem::size_of::(); - accounts[i].write(AccountInfo { raw: account_info }); + accounts[i].write(account.into()); } else { offset += core::mem::size_of::(); // duplicated account – clone the original pointer using `borrow_state` since it represents the // index of the duplicated account passed by the runtime. accounts[i].write( accounts - .get_unchecked((*account_info).borrow_state as usize) + .get_unchecked((*account).borrow_state as usize) .assume_init_ref() .clone(), ); diff --git a/sdk/pinocchio/src/instruction.rs b/sdk/pinocchio/src/instruction.rs index 4b4ffaeb..c80e5352 100644 --- a/sdk/pinocchio/src/instruction.rs +++ b/sdk/pinocchio/src/instruction.rs @@ -2,7 +2,7 @@ use core::{marker::PhantomData, ops::Deref}; -use crate::account_info::AccountInfo; +use solana_account_view::AccountView; use solana_address::Address; /// Information about a CPI instruction. @@ -35,7 +35,7 @@ pub struct ProcessedSiblingInstruction { /// An `Account` for CPI invocations. /// -/// This struct contains the same information as an [`AccountInfo`], but has +/// This struct contains the same information as an [`AccountView`], but has /// the memory layout as expected by `sol_invoke_signed_c` syscall. #[repr(C)] #[derive(Clone)] @@ -67,34 +67,32 @@ pub struct Account<'a> { // This account's data contains a loaded program (and is now read-only). executable: bool, - /// The pointers to the `AccountInfo` data are only valid for as long as the - /// `&'a AccountInfo` lives. Instead of holding a reference to the actual `AccountInfo`, + /// The pointers to the `AccountView` data are only valid for as long as the + /// `&'a AccountView` lives. Instead of holding a reference to the actual `AccountView`, /// which would increase the size of the type, we claim to hold a reference without - /// actually holding one using a `PhantomData<&'a AccountInfo>`. - _account_info: PhantomData<&'a AccountInfo>, + /// actually holding one using a `PhantomData<&'a AccountView>`. + _account_info: PhantomData<&'a AccountView>, } -#[inline(always)] -const fn offset(ptr: *const T, offset: usize) -> *const U { - unsafe { (ptr as *const u8).add(offset) as *const U } -} - -impl<'a> From<&'a AccountInfo> for Account<'a> { - fn from(account: &'a AccountInfo) -> Self { +impl<'a> From<&'a AccountView> for Account<'a> { + fn from(account: &'a AccountView) -> Self { Account { - key: offset(account.raw, 8), - lamports: offset(account.raw, 72), + key: account.key(), + lamports: &account.lamports(), data_len: account.data_len() as u64, - data: offset(account.raw, 88), - owner: offset(account.raw, 40), - // The `rent_epoch` field is not present in the `AccountInfo` struct, + // SAFETY: The caller ensures that the `AccountView` data is not mutably + // borrowed, so that the data pointer is valid. + data: unsafe { account.data_ptr() }, + // SAFETY: The caller ensures that the `AccountView` owner is valid. + owner: unsafe { account.owner() }, + // The `rent_epoch` field is not present in the `AccountView` struct, // since the value occurs after the variable data of the account in // the runtime input data. rent_epoch: 0, is_signer: account.is_signer(), is_writable: account.is_writable(), executable: account.executable(), - _account_info: PhantomData::<&'a AccountInfo>, + _account_info: PhantomData::<&'a AccountView>, } } } @@ -159,8 +157,8 @@ impl<'a> AccountMeta<'a> { } } -impl<'a> From<&'a AccountInfo> for AccountMeta<'a> { - fn from(account: &'a crate::account_info::AccountInfo) -> Self { +impl<'a> From<&'a AccountView> for AccountMeta<'a> { + fn from(account: &'a AccountView) -> Self { AccountMeta::new(account.key(), account.is_writable(), account.is_signer()) } } diff --git a/sdk/pinocchio/src/lib.rs b/sdk/pinocchio/src/lib.rs index 8af9c7f3..8381f657 100644 --- a/sdk/pinocchio/src/lib.rs +++ b/sdk/pinocchio/src/lib.rs @@ -30,7 +30,7 @@ //! To use the `entrypoint!` macro, use the following in your entrypoint definition: //! ```ignore //! use pinocchio::{ -//! account_info::AccountInfo, +//! AccountView, //! entrypoint, //! msg, //! ProgramResult, @@ -41,7 +41,7 @@ //! //! pub fn process_instruction( //! program_id: &Address, -//! accounts: &[AccountInfo], +//! accounts: &[AccountView], //! instruction_data: &[u8], //! ) -> ProgramResult { //! msg!("Hello from my program!"); @@ -136,7 +136,7 @@ //! To use the [`no_allocator!`] macro, use the following in your entrypoint definition: //! ```ignore //! use pinocchio::{ -//! account_info::AccountInfo, +//! AccountView, //! default_panic_handler, //! msg, //! no_allocator, @@ -151,7 +151,7 @@ //! //! pub fn process_instruction( //! program_id: &Address, -//! accounts: &[AccountInfo], +//! accounts: &[AccountView], //! instruction_data: &[u8], //! ) -> ProgramResult { //! msg!("Hello from `no_std` program!"); @@ -193,7 +193,7 @@ //! #[cfg(feature = "bpf-entrypoint")] //! mod entrypoint { //! use pinocchio::{ -//! account_info::AccountInfo, +//! AccountView, //! entrypoint, //! msg, //! ProgramResult, @@ -204,7 +204,7 @@ //! //! pub fn process_instruction( //! program_id: &Address, -//! accounts: &[AccountInfo], +//! accounts: &[AccountView], //! instruction_data: &[u8], //! ) -> ProgramResult { //! msg!("Hello from my program!"); @@ -223,7 +223,6 @@ #[cfg(feature = "std")] extern crate std; -pub mod account_info; pub mod cpi; pub mod entrypoint; pub mod instruction; @@ -238,6 +237,8 @@ pub mod sysvars; #[deprecated(since = "0.7.0", note = "Use the `entrypoint` module instead")] pub use entrypoint::lazy as lazy_entrypoint; +// Re-export the `solana_account_view` type for downstream use. +pub use solana_account_view as account_view; // Re-export the `Address` type for downstream use. pub use solana_address::Address; pub use solana_program_error as program_error; @@ -245,7 +246,7 @@ pub use solana_program_error as program_error; /// Maximum number of accounts that a transaction may process. /// /// This value is used to set the maximum number of accounts that a program -/// is expecting and statically initialize the array of `AccountInfo`. +/// is expecting and statically initialize the array of `AccountView`. /// /// This is based on the current [maximum number of accounts] that a transaction /// may lock in a block. diff --git a/sdk/pinocchio/src/log.rs b/sdk/pinocchio/src/log.rs index e0e14375..5121506f 100644 --- a/sdk/pinocchio/src/log.rs +++ b/sdk/pinocchio/src/log.rs @@ -32,7 +32,7 @@ //! //! [`Address`]: solana_address::Address -use crate::account_info::AccountInfo; +use solana_account_view::AccountView; /// Print a message to the log. /// @@ -134,11 +134,11 @@ pub fn sol_log_slice(slice: &[u8]) { /// Print the hexadecimal representation of the program's input parameters. /// -/// - `accounts` - A slice of [`AccountInfo`]. +/// - `accounts` - A slice of [`AccountView`]. /// - `data` - The instruction data. -pub fn sol_log_params(accounts: &[AccountInfo], data: &[u8]) { +pub fn sol_log_params(accounts: &[AccountView], data: &[u8]) { for (i, account) in accounts.iter().enumerate() { - msg!("AccountInfo"); + msg!("AccountView"); sol_log_64(0, 0, 0, 0, i as u64); msg!("- Is signer"); sol_log_64(0, 0, 0, 0, account.is_signer() as u64); diff --git a/sdk/pinocchio/src/sysvars/rent.rs b/sdk/pinocchio/src/sysvars/rent.rs index 3fe349db..f404c71b 100644 --- a/sdk/pinocchio/src/sysvars/rent.rs +++ b/sdk/pinocchio/src/sysvars/rent.rs @@ -3,11 +3,8 @@ //! This is required for the rent sysvar implementation. use super::Sysvar; -use crate::{ - account_info::{AccountInfo, Ref}, - impl_sysvar_get, - program_error::ProgramError, -}; +use crate::{impl_sysvar_get, program_error::ProgramError}; +use solana_account_view::{AccountView, Ref}; use solana_address::Address; /// The ID of the rent sysvar. @@ -72,7 +69,7 @@ impl Rent { /// /// This method performs a check on the account info key. #[inline] - pub fn from_account_info(account_info: &AccountInfo) -> Result, ProgramError> { + pub fn from_account_info(account_info: &AccountView) -> Result, ProgramError> { if account_info.key() != &RENT_ID { return Err(ProgramError::InvalidArgument); } @@ -92,7 +89,7 @@ impl Rent { /// no mutable borrows of the account data. #[inline] pub unsafe fn from_account_info_unchecked( - account_info: &AccountInfo, + account_info: &AccountView, ) -> Result<&Self, ProgramError> { if account_info.key() != &RENT_ID { return Err(ProgramError::InvalidArgument);