Skip to content

Commit

Permalink
test: add PLONK test for public input mapping (#1123)
Browse files Browse the repository at this point in the history
  • Loading branch information
ivokub authored May 3, 2024
1 parent 88712e5 commit 2031950
Showing 1 changed file with 202 additions and 0 deletions.
202 changes: 202 additions & 0 deletions std/recursion/plonk/verifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -599,3 +599,205 @@ func TestBLS12InBW6MultiHashed(t *testing.T) {
err = test.IsSolved(aggCircuit, aggAssignment, ecc.BW6_761.ScalarField())
assert.NoError(err)
}

// interconnection circuit
type HubCircuit struct {
PerCircuitInput []frontend.Variable `gnark:",public"`
RootInput frontend.Variable `gnark:",public"`
}

func (c *HubCircuit) Define(api frontend.API) error {
p := api.Mul(c.PerCircuitInput[0], c.PerCircuitInput[1])
for i := 2; i < len(c.PerCircuitInput); i++ {
p = api.Mul(p, c.PerCircuitInput[i])
}
api.AssertIsEqual(p, c.RootInput)
return nil
}

type AggregationDiffPubs[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT, GtEl algebra.GtElementT] struct {
BaseKeySinglePub BaseVerifyingKey[FR, G1El, G2El] `gnark:"-"`
CircuitKeys []CircuitVerifyingKey[FR, G1El]
Selectors []frontend.Variable
Proofs []Proof[FR, G1El, G2El]
Witnesses []Witness[FR]

HubKey VerifyingKey[FR, G1El, G2El] `gnark:"-"`
PublicInput emulated.Element[FR] `gnark:",public"`
HubProof Proof[FR, G1El, G2El]
}

func (c *AggregationDiffPubs[FR, G1El, G2El, GtEl]) Define(api frontend.API) error {
v, err := NewVerifier[FR, G1El, G2El, GtEl](api)
if err != nil {
return fmt.Errorf("plonk verifier: %w", err)
}
// var foldedDigests []kzg.Commitment[G1El]
// var foldedProofs []kzg.OpeningProof[FR, G1El]
// var foldedPoints []emulated.Element[FR]
// for i := range c.Proofs {
// vk, err := v.SwitchVerificationKey(c.BaseKeySinglePub, c.Selectors[i], c.CircuitKeys)
// if err != nil {
// return fmt.Errorf("switch verification key: %w", err)
// }
// dg, pr, pts, err := v.PrepareVerification(vk, c.Proofs[i], c.Witnesses[i])
// if err != nil {
// return fmt.Errorf("prepare proof %d: %w", i, err)
// }
// foldedDigests = append(foldedDigests, dg...)
// foldedProofs = append(foldedProofs, pr...)
// foldedPoints = append(foldedPoints, pts...)
// }
if err := v.AssertDifferentProofs(c.BaseKeySinglePub, c.CircuitKeys, c.Selectors, c.Proofs, c.Witnesses); err != nil {
return fmt.Errorf("assert different proofs: %w", err)
}
hubWitness := Witness[FR]{Public: make([]emulated.Element[FR], len(c.Witnesses)+1)}
for i := range c.Witnesses {
hubWitness.Public[i] = c.Witnesses[i].Public[0]
}
hubWitness.Public[len(c.Witnesses)] = c.PublicInput
if err := v.AssertProof(c.HubKey, c.HubProof, hubWitness, WithCompleteArithmetic()); err != nil {
return fmt.Errorf("assert hub proof: %w", err)
}
// dg, pr, pts, err := v.PrepareVerification(c.HubKey, c.HubProof, hubWitness, WithCompleteArithmetic())
// if err != nil {
// return fmt.Errorf("prepare hub proof: %w", err)
// }
// foldedDigests = append(foldedDigests, dg...)
// foldedProofs = append(foldedProofs, pr...)
// foldedPoints = append(foldedPoints, pts...)
// k, err := kzg.NewVerifier[FR, G1El, G2El, GtEl](api)
// if err != nil {
// return fmt.Errorf("kzg verifier: %w", err)
// }
// if err := k.BatchVerifyMultiPoints(foldedDigests, foldedProofs, foldedPoints, c.BaseKeySinglePub.Kzg); err != nil {
// return fmt.Errorf("batch verify multi points: %w", err)
// }

return nil
}

func getParametricSetups2[FR emulated.FieldParams](assert *test.Assert, field *big.Int, nbParams, nbInner int) ([]constraint.ConstraintSystem, []native_plonk.VerifyingKey, []native_plonk.ProvingKey) {
var err error

ccss := make([]constraint.ConstraintSystem, nbParams+1)
vks := make([]native_plonk.VerifyingKey, nbParams+1)
pks := make([]native_plonk.ProvingKey, nbParams+1)
for i := range ccss {
ccss[i], err = frontend.Compile(field, scs.NewBuilder, &InnerCircuitParametric{parameter: 8 << i})
assert.NoError(err)
}
ccss[nbParams], err = frontend.Compile(field, scs.NewBuilder, &HubCircuit{PerCircuitInput: make([]frontend.Variable, nbInner)})
assert.NoError(err)

srs, srsLagrange, err := unsafekzg.NewSRS(ccss[nbParams-1])
assert.NoError(err)
srsT, ok := srs.(*kzg_bls12377.SRS)
assert.True(ok)
srsLagrangeT, ok := srsLagrange.(*kzg_bls12377.SRS)
assert.True(ok)

for i := range vks {
sizeSystem := ccss[i].GetNbPublicVariables() + ccss[i].GetNbConstraints()
nextPowerTwo := 1 << stdbits.Len(uint(sizeSystem))
srsLagrangeT.Pk.G1, err = kzg_bls12377.ToLagrangeG1(srsT.Pk.G1[:nextPowerTwo])
assert.NoError(err)
pks[i], vks[i], err = native_plonk.Setup(ccss[i], srsT, srsLagrangeT)
assert.NoError(err)
}
return ccss, vks, pks
}

func getHubProof(assert *test.Assert, outer, field *big.Int, witness []witness.Witness, ccs constraint.ConstraintSystem, vk native_plonk.VerifyingKey, pk native_plonk.ProvingKey) (native_plonk.Proof, fr_bls12377.Element) {
witnesses := make([]fr_bls12377.Element, len(witness))
root := fr_bls12377.One()
for i := range witness {
pubWit, err := witness[i].Public()
assert.NoError(err)
vec, ok := pubWit.Vector().(fr_bls12377.Vector)
assert.True(ok)
witnesses[i] = vec[0]
root.Mul(&root, &witnesses[i])
}
hubAssignment := HubCircuit{PerCircuitInput: make([]frontend.Variable, len(witnesses)), RootInput: root.String()}
for i := range witnesses {
hubAssignment.PerCircuitInput[i] = witnesses[i].String()
}
hubWit, err := frontend.NewWitness(&hubAssignment, field)
assert.NoError(err)
proof, err := native_plonk.Prove(ccs, pk, hubWit, GetNativeProverOptions(outer, field))
assert.NoError(err)
hubWitPub, err := hubWit.Public()
assert.NoError(err)
err = native_plonk.Verify(proof, vk, hubWitPub, GetNativeVerifierOptions(outer, field))
assert.NoError(err)
return proof, root
}

func TestAggregationDiff(t *testing.T) {
innerField := ecc.BLS12_377.ScalarField()
outerField := ecc.BW6_761.ScalarField()
nbCircuits := 5
nbProofs := 20
assert := test.NewAssert(t)
ccss, vks, pks := getParametricSetups2[sw_bls12377.ScalarField](assert, innerField, nbCircuits, nbProofs)
hubCcs, hubVk, hubPk := ccss[nbCircuits], vks[nbCircuits], pks[nbCircuits]
innerProofs := make([]native_plonk.Proof, nbProofs)
innerWitnesses := make([]witness.Witness, nbProofs)
innerSelectors := make([]int, nbProofs)
for i := 0; i < nbProofs; i++ {
innerSelectors[i], innerWitnesses[i], innerProofs[i] = getRandomParametricProof(assert, innerField, outerField, ccss[:nbCircuits], vks[:nbCircuits], pks[:nbCircuits])
}
hubProof, hubRoot := getHubProof(assert, outerField, innerField, innerWitnesses, hubCcs, hubVk, hubPk)
circuitHubProof, err := ValueOfProof[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine](hubProof)
assert.NoError(err)
circuitVk, err := ValueOfVerifyingKey[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine](hubVk)
assert.NoError(err)
circuitBvk, err := ValueOfBaseVerifyingKey[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine](vks[0])
assert.NoError(err)
circuitVks := make([]CircuitVerifyingKey[sw_bls12377.ScalarField, sw_bls12377.G1Affine], nbCircuits)
for i := range circuitVks {
circuitVks[i], err = ValueOfCircuitVerifyingKey[sw_bls12377.ScalarField, sw_bls12377.G1Affine](vks[i])
assert.NoError(err)
}
circuitSelector := make([]frontend.Variable, nbProofs)
for i := range circuitSelector {
circuitSelector[i] = innerSelectors[i]
}
circuitProofs := make([]Proof[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine], nbProofs)
for i := range circuitProofs {
circuitProofs[i], err = ValueOfProof[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine](innerProofs[i])
assert.NoError(err)
}
circuitWitnesses := make([]Witness[sw_bls12377.ScalarField], nbProofs)
for i := range circuitWitnesses {
circuitWitnesses[i], err = ValueOfWitness[sw_bls12377.ScalarField](innerWitnesses[i])
assert.NoError(err)
}
aggCircuit := &AggregationDiffPubs[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine, sw_bls12377.GT]{
BaseKeySinglePub: circuitBvk,
CircuitKeys: make([]CircuitVerifyingKey[sw_bls12377.ScalarField, sw_bls12377.G1Affine], nbCircuits),
Selectors: make([]frontend.Variable, nbProofs),
Proofs: make([]Proof[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine], nbProofs),
Witnesses: make([]Witness[sw_bls12377.ScalarField], nbProofs),
HubKey: circuitVk,
HubProof: PlaceholderProof[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine](hubCcs),
}
for i := 0; i < nbCircuits; i++ {
aggCircuit.CircuitKeys[i] = PlaceholderCircuitVerifyingKey[sw_bls12377.ScalarField, sw_bls12377.G1Affine](ccss[i])
}
for i := 0; i < nbProofs; i++ {
aggCircuit.Proofs[i] = PlaceholderProof[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine](ccss[0])
aggCircuit.Witnesses[i] = PlaceholderWitness[sw_bls12377.ScalarField](ccss[0])
}
aggAssignment := &AggregationDiffPubs[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine, sw_bls12377.GT]{
CircuitKeys: circuitVks,
Selectors: circuitSelector,
Proofs: circuitProofs,
Witnesses: circuitWitnesses,
PublicInput: emulated.ValueOf[sw_bls12377.ScalarField](hubRoot),
HubProof: circuitHubProof,
}
err = test.IsSolved(aggCircuit, aggAssignment, ecc.BW6_761.ScalarField())
assert.NoError(err)
}

0 comments on commit 2031950

Please sign in to comment.