Expose tick_height to bpf programs
This commit is contained in:
parent
5a8938209b
commit
1fda4b77ef
|
@ -188,6 +188,14 @@ SOL_FN_PREFIX void _sol_panic(uint64_t line) {
|
||||||
_sol_panic(__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
|
* 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`.
|
* number of filled accounts in `ka_len_out`.
|
||||||
* @param data On return, a pointer to the instruction data
|
* @param data On return, a pointer to the instruction data
|
||||||
* @param data_len On return, the length in bytes of 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
|
* @return Boolean true if successful
|
||||||
*/
|
*/
|
||||||
SOL_FN_PREFIX bool sol_deserialize(
|
SOL_FN_PREFIX bool sol_deserialize(
|
||||||
|
@ -214,7 +223,8 @@ SOL_FN_PREFIX bool sol_deserialize(
|
||||||
uint64_t ka_len,
|
uint64_t ka_len,
|
||||||
uint64_t *ka_len_out,
|
uint64_t *ka_len_out,
|
||||||
const uint8_t **data,
|
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;
|
*data_len = *(uint64_t *) input;
|
||||||
input += sizeof(uint64_t);
|
input += sizeof(uint64_t);
|
||||||
*data = input;
|
*data = input;
|
||||||
|
input += sizeof(*data_len);
|
||||||
|
|
||||||
|
if (cluster_info != NULL) {
|
||||||
|
cluster_info->tick_height = *(uint64_t *) input;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ extern bool entrypoint(const uint8_t *input) {
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
uint64_t data_len;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,13 @@ extern bool entrypoint(const uint8_t *input) {
|
||||||
uint64_t ka_len;
|
uint64_t ka_len;
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
uint64_t data_len;
|
uint64_t data_len;
|
||||||
|
SolClusterInfo info;
|
||||||
|
|
||||||
sol_log("noop++");
|
sol_log(__FILE__);
|
||||||
|
if (!sol_deserialize(input, ka, SOL_ARRAY_SIZE(ka), &ka_len, &data, &data_len, &info)) {
|
||||||
if (!sol_deserialize(input, ka, SOL_ARRAY_SIZE(ka), &ka_len, &data, &data_len)) {
|
|
||||||
return false;
|
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
|
// 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
|
// the no-op program, no account keys or input data are expected but real
|
||||||
|
|
|
@ -9,12 +9,14 @@ extern bool entrypoint(const uint8_t *input) {
|
||||||
uint64_t ka_len;
|
uint64_t ka_len;
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
uint64_t data_len;
|
uint64_t data_len;
|
||||||
|
SolClusterInfo info;
|
||||||
|
|
||||||
sol_log(__FILE__);
|
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;
|
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
|
// 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
|
// the no-op program, no account keys or input data are expected but real
|
||||||
|
|
|
@ -70,13 +70,12 @@ pub fn helper_sol_log_verify(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
pub fn helper_sol_log(addr: u64, _arg2: u64, _arg3: u64, _arg4: u64, _arg5: u64) -> u64 {
|
||||||
pub fn helper_sol_log(addr: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
|
|
||||||
let c_buf: *const c_char = addr as *const c_char;
|
let c_buf: *const c_char = addr as *const c_char;
|
||||||
let c_str: &CStr = unsafe { CStr::from_ptr(c_buf) };
|
let c_str: &CStr = unsafe { CStr::from_ptr(c_buf) };
|
||||||
match c_str.to_str() {
|
match c_str.to_str() {
|
||||||
Ok(slice) => info!("sol_log: {:?}", slice),
|
Ok(slice) => info!("sol_log: {:?}", slice),
|
||||||
Err(e) => warn!("Error: Cannot print invalid string"),
|
Err(e) => warn!("Error: Cannot print invalid string: {}", e),
|
||||||
};
|
};
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -99,7 +98,11 @@ fn create_vm(prog: &[u8]) -> Result<EbpfVmRaw, Error> {
|
||||||
Ok(vm)
|
Ok(vm)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_parameters(keyed_accounts: &mut [KeyedAccount], data: &[u8]) -> Vec<u8> {
|
fn serialize_parameters(
|
||||||
|
keyed_accounts: &mut [KeyedAccount],
|
||||||
|
data: &[u8],
|
||||||
|
tick_height: u64,
|
||||||
|
) -> Vec<u8> {
|
||||||
assert_eq!(32, mem::size_of::<Pubkey>());
|
assert_eq!(32, mem::size_of::<Pubkey>());
|
||||||
|
|
||||||
let mut v: Vec<u8> = Vec::new();
|
let mut v: Vec<u8> = Vec::new();
|
||||||
|
@ -115,6 +118,7 @@ fn serialize_parameters(keyed_accounts: &mut [KeyedAccount], data: &[u8]) -> Vec
|
||||||
}
|
}
|
||||||
v.write_u64::<LittleEndian>(data.len() as u64).unwrap();
|
v.write_u64::<LittleEndian>(data.len() as u64).unwrap();
|
||||||
v.write_all(data).unwrap();
|
v.write_all(data).unwrap();
|
||||||
|
v.write_u64::<LittleEndian>(tick_height).unwrap();
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +141,7 @@ fn deserialize_parameters(keyed_accounts: &mut [KeyedAccount], buffer: &[u8]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
solana_entrypoint!(entrypoint);
|
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;
|
static INIT: Once = ONCE_INIT;
|
||||||
INIT.call_once(|| {
|
INIT.call_once(|| {
|
||||||
// env_logger can only be initialized 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;
|
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()) {
|
match vm.execute_program(v.as_mut_slice()) {
|
||||||
Ok(status) => {
|
Ok(status) => {
|
||||||
if 0 == status {
|
if 0 == status {
|
||||||
|
|
Loading…
Reference in New Issue