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:
parent
0291e8c702
commit
c10f337f85
|
@ -5856,6 +5856,19 @@ dependencies = [
|
||||||
"tokio",
|
"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]]
|
[[package]]
|
||||||
name = "solana-local-cluster"
|
name = "solana-local-cluster"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
|
|
|
@ -59,6 +59,7 @@ members = [
|
||||||
"programs/compute-budget",
|
"programs/compute-budget",
|
||||||
"programs/config",
|
"programs/config",
|
||||||
"programs/ed25519-tests",
|
"programs/ed25519-tests",
|
||||||
|
"programs/loader-v3",
|
||||||
"programs/stake",
|
"programs/stake",
|
||||||
"programs/vote",
|
"programs/vote",
|
||||||
"programs/zk-token-proof",
|
"programs/zk-token-proof",
|
||||||
|
|
|
@ -9,8 +9,8 @@ use {
|
||||||
vm::{BuiltInProgram, VerifiedExecutable},
|
vm::{BuiltInProgram, VerifiedExecutable},
|
||||||
},
|
},
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, clock::Slot, pubkey::Pubkey,
|
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, clock::Slot, loader_v3,
|
||||||
saturating_add_assign,
|
pubkey::Pubkey, saturating_add_assign,
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
@ -61,7 +61,7 @@ pub enum LoadedProgramType {
|
||||||
Invalid,
|
Invalid,
|
||||||
LegacyV0(VerifiedExecutable<RequisiteVerifier, InvokeContext<'static>>),
|
LegacyV0(VerifiedExecutable<RequisiteVerifier, InvokeContext<'static>>),
|
||||||
LegacyV1(VerifiedExecutable<RequisiteVerifier, InvokeContext<'static>>),
|
LegacyV1(VerifiedExecutable<RequisiteVerifier, InvokeContext<'static>>),
|
||||||
// Typed(TypedProgram<InvokeContext<'static>>),
|
Typed(VerifiedExecutable<RequisiteVerifier, InvokeContext<'static>>),
|
||||||
BuiltIn(BuiltInProgram<InvokeContext<'static>>),
|
BuiltIn(BuiltInProgram<InvokeContext<'static>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@ impl Debug for LoadedProgramType {
|
||||||
LoadedProgramType::Invalid => write!(f, "LoadedProgramType::Invalid"),
|
LoadedProgramType::Invalid => write!(f, "LoadedProgramType::Invalid"),
|
||||||
LoadedProgramType::LegacyV0(_) => write!(f, "LoadedProgramType::LegacyV0"),
|
LoadedProgramType::LegacyV0(_) => write!(f, "LoadedProgramType::LegacyV0"),
|
||||||
LoadedProgramType::LegacyV1(_) => write!(f, "LoadedProgramType::LegacyV1"),
|
LoadedProgramType::LegacyV1(_) => write!(f, "LoadedProgramType::LegacyV1"),
|
||||||
|
LoadedProgramType::Typed(_) => write!(f, "LoadedProgramType::Typed"),
|
||||||
LoadedProgramType::BuiltIn(_) => write!(f, "LoadedProgramType::BuiltIn"),
|
LoadedProgramType::BuiltIn(_) => write!(f, "LoadedProgramType::BuiltIn"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,6 +144,8 @@ impl LoadedProgram {
|
||||||
LoadedProgramType::LegacyV0(VerifiedExecutable::from_executable(executable)?)
|
LoadedProgramType::LegacyV0(VerifiedExecutable::from_executable(executable)?)
|
||||||
} else if bpf_loader::check_id(loader_key) || bpf_loader_upgradeable::check_id(loader_key) {
|
} else if bpf_loader::check_id(loader_key) || bpf_loader_upgradeable::check_id(loader_key) {
|
||||||
LoadedProgramType::LegacyV1(VerifiedExecutable::from_executable(executable)?)
|
LoadedProgramType::LegacyV1(VerifiedExecutable::from_executable(executable)?)
|
||||||
|
} else if loader_v3::check_id(loader_key) {
|
||||||
|
LoadedProgramType::Typed(VerifiedExecutable::from_executable(executable)?)
|
||||||
} else {
|
} else {
|
||||||
panic!();
|
panic!();
|
||||||
};
|
};
|
||||||
|
@ -156,6 +159,7 @@ impl LoadedProgram {
|
||||||
match &mut program {
|
match &mut program {
|
||||||
LoadedProgramType::LegacyV0(executable) => executable.jit_compile(),
|
LoadedProgramType::LegacyV0(executable) => executable.jit_compile(),
|
||||||
LoadedProgramType::LegacyV1(executable) => executable.jit_compile(),
|
LoadedProgramType::LegacyV1(executable) => executable.jit_compile(),
|
||||||
|
LoadedProgramType::Typed(executable) => executable.jit_compile(),
|
||||||
_ => Err(EbpfError::JitNotCompiled),
|
_ => Err(EbpfError::JitNotCompiled),
|
||||||
}?;
|
}?;
|
||||||
jit_compile_time.stop();
|
jit_compile_time.stop();
|
||||||
|
|
|
@ -578,7 +578,7 @@ fn process_instruction_common(
|
||||||
LoadedProgramType::Invalid => Err(InstructionError::InvalidAccountData),
|
LoadedProgramType::Invalid => Err(InstructionError::InvalidAccountData),
|
||||||
LoadedProgramType::LegacyV0(executable) => execute(executable, invoke_context),
|
LoadedProgramType::LegacyV0(executable) => execute(executable, invoke_context),
|
||||||
LoadedProgramType::LegacyV1(executable) => execute(executable, invoke_context),
|
LoadedProgramType::LegacyV1(executable) => execute(executable, invoke_context),
|
||||||
LoadedProgramType::BuiltIn(_) => Err(InstructionError::IncorrectProgramId),
|
_ => Err(InstructionError::IncorrectProgramId),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
@ -500,6 +500,8 @@ pub mod keccak;
|
||||||
pub mod lamports;
|
pub mod lamports;
|
||||||
pub mod loader_instruction;
|
pub mod loader_instruction;
|
||||||
pub mod loader_upgradeable_instruction;
|
pub mod loader_upgradeable_instruction;
|
||||||
|
pub mod loader_v3;
|
||||||
|
pub mod loader_v3_instruction;
|
||||||
pub mod log;
|
pub mod log;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
pub mod native_token;
|
pub mod native_token;
|
||||||
|
|
|
@ -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>()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,
|
||||||
|
}
|
|
@ -47,11 +47,12 @@ pub use solana_program::{
|
||||||
bpf_loader_deprecated, bpf_loader_upgradeable, clock, config, custom_heap_default,
|
bpf_loader_deprecated, bpf_loader_upgradeable, clock, config, custom_heap_default,
|
||||||
custom_panic_default, debug_account_data, declare_deprecated_sysvar_id, declare_sysvar_id,
|
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,
|
decode_error, ed25519_program, epoch_schedule, fee_calculator, impl_sysvar_get, incinerator,
|
||||||
instruction, keccak, lamports, loader_instruction, loader_upgradeable_instruction, message,
|
instruction, keccak, lamports, loader_instruction, loader_upgradeable_instruction, loader_v3,
|
||||||
msg, native_token, nonce, program, program_error, program_memory, program_option, program_pack,
|
loader_v3_instruction, message, msg, native_token, nonce, program, program_error,
|
||||||
rent, sanitize, sdk_ids, secp256k1_program, secp256k1_recover, serde_varint, serialize_utils,
|
program_memory, program_option, program_pack, rent, sanitize, sdk_ids, secp256k1_program,
|
||||||
short_vec, slot_hashes, slot_history, stable_layout, stake, stake_history, syscalls,
|
secp256k1_recover, serde_varint, serialize_utils, short_vec, slot_hashes, slot_history,
|
||||||
system_instruction, system_program, sysvar, unchecked_div_by_const, vote, wasm_bindgen,
|
stable_layout, stake, stake_history, syscalls, system_instruction, system_program, sysvar,
|
||||||
|
unchecked_div_by_const, vote, wasm_bindgen,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod account;
|
pub mod account;
|
||||||
|
|
Loading…
Reference in New Issue