Step test case with public inputs (#23)

* added step test case

* export solidity code

* just set proof's public input as public variables

* make serialization a command line option

* added flag to output solidity

* some changes to the benchmark file

* used gnark cherry picked bug fix

* removed fuzz testing

* added some logging

* more debug messages and test cases for the hint issue

* removed usage of goldilocks reduce

* removed prints

* removed GoldilocksReduce

* removed prints

* added a todo

* some serialization changes
This commit is contained in:
Kevin Jue
2023-06-17 19:44:20 -07:00
committed by GitHub
parent 15b7dcbcdb
commit 9ce7bb7dbb
12 changed files with 17094 additions and 95 deletions

View File

@@ -0,0 +1,181 @@
{
"config": {
"num_wires": 136,
"num_routed_wires": 80,
"num_constants": 2,
"use_base_arithmetic_gate": true,
"security_bits": 100,
"num_challenges": 2,
"zero_knowledge": false,
"max_quotient_degree_factor": 8,
"fri_config": {
"rate_bits": 3,
"cap_height": 4,
"proof_of_work_bits": 16,
"reduction_strategy": {
"ConstantArityBits": [
4,
5
]
},
"num_query_rounds": 28
}
},
"fri_params": {
"config": {
"rate_bits": 3,
"cap_height": 4,
"proof_of_work_bits": 16,
"reduction_strategy": {
"ConstantArityBits": [
4,
5
]
},
"num_query_rounds": 28
},
"hiding": false,
"degree_bits": 13,
"reduction_arity_bits": [
4,
4
]
},
"gates": [
"NoopGate",
"PoseidonMdsGate(PhantomData<plonky2_field::goldilocks_field::GoldilocksField>)<WIDTH=12>",
"PublicInputGate",
"BaseSumGate { num_limbs: 63 } + Base: 2",
"ReducingExtensionGate { num_coeffs: 33 }",
"ReducingGate { num_coeffs: 44 }",
"ArithmeticExtensionGate { num_ops: 10 }",
"ArithmeticGate { num_ops: 20 }",
"MulExtensionGate { num_ops: 13 }",
"ExponentiationGate { num_power_bits: 67, _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>",
"RandomAccessGate { bits: 4, num_copies: 4, num_extra_constants: 2, _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>",
"CosetInterpolationGate { subgroup_bits: 4, degree: 6, barycentric_weights: [17293822565076172801, 18374686475376656385, 18446744069413535745, 281474976645120, 17592186044416, 18446744069414584577, 18446744000695107601, 18446744065119617025, 1152921504338411520, 72057594037927936, 18446744069415632897, 18446462594437939201, 18446726477228539905, 18446744069414584065, 68719476720, 4294967296], _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>",
"PoseidonGate(PhantomData<plonky2_field::goldilocks_field::GoldilocksField>)<WIDTH=12>"
],
"selectors_info": {
"selector_indices": [
0,
0,
0,
0,
0,
0,
1,
1,
1,
1,
2,
2,
3
],
"groups": [
{
"start": 0,
"end": 6
},
{
"start": 6,
"end": 10
},
{
"start": 10,
"end": 12
},
{
"start": 12,
"end": 13
}
]
},
"quotient_degree_factor": 8,
"num_gate_constraints": 123,
"num_constants": 6,
"num_public_inputs": 1350,
"k_is": [
1,
7,
49,
343,
2401,
16807,
117649,
823543,
5764801,
40353607,
282475249,
1977326743,
13841287201,
96889010407,
678223072849,
4747561509943,
33232930569601,
232630513987207,
1628413597910449,
11398895185373143,
79792266297612001,
558545864083284007,
3909821048582988049,
8922003270666332022,
7113790686420571191,
12903046666114829695,
16534350385145470581,
5059988279530788141,
16973173887300932666,
8131752794619022736,
1582037354089406189,
11074261478625843323,
3732854072722565977,
7683234439643377518,
16889152938674473984,
7543606154233811962,
15911754940807515092,
701820169165099718,
4912741184155698026,
15942444219675301861,
916645121239607101,
6416515848677249707,
8022122801911579307,
814627405137302186,
5702391835961115302,
3023254712898638472,
2716038920875884983,
565528376716610560,
3958698637016273920,
9264146389699333119,
9508792519651578870,
11221315429317299127,
4762231727562756605,
14888878023524711914,
11988425817600061793,
10132004445542095267,
15583798910550913906,
16852872026783475737,
7289639770996824233,
14133990258148600989,
6704211459967285318,
10035992080941828584,
14911712358349047125,
12148266161370408270,
11250886851934520606,
4969231685883306958,
16337877731768564385,
3684679705892444769,
7346013871832529062,
14528608963998534792,
9466542400916821939,
10925564598174000610,
2691975909559666986,
397087297503084581,
2779611082521592067,
1010533508236560148,
7073734557655921036,
12622653764762278610,
14571600075677612986,
9767480182670369297
],
"num_partial_products": 9
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
{
"constants_sigmas_cap": [
"16410135397206963995867986152754239948699603273283903389293816335827918317917",
"793737431233885020076403438726099627357557537710771017261200370525509120433",
"12956281394520952097582330637773878261111274369940411254759688417761804822142",
"10577530380775003887407451820221412218265659263471194993014549768898454599785",
"13610846379681807478607563401071620391800469867382019709290833315244210704863",
"765151448660164966011013501838259753360401123903311092227424737087007538841",
"13786717651422653112944870403443265466526140408716569251322854236333823743208",
"12716088402533018234480445545939519356897157402541455414075663659898205294136",
"7714394992134137076670975536966103814585482420260383440808539140364081464561",
"21494844788603743891376885362562637287120172946709821128154824772001032728080",
"14153637094178605853060659242981358456456672896438884686797867119060652807634",
"8426523842338951741294543051254253278084158527312126154422449980067255373785",
"9336152063716553400528035177375603771317196761317425271006398060378250593421",
"19032686473689874529303788521545715886983137707759075261782048632012085567581",
"15713676428971866339564327334872368460630508652571308740737040859682008007854",
"11466448479127530610447443676955276964009242931295623425740153710621884444011"
],
"circuit_digest": "9787759494185596126611266365248694578977961103378519017707766709237231108177"
}

View File

@@ -24,7 +24,7 @@ func (circuit *TestPlonkCircuit) Define(api frontend.API) error {
verifierChip := verifier.NewVerifierChip(api, commonCircuitData)
publicInputsHash := verifierChip.GetPublicInputsHash(proofWithPis.PublicInputs)
proofChallenges := verifierChip.GetChallenges(proofWithPis, publicInputsHash, commonCircuitData, verifierOnlyCircuitData)
proofChallenges := verifierChip.GetChallenges(proofWithPis.Proof, publicInputsHash, commonCircuitData, verifierOnlyCircuitData)
fieldAPI := field.NewFieldAPI(api)
qeAPI := field.NewQuadraticExtensionAPI(api, fieldAPI)

View File

@@ -47,7 +47,7 @@ func (c *VerifierChip) GetPublicInputsHash(publicInputs []field.F) poseidon.Pose
}
func (c *VerifierChip) GetChallenges(
proofWithPis common.ProofWithPublicInputs,
proof common.Proof,
publicInputsHash poseidon.PoseidonHashOut,
commonData common.CommonCircuitData,
verifierData common.VerifierOnlyCircuitData,
@@ -60,17 +60,17 @@ func (c *VerifierChip) GetChallenges(
challenger.ObserveBN128Hash(circuitDigest)
challenger.ObserveHash(publicInputsHash)
challenger.ObserveCap(proofWithPis.Proof.WiresCap)
challenger.ObserveCap(proof.WiresCap)
plonkBetas := challenger.GetNChallenges(numChallenges)
plonkGammas := challenger.GetNChallenges(numChallenges)
challenger.ObserveCap(proofWithPis.Proof.PlonkZsPartialProductsCap)
challenger.ObserveCap(proof.PlonkZsPartialProductsCap)
plonkAlphas := challenger.GetNChallenges(numChallenges)
challenger.ObserveCap(proofWithPis.Proof.QuotientPolysCap)
challenger.ObserveCap(proof.QuotientPolysCap)
plonkZeta := challenger.GetExtensionChallenge()
challenger.ObserveOpenings(fri.ToFriOpenings(proofWithPis.Proof.Openings))
challenger.ObserveOpenings(fri.ToFriOpenings(proof.Openings))
return common.ProofChallenges{
PlonkBetas: plonkBetas,
@@ -78,9 +78,9 @@ func (c *VerifierChip) GetChallenges(
PlonkAlphas: plonkAlphas,
PlonkZeta: plonkZeta,
FriChallenges: challenger.GetFriChallenges(
proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps,
proofWithPis.Proof.OpeningProof.FinalPoly,
proofWithPis.Proof.OpeningProof.PowWitness,
proof.OpeningProof.CommitPhaseMerkleCaps,
proof.OpeningProof.FinalPoly,
proof.OpeningProof.PowWitness,
commonData.DegreeBits,
config.FriConfig,
),
@@ -154,18 +154,20 @@ func (c *VerifierChip) generateProofInput(commonData common.CommonCircuitData) c
}
*/
func (c *VerifierChip) Verify(proofWithPis common.ProofWithPublicInputs, verifierData common.VerifierOnlyCircuitData, commonData common.CommonCircuitData) {
// Generate the parts of the witness that is for the plonky2 proof input
publicInputsHash := c.GetPublicInputsHash(proofWithPis.PublicInputs)
proofChallenges := c.GetChallenges(proofWithPis, publicInputsHash, commonData, verifierData)
func (c *VerifierChip) Verify(proof common.Proof, publicInputs []field.F, verifierData common.VerifierOnlyCircuitData, commonData common.CommonCircuitData) {
// TODO: Need to range check all the proof and public input elements to make sure they are within goldilocks field
c.plonkChip.Verify(proofChallenges, proofWithPis.Proof.Openings, publicInputsHash)
// Generate the parts of the witness that is for the plonky2 proof input
publicInputsHash := c.GetPublicInputsHash(publicInputs)
proofChallenges := c.GetChallenges(proof, publicInputsHash, commonData, verifierData)
c.plonkChip.Verify(proofChallenges, proof.Openings, publicInputsHash)
initialMerkleCaps := []common.MerkleCap{
verifierData.ConstantSigmasCap,
proofWithPis.Proof.WiresCap,
proofWithPis.Proof.PlonkZsPartialProductsCap,
proofWithPis.Proof.QuotientPolysCap,
proof.WiresCap,
proof.PlonkZsPartialProductsCap,
proof.QuotientPolysCap,
}
// Seems like there is a bug in the emulated field code.
@@ -189,9 +191,9 @@ func (c *VerifierChip) Verify(proofWithPis common.ProofWithPublicInputs, verifie
c.friChip.VerifyFriProof(
fri.GetFriInstance(&commonData, c.qeAPI, proofChallenges.PlonkZeta, commonData.DegreeBits),
fri.ToFriOpenings(proofWithPis.Proof.Openings),
fri.ToFriOpenings(proof.Openings),
&proofChallenges.FriChallenges,
initialMerkleCaps,
&proofWithPis.Proof.OpeningProof,
&proof.OpeningProof,
)
}

View File

@@ -3,42 +3,121 @@ package verifier_test
import (
"testing"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/math/emulated"
"github.com/consensys/gnark/test"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/utils"
)
type TestVerifierCircuit struct {
proofWithPIsFilename string `gnark:"-"`
commonCircuitDataFilename string `gnark:"-"`
verifierOnlyCircuitDataFilename string `gnark:"-"`
Proof common.Proof
PublicInputs []field.F `gnark:",public"`
verifierChip *verifier.VerifierChip `gnark:"-"`
plonky2CircuitName string `gnark:"-"`
}
func (c *TestVerifierCircuit) Define(api frontend.API) error {
proofWithPis := utils.DeserializeProofWithPublicInputs(c.proofWithPIsFilename)
commonCircuitData := utils.DeserializeCommonCircuitData(c.commonCircuitDataFilename)
verfierOnlyCircuitData := utils.DeserializeVerifierOnlyCircuitData(c.verifierOnlyCircuitDataFilename)
circuitDirname := "./data/" + c.plonky2CircuitName + "/"
commonCircuitData := utils.DeserializeCommonCircuitData(circuitDirname + "common_circuit_data.json")
verifierOnlyCircuitData := utils.DeserializeVerifierOnlyCircuitData(circuitDirname + "verifier_only_circuit_data.json")
c.verifierChip = verifier.NewVerifierChip(api, commonCircuitData)
c.verifierChip.Verify(c.Proof, c.PublicInputs, verifierOnlyCircuitData, commonCircuitData)
verifierChip := verifier.NewVerifierChip(api, commonCircuitData)
verifierChip.Verify(proofWithPis, verfierOnlyCircuitData, commonCircuitData)
return nil
}
func TestDecodeBlockVerifier(t *testing.T) {
func TestStepVerifier(t *testing.T) {
assert := test.NewAssert(t)
testCase := func() {
plonky2Circuit := "step"
proofWithPis := utils.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
circuit := TestVerifierCircuit{
proofWithPIsFilename: "./data/decode_block/proof_with_public_inputs.json",
commonCircuitDataFilename: "./data/decode_block/common_circuit_data.json",
verifierOnlyCircuitDataFilename: "./data/decode_block/verifier_only_circuit_data.json",
plonky2CircuitName: plonky2Circuit,
Proof: proofWithPis.Proof,
PublicInputs: proofWithPis.PublicInputs,
}
proofWithPis2 := utils.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
witness := TestVerifierCircuit{
plonky2CircuitName: plonky2Circuit,
Proof: proofWithPis2.Proof,
PublicInputs: proofWithPis2.PublicInputs,
}
witness := TestVerifierCircuit{}
err := test.IsSolved(&circuit, &witness, field.TEST_CURVE.ScalarField())
assert.NoError(err)
}
testCase()
}
func TestStepVerifier2(t *testing.T) {
assert := test.NewAssert(t)
plonky2Circuit := "step"
proofWithPis := utils.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
circuit := TestVerifierCircuit{
plonky2CircuitName: plonky2Circuit,
Proof: proofWithPis.Proof,
PublicInputs: proofWithPis.PublicInputs,
}
proofWithPis2 := utils.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
witness := TestVerifierCircuit{
plonky2CircuitName: plonky2Circuit,
Proof: proofWithPis2.Proof,
PublicInputs: proofWithPis2.PublicInputs,
}
assert.ProverSucceeded(
&circuit,
&witness,
test.WithBackends(backend.GROTH16),
test.WithCurves(ecc.BN254),
test.NoFuzzing(),
test.NoSerialization(),
)
}
type testCircuit struct {
Arr [2]emulated.Element[emulated.Secp256k1Fp]
Expected emulated.Element[emulated.Secp256k1Fp]
}
func (circuit *testCircuit) Define(api frontend.API) error {
field, _ := emulated.NewField[emulated.Secp256k1Fp](api)
mulRes := field.Mul(&circuit.Arr[0], &circuit.Arr[1])
field.AssertIsEqual(mulRes, &circuit.Expected)
return nil
}
func TestMain(t *testing.T) {
assert := test.NewAssert(t)
var circuit testCircuit
assert.ProverSucceeded(
&circuit,
&testCircuit{
Arr: [2]emulated.Element[emulated.Secp256k1Fp]{
emulated.ValueOf[emulated.Secp256k1Fp](42),
emulated.ValueOf[emulated.Secp256k1Fp](24),
},
Expected: emulated.ValueOf[emulated.Secp256k1Fp](1008),
},
test.WithBackends(backend.GROTH16),
test.WithCurves(ecc.BN254),
test.NoFuzzing(),
test.NoSerialization(),
)
}