program log pubkey as base58 (#12901)

This commit is contained in:
Jack May 2020-10-15 09:11:54 -07:00 committed by GitHub
parent b1b2c6ee7b
commit 3f9e6a600b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 142 additions and 34 deletions

View File

@ -229,8 +229,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
)
.unwrap();
let r = vm.execute_program_metered(&mut serialized, &[], &[], instruction_meter.clone());
measure.stop();
let _ = vm.execute_program_metered(&mut serialized, &[], &[], instruction_meter.clone()); measure.stop();
assert_eq!(
0,
instruction_meter.get_remaining(),

View File

@ -12,9 +12,9 @@
extern uint64_t entrypoint(const uint8_t *input) {
SolAccountInfo ka[NUM_KA];
SolParameters params = (SolParameters) { .ka = ka };
SolParameters params = (SolParameters){.ka = ka};
if (!sol_deserialize(input, &params, SOL_ARRAY_SIZE(ka))) {
return ERROR_INVALID_ARGUMENT;
return ERROR_INVALID_ARGUMENT;
}
uint8_t *val = (uint8_t *)ka[0].data;
size_t current = 1;
@ -35,6 +35,12 @@ extern uint64_t entrypoint(const uint8_t *input) {
// sol_sha256(bytes, SOL_ARRAY_SIZE(bytes), result);
// *val = result[0];
// }
// // Uncomment for Pubkey logging syscall
// {
// SolPubkey pubkey;
// sol_log_pubkey(&pubkey);
// }
}
return *val;
}

View File

@ -7,7 +7,6 @@ use solana_sdk::{
entrypoint,
entrypoint::ProgramResult,
info,
log::Log,
pubkey::Pubkey,
rent,
sysvar::{

View File

@ -612,6 +612,7 @@ mod tests {
sha256_byte_cost: 1,
max_call_depth: 20,
stack_frame_size: 4096,
log_pubkey_units: 100,
},
Rc::new(RefCell::new(Executors::default())),
None,

View File

@ -8,7 +8,9 @@ use solana_rbpf::{
vm::{EbpfVm, SyscallObject},
};
use solana_runtime::{
feature_set::{ristretto_mul_syscall_enabled, sha256_syscall_enabled},
feature_set::{
pubkey_log_syscall_enabled, ristretto_mul_syscall_enabled, sha256_syscall_enabled,
},
message_processor::MessageProcessor,
process_instruction::{ComputeMeter, InvokeContext, Logger},
};
@ -120,6 +122,18 @@ pub fn register_syscalls<'a>(
}),
)?;
if invoke_context.is_feature_active(&pubkey_log_syscall_enabled::id()) {
vm.register_syscall_with_context_ex(
"sol_log_pubkey",
Box::new(SyscallLogPubkey {
cost: compute_budget.log_pubkey_units,
compute_meter: invoke_context.get_compute_meter(),
logger: invoke_context.get_logger(),
loader_id,
}),
)?;
}
if invoke_context.is_feature_active(&sha256_syscall_enabled::id()) {
vm.register_syscall_with_context_ex(
"sol_sha256",
@ -400,6 +414,37 @@ impl SyscallObject<BPFError> for SyscallLogU64 {
}
}
/// Log 5 64-bit values
pub struct SyscallLogPubkey<'a> {
cost: u64,
compute_meter: Rc<RefCell<dyn ComputeMeter>>,
logger: Rc<RefCell<dyn Logger>>,
loader_id: &'a Pubkey,
}
impl<'a> SyscallObject<BPFError> for SyscallLogPubkey<'a> {
fn call(
&mut self,
pubkey_addr: u64,
_arg2: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
ro_regions: &[MemoryRegion],
_rw_regions: &[MemoryRegion],
) -> Result<u64, EbpfError<BPFError>> {
self.compute_meter.consume(self.cost)?;
let mut logger = self
.logger
.try_borrow_mut()
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
if logger.log_enabled() {
let pubkey = translate_type!(Pubkey, pubkey_addr, ro_regions, self.loader_id)?;
logger.log(&format!("Program log: {}", pubkey));
}
Ok(0)
}
}
/// Dynamic memory allocation syscall called when the BPF program calls
/// `sol_alloc_free_()`. The allocator is expected to allocate/free
/// from/to a given chunk of memory and enforce size restrictions. The
@ -1194,6 +1239,7 @@ mod tests {
use super::*;
use crate::tests::{MockComputeMeter, MockLogger};
use solana_sdk::hash::hashv;
use std::str::FromStr;
macro_rules! assert_access_violation {
($result:expr, $va:expr, $len:expr) => {
@ -1467,6 +1513,55 @@ mod tests {
assert_eq!(log.borrow()[0], "Program log: 0x1, 0x2, 0x3, 0x4, 0x5");
}
#[test]
fn test_syscall_sol_pubkey() {
let pubkey = Pubkey::from_str("MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN").unwrap();
let addr = &pubkey.as_ref()[0] as *const _ as u64;
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
Rc::new(RefCell::new(MockComputeMeter { remaining: 2 }));
let log = Rc::new(RefCell::new(vec![]));
let logger: Rc<RefCell<dyn Logger>> =
Rc::new(RefCell::new(MockLogger { log: log.clone() }));
let mut syscall_sol_pubkey = SyscallLogPubkey {
cost: 1,
compute_meter,
logger,
loader_id: &bpf_loader::id(),
};
let ro_regions = &[MemoryRegion {
addr_host: addr,
addr_vm: 100,
len: 32,
}];
let rw_regions = &[MemoryRegion::default()];
syscall_sol_pubkey
.call(100, 0, 0, 0, 0, ro_regions, rw_regions)
.unwrap();
assert_eq!(log.borrow().len(), 1);
assert_eq!(
log.borrow()[0],
"Program log: MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN"
);
assert_access_violation!(
syscall_sol_pubkey.call(
101, // AccessViolation
32, 0, 0, 0, ro_regions, rw_regions,
),
101,
32
);
assert_eq!(
Err(EbpfError::UserError(BPFError::SyscallError(
SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded)
))),
syscall_sol_pubkey.call(100, 32, 0, 0, 0, ro_regions, rw_regions)
);
}
#[test]
fn test_syscall_sol_alloc_free() {
// large alloc

View File

@ -65,6 +65,10 @@ pub mod cumulative_rent_related_fixes {
solana_sdk::declare_id!("FtjnuAtJTWwX3Kx9m24LduNEhzaGuuPfDW6e14SX2Fy5");
}
pub mod pubkey_log_syscall_enabled {
solana_sdk::declare_id!("MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN");
}
lazy_static! {
/// Map of feature identifiers to user-visible description
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
@ -83,6 +87,7 @@ lazy_static! {
(max_program_call_depth_64::id(), "max program call depth 64"),
(timestamp_correction::id(), "correct bank timestamps"),
(cumulative_rent_related_fixes::id(), "rent fixes (#10206, #10468, #11342)"),
(pubkey_log_syscall_enabled::id(), "pubkey log syscall"),
/*************** ADD NEW FEATURES HERE ***************/
]
.iter()

View File

@ -1,5 +1,6 @@
use crate::feature_set::{
compute_budget_balancing, max_invoke_depth_4, max_program_call_depth_64, FeatureSet,
compute_budget_balancing, max_invoke_depth_4, max_program_call_depth_64,
pubkey_log_syscall_enabled, FeatureSet,
};
use solana_sdk::{
account::{Account, KeyedAccount},
@ -85,19 +86,21 @@ pub struct ComputeBudget {
pub log_64_units: u64,
/// Number of compute units consumed by a create_program_address call
pub create_program_address_units: u64,
/// Number of compute units consumed by an invoke call (not including the cost incured by
/// Number of compute units consumed by an invoke call (not including the cost incurred by
/// the called program)
pub invoke_units: u64,
/// Maximum cross-program invocation depth allowed including the orignal caller
/// Maximum cross-program invocation depth allowed including the original caller
pub max_invoke_depth: usize,
/// Base number of compute units consumed to call sha256
/// Base number of compute units consumed to call SHA256
pub sha256_base_cost: u64,
/// Incremental number of units consumed by sha256 (based on bytes)
/// Incremental number of units consumed by SHA256 (based on bytes)
pub sha256_byte_cost: u64,
/// Maximum BPF to BPF call depth
pub max_call_depth: usize,
/// Size of a stack frame in bytes, must match the size specified in the LLVM BPF backend
pub stack_frame_size: usize,
/// Number of compute units consumed by logging a `Pubkey`
pub log_pubkey_units: u64,
}
impl Default for ComputeBudget {
fn default() -> Self {
@ -119,6 +122,7 @@ impl ComputeBudget {
sha256_byte_cost: 1,
max_call_depth: 20,
stack_frame_size: 4_096,
log_pubkey_units: 0,
};
if feature_set.is_active(&compute_budget_balancing::id()) {
@ -144,6 +148,12 @@ impl ComputeBudget {
..compute_budget
};
}
if feature_set.is_active(&pubkey_log_syscall_enabled::id()) {
compute_budget = ComputeBudget {
log_pubkey_units: 100,
..compute_budget
};
}
compute_budget
}
}

View File

@ -540,11 +540,9 @@ static uint64_t sol_invoke(
*
* @param key The public key to print
*/
static void sol_log_key(const SolPubkey *key) {
for (int j = 0; j < sizeof(*key); j++) {
sol_log_64(0, 0, 0, j, key->x[j]);
}
}
void sol_log_pubkey(
const SolPubkey *pubkey
);
/**
* Prints the hexadecimal representation of an array
@ -564,7 +562,7 @@ static void sol_log_array(const uint8_t *array, int len) {
*/
static void sol_log_params(const SolParameters *params) {
sol_log("- Program identifier:");
sol_log_key(params->program_id);
sol_log_pubkey(params->program_id);
sol_log("- Number of KeyedAccounts");
sol_log_64(0, 0, 0, 0, params->ka_num);
@ -574,13 +572,13 @@ static void sol_log_params(const SolParameters *params) {
sol_log(" - Is writable");
sol_log_64(0, 0, 0, 0, params->ka[i].is_writable);
sol_log(" - Key");
sol_log_key(params->ka[i].key);
sol_log_pubkey(params->ka[i].key);
sol_log(" - Lamports");
sol_log_64(0, 0, 0, 0, *params->ka[i].lamports);
sol_log(" - data");
sol_log_array(params->ka[i].data, params->ka[i].data_len);
sol_log(" - Owner");
sol_log_key(params->ka[i].owner);
sol_log_pubkey(params->ka[i].owner);
sol_log(" - Executable");
sol_log_64(0, 0, 0, 0, params->ka[i].executable);
sol_log(" - Rent Epoch");

View File

@ -2,7 +2,7 @@
#![cfg(feature = "program")]
use crate::{account_info::AccountInfo, pubkey::Pubkey};
use crate::account_info::AccountInfo;
/// Prints a string
/// There are two forms and are fast
@ -63,18 +63,6 @@ pub fn sol_log_slice(slice: &[u8]) {
}
}
/// Prints a pubkey
pub trait Log {
fn log(&self);
}
impl Log for Pubkey {
fn log(&self) {
for (i, k) in self.to_bytes().iter().enumerate() {
info!(0, 0, 0, i, *k);
}
}
}
/// Prints the hexadecimal representation of the program's input parameters
///
/// @param ka - A pointer to an array of `AccountInfo` to print

View File

@ -202,9 +202,16 @@ impl Pubkey {
pub fn to_bytes(self) -> [u8; 32] {
self.0
}
}
// TODO localalize this
/// Log a `Pubkey` from a program
#[cfg(feature = "program")]
pub fn log(&self) {
extern "C" {
fn sol_log_pubkey(pubkey_addr: *const u8);
};
unsafe { sol_log_pubkey(self.as_ref() as *const _ as *const u8) };
}
}
impl AsRef<[u8]> for Pubkey {
fn as_ref(&self) -> &[u8] {