Skip to content

Commit

Permalink
feat: change yul code into Solidity assembly (#47)
Browse files Browse the repository at this point in the history
* feat: change yul code into Solidity assembly

Just changes to wrapping yul in solidity assembly block

* chore: loosen pragma

* chore: remove example sol file
  • Loading branch information
jonathanpwang authored Sep 14, 2023
1 parent 810ba0d commit a440ff9
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 85 deletions.
19 changes: 13 additions & 6 deletions snark-verifier-sdk/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "snark-verifier-sdk"
version = "0.1.1"
version = "0.1.2"
edition = "2021"

[dependencies]
Expand All @@ -21,14 +21,16 @@ snark-verifier = { path = "../snark-verifier", default-features = false }

# system_halo2
halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2", tag = "v2023_04_20" } # not optional for now
halo2curves = { git = 'https://github.com/privacy-scaling-explorations/halo2curves', tag = "0.3.2" } # must be same version as in halo2_proofs
halo2curves = { git = 'https://github.com/privacy-scaling-explorations/halo2curves', tag = "0.3.2" } # must be same version as in halo2_proofs

# loader_halo2
halo2_wrong_ecc = { git = "https://github.com/privacy-scaling-explorations/halo2wrong", tag = "v2023_04_20", package = "ecc", optional = true }
poseidon = { git = "https://github.com/privacy-scaling-explorations/poseidon", tag = "v2023_04_20", optional = true }

# loader_evm
ethereum-types = { version = "0.14", default-features = false, features = ["std"], optional = true }
ethereum-types = { version = "0.14", default-features = false, features = [
"std",
], optional = true }

[dev-dependencies]
ark-std = { version = "0.3.0", features = ["print-trace"] }
Expand All @@ -41,12 +43,17 @@ criterion-macro = "0.4"
default = ["loader_halo2", "loader_evm", "derive_serde", "display"]
display = ["dep:ark-std"]
loader_evm = ["snark-verifier/loader_evm", "dep:ethereum-types"]
loader_halo2 = ["snark-verifier/system_halo2", "snark-verifier/loader_halo2", "dep:halo2_wrong_ecc", "dep:poseidon"]
loader_halo2 = [
"snark-verifier/system_halo2",
"snark-verifier/loader_halo2",
"dep:halo2_wrong_ecc",
"dep:poseidon",
]
parallel = ["snark-verifier/parallel"]
derive_serde = ["snark-verifier/derive_serde", "halo2curves/derive_serde"]
halo2_circuit_params = ["snark-verifier/halo2_circuit_params"]

[[bench]]

name = "standard_plonk"
required-features = ["loader_halo2"]
harness = false
required-features = ["loader_halo2", "loader_evm"]
30 changes: 9 additions & 21 deletions snark-verifier-sdk/examples/standard_plonk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,27 +170,15 @@ fn main() {
);
end_timer!(start0);

std::fs::remove_file("./examples/agg.snark").unwrap_or_default();
let _snark = gen_snark_shplonk(
let num_instances = agg_circuit.num_instance();
let instances = agg_circuit.instances();
let proof_calldata = gen_evm_proof_shplonk(&params, &pk, agg_circuit, instances.clone());

let deployment_code = gen_evm_verifier_shplonk::<AggregationCircuit<SHPLONK>>(
&params,
&pk,
agg_circuit.clone(),
Some(Path::new("./examples/agg.snark")),
pk.get_vk(),
num_instances,
Some(Path::new("./examples/StandardPlonkVerifierExample.sol")),
);

#[cfg(feature = "loader_evm")]
{
// do one more time to verify
let num_instances = agg_circuit.num_instance();
let instances = agg_circuit.instances();
let proof_calldata = gen_evm_proof_shplonk(&params, &pk, agg_circuit, instances.clone());

let deployment_code = gen_evm_verifier_shplonk::<AggregationCircuit<SHPLONK>>(
&params,
pk.get_vk(),
num_instances,
Some(Path::new("./examples/standard_plonk.yul")),
);
evm_verify(deployment_code, instances, proof_calldata);
}
evm_verify(deployment_code, instances, proof_calldata);
}
8 changes: 4 additions & 4 deletions snark-verifier-sdk/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use itertools::Itertools;
use rand::{rngs::StdRng, SeedableRng};
pub use snark_verifier::loader::evm::encode_calldata;
use snark_verifier::{
loader::evm::{compile_yul, deploy_and_call, EvmLoader},
loader::evm::{compile_solidity, deploy_and_call, EvmLoader},
pcs::{
kzg::{KzgAccumulator, KzgAsVerifyingKey, KzgDecidingKey, KzgSuccinctVerifyingKey},
AccumulationDecider, AccumulationScheme, PolynomialCommitmentScheme,
Expand Down Expand Up @@ -148,13 +148,13 @@ where
PlonkVerifier::<AS>::read_proof(&dk, &protocol, &instances, &mut transcript).unwrap();
PlonkVerifier::<AS>::verify(&dk, &protocol, &instances, &proof).unwrap();

let yul_code = loader.yul_code();
let byte_code = compile_yul(&yul_code);
let sol_code = loader.solidity_code();
let byte_code = compile_solidity(&sol_code);
if let Some(path) = path {
path.parent()
.and_then(|dir| fs::create_dir_all(dir).ok())
.unwrap();
fs::write(path, yul_code).unwrap();
fs::write(path, sol_code).unwrap();
}
byte_code
}
Expand Down
7 changes: 5 additions & 2 deletions snark-verifier/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "snark-verifier"
version = "0.1.0"
version = "0.1.1"
edition = "2021"

[dependencies]
Expand Down Expand Up @@ -50,7 +50,10 @@ loader_halo2 = ["dep:halo2_proofs", "dep:halo2_wrong_ecc", "dep:poseidon"]
system_halo2 = ["dep:halo2_proofs"]

# features of halo2
halo2_circuit_params = ["halo2_proofs?/circuit-params", "halo2_wrong_ecc?/circuit-params"]
halo2_circuit_params = [
"halo2_proofs?/circuit-params",
"halo2_wrong_ecc?/circuit-params",
]
derive_serde = ["dep:serde"]

[[example]]
Expand Down
2 changes: 1 addition & 1 deletion snark-verifier/examples/evm-verifier-with-accumulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ fn gen_aggregation_evm_verifier(
let proof = PlonkVerifier::read_proof(&vk, &protocol, &instances, &mut transcript).unwrap();
PlonkVerifier::verify(&vk, &protocol, &instances, &proof).unwrap();

evm::compile_yul(&loader.yul_code())
evm::compile_solidity(&loader.solidity_code())
}

fn evm_verify(deployment_code: Vec<u8>, instances: Vec<Vec<Fr>>, proof: Vec<u8>) {
Expand Down
2 changes: 1 addition & 1 deletion snark-verifier/examples/evm-verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ fn gen_evm_verifier(
let proof = PlonkVerifier::read_proof(&vk, &protocol, &instances, &mut transcript).unwrap();
PlonkVerifier::verify(&vk, &protocol, &instances, &proof).unwrap();

evm::compile_yul(&loader.yul_code())
evm::compile_solidity(&loader.solidity_code())
}

fn evm_verify(deployment_code: Vec<u8>, instances: Vec<Vec<Fr>>, proof: Vec<u8>) {
Expand Down
4 changes: 2 additions & 2 deletions snark-verifier/src/loader/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ pub(crate) mod util;

pub use loader::{EcPoint, EvmLoader, Scalar};
pub use util::{
compile_yul, deploy_and_call, encode_calldata, estimate_gas, fe_to_u256, modulus, u256_to_fe,
Address, B256, U256, U512,
compile_solidity, deploy_and_call, encode_calldata, estimate_gas, fe_to_u256, modulus,
u256_to_fe, Address, B256, U256, U512,
};
66 changes: 30 additions & 36 deletions snark-verifier/src/loader/evm/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,57 +6,51 @@ pub enum Precompiled {
}

#[derive(Clone, Debug)]
pub struct YulCode {
pub struct SolidityAssemblyCode {
// runtime code area
runtime: String,
}

impl YulCode {
impl SolidityAssemblyCode {
pub fn new() -> Self {
YulCode {
Self {
runtime: String::new(),
}
}

pub fn code(&self, base_modulus: String, scalar_modulus: String) -> String {
format!(
"
object \"plonk_verifier\" {{
code {{
function allocate(size) -> ptr {{
ptr := mload(0x40)
if eq(ptr, 0) {{ ptr := 0x60 }}
mstore(0x40, add(ptr, size))
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Halo2Verifier {{
fallback(bytes calldata) external returns (bytes memory) {{
assembly {{
let success := true
let f_p := {base_modulus}
let f_q := {scalar_modulus}
function validate_ec_point(x, y) -> valid {{
{{
let x_lt_p := lt(x, {base_modulus})
let y_lt_p := lt(y, {base_modulus})
valid := and(x_lt_p, y_lt_p)
}}
let size := datasize(\"Runtime\")
let offset := allocate(size)
datacopy(offset, dataoffset(\"Runtime\"), size)
return(offset, size)
}}
object \"Runtime\" {{
code {{
let success:bool := true
let f_p := {base_modulus}
let f_q := {scalar_modulus}
function validate_ec_point(x, y) -> valid:bool {{
{{
let x_lt_p:bool := lt(x, {base_modulus})
let y_lt_p:bool := lt(y, {base_modulus})
valid := and(x_lt_p, y_lt_p)
}}
{{
let y_square := mulmod(y, y, {base_modulus})
let x_square := mulmod(x, x, {base_modulus})
let x_cube := mulmod(x_square, x, {base_modulus})
let x_cube_plus_3 := addmod(x_cube, 3, {base_modulus})
let is_affine:bool := eq(x_cube_plus_3, y_square)
valid := and(valid, is_affine)
}}
}}
{}
{{
let y_square := mulmod(y, y, {base_modulus})
let x_square := mulmod(x, x, {base_modulus})
let x_cube := mulmod(x_square, x, {base_modulus})
let x_cube_plus_3 := addmod(x_cube, 3, {base_modulus})
let is_affine := eq(x_cube_plus_3, y_square)
valid := and(valid, is_affine)
}}
}}
}}",
{}
}}
}}
}}
",
self.runtime
)
}
Expand Down
18 changes: 11 additions & 7 deletions snark-verifier/src/loader/evm/loader.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
loader::{
evm::{
code::{Precompiled, YulCode},
code::{Precompiled, SolidityAssemblyCode},
fe_to_u256, modulus, u256_to_fe, U256, U512,
},
EcPointLoader, LoadedEcPoint, LoadedScalar, Loader, ScalarLoader,
Expand Down Expand Up @@ -53,7 +53,7 @@ impl<T: Debug> Value<T> {
pub struct EvmLoader {
base_modulus: U256,
scalar_modulus: U256,
code: RefCell<YulCode>,
code: RefCell<SolidityAssemblyCode>,
ptr: RefCell<usize>,
cache: RefCell<HashMap<String, usize>>,
}
Expand All @@ -71,7 +71,7 @@ impl EvmLoader {
{
let base_modulus = modulus::<Base>();
let scalar_modulus = modulus::<Scalar>();
let code = YulCode::new();
let code = SolidityAssemblyCode::new();

Rc::new(Self {
base_modulus,
Expand All @@ -82,10 +82,14 @@ impl EvmLoader {
})
}

/// Returns generated yul code.
pub fn yul_code(self: &Rc<Self>) -> String {
/// Returns generated Solidity code. This is "Solidity" code that is wrapped in an assembly block.
/// In other words, it's basically just assembly (equivalently, Yul).
pub fn solidity_code(self: &Rc<Self>) -> String {
let code = "
if not(success) { revert(0, 0) }
// Revert if anything fails
if iszero(success) { revert(0, 0) }
// Return empty bytes on success
return(0, 0)"
.to_string();
self.code.borrow_mut().runtime_append(code);
Expand All @@ -106,7 +110,7 @@ impl EvmLoader {
*self.ptr.borrow()
}

pub(crate) fn code_mut(&self) -> impl DerefMut<Target = YulCode> + '_ {
pub(crate) fn code_mut(&self) -> impl DerefMut<Target = SolidityAssemblyCode> + '_ {
self.code.borrow_mut()
}

Expand Down
5 changes: 2 additions & 3 deletions snark-verifier/src/loader/evm/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,12 @@ pub fn estimate_gas(cost: Cost) -> usize {
intrinsic_cost + calldata_cost + ec_operation_cost
}

/// Compile given yul `code` into deployment bytecode.
pub fn compile_yul(code: &str) -> Vec<u8> {
/// Compile given Solidity `code` into deployment bytecode.
pub fn compile_solidity(code: &str) -> Vec<u8> {
let mut cmd = Command::new("solc")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.arg("--bin")
.arg("--yul")
.arg("-")
.spawn()
.unwrap();
Expand Down
4 changes: 2 additions & 2 deletions snark-verifier/src/system/halo2/test/kzg/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ macro_rules! halo2_kzg_evm_verify {
use halo2_proofs::poly::commitment::ParamsProver;
use std::rc::Rc;
use $crate::{
loader::evm::{compile_yul, deploy_and_call, encode_calldata, EvmLoader},
loader::evm::{compile_solidity, deploy_and_call, encode_calldata, EvmLoader},
system::halo2::{
test::kzg::{BITS, LIMBS},
transcript::evm::EvmTranscript,
Expand All @@ -48,7 +48,7 @@ macro_rules! halo2_kzg_evm_verify {
<$plonk_verifier>::read_proof(&vk, &protocol, &instances, &mut transcript).unwrap();
<$plonk_verifier>::verify(&vk, &protocol, &instances, &proof).unwrap();

compile_yul(&loader.yul_code())
compile_solidity(&loader.solidity_code())
};

let calldata = encode_calldata($instances, &$proof);
Expand Down

0 comments on commit a440ff9

Please sign in to comment.