Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds stable layout types to pass to the runtime #30192

Merged
merged 13 commits into from
Feb 16, 2023
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions program-runtime/src/invoke_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ use {
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
feature_set::{enable_early_verification_of_account_modifications, FeatureSet},
hash::Hash,
instruction::{AccountMeta, Instruction, InstructionError},
instruction::{AccountMeta, InstructionError},
native_loader,
pubkey::Pubkey,
rent::Rent,
saturating_add_assign,
stable_layout::stable_instruction::StableInstruction,
transaction_context::{
IndexOfAccount, InstructionAccount, TransactionAccount, TransactionContext,
},
Expand Down Expand Up @@ -489,7 +490,7 @@ impl<'a> InvokeContext<'a> {
/// Entrypoint for a cross-program invocation from a builtin program
pub fn native_invoke(
&mut self,
instruction: Instruction,
instruction: StableInstruction,
signers: &[Pubkey],
) -> Result<(), InstructionError> {
let (instruction_accounts, program_indices) =
Expand All @@ -509,7 +510,7 @@ impl<'a> InvokeContext<'a> {
#[allow(clippy::type_complexity)]
pub fn prepare_instruction(
&mut self,
instruction: &Instruction,
instruction: &StableInstruction,
signers: &[Pubkey],
) -> Result<(Vec<InstructionAccount>, Vec<IndexOfAccount>), InstructionError> {
// Finds the index of each account in the instruction by its pubkey.
Expand Down Expand Up @@ -1036,7 +1037,7 @@ mod tests {
super::*,
crate::compute_budget,
serde::{Deserialize, Serialize},
solana_sdk::account::WritableAccount,
solana_sdk::{account::WritableAccount, instruction::Instruction},
};

#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -1161,7 +1162,7 @@ mod tests {
assert_eq!(result, Err(InstructionError::UnbalancedInstruction));
result?;
invoke_context
.native_invoke(inner_instruction, &[])
.native_invoke(inner_instruction.into(), &[])
.and(invoke_context.pop())?;
}
MockInstruction::UnbalancedPop => instruction_context
Expand Down Expand Up @@ -1336,7 +1337,7 @@ mod tests {
let inner_instruction =
Instruction::new_with_bincode(callee_program_id, &case.0, metas.clone());
let result = invoke_context
.native_invoke(inner_instruction, &[])
.native_invoke(inner_instruction.into(), &[])
.and(invoke_context.pop());
assert_eq!(result, case.1);
}
Expand All @@ -1359,6 +1360,7 @@ mod tests {
},
metas.clone(),
);
let inner_instruction = StableInstruction::from(inner_instruction);
let (inner_instruction_accounts, program_indices) = invoke_context
.prepare_instruction(&inner_instruction, &[])
.unwrap();
Expand Down
4 changes: 3 additions & 1 deletion program-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use {
pubkey::Pubkey,
rent::Rent,
signature::{Keypair, Signer},
stable_layout::stable_instruction::StableInstruction,
sysvar::{Sysvar, SysvarId},
},
solana_vote_program::vote_state::{self, VoteState, VoteStateVersions},
Expand Down Expand Up @@ -227,6 +228,7 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
account_infos: &[AccountInfo],
signers_seeds: &[&[&[u8]]],
) -> ProgramResult {
let instruction = StableInstruction::from(instruction.clone());
let invoke_context = get_invoke_context();
let log_collector = invoke_context.get_log_collector();
let transaction_context = &invoke_context.transaction_context;
Expand All @@ -249,7 +251,7 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
.collect::<Vec<_>>();

let (instruction_accounts, program_indices) = invoke_context
.prepare_instruction(instruction, &signers)
.prepare_instruction(&instruction, &signers)
.unwrap();

// Copy caller's account_info modifications into invoke_context accounts
Expand Down
8 changes: 4 additions & 4 deletions programs/address-lookup-table/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,18 +144,18 @@ impl Processor {

if required_lamports > 0 {
invoke_context.native_invoke(
system_instruction::transfer(&payer_key, &table_key, required_lamports),
system_instruction::transfer(&payer_key, &table_key, required_lamports).into(),
&[payer_key],
)?;
}

invoke_context.native_invoke(
system_instruction::allocate(&table_key, table_account_data_len as u64),
system_instruction::allocate(&table_key, table_account_data_len as u64).into(),
&[table_key],
)?;

invoke_context.native_invoke(
system_instruction::assign(&table_key, &crate::id()),
system_instruction::assign(&table_key, &crate::id()).into(),
&[table_key],
)?;

Expand Down Expand Up @@ -332,7 +332,7 @@ impl Processor {
drop(payer_account);

invoke_context.native_invoke(
system_instruction::transfer(&payer_key, &table_key, required_lamports),
system_instruction::transfer(&payer_key, &table_key, required_lamports).into(),
&[payer_key],
)?;
}
Expand Down
3 changes: 3 additions & 0 deletions programs/bpf_loader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ solana-zk-token-sdk = { path = "../../zk-token-sdk", version = "=1.16.0" }
solana_rbpf = "=0.2.38"
thiserror = "1.0"

[dev-dependencies]
memoffset = "0.8"

[lib]
crate-type = ["lib"]
name = "solana_bpf_loader_program"
Expand Down
5 changes: 3 additions & 2 deletions programs/bpf_loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ fn process_loader_upgradeable_instruction(
.iter()
.map(|seeds| Pubkey::create_program_address(seeds, caller_program_id))
.collect::<Result<Vec<Pubkey>, solana_sdk::pubkey::PubkeyError>>()?;
invoke_context.native_invoke(instruction, signers.as_slice())?;
invoke_context.native_invoke(instruction.into(), signers.as_slice())?;

// Load and verify the program bits
let transaction_context = &invoke_context.transaction_context;
Expand Down Expand Up @@ -1299,7 +1299,8 @@ fn process_loader_upgradeable_instruction(
)?;

invoke_context.native_invoke(
system_instruction::transfer(&payer_key, &programdata_key, required_payment),
system_instruction::transfer(&payer_key, &programdata_key, required_payment)
.into(),
&[],
)?;
}
Expand Down
28 changes: 16 additions & 12 deletions programs/bpf_loader/src/syscalls/cpi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use {
crate::declare_syscall,
solana_sdk::{
feature_set::enable_bpf_loader_set_authority_checked_ix,
stable_layout::stable_instruction::StableInstruction,
syscalls::{
MAX_CPI_ACCOUNT_INFOS, MAX_CPI_INSTRUCTION_ACCOUNTS, MAX_CPI_INSTRUCTION_DATA_LEN,
},
Expand Down Expand Up @@ -211,7 +212,7 @@ trait SyscallInvokeSigned {
addr: u64,
memory_mapping: &mut MemoryMapping,
invoke_context: &mut InvokeContext,
) -> Result<Instruction, EbpfError>;
) -> Result<StableInstruction, EbpfError>;
fn translate_accounts<'a>(
instruction_accounts: &[InstructionAccount],
program_indices: &[IndexOfAccount],
Expand Down Expand Up @@ -258,8 +259,8 @@ impl SyscallInvokeSigned for SyscallInvokeSignedRust {
addr: u64,
memory_mapping: &mut MemoryMapping,
invoke_context: &mut InvokeContext,
) -> Result<Instruction, EbpfError> {
let ix = translate_type::<Instruction>(
) -> Result<StableInstruction, EbpfError> {
let ix = translate_type::<StableInstruction>(
memory_mapping,
addr,
invoke_context.get_check_aligned(),
Expand Down Expand Up @@ -296,10 +297,11 @@ impl SyscallInvokeSigned for SyscallInvokeSignedRust {
invoke_context.get_check_size(),
)?
.to_vec();
Ok(Instruction {

Ok(StableInstruction {
accounts: accounts.into(),
data: data.into(),
program_id: ix.program_id,
accounts,
data,
})
}

Expand Down Expand Up @@ -469,7 +471,7 @@ impl SyscallInvokeSigned for SyscallInvokeSignedC {
addr: u64,
memory_mapping: &mut MemoryMapping,
invoke_context: &mut InvokeContext,
) -> Result<Instruction, EbpfError> {
) -> Result<StableInstruction, EbpfError> {
let ix_c = translate_type::<SolInstruction>(
memory_mapping,
addr,
Expand Down Expand Up @@ -530,10 +532,10 @@ impl SyscallInvokeSigned for SyscallInvokeSignedC {
})
.collect::<Result<Vec<AccountMeta>, EbpfError>>()?;

Ok(Instruction {
Ok(StableInstruction {
accounts: accounts.into(),
data: data.into(),
program_id: *program_id,
accounts,
data,
})
}

Expand Down Expand Up @@ -1128,6 +1130,7 @@ mod tests {
solana_sdk::{
account::{Account, AccountSharedData},
clock::Epoch,
instruction::Instruction,
rent::Rent,
transaction_context::{TransactionAccount, TransactionContext},
},
Expand Down Expand Up @@ -1693,12 +1696,12 @@ mod tests {
fn into_region(self, vm_addr: u64) -> (Vec<u8>, MemoryRegion) {
let accounts_len = mem::size_of::<AccountMeta>() * self.accounts.len();

let size = mem::size_of::<Instruction>() + accounts_len + self.data.len();
let size = mem::size_of::<StableInstruction>() + accounts_len + self.data.len();

let mut data = vec![0; size];

let vm_addr = vm_addr as usize;
let accounts_addr = vm_addr + mem::size_of::<Instruction>();
let accounts_addr = vm_addr + mem::size_of::<StableInstruction>();
let data_addr = accounts_addr + accounts_len;

let ins = Instruction {
Expand All @@ -1714,6 +1717,7 @@ mod tests {
Vec::from_raw_parts(data_addr as *mut _, self.data.len(), self.data.len())
},
};
let ins = StableInstruction::from(ins);

unsafe {
ptr::write_unaligned(data.as_mut_ptr().cast(), ins);
Expand Down
11 changes: 7 additions & 4 deletions programs/bpf_loader/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use {
},
hash::{Hasher, HASH_BYTES},
instruction::{
AccountMeta, Instruction, InstructionError, ProcessedSiblingInstruction,
AccountMeta, InstructionError, ProcessedSiblingInstruction,
TRANSACTION_LEVEL_STACK_HEIGHT,
},
keccak, native_loader,
Expand Down Expand Up @@ -1821,7 +1821,9 @@ mod tests {
bpf_loader,
fee_calculator::FeeCalculator,
hash::hashv,
instruction::Instruction,
program::check_type_assumptions,
stable_layout::stable_instruction::StableInstruction,
sysvar::{clock::Clock, epoch_schedule::EpochSchedule, rent::Rent},
transaction_context::TransactionContext,
},
Expand Down Expand Up @@ -1936,17 +1938,18 @@ mod tests {
&"foobar",
vec![AccountMeta::new(solana_sdk::pubkey::new_rand(), false)],
);
let instruction = StableInstruction::from(instruction);
let addr = &instruction as *const _ as u64;
let mut memory_region = MemoryRegion {
host_addr: addr,
vm_addr: 0x100000000,
len: std::mem::size_of::<Instruction>() as u64,
len: std::mem::size_of::<StableInstruction>() as u64,
vm_gap_shift: 63,
is_writable: false,
};
let mut memory_mapping = MemoryMapping::new(vec![memory_region.clone()], &config).unwrap();
let translated_instruction =
translate_type::<Instruction>(&memory_mapping, 0x100000000, true).unwrap();
translate_type::<StableInstruction>(&memory_mapping, 0x100000000, true).unwrap();
assert_eq!(instruction, *translated_instruction);
memory_region.len = 1;
let memory_region_index = memory_mapping
Expand All @@ -1957,7 +1960,7 @@ mod tests {
memory_mapping
.replace_region(memory_region_index, memory_region)
.unwrap();
assert!(translate_type::<Instruction>(&memory_mapping, 0x100000000, true).is_err());
assert!(translate_type::<StableInstruction>(&memory_mapping, 0x100000000, true).is_err());
}

#[test]
Expand Down
1 change: 1 addition & 0 deletions sdk/program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ pub mod serialize_utils;
pub mod short_vec;
pub mod slot_hashes;
pub mod slot_history;
pub mod stable_layout;
pub mod stake;
pub mod stake_history;
pub mod syscalls;
Expand Down
11 changes: 7 additions & 4 deletions sdk/program/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use crate::{
account_info::AccountInfo, entrypoint::ProgramResult, instruction::Instruction, pubkey::Pubkey,
stable_layout::stable_instruction::StableInstruction,
};

/// Invoke a cross-program instruction.
Expand Down Expand Up @@ -292,9 +293,10 @@ pub fn invoke_signed_unchecked(
) -> ProgramResult {
#[cfg(target_os = "solana")]
{
let instruction = StableInstruction::from(instruction.clone());
let result = unsafe {
crate::syscalls::sol_invoke_signed_rust(
instruction as *const _ as *const u8,
&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,
Expand Down Expand Up @@ -432,17 +434,18 @@ pub fn check_type_assumptions() {
accounts: vec![account_meta1.clone(), account_meta2.clone()],
data: data.clone(),
};
let instruction = StableInstruction::from(instruction);
let instruction_addr = &instruction as *const _ as u64;

// program id
assert_eq!(offset_of!(Instruction, program_id), 48);
assert_eq!(offset_of!(StableInstruction, program_id), 48);
let pubkey_ptr = (instruction_addr + 48) as *const Pubkey;
unsafe {
assert_eq!(*pubkey_ptr, pubkey1);
}

// accounts
assert_eq!(offset_of!(Instruction, accounts), 0);
assert_eq!(offset_of!(StableInstruction, accounts), 0);
let accounts_ptr = (instruction_addr) as *const *const AccountMeta;
let accounts_cap = (instruction_addr + 8) as *const usize;
let accounts_len = (instruction_addr + 16) as *const usize;
Expand All @@ -455,7 +458,7 @@ pub fn check_type_assumptions() {
}

// data
assert_eq!(offset_of!(Instruction, data), 24);
assert_eq!(offset_of!(StableInstruction, data), 24);
let data_ptr = (instruction_addr + 24) as *const *const [u8; 5];
let data_cap = (instruction_addr + 24 + 8) as *const usize;
let data_len = (instruction_addr + 24 + 16) as *const usize;
Expand Down
10 changes: 10 additions & 0 deletions sdk/program/src/stable_layout.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![doc(hidden)]
//! Types with stable memory layouts
//!
//! Internal use only; here be dragons!

brooksprumo marked this conversation as resolved.
Show resolved Hide resolved
pub mod stable_instruction;
pub mod stable_rc;
pub mod stable_ref_cell;
pub mod stable_slice;
pub mod stable_vec;
Loading