Programs can only sign their accounts

This commit is contained in:
Jack May 2020-05-08 12:24:36 -07:00
parent b4b4d6b00d
commit 97e17f9b32
10 changed files with 187 additions and 100 deletions

View File

@ -1,22 +1,23 @@
/**
* @brief Example C-based BPF program that prints out the parameters
* passed to it
* @brief Example C-based BPF program that tests cross-program invocations
*/
#include "../invoked/instruction.h"
#include <solana_sdk.h>
#define MINT_INDEX 0
#define ARGUMENT_INDEX 1
#define INVOKED_PROGRAM_INDEX 2
#define INVOKED_ARGUMENT_INDEX 3
#define INVOKED_PROGRAM_DUP_INDEX 4
#define ARGUMENT_DUP_INDEX 5
#define DERIVED_KEY_INDEX 6
#define DERIVED_KEY2_INDEX 7
static const int MINT_INDEX = 0;
static const int ARGUMENT_INDEX = 1;
static const int INVOKED_PROGRAM_INDEX = 2;
static const int INVOKED_ARGUMENT_INDEX = 3;
static const int INVOKED_PROGRAM_DUP_INDEX = 4;
static const int ARGUMENT_DUP_INDEX = 5;
static const int DERIVED_KEY1_INDEX = 6;
static const int DERIVED_KEY2_INDEX = 7;
static const int DERIVED_KEY3_INDEX = 8;
extern uint64_t entrypoint(const uint8_t *input) {
sol_log("Invoke C program");
SolAccountInfo accounts[8];
SolAccountInfo accounts[9];
SolParameters params = (SolParameters){.ka = accounts};
if (!sol_deserialize(input, &params, SOL_ARRAY_SIZE(accounts))) {
@ -34,40 +35,45 @@ extern uint64_t entrypoint(const uint8_t *input) {
{accounts[INVOKED_ARGUMENT_INDEX].key, true, true},
{accounts[INVOKED_PROGRAM_INDEX].key, false, false},
{accounts[INVOKED_PROGRAM_DUP_INDEX].key, false, false}};
uint8_t data[] = {0, 1, 2, 3, 4, 5};
uint8_t data[] = {TEST_VERIFY_TRANSLATIONS, 1, 2, 3, 4, 5};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, 4, data, 6};
sol_assert(SUCCESS == sol_invoke(&instruction, accounts,
SOL_ARRAY_SIZE(accounts)));
sol_assert(SUCCESS ==
sol_invoke(&instruction, accounts, SOL_ARRAY_SIZE(accounts)));
}
sol_log("Test return error");
{
SolAccountMeta arguments[] = {{accounts[ARGUMENT_INDEX].key, true, true}};
uint8_t data[] = {1};
uint8_t data[] = {TEST_RETURN_ERROR};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};
sol_assert(42 == sol_invoke(&instruction, accounts,
SOL_ARRAY_SIZE(accounts)));
sol_assert(42 ==
sol_invoke(&instruction, accounts, SOL_ARRAY_SIZE(accounts)));
}
sol_log("Test derived signers");
{
sol_assert(!accounts[DERIVED_KEY1_INDEX].is_signer);
sol_assert(!accounts[DERIVED_KEY2_INDEX].is_signer);
sol_assert(!accounts[DERIVED_KEY3_INDEX].is_signer);
SolAccountMeta arguments[] = {
{accounts[DERIVED_KEY_INDEX].key, true, true},
{accounts[DERIVED_KEY2_INDEX].key, false, true}};
uint8_t data[] = {2};
{accounts[INVOKED_PROGRAM_INDEX].key, false, false},
{accounts[DERIVED_KEY1_INDEX].key, true, true},
{accounts[DERIVED_KEY2_INDEX].key, true, false},
{accounts[DERIVED_KEY3_INDEX].key, false, false}};
uint8_t data[] = {TEST_DERIVED_SIGNERS};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};
const SolSignerSeed seeds1[] = {{"Lil'", 4}, {"Bits", 4}};
const SolSignerSeed seeds2[] = {{"Gar Ma Nar Nar", 14}};
const SolSignerSeed seeds1[] = {{"You pass butter", 15}};
const SolSignerSeed seeds2[] = {{"Lil'", 4}, {"Bits", 4}};
const SolSignerSeeds signers_seeds[] = {{seeds1, SOL_ARRAY_SIZE(seeds1)},
{seeds2, SOL_ARRAY_SIZE(seeds2)}};
sol_assert(SUCCESS == sol_invoke_signed(
&instruction, accounts, SOL_ARRAY_SIZE(accounts),
signers_seeds, SOL_ARRAY_SIZE(signers_seeds)));
@ -77,43 +83,36 @@ extern uint64_t entrypoint(const uint8_t *input) {
{
SolAccountMeta arguments[] = {
{accounts[INVOKED_ARGUMENT_INDEX].key, true, false}};
uint8_t data[] = {3};
uint8_t data[] = {TEST_VERIFY_WRITER};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};
sol_assert(SUCCESS == sol_invoke(&instruction, accounts,
SOL_ARRAY_SIZE(accounts)));
sol_assert(SUCCESS ==
sol_invoke(&instruction, accounts, SOL_ARRAY_SIZE(accounts)));
}
sol_log("Test invoke");
{
sol_assert(accounts[ARGUMENT_INDEX].is_signer);
sol_assert(!accounts[DERIVED_KEY_INDEX].is_signer);
sol_assert(!accounts[DERIVED_KEY2_INDEX].is_signer);
*accounts[ARGUMENT_INDEX].lamports -= 5;
*accounts[INVOKED_ARGUMENT_INDEX].lamports += 5;
SolAccountMeta arguments[] = {
{accounts[INVOKED_ARGUMENT_INDEX].key, true, true},
{accounts[ARGUMENT_INDEX].key, true, true},
{accounts[DERIVED_KEY_INDEX].key, true, true}};
uint8_t data[] = {4};
{accounts[ARGUMENT_INDEX].key, true, true}};
uint8_t data[] = {TEST_NESTED_INVOKE};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};
const SolSignerSeed seeds[] = {{"Lil'", 4}, {"Bits", 4}};
const SolSignerSeeds signers_seeds[] = {{seeds, SOL_ARRAY_SIZE(seeds)}};
sol_log("Fist invoke");
sol_assert(SUCCESS == sol_invoke_signed(
&instruction, accounts, SOL_ARRAY_SIZE(accounts),
signers_seeds, SOL_ARRAY_SIZE(signers_seeds)));
sol_assert(SUCCESS ==
sol_invoke(&instruction, accounts, SOL_ARRAY_SIZE(accounts)));
sol_log("2nd invoke from first program");
sol_assert(SUCCESS == sol_invoke_signed(
&instruction, accounts, SOL_ARRAY_SIZE(accounts),
signers_seeds, SOL_ARRAY_SIZE(signers_seeds)));
sol_assert(SUCCESS ==
sol_invoke(&instruction, accounts, SOL_ARRAY_SIZE(accounts)));
sol_assert(*accounts[ARGUMENT_INDEX].lamports == 42 - 5 + 1 + 1);
sol_assert(*accounts[INVOKED_ARGUMENT_INDEX].lamports == 10 + 5 - 1 - 1);

