Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lang: Type safe bumps #2542

Merged
merged 20 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ The minor version will be incremented upon a breaking change and the patch versi

### Breaking

- lang: Switch to type safe bumps in context ([#2542](https://github.com/coral-xyz/anchor/pull/2542)).

## [0.28.0] - 2023-06-09

### Features
Expand Down
178 changes: 89 additions & 89 deletions bench/COMPUTE_UNITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,95 +16,95 @@ The programs and their tests are located in [/tests/bench](https://github.com/co

Solana version: 1.16.0

| Instruction | Compute Units | +/- |
| --------------------------- | ------------- | --- |
| accountInfo1 | 1015 | - |
| accountInfo2 | 1475 | - |
| accountInfo4 | 1964 | - |
| accountInfo8 | 3841 | - |
| accountEmptyInit1 | 5817 | - |
| accountEmpty1 | 1149 | - |
| accountEmptyInit2 | 10402 | - |
| accountEmpty2 | 1754 | - |
| accountEmptyInit4 | 19508 | - |
| accountEmpty4 | 2540 | - |
| accountEmptyInit8 | 37265 | - |
| accountEmpty8 | 5016 | - |
| accountSizedInit1 | 5924 | - |
| accountSized1 | 1214 | - |
| accountSizedInit2 | 10680 | - |
| accountSized2 | 1873 | - |
| accountSizedInit4 | 19970 | - |
| accountSized4 | 2762 | - |
| accountSizedInit8 | 38122 | - |
| accountSized8 | 5353 | - |
| accountUnsizedInit1 | 6052 | - |
| accountUnsized1 | 1338 | - |
| accountUnsizedInit2 | 10929 | - |
| accountUnsized2 | 1778 | - |
| accountUnsizedInit4 | 20339 | - |
| accountUnsized4 | 3136 | - |
| accountUnsizedInit8 | 39096 | - |
| accountUnsized8 | 5952 | - |
| boxedAccountEmptyInit1 | 6034 | - |
| boxedAccountEmpty1 | 888 | - |
| boxedAccountEmptyInit2 | 10633 | - |
| boxedAccountEmpty2 | 1401 | - |
| boxedAccountEmptyInit4 | 19311 | - |
| boxedAccountEmpty4 | 2424 | - |
| boxedAccountEmptyInit8 | 37136 | - |
| boxedAccountEmpty8 | 4659 | - |
| boxedAccountSizedInit1 | 6130 | - |
| boxedAccountSized1 | 917 | - |
| boxedAccountSizedInit2 | 10828 | - |
| boxedAccountSized2 | 1463 | - |
| boxedAccountSizedInit4 | 19703 | - |
| boxedAccountSized4 | 2543 | - |
| boxedAccountSizedInit8 | 37919 | - |
| boxedAccountSized8 | 4898 | - |
| boxedAccountUnsizedInit1 | 6240 | - |
| boxedAccountUnsized1 | 972 | - |
| boxedAccountUnsizedInit2 | 11048 | - |
| boxedAccountUnsized2 | 1570 | - |
| boxedAccountUnsizedInit4 | 20138 | - |
| boxedAccountUnsized4 | 2768 | - |
| boxedAccountUnsizedInit8 | 38791 | - |
| boxedAccountUnsized8 | 5347 | - |
| boxedInterfaceAccountMint1 | 2296 | - |
| boxedInterfaceAccountMint2 | 4129 | - |
| boxedInterfaceAccountMint4 | 7783 | - |
| boxedInterfaceAccountMint8 | 15281 | - |
| boxedInterfaceAccountToken1 | 2023 | - |
| boxedInterfaceAccountToken2 | 3582 | - |
| boxedInterfaceAccountToken4 | 6692 | - |
| boxedInterfaceAccountToken8 | 13098 | - |
| interfaceAccountMint1 | 2364 | - |
| interfaceAccountMint2 | 5030 | - |
| interfaceAccountMint4 | 9803 | - |
| interfaceAccountMint8 | 18400 | - |
| interfaceAccountToken1 | 2091 | - |
| interfaceAccountToken2 | 3948 | - |
| interfaceAccountToken4 | 7547 | - |
| interface1 | 1059 | - |
| interface2 | 1479 | - |
| interface4 | 1900 | - |
| interface8 | 3646 | - |
| program1 | 1053 | - |
| program2 | 1467 | - |
| program4 | 1878 | - |
| program8 | 3598 | - |
| signer1 | 1018 | - |
| signer2 | 1484 | - |
| signer4 | 1984 | - |
| signer8 | 3880 | - |
| systemAccount1 | 1072 | - |
| systemAccount2 | 1590 | - |
| systemAccount4 | 2195 | - |
| systemAccount8 | 4305 | - |
| uncheckedAccount1 | 1014 | - |
| uncheckedAccount2 | 1475 | - |
| uncheckedAccount4 | 1965 | - |
| uncheckedAccount8 | 3841 | - |
| Instruction | Compute Units | +/- |
| --------------------------- | ------------- | -------------- |
| accountInfo1 | 810 | 🟢 **-20.20%** |
Aursen marked this conversation as resolved.
Show resolved Hide resolved
| accountInfo2 | 1400 | 🟢 **-5.08%** |
| accountInfo4 | 1855 | 🟢 **-5.55%** |
| accountInfo8 | 3674 | 🟢 **-4.35%** |
| accountEmptyInit1 | 5817 | - |
| accountEmpty1 | 980 | 🟢 **-14.71%** |
| accountEmptyInit2 | 10402 | - |
| accountEmpty2 | 1754 | - |
| accountEmptyInit4 | 19508 | - |
| accountEmpty4 | 2540 | - |
| accountEmptyInit8 | 37265 | - |
| accountEmpty8 | 5016 | - |
| accountSizedInit1 | 5924 | - |
| accountSized1 | 1027 | 🟢 **-15.40%** |
| accountSizedInit2 | 10680 | - |
| accountSized2 | 1873 | - |
| accountSizedInit4 | 19970 | - |
| accountSized4 | 2762 | - |
| accountSizedInit8 | 38122 | - |
| accountSized8 | 5353 | - |
| accountUnsizedInit1 | 6052 | - |
| accountUnsized1 | 1116 | 🟢 **-16.59%** |
| accountUnsizedInit2 | 10929 | - |
| accountUnsized2 | 1778 | - |
| accountUnsizedInit4 | 20339 | - |
| accountUnsized4 | 3136 | - |
| accountUnsizedInit8 | 39096 | - |
| accountUnsized8 | 5952 | - |
| boxedAccountEmptyInit1 | 6034 | - |
| boxedAccountEmpty1 | 866 | 🟢 **-2.48%** |
| boxedAccountEmptyInit2 | 10633 | - |
| boxedAccountEmpty2 | 1386 | 🟢 **-1.07%** |
| boxedAccountEmptyInit4 | 19311 | - |
| boxedAccountEmpty4 | 2424 | - |
| boxedAccountEmptyInit8 | 37136 | - |
| boxedAccountEmpty8 | 4659 | - |
| boxedAccountSizedInit1 | 6130 | - |
| boxedAccountSized1 | 895 | 🟢 **-2.40%** |
| boxedAccountSizedInit2 | 10828 | - |
| boxedAccountSized2 | 1448 | 🟢 **-1.03%** |
| boxedAccountSizedInit4 | 19703 | - |
| boxedAccountSized4 | 2543 | - |
| boxedAccountSizedInit8 | 37919 | - |
| boxedAccountSized8 | 4898 | - |
| boxedAccountUnsizedInit1 | 6240 | - |
| boxedAccountUnsized1 | 953 | 🟢 **-1.95%** |
| boxedAccountUnsizedInit2 | 11048 | - |
| boxedAccountUnsized2 | 1570 | - |
| boxedAccountUnsizedInit4 | 20138 | - |
| boxedAccountUnsized4 | 2768 | - |
| boxedAccountUnsizedInit8 | 38791 | - |
| boxedAccountUnsized8 | 5347 | - |
| boxedInterfaceAccountMint1 | 2296 | - |
| boxedInterfaceAccountMint2 | 4129 | - |
| boxedInterfaceAccountMint4 | 7783 | - |
| boxedInterfaceAccountMint8 | 15281 | - |
| boxedInterfaceAccountToken1 | 2001 | 🟢 **-1.09%** |
| boxedInterfaceAccountToken2 | 3582 | - |
| boxedInterfaceAccountToken4 | 6692 | - |
| boxedInterfaceAccountToken8 | 13098 | - |
| interfaceAccountMint1 | 2291 | 🟢 **-3.09%** |
| interfaceAccountMint2 | 5030 | - |
| interfaceAccountMint4 | 9803 | - |
| interfaceAccountMint8 | 18400 | - |
| interfaceAccountToken1 | 2018 | 🟢 **-3.49%** |
| interfaceAccountToken2 | 3948 | - |
| interfaceAccountToken4 | 7547 | - |
| interface1 | 892 | 🟢 **-15.77%** |
| interface2 | 1479 | - |
| interface4 | 1900 | - |
| interface8 | 3646 | - |
| program1 | 887 | 🟢 **-15.76%** |
| program2 | 1467 | - |
| program4 | 1878 | - |
| program8 | 3598 | - |
| signer1 | 822 | 🟢 **-19.25%** |
| signer2 | 1424 | 🟢 **-4.04%** |
| signer4 | 1907 | 🟢 **-3.88%** |
| signer8 | 3770 | 🟢 **-2.84%** |
| systemAccount1 | 876 | 🟢 **-18.28%** |
| systemAccount2 | 1530 | 🟢 **-3.77%** |
| systemAccount4 | 2118 | 🟢 **-3.51%** |
| systemAccount8 | 4195 | 🟢 **-2.56%** |
| uncheckedAccount1 | 809 | 🟢 **-20.22%** |
| uncheckedAccount2 | 1400 | 🟢 **-5.08%** |
| uncheckedAccount4 | 1856 | 🟢 **-5.55%** |
| uncheckedAccount8 | 3674 | 🟢 **-4.35%** |

### Notable changes

Expand Down
4 changes: 2 additions & 2 deletions docs/src/pages/docs/pdas.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ pub mod game {
panic!();
}
user_stats.name = name;
user_stats.bump = *ctx.bumps.get("user_stats").unwrap();
user_stats.bump = ctx.bumps.user_stats;
Ok(())
}
}
Expand Down Expand Up @@ -158,7 +158,7 @@ pub struct CreateUserStats<'info> {

In the account validation struct we use `seeds` together with `init` to create a PDA with the desired seeds.
Additionally, we add an empty `bump` constraint to signal to anchor that it should find the canonical bump itself.
Then, in the handler, we call `ctx.bumps.get("user_stats")` to get the bump anchor found and save it to the user stats
Then, in the handler, we call `ctx.bumps.user_stats` to get the bump anchor found and save it to the user stats
account as an extra property.

If we then want to use the created pda in a different instruction, we can add a new validation struct (This will check that the `user_stats` account is the pda created by running `hash(seeds, user_stats.bump, game_program_id)`):
Expand Down
4 changes: 1 addition & 3 deletions examples/tutorial/basic-4/programs/basic-4/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub mod basic_4 {

pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
let counter = ctx.accounts.counter.deref_mut();
let bump = *ctx.bumps.get("counter").ok_or(ErrorCode::CannotGetBump)?;
let bump = ctx.bumps.counter;

*counter = Counter {
authority: *ctx.accounts.authority.key,
Expand Down Expand Up @@ -73,6 +73,4 @@ impl Counter {
pub enum ErrorCode {
#[msg("You are not authorized to perform this action.")]
Unauthorized,
#[msg("Cannot get the bump.")]
CannotGetBump,
}
3 changes: 1 addition & 2 deletions lang/attribute/event/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,12 @@ pub fn emit_cpi(input: proc_macro::TokenStream) -> proc_macro::TokenStream {

let authority = EventAuthority::get();
let authority_name = authority.name_token_stream();
let authority_name_str = authority.name;
let authority_seeds = authority.seeds;

proc_macro::TokenStream::from(quote! {
{
let authority_info = ctx.accounts.#authority_name.to_account_info();
let authority_bump = *ctx.bumps.get(#authority_name_str).unwrap();
let authority_bump = ctx.bumps.#authority_name;

let disc = anchor_lang::event::EVENT_IX_TAG_LE;
let inner_data = anchor_lang::Event::data(&#event_struct);
Expand Down
6 changes: 3 additions & 3 deletions lang/src/accounts/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use solana_program::account_info::AccountInfo;
use solana_program::instruction::AccountMeta;
use solana_program::pubkey::Pubkey;
use solana_program::system_program;
use std::collections::{BTreeMap, BTreeSet};
use std::collections::BTreeSet;
use std::fmt;
use std::ops::{Deref, DerefMut};

Expand Down Expand Up @@ -334,7 +334,7 @@ impl<'a, T: AccountSerialize + AccountDeserialize + Owner + Clone> Account<'a, T
}
}

impl<'info, T: AccountSerialize + AccountDeserialize + Owner + Clone> Accounts<'info>
impl<'info, B, T: AccountSerialize + AccountDeserialize + Owner + Clone> Accounts<'info, B>
for Account<'info, T>
where
T: AccountSerialize + AccountDeserialize + Owner + Clone,
Expand All @@ -344,7 +344,7 @@ where
_program_id: &Pubkey,
accounts: &mut &[AccountInfo<'info>],
_ix_data: &[u8],
_bumps: &mut BTreeMap<String, u8>,
_bumps: &mut B,
_reallocs: &mut BTreeSet<Pubkey>,
) -> Result<Self> {
if accounts.is_empty() {
Expand Down
6 changes: 3 additions & 3 deletions lang/src/accounts/account_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use crate::{Accounts, AccountsExit, Key, Result, ToAccountInfos, ToAccountMetas}
use solana_program::account_info::AccountInfo;
use solana_program::instruction::AccountMeta;
use solana_program::pubkey::Pubkey;
use std::collections::{BTreeMap, BTreeSet};
use std::collections::BTreeSet;

impl<'info> Accounts<'info> for AccountInfo<'info> {
impl<'info, B> Accounts<'info, B> for AccountInfo<'info> {
fn try_accounts(
_program_id: &Pubkey,
accounts: &mut &[AccountInfo<'info>],
_ix_data: &[u8],
_bumps: &mut BTreeMap<String, u8>,
_bumps: &mut B,
_reallocs: &mut BTreeSet<Pubkey>,
) -> Result<Self> {
if accounts.is_empty() {
Expand Down
6 changes: 3 additions & 3 deletions lang/src/accounts/account_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use solana_program::account_info::AccountInfo;
use solana_program::instruction::AccountMeta;
use solana_program::pubkey::Pubkey;
use std::cell::{Ref, RefMut};
use std::collections::{BTreeMap, BTreeSet};
use std::collections::BTreeSet;
use std::fmt;
use std::io::Write;
use std::marker::PhantomData;
Expand Down Expand Up @@ -214,13 +214,13 @@ impl<'info, T: ZeroCopy + Owner> AccountLoader<'info, T> {
}
}

impl<'info, T: ZeroCopy + Owner> Accounts<'info> for AccountLoader<'info, T> {
impl<'info, B, T: ZeroCopy + Owner> Accounts<'info, B> for AccountLoader<'info, T> {
#[inline(never)]
fn try_accounts(
_program_id: &Pubkey,
accounts: &mut &[AccountInfo<'info>],
_ix_data: &[u8],
_bumps: &mut BTreeMap<String, u8>,
_bumps: &mut B,
_reallocs: &mut BTreeSet<Pubkey>,
) -> Result<Self> {
if accounts.is_empty() {
Expand Down
6 changes: 3 additions & 3 deletions lang/src/accounts/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ use crate::{Accounts, AccountsClose, AccountsExit, Result, ToAccountInfos, ToAcc
use solana_program::account_info::AccountInfo;
use solana_program::instruction::AccountMeta;
use solana_program::pubkey::Pubkey;
use std::collections::{BTreeMap, BTreeSet};
use std::collections::BTreeSet;
use std::ops::Deref;

impl<'info, T: Accounts<'info>> Accounts<'info> for Box<T> {
impl<'info, B, T: Accounts<'info, B>> Accounts<'info, B> for Box<T> {
fn try_accounts(
program_id: &Pubkey,
accounts: &mut &[AccountInfo<'info>],
ix_data: &[u8],
bumps: &mut BTreeMap<String, u8>,
bumps: &mut B,
reallocs: &mut BTreeSet<Pubkey>,
) -> Result<Self> {
T::try_accounts(program_id, accounts, ix_data, bumps, reallocs).map(Box::new)
Expand Down
6 changes: 3 additions & 3 deletions lang/src/accounts/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
use solana_program::account_info::AccountInfo;
use solana_program::instruction::AccountMeta;
use solana_program::pubkey::Pubkey;
use std::collections::{BTreeMap, BTreeSet};
use std::collections::BTreeSet;
use std::ops::Deref;

/// Type validating that the account is one of a set of given Programs
Expand Down Expand Up @@ -105,13 +105,13 @@ impl<'info, T> AsRef<AccountInfo<'info>> for Interface<'info, T> {
}
}

impl<'info, T: CheckId> Accounts<'info> for Interface<'info, T> {
impl<'info, B, T: CheckId> Accounts<'info, B> for Interface<'info, T> {
#[inline(never)]
fn try_accounts(
_program_id: &Pubkey,
accounts: &mut &[AccountInfo<'info>],
_ix_data: &[u8],
_bumps: &mut BTreeMap<String, u8>,
_bumps: &mut B,
_reallocs: &mut BTreeSet<Pubkey>,
) -> Result<Self> {
if accounts.is_empty() {
Expand Down
6 changes: 3 additions & 3 deletions lang/src/accounts/interface_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use solana_program::account_info::AccountInfo;
use solana_program::instruction::AccountMeta;
use solana_program::pubkey::Pubkey;
use solana_program::system_program;
use std::collections::{BTreeMap, BTreeSet};
use std::collections::BTreeSet;
use std::fmt;
use std::ops::{Deref, DerefMut};

Expand Down Expand Up @@ -241,15 +241,15 @@ impl<'a, T: AccountSerialize + AccountDeserialize + CheckOwner + Clone> Interfac
}
}

impl<'info, T: AccountSerialize + AccountDeserialize + CheckOwner + Clone> Accounts<'info>
impl<'info, B, T: AccountSerialize + AccountDeserialize + CheckOwner + Clone> Accounts<'info, B>
for InterfaceAccount<'info, T>
{
#[inline(never)]
fn try_accounts(
_program_id: &Pubkey,
accounts: &mut &[AccountInfo<'info>],
_ix_data: &[u8],
_bumps: &mut BTreeMap<String, u8>,
_bumps: &mut B,
_reallocs: &mut BTreeSet<Pubkey>,
) -> Result<Self> {
if accounts.is_empty() {
Expand Down
Loading