mirror of
https://github.com/logos-storage/proof-aggregation.git
synced 2026-01-02 13:53:13 +00:00
245 lines
6.9 KiB
Go
245 lines
6.9 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.com/consensys/gnark/backend/groth16"
|
|
groth16_bn254 "github.com/consensys/gnark/backend/groth16/bn254"
|
|
plonk_bn254 "github.com/consensys/gnark/backend/plonk/bn254"
|
|
|
|
"os"
|
|
"time"
|
|
|
|
gnark_verifier_types "github.com/codex-storage/gnark-plonky2-verifier/types"
|
|
"github.com/codex-storage/gnark-plonky2-verifier/variables"
|
|
"github.com/consensys/gnark-crypto/ecc"
|
|
"github.com/consensys/gnark/backend/plonk"
|
|
"github.com/consensys/gnark/backend/witness"
|
|
"github.com/consensys/gnark/constraint"
|
|
"github.com/consensys/gnark/frontend"
|
|
"github.com/consensys/gnark/logger"
|
|
)
|
|
|
|
func loadR1CS(path string) (constraint.ConstraintSystem, error) {
|
|
log := logger.Logger()
|
|
r1csFile, err := os.Open(path + "/r1cs.bin")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to open r1cs file: %w", err)
|
|
}
|
|
r1cs := plonk.NewCS(ecc.BN254)
|
|
start := time.Now()
|
|
r1csReader := bufio.NewReader(r1csFile)
|
|
_, err = r1cs.ReadFrom(r1csReader)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read r1cs file: %w", err)
|
|
}
|
|
r1csFile.Close()
|
|
elapsed := time.Since(start)
|
|
log.Debug().Msg("Successfully loaded constraint system, time: " + elapsed.String())
|
|
return r1cs, nil
|
|
}
|
|
|
|
func LoadPlonkProverData(path string) (constraint.ConstraintSystem, plonk.ProvingKey, error) {
|
|
log := logger.Logger()
|
|
|
|
r1cs, err := loadR1CS(path)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to load r1cs file: %w", err)
|
|
}
|
|
|
|
pkFile, err := os.Open(path + "/pk.bin")
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to open pk file: %w", err)
|
|
}
|
|
pk := plonk.NewProvingKey(ecc.BN254)
|
|
start := time.Now()
|
|
pkReader := bufio.NewReader(pkFile)
|
|
_, err = pk.ReadFrom(pkReader)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to read pk file: %w", err)
|
|
}
|
|
pkFile.Close()
|
|
elapsed := time.Since(start)
|
|
log.Debug().Msg("Successfully loaded proving key, time: " + elapsed.String())
|
|
|
|
return r1cs, pk, nil
|
|
}
|
|
|
|
func LoadGroth16ProverData(path string) (constraint.ConstraintSystem, groth16.ProvingKey, error) {
|
|
log := logger.Logger()
|
|
|
|
r1cs, err := loadR1CS(path)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to load r1cs file: %w", err)
|
|
}
|
|
|
|
pkFile, err := os.Open(path + "/pk.bin")
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to open pk file: %w", err)
|
|
}
|
|
pk := groth16.NewProvingKey(ecc.BN254)
|
|
start := time.Now()
|
|
pkReader := bufio.NewReader(pkFile)
|
|
_, err = pk.ReadFrom(pkReader)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to read pk file: %w", err)
|
|
}
|
|
pkFile.Close()
|
|
elapsed := time.Since(start)
|
|
log.Debug().Msg("Successfully loaded proving key, time: " + elapsed.String())
|
|
|
|
return r1cs, pk, nil
|
|
}
|
|
|
|
func GetWitness(circuitPath string) (witness.Witness, error) {
|
|
log := logger.Logger()
|
|
|
|
verifierOnlyCircuitData := variables.DeserializeVerifierOnlyCircuitData(
|
|
gnark_verifier_types.ReadVerifierOnlyCircuitData(circuitPath + "/verifier_only_circuit_data.json"),
|
|
)
|
|
proofWithPis := gnark_verifier_types.ReadProofWithPublicInputs(circuitPath + "/proof_with_public_inputs.json")
|
|
proofWithPisVariable := variables.DeserializeProofWithPublicInputs(proofWithPis)
|
|
|
|
// Circuit assignment
|
|
assignment := &Plonky2VerifierCircuit{
|
|
Proof: proofWithPisVariable.Proof,
|
|
PublicInputs: proofWithPisVariable.PublicInputs,
|
|
VerifierData: verifierOnlyCircuitData,
|
|
}
|
|
|
|
log.Debug().Msg("Generating witness")
|
|
start := time.Now()
|
|
witness, err := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to generate witness: %w", err)
|
|
}
|
|
elapsed := time.Since(start)
|
|
log.Debug().Msg("Successfully generated witness, time: " + elapsed.String())
|
|
|
|
return witness, nil
|
|
}
|
|
|
|
func ProvePlonk(dataPath string, r1cs constraint.ConstraintSystem, pk plonk.ProvingKey, witness witness.Witness) (plonk.Proof, error) {
|
|
log := logger.Logger()
|
|
|
|
log.Debug().Msg("Creating proof")
|
|
start := time.Now()
|
|
proof, err := plonk.Prove(r1cs, pk, witness)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create proof: %w", err)
|
|
}
|
|
elapsed := time.Since(start)
|
|
log.Info().Msg("Successfully created proof, time: " + elapsed.String())
|
|
|
|
// export proof
|
|
err = ExportPlonkProof(dataPath, proof)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// export witness
|
|
publicWitness, err := witness.Public()
|
|
err = ExportWitness(dataPath, publicWitness)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return proof, nil
|
|
}
|
|
|
|
func ProveGroth16(dataPath string, r1cs constraint.ConstraintSystem, pk groth16.ProvingKey, witness witness.Witness) (groth16.Proof, error) {
|
|
log := logger.Logger()
|
|
|
|
log.Debug().Msg("Creating proof")
|
|
start := time.Now()
|
|
proof, err := groth16.Prove(r1cs, pk, witness)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create proof: %w", err)
|
|
}
|
|
elapsed := time.Since(start)
|
|
log.Info().Msg("Successfully created proof, time: " + elapsed.String())
|
|
|
|
// export proof
|
|
err = ExportGroth16Proof(dataPath, proof)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// export witness
|
|
publicWitness, err := witness.Public()
|
|
err = ExportWitness(dataPath, publicWitness)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return proof, nil
|
|
}
|
|
|
|
func ExportWitness(circuitPath string, witness witness.Witness) error {
|
|
log := logger.Logger()
|
|
|
|
publicWitness, err := witness.Public()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get public witness: %w", err)
|
|
}
|
|
|
|
log.Info().Msg("Saving public witness to public_witness.bin")
|
|
witnessFile, err := os.Create(circuitPath + "/public_witness.bin")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create public witness file: %w", err)
|
|
}
|
|
_, err = publicWitness.WriteTo(witnessFile)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to write public witness file: %w", err)
|
|
}
|
|
witnessFile.Close()
|
|
log.Info().Msg("Successfully saved public witness")
|
|
|
|
return nil
|
|
}
|
|
|
|
func ExportPlonkProof(circuitPath string, proof plonk.Proof) error {
|
|
log := logger.Logger()
|
|
|
|
_proof := proof.(*plonk_bn254.Proof)
|
|
log.Info().Msg("Saving proof to proof.json")
|
|
jsonProof, err := json.Marshal(_proof.MarshalSolidity())
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal proof: %w", err)
|
|
}
|
|
proofFile, err := os.Create(circuitPath + "/proof.json")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create proof file: %w", err)
|
|
}
|
|
_, err = proofFile.Write(jsonProof)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to write proof file: %w", err)
|
|
}
|
|
proofFile.Close()
|
|
log.Info().Msg("Successfully saved proof")
|
|
|
|
return nil
|
|
}
|
|
|
|
func ExportGroth16Proof(circuitPath string, proof groth16.Proof) error {
|
|
log := logger.Logger()
|
|
|
|
_proof := proof.(*groth16_bn254.Proof)
|
|
log.Info().Msg("Saving proof to proof.json")
|
|
jsonProof, err := json.Marshal(_proof)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal proof: %w", err)
|
|
}
|
|
proofFile, err := os.Create(circuitPath + "/proof.json")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create proof file: %w", err)
|
|
}
|
|
_, err = proofFile.Write(jsonProof)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to write proof file: %w", err)
|
|
}
|
|
proofFile.Close()
|
|
log.Info().Msg("Successfully saved proof")
|
|
|
|
return nil
|
|
}
|