Add msg! macro for program logging, deprecate info! macro

This commit is contained in:
Michael Vines 2020-11-30 13:28:58 -08:00
parent 254790f8c8
commit 6705b5a98c
22 changed files with 162 additions and 141 deletions

View File

@ -2,7 +2,7 @@
#[macro_use]
extern crate alloc;
use solana_program::{entrypoint::SUCCESS, info};
use solana_program::{entrypoint::SUCCESS, msg};
use std::{alloc::Layout, mem};
#[no_mangle]
@ -13,7 +13,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
let layout = Layout::from_size_align(std::usize::MAX, mem::align_of::<u8>()).unwrap();
let ptr = alloc::alloc::alloc(layout);
if !ptr.is_null() {
info!("Error: Alloc of very larger buffer should fail");
msg!("Error: Alloc of very larger buffer should fail");
panic!();
}
}
@ -24,7 +24,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
let layout = Layout::from_size_align(100, mem::align_of::<u8>()).unwrap();
let ptr = alloc::alloc::alloc(layout);
if ptr.is_null() {
info!("Error: Alloc of 100 bytes failed");
msg!("Error: Alloc of 100 bytes failed");
alloc::alloc::handle_alloc_error(layout);
}
alloc::alloc::dealloc(ptr, layout);
@ -37,7 +37,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
let layout = Layout::from_size_align(ITERS, mem::align_of::<u8>()).unwrap();
let ptr = alloc::alloc::alloc(layout);
if ptr.is_null() {
info!("Error: Alloc failed");
msg!("Error: Alloc failed");
alloc::alloc::handle_alloc_error(layout);
}
for i in 0..ITERS {
@ -46,7 +46,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
for i in 0..ITERS {
assert_eq!(*ptr.add(i as usize), i as u8);
}
info!(0x3, 0, 0, 0, u64::from(*ptr.add(42)));
msg!(0x3, 0, 0, 0, u64::from(*ptr.add(42)));
assert_eq!(*ptr.add(42), 42);
alloc::alloc::dealloc(ptr, layout);
}
@ -61,7 +61,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
for v in ones.iter() {
sum += ones[*v];
}
info!(0x0, 0, 0, 0, sum as u64);
msg!(0x0, 0, 0, 0, sum as u64);
assert_eq!(sum, ITERS);
}
@ -74,7 +74,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
for i in 0..ITERS {
v.push(i);
}
info!(0x4, 0, 0, 0, v.len() as u64);
msg!(0x4, 0, 0, 0, v.len() as u64);
assert_eq!(v.len(), ITERS);
}

View File

