Add support for idiomatic error handling to BPF instruction processors (#7968)

This commit is contained in:
Jack May
2020-01-30 09:47:22 -08:00
committed by GitHub
parent 0c55b37976
commit dd276138c2
25 changed files with 515 additions and 108 deletions

View File

@ -0,0 +1,29 @@
# Note: This crate must be built using do.sh
[package]
name = "solana-bpf-rust-error-handling"
version = "0.24.0"
description = "Solana BPF test 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]
num-derive = "0.2"
num-traits = "0.2"
solana-sdk = { path = "../../../../sdk/", version = "0.24.0", default-features = false }
thiserror = "1.0"
[dev_dependencies]
solana-sdk-bpf-test = { path = "../../../../sdk/bpf/rust/test", version = "0.24.0" }
[features]
program = ["solana-sdk/program"]
default = ["program"]
[lib]
name = "solana_bpf_rust_error_handling"
crate-type = ["cdylib"]

View File

@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []

View File

@ -0,0 +1,60 @@
//! @brief Example Rust-based BPF program that exercises error handling
extern crate solana_sdk;
use num_derive::FromPrimitive;
use solana_sdk::{
account_info::AccountInfo, entrypoint, info, program_error::ProgramError, pubkey::Pubkey,
};
use thiserror::Error;
/// Custom program errors
#[derive(Error, Debug, Clone, PartialEq, FromPrimitive)]
// Clippy compains about 0x8000_002d, but we don't care about C compatibility here
#[allow(clippy::enum_clike_unportable_variant)]
pub enum MyError {
#[error("The Answer")]
TheAnswer = 42,
#[error("Conflicting with success")]
ConflictingSuccess = 0,
#[error("Conflicting with builtin")]
ConflictingBuiltin = 0x8000_002d,
}
impl From<MyError> for ProgramError {
fn from(e: MyError) -> Self {
ProgramError::CustomError(e as u32)
}
}
entrypoint!(process_instruction);
fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
instruction_data: &[u8],
) -> Result<(), ProgramError> {
match instruction_data[0] {
1 => {
info!("return success");
Ok(())
}
2 => {
info!("return a builtin");
Err(ProgramError::AccountBorrowFailed)
}
3 => {
info!("return custom error");
Err(MyError::TheAnswer.into())
}
4 => {
info!("return error that conflicts with success");
Err(MyError::ConflictingSuccess.into())
}
5 => {
info!("return error that conflicts with builtin");
Err(MyError::ConflictingBuiltin.into())
}
_ => {
info!("Unrecognized command");
Err(ProgramError::InvalidInstructionData)
}
}
}