diff --git a/field/field.go b/field/field.go index 1894787..bbd71a1 100644 --- a/field/field.go +++ b/field/field.go @@ -8,6 +8,7 @@ import ( type EmulatedField = emulated.Goldilocks type F = emulated.Element[EmulatedField] +type QuadraticExtension = [2]F type Hash = [4]F var TEST_CURVE = ecc.BN254 diff --git a/plonky2_verifier/challenger_test.go b/plonky2_verifier/challenger_test.go index b351c9f..7516d3e 100644 --- a/plonky2_verifier/challenger_test.go +++ b/plonky2_verifier/challenger_test.go @@ -23,8 +23,8 @@ type TestChallengerCircuit struct { func (circuit *TestChallengerCircuit) Define(api frontend.API) error { field := field.NewFieldAPI(api) - poseidon := NewPoseidonChip(api, field) - challenger := NewChallengerChip(api, field, *poseidon) + poseidonChip := NewPoseidonChip(api, field) + challengerChip := NewChallengerChip(api, field, *poseidonChip) var circuitDigest [4]F for i := 0; i < len(circuitDigest); i++ { @@ -43,14 +43,14 @@ func (circuit *TestChallengerCircuit) Define(api frontend.API) error { } } - publicInputHash := poseidon.HashNoPad(publicInputs[:]) - challenger.ObserveHash(circuitDigest) - challenger.ObserveHash(publicInputHash) - challenger.ObserveCap(wiresCap[:]) + publicInputHash := poseidonChip.HashNoPad(publicInputs[:]) + challengerChip.ObserveHash(circuitDigest) + challengerChip.ObserveHash(publicInputHash) + challengerChip.ObserveCap(wiresCap[:]) nbChallenges := 2 - plonkBetas := challenger.GetNChallenges(nbChallenges) - plonkGammas := challenger.GetNChallenges(nbChallenges) + plonkBetas := challengerChip.GetNChallenges(nbChallenges) + plonkGammas := challengerChip.GetNChallenges(nbChallenges) expectedPlonkBetas := [2]frontend.Variable{ frontend.Variable("4678728155650926271"), diff --git a/plonky2_verifier/deserialize_proof.go b/plonky2_verifier/deserialize_proof.go new file mode 100644 index 0000000..23551e2 --- /dev/null +++ b/plonky2_verifier/deserialize_proof.go @@ -0,0 +1,241 @@ +package plonky2_verifier + +import ( + "encoding/json" + . "gnark-ed25519/field" + "gnark-ed25519/utils" + "io/ioutil" + "os" +) + +// type HashRaw = []uint64 + +// type MerkleCapRaw struct { +// Elements []HashRaw `json:"elements"` +// } + +// type QuadraticExtensionRaw = [2]uint64 + +// type OpeningSetRaw struct { +// Constants []QuadraticExtensionRaw `json:"constants"` +// PlonkSigmas []QuadraticExtensionRaw `json:"plonk_sigmas"` +// Wires []QuadraticExtensionRaw `json:"wires"` +// PlonkZs []QuadraticExtensionRaw `json:"plonk_zs"` +// PlonkZsNext []QuadraticExtensionRaw `json:"plonk_zs_next"` +// PartialProducts []QuadraticExtensionRaw `json:"partial_products"` +// QuotientPolys []QuadraticExtensionRaw `json:"quotient_polys"` +// } + +// type FriQueryRoundRaw struct { +// InitialTreesProof struct { +// EvalsProofs [][]interface{} `json:"evals_proofs"` +// } `json:"initial_trees_proof"` +// Steps []uint64 `json:"steps"` +// } + +// type PolynomialCoeffsRaw struct { +// Coeffs []uint64 `json:"coeffs"` +// } + +// type FriProofRaw struct { +// CommitPhaseMerkleCaps []MerkleCapRaw `json:"commit_phase_merkle_caps"` +// QueryRoundProofs FriQueryRoundRaw `json:"query_round_proofs"` +// FinalPoly PolynomialCoeffsRaw `json:"final_poly"` +// PowWitness uint64 `json:"pow_witness"` +// } + +// type ProofWithPublicInputsRaw struct { +// Proof struct { +// WiresCap MerkleCapRaw `json:"wires_cap"` +// PlonkZsPartialProductsCap MerkleCapRaw `json:"plonk_zs_partial_products_cap"` +// QuotientPolysCap MerkleCapRaw `json:"quotient_polys_cap"` +// Openings OpeningSetRaw `json:"openings"` +// OpeningProof FriProofRaw `json:"opening_proof"` +// } `json:"proof"` +// PublicInputs []uint64 `json:"public_inputs"` +// } + +type ProofWithPublicInputsRaw struct { + Proof struct { + WiresCap []struct { + Elements []uint64 `json:"elements"` + } `json:"wires_cap"` + PlonkZsPartialProductsCap []struct { + Elements []uint64 `json:"elements"` + } `json:"plonk_zs_partial_products_cap"` + QuotientPolysCap []struct { + Elements []uint64 `json:"elements"` + } `json:"quotient_polys_cap"` + Openings struct { + Constants [][]uint64 `json:"constants"` + PlonkSigmas [][]uint64 `json:"plonk_sigmas"` + Wires [][]uint64 `json:"wires"` + PlonkZs [][]uint64 `json:"plonk_zs"` + PlonkZsNext [][]uint64 `json:"plonk_zs_next"` + PartialProducts [][]uint64 `json:"partial_products"` + QuotientPolys [][]uint64 `json:"quotient_polys"` + } `json:"openings"` + OpeningProof struct { + CommitPhaseMerkleCaps []interface{} `json:"commit_phase_merkle_caps"` + QueryRoundProofs []struct { + InitialTreesProof struct { + EvalsProofs [][]interface{} `json:"evals_proofs"` + } `json:"initial_trees_proof"` + Steps []interface{} `json:"steps"` + } `json:"query_round_proofs"` + FinalPoly struct { + Coeffs [][]uint64 `json:"coeffs"` + } `json:"final_poly"` + PowWitness uint64 `json:"pow_witness"` + } `json:"opening_proof"` + } `json:"proof"` + PublicInputs []interface{} `json:"public_inputs"` +} + +type CommonCircuitDataRaw struct { + Config struct { + NumWires uint64 `json:"num_wires"` + NumRoutedWires uint64 `json:"num_routed_wires"` + NumConstants uint64 `json:"num_constants"` + UseBaseArithmeticGate bool `json:"use_base_arithmetic_gate"` + SecurityBits uint64 `json:"security_bits"` + NumChallenges uint64 `json:"num_challenges"` + ZeroKnowledge bool `json:"zero_knowledge"` + MaxQuotientDegreeFactor uint64 `json:"max_quotient_degree_factor"` + FriConfig struct { + RateBits uint64 `json:"rate_bits"` + CapHeight uint64 `json:"cap_height"` + ProofOfWorkBits uint64 `json:"proof_of_work_bits"` + ReductionStrategy struct { + ConstantArityBits []uint64 `json:"ConstantArityBits"` + } `json:"reduction_strategy"` + NumQueryRounds uint64 `json:"num_query_rounds"` + } `json:"fri_config"` + } `json:"config"` + FriParams struct { + Config struct { + RateBits uint64 `json:"rate_bits"` + CapHeight uint64 `json:"cap_height"` + ProofOfWorkBits uint64 `json:"proof_of_work_bits"` + ReductionStrategy struct { + ConstantArityBits []uint64 `json:"ConstantArityBits"` + } `json:"reduction_strategy"` + NumQueryRounds uint64 `json:"num_query_rounds"` + } `json:"config"` + Hiding bool `json:"hiding"` + DegreeBits uint64 `json:"degree_bits"` + ReductionArityBits []interface{} `json:"reduction_arity_bits"` + } `json:"fri_params"` + DegreeBits uint64 `json:"degree_bits"` + SelectorsInfo struct { + SelectorIndices []uint64 `json:"selector_indices"` + Groups []struct { + Start uint64 `json:"start"` + End uint64 `json:"end"` + } `json:"groups"` + } `json:"selectors_info"` + QuotientDegreeFactor uint64 `json:"quotient_degree_factor"` + NumGateConstraints uint64 `json:"num_gate_constraints"` + NumConstants uint64 `json:"num_constants"` + NumPublicInputs uint64 `json:"num_public_inputs"` + KIs []interface{} `json:"k_is"` + NumPartialProducts uint64 `json:"num_partial_products"` + CircuitDigest struct { + Elements []uint64 `json:"elements"` + } `json:"circuit_digest"` +} + +type VerifierOnlyCircuitDataRaw struct { + ConstantsSigmasCap []struct { + Elements []uint64 `json:"elements"` + } `json:"constants_sigmas_cap"` +} + +func DeserializeMerkleCap(merkleCapRaw []struct{ Elements []uint64 }) MerkleCap { + n := len(merkleCapRaw) + merkleCap := make([]Hash, n) + for i := 0; i < n; i++ { + copy(merkleCap[i][:], utils.Uint64ArrayToFArray(merkleCapRaw[i].Elements)) + } + return merkleCap +} + +func DeserializeOpeningSet(openingSetRaw struct { + Constants [][]uint64 + PlonkSigmas [][]uint64 + Wires [][]uint64 + PlonkZs [][]uint64 + PlonkZsNext [][]uint64 + PartialProducts [][]uint64 + QuotientPolys [][]uint64 +}) OpeningSet { + return OpeningSet{ + Constants: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.Constants), + PlonkSigmas: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkSigmas), + Wires: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.Wires), + PlonkZs: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkZs), + PlonkZsNext: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PlonkZsNext), + PartialProducts: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.PartialProducts), + QuotientPolys: utils.Uint64ArrayToQuadraticExtensionArray(openingSetRaw.QuotientPolys), + } +} + +func DeserializeFriProof(openingProofRaw struct { + CommitPhaseMerkleCaps []interface{} + QueryRoundProofs []struct { + InitialTreesProof struct { + EvalsProofs [][]interface{} + } + Steps []interface{} + } + FinalPoly struct { + Coeffs [][]uint64 + } + PowWitness uint64 +}) FriProof { + var openingProof FriProof + openingProof.PowWitness = NewFieldElement(openingProofRaw.PowWitness) + openingProof.FinalPoly.Coeffs = utils.Uint64ArrayToQuadraticExtensionArray(openingProofRaw.FinalPoly.Coeffs) + return openingProof +} + +func DeserializeProofWithPublicInputs(path string) ProofWithPublicInputs { + jsonFile, err := os.Open(path) + if err != nil { + panic(err) + } + + defer jsonFile.Close() + rawBytes, _ := ioutil.ReadAll(jsonFile) + + var raw ProofWithPublicInputsRaw + err = json.Unmarshal(rawBytes, &raw) + if err != nil { + panic(err) + } + + var proofWithPis ProofWithPublicInputs + proofWithPis.Proof.WiresCap = DeserializeMerkleCap([]struct{ Elements []uint64 }(raw.Proof.WiresCap)) + proofWithPis.Proof.PlonkZsPartialProductsCap = DeserializeMerkleCap([]struct{ Elements []uint64 }(raw.Proof.PlonkZsPartialProductsCap)) + proofWithPis.Proof.QuotientPolysCap = DeserializeMerkleCap([]struct{ Elements []uint64 }(raw.Proof.QuotientPolysCap)) + proofWithPis.Proof.Openings = DeserializeOpeningSet(struct { + Constants [][]uint64 + PlonkSigmas [][]uint64 + Wires [][]uint64 + PlonkZs [][]uint64 + PlonkZsNext [][]uint64 + PartialProducts [][]uint64 + QuotientPolys [][]uint64 + }(raw.Proof.Openings)) + proofWithPis.Proof.OpeningProof = DeserializeFriProof(struct { + CommitPhaseMerkleCaps []interface{} + QueryRoundProofs []struct { + InitialTreesProof struct{ EvalsProofs [][]interface{} } + Steps []interface{} + } + FinalPoly struct{ Coeffs [][]uint64 } + PowWitness uint64 + }(raw.Proof.OpeningProof)) + + return proofWithPis +} diff --git a/plonky2_verifier/deserialize_proof_test.go b/plonky2_verifier/deserialize_proof_test.go new file mode 100644 index 0000000..c88be42 --- /dev/null +++ b/plonky2_verifier/deserialize_proof_test.go @@ -0,0 +1,12 @@ +package plonky2_verifier + +import ( + "fmt" + "testing" +) + +func TestDeserializeProofWithPublicInputs(t *testing.T) { + proofWithPis := DeserializeProofWithPublicInputs("./fibonacci_proof.json") + fmt.Printf("%+v\n", proofWithPis) + panic("look at stdout") +} diff --git a/plonky2_verifier/proof.go b/plonky2_verifier/proof.go index 6bb5863..b13e822 100644 --- a/plonky2_verifier/proof.go +++ b/plonky2_verifier/proof.go @@ -4,8 +4,6 @@ import ( . "gnark-ed25519/field" ) -type QuadraticExtension = [2]F - type MerkleCap = []Hash type MerkleProof struct { @@ -32,7 +30,7 @@ type FriQueryRound struct { } type PolynomialCoeffs struct { - Coeffs []F + Coeffs []QuadraticExtension } type FriProof struct { diff --git a/poseidon/poseidon_test.go b/poseidon/poseidon_test.go index 1271b60..03137c8 100644 --- a/poseidon/poseidon_test.go +++ b/poseidon/poseidon_test.go @@ -25,8 +25,8 @@ func (circuit *TestPoseidonCircuit) Define(api frontend.API) error { input[i] = goldilocksApi.FromBinary(api.ToBinary(circuit.In[i], 64)).(F) } - chip := NewPoseidonChip(api, goldilocksApi) - output := chip.Poseidon(input) + poseidonChip := NewPoseidonChip(api, goldilocksApi) + output := poseidonChip.Poseidon(input) for i := 0; i < 12; i++ { goldilocksApi.AssertIsEqual( diff --git a/utils/utils.go b/utils/utils.go index f2e2f91..b4d30d8 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -33,3 +33,11 @@ func Uint64ArrayToFArray(input []uint64) []F { } return output } + +func Uint64ArrayToQuadraticExtensionArray(input [][]uint64) []QuadraticExtension { + var output []QuadraticExtension + for i := 0; i < len(input); i++ { + output = append(output, [2]F{NewFieldElement(input[i][0]), NewFieldElement(input[i][1])}) + } + return output +}