@ -1,6 +1,6 @@
//! @brief Example Rust-based BPF program that tests call depth and stack usage
use solana_program::{entrypoint::SUCCESS, info};
use solana_program::{entrypoint::SUCCESS, msg};
#[inline(never)]
pub fn recurse(data: &mut [u8]) {
@ -8,16 +8,16 @@ pub fn recurse(data: &mut [u8]) {
return;
}
recurse(&mut data[1..]);
info!(line!(), 0, 0, 0, data[0]);
msg!(line!(), 0, 0, 0, data[0]);
}
/// # Safety
#[inline(never)]
#[no_mangle]
pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 {
info!("Call depth");
msg!("Call depth");
let depth = *(input.add(16) as *mut u8);
info!(line!(), 0, 0, 0, depth);
msg!(line!(), 0, 0, 0, depth);
let mut data = Vec::with_capacity(depth as usize);
for i in 0_u8..depth {
data.push(i);

View File

@ -4,7 +4,7 @@ use solana_program::{
account_info::AccountInfo,
entrypoint,
entrypoint::{ProgramResult, HEAP_LENGTH, HEAP_START_ADDRESS},
info,
msg,
pubkey::Pubkey,
};
use std::{
@ -58,7 +58,7 @@ fn process_instruction(
_accounts: &[AccountInfo],
_instruction_data: &[u8],
) -> ProgramResult {
info!("Custom heap");
msg!("Custom heap");
unsafe {
let layout = Layout::from_size_align(usize::MAX - 0x42, align_of::<u8>()).unwrap();
let ptr = alloc(layout);

View File

@ -5,7 +5,7 @@
extern crate solana_program;
use solana_program::{
account_info::AccountInfo, bpf_loader, entrypoint_deprecated,
entrypoint_deprecated::ProgramResult, info, log::*, pubkey::Pubkey,
entrypoint_deprecated::ProgramResult, log::*, msg, pubkey::Pubkey,
};
#[derive(Debug, PartialEq)]
@ -26,7 +26,7 @@ fn process_instruction(
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
info!("Program identifier:");
msg!("Program identifier:");
program_id.log();
assert!(!bpf_loader::check_id(program_id));
@ -34,7 +34,7 @@ fn process_instruction(
// Log the provided account keys and instruction input data. In the case of
// the no-op program, no account keys or input data are expected but real
// programs will have specific requirements so they can do their work.
info!("Account keys and instruction input data:");
msg!("Account keys and instruction input data:");
sol_log_params(accounts, instruction_data);
{
@ -45,7 +45,7 @@ fn process_instruction(
let result_str = std::str::from_utf8(&sparkle_heart).unwrap();
assert_eq!(4, result_str.len());
assert_eq!("💖", result_str);
info!(result_str);
msg!(result_str);
}
{

View File

@ -2,7 +2,7 @@
extern crate solana_program;
use solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, info,
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg,
program_error::ProgramError, pubkey::Pubkey,
};
@ -14,36 +14,36 @@ fn process_instruction(
) -> ProgramResult {
match instruction_data[0] {
1 => {
info!("modify first account data");
msg!("modify first account data");
accounts[2].data.borrow_mut()[0] = 1;
}
2 => {
info!("modify first account data");
msg!("modify first account data");
accounts[3].data.borrow_mut()[0] = 2;
}
3 => {
info!("modify both account data");
msg!("modify both account data");
accounts[2].data.borrow_mut()[0] += 1;
accounts[3].data.borrow_mut()[0] += 2;
}
4 => {
info!("modify first account lamports");
msg!("modify first account lamports");
**accounts[1].lamports.borrow_mut() -= 1;
**accounts[2].lamports.borrow_mut() += 1;
}
5 => {
info!("modify first account lamports");
msg!("modify first account lamports");
**accounts[1].lamports.borrow_mut() -= 2;
**accounts[3].lamports.borrow_mut() += 2;
}
6 => {
info!("modify both account lamports");
msg!("modify both account lamports");
**accounts[1].lamports.borrow_mut() -= 3;
**accounts[2].lamports.borrow_mut() += 1;
**accounts[3].lamports.borrow_mut() += 2;
}
_ => {
info!("Unrecognized command");
msg!("Unrecognized command");
return Err(ProgramError::InvalidArgument);
}
}

View File

@ -8,7 +8,7 @@ use solana_program::{
decode_error::DecodeError,
entrypoint,
entrypoint::ProgramResult,
info,
msg,
program_error::{PrintProgramError, ProgramError},
pubkey::{Pubkey, PubkeyError},
};
@ -38,8 +38,8 @@ impl PrintProgramError for MyError {
E: 'static + std::error::Error + DecodeError<E> + PrintProgramError + FromPrimitive,
{
match self {
MyError::DefaultEnumStart => info!("Error: Default enum start"),
MyError::TheAnswer => info!("Error: The Answer"),
MyError::DefaultEnumStart => msg!("Error: Default enum start"),
MyError::TheAnswer => msg!("Error: The Answer"),
}
}
}
@ -52,19 +52,19 @@ fn process_instruction(
) -> ProgramResult {
match instruction_data[0] {
1 => {
info!("return success");
msg!("return success");
Ok(())
}
2 => {
info!("return a builtin");
msg!("return a builtin");
Err(ProgramError::InvalidAccountData)
}
3 => {
info!("return default enum start value");
msg!("return default enum start value");
Err(MyError::DefaultEnumStart.into())
}
4 => {
info!("return custom error");
msg!("return custom error");
Err(MyError::TheAnswer.into())
}
7 => {
@ -74,11 +74,11 @@ fn process_instruction(
Ok(())
}
9 => {
info!("return pubkey error");
msg!("return pubkey error");
Err(PubkeyError::MaxSeedLengthExceeded.into())
}
_ => {
info!("Unsupported");
msg!("Unsupported");
Err(ProgramError::InvalidInstructionData)
}
}

View File

@ -3,7 +3,7 @@
extern crate solana_program;
use solana_program::{
account_info::next_account_info, account_info::AccountInfo, entrypoint,
entrypoint::ProgramResult, info, program_error::ProgramError, pubkey::Pubkey,
entrypoint::ProgramResult, msg, program_error::ProgramError, pubkey::Pubkey,
sysvar::instructions,
};
@ -37,9 +37,9 @@ fn process_instruction(
let my_index = instruction_data[1] as u16;
assert_eq!(current_instruction, my_index);
info!(&format!("id: {}", instruction.program_id));
msg!(&format!("id: {}", instruction.program_id));
info!(&format!("data[0]: {}", instruction.data[0]));
info!(&format!("index: {}", current_instruction));
msg!(&format!("data[0]: {}", instruction.data[0]));
msg!(&format!("index: {}", current_instruction));
Ok(())
}

View File

@ -9,7 +9,7 @@ use solana_program::{
account_info::AccountInfo,
entrypoint,
entrypoint::{ProgramResult, MAX_PERMITTED_DATA_INCREASE},
info,
msg,
program::{invoke, invoke_signed},
program_error::ProgramError,
pubkey::{Pubkey, PubkeyError},
@ -39,7 +39,7 @@ fn process_instruction(
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
info!("invoke Rust program");
msg!("invoke Rust program");
let bump_seed1 = instruction_data[1];
let bump_seed2 = instruction_data[2];
@ -47,7 +47,7 @@ fn process_instruction(
match instruction_data[0] {
TEST_SUCCESS => {
info!("Call system program create account");
msg!("Call system program create account");
{
let from_lamports = accounts[FROM_INDEX].lamports();
let to_lamports = accounts[DERIVED_KEY1_INDEX].lamports();
@ -85,7 +85,7 @@ fn process_instruction(
}
}
info!("Call system program transfer");
msg!("Call system program transfer");
{
let from_lamports = accounts[FROM_INDEX].lamports();
let to_lamports = accounts[DERIVED_KEY1_INDEX].lamports();
@ -99,7 +99,7 @@ fn process_instruction(
assert_eq!(accounts[DERIVED_KEY1_INDEX].lamports(), to_lamports + 1);
}
info!("Test data translation");
msg!("Test data translation");
{
{
let mut data = accounts[ARGUMENT_INDEX].try_borrow_mut_data()?;
@ -121,7 +121,7 @@ fn process_instruction(
invoke(&instruction, accounts)?;
}
info!("Test no instruction data");
msg!("Test no instruction data");
{
let instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
@ -131,7 +131,7 @@ fn process_instruction(
invoke(&instruction, accounts)?;
}
info!("Test return error");
msg!("Test return error");
{
assert_eq!(
10,
@ -154,7 +154,7 @@ fn process_instruction(
assert_eq!(0, accounts[INVOKED_ARGUMENT_INDEX].try_borrow_data()?[0]);
}
info!("Test refcell usage");
msg!("Test refcell usage");
{
let writable = INVOKED_ARGUMENT_INDEX;
let readable = INVOKED_PROGRAM_INDEX;
@ -240,7 +240,7 @@ fn process_instruction(
}
}
info!("Test create_program_address");
msg!("Test create_program_address");
{
assert_eq!(
&Pubkey::create_program_address(
@ -256,7 +256,7 @@ fn process_instruction(
);
}
info!("Test derived signers");
msg!("Test derived signers");
{
assert!(!accounts[DERIVED_KEY1_INDEX].is_signer);
assert!(!accounts[DERIVED_KEY2_INDEX].is_signer);
@ -279,7 +279,7 @@ fn process_instruction(
)?;
}
info!("Test readonly with writable account");
msg!("Test readonly with writable account");
{
let invoked_instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
@ -289,14 +289,14 @@ fn process_instruction(
invoke(&invoked_instruction, accounts)?;
}
info!("Test nested invoke");
msg!("Test nested invoke");
{
assert!(accounts[ARGUMENT_INDEX].is_signer);
**accounts[ARGUMENT_INDEX].lamports.borrow_mut() -= 5;
**accounts[INVOKED_ARGUMENT_INDEX].lamports.borrow_mut() += 5;
info!("First invoke");
msg!("First invoke");
let instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[
@ -308,7 +308,7 @@ fn process_instruction(
vec![TEST_NESTED_INVOKE],
);
invoke(&instruction, accounts)?;
info!("2nd invoke from first program");
msg!("2nd invoke from first program");
invoke(&instruction, accounts)?;
assert_eq!(accounts[ARGUMENT_INDEX].lamports(), 42 - 5 + 1 + 1 + 1 + 1);
@ -318,7 +318,7 @@ fn process_instruction(
);
}
info!("Verify data values are retained and updated");
msg!("Verify data values are retained and updated");
{
let data = accounts[ARGUMENT_INDEX].try_borrow_data()?;
for i in 0..100 {
@ -331,7 +331,7 @@ fn process_instruction(
}
}
TEST_PRIVILEGE_ESCALATION_SIGNER => {
info!("Test privilege escalation signer");
msg!("Test privilege escalation signer");
let mut invoked_instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[(accounts[DERIVED_KEY3_INDEX].key, false, false)],
@ -344,7 +344,7 @@ fn process_instruction(
invoke(&invoked_instruction, accounts)?;
}
TEST_PRIVILEGE_ESCALATION_WRITABLE => {
info!("Test privilege escalation writable");
msg!("Test privilege escalation writable");
let mut invoked_instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[(accounts[DERIVED_KEY3_INDEX].key, false, false)],
@ -358,7 +358,7 @@ fn process_instruction(
invoke(&invoked_instruction, accounts)?;
}
TEST_PPROGRAM_NOT_EXECUTABLE => {
info!("Test program not executable");
msg!("Test program not executable");
let instruction = create_instruction(
*accounts[ARGUMENT_INDEX].key,
&[(accounts[ARGUMENT_INDEX].key, true, true)],

View File

@ -7,7 +7,7 @@ use solana_program::{
account_info::AccountInfo,
bpf_loader, entrypoint,
entrypoint::ProgramResult,
info,
msg,
program::{invoke, invoke_signed},
program_error::ProgramError,
pubkey::Pubkey,
@ -20,7 +20,7 @@ fn process_instruction(
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
info!("Invoked program");
msg!("Invoked program");
if instruction_data.is_empty() {
return Ok(());
@ -28,7 +28,7 @@ fn process_instruction(
match instruction_data[0] {
TEST_VERIFY_TRANSLATIONS => {
info!("verify data translations");
msg!("verify data translations");
const ARGUMENT_INDEX: usize = 0;
const INVOKED_ARGUMENT_INDEX: usize = 1;
@ -102,11 +102,11 @@ fn process_instruction(
assert!(accounts[INVOKED_PROGRAM_DUP_INDEX]
.try_borrow_mut_data()
.is_err());
info!(data[0], 0, 0, 0, 0);
msg!(data[0], 0, 0, 0, 0);
}
}
TEST_RETURN_ERROR => {
info!("return error");
msg!("return error");
const ARGUMENT_INDEX: usize = 0;
// modify lamports that should be dropped
@ -118,7 +118,7 @@ fn process_instruction(
return Err(ProgramError::Custom(42));
}
TEST_DERIVED_SIGNERS => {
info!("verify derived signers");
msg!("verify derived signers");
const INVOKED_PROGRAM_INDEX: usize = 0;
const DERIVED_KEY1_INDEX: usize = 1;
const DERIVED_KEY2_INDEX: usize = 2;
@ -149,7 +149,7 @@ fn process_instruction(
)?;
}
TEST_VERIFY_NESTED_SIGNERS => {
info!("verify nested derived signers");
msg!("verify nested derived signers");
const DERIVED_KEY1_INDEX: usize = 0;
const DERIVED_KEY2_INDEX: usize = 1;
const DERIVED_KEY3_INDEX: usize = 2;
@ -159,16 +159,16 @@ fn process_instruction(
assert!(accounts[DERIVED_KEY3_INDEX].is_signer);
}
TEST_VERIFY_WRITER => {
info!("verify writable");
msg!("verify writable");
const ARGUMENT_INDEX: usize = 0;
assert!(!accounts[ARGUMENT_INDEX].is_writable);
}
TEST_VERIFY_PRIVILEGE_ESCALATION => {
info!("Success");
msg!("Success");
}
TEST_NESTED_INVOKE => {
info!("nested invoke");
msg!("nested invoke");
const ARGUMENT_INDEX: usize = 0;
const INVOKED_ARGUMENT_INDEX: usize = 1;
@ -179,7 +179,7 @@ fn process_instruction(
**accounts[INVOKED_ARGUMENT_INDEX].lamports.borrow_mut() -= 1;
**accounts[ARGUMENT_INDEX].lamports.borrow_mut() += 1;
if accounts.len() > 2 {
info!("Invoke again");
msg!("Invoke again");
let invoked_instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[
@ -190,7 +190,7 @@ fn process_instruction(
);
invoke(&invoked_instruction, accounts)?;
} else {
info!("Last invoked");
msg!("Last invoked");
{
let mut data = accounts[INVOKED_ARGUMENT_INDEX].try_borrow_mut_data()?;
for i in 0..10 {

View File

@ -1,7 +1,7 @@
//! @brief Example Rust-based BPF program tests loop iteration
extern crate solana_program;
use solana_program::{entrypoint::SUCCESS, info};
use solana_program::{entrypoint::SUCCESS, msg};
#[no_mangle]
pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
@ -12,7 +12,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
for v in ones.iter() {
sum += *v;
}
info!(0xff, 0, 0, 0, sum);
msg!(0xff, 0, 0, 0, sum);
assert_eq!(sum, ITERS as u64);
SUCCESS

View File

@ -2,14 +2,14 @@
mod helper;
extern crate solana_program;
use solana_program::{entrypoint::SUCCESS, info};
use solana_program::{entrypoint::SUCCESS, msg};
#[no_mangle]
pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
info!("Call same package");
msg!("Call same package");
assert_eq!(crate::helper::many_args(1, 2, 3, 4, 5, 6, 7, 8, 9), 45);
info!("Call another package");
msg!("Call another package");
assert_eq!(
solana_bpf_rust_many_args_dep::many_args(1, 2, 3, 4, 5, 6, 7, 8, 9),
45

View File

@ -1,7 +1,7 @@
//! @brief Solana Rust-based BPF program utility functions and types
extern crate solana_program;
use solana_program::info;
use solana_program::msg;
pub fn many_args(
arg1: u64,
@ -14,9 +14,9 @@ pub fn many_args(
arg8: u64,
arg9: u64,
) -> u64 {
info!("Another package - many_args");
info!(arg1, arg2, arg3, arg4, arg5);
info!(arg6, arg7, arg8, arg9, 0);
msg!("Another package - many_args");
msg!(arg1, arg2, arg3, arg4, arg5);
msg!(arg6, arg7, arg8, arg9, 0);
arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9
}
@ -38,9 +38,9 @@ pub fn many_args_sret(
arg8: u64,
arg9: u64,
) -> Ret {
info!("Another package - many_args_sret");
info!(arg1, arg2, arg3, arg4, arg5);
info!(arg6, arg7, arg8, arg9, 0);
msg!("Another package - many_args_sret");
msg!(arg1, arg2, arg3, arg4, arg5);
msg!(arg6, arg7, arg8, arg9, 0);
Ret {
group1: u128::from(arg1) + u128::from(arg2) + u128::from(arg3),
group2: u128::from(arg4) + u128::from(arg5) + u128::from(arg6),

View File

@ -4,8 +4,8 @@
#[no_mangle]
fn custom_panic(info: &core::panic::PanicInfo<'_>) {
// Note: Full panic reporting is included here for testing purposes
solana_program::info!("program custom panic enabled");
solana_program::info!(&format!("{}", info));
solana_program::msg!("program custom panic enabled");
solana_program::msg!(&format!("{}", info));
}
extern crate solana_program;

View File

@ -2,7 +2,7 @@
extern crate solana_program;
use solana_bpf_rust_param_passing_dep::{Data, TestDep};
use solana_program::{entrypoint::SUCCESS, info};
use solana_program::{entrypoint::SUCCESS, msg};
#[no_mangle]
pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
@ -17,7 +17,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
};
let test_dep = TestDep::new(&data, 1, 2, 3, 4, 5);
info!(0, 0, 0, 0, test_dep.thirty);
msg!(0, 0, 0, 0, test_dep.thirty);
assert!(test_dep.thirty == 30);
SUCCESS

View File

@ -4,7 +4,7 @@
extern crate solana_program;
use solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, info, pubkey::Pubkey,
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, pubkey::Pubkey,
};
entrypoint!(process_instruction);
@ -13,6 +13,6 @@ fn process_instruction(
_accounts: &[AccountInfo],
_instruction_data: &[u8],
) -> ProgramResult {
info!("rand");
msg!("rand");
Ok(())
}

View File

@ -5,7 +5,7 @@ pub mod ristretto;
use crate::ristretto::ristretto_mul;
use curve25519_dalek::{constants::RISTRETTO_BASEPOINT_POINT, scalar::Scalar};
use solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, info, pubkey::Pubkey,
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, pubkey::Pubkey,
};
fn test_ristretto_mul() -> ProgramResult {
@ -28,7 +28,7 @@ fn process_instruction(
_accounts: &[AccountInfo],
_instruction_data: &[u8],
) -> ProgramResult {
info!("Ristretto multiply");
msg!("Ristretto multiply");
test_ristretto_mul()?;

View File

@ -4,7 +4,7 @@
extern crate solana_program;
use solana_program::{
account_info::AccountInfo, bpf_loader, entrypoint, entrypoint::ProgramResult, info, log::*,
account_info::AccountInfo, bpf_loader, entrypoint, entrypoint::ProgramResult, log::*, msg,
pubkey::Pubkey,
};
@ -26,7 +26,7 @@ fn process_instruction(
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
info!("Program identifier:");
msg!("Program identifier:");
program_id.log();
assert!(!bpf_loader::check_id(program_id));
@ -34,7 +34,7 @@ fn process_instruction(
// Log the provided account keys and instruction input data. In the case of
// the no-op program, no account keys or input data are expected but real
// programs will have specific requirements so they can do their work.
info!("Account keys and instruction input data:");
msg!("Account keys and instruction input data:");
sol_log_params(accounts, instruction_data);
{
@ -45,7 +45,7 @@ fn process_instruction(
let result_str = std::str::from_utf8(&sparkle_heart).unwrap();
assert_eq!(4, result_str.len());
assert_eq!("💖", result_str);
info!(result_str);
msg!(result_str);
}
{

View File

@ -3,7 +3,7 @@
extern crate solana_program;
use solana_program::{
hash::{hashv, Hasher},
info,
msg,
};
fn test_hasher() {
@ -15,7 +15,7 @@ fn test_hasher() {
#[no_mangle]
pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
info!("sha256");
msg!("sha256");
test_hasher();

View File

@ -2,8 +2,8 @@ use solana_program::{
account_info::AccountInfo,
entrypoint,
entrypoint::ProgramResult,
info,
instruction::{AccountMeta, Instruction},
msg,
program::invoke,
pubkey::Pubkey,
system_instruction::SystemInstruction,
@ -42,7 +42,7 @@ fn process_instruction(
account_metas,
);
info!("swapped owner and data");
msg!("swapped owner and data");
invoke(&ix, &[target.clone(), me.clone(), new_system])?;
let owner_addr = accounts[0].owner as *const Pubkey;

View File

@ -6,7 +6,7 @@ use solana_program::{
clock::DEFAULT_SLOTS_PER_EPOCH,
entrypoint,
entrypoint::ProgramResult,
info,
msg,
pubkey::Pubkey,
rent,
sysvar::{
@ -22,26 +22,26 @@ fn process_instruction(
_instruction_data: &[u8],
) -> ProgramResult {
// Clock
info!("Clock identifier:");
msg!("Clock identifier:");
sysvar::clock::id().log();
let clock = Clock::from_account_info(&accounts[2]).expect("clock");
assert_eq!(clock.slot, DEFAULT_SLOTS_PER_EPOCH + 1);
// Fees
info!("Fees identifier:");
msg!("Fees identifier:");
sysvar::fees::id().log();
let fees = Fees::from_account_info(&accounts[3]).expect("fees");
let fee_calculator = fees.fee_calculator;
assert_eq!(fee_calculator.lamports_per_signature, 0);
// Slot Hashes
info!("SlotHashes identifier:");
msg!("SlotHashes identifier:");
sysvar::slot_hashes::id().log();
let slot_hashes = SlotHashes::from_account_info(&accounts[4]).expect("slot_hashes");
assert!(slot_hashes.len() >= 1);
// Stake History
info!("StakeHistory identifier:");
msg!("StakeHistory identifier:");
sysvar::stake_history::id().log();
let stake_history = StakeHistory::from_account_info(&accounts[5]).expect("stake_history");
assert!(stake_history.len() >= 1);

View File

@ -2,11 +2,8 @@
use crate::account_info::AccountInfo;
/// Prints a string
/// There are two forms and are fast
/// 1. Single string
/// 2. 5 integers
#[macro_export]
#[deprecated(since = "1.4.14", note = "use `msg` macro instead")]
macro_rules! info {
($msg:expr) => {
$crate::log::sol_log($msg)
@ -19,12 +16,37 @@ macro_rules! info {
$arg4 as u64,
$arg5 as u64,
)
}; // `format!()` is not supported yet, Issue #3099
// `format!()` incurs a very large runtime overhead so it should be used with care
// ($($arg:tt)*) => ($crate::log::sol_log(&format!($($arg)*)));
};
}
/// Prints a string to stdout
/// Print a message to the log
///
/// There are two fast forms:
/// 1. Single string: `msg!("hi")`
/// 2. 5 integers: `msg!(1, 2, 3, 4, 5)`
///
/// The third form is more generic and incurs a very large runtime overhead so it should be used
/// with care:
/// 3. Generalized format string: `msg!("Hello {}: 1, 2, {}", "World", 3)`
///
#[macro_export]
macro_rules! msg {
($msg:expr) => {
$crate::log::sol_log($msg)
};
($arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr) => {
$crate::log::sol_log_64(
$arg1 as u64,
$arg2 as u64,
$arg3 as u64,
$arg4 as u64,
$arg5 as u64,
)
};
($($arg:tt)*) => ($crate::log::sol_log(&format!($($arg)*)));
}
/// Print a string to the log
///
/// @param message - Message to print
#[inline]
@ -43,7 +65,7 @@ extern "C" {
fn sol_log_(message: *const u8, len: u64);
}
/// Prints 64 bit values represented as hexadecimal to stdout
/// Print 64-bit values represented as hexadecimal to the log
///
/// @param argx - integer arguments to print
@ -63,41 +85,41 @@ extern "C" {
fn sol_log_64_(arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64);
}
/// Prints the hexadecimal representation of a slice
/// Print the hexadecimal representation of a slice
///
/// @param slice - The array to print
#[allow(dead_code)]
pub fn sol_log_slice(slice: &[u8]) {
for (i, s) in slice.iter().enumerate() {
info!(0, 0, 0, i, *s);
msg!(0, 0, 0, i, *s);
}
}
/// Prints the hexadecimal representation of the program's input parameters
/// Print the hexadecimal representation of the program's input parameters
///
/// @param ka - A pointer to an array of `AccountInfo` to print
/// @param data - A pointer to the instruction data to print
#[allow(dead_code)]
pub fn sol_log_params(accounts: &[AccountInfo], data: &[u8]) {
for (i, account) in accounts.iter().enumerate() {
info!("AccountInfo");
info!(0, 0, 0, 0, i);
info!("- Is signer");
info!(0, 0, 0, 0, account.is_signer);
info!("- Key");
msg!("AccountInfo");
msg!(0, 0, 0, 0, i);
msg!("- Is signer");
msg!(0, 0, 0, 0, account.is_signer);
msg!("- Key");
account.key.log();
info!("- Lamports");
info!(0, 0, 0, 0, account.lamports());
info!("- Account data length");
info!(0, 0, 0, 0, account.data_len());
info!("- Owner");
msg!("- Lamports");
msg!(0, 0, 0, 0, account.lamports());
msg!("- Account data length");
msg!(0, 0, 0, 0, account.data_len());
msg!("- Owner");
account.owner.log();
}
info!("Instruction data");
msg!("Instruction data");
sol_log_slice(data);
}
/// Logs the remaining compute units the program may consume
/// Print the remaining compute units the program may consume
#[inline]
pub fn sol_log_compute_units() {
#[cfg(target_arch = "bpf")]

View File

@ -1,5 +1,4 @@
use crate::info;
use crate::{decode_error::DecodeError, instruction::InstructionError, pubkey::PubkeyError};
use crate::{decode_error::DecodeError, instruction::InstructionError, msg, pubkey::PubkeyError};
use num_traits::{FromPrimitive, ToPrimitive};
use std::convert::TryFrom;
use thiserror::Error;
@ -56,22 +55,22 @@ impl PrintProgramError for ProgramError {
if let Some(custom_error) = E::decode_custom_error_to_enum(*error) {
custom_error.print::<E>();
} else {
info!("Error: Unknown");
msg!("Error: Unknown");
}
}
Self::InvalidArgument => info!("Error: InvalidArgument"),
Self::InvalidInstructionData => info!("Error: InvalidInstructionData"),
Self::InvalidAccountData => info!("Error: InvalidAccountData"),
Self::AccountDataTooSmall => info!("Error: AccountDataTooSmall"),
Self::InsufficientFunds => info!("Error: InsufficientFunds"),
Self::IncorrectProgramId => info!("Error: IncorrectProgramId"),
Self::MissingRequiredSignature => info!("Error: MissingRequiredSignature"),
Self::AccountAlreadyInitialized => info!("Error: AccountAlreadyInitialized"),
Self::UninitializedAccount => info!("Error: UninitializedAccount"),
Self::NotEnoughAccountKeys => info!("Error: NotEnoughAccountKeys"),
Self::AccountBorrowFailed => info!("Error: AccountBorrowFailed"),
Self::MaxSeedLengthExceeded => info!("Error: MaxSeedLengthExceeded"),
Self::InvalidSeeds => info!("Error: InvalidSeeds"),
Self::InvalidArgument => msg!("Error: InvalidArgument"),
Self::InvalidInstructionData => msg!("Error: InvalidInstructionData"),
Self::InvalidAccountData => msg!("Error: InvalidAccountData"),
Self::AccountDataTooSmall => msg!("Error: AccountDataTooSmall"),
Self::InsufficientFunds => msg!("Error: InsufficientFunds"),
Self::IncorrectProgramId => msg!("Error: IncorrectProgramId"),
Self::MissingRequiredSignature => msg!("Error: MissingRequiredSignature"),
Self::AccountAlreadyInitialized => msg!("Error: AccountAlreadyInitialized"),
Self::UninitializedAccount => msg!("Error: UninitializedAccount"),
Self::NotEnoughAccountKeys => msg!("Error: NotEnoughAccountKeys"),
Self::AccountBorrowFailed => msg!("Error: AccountBorrowFailed"),
Self::MaxSeedLengthExceeded => msg!("Error: MaxSeedLengthExceeded"),
Self::InvalidSeeds => msg!("Error: InvalidSeeds"),
}
}
}