Skip to content
This repository has been archived by the owner on Aug 16, 2024. It is now read-only.

Commit

Permalink
✨ add EC precompiles
Browse files Browse the repository at this point in the history
  • Loading branch information
ZamDimon authored and NikitaMasych committed May 27, 2024
1 parent 17ad0dd commit 12a6b87
Show file tree
Hide file tree
Showing 12 changed files with 814 additions and 13 deletions.
4 changes: 2 additions & 2 deletions circuit_definitions/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ license = "MIT OR Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
snark_wrapper = {git = "https://github.com/matter-labs/snark-wrapper.git", branch = "main"}
# snark_wrapper = {path = "../../snark_wrapper"}
# snark_wrapper = {git = "https://github.com/matter-labs/snark-wrapper.git", branch = "main"}
snark_wrapper = {path = "../../snark-wrapper"}

circuit_encodings = {path = "../circuit_encodings"}

Expand Down
178 changes: 178 additions & 0 deletions circuit_definitions/src/circuit_definitions/base_layer/ecadd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
use crate::zkevm_circuits::bn254::ec_add::input::EcAddCircuitInstanceWitness;
use circuit_encodings::zkevm_circuits::bn254::{
ec_add::ecadd_function_entry_point,
fixed_base_mul_table::{create_fixed_base_mul_table, FixedBaseMulTable},
};
use derivative::*;

use super::*;
use crate::boojum::cs::traits::circuit::CircuitBuilder;

type F = GoldilocksField;
type R = Poseidon2Goldilocks;

#[derive(Derivative, serde::Serialize, serde::Deserialize)]
#[derivative(Clone, Copy, Debug, Default(bound = ""))]
pub struct ECAddFunctionInstanceSynthesisFunction {
_marker: std::marker::PhantomData<(F, R)>,
}

impl CircuitBuilder<F> for ECAddFunctionInstanceSynthesisFunction
where
[(); <LogQuery<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <MemoryQuery<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <DecommitQuery<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <UInt256<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <UInt256<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN + 1]:,
{
fn geometry() -> CSGeometry {
CSGeometry {
num_columns_under_copy_permutation: 200,
num_witness_columns: 0,
num_constant_columns: 8,
max_allowed_constraint_degree: 4,
}
}

fn lookup_parameters() -> LookupParameters {
LookupParameters::UseSpecializedColumnsWithTableIdAsConstant {
width: 3,
num_repetitions: 8,
share_table_id: true,
}
}

fn configure_builder<
T: CsBuilderImpl<F, T>,
GC: GateConfigurationHolder<F>,
TB: StaticToolboxHolder,
>(
builder: CsBuilder<T, F, GC, TB>,
) -> CsBuilder<T, F, impl GateConfigurationHolder<F>, impl StaticToolboxHolder> {
// TODO: Maybe some gates are not actually needed since it was copy-pasting from the previous secp256k1 ecmul implementation.
let builder = builder.allow_lookup(<Self as CircuitBuilder<F>>::lookup_parameters());

let builder = U8x4FMAGate::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = ConstantsAllocatorGate::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = FmaGateInBaseFieldWithoutConstant::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = ReductionGate::<F, 4>::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
// let owned_cs = ReductionGate::<F, 4>::configure_for_cs(owned_cs, GatePlacementStrategy::UseSpecializedColumns { num_repetitions: 8, share_constants: true });
let builder = BooleanConstraintGate::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = UIntXAddGate::<32>::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = UIntXAddGate::<16>::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = UIntXAddGate::<8>::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = SelectionGate::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = ZeroCheckGate::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
false,
);
let builder = DotProductGate::<4>::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder =
NopGate::configure_builder(builder, GatePlacementStrategy::UseGeneralPurposeColumns);

builder
}
}

