Update examples to new SDK (#358)
This commit is contained in:
		@@ -3,23 +3,20 @@
 | 
			
		||||
 | 
			
		||||
[package]
 | 
			
		||||
name = "solana-bpf-rust-noop"
 | 
			
		||||
version = "0.15.0"
 | 
			
		||||
version = "0.16.0"
 | 
			
		||||
description = "Solana BPF noop program written in Rust"
 | 
			
		||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
 | 
			
		||||
repository = "https://github.com/solana-labs/solana"
 | 
			
		||||
license = "Apache-2.0"
 | 
			
		||||
homepage = "https://solana.com/"
 | 
			
		||||
edition = "2018"
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
# byteorder = { version = "1.3.1", default-features = false }
 | 
			
		||||
# heapless = { version = "0.4.0", default-features = false }
 | 
			
		||||
# byte = { version = "0.2", default-features = false }
 | 
			
		||||
solana-sdk-bpf-utils = { path = "../../bpf-sdk/rust/rust-utils", version = "0.16.0" }
 | 
			
		||||
 | 
			
		||||
[workspace]
 | 
			
		||||
members = []
 | 
			
		||||
 | 
			
		||||
[lib]
 | 
			
		||||
name = "solana_bpf_rust_noop"
 | 
			
		||||
crate-type = ["cdylib"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
name = "solana_bpf_rust_noop"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[dependencies.compiler_builtins]
 | 
			
		||||
path = "../../bpf-sdk/rust-bpf-sysroot/src/compiler-builtins"
 | 
			
		||||
path = "../../bpf-sdk/dependencies/rust-bpf-sysroot/src/compiler-builtins"
 | 
			
		||||
features = ["c", "mem"]
 | 
			
		||||
 | 
			
		||||
[target.bpfel-unknown-unknown.dependencies]
 | 
			
		||||
alloc = { path = "../../bpf-sdk/dependencies/rust-bpf-sysroot/src/liballoc" }
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
PHDRS
 | 
			
		||||
{
 | 
			
		||||
  text PT_LOAD  ;
 | 
			
		||||
  rodata PT_LOAD ;
 | 
			
		||||
  dynamic PT_DYNAMIC ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SECTIONS
 | 
			
		||||
{
 | 
			
		||||
  . = SIZEOF_HEADERS;
 | 
			
		||||
  .text : { *(.text) } :text
 | 
			
		||||
  .rodata : { *(.rodata) } :rodata
 | 
			
		||||
  .dynamic : { *(.dynamic) } :dynamic
 | 
			
		||||
  .dynsym : { *(.dynsym) } :dynamic
 | 
			
		||||
  .dynstr : { *(.dynstr) } :dynamic
 | 
			
		||||
  .gnu.hash : { *(.gnu.hash) } :dynamic
 | 
			
		||||
  .rel.dyn : { *(.rel.dyn) } :dynamic
 | 
			
		||||
  .hash : { *(.hash) } :dynamic
 | 
			
		||||
}
 | 
			
		||||
@@ -1,27 +0,0 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
cd "$(dirname "$0")"
 | 
			
		||||
 | 
			
		||||
cargo install xargo
 | 
			
		||||
 | 
			
		||||
set -ex
 | 
			
		||||
 | 
			
		||||
# Ensure the sdk is installed
 | 
			
		||||
../../bpf-sdk/scripts/install.sh
 | 
			
		||||
rustup override set bpf
 | 
			
		||||
 | 
			
		||||
export RUSTFLAGS="$RUSTFLAGS \
 | 
			
		||||
    -C lto=no \
 | 
			
		||||
    -C opt-level=2 \
 | 
			
		||||
    -C link-arg=-Tbpf.ld \
 | 
			
		||||
    -C link-arg=-z -C link-arg=notext \
 | 
			
		||||
    -C link-arg=--Bdynamic \
 | 
			
		||||
    -C link-arg=-shared \
 | 
			
		||||
    -C link-arg=--entry=entrypoint \
 | 
			
		||||
    -C linker=../../bpf-sdk/llvm-native/bin/ld.lld"
 | 
			
		||||
export XARGO_HOME="$PWD/target/xargo"
 | 
			
		||||
export XARGO_RUST_SRC="../../bpf-sdk/rust-bpf-sysroot/src"
 | 
			
		||||
# export XARGO_RUST_SRC="../../../../../rust-bpf-sysroot/src"
 | 
			
		||||
xargo build --target bpfel-unknown-unknown --release -v
 | 
			
		||||
 | 
			
		||||
{ { set +x; } 2>/dev/null; echo Success; }
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
set -ex
 | 
			
		||||
 | 
			
		||||
cargo clean
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
cp dump.txt dump_last.txt 2>/dev/null
 | 
			
		||||
 | 
			
		||||
set -x
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
./clean.sh
 | 
			
		||||
./build.sh
 | 
			
		||||
ls -la ./target/bpfel_unknown_unknown/release/solana_bpf_rust_noop.so > dump.txt
 | 
			
		||||
greadelf -aW ./target/bpfel_unknown_unknown/release/solana_bpf_rust_noop.so | rustfilt >> dump.txt
 | 
			
		||||
llvm-objdump -print-imm-hex --source --disassemble ./target/bpfel_unknown_unknown/release/solana_bpf_rust_noop.so >> dump.txt
 | 
			
		||||
@@ -1,11 +1,13 @@
 | 
			
		||||
//! @brief Example Rust-based BPF program that prints out the parameters passed to it
 | 
			
		||||
 | 
			
		||||
#![cfg(not(test))]
 | 
			
		||||
#![no_std]
 | 
			
		||||
#![allow(unreachable_code)]
 | 
			
		||||
 | 
			
		||||
mod solana_sdk;
 | 
			
		||||
extern crate solana_sdk_bpf_utils;
 | 
			
		||||
 | 
			
		||||
use solana_sdk::*;
 | 
			
		||||
use solana_sdk_bpf_utils::entrypoint;
 | 
			
		||||
use solana_sdk_bpf_utils::entrypoint::*;
 | 
			
		||||
use solana_sdk_bpf_utils::log::*;
 | 
			
		||||
 | 
			
		||||
struct SStruct {
 | 
			
		||||
    x: u64,
 | 
			
		||||
@@ -18,7 +20,12 @@ fn return_sstruct() -> SStruct {
 | 
			
		||||
    SStruct { x: 1, y: 2, z: 3 }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn process(ka: &mut [SolKeyedAccount], data: &[u8], info: &SolClusterInfo) -> bool {
 | 
			
		||||
entrypoint!(process_instruction);
 | 
			
		||||
fn process_instruction(
 | 
			
		||||
    ka: &mut [Option<SolKeyedAccount>; MAX_ACCOUNTS],
 | 
			
		||||
    info: &SolClusterInfo,
 | 
			
		||||
    data: &[u8],
 | 
			
		||||
) -> bool {
 | 
			
		||||
    sol_log("Program identifier:");
 | 
			
		||||
    sol_log_key(&info.program_id);
 | 
			
		||||
 | 
			
		||||
@@ -28,23 +35,27 @@ fn process(ka: &mut [SolKeyedAccount], data: &[u8], info: &SolClusterInfo) -> bo
 | 
			
		||||
    sol_log("Account keys and instruction input data:");
 | 
			
		||||
    sol_log_params(ka, data);
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        // Test - arch config
 | 
			
		||||
        #[cfg(not(target_arch = "bpf"))]
 | 
			
		||||
        panic!();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        // Test - use core methods, unwrap
 | 
			
		||||
 | 
			
		||||
        // valid bytes, in a stack-allocated array
 | 
			
		||||
        let sparkle_heart = [240, 159, 146, 150];
 | 
			
		||||
 | 
			
		||||
        let result_str = core::str::from_utf8(&sparkle_heart).unwrap();
 | 
			
		||||
 | 
			
		||||
        sol_log_64(0, 0, 0, 0, result_str.len() as u64);
 | 
			
		||||
        sol_log(result_str);
 | 
			
		||||
        assert_eq!(4, result_str.len());
 | 
			
		||||
        assert_eq!("💖", result_str);
 | 
			
		||||
        sol_log(result_str);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        // Test - struct return
 | 
			
		||||
 | 
			
		||||
        let s = return_sstruct();
 | 
			
		||||
        sol_log_64(0, 0, s.x, s.y, s.z);
 | 
			
		||||
        assert_eq!(s.x + s.y + s.z, 6);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,409 +0,0 @@
 | 
			
		||||
//! @brief Solana Rust-based BPF program utility functions and types
 | 
			
		||||
 | 
			
		||||
// extern crate heapless;
 | 
			
		||||
 | 
			
		||||
// use self::heapless::consts::*;
 | 
			
		||||
// use self::heapless::String; // fixed capacity `std::Vec` // type level integer used to specify capacity
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
use self::tests::process;
 | 
			
		||||
use core::mem::size_of;
 | 
			
		||||
use core::panic::PanicInfo;
 | 
			
		||||
use core::slice::from_raw_parts;
 | 
			
		||||
 | 
			
		||||
#[cfg(not(test))]
 | 
			
		||||
use process;
 | 
			
		||||
 | 
			
		||||
// Panic handling
 | 
			
		||||
extern "C" {
 | 
			
		||||
    pub fn sol_panic_() -> !;
 | 
			
		||||
}
 | 
			
		||||
#[panic_handler]
 | 
			
		||||
fn panic(_info: &PanicInfo) -> ! {
 | 
			
		||||
    sol_log("Panic!");
 | 
			
		||||
    // TODO rashes! sol_log(_info.payload().downcast_ref::<&str>().unwrap());
 | 
			
		||||
    if let Some(location) = _info.location() {
 | 
			
		||||
        if !location.file().is_empty() {
 | 
			
		||||
            // TODO location.file() returns empty str, if we get here its been fixed
 | 
			
		||||
            sol_log(location.file());
 | 
			
		||||
            sol_log("location.file() is fixed!!");
 | 
			
		||||
            unsafe {
 | 
			
		||||
                sol_panic_();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        sol_log_64(0, 0, 0, location.line() as u64, location.column() as u64);
 | 
			
		||||
    } else {
 | 
			
		||||
        sol_log("Panic! but could not get location information");
 | 
			
		||||
    }
 | 
			
		||||
    unsafe {
 | 
			
		||||
        sol_panic_();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
    fn sol_log_(message: *const u8);
 | 
			
		||||
}
 | 
			
		||||
/// Helper function that prints a string to stdout
 | 
			
		||||
#[inline(never)] // stack intensive, block inline so everyone does not incur
 | 
			
		||||
pub fn sol_log(message: &str) {
 | 
			
		||||
    // TODO This is extremely slow, do something better
 | 
			
		||||
    let mut buf: [u8; 128] = [0; 128];
 | 
			
		||||
    for (i, b) in message.as_bytes().iter().enumerate() {
 | 
			
		||||
        if i >= 126 {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        buf[i] = *b;
 | 
			
		||||
    }
 | 
			
		||||
    unsafe {
 | 
			
		||||
        sol_log_(buf.as_ptr());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // let mut c_string: String<U256> = String::new();
 | 
			
		||||
    // if message.len() < 256 {
 | 
			
		||||
    //     if c_string.push_str(message).is_err() {
 | 
			
		||||
    //         c_string
 | 
			
		||||
    //             .push_str("Attempted to log a malformed string\0")
 | 
			
		||||
    //             .is_ok();
 | 
			
		||||
    //     }
 | 
			
		||||
    //     if c_string.push('\0').is_err() {
 | 
			
		||||
    //         c_string.push_str("Failed to log string\0").is_ok();
 | 
			
		||||
    //     };
 | 
			
		||||
    // } else {
 | 
			
		||||
    //     c_string
 | 
			
		||||
    //         .push_str("Attempted to log a string that is too long\0")
 | 
			
		||||
    //         .is_ok();
 | 
			
		||||
    // }
 | 
			
		||||
    // unsafe {
 | 
			
		||||
    //     sol_log_(message.as_ptr());
 | 
			
		||||
    // }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
    fn sol_log_64_(arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64);
 | 
			
		||||
}
 | 
			
		||||
/// Helper function that prints a 64 bit values represented in hexadecimal
 | 
			
		||||
/// to stdout
 | 
			
		||||
pub fn sol_log_64(arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) {
 | 
			
		||||
    unsafe {
 | 
			
		||||
        sol_log_64_(arg1, arg2, arg3, arg4, arg5);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Prints the hexadecimal representation of a public key
 | 
			
		||||
///
 | 
			
		||||
/// @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() {
 | 
			
		||||
        sol_log_64(0, 0, 0, i as u64, u64::from(*k));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Prints the hexadecimal representation of a slice
 | 
			
		||||
///
 | 
			
		||||
/// @param slice The array to print
 | 
			
		||||
#[allow(dead_code)]
 | 
			
		||||
pub fn sol_log_slice(slice: &[u8]) {
 | 
			
		||||
    for (i, s) in slice.iter().enumerate() {
 | 
			
		||||
        sol_log_64(0, 0, 0, i as u64, u64::from(*s));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Prints the hexadecimal representation of the program's input parameters
 | 
			
		||||
///
 | 
			
		||||
/// @param ka A pointer to an array of SolKeyedAccount to print
 | 
			
		||||
/// @param data A pointer to the instruction data to print
 | 
			
		||||
#[allow(dead_code)]
 | 
			
		||||
pub fn sol_log_params(ka: &[SolKeyedAccount], data: &[u8]) {
 | 
			
		||||
    sol_log("- Number of KeyedAccounts");
 | 
			
		||||
    sol_log_64(0, 0, 0, 0, ka.len() as u64);
 | 
			
		||||
    for k in ka.iter() {
 | 
			
		||||
        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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub const SIZE_PUBKEY: usize = 32;
 | 
			
		||||
 | 
			
		||||
/// Public key
 | 
			
		||||
pub struct SolPubkey<'a> {
 | 
			
		||||
    pub key: &'a [u8],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Keyed Account
 | 
			
		||||
pub struct SolKeyedAccount<'a> {
 | 
			
		||||
    /// Public key of the account
 | 
			
		||||
    pub key: SolPubkey<'a>,
 | 
			
		||||
    /// Public key of the account
 | 
			
		||||
    pub is_signer: u64,
 | 
			
		||||
    /// Number of lamports owned by this account
 | 
			
		||||
    pub lamports: u64,
 | 
			
		||||
    /// On-chain data within this account
 | 
			
		||||
    pub data: &'a [u8],
 | 
			
		||||
    /// Program that owns this account
 | 
			
		||||
    pub owner: SolPubkey<'a>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// 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>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[no_mangle]
 | 
			
		||||
pub extern "C" fn entrypoint(input: *mut u8) -> bool {
 | 
			
		||||
    const NUM_KA: usize = 1; // Number of KeyedAccounts expected
 | 
			
		||||
    let mut offset: usize = 0;
 | 
			
		||||
 | 
			
		||||
    // Number of KeyedAccounts present
 | 
			
		||||
 | 
			
		||||
    let num_ka = unsafe {
 | 
			
		||||
        #[allow(clippy::cast_ptr_alignment)]
 | 
			
		||||
        let num_ka_ptr: *const u64 = input.add(offset) as *const u64;
 | 
			
		||||
        *num_ka_ptr
 | 
			
		||||
    };
 | 
			
		||||
    offset += 8;
 | 
			
		||||
 | 
			
		||||
    if num_ka != NUM_KA as u64 {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // KeyedAccounts
 | 
			
		||||
 | 
			
		||||
    let is_signer = unsafe {
 | 
			
		||||
        #[allow(clippy::cast_ptr_alignment)]
 | 
			
		||||
        let is_signer_ptr: *const u64 = input.add(offset) as *const u64;
 | 
			
		||||
        *is_signer_ptr
 | 
			
		||||
    };
 | 
			
		||||
    offset += size_of::<u64>();
 | 
			
		||||
 | 
			
		||||
    let key_slice = unsafe { from_raw_parts(input.add(offset), SIZE_PUBKEY) };
 | 
			
		||||
    let key = SolPubkey { key: &key_slice };
 | 
			
		||||
    offset += SIZE_PUBKEY;
 | 
			
		||||
 | 
			
		||||
    let lamports = unsafe {
 | 
			
		||||
        #[allow(clippy::cast_ptr_alignment)]
 | 
			
		||||
        let lamports_ptr: *const u64 = input.add(offset) as *const u64;
 | 
			
		||||
        *lamports_ptr
 | 
			
		||||
    };
 | 
			
		||||
    offset += size_of::<u64>();
 | 
			
		||||
 | 
			
		||||
    let data_length = unsafe {
 | 
			
		||||
        #[allow(clippy::cast_ptr_alignment)]
 | 
			
		||||
        let data_length_ptr: *const u64 = input.add(offset) as *const u64;
 | 
			
		||||
        *data_length_ptr
 | 
			
		||||
    } as usize;
 | 
			
		||||
    offset += size_of::<u64>();
 | 
			
		||||
 | 
			
		||||
    let data = unsafe { from_raw_parts(input.add(offset), data_length) };
 | 
			
		||||
    offset += data_length;
 | 
			
		||||
 | 
			
		||||
    let owner_slice = unsafe { from_raw_parts(input.add(offset), SIZE_PUBKEY) };
 | 
			
		||||
    let owner = SolPubkey { key: &owner_slice };
 | 
			
		||||
    offset += SIZE_PUBKEY;
 | 
			
		||||
 | 
			
		||||
    let mut ka = [SolKeyedAccount {
 | 
			
		||||
        key,
 | 
			
		||||
        is_signer,
 | 
			
		||||
        lamports,
 | 
			
		||||
        data,
 | 
			
		||||
        owner,
 | 
			
		||||
    }];
 | 
			
		||||
 | 
			
		||||
    // Instruction data
 | 
			
		||||
 | 
			
		||||
    let data_length = unsafe {
 | 
			
		||||
        #[allow(clippy::cast_ptr_alignment)]
 | 
			
		||||
        let data_length_ptr: *const u64 = input.add(offset) as *const u64;
 | 
			
		||||
        *data_length_ptr
 | 
			
		||||
    } as usize;
 | 
			
		||||
    offset += size_of::<u64>();
 | 
			
		||||
 | 
			
		||||
    let data = unsafe { from_raw_parts(input.add(offset), data_length) };
 | 
			
		||||
    offset += data_length;
 | 
			
		||||
 | 
			
		||||
    // Id
 | 
			
		||||
 | 
			
		||||
    let program_id_slice = unsafe { from_raw_parts(input.add(offset), SIZE_PUBKEY) };
 | 
			
		||||
    let program_id: SolPubkey = SolPubkey {
 | 
			
		||||
        key: &program_id_slice,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let info = SolClusterInfo {
 | 
			
		||||
        program_id,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Call user implementable function
 | 
			
		||||
    process(&mut ka, &data, &info)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    extern crate std;
 | 
			
		||||
 | 
			
		||||
    use self::std::ffi::CStr;
 | 
			
		||||
    use self::std::println;
 | 
			
		||||
    use self::std::string::String;
 | 
			
		||||
    use super::*;
 | 
			
		||||
 | 
			
		||||
    static mut _LOG_SCENARIO: u64 = 0;
 | 
			
		||||
    fn get_log_scenario() -> u64 {
 | 
			
		||||
        unsafe { _LOG_SCENARIO }
 | 
			
		||||
    }
 | 
			
		||||
    fn set_log_scenario(test: u64) {
 | 
			
		||||
        unsafe { _LOG_SCENARIO = test };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    fn sol_log_(message: *const u8) {
 | 
			
		||||
        let scenario = get_log_scenario();
 | 
			
		||||
        let c_str = unsafe { CStr::from_ptr(message as *const i8) };
 | 
			
		||||
        let string = c_str.to_str().unwrap();
 | 
			
		||||
        match scenario {
 | 
			
		||||
            1 => assert_eq!(string, "This is a test message"),
 | 
			
		||||
            2 => assert_eq!(string, "Attempted to log a string that is too long"),
 | 
			
		||||
            3 => {
 | 
			
		||||
                let s: String = ['a'; 255].iter().collect();
 | 
			
		||||
                assert_eq!(string, s);
 | 
			
		||||
            }
 | 
			
		||||
            4 => println!("{:?}", string),
 | 
			
		||||
            _ => panic!("Unkown sol_log test"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static mut _LOG_64_SCENARIO: u64 = 0;
 | 
			
		||||
    fn get_log_64_scenario() -> u64 {
 | 
			
		||||
        unsafe { _LOG_64_SCENARIO }
 | 
			
		||||
    }
 | 
			
		||||
    fn set_log_64_scenario(test: u64) {
 | 
			
		||||
        unsafe { _LOG_64_SCENARIO = test };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    fn sol_log_64_(arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) {
 | 
			
		||||
        let scenario = get_log_64_scenario();
 | 
			
		||||
        match scenario {
 | 
			
		||||
            1 => {
 | 
			
		||||
                assert_eq!(1, arg1);
 | 
			
		||||
                assert_eq!(2, arg2);
 | 
			
		||||
                assert_eq!(3, arg3);
 | 
			
		||||
                assert_eq!(4, arg4);
 | 
			
		||||
                assert_eq!(5, arg5);
 | 
			
		||||
            }
 | 
			
		||||
            2 => {
 | 
			
		||||
                assert_eq!(0, arg1);
 | 
			
		||||
                assert_eq!(0, arg2);
 | 
			
		||||
                assert_eq!(0, arg3);
 | 
			
		||||
                assert_eq!(arg4 + 1, arg5);
 | 
			
		||||
            }
 | 
			
		||||
            3 => {
 | 
			
		||||
                assert_eq!(0, arg1);
 | 
			
		||||
                assert_eq!(0, arg2);
 | 
			
		||||
                assert_eq!(0, arg3);
 | 
			
		||||
                assert_eq!(arg4 + 1, arg5);
 | 
			
		||||
            }
 | 
			
		||||
            4 => println!("{:?} {:?} {:?} {:?} {:?}", arg1, arg2, arg3, arg4, arg5),
 | 
			
		||||
            _ => panic!("Unknown sol_log_64 test"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_sol_log() {
 | 
			
		||||
        set_log_scenario(1);
 | 
			
		||||
        sol_log("This is a test message");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_sol_log_long() {
 | 
			
		||||
        set_log_scenario(2);
 | 
			
		||||
        let s: String = ['a'; 256].iter().collect();
 | 
			
		||||
        sol_log(&s);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_sol_log_max_length() {
 | 
			
		||||
        set_log_scenario(3);
 | 
			
		||||
        let s: String = ['a'; 255].iter().collect();
 | 
			
		||||
        sol_log(&s);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_sol_log_64() {
 | 
			
		||||
        set_log_64_scenario(1);
 | 
			
		||||
        sol_log_64(1, 2, 3, 4, 5);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_sol_log_key() {
 | 
			
		||||
        set_log_64_scenario(2);
 | 
			
		||||
        let key_array = [
 | 
			
		||||
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
 | 
			
		||||
            25, 26, 27, 28, 29, 30, 31, 32,
 | 
			
		||||
        ];
 | 
			
		||||
        let key = SolPubkey { key: &key_array };
 | 
			
		||||
        sol_log_key(&key);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_sol_log_slice() {
 | 
			
		||||
        set_log_64_scenario(3);
 | 
			
		||||
        let array = [
 | 
			
		||||
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
 | 
			
		||||
            25, 26, 27, 28, 29, 30, 31, 32,
 | 
			
		||||
        ];
 | 
			
		||||
        sol_log_slice(&array);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn process(ka: &mut [SolKeyedAccount], data: &[u8], info: &SolClusterInfo) -> bool {
 | 
			
		||||
        assert_eq!(1, ka.len());
 | 
			
		||||
        assert_eq!(1, ka[0].is_signer);
 | 
			
		||||
        let key = [
 | 
			
		||||
            151, 116, 3, 85, 181, 39, 151, 99, 155, 29, 208, 191, 255, 191, 11, 161, 4, 43, 104,
 | 
			
		||||
            189, 202, 240, 231, 111, 146, 255, 199, 71, 67, 34, 254, 68,
 | 
			
		||||
        ];
 | 
			
		||||
        assert_eq!(SIZE_PUBKEY, ka[0].key.key.len());
 | 
			
		||||
        assert_eq!(key, ka[0].key.key);
 | 
			
		||||
        assert_eq!(48, ka[0].lamports);
 | 
			
		||||
        assert_eq!(1, ka[0].data.len());
 | 
			
		||||
        let owner = [0; 32];
 | 
			
		||||
        assert_eq!(SIZE_PUBKEY, ka[0].owner.key.len());
 | 
			
		||||
        assert_eq!(owner, ka[0].owner.key);
 | 
			
		||||
        let d = [1, 0, 0, 0, 0, 0, 0, 0, 1];
 | 
			
		||||
        assert_eq!(9, data.len());
 | 
			
		||||
        assert_eq!(d, data);
 | 
			
		||||
        let program_id = [
 | 
			
		||||
            190, 103, 191, 69, 193, 202, 38, 193, 95, 62, 131, 135, 105, 13, 142, 240, 155, 120,
 | 
			
		||||
            177, 90, 212, 54, 10, 118, 40, 33, 192, 8, 54, 141, 187, 63,
 | 
			
		||||
        ];
 | 
			
		||||
        assert_eq!(program_id, info.program_id.key);
 | 
			
		||||
 | 
			
		||||
        true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_entrypoint() {
 | 
			
		||||
        set_log_scenario(4);
 | 
			
		||||
        set_log_64_scenario(4);
 | 
			
		||||
        let mut input: [u8; 154] = [
 | 
			
		||||
            1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 151, 116, 3, 85, 181, 39, 151, 99, 155,
 | 
			
		||||
            29, 208, 191, 255, 191, 11, 161, 4, 43, 104, 189, 202, 240, 231, 111, 146, 255, 199,
 | 
			
		||||
            71, 67, 34, 254, 68, 48, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0,
 | 
			
		||||
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
 | 
			
		||||
            0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 190, 103, 191,
 | 
			
		||||
            69, 193, 202, 38, 193, 95, 62, 131, 135, 105, 13, 142, 240, 155, 120, 177, 90, 212, 54,
 | 
			
		||||
            10, 118, 40, 33, 192, 8, 54, 141, 187, 63,
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        entrypoint(&mut input[0] as *mut u8);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user