diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index 23bed2a0d3..83975e9c24 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -1818,6 +1818,13 @@ dependencies = [ "solana-sdk", ] +[[package]] +name = "solana-bpf-rust-sanity" +version = "1.4.0" +dependencies = [ + "solana-sdk", +] + [[package]] name = "solana-bpf-rust-sysval" version = "1.4.0" diff --git a/programs/bpf/Cargo.toml b/programs/bpf/Cargo.toml index ca055e7c5b..b0d65f8990 100644 --- a/programs/bpf/Cargo.toml +++ b/programs/bpf/Cargo.toml @@ -50,6 +50,7 @@ members = [ "rust/panic", "rust/param_passing", "rust/param_passing_dep", + "rust/sanity", "rust/sysval", ] diff --git a/programs/bpf/build.rs b/programs/bpf/build.rs index eaaedc7574..ac7d51c1ad 100644 --- a/programs/bpf/build.rs +++ b/programs/bpf/build.rs @@ -79,6 +79,7 @@ fn main() { "noop", "panic", "param_passing", + "sanity", "sysval", ]; for program in rust_programs.iter() { diff --git a/programs/bpf/c/src/noop/noop.c b/programs/bpf/c/src/noop/noop.c index de5277d3a7..0934995599 100644 --- a/programs/bpf/c/src/noop/noop.c +++ b/programs/bpf/c/src/noop/noop.c @@ -1,22 +1,13 @@ /** - * @brief Example C-based BPF program that prints out the parameters - * passed to it + * @brief Example C-based BPF noop program */ #include extern uint64_t entrypoint(const uint8_t *input) { SolAccountInfo ka[1]; SolParameters params = (SolParameters) { .ka = ka }; - - sol_log(__FILE__); - if (!sol_deserialize(input, ¶ms, SOL_ARRAY_SIZE(ka))) { return ERROR_INVALID_ARGUMENT; } - - // Log the provided input parameters. In the case of the no-op - // program, no account keys or input data are expected but real - // programs will have specific requirements so they can do their work. - sol_log_params(¶ms); return SUCCESS; } diff --git a/programs/bpf/c/src/sanity/sanity.c b/programs/bpf/c/src/sanity/sanity.c new file mode 100644 index 0000000000..e77c4ce8ac --- /dev/null +++ b/programs/bpf/c/src/sanity/sanity.c @@ -0,0 +1,22 @@ +/** + * @brief Example C-based BPF sanity rogram that prints out the parameters + * passed to it + */ +#include + +extern uint64_t entrypoint(const uint8_t *input) { + SolAccountInfo ka[1]; + SolParameters params = (SolParameters) { .ka = ka }; + + sol_log(__FILE__); + + if (!sol_deserialize(input, ¶ms, SOL_ARRAY_SIZE(ka))) { + return ERROR_INVALID_ARGUMENT; + } + + // Log the provided input parameters. In the case of the no-op + // program, no account keys or input data are expected but real + // programs will have specific requirements so they can do their work. + sol_log_params(¶ms); + return SUCCESS; +} diff --git a/programs/bpf/rust/noop/src/lib.rs b/programs/bpf/rust/noop/src/lib.rs index 6b196acde5..206b5b1727 100644 --- a/programs/bpf/rust/noop/src/lib.rs +++ b/programs/bpf/rust/noop/src/lib.rs @@ -1,77 +1,15 @@ -//! @brief Example Rust-based BPF program that prints out the parameters passed to it - -#![allow(unreachable_code)] +//! @brief Example Rust-based BPF noop program extern crate solana_sdk; use solana_sdk::{ - account_info::AccountInfo, bpf_loader, entrypoint, entrypoint::ProgramResult, info, log::*, - pubkey::Pubkey, + account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, pubkey::Pubkey, }; -#[derive(Debug, PartialEq)] -struct SStruct { - x: u64, - y: u64, - z: u64, -} - -#[inline(never)] -fn return_sstruct() -> SStruct { - SStruct { x: 1, y: 2, z: 3 } -} - entrypoint!(process_instruction); fn process_instruction( - program_id: &Pubkey, - accounts: &[AccountInfo], - instruction_data: &[u8], + _program_id: &Pubkey, + _accounts: &[AccountInfo], + _instruction_data: &[u8], ) -> ProgramResult { - info!("Program identifier:"); - program_id.log(); - - assert!(!bpf_loader::check_id(program_id)); - - // Log the provided account keys and instruction input data. In the case of - // the no-op program, no account keys or input data are expected but real - // programs will have specific requirements so they can do their work. - info!("Account keys and instruction input data:"); - sol_log_params(accounts, instruction_data); - - { - // Test - use std methods, unwrap - - // valid bytes, in a stack-allocated array - let sparkle_heart = [240, 159, 146, 150]; - let result_str = std::str::from_utf8(&sparkle_heart).unwrap(); - assert_eq!(4, result_str.len()); - assert_eq!("💖", result_str); - info!(result_str); - } - - { - // Test - struct return - - let s = return_sstruct(); - assert_eq!(s.x + s.y + s.z, 6); - } - - { - // Test - arch config - #[cfg(not(target_arch = "bpf"))] - panic!(); - } - Ok(()) } - -#[cfg(test)] -mod test { - use super::*; - // Pull in syscall stubs when building for non-BPF targets - solana_sdk::program_stubs!(); - - #[test] - fn test_return_sstruct() { - assert_eq!(SStruct { x: 1, y: 2, z: 3 }, return_sstruct()); - } -} diff --git a/programs/bpf/rust/sanity/Cargo.toml b/programs/bpf/rust/sanity/Cargo.toml new file mode 100644 index 0000000000..8511d0790a --- /dev/null +++ b/programs/bpf/rust/sanity/Cargo.toml @@ -0,0 +1,26 @@ + +# Note: This crate must be built using do.sh + +[package] +name = "solana-bpf-rust-sanity" +version = "1.4.0" +description = "Solana BPF test program written in Rust" +authors = ["Solana Maintainers "] +repository = "https://github.com/solana-labs/solana" +license = "Apache-2.0" +homepage = "https://solana.com/" +edition = "2018" + +[dependencies] +solana-sdk = { path = "../../../../sdk/", version = "1.4.0", default-features = false } + +[features] +program = ["solana-sdk/program"] +default = ["program", "solana-sdk/default"] + +[lib] +name = "solana_bpf_rust_sanity" +crate-type = ["cdylib"] + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] diff --git a/programs/bpf/rust/sanity/Xargo.toml b/programs/bpf/rust/sanity/Xargo.toml new file mode 100644 index 0000000000..1744f098ae --- /dev/null +++ b/programs/bpf/rust/sanity/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] \ No newline at end of file diff --git a/programs/bpf/rust/sanity/src/lib.rs b/programs/bpf/rust/sanity/src/lib.rs new file mode 100644 index 0000000000..704fde03c2 --- /dev/null +++ b/programs/bpf/rust/sanity/src/lib.rs @@ -0,0 +1,77 @@ +//! @brief Example Rust-based BPF sanity program that prints out the parameters passed to it + +#![allow(unreachable_code)] + +extern crate solana_sdk; +use solana_sdk::{ + account_info::AccountInfo, bpf_loader, entrypoint, entrypoint::ProgramResult, info, log::*, + pubkey::Pubkey, +}; + +#[derive(Debug, PartialEq)] +struct SStruct { + x: u64, + y: u64, + z: u64, +} + +#[inline(never)] +fn return_sstruct() -> SStruct { + SStruct { x: 1, y: 2, z: 3 } +} + +entrypoint!(process_instruction); +fn process_instruction( + program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], +) -> ProgramResult { + info!("Program identifier:"); + program_id.log(); + + assert!(!bpf_loader::check_id(program_id)); + + // Log the provided account keys and instruction input data. In the case of + // the no-op program, no account keys or input data are expected but real + // programs will have specific requirements so they can do their work. + info!("Account keys and instruction input data:"); + sol_log_params(accounts, instruction_data); + + { + // Test - use std methods, unwrap + + // valid bytes, in a stack-allocated array + let sparkle_heart = [240, 159, 146, 150]; + let result_str = std::str::from_utf8(&sparkle_heart).unwrap(); + assert_eq!(4, result_str.len()); + assert_eq!("💖", result_str); + info!(result_str); + } + + { + // Test - struct return + + let s = return_sstruct(); + assert_eq!(s.x + s.y + s.z, 6); + } + + { + // Test - arch config + #[cfg(not(target_arch = "bpf"))] + panic!(); + } + + Ok(()) +} + +#[cfg(test)] +mod test { + use super::*; + // Pull in syscall stubs when building for non-BPF targets + solana_sdk::program_stubs!(); + + #[test] + fn test_return_sstruct() { + assert_eq!(SStruct { x: 1, y: 2, z: 3 }, return_sstruct()); + } +}