Skip to content

Commit

Permalink
Add BPF Rust noop example (solana-labs#316)
Browse files Browse the repository at this point in the history
  • Loading branch information
jackcmay authored and mvines committed Jun 15, 2020
1 parent f7a02e5 commit 4c4f5a0
Show file tree
Hide file tree
Showing 16 changed files with 605 additions and 5 deletions.
3 changes: 2 additions & 1 deletion web3.js/.travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ before_install:
- sudo apt-get update
- sudo apt-get install -y clang-7 --allow-unauthenticated
- clang-7 --version
- curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
- curl https://sh.rustup.rs -sSf | sh -s -- -y
- PATH=$HOME/.cargo/bin:$PATH
- rustup --version

Expand All @@ -31,6 +31,7 @@ script:
- npm run lint
- npm run codecov
- make -C examples/bpf-c-noop/
- ./examples/bpf-rust-noop/build.sh
- npm run localnet:update
- npm run localnet:up
- npm run examples
Expand Down
5 changes: 4 additions & 1 deletion web3.js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ $ npm install --save @solana/web3.js

### BPF program development
clang-7.0 must be installed to build BPF programs, such as
`examples/bpf-c-noop/`. See `bpf-sdk/README.md` for installation details
`examples/bpf-c-noop/`. See `bpf-sdk/README.md` for installation details.

Rust must be installed to build Rust BPF programs, see: https://www.rust-lang.org/install.html such as
`examples/bpf-rust-noop/`. See https://www.rust-lang.org/install.html for installation details.

## Usage

Expand Down
3 changes: 3 additions & 0 deletions web3.js/examples/bpf-rust-noop/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/target/

Cargo.lock
25 changes: 25 additions & 0 deletions web3.js/examples/bpf-rust-noop/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

# Note: This crate must be built using build.sh

[package]
name = "solana-bpf-rust-noop"
version = "0.15.0"
description = "Solana BPF noop program written in Rust"
authors = ["Solana Maintainers <maintainers@solana.com>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"

[dependencies]
# byteorder = { version = "1.3.1", default-features = false }
# heapless = { version = "0.4.0", default-features = false }
# byte = { version = "0.2", default-features = false }

[workspace]
members = []

[lib]
name = "solana_bpf_rust_noop"
crate-type = ["cdylib"]


4 changes: 4 additions & 0 deletions web3.js/examples/bpf-rust-noop/Xargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@


[dependencies.compiler_builtins]
path = "../../bpf-sdk/rust-bpf-sysroot/src/compiler-builtins"
19 changes: 19 additions & 0 deletions web3.js/examples/bpf-rust-noop/bpf.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
PHDRS
{
text PT_LOAD ;
rodata PT_LOAD ;
dynamic PT_DYNAMIC ;
}

SECTIONS
{
. = SIZEOF_HEADERS;
.text : { *(.text) } :text
.rodata : { *(.rodata) } :rodata
.dynamic : { *(.dynamic) } :dynamic
.dynsym : { *(.dynsym) } :dynamic
.dynstr : { *(.dynstr) } :dynamic
.gnu.hash : { *(.gnu.hash) } :dynamic
.rel.dyn : { *(.rel.dyn) } :dynamic
.hash : { *(.hash) } :dynamic
}
27 changes: 27 additions & 0 deletions web3.js/examples/bpf-rust-noop/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash

cd "$(dirname "$0")"

cargo install xargo

set -ex

# Ensure the sdk is installed
../../bpf-sdk/scripts/install.sh
rustup override set bpf

export RUSTFLAGS="$RUSTFLAGS \
-C lto=no \
-C opt-level=2 \
-C link-arg=-Tbpf.ld \
-C link-arg=-z -C link-arg=notext \
-C link-arg=--Bdynamic \
-C link-arg=-shared \
-C link-arg=--entry=entrypoint \
-C linker=../../bpf-sdk/llvm-native/bin/ld.lld"
export XARGO_HOME="$PWD/target/xargo"
export XARGO_RUST_SRC="../../bpf-sdk/rust-bpf-sysroot/src"
# export XARGO_RUST_SRC="../../../../../rust-bpf-sysroot/src"
xargo build --target bpfel-unknown-unknown --release -v

{ { set +x; } 2>/dev/null; echo Success; }
5 changes: 5 additions & 0 deletions web3.js/examples/bpf-rust-noop/clean.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash

set -ex

cargo clean
12 changes: 12 additions & 0 deletions web3.js/examples/bpf-rust-noop/dump.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash

cp dump.txt dump_last.txt 2>/dev/null

set -x
set -e

./clean.sh
./build.sh
ls -la ./target/bpfel_unknown_unknown/release/solana_bpf_rust_noop.so > dump.txt
greadelf -aW ./target/bpfel_unknown_unknown/release/solana_bpf_rust_noop.so | rustfilt >> dump.txt
llvm-objdump -print-imm-hex --source --disassemble ./target/bpfel_unknown_unknown/release/solana_bpf_rust_noop.so >> dump.txt
55 changes: 55 additions & 0 deletions web3.js/examples/bpf-rust-noop/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//! @brief Example Rust-based BPF program that prints out the parameters passed to it
#![cfg(not(test))]
#![no_std]

mod solana_sdk;

use solana_sdk::*;

struct SStruct {
x: u64,
y: u64,
z: u64,
}

#[inline(never)]
fn return_sstruct() -> SStruct {
SStruct { x: 1, y: 2, z: 3 }
}

fn process(ka: &mut [SolKeyedAccount], data: &[u8], info: &SolClusterInfo) -> bool {
sol_log("Tick height:");
sol_log_64(info.tick_height, 0, 0, 0, 0);
sol_log("Program identifier:");
sol_log_key(&info.program_id);

// Log the provided account keys and instruction input data. In the case of
// the no-op program, no account keys or input data are expected but real
// programs will have specific requirements so they can do their work.
sol_log("Account keys and instruction input data:");
sol_log_params(ka, data);

{
// Test - use core methods, unwrap

// valid bytes, in a stack-allocated array
let sparkle_heart = [240, 159, 146, 150];

let result_str = core::str::from_utf8(&sparkle_heart).unwrap();

sol_log_64(0, 0, 0, 0, result_str.len() as u64);
sol_log(result_str);
assert_eq!("💖", result_str);
}

{
// Test - struct return
let s = return_sstruct();
sol_log_64(0, 0, s.x, s.y, s.z);
assert_eq!(s.x + s.y + s.z, 6);
}

sol_log("Success");
true
}
Loading

0 comments on commit 4c4f5a0

Please sign in to comment.