Migrate SDK from BPF to SBF

This commit is contained in:
Dmitri Makarov 2022-09-28 17:24:42 -04:00 committed by Dmitri Makarov
parent c10c2f80d0
commit f4dd24491f
59 changed files with 2596 additions and 97 deletions

2
Cargo.lock generated
View File

@ -4775,6 +4775,8 @@ version = "1.15.0"
dependencies = [
"cargo_metadata",
"clap 3.1.8",
"log",
"solana-logger 1.15.0",
"solana-sdk 1.15.0",
]

View File

@ -163,13 +163,13 @@ all_test_steps() {
command_step stable ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-stable.sh" 70
wait_step
# BPF test suite
# SBF test suite
if affects \
.rs$ \
Cargo.lock$ \
Cargo.toml$ \
^ci/rust-version.sh \
^ci/test-stable-bpf.sh \
^ci/test-stable-sbf.sh \
^ci/test-stable.sh \
^ci/test-local-cluster.sh \
^core/build.rs \
@ -178,16 +178,16 @@ all_test_steps() {
^sdk/ \
; then
cat >> "$output_file" <<"EOF"
- command: "ci/test-stable-bpf.sh"
name: "stable-bpf"
- command: "ci/test-stable-sbf.sh"
name: "stable-sbf"
timeout_in_minutes: 35
artifact_paths: "bpf-dumps.tar.bz2"
artifact_paths: "sbf-dumps.tar.bz2"
agents:
queue: "gcp"
EOF
else
annotate --style info \
"Stable-BPF skipped as no relevant files were modified"
"Stable-SBF skipped as no relevant files were modified"
fi
# Perf test suite

View File

@ -163,13 +163,13 @@ all_test_steps() {
fi
wait_step
# BPF test suite
# SBF test suite
if affects \
.rs$ \
Cargo.lock$ \
Cargo.toml$ \
^ci/rust-version.sh \
^ci/test-stable-bpf.sh \
^ci/test-stable-sbf.sh \
^ci/test-stable.sh \
^ci/test-local-cluster.sh \
^core/build.rs \
@ -178,16 +178,16 @@ all_test_steps() {
^sdk/ \
; then
cat >> "$output_file" <<"EOF"
- command: "ci/test-stable-bpf.sh"
name: "stable-bpf"
- command: "ci/test-stable-sbf.sh"
name: "stable-sbf"
timeout_in_minutes: 35
artifact_paths: "bpf-dumps.tar.bz2"
artifact_paths: "sbf-dumps.tar.bz2"
agents:
queue: "gcp"
EOF
else
annotate --style info \
"Stable-BPF skipped as no relevant files were modified"
"Stable-SBF skipped as no relevant files were modified"
fi
# Perf test suite

View File

@ -163,13 +163,13 @@ all_test_steps() {
fi
wait_step
# BPF test suite
# SBF test suite
if affects \
.rs$ \
Cargo.lock$ \
Cargo.toml$ \
^ci/rust-version.sh \
^ci/test-stable-bpf.sh \
^ci/test-stable-sbf.sh \
^ci/test-stable.sh \
^ci/test-local-cluster.sh \
^core/build.rs \
@ -178,16 +178,16 @@ all_test_steps() {
^sdk/ \
; then
cat >> "$output_file" <<"EOF"
- command: "ci/test-stable-bpf.sh"
name: "stable-bpf"
- command: "ci/test-stable-sbf.sh"
name: "stable-sbf"
timeout_in_minutes: 35
artifact_paths: "bpf-dumps.tar.bz2"
artifact_paths: "sbf-dumps.tar.bz2"
agents:
queue: "sol-private"
EOF
else
annotate --style info \
"Stable-BPF skipped as no relevant files were modified"
"Stable-SBF skipped as no relevant files were modified"
fi
# Perf test suite

View File

@ -25,9 +25,9 @@ declare print_free_tree=(
':metrics/src/**.rs'
':net-utils/src/**.rs'
':runtime/src/**.rs'
':sdk/bpf/rust/rust-utils/**.rs'
':sdk/sbf/rust/rust-utils/**.rs'
':sdk/**.rs'
':^sdk/cargo-build-bpf/**.rs'
':^sdk/cargo-build-sbf/**.rs'
':^sdk/program/src/program_option.rs'
':^sdk/program/src/program_stubs.rs'
':programs/**.rs'

View File

@ -102,10 +102,10 @@ MAYBE_TARBALLS=
if [[ "$CI_OS_NAME" = linux ]]; then
(
set -x
sdk/bpf/scripts/package.sh
[[ -f bpf-sdk.tar.bz2 ]]
sdk/sbf/scripts/package.sh
[[ -f sbf-sdk.tar.bz2 ]]
)
MAYBE_TARBALLS="bpf-sdk.tar.bz2"
MAYBE_TARBALLS="sbf-sdk.tar.bz2"
fi
source ci/upload-ci-artifact.sh

View File

@ -12,7 +12,7 @@ steps+=(shellcheck)
steps+=(test-checks)
steps+=(test-coverage)
steps+=(test-stable)
steps+=(test-stable-bpf)
steps+=(test-stable-sbf)
steps+=(test-stable-perf)
steps+=(test-downstream-builds)
steps+=(test-bench)

View File

@ -28,8 +28,8 @@ _ "$cargo" build --manifest-path=keygen/Cargo.toml
export PATH="$PWD/target/debug":$PATH
# Clear the C dependency files, if dependency moves these files are not regenerated
test -d target/debug/bpf && find target/debug/bpf -name '*.d' -delete
test -d target/release/bpf && find target/release/bpf -name '*.d' -delete
test -d target/debug/sbf && find target/debug/sbf -name '*.d' -delete
test -d target/release/sbf && find target/release/sbf -name '*.d' -delete
# Ensure all dependencies are built
_ "$cargo" nightly build --release
@ -57,7 +57,7 @@ _ "$cargo" nightly bench --manifest-path poh/Cargo.toml ${V:+--verbose} \
_ "$cargo" nightly bench --manifest-path core/Cargo.toml ${V:+--verbose} \
-- -Z unstable-options --format=json | tee -a "$BENCH_FILE"
# Run bpf benches
# Run sbf benches
_ "$cargo" nightly bench --manifest-path programs/bpf/Cargo.toml ${V:+--verbose} --features=bpf_c \
-- -Z unstable-options --format=json --nocapture | tee -a "$BENCH_FILE"

View File

@ -68,25 +68,25 @@ test-stable)
_ "$cargo" stable test --jobs "$JOBS" --all --tests --exclude solana-local-cluster ${V:+--verbose} -- --nocapture
fi
;;
test-stable-bpf)
test-stable-sbf)
# Clear the C dependency files, if dependency moves these files are not regenerated
test -d target/debug/bpf && find target/debug/bpf -name '*.d' -delete
test -d target/release/bpf && find target/release/bpf -name '*.d' -delete
test -d target/debug/sbf && find target/debug/sbf -name '*.d' -delete
test -d target/release/sbf && find target/release/sbf -name '*.d' -delete
# rustfilt required for dumping BPF assembly listings
# rustfilt required for dumping SBF assembly listings
"$cargo" install rustfilt
# solana-keygen required when building C programs
_ "$cargo" build --manifest-path=keygen/Cargo.toml
export PATH="$PWD/target/debug":$PATH
cargo_build_bpf="$(realpath ./cargo-build-bpf)"
cargo_test_bpf="$(realpath ./cargo-test-bpf)"
cargo_build_sbf="$(realpath ./cargo-build-sbf)"
cargo_test_sbf="$(realpath ./cargo-test-sbf)"
# BPF solana-sdk legacy compile test
"$cargo_build_bpf" --manifest-path sdk/Cargo.toml
# SBF solana-sdk legacy compile test
"$cargo_build_sbf" --manifest-path sdk/Cargo.toml
# BPF C program system tests
# SBF C program system tests
_ make -C programs/bpf/c tests
if need_to_generate_test_result; then
_ "$cargo" stable test \
@ -99,16 +99,16 @@ test-stable-bpf)
--no-default-features --features=bpf_c,bpf_rust -- --nocapture
fi
# BPF Rust program unit tests
for bpf_test in programs/bpf/rust/*; do
if pushd "$bpf_test"; then
# SBF Rust program unit tests
for sbf_test in programs/bpf/rust/*; do
if pushd "$sbf_test"; then
"$cargo" test
"$cargo_build_bpf" --bpf-sdk ../../../../sdk/bpf --dump
"$cargo_test_bpf" --bpf-sdk ../../../../sdk/bpf
"$cargo_build_sbf" --sbf-sdk ../../../../sdk/sbf --dump
"$cargo_test_sbf" --sbf-sdk ../../../../sdk/sbf
popd
fi
done |& tee cargo.log
# Save the output of cargo building the bpf tests so we can analyze
# Save the output of cargo building the sbf tests so we can analyze
# the number of redundant rebuilds of dependency crates. The
# expected number of solana-program crate compilations is 4. There
# should be 3 builds of solana-program while 128bit crate is
@ -125,27 +125,27 @@ test-stable-bpf)
exit 1
fi
# bpf-tools version
"$cargo_build_bpf" -V
# sbf-tools version
"$cargo_build_sbf" -V
# BPF program instruction count assertion
bpf_target_path=programs/bpf/target
# SBF program instruction count assertion
sbf_target_path=programs/bpf/target
if need_to_generate_test_result; then
_ "$cargo" stable test \
--manifest-path programs/bpf/Cargo.toml \
--no-default-features --features=bpf_c,bpf_rust assert_instruction_count \
-- -Z unstable-options --format json --report-time |& tee results.json
awk '!/{ "type": .* }/' results.json >"${bpf_target_path}"/deploy/instuction_counts.txt
awk '!/{ "type": .* }/' results.json >"${sbf_target_path}"/deploy/instuction_counts.txt
else
_ "$cargo" stable test \
--manifest-path programs/bpf/Cargo.toml \
--no-default-features --features=bpf_c,bpf_rust assert_instruction_count \
-- --nocapture &> "${bpf_target_path}"/deploy/instuction_counts.txt
-- --nocapture &> "${sbf_target_path}"/deploy/instuction_counts.txt
fi
bpf_dump_archive="bpf-dumps.tar.bz2"
rm -f "$bpf_dump_archive"
tar cjvf "$bpf_dump_archive" "${bpf_target_path}"/{deploy/*.txt,bpfel-unknown-unknown/release/*.so}
sbf_dump_archive="sbf-dumps.tar.bz2"
rm -f "$sbf_dump_archive"
tar cjvf "$sbf_dump_archive" "${sbf_target_path}"/{deploy/*.txt,sbf-solana-solana/release/*.so}
exit 0
;;
test-stable-perf)

View File

@ -18,10 +18,10 @@ The `makefile` should contain the following:
```bash
OUT_DIR := <path to place to resulting shared object>
include ~/.local/share/solana/install/active_release/bin/sdk/bpf/c/bpf.mk
include ~/.local/share/solana/install/active_release/bin/sdk/sbf/c/sbf.mk
```
The bpf-sdk may not be in the exact place specified above but if you setup your
The sbf-sdk may not be in the exact place specified above but if you setup your
environment per [How to Build](#how-to-build) then it should be.
Take a look at
@ -56,14 +56,14 @@ information on how to write a test case.
## Program Entrypoint
Programs export a known entrypoint symbol which the Solana runtime looks up and
calls when invoking a program. Solana supports multiple [versions of the BPF
calls when invoking a program. Solana supports multiple [versions of the SBF
loader](overview.md#versions) and the entrypoints may vary between them.
Programs must be written for and deployed to the same loader. For more details
see the [overview](overview#loaders).
Currently there are two supported loaders [BPF
Currently there are two supported loaders [SBF
Loader](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader.rs#L17)
and [BPF loader
and [SBF loader
deprecated](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader_deprecated.rs#L14).
They both have the same raw entrypoint definition, the following is the raw
@ -89,10 +89,10 @@ function](https://github.com/solana-labs/example-helloworld/blob/bc0b25c0ccebeff
Each loader provides a helper function that deserializes the program's input
parameters into C types:
- [BPF Loader
deserialization](https://github.com/solana-labs/solana/blob/d2ee9db2143859fa5dc26b15ee6da9c25cc0429c/sdk/bpf/c/inc/solana_sdk.h#L304)
- [BPF Loader deprecated
deserialization](https://github.com/solana-labs/solana/blob/8415c22b593f164020adc7afe782e8041d756ddf/sdk/bpf/c/inc/deserialize_deprecated.h#L25)
- [SBF Loader
deserialization](https://github.com/solana-labs/solana/blob/d2ee9db2143859fa5dc26b15ee6da9c25cc0429c/sdk/sbf/c/inc/solana_sdk.h#L304)
- [SBF Loader deprecated
deserialization](https://github.com/solana-labs/solana/blob/8415c22b593f164020adc7afe782e8041d756ddf/sdk/sbf/c/inc/deserialize_deprecated.h#L25)
Some programs may want to perform deserialization themselves, and they can by
providing their own implementation of the [raw entrypoint](#program-entrypoint).
@ -109,7 +109,7 @@ Details on how the loader serializes the program inputs can be found in the
## Data Types
The loader's deserialization helper function populates the
[SolParameters](https://github.com/solana-labs/solana/blob/8415c22b593f164020adc7afe782e8041d756ddf/sdk/bpf/c/inc/solana_sdk.h#L276)
[SolParameters](https://github.com/solana-labs/solana/blob/8415c22b593f164020adc7afe782e8041d756ddf/sdk/sbf/c/inc/solana_sdk.h#L276)
structure:
```c
@ -128,7 +128,7 @@ typedef struct {
'ka' is an ordered array of the accounts referenced by the instruction and
represented as a
[SolAccountInfo](https://github.com/solana-labs/solana/blob/8415c22b593f164020adc7afe782e8041d756ddf/sdk/bpf/c/inc/solana_sdk.h#L173)
[SolAccountInfo](https://github.com/solana-labs/solana/blob/8415c22b593f164020adc7afe782e8041d756ddf/sdk/sbf/c/inc/solana_sdk.h#L173)
structures. An account's place in the array signifies its meaning, for example,
when transferring lamports an instruction may define the first account as the
source and the second as the destination.
@ -153,7 +153,7 @@ processed.
## Heap
C programs can allocate memory via the system call
[`calloc`](https://github.com/solana-labs/solana/blob/c3d2d2134c93001566e1e56f691582f379b5ae55/sdk/bpf/c/inc/solana_sdk.h#L245)
[`calloc`](https://github.com/solana-labs/solana/blob/c3d2d2134c93001566e1e56f691582f379b5ae55/sdk/sbf/c/inc/solana_sdk.h#L245)
or implement their own heap on top of the 32KB heap region starting at virtual
address x300000000. The heap region is also used by `calloc` so if a program
implements their own heap it should not also call `calloc`.
@ -163,8 +163,8 @@ implements their own heap it should not also call `calloc`.
The runtime provides two system calls that take data and log it to the program
logs.
- [`sol_log(const char*)`](https://github.com/solana-labs/solana/blob/d2ee9db2143859fa5dc26b15ee6da9c25cc0429c/sdk/bpf/c/inc/solana_sdk.h#L128)
- [`sol_log_64(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)`](https://github.com/solana-labs/solana/blob/d2ee9db2143859fa5dc26b15ee6da9c25cc0429c/sdk/bpf/c/inc/solana_sdk.h#L134)
- [`sol_log(const char*)`](https://github.com/solana-labs/solana/blob/d2ee9db2143859fa5dc26b15ee6da9c25cc0429c/sdk/sbf/c/inc/solana_sdk.h#L128)
- [`sol_log_64(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)`](https://github.com/solana-labs/solana/blob/d2ee9db2143859fa5dc26b15ee6da9c25cc0429c/sdk/sbf/c/inc/solana_sdk.h#L134)
The [debugging](debugging.md#logging) section has more information about working
with program logs.
@ -172,7 +172,7 @@ with program logs.
## Compute Budget
Use the system call
[`sol_log_compute_units()`](https://github.com/solana-labs/solana/blob/d3a3a7548c857f26ec2cb10e270da72d373020ec/sdk/bpf/c/inc/solana_sdk.h#L140)
[`sol_log_compute_units()`](https://github.com/solana-labs/solana/blob/d3a3a7548c857f26ec2cb10e270da72d373020ec/sdk/sbf/c/inc/solana_sdk.h#L140)
to log a message containing the remaining number of compute units the program
may consume before execution is halted
@ -181,10 +181,10 @@ for more information.
## ELF Dump
The BPF shared object internals can be dumped to a text file to gain more
The SBF shared object internals can be dumped to a text file to gain more
insight into a program's composition and what it may be doing at runtime. The
dump will contain both the ELF information as well as a list of all the symbols
and the instructions that implement them. Some of the BPF loader's error log
and the instructions that implement them. Some of the SBF loader's error log
messages will reference specific instruction numbers where the error occurred.
These references can be looked up in the ELF dump to identify the offending
instruction and its context.

View File

@ -1,2 +1,2 @@
BPF_SDK := ../../../sdk/bpf/c
include $(BPF_SDK)/bpf.mk
SBF_SDK := ../../../sdk/sbf/c
include $(SBF_SDK)/sbf.mk

View File

@ -1,2 +1,2 @@
BPF_SDK := ../../../sdk/bpf/c
include $(BPF_SDK)/bpf.mk
SBF_SDK := ../../../sdk/sbf/c
include $(SBF_SDK)/sbf.mk

View File

@ -12,8 +12,8 @@ source scripts/read-cargo-variable.sh
solana_ver=$(readCargoVariable version sdk/Cargo.toml)
solana_dir=$PWD
cargo="$solana_dir"/cargo
cargo_build_bpf="$solana_dir"/cargo-build-bpf
cargo_test_bpf="$solana_dir"/cargo-test-bpf
cargo_build_sbf="$solana_dir"/cargo-build-sbf
cargo_test_sbf="$solana_dir"/cargo-test-sbf
mkdir -p target/downstream-projects-anchor
cd target/downstream-projects-anchor
@ -72,8 +72,8 @@ mango() {
$cargo build
$cargo test
$cargo_build_bpf
$cargo_test_bpf
$cargo_build_sbf
$cargo_test_sbf
)
}
@ -91,8 +91,8 @@ metaplex() {
$cargo build
$cargo test
$cargo_build_bpf
$cargo_test_bpf
$cargo_build_sbf
$cargo_test_sbf
)
}

View File

@ -13,8 +13,8 @@ source scripts/read-cargo-variable.sh
solana_ver=$(readCargoVariable version sdk/Cargo.toml)
solana_dir=$PWD
cargo="$solana_dir"/cargo
cargo_build_bpf="$solana_dir"/cargo-build-bpf
cargo_test_bpf="$solana_dir"/cargo-test-bpf
cargo_build_sbf="$solana_dir"/cargo-build-sbf
cargo_test_sbf="$solana_dir"/cargo-test-sbf
mkdir -p target/downstream-projects
cd target/downstream-projects
@ -30,7 +30,7 @@ example_helloworld() {
patch_crates_io_solana src/program-rust/Cargo.toml "$solana_dir"
echo "[workspace]" >> src/program-rust/Cargo.toml
$cargo_build_bpf \
$cargo_build_sbf \
--manifest-path src/program-rust/Cargo.toml
# TODO: Build src/program-c/...
@ -68,7 +68,7 @@ spl() {
./patch.crates-io.sh "$solana_dir"
for program in "${PROGRAMS[@]}"; do
$cargo_test_bpf --manifest-path "$program"/Cargo.toml
$cargo_test_sbf --manifest-path "$program"/Cargo.toml
done
# TODO better: `build.rs` for spl-token-cli doesn't seem to properly build
@ -98,7 +98,7 @@ exclude = [
EOF
$cargo build
$cargo_build_bpf \
$cargo_build_sbf \
--manifest-path dex/Cargo.toml --no-default-features --features program
$cargo test \

View File

@ -161,8 +161,8 @@ if [[ -z "$validatorOnly" ]]; then
"$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
mkdir -p "$installDir"/bin/sdk/sbf
cp -a sdk/sbf/* "$installDir"/bin/sdk/sbf
fi
(

View File

@ -12,6 +12,8 @@ publish = false
[dependencies]
cargo_metadata = "0.15.0"
clap = { version = "3.1.5", features = ["cargo", "env"] }
log = { version = "0.4.14", features = ["std"] }
solana-logger = { path = "../../logger", version = "=1.15.0" }
solana-sdk = { path = "..", version = "=1.15.0" }
[features]

View File

@ -1,11 +1,15 @@
use std::{
env,
path::PathBuf,
process::{exit, Command, Stdio},
use {
log::*,
std::{
env,
path::PathBuf,
process::{exit, Command, Stdio},
},
};
fn main() {
println!("Warning: cargo-build-bpf is deprecated. Please, use cargo-build-sbf");
solana_logger::setup();
warn!("cargo-build-bpf is deprecated. Please, use cargo-build-sbf");
let mut args = env::args()
.map(|x| {
let s = x;
@ -29,22 +33,21 @@ fn main() {
let index = args.iter().position(|x| x == "--").unwrap_or(args.len());
args.insert(index, "bpf".to_string());
args.insert(index, "--arch".to_string());
print!("cargo-build-bpf child: {}", program.display());
info!("cargo-build-bpf child: {}", program.display());
for a in &args {
print!(" {}", a);
info!(" {}", a);
}
println!();
let child = Command::new(&program)
.args(&args)
.stdout(Stdio::piped())
.spawn()
.unwrap_or_else(|err| {
eprintln!("Failed to execute {}: {}", program.display(), err);
error!("Failed to execute {}: {}", program.display(), err);
exit(1);
});
let output = child.wait_with_output().expect("failed to wait on child");
println!(
info!(
"{}",
output
.stdout

View File

@ -48,7 +48,7 @@ impl Default for Config<'_> {
.expect("Unable to get parent directory")
.to_path_buf()
.join("sdk")
.join("bpf"),
.join("sbf"),
sbf_out_dir: None,
sbf_tools_version: "(unknown)",
dump: false,
@ -526,7 +526,7 @@ fn build_sbf_package(config: &Config, target_directory: &Path, package: &cargo_m
install_if_missing(
config,
package,
"https://github.com/solana-labs/bpf-tools/releases/download",
"https://github.com/solana-labs/sbf-tools/releases/download",
sbf_tools_download_file_name,
&target_path,
)

11
sdk/sbf/.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
/dependencies/criterion*
/dependencies/hashbrown*
/dependencies/llvm-native*
/dependencies/rust-bpf-sysroot*
/dependencies/bpf-tools*
/dependencies/sbf-tools*
/dependencies/xargo*
/dependencies/bin*
/dependencies/.crates.toml
/dependencies/.crates2.json
/syscalls.txt

44
sdk/sbf/c/README.md Normal file
View File

@ -0,0 +1,44 @@
## Development
### Quick start
To get started create a `makefile` containing:
```make
include path/to/sbf.mk
```
and `src/program.c` containing:
```c
#include <solana_sdk.h>
bool entrypoint(const uint8_t *input) {
SolKeyedAccount ka[1];
uint8_t *data;
uint64_t data_len;
if (!sol_deserialize(buf, ka, SOL_ARRAY_SIZE(ka), NULL, &data, &data_len)) {
return false;
}
print_params(1, ka, data, data_len);
return true;
}
```
Then run `make` to build `out/program.o`.
Run `make help` for more details.
### Unit tests
Built-in support for unit testing is provided by the
[Criterion](https://criterion.readthedocs.io/en/master/index.html) test framework.
To get started create the file `test/example.c` containing:
```c
#include <criterion/criterion.h>
#include "../src/program.c"
Test(test_suite_name, test_case_name) {
cr_assert(true);
}
```
Then run `make test`.
### Limitations
* Programs must be fully contained within a single .c file
* No libc is available but `solana_sdk.h` provides a minimal set of primitives

View File

@ -0,0 +1 @@
#include <sol/deserialize_deprecated.h>

View File

@ -0,0 +1,56 @@
#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
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/assert.inc AND RUN `cargo run --bin gen-headers` */
#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)
/**
* 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
/**@}*/

View File

@ -0,0 +1,39 @@
#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
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/blake3.inc AND RUN `cargo run --bin gen-headers` */
#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
}
#endif
/**@}*/

138
sdk/sbf/c/inc/sol/cpi.h Normal file
View File

@ -0,0 +1,138 @@
#pragma once
/**
* @brief Solana Cross-Program Invocation
*/
#include <sol/types.h>
#include <sol/pubkey.h>
#include <sol/entrypoint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Maximum CPI instruction data size. 10 KiB was chosen to ensure that CPI
* instructions are not more limited than transaction instructions if the size
* of transactions is doubled in the future.
*/
static const uint64_t MAX_CPI_INSTRUCTION_DATA_LEN = 10240;
/**
* Maximum CPI instruction accounts. 255 was chosen to ensure that instruction
* accounts are always within the maximum instruction account limit for BPF
* program instructions.
*/
static const uint8_t MAX_CPI_INSTRUCTION_ACCOUNTS = 255;
/**
* Maximum number of account info structs that can be used in a single CPI
* invocation. A limit on account info structs is effectively the same as
* limiting the number of unique accounts. 128 was chosen to match the max
* number of locked accounts per transaction (MAX_TX_ACCOUNT_LOCKS).
*/
static const uint16_t MAX_CPI_ACCOUNT_INFOS = 128;
/**
* 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
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/cpi.inc AND RUN `cargo run --bin gen-headers` */
#ifndef SOL_SBFV2
uint64_t sol_invoke_signed_c(
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
*
* @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
/**@}*/

View File

@ -0,0 +1,137 @@
#pragma once
/**
* @brief Solana BPF loader deserializer to be used when deploying
* a program with `BPFLoader2111111111111111111111111111111111` or
* `BPFLoaderUpgradeab1e11111111111111111111111`
*/
#include <sol/types.h>
#include <sol/pubkey.h>
#include <sol/entrypoint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Maximum number of bytes a program may add to an account during a single realloc
*/
#define MAX_PERMITTED_DATA_INCREASE (1024 * 10)
/**
* De-serializes the input parameters into usable types
*
* Use this function to deserialize the buffer passed to the program entrypoint
* into usable types. This function does not perform copy deserialization,
* instead it populates the pointers and lengths in SolAccountInfo and data so
* that any modification to lamports or account data take place on the original
* buffer. Doing so also eliminates the need to serialize back into the buffer
* at the end of the program.
*
* @param input Source buffer containing serialized input parameters
* @param params Pointer to a SolParameters structure
* @return Boolean true if successful.
*/
static bool sol_deserialize(
const uint8_t *input,
SolParameters *params,
uint64_t ka_num
) {
if (NULL == input || NULL == params) {
return false;
}
params->ka_num = *(uint64_t *) input;
input += sizeof(uint64_t);
for (int i = 0; i < params->ka_num; i++) {
uint8_t dup_info = input[0];
input += sizeof(uint8_t);
if (i >= ka_num) {
if (dup_info == UINT8_MAX) {
input += sizeof(uint8_t);
input += sizeof(uint8_t);
input += sizeof(uint8_t);
input += 4; // padding
input += sizeof(SolPubkey);
input += sizeof(SolPubkey);
input += sizeof(uint64_t);
uint64_t data_len = *(uint64_t *) input;
input += sizeof(uint64_t);
input += data_len;
input += MAX_PERMITTED_DATA_INCREASE;
input = (uint8_t*)(((uint64_t)input + 8 - 1) & ~(8 - 1)); // padding
input += sizeof(uint64_t);
} else {
input += 7; // padding
}
continue;
}
if (dup_info == UINT8_MAX) {
// is signer?
params->ka[i].is_signer = *(uint8_t *) input != 0;
input += sizeof(uint8_t);
// is writable?
params->ka[i].is_writable = *(uint8_t *) input != 0;
input += sizeof(uint8_t);
// executable?
params->ka[i].executable = *(uint8_t *) input;
input += sizeof(uint8_t);
input += 4; // padding
// key
params->ka[i].key = (SolPubkey *) input;
input += sizeof(SolPubkey);
// owner
params->ka[i].owner = (SolPubkey *) input;
input += sizeof(SolPubkey);
// lamports
params->ka[i].lamports = (uint64_t *) input;
input += sizeof(uint64_t);
// account data
params->ka[i].data_len = *(uint64_t *) input;
input += sizeof(uint64_t);
params->ka[i].data = (uint8_t *) input;
input += params->ka[i].data_len;
input += MAX_PERMITTED_DATA_INCREASE;
input = (uint8_t*)(((uint64_t)input + 8 - 1) & ~(8 - 1)); // padding
// rent epoch
params->ka[i].rent_epoch = *(uint64_t *) input;
input += sizeof(uint64_t);
} else {
params->ka[i].is_signer = params->ka[dup_info].is_signer;
params->ka[i].is_writable = params->ka[dup_info].is_writable;
params->ka[i].executable = params->ka[dup_info].executable;
params->ka[i].key = params->ka[dup_info].key;
params->ka[i].owner = params->ka[dup_info].owner;
params->ka[i].lamports = params->ka[dup_info].lamports;
params->ka[i].data_len = params->ka[dup_info].data_len;
params->ka[i].data = params->ka[dup_info].data;
params->ka[i].rent_epoch = params->ka[dup_info].rent_epoch;
input += 7; // padding
}
}
params->data_len = *(uint64_t *) input;
input += sizeof(uint64_t);
params->data = input;
input += params->data_len;
params->program_id = (SolPubkey *) input;
input += sizeof(SolPubkey);
return true;
}
#ifdef __cplusplus
}
#endif
/**@}*/

View File

@ -0,0 +1,119 @@
#pragma once
/**
* @brief Solana deprecated BPF loader deserializer to be used when deploying
* a program with `BPFLoader1111111111111111111111111111111111`
*/
#include <sol/types.h>
#include <sol/pubkey.h>
#include <sol/entrypoint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* De-serializes the input parameters into usable types
*
* Use this function to deserialize the buffer passed to the program entrypoint
* into usable types. This function does not perform copy deserialization,
* instead it populates the pointers and lengths in SolAccountInfo and data so
* that any modification to lamports or account data take place on the original
* buffer. Doing so also eliminates the need to serialize back into the buffer
* at the end of the program.
*
* @param input Source buffer containing serialized input parameters
* @param params Pointer to a SolParameters structure
* @return Boolean true if successful.
*/
static bool sol_deserialize_deprecated(
const uint8_t *input,
SolParameters *params,
uint64_t ka_num
) {
if (NULL == input || NULL == params) {
return false;
}
params->ka_num = *(uint64_t *) input;
input += sizeof(uint64_t);
for (int i = 0; i < params->ka_num; i++) {
uint8_t dup_info = input[0];
input += sizeof(uint8_t);
if (i >= ka_num) {
if (dup_info == UINT8_MAX) {
input += sizeof(uint8_t);
input += sizeof(uint8_t);
input += sizeof(SolPubkey);
input += sizeof(uint64_t);
input += *(uint64_t *) input;
input += sizeof(uint64_t);
input += sizeof(SolPubkey);
input += sizeof(uint8_t);
input += sizeof(uint64_t);
}
continue;
}
if (dup_info == UINT8_MAX) {
// is signer?
params->ka[i].is_signer = *(uint8_t *) input != 0;
input += sizeof(uint8_t);
// is writable?
params->ka[i].is_writable = *(uint8_t *) input != 0;
input += sizeof(uint8_t);
// key
params->ka[i].key = (SolPubkey *) input;
input += sizeof(SolPubkey);
// lamports
params->ka[i].lamports = (uint64_t *) input;
input += sizeof(uint64_t);
// account data
params->ka[i].data_len = *(uint64_t *) input;
input += sizeof(uint64_t);
params->ka[i].data = (uint8_t *) input;
input += params->ka[i].data_len;
// owner
params->ka[i].owner = (SolPubkey *) input;
input += sizeof(SolPubkey);
// executable?
params->ka[i].executable = *(uint8_t *) input;
input += sizeof(uint8_t);
// rent epoch
params->ka[i].rent_epoch = *(uint64_t *) input;
input += sizeof(uint64_t);
} else {
params->ka[i].is_signer = params->ka[dup_info].is_signer;
params->ka[i].key = params->ka[dup_info].key;
params->ka[i].lamports = params->ka[dup_info].lamports;
params->ka[i].data_len = params->ka[dup_info].data_len;
params->ka[i].data = params->ka[dup_info].data;
params->ka[i].owner = params->ka[dup_info].owner;
params->ka[i].executable = params->ka[dup_info].executable;
params->ka[i].rent_epoch = params->ka[dup_info].rent_epoch;
}
}
params->data_len = *(uint64_t *) input;
input += sizeof(uint64_t);
params->data = input;
input += params->data_len;
params->program_id = (SolPubkey *) input;
input += sizeof(SolPubkey);
return true;
}
#ifdef __cplusplus
}
#endif
/**@}*/

View File

@ -0,0 +1,66 @@
#pragma once
/**
* @brief Solana program entrypoint
*/
#include <sol/types.h>
#include <sol/pubkey.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Keyed Account
*/
typedef struct {
SolPubkey *key; /** Public key of the account */
uint64_t *lamports; /** Number of lamports owned by this account */
uint64_t data_len; /** Length of data in bytes */
uint8_t *data; /** On-chain data within this account */
SolPubkey *owner; /** Program that owns this account */
uint64_t rent_epoch; /** The epoch at which this account will next owe rent */
bool is_signer; /** Transaction was signed by this account's key? */
bool is_writable; /** Is the account writable? */
bool executable; /** This account's data contains a loaded program (and is now read-only) */
} SolAccountInfo;
/**
* The Solana runtime provides a memory region that is available to programs at
* a fixed virtual address and length. The builtin functions `sol_calloc` and
* `sol_free` call into the Solana runtime to allocate from this memory region
* for heap operations. Because the memory region is directly available to
* programs another option is a program can implement their own heap directly on
* top of that region. If a program chooses to implement their own heap they
* should not call the builtin heap functions because they will conflict.
* `HEAP_START_ADDRESS` and `HEAP_LENGTH` specify the memory region's start
* virtual address and length.
*/
#define HEAP_START_ADDRESS (uint64_t)0x300000000
#define HEAP_LENGTH (uint64_t)(32 * 1024)
/**
* Structure that the program's entrypoint input data is deserialized into.
*/
typedef struct {
SolAccountInfo* ka; /** Pointer to an array of SolAccountInfo, must already
point to an array of SolAccountInfos */
uint64_t ka_num; /** Number of SolAccountInfo entries in `ka` */
const uint8_t *data; /** pointer to the instruction data */
uint64_t data_len; /** Length in bytes of the instruction data */
const SolPubkey *program_id; /** program_id of the currently executing program */
} SolParameters;
/**
* Program instruction entrypoint
*
* @param input Buffer of serialized input parameters. Use sol_deserialize() to decode
* @return 0 if the instruction executed successfully
*/
uint64_t entrypoint(const uint8_t *input);
#ifdef __cplusplus
}
#endif
/**@}*/

