Skip to content

Commit

Permalink
Modify seal function to be callable from C (zcash#99)
Browse files Browse the repository at this point in the history
* modify seal function to be callable from cgo

- can't pass arrays by value in C; need to pass pointer to first cell
- seal accepts pointer to result-array so that callers manage memory instead of Rust

* line reorg

* rename symbol

* apply cargo fmt

* add comments for seal parameters

* create lib crate-type for Rust tests

* dylib seems to work with cgo

* kick off ci
  • Loading branch information
laser authored Jul 30, 2018
1 parent fcbfc1e commit bba5f67
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 4 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name = "proofs"
version = "0.1.0"
authors = ["dignifiedquire <[email protected]>"]

[lib]
crate-type = ["rlib", "dylib"]

[dependencies]
sapling-crypto = { git = "https://github.com/zcash-hackworks/sapling-crypto", branch = "master" }
rand = "0.4"
Expand Down
118 changes: 114 additions & 4 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
use libc;
use std::ffi::{CStr, CString};
use std::slice;

type CstrT = *const libc::c_char;

type SectorID = i32;
type Commitment = u32;
type ProverID = [u8; 31];
type ChallengeSeed = [u32; 8];
type RandomSeed = [u32; 8];

// arrays cannot be passed by value in C; callers instead pass a pointer to the
// head and Rust makes runtime assertions of length while marshaling
type ProverIDPtr = *const u8;
type ChallengeSeedPtr = *const u32;
type RandomSeedPtr = *const u32;
type ResultPtr = *const Commitment;

type SectorAccess = CstrT;
type SectorAccessor = extern "C" fn(i: SectorID) -> CstrT;
type SectorAccessor = extern "C" fn(i: SectorID) -> SectorAccess;

fn from_cstr(c_str: CstrT) -> String {
unsafe {
Expand All @@ -19,21 +29,99 @@ fn from_cstr(c_str: CstrT) -> String {
}
}

fn u32ptr_to_array8(x: *const u32) -> [u32; 8] {
let s = unsafe { slice::from_raw_parts(x, 8).to_owned() };

assert_eq!(
s.len(),
8,
"actual len(s) = {}, expected len(s) = {}",
s.len(),
8
);

let mut out: [u32; 8] = Default::default();
out.copy_from_slice(&s[0..8]);
out
}

fn u8ptr_to_array31(x: *const u8) -> [u8; 31] {
let s = unsafe { slice::from_raw_parts(x, 31).to_owned() };

assert_eq!(
s.len(),
31,
"actual len(s) = {}, expected len(s) = {}",
s.len(),
31
);

let mut out: [u8; 31] = Default::default();
out.copy_from_slice(&s[0..31]);
out
}

fn to_cstring(s: &str) -> CString {
CString::new(s).unwrap()
}

const DUMMY_COMM_R: Commitment = 12345;
const DUMMY_COMM_D: Commitment = 54321;

/// Seals a sector.
///
/// # Arguments
///
/// * `sector_id` - identity of the unsealed sector
/// * `unsealed` - function pointer used to get access to unsealed
/// sector
/// * `sealed` - function pointer used to get access to sealed
/// sector
/// * `_prover_id_ptr` - pointer to first cell in a 31-length array of u8
/// * `_challenge_seed_ptr` - pointer to first cell in a 8-length array of u32
/// * `_random_seed_ptr` - pointer to first cell in a 8-length array of u32
/// * `result_ptr` - pointer to first cell in a 2-length array of u32,
/// mutated by seal in order to pass commitments back
/// to caller
/// ```
#[no_mangle]
pub extern "C" fn seal(
sector_id: SectorID,
unsealed: SectorAccessor,
sealed: SectorAccessor,
_prover_id_ptr: ProverIDPtr,
_challenge_seed_ptr: ChallengeSeedPtr,
_random_seed_ptr: RandomSeedPtr,
result_ptr: ResultPtr,
) -> () {
let prover_id = u8ptr_to_array31(_prover_id_ptr);
let challenge_seed = u32ptr_to_array8(_challenge_seed_ptr);
let random_seed = u32ptr_to_array8(_random_seed_ptr);

let comms = seal_internal(
sector_id,
unsealed,
sealed,
prover_id,
challenge_seed,
random_seed,
);

// let caller manage this memory, preventing the need for calling back into
// Rust code later to deallocate
unsafe {
*(result_ptr.offset(0 as isize) as *mut u32) = comms[0];
*(result_ptr.offset(1 as isize) as *mut u32) = comms[1];
};
}

fn seal_internal(
sector_id: SectorID,
unsealed: SectorAccessor,
sealed: SectorAccessor,
_prover_id: ProverID,
_challenge_seed: [u32; 8],
_random_seed: [u32; 8],
_challenge_seed: ChallengeSeed,
_random_seed: RandomSeed,
) -> [Commitment; 2] {
let _in_path = from_cstr(unsealed(sector_id));
let _out_path = from_cstr(sealed(sector_id));
Expand Down Expand Up @@ -73,7 +161,29 @@ mod tests {

#[test]
fn seal_verify() {
let comms = seal(
let result: [u32; 2] = [0; 2];
let prover_id: [u8; 31] = [1; 31];
let challenge_seed: [u32; 8] = [2; 8];
let random_seed: [u32; 8] = [3; 8];

seal(
123,
sector_accessor,
sector_accessor,
&prover_id[0],
&challenge_seed[0],
&random_seed[0],
&result[0],
);

assert_ne!(result[0], result[1]);
assert!(verifySeal(result[0], result[1]));
assert!(!verifySeal(result[1], result[0]));
}

#[test]
fn seal_internal_verify() {
let comms = seal_internal(
123,
sector_accessor,
sector_accessor,
Expand Down

0 comments on commit bba5f67

Please sign in to comment.