Skip to content

Commit

Permalink
fix: add exclusive constraint for Miller loop and Final exp masks (#174)
Browse files Browse the repository at this point in the history
* feat: add IsActive to Unaligned pairing data submodule

* feat: only unaligned g2 data or pairing data active at a time

* chore: use common constraint for pairwise exclusive columns

* fix: exclusive Miller loop and final exp masks

* fix: remove double constraints

* test: unaligned pairing data IsActive unit test

* chore: use common cs for accumulator masks

* chore: remove duplicate constraint

* chore: use unaligned pairing data IsActive

* fix: add constraints when zero-ness cannot be deduced from projection or other constraints
  • Loading branch information
ivokub authored Oct 16, 2024
1 parent 3c6219d commit 5a2ab95
Show file tree
Hide file tree
Showing 8 changed files with 830 additions and 816 deletions.
6 changes: 6 additions & 0 deletions prover/zkevm/prover/ecpair/ecpair.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ func newECPair(comp *wizard.CompiledIOP, limits *Limits, ecSource *ECPairSource)
res.csLastPairToFinalExp(comp)
res.csIndexConsistency(comp)
res.csAccumulatorMask(comp)
// only Unaligned Pairing data or G2 membership data is active at a time
res.csExclusiveUnalignedDatas(comp)
// only to Miller loop or to FinalExp
res.csExclusivePairingCircuitMasks(comp)

return res
}
Expand Down Expand Up @@ -221,6 +225,7 @@ func newUnalignedG2MembershipData(comp *wizard.CompiledIOP, limits *Limits) *Una
//
// Use [newUnalignedPairingData] to create a new instance of UnalignedPairingData.
type UnalignedPairingData struct {
IsActive ifaces.Column
IsPulling ifaces.Column
IsComputed ifaces.Column
IsAccumulatorInit ifaces.Column
Expand All @@ -246,6 +251,7 @@ func newUnalignedPairingData(comp *wizard.CompiledIOP, limits *Limits) *Unaligne
createCol := createColFn(comp, namePairingData, size)

return &UnalignedPairingData{
IsActive: createCol("IS_ACTIVE"),
IsPulling: createCol("IS_PULLING"),
IsComputed: createCol("IS_COMPUTED"),
Limb: createCol("LIMB"),
Expand Down
3 changes: 3 additions & 0 deletions prover/zkevm/prover/ecpair/ecpair_assignment.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func (ec *ECPair) assignPairingData(run *wizard.ProverRuntime) {
)

var (
dstIsActive = common.NewVectorBuilder(ec.UnalignedPairingData.IsActive)
dstLimb = common.NewVectorBuilder(ec.UnalignedPairingData.Limb)
dstToMillerLoop = common.NewVectorBuilder(ec.UnalignedPairingData.ToMillerLoopCircuitMask)
dstToFinalExp = common.NewVectorBuilder(ec.UnalignedPairingData.ToFinalExpCircuitMask)
Expand Down Expand Up @@ -130,6 +131,7 @@ func (ec *ECPair) assignPairingData(run *wizard.ProverRuntime) {
}
dstInstanceId.PushField(instanceId)
dstIndex.PushInt(i)
dstIsActive.PushOne()
}
for i := 0; i < nbInputs-1; i++ {
for j := 0; j < nbGtLimbs; j++ {
Expand Down Expand Up @@ -221,6 +223,7 @@ func (ec *ECPair) assignPairingData(run *wizard.ProverRuntime) {
}
currPos += nbInputs*(nbG1Limbs+nbG2Limbs) + 2
}
dstIsActive.PadAndAssign(run, field.Zero())
dstLimb.PadAndAssign(run, field.Zero())
dstPairId.PadAndAssign(run, field.Zero())
dstTotalPairs.PadAndAssign(run, field.Zero())
Expand Down
92 changes: 48 additions & 44 deletions prover/zkevm/prover/ecpair/ecpair_constraints.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,36 @@ func (ec *ECPair) csIsActiveActivation(comp *wizard.CompiledIOP) {
}

func (ec *ECPair) csBinaryConstraints(comp *wizard.CompiledIOP) {
common.MustBeBinary(comp, ec.UnalignedPairingData.IsPulling)
common.MustBeBinary(comp, ec.UnalignedPairingData.IsComputed)
common.MustBeBinary(comp, ec.UnalignedPairingData.IsFirstLineOfInstance)
common.MustBeBinary(comp, ec.UnalignedPairingData.IsAccumulatorInit)
common.MustBeBinary(comp, ec.UnalignedPairingData.IsAccumulatorCurr)
common.MustBeBinary(comp, ec.UnalignedPairingData.IsAccumulatorPrev)
common.MustBeBinary(comp, ec.UnalignedPairingData.ToMillerLoopCircuitMask)
common.MustBeBinary(comp, ec.UnalignedPairingData.ToFinalExpCircuitMask)
common.MustBeBinary(comp, ec.UnalignedG2MembershipData.IsPulling)
common.MustBeBinary(comp, ec.UnalignedG2MembershipData.IsComputed)
common.MustBeBinary(comp, ec.UnalignedG2MembershipData.ToG2MembershipCircuitMask)
common.MustBeBinary(comp, ec.UnalignedPairingData.IsFirstLineOfPrevAccumulator)
common.MustBeBinary(comp, ec.UnalignedPairingData.IsFirstLineOfCurrAccumulator)
}

func (ec *ECPair) csFlagConsistency(comp *wizard.CompiledIOP) {
// flag consistency. That the assigned data is pulled from input or computed.
comp.InsertGlobal(
roundNr,
ifaces.QueryIDf("%v_FLAG_CONSISTENCY", nameECPair),
sym.Sub(ec.IsActive,
ec.UnalignedPairingData.IsPulling,
ec.UnalignedPairingData.IsComputed,
ec.UnalignedG2MembershipData.IsPulling,
ec.UnalignedG2MembershipData.IsComputed),
)
common.MustBeMutuallyExclusiveBinaryFlags(comp, ec.UnalignedPairingData.IsActive, []ifaces.Column{
ec.UnalignedPairingData.IsPulling,
ec.UnalignedPairingData.IsComputed,
})
common.MustBeMutuallyExclusiveBinaryFlags(comp, ec.UnalignedG2MembershipData.ToG2MembershipCircuitMask, []ifaces.Column{
ec.UnalignedG2MembershipData.IsPulling,
ec.UnalignedG2MembershipData.IsComputed,
})
}

func (ec *ECPair) csOffWhenInactive(comp *wizard.CompiledIOP) {
// nothing is set when inactive
common.MustZeroWhenInactive(comp, ec.IsActive,
ec.UnalignedPairingData.InstanceID,
ec.UnalignedPairingData.PairID,
ec.UnalignedPairingData.TotalPairs,
ec.UnalignedPairingData.Limb,
ec.UnalignedPairingData.ToMillerLoopCircuitMask,
ec.UnalignedPairingData.ToFinalExpCircuitMask,
ec.UnalignedPairingData.Index,
ec.UnalignedPairingData.IsFirstLineOfInstance,
ec.UnalignedPairingData.IsFirstLineOfPrevAccumulator,
ec.UnalignedPairingData.IsFirstLineOfCurrAccumulator,
ec.UnalignedG2MembershipData.Limb,
ec.UnalignedG2MembershipData.ToG2MembershipCircuitMask,
ec.UnalignedG2MembershipData.SuccessBit,
)
}

Expand Down Expand Up @@ -94,7 +88,7 @@ func (ec *ECPair) csConstantWhenIsComputing(comp *wizard.CompiledIOP) {
roundNr,
ifaces.QueryIDf("%v_COUNTERS_CONSISTENCY", nameECPair),
sym.Mul(
ec.IsActive,
ec.UnalignedPairingData.IsActive,
ec.UnalignedPairingData.IsComputed,
sym.Sub(1, ec.UnalignedPairingData.IsFirstLineOfInstance),
sym.Sub(ec.UnalignedPairingData.PairID, column.Shift(ec.UnalignedPairingData.PairID, -1)),
Expand Down Expand Up @@ -122,8 +116,8 @@ func (ec *ECPair) csInstanceIDChangeWhenNewInstance(comp *wizard.CompiledIOP) {
roundNr,
ifaces.QueryIDf("%v_INSTANCE_ID_CHANGE", nameECPair),
sym.Mul(
column.Shift(verifiercol.NewConstantCol(field.One(), ec.IsActive.Size()), -1), // this "useless" line helps cancelling the constraint on the first row
ec.IsActive,
column.Shift(verifiercol.NewConstantCol(field.One(), ec.UnalignedPairingData.IsActive.Size()), -1), // this "useless" line helps cancelling the constraint on the first row
ec.UnalignedPairingData.IsActive,
ec.UnalignedPairingData.IsFirstLineOfInstance,
ec.UnalignedPairingData.InstanceID,
prevEqualCurrID,
Expand All @@ -148,7 +142,7 @@ func (ec *ECPair) csAccumulatorInit(comp *wizard.CompiledIOP) {
roundNr,
ifaces.QueryIDf("%v_ACCUMULATOR_INIT", nameECPair),
sym.Mul(
ec.IsActive,
ec.UnalignedPairingData.IsActive,
ec.UnalignedPairingData.IsFirstLineOfInstance,
accLimbSum,
),
Expand All @@ -173,7 +167,7 @@ func (ec *ECPair) csLastPairToFinalExp(comp *wizard.CompiledIOP) {
roundNr,
ifaces.QueryIDf("%v_LAST_PAIR_TO_FINAL_EXP", nameECPair),
sym.Mul(
ec.IsActive,
ec.UnalignedPairingData.IsActive,
sym.Sub(ec.UnalignedPairingData.PairID, ec.UnalignedPairingData.TotalPairs),
ec.UnalignedPairingData.PairID,
ec.UnalignedPairingData.ToFinalExpCircuitMask,
Expand All @@ -187,7 +181,7 @@ func (ec *ECPair) csIndexConsistency(comp *wizard.CompiledIOP) {
roundNr,
ifaces.QueryIDf("%v_INDEX_START", nameECPair),
sym.Mul(
ec.IsActive,
ec.UnalignedPairingData.IsActive,
ec.UnalignedPairingData.IsFirstLineOfInstance,
ec.UnalignedPairingData.Index,
),
Expand All @@ -196,7 +190,7 @@ func (ec *ECPair) csIndexConsistency(comp *wizard.CompiledIOP) {
roundNr,
ifaces.QueryIDf("%v_INDEX_INCREMENT", nameECPair),
sym.Mul(
ec.IsActive,
ec.UnalignedPairingData.IsActive,
sym.Sub(1, ec.UnalignedG2MembershipData.IsPulling, ec.UnalignedG2MembershipData.IsComputed), // we dont use index in the G2 membership check
sym.Sub(1, ec.UnalignedPairingData.IsFirstLineOfInstance),
sym.Sub(ec.UnalignedPairingData.Index, column.Shift(ec.UnalignedPairingData.Index, -1), 1),
Expand All @@ -206,23 +200,18 @@ func (ec *ECPair) csIndexConsistency(comp *wizard.CompiledIOP) {

func (ec *ECPair) csAccumulatorMask(comp *wizard.CompiledIOP) {
// accumulator sum is IS_COMPUTED
comp.InsertGlobal(
roundNr,
ifaces.QueryIDf("%v_ACCUMULATOR_MASK", nameECPair),
sym.Sub(
ec.UnalignedPairingData.IsComputed,
ec.UnalignedPairingData.IsAccumulatorCurr,
ec.UnalignedPairingData.IsAccumulatorPrev,
ec.UnalignedPairingData.IsAccumulatorInit,
),
)
common.MustBeMutuallyExclusiveBinaryFlags(comp, ec.UnalignedPairingData.IsComputed, []ifaces.Column{
ec.UnalignedPairingData.IsAccumulatorCurr,
ec.UnalignedPairingData.IsAccumulatorPrev,
ec.UnalignedPairingData.IsAccumulatorInit,
})

// first prev accumulator is 1 when pairID*60 == index
comp.InsertGlobal(
roundNr,
ifaces.QueryIDf("%v_FIRST_ACC_PREV", nameECPair),
sym.Mul(
ec.IsActive,
ec.UnalignedPairingData.IsActive,
ec.UnalignedPairingData.IsFirstLineOfPrevAccumulator,
sym.Sub(
sym.Mul(nbG1Limbs+nbG2Limbs+2*nbGtLimbs, sym.Sub(ec.UnalignedPairingData.PairID, 1)),
Expand All @@ -236,7 +225,7 @@ func (ec *ECPair) csAccumulatorMask(comp *wizard.CompiledIOP) {
roundNr,
ifaces.QueryIDf("%v_FIRST_ACC_CURR", nameECPair),
sym.Mul(
ec.IsActive,
ec.UnalignedPairingData.IsActive,
ec.UnalignedPairingData.IsFirstLineOfCurrAccumulator,
sym.Sub(
sym.Mul(nbG1Limbs+nbG2Limbs+2*nbGtLimbs, ec.UnalignedPairingData.PairID),
Expand All @@ -258,7 +247,7 @@ func (ec *ECPair) csAccumulatorMask(comp *wizard.CompiledIOP) {
roundNr,
ifaces.QueryIDf("%v_INIT_ACC_MASK", nameECPair),
sym.Mul(
ec.IsActive,
ec.UnalignedPairingData.IsActive,
ec.UnalignedPairingData.IsFirstLineOfInstance,
sym.Sub(nbGtLimbs, sumMask(ec.UnalignedPairingData.IsAccumulatorInit)),
),
Expand All @@ -269,7 +258,7 @@ func (ec *ECPair) csAccumulatorMask(comp *wizard.CompiledIOP) {
roundNr,
ifaces.QueryIDf("%v_CURR_ACC_MASK", nameECPair),
sym.Mul(
ec.IsActive,
ec.UnalignedPairingData.IsActive,
ec.UnalignedPairingData.IsFirstLineOfCurrAccumulator,
sym.Sub(nbGtLimbs, sumMask(ec.UnalignedPairingData.IsAccumulatorCurr)),
),
Expand All @@ -280,9 +269,24 @@ func (ec *ECPair) csAccumulatorMask(comp *wizard.CompiledIOP) {
roundNr,
ifaces.QueryIDf("%v_PREV_ACC_MASK", nameECPair),
sym.Mul(
ec.IsActive,
ec.UnalignedPairingData.IsActive,
ec.UnalignedPairingData.IsFirstLineOfPrevAccumulator,
sym.Sub(nbGtLimbs, sumMask(ec.UnalignedPairingData.IsAccumulatorPrev)),
),
)
}

func (ec *ECPair) csExclusiveUnalignedDatas(comp *wizard.CompiledIOP) {
common.MustBeMutuallyExclusiveBinaryFlags(comp, ec.IsActive, []ifaces.Column{
ec.UnalignedG2MembershipData.ToG2MembershipCircuitMask,
ec.UnalignedPairingData.IsActive,
})
}

func (ec *ECPair) csExclusivePairingCircuitMasks(comp *wizard.CompiledIOP) {
// the pairing circuit masks are mutually exclusive
common.MustBeMutuallyExclusiveBinaryFlags(comp, ec.UnalignedPairingData.IsActive, []ifaces.Column{
ec.UnalignedPairingData.ToMillerLoopCircuitMask,
ec.UnalignedPairingData.ToFinalExpCircuitMask,
})
}
1 change: 1 addition & 0 deletions prover/zkevm/prover/ecpair/ecpair_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ func testModule(t *testing.T, tc pairingDataTestCase, withPairingCircuit, withG2
if checkPairingModule {
modCt.CheckAssignment(run,
"ECPAIR_IS_ACTIVE",
"ECPAIR_UNALIGNED_PAIRING_DATA_IS_ACTIVE",
"ECPAIR_UNALIGNED_PAIRING_DATA_INDEX",
"ECPAIR_UNALIGNED_PAIRING_DATA_INSTANCE_ID",
"ECPAIR_UNALIGNED_PAIRING_DATA_PAIR_ID",
Expand Down
Loading

0 comments on commit 5a2ab95

Please sign in to comment.