diff --git a/programs/bpf/rust/128bit/src/lib.rs b/programs/bpf/rust/128bit/src/lib.rs index e034b33ece..8e395103fa 100644 --- a/programs/bpf/rust/128bit/src/lib.rs +++ b/programs/bpf/rust/128bit/src/lib.rs @@ -1,7 +1,7 @@ //! @brief Example Rust-based BPF program tests loop iteration extern crate solana_program; -use solana_program::entrypoint::SUCCESS; +use solana_program::{custom_panic_default, entrypoint::SUCCESS}; #[no_mangle] pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { @@ -50,6 +50,8 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { SUCCESS } +custom_panic_default!(); + #[cfg(test)] mod test { use super::*; diff --git a/programs/bpf/rust/alloc/src/lib.rs b/programs/bpf/rust/alloc/src/lib.rs index e735c9b39b..1df03a1cf8 100644 --- a/programs/bpf/rust/alloc/src/lib.rs +++ b/programs/bpf/rust/alloc/src/lib.rs @@ -2,7 +2,7 @@ #[macro_use] extern crate alloc; -use solana_program::{entrypoint::SUCCESS, msg}; +use solana_program::{custom_panic_default, entrypoint::SUCCESS, msg}; use std::{alloc::Layout, mem}; #[no_mangle] @@ -81,6 +81,8 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { SUCCESS } +custom_panic_default!(); + #[cfg(test)] mod test { use super::*; diff --git a/programs/bpf/rust/call_depth/src/lib.rs b/programs/bpf/rust/call_depth/src/lib.rs index 562731a69f..f5ec2168a9 100644 --- a/programs/bpf/rust/call_depth/src/lib.rs +++ b/programs/bpf/rust/call_depth/src/lib.rs @@ -1,6 +1,6 @@ //! @brief Example Rust-based BPF program that tests call depth and stack usage -use solana_program::{entrypoint::SUCCESS, msg}; +use solana_program::{custom_panic_default, entrypoint::SUCCESS, msg}; #[inline(never)] pub fn recurse(data: &mut [u8]) { @@ -25,3 +25,5 @@ pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 { recurse(&mut data); SUCCESS } + +custom_panic_default!(); diff --git a/programs/bpf/rust/iter/src/lib.rs b/programs/bpf/rust/iter/src/lib.rs index 3eec536b2b..efa9825f26 100644 --- a/programs/bpf/rust/iter/src/lib.rs +++ b/programs/bpf/rust/iter/src/lib.rs @@ -1,7 +1,7 @@ //! @brief Example Rust-based BPF program tests loop iteration extern crate solana_program; -use solana_program::{entrypoint::SUCCESS, msg}; +use solana_program::{custom_panic_default, entrypoint::SUCCESS, msg}; #[no_mangle] pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { @@ -18,6 +18,8 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { SUCCESS } +custom_panic_default!(); + #[cfg(test)] mod test { use super::*; diff --git a/programs/bpf/rust/many_args/src/lib.rs b/programs/bpf/rust/many_args/src/lib.rs index 39de05eadf..2cf8f37501 100644 --- a/programs/bpf/rust/many_args/src/lib.rs +++ b/programs/bpf/rust/many_args/src/lib.rs @@ -2,7 +2,7 @@ mod helper; extern crate solana_program; -use solana_program::{entrypoint::SUCCESS, msg}; +use solana_program::{custom_panic_default, entrypoint::SUCCESS, msg}; #[no_mangle] pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { @@ -26,6 +26,8 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { SUCCESS } +custom_panic_default!(); + #[cfg(test)] mod test { use super::*; diff --git a/programs/bpf/rust/mem/src/lib.rs b/programs/bpf/rust/mem/src/lib.rs index fe08f6e03e..860ff16a24 100644 --- a/programs/bpf/rust/mem/src/lib.rs +++ b/programs/bpf/rust/mem/src/lib.rs @@ -4,7 +4,7 @@ #![feature(compiler_builtins_lib)] extern crate compiler_builtins; -use solana_program::entrypoint::SUCCESS; +use solana_program::{custom_panic_default, entrypoint::SUCCESS, info}; #[no_mangle] pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { @@ -183,3 +183,5 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { SUCCESS } + +custom_panic_default!(); diff --git a/programs/bpf/rust/panic/Cargo.toml b/programs/bpf/rust/panic/Cargo.toml index 8be2540a63..8ce35cbd03 100644 --- a/programs/bpf/rust/panic/Cargo.toml +++ b/programs/bpf/rust/panic/Cargo.toml @@ -11,6 +11,10 @@ edition = "2018" [dependencies] solana-program = { path = "../../../../sdk/program", version = "1.4.15" } +[features] +default = ["custom-panic"] +custom-panic = [] + [lib] name = "solana_bpf_rust_panic" crate-type = ["cdylib"] diff --git a/programs/bpf/rust/panic/src/lib.rs b/programs/bpf/rust/panic/src/lib.rs index 0d579f205c..f79f27c223 100644 --- a/programs/bpf/rust/panic/src/lib.rs +++ b/programs/bpf/rust/panic/src/lib.rs @@ -1,8 +1,24 @@ //! @brief Example Rust-based BPF program that panics -extern crate solana_program; - +#[cfg(all(feature = "custom-panic", target_arch = "bpf"))] #[no_mangle] -pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { - panic!(); +fn custom_panic(info: &core::panic::PanicInfo<'_>) { + // Note: Full panic reporting is included here for testing purposes + solana_program::msg!("program custom panic enabled"); + solana_program::msg!(&format!("{}", info)); +} + +extern crate solana_program; +use solana_program::{ + account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, pubkey::Pubkey, +}; + +entrypoint!(process_instruction); +fn process_instruction( + _program_id: &Pubkey, + _accounts: &[AccountInfo], + _instruction_data: &[u8], +) -> ProgramResult { + assert_eq!(1, 2); + Ok(()) } diff --git a/programs/bpf/rust/param_passing/src/lib.rs b/programs/bpf/rust/param_passing/src/lib.rs index 5c38fd76c7..9d1002d92b 100644 --- a/programs/bpf/rust/param_passing/src/lib.rs +++ b/programs/bpf/rust/param_passing/src/lib.rs @@ -2,7 +2,7 @@ extern crate solana_program; use solana_bpf_rust_param_passing_dep::{Data, TestDep}; -use solana_program::{entrypoint::SUCCESS, msg}; +use solana_program::{custom_panic_default, entrypoint::SUCCESS, msg}; #[no_mangle] pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { @@ -23,6 +23,8 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { SUCCESS } +custom_panic_default!(); + #[cfg(test)] mod test { use super::*; diff --git a/programs/bpf/rust/ro_modify/src/lib.rs b/programs/bpf/rust/ro_modify/src/lib.rs index e002445e2d..d55179a729 100644 --- a/programs/bpf/rust/ro_modify/src/lib.rs +++ b/programs/bpf/rust/ro_modify/src/lib.rs @@ -203,12 +203,12 @@ fn process_instruction( macro_rules! check { ($left:expr, $right:expr) => { if $left != $right { - msg!(&format!( + msg!( "Condition failure: {:?} != {:?} at line {:?}", $left, $right, line!() - )); + ); return Err(ProgramError::Custom(0)); } }; diff --git a/programs/bpf/rust/sha256/src/lib.rs b/programs/bpf/rust/sha256/src/lib.rs index c215050a5f..fc5c55b3e6 100644 --- a/programs/bpf/rust/sha256/src/lib.rs +++ b/programs/bpf/rust/sha256/src/lib.rs @@ -2,6 +2,7 @@ extern crate solana_program; use solana_program::{ + custom_panic_default, hash::{hashv, Hasher}, msg, }; @@ -22,6 +23,8 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { 0 } +custom_panic_default!(); + #[cfg(test)] mod test { use super::*; diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index d61a36ce50..4ec5e0f89f 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -835,7 +835,6 @@ fn test_program_bpf_ro_modify() { let instruction = Instruction::new(program_pubkey, &[1_u8], account_metas.clone()); let message = Message::new(&[instruction], Some(&mint_keypair.pubkey())); let result = bank_client.send_and_confirm_message(&[&mint_keypair, &test_keypair], message); - println!("result {:?}", result); assert_eq!( result.unwrap_err().unwrap(), TransactionError::InstructionError(0, InstructionError::Custom(0xb9f0002)) @@ -844,7 +843,6 @@ fn test_program_bpf_ro_modify() { let instruction = Instruction::new(program_pubkey, &[3_u8], account_metas.clone()); let message = Message::new(&[instruction], Some(&mint_keypair.pubkey())); let result = bank_client.send_and_confirm_message(&[&mint_keypair, &test_keypair], message); - println!("result {:?}", result); assert_eq!( result.unwrap_err().unwrap(), TransactionError::InstructionError(0, InstructionError::Custom(0xb9f0002)) @@ -911,8 +909,8 @@ fn assert_instruction_count() { ("multiple_static", 8), ("noop", 57), ("relative_call", 10), - ("sanity", 1140), - ("sanity++", 1140), + ("sanity", 176), + ("sanity++", 176), ("struct_pass", 8), ("struct_ret", 22), ]); @@ -920,16 +918,16 @@ fn assert_instruction_count() { #[cfg(feature = "bpf_rust")] { programs.extend_from_slice(&[ - ("solana_bpf_rust_128bit", 543), - ("solana_bpf_rust_alloc", 19082), + ("solana_bpf_rust_128bit", 572), + ("solana_bpf_rust_alloc", 12919), ("solana_bpf_rust_dep_crate", 2), - ("solana_bpf_rust_external_spend", 538), - ("solana_bpf_rust_iter", 723), - ("solana_bpf_rust_many_args", 231), + ("solana_bpf_rust_external_spend", 514), + ("solana_bpf_rust_iter", 724), + ("solana_bpf_rust_many_args", 237), ("solana_bpf_rust_noop", 488), - ("solana_bpf_rust_param_passing", 46), + ("solana_bpf_rust_param_passing", 48), ("solana_bpf_rust_ristretto", 19399), - ("solana_bpf_rust_sanity", 1965), + ("solana_bpf_rust_sanity", 894), ]); } @@ -982,7 +980,6 @@ fn test_program_bpf_instruction_introspection() { Some(&mint_keypair.pubkey()), ); let result = bank_client.send_and_confirm_message(&[&mint_keypair], message); - println!("result: {:?}", result); assert!(result.is_ok()); // writable special instructions11111 key, should not be allowed diff --git a/sdk/bpf/scripts/install.sh b/sdk/bpf/scripts/install.sh index 464fff22e2..88a5808d31 100755 --- a/sdk/bpf/scripts/install.sh +++ b/sdk/bpf/scripts/install.sh @@ -174,7 +174,7 @@ if [[ ! -e rust-bpf-$machine-$version.md || ! -e rust-bpf-$machine ]]; then fi # Install Rust-BPF Sysroot sources -version=v0.12 +version=v0.13 if [[ ! -e rust-bpf-sysroot-$version.md || ! -e rust-bpf-sysroot ]]; then ( set -e diff --git a/sdk/program/src/entrypoint.rs b/sdk/program/src/entrypoint.rs index 588cb65b0e..44664a9e1f 100644 --- a/sdk/program/src/entrypoint.rs +++ b/sdk/program/src/entrypoint.rs @@ -38,23 +38,9 @@ pub const HEAP_LENGTH: usize = 32 * 1024; /// Deserialize the program input arguments and call the user defined /// `process_instruction` function. Users must call this macro otherwise an /// entry point for their program will not be created. -/// -/// If the program defines the feature `custom-heap` then the default heap -/// implementation will not be included and the program is free to implement -/// their own `#[global_allocator]` #[macro_export] macro_rules! entrypoint { ($process_instruction:ident) => { - /// A program can provide their own custom heap implementation by adding - /// a `custom-heap` feature to `Cargo.toml` and implementing their own - /// `global_allocator`. - #[cfg(all(not(feature = "custom-heap"), target_arch = "bpf"))] - #[global_allocator] - static A: $crate::entrypoint::BumpAllocator = $crate::entrypoint::BumpAllocator { - start: $crate::entrypoint::HEAP_START_ADDRESS, - len: $crate::entrypoint::HEAP_LENGTH, - }; - /// # Safety #[no_mangle] pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 { @@ -65,6 +51,50 @@ macro_rules! entrypoint { Err(error) => error.into(), } } + $crate::custom_heap_default!(); + $crate::custom_panic_default!(); + }; +} + +/// Fallback to default for unused custom heap feature. +#[macro_export] +macro_rules! custom_heap_default { + () => { + /// A program can provide their own custom heap implementation by adding + /// a `custom-heap` feature to `Cargo.toml` and implementing their own + /// `global_allocator`. + /// + /// If the program defines the feature `custom-heap` then the default heap + /// implementation will not be included and the program is free to implement + /// their own `#[global_allocator]` + #[cfg(all(not(feature = "custom-heap"), target_arch = "bpf"))] + #[global_allocator] + static A: $crate::entrypoint::BumpAllocator = $crate::entrypoint::BumpAllocator { + start: $crate::entrypoint::HEAP_START_ADDRESS, + len: $crate::entrypoint::HEAP_LENGTH, + }; + }; +} + +/// Fallback to default for unused custom panic feature. +/// This must be used if the entrypoint! macro is not used. +#[macro_export] +macro_rules! custom_panic_default { + () => { + /// A program can provide their own custom panic implementation by + /// adding a `custom-panic` feature to `Cargo.toml` and implementing + /// their own `custom_panic`. + /// + /// A good way to reduce the final size of the program is to provide a + /// `custom_panic` implementation that does nothing. Doing so will cut + /// ~25kb from a noop program. That number goes down the more the + /// programs pulls in Rust's libstd for other purposes. + #[cfg(all(not(feature = "custom-panic"), target_arch = "bpf"))] + #[no_mangle] + fn custom_panic(info: &core::panic::PanicInfo<'_>) { + // Full panic reporting + $crate::msg!("{}", info); + } }; }