Skip to content

Commit

Permalink
Add get_processed_sibling_instruction syscall (solana-labs#22859)
Browse files Browse the repository at this point in the history
  • Loading branch information
jackcmay committed Feb 7, 2022
1 parent 8047601 commit 3f9ccfa
Show file tree
Hide file tree
Showing 19 changed files with 863 additions and 65 deletions.
38 changes: 33 additions & 5 deletions program-runtime/src/instruction_recorder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use {
};

/// Records and compiles cross-program invoked instructions
#[derive(Clone, Default)]
#[derive(Clone, Debug, Default, PartialEq)]
pub struct InstructionRecorder {
inner: Rc<RefCell<Vec<Instruction>>>,
inner: Rc<RefCell<Vec<(usize, Instruction)>>>,
}

impl InstructionRecorder {
Expand All @@ -20,11 +20,39 @@ impl InstructionRecorder {
self.inner
.borrow()
.iter()
.map(|ix| message.try_compile_instruction(ix))
.skip(1)
.map(|(_, ix)| message.try_compile_instruction(ix))
.collect()
}

pub fn record_instruction(&self, instruction: Instruction) {
self.inner.borrow_mut().push(instruction);
pub fn record_instruction(&self, stack_height: usize, instruction: Instruction) {
self.inner.borrow_mut().push((stack_height, instruction));
}

pub fn get(&self, index: usize) -> Option<Instruction> {
self.inner
.borrow()
.get(index)
.map(|(_, instruction)| instruction.clone())
}

pub fn find(&self, stack_height: usize, index: usize) -> Option<Instruction> {
let mut current_index = 0;
self.inner
.borrow()
.iter()
.rev()
.skip(1)
.find(|(this_stack_height, _)| {
if stack_height == *this_stack_height {
if index == current_index {
return true;
} else {
current_index = current_index.saturating_add(1);
}
}
false
})
.map(|(_, instruction)| instruction.clone())
}
}
40 changes: 32 additions & 8 deletions program-runtime/src/invoke_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ use {
tx_wide_compute_cap, FeatureSet,
},
hash::Hash,
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
instruction::{
AccountMeta, CompiledInstruction, Instruction, InstructionError,
TRANSACTION_LEVEL_STACK_HEIGHT,
},
keyed_account::{create_keyed_accounts_unified, keyed_account_at_index, KeyedAccount},
message::{Message, SanitizedMessage},
pubkey::Pubkey,
Expand Down Expand Up @@ -201,7 +204,7 @@ pub struct InvokeContext<'a> {
compute_meter: Rc<RefCell<ComputeMeter>>,
accounts_data_meter: AccountsDataMeter,
executors: Rc<RefCell<Executors>>,
pub instruction_recorder: Option<&'a InstructionRecorder>,
pub instruction_trace: Vec<InstructionRecorder>,
pub feature_set: Arc<FeatureSet>,
pub timings: ExecuteDetailsTimings,
pub blockhash: Hash,
Expand Down Expand Up @@ -237,7 +240,7 @@ impl<'a> InvokeContext<'a> {
compute_meter: ComputeMeter::new_ref(compute_budget.max_units),
accounts_data_meter: AccountsDataMeter::new(current_accounts_data_len),
executors,
instruction_recorder: None,
instruction_trace: Vec::new(),
feature_set,
timings: ExecuteDetailsTimings::default(),
blockhash,
Expand Down Expand Up @@ -375,8 +378,8 @@ impl<'a> InvokeContext<'a> {
self.invoke_stack.pop();
}

/// Current depth of the invocation stack
pub fn invoke_depth(&self) -> usize {
/// Current height of the stack
pub fn get_stack_height(&self) -> usize {
self.invoke_stack.len()
}

Expand Down Expand Up @@ -566,9 +569,7 @@ impl<'a> InvokeContext<'a> {
prev_account_sizes.push((account, account_length));
}

if let Some(instruction_recorder) = &self.instruction_recorder {
instruction_recorder.record_instruction(instruction);
}
self.record_instruction(self.get_stack_height(), instruction);

let message = SanitizedMessage::Legacy(message);
self.process_instruction(
Expand Down Expand Up @@ -954,6 +955,29 @@ impl<'a> InvokeContext<'a> {
pub fn get_sysvar_cache(&self) -> &SysvarCache {
&self.sysvar_cache
}

/// Record top-level instruction in the instruction trace
pub fn record_top_level_instruction(&mut self, instruction: Instruction) {
self.instruction_trace.push(InstructionRecorder::default());
self.record_instruction(TRANSACTION_LEVEL_STACK_HEIGHT, instruction);
}

/// Record instruction in the instruction trace
pub fn record_instruction(&mut self, stack_height: usize, instruction: Instruction) {
if let Some(instruction_recorder) = self.instruction_trace.last() {
instruction_recorder.record_instruction(stack_height, instruction)
}
}

/// Get the instruction trace
pub fn get_instruction_trace(&self) -> &[InstructionRecorder] {
&self.instruction_trace
}

/// Get the mutable instruction trace
pub fn get_instruction_trace_mut(&mut self) -> &mut Vec<InstructionRecorder> {
&mut self.instruction_trace
}
}

pub struct MockInvokeContextPreparation {
Expand Down
16 changes: 11 additions & 5 deletions program-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ pub fn builtin_process_instruction(

let log_collector = invoke_context.get_log_collector();
let program_id = invoke_context.get_caller()?;
stable_log::program_invoke(&log_collector, program_id, invoke_context.invoke_depth());
stable_log::program_invoke(
&log_collector,
program_id,
invoke_context.get_stack_height(),
);

// Skip the processor account
let keyed_accounts = &invoke_context.get_keyed_accounts()?[1..];
Expand Down Expand Up @@ -246,7 +250,11 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
.map(|(i, _)| message.is_writable(i))
.collect::<Vec<bool>>();

stable_log::program_invoke(&log_collector, &program_id, invoke_context.invoke_depth());
stable_log::program_invoke(
&log_collector,
&program_id,
invoke_context.get_stack_height(),
);

// Convert AccountInfos into Accounts
let mut account_indices = Vec::with_capacity(message.account_keys.len());
Expand Down Expand Up @@ -305,9 +313,7 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
}
}

if let Some(instruction_recorder) = &invoke_context.instruction_recorder {
instruction_recorder.record_instruction(instruction.clone());
}
invoke_context.record_instruction(invoke_context.get_stack_height(), instruction.clone());

let message = SanitizedMessage::Legacy(message);
invoke_context
Expand Down
14 changes: 14 additions & 0 deletions programs/bpf/Cargo.lock

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

2 changes: 2 additions & 0 deletions programs/bpf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ members = [
"rust/sanity",
"rust/secp256k1_recover",
"rust/sha",
"rust/sibling_inner_instruction",
"rust/sibling_instruction",
"rust/spoof1",
"rust/spoof1_system",
"rust/sysvar",
Expand Down
2 changes: 2 additions & 0 deletions programs/bpf/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ fn main() {
"sanity",
"secp256k1_recover",
"sha",
"sibling_inner_instruction",
"sibling_instruction",
"spoof1",
"spoof1_system",
"upgradeable",
Expand Down
23 changes: 23 additions & 0 deletions programs/bpf/rust/sibling_inner_instruction/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "solana-bpf-rust-sibling_inner-instructions"
version = "1.9.6"
description = "Solana BPF test program written in Rust"
authors = ["Solana Maintainers <[email protected]>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-bpf-rust-log-data"
edition = "2021"

[dependencies]
solana-program = { path = "../../../../sdk/program", version = "=1.9.6" }

[features]
default = ["program"]
program = []

[lib]
crate-type = ["lib", "cdylib"]

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
69 changes: 69 additions & 0 deletions programs/bpf/rust/sibling_inner_instruction/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//! Example Rust-based BPF program that queries sibling instructions
#![cfg(feature = "program")]

use solana_program::{
account_info::AccountInfo,
entrypoint,
entrypoint::ProgramResult,
instruction::{
get_processed_sibling_instruction, get_stack_height, AccountMeta, Instruction,
TRANSACTION_LEVEL_STACK_HEIGHT,
},
msg,
pubkey::Pubkey,
};

entrypoint!(process_instruction);
fn process_instruction(
_program_id: &Pubkey,
accounts: &[AccountInfo],
_instruction_data: &[u8],
) -> ProgramResult {
msg!("sibling inner");

// account 0 is mint
// account 1 is noop
// account 2 is invoke_and_return

// Check sibling instructions

let sibling_instruction2 = Instruction::new_with_bytes(
*accounts[2].key,
&[3],
vec![AccountMeta::new_readonly(*accounts[1].key, false)],
);
let sibling_instruction1 = Instruction::new_with_bytes(
*accounts[1].key,
&[2],
vec![
AccountMeta::new_readonly(*accounts[0].key, true),
AccountMeta::new_readonly(*accounts[1].key, false),
],
);
let sibling_instruction0 = Instruction::new_with_bytes(
*accounts[1].key,
&[1],
vec![
AccountMeta::new_readonly(*accounts[1].key, false),
AccountMeta::new_readonly(*accounts[0].key, true),
],
);

assert_eq!(TRANSACTION_LEVEL_STACK_HEIGHT + 1, get_stack_height());
assert_eq!(
get_processed_sibling_instruction(0),
Some(sibling_instruction0)
);
assert_eq!(
get_processed_sibling_instruction(1),
Some(sibling_instruction1)
);
assert_eq!(
get_processed_sibling_instruction(2),
Some(sibling_instruction2)
);
assert_eq!(get_processed_sibling_instruction(3), None);

Ok(())
}
23 changes: 23 additions & 0 deletions programs/bpf/rust/sibling_instruction/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "solana-bpf-rust-sibling-instructions"
version = "1.9.6"
description = "Solana BPF test program written in Rust"
authors = ["Solana Maintainers <[email protected]>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-bpf-rust-log-data"
edition = "2021"

[dependencies]
solana-program = { path = "../../../../sdk/program", version = "=1.9.6" }

[features]
default = ["program"]
program = []

[lib]
crate-type = ["lib", "cdylib"]

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
Loading

0 comments on commit 3f9ccfa

Please sign in to comment.