-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
program: introduce core BPF implementation
- Loading branch information
1 parent
ad4436b
commit 227a8a0
Showing
10 changed files
with
1,623 additions
and
238 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains 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 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,35 @@ | ||
[package] | ||
name = "address-lookup-table" | ||
version = "0.1.0" | ||
edition = "2021" | ||
readme = "./README.md" | ||
license-file = "../LICENSE" | ||
publish = false | ||
|
||
[package.metadata.solana] | ||
program-id = "AddressLookupTab1e1111111111111111111111111" | ||
|
||
[features] | ||
no-entrypoint = [] | ||
test-sbf = [] | ||
|
||
[dependencies] | ||
bincode = "1.3.3" | ||
bytemuck = "1.14.1" | ||
log = "0.4.20" | ||
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] | ||
assert_matches = "1.5.0" | ||
solana-program-test = "1.18.2" | ||
solana-sdk = "1.18.2" | ||
|
||
[lib] | ||
crate-type = ["cdylib", "lib"] | ||
|
||
[build-dependencies] | ||
rustc_version = "0.4" |
This file contains 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,28 @@ | ||
//! 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"); | ||
// See https://github.com/solana-labs/solana/issues/11055 | ||
// We may be running the custom `rust-bpf-builder` toolchain, | ||
// which currently needs `#![feature(proc_macro_hygiene)]` to | ||
// be applied. | ||
println!("cargo:rustc-cfg=RUSTC_NEEDS_PROC_MACRO_HYGIENE"); | ||
} | ||
} | ||
} |
This file contains 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 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,33 @@ | ||
//! Program error types | ||
#[cfg(not(target_os = "solana"))] | ||
use solana_program::message::AddressLoaderError; | ||
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, | ||
} | ||
|
||
#[cfg(not(target_os = "solana"))] | ||
impl From<AddressLookupError> for AddressLoaderError { | ||
fn from(err: AddressLookupError) -> Self { | ||
match err { | ||
AddressLookupError::LookupTableAccountNotFound => Self::LookupTableAccountNotFound, | ||
AddressLookupError::InvalidAccountOwner => Self::InvalidAccountOwner, | ||
AddressLookupError::InvalidAccountData => Self::InvalidAccountData, | ||
AddressLookupError::InvalidLookupIndex => Self::InvalidLookupIndex, | ||
} | ||
} | ||
} |
This file contains 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 ProgramInstruction { | ||
/// 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. | ||
|
||
/// 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(), | ||
&ProgramInstruction::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(), | ||
&ProgramInstruction::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(), | ||
&ProgramInstruction::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(), | ||
&ProgramInstruction::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(), | ||
&ProgramInstruction::CloseLookupTable, | ||
vec![ | ||
AccountMeta::new(lookup_table_address, false), | ||
AccountMeta::new_readonly(authority_address, true), | ||
AccountMeta::new(recipient_address, false), | ||
], | ||
) | ||
} |
This file contains 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,25 @@ | ||
//! 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(not(feature = "no-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"); | ||
|
||
/// The definition of address lookup table accounts. | ||
/// | ||
/// As used by the `crate::message::v0` message format. | ||
#[derive(Debug, PartialEq, Eq, Clone)] | ||
pub struct AddressLookupTableAccount { | ||
pub key: solana_program::pubkey::Pubkey, | ||
pub addresses: Vec<solana_program::pubkey::Pubkey>, | ||
} |
Oops, something went wrong.