Add a repo to support the WASM version of partial_eq
This commit is contained in:
parent
0ce5406fc8
commit
cc21fd21be
8 changed files with 428 additions and 1 deletions
2
plugins/partialeq_wasm/.gitignore
vendored
Normal file
2
plugins/partialeq_wasm/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
**/*.rs.bk
|
152
plugins/partialeq_wasm/Cargo.lock
generated
Normal file
152
plugins/partialeq_wasm/Cargo.lock
generated
Normal file
|
@ -0,0 +1,152 @@
|
|||
[[package]]
|
||||
name = "bincode"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "partialeq_wasm"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"zokrates_field 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "zokrates_field"
|
||||
version = "0.3.0"
|
||||
dependencies = [
|
||||
"bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e103c8b299b28a9c6990458b7013dc4a8356a9b854c51b9883241f5866fac36e"
|
||||
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
|
||||
"checksum lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417"
|
||||
"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
|
||||
"checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1"
|
||||
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
|
||||
"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124"
|
||||
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
||||
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
|
||||
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
|
||||
"checksum serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "6fa52f19aee12441d5ad11c9a00459122bd8f98707cadf9778c540674f1935b6"
|
||||
"checksum serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "96a7f9496ac65a2db5929afa087b54f8fc5008dcfbe48a8874ed20049b0d6154"
|
||||
"checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
10
plugins/partialeq_wasm/Cargo.toml
Normal file
10
plugins/partialeq_wasm/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "partialeq_wasm"
|
||||
version = "0.1.0"
|
||||
authors = ["Guillaume Ballet <gballet@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
num = {version = "0.1.36", default-features = false}
|
||||
lazy_static = "0.1.*"
|
||||
zokrates_field = {version = "0.3", path = "../../zokrates_field" }
|
33
plugins/partialeq_wasm/src/main.rs
Normal file
33
plugins/partialeq_wasm/src/main.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
extern crate zokrates_field;
|
||||
extern crate num;
|
||||
use zokrates_field::field::{Field, FieldPrime};
|
||||
use num::{Zero, One};
|
||||
|
||||
static INPUT_BUFFER : [u8;32] = [0u8;32];
|
||||
static mut OUTPUT_BUFFER : [u8;64] = [0u8;64];
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn get_inputs_off() -> *const u8 {
|
||||
return &INPUT_BUFFER as *const u8;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn solve() -> *const u8 {
|
||||
// Transform the input bytes into output
|
||||
let input = FieldPrime::from_byte_vector(Vec::from(&INPUT_BUFFER[..]));
|
||||
|
||||
let (output0, output1) = if input.is_zero() {
|
||||
(FieldPrime::zero(), FieldPrime::one())
|
||||
} else {
|
||||
(FieldPrime::one(), FieldPrime::one() / input)
|
||||
};
|
||||
|
||||
// Transform outputs back into bytes
|
||||
&OUTPUT_BUFFER[..32].copy_from_slice(&output0.into_byte_vector()[..]);
|
||||
&OUTPUT_BUFFER[32..].copy_from_slice(&output1.into_byte_vector()[..]);
|
||||
|
||||
return &OUTPUT_BUFFER as *const u8;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
|
@ -36,3 +36,4 @@ assert_cli = "0.5"
|
|||
[build-dependencies]
|
||||
cc = { version = "1.0", features = ["parallel"] }
|
||||
cmake = "0.1.31"
|
||||
parity-wasm = "0.35.3"
|
|
@ -60,4 +60,233 @@ fn main() {
|
|||
println!("cargo:rustc-link-lib=static=ff");
|
||||
}
|
||||
}
|
||||
|
||||
// #[cfg(feature = "wasm")]
|
||||
{
|
||||
extern crate parity_wasm;
|
||||
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::io::prelude::*;
|
||||
|
||||
fn has_symbol(symbol : &str,
|
||||
exports : &[parity_wasm::elements::ExportEntry], funcs: &[parity_wasm::elements::Func], types: &[parity_wasm::elements::Type]) -> Result<(), String> {
|
||||
match exports.iter().find(|ref export| export.field() == symbol) {
|
||||
Some(export) => {
|
||||
match export.internal() {
|
||||
&parity_wasm::elements::Internal::Function(fidx) => {
|
||||
let tidx = funcs[fidx as usize].type_ref();
|
||||
let parity_wasm::elements::Type::Function(t) = &types[tidx as usize];
|
||||
match t.return_type() {
|
||||
Some(parity_wasm::elements::ValueType::I32) => {}
|
||||
_ => return Err(format!("Invalid return type for `{}", symbol))
|
||||
}
|
||||
let params = t.params();
|
||||
if params.len() != 0 {
|
||||
Err(format!("Invalid number of parameters for `{}`", symbol))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
_ => return Err(format!("Module has a `{}` export that is not a function", symbol))
|
||||
}
|
||||
}
|
||||
None => Err(format!("Module is missing a `{}` export", symbol))
|
||||
}
|
||||
}
|
||||
|
||||
fn validate<U : Into<String>>(input : U) -> Result<parity_wasm::elements::Module, String> {
|
||||
let fname = input.into();
|
||||
|
||||
let module = parity_wasm::deserialize_file(fname.clone())
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let functions = module.function_section()
|
||||
.ok_or("Module has no function section")?
|
||||
.entries();
|
||||
let types = module.type_section()
|
||||
.ok_or("Module has no function section")?
|
||||
.types();
|
||||
let exports = module.export_section()
|
||||
.ok_or("Module has no export section")?
|
||||
.entries();
|
||||
|
||||
/* Look for `get_input_offs` */
|
||||
has_symbol("get_inputs_off", exports, functions, types)?;
|
||||
|
||||
/* Look for `solve` */
|
||||
has_symbol("solve", exports, functions, types)?;
|
||||
|
||||
Ok(module.clone())
|
||||
}
|
||||
|
||||
fn add_global(symbol : &str, module : &parity_wasm::elements::Module, value : i32) -> Result<parity_wasm::elements::Module, String> {
|
||||
let nglobals = module
|
||||
.global_section()
|
||||
.unwrap()
|
||||
.entries()
|
||||
.len();
|
||||
println!("Adding global at index {}", nglobals);
|
||||
let nm = parity_wasm::builder::from_module(module.clone())
|
||||
.global()
|
||||
.value_type().i32()
|
||||
.init_expr(parity_wasm::elements::Instruction::I32Const(value))
|
||||
.build()
|
||||
.export()
|
||||
.field(symbol)
|
||||
.internal()
|
||||
.global(nglobals as u32)
|
||||
.build()
|
||||
.build();
|
||||
Ok(nm)
|
||||
}
|
||||
|
||||
fn add_global_if_missing(symbol : &str, module : &parity_wasm::elements::Module, expected_type : parity_wasm::elements::ValueType, value : i32, _force : bool) -> Result<parity_wasm::elements::Module, String> {
|
||||
let global_section = module.global_section()
|
||||
.ok_or("Could not get globals section")?
|
||||
.entries()
|
||||
.clone();
|
||||
let exports = module
|
||||
.export_section()
|
||||
.ok_or("Could not get exports section")?
|
||||
.entries();
|
||||
|
||||
let mut found = false;
|
||||
|
||||
if let Some(export) = exports.iter().find(|ref export| export.field() == symbol) {
|
||||
found = true;
|
||||
|
||||
// Export already exists, check its type and return it if said
|
||||
// type is correct.
|
||||
if let &parity_wasm::elements::Internal::Global(gidx) = export.internal() {
|
||||
let global_type = global_section[gidx as usize]
|
||||
.global_type();
|
||||
if !global_type.is_mutable() && expected_type == global_type.content_type() {
|
||||
return Ok(module.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* overwrite only if asked with the -f switch */
|
||||
if !found {
|
||||
add_global(symbol, module, value)
|
||||
} else {
|
||||
Err(format!("Symbol {} is already present with a different type in module", symbol))
|
||||
}
|
||||
}
|
||||
|
||||
/* Regenerate if files have changed */
|
||||
println!("cargo:rerun-if-changed=./plugins");
|
||||
|
||||
/* Build the WASM helpers and turn them into files */
|
||||
let status = Command::new("cargo")
|
||||
.current_dir("../plugins/partialeq_wasm")
|
||||
.args(&["build", "--target", "wasm32-unknown-unknown", "--release"])
|
||||
.status()
|
||||
.unwrap();
|
||||
if !status.success() {
|
||||
panic!("Error building WASM helpers");
|
||||
}
|
||||
|
||||
/* Turn the output binary into a source file for zokrates_core */
|
||||
let fname =
|
||||
"../plugins/partialeq_wasm/target/wasm32-unknown-unknown/release/partialeq_wasm.wasm";
|
||||
match validate(fname) {
|
||||
Ok(module) => {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let dest_path = Path::new(&out_dir).join("partialeq_wasm.rs");
|
||||
let m0 = module.clone();
|
||||
let m1 = add_global_if_missing(
|
||||
"min_inputs",
|
||||
&m0,
|
||||
parity_wasm::elements::ValueType::I32,
|
||||
1,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
let m2 = add_global_if_missing(
|
||||
"min_outputs",
|
||||
&m1,
|
||||
parity_wasm::elements::ValueType::I32,
|
||||
2,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
let m3 = add_global_if_missing(
|
||||
"field_size",
|
||||
&m2,
|
||||
parity_wasm::elements::ValueType::I32,
|
||||
32,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
let buf = parity_wasm::serialize(m3).unwrap();
|
||||
std::fs::File::create(dest_path)
|
||||
.unwrap()
|
||||
.write_all(
|
||||
format!(
|
||||
"
|
||||
pub const PARTIALEQ_WASM : &'static [u8] = &{:?};
|
||||
",
|
||||
buf
|
||||
)
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
Err(e) => panic!(format!("Module validation error: {}", e.to_string())),
|
||||
}
|
||||
}
|
||||
} }
|
||||
|
||||
/* Turn the output binary into a source file for zokrates_core */
|
||||
let fname =
|
||||
"../plugins/partialeq_wasm/target/wasm32-unknown-unknown/release/partialeq_wasm.wasm";
|
||||
match validate(fname) {
|
||||
Ok(module) => {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let dest_path = Path::new(&out_dir).join("partialeq_wasm.rs");
|
||||
let m0 = module.clone();
|
||||
let m1 = add_global_if_missing(
|
||||
"min_inputs",
|
||||
&m0,
|
||||
parity_wasm::elements::ValueType::I32,
|
||||
1,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
let m2 = add_global_if_missing(
|
||||
"min_outputs",
|
||||
&m1,
|
||||
parity_wasm::elements::ValueType::I32,
|
||||
2,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
let m3 = add_global_if_missing(
|
||||
"field_size",
|
||||
&m2,
|
||||
parity_wasm::elements::ValueType::I32,
|
||||
32,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
let buf = parity_wasm::serialize(m3).unwrap();
|
||||
std::fs::File::create(dest_path)
|
||||
.unwrap()
|
||||
.write_all(
|
||||
format!(
|
||||
"
|
||||
pub const PARTIALEQ_WASM : &'static [u8] = &{:?};
|
||||
",
|
||||
buf
|
||||
)
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
Err(e) => panic!(format!("Module validation error: {}", e.to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ pub use self::wasm::WasmHelper;
|
|||
use flat_absy::{FlatExpression, FlatVariable};
|
||||
use std::fmt;
|
||||
use zokrates_field::field::Field;
|
||||
include!(concat!(env!("OUT_DIR"), "/partialeq_wasm.rs"));
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct DirectiveStatement<T: Field> {
|
||||
|
|
|
@ -5,7 +5,6 @@ authors = ["Guillaume Ballet <gballet@gmail.com>"]
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
lazy_static = "0.1.*"
|
||||
|
|
Loading…
Reference in a new issue