View File

@ -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
/**@}*/

View File

@ -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
/**@}*/

View File

@ -0,0 +1,117 @@
#pragma once
/**
* @brief Solana Cross-Program Invocation
*/
#include <sol/types.h>
#include <sol/pubkey.h>
#include <sol/entrypoint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Maximum CPI instruction data size. 10 KiB was chosen to ensure that CPI
* instructions are not more limited than transaction instructions if the size
* of transactions is doubled in the future.
*/
static const uint64_t MAX_CPI_INSTRUCTION_DATA_LEN = 10240;
/**
* Maximum CPI instruction accounts. 255 was chosen to ensure that instruction
* accounts are always within the maximum instruction account limit for BPF
* program instructions.
*/
static const uint8_t MAX_CPI_INSTRUCTION_ACCOUNTS = 255;
/**
* Maximum number of account info structs that can be used in a single CPI
* invocation. A limit on account info structs is effectively the same as
* limiting the number of unique accounts. 128 was chosen to match the max
* number of locked accounts per transaction (MAX_TX_ACCOUNT_LOCKS).
*/
static const uint16_t MAX_CPI_ACCOUNT_INFOS = 128;
/**
* 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
/**@}*/

View File

@ -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
/**@}*/

View File

@ -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
/**@}*/

View File

