Skip to content

Commit

Permalink
Expose proving in a C library (#4)
Browse files Browse the repository at this point in the history
* Difficulty calculation

* Benchmark various proving algos

* Expose proof generation via C library

* fix build

* Refactor Prover::prove to accept raw bytes and index

* Benchmark on many cores with rayon

* Clean up deps and optimize staticlib size

* Build for linux, macos and windows

* Fix CI and reorg workflow file

* Fix saving libpost.a artifact

* Fix post library artifact name for windows

* Test proving by checking if indicies in proof satisfy difficulty

* Fix batch index and AES cipher creation

* Review fixes

* Build shared library in addition to static one (#5)

* Build shared library instead of static one

* Build on ubuntu-20.04 too

* Build staticlib and dylib
  • Loading branch information
poszu authored Mar 2, 2023
1 parent 40fca2f commit 6db4b49
Show file tree
Hide file tree
Showing 16 changed files with 863 additions and 129 deletions.
46 changes: 44 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
branches:
- main

name: Tests
name: CI

jobs:
check:
Expand All @@ -22,6 +22,8 @@ jobs:

test:
name: Test Suite
needs:
- check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand All @@ -32,7 +34,6 @@ jobs:
- uses: actions-rs/cargo@v1
with:
command: test

fmt:
name: Rustfmt
runs-on: ubuntu-latest
Expand All @@ -57,3 +58,44 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features

build:
name: Build library
runs-on: ${{ matrix.os }}
needs:
- test
- fmt
- clippy
strategy:
matrix:
include:
- os: ubuntu-20.04
dylib: libpost.so
staticlib: libpost.a
- os: ubuntu-latest
dylibn: libpost.so
staticlib: libpost.a
- os: macos-latest
dylib: libpost.dylib
staticlib: libpost.a
rustflags: --cfg=aes_armv8
- os: windows-latest
dylib: post.dll
staticlib: post.lib
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
- run: cargo +nightly build --profile release-clib -p post
env:
RUSTFLAGS: ${{ matrix.rustflags }}
- name: Archive production artifacts
uses: actions/upload-artifact@v3
with:
name: libpost-${{ matrix.os }}
path: |
ffi/prover.h
target/release-clib/${{ matrix.dylib }}
target/release-clib/${{ matrix.staticlib }}
24 changes: 21 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[workspace]
members = [".", "ffi"]

[package]
name = "post-rs"
version = "0.1.0"
Expand All @@ -7,18 +10,33 @@ edition = "2021"
name = "post"

[dependencies]
rand = "0.8.5"
aes = "0.8.2"
cipher = "0.4.2"
eyre = "0.6.8"
regex = "1.7.1"
itertools = "0.10.5"
serde = { version = "1.0.152", features = ["derive"] }
serde_json = "1.0.93"
bytemuck = "1.13.0"
serde_with = { version = "2.2.0", features = ["base64"] }

[dev-dependencies]
criterion = "0.4"
pprof = { version = "0.11.1", features = ["flamegraph", "criterion"] }
tempfile = "3.3.0"
rayon = "1.6.1"
rand = "0.8.5"

[features]
default = ["block-padding"]
block-padding = ["cipher/block-padding"]

[[bench]]
name = "aes"
name = "proving"
harness = false
opt-level = 3


[profile.release-clib]
inherits = "release"
strip = true
lto = true
32 changes: 0 additions & 32 deletions benches/aes.rs

This file was deleted.

140 changes: 140 additions & 0 deletions benches/proving.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
use std::hint::black_box;

use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use post::Prover;
use pprof::criterion::{Output, PProfProfiler};
use rand::{thread_rng, RngCore};
use rayon::prelude::{ParallelBridge, ParallelIterator};

const KIB: usize = 1024;
const MIB: usize = 1024 * KIB;

const CHALLENGE: &[u8; 32] = b"hello world, CHALLENGE me!!!!!!!";

fn threads_to_str(threads: usize) -> String {
if threads == 0 {
"auto".into()
} else {
threads.to_string()
}
}

fn prover_bench(c: &mut Criterion) {
let mut group = c.benchmark_group("proving");

let mut data = vec![0; 32 * MIB];
thread_rng().fill_bytes(&mut data);
group.throughput(criterion::Throughput::Bytes(data.len() as u64));

let chunk_size = 64 * KIB;

for (nonces, threads) in itertools::iproduct!(
[2, 20, 200],
[0, 1] // 0 == automatic
) {
group.bench_with_input(
BenchmarkId::new(
format!("D=8/B=16/chunk={}KiB", chunk_size as f64 / KIB as f64),
format!("nonces={nonces}/threads={}", threads_to_str(threads)),
),
&(nonces, threads),
|b, &(nonces, threads)| {
let prover = post::ConstDProver::new(CHALLENGE, 0, 0..nonces);
b.iter(|| {
let f = black_box(|_, _| false);
match threads {
1 => data.chunks_exact(chunk_size).for_each(|chunk| {
prover.prove(chunk, 0, f);
}),
0 => data
.chunks_exact(chunk_size)
.par_bridge()
.for_each(|chunk| {
prover.prove(chunk, 0, f);
}),
n => {
let pool = rayon::ThreadPoolBuilder::new()
.num_threads(n)
.build()
.unwrap();
pool.install(|| {
data.chunks_exact(chunk_size)
.par_bridge()
.for_each(|chunk| {
prover.prove(chunk, 0, f);
})
});
}
}
});
},
);
}
}

fn var_b_prover_bench(c: &mut Criterion) {
let mut group = c.benchmark_group("proving");

let mut data = vec![0; 32 * MIB];
thread_rng().fill_bytes(&mut data);
group.throughput(criterion::Throughput::Bytes(data.len() as u64));

let chunk_size = 64 * KIB;

for (nonces, threads, param_b) in itertools::iproduct!(
[2, 20, 200],
[0, 1], // 0 == automatic
[8]
) {
group.bench_with_input(
BenchmarkId::new(
format!("D=8/chunk={}KiB", chunk_size as f64 / KIB as f64),
format!(
"B={param_b}/nonces={nonces}/threads={}",
threads_to_str(threads)
),
),
&(nonces, threads, param_b),
|b, &(nonces, threads, param_b)| {
let prover = post::ConstDVarBProver::new(CHALLENGE, 0, 0..nonces, param_b);
b.iter(|| {
let f = black_box(|_, _| false);
match threads {
1 => data.chunks_exact(chunk_size).for_each(|chunk| {
prover.prove(chunk, 0, f);
}),
0 => data
.chunks_exact(chunk_size)
.par_bridge()
.for_each(|chunk| {
prover.prove(chunk, 0, f);
}),
n => {
let pool = rayon::ThreadPoolBuilder::new()
.num_threads(n)
.build()
.unwrap();
pool.install(|| {
data.chunks_exact(chunk_size)
.par_bridge()
.for_each(|chunk| {
prover.prove(chunk, 0, f);
})
});
}
}
});
},
);
}
}

criterion_group!(
name = benches;
config = Criterion::default().with_profiler(PProfProfiler::new(1000, Output::Flamegraph(None)));
targets=
prover_bench,
var_b_prover_bench,
);

criterion_main!(benches);
1 change: 1 addition & 0 deletions ffi/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
prover.h
14 changes: 14 additions & 0 deletions ffi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "post"
version = "0.1.0"
edition = "2021"

[lib]
crate_type = ["staticlib", "cdylib"]

[dependencies]
eyre = "0.6.8"
post-rs = { path = "../" }

[build-dependencies]
cbindgen = "*"
14 changes: 14 additions & 0 deletions ffi/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
extern crate cbindgen;

use std::env;

fn main() {
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

cbindgen::Builder::new()
.with_language(cbindgen::Language::C)
.with_crate(crate_dir)
.generate()
.expect("Unable to generate bindings")
.write_to_file("prover.h");
}
2 changes: 2 additions & 0 deletions ffi/rust-toolchain
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[toolchain]
channel = "nightly-2023-02-28"
Loading

0 comments on commit 6db4b49

Please sign in to comment.