Add support for BPF program custom errors (#5743)
* Add support for BPF program custom errors * Rename SOL_SUCCESS -> SUCCESS
This commit is contained in:
parent
d3052d094c
commit
81c36699c4
|
@ -80,7 +80,7 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||||
|
|
||||||
println!("Interpreted:");
|
println!("Interpreted:");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
1, /*true*/
|
0, /*success*/
|
||||||
vm.execute_program(&mut inner_iter, &[], &[]).unwrap()
|
vm.execute_program(&mut inner_iter, &[], &[]).unwrap()
|
||||||
);
|
);
|
||||||
assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter));
|
assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter));
|
||||||
|
@ -106,7 +106,7 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||||
// vm.jit_compile().unwrap();
|
// vm.jit_compile().unwrap();
|
||||||
// unsafe {
|
// unsafe {
|
||||||
// assert_eq!(
|
// assert_eq!(
|
||||||
// 1, /*true*/
|
// 0, /*success*/
|
||||||
// vm.execute_program_jit(&mut inner_iter).unwrap()
|
// vm.execute_program_jit(&mut inner_iter).unwrap()
|
||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include <solana_sdk.h>
|
#include <solana_sdk.h>
|
||||||
|
|
||||||
extern bool entrypoint(const uint8_t *input) {
|
extern uint32_t entrypoint(const uint8_t *input) {
|
||||||
uint64_t x = *(uint64_t *) input;
|
uint64_t x = *(uint64_t *) input;
|
||||||
uint64_t *result = (uint64_t *) input + 1;
|
uint64_t *result = (uint64_t *) input + 1;
|
||||||
uint64_t count = 0;
|
uint64_t count = 0;
|
||||||
|
@ -26,5 +26,5 @@ extern bool entrypoint(const uint8_t *input) {
|
||||||
|
|
||||||
// sol_log_64(x, count, 0, 0, 0);
|
// sol_log_64(x, count, 0, 0, 0);
|
||||||
*result = count;
|
*result = count;
|
||||||
return true;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
Test(bench_alu, sanity) {
|
Test(bench_alu, sanity) {
|
||||||
uint64_t input[] = {500, 0};
|
uint64_t input[] = {500, 0};
|
||||||
|
|
||||||
cr_assert(entrypoint((uint8_t *) input));
|
cr_assert_eq(entrypoint((uint8_t *) input), 0);
|
||||||
|
|
||||||
cr_assert_eq(input[0], 500);
|
cr_assert_eq(input[0], 500);
|
||||||
cr_assert_eq(input[1], 5);
|
cr_assert_eq(input[1], 5);
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
|
|
||||||
#include "helper.h"
|
#include "helper.h"
|
||||||
|
|
||||||
extern bool entrypoint(const uint8_t *input) {
|
extern uint32_t entrypoint(const uint8_t *input) {
|
||||||
sol_log(__FILE__);
|
sol_log(__FILE__);
|
||||||
helper_function();
|
helper_function();
|
||||||
sol_log(__FILE__);
|
sol_log(__FILE__);
|
||||||
return true;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,17 +11,27 @@
|
||||||
*/
|
*/
|
||||||
#define NUM_KA 3
|
#define NUM_KA 3
|
||||||
|
|
||||||
extern bool entrypoint(const uint8_t *input) {
|
/**
|
||||||
|
* Custom error for when input serialization fails
|
||||||
|
*/
|
||||||
|
#define INVALID_INPUT 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom error for when transaction is not signed properly
|
||||||
|
*/
|
||||||
|
#define NOT_SIGNED 2
|
||||||
|
|
||||||
|
extern uint32_t entrypoint(const uint8_t *input) {
|
||||||
SolKeyedAccount ka[NUM_KA];
|
SolKeyedAccount ka[NUM_KA];
|
||||||
SolParameters params = (SolParameters) { .ka = ka };
|
SolParameters params = (SolParameters) { .ka = ka };
|
||||||
|
|
||||||
if (!sol_deserialize(input, ¶ms, SOL_ARRAY_SIZE(ka))) {
|
if (!sol_deserialize(input, ¶ms, SOL_ARRAY_SIZE(ka))) {
|
||||||
return false;
|
return INVALID_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!params.ka[0].is_signer) {
|
if (!params.ka[0].is_signer) {
|
||||||
sol_log("Transaction not signed by key 0");
|
sol_log("Transaction not signed by key 0");
|
||||||
return false;
|
return NOT_SIGNED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t lamports = *(int64_t *)params.data;
|
int64_t lamports = *(int64_t *)params.data;
|
||||||
|
@ -32,5 +42,5 @@ extern bool entrypoint(const uint8_t *input) {
|
||||||
} else {
|
} else {
|
||||||
// sol_log_64(0, 0, 0xFF, *ka[0].lamports, lamports);
|
// sol_log_64(0, 0, 0xFF, *ka[0].lamports, lamports);
|
||||||
}
|
}
|
||||||
return true;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
static const char msg[] = "This is a message";
|
static const char msg[] = "This is a message";
|
||||||
static const char msg2[] = "This is a different message";
|
static const char msg2[] = "This is a different message";
|
||||||
|
|
||||||
extern bool entrypoint(const uint8_t *input) {
|
extern uint32_t entrypoint(const uint8_t *input) {
|
||||||
sol_log((char*)msg);
|
sol_log((char*)msg);
|
||||||
sol_log((char*)msg2);
|
sol_log((char*)msg2);
|
||||||
return true;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,24 @@
|
||||||
*/
|
*/
|
||||||
#include <solana_sdk.h>
|
#include <solana_sdk.h>
|
||||||
|
|
||||||
extern bool entrypoint(const uint8_t *input) {
|
/**
|
||||||
|
* Custom error for when input serialization fails
|
||||||
|
*/
|
||||||
|
#define INVALID_INPUT 1
|
||||||
|
|
||||||
|
extern uint32_t entrypoint(const uint8_t *input) {
|
||||||
SolKeyedAccount ka[1];
|
SolKeyedAccount ka[1];
|
||||||
SolParameters params = (SolParameters) { .ka = ka };
|
SolParameters params = (SolParameters) { .ka = ka };
|
||||||
|
|
||||||
sol_log(__FILE__);
|
sol_log(__FILE__);
|
||||||
|
|
||||||
if (!sol_deserialize(input, ¶ms, SOL_ARRAY_SIZE(ka))) {
|
if (!sol_deserialize(input, ¶ms, SOL_ARRAY_SIZE(ka))) {
|
||||||
return false;
|
return INVALID_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log the provided input parameters. In the case of the no-op
|
// Log the provided input parameters. In the case of the no-op
|
||||||
// program, no account keys or input data are expected but real
|
// program, no account keys or input data are expected but real
|
||||||
// programs will have specific requirements so they can do their work.
|
// programs will have specific requirements so they can do their work.
|
||||||
sol_log_params(¶ms);
|
sol_log_params(¶ms);
|
||||||
return true;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,20 +4,24 @@
|
||||||
*/
|
*/
|
||||||
#include <solana_sdk.h>
|
#include <solana_sdk.h>
|
||||||
|
|
||||||
extern bool entrypoint(const uint8_t *input) {
|
/**
|
||||||
|
* Custom error for when input serialization fails
|
||||||
|
*/
|
||||||
|
#define INVALID_INPUT 1
|
||||||
|
|
||||||
|
extern uint32_t entrypoint(const uint8_t *input) {
|
||||||
SolKeyedAccount ka[1];
|
SolKeyedAccount ka[1];
|
||||||
SolParameters params = (SolParameters) { .ka = ka };
|
SolParameters params = (SolParameters) { .ka = ka };
|
||||||
|
|
||||||
sol_log(__FILE__);
|
sol_log(__FILE__);
|
||||||
|
|
||||||
if (!sol_deserialize(input, ¶ms, SOL_ARRAY_SIZE(ka))) {
|
if (!sol_deserialize(input, ¶ms, SOL_ARRAY_SIZE(ka))) {
|
||||||
return false;
|
return INVALID_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log the provided input parameters. In the case of the no-op
|
// Log the provided input parameters. In the case of the no-op
|
||||||
// program, no account keys or input data are expected but real
|
// program, no account keys or input data are expected but real
|
||||||
// programs will have specific requirements so they can do their work.
|
// programs will have specific requirements so they can do their work.
|
||||||
sol_log_params(¶ms);
|
sol_log_params(¶ms);
|
||||||
return true;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
*/
|
*/
|
||||||
#include <solana_sdk.h>
|
#include <solana_sdk.h>
|
||||||
|
|
||||||
extern bool entrypoint(const uint8_t *input) {
|
extern uint32_t entrypoint(const uint8_t *input) {
|
||||||
sol_panic();
|
sol_panic();
|
||||||
return true;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,8 @@ void __attribute__ ((noinline)) helper() {
|
||||||
sol_log(__func__);
|
sol_log(__func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern bool entrypoint(const uint8_t *input) {
|
extern uint32_t entrypoint(const uint8_t *input) {
|
||||||
sol_log(__func__);
|
sol_log(__func__);
|
||||||
helper();
|
helper();
|
||||||
return true;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,15 +3,14 @@
|
||||||
struct foo {const uint8_t *input;};
|
struct foo {const uint8_t *input;};
|
||||||
void foo(const uint8_t *input, struct foo foo) ;
|
void foo(const uint8_t *input, struct foo foo) ;
|
||||||
|
|
||||||
extern bool entrypoint(const uint8_t *input) {
|
extern uint32_t entrypoint(const uint8_t *input) {
|
||||||
struct foo f;
|
struct foo f;
|
||||||
f.input = input;
|
f.input = input;
|
||||||
foo(input, f);
|
foo(input, f);
|
||||||
return true;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void foo(const uint8_t *input, struct foo foo) {
|
void foo(const uint8_t *input, struct foo foo) {
|
||||||
sol_log_64(0, 0, 0, (uint64_t)input, (uint64_t)foo.input);
|
sol_log_64(0, 0, 0, (uint64_t)input, (uint64_t)foo.input);
|
||||||
sol_assert(input == foo.input);
|
sol_assert(input == foo.input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
#include <solana_sdk.h>
|
#include <solana_sdk.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom error for when struct doesn't add to 12
|
||||||
|
*/
|
||||||
|
#define INCORRECT_SUM 1
|
||||||
|
|
||||||
struct test_struct { uint64_t x; uint64_t y; uint64_t z;};
|
struct test_struct { uint64_t x; uint64_t y; uint64_t z;};
|
||||||
|
|
||||||
static struct test_struct __attribute__ ((noinline)) test_function(void) {
|
static struct test_struct __attribute__ ((noinline)) test_function(void) {
|
||||||
|
@ -10,12 +15,11 @@ static struct test_struct __attribute__ ((noinline)) test_function(void) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern bool entrypoint(const uint8_t* input) {
|
extern uint32_t entrypoint(const uint8_t* input) {
|
||||||
struct test_struct s = test_function();
|
struct test_struct s = test_function();
|
||||||
sol_log("foobar");
|
sol_log("foobar");
|
||||||
if (s.x + s.y + s.z == 12 ) {
|
if (s.x + s.y + s.z == 12 ) {
|
||||||
return true;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
return false;
|
return INCORRECT_SUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
//! @brief Example Rust-based BPF program tests loop iteration
|
//! @brief Example Rust-based BPF program tests loop iteration
|
||||||
|
|
||||||
extern crate solana_sdk;
|
extern crate solana_sdk;
|
||||||
|
use solana_sdk::entrypoint::SUCCESS;
|
||||||
use solana_sdk::info;
|
use solana_sdk::info;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
|
pub extern "C" fn entrypoint(_input: *mut u8) -> u32 {
|
||||||
let x: u128 = 1;
|
let x: u128 = 1;
|
||||||
let y = x.rotate_right(1);
|
let y = x.rotate_right(1);
|
||||||
assert_eq!(y, 170_141_183_460_469_231_731_687_303_715_884_105_728);
|
assert_eq!(y, 170_141_183_460_469_231_731_687_303_715_884_105_728);
|
||||||
|
@ -48,5 +49,5 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
|
||||||
assert_eq!(x, 0x0001_ffff_ffff_ffff_fffe);
|
assert_eq!(x, 0x0001_ffff_ffff_ffff_fffe);
|
||||||
|
|
||||||
info!("Success");
|
info!("Success");
|
||||||
true
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate solana_sdk;
|
extern crate solana_sdk;
|
||||||
|
use solana_sdk::entrypoint::SUCCESS;
|
||||||
use solana_sdk::info;
|
use solana_sdk::info;
|
||||||
use std::alloc::Layout;
|
use std::alloc::Layout;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
|
pub extern "C" fn entrypoint(_input: *mut u8) -> u32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Confirm large allocation fails
|
// Confirm large allocation fails
|
||||||
|
|
||||||
|
@ -100,5 +101,5 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Success");
|
info!("Success");
|
||||||
true
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
extern crate solana_sdk;
|
extern crate solana_sdk;
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
|
use solana_sdk::entrypoint::SUCCESS;
|
||||||
use solana_sdk::info;
|
use solana_sdk::info;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
|
pub extern "C" fn entrypoint(_input: *mut u8) -> u32 {
|
||||||
let mut buf = [0; 4];
|
let mut buf = [0; 4];
|
||||||
LittleEndian::write_u32(&mut buf, 1_000_000);
|
LittleEndian::write_u32(&mut buf, 1_000_000);
|
||||||
assert_eq!(1_000_000, LittleEndian::read_u32(&buf));
|
assert_eq!(1_000_000, LittleEndian::read_u32(&buf));
|
||||||
|
@ -15,5 +16,5 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
|
||||||
assert_eq!(-5_000, LittleEndian::read_i16(&buf));
|
assert_eq!(-5_000, LittleEndian::read_i16(&buf));
|
||||||
|
|
||||||
info!("Success");
|
info!("Success");
|
||||||
true
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,10 @@ use solana_sdk::entrypoint::*;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
|
||||||
entrypoint!(process_instruction);
|
entrypoint!(process_instruction);
|
||||||
fn process_instruction(_program_id: &Pubkey, ka: &mut [SolKeyedAccount], _data: &[u8]) -> bool {
|
fn process_instruction(_program_id: &Pubkey, ka: &mut [SolKeyedAccount], _data: &[u8]) -> u32 {
|
||||||
// account 0 is the mint and not owned by this program, any debit of its lamports
|
// account 0 is the mint and not owned by this program, any debit of its lamports
|
||||||
// should result in a failed program execution. Test to ensure that this debit
|
// should result in a failed program execution. Test to ensure that this debit
|
||||||
// is seen by the runtime and fails as expected
|
// is seen by the runtime and fails as expected
|
||||||
*ka[0].lamports -= 1;
|
*ka[0].lamports -= 1;
|
||||||
|
SUCCESS
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
//! @brief Example Rust-based BPF program tests loop iteration
|
//! @brief Example Rust-based BPF program tests loop iteration
|
||||||
|
|
||||||
extern crate solana_sdk;
|
extern crate solana_sdk;
|
||||||
|
use solana_sdk::entrypoint::SUCCESS;
|
||||||
use solana_sdk::info;
|
use solana_sdk::info;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
|
pub extern "C" fn entrypoint(_input: *mut u8) -> u32 {
|
||||||
const ITERS: usize = 100;
|
const ITERS: usize = 100;
|
||||||
let ones = [1_u64; ITERS];
|
let ones = [1_u64; ITERS];
|
||||||
let mut sum: u64 = 0;
|
let mut sum: u64 = 0;
|
||||||
|
@ -16,5 +17,5 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
|
||||||
assert_eq!(sum, ITERS as u64);
|
assert_eq!(sum, ITERS as u64);
|
||||||
|
|
||||||
info!("Success");
|
info!("Success");
|
||||||
true
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
mod helper;
|
mod helper;
|
||||||
extern crate solana_sdk;
|
extern crate solana_sdk;
|
||||||
|
use solana_sdk::entrypoint::SUCCESS;
|
||||||
use solana_sdk::info;
|
use solana_sdk::info;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
|
pub extern "C" fn entrypoint(_input: *mut u8) -> u32 {
|
||||||
info!("Call same package");
|
info!("Call same package");
|
||||||
assert_eq!(crate::helper::many_args(1, 2, 3, 4, 5, 6, 7, 8, 9), 45);
|
assert_eq!(crate::helper::many_args(1, 2, 3, 4, 5, 6, 7, 8, 9), 45);
|
||||||
|
|
||||||
|
@ -24,5 +25,5 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
|
||||||
);
|
);
|
||||||
|
|
||||||
info!("Success");
|
info!("Success");
|
||||||
true
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ fn return_sstruct() -> SStruct {
|
||||||
}
|
}
|
||||||
|
|
||||||
entrypoint!(process_instruction);
|
entrypoint!(process_instruction);
|
||||||
fn process_instruction(program_id: &Pubkey, ka: &mut [SolKeyedAccount], data: &[u8]) -> bool {
|
fn process_instruction(program_id: &Pubkey, ka: &mut [SolKeyedAccount], data: &[u8]) -> u32 {
|
||||||
info!("Program identifier:");
|
info!("Program identifier:");
|
||||||
program_id.log();
|
program_id.log();
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ fn process_instruction(program_id: &Pubkey, ka: &mut [SolKeyedAccount], data: &[
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Success");
|
info!("Success");
|
||||||
true
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
extern crate solana_sdk;
|
extern crate solana_sdk;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
|
pub extern "C" fn entrypoint(_input: *mut u8) -> u32 {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
extern crate solana_sdk;
|
extern crate solana_sdk;
|
||||||
use solana_bpf_rust_param_passing_dep::{Data, TestDep};
|
use solana_bpf_rust_param_passing_dep::{Data, TestDep};
|
||||||
|
use solana_sdk::entrypoint::SUCCESS;
|
||||||
use solana_sdk::info;
|
use solana_sdk::info;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
|
pub extern "C" fn entrypoint(_input: *mut u8) -> u32 {
|
||||||
let array = [0xA, 0xB, 0xC, 0xD, 0xE, 0xF];
|
let array = [0xA, 0xB, 0xC, 0xD, 0xE, 0xF];
|
||||||
let data = Data {
|
let data = Data {
|
||||||
twentyone: 21u64,
|
twentyone: 21u64,
|
||||||
|
@ -18,5 +19,6 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
|
||||||
|
|
||||||
let test_dep = TestDep::new(&data, 1, 2, 3, 4, 5);
|
let test_dep = TestDep::new(&data, 1, 2, 3, 4, 5);
|
||||||
info!(0, 0, 0, 0, test_dep.thirty);
|
info!(0, 0, 0, 0, test_dep.thirty);
|
||||||
test_dep.thirty == 30
|
assert!(test_dep.thirty == 30);
|
||||||
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,10 @@ use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::{entrypoint, info};
|
use solana_sdk::{entrypoint, info};
|
||||||
|
|
||||||
entrypoint!(process_instruction);
|
entrypoint!(process_instruction);
|
||||||
fn process_instruction(_program_id: &Pubkey, ka: &mut [SolKeyedAccount], _data: &[u8]) -> bool {
|
fn process_instruction(_program_id: &Pubkey, ka: &mut [SolKeyedAccount], _data: &[u8]) -> u32 {
|
||||||
let tick_height = LittleEndian::read_u64(ka[2].data);
|
let tick_height = LittleEndian::read_u64(ka[2].data);
|
||||||
assert_eq!(10u64, tick_height);
|
assert_eq!(10u64, tick_height);
|
||||||
|
|
||||||
info!("Success");
|
info!("Success");
|
||||||
true
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ use solana_sdk::account::KeyedAccount;
|
||||||
use solana_sdk::instruction::InstructionError;
|
use solana_sdk::instruction::InstructionError;
|
||||||
use solana_sdk::loader_instruction::LoaderInstruction;
|
use solana_sdk::loader_instruction::LoaderInstruction;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -136,12 +137,18 @@ pub fn process_instruction(
|
||||||
let mut v = serialize_parameters(program_id, params, &data);
|
let mut v = serialize_parameters(program_id, params, &data);
|
||||||
|
|
||||||
match vm.execute_program(v.as_mut_slice(), &[], &[heap_region]) {
|
match vm.execute_program(v.as_mut_slice(), &[], &[heap_region]) {
|
||||||
|
Ok(status) => match u32::try_from(status) {
|
||||||
Ok(status) => {
|
Ok(status) => {
|
||||||
if 0 == status {
|
if status > 0 {
|
||||||
warn!("BPF program failed: {}", status);
|
warn!("BPF program failed: {}", status);
|
||||||
|
return Err(InstructionError::CustomError(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
warn!("BPF VM encountered invalid status: {}", e);
|
||||||
return Err(InstructionError::GenericError);
|
return Err(InstructionError::GenericError);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("BPF VM failed to run program: {}", e);
|
warn!("BPF VM failed to run program: {}", e);
|
||||||
return Err(InstructionError::GenericError);
|
return Err(InstructionError::GenericError);
|
||||||
|
|
|
@ -51,6 +51,11 @@ static_assert(sizeof(uint64_t) == 8);
|
||||||
*/
|
*/
|
||||||
#define NULL 0
|
#define NULL 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SUCCESS return value
|
||||||
|
*/
|
||||||
|
#define SUCCESS 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boolean type
|
* Boolean type
|
||||||
*/
|
*/
|
||||||
|
@ -319,9 +324,9 @@ SOL_FN_PREFIX void sol_log_params(const SolParameters *params) {
|
||||||
* Program instruction entrypoint
|
* Program instruction entrypoint
|
||||||
*
|
*
|
||||||
* @param input Buffer of serialized input parameters. Use sol_deserialize() to decode
|
* @param input Buffer of serialized input parameters. Use sol_deserialize() to decode
|
||||||
* @return true if the instruction executed successfully
|
* @return 0 if the instruction executed successfully
|
||||||
*/
|
*/
|
||||||
bool entrypoint(const uint8_t *input);
|
uint32_t entrypoint(const uint8_t *input);
|
||||||
|
|
||||||
|
|
||||||
#ifdef SOL_TEST
|
#ifdef SOL_TEST
|
||||||
|
|
|
@ -28,6 +28,9 @@ pub struct SolKeyedAccount<'a> {
|
||||||
pub type ProcessInstruction =
|
pub type ProcessInstruction =
|
||||||
fn(program_id: &Pubkey, accounts: &mut [SolKeyedAccount], data: &[u8]) -> bool;
|
fn(program_id: &Pubkey, accounts: &mut [SolKeyedAccount], data: &[u8]) -> bool;
|
||||||
|
|
||||||
|
/// Programs indicate success with a return value of 0
|
||||||
|
pub const SUCCESS: u32 = 0;
|
||||||
|
|
||||||
/// Declare entrypoint of the program.
|
/// Declare entrypoint of the program.
|
||||||
///
|
///
|
||||||
/// Deserialize the program input parameters and call
|
/// Deserialize the program input parameters and call
|
||||||
|
@ -38,13 +41,10 @@ pub type ProcessInstruction =
|
||||||
macro_rules! entrypoint {
|
macro_rules! entrypoint {
|
||||||
($process_instruction:ident) => {
|
($process_instruction:ident) => {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn entrypoint(input: *mut u8) -> bool {
|
pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Ok((program_id, mut kas, data)) = $crate::entrypoint::deserialize(input) {
|
let (program_id, mut kas, data) = $crate::entrypoint::deserialize(input);
|
||||||
$process_instruction(&program_id, &mut kas, &data)
|
$process_instruction(&program_id, &mut kas, &data)
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -54,7 +54,7 @@ macro_rules! entrypoint {
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub unsafe fn deserialize<'a>(
|
pub unsafe fn deserialize<'a>(
|
||||||
input: *mut u8,
|
input: *mut u8,
|
||||||
) -> Result<(&'a Pubkey, Vec<SolKeyedAccount<'a>>, &'a [u8]), ()> {
|
) -> (&'a Pubkey, Vec<SolKeyedAccount<'a>>, &'a [u8]) {
|
||||||
let mut offset: usize = 0;
|
let mut offset: usize = 0;
|
||||||
|
|
||||||
// Number of KeyedAccounts present
|
// Number of KeyedAccounts present
|
||||||
|
@ -113,5 +113,5 @@ pub unsafe fn deserialize<'a>(
|
||||||
|
|
||||||
let program_id: &Pubkey = &*(input.add(offset) as *const Pubkey);
|
let program_id: &Pubkey = &*(input.add(offset) as *const Pubkey);
|
||||||
|
|
||||||
Ok((program_id, kas, data))
|
(program_id, kas, data)
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,9 @@ pub enum InstructionError {
|
||||||
/// CustomError allows on-chain programs to implement program-specific error types and see
|
/// CustomError allows on-chain programs to implement program-specific error types and see
|
||||||
/// them returned by the Solana runtime. A CustomError may be any type that is represented
|
/// them returned by the Solana runtime. A CustomError may be any type that is represented
|
||||||
/// as or serialized to a u32 integer.
|
/// as or serialized to a u32 integer.
|
||||||
|
///
|
||||||
|
/// NOTE: u64 requires special serialization to avoid the loss of precision in JS clients and
|
||||||
|
/// so is not used for now.
|
||||||
CustomError(u32),
|
CustomError(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue