-
Notifications
You must be signed in to change notification settings - Fork 12
program: introduce core BPF implementation #7
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
Merged
buffalojoec
merged 14 commits into
main
from
03-05-program_introduce_core_BPF_implementation
Mar 13, 2024
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
d5430e5
program: introduce core BPF implementation
buffalojoec 3b3516b
rename instruction enum
buffalojoec 052393b
avoid dereferencing mutable account slices
buffalojoec c00dbcb
add more error logging
buffalojoec a501737
variablize lookup table seeds
buffalojoec 25a598c
update clock slot evaluation
buffalojoec 3632158
document and test new state serializers
buffalojoec 206e1d9
remove proc macro hygiene
buffalojoec f36dc6c
drop no-entrypoint
buffalojoec 8376c00
drop items moved in SDK and runtime
buffalojoec 0cfc9f7
rename program crate
buffalojoec 728cb60
change `deserialize_addresses_from_index_mut` parameter `index` to `u8`
buffalojoec f74c883
add position buffer to `calculate_slot_position`
buffalojoec f7164f3
remove off-by-one in status
buffalojoec File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| [workspace] | ||
| resolver = "2" | ||
| members = ["clients/rust"] | ||
| members = ["clients/rust", "program"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| [package] | ||
| name = "scbpf-address-lookup-table" | ||
| version = "0.1.0" | ||
| edition = "2021" | ||
| readme = "./README.md" | ||
| license-file = "../LICENSE" | ||
| publish = false | ||
|
|
||
| [package.metadata.solana] | ||
| program-id = "AddressLookupTab1e1111111111111111111111111" | ||
|
|
||
| [features] | ||
| bpf-entrypoint = [] | ||
| test-sbf = [] | ||
|
|
||
| [dependencies] | ||
| bincode = "1.3.3" | ||
| bytemuck = "1.14.1" | ||
| log = "0.4.20" | ||
|
buffalojoec marked this conversation as resolved.
|
||
| serde = { version = "1.0.193", features = ["derive"] } | ||
| solana-frozen-abi = "1.18.2" | ||
| solana-frozen-abi-macro = "1.18.2" | ||
| solana-program = "1.18.2" | ||
| spl-program-error = "0.3.1" | ||
|
|
||
| [dev-dependencies] | ||
| solana-sdk = "1.18.2" | ||
| test-case = "3.3.1" | ||
|
|
||
| [lib] | ||
| crate-type = ["cdylib", "lib"] | ||
|
|
||
| [build-dependencies] | ||
| rustc_version = "0.4" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| //! Required for `solana-frozen-abi-macro` to work. | ||
| extern crate rustc_version; | ||
| use rustc_version::{version_meta, Channel}; | ||
|
|
||
| fn main() { | ||
| // Copied and adapted from | ||
| // https://github.com/Kimundi/rustc-version-rs/blob/1d692a965f4e48a8cb72e82cda953107c0d22f47/README.md#example | ||
| // Licensed under Apache-2.0 + MIT | ||
| match version_meta().unwrap().channel { | ||
| Channel::Stable => { | ||
| println!("cargo:rustc-cfg=RUSTC_WITHOUT_SPECIALIZATION"); | ||
| } | ||
| Channel::Beta => { | ||
| println!("cargo:rustc-cfg=RUSTC_WITHOUT_SPECIALIZATION"); | ||
| } | ||
| Channel::Nightly => { | ||
| println!("cargo:rustc-cfg=RUSTC_WITH_SPECIALIZATION"); | ||
| } | ||
| Channel::Dev => { | ||
| println!("cargo:rustc-cfg=RUSTC_WITH_SPECIALIZATION"); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| //! Program entrypoint | ||
|
|
||
| use { | ||
| crate::{error::AddressLookupError, processor}, | ||
| solana_program::{ | ||
| account_info::AccountInfo, entrypoint::ProgramResult, program_error::PrintProgramError, | ||
| pubkey::Pubkey, | ||
| }, | ||
| }; | ||
|
|
||
| solana_program::entrypoint!(process_instruction); | ||
| fn process_instruction( | ||
| program_id: &Pubkey, | ||
| accounts: &[AccountInfo], | ||
| instruction_data: &[u8], | ||
| ) -> ProgramResult { | ||
| if let Err(error) = processor::process(program_id, accounts, instruction_data) { | ||
| error.print::<AddressLookupError>(); | ||
| return Err(error); | ||
| } | ||
| Ok(()) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| //! Program error types | ||
|
|
||
| use spl_program_error::*; | ||
|
|
||
| #[spl_program_error] | ||
| pub enum AddressLookupError { | ||
| /// Attempted to lookup addresses from a table that does not exist | ||
| #[error("Attempted to lookup addresses from a table that does not exist")] | ||
| LookupTableAccountNotFound, | ||
| /// Attempted to lookup addresses from an account owned by the wrong program | ||
| #[error("Attempted to lookup addresses from an account owned by the wrong program")] | ||
| InvalidAccountOwner, | ||
| /// Attempted to lookup addresses from an invalid account | ||
| #[error("Attempted to lookup addresses from an invalid account")] | ||
| InvalidAccountData, | ||
| /// Address lookup contains an invalid index | ||
| #[error("Address lookup contains an invalid index")] | ||
| InvalidLookupIndex, | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,193 @@ | ||
| //! Program instruction types | ||
|
|
||
| use { | ||
| serde::{Deserialize, Serialize}, | ||
| solana_program::{ | ||
| clock::Slot, | ||
| instruction::{AccountMeta, Instruction}, | ||
| pubkey::Pubkey, | ||
| system_program, | ||
| }, | ||
| }; | ||
|
|
||
| #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] | ||
| pub enum AddressLookupTableInstruction { | ||
| /// Create an address lookup table | ||
| /// | ||
| /// # Account references | ||
| /// 0. `[WRITE]` Uninitialized address lookup table account | ||
| /// 1. `[SIGNER]` Account used to derive and control the new address | ||
| /// lookup table. | ||
| /// 2. `[SIGNER, WRITE]` Account that will fund the new address lookup | ||
| /// table. | ||
| /// 3. `[]` System program for CPI. | ||
| CreateLookupTable { | ||
| /// A recent slot must be used in the derivation path | ||
| /// for each initialized table. When closing table accounts, | ||
| /// the initialization slot must no longer be "recent" to prevent | ||
| /// address tables from being recreated with reordered or | ||
| /// otherwise malicious addresses. | ||
| recent_slot: Slot, | ||
| /// Address tables are always initialized at program-derived | ||
| /// addresses using the funding address, recent blockhash, and | ||
| /// the user-passed `bump_seed`. | ||
| bump_seed: u8, | ||
| }, | ||
|
|
||
| /// Permanently freeze an address lookup table, making it immutable. | ||
| /// | ||
| /// # Account references | ||
| /// 0. `[WRITE]` Address lookup table account to freeze | ||
| /// 1. `[SIGNER]` Current authority | ||
| FreezeLookupTable, | ||
|
|
||
| /// Extend an address lookup table with new addresses. Funding account and | ||
| /// system program account references are only required if the lookup table | ||
| /// account requires additional lamports to cover the rent-exempt balance | ||
| /// after being extended. | ||
| /// | ||
| /// # Account references | ||
| /// 0. `[WRITE]` Address lookup table account to extend | ||
| /// 1. `[SIGNER]` Current authority | ||
| /// 2. `[SIGNER, WRITE, OPTIONAL]` Account that will fund the table | ||
| /// reallocation | ||
| /// 3. `[OPTIONAL]` System program for CPI. | ||
| ExtendLookupTable { new_addresses: Vec<Pubkey> }, | ||
|
|
||
| /// Deactivate an address lookup table, making it unusable and | ||
| /// eligible for closure after a short period of time. | ||
| /// | ||
| /// # Account references | ||
| /// 0. `[WRITE]` Address lookup table account to deactivate | ||
| /// 1. `[SIGNER]` Current authority | ||
| DeactivateLookupTable, | ||
|
|
||
| /// Close an address lookup table account | ||
| /// | ||
| /// # Account references | ||
| /// 0. `[WRITE]` Address lookup table account to close | ||
| /// 1. `[SIGNER]` Current authority | ||
| /// 2. `[WRITE]` Recipient of closed account lamports | ||
| CloseLookupTable, | ||
| } | ||
|
|
||
| /// Derives the address of an address table account from a wallet address and a | ||
| /// recent block's slot. | ||
| pub fn derive_lookup_table_address( | ||
| authority_address: &Pubkey, | ||
| recent_block_slot: Slot, | ||
| ) -> (Pubkey, u8) { | ||
| Pubkey::find_program_address( | ||
| &[authority_address.as_ref(), &recent_block_slot.to_le_bytes()], | ||
| &crate::id(), | ||
| ) | ||
| } | ||
|
|
||
| // [Core BPF]: `create_lookup_table_signed` has been removed, since feature | ||
| // "FKAcEvNgSY79RpqsPNUV5gDyumopH4cEHqUxyfm8b8Ap" | ||
| // (relax_authority_signer_check_for_lookup_table_creation) has been activated | ||
| // on all clusters. | ||
|
buffalojoec marked this conversation as resolved.
|
||
|
|
||
| /// Constructs an instruction to create a table account and returns | ||
| /// the instruction and the table account's derived address. | ||
| pub fn create_lookup_table( | ||
| authority_address: Pubkey, | ||
| payer_address: Pubkey, | ||
| recent_slot: Slot, | ||
| ) -> (Instruction, Pubkey) { | ||
| let (lookup_table_address, bump_seed) = | ||
| derive_lookup_table_address(&authority_address, recent_slot); | ||
|
|
||
| let instruction = Instruction::new_with_bincode( | ||
| crate::id(), | ||
| &AddressLookupTableInstruction::CreateLookupTable { | ||
| recent_slot, | ||
| bump_seed, | ||
| }, | ||
| vec![ | ||
| AccountMeta::new(lookup_table_address, false), | ||
| AccountMeta::new_readonly(authority_address, false), | ||
| AccountMeta::new(payer_address, true), | ||
| AccountMeta::new_readonly(system_program::id(), false), | ||
| ], | ||
| ); | ||
|
|
||
| (instruction, lookup_table_address) | ||
| } | ||
|
|
||
| /// Constructs an instruction that freezes an address lookup | ||
| /// table so that it can never be closed or extended again. Empty | ||
| /// lookup tables cannot be frozen. | ||
| pub fn freeze_lookup_table(lookup_table_address: Pubkey, authority_address: Pubkey) -> Instruction { | ||
| Instruction::new_with_bincode( | ||
| crate::id(), | ||
| &AddressLookupTableInstruction::FreezeLookupTable, | ||
| vec![ | ||
| AccountMeta::new(lookup_table_address, false), | ||
| AccountMeta::new_readonly(authority_address, true), | ||
| ], | ||
| ) | ||
| } | ||
|
|
||
| /// Constructs an instruction which extends an address lookup | ||
| /// table account with new addresses. | ||
| pub fn extend_lookup_table( | ||
| lookup_table_address: Pubkey, | ||
| authority_address: Pubkey, | ||
| payer_address: Option<Pubkey>, | ||
| new_addresses: Vec<Pubkey>, | ||
| ) -> Instruction { | ||
| let mut accounts = vec![ | ||
| AccountMeta::new(lookup_table_address, false), | ||
| AccountMeta::new_readonly(authority_address, true), | ||
| ]; | ||
|
|
||
| if let Some(payer_address) = payer_address { | ||
| accounts.extend([ | ||
| AccountMeta::new(payer_address, true), | ||
| AccountMeta::new_readonly(system_program::id(), false), | ||
| ]); | ||
| } | ||
|
|
||
| Instruction::new_with_bincode( | ||
| crate::id(), | ||
| &AddressLookupTableInstruction::ExtendLookupTable { new_addresses }, | ||
| accounts, | ||
| ) | ||
| } | ||
|
|
||
| /// Constructs an instruction that deactivates an address lookup | ||
| /// table so that it cannot be extended again and will be unusable | ||
| /// and eligible for closure after a short amount of time. | ||
| pub fn deactivate_lookup_table( | ||
| lookup_table_address: Pubkey, | ||
| authority_address: Pubkey, | ||
| ) -> Instruction { | ||
| Instruction::new_with_bincode( | ||
| crate::id(), | ||
| &AddressLookupTableInstruction::DeactivateLookupTable, | ||
| vec![ | ||
| AccountMeta::new(lookup_table_address, false), | ||
| AccountMeta::new_readonly(authority_address, true), | ||
| ], | ||
| ) | ||
| } | ||
|
|
||
| /// Returns an instruction that closes an address lookup table | ||
| /// account. The account will be deallocated and the lamports | ||
| /// will be drained to the recipient address. | ||
| pub fn close_lookup_table( | ||
| lookup_table_address: Pubkey, | ||
| authority_address: Pubkey, | ||
| recipient_address: Pubkey, | ||
| ) -> Instruction { | ||
| Instruction::new_with_bincode( | ||
| crate::id(), | ||
| &AddressLookupTableInstruction::CloseLookupTable, | ||
| vec![ | ||
| AccountMeta::new(lookup_table_address, false), | ||
| AccountMeta::new_readonly(authority_address, true), | ||
| AccountMeta::new(recipient_address, false), | ||
| ], | ||
| ) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| //! Address Lookup Table Program | ||
| // [Core BPF]: Required for `solana-frozen-abi-macro` to work. | ||
| #![allow(incomplete_features)] | ||
| #![cfg_attr(RUSTC_WITH_SPECIALIZATION, feature(specialization))] | ||
|
|
||
| #[cfg(all(target_os = "solana", feature = "bpf-entrypoint"))] | ||
| mod entrypoint; | ||
| pub mod error; | ||
| pub mod instruction; | ||
| pub mod processor; | ||
| pub mod state; | ||
|
|
||
| // [Core BPF]: TODO: Program-test will not overwrite existing built-ins. | ||
| // See https://github.com/solana-labs/solana/pull/35233 | ||
| // solana_program::declare_id!("AddressLookupTab1e1111111111111111111111111"); | ||
| solana_program::declare_id!("AaoNx79M6YE3DcXfrRN4nmBcQvQPqdpowi6uEESuJdnm"); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.