Feature - Loader built-in program v3 (#30464)

* Adds loader-v3 in SDK.

* Adds loader-v3 built-in program.

* Adds tests.
This commit is contained in:
Alexander Meißner 2023-03-23 18:13:47 +01:00 committed by GitHub
parent 0291e8c702
commit c10f337f85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1635 additions and 9 deletions

13
Cargo.lock generated
View File

@ -5856,6 +5856,19 @@ dependencies = [
"tokio",
]
[[package]]
name = "solana-loader-v3-program"
version = "1.16.0"
dependencies = [
"bincode",
"log",
"rand 0.7.3",
"solana-measure",
"solana-program-runtime",
"solana-sdk 1.16.0",
"solana_rbpf",
]
[[package]]
name = "solana-local-cluster"
version = "1.16.0"

View File

@ -59,6 +59,7 @@ members = [
"programs/compute-budget",
"programs/config",
"programs/ed25519-tests",
"programs/loader-v3",
"programs/stake",
"programs/vote",
"programs/zk-token-proof",

View File

@ -9,8 +9,8 @@ use {
vm::{BuiltInProgram, VerifiedExecutable},
},
solana_sdk::{
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, clock::Slot, pubkey::Pubkey,
saturating_add_assign,
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, clock::Slot, loader_v3,
pubkey::Pubkey, saturating_add_assign,
},
std::{
collections::HashMap,
@ -61,7 +61,7 @@ pub enum LoadedProgramType {
Invalid,
LegacyV0(VerifiedExecutable<RequisiteVerifier, InvokeContext<'static>>),
LegacyV1(VerifiedExecutable<RequisiteVerifier, InvokeContext<'static>>),
// Typed(TypedProgram<InvokeContext<'static>>),
Typed(VerifiedExecutable<RequisiteVerifier, InvokeContext<'static>>),
BuiltIn(BuiltInProgram<InvokeContext<'static>>),
}
@ -71,6 +71,7 @@ impl Debug for LoadedProgramType {
LoadedProgramType::Invalid => write!(f, "LoadedProgramType::Invalid"),
LoadedProgramType::LegacyV0(_) => write!(f, "LoadedProgramType::LegacyV0"),
LoadedProgramType::LegacyV1(_) => write!(f, "LoadedProgramType::LegacyV1"),
LoadedProgramType::Typed(_) => write!(f, "LoadedProgramType::Typed"),
LoadedProgramType::BuiltIn(_) => write!(f, "LoadedProgramType::BuiltIn"),
}
}
@ -143,6 +144,8 @@ impl LoadedProgram {
LoadedProgramType::LegacyV0(VerifiedExecutable::from_executable(executable)?)
} else if bpf_loader::check_id(loader_key) || bpf_loader_upgradeable::check_id(loader_key) {
LoadedProgramType::LegacyV1(VerifiedExecutable::from_executable(executable)?)
} else if loader_v3::check_id(loader_key) {
LoadedProgramType::Typed(VerifiedExecutable::from_executable(executable)?)
} else {
panic!();
};
@ -156,6 +159,7 @@ impl LoadedProgram {
match &mut program {
LoadedProgramType::LegacyV0(executable) => executable.jit_compile(),
LoadedProgramType::LegacyV1(executable) => executable.jit_compile(),
LoadedProgramType::Typed(executable) => executable.jit_compile(),
_ => Err(EbpfError::JitNotCompiled),
}?;
jit_compile_time.stop();

View File

@ -578,7 +578,7 @@ fn process_instruction_common(
LoadedProgramType::Invalid => Err(InstructionError::InvalidAccountData),
LoadedProgramType::LegacyV0(executable) => execute(executable, invoke_context),
LoadedProgramType::LegacyV1(executable) => execute(executable, invoke_context),
LoadedProgramType::BuiltIn(_) => Err(InstructionError::IncorrectProgramId),
_ => Err(InstructionError::IncorrectProgramId),
}
}

View File

@ -0,0 +1,28 @@
[package]
name = "solana-loader-v3-program"
version = "1.16.0"
description = "Solana Loader v3"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
edition = "2021"
publish = false
[dependencies]
log = { workspace = true }
rand = { workspace = true }
solana-measure = { workspace = true }
solana-program-runtime = { workspace = true }
solana-sdk = { workspace = true }
solana_rbpf = { workspace = true }
[dev-dependencies]
bincode = { workspace = true }
[lib]
crate-type = ["lib"]
name = "solana_loader_v3_program"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -500,6 +500,8 @@ pub mod keccak;
pub mod lamports;
pub mod loader_instruction;
pub mod loader_upgradeable_instruction;
pub mod loader_v3;
pub mod loader_v3_instruction;
pub mod log;
pub mod message;
pub mod native_token;

View File

@ -0,0 +1,31 @@
//! The v3 built-in loader program.
//!
//! This is the loader of the program runtime v2.
use crate::pubkey::Pubkey;
crate::declare_id!("LoaderV311111111111111111111111111111111111");
/// Cooldown before a program can be un-/redeployed again
pub const DEPLOYMENT_COOLDOWN_IN_SLOTS: u64 = 750;
/// LoaderV3 account states
#[repr(C)]
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy, AbiExample)]
pub struct LoaderV3State {
/// Slot that the program was last initialized, deployed or retracted in.
pub slot: u64,
/// True if the program is ready to be executed, false if it is retracted for maintainance.
pub is_deployed: bool,
/// Authority address, `None` means it is finalized.
pub authority_address: Option<Pubkey>,
// The raw program data follows this serialized structure in the
// account's data.
}
impl LoaderV3State {
/// Size of a serialized program account.
pub const fn program_data_offset() -> usize {
std::mem::size_of::<Self>()
}
}

View File

@ -0,0 +1,74 @@
//! Instructions for the SBF loader.
#[repr(u8)]
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum LoaderV3Instruction {
/// Write ELF data into an undeployed program account.
///
/// Writing at the end (offset is length) increases the size of the program account and
/// providing additional lamports (via the payer account) is necessary to reach rent exemption.
/// The first write (at offset zero when the account is empty) automatically
/// initializes the program account and sets the authority needed for subsequent writes.
/// Thus, the first write should be in the same transaction as the account creation.
///
/// # Account references
/// 0. `[writable]` The program account to write to.
/// 1. `[signer]` The authority of the program.
/// 2. `[signer]` Optional, the payer account.
Write {
/// Offset at which to write the given bytes.
offset: u32,
/// Serialized program data
#[serde(with = "serde_bytes")]
bytes: Vec<u8>,
},
/// Decrease the size of an undeployed program account.
///
/// Decreasing to size zero closes the program account and resets it into an uninitialized state.
/// Superflous lamports are transfered to the recipient account.
///
/// # Account references
/// 0. `[writable]` The program account to change the size of.
/// 1. `[signer]` The authority of the program.
/// 2. `[writable]` The recipient account.
Truncate {
/// Offset at which to cut off the rest. This will be the size after the operation.
offset: u32,
},
/// Verify the data of a program account to be a valid ELF.
///
/// If this succeeds the program becomes executable, and is ready to use.
/// A source program account can be provided to overwrite the data before deployment
/// in one step, instead retracting the program and writing to it and redeploying it.
/// The source program is truncated to zero (thus closed) and lamports necessary for
/// rent exemption are transferred, in case that the source was bigger than the program.
///
/// # Account references
/// 0. `[writable]` The program account to deploy.
/// 1. `[signer]` The authority of the program.
/// 2. `[writable]` Optional, an undeployed source program account to take data and lamports from.
Deploy,
/// Undo the deployment of a program account.
///
/// The program is no longer executable and goes into maintainance.
/// Necessary for writing data and truncating.
///
/// # Account references
/// 0. `[writable]` The program account to retract.
/// 1. `[signer]` The authority of the program.
Retract,
/// Transfers the authority over a program account.
///
/// WARNING: Using this instruction without providing a new authority
/// finalizes the program (it becomes immutable).
///
/// # Account references
/// 0. `[writable]` The program account to change the authority of.
/// 1. `[signer]` The current authority of the program.
/// 2. `[signer]` The new authority of the program. Optional if program is currently deployed.
TransferAuthority,
}

View File

@ -47,11 +47,12 @@ pub use solana_program::{
bpf_loader_deprecated, bpf_loader_upgradeable, clock, config, custom_heap_default,
custom_panic_default, debug_account_data, declare_deprecated_sysvar_id, declare_sysvar_id,
decode_error, ed25519_program, epoch_schedule, fee_calculator, impl_sysvar_get, incinerator,
instruction, keccak, lamports, loader_instruction, loader_upgradeable_instruction, message,
msg, native_token, nonce, program, program_error, program_memory, program_option, program_pack,
rent, sanitize, sdk_ids, secp256k1_program, secp256k1_recover, serde_varint, serialize_utils,
short_vec, slot_hashes, slot_history, stable_layout, stake, stake_history, syscalls,
system_instruction, system_program, sysvar, unchecked_div_by_const, vote, wasm_bindgen,
instruction, keccak, lamports, loader_instruction, loader_upgradeable_instruction, loader_v3,
loader_v3_instruction, message, msg, native_token, nonce, program, program_error,
program_memory, program_option, program_pack, rent, sanitize, sdk_ids, secp256k1_program,
secp256k1_recover, serde_varint, serialize_utils, short_vec, slot_hashes, slot_history,
stable_layout, stake, stake_history, syscalls, system_instruction, system_program, sysvar,
unchecked_div_by_const, vote, wasm_bindgen,
};
pub mod account;