Programs can only sign their accounts
This commit is contained in:
parent
b4b4d6b00d
commit
97e17f9b32
|
@ -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, ¶ms, 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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -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, ¶ms, 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, ¶ms, 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, ¶ms, 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, ¶ms, 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, ¶ms, 3));
|
||||
sol_assert(sol_deserialize(input, ¶ms, 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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)],
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -157,4 +157,5 @@ pub trait InvokeContext {
|
|||
signers: &[Pubkey],
|
||||
accounts: &[Rc<RefCell<Account>>],
|
||||
) -> Result<(), InstructionError>;
|
||||
fn get_caller(&self) -> Result<&Pubkey, InstructionError>;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue