|
package plonk
|
|
|
|
import (
|
|
"math/big"
|
|
"testing"
|
|
|
|
"github.com/consensys/gnark/backend/groth16"
|
|
"github.com/consensys/gnark/frontend"
|
|
"github.com/consensys/gnark/frontend/cs/r1cs"
|
|
"github.com/consensys/gnark/test"
|
|
"github.com/succinctlabs/gnark-plonky2-verifier/field"
|
|
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
|
|
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
|
|
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/internal/fri"
|
|
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/utils"
|
|
)
|
|
|
|
type TestChallengerCircuit struct {
|
|
commonCircuitDataFilename string `gnark:"-"`
|
|
|
|
CircuitDigest frontend.Variable `gnark:",public"`
|
|
PublicInputs []field.F `gnark:",public"`
|
|
WiresCap []frontend.Variable
|
|
PlonkZsPartialProductsCap []frontend.Variable
|
|
QuotientPolysCap []frontend.Variable
|
|
FriOpenings fri.FriOpenings
|
|
CommitPhaseMerkleCaps [][]frontend.Variable
|
|
FinalPoly common.PolynomialCoeffs
|
|
PowWitness field.F
|
|
}
|
|
|
|
func (circuit *TestChallengerCircuit) Define(api frontend.API) error {
|
|
commonCircuitData := utils.DeserializeCommonCircuitData(circuit.commonCircuitDataFilename)
|
|
|
|
config := commonCircuitData.Config
|
|
numChallenges := config.NumChallenges
|
|
fieldAPI := field.NewFieldAPI(api)
|
|
qeAPI := field.NewQuadraticExtensionAPI(api, fieldAPI)
|
|
poseidonChip := poseidon.NewPoseidonChip(api, fieldAPI, qeAPI)
|
|
poseidonBN128Chip := poseidon.NewPoseidonBN128Chip(api, fieldAPI)
|
|
challenger := NewChallengerChip(api, fieldAPI, poseidonChip, poseidonBN128Chip)
|
|
|
|
challenger.ObserveBN128Hash(circuit.CircuitDigest)
|
|
challenger.ObserveHash(poseidonChip.HashNoPad(circuit.PublicInputs))
|
|
challenger.ObserveCap(circuit.WiresCap)
|
|
plonkBetas := challenger.GetNChallenges(numChallenges)
|
|
plonkGammas := challenger.GetNChallenges(numChallenges)
|
|
|
|
challenger.ObserveCap(circuit.PlonkZsPartialProductsCap)
|
|
plonkAlphas := challenger.GetNChallenges(numChallenges)
|
|
|
|
challenger.ObserveCap(circuit.QuotientPolysCap)
|
|
plonkZeta := challenger.GetExtensionChallenge()
|
|
|
|
challenger.ObserveOpenings(circuit.FriOpenings)
|
|
|
|
friChallenges := challenger.GetFriChallenges(
|
|
circuit.CommitPhaseMerkleCaps,
|
|
circuit.FinalPoly,
|
|
circuit.PowWitness,
|
|
commonCircuitData.DegreeBits,
|
|
config.FriConfig,
|
|
)
|
|
|
|
expectedPlonkBetas := [2]field.F{
|
|
field.NewFieldConstFromString("17615363392879944733"),
|
|
field.NewFieldConstFromString("9422446877322953047"),
|
|
}
|
|
|
|
expectedPlonkGammas := [2]field.F{
|
|
field.NewFieldConstFromString("15174493176564484303"),
|
|
field.NewFieldConstFromString("6175150444166239851"),
|
|
}
|
|
|
|
for i := 0; i < 2; i++ {
|
|
fieldAPI.AssertIsEqual(plonkBetas[i], expectedPlonkBetas[i])
|
|
fieldAPI.AssertIsEqual(plonkGammas[i], expectedPlonkGammas[i])
|
|
}
|
|
|
|
expectedPlonkAlphas := [2]field.F{
|
|
field.NewFieldConstFromString("9276470834414745550"),
|
|
field.NewFieldConstFromString("5302812342351431915"),
|
|
}
|
|
|
|
for i := 0; i < 2; i++ {
|
|
fieldAPI.AssertIsEqual(plonkAlphas[i], expectedPlonkAlphas[i])
|
|
}
|
|
|
|
expectedPlonkZeta := field.QuadraticExtension{
|
|
field.NewFieldConstFromString("3892795992421241388"),
|
|
field.NewFieldConstFromString("15786647757418200302"),
|
|
}
|
|
|
|
for i := 0; i < 2; i++ {
|
|
fieldAPI.AssertIsEqual(plonkZeta[i], expectedPlonkZeta[i])
|
|
}
|
|
|
|
fieldAPI.AssertIsEqual(friChallenges.FriAlpha[0], field.NewFieldConst(885535811531859621))
|
|
|
|
fieldAPI.AssertIsEqual(friChallenges.FriBetas[0][0], field.NewFieldConst(5231781384587895507))
|
|
|
|
fieldAPI.AssertIsEqual(friChallenges.FriPowResponse, field.NewFieldConst(70715523064019))
|
|
|
|
fieldAPI.AssertIsEqual(friChallenges.FriQueryIndices[0], field.NewFieldConst(11890500485816111017))
|
|
|
|
return nil
|
|
}
|
|
|
|
func StringToBN128Hash(hashStr string) poseidon.PoseidonBN128HashOut {
|
|
hashBigInt, ok := new(big.Int).SetString(hashStr, 10)
|
|
if !(ok) {
|
|
panic("Invalid hash: " + hashStr)
|
|
}
|
|
|
|
hashVar := frontend.Variable(*hashBigInt)
|
|
return poseidon.PoseidonBN128HashOut(hashVar)
|
|
}
|
|
|
|
func TestChallengerWitness(t *testing.T) {
|
|
assert := test.NewAssert(t)
|
|
|
|
testCase := func() {
|
|
proofWithPis := utils.DeserializeProofWithPublicInputs("../../data/decode_block/proof_with_public_inputs.json")
|
|
verifierData := utils.DeserializeVerifierOnlyCircuitData("../../data/decode_block/verifier_only_circuit_data.json")
|
|
|
|
circuit := TestChallengerCircuit{
|
|
commonCircuitDataFilename: "../../data/decode_block/common_circuit_data.json",
|
|
|
|
CircuitDigest: verifierData.CircuitDigest,
|
|
PublicInputs: proofWithPis.PublicInputs,
|
|
WiresCap: proofWithPis.Proof.WiresCap,
|
|
PlonkZsPartialProductsCap: proofWithPis.Proof.PlonkZsPartialProductsCap,
|
|
QuotientPolysCap: proofWithPis.Proof.QuotientPolysCap,
|
|
FriOpenings: fri.ToFriOpenings(proofWithPis.Proof.Openings),
|
|
CommitPhaseMerkleCaps: proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps,
|
|
FinalPoly: proofWithPis.Proof.OpeningProof.FinalPoly,
|
|
PowWitness: proofWithPis.Proof.OpeningProof.PowWitness,
|
|
}
|
|
witness := TestChallengerCircuit{
|
|
CircuitDigest: verifierData.CircuitDigest,
|
|
PublicInputs: proofWithPis.PublicInputs,
|
|
WiresCap: proofWithPis.Proof.WiresCap,
|
|
PlonkZsPartialProductsCap: proofWithPis.Proof.PlonkZsPartialProductsCap,
|
|
QuotientPolysCap: proofWithPis.Proof.QuotientPolysCap,
|
|
FriOpenings: fri.ToFriOpenings(proofWithPis.Proof.Openings),
|
|
CommitPhaseMerkleCaps: proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps,
|
|
FinalPoly: proofWithPis.Proof.OpeningProof.FinalPoly,
|
|
PowWitness: proofWithPis.Proof.OpeningProof.PowWitness,
|
|
}
|
|
err := test.IsSolved(&circuit, &witness, field.TEST_CURVE.ScalarField())
|
|
assert.NoError(err)
|
|
}
|
|
|
|
testCase()
|
|
}
|
|
|
|
func TestChallengerProver(t *testing.T) {
|
|
proofWithPis := utils.DeserializeProofWithPublicInputs("../../data/decode_block/proof_with_public_inputs.json")
|
|
verifierData := utils.DeserializeVerifierOnlyCircuitData("../../data/decode_block/verifier_only_circuit_data.json")
|
|
|
|
circuit := TestChallengerCircuit{
|
|
commonCircuitDataFilename: "../../data/decode_block/common_circuit_data.json",
|
|
|
|
CircuitDigest: verifierData.CircuitDigest,
|
|
PublicInputs: proofWithPis.PublicInputs,
|
|
WiresCap: proofWithPis.Proof.WiresCap,
|
|
PlonkZsPartialProductsCap: proofWithPis.Proof.PlonkZsPartialProductsCap,
|
|
QuotientPolysCap: proofWithPis.Proof.QuotientPolysCap,
|
|
FriOpenings: fri.ToFriOpenings(proofWithPis.Proof.Openings),
|
|
CommitPhaseMerkleCaps: proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps,
|
|
FinalPoly: proofWithPis.Proof.OpeningProof.FinalPoly,
|
|
PowWitness: proofWithPis.Proof.OpeningProof.PowWitness,
|
|
}
|
|
|
|
proofWithPis = utils.DeserializeProofWithPublicInputs("../../data/decode_block/proof_with_public_inputs.json")
|
|
verifierData = utils.DeserializeVerifierOnlyCircuitData("../../data/decode_block/verifier_only_circuit_data.json")
|
|
|
|
assignment := TestChallengerCircuit{
|
|
commonCircuitDataFilename: "../../data/decode_block/common_circuit_data.json",
|
|
|
|
CircuitDigest: verifierData.CircuitDigest,
|
|
PublicInputs: proofWithPis.PublicInputs,
|
|
WiresCap: proofWithPis.Proof.WiresCap,
|
|
PlonkZsPartialProductsCap: proofWithPis.Proof.PlonkZsPartialProductsCap,
|
|
QuotientPolysCap: proofWithPis.Proof.QuotientPolysCap,
|
|
FriOpenings: fri.ToFriOpenings(proofWithPis.Proof.Openings),
|
|
CommitPhaseMerkleCaps: proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps,
|
|
FinalPoly: proofWithPis.Proof.OpeningProof.FinalPoly,
|
|
PowWitness: proofWithPis.Proof.OpeningProof.PowWitness,
|
|
}
|
|
|
|
r1cs, err := frontend.Compile(field.TEST_CURVE.ScalarField(), r1cs.NewBuilder, &circuit)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
println("num constraints is ", r1cs.GetNbConstraints())
|
|
|
|
assert := test.NewAssert(t)
|
|
err = test.IsSolved(&circuit, &assignment, field.TEST_CURVE.ScalarField())
|
|
assert.NoError(err)
|
|
|
|
witness, err := frontend.NewWitness(&assignment, field.TEST_CURVE.ScalarField())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
pk, vk, err := groth16.Setup(r1cs)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
proof, err := groth16.Prove(r1cs, pk, witness)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
publicWitness, err := witness.Public()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
err = groth16.Verify(proof, vk, publicWitness)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|