@ -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
/**@}*/

View File

@ -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(uint8_t *, uint64_t, SolPubkey *);
#ifdef __cplusplus
}
#endif
/**@}*/

View File

@ -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
/**@}*/

View File

@ -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
/**@}*/

View File

@ -0,0 +1,39 @@
#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
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/keccak.inc AND RUN `cargo run --bin gen-headers` */
#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
}
#endif
/**@}*/

139
sdk/sbf/c/inc/sol/log.h Normal file
View File

@ -0,0 +1,139 @@
#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
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/log.inc AND RUN `cargo run --bin gen-headers` */
#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
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/log.inc AND RUN `cargo run --bin gen-headers` */
#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
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/log.inc AND RUN `cargo run --bin gen-headers` */
#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_()
/**
* 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.
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/log.inc AND RUN `cargo run --bin gen-headers` */
#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
*
* @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
/**@}*/

134
sdk/sbf/c/inc/sol/pubkey.h Normal file
View File

@ -0,0 +1,134 @@
#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
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/pubkey.inc AND RUN `cargo run --bin gen-headers` */
#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
*
* @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
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/pubkey.inc AND RUN `cargo run --bin gen-headers` */
#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
*
* @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
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/pubkey.inc AND RUN `cargo run --bin gen-headers` */
#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
/**
* 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
/**@}*/

