BPF rust language updates (#4752)
This commit is contained in:
parent
aacb38864c
commit
e59b53dfa8
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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::<u8>()).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::<u8>()).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::<u8>()).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::<u8>()).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::<u8>()).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
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
usage() {
|
||||
echo ""
|
||||
echo " Usage: do.sh action <project>"
|
||||
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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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" }
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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<SolKeyedAccount>; 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
|
||||
}
|
||||
|
|
|
@ -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<SolKeyedAccount>; 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
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
];
|
||||
|
|
|
@ -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<Box<Any + 'static>>,
|
||||
) -> u64 {
|
||||
info!(
|
||||
"sol_log_u64: {:#x}, {:#x}, {:#x}, {:#x}, {:#x}",
|
||||
"info!: {:#x}, {:#x}, {:#x}, {:#x}, {:#x}",
|
||||
arg1, arg2, arg3, arg4, arg5
|
||||
);
|
||||
0
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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<SolKeyedAccount<'a>>; MAX_ACCOUNTS],
|
||||
SolClusterInfo<'a>,
|
||||
&'a [u8],
|
||||
),
|
||||
(),
|
||||
> {
|
||||
) -> Result<(Vec<SolKeyedAccount<'a>>, 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::<u64>();
|
||||
|
||||
// KeyedAccounts
|
||||
|
||||
if num_ka > MAX_ACCOUNTS {
|
||||
sol_log("Error: Too many accounts");
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let mut kas: [Option<SolKeyedAccount>; 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::<u64>();
|
||||
|
||||
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::<SolPubkey>()]);
|
||||
offset += size_of::<SolPubkey>();
|
||||
|
||||
#[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::<SolPubkey>()]);
|
||||
offset += size_of::<SolPubkey>();
|
||||
|
||||
*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::<SolPubkey>()]);
|
||||
let info = SolClusterInfo { program_id };
|
||||
|
||||
Ok((kas, info, data))
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<SolKeyedAccount>], 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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue