Support cross-program invocation to native programs (#10136)
This commit is contained in:
@ -13,17 +13,35 @@ 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;
|
||||
static const int SYSTEM_PROGRAM_INDEX = 9;
|
||||
static const int FROM_INDEX = 10;
|
||||
|
||||
extern uint64_t entrypoint(const uint8_t *input) {
|
||||
sol_log("Invoke C program");
|
||||
|
||||
SolAccountInfo accounts[9];
|
||||
SolAccountInfo accounts[11];
|
||||
SolParameters params = (SolParameters){.ka = accounts};
|
||||
|
||||
if (!sol_deserialize(input, ¶ms, SOL_ARRAY_SIZE(accounts))) {
|
||||
return ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
sol_log("Call system program");
|
||||
{
|
||||
sol_assert(*accounts[FROM_INDEX].lamports = 43);
|
||||
sol_assert(*accounts[ARGUMENT_INDEX].lamports = 41);
|
||||
SolAccountMeta arguments[] = {{accounts[FROM_INDEX].key, false, true},
|
||||
{accounts[ARGUMENT_INDEX].key, false, false}};
|
||||
uint8_t data[] = {2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0};
|
||||
const SolInstruction instruction = {accounts[SYSTEM_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(*accounts[FROM_INDEX].lamports = 42);
|
||||
sol_assert(*accounts[ARGUMENT_INDEX].lamports = 42);
|
||||
}
|
||||
|
||||
sol_log("Test data translation");
|
||||
{
|
||||
for (int i = 0; i < accounts[ARGUMENT_INDEX].data_len; i++) {
|
||||
@ -37,7 +55,8 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
||||
{accounts[INVOKED_PROGRAM_DUP_INDEX].key, false, false}};
|
||||
uint8_t data[] = {TEST_VERIFY_TRANSLATIONS, 1, 2, 3, 4, 5};
|
||||
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
|
||||
arguments, 4, data, 6};
|
||||
arguments, SOL_ARRAY_SIZE(arguments),
|
||||
data, SOL_ARRAY_SIZE(data)};
|
||||
|
||||
sol_assert(SUCCESS ==
|
||||
sol_invoke(&instruction, accounts, SOL_ARRAY_SIZE(accounts)));
|
||||
@ -70,8 +89,12 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
||||
const SolInstruction instruction = {accounts[INVOKED_PROGRAM_INDEX].key,
|
||||
arguments, SOL_ARRAY_SIZE(arguments),
|
||||
data, SOL_ARRAY_SIZE(data)};
|
||||
const SolSignerSeed seeds1[] = {{"You pass butter", 15}};
|
||||
const SolSignerSeed seeds2[] = {{"Lil'", 4}, {"Bits", 4}};
|
||||
char seed1[] = "You pass butter";
|
||||
char seed2[] = "Lil'";
|
||||
char seed3[] = "Bits";
|
||||
const SolSignerSeed seeds1[] = {{seed1, sol_strlen(seed1)}};
|
||||
const SolSignerSeed seeds2[] = {{seed2, sol_strlen(seed2)},
|
||||
{seed3, sol_strlen(seed3)}};
|
||||
const SolSignerSeeds signers_seeds[] = {{seeds1, SOL_ARRAY_SIZE(seeds1)},
|
||||
{seeds2, SOL_ARRAY_SIZE(seeds2)}};
|
||||
sol_assert(SUCCESS == sol_invoke_signed(
|
||||
|
@ -100,8 +100,12 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
||||
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}};
|
||||
char seed1[] = "Lil'";
|
||||
char seed2[] = "Bits";
|
||||
char seed3[] = "Gar Ma Nar Nar";
|
||||
const SolSignerSeed seeds1[] = {{seed1, sol_strlen(seed1)},
|
||||
{seed2, sol_strlen(seed2)}};
|
||||
const SolSignerSeed seeds2[] = {{seed3, sol_strlen(seed3)}};
|
||||
const SolSignerSeeds signers_seeds[] = {{seeds1, SOL_ARRAY_SIZE(seeds1)},
|
||||
{seeds2, SOL_ARRAY_SIZE(seeds2)}};
|
||||
|
||||
|
@ -13,6 +13,7 @@ use solana_sdk::{
|
||||
program::{invoke, invoke_signed},
|
||||
program_error::ProgramError,
|
||||
pubkey::Pubkey,
|
||||
system_instruction,
|
||||
};
|
||||
|
||||
// const MINT_INDEX: usize = 0;
|
||||
@ -24,6 +25,8 @@ const INVOKED_PROGRAM_DUP_INDEX: usize = 4;
|
||||
const DERIVED_KEY1_INDEX: usize = 6;
|
||||
const DERIVED_KEY2_INDEX: usize = 7;
|
||||
const DERIVED_KEY3_INDEX: usize = 8;
|
||||
// const SYSTEM_PROGRAM_INDEX: usize = 9;
|
||||
const FROM_INDEX: usize = 10;
|
||||
|
||||
entrypoint!(process_instruction);
|
||||
fn process_instruction(
|
||||
@ -33,6 +36,17 @@ fn process_instruction(
|
||||
) -> ProgramResult {
|
||||
info!("invoke Rust program");
|
||||
|
||||
info!("Call system program");
|
||||
{
|
||||
assert_eq!(accounts[FROM_INDEX].lamports(), 43);
|
||||
assert_eq!(accounts[ARGUMENT_INDEX].lamports(), 41);
|
||||
let instruction =
|
||||
system_instruction::transfer(accounts[FROM_INDEX].key, accounts[ARGUMENT_INDEX].key, 1);
|
||||
invoke(&instruction, accounts)?;
|
||||
assert_eq!(accounts[FROM_INDEX].lamports(), 42);
|
||||
assert_eq!(accounts[ARGUMENT_INDEX].lamports(), 42);
|
||||
}
|
||||
|
||||
info!("Test data translation");
|
||||
{
|
||||
{
|
||||
|
@ -336,14 +336,18 @@ mod bpf {
|
||||
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, &invoke_program_id);
|
||||
let argument_keypair = Keypair::new();
|
||||
let account = Account::new(41, 100, &invoke_program_id);
|
||||
bank.store_account(&argument_keypair.pubkey(), &account);
|
||||
|
||||
let account = Account::new(10, 10, &invoked_program_id);
|
||||
let invoked_argument_keypair = Keypair::new();
|
||||
let account = Account::new(10, 10, &invoked_program_id);
|
||||
bank.store_account(&invoked_argument_keypair.pubkey(), &account);
|
||||
|
||||
let from_keypair = Keypair::new();
|
||||
let account = Account::new(43, 0, &solana_sdk::system_program::id());
|
||||
bank.store_account(&from_keypair.pubkey(), &account);
|
||||
|
||||
let derived_key1 =
|
||||
Pubkey::create_program_address(&["You pass butter"], &invoke_program_id).unwrap();
|
||||
let derived_key2 =
|
||||
@ -361,6 +365,8 @@ mod bpf {
|
||||
AccountMeta::new(derived_key1, false),
|
||||
AccountMeta::new(derived_key2, false),
|
||||
AccountMeta::new_readonly(derived_key3, false),
|
||||
AccountMeta::new_readonly(solana_sdk::system_program::id(), false),
|
||||
AccountMeta::new(from_keypair.pubkey(), true),
|
||||
];
|
||||
|
||||
let instruction = Instruction::new(invoke_program_id, &1u8, account_metas);
|
||||
@ -368,7 +374,7 @@ mod bpf {
|
||||
|
||||
assert!(bank_client
|
||||
.send_message(
|
||||
&[&mint_keypair, &argument_keypair, &invoked_argument_keypair],
|
||||
&[&mint_keypair, &argument_keypair, &invoked_argument_keypair, &from_keypair],
|
||||
message,
|
||||
)
|
||||
.is_ok());
|
||||
|
@ -6,7 +6,7 @@ use solana_rbpf::{
|
||||
memory_region::{translate_addr, MemoryRegion},
|
||||
EbpfVm,
|
||||
};
|
||||
use solana_runtime::message_processor::MessageProcessor;
|
||||
use solana_runtime::{builtin_programs::get_builtin_programs, message_processor::MessageProcessor};
|
||||
use solana_sdk::{
|
||||
account::Account,
|
||||
account_info::AccountInfo,
|
||||
@ -712,19 +712,20 @@ fn call<'a>(
|
||||
// Process instruction
|
||||
|
||||
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![(callee_program_id, program_account)];
|
||||
let mut message_processor = MessageProcessor::default();
|
||||
let builtin_programs = get_builtin_programs();
|
||||
for program in builtin_programs.iter() {
|
||||
message_processor.add_program(program.id, program.process_instruction);
|
||||
}
|
||||
message_processor.add_loader(bpf_loader::id(), crate::process_instruction);
|
||||
|
||||
#[allow(clippy::deref_addrof)]
|
||||
match MessageProcessor::process_cross_program_instruction(
|
||||
match message_processor.process_cross_program_instruction(
|
||||
&message,
|
||||
&executable_accounts,
|
||||
&accounts,
|
||||
&signers,
|
||||
crate::process_instruction,
|
||||
*(&mut *invoke_context),
|
||||
) {
|
||||
Ok(()) => (),
|
||||
|
Reference in New Issue
Block a user