View File

@ -0,0 +1,59 @@
#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.
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/return_data.inc AND RUN `cargo run --bin gen-headers` */
#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
*
* @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)
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/return_data.inc AND RUN `cargo run --bin gen-headers` */
#ifndef SOL_SBFV2
uint64_t sol_get_return_data(uint8_t *, uint64_t, SolPubkey *);
#else
typedef uint64_t(*sol_get_return_data_pointer_type)(uint8_t *, uint64_t, SolPubkey *);
static uint64_t sol_get_return_data(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
}
#endif
/**@}*/

View File

@ -0,0 +1,50 @@
#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
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/secp256k1.inc AND RUN `cargo run --bin gen-headers` */
#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
}
#endif
/**@}*/

39
sdk/sbf/c/inc/sol/sha.h Normal file
View File

@ -0,0 +1,39 @@
#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
*/
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/sha.inc AND RUN `cargo run --bin gen-headers` */
#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
}
#endif
/**@}*/

123
sdk/sbf/c/inc/sol/string.h Normal file
View File

@ -0,0 +1,123 @@
#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--;
}
return b;
}
/**
* Find length of string
*/
static size_t sol_strlen(const char *s) {
size_t len = 0;
while (*s) {
len++;
s++;
}
return len;
}
/**
* Start address of the memory region used for program heap.
*/
#define HEAP_START_ADDRESS (0x300000000)
/**
* Length of the heap memory region used for program heap.
*/
#define HEAP_LENGTH (32 * 1024)
/**
* Alloc zero-initialized memory
*/
static void *sol_calloc(size_t nitems, size_t size) {
// Bump allocator
uint64_t* pos_ptr = (uint64_t*)HEAP_START_ADDRESS;
uint64_t pos = *pos_ptr;
if (pos == 0) {
/** First time, set starting position */
pos = HEAP_START_ADDRESS + HEAP_LENGTH;
}
uint64_t bytes = (uint64_t)(nitems * size);
if (size == 0 ||
!(nitems == 0 || size == 0) &&
!(nitems == bytes / size)) {
/** Overflow */
return NULL;
}
if (pos < bytes) {
/** Saturated */
pos = 0;
} else {
pos -= bytes;
}
uint64_t align = size;
align--;
align |= align >> 1;
align |= align >> 2;
align |= align >> 4;
align |= align >> 8;
align |= align >> 16;
align |= align >> 32;
align++;
pos &= ~(align - 1);
if (pos < HEAP_START_ADDRESS + sizeof(uint8_t*)) {
return NULL;
}
*pos_ptr = pos;
return (void*)pos;
}
/**
* Deallocates the memory previously allocated by sol_calloc
*/
static void sol_free(void *ptr) {
// I'm a bump allocator, I don't free
}
#ifdef __cplusplus
}
#endif
/**@}*/

