Эх сурвалжийг харах

BPF Loader: Hoist syscalls into their own crate (#5559)

* agave-syscalls: init new crate

* agave-syscalls: move all syscall modules to new crate

* update all dependencies

* refactor tests to remove circular dep
Joe C 3 сар өмнө
parent
commit
92687e91ed

+ 54 - 19
Cargo.lock

@@ -202,6 +202,7 @@ version = "3.0.0"
 dependencies = [
  "agave-feature-set",
  "agave-reserved-account-keys",
+ "agave-syscalls",
  "assert_cmd",
  "bs58",
  "chrono",
@@ -339,6 +340,55 @@ dependencies = [
  "solana-version",
 ]
 
+[[package]]
+name = "agave-syscalls"
+version = "3.0.0"
+dependencies = [
+ "assert_matches",
+ "bincode",
+ "libsecp256k1",
+ "num-traits",
+ "solana-account",
+ "solana-account-info",
+ "solana-big-mod-exp",
+ "solana-blake3-hasher",
+ "solana-bn254",
+ "solana-clock",
+ "solana-cpi",
+ "solana-curve25519 3.0.0",
+ "solana-epoch-rewards",
+ "solana-epoch-schedule",
+ "solana-fee-calculator",
+ "solana-hash",
+ "solana-instruction",
+ "solana-keccak-hasher",
+ "solana-last-restart-slot",
+ "solana-loader-v3-interface",
+ "solana-log-collector",
+ "solana-measure",
+ "solana-poseidon",
+ "solana-program",
+ "solana-program-entrypoint",
+ "solana-program-runtime",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sbpf",
+ "solana-sdk-ids",
+ "solana-secp256k1-recover",
+ "solana-sha256-hasher",
+ "solana-slot-hashes",
+ "solana-stable-layout",
+ "solana-svm-callback",
+ "solana-svm-feature-set",
+ "solana-sysvar",
+ "solana-sysvar-id",
+ "solana-timings",
+ "solana-transaction-context",
+ "solana-type-overrides",
+ "test-case",
+ "thiserror 2.0.12",
+]
+
 [[package]]
 name = "agave-thread-manager"
 version = "3.0.0"
@@ -7208,36 +7258,26 @@ dependencies = [
 name = "solana-bpf-loader-program"
 version = "3.0.0"
 dependencies = [
+ "agave-syscalls",
  "assert_matches",
  "bincode",
  "criterion",
- "libsecp256k1",
- "num-traits",
  "qualifier_attr",
  "rand 0.8.5",
  "solana-account",
- "solana-account-info",
- "solana-big-mod-exp",
  "solana-bincode",
- "solana-blake3-hasher",
- "solana-bn254",
  "solana-bpf-loader-program",
  "solana-clock",
- "solana-cpi",
- "solana-curve25519 3.0.0",
  "solana-epoch-rewards",
  "solana-epoch-schedule",
  "solana-fee-calculator",
- "solana-hash",
  "solana-instruction",
- "solana-keccak-hasher",
  "solana-last-restart-slot",
  "solana-loader-v3-interface",
  "solana-loader-v4-interface",
  "solana-log-collector",
  "solana-measure",
  "solana-packet",
- "solana-poseidon",
  "solana-program",
  "solana-program-entrypoint",
  "solana-program-runtime",
@@ -7245,21 +7285,14 @@ dependencies = [
  "solana-rent",
  "solana-sbpf",
  "solana-sdk-ids",
- "solana-secp256k1-recover",
- "solana-sha256-hasher",
  "solana-slot-hashes",
- "solana-stable-layout",
  "solana-svm-callback",
  "solana-svm-feature-set",
  "solana-system-interface",
- "solana-sysvar",
- "solana-sysvar-id",
- "solana-timings",
  "solana-transaction-context",
  "solana-type-overrides",
  "static_assertions",
  "test-case",
- "thiserror 2.0.12",
 ]
 
 [[package]]
@@ -7442,6 +7475,7 @@ name = "solana-cli"
 version = "3.0.0"
 dependencies = [
  "agave-feature-set",
+ "agave-syscalls",
  "assert_matches",
  "bincode",
  "bs58",
@@ -7465,7 +7499,6 @@ dependencies = [
  "solana-account-decoder",
  "solana-address-lookup-table-interface",
  "solana-borsh",
- "solana-bpf-loader-program",
  "solana-clap-utils",
  "solana-cli-config",
  "solana-cli-output",
@@ -10131,6 +10164,7 @@ dependencies = [
  "agave-feature-set",
  "agave-precompiles",
  "agave-reserved-account-keys",
+ "agave-syscalls",
  "agave-transaction-view",
  "ahash 0.8.11",
  "aquamarine",
@@ -10815,6 +10849,7 @@ version = "3.0.0"
 dependencies = [
  "agave-feature-set",
  "agave-reserved-account-keys",
+ "agave-syscalls",
  "ahash 0.8.11",
  "assert_matches",
  "bincode",

+ 3 - 1
Cargo.toml

@@ -71,7 +71,6 @@ members = [
     "program-test",
     "programs/bpf-loader-tests",
     "programs/bpf_loader",
-    "programs/bpf_loader/gen-syscall-list",
     "programs/compute-budget",
     "programs/compute-budget-bench",
     "programs/ed25519-tests",
@@ -109,6 +108,8 @@ members = [
     "svm-feature-set",
     "svm-rent-collector",
     "svm-transaction",
+    "syscalls",
+    "syscalls/gen-syscall-list",
     "test-validator",
     "thin-client",
     "thread-manager",
@@ -182,6 +183,7 @@ agave-geyser-plugin-interface = { path = "geyser-plugin-interface", version = "=
 agave-io-uring = { path = "io-uring", version = "=3.0.0" }
 agave-precompiles = { path = "precompiles", version = "=3.0.0" }
 agave-reserved-account-keys = { path = "reserved-account-keys", version = "=3.0.0" }
+agave-syscalls = { path = "syscalls", version = "=3.0.0" }
 agave-thread-manager = { path = "thread-manager", version = "=3.0.0" }
 agave-transaction-view = { path = "transaction-view", version = "=3.0.0" }
 agave-verified-packet-receiver = { path = "verified-packet-receiver", version = "=3.0.0" }

+ 1 - 1
cargo-build-sbf

@@ -11,6 +11,6 @@ done
 
 set -ex
 if [[ ! -f "$here"/platform-tools-sdk/sbf/syscalls.txt ]]; then
-  cargo build --manifest-path "$here"/programs/bpf_loader/gen-syscall-list/Cargo.toml
+  cargo build --manifest-path "$here"/syscalls/gen-syscall-list/Cargo.toml
 fi
 exec cargo run --manifest-path "$here"/platform-tools-sdk/cargo-build-sbf/Cargo.toml -- $maybe_sbf_sdk "$@"

+ 1 - 1
cli/Cargo.toml

@@ -18,6 +18,7 @@ path = "src/main.rs"
 
 [dependencies]
 agave-feature-set = { workspace = true }
+agave-syscalls = { workspace = true }
 bincode = { workspace = true }
 bs58 = { workspace = true }
 clap = { workspace = true }
@@ -40,7 +41,6 @@ solana-account = "=2.2.1"
 solana-account-decoder = { workspace = true }
 solana-address-lookup-table-interface = { workspace = true }
 solana-borsh = "=2.2.1"
-solana-bpf-loader-program = { workspace = true }
 solana-clap-utils = { workspace = true }
 solana-cli-config = { workspace = true }
 solana-cli-output = { workspace = true }

+ 1 - 1
cli/src/program.rs

@@ -12,12 +12,12 @@ use {
         feature::{status_from_account, CliFeatureStatus},
     },
     agave_feature_set::{FeatureSet, FEATURE_NAMES},
+    agave_syscalls::create_program_runtime_environment_v1,
     bip39::{Language, Mnemonic, MnemonicType, Seed},
     clap::{App, AppSettings, Arg, ArgMatches, SubCommand},
     log::*,
     solana_account::{state_traits::StateMut, Account},
     solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig},
-    solana_bpf_loader_program::syscalls::create_program_runtime_environment_v1,
     solana_clap_utils::{
         self,
         compute_budget::{compute_unit_price_arg, ComputeUnitLimit},

+ 7 - 8
cli/src/program_v4.rs

@@ -715,14 +715,13 @@ pub fn process_deploy_program(
                 }
             });
     }
-    let program_runtime_environment =
-        solana_bpf_loader_program::syscalls::create_program_runtime_environment_v1(
-            &feature_set.runtime_features(),
-            &SVMTransactionExecutionBudget::default(),
-            true,
-            false,
-        )
-        .unwrap();
+    let program_runtime_environment = agave_syscalls::create_program_runtime_environment_v1(
+        &feature_set.runtime_features(),
+        &SVMTransactionExecutionBudget::default(),
+        true,
+        false,
+    )
+    .unwrap();
 
     // Verify the program
     let upload_range =

+ 1 - 0
ledger-tool/Cargo.toml

@@ -18,6 +18,7 @@ dev-context-only-utils = []
 [dependencies]
 agave-feature-set = { workspace = true }
 agave-reserved-account-keys = { workspace = true }
+agave-syscalls = { workspace = true }
 bs58 = { workspace = true }
 chrono = { workspace = true, features = ["default"] }
 clap = { workspace = true }

+ 2 - 3
ledger-tool/src/program.rs

@@ -1,5 +1,6 @@
 use {
     crate::{args::*, canonicalize_ledger_path, ledger_utils::*},
+    agave_syscalls::create_program_runtime_environment_v1,
     clap::{App, AppSettings, Arg, ArgMatches, SubCommand},
     log::*,
     serde_derive::{Deserialize, Serialize},
@@ -7,9 +8,7 @@ use {
     solana_account::{
         create_account_shared_data_for_test, state_traits::StateMut, AccountSharedData,
     },
-    solana_bpf_loader_program::{
-        create_vm, load_program_from_bytes, syscalls::create_program_runtime_environment_v1,
-    },
+    solana_bpf_loader_program::{create_vm, load_program_from_bytes},
     solana_cli_output::{OutputFormat, QuietDisplay, VerboseDisplay},
     solana_clock::Slot,
     solana_ledger::blockstore_options::AccessType,

+ 1 - 18
programs/bpf_loader/Cargo.toml

@@ -27,44 +27,27 @@ shuttle-test = [
 svm-internal = []
 
 [dependencies]
+agave-syscalls = { workspace = true }
 bincode = { workspace = true }
-libsecp256k1 = { workspace = true }
-num-traits = { workspace = true }
 qualifier_attr = { workspace = true }
 solana-account = { workspace = true }
-solana-account-info = { workspace = true }
-solana-big-mod-exp = { workspace = true }
 solana-bincode = { workspace = true }
-solana-blake3-hasher = { workspace = true }
-solana-bn254 = { workspace = true }
 solana-clock = { workspace = true }
-solana-cpi = { workspace = true }
-solana-curve25519 = { workspace = true }
-solana-hash = { workspace = true }
 solana-instruction = { workspace = true }
-solana-keccak-hasher = { workspace = true }
 solana-loader-v3-interface = { workspace = true, features = ["serde"] }
 solana-loader-v4-interface = { workspace = true, features = ["bincode"] }
 solana-log-collector = { workspace = true }
 solana-measure = { workspace = true }
 solana-packet = { workspace = true }
-solana-poseidon = { workspace = true }
 solana-program-entrypoint = { workspace = true }
 solana-program-runtime = { workspace = true }
 solana-pubkey = { workspace = true }
 solana-sbpf = { workspace = true }
 solana-sdk-ids = { workspace = true }
-solana-secp256k1-recover = { workspace = true }
-solana-sha256-hasher = { workspace = true }
-solana-stable-layout = { workspace = true }
 solana-svm-feature-set = { workspace = true }
 solana-system-interface = { workspace = true }
-solana-sysvar = { workspace = true }
-solana-sysvar-id = { workspace = true }
-solana-timings = { workspace = true }
 solana-transaction-context = { workspace = true, features = ["bincode"] }
 solana-type-overrides = { workspace = true }
-thiserror = { workspace = true }
 
 [dev-dependencies]
 assert_matches = { workspace = true }

+ 24 - 31
programs/bpf_loader/src/lib.rs

@@ -1,8 +1,6 @@
 #![deny(clippy::arithmetic_side_effects)]
 #![deny(clippy::indexing_slicing)]
 
-pub mod syscalls;
-
 #[cfg(feature = "svm-internal")]
 use qualifier_attr::qualifiers;
 use {
@@ -30,7 +28,7 @@ use {
     solana_sbpf::{
         declare_builtin_function,
         ebpf::{self, MM_HEAP_START},
-        elf::Executable,
+        elf::{ElfError, Executable},
         error::{EbpfError, ProgramResult},
         memory_region::{AccessType, MemoryMapping, MemoryRegion},
         program::BuiltinProgram,
@@ -44,7 +42,6 @@ use {
     solana_transaction_context::{IndexOfAccount, InstructionContext, TransactionContext},
     solana_type_overrides::sync::{atomic::Ordering, Arc},
     std::{cell::RefCell, mem, rc::Rc},
-    syscalls::morph_into_deployment_environment_v1,
 };
 
 #[cfg_attr(feature = "svm-internal", qualifiers(pub))]
@@ -58,6 +55,28 @@ thread_local! {
     pub static MEMORY_POOL: RefCell<VmMemoryPool> = RefCell::new(VmMemoryPool::new());
 }
 
+fn morph_into_deployment_environment_v1(
+    from: Arc<BuiltinProgram<InvokeContext>>,
+) -> Result<BuiltinProgram<InvokeContext>, ElfError> {
+    let mut config = from.get_config().clone();
+    config.reject_broken_elfs = true;
+    // Once the tests are being build using a toolchain which supports the newer SBPF versions,
+    // the deployment of older versions will be disabled:
+    // config.enabled_sbpf_versions =
+    //     *config.enabled_sbpf_versions.end()..=*config.enabled_sbpf_versions.end();
+
+    let mut result = BuiltinProgram::new_loader(config);
+
+    for (_key, (name, value)) in from.get_function_registry().iter() {
+        // Deployment of programs with sol_alloc_free is disabled. So do not register the syscall.
+        if name != *b"sol_alloc_free_" {
+            result.register_function(unsafe { std::str::from_utf8_unchecked(name) }, value)?;
+        }
+    }
+
+    Ok(result)
+}
+
 #[allow(clippy::too_many_arguments)]
 pub fn load_program_from_bytes(
     log_collector: Option<Rc<RefCell<LogCollector>>>,
@@ -297,32 +316,6 @@ macro_rules! create_vm {
     };
 }
 
-#[macro_export]
-macro_rules! mock_create_vm {
-    ($vm:ident, $additional_regions:expr, $accounts_metadata:expr, $invoke_context:expr $(,)?) => {
-        let loader = solana_type_overrides::sync::Arc::new(BuiltinProgram::new_mock());
-        let function_registry = solana_sbpf::program::FunctionRegistry::default();
-        let executable = solana_sbpf::elf::Executable::<InvokeContext>::from_text_bytes(
-            &[0x07, 0x0A, 0, 0, 0, 0, 0, 0, 0x9D, 0, 0, 0, 0, 0, 0, 0],
-            loader,
-            SBPFVersion::V3,
-            function_registry,
-        )
-        .unwrap();
-        executable
-            .verify::<solana_sbpf::verifier::RequisiteVerifier>()
-            .unwrap();
-        $crate::create_vm!(
-            $vm,
-            &executable,
-            $additional_regions,
-            $accounts_metadata,
-            $invoke_context,
-        );
-        let $vm = $vm.map(|(vm, _, _)| vm);
-    };
-}
-
 fn create_memory_mapping<'a, 'b, C: ContextObject>(
     executable: &'a Executable<C>,
     stack: &'b mut [u8],
@@ -1796,7 +1789,7 @@ fn execute<'a, 'b: 'a>(
 mod test_utils {
     #[cfg(feature = "svm-internal")]
     use {
-        super::*, crate::syscalls::create_program_runtime_environment_v1,
+        super::*, agave_syscalls::create_program_runtime_environment_v1,
         solana_account::ReadableAccount, solana_loader_v4_interface::state::LoaderV4State,
         solana_program_runtime::loaded_programs::DELAY_VISIBILITY_SLOT_OFFSET,
         solana_sdk_ids::loader_v4,

+ 43 - 18
programs/sbf/Cargo.lock

@@ -136,6 +136,46 @@ dependencies = [
  "solana-sdk-ids",
 ]
 
+[[package]]
+name = "agave-syscalls"
+version = "3.0.0"
+dependencies = [
+ "bincode",
+ "libsecp256k1 0.6.0",
+ "num-traits",
+ "solana-account",
+ "solana-account-info",
+ "solana-big-mod-exp",
+ "solana-blake3-hasher",
+ "solana-bn254",
+ "solana-clock",
+ "solana-cpi",
+ "solana-curve25519 3.0.0",
+ "solana-hash",
+ "solana-instruction",
+ "solana-keccak-hasher",
+ "solana-loader-v3-interface 5.0.0",
+ "solana-log-collector",
+ "solana-measure",
+ "solana-poseidon",
+ "solana-program-entrypoint",
+ "solana-program-runtime",
+ "solana-pubkey",
+ "solana-sbpf",
+ "solana-sdk-ids",
+ "solana-secp256k1-recover",
+ "solana-sha256-hasher",
+ "solana-stable-layout",
+ "solana-svm-callback",
+ "solana-svm-feature-set",
+ "solana-sysvar",
+ "solana-sysvar-id",
+ "solana-timings",
+ "solana-transaction-context",
+ "solana-type-overrides",
+ "thiserror 2.0.12",
+]
+
 [[package]]
 name = "agave-transaction-view"
 version = "3.0.0"
@@ -5687,44 +5727,27 @@ dependencies = [
 name = "solana-bpf-loader-program"
 version = "3.0.0"
 dependencies = [
+ "agave-syscalls",
  "bincode",
- "libsecp256k1 0.6.0",
- "num-traits",
  "qualifier_attr",
  "solana-account",
- "solana-account-info",
- "solana-big-mod-exp",
  "solana-bincode",
- "solana-blake3-hasher",
- "solana-bn254",
  "solana-clock",
- "solana-cpi",
- "solana-curve25519 3.0.0",
- "solana-hash",
  "solana-instruction",
- "solana-keccak-hasher",
  "solana-loader-v3-interface 5.0.0",
  "solana-loader-v4-interface",
  "solana-log-collector",
  "solana-measure",
  "solana-packet",
- "solana-poseidon",
  "solana-program-entrypoint",
  "solana-program-runtime",
  "solana-pubkey",
  "solana-sbpf",
  "solana-sdk-ids",
- "solana-secp256k1-recover",
- "solana-sha256-hasher",
- "solana-stable-layout",
  "solana-svm-feature-set",
  "solana-system-interface",
- "solana-sysvar",
- "solana-sysvar-id",
- "solana-timings",
  "solana-transaction-context",
  "solana-type-overrides",
- "thiserror 2.0.12",
 ]
 
 [[package]]
@@ -7793,6 +7816,7 @@ dependencies = [
  "agave-feature-set",
  "agave-precompiles",
  "agave-reserved-account-keys",
+ "agave-syscalls",
  "ahash 0.8.11",
  "aquamarine",
  "arrayref",
@@ -7950,6 +7974,7 @@ version = "3.0.0"
 dependencies = [
  "agave-feature-set",
  "agave-reserved-account-keys",
+ "agave-syscalls",
  "agave-validator",
  "bincode",
  "borsh 1.5.7",

+ 2 - 0
programs/sbf/Cargo.toml

@@ -92,6 +92,7 @@ check-cfg = [
 [workspace.dependencies]
 agave-feature-set = { path = "../../feature-set", version = "=3.0.0" }
 agave-reserved-account-keys = { path = "../../reserved-account-keys", version = "=3.0.0" }
+agave-syscalls = { path = "../../syscalls", version = "=3.0.0" }
 agave-validator = { path = "../../validator", version = "=3.0.0" }
 array-bytes = "=1.4.1"
 bincode = { version = "1.1.4", default-features = false }
@@ -182,6 +183,7 @@ frozen-abi = []
 [dev-dependencies]
 agave-feature-set = { workspace = true }
 agave-reserved-account-keys = { workspace = true }
+agave-syscalls = { workspace = true }
 agave-validator = { workspace = true }
 bincode = { workspace = true }
 borsh = { workspace = true }

+ 2 - 1
programs/sbf/benches/bpf_loader.rs

@@ -12,9 +12,10 @@ use {solana_keypair::Keypair, std::slice};
 extern crate test;
 
 use {
+    agave_syscalls::create_program_runtime_environment_v1,
     byteorder::{ByteOrder, LittleEndian, WriteBytesExt},
     solana_account::AccountSharedData,
-    solana_bpf_loader_program::{create_vm, syscalls::create_program_runtime_environment_v1},
+    solana_bpf_loader_program::create_vm,
     solana_client_traits::SyncClient,
     solana_instruction::{AccountMeta, Instruction},
     solana_measure::measure::Measure,

+ 1 - 0
runtime/Cargo.toml

@@ -50,6 +50,7 @@ frozen-abi = [
 agave-feature-set = { workspace = true }
 agave-precompiles = { workspace = true }
 agave-reserved-account-keys = { workspace = true }
+agave-syscalls = { workspace = true }
 ahash = { workspace = true }
 aquamarine = { workspace = true }
 arrayref = { workspace = true }

+ 3 - 3
runtime/src/bank.rs

@@ -60,6 +60,9 @@ use {
     agave_feature_set::{self as feature_set, FeatureSet},
     agave_precompiles::{get_precompile, get_precompiles, is_precompile},
     agave_reserved_account_keys::ReservedAccountKeys,
+    agave_syscalls::{
+        create_program_runtime_environment_v1, create_program_runtime_environment_v2,
+    },
     ahash::{AHashSet, RandomState},
     dashmap::DashMap,
     log::*,
@@ -81,9 +84,6 @@ use {
         blockhash_queue::BlockhashQueue,
         storable_accounts::StorableAccounts,
     },
-    solana_bpf_loader_program::syscalls::{
-        create_program_runtime_environment_v1, create_program_runtime_environment_v2,
-    },
     solana_builtins::{prototype::BuiltinPrototype, BUILTINS, STATELESS_BUILTINS},
     solana_clock::{
         BankId, Epoch, Slot, SlotIndex, UnixTimestamp, INITIAL_RENT_EPOCH, MAX_PROCESSING_AGE,

+ 1 - 0
svm/Cargo.toml

@@ -83,6 +83,7 @@ thiserror = { workspace = true }
 [dev-dependencies]
 agave-feature-set = { workspace = true }
 agave-reserved-account-keys = { workspace = true }
+agave-syscalls = { workspace = true }
 assert_matches = { workspace = true }
 bincode = { workspace = true }
 ed25519-dalek = { workspace = true }

+ 44 - 18
svm/examples/Cargo.lock

@@ -136,6 +136,46 @@ dependencies = [
  "solana-sdk-ids",
 ]
 
+[[package]]
+name = "agave-syscalls"
+version = "3.0.0"
+dependencies = [
+ "bincode",
+ "libsecp256k1",
+ "num-traits",
+ "solana-account",
+ "solana-account-info",
+ "solana-big-mod-exp",
+ "solana-blake3-hasher",
+ "solana-bn254",
+ "solana-clock",
+ "solana-cpi",
+ "solana-curve25519 3.0.0",
+ "solana-hash",
+ "solana-instruction",
+ "solana-keccak-hasher",
+ "solana-loader-v3-interface 5.0.0",
+ "solana-log-collector",
+ "solana-measure",
+ "solana-poseidon",
+ "solana-program-entrypoint",
+ "solana-program-runtime",
+ "solana-pubkey",
+ "solana-sbpf",
+ "solana-sdk-ids",
+ "solana-secp256k1-recover",
+ "solana-sha256-hasher",
+ "solana-stable-layout",
+ "solana-svm-callback",
+ "solana-svm-feature-set",
+ "solana-sysvar",
+ "solana-sysvar-id",
+ "solana-timings",
+ "solana-transaction-context",
+ "solana-type-overrides",
+ "thiserror 2.0.12",
+]
+
 [[package]]
 name = "agave-transaction-view"
 version = "3.0.0"
@@ -2915,6 +2955,7 @@ version = "3.0.0"
 dependencies = [
  "agave-feature-set",
  "agave-reserved-account-keys",
+ "agave-syscalls",
  "base64 0.22.1",
  "bincode",
  "bs58",
@@ -5520,44 +5561,27 @@ dependencies = [
 name = "solana-bpf-loader-program"
 version = "3.0.0"
 dependencies = [
+ "agave-syscalls",
  "bincode",
- "libsecp256k1",
- "num-traits",
  "qualifier_attr",
  "solana-account",
- "solana-account-info",
- "solana-big-mod-exp",
  "solana-bincode",
- "solana-blake3-hasher",
- "solana-bn254",
  "solana-clock",
- "solana-cpi",
- "solana-curve25519 3.0.0",
- "solana-hash",
  "solana-instruction",
- "solana-keccak-hasher",
  "solana-loader-v3-interface 5.0.0",
  "solana-loader-v4-interface",
  "solana-log-collector",
  "solana-measure",
  "solana-packet",
- "solana-poseidon",
  "solana-program-entrypoint",
  "solana-program-runtime",
  "solana-pubkey",
  "solana-sbpf",
  "solana-sdk-ids",
- "solana-secp256k1-recover",
- "solana-sha256-hasher",
- "solana-stable-layout",
  "solana-svm-feature-set",
  "solana-system-interface",
- "solana-sysvar",
- "solana-sysvar-id",
- "solana-timings",
  "solana-transaction-context",
  "solana-type-overrides",
- "thiserror 2.0.12",
 ]
 
 [[package]]
@@ -7591,6 +7615,7 @@ dependencies = [
  "agave-feature-set",
  "agave-precompiles",
  "agave-reserved-account-keys",
+ "agave-syscalls",
  "ahash 0.8.11",
  "aquamarine",
  "arrayref",
@@ -8209,6 +8234,7 @@ name = "solana-svm-example-paytube"
 version = "3.0.0"
 dependencies = [
  "agave-feature-set",
+ "agave-syscalls",
  "solana-account",
  "solana-bpf-loader-program",
  "solana-client",

+ 1 - 0
svm/examples/Cargo.toml

@@ -14,6 +14,7 @@ edition = "2021"
 [workspace.dependencies]
 agave-feature-set = { path = "../../feature-set" }
 agave-reserved-account-keys = { path = "../../reserved-account-keys" }
+agave-syscalls = { path = "../../syscalls" }
 base64 = "0.22.1"
 bincode = "1.3.3"
 borsh = { version = "1.5.2", features = ["derive"] }

+ 1 - 0
svm/examples/json-rpc/server/Cargo.toml

@@ -12,6 +12,7 @@ frozen-abi = []
 [dependencies]
 agave-feature-set = { workspace = true }
 agave-reserved-account-keys = { workspace = true }
+agave-syscalls = { workspace = true }
 base64 = { workspace = true }
 bincode = { workspace = true }
 bs58 = { workspace = true }

+ 3 - 3
svm/examples/json-rpc/server/src/svm_bridge.rs

@@ -1,12 +1,12 @@
 use {
     agave_feature_set::FeatureSet,
-    log::*,
-    solana_account::{Account, AccountSharedData, ReadableAccount},
-    solana_bpf_loader_program::syscalls::{
+    agave_syscalls::{
         SyscallAbort, SyscallGetClockSysvar, SyscallInvokeSignedRust, SyscallLog,
         SyscallLogBpfComputeUnits, SyscallLogPubkey, SyscallLogU64, SyscallMemcpy, SyscallMemset,
         SyscallSetReturnData,
     },
+    log::*,
+    solana_account::{Account, AccountSharedData, ReadableAccount},
     solana_clock::{Clock, Slot, UnixTimestamp},
     solana_compute_budget::compute_budget::ComputeBudget,
     solana_message::AccountKeys,

+ 1 - 0
svm/examples/paytube/Cargo.toml

@@ -11,6 +11,7 @@ frozen-abi = []
 
 [dependencies]
 agave-feature-set = { workspace = true }
+agave-syscalls = { workspace = true }
 solana-account = { workspace = true }
 solana-bpf-loader-program = { workspace = true }
 solana-client = { workspace = true }

+ 1 - 1
svm/examples/paytube/src/processor.rs

@@ -1,7 +1,7 @@
 //! A helper to initialize Solana SVM API's `TransactionBatchProcessor`.
 
 use {
-    solana_bpf_loader_program::syscalls::create_program_runtime_environment_v1,
+    agave_syscalls::create_program_runtime_environment_v1,
     solana_clock::Slot,
     solana_compute_budget::compute_budget_limits::ComputeBudgetLimits,
     solana_fee_structure::FeeDetails,

+ 1 - 1
svm/tests/conformance.rs

@@ -4,9 +4,9 @@ use {
         transaction_builder::SanitizedTransactionBuilder,
     },
     agave_feature_set::{FeatureSet, FEATURE_NAMES},
+    agave_syscalls::create_program_runtime_environment_v1,
     prost::Message,
     solana_account::{AccountSharedData, ReadableAccount, WritableAccount},
-    solana_bpf_loader_program::syscalls::create_program_runtime_environment_v1,
     solana_clock::Clock,
     solana_epoch_schedule::EpochSchedule,
     solana_hash::Hash,

+ 2 - 2
svm/tests/mock_bank.rs

@@ -3,12 +3,12 @@
 #[allow(deprecated)]
 use solana_sysvar::recent_blockhashes::{Entry as BlockhashesEntry, RecentBlockhashes};
 use {
-    solana_account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
-    solana_bpf_loader_program::syscalls::{
+    agave_syscalls::{
         SyscallAbort, SyscallGetClockSysvar, SyscallGetEpochScheduleSysvar, SyscallGetRentSysvar,
         SyscallInvokeSignedRust, SyscallLog, SyscallMemcmp, SyscallMemcpy, SyscallMemmove,
         SyscallMemset, SyscallSetReturnData,
     },
+    solana_account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
     solana_clock::{Clock, Slot, UnixTimestamp},
     solana_epoch_schedule::EpochSchedule,
     solana_fee_structure::{FeeDetails, FeeStructure},

+ 76 - 0
syscalls/Cargo.toml

@@ -0,0 +1,76 @@
+[package]
+name = "agave-syscalls"
+description = "Agave implementation of the Solana syscalls."
+documentation = "https://docs.rs/agave-syscalls"
+version = { workspace = true }
+authors = { workspace = true }
+repository = { workspace = true }
+homepage = { workspace = true }
+license = { workspace = true }
+edition = { workspace = true }
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[features]
+default = ["metrics"]
+metrics = ["solana-program-runtime/metrics"]
+shuttle-test = [
+    "solana-type-overrides/shuttle-test",
+    "solana-program-runtime/shuttle-test",
+    "solana-sbpf/shuttle-test",
+]
+svm-internal = []
+
+[dependencies]
+bincode = { workspace = true }
+libsecp256k1 = { workspace = true }
+num-traits = { workspace = true }
+solana-account = { workspace = true }
+solana-account-info = { workspace = true }
+solana-big-mod-exp = { workspace = true }
+solana-blake3-hasher = { workspace = true }
+solana-bn254 = { workspace = true }
+solana-clock = { workspace = true }
+solana-cpi = { workspace = true }
+solana-curve25519 = { workspace = true }
+solana-hash = { workspace = true }
+solana-instruction = { workspace = true }
+solana-keccak-hasher = { workspace = true }
+solana-loader-v3-interface = { workspace = true, features = ["serde"] }
+solana-log-collector = { workspace = true }
+solana-measure = { workspace = true }
+solana-poseidon = { workspace = true }
+solana-program-entrypoint = { workspace = true }
+solana-program-runtime = { workspace = true }
+solana-pubkey = { workspace = true }
+solana-sbpf = { workspace = true }
+solana-sdk-ids = { workspace = true }
+solana-secp256k1-recover = { workspace = true }
+solana-sha256-hasher = { workspace = true }
+solana-stable-layout = { workspace = true }
+solana-svm-callback = { workspace = true }
+solana-svm-feature-set = { workspace = true }
+solana-sysvar = { workspace = true }
+solana-sysvar-id = { workspace = true }
+solana-timings = { workspace = true }
+solana-transaction-context = { workspace = true, features = ["bincode"] }
+solana-type-overrides = { workspace = true }
+thiserror = { workspace = true }
+
+[dev-dependencies]
+assert_matches = { workspace = true }
+solana-epoch-rewards = { workspace = true }
+solana-epoch-schedule = { workspace = true }
+solana-fee-calculator = { workspace = true }
+solana-last-restart-slot = { workspace = true }
+solana-program = { workspace = true }
+solana-program-runtime = { workspace = true, features = ["dev-context-only-utils"] }
+solana-pubkey = { workspace = true, features = ["rand"] }
+solana-rent = { workspace = true }
+solana-slot-hashes = { workspace = true }
+solana-transaction-context = { workspace = true, features = ["dev-context-only-utils"] }
+test-case = { workspace = true }
+
+[lints]
+workspace = true

+ 0 - 0
programs/bpf_loader/gen-syscall-list/Cargo.toml → syscalls/gen-syscall-list/Cargo.toml


+ 2 - 2
programs/bpf_loader/gen-syscall-list/build.rs → syscalls/gen-syscall-list/build.rs

@@ -14,8 +14,8 @@ use {
  * to verify undefined symbols in a .so module that cargo-build-sbf has built.
  */
 fn main() {
-    let syscalls_rs_path = PathBuf::from("../src/syscalls/mod.rs");
-    let syscalls_txt_path = PathBuf::from("../../../platform-tools-sdk/sbf/syscalls.txt");
+    let syscalls_rs_path = PathBuf::from("../src/lib.rs");
+    let syscalls_txt_path = PathBuf::from("../../platform-tools-sdk/sbf/syscalls.txt");
     println!(
         "cargo:warning=(not a warning) Generating {1} from {0}",
         syscalls_rs_path.display(),

+ 0 - 0
programs/bpf_loader/gen-syscall-list/src/main.rs → syscalls/gen-syscall-list/src/main.rs


+ 9 - 3
programs/bpf_loader/src/syscalls/cpi.rs → syscalls/src/cpi.rs

@@ -1274,13 +1274,13 @@ fn update_caller_account(
 mod tests {
     use {
         super::*,
-        crate::mock_create_vm,
         assert_matches::assert_matches,
         solana_account::{Account, AccountSharedData, ReadableAccount},
         solana_clock::Epoch,
         solana_instruction::Instruction,
         solana_program_runtime::{
-            invoke_context::SerializedAccountMetadata, with_mock_invoke_context_with_feature_set,
+            invoke_context::{BpfAllocator, SerializedAccountMetadata, SyscallContext},
+            with_mock_invoke_context_with_feature_set,
         },
         solana_sbpf::{
             ebpf::MM_INPUT_START, memory_region::MemoryRegion, program::SBPFVersion, vm::Config,
@@ -1840,7 +1840,13 @@ mod tests {
             &[1, 1]
         );
 
-        mock_create_vm!(_vm, Vec::new(), vec![account_metadata], &mut invoke_context);
+        invoke_context
+            .set_syscall_context(SyscallContext {
+                allocator: BpfAllocator::new(solana_program_entrypoint::HEAP_LENGTH as u64),
+                accounts_metadata: vec![account_metadata],
+                trace_log: Vec::new(),
+            })
+            .unwrap();
 
         invoke_context
             .transaction_context

+ 64 - 60
programs/bpf_loader/src/syscalls/mod.rs → syscalls/src/lib.rs

@@ -12,7 +12,7 @@ pub use self::{
 };
 #[allow(deprecated)]
 use {
-    crate::syscalls::mem_ops::is_nonoverlapping,
+    crate::mem_ops::is_nonoverlapping,
     solana_account_info::AccountInfo,
     solana_big_mod_exp::{big_mod_exp, BigModExpParams},
     solana_blake3_hasher as blake3,
@@ -294,28 +294,6 @@ macro_rules! register_feature_gated_function {
     };
 }
 
-pub(crate) fn morph_into_deployment_environment_v1(
-    from: Arc<BuiltinProgram<InvokeContext>>,
-) -> Result<BuiltinProgram<InvokeContext>, Error> {
-    let mut config = from.get_config().clone();
-    config.reject_broken_elfs = true;
-    // Once the tests are being build using a toolchain which supports the newer SBPF versions,
-    // the deployment of older versions will be disabled:
-    // config.enabled_sbpf_versions =
-    //     *config.enabled_sbpf_versions.end()..=*config.enabled_sbpf_versions.end();
-
-    let mut result = BuiltinProgram::new_loader(config);
-
-    for (_key, (name, value)) in from.get_function_registry().iter() {
-        // Deployment of programs with sol_alloc_free is disabled. So do not register the syscall.
-        if name != *b"sol_alloc_free_" {
-            result.register_function(unsafe { std::str::from_utf8_unchecked(name) }, value)?;
-        }
-    }
-
-    Ok(result)
-}
-
 pub fn create_program_runtime_environment_v1<'a>(
     feature_set: &SVMFeatureSet,
     compute_budget: &SVMTransactionExecutionBudget,
@@ -2180,7 +2158,6 @@ mod tests {
     use solana_sysvar::fees::Fees;
     use {
         super::*,
-        crate::mock_create_vm,
         assert_matches::assert_matches,
         core::slice,
         solana_account::{create_account_shared_data_for_test, AccountSharedData},
@@ -2192,9 +2169,18 @@ mod tests {
         solana_instruction::Instruction,
         solana_last_restart_slot::LastRestartSlot,
         solana_program::program::check_type_assumptions,
-        solana_program_runtime::{invoke_context::InvokeContext, with_mock_invoke_context},
+        solana_program_runtime::{
+            execution_budget::MAX_HEAP_FRAME_BYTES,
+            invoke_context::{BpfAllocator, InvokeContext, SyscallContext},
+            with_mock_invoke_context,
+        },
         solana_sbpf::{
-            error::EbpfError, memory_region::MemoryRegion, program::SBPFVersion, vm::Config,
+            aligned_memory::AlignedMemory,
+            ebpf::{self, HOST_ALIGN},
+            error::EbpfError,
+            memory_region::{MemoryMapping, MemoryRegion},
+            program::SBPFVersion,
+            vm::Config,
         },
         solana_sdk_ids::{bpf_loader, bpf_loader_upgradeable, sysvar},
         solana_sha256_hasher::hashv,
@@ -2634,82 +2620,104 @@ mod tests {
         );
     }
 
+    macro_rules! setup_alloc_test {
+        ($invoke_context:ident, $memory_mapping:ident, $heap:ident) => {
+            prepare_mockup!($invoke_context, program_id, bpf_loader::id());
+            $invoke_context
+                .set_syscall_context(SyscallContext {
+                    allocator: BpfAllocator::new(solana_program_entrypoint::HEAP_LENGTH as u64),
+                    accounts_metadata: Vec::new(),
+                    trace_log: Vec::new(),
+                })
+                .unwrap();
+            let config = Config {
+                aligned_memory_mapping: false,
+                ..Config::default()
+            };
+            let mut $heap =
+                AlignedMemory::<{ HOST_ALIGN }>::zero_filled(MAX_HEAP_FRAME_BYTES as usize);
+            let regions = vec![MemoryRegion::new_writable(
+                $heap.as_slice_mut(),
+                ebpf::MM_HEAP_START,
+            )];
+            let mut $memory_mapping =
+                MemoryMapping::new(regions, &config, SBPFVersion::V3).unwrap();
+        };
+    }
+
     #[test]
     fn test_syscall_sol_alloc_free() {
         // large alloc
         {
-            prepare_mockup!(invoke_context, program_id, bpf_loader::id());
-            mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
-            let mut vm = vm.unwrap();
-            let invoke_context = &mut vm.context_object_pointer;
-            let memory_mapping = &mut vm.memory_mapping;
+            setup_alloc_test!(invoke_context, memory_mapping, heap);
             let result = SyscallAllocFree::rust(
-                invoke_context,
+                &mut invoke_context,
                 solana_program_entrypoint::HEAP_LENGTH as u64,
                 0,
                 0,
                 0,
                 0,
-                memory_mapping,
+                &mut memory_mapping,
             );
             assert_ne!(result.unwrap(), 0);
             let result = SyscallAllocFree::rust(
-                invoke_context,
+                &mut invoke_context,
                 solana_program_entrypoint::HEAP_LENGTH as u64,
                 0,
                 0,
                 0,
                 0,
-                memory_mapping,
+                &mut memory_mapping,
             );
             assert_eq!(result.unwrap(), 0);
-            let result =
-                SyscallAllocFree::rust(invoke_context, u64::MAX, 0, 0, 0, 0, memory_mapping);
+            let result = SyscallAllocFree::rust(
+                &mut invoke_context,
+                u64::MAX,
+                0,
+                0,
+                0,
+                0,
+                &mut memory_mapping,
+            );
             assert_eq!(result.unwrap(), 0);
         }
 
         // many small unaligned allocs
         {
-            prepare_mockup!(invoke_context, program_id, bpf_loader::id());
-            mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
-            let mut vm = vm.unwrap();
-            let invoke_context = &mut vm.context_object_pointer;
-            let memory_mapping = &mut vm.memory_mapping;
+            setup_alloc_test!(invoke_context, memory_mapping, heap);
             for _ in 0..100 {
-                let result = SyscallAllocFree::rust(invoke_context, 1, 0, 0, 0, 0, memory_mapping);
+                let result =
+                    SyscallAllocFree::rust(&mut invoke_context, 1, 0, 0, 0, 0, &mut memory_mapping);
                 assert_ne!(result.unwrap(), 0);
             }
             let result = SyscallAllocFree::rust(
-                invoke_context,
+                &mut invoke_context,
                 solana_program_entrypoint::HEAP_LENGTH as u64,
                 0,
                 0,
                 0,
                 0,
-                memory_mapping,
+                &mut memory_mapping,
             );
             assert_eq!(result.unwrap(), 0);
         }
 
         // many small aligned allocs
         {
-            prepare_mockup!(invoke_context, program_id, bpf_loader::id());
-            mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
-            let mut vm = vm.unwrap();
-            let invoke_context = &mut vm.context_object_pointer;
-            let memory_mapping = &mut vm.memory_mapping;
+            setup_alloc_test!(invoke_context, memory_mapping, heap);
             for _ in 0..12 {
-                let result = SyscallAllocFree::rust(invoke_context, 1, 0, 0, 0, 0, memory_mapping);
+                let result =
+                    SyscallAllocFree::rust(&mut invoke_context, 1, 0, 0, 0, 0, &mut memory_mapping);
                 assert_ne!(result.unwrap(), 0);
             }
             let result = SyscallAllocFree::rust(
-                invoke_context,
+                &mut invoke_context,
                 solana_program_entrypoint::HEAP_LENGTH as u64,
                 0,
                 0,
                 0,
                 0,
-                memory_mapping,
+                &mut memory_mapping,
             );
             assert_eq!(result.unwrap(), 0);
         }
@@ -2717,19 +2725,15 @@ mod tests {
         // aligned allocs
 
         fn aligned<T>() {
-            prepare_mockup!(invoke_context, program_id, bpf_loader::id());
-            mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
-            let mut vm = vm.unwrap();
-            let invoke_context = &mut vm.context_object_pointer;
-            let memory_mapping = &mut vm.memory_mapping;
+            setup_alloc_test!(invoke_context, memory_mapping, heap);
             let result = SyscallAllocFree::rust(
-                invoke_context,
+                &mut invoke_context,
                 size_of::<T>() as u64,
                 0,
                 0,
                 0,
                 0,
-                memory_mapping,
+                &mut memory_mapping,
             );
             let address = result.unwrap();
             assert_ne!(address, 0);

+ 0 - 0
programs/bpf_loader/src/syscalls/logging.rs → syscalls/src/logging.rs


+ 0 - 0
programs/bpf_loader/src/syscalls/mem_ops.rs → syscalls/src/mem_ops.rs


+ 0 - 0
programs/bpf_loader/src/syscalls/sysvar.rs → syscalls/src/sysvar.rs