This repository has been archived by the owner on Aug 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 57
✨ add EC and modexp precompiles #143
Open
NikitaMasych
wants to merge
4
commits into
matter-labs:dl-precompiles
Choose a base branch
from
distributed-lab:feature/ec-and-modexp-precompiles
base: dl-precompiles
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+2,439
−29
Open
Changes from 1 commit
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
12a6b87
:sparkles: add EC precompiles
ZamDimon 5f7a28e
:pushpin: added notes on dl-precompile dependencies in Cargo.toml files
NikitaMasych 67f3694
:sparkles: added modexp, finalized generation for ec
NikitaMasych 774ab8c
:pushpin: pin deps in Cargo.toml's to git versions; update recursion_…
NikitaMasych File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
178 changes: 178 additions & 0 deletions
178
circuit_definitions/src/circuit_definitions/base_layer/ecadd.rs
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,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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are any of these tables actually necessary? i thought ecadd only uses gates and it seems useless to add byte splits, bitwise ops and fixed base muls |
||
// 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
177
circuit_definitions/src/circuit_definitions/base_layer/ecmul.rs
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,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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i assume it's the same case with gates and tables here but these should be checked and removed before merging on each new circuit |
||
// 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) | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can check if this is the case or not by running a full proof of the circuit and then printing the gate stats - it should give you a tally of how often each gate is called