141
sdk/sbf/c/inc/sol/types.h Normal file
View File

@ -0,0 +1,141 @@
#pragma once
/**
* @brief Solana types for BPF programs
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* Pick up static_assert if C11 or greater
*
* Inlined here until <assert.h> is available
*/
#if (defined _ISOC11_SOURCE || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L)) && !defined (__cplusplus)
#undef static_assert
#define static_assert _Static_assert
#endif
/**
* Numeric types
*/
#ifndef __LP64__
#error LP64 data model required
#endif
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed long int int64_t;
typedef unsigned long int uint64_t;
typedef int64_t ssize_t;
typedef uint64_t size_t;
#if defined (__cplusplus) || defined(static_assert)
static_assert(sizeof(int8_t) == 1);
static_assert(sizeof(uint8_t) == 1);
static_assert(sizeof(int16_t) == 2);
static_assert(sizeof(uint16_t) == 2);
static_assert(sizeof(int32_t) == 4);
static_assert(sizeof(uint32_t) == 4);
static_assert(sizeof(int64_t) == 8);
static_assert(sizeof(uint64_t) == 8);
#endif
/**
* Minimum of signed integral types
*/
#define INT8_MIN (-128)
#define INT16_MIN (-32767-1)
#define INT32_MIN (-2147483647-1)
#define INT64_MIN (-9223372036854775807L-1)
/**
* Maximum of signed integral types
*/
#define INT8_MAX (127)
#define INT16_MAX (32767)
#define INT32_MAX (2147483647)
#define INT64_MAX (9223372036854775807L)
/**
* Maximum of unsigned integral types
*/
#define UINT8_MAX (255)
#define UINT16_MAX (65535)
#define UINT32_MAX (4294967295U)
#define UINT64_MAX (18446744073709551615UL)
/**
* NULL
*/
#define NULL 0
/** Indicates the instruction was processed successfully */
#define SUCCESS 0
/**
* Builtin program status values occupy the upper 32 bits of the program return
* value. Programs may define their own error values but they must be confined
* to the lower 32 bits.
*/
#define TO_BUILTIN(error) ((uint64_t)(error) << 32)
/** Note: Not applicable to program written in C */
#define ERROR_CUSTOM_ZERO TO_BUILTIN(1)
/** The arguments provided to a program instruction where invalid */
#define ERROR_INVALID_ARGUMENT TO_BUILTIN(2)
/** An instruction's data contents was invalid */
#define ERROR_INVALID_INSTRUCTION_DATA TO_BUILTIN(3)
/** An account's data contents was invalid */
#define ERROR_INVALID_ACCOUNT_DATA TO_BUILTIN(4)
/** An account's data was too small */
#define ERROR_ACCOUNT_DATA_TOO_SMALL TO_BUILTIN(5)
/** An account's balance was too small to complete the instruction */
#define ERROR_INSUFFICIENT_FUNDS TO_BUILTIN(6)
/** The account did not have the expected program id */
#define ERROR_INCORRECT_PROGRAM_ID TO_BUILTIN(7)
/** A signature was required but not found */
#define ERROR_MISSING_REQUIRED_SIGNATURES TO_BUILTIN(8)
/** An initialize instruction was sent to an account that has already been initialized */
#define ERROR_ACCOUNT_ALREADY_INITIALIZED TO_BUILTIN(9)
/** An attempt to operate on an account that hasn't been initialized */
#define ERROR_UNINITIALIZED_ACCOUNT TO_BUILTIN(10)
/** The instruction expected additional account keys */
#define ERROR_NOT_ENOUGH_ACCOUNT_KEYS TO_BUILTIN(11)
/** Note: Not applicable to program written in C */
#define ERROR_ACCOUNT_BORROW_FAILED TO_BUILTIN(12)
/** The length of the seed is too long for address generation */
#define MAX_SEED_LENGTH_EXCEEDED TO_BUILTIN(13)
/** Provided seeds do not result in a valid address */
#define INVALID_SEEDS TO_BUILTIN(14)
/**
* Boolean type
*/
#ifndef __cplusplus
#include <stdbool.h>
#endif
/**
* Computes the number of elements in an array
*/
#define SOL_ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
/**
* Byte array pointer and string
*/
typedef struct {
const uint8_t *addr; /** bytes */
uint64_t len; /** number of bytes*/
} SolBytes;
#ifdef __cplusplus
}
#endif
/**@}*/

