Skip to content

Commit

Permalink
Add stable program logging for BPF and native programs
Browse files Browse the repository at this point in the history
  • Loading branch information
mvines committed Nov 14, 2020
1 parent 13f3043 commit baa6b3a
Show file tree
Hide file tree
Showing 9 changed files with 192 additions and 75 deletions.
15 changes: 12 additions & 3 deletions core/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3788,7 +3788,10 @@ pub mod tests {
"jsonrpc": "2.0",
"result": {
"context":{"slot":0},
"value":{"err":null, "logs":[]}
"value":{"err":null, "logs":[
"Program 11111111111111111111111111111111 invoke [1]",
"Program 11111111111111111111111111111111 success"
]}
},
"id": 1,
});
Expand Down Expand Up @@ -3829,7 +3832,10 @@ pub mod tests {
"jsonrpc": "2.0",
"result": {
"context":{"slot":0},
"value":{"err":null, "logs":[]}
"value":{"err":null, "logs":[
"Program 11111111111111111111111111111111 invoke [1]",
"Program 11111111111111111111111111111111 success"
]}
},
"id": 1,
});
Expand All @@ -3849,7 +3855,10 @@ pub mod tests {
"jsonrpc": "2.0",
"result": {
"context":{"slot":0},
"value":{"err":null, "logs":[]}
"value":{"err":null, "logs":[
"Program 11111111111111111111111111111111 invoke [1]",
"Program 11111111111111111111111111111111 success"
]}
},
"id": 1,
});
Expand Down
2 changes: 1 addition & 1 deletion program-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ impl Default for ProgramTest {
solana_logger::setup_with_default(
"solana_bpf_loader=debug,\
solana_rbpf::vm=debug,\
solana_runtime::message_processor=info,\
solana_runtime::message_processor=debug,\
solana_runtime::system_instruction_processor=trace,\
solana_program_test=info",
);
Expand Down
34 changes: 14 additions & 20 deletions programs/bpf_loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use solana_sdk::{
instruction::InstructionError,
keyed_account::{is_executable, next_keyed_account, KeyedAccount},
loader_instruction::LoaderInstruction,
process_instruction::{ComputeMeter, Executor, InvokeContext},
process_instruction::{stable_log, ComputeMeter, Executor, InvokeContext},
program_utils::limited_deserialize,
pubkey::Pubkey,
};
Expand Down Expand Up @@ -63,7 +63,7 @@ pub enum BPFError {
impl UserDefinedError for BPFError {}

/// Point all log messages to the log collector
macro_rules! log{
macro_rules! log {
($logger:ident, $message:expr) => {
if let Ok(logger) = $logger.try_borrow_mut() {
if logger.log_enabled() {
Expand Down Expand Up @@ -238,6 +238,7 @@ impl Executor for BPFExecutor {
invoke_context: &mut dyn InvokeContext,
) -> Result<(), InstructionError> {
let logger = invoke_context.get_logger();
let invoke_depth = invoke_context.invoke_depth();

let mut keyed_accounts_iter = keyed_accounts.iter();
let program = next_keyed_account(&mut keyed_accounts_iter)?;
Expand Down Expand Up @@ -265,7 +266,7 @@ impl Executor for BPFExecutor {
}
};

log!(logger, "Call BPF program {}", program.unsigned_key());
stable_log::program_invoke(&logger, program.unsigned_key(), invoke_depth);
let mut instruction_meter = ThisInstructionMeter::new(compute_meter.clone());
let before = compute_meter.borrow().get_remaining();
const IS_JIT_ENABLED: bool = false;
Expand All @@ -280,41 +281,34 @@ impl Executor for BPFExecutor {
let after = compute_meter.borrow().get_remaining();
log!(
logger,
"BPF program consumed {} of {} units",
"Program {} consumed {} of {} compute units",
program.unsigned_key(),
before - after,
before
);
match result {
Ok(status) => {
if status != SUCCESS {
let error: InstructionError = status.into();
log!(
logger,
"BPF program {} failed: {}",
program.unsigned_key(),
error
);
stable_log::program_failure(&logger, program.unsigned_key(), &error);
return Err(error);
}
}
Err(error) => {
log!(
logger,
"BPF program {} failed: {}",
program.unsigned_key(),
error
);
return match error {
let error = match error {
EbpfError::UserError(BPFError::SyscallError(
SyscallError::InstructionError(error),
)) => Err(error),
_ => Err(BPFLoaderError::VirtualMachineFailedToRunProgram.into()),
)) => error,
_ => BPFLoaderError::VirtualMachineFailedToRunProgram.into(),
};

stable_log::program_failure(&logger, program.unsigned_key(), &error);
return Err(error);
}
}
}
deserialize_parameters(program_id, parameter_accounts, &parameter_bytes)?;
log!(logger, "BPF program {} success", program.unsigned_key());
stable_log::program_success(&logger, program.unsigned_key());
Ok(())
}
}
Expand Down
67 changes: 26 additions & 41 deletions programs/bpf_loader/src/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use solana_sdk::{
instruction::{AccountMeta, Instruction, InstructionError},
keyed_account::KeyedAccount,
message::Message,
process_instruction::{ComputeMeter, InvokeContext, Logger},
process_instruction::{stable_log, ComputeMeter, InvokeContext, Logger},
program_error::ProgramError,
pubkey::{Pubkey, PubkeyError},
};
Expand Down Expand Up @@ -369,23 +369,17 @@ impl<'a> SyscallObject<BPFError> for SyscallLog<'a> {
memory_mapping: &MemoryMapping,
) -> Result<u64, EbpfError<BPFError>> {
self.compute_meter.consume(self.cost)?;
let logger = self
.logger
.try_borrow_mut()
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
if logger.log_enabled() {
translate_string_and_do(
memory_mapping,
AccessType::Load,
addr,
len,
&self.loader_id,
&mut |string: &str| {
logger.log(&format!("Program log: {}", string));
Ok(0)
},
)?;
}
translate_string_and_do(
memory_mapping,
AccessType::Load,
addr,
len,
&self.loader_id,
&mut |string: &str| {
stable_log::program_log(&self.logger, string);
Ok(0)
},
)?;
Ok(0)
}
}
Expand All @@ -407,16 +401,13 @@ impl SyscallObject<BPFError> for SyscallLogU64 {
_memory_mapping: &MemoryMapping,
) -> Result<u64, EbpfError<BPFError>> {
self.compute_meter.consume(self.cost)?;
let logger = self
.logger
.try_borrow_mut()
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
if logger.log_enabled() {
logger.log(&format!(
"Program log: {:#x}, {:#x}, {:#x}, {:#x}, {:#x}",
stable_log::program_log(
&self.logger,
&format!(
"{:#x}, {:#x}, {:#x}, {:#x}, {:#x}",
arg1, arg2, arg3, arg4, arg5
));
}
),
);
Ok(0)
}
}
Expand Down Expand Up @@ -470,20 +461,14 @@ impl<'a> SyscallObject<BPFError> for SyscallLogPubkey<'a> {
memory_mapping: &MemoryMapping,
) -> Result<u64, EbpfError<BPFError>> {
self.compute_meter.consume(self.cost)?;
let logger = self
.logger
.try_borrow_mut()
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
if logger.log_enabled() {
let pubkey = translate_type!(
memory_mapping,
AccessType::Load,
pubkey_addr,
Pubkey,
self.loader_id
)?;
logger.log(&format!("Program log: {}", pubkey));
}
let pubkey = translate_type!(
memory_mapping,
AccessType::Load,
pubkey_addr,
Pubkey,
self.loader_id
)?;
stable_log::program_log(&self.logger, &pubkey.to_string());
Ok(0)
}
}
Expand Down
2 changes: 1 addition & 1 deletion run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ $ok || {
exit 1
}

export RUST_LOG=${RUST_LOG:-solana=info} # if RUST_LOG is unset, default to info
export RUST_LOG=${RUST_LOG:-solana=info,solana_runtime::message_processor=debug} # if RUST_LOG is unset, default to info
export RUST_BACKTRACE=1
dataDir=$PWD/config/"$(basename "$0" .sh)"
ledgerDir=$PWD/config/ledger
Expand Down
55 changes: 50 additions & 5 deletions runtime/src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,77 @@ use crate::{
bank::{Builtin, Builtins},
system_instruction_processor,
};
use solana_sdk::{feature_set, pubkey::Pubkey, system_program};
use solana_sdk::{
feature_set,
instruction::InstructionError,
keyed_account::KeyedAccount,
process_instruction::{stable_log, InvokeContext, ProcessInstructionWithContext},
pubkey::Pubkey,
system_program,
};

fn process_instruction_with_program_logging(
process_instruction: ProcessInstructionWithContext,
program_id: &Pubkey,
keyed_accounts: &[KeyedAccount],
instruction_data: &[u8],
invoke_context: &mut dyn InvokeContext,
) -> Result<(), InstructionError> {
let logger = invoke_context.get_logger();
stable_log::program_invoke(&logger, program_id, invoke_context.invoke_depth());

let result = process_instruction(program_id, keyed_accounts, instruction_data, invoke_context);

match &result {
Ok(()) => stable_log::program_success(&logger, program_id),
Err(err) => stable_log::program_failure(&logger, program_id, err),
}
result
}

macro_rules! with_program_logging {
($process_instruction:expr) => {
|program_id: &Pubkey,
keyed_accounts: &[KeyedAccount],
instruction_data: &[u8],
invoke_context: &mut dyn InvokeContext| {
process_instruction_with_program_logging(
$process_instruction,
program_id,
keyed_accounts,
instruction_data,
invoke_context,
)
}
};
}

/// Builtin programs that are always available
fn genesis_builtins() -> Vec<Builtin> {
vec![
Builtin::new(
"system_program",
system_program::id(),
system_instruction_processor::process_instruction,
with_program_logging!(system_instruction_processor::process_instruction),
),
Builtin::new(
"vote_program",
solana_vote_program::id(),
solana_vote_program::vote_instruction::process_instruction,
with_program_logging!(solana_vote_program::vote_instruction::process_instruction),
),
// Remove legacy_stake_processor and move stake_instruction::process_instruction back to
// genesis_builtins around the v1.6 timeframe
Builtin::new(
"stake_program",
solana_stake_program::id(),
solana_stake_program::legacy_stake_processor::process_instruction,
with_program_logging!(
solana_stake_program::legacy_stake_processor::process_instruction
),
),
Builtin::new(
"config_program",
solana_config_program::id(),
solana_config_program::config_processor::process_instruction,
with_program_logging!(solana_config_program::config_processor::process_instruction),
),
]
}
Expand Down
5 changes: 4 additions & 1 deletion runtime/src/message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> {
fn pop(&mut self) {
self.program_ids.pop();
}
fn invoke_depth(&self) -> usize {
self.program_ids.len()
}
fn verify_and_update(
&mut self,
message: &Message,
Expand Down Expand Up @@ -314,7 +317,7 @@ impl Logger for ThisLogger {
log_enabled!(log::Level::Info) || self.log_collector.is_some()
}
fn log(&self, message: &str) {
info!("{}", message);
debug!("{}", message);
if let Some(log_collector) = &self.log_collector {
log_collector.log(message);
}
Expand Down
Loading

0 comments on commit baa6b3a

Please sign in to comment.