View File

@ -1,7 +1,7 @@
/**
* @brief Example C-based BPF program that prints out the parameters
* passed to it
* @brief Example C-based BPF program that tests cross-program invocations
*/
#include "instruction.h"
#include <solana_sdk.h>
extern uint64_t entrypoint(const uint8_t *input) {
@ -13,7 +13,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
}
switch (params.data[0]) {
case (0): {
case TEST_VERIFY_TRANSLATIONS: {
sol_log("verify data translations");
static const int ARGUMENT_INDEX = 0;
@ -54,7 +54,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
sol_assert(
SolPubkey_same(accounts[INVOKED_PROGRAM_INDEX].key, params.program_id))
sol_assert(SolPubkey_same(accounts[INVOKED_PROGRAM_INDEX].owner,
&bpf_loader_id));
&bpf_loader_id));
sol_assert(!accounts[INVOKED_PROGRAM_INDEX].is_signer);
sol_assert(!accounts[INVOKED_PROGRAM_INDEX].is_writable);
sol_assert(accounts[INVOKED_PROGRAM_INDEX].rent_epoch == 1);
@ -76,21 +76,55 @@ extern uint64_t entrypoint(const uint8_t *input) {
accounts[INVOKED_PROGRAM_DUP_INDEX].executable);
break;
}
case (1): {
case TEST_RETURN_ERROR: {
sol_log("reutrn error");
return 42;
}
case (2): {
case TEST_DERIVED_SIGNERS: {
sol_log("verify derived signers");
static const int DERIVED_KEY_INDEX = 0;
static const int DERIVED_KEY2_INDEX = 1;
sol_assert(sol_deserialize(input, &params, 2));
static const int INVOKED_PROGRAM_INDEX = 0;
static const int DERIVED_KEY1_INDEX = 1;
static const int DERIVED_KEY2_INDEX = 2;
static const int DERIVED_KEY3_INDEX = 3;
sol_assert(sol_deserialize(input, &params, 4));
sol_assert(accounts[DERIVED_KEY_INDEX].is_signer);
sol_assert(accounts[DERIVED_KEY1_INDEX].is_signer);
sol_assert(!accounts[DERIVED_KEY2_INDEX].is_signer);
sol_assert(!accounts[DERIVED_KEY2_INDEX].is_signer);
SolAccountMeta arguments[] = {
{accounts[DERIVED_KEY1_INDEX].key, true, false},
{accounts[DERIVED_KEY2_INDEX].key, true, true},
{accounts[DERIVED_KEY3_INDEX].key, false, true}};
uint8_t data[] = {TEST_VERIFY_NESTED_SIGNERS};
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
arguments, SOL_ARRAY_SIZE(arguments),
data, SOL_ARRAY_SIZE(data)};
const SolSignerSeed seeds1[] = {{"Lil'", 4}, {"Bits", 4}};
const SolSignerSeed seeds2[] = {{"Gar Ma Nar Nar", 14}};
const SolSignerSeeds signers_seeds[] = {{seeds1, SOL_ARRAY_SIZE(seeds1)},
{seeds2, SOL_ARRAY_SIZE(seeds2)}};
sol_assert(SUCCESS == sol_invoke_signed(
&instruction, accounts, SOL_ARRAY_SIZE(accounts),
signers_seeds, SOL_ARRAY_SIZE(signers_seeds)));
break;
}
case TEST_VERIFY_NESTED_SIGNERS: {
sol_log("verify derived nested signers");
static const int DERIVED_KEY1_INDEX = 0;
static const int DERIVED_KEY2_INDEX = 1;
static const int DERIVED_KEY3_INDEX = 2;
sol_assert(sol_deserialize(input, &params, 3));
sol_assert(!accounts[DERIVED_KEY1_INDEX].is_signer);
sol_assert(accounts[DERIVED_KEY2_INDEX].is_signer);
sol_assert(accounts[DERIVED_KEY2_INDEX].is_signer);
break;
}
case (3): {
case TEST_VERIFY_WRITER: {
sol_log("verify writable");
static const int ARGUMENT_INDEX = 0;
sol_assert(sol_deserialize(input, &params, 1));
@ -98,17 +132,15 @@ extern uint64_t entrypoint(const uint8_t *input) {
sol_assert(accounts[ARGUMENT_INDEX].is_writable);
break;
}
case (4): {
case TEST_NESTED_INVOKE: {
sol_log("invoke");
static const int INVOKED_ARGUMENT_INDEX = 0;
static const int ARGUMENT_INDEX = 1;
static const int DERIVED_KEY_INDEX = 2;
sol_assert(sol_deserialize(input, &params, 3));
sol_assert(sol_deserialize(input, &params, 2));
sol_assert(accounts[INVOKED_ARGUMENT_INDEX].is_signer);
sol_assert(accounts[ARGUMENT_INDEX].is_signer);
sol_assert(accounts[DERIVED_KEY_INDEX].is_signer);
*accounts[INVOKED_ARGUMENT_INDEX].lamports -= 1;
*accounts[ARGUMENT_INDEX].lamports += 1;

View File

@ -4,7 +4,7 @@
extern crate solana_sdk;
use solana_bpf_rust_invoked::instruction::create_instruction;
use solana_bpf_rust_invoked::instruction::*;
use solana_sdk::{
account_info::AccountInfo,
entrypoint,
@ -21,8 +21,9 @@ const INVOKED_PROGRAM_INDEX: usize = 2;
const INVOKED_ARGUMENT_INDEX: usize = 3;
const INVOKED_PROGRAM_DUP_INDEX: usize = 4;
// const ARGUMENT_DUP_INDEX: usize = 5;
const DERIVED_KEY_INDEX: usize = 6;
const DERIVED_KEY1_INDEX: usize = 6;
const DERIVED_KEY2_INDEX: usize = 7;
const DERIVED_KEY3_INDEX: usize = 8;
entrypoint!(process_instruction);
fn process_instruction(
@ -49,7 +50,7 @@ fn process_instruction(
(accounts[INVOKED_PROGRAM_INDEX].key, false, false),
(accounts[INVOKED_PROGRAM_DUP_INDEX].key, false, false),
],
vec![0, 1, 2, 3, 4, 5],
vec![TEST_VERIFY_TRANSLATIONS, 1, 2, 3, 4, 5],
);
invoke(&instruction, accounts)?;
}
@ -59,7 +60,7 @@ fn process_instruction(
let instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[(accounts[ARGUMENT_INDEX].key, true, true)],
vec![1],
vec![TEST_RETURN_ERROR],
);
assert_eq!(
invoke(&instruction, accounts),
@ -69,21 +70,24 @@ fn process_instruction(
info!("Test derived signers");
{
assert!(!accounts[DERIVED_KEY_INDEX].is_signer);
assert!(!accounts[DERIVED_KEY1_INDEX].is_signer);
assert!(!accounts[DERIVED_KEY2_INDEX].is_signer);
assert!(!accounts[DERIVED_KEY3_INDEX].is_signer);
let invoked_instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[
(accounts[DERIVED_KEY_INDEX].key, true, true),
(accounts[DERIVED_KEY2_INDEX].key, false, true),
(accounts[INVOKED_PROGRAM_INDEX].key, false, false),
(accounts[DERIVED_KEY1_INDEX].key, true, true),
(accounts[DERIVED_KEY2_INDEX].key, true, false),
(accounts[DERIVED_KEY3_INDEX].key, false, false),
],
vec![2],
vec![TEST_DERIVED_SIGNERS],
);
invoke_signed(
&invoked_instruction,
accounts,
&[&["Lil'", "Bits"], &["Gar Ma Nar Nar"]],
&[&["You pass butter"], &["Lil'", "Bits"]],
)?;
}
@ -92,7 +96,7 @@ fn process_instruction(
let invoked_instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[(accounts[ARGUMENT_INDEX].key, false, true)],
vec![3],
vec![TEST_VERIFY_WRITER],
);
invoke(&invoked_instruction, accounts)?;
}
@ -100,8 +104,6 @@ fn process_instruction(
info!("Test nested invoke");
{
assert!(accounts[ARGUMENT_INDEX].is_signer);
assert!(!accounts[DERIVED_KEY_INDEX].is_signer);
assert!(!accounts[DERIVED_KEY2_INDEX].is_signer);
**accounts[ARGUMENT_INDEX].lamports.borrow_mut() -= 5;
**accounts[INVOKED_ARGUMENT_INDEX].lamports.borrow_mut() += 5;
@ -112,11 +114,10 @@ fn process_instruction(
&[
(accounts[ARGUMENT_INDEX].key, true, true),
(accounts[INVOKED_ARGUMENT_INDEX].key, true, true),
(accounts[DERIVED_KEY_INDEX].key, true, false),
(accounts[INVOKED_PROGRAM_DUP_INDEX].key, false, false),
(accounts[INVOKED_PROGRAM_DUP_INDEX].key, false, false),
],
vec![4],
vec![TEST_NESTED_INVOKE],
);
invoke(&instruction, accounts)?;
info!("2nd invoke from first program");

View File

@ -5,6 +5,13 @@ use solana_sdk::{
pubkey::Pubkey,
};
pub const TEST_VERIFY_TRANSLATIONS: u8 = 0;
pub const TEST_RETURN_ERROR: u8 = 1;
pub const TEST_DERIVED_SIGNERS: u8 = 2;
pub const TEST_VERIFY_NESTED_SIGNERS: u8 = 3;
pub const TEST_VERIFY_WRITER: u8 = 4;
pub const TEST_NESTED_INVOKE: u8 = 5;
pub fn create_instruction(
program_id: Pubkey,
arguments: &[(&Pubkey, bool, bool)],

View File

@ -6,10 +6,15 @@ pub mod instruction;
extern crate solana_sdk;
use crate::instruction::create_instruction;
use crate::instruction::*;
use solana_sdk::{
account_info::AccountInfo, bpf_loader, entrypoint, entrypoint::ProgramResult, info,
program::invoke_signed, program_error::ProgramError, pubkey::Pubkey,
account_info::AccountInfo,
bpf_loader, entrypoint,
entrypoint::ProgramResult,
info,
program::{invoke, invoke_signed},
program_error::ProgramError,
pubkey::Pubkey,
};
entrypoint!(process_instruction);
@ -22,7 +27,7 @@ fn process_instruction(
info!("Invoked program");
match instruction_data[0] {
0 => {
TEST_VERIFY_TRANSLATIONS => {
info!("verify data translations");
const ARGUMENT_INDEX: usize = 0;
@ -30,7 +35,7 @@ fn process_instruction(
const INVOKED_PROGRAM_INDEX: usize = 2;
const INVOKED_PROGRAM_DUP_INDEX: usize = 3;
assert_eq!(instruction_data, &[0, 1, 2, 3, 4, 5]);
assert_eq!(&instruction_data[1..], &[1, 2, 3, 4, 5]);
assert_eq!(accounts.len(), 4);
assert_eq!(accounts[ARGUMENT_INDEX].lamports(), 42);
@ -100,51 +105,76 @@ fn process_instruction(
info!(data[0], 0, 0, 0, 0);
}
}
1 => {
TEST_RETURN_ERROR => {
info!("return error");
return Err(ProgramError::Custom(42));
}
2 => {
TEST_DERIVED_SIGNERS => {
info!("verify derived signers");
const DERIVED_KEY_INDEX: usize = 0;
const DERIVED_KEY2_INDEX: usize = 1;
const INVOKED_PROGRAM_INDEX: usize = 0;
const DERIVED_KEY1_INDEX: usize = 1;
const DERIVED_KEY2_INDEX: usize = 2;
const DERIVED_KEY3_INDEX: usize = 3;
assert!(accounts[DERIVED_KEY_INDEX].is_signer);
assert!(accounts[DERIVED_KEY2_INDEX].is_signer);
assert!(accounts[DERIVED_KEY1_INDEX].is_signer);
assert!(!accounts[DERIVED_KEY2_INDEX].is_signer);
assert!(!accounts[DERIVED_KEY3_INDEX].is_signer);
let invoked_instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[
(accounts[DERIVED_KEY1_INDEX].key, true, false),
(accounts[DERIVED_KEY2_INDEX].key, true, true),
(accounts[DERIVED_KEY3_INDEX].key, false, true),
],
vec![TEST_VERIFY_NESTED_SIGNERS],
);
invoke_signed(
&invoked_instruction,
accounts,
&[&["Lil'", "Bits"], &["Gar Ma Nar Nar"]],
)?;
}
3 => {
TEST_VERIFY_NESTED_SIGNERS => {
info!("verify nested derived signers");
const DERIVED_KEY1_INDEX: usize = 0;
const DERIVED_KEY2_INDEX: usize = 1;
const DERIVED_KEY3_INDEX: usize = 2;
assert!(!accounts[DERIVED_KEY1_INDEX].is_signer);
assert!(accounts[DERIVED_KEY2_INDEX].is_signer);
assert!(accounts[DERIVED_KEY3_INDEX].is_signer);
}
TEST_VERIFY_WRITER => {
info!("verify writable");
const ARGUMENT_INDEX: usize = 0;
assert!(!accounts[ARGUMENT_INDEX].is_writable);
}
4 => {
TEST_NESTED_INVOKE => {
info!("nested invoke");
const ARGUMENT_INDEX: usize = 0;
const INVOKED_ARGUMENT_INDEX: usize = 1;
const DERIVED_KEY_INDEX: usize = 2;
const INVOKED_PROGRAM_INDEX: usize = 3;
assert!(accounts[INVOKED_ARGUMENT_INDEX].is_signer);
**accounts[INVOKED_ARGUMENT_INDEX].lamports.borrow_mut() -= 1;
**accounts[ARGUMENT_INDEX].lamports.borrow_mut() += 1;
if accounts.len() > 3 {
if accounts.len() > 2 {
info!("Invoke again");
let invoked_instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[
(accounts[ARGUMENT_INDEX].key, true, true),
(accounts[INVOKED_ARGUMENT_INDEX].key, true, true),
(accounts[DERIVED_KEY_INDEX].key, true, true),
],
vec![4],
vec![TEST_NESTED_INVOKE],
);
invoke_signed(&invoked_instruction, accounts, &[&["Lil'", "Bits"]])?;
invoke(&invoked_instruction, accounts)?;
} else {
info!("Last invoked");
assert!(accounts[DERIVED_KEY_INDEX].is_signer);
{
let mut data = accounts[INVOKED_ARGUMENT_INDEX].try_borrow_mut_data()?;
for i in 0..10 {

View File

@ -333,10 +333,10 @@ mod bpf {
let bank = Arc::new(Bank::new(&genesis_config));
let bank_client = BankClient::new_shared(&bank);
let program_id = load_bpf_program(&bank_client, &mint_keypair, program.0);
let invoke_program_id = load_bpf_program(&bank_client, &mint_keypair, program.0);
let invoked_program_id = load_bpf_program(&bank_client, &mint_keypair, program.1);
let account = Account::new(42, 100, &program_id);
let account = Account::new(42, 100, &invoke_program_id);
let argument_keypair = Keypair::new();
bank.store_account(&argument_keypair.pubkey(), &account);
@ -344,9 +344,11 @@ mod bpf {
let invoked_argument_keypair = Keypair::new();
bank.store_account(&invoked_argument_keypair.pubkey(), &account);
let derived_key =
Pubkey::create_program_address(&["Lil'", "Bits"], &invoked_program_id).unwrap();
let derived_key1 =
Pubkey::create_program_address(&["You pass butter"], &invoke_program_id).unwrap();
let derived_key2 =
Pubkey::create_program_address(&["Lil'", "Bits"], &invoked_program_id).unwrap();
let derived_key3 =
Pubkey::create_program_address(&["Gar Ma Nar Nar"], &invoked_program_id).unwrap();
let account_metas = vec![
@ -356,11 +358,12 @@ mod bpf {
AccountMeta::new(invoked_argument_keypair.pubkey(), true),
AccountMeta::new_readonly(invoked_program_id, false),
AccountMeta::new(argument_keypair.pubkey(), true),
AccountMeta::new(derived_key, false),
AccountMeta::new_readonly(derived_key2, false),
AccountMeta::new(derived_key1, false),
AccountMeta::new(derived_key2, false),
AccountMeta::new_readonly(derived_key3, false),
];
let instruction = Instruction::new(program_id, &1u8, account_metas);
let instruction = Instruction::new(invoke_program_id, &1u8, account_metas);
let message = Message::new(&[instruction]);
assert!(bank_client

View File

@ -262,7 +262,9 @@ mod tests {
use std::{cell::RefCell, fs::File, io::Read, ops::Range, rc::Rc};
#[derive(Debug, Default)]
pub struct MockInvokeContext {}
pub struct MockInvokeContext {
key: Pubkey,
}
impl InvokeContext for MockInvokeContext {
fn push(&mut self, _key: &Pubkey) -> Result<(), InstructionError> {
Ok(())
@ -277,6 +279,9 @@ mod tests {
) -> Result<(), InstructionError> {
Ok(())
}
fn get_caller(&self) -> Result<&Pubkey, InstructionError> {
Ok(&self.key)
}
}
#[test]

View File

@ -693,8 +693,12 @@ fn call<'a>(
let instruction = syscall.translate_instruction(instruction_addr, ro_regions)?;
let message = Message::new(&[instruction]);
let program_id_index = message.instructions[0].program_id_index as usize;
let program_id = message.account_keys[program_id_index];
let callee_program_id_index = message.instructions[0].program_id_index as usize;
let callee_program_id = message.account_keys[callee_program_id_index];
let caller_program_id = invoke_context
.get_caller()
.map_err(|err| SyscallError::InstructionError(err))?
.into();
let (accounts, refs) = syscall.translate_accounts(
&message,
account_infos_addr,
@ -703,7 +707,7 @@ fn call<'a>(
rw_regions,
)?;
let signers = syscall.translate_signers(
&program_id,
caller_program_id,
signers_seeds_addr,
signers_seeds_len as usize,
ro_regions,
@ -711,12 +715,12 @@ fn call<'a>(
// Process instruction
let program_account = (*accounts[program_id_index]).clone();
let program_account = (*accounts[callee_program_id_index]).clone();
if program_account.borrow().owner != bpf_loader::id() {
// Only BPF programs supported for now
return Err(SyscallError::ProgramNotSupported.into());
}
let executable_accounts = vec![(program_id, program_account)];
let executable_accounts = vec![(callee_program_id, program_account)];
#[allow(clippy::deref_addrof)]
match MessageProcessor::process_cross_program_instruction(

View File

@ -229,6 +229,11 @@ impl InvokeContext for ThisInvokeContext {
None => Err(InstructionError::GenericError), // Should never happen
}
}
fn get_caller(&self) -> Result<&Pubkey, InstructionError> {
self.program_ids
.last()
.ok_or(InstructionError::GenericError)
}
}
pub type ProcessInstruction = fn(&Pubkey, &[KeyedAccount], &[u8]) -> Result<(), InstructionError>;

View File

@ -157,4 +157,5 @@ pub trait InvokeContext {
signers: &[Pubkey],
accounts: &[Rc<RefCell<Account>>],
) -> Result<(), InstructionError>;
fn get_caller(&self) -> Result<&Pubkey, InstructionError>;
}