View File

@ -0,0 +1,21 @@
#pragma once
/**
* @brief Solana C-based BPF program types and utility functions
*/
#include <sol/assert.h>
#include <sol/blake3.h>
#include <sol/cpi.h>
#include <sol/deserialize.h>
#include <sol/deserialize_deprecated.h>
#include <sol/entrypoint.h>
#include <sol/keccak.h>
#include <sol/log.h>
#include <sol/pubkey.h>
#include <sol/return_data.h>
#include <sol/secp256k1.h>
#include <sol/sha.h>
#include <sol/string.h>
#include <sol/types.h>
/**@}*/

4
sdk/sbf/c/inc/stdio.h Normal file
View File

@ -0,0 +1,4 @@
#pragma once
typedef void *FILE;
int printf(const char * restrictformat, ... );

2
sdk/sbf/c/inc/stdlib.h Normal file
View File

@ -0,0 +1,2 @@
#pragma once
#include <solana_sdk.h>

6
sdk/sbf/c/inc/string.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <solana_sdk.h>
#define memcpy sol_memcpy
#define memset sol_memset
#define strlen sol_strlen

View File

@ -0,0 +1 @@
#pragma once

1
sdk/sbf/c/inc/wchar.h Normal file
View File

@ -0,0 +1 @@
#pragma once

24
sdk/sbf/c/sbf.ld Normal file
View File

@ -0,0 +1,24 @@
PHDRS
{
text PT_LOAD ;
rodata PT_LOAD ;
data PT_LOAD ;
dynamic PT_DYNAMIC ;
}
SECTIONS
{
. = SIZEOF_HEADERS;
.text : { *(.text*) } :text
.rodata : { *(.rodata*) } :rodata
.data.rel.ro : { *(.data.rel.ro*) } :rodata
.dynamic : { *(.dynamic) } :dynamic
.dynsym : { *(.dynsym) } :data
.dynstr : { *(.dynstr) } :data
.rel.dyn : { *(.rel.dyn) } :data
/DISCARD/ : {
*(.eh_frame*)
*(.gnu.hash*)
*(.hash*)
}
}

311
sdk/sbf/c/sbf.mk Normal file
View File

