Add Cross-program invocations (#9582)

This commit is contained in:
Jack May
2020-04-28 14:33:56 -07:00
committed by GitHub
parent 063f616a19
commit 068f12fd6f
27 changed files with 2164 additions and 208 deletions

View File

@ -1,6 +1,10 @@
//! @brief Solana Native program entry point
use crate::{account::KeyedAccount, instruction::InstructionError, pubkey::Pubkey};
use crate::{
account::Account, account::KeyedAccount, instruction::CompiledInstruction,
instruction::InstructionError, message::Message, pubkey::Pubkey,
};
use std::{cell::RefCell, rc::Rc};
// Prototype of a native program entry point
///
@ -23,6 +27,7 @@ pub type LoaderEntrypoint = unsafe extern "C" fn(
program_id: &Pubkey,
keyed_accounts: &[KeyedAccount],
instruction_data: &[u8],
invoke_context: &dyn InvokeContext,
) -> Result<(), InstructionError>;
/// Convenience macro to declare a native program
@ -134,8 +139,22 @@ macro_rules! declare_loader(
program_id: &$crate::pubkey::Pubkey,
keyed_accounts: &[$crate::account::KeyedAccount],
instruction_data: &[u8],
invoke_context: &mut dyn $crate::entrypoint_native::InvokeContext,
) -> Result<(), $crate::instruction::InstructionError> {
$entrypoint(program_id, keyed_accounts, instruction_data)
$entrypoint(program_id, keyed_accounts, instruction_data, invoke_context)
}
)
);
/// Cross-program invocation context passed to loaders
pub trait InvokeContext {
fn push(&mut self, key: &Pubkey) -> Result<(), InstructionError>;
fn pop(&mut self);
fn verify_and_update(
&mut self,
message: &Message,
instruction: &CompiledInstruction,
signers: &[Pubkey],
accounts: &[Rc<RefCell<Account>>],
) -> Result<(), InstructionError>;
}

View File

@ -87,7 +87,7 @@ pub enum InstructionError {
RentEpochModified,
/// The instruction expected additional account keys
#[error("insufficient account key count for instruction")]
#[error("insufficient account keys for instruction")]
NotEnoughAccountKeys,
/// A non-system program changed the size of the account data
@ -138,6 +138,26 @@ pub enum InstructionError {
/// Unsupported program id
#[error("Unsupported program id")]
UnsupportedProgramId,
/// Writable bit on account info changed, but shouldn't have
#[error("Writable bit on account info changed, but shouldn't have")]
WritableModified,
/// Signer bit on account info changed, but shouldn't have
#[error("Signer bit on account info changed, but shouldn't have")]
SignerModified,
/// Cross-program invocation call depth too deep
#[error("Cross-program invocation call depth too deep")]
CallDepth,
/// An account required by the instruction is missing
#[error("An account required by the instruction is missing")]
MissingAccount,
/// Cross-program invocation reentrancy not allowed for this instruction
#[error("Cross-program invocation reentrancy not allowed for this instruction")]
ReentrancyNotAllowed,
}
impl InstructionError {

View File

@ -61,6 +61,7 @@ pub use solana_sdk_macro::declare_id;
pub mod account_info;
pub mod entrypoint;
pub mod log;
pub mod program;
pub mod program_error;
// Modules not usable by on-chain programs

42
sdk/src/program.rs Normal file
View File

@ -0,0 +1,42 @@
#![cfg(feature = "program")]
use crate::{
account_info::AccountInfo, entrypoint::ProgramResult, entrypoint::SUCCESS,
instruction::Instruction,
};
/// Invoke a cross-program instruction
pub fn invoke(instruction: &Instruction, account_infos: &[AccountInfo]) -> ProgramResult {
invoke_signed(instruction, account_infos, &[])
}
/// Invoke a cross-program instruction with program signatures
pub fn invoke_signed(
instruction: &Instruction,
account_infos: &[AccountInfo],
signers_seeds: &[&[&str]],
) -> ProgramResult {
let result = unsafe {
sol_invoke_signed_rust(
instruction as *const _ as *const u8,
account_infos as *const _ as *const u8,
account_infos.len() as u64,
signers_seeds as *const _ as *const u8,
signers_seeds.len() as u64,
)
};
match result {
SUCCESS => Ok(()),
_ => Err(result.into()),
}
}
extern "C" {
fn sol_invoke_signed_rust(
instruction_addr: *const u8,
account_infos_addr: *const u8,
account_infos_len: u64,
signers_seeds_addr: *const u8,
signers_seeds_len: u64,
) -> u64;
}