Generate syscall headers
This commit is contained in:
parent
0cc97689f9
commit
66366615bb
|
@ -1566,6 +1566,14 @@ dependencies = [
|
|||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gen-headers"
|
||||
version = "1.11.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gen-syscall-list"
|
||||
version = "1.11.0"
|
||||
|
|
|
@ -67,6 +67,7 @@ members = [
|
|||
"sdk",
|
||||
"sdk/cargo-build-bpf",
|
||||
"sdk/cargo-test-bpf",
|
||||
"sdk/gen-headers",
|
||||
"send-transaction-service",
|
||||
"stake-accounts",
|
||||
"storage-bigtable",
|
||||
|
|
|
@ -148,6 +148,8 @@ fi
|
|||
if [[ -z "$validatorOnly" ]]; then
|
||||
# shellcheck disable=SC2086 # Don't want to double quote $rust_version
|
||||
"$cargo" $maybeRustVersion build --manifest-path programs/bpf_loader/gen-syscall-list/Cargo.toml
|
||||
# shellcheck disable=SC2086 # Don't want to double quote $rust_version
|
||||
"$cargo" $maybeRustVersion run --bin gen-headers
|
||||
mkdir -p "$installDir"/bin/sdk/bpf
|
||||
cp -a sdk/bpf/* "$installDir"/bin/sdk/bpf
|
||||
fi
|
||||
|
|
|
@ -41,6 +41,12 @@ C_FLAGS := \
|
|||
$(addprefix -I,$(STD_INC_DIRS)) \
|
||||
$(addprefix -I,$(INC_DIRS)) \
|
||||
|
||||
ifeq ($(SOL_SBFV2),1)
|
||||
C_FLAGS := \
|
||||
$(C_FLAGS) \
|
||||
-DSOL_SBFV2=1
|
||||
endif
|
||||
|
||||
CXX_FLAGS := \
|
||||
$(C_FLAGS) \
|
||||
-std=c++17 \
|
||||
|
@ -70,6 +76,12 @@ BPF_LLD_FLAGS := \
|
|||
-L $(STD_LIB_DIRS) \
|
||||
-lc \
|
||||
|
||||
ifeq ($(SOL_SBFV2),1)
|
||||
BPF_LLD_FLAGS := \
|
||||
$(BPF_LLD_FLAGS) \
|
||||
--pack-dyn-relocs=relr
|
||||
endif
|
||||
|
||||
OBJ_DUMP_FLAGS := \
|
||||
--source \
|
||||
--disassemble \
|
||||
|
|
|
@ -16,7 +16,15 @@ extern "C" {
|
|||
* Prints the line number where the panic occurred and then causes
|
||||
* the BPF VM to immediately halt execution. No accounts' data are updated
|
||||
*/
|
||||
#ifndef SOL_SBFV2
|
||||
void sol_panic_(const char *, uint64_t, uint64_t, uint64_t);
|
||||
#else
|
||||
typedef void(*sol_panic__pointer_type)(const char *, uint64_t, uint64_t, uint64_t);
|
||||
static void sol_panic_(const char * arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4) {
|
||||
sol_panic__pointer_type sol_panic__pointer = (sol_panic__pointer_type) 1751159739;
|
||||
sol_panic__pointer(arg1, arg2, arg3, arg4);
|
||||
}
|
||||
#endif
|
||||
#define sol_panic() sol_panic_(__FILE__, sizeof(__FILE__), __LINE__, 0)
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,11 +21,15 @@ extern "C" {
|
|||
* @param bytes_len Number of byte arrays
|
||||
* @param result 32 byte array to hold the result
|
||||
*/
|
||||
uint64_t sol_blake3(
|
||||
const SolBytes *bytes,
|
||||
int bytes_len,
|
||||
const uint8_t *result
|
||||
);
|
||||
#ifndef SOL_SBFV2
|
||||
uint64_t sol_blake3(const SolBytes *, int, const uint8_t *);
|
||||
#else
|
||||
typedef uint64_t(*sol_blake3_pointer_type)(const SolBytes *, int, const uint8_t *);
|
||||
static uint64_t sol_blake3(const SolBytes * arg1, int arg2, const uint8_t * arg3) {
|
||||
sol_blake3_pointer_type sol_blake3_pointer = (sol_blake3_pointer_type) 390877474;
|
||||
return sol_blake3_pointer(arg1, arg2, arg3);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -34,13 +34,33 @@ typedef struct {
|
|||
/**
|
||||
* Internal cross-program invocation function
|
||||
*/
|
||||
#ifndef SOL_SBFV2
|
||||
uint64_t sol_invoke_signed_c(
|
||||
const SolInstruction *instruction,
|
||||
const SolAccountInfo *account_infos,
|
||||
int account_infos_len,
|
||||
const SolSignerSeeds *signers_seeds,
|
||||
int signers_seeds_len
|
||||
const SolInstruction *,
|
||||
const SolAccountInfo *,
|
||||
int,
|
||||
const SolSignerSeeds *,
|
||||
int
|
||||
);
|
||||
#else
|
||||
typedef uint64_t(*sol_invoke_signed_c_pointer_type)(
|
||||
const SolInstruction *,
|
||||
const SolAccountInfo *,
|
||||
int,
|
||||
const SolSignerSeeds *,
|
||||
int
|
||||
);
|
||||
static uint64_t sol_invoke_signed_c(
|
||||
const SolInstruction * arg1,
|
||||
const SolAccountInfo * arg2,
|
||||
int arg3,
|
||||
const SolSignerSeeds * arg4,
|
||||
int
|
||||
arg5) {
|
||||
sol_invoke_signed_c_pointer_type sol_invoke_signed_c_pointer = (sol_invoke_signed_c_pointer_type) 2720767109;
|
||||
return sol_invoke_signed_c_pointer(arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Invoke another program and sign for some of the keys
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana assert and panic utilities
|
||||
*/
|
||||
|
||||
#include <sol/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Panics
|
||||
*
|
||||
* Prints the line number where the panic occurred and then causes
|
||||
* the BPF VM to immediately halt execution. No accounts' data are updated
|
||||
*/
|
||||
@SYSCALL void sol_panic_(const char *, uint64_t, uint64_t, uint64_t);
|
||||
#define sol_panic() sol_panic_(__FILE__, sizeof(__FILE__), __LINE__, 0)
|
||||
|
||||
/**
|
||||
* Asserts
|
||||
*/
|
||||
#define sol_assert(expr) \
|
||||
if (!(expr)) { \
|
||||
sol_panic(); \
|
||||
}
|
||||
|
||||
#ifdef SOL_TEST
|
||||
/**
|
||||
* Stub functions when building tests
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void sol_panic_(const char *file, uint64_t len, uint64_t line, uint64_t column) {
|
||||
printf("Panic in %s at %d:%d\n", file, line, column);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana Blake3 system call
|
||||
*/
|
||||
|
||||
#include <sol/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Length of a Blake3 hash result
|
||||
*/
|
||||
#define BLAKE3_RESULT_LENGTH 32
|
||||
|
||||
/**
|
||||
* Blake3
|
||||
*
|
||||
* @param bytes Array of byte arrays
|
||||
* @param bytes_len Number of byte arrays
|
||||
* @param result 32 byte array to hold the result
|
||||
*/
|
||||
@SYSCALL uint64_t sol_blake3(const SolBytes *, int, const uint8_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,95 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana Cross-Program Invocation
|
||||
*/
|
||||
|
||||
#include <sol/types.h>
|
||||
#include <sol/pubkey.h>
|
||||
#include <sol/entrypoint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Account Meta
|
||||
*/
|
||||
typedef struct {
|
||||
SolPubkey *pubkey; /** An account's public key */
|
||||
bool is_writable; /** True if the `pubkey` can be loaded as a read-write account */
|
||||
bool is_signer; /** True if an Instruction requires a Transaction signature matching `pubkey` */
|
||||
} SolAccountMeta;
|
||||
|
||||
/**
|
||||
* Instruction
|
||||
*/
|
||||
typedef struct {
|
||||
SolPubkey *program_id; /** Pubkey of the instruction processor that executes this instruction */
|
||||
SolAccountMeta *accounts; /** Metadata for what accounts should be passed to the instruction processor */
|
||||
uint64_t account_len; /** Number of SolAccountMetas */
|
||||
uint8_t *data; /** Opaque data passed to the instruction processor */
|
||||
uint64_t data_len; /** Length of the data in bytes */
|
||||
} SolInstruction;
|
||||
|
||||
/**
|
||||
* Internal cross-program invocation function
|
||||
*/
|
||||
@SYSCALL uint64_t sol_invoke_signed_c(
|
||||
const SolInstruction *,
|
||||
const SolAccountInfo *,
|
||||
int,
|
||||
const SolSignerSeeds *,
|
||||
int
|
||||
);
|
||||
|
||||
/**
|
||||
* Invoke another program and sign for some of the keys
|
||||
*
|
||||
* @param instruction Instruction to process
|
||||
* @param account_infos Accounts used by instruction
|
||||
* @param account_infos_len Length of account_infos array
|
||||
* @param seeds Seed bytes used to sign program accounts
|
||||
* @param seeds_len Length of the seeds array
|
||||
*/
|
||||
static uint64_t sol_invoke_signed(
|
||||
const SolInstruction *instruction,
|
||||
const SolAccountInfo *account_infos,
|
||||
int account_infos_len,
|
||||
const SolSignerSeeds *signers_seeds,
|
||||
int signers_seeds_len
|
||||
) {
|
||||
return sol_invoke_signed_c(
|
||||
instruction,
|
||||
account_infos,
|
||||
account_infos_len,
|
||||
signers_seeds,
|
||||
signers_seeds_len
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Invoke another program
|
||||
*
|
||||
* @param instruction Instruction to process
|
||||
* @param account_infos Accounts used by instruction
|
||||
* @param account_infos_len Length of account_infos array
|
||||
*/
|
||||
static uint64_t sol_invoke(
|
||||
const SolInstruction *instruction,
|
||||
const SolAccountInfo *account_infos,
|
||||
int account_infos_len
|
||||
) {
|
||||
const SolSignerSeeds signers_seeds[] = {{}};
|
||||
return sol_invoke_signed(
|
||||
instruction,
|
||||
account_infos,
|
||||
account_infos_len,
|
||||
signers_seeds,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana keccak system call
|
||||
**/
|
||||
|
||||
#include <sol/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Length of a Keccak hash result
|
||||
*/
|
||||
#define KECCAK_RESULT_LENGTH 32
|
||||
|
||||
/**
|
||||
* Keccak
|
||||
*
|
||||
* @param bytes Array of byte arrays
|
||||
* @param bytes_len Number of byte arrays
|
||||
* @param result 32 byte array to hold the result
|
||||
*/
|
||||
@SYSCALL uint64_t sol_keccak256(const SolBytes *, int, uint8_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,103 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana logging utilities
|
||||
*/
|
||||
|
||||
#include <sol/types.h>
|
||||
#include <sol/string.h>
|
||||
#include <sol/entrypoint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Prints a string to stdout
|
||||
*/
|
||||
@SYSCALL void sol_log_(const char *, uint64_t);
|
||||
#define sol_log(message) sol_log_(message, sol_strlen(message))
|
||||
|
||||
/**
|
||||
* Prints a 64 bit values represented in hexadecimal to stdout
|
||||
*/
|
||||
@SYSCALL void sol_log_64_(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
|
||||
#define sol_log_64 sol_log_64_
|
||||
|
||||
/**
|
||||
* Prints the current compute unit consumption to stdout
|
||||
*/
|
||||
@SYSCALL void sol_log_compute_units_();
|
||||
#define sol_log_compute_units() sol_log_compute_units_()
|
||||
|
||||
/**
|
||||
* Prints the hexadecimal representation of an array
|
||||
*
|
||||
* @param array The array to print
|
||||
*/
|
||||
static void sol_log_array(const uint8_t *array, int len) {
|
||||
for (int j = 0; j < len; j++) {
|
||||
sol_log_64(0, 0, 0, j, array[j]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the base64 representation of some arrays.
|
||||
*/
|
||||
@SYSCALL void sol_log_data(SolBytes *, uint64_t);
|
||||
|
||||
/**
|
||||
* Prints the program's input parameters
|
||||
*
|
||||
* @param params Pointer to a SolParameters structure
|
||||
*/
|
||||
static void sol_log_params(const SolParameters *params) {
|
||||
sol_log("- Program identifier:");
|
||||
sol_log_pubkey(params->program_id);
|
||||
|
||||
sol_log("- Number of KeyedAccounts");
|
||||
sol_log_64(0, 0, 0, 0, params->ka_num);
|
||||
for (int i = 0; i < params->ka_num; i++) {
|
||||
sol_log(" - Is signer");
|
||||
sol_log_64(0, 0, 0, 0, params->ka[i].is_signer);
|
||||
sol_log(" - Is writable");
|
||||
sol_log_64(0, 0, 0, 0, params->ka[i].is_writable);
|
||||
sol_log(" - 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_pubkey(params->ka[i].owner);
|
||||
sol_log(" - Executable");
|
||||
sol_log_64(0, 0, 0, 0, params->ka[i].executable);
|
||||
sol_log(" - Rent Epoch");
|
||||
sol_log_64(0, 0, 0, 0, params->ka[i].rent_epoch);
|
||||
}
|
||||
sol_log("- Instruction data\0");
|
||||
sol_log_array(params->data, params->data_len);
|
||||
}
|
||||
|
||||
#ifdef SOL_TEST
|
||||
/**
|
||||
* Stub functions when building tests
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
void sol_log_(const char *s, uint64_t len) {
|
||||
printf("Program log: %s\n", s);
|
||||
}
|
||||
void sol_log_64(uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) {
|
||||
printf("Program log: %llu, %llu, %llu, %llu, %llu\n", arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
|
||||
void sol_log_compute_units_() {
|
||||
printf("Program consumption: __ units remaining\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,107 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana Public key
|
||||
*/
|
||||
|
||||
#include <sol/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Size of Public key in bytes
|
||||
*/
|
||||
#define SIZE_PUBKEY 32
|
||||
|
||||
/**
|
||||
* Public key
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t x[SIZE_PUBKEY];
|
||||
} SolPubkey;
|
||||
|
||||
/**
|
||||
* Prints the hexadecimal representation of a public key
|
||||
*
|
||||
* @param key The public key to print
|
||||
*/
|
||||
@SYSCALL void sol_log_pubkey(const SolPubkey *);
|
||||
|
||||
/**
|
||||
* Compares two public keys
|
||||
*
|
||||
* @param one First public key
|
||||
* @param two Second public key
|
||||
* @return true if the same
|
||||
*/
|
||||
static bool SolPubkey_same(const SolPubkey *one, const SolPubkey *two) {
|
||||
for (int i = 0; i < sizeof(*one); i++) {
|
||||
if (one->x[i] != two->x[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed used to create a program address or passed to sol_invoke_signed
|
||||
*/
|
||||
typedef struct {
|
||||
const uint8_t *addr; /** Seed bytes */
|
||||
uint64_t len; /** Length of the seed bytes */
|
||||
} SolSignerSeed;
|
||||
|
||||
/**
|
||||
* Seeds used by a signer to create a program address or passed to
|
||||
* sol_invoke_signed
|
||||
*/
|
||||
typedef struct {
|
||||
const SolSignerSeed *addr; /** An array of a signer's seeds */
|
||||
uint64_t len; /** Number of seeds */
|
||||
} SolSignerSeeds;
|
||||
|
||||
/**
|
||||
* Create a program address
|
||||
*
|
||||
* @param seeds Seed bytes used to sign program accounts
|
||||
* @param seeds_len Length of the seeds array
|
||||
* @param program_id Program id of the signer
|
||||
* @param program_address Program address created, filled on return
|
||||
*/
|
||||
@SYSCALL uint64_t sol_create_program_address(const SolSignerSeed *, int, const SolPubkey *, SolPubkey *);
|
||||
|
||||
/**
|
||||
* Try to find a program address and return corresponding bump seed
|
||||
*
|
||||
* @param seeds Seed bytes used to sign program accounts
|
||||
* @param seeds_len Length of the seeds array
|
||||
* @param program_id Program id of the signer
|
||||
* @param program_address Program address created, filled on return
|
||||
* @param bump_seed Bump seed required to create a valid program address
|
||||
*/
|
||||
@SYSCALL uint64_t sol_try_find_program_address(const SolSignerSeed *, int, const SolPubkey *, SolPubkey *, uint8_t *);
|
||||
|
||||
#ifdef SOL_TEST
|
||||
/**
|
||||
* Stub functions when building tests
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
void sol_log_pubkey(
|
||||
const SolPubkey *pubkey
|
||||
) {
|
||||
printf("Program log: ");
|
||||
for (int i = 0; i < SIZE_PUBKEY; i++) {
|
||||
printf("%02 ", pubkey->x[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana return data system calls
|
||||
**/
|
||||
|
||||
#include <sol/types.h>
|
||||
#include <sol/pubkey.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Maximum size of return data
|
||||
*/
|
||||
#define MAX_RETURN_DATA 1024
|
||||
|
||||
/**
|
||||
* Set the return data
|
||||
*
|
||||
* @param bytes byte array to set
|
||||
* @param bytes_len length of byte array. This may not exceed MAX_RETURN_DATA.
|
||||
*/
|
||||
@SYSCALL void sol_set_return_data(const uint8_t *, uint64_t);
|
||||
|
||||
/**
|
||||
* Get the return data
|
||||
*
|
||||
* @param bytes byte buffer
|
||||
* @param bytes_len maximum length of buffer
|
||||
* @param program_id the program_id which set the return data. Only set if there was some return data (the function returns non-zero).
|
||||
* @param result length of return data (may exceed bytes_len if the return data is longer)
|
||||
*/
|
||||
@SYSCALL uint64_t sol_get_return_data(const uint8_t *, uint64_t, SolPubkey *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana secp256k1 system call
|
||||
*/
|
||||
|
||||
#include <sol/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Length of a secp256k1 recover input hash */
|
||||
#define SECP256K1_RECOVER_HASH_LENGTH 32
|
||||
/** Length of a secp256k1 input signature */
|
||||
#define SECP256K1_RECOVER_SIGNATURE_LENGTH 64
|
||||
/** Length of a secp256k1 recover result */
|
||||
#define SECP256K1_RECOVER_RESULT_LENGTH 64
|
||||
|
||||
/** The hash provided to a sol_secp256k1_recover is invalid */
|
||||
#define SECP256K1_RECOVER_ERROR_INVALID_HASH 1
|
||||
/** The recovery_id provided to a sol_secp256k1_recover is invalid */
|
||||
#define SECP256K1_RECOVER_ERROR_INVALID_RECOVERY_ID 2
|
||||
/** The signature provided to a sol_secp256k1_recover is invalid */
|
||||
#define SECP256K1_RECOVER_ERROR_INVALID_SIGNATURE 3
|
||||
|
||||
/**
|
||||
* Recover public key from a signed message.
|
||||
*
|
||||
* @param hash Hashed message
|
||||
* @param recovery_id Tag used for public key recovery from signatures. Can be 0 or 1
|
||||
* @param signature An ECDSA signature
|
||||
* @param result 64 byte array to hold the result. A recovered public key
|
||||
* @return 0 if executed successfully
|
||||
*/
|
||||
@SYSCALL uint64_t sol_secp256k1_recover(const uint8_t *, uint64_t, const uint8_t *, uint8_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana sha system call
|
||||
*/
|
||||
|
||||
#include <sol/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Length of a sha256 hash result
|
||||
*/
|
||||
#define SHA256_RESULT_LENGTH 32
|
||||
|
||||
/**
|
||||
* Sha256
|
||||
*
|
||||
* @param bytes Array of byte arrays
|
||||
* @param bytes_len Number of byte arrays
|
||||
* @param result 32 byte array to hold the result
|
||||
*/
|
||||
@SYSCALL uint64_t sol_sha256(const SolBytes *, int, uint8_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,81 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana string and memory system calls and utilities
|
||||
*/
|
||||
|
||||
#include <sol/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Copies memory
|
||||
*/
|
||||
static void sol_memcpy(void *dst, const void *src, int len) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
*((uint8_t *)dst + i) = *((const uint8_t *)src + i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares memory
|
||||
*/
|
||||
static int sol_memcmp(const void *s1, const void *s2, int n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
uint8_t diff = *((uint8_t *)s1 + i) - *((const uint8_t *)s2 + i);
|
||||
if (diff) {
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill a byte string with a byte value
|
||||
*/
|
||||
static void *sol_memset(void *b, int c, size_t len) {
|
||||
uint8_t *a = (uint8_t *) b;
|
||||
while (len > 0) {
|
||||
*a = c;
|
||||
a++;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find length of string
|
||||
*/
|
||||
static size_t sol_strlen(const char *s) {
|
||||
size_t len = 0;
|
||||
while (*s) {
|
||||
len++;
|
||||
s++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal memory alloc/free function
|
||||
*/
|
||||
@SYSCALL void* sol_alloc_free_(uint64_t, void *);
|
||||
|
||||
/**
|
||||
* Alloc zero-initialized memory
|
||||
*/
|
||||
static void *sol_calloc(size_t nitems, size_t size) {
|
||||
return sol_alloc_free_(nitems * size, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deallocates the memory previously allocated by sol_calloc
|
||||
*/
|
||||
static void sol_free(void *ptr) {
|
||||
(void) sol_alloc_free_(0, ptr);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -21,11 +21,15 @@ extern "C" {
|
|||
* @param bytes_len Number of byte arrays
|
||||
* @param result 32 byte array to hold the result
|
||||
*/
|
||||
uint64_t sol_keccak256(
|
||||
const SolBytes *bytes,
|
||||
int bytes_len,
|
||||
uint8_t *result
|
||||
);
|
||||
#ifndef SOL_SBFV2
|
||||
uint64_t sol_keccak256(const SolBytes *, int, uint8_t *);
|
||||
#else
|
||||
typedef uint64_t(*sol_keccak256_pointer_type)(const SolBytes *, int, uint8_t *);
|
||||
static uint64_t sol_keccak256(const SolBytes * arg1, int arg2, uint8_t * arg3) {
|
||||
sol_keccak256_pointer_type sol_keccak256_pointer = (sol_keccak256_pointer_type) 3615046331;
|
||||
return sol_keccak256_pointer(arg1, arg2, arg3);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -14,19 +14,43 @@ extern "C" {
|
|||
/**
|
||||
* Prints a string to stdout
|
||||
*/
|
||||
#ifndef SOL_SBFV2
|
||||
void sol_log_(const char *, uint64_t);
|
||||
#else
|
||||
typedef void(*sol_log__pointer_type)(const char *, uint64_t);
|
||||
static void sol_log_(const char * arg1, uint64_t arg2) {
|
||||
sol_log__pointer_type sol_log__pointer = (sol_log__pointer_type) 544561597;
|
||||
sol_log__pointer(arg1, arg2);
|
||||
}
|
||||
#endif
|
||||
#define sol_log(message) sol_log_(message, sol_strlen(message))
|
||||
|
||||
/**
|
||||
* Prints a 64 bit values represented in hexadecimal to stdout
|
||||
*/
|
||||
#ifndef SOL_SBFV2
|
||||
void sol_log_64_(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
|
||||
#else
|
||||
typedef void(*sol_log_64__pointer_type)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
|
||||
static void sol_log_64_(uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) {
|
||||
sol_log_64__pointer_type sol_log_64__pointer = (sol_log_64__pointer_type) 1546269048;
|
||||
sol_log_64__pointer(arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
#endif
|
||||
#define sol_log_64 sol_log_64_
|
||||
|
||||
/**
|
||||
* Prints the current compute unit consumption to stdout
|
||||
*/
|
||||
#ifndef SOL_SBFV2
|
||||
void sol_log_compute_units_();
|
||||
#else
|
||||
typedef void(*sol_log_compute_units__pointer_type)();
|
||||
static void sol_log_compute_units_() {
|
||||
sol_log_compute_units__pointer_type sol_log_compute_units__pointer = (sol_log_compute_units__pointer_type) 1387942038;
|
||||
sol_log_compute_units__pointer();
|
||||
}
|
||||
#endif
|
||||
#define sol_log_compute_units() sol_log_compute_units_()
|
||||
|
||||
/**
|
||||
|
@ -43,7 +67,15 @@ static void sol_log_array(const uint8_t *array, int len) {
|
|||
/**
|
||||
* Print the base64 representation of some arrays.
|
||||
*/
|
||||
void sol_log_data(SolBytes *fields, uint64_t fields_len);
|
||||
#ifndef SOL_SBFV2
|
||||
void sol_log_data(SolBytes *, uint64_t);
|
||||
#else
|
||||
typedef void(*sol_log_data_pointer_type)(SolBytes *, uint64_t);
|
||||
static void sol_log_data(SolBytes * arg1, uint64_t arg2) {
|
||||
sol_log_data_pointer_type sol_log_data_pointer = (sol_log_data_pointer_type) 1930933300;
|
||||
sol_log_data_pointer(arg1, arg2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Prints the program's input parameters
|
||||
|
|
|
@ -26,9 +26,15 @@ typedef struct {
|
|||
*
|
||||
* @param key The public key to print
|
||||
*/
|
||||
void sol_log_pubkey(
|
||||
const SolPubkey *pubkey
|
||||
);
|
||||
#ifndef SOL_SBFV2
|
||||
void sol_log_pubkey(const SolPubkey *);
|
||||
#else
|
||||
typedef void(*sol_log_pubkey_pointer_type)(const SolPubkey *);
|
||||
static void sol_log_pubkey(const SolPubkey * arg1) {
|
||||
sol_log_pubkey_pointer_type sol_log_pubkey_pointer = (sol_log_pubkey_pointer_type) 2129692874;
|
||||
sol_log_pubkey_pointer(arg1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Compares two public keys
|
||||
|
@ -71,12 +77,15 @@ typedef struct {
|
|||
* @param program_id Program id of the signer
|
||||
* @param program_address Program address created, filled on return
|
||||
*/
|
||||
uint64_t sol_create_program_address(
|
||||
const SolSignerSeed *seeds,
|
||||
int seeds_len,
|
||||
const SolPubkey *program_id,
|
||||
SolPubkey *program_address
|
||||
);
|
||||
#ifndef SOL_SBFV2
|
||||
uint64_t sol_create_program_address(const SolSignerSeed *, int, const SolPubkey *, SolPubkey *);
|
||||
#else
|
||||
typedef uint64_t(*sol_create_program_address_pointer_type)(const SolSignerSeed *, int, const SolPubkey *, SolPubkey *);
|
||||
static uint64_t sol_create_program_address(const SolSignerSeed * arg1, int arg2, const SolPubkey * arg3, SolPubkey * arg4) {
|
||||
sol_create_program_address_pointer_type sol_create_program_address_pointer = (sol_create_program_address_pointer_type) 2474062396;
|
||||
return sol_create_program_address_pointer(arg1, arg2, arg3, arg4);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Try to find a program address and return corresponding bump seed
|
||||
|
@ -87,13 +96,15 @@ uint64_t sol_create_program_address(
|
|||
* @param program_address Program address created, filled on return
|
||||
* @param bump_seed Bump seed required to create a valid program address
|
||||
*/
|
||||
uint64_t sol_try_find_program_address(
|
||||
const SolSignerSeed *seeds,
|
||||
int seeds_len,
|
||||
const SolPubkey *program_id,
|
||||
SolPubkey *program_address,
|
||||
uint8_t *bump_seed
|
||||
);
|
||||
#ifndef SOL_SBFV2
|
||||
uint64_t sol_try_find_program_address(const SolSignerSeed *, int, const SolPubkey *, SolPubkey *, uint8_t *);
|
||||
#else
|
||||
typedef uint64_t(*sol_try_find_program_address_pointer_type)(const SolSignerSeed *, int, const SolPubkey *, SolPubkey *, uint8_t *);
|
||||
static uint64_t sol_try_find_program_address(const SolSignerSeed * arg1, int arg2, const SolPubkey * arg3, SolPubkey * arg4, uint8_t * arg5) {
|
||||
sol_try_find_program_address_pointer_type sol_try_find_program_address_pointer = (sol_try_find_program_address_pointer_type) 1213221432;
|
||||
return sol_try_find_program_address_pointer(arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SOL_TEST
|
||||
/**
|
||||
|
|
|
@ -22,7 +22,15 @@ extern "C"
|
|||
* @param bytes byte array to set
|
||||
* @param bytes_len length of byte array. This may not exceed MAX_RETURN_DATA.
|
||||
*/
|
||||
void sol_set_return_data(const uint8_t *bytes, uint64_t bytes_len);
|
||||
#ifndef SOL_SBFV2
|
||||
void sol_set_return_data(const uint8_t *, uint64_t);
|
||||
#else
|
||||
typedef void(*sol_set_return_data_pointer_type)(const uint8_t *, uint64_t);
|
||||
static void sol_set_return_data(const uint8_t * arg1, uint64_t arg2) {
|
||||
sol_set_return_data_pointer_type sol_set_return_data_pointer = (sol_set_return_data_pointer_type) 2720453611;
|
||||
sol_set_return_data_pointer(arg1, arg2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get the return data
|
||||
|
@ -32,7 +40,15 @@ void sol_set_return_data(const uint8_t *bytes, uint64_t bytes_len);
|
|||
* @param program_id the program_id which set the return data. Only set if there was some return data (the function returns non-zero).
|
||||
* @param result length of return data (may exceed bytes_len if the return data is longer)
|
||||
*/
|
||||
uint64_t sol_get_return_data(const uint8_t *bytes, uint64_t bytes_len, SolPubkey *program_id);
|
||||
#ifndef SOL_SBFV2
|
||||
uint64_t sol_get_return_data(const uint8_t *, uint64_t, SolPubkey *);
|
||||
#else
|
||||
typedef uint64_t(*sol_get_return_data_pointer_type)(const uint8_t *, uint64_t, SolPubkey *);
|
||||
static uint64_t sol_get_return_data(const uint8_t * arg1, uint64_t arg2, SolPubkey * arg3) {
|
||||
sol_get_return_data_pointer_type sol_get_return_data_pointer = (sol_get_return_data_pointer_type) 1562527204;
|
||||
return sol_get_return_data_pointer(arg1, arg2, arg3);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -32,12 +32,15 @@ extern "C" {
|
|||
* @param result 64 byte array to hold the result. A recovered public key
|
||||
* @return 0 if executed successfully
|
||||
*/
|
||||
uint64_t sol_secp256k1_recover(
|
||||
const uint8_t *hash,
|
||||
uint64_t recovery_id,
|
||||
const uint8_t *signature,
|
||||
uint8_t *result
|
||||
);
|
||||
#ifndef SOL_SBFV2
|
||||
uint64_t sol_secp256k1_recover(const uint8_t *, uint64_t, const uint8_t *, uint8_t *);
|
||||
#else
|
||||
typedef uint64_t(*sol_secp256k1_recover_pointer_type)(const uint8_t *, uint64_t, const uint8_t *, uint8_t *);
|
||||
static uint64_t sol_secp256k1_recover(const uint8_t * arg1, uint64_t arg2, const uint8_t * arg3, uint8_t * arg4) {
|
||||
sol_secp256k1_recover_pointer_type sol_secp256k1_recover_pointer = (sol_secp256k1_recover_pointer_type) 400819024;
|
||||
return sol_secp256k1_recover_pointer(arg1, arg2, arg3, arg4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -21,11 +21,15 @@ extern "C" {
|
|||
* @param bytes_len Number of byte arrays
|
||||
* @param result 32 byte array to hold the result
|
||||
*/
|
||||
uint64_t sol_sha256(
|
||||
const SolBytes *bytes,
|
||||
int bytes_len,
|
||||
uint8_t *result
|
||||
);
|
||||
#ifndef SOL_SBFV2
|
||||
uint64_t sol_sha256(const SolBytes *, int, uint8_t *);
|
||||
#else
|
||||
typedef uint64_t(*sol_sha256_pointer_type)(const SolBytes *, int, uint8_t *);
|
||||
static uint64_t sol_sha256(const SolBytes * arg1, int arg2, uint8_t * arg3) {
|
||||
sol_sha256_pointer_type sol_sha256_pointer = (sol_sha256_pointer_type) 301243782;
|
||||
return sol_sha256_pointer(arg1, arg2, arg3);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -58,7 +58,15 @@ static size_t sol_strlen(const char *s) {
|
|||
/**
|
||||
* Internal memory alloc/free function
|
||||
*/
|
||||
void *sol_alloc_free_(uint64_t size, void *ptr);
|
||||
#ifndef SOL_SBFV2
|
||||
void* sol_alloc_free_(uint64_t, void *);
|
||||
#else
|
||||
typedef void*(*sol_alloc_free__pointer_type)(uint64_t, void *);
|
||||
static void* sol_alloc_free_(uint64_t arg1, void * arg2) {
|
||||
sol_alloc_free__pointer_type sol_alloc_free__pointer = (sol_alloc_free__pointer_type) 2213547663;
|
||||
return sol_alloc_free__pointer(arg1, arg2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Alloc zero-initialized memory
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "gen-headers"
|
||||
version = "1.11.0"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
log = { version = "0.4.17", features = ["std"] }
|
||||
regex = "1.5.4"
|
||||
|
||||
[[bin]]
|
||||
name = "gen-headers"
|
||||
path = "src/main.rs"
|
|
@ -0,0 +1,172 @@
|
|||
#![allow(clippy::integer_arithmetic)]
|
||||
|
||||
use {
|
||||
log::info,
|
||||
regex::{Captures, Regex},
|
||||
std::{
|
||||
ffi::OsStr,
|
||||
fs,
|
||||
io::{prelude::*, BufWriter},
|
||||
path::PathBuf,
|
||||
str,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* 1. process every inc file in syscalls header file
|
||||
*
|
||||
* 2. in every such file replace the syscall declaration by a new
|
||||
* declaration with a new extended name, and a static function
|
||||
* definition that computes a hash of the original name and uses the
|
||||
* hash to initialize a function pointer, the function pointer then is
|
||||
* used the call the syscall function.
|
||||
*/
|
||||
fn main() {
|
||||
let syscalls_inc_path = PathBuf::from("sdk/bpf/c/inc/sol/inc");
|
||||
|
||||
if syscalls_inc_path.is_dir() {
|
||||
for entry in fs::read_dir(syscalls_inc_path).expect("Can't open headers dir") {
|
||||
let entry = entry.expect("Can't open header file");
|
||||
let path = entry.path();
|
||||
if !path.is_dir() {
|
||||
let extension = path.extension();
|
||||
if extension == Some(OsStr::new("inc")) {
|
||||
transform(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform input inc file to a valid C header file replacing
|
||||
* declaration templates with valid C code.
|
||||
*/
|
||||
fn transform(inc: &PathBuf) {
|
||||
let inc_path = PathBuf::from(inc);
|
||||
let filename = match inc_path.file_name() {
|
||||
Some(f) => f,
|
||||
None => return,
|
||||
};
|
||||
let parent = match inc_path.parent() {
|
||||
Some(f) => f,
|
||||
None => return,
|
||||
};
|
||||
let parent = match parent.parent() {
|
||||
Some(f) => f,
|
||||
None => return,
|
||||
};
|
||||
let mut header_path = PathBuf::from(parent);
|
||||
let mut filename = PathBuf::from(filename);
|
||||
filename.set_extension("h");
|
||||
header_path.push(filename);
|
||||
info!(
|
||||
"Transforming file {} -> {}",
|
||||
inc.display(),
|
||||
header_path.display()
|
||||
);
|
||||
let mut input = match fs::File::open(inc) {
|
||||
Ok(x) => x,
|
||||
Err(err) => panic!("Failed to open {}: {}", inc.display(), err),
|
||||
};
|
||||
let mut input_content = vec![];
|
||||
input.read_to_end(&mut input_content).unwrap();
|
||||
let input_content = str::from_utf8(&input_content).unwrap();
|
||||
let output = match fs::File::create(&header_path) {
|
||||
Ok(x) => x,
|
||||
Err(err) => panic!("Failed to create {}: {}", header_path.display(), err),
|
||||
};
|
||||
let mut output_writer = BufWriter::new(output);
|
||||
let decl_re =
|
||||
Regex::new(r"@SYSCALL ([0-9A-Za-z_*]+)[[:space:]]+(sol_[0-9A-Za-z_]+)\(([^);]*)\);")
|
||||
.unwrap();
|
||||
let comm_re = Regex::new(r",").unwrap();
|
||||
let output_content = decl_re.replace_all(input_content, |caps: &Captures| {
|
||||
let ty = &caps[1].to_string();
|
||||
let func = &caps[2].to_string();
|
||||
let args = &caps[3].to_string();
|
||||
let ifndef = format!("#ifndef SOL_SBFV2\n{} {}({});", ty, func, args);
|
||||
let hash = sys_hash(func);
|
||||
let typedef_statement = format!("typedef {}(*{}_pointer_type)({});", ty, func, args);
|
||||
let mut arg = 0;
|
||||
let mut arg_list = "".to_string();
|
||||
if !args.is_empty() {
|
||||
arg_list = comm_re
|
||||
.replace_all(args, |_caps: &Captures| {
|
||||
arg += 1;
|
||||
format!(" arg{},", arg)
|
||||
})
|
||||
.to_string();
|
||||
arg += 1;
|
||||
arg_list = format!("{} arg{}", arg_list, arg);
|
||||
}
|
||||
let function_signature = format!("static {} {}({})", ty, func, arg_list);
|
||||
let pointer_assignment = format!(
|
||||
"{}_pointer_type {}_pointer = ({}_pointer_type) {};",
|
||||
func, func, func, hash
|
||||
);
|
||||
if !args.is_empty() {
|
||||
arg_list = "arg1".to_string();
|
||||
for a in 2..arg + 1 {
|
||||
arg_list = format!("{}, arg{}", arg_list, a);
|
||||
}
|
||||
}
|
||||
let return_statement = if ty == "void" {
|
||||
format!("{}_pointer({});", func, arg_list)
|
||||
} else {
|
||||
format!("return {}_pointer({});", func, arg_list)
|
||||
};
|
||||
format!(
|
||||
"{}\n#else\n{}\n{} {{\n {}\n {}\n}}\n#endif",
|
||||
ifndef, typedef_statement, function_signature, pointer_assignment, return_statement,
|
||||
)
|
||||
});
|
||||
write!(output_writer, "{}", output_content).unwrap();
|
||||
}
|
||||
|
||||
const fn sys_hash(name: &str) -> usize {
|
||||
murmur3_32(name.as_bytes(), 0) as usize
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
const fn murmur3_32(buf: &[u8], seed: u32) -> u32 {
|
||||
let mut hash = seed;
|
||||
let mut i = 0;
|
||||
while i < buf.len() / 4 {
|
||||
let buf = [buf[i * 4], buf[i * 4 + 1], buf[i * 4 + 2], buf[i * 4 + 3]];
|
||||
hash ^= pre_mix(buf);
|
||||
hash = hash.rotate_left(13);
|
||||
hash = hash.wrapping_mul(5).wrapping_add(0xe6546b64);
|
||||
|
||||
i += 1;
|
||||
}
|
||||
match buf.len() % 4 {
|
||||
0 => {}
|
||||
1 => {
|
||||
hash ^= pre_mix([buf[i * 4], 0, 0, 0]);
|
||||
}
|
||||
2 => {
|
||||
hash ^= pre_mix([buf[i * 4], buf[i * 4 + 1], 0, 0]);
|
||||
}
|
||||
3 => {
|
||||
hash ^= pre_mix([buf[i * 4], buf[i * 4 + 1], buf[i * 4 + 2], 0]);
|
||||
}
|
||||
_ => { /* unreachable!() */ }
|
||||
}
|
||||
|
||||
hash ^= buf.len() as u32;
|
||||
hash ^= hash.wrapping_shr(16);
|
||||
hash = hash.wrapping_mul(0x85ebca6b);
|
||||
hash ^= hash.wrapping_shr(13);
|
||||
hash = hash.wrapping_mul(0xc2b2ae35);
|
||||
hash ^= hash.wrapping_shr(16);
|
||||
|
||||
hash
|
||||
}
|
||||
|
||||
const fn pre_mix(buf: [u8; 4]) -> u32 {
|
||||
u32::from_le_bytes(buf)
|
||||
.wrapping_mul(0xcc9e2d51)
|
||||
.rotate_left(15)
|
||||
.wrapping_mul(0x1b873593)
|
||||
}
|
Loading…
Reference in New Issue