@ -0,0 +1,311 @@
LOCAL_PATH := $(dir $(lastword $(MAKEFILE_LIST)))
INSTALL_SH := $(abspath $(LOCAL_PATH)/../scripts/install.sh)
all:
.PHONY: help all clean
ifneq ($(V),1)
_@ :=@
endif
INC_DIRS ?=
SRC_DIR ?= ./src
TEST_PREFIX ?= test_
OUT_DIR ?= ./out
OS := $(shell uname)
LLVM_DIR = $(LOCAL_PATH)../dependencies/sbf-tools/llvm
LLVM_SYSTEM_INC_DIRS := $(LLVM_DIR)/lib/clang/14.0.0/include
COMPILER_RT_DIR = $(LOCAL_PATH)../dependencies/sbf-tools/rust/lib/rustlib/sbf-solana-solana/lib
STD_INC_DIRS := $(LLVM_DIR)/include
STD_LIB_DIRS := $(LLVM_DIR)/lib
ifdef LLVM_DIR
CC := $(LLVM_DIR)/bin/clang
CXX := $(LLVM_DIR)/bin/clang++
LLD := $(LLVM_DIR)/bin/ld.lld
OBJ_DUMP := $(LLVM_DIR)/bin/llvm-objdump
READ_ELF := $(LLVM_DIR)/bin/llvm-readelf
endif
SYSTEM_INC_DIRS := \
$(LOCAL_PATH)inc \
$(LLVM_SYSTEM_INC_DIRS) \
C_FLAGS := \
-Werror \
-O2 \
-fno-builtin \
-std=c17 \
$(addprefix -isystem,$(SYSTEM_INC_DIRS)) \
$(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 \
SBF_C_FLAGS := \
$(C_FLAGS) \
-target sbf \
-fPIC
SBF_CXX_FLAGS := \
$(CXX_FLAGS) \
-target sbf \
-fPIC \
-fomit-frame-pointer \
-fno-exceptions \
-fno-asynchronous-unwind-tables \
-fno-unwind-tables
SBF_LLD_FLAGS := \
-z notext \
-shared \
--Bdynamic \
$(LOCAL_PATH)sbf.ld \
--entry entrypoint \
-L $(STD_LIB_DIRS) \
-lc \
ifeq ($(SOL_SBFV2),1)
SBF_LLD_FLAGS := \
$(SBF_LLD_FLAGS) \
--pack-dyn-relocs=relr
endif
OBJ_DUMP_FLAGS := \
--source \
--disassemble \
READ_ELF_FLAGS := \
--all \
TESTFRAMEWORK_RPATH := $(abspath $(LOCAL_PATH)../dependencies/criterion/lib)
TESTFRAMEWORK_FLAGS := \
-DSOL_TEST \
-isystem $(LOCAL_PATH)../dependencies/criterion/include \
-L $(LOCAL_PATH)../dependencies/criterion/lib \
-rpath $(TESTFRAMEWORK_RPATH) \
-lcriterion \
MACOS_ADJUST_TEST_DYLIB := \
$(if $(filter $(OS),Darwin),\
$(_@)install_name_tool -change libcriterion.3.dylib $(TESTFRAMEWORK_RPATH)/libcriterion.3.dylib, \
: \
)
TEST_C_FLAGS := \
$(C_FLAGS) \
$(TESTFRAMEWORK_FLAGS) \
TEST_CXX_FLAGS := \
$(CXX_FLAGS) \
$(TESTFRAMEWORK_FLAGS) \
help:
@echo ''
@echo 'SBF Program makefile'
@echo ''
@echo 'This makefile will build SBF Programs from C or C++ source files into ELFs'
@echo ''
@echo 'Assumptions:'
@echo ' - Programs are located in the source directory: $(SRC_DIR)/<program name>'
@echo ' - Programs are named by their directory name (eg. directory name:src/foo/ -> program name:foo)'
@echo ' - Tests are located in their corresponding program directory and must being with "test_"'
@echo ' - Output files will be placed in the directory: $(OUT_DIR)'
@echo ''
@echo 'User settings'
@echo ' - The following setting are overridable on the command line, default values shown:'
@echo ' - Show commands while building: V=1'
@echo ' V=$(V)'
@echo ' - List of include directories:'
@echo ' INC_DIRS=$(INC_DIRS)'
@echo ' - List of system include directories:'
@echo ' SYSTEM_INC_DIRS=$(SYSTEM_INC_DIRS)'
@echo ' - List of standard library include directories:'
@echo ' STD_INC_DIRS=$(STD_INC_DIRS)'
@echo ' - List of standard library archive directories:'
@echo ' STD_LIB_DIRS=$(STD_LIB_DIRS)'
@echo ' - Location of source directories:'
@echo ' SRC_DIR=$(SRC_DIR)'
@echo ' - Location to place output files:'
@echo ' OUT_DIR=$(OUT_DIR)'
@echo ' - Location of LLVM:'
@echo ' LLVM_DIR=$(LLVM_DIR)'
@echo ''
@echo 'Usage:'
@echo ' - make help - This help message'
@echo ' - make all - Build all the programs and tests, run the tests'
@echo ' - make programs - Build all the programs'
@echo ' - make tests - Build and run all tests'
@echo ' - make dump_<program name> - Dump the contents of the program to stdout'
@echo ' - make readelf_<program name> - Display information about the ELF binary'
@echo ' - make <program name> - Build a single program by name'
@echo ' - make <test name> - Build and run a single test by name'
@echo ''
@echo 'Available programs:'
$(foreach name, $(PROGRAM_NAMES), @echo ' - $(name)'$(\n))
@echo ''
@echo 'Available tests:'
$(foreach name, $(TEST_NAMES), @echo ' - $(name)'$(\n))
@echo ''
@echo 'Example:'
@echo ' - Assuming a program named foo (src/foo/foo.c)'
@echo ' - make foo'
@echo ' - make dump_foo'
@echo ''
define C_RULE
$1: $2
@echo "[cc] $1 ($2)"
$(_@)mkdir -p $(dir $1)
$(_@)$(CC) $(SBF_C_FLAGS) -o $1 -c $2
endef
define CC_RULE
$1: $2
@echo "[cxx] $1 ($2)"
$(_@)mkdir -p $(dir $1)
$(_@)$(CXX) $(SBF_CXX_FLAGS) -o $1 -c $2
endef
define D_RULE
$1: $2 $(LOCAL_PATH)/sbf.mk
@echo "[GEN] $1 ($2)"
$(_@)mkdir -p $(dir $1)
$(_@)$(CC) -M -MT '$(basename $1).o' $(SBF_C_FLAGS) $2 | sed 's,\($(basename $1)\)\.o[ :]*,\1.o $1 : ,g' > $1
endef
define DXX_RULE
$1: $2 $(LOCAL_PATH)/sbf.mk
@echo "[GEN] $1 ($2)"
$(_@)mkdir -p $(dir $1)
$(_@)$(CXX) -M -MT '$(basename $1).o' $(SBF_CXX_FLAGS) $2 | sed 's,\($(basename $1)\)\.o[ :]*,\1.o $1 : ,g' > $1
endef
define O_RULE
$1: $2
@echo "[llc] $1 ($2)"
$(_@)mkdir -p $(dir $1)
$(_@)$(LLC) $(SBF_LLC_FLAGS) -o $1 $2
endef
define SO_RULE
$1: $2
@echo "[lld] $1 ($2)"
$(_@)mkdir -p $(dir $1)
$(_@)$(LLD) $(SBF_LLD_FLAGS) -o $1 $2 $(COMPILER_RT_DIR)/libcompiler_builtins-*.rlib
ifeq (,$(wildcard $(subst .so,-keypair.json,$1)))
$(_@)solana-keygen new --no-passphrase --silent -o $(subst .so,-keypair.json,$1)
endif
@echo To deploy this program:
@echo $$$$ solana program deploy $(abspath $1)
endef
define TEST_C_RULE
$1: $2
@echo "[test cc] $1 ($2)"
$(_@)mkdir -p $(dir $1)
$(_@)$(CC) $(TEST_C_FLAGS) -o $1 $2
$(_@)$(MACOS_ADJUST_TEST_DYLIB) $1
endef
define TEST_CC_RULE
$1: $2
@echo "[test cxx] $1 ($2)"
$(_@)mkdir -p $(dir $1)
$(_@)$(CXX) $(TEST_CXX_FLAGS) -o $1 $2
$(_@)$(MACOS_ADJUST_TEST_DYLIB) $1
endef
define TEST_D_RULE
$1: $2 $(LOCAL_PATH)/sbf.mk
@echo "[GEN] $1 ($2)"
$(_@)mkdir -p $(dir $1)
$(_@)$(CC) -M -MT '$(basename $1)' $(TEST_C_FLAGS) $2 | sed 's,\($(basename $1)\)[ :]*,\1 $1 : ,g' > $1
endef
define TEST_DXX_RULE
$1: $2 $(LOCAL_PATH)/sbf.mk
@echo "[GEN] $1 ($2)"
$(_@)mkdir -p $(dir $1)
$(_@)$(CXX) -M -MT '$(basename $1)' $(TEST_CXX_FLAGS) $2 | sed 's,\($(basename $1)\)[ :]*,\1 $1 : ,g' > $1
endef
define TEST_EXEC_RULE
$1: $2
LD_LIBRARY_PATH=$(TESTFRAMEWORK_RPATH) \
$2$(\n)
endef
.PHONY: $(INSTALL_SH)
$(INSTALL_SH):
$(_@)$(INSTALL_SH)
PROGRAM_NAMES := $(notdir $(basename $(wildcard $(SRC_DIR)/*)))
define \n
endef
all: programs tests
$(foreach PROGRAM, $(PROGRAM_NAMES), \
$(eval -include $(wildcard $(OUT_DIR)/$(PROGRAM)/*.d)) \
\
$(eval $(PROGRAM): %: $(addprefix $(OUT_DIR)/, %.so)) \
$(eval $(PROGRAM)_SRCS := \
$(addprefix $(SRC_DIR)/$(PROGRAM)/, \
$(filter-out $(TEST_PREFIX)%,$(notdir $(wildcard $(SRC_DIR)/$(PROGRAM)/*.c $(SRC_DIR)/$(PROGRAM)/*.cc))))) \
$(eval $(PROGRAM)_OBJS := $(subst $(SRC_DIR), $(OUT_DIR), \
$(patsubst %.c,%.o, \
$(patsubst %.cc,%.o,$($(PROGRAM)_SRCS))))) \
$(eval $($(PROGRAM)_SRCS): $(INSTALL_SH)) \
$(eval $(call SO_RULE,$(OUT_DIR)/$(PROGRAM).so,$($(PROGRAM)_OBJS))) \
$(foreach _,$(filter %.c,$($(PROGRAM)_SRCS)), \
$(eval $(call D_RULE,$(subst $(SRC_DIR),$(OUT_DIR),$(_:%.c=%.d)),$_)) \
$(eval $(call C_RULE,$(subst $(SRC_DIR),$(OUT_DIR),$(_:%.c=%.o)),$_))) \
$(foreach _,$(filter %.cc,$($(PROGRAM)_SRCS)), \
$(eval $(call DXX_RULE,$(subst $(SRC_DIR),$(OUT_DIR),$(_:%.cc=%.d)),$_)) \
$(eval $(call CC_RULE,$(subst $(SRC_DIR),$(OUT_DIR),$(_:%.cc=%.o)),$_))) \
\
$(eval TESTS := $(notdir $(basename $(wildcard $(SRC_DIR)/$(PROGRAM)/$(TEST_PREFIX)*.c)))) \
$(eval $(TESTS) : %: $(addprefix $(OUT_DIR)/$(PROGRAM)/, %)) \
$(eval TEST_NAMES := $(TEST_NAMES) $(TESTS)) \
$(foreach TEST, $(TESTS), \
$(eval $(TEST)_SRCS := \
$(addprefix $(SRC_DIR)/$(PROGRAM)/, \
$(notdir $(wildcard $(SRC_DIR)/$(PROGRAM)/$(TEST).c $(SRC_DIR)/$(PROGRAM)/$(TEST).cc)))) \
$(eval $($(TEST)_SRCS): $(INSTALL_SH)) \
$(foreach _,$(filter %.c,$($(TEST)_SRCS)), \
$(eval $(call TEST_D_RULE,$(subst $(SRC_DIR),$(OUT_DIR),$(_:%.c=%.d)),$_)) \
$(eval $(call TEST_C_RULE,$(subst $(SRC_DIR),$(OUT_DIR),$(_:%.c=%)),$_))) \
$(foreach _,$(filter %.cc, $($(TEST)_SRCS)), \
$(eval $(call TEST_DXX_RULE,$(subst $(SRC_DIR),$(OUT_DIR),$(_:%.cc=%.d)),$_)) \
$(eval $(call TEST_CC_RULE,$(subst $(SRC_DIR),$(OUT_DIR),$(_:%.cc=%)),$_))) \
$(eval $(call TEST_EXEC_RULE,$(TEST),$(addprefix $(OUT_DIR)/$(PROGRAM)/, $(TEST)))) \
) \
)
.PHONY: $(PROGRAM_NAMES)
programs: $(PROGRAM_NAMES)
.PHONY: $(TEST_NAMES)
tests: $(TEST_NAMES)
dump_%: %
$(_@)$(OBJ_DUMP) $(OBJ_DUMP_FLAGS) $(addprefix $(OUT_DIR)/, $(addsuffix .so, $<))
readelf_%: %
$(_@)$(READ_ELF) $(READ_ELF_FLAGS) $(addprefix $(OUT_DIR)/, $(addsuffix .so, $<))
clean:
rm -rf $(OUT_DIR)

16
sdk/sbf/env.sh Normal file
View File

@ -0,0 +1,16 @@
#
# Configures the SBF SDK environment
#
if [ -z "$sbf_sdk" ]; then
sbf_sdk=.
fi
# Ensure the sdk is installed
"$sbf_sdk"/scripts/install.sh
# Use the SDK's version of llvm to build the compiler-builtins for SBF
export CC="$sbf_sdk/dependencies/sbf-tools/llvm/bin/clang"
export AR="$sbf_sdk/dependencies/sbf-tools/llvm/bin/llvm-ar"
export OBJDUMP="$sbf_sdk/dependencies/sbf-tools/llvm/bin/llvm-objdump"
export OBJCOPY="$sbf_sdk/dependencies/sbf-tools/llvm/bin/llvm-objcopy"

46
sdk/sbf/scripts/dump.sh Executable file
View File

@ -0,0 +1,46 @@
#!/usr/bin/env bash
sbf_sdk=$(cd "$(dirname "$0")/.." && pwd)
# shellcheck source=sdk/sbf/env.sh
source "$sbf_sdk"/env.sh
so=$1
dump=$2
if [[ -z $so ]] || [[ -z $dump ]]; then
echo "Usage: $0 sbf-program.so dump.txt" >&2
exit 1
fi
if [[ ! -r $so ]]; then
echo "Error: File not found or readable: $so" >&2
exit 1
fi
if ! command -v rustfilt > /dev/null; then
echo "Error: rustfilt not found. It can be installed by running: cargo install rustfilt" >&2
exit 1
fi
set -e
out_dir=$(dirname "$dump")
if [[ ! -d $out_dir ]]; then
mkdir -p "$out_dir"
fi
dump_mangled=$dump.mangled
(
set -ex
ls -la "$so" > "$dump_mangled"
"$sbf_sdk"/dependencies/sbf-tools/llvm/bin/llvm-readelf -aW "$so" >>"$dump_mangled"
"$OBJDUMP" --print-imm-hex --source --disassemble "$so" >> "$dump_mangled"
sed s/://g < "$dump_mangled" | rustfilt > "$dump"
)
rm -f "$dump_mangled"
if [[ ! -f "$dump" ]]; then
echo "Error: Failed to create $dump" >&2
exit 1
fi
echo >&2
echo "Wrote $dump" >&2

131
sdk/sbf/scripts/install.sh Executable file
View File

@ -0,0 +1,131 @@
#!/usr/bin/env bash
mkdir -p "$(dirname "$0")"/../dependencies
cd "$(dirname "$0")"/../dependencies
unameOut="$(uname -s)"
case "${unameOut}" in
Linux*)
criterion_suffix=
machine=linux;;
Darwin*)
criterion_suffix=
machine=osx;;
MINGW*)
criterion_suffix=-mingw
machine=windows;;
*)
criterion_suffix=
machine=linux
esac
download() {
declare url="$1/$2/$3"
declare filename=$3
declare wget_args=(
"$url" -O "$filename"
"--progress=dot:giga"
"--retry-connrefused"
"--read-timeout=30"
)
declare curl_args=(
-L "$url" -o "$filename"
)
if hash wget 2>/dev/null; then
wget_or_curl="wget ${wget_args[*]}"
elif hash curl 2>/dev/null; then
wget_or_curl="curl ${curl_args[*]}"
else
echo "Error: Neither curl nor wget were found" >&2
return 1
fi
set -x
if $wget_or_curl; then
tar --strip-components 1 -jxf "$filename" || return 1
{ set +x; } 2>/dev/null
rm -rf "$filename"
return 0
fi
return 1
}
get() {
declare version=$1
declare dirname=$2
declare job=$3
declare cache_root=~/.cache/solana
declare cache_dirname="$cache_root/$version/$dirname"
declare cache_partial_dirname="$cache_dirname"_partial
if [[ -r $cache_dirname ]]; then
ln -sf "$cache_dirname" "$dirname" || return 1
return 0
fi
rm -rf "$cache_partial_dirname" || return 1
mkdir -p "$cache_partial_dirname" || return 1
pushd "$cache_partial_dirname"
if $job; then
popd
mv "$cache_partial_dirname" "$cache_dirname" || return 1
ln -sf "$cache_dirname" "$dirname" || return 1
return 0
fi
popd
return 1
}
# Install Criterion
if [[ $machine == "linux" ]]; then
version=v2.3.3
else
version=v2.3.2
fi
if [[ ! -e criterion-$version.md || ! -e criterion ]]; then
(
set -e
rm -rf criterion*
job="download \
https://github.com/Snaipe/Criterion/releases/download \
$version \
criterion-$version-$machine$criterion_suffix-x86_64.tar.bz2 \
criterion"
get $version criterion "$job"
)
exitcode=$?
if [[ $exitcode -ne 0 ]]; then
exit 1
fi
touch criterion-$version.md
fi
# Install Rust-SBF
version=v1.29
if [[ ! -e sbf-tools-$version.md || ! -e sbf-tools ]]; then
(
set -e
rm -rf sbf-tools*
job="download \
https://github.com/solana-labs/sbf-tools/releases/download \
$version \
solana-sbf-tools-$machine.tar.bz2 \
sbf-tools"
get $version sbf-tools "$job"
)
exitcode=$?
if [[ $exitcode -ne 0 ]]; then
exit 1
fi
touch sbf-tools-$version.md
set -ex
./sbf-tools/rust/bin/rustc --version
./sbf-tools/rust/bin/rustc --print sysroot
set +e
rustup toolchain uninstall sbf
set -e
rustup toolchain link sbf sbf-tools/rust
fi
exit 0

6
sdk/sbf/scripts/objcopy.sh Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
sbf_sdk=$(cd "$(dirname "$0")/.." && pwd)
# shellcheck source=sdk/sbf/env.sh
source "$sbf_sdk"/env.sh
exec "$sbf_sdk"/dependencies/sbf-tools/llvm/bin/llvm-objcopy "$@"

19
sdk/sbf/scripts/package.sh Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -ex
cd "$(dirname "$0")"/../../..
echo --- Creating sbf-sdk tarball
rm -rf sbf-sdk.tar.bz2 sbf-sdk/
mkdir sbf-sdk/
cp LICENSE sbf-sdk/
(
ci/crate-version.sh sdk/Cargo.toml
git rev-parse HEAD
) > sbf-sdk/version.txt
cp -a sdk/sbf/* sbf-sdk/
tar jvcf sbf-sdk.tar.bz2 sbf-sdk/

23
sdk/sbf/scripts/strip.sh Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env bash
so=$1
if [[ ! -r $so ]]; then
echo "Error: file not found: $so"
exit 1
fi
so_stripped=$2
if [[ -z $so_stripped ]]; then
echo "Usage: $0 unstripped.so stripped.so"
exit 1
fi
sbf_sdk=$(cd "$(dirname "$0")/.." && pwd)
# shellcheck source=sdk/sbf/env.sh
source "$sbf_sdk"/env.sh
set -e
out_dir=$(dirname "$so_stripped")
if [[ ! -d $out_dir ]]; then
mkdir -p "$out_dir"
fi
"$sbf_sdk"/dependencies/sbf-tools/llvm/bin/llvm-objcopy --strip-all "$so" "$so_stripped"