From 1fda4b77efde72b0702f18b189ddd0e268c8237c Mon Sep 17 00:00:00 2001 From: Michael Vines Date: Tue, 13 Nov 2018 19:54:41 -0800 Subject: [PATCH] Expose tick_height to bpf programs --- programs/bpf/c/sdk/inc/solana_sdk.h | 16 +++++++++++++++- programs/bpf/c/src/move_funds.c | 2 +- programs/bpf/c/src/noop++.cc | 7 ++++--- programs/bpf/c/src/noop.c | 4 +++- programs/native/bpf_loader/src/lib.rs | 16 ++++++++++------ 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/programs/bpf/c/sdk/inc/solana_sdk.h b/programs/bpf/c/sdk/inc/solana_sdk.h index f283529dc..7be5142a2 100644 --- a/programs/bpf/c/sdk/inc/solana_sdk.h +++ b/programs/bpf/c/sdk/inc/solana_sdk.h @@ -188,6 +188,14 @@ SOL_FN_PREFIX void _sol_panic(uint64_t line) { _sol_panic(__LINE__); \ } +/** + * Information about the state of the cluster immediately before the program + * started executing the current instruction + */ +typedef struct { + uint64_t tick_height; /** Current ledger tick */ +} SolClusterInfo; + /** * De-serializes the input parameters into usable types * @@ -206,6 +214,7 @@ SOL_FN_PREFIX void _sol_panic(uint64_t line) { * number of filled accounts in `ka_len_out`. * @param data On return, a pointer to the instruction data * @param data_len On return, the length in bytes of the instruction data + * @param cluster_info If not NULL, fill cluster_info * @return Boolean true if successful */ SOL_FN_PREFIX bool sol_deserialize( @@ -214,7 +223,8 @@ SOL_FN_PREFIX bool sol_deserialize( uint64_t ka_len, uint64_t *ka_len_out, const uint8_t **data, - uint64_t *data_len + uint64_t *data_len, + SolClusterInfo *cluster_info ) { @@ -255,7 +265,11 @@ SOL_FN_PREFIX bool sol_deserialize( *data_len = *(uint64_t *) input; input += sizeof(uint64_t); *data = input; + input += sizeof(*data_len); + if (cluster_info != NULL) { + cluster_info->tick_height = *(uint64_t *) input; + } return true; } diff --git a/programs/bpf/c/src/move_funds.c b/programs/bpf/c/src/move_funds.c index 6c4d354c0..f8722ab58 100644 --- a/programs/bpf/c/src/move_funds.c +++ b/programs/bpf/c/src/move_funds.c @@ -16,7 +16,7 @@ extern bool entrypoint(const uint8_t *input) { const uint8_t *data; uint64_t data_len; - if (!sol_deserialize(input, ka, NUM_KA, NULL, &data, &data_len)) { + if (!sol_deserialize(input, ka, NUM_KA, NULL, &data, &data_len, NULL)) { return false; } diff --git a/programs/bpf/c/src/noop++.cc b/programs/bpf/c/src/noop++.cc index efd123bb7..c9f14a4be 100644 --- a/programs/bpf/c/src/noop++.cc +++ b/programs/bpf/c/src/noop++.cc @@ -9,12 +9,13 @@ extern bool entrypoint(const uint8_t *input) { uint64_t ka_len; const uint8_t *data; uint64_t data_len; + SolClusterInfo info; - sol_log("noop++"); - - if (!sol_deserialize(input, ka, SOL_ARRAY_SIZE(ka), &ka_len, &data, &data_len)) { + sol_log(__FILE__); + if (!sol_deserialize(input, ka, SOL_ARRAY_SIZE(ka), &ka_len, &data, &data_len, &info)) { return false; } + sol_log_64(info.tick_height, 0, 0, 0, 0); // 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 diff --git a/programs/bpf/c/src/noop.c b/programs/bpf/c/src/noop.c index 13c5abb5d..f8aba9893 100644 --- a/programs/bpf/c/src/noop.c +++ b/programs/bpf/c/src/noop.c @@ -9,12 +9,14 @@ extern bool entrypoint(const uint8_t *input) { uint64_t ka_len; const uint8_t *data; uint64_t data_len; + SolClusterInfo info; sol_log(__FILE__); - if (!sol_deserialize(input, ka, SOL_ARRAY_SIZE(ka), &ka_len, &data, &data_len)) { + if (!sol_deserialize(input, ka, SOL_ARRAY_SIZE(ka), &ka_len, &data, &data_len, &info)) { return false; } + sol_log_64(info.tick_height, 0, 0, 0, 0); // 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 diff --git a/programs/native/bpf_loader/src/lib.rs b/programs/native/bpf_loader/src/lib.rs index de0198d89..8dc87a259 100644 --- a/programs/native/bpf_loader/src/lib.rs +++ b/programs/native/bpf_loader/src/lib.rs @@ -70,13 +70,12 @@ pub fn helper_sol_log_verify( )) } -#[allow(unused_variables)] -pub fn helper_sol_log(addr: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 { +pub fn helper_sol_log(addr: u64, _arg2: u64, _arg3: u64, _arg4: u64, _arg5: u64) -> u64 { let c_buf: *const c_char = addr as *const c_char; let c_str: &CStr = unsafe { CStr::from_ptr(c_buf) }; match c_str.to_str() { Ok(slice) => info!("sol_log: {:?}", slice), - Err(e) => warn!("Error: Cannot print invalid string"), + Err(e) => warn!("Error: Cannot print invalid string: {}", e), }; 0 } @@ -99,7 +98,11 @@ fn create_vm(prog: &[u8]) -> Result { Ok(vm) } -fn serialize_parameters(keyed_accounts: &mut [KeyedAccount], data: &[u8]) -> Vec { +fn serialize_parameters( + keyed_accounts: &mut [KeyedAccount], + data: &[u8], + tick_height: u64, +) -> Vec { assert_eq!(32, mem::size_of::()); let mut v: Vec = Vec::new(); @@ -115,6 +118,7 @@ fn serialize_parameters(keyed_accounts: &mut [KeyedAccount], data: &[u8]) -> Vec } v.write_u64::(data.len() as u64).unwrap(); v.write_all(data).unwrap(); + v.write_u64::(tick_height).unwrap(); v } @@ -137,7 +141,7 @@ fn deserialize_parameters(keyed_accounts: &mut [KeyedAccount], buffer: &[u8]) { } solana_entrypoint!(entrypoint); -fn entrypoint(keyed_accounts: &mut [KeyedAccount], tx_data: &[u8], _tick_height: u64) -> bool { +fn entrypoint(keyed_accounts: &mut [KeyedAccount], tx_data: &[u8], tick_height: u64) -> bool { static INIT: Once = ONCE_INIT; INIT.call_once(|| { // env_logger can only be initialized once @@ -155,7 +159,7 @@ fn entrypoint(keyed_accounts: &mut [KeyedAccount], tx_data: &[u8], _tick_height: return false; } }; - let mut v = serialize_parameters(&mut keyed_accounts[1..], &tx_data); + let mut v = serialize_parameters(&mut keyed_accounts[1..], &tx_data, tick_height); match vm.execute_program(v.as_mut_slice()) { Ok(status) => { if 0 == status {