impl ZkSyncUniformSynthesisFunction<F> for ECAddFunctionInstanceSynthesisFunction
where
[(); <LogQuery<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <MemoryQuery<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <DecommitQuery<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <UInt256<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <UInt256<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN + 1]:,
{
type Witness = EcAddCircuitInstanceWitness<F>;
type Config = usize;
type RoundFunction = R;

fn description() -> String {
"Elliptic Curve Addition".to_string()
}

fn size_hint() -> (Option<usize>, Option<usize>) {
(Some(TARGET_CIRCUIT_TRACE_LENGTH), Some(1 << 26))
}

fn add_tables<CS: ConstraintSystem<F>>(cs: &mut CS) {
// let table = create_range_check_table::<F, 8>();
// cs.add_lookup_table::<RangeCheckTable<8>, 1>(table);

// let table = create_range_check_16_bits_table::<F>();
// cs.add_lookup_table::<RangeCheck16BitsTable, 1>(table);

let table = create_xor8_table();
cs.add_lookup_table::<Xor8Table, 3>(table);

let table = create_and8_table();
cs.add_lookup_table::<And8Table, 3>(table);

seq_macro::seq!(C in 0..32 {
let table = create_fixed_base_mul_table::<F, 0, C>();
cs.add_lookup_table::<FixedBaseMulTable<0, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 1, C>();
cs.add_lookup_table::<FixedBaseMulTable<1, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 2, C>();
cs.add_lookup_table::<FixedBaseMulTable<2, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 3, C>();
cs.add_lookup_table::<FixedBaseMulTable<3, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 4, C>();
cs.add_lookup_table::<FixedBaseMulTable<4, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 5, C>();
cs.add_lookup_table::<FixedBaseMulTable<5, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 6, C>();
cs.add_lookup_table::<FixedBaseMulTable<6, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 7, C>();
cs.add_lookup_table::<FixedBaseMulTable<7, C>, 3>(table);
});

let table = create_byte_split_table::<F, 1>();
cs.add_lookup_table::<ByteSplitTable<1>, 3>(table);
let table = create_byte_split_table::<F, 2>();
cs.add_lookup_table::<ByteSplitTable<2>, 3>(table);
let table = create_byte_split_table::<F, 3>();
cs.add_lookup_table::<ByteSplitTable<3>, 3>(table);
let table = create_byte_split_table::<F, 4>();
cs.add_lookup_table::<ByteSplitTable<4>, 3>(table);
}

fn synthesize_into_cs_inner<CS: ConstraintSystem<F>>(
cs: &mut CS,
witness: Self::Witness,
round_function: &Self::RoundFunction,
config: Self::Config,
) -> [Num<F>; INPUT_OUTPUT_COMMITMENT_LENGTH] {
ecadd_function_entry_point(cs, witness, round_function, config)
}
}
177 changes: 177 additions & 0 deletions circuit_definitions/src/circuit_definitions/base_layer/ecmul.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
use circuit_encodings::zkevm_circuits::bn254::{
ec_mul::{ecmul_function_entry_point, input::EcMulCircuitInstanceWitness},
fixed_base_mul_table::{create_fixed_base_mul_table, FixedBaseMulTable},
};
use derivative::*;

use super::*;
use crate::boojum::cs::traits::circuit::CircuitBuilder;

type F = GoldilocksField;
type R = Poseidon2Goldilocks;

#[derive(Derivative, serde::Serialize, serde::Deserialize)]
#[derivative(Clone, Copy, Debug, Default(bound = ""))]
pub struct ECMulFunctionInstanceSynthesisFunction {
_marker: std::marker::PhantomData<(F, R)>,
}

