-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add solidity groth16, kzg10 and final decider verifiers in a dedicate…
…d workspace (#70) * change: Refactor structure into workspace * chore: Add empty readme * change: Transform repo into workspace * add: Create folding-verifier-solidity crate * add: Include askama.toml for `sol` extension escaper * add: Jordi's old Groth16 verifier .sol template and adapt it * tmp: create simple template struct to test * Update FoldingSchemes trait, fit Nova+CycleFold - update lib.rs's `FoldingScheme` trait interface - fit Nova+CycleFold into the `FoldingScheme` trait - refactor `src/nova/*` * chore: add serialization assets for testing Now we include an `assets` folder with a serialized proof & vk for tests * Add `examples` dir, with Nova's `FoldingScheme` example * polishing * expose poseidon_test_config outside tests * change: Refactor structure into workspace * chore: Add empty readme * change: Transform repo into workspace * add: Create folding-verifier-solidity crate * add: Include askama.toml for `sol` extension escaper * add: Jordi's old Groth16 verifier .sol template and adapt it * tmp: create simple template struct to test * feat: templating kzg working * chore: add emv and revm * feat: start evm file * chore: add ark-poly-commit * chore: move `commitment` to `folding-schemes` * chore: update `.gitignore` to ignore generated contracts * chore: update template with bn254 lib on it (avoids import), update for loop to account for whitespaces * refactor: update template with no lib * feat: add evm deploy code, compile and create kzg verifier * chore: update `Cargo.toml` to have `folding-schemes` available with verifiers * feat: start kzg prove and verify with sol * chore: compute crs from kzg prover * feat: evm kzg verification passing * tmp * change: Swap order of G2 coordinates within the template * Update way to serialize proof with correct order * chore: update `Cargo.toml` * chore: add revm * chore: add `save_solidity` * refactor: verifiers in dedicated mod * refactor: have dedicated `utils` module * chore: expose modules * chore: update verifier for kzg * chore: rename templates * fix: look for binary using also name of contract * refactor: generate groth16 proof for sha256 pre-image, generate groth16 template with verifying key * chore: template renaming * fix: switch circuit for circuit that simply adds * feat: generates test data on the fly * feat: update to latest groth16 verifier * refactor: rename folder, update `.gitignore` * chore: update `Cargo.toml` * chore: update templates extension to indicate that they are templates * chore: rename templates, both files and structs * fix: template inheritance working * feat: template spdx and pragma statements * feat: decider verifier compiles, update test for kzg10 and groth16 templates * feat: parameterize which size of the crs should be stored on the contract * chore: add comment on how the groth16 and kzg10 proofs will be linked together * chore: cargo clippy run * chore: cargo clippy tests * chore: cargo fmt * refactor: remove unused lifetime parameter * chore: end merge * chore: move examples to `folding-schemes` workspace * get latest main changes * fix: temp fix clippy warnings, will remove lints once not used in tests only * fix: cargo clippy lint added on `code_size` * fix: update path to test circuit and add step for installing solc * chore: remove `save_solidity` steps * fix: the borrowed expression implements the required traits * chore: update `Cargo.toml` * chore: remove extra `[patch.crates-io]` * fix: update to patch at the workspace level and add comment explaining this * refactor: correct `staticcall` with valid input/output sizes and change return syntax for pairing * refactor: expose modules and remove `dead_code` calls * chore: update `README.md`, add additional comments on `kzg10` template and update `groth16` template comments * chore: be clearer on attributions on `kzg10` --------- Co-authored-by: CPerezz <c.perezbaro@gmail.com> Co-authored-by: arnaucube <root@arnaucube.com>
- Loading branch information
1 parent
97e973a
commit 63dbbfe
Showing
67 changed files
with
1,208 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,14 @@ | ||
[package] | ||
name = "folding-schemes" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
ark-ec = "^0.4.0" | ||
ark-ff = "^0.4.0" | ||
ark-poly = "^0.4.0" | ||
ark-std = "^0.4.0" | ||
ark-crypto-primitives = { version = "^0.4.0", default-features = false, features = ["r1cs", "sponge", "crh"] } | ||
ark-poly-commit = "^0.4.0" | ||
ark-relations = { version = "^0.4.0", default-features = false } | ||
ark-r1cs-std = { default-features = false } # use latest version from the patch | ||
ark-snark = { version = "^0.4.0"} | ||
ark-serialize = "^0.4.0" | ||
ark-circom = { git = "https://github.com/gakonst/ark-circom.git" } | ||
thiserror = "1.0" | ||
rayon = "1.7.0" | ||
num-bigint = "0.4" | ||
color-eyre = "=0.6.2" | ||
|
||
# tmp imports for espresso's sumcheck | ||
espresso_subroutines = {git="https://github.com/EspressoSystems/hyperplonk", package="subroutines"} | ||
|
||
[dev-dependencies] | ||
ark-pallas = {version="0.4.0", features=["r1cs"]} | ||
ark-vesta = {version="0.4.0", features=["r1cs"]} | ||
ark-bn254 = "0.4.0" | ||
ark-mnt4-298 = {version="0.4.0", features=["r1cs"]} | ||
ark-mnt6-298 = {version="0.4.0", features=["r1cs"]} | ||
ark-groth16 = { version = "^0.4.0" } | ||
rand = "0.8.5" | ||
tracing = { version = "0.1", default-features = false, features = [ "attributes" ] } | ||
tracing-subscriber = { version = "0.2" } | ||
|
||
[features] | ||
default = ["parallel"] | ||
|
||
parallel = [ | ||
"ark-std/parallel", | ||
"ark-ff/parallel", | ||
"ark-ec/parallel", | ||
"ark-poly/parallel", | ||
"ark-crypto-primitives/parallel", | ||
"ark-r1cs-std/parallel", | ||
] | ||
[workspace] | ||
resolver = "1" | ||
members = [ | ||
"folding-schemes", | ||
"folding-schemes-solidity" | ||
] | ||
|
||
# The following patch is to use a version of ark-r1cs-std compatible with | ||
# v0.4.0 but that includes a cherry-picked commit from after v0.4.0 which fixes | ||
# the in-circuit scalar multiplication of the zero point. The commit is from | ||
# https://github.com/arkworks-rs/r1cs-std/pull/124, without including other | ||
# changes done between v0.4.0 and this fix which would break compatibility. | ||
[patch.crates-io] | ||
ark-r1cs-std = { git = "https://github.com/arnaucube/ark-r1cs-std-cherry-picked/" } | ||
|
||
ark-r1cs-std = { git = "https://github.com/arnaucube/ark-r1cs-std-cherry-picked/" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
[package] | ||
name = "folding-schemes-solidity" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
ark-ec = "0.4" | ||
ark-ff = "0.4" | ||
ark-poly = "0.4" | ||
ark-std = "0.4" | ||
ark-groth16 = "0.4" | ||
askama = { version = "0.12.0", features = ["config"], default-features = false } | ||
ark-bn254 = "0.4.0" | ||
ark-poly-commit = "0.4.0" | ||
folding-schemes = { path = "../folding-schemes/" } | ||
itertools = "0.12.1" | ||
ark-serialize = "0.4.1" | ||
revm = "3.5.0" | ||
|
||
[dev-dependencies] | ||
ark-crypto-primitives = "0.4.0" | ||
ark-groth16 = "0.4" | ||
ark-r1cs-std = "0.4.0" | ||
ark-relations = "0.4.0" | ||
revm = "3.5.0" | ||
tracing = { version = "0.1", default-features = false, features = [ "attributes" ] } | ||
tracing-subscriber = { version = "0.2" } | ||
|
||
[features] | ||
default = ["parallel"] | ||
|
||
parallel = [ | ||
"ark-std/parallel", | ||
"ark-ff/parallel", | ||
"ark-poly/parallel", | ||
] | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# `folding-schemes-solidity` | ||
|
||
This crate implements templating logic to output verifier contracts for `folding-schemes`-generated decider proofs. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[[escaper]] | ||
path = "askama::Text" | ||
extensions = ["sol"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
pub use revm; | ||
use revm::{ | ||
primitives::{hex, Address, CreateScheme, ExecutionResult, Output, TransactTo, TxEnv}, | ||
InMemoryDB, EVM, | ||
}; | ||
use std::{ | ||
fmt::{self, Debug, Formatter}, | ||
fs::{create_dir_all, File}, | ||
io::{self, Write}, | ||
process::{Command, Stdio}, | ||
str, | ||
}; | ||
|
||
// from: https://github.com/privacy-scaling-explorations/halo2-solidity-verifier/blob/85cb77b171ce3ee493628007c7a1cfae2ea878e6/examples/separately.rs#L56 | ||
pub fn save_solidity(name: impl AsRef<str>, solidity: &str) { | ||
const DIR_GENERATED: &str = "./generated"; | ||
create_dir_all(DIR_GENERATED).unwrap(); | ||
File::create(format!("{DIR_GENERATED}/{}", name.as_ref())) | ||
.unwrap() | ||
.write_all(solidity.as_bytes()) | ||
.unwrap(); | ||
} | ||
|
||
/// Compile solidity with `--via-ir` flag, then return creation bytecode. | ||
/// | ||
/// # Panics | ||
/// Panics if executable `solc` can not be found, or compilation fails. | ||
pub fn compile_solidity(solidity: impl AsRef<[u8]>, contract_name: &str) -> Vec<u8> { | ||
let mut process = match Command::new("solc") | ||
.stdin(Stdio::piped()) | ||
.stdout(Stdio::piped()) | ||
.stderr(Stdio::piped()) | ||
.arg("--bin") | ||
.arg("--optimize") | ||
.arg("-") | ||
.spawn() | ||
{ | ||
Ok(process) => process, | ||
Err(err) if err.kind() == io::ErrorKind::NotFound => { | ||
panic!("Command 'solc' not found"); | ||
} | ||
Err(err) => { | ||
panic!("Failed to spawn process with command 'solc':\n{err}"); | ||
} | ||
}; | ||
process | ||
.stdin | ||
.take() | ||
.unwrap() | ||
.write_all(solidity.as_ref()) | ||
.unwrap(); | ||
let output = process.wait_with_output().unwrap(); | ||
let stdout = str::from_utf8(&output.stdout).unwrap(); | ||
if let Some(binary) = find_binary(stdout, contract_name) { | ||
binary | ||
} else { | ||
panic!( | ||
"Compilation fails:\n{}", | ||
str::from_utf8(&output.stderr).unwrap() | ||
) | ||
} | ||
} | ||
|
||
/// Find binary from `stdout` with given `contract_name`. | ||
/// `contract_name` is provided since `solc` may compile multiple contracts or libraries. | ||
/// hence, we need to find the correct binary. | ||
fn find_binary(stdout: &str, contract_name: &str) -> Option<Vec<u8>> { | ||
let start_contract = stdout.find(contract_name)?; | ||
let stdout_contract = &stdout[start_contract..]; | ||
let start = stdout_contract.find("Binary:")? + 8; | ||
Some(hex::decode(&stdout_contract[start..stdout_contract.len() - 1]).unwrap()) | ||
} | ||
|
||
/// Evm runner. | ||
pub struct Evm { | ||
evm: EVM<InMemoryDB>, | ||
} | ||
|
||
impl Debug for Evm { | ||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | ||
let mut debug_struct = f.debug_struct("Evm"); | ||
debug_struct | ||
.field("env", &self.evm.env) | ||
.field("db", &self.evm.db.as_ref().unwrap()) | ||
.finish() | ||
} | ||
} | ||
|
||
impl Default for Evm { | ||
fn default() -> Self { | ||
Self { | ||
evm: EVM { | ||
env: Default::default(), | ||
db: Some(Default::default()), | ||
}, | ||
} | ||
} | ||
} | ||
|
||
impl Evm { | ||
/// Return code_size of given address. | ||
/// | ||
/// # Panics | ||
/// Panics if given address doesn't have bytecode. | ||
pub fn code_size(&mut self, address: Address) -> usize { | ||
self.evm.db.as_ref().unwrap().accounts[&address] | ||
.info | ||
.code | ||
.as_ref() | ||
.unwrap() | ||
.len() | ||
} | ||
|
||
/// Apply create transaction with given `bytecode` as creation bytecode. | ||
/// Return created `address`. | ||
/// | ||
/// # Panics | ||
/// Panics if execution reverts or halts unexpectedly. | ||
pub fn create(&mut self, bytecode: Vec<u8>) -> Address { | ||
let (_, output) = self.transact_success_or_panic(TxEnv { | ||
gas_limit: u64::MAX, | ||
transact_to: TransactTo::Create(CreateScheme::Create), | ||
data: bytecode.into(), | ||
..Default::default() | ||
}); | ||
match output { | ||
Output::Create(_, Some(address)) => address, | ||
_ => unreachable!(), | ||
} | ||
} | ||
|
||
/// Apply call transaction to given `address` with `calldata`. | ||
/// Returns `gas_used` and `return_data`. | ||
/// | ||
/// # Panics | ||
/// Panics if execution reverts or halts unexpectedly. | ||
pub fn call(&mut self, address: Address, calldata: Vec<u8>) -> (u64, Vec<u8>) { | ||
let (gas_used, output) = self.transact_success_or_panic(TxEnv { | ||
gas_limit: u64::MAX, | ||
transact_to: TransactTo::Call(address), | ||
data: calldata.into(), | ||
..Default::default() | ||
}); | ||
match output { | ||
Output::Call(output) => (gas_used, output.into()), | ||
_ => unreachable!(), | ||
} | ||
} | ||
|
||
fn transact_success_or_panic(&mut self, tx: TxEnv) -> (u64, Output) { | ||
self.evm.env.tx = tx; | ||
let result = self.evm.transact_commit().unwrap(); | ||
self.evm.env.tx = Default::default(); | ||
match result { | ||
ExecutionResult::Success { | ||
gas_used, | ||
output, | ||
logs, | ||
.. | ||
} => { | ||
if !logs.is_empty() { | ||
println!("--- logs from {} ---", logs[0].address); | ||
for (log_idx, log) in logs.iter().enumerate() { | ||
println!("log#{log_idx}"); | ||
for (topic_idx, topic) in log.topics.iter().enumerate() { | ||
println!(" topic{topic_idx}: {topic:?}"); | ||
} | ||
} | ||
println!("--- end ---"); | ||
} | ||
(gas_used, output) | ||
} | ||
ExecutionResult::Revert { gas_used, output } => { | ||
panic!("Transaction reverts with gas_used {gas_used} and output {output:#x}") | ||
} | ||
ExecutionResult::Halt { reason, gas_used } => panic!( | ||
"Transaction halts unexpectedly with gas_used {gas_used} and reason {reason:?}" | ||
), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
pub use evm::*; | ||
pub use verifiers::templates::*; | ||
mod evm; | ||
mod utils; | ||
mod verifiers; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/// Defines encodings of G1 and G2 elements for use in Solidity templates. | ||
use ark_bn254::{Fq, G1Affine, G2Affine}; | ||
use std::fmt::{self, Display}; | ||
|
||
#[derive(Debug, Default)] | ||
pub struct FqWrapper(pub Fq); | ||
|
||
impl Display for FqWrapper { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "{}", self.0) | ||
} | ||
} | ||
|
||
#[derive(Debug, Default)] | ||
pub struct G1Repr(pub [FqWrapper; 2]); | ||
|
||
impl Display for G1Repr { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "{:#?}", self.0) | ||
} | ||
} | ||
|
||
/// Converts a G1 element to a representation that can be used in Solidity templates. | ||
pub fn g1_to_fq_repr(g1: G1Affine) -> G1Repr { | ||
G1Repr([FqWrapper(g1.x), FqWrapper(g1.y)]) | ||
} | ||
|
||
#[derive(Debug, Default)] | ||
pub struct G2Repr(pub [[FqWrapper; 2]; 2]); | ||
|
||
impl Display for G2Repr { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "{:#?}", self.0) | ||
} | ||
} | ||
|
||
/// Converts a G2 element to a representation that can be used in Solidity templates. | ||
pub fn g2_to_fq_repr(g2: G2Affine) -> G2Repr { | ||
G2Repr([ | ||
[FqWrapper(g2.x.c0), FqWrapper(g2.x.c1)], | ||
[FqWrapper(g2.y.c0), FqWrapper(g2.y.c1)], | ||
]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod encoding; |
Oops, something went wrong.