diff --git a/ci/test-checks.sh b/ci/test-checks.sh index 8fc42bf842..b90499c1a7 100755 --- a/ci/test-checks.sh +++ b/ci/test-checks.sh @@ -10,14 +10,22 @@ source ci/rust-version.sh nightly export RUST_BACKTRACE=1 export RUSTFLAGS="-D warnings" -( - for project in programs/bpf/rust/*/ ; do - ( - cd "$project" +do_bpf_check() { _ cargo +"$rust_stable" fmt --all -- --check _ cargo +"$rust_nightly" clippy --all -- --version _ cargo +"$rust_nightly" clippy --all -- --deny=warnings _ cargo +"$rust_stable" audit +} + +( + ( + cd sdk/bpf/rust/rust-utils + do_bpf_check + ) + for project in programs/bpf/rust/*/ ; do + ( + cd "$project" + do_bpf_check ) done ) diff --git a/programs/bpf/build.rs b/programs/bpf/build.rs index 8d29eca326..504f53b489 100644 --- a/programs/bpf/build.rs +++ b/programs/bpf/build.rs @@ -81,8 +81,9 @@ fn main() { "cargo:warning=(not a warning) Building Rust-based BPF programs: solana_bpf_rust_{}", program ); - assert!(Command::new("./build.sh") + assert!(Command::new("./do.sh") .current_dir("rust") + .arg("build") .arg(program) .status() .expect(&format!( diff --git a/programs/bpf/rust/alloc/src/lib.rs b/programs/bpf/rust/alloc/src/lib.rs index e30b54c4a5..aadbd25b22 100644 --- a/programs/bpf/rust/alloc/src/lib.rs +++ b/programs/bpf/rust/alloc/src/lib.rs @@ -6,11 +6,10 @@ extern crate alloc; extern crate solana_sdk_bpf_utils; -use solana_sdk_bpf_utils::log::*; - use alloc::vec::Vec; use core::alloc::Layout; use core::mem; +use solana_sdk_bpf_utils::info; #[no_mangle] pub extern "C" fn entrypoint(_input: *mut u8) -> bool { @@ -20,7 +19,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool { let layout = Layout::from_size_align(core::usize::MAX, mem::align_of::()).unwrap(); let ptr = alloc::alloc::alloc(layout); if !ptr.is_null() { - sol_log("Error: Alloc of very larger buffer should fail"); + info!("Error: Alloc of very larger buffer should fail"); panic!(); } } @@ -31,7 +30,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool { let layout = Layout::from_size_align(100, mem::align_of::()).unwrap(); let ptr = alloc::alloc::alloc(layout); if ptr.is_null() { - sol_log("Error: Alloc of 100 bytes failed"); + info!("Error: Alloc of 100 bytes failed"); alloc::alloc::handle_alloc_error(layout); } alloc::alloc::dealloc(ptr, layout); @@ -44,7 +43,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool { let layout = Layout::from_size_align(100, mem::align_of::()).unwrap(); let ptr = alloc::alloc::alloc(layout); if ptr.is_null() { - sol_log("Error: Alloc failed"); + info!("Error: Alloc failed"); alloc::alloc::handle_alloc_error(layout); } for i in 0..ITERS { @@ -53,7 +52,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool { for i in 0..ITERS { assert_eq!(*ptr.add(i as usize), i as u8); } - sol_log_64(0x3, 0, 0, 0, u64::from(*ptr.add(42))); + info!(0x3, 0, 0, 0, u64::from(*ptr.add(42))); assert_eq!(*ptr.add(42), 42); alloc::alloc::dealloc(ptr, layout); } @@ -65,13 +64,13 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool { // let layout = Layout::from_size_align(2048, mem::align_of::()).unwrap(); // let ptr = alloc::alloc::alloc(layout); // if ptr.is_null() { - // sol_log("Error: Alloc of 2048 bytes failed"); + // info!("Error: Alloc of 2048 bytes failed"); // alloc::alloc::handle_alloc_error(layout); // } // let layout = Layout::from_size_align(1, mem::align_of::()).unwrap(); // let ptr_fail = alloc::alloc::alloc(layout); // if !ptr_fail.is_null() { - // sol_log("Error: Able to alloc 1 more then max"); + // info!("Error: Able to alloc 1 more then max"); // panic!(); // } // alloc::alloc::dealloc(ptr, layout); @@ -87,7 +86,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool { for v in ones.iter() { sum += ones[*v]; } - sol_log_64(0x0, 0, 0, 0, sum as u64); + info!(0x0, 0, 0, 0, sum as u64); assert_eq!(sum, ITERS); } @@ -98,13 +97,12 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool { let mut v = Vec::new(); for i in 0..ITERS { - sol_log_64(i as u64, 0, 0, 0, 0); v.push(i); } - sol_log_64(0x4, 0, 0, 0, v.len() as u64); + info!(0x4, 0, 0, 0, v.len() as u64); assert_eq!(v.len(), ITERS); } - sol_log("Success"); + info!("Success"); true } diff --git a/programs/bpf/rust/build.sh b/programs/bpf/rust/build.sh deleted file mode 100755 index 5f63f88dd3..0000000000 --- a/programs/bpf/rust/build.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -if [ "$#" -ne 1 ]; then - # Build all projects - for project in */ ; do - ./../../../sdk/bpf/rust/build.sh "$PWD/$project" - done -else - # Build requested project - ./../../../sdk/bpf/rust/build.sh "$PWD/$1" - -fi \ No newline at end of file diff --git a/programs/bpf/rust/clean.sh b/programs/bpf/rust/clean.sh deleted file mode 100755 index 7bdf69451c..0000000000 --- a/programs/bpf/rust/clean.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -if [ "$#" -ne 1 ]; then - # Clean all projects - for project in */ ; do - ./../../../sdk/bpf/rust/clean.sh "$PWD/$project" - done -else - # Clean requested project - ./../../../sdk/bpf/rust/clean.sh "$PWD/$1" - -fi diff --git a/programs/bpf/rust/dep_crate/src/lib.rs b/programs/bpf/rust/dep_crate/src/lib.rs index 5781062dff..0c3b9bbdf9 100644 --- a/programs/bpf/rust/dep_crate/src/lib.rs +++ b/programs/bpf/rust/dep_crate/src/lib.rs @@ -6,7 +6,7 @@ extern crate solana_sdk_bpf_utils; use byteorder::{ByteOrder, LittleEndian}; -use solana_sdk_bpf_utils::log::*; +use solana_sdk_bpf_utils::info; #[no_mangle] pub extern "C" fn entrypoint(_input: *mut u8) -> bool { @@ -18,6 +18,6 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool { LittleEndian::write_i16(&mut buf, -5_000); assert_eq!(-5_000, LittleEndian::read_i16(&buf)); - sol_log("Success"); + info!("Success"); true } diff --git a/programs/bpf/rust/do.sh b/programs/bpf/rust/do.sh new file mode 100755 index 0000000000..9db6593389 --- /dev/null +++ b/programs/bpf/rust/do.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash + +usage() { + echo "" + echo " Usage: do.sh action " + echo "" + echo " If relative_project_path is ommitted then action will" + echo " be performed on all projects" + echo "" + echo " Supported actions:" + echo " build" + echo " clean" + echo " clippy" + echo " fmt" + echo "" +} + +perform_action() { + set -e + case "$1" in + build) + ./../../../sdk/bpf/rust/build.sh "$2" + ;; + clean) + ./../../../sdk/bpf/rust/clean.sh "$2" + ;; + clippy) + ( + cd "$2" + echo "clippy $2" + cargo +nightly clippy + ) + ;; + fmt) + ( + cd "$2" + echo "formatting $2" + cargo fmt + ) + ;; + dump) + # Dump depends on tools that are not installed by default and must be installed manually + # - greadelf + # - llvm-objdump + # - rustfilt + ( + pwd + ./do.sh clean "$3" + ./do.sh build "$3" + + cd "$3" + + set +e + cp ./target/dump.txt ./targetdump-last.txt 2>/dev/null + set -e + + ls \ + -la \ + ./target/bpfel-unknown-unknown/release/solana_bpf_rust_"${3%/}".so \ + > ./target/dump_mangled.txt + greadelf \ + -aW \ + ./target/bpfel-unknown-unknown/release/solana_bpf_rust_"${3%/}".so \ + >> ./target/dump_mangled.txt + llvm-objdump \ + -print-imm-hex \ + --source \ + --disassemble \ + ./target/bpfel-unknown-unknown/release/solana_bpf_rust_"${3%/}".so \ + >> ./target/dump_mangled.txt + sed \ + s/://g \ + < ./target/dump_mangled.txt \ + | rustfilt \ + > ./target/dump.txt + ) + ;; + help) + usage + exit + ;; + *) + echo "Error: Unknown command" + usage + exit + ;; + esac +} + +set -e + +if [ "$#" -ne 2 ]; then + # Build all projects + for project in */ ; do + perform_action "$1" "$PWD/$project" "$project" + done +else + # Build requested project + perform_action "$1" "$PWD/$2" "$2" +fi \ No newline at end of file diff --git a/programs/bpf/rust/dump.sh b/programs/bpf/rust/dump.sh deleted file mode 100755 index 8dac0490d6..0000000000 --- a/programs/bpf/rust/dump.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -if [ "$#" -ne 1 ]; then - echo "Error: Must provide the name of the project to dump" - exit 1 -fi - -./clean.sh "$1" -./build.sh "$1" - -cd "$1" - -cp ./target/dump.txt ./targetdump-last.txt 2>/dev/null - -set -ex - -ls -la ./target/bpfel-unknown-unknown/release/solana_bpf_rust_"${1%/}".so > ./target/dump_mangled.txt -greadelf -aW ./target/bpfel-unknown-unknown/release/solana_bpf_rust_"${1%/}".so >> ./target/dump_mangled.txt -llvm-objdump -print-imm-hex --source --disassemble ./target/bpfel-unknown-unknown/release/solana_bpf_rust_"${1%/}".so >> ./target/dump_mangled.txt -sed s/://g < ./target/dump_mangled.txt | rustfilt > ./target/dump.txt - diff --git a/programs/bpf/rust/iter/src/lib.rs b/programs/bpf/rust/iter/src/lib.rs index b4dd3b1297..f610b69029 100644 --- a/programs/bpf/rust/iter/src/lib.rs +++ b/programs/bpf/rust/iter/src/lib.rs @@ -5,7 +5,7 @@ extern crate solana_sdk_bpf_utils; -use solana_sdk_bpf_utils::log::*; +use solana_sdk_bpf_utils::info; #[no_mangle] pub extern "C" fn entrypoint(_input: *mut u8) -> bool { @@ -16,9 +16,9 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool { for v in ones.iter() { sum += *v; } - sol_log_64(0xff, 0, 0, 0, sum); + info!(0xff, 0, 0, 0, sum); assert_eq!(sum, ITERS as u64); - sol_log("Success"); + info!("Success"); true } diff --git a/programs/bpf/rust/many_args/src/lib.rs b/programs/bpf/rust/many_args/src/lib.rs index 3642a6042d..43417da641 100644 --- a/programs/bpf/rust/many_args/src/lib.rs +++ b/programs/bpf/rust/many_args/src/lib.rs @@ -7,18 +7,18 @@ mod helper; extern crate solana_sdk_bpf_utils; -use solana_sdk_bpf_utils::log::*; +use solana_sdk_bpf_utils::info; #[no_mangle] pub extern "C" fn entrypoint(_input: *mut u8) -> bool { - sol_log("call same package"); + info!("call same package"); assert_eq!(crate::helper::many_args(1, 2, 3, 4, 5, 6, 7, 8, 9), 45); - sol_log("call another package"); + info!("call another package"); assert_eq!( solana_bpf_rust_many_args_dep::many_args(1, 2, 3, 4, 5, 6, 7, 8, 9), 45 ); - sol_log("Success"); + info!("Success"); true } diff --git a/programs/bpf/rust/many_args_dep/Xargo.toml b/programs/bpf/rust/many_args_dep/Xargo.toml new file mode 100644 index 0000000000..385a264b04 --- /dev/null +++ b/programs/bpf/rust/many_args_dep/Xargo.toml @@ -0,0 +1,6 @@ +[dependencies.compiler_builtins] +path = "../../../../sdk/bpf/dependencies/rust-bpf-sysroot/src/compiler-builtins" +features = ["c", "mem"] + +[target.bpfel-unknown-unknown.dependencies] +alloc = { path = "../../../../sdk/bpf/dependencies/rust-bpf-sysroot/src/liballoc" } \ No newline at end of file diff --git a/programs/bpf/rust/many_args_dep/src/lib.rs b/programs/bpf/rust/many_args_dep/src/lib.rs index 8f24671365..c89891a92f 100644 --- a/programs/bpf/rust/many_args_dep/src/lib.rs +++ b/programs/bpf/rust/many_args_dep/src/lib.rs @@ -4,7 +4,7 @@ extern crate solana_sdk_bpf_utils; -use solana_sdk_bpf_utils::log::*; +use solana_sdk_bpf_utils::info; pub fn many_args( arg1: u64, @@ -17,8 +17,8 @@ pub fn many_args( arg8: u64, arg9: u64, ) -> u64 { - sol_log("another package"); - sol_log_64(arg1, arg2, arg3, arg4, arg5); - sol_log_64(arg6, arg7, arg8, arg9, 0); + info!("another package"); + info!(arg1, arg2, arg3, arg4, arg5); + info!(arg6, arg7, arg8, arg9, 0); arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 } diff --git a/programs/bpf/rust/noop/src/lib.rs b/programs/bpf/rust/noop/src/lib.rs index 05060a411b..edcfb140d3 100644 --- a/programs/bpf/rust/noop/src/lib.rs +++ b/programs/bpf/rust/noop/src/lib.rs @@ -2,12 +2,13 @@ #![no_std] #![allow(unreachable_code)] +#![allow(unused_attributes)] extern crate solana_sdk_bpf_utils; -use solana_sdk_bpf_utils::entrypoint; use solana_sdk_bpf_utils::entrypoint::*; use solana_sdk_bpf_utils::log::*; +use solana_sdk_bpf_utils::{entrypoint, info}; struct SStruct { x: u64, @@ -21,18 +22,14 @@ fn return_sstruct() -> SStruct { } entrypoint!(process_instruction); -fn process_instruction( - ka: &mut [Option; MAX_ACCOUNTS], - info: &SolClusterInfo, - data: &[u8], -) -> bool { - sol_log("Program identifier:"); +fn process_instruction(ka: &mut [SolKeyedAccount], info: &SolClusterInfo, data: &[u8]) -> bool { + info!("Program identifier:"); sol_log_key(&info.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. - sol_log("Account keys and instruction input data:"); + info!("Account keys and instruction input data:"); sol_log_params(ka, data); { @@ -49,7 +46,7 @@ fn process_instruction( let result_str = core::str::from_utf8(&sparkle_heart).unwrap(); assert_eq!(4, result_str.len()); assert_eq!("💖", result_str); - sol_log(result_str); + info!(result_str); } { @@ -59,6 +56,6 @@ fn process_instruction( assert_eq!(s.x + s.y + s.z, 6); } - sol_log("Success"); + info!("Success"); true } diff --git a/programs/bpf/rust/tick_height/src/lib.rs b/programs/bpf/rust/tick_height/src/lib.rs index 3f2690ce71..220058ba73 100644 --- a/programs/bpf/rust/tick_height/src/lib.rs +++ b/programs/bpf/rust/tick_height/src/lib.rs @@ -6,22 +6,14 @@ extern crate solana_sdk_bpf_utils; use byteorder::{ByteOrder, LittleEndian}; -use solana_sdk_bpf_utils::entrypoint; use solana_sdk_bpf_utils::entrypoint::*; -use solana_sdk_bpf_utils::log::*; +use solana_sdk_bpf_utils::{entrypoint, info}; entrypoint!(process_instruction); -fn process_instruction( - ka: &mut [Option; MAX_ACCOUNTS], - _info: &SolClusterInfo, - _data: &[u8], -) -> bool { - sol_log("Tick Height:"); - if let Some(k) = &ka[2] { - let tick_height = LittleEndian::read_u64(k.data); - assert_eq!(10u64, tick_height); - sol_log("Success"); - return true; - } - panic!(); +fn process_instruction(ka: &mut [SolKeyedAccount], _info: &SolClusterInfo, _data: &[u8]) -> bool { + let tick_height = LittleEndian::read_u64(ka[2].data); + assert_eq!(10u64, tick_height); + + info!("Success"); + true } diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 076be996fd..af51c0c03d 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -87,10 +87,10 @@ mod bpf { let programs = [ ("solana_bpf_rust_alloc", true), + ("solana_bpf_rust_dep_crate", true), ("solana_bpf_rust_iter", true), // ("solana_bpf_rust_many_args", true), // Issue #3099 ("solana_bpf_rust_noop", true), - ("solana_bpf_rust_dep_crate", true), ("solana_bpf_rust_panic", false), ("solana_bpf_rust_tick_height", true), ]; diff --git a/programs/bpf_loader_api/src/lib.rs b/programs/bpf_loader_api/src/lib.rs index 35242333af..313ff6d94c 100644 --- a/programs/bpf_loader_api/src/lib.rs +++ b/programs/bpf_loader_api/src/lib.rs @@ -164,7 +164,7 @@ pub fn helper_sol_log( let c_buf: *const c_char = addr as *const c_char; let c_str: &CStr = unsafe { CStr::from_ptr(c_buf) }; match c_str.to_str() { - Ok(slice) => info!("sol_log: {:?}", slice), + Ok(slice) => info!("info!: {:?}", slice), Err(e) => warn!("Error: Cannot print invalid string: {}", e), }; 0 @@ -178,7 +178,7 @@ pub fn helper_sol_log_u64( _context: &mut Option>, ) -> u64 { info!( - "sol_log_u64: {:#x}, {:#x}, {:#x}, {:#x}, {:#x}", + "info!: {:#x}, {:#x}, {:#x}, {:#x}, {:#x}", arg1, arg2, arg3, arg4, arg5 ); 0 diff --git a/sdk/bpf/rust/build.sh b/sdk/bpf/rust/build.sh index 8233083208..e58cca5af2 100755 --- a/sdk/bpf/rust/build.sh +++ b/sdk/bpf/rust/build.sh @@ -9,6 +9,8 @@ if [ ! -f "$1/Cargo.toml" ]; then exit 1 fi +echo "Building $1" + pushd "$(dirname "$0")" bpf_sdk="$PWD/.." popd @@ -28,7 +30,6 @@ export AR="$bpf_sdk/dependencies/llvm-native/bin/llvm-ar" # Use the SDK's version of Rust to build for BPF export RUSTUP_TOOLCHAIN=bpf export RUSTFLAGS=" - --emit=llvm-ir \ -C lto=no \ -C opt-level=2 \ -C link-arg=-z -C link-arg=notext \ @@ -39,6 +40,6 @@ export RUSTFLAGS=" -C linker=$bpf_sdk/dependencies/llvm-native/bin/ld.lld" export XARGO_HOME="$bpf_sdk/dependencies/xargo" export XARGO_RUST_SRC="$bpf_sdk/dependencies/rust-bpf-sysroot/src" -xargo build --target bpfel-unknown-unknown --release -v +xargo build --target bpfel-unknown-unknown --release { { set +x; } 2>/dev/null; echo Success; } diff --git a/sdk/bpf/rust/rust-utils/src/entrypoint.rs b/sdk/bpf/rust/rust-utils/src/entrypoint.rs index 1174d43b8a..41407b0e80 100644 --- a/sdk/bpf/rust/rust-utils/src/entrypoint.rs +++ b/sdk/bpf/rust/rust-utils/src/entrypoint.rs @@ -1,24 +1,17 @@ //! @brief Solana Rust-based BPF program entrypoint and its parameter types +extern crate alloc; -use crate::log::*; +use alloc::vec::Vec; use core::mem::size_of; use core::slice::{from_raw_parts, from_raw_parts_mut}; -/// Max number of accounts supported -pub const MAX_ACCOUNTS: usize = 10; - -/// Size in bytes of a public key -pub const SIZE_PUBKEY: usize = 32; - /// Public key -pub struct SolPubkey<'a> { - pub key: &'a [u8; SIZE_PUBKEY], -} +pub type SolPubkey = [u8; 32]; /// Keyed Account pub struct SolKeyedAccount<'a> { /// Public key of the account - pub key: SolPubkey<'a>, + pub key: &'a SolPubkey, /// Public key of the account pub is_signer: bool, /// Number of lamports owned by this account @@ -26,14 +19,14 @@ pub struct SolKeyedAccount<'a> { /// On-chain data within this account pub data: &'a mut [u8], /// Program that owns this account - pub owner: SolPubkey<'a>, + pub owner: &'a SolPubkey, } /// Information about the state of the cluster immediately before the program /// started executing the current instruction pub struct SolClusterInfo<'a> { - ///program_id of the currently executing program - pub program_id: SolPubkey<'a>, + /// program_id of the currently executing program + pub program_id: &'a SolPubkey, } /// Declare entrypoint of the program. @@ -48,9 +41,8 @@ macro_rules! entrypoint { #[no_mangle] pub unsafe extern "C" fn entrypoint(input: *mut u8) -> bool { unsafe { - if let Ok((mut ka, info, data)) = $crate::entrypoint::deserialize(input) { - // Call use function - $process_instruction(&mut ka, &info, &data) + if let Ok((mut kas, info, data)) = $crate::entrypoint::deserialize(input) { + $process_instruction(&mut kas, &info, &data) } else { false } @@ -63,32 +55,19 @@ macro_rules! entrypoint { #[allow(clippy::type_complexity)] pub unsafe fn deserialize<'a>( input: *mut u8, -) -> Result< - ( - [Option>; MAX_ACCOUNTS], - SolClusterInfo<'a>, - &'a [u8], - ), - (), -> { +) -> Result<(Vec>, SolClusterInfo<'a>, &'a [u8]), ()> { let mut offset: usize = 0; // Number of KeyedAccounts present #[allow(clippy::cast_ptr_alignment)] let num_ka = *(input.add(offset) as *const u64) as usize; - offset += 8; + offset += size_of::(); // KeyedAccounts - if num_ka > MAX_ACCOUNTS { - sol_log("Error: Too many accounts"); - return Err(()); - } - - let mut kas: [Option; MAX_ACCOUNTS] = - [None, None, None, None, None, None, None, None, None, None]; - for ka in kas.iter_mut().take(num_ka) { + let mut kas = Vec::new(); + for _ in 0..num_ka { let is_signer = { #[allow(clippy::cast_ptr_alignment)] let is_signer_val = *(input.add(offset) as *const u64); @@ -96,12 +75,8 @@ pub unsafe fn deserialize<'a>( }; offset += size_of::(); - let key = { - SolPubkey { - key: &*(input.add(offset) as *mut [u8; SIZE_PUBKEY]), - } - }; - offset += SIZE_PUBKEY; + let key: &SolPubkey = &*(input.add(offset) as *const [u8; size_of::()]); + offset += size_of::(); #[allow(clippy::cast_ptr_alignment)] let lamports = *(input.add(offset) as *const u64); @@ -114,14 +89,10 @@ pub unsafe fn deserialize<'a>( let data = { from_raw_parts_mut(input.add(offset), data_length) }; offset += data_length; - let owner = { - SolPubkey { - key: &*(input.add(offset) as *mut [u8; SIZE_PUBKEY]), - } - }; - offset += SIZE_PUBKEY; + let owner: &SolPubkey = &*(input.add(offset) as *const [u8; size_of::()]); + offset += size_of::(); - *ka = Some(SolKeyedAccount { + kas.push(SolKeyedAccount { key, is_signer, lamports, @@ -139,14 +110,9 @@ pub unsafe fn deserialize<'a>( let data = { from_raw_parts(input.add(offset), data_length) }; offset += data_length; - // Id - - let program_id = { - SolPubkey { - key: &*(input.add(offset) as *mut [u8; SIZE_PUBKEY]), - } - }; + // Program Id + let program_id: &SolPubkey = &*(input.add(offset) as *const [u8; size_of::()]); let info = SolClusterInfo { program_id }; Ok((kas, info, data)) diff --git a/sdk/bpf/rust/rust-utils/src/lib.rs b/sdk/bpf/rust/rust-utils/src/lib.rs index f07f6c9b55..a19f97c7d0 100644 --- a/sdk/bpf/rust/rust-utils/src/lib.rs +++ b/sdk/bpf/rust/rust-utils/src/lib.rs @@ -6,7 +6,8 @@ #![feature(panic_info_message)] #![feature(compiler_builtins_lib)] #![feature(lang_items)] -#[lang = "eh_personality"] extern fn eh_personality() {} +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} extern crate compiler_builtins; diff --git a/sdk/bpf/rust/rust-utils/src/log.rs b/sdk/bpf/rust/rust-utils/src/log.rs index bb3d3a4c89..82b6d5558e 100644 --- a/sdk/bpf/rust/rust-utils/src/log.rs +++ b/sdk/bpf/rust/rust-utils/src/log.rs @@ -2,13 +2,37 @@ use crate::entrypoint::{SolKeyedAccount, SolPubkey}; +/// Prints a string +/// There are two forms and are fast +/// 1. Single string +/// 2. 5 integers +#[macro_export] +macro_rules! info { + ($msg:expr) => { + $crate::log::sol_log($msg) + }; + ($arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr) => { + $crate::log::sol_log_64( + $arg1 as u64, + $arg2 as u64, + $arg3 as u64, + $arg4 as u64, + $arg5 as u64, + ) + }; // `format!()` is not supported yet, Issue #3099 + // `format!()` incurs a very large runtime overhead so it should be used with care + // ($($arg:tt)*) => ($crate::log::sol_log(&format!($($arg)*))); +} + /// Prints a string to stdout -#[inline(never)] // stack intensive, prevent inline so everyone does not incur cost +/// +/// @param message - Message to print +#[inline(never)] // prevent inline so everyone does not incur stack cost pub fn sol_log(message: &str) { - // TODO This is extremely slow, do something better + // Not pretty but 1/3 faster then using `clone_from_slice()` let mut buf: [u8; 128] = [0; 128]; for (i, b) in message.as_bytes().iter().enumerate() { - if i >= 126 { + if i > 127 { break; } buf[i] = *b; @@ -22,6 +46,8 @@ extern "C" { } /// Prints 64 bit values represented as hexadecimal to stdout +/// +/// @param argx - integer arguments to print pub fn sol_log_64(arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) { unsafe { sol_log_64_(arg1, arg2, arg3, arg4, arg5); @@ -36,7 +62,7 @@ extern "C" { /// @param - key The public key to print #[allow(dead_code)] pub fn sol_log_key(key: &SolPubkey) { - for (i, k) in key.key.iter().enumerate() { + for (i, k) in key.iter().enumerate() { sol_log_64(0, 0, 0, i as u64, u64::from(*k)); } } @@ -56,22 +82,20 @@ pub fn sol_log_slice(slice: &[u8]) { /// @param ka - A pointer to an array of `SolKeyedAccounts` to print /// @param data - A pointer to the instruction data to print #[allow(dead_code)] -pub fn sol_log_params(ka: &[Option], data: &[u8]) { +pub fn sol_log_params(ka: &[SolKeyedAccount], data: &[u8]) { for (i, k) in ka.iter().enumerate() { - if let Some(k) = k { - sol_log("SolKeyedAccount"); - sol_log_64(0, 0, 0, 0, i as u64); - sol_log("- Is signer"); - sol_log_64(0, 0, 0, 0, k.is_signer as u64); - sol_log("- Key"); - sol_log_key(&k.key); - sol_log("- Lamports"); - sol_log_64(0, 0, 0, 0, k.lamports); - sol_log("- AccountData"); - sol_log_slice(k.data); - sol_log("- Owner"); - sol_log_key(&k.owner); - } + sol_log("SolKeyedAccount"); + sol_log_64(0, 0, 0, 0, i as u64); + sol_log("- Is signer"); + sol_log_64(0, 0, 0, 0, k.is_signer as u64); + sol_log("- Key"); + sol_log_key(&k.key); + sol_log("- Lamports"); + sol_log_64(0, 0, 0, 0, k.lamports); + sol_log("- AccountData"); + sol_log_slice(k.data); + sol_log("- Owner"); + sol_log_key(&k.owner); } sol_log("Instruction data"); sol_log_slice(data); diff --git a/sdk/bpf/rust/rust-utils/src/panic.rs b/sdk/bpf/rust/rust-utils/src/panic.rs index 4335f0cf28..6b7fdd2dec 100644 --- a/sdk/bpf/rust/rust-utils/src/panic.rs +++ b/sdk/bpf/rust/rust-utils/src/panic.rs @@ -6,11 +6,12 @@ use core::ptr; #[cfg(not(test))] #[panic_handler] fn panic(info: &PanicInfo) -> ! { + // Message is ignored for now to avoid incurring formatting program size overhead match info.location() { Some(location) => { let mut file: [u8; 128] = [0; 128]; for (i, c) in location.file().as_bytes().iter().enumerate() { - if i >= 126 { + if i > 127 { break; } file[i] = *c;