impl CircuitBuilder<F> for ECMulFunctionInstanceSynthesisFunction
where
[(); <LogQuery<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <MemoryQuery<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <DecommitQuery<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <UInt256<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <UInt256<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN + 1]:,
{
fn geometry() -> CSGeometry {
CSGeometry {
num_columns_under_copy_permutation: 200,
num_witness_columns: 0,
num_constant_columns: 8,
max_allowed_constraint_degree: 4,
}
}

fn lookup_parameters() -> LookupParameters {
LookupParameters::UseSpecializedColumnsWithTableIdAsConstant {
width: 3,
num_repetitions: 8,
share_table_id: true,
}
}

fn configure_builder<
T: CsBuilderImpl<F, T>,
GC: GateConfigurationHolder<F>,
TB: StaticToolboxHolder,
>(
builder: CsBuilder<T, F, GC, TB>,
) -> CsBuilder<T, F, impl GateConfigurationHolder<F>, impl StaticToolboxHolder> {
// TODO: Maybe some gates are not actually needed since it was copy-pasting from the previous secp256k1 ecmul implementation.
let builder = builder.allow_lookup(<Self as CircuitBuilder<F>>::lookup_parameters());

let builder = U8x4FMAGate::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = ConstantsAllocatorGate::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = FmaGateInBaseFieldWithoutConstant::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = ReductionGate::<F, 4>::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
// let owned_cs = ReductionGate::<F, 4>::configure_for_cs(owned_cs, GatePlacementStrategy::UseSpecializedColumns { num_repetitions: 8, share_constants: true });
let builder = BooleanConstraintGate::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = UIntXAddGate::<32>::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = UIntXAddGate::<16>::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = UIntXAddGate::<8>::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = SelectionGate::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder = ZeroCheckGate::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
false,
);
let builder = DotProductGate::<4>::configure_builder(
builder,
GatePlacementStrategy::UseGeneralPurposeColumns,
);
let builder =
NopGate::configure_builder(builder, GatePlacementStrategy::UseGeneralPurposeColumns);

builder
}
}

impl ZkSyncUniformSynthesisFunction<F> for ECMulFunctionInstanceSynthesisFunction
where
[(); <LogQuery<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <MemoryQuery<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <DecommitQuery<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <UInt256<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN]:,
[(); <UInt256<F> as CSAllocatableExt<F>>::INTERNAL_STRUCT_LEN + 1]:,
{
type Witness = EcMulCircuitInstanceWitness<F>;
type Config = usize;
type RoundFunction = R;

fn description() -> String {
"Elliptic Curve Multiplication".to_string()
}

fn size_hint() -> (Option<usize>, Option<usize>) {
(Some(TARGET_CIRCUIT_TRACE_LENGTH), Some(1 << 26))
}

fn add_tables<CS: ConstraintSystem<F>>(cs: &mut CS) {
// let table = create_range_check_table::<F, 8>();
// cs.add_lookup_table::<RangeCheckTable<8>, 1>(table);

// let table = create_range_check_16_bits_table::<F>();
// cs.add_lookup_table::<RangeCheck16BitsTable, 1>(table);

let table = create_xor8_table();
cs.add_lookup_table::<Xor8Table, 3>(table);

let table = create_and8_table();
cs.add_lookup_table::<And8Table, 3>(table);

seq_macro::seq!(C in 0..32 {
let table = create_fixed_base_mul_table::<F, 0, C>();
cs.add_lookup_table::<FixedBaseMulTable<0, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 1, C>();
cs.add_lookup_table::<FixedBaseMulTable<1, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 2, C>();
cs.add_lookup_table::<FixedBaseMulTable<2, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 3, C>();
cs.add_lookup_table::<FixedBaseMulTable<3, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 4, C>();
cs.add_lookup_table::<FixedBaseMulTable<4, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 5, C>();
cs.add_lookup_table::<FixedBaseMulTable<5, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 6, C>();
cs.add_lookup_table::<FixedBaseMulTable<6, C>, 3>(table);
let table = create_fixed_base_mul_table::<F, 7, C>();
cs.add_lookup_table::<FixedBaseMulTable<7, C>, 3>(table);
});

let table = create_byte_split_table::<F, 1>();
cs.add_lookup_table::<ByteSplitTable<1>, 3>(table);
let table = create_byte_split_table::<F, 2>();
cs.add_lookup_table::<ByteSplitTable<2>, 3>(table);
let table = create_byte_split_table::<F, 3>();
cs.add_lookup_table::<ByteSplitTable<3>, 3>(table);
let table = create_byte_split_table::<F, 4>();
cs.add_lookup_table::<ByteSplitTable<4>, 3>(table);
}

fn synthesize_into_cs_inner<CS: ConstraintSystem<F>>(
cs: &mut CS,
witness: Self::Witness,
round_function: &Self::RoundFunction,
config: Self::Config,
) -> [Num<F>; INPUT_OUTPUT_COMMITMENT_LENGTH] {
ecmul_function_entry_point(cs, witness, round_function, config)
}
}
Loading

0 comments on commit 12a6b87

Please sign in to comment.