diff --git a/circomx/src/circuit.ts b/circomx/src/circuit.ts index 3f29fa55b..15b6de1ad 100644 --- a/circomx/src/circuit.ts +++ b/circomx/src/circuit.ts @@ -79,13 +79,7 @@ export abstract class Circuit { solidityVerifier = solidityVerifier.replaceAll("calldataload", "mload"); solidityVerifier = solidityVerifier.replaceAll("calldata", "memory"); solidityVerifier = solidityVerifier.replaceAll( - "_pB, _pC", - // for some reason, uint256[2][2] memory _pB has two words (two lengths?) prepended to it - // and calldata doesn't have it - "add(_pB, 64), _pC" - ); - solidityVerifier = solidityVerifier.replaceAll( - "pragma solidity >=0.7.0 <0.9.0;", + "pragma solidity ^0.8.0;", "pragma solidity ^0.8.16;" ); solidityVerifier += ` @@ -99,27 +93,38 @@ interface IFunctionVerifier { contract FunctionVerifier is IFunctionVerifier, Groth16Verifier { function verify(bytes32 _inputHash, bytes32 _outputHash, bytes memory _proof) external view returns (bool) { - (uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c) = - abi.decode(_proof, (uint256[2], uint256[2][2], uint256[2])); + (uint256[8] memory proof) = abi.decode(_proof, (uint256[8])); - uint256[2] memory input = [uint256(_outputHash), uint256(_inputHash)]; - input[0] = input[0] & ((1 << 253) - 1); - input[1] = input[1] & ((1 << 253) - 1); + uint256[4] memory input; + input[0] = uint256(CIRCUIT_DIGEST); + input[1] = uint256(_inputHash) & ((1 << 253) - 1); + input[2] = uint256(_outputHash) & ((1 << 253) - 1); - return verifyProof(a, b, c, input); + this.verifyProof(proof, input); + + return true; } function verificationKeyHash() external pure returns (bytes32) { - bytes memory left; - bytes memory right; - { - left = abi.encode(alphax, alphay, betax1, betax2, betay1, betay2); - } - { - right = abi.encode(gammax1, gammax2, gammay1, gammay2, deltax1, deltax2, deltay1, deltay2); - } - return keccak256(abi.encode(left, right)); - } + bytes memory left; + bytes memory right; + { + left = abi.encode(ALPHA_X, ALPHA_Y, BETA_NEG_X_1, BETA_NEG_X_0, BETA_NEG_Y_1, BETA_NEG_Y_0); + } + { + right = abi.encode( + GAMMA_NEG_X_1, + GAMMA_NEG_X_0, + GAMMA_NEG_Y_1, + GAMMA_NEG_Y_0, + DELTA_NEG_X_1, + DELTA_NEG_X_0, + DELTA_NEG_Y_1, + DELTA_NEG_Y_0 + ); + } + return keccak256(abi.encode(left, right)); + } } `; fs.writeFileSync("build/FunctionVerifier.sol", solidityVerifier); diff --git a/plonky2x/.gitignore b/plonky2x/.gitignore index 19df4a90a..ffbe4e7f8 100644 --- a/plonky2x/.gitignore +++ b/plonky2x/.gitignore @@ -1,4 +1,5 @@ verifier-build/ core/wrapped/ *tar.gz -verifier-build-groth16/ \ No newline at end of file +verifier-build-groth16/ +proof_with_witness.json \ No newline at end of file diff --git a/plonky2x/core/src/backend/function/mod.rs b/plonky2x/core/src/backend/function/mod.rs index 5e3f4e977..969ef721b 100644 --- a/plonky2x/core/src/backend/function/mod.rs +++ b/plonky2x/core/src/backend/function/mod.rs @@ -289,8 +289,7 @@ impl Plonky2xFunction for C { let wrapper_verifier_contract = fs::read_to_string(wrapper_verifier_path) .expect("Failed to read wrapper_verifier_path"); let generated_contract = wrapper_verifier_contract - .replace("pragma solidity ^0.8.19;", "pragma solidity ^0.8.16;") - .replace("function Verify", "function verifyProof"); + .replace("pragma solidity ^0.8.0;", "pragma solidity ^0.8.16;"); let verifier_contract = " @@ -300,17 +299,21 @@ interface IFunctionVerifier { function verificationKeyHash() external pure returns (bytes32); } -contract FunctionVerifier is IFunctionVerifier, PlonkVerifier { +contract FunctionVerifier is IFunctionVerifier, Verifier { bytes32 public constant CIRCUIT_DIGEST = {CIRCUIT_DIGEST}; function verify(bytes32 _inputHash, bytes32 _outputHash, bytes memory _proof) external view returns (bool) { - uint256[] memory input = new uint256[](3); + (uint256[8] memory proof) = abi.decode(_proof, (uint256[8])); + + uint256[4] memory input; input[0] = uint256(CIRCUIT_DIGEST); input[1] = uint256(_inputHash) & ((1 << 253) - 1); - input[2] = uint256(_outputHash) & ((1 << 253) - 1); + input[2] = uint256(_outputHash) & ((1 << 253) - 1); + + this.verifyProof(proof, input); - return this.verifyProof(_proof, input); + return true; } function verificationKeyHash() external pure returns (bytes32) { diff --git a/plonky2x/verifier/cli.go b/plonky2x/verifier/cli.go index 2ad5f9fc9..071f05955 100644 --- a/plonky2x/verifier/cli.go +++ b/plonky2x/verifier/cli.go @@ -5,8 +5,8 @@ import ( "flag" "os" + "github.com/consensys/gnark/logger" "github.com/succinctlabs/succinctx/plonky2x/verifier/system" - "go.uber.org/zap" ) func main() { @@ -21,22 +21,18 @@ func main() { systemFlag := flag.String("system", "groth16", "proving system to use (groth16, plonk)") flag.Parse() - logger, err := zap.NewDevelopment() - if err != nil { - panic(err) - } - defer logger.Sync() - + logger := logger.Logger() if *circuitPath == "" { - logger.Info("no circuitPath flag found, so user must input circuitPath via stdin") + logger.Info().Msg("no circuitPath flag found, so user must input circuitPath via stdin") + os.Exit(1) } if *dataPath == "" { - logger.Error("please specify a path to data dir (where the compiled gnark circuit data will be)") + logger.Error().Msg("please specify a path to data dir (where the compiled gnark circuit data will be)") os.Exit(1) } - logger.Info("Circuit path: " + *circuitPath) - logger.Info("Data path: " + *dataPath) + logger.Info().Msg("Circuit path: " + *circuitPath) + logger.Info().Msg("Data path: " + *dataPath) var s system.ProvingSystem if *systemFlag == "groth16" { @@ -44,14 +40,14 @@ func main() { } else if *systemFlag == "plonk" { s = system.NewPlonkSystem(logger, "./data/dummy", *dataPath) } else { - logger.Error("invalid proving system") + logger.Error().Msg("invalid proving system") os.Exit(1) } if *compileFlag { err := s.Compile() if err != nil { - logger.Error("failed to compile verifier circuit:" + err.Error()) + logger.Error().Msg("failed to compile verifier circuit:" + err.Error()) os.Exit(1) } } @@ -59,7 +55,7 @@ func main() { if *proofFlag { err := s.Prove() if err != nil { - logger.Error("failed to create proof:" + err.Error()) + logger.Error().Msg("failed to create proof:" + err.Error()) os.Exit(1) } } @@ -67,7 +63,7 @@ func main() { if *verifyFlag { err := s.Verify() if err != nil { - logger.Error("failed to verify proof:" + err.Error()) + logger.Error().Msg("failed to verify proof:" + err.Error()) os.Exit(1) } } @@ -75,7 +71,7 @@ func main() { if *exportFlag { err := s.Export() if err != nil { - logger.Error("failed to export verifier circuit:" + err.Error()) + logger.Error().Msg("failed to export verifier circuit:" + err.Error()) os.Exit(1) } } diff --git a/plonky2x/verifier/groth16_proof_data.json b/plonky2x/verifier/groth16_proof_data.json deleted file mode 100644 index 1dbba0fda..000000000 --- a/plonky2x/verifier/groth16_proof_data.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "proof": [ - "0x107de8c771bfe4c284de2dce673e5404460cf0875ffd61028b4df6e0fe0b7926", - "0x0c4237ff755b97ae5ee90844477a01453155c7fa7a0d39d8be6fbbecf06c0a24", - "0x188267b5161851d08bccd329c4117d7da37d03229fe0601154f7f153d505f94f", - "0x16c501cd276f6c593425ffc36d30141cce389b6a06d2b011001b77f549f28b5c", - "0x1943f3f4d7d55a9a9bd8cf0c1ba54921fa8980f585ba129e5c8469ff68f5034d", - "0x27c67c8cb9aa9f497324d883e6bde979d7b0d7a0141cee942c1feec8dab6339b", - "0x0b94f6e01436f9c625fa25d7c496abf3cd1bdd52236d9df62793f0026a202df6", - "0x01679db2dcb9f9f095c595ab3ad7a1e39091364fcfb78491d15f308c1a9360db" - ], - "inputs": [ - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000003" - ] -} \ No newline at end of file diff --git a/plonky2x/verifier/plonk_proof_data_range_check.json b/plonky2x/verifier/plonk_proof_data_range_check.json deleted file mode 100644 index cb344d002..000000000 --- a/plonky2x/verifier/plonk_proof_data_range_check.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "proof": "0x051d626d87ae45b337e86f8e386fe0e4b8b5dee3d39c0fe946ad0fdaf19d10650f305385baef88f1d4a78416a3cf16c93a01278d2c1da19e90b54c3aac9814202e3a67d586a0c15b97aa85a2e9f50f17374485d8fd305cf9ec7814189e233ce205a4a7643bc25292b9dd14e9df9baf9956405bd95e71a02bed2e003356ae3e2b2c5e0056a0a6c1151402c2ca2daef5b9f1b41a728630f1e79e2ccac014e28ce70b549e91ecffe777fd0ccd9821a0457eafe4044deaa046e573759a31959232a91fa98041111be659b641fa88852e83ecbae2909ec96223611f407988afc0071819423d472c1198f708c4c3683497651ca8efdeb6ac51b4bb025983c1dd972d7809033c285e95ae0efef7ee8731d767e7e27c0a9cb2aca221115a2fd18197bb1801e58b161694039d74eb632c2011b9395e3d010d0e8fe3a645c3f06dddf85c700c7737ed865de7690fda22f9c78426385072b74d7cff638495fed7953c7639430ab9316dde7303a7a504d2ee204b01bb52c7adf280dcdb9152f200df56074a2c0bf4a7c87ea73e6881b943c1a5230901ef6c2e8ab2616aaaeb6c9704ddc5e29023f58e474d8127c26a708fafa6c78a52eecbc5a95f3605189bab6fbcf38730d306ca8fc51809d9707ab45ab4f5a7679a8446d8647b820e4f0421a5abbf72ac4d0c0270a5d5283eeb1475138396808f856696d36d49bbc156655cb3d2676d19db1b0261915bb864d7213ac3bc7adf0b73d7b58062d7c1387a3d637e7dfc733bd00d07c1f8e4605500385dbaeebfefc6b840da9dc22e281d8b6b39b5629a2b830005666a00d74abb03c6b23ed1e2a275190c41cc4334db1918c690303b70afcfcb06b92ee2d22e7f8a7dbe2f3a49a4f6f4f6005d273b8d92feb4decfe50b06c69e0386445664225ca47aa7fd88882f8a6752ef3744bd99a5197be5d6b42ae94a0106c5bb1c2a6eb7eff64702d51fce4d39caba8b6f1f33547f05eac546dabc55ad0ee882edc320c56eadd7d57a11b03ce3da6bb78550e654a94e1d6f469e8b479b1c9353eef6e47fbbc13495f1d178acec394f47720aaffaa36b535534538e81b62a15ae250b1791af97a7db230f3c0a6c807e26ecee10c936173adbb74c349b630636b0481ff0a8b53e48283ac65c652136f4da001da3495a23942c2cd4b8a8f018ee6922fac48482d609bdd000ac151bb2ff28f18842aa26c2dc55b6b5e9062b2153fe8d35233a9c20bb4e6d82349a19f6d5c7db12e136f881f07e83011b608205a7ef5640d961e9154dbab91b7027c01a1681ca6ce9490c80a98c625e242d3c", - "inputs": [ - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000003" - ] -} \ No newline at end of file diff --git a/plonky2x/verifier/verifier_test.go b/plonky2x/verifier/system/circuit_test.go similarity index 99% rename from plonky2x/verifier/verifier_test.go rename to plonky2x/verifier/system/circuit_test.go index fdc4cfd05..0aea477c8 100644 --- a/plonky2x/verifier/verifier_test.go +++ b/plonky2x/verifier/system/circuit_test.go @@ -1,4 +1,4 @@ -package main +package system import ( "testing" diff --git a/plonky2x/verifier/system/groth16.go b/plonky2x/verifier/system/groth16.go index 82ec636d2..7150d765a 100644 --- a/plonky2x/verifier/system/groth16.go +++ b/plonky2x/verifier/system/groth16.go @@ -19,19 +19,19 @@ import ( "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" - "go.uber.org/zap" + "github.com/rs/zerolog" gnark_verifier_types "github.com/succinctlabs/gnark-plonky2-verifier/types" "github.com/succinctlabs/gnark-plonky2-verifier/variables" ) type Groth16System struct { - logger *zap.Logger + logger zerolog.Logger circuitPath string dataPath string } -func NewGroth16System(logger *zap.Logger, circuitPath string, dataPath string) *Groth16System { +func NewGroth16System(logger zerolog.Logger, circuitPath string, dataPath string) *Groth16System { return &Groth16System{ logger: logger, circuitPath: circuitPath, @@ -40,7 +40,7 @@ func NewGroth16System(logger *zap.Logger, circuitPath string, dataPath string) * } func (s *Groth16System) Compile() error { - s.logger.Info("starting compiling verifier circuit") + s.logger.Info().Msg("starting compiling verifier circuit") r1cs, pk, vk, err := s.CompileVerifierCircuit() if err != nil { @@ -52,22 +52,22 @@ func (s *Groth16System) Compile() error { return errors.Wrap(err, "save verifier circuit") } - s.logger.Info("successfully compiled verifier circuit") + s.logger.Info().Msg("successfully compiled verifier circuit") return nil } func (s *Groth16System) Prove() error { - s.logger.Info("starting prove -- loading verifier circuit and proving key") + s.logger.Info().Msg("starting prove -- loading verifier circuit and proving key") // If the circuitPath is "" and not provided as part of the CLI flags, then we wait // for user input. if s.circuitPath == "" { - s.logger.Info("no circuitPath flag found, so user must input circuitPath via stdin") + s.logger.Info().Msg("no circuitPath flag found, so user must input circuitPath via stdin") reader := bufio.NewReader(os.Stdin) str, err := reader.ReadString('\n') if err != nil { - s.logger.Error("failed to parse the user provided circuitPath", zap.Error(err)) + return errors.Wrap(err, "read circuitPath from stdin") } trimmed := strings.TrimSuffix(str, "\n") s.circuitPath = trimmed @@ -87,13 +87,13 @@ func (s *Groth16System) Prove() error { return errors.Wrap(err, "create proof") } - s.logger.Info("successfully created proof") + s.logger.Info().Msg("successfully created proof") return nil } func (s *Groth16System) Verify() error { - s.logger.Info("starting verify -- loading verifier key, public witness, and proof") + s.logger.Info().Msg("starting verify -- loading verifier key, public witness, and proof") vk, err := s.LoadVerifierKey() if err != nil { @@ -115,13 +115,13 @@ func (s *Groth16System) Verify() error { return errors.Wrap(err, "verify proof") } - s.logger.Info("successfully verified proof") + s.logger.Info().Msg("successfully verified proof") return nil } func (s *Groth16System) Export() error { - s.logger.Info("starting export -- loading verifier key and exporting Verifier solidity") + s.logger.Info().Msg("starting export -- loading verifier key and exporting Verifier solidity") vk, err := s.LoadVerifierKey() if err != nil { @@ -133,7 +133,7 @@ func (s *Groth16System) Export() error { return errors.Wrap(err, "export Verifier solidity") } - s.logger.Info("successfully exported Verifier solidity") + s.logger.Info().Msg("successfully exported Verifier solidity") return nil } @@ -160,14 +160,14 @@ func (s *Groth16System) CompileVerifierCircuit() (constraint.ConstraintSystem, g return nil, nil, nil, errors.Wrap(err, "compile verifier circuit") } - s.logger.Info("Running circuit setup") + s.logger.Info().Msg("Running circuit setup") start := time.Now() pk, vk, err := groth16.Setup(r1cs) if err != nil { return nil, nil, nil, err } elapsed := time.Since(start) - s.logger.Info("Successfully ran circuit setup", zap.String("time", elapsed.String())) + s.logger.Info().Msg("Successfully ran circuit setup in " + elapsed.String()) return r1cs, pk, vk, nil } @@ -181,16 +181,16 @@ func (s *Groth16System) SaveVerifierCircuit(r1cs constraint.ConstraintSystem, pk } r1cs.WriteTo(r1csFile) r1csFile.Close() - s.logger.Debug("Successfully saved circuit constraints", zap.String("path", s.dataPath+"/r1cs.bin")) + s.logger.Info().Msg("Successfully saved circuit constraints to r1cs.bin") - s.logger.Info("Saving proving key", zap.String("path", s.dataPath+"/pk.bin")) + s.logger.Info().Msg("Saving proving key to pk.bin") pkFile, err := os.Create(s.dataPath + "/pk.bin") if err != nil { return errors.Wrap(err, "create pk file") } pk.WriteRawTo(pkFile) pkFile.Close() - s.logger.Debug("Successfully saved proving key", zap.String("path", s.dataPath+"/pk.bin")) + s.logger.Info().Msg("Successfully saved proving key to pk.bin") vkFile, err := os.Create(s.dataPath + "/vk.bin") if err != nil { @@ -198,12 +198,13 @@ func (s *Groth16System) SaveVerifierCircuit(r1cs constraint.ConstraintSystem, pk } vk.WriteRawTo(vkFile) vkFile.Close() - s.logger.Debug("Successfully saved verifying key", zap.String("path", s.dataPath+"/vk.bin")) + s.logger.Info().Msg("Successfully saved verifying key to vk.bin") return nil } func (s *Groth16System) ProveCircuit(r1cs constraint.ConstraintSystem, pk groth16.ProvingKey) (groth16.Proof, witness.Witness, error) { + s.logger.Info().Msg("Loading verifier only circuit data and proof with public inputs in path " + s.circuitPath) verifierOnlyCircuitData := variables.DeserializeVerifierOnlyCircuitData( gnark_verifier_types.ReadVerifierOnlyCircuitData(s.circuitPath + "/verifier_only_circuit_data.json"), ) @@ -221,26 +222,26 @@ func (s *Groth16System) ProveCircuit(r1cs constraint.ConstraintSystem, pk groth1 OutputHash: frontend.Variable(outputHash), } - s.logger.Debug("Generating witness") + s.logger.Info().Msg("Generating witness") start := time.Now() witness, err := frontend.NewWitness(assignment, ecc.BN254.ScalarField()) if err != nil { return nil, nil, errors.Wrap(err, "generate witness") } elapsed := time.Since(start) - s.logger.Debug("Successfully generated witness", zap.Duration("time", elapsed)) + s.logger.Info().Msg("Successfully generated witness in " + elapsed.String()) - s.logger.Debug("Creating proof") + s.logger.Info().Msg("Creating proof") start = time.Now() proof, err := groth16.Prove(r1cs, pk, witness) if err != nil { return nil, nil, errors.Wrap(err, "create proof") } elapsed = time.Since(start) - s.logger.Info("Successfully created proof", zap.Duration("time", elapsed)) + s.logger.Info().Msg("Successfully created proof in " + elapsed.String()) _proof := proof.(*groth16Bn254.Proof) - s.logger.Info("Saving proof to proof.json") + s.logger.Info().Msg("Saving proof to proof.json") jsonProof, err := json.Marshal(ProofResult{ Output: []byte{}, Proof: _proof.Ar.Marshal(), @@ -256,7 +257,7 @@ func (s *Groth16System) ProveCircuit(r1cs constraint.ConstraintSystem, pk groth1 if _, err = proofFile.Write(jsonProof); err != nil { return nil, nil, errors.Wrap(err, "write proof file") } - s.logger.Info("Successfully saved proof") + s.logger.Info().Msg("Successfully saved proof") // Write proof with all the public inputs and save to disk. jsonProofWithWitness, err := json.Marshal(struct { @@ -281,14 +282,14 @@ func (s *Groth16System) ProveCircuit(r1cs constraint.ConstraintSystem, pk groth1 if _, err = proofFile.Write(jsonProofWithWitness); err != nil { return nil, nil, errors.Wrap(err, "write proof_with_witness file") } - s.logger.Info("Successfully saved proof_with_witness", zap.String("proofWithWitness", string(jsonProofWithWitness))) + s.logger.Info().Msg("Successfully saved proof_with_witness to proof_with_witness.json") publicWitness, err := witness.Public() if err != nil { return nil, nil, errors.Wrap(err, "get public witness") } - s.logger.Info("Saving public witness to public_witness.bin") + s.logger.Info().Msg("Saving public witness to public_witness.bin") witnessFile, err := os.Create("public_witness.bin") if err != nil { return nil, nil, errors.Wrap(err, "create public witness file") @@ -297,7 +298,7 @@ func (s *Groth16System) ProveCircuit(r1cs constraint.ConstraintSystem, pk groth1 if _, err = publicWitness.WriteTo(witnessFile); err != nil { return nil, nil, errors.Wrap(err, "write public witness file") } - s.logger.Info("Successfully saved public witness") + s.logger.Info().Msg("Successfully saved public witness") return proof, publicWitness, nil } @@ -368,7 +369,7 @@ func (s *Groth16System) LoadVerifierKey() (vk groth16.VerifyingKey, err error) { if err != nil { return nil, errors.Wrap(err, "open vk file") } - _, err = readV08VerifyingKey(vk.(*groth16Bn254.VerifyingKey), f) + _, err = vk.ReadFrom(f) if err != nil { return nil, errors.Wrap(err, "read vk file") } diff --git a/plonky2x/verifier/system/groth16_deserializer.go b/plonky2x/verifier/system/groth16_deserializer.go deleted file mode 100644 index 363e2c598..000000000 --- a/plonky2x/verifier/system/groth16_deserializer.go +++ /dev/null @@ -1,332 +0,0 @@ -package system - -import ( - "encoding/json" - "io" - - "github.com/consensys/gnark-crypto/ecc/bn254/fp" - "github.com/consensys/gnark-crypto/ecc/bn254/fr" - "github.com/consensys/gnark-crypto/ecc/bn254/fr/iop" - - "github.com/consensys/gnark-crypto/ecc/bn254" - "github.com/consensys/gnark/backend/groth16" - groth16Bn254 "github.com/consensys/gnark/backend/groth16/bn254" -) - -// func readV08ProvingKey(pk *groth16Bn254.ProvingKey, r io.Reader) (int64, error) { -// dec := bn254.NewDecoder(r) - -// // Read domain -// if err := dec.Decode(&pk.Domain); err != nil { -// return dec.BytesRead(), err -// } -// fmt.Println("pk.Domain", pk.Domain) -// // Read G1 (Alpha, Beta, Delta, A, B, Z, K) -// if err := dec.Decode(&pk.G1.Alpha); err != nil { -// return dec.BytesRead(), err -// } -// fmt.Println("pk.G1.Alpha", pk.G1.Alpha) -// if err := dec.Decode(&pk.G1.Beta); err != nil { -// return dec.BytesRead(), err -// } -// fmt.Println("pk.G1.Beta", pk.G1.Beta) -// if err := dec.Decode(&pk.G1.Delta); err != nil { -// return dec.BytesRead(), err -// } -// fmt.Println("pk.G1.Delta", pk.G1.Delta) -// if err := dec.Decode(&pk.G1.A); err != nil { -// return dec.BytesRead(), err -// } -// if err := dec.Decode(&pk.G1.B); err != nil { -// return dec.BytesRead(), err -// } -// fmt.Println("pk.G1.B", pk.G1.B) -// if err := dec.Decode(&pk.G1.Z); err != nil { -// return dec.BytesRead(), err -// } -// if err := dec.Decode(&pk.G1.K); err != nil { -// return dec.BytesRead(), err -// } -// fmt.Println("pk.G1.K", pk.G1.K) - -// // Read G2 (Beta, Delta, B) -// if err := dec.Decode(&pk.G2.Beta); err != nil { -// return dec.BytesRead(), err -// } -// fmt.Println("pk.G2.Beta", pk.G2.Beta) -// if err := dec.Decode(&pk.G2.Delta); err != nil { -// return dec.BytesRead(), err -// } -// fmt.Println("pk.G2.Delta", pk.G2.Delta) -// if err := dec.Decode(&pk.G2.B); err != nil { -// return dec.BytesRead(), err -// } -// fmt.Println("pk.G2.B", pk.G2.B) - -// // Read InfinityA, InfinityB, NbInfinityA, NbInfinityB -// if err := dec.Decode(&pk.InfinityA); err != nil { -// return dec.BytesRead(), err -// } -// fmt.Println("pk.InfinityA", pk.InfinityA) -// if err := dec.Decode(&pk.InfinityB); err != nil { -// return dec.BytesRead(), err -// } -// fmt.Println("pk.InfinityB", pk.InfinityB) -// if err := dec.Decode(&pk.NbInfinityA); err != nil { -// return dec.BytesRead(), err -// } -// fmt.Println("pk.NbInfinityA", pk.NbInfinityA) -// if err := dec.Decode(&pk.NbInfinityB); err != nil { -// return dec.BytesRead(), err -// } -// fmt.Println("pk.NbInfinityB", pk.NbInfinityB) - -// return dec.BytesRead(), nil -// } - -func readV08ProvingKey(pk *groth16Bn254.ProvingKey, r io.Reader) (int64, error) { - pk.Vk = &groth16.VerifyingKey{} - n, err := pk.Vk.ReadFrom(r) - if err != nil { - return n, err - } - - n2, err, chDomain0 := pk.Domain[0].AsyncReadFrom(r) - n += n2 - if err != nil { - return n, err - } - - n2, err, chDomain1 := pk.Domain[1].AsyncReadFrom(r) - n += n2 - if err != nil { - return n, err - } - - if withSubgroupChecks { - n2, err = pk.Kzg.ReadFrom(r) - } else { - n2, err = pk.Kzg.UnsafeReadFrom(r) - } - n += n2 - if err != nil { - return n, err - } - if withSubgroupChecks { - n2, err = pk.KzgLagrange.ReadFrom(r) - } else { - n2, err = pk.KzgLagrange.UnsafeReadFrom(r) - } - n += n2 - if err != nil { - return n, err - } - - pk.trace.S = make([]int64, 3*pk.Domain[0].Cardinality) - - dec := curve.NewDecoder(r) - - var ql, qr, qm, qo, qk, s1, s2, s3 []fr.Element - var qcp [][]fr.Element - - // TODO @gbotrel: this is a bit ugly, we should probably refactor this. - // The order of the variables is important, as it matches the order in which they are - // encoded in the WriteTo(...) method. - - // Note: instead of calling dec.Decode(...) for each of the above variables, - // we call AsyncReadFrom when possible which allows to consume bytes from the reader - // and perform the decoding in parallel - - type v struct { - data *fr.Vector - chErr chan error - } - - vectors := make([]v, 8) - vectors[0] = v{data: (*fr.Vector)(&ql)} - vectors[1] = v{data: (*fr.Vector)(&qr)} - vectors[2] = v{data: (*fr.Vector)(&qm)} - vectors[3] = v{data: (*fr.Vector)(&qo)} - vectors[4] = v{data: (*fr.Vector)(&qk)} - vectors[5] = v{data: (*fr.Vector)(&s1)} - vectors[6] = v{data: (*fr.Vector)(&s2)} - vectors[7] = v{data: (*fr.Vector)(&s3)} - - // read ql, qr, qm, qo, qk - for i := 0; i < 5; i++ { - n2, err, ch := vectors[i].data.AsyncReadFrom(r) - n += n2 - if err != nil { - return n, err - } - vectors[i].chErr = ch - } - - // read qcp - if err := dec.Decode(&qcp); err != nil { - return n + dec.BytesRead(), err - } - - // read lqk, s1, s2, s3 - for i := 5; i < 8; i++ { - n2, err, ch := vectors[i].data.AsyncReadFrom(r) - n += n2 - if err != nil { - return n, err - } - vectors[i].chErr = ch - } - - // read pk.Trace.S - if err := dec.Decode(&pk.trace.S); err != nil { - return n + dec.BytesRead(), err - } - - // wait for all AsyncReadFrom(...) to complete - for i := range vectors { - if err := <-vectors[i].chErr; err != nil { - return n, err - } - } - - canReg := iop.Form{Basis: iop.Canonical, Layout: iop.Regular} - pk.trace.Ql = iop.NewPolynomial(&ql, canReg) - pk.trace.Qr = iop.NewPolynomial(&qr, canReg) - pk.trace.Qm = iop.NewPolynomial(&qm, canReg) - pk.trace.Qo = iop.NewPolynomial(&qo, canReg) - pk.trace.Qk = iop.NewPolynomial(&qk, canReg) - pk.trace.S1 = iop.NewPolynomial(&s1, canReg) - pk.trace.S2 = iop.NewPolynomial(&s2, canReg) - pk.trace.S3 = iop.NewPolynomial(&s3, canReg) - - pk.trace.Qcp = make([]*iop.Polynomial, len(qcp)) - for i := range qcp { - pk.trace.Qcp[i] = iop.NewPolynomial(&qcp[i], canReg) - } - - // wait for FFT to be precomputed - <-chDomain0 - <-chDomain1 - - return n + dec.BytesRead(), nil - -} - -func readV08VerifyingKey(vk *groth16Bn254.VerifyingKey, r io.Reader) (int64, error) { - dec := bn254.NewDecoder(r) - if err := dec.Decode(&vk.G1.Alpha); err != nil { - return dec.BytesRead(), err - } - if err := dec.Decode(&vk.G1.Beta); err != nil { - return dec.BytesRead(), err - } - if err := dec.Decode(&vk.G2.Beta); err != nil { - return dec.BytesRead(), err - } - if err := dec.Decode(&vk.G2.Gamma); err != nil { - return dec.BytesRead(), err - } - if err := dec.Decode(&vk.G1.Delta); err != nil { - return dec.BytesRead(), err - } - if err := dec.Decode(&vk.G2.Delta); err != nil { - return dec.BytesRead(), err - } - - // uint32(len(Kvk)),[Kvk]1 - if err := dec.Decode(&vk.G1.K); err != nil { - return dec.BytesRead(), err - } - - if err := vk.Precompute(); err != nil { - return dec.BytesRead(), err - } - - return dec.BytesRead(), nil -} - -// G1 projective point coordinates -type g1ProjJson [3]string - -// G2 projective point coordinates -type g2ProjJson [3][2]string - -type vkJson struct { - AlphaG1 g1ProjJson `json:"vk_alpha_1"` - BetaG2 g2ProjJson `json:"vk_beta_2"` - GammaG2 g2ProjJson `json:"vk_gamma_2"` - DeltaG2 g2ProjJson `json:"vk_delta_2"` - // length dependent on circuit public inputs - G1K []g1ProjJson `json:"IC"` -} - -type g2Proj struct { - X, Y, Z bn254.E2 -} - -func (g *g2Proj) fromJson(j *g2ProjJson) *g2Proj { - g.X.SetString(j[0][0], j[0][1]) - g.Y.SetString(j[1][0], j[1][1]) - g.Z.SetString(j[2][0], j[2][1]) - return g -} - -func (g *g2Proj) toAffine() bn254.G2Affine { - res := bn254.G2Affine{} - if !g.Z.IsZero() { - res.X.Div(&g.X, &g.Z) - res.Y.Div(&g.Y, &g.Z) - } - return res -} - -type g1Proj struct { - X, Y, Z fp.Element -} - -func (g *g1Proj) fromJson(j *g1ProjJson) *g1Proj { - g.X.SetString(j[0]) - g.Y.SetString(j[1]) - g.Z.SetString(j[2]) - return g -} - -func (g *g1Proj) toAffine() bn254.G1Affine { - res := bn254.G1Affine{} - if !g.Z.IsZero() { - res.X.Div(&g.X, &g.Z) - res.Y.Div(&g.Y, &g.Z) - } - return res -} - -func readJsonVerifyingKey(vk *groth16Bn254.VerifyingKey, r io.Reader) error { - data, err := io.ReadAll(r) - - if err != nil { - return err - } - - var vkJson vkJson - - err = json.Unmarshal(data, &vkJson) - - if err != nil { - return err - } - - vk.G1.Alpha = new(g1Proj).fromJson(&vkJson.AlphaG1).toAffine() - - vk.G2.Beta = new(g2Proj).fromJson(&vkJson.BetaG2).toAffine() - vk.G2.Gamma = new(g2Proj).fromJson(&vkJson.GammaG2).toAffine() - vk.G2.Delta = new(g2Proj).fromJson(&vkJson.DeltaG2).toAffine() - - vk.G1.K = make([]bn254.G1Affine, len(vkJson.G1K)) - for i := 0; i < len(vkJson.G1K); i++ { - vk.G1.K[i] = new(g1Proj).fromJson(&vkJson.G1K[i]).toAffine() - } - - vk.Precompute() - - return nil -} diff --git a/plonky2x/verifier/system/groth16_test.go b/plonky2x/verifier/system/groth16_test.go new file mode 100644 index 000000000..b39ca819c --- /dev/null +++ b/plonky2x/verifier/system/groth16_test.go @@ -0,0 +1,124 @@ +// Useful reference files in gnark: +// https://github.com/Consensys/gnark-solidity-checker/blob/main/cmd/templates.go +// https://github.com/Consensys/gnark/blob/cfe83dbce12428ad0b095bcc33de55c6a9121949/test/assert_solidity.go#L60-L77 +package system + +import ( + "bufio" + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "os" + "testing" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark/backend/groth16" + "github.com/consensys/gnark/frontend" + "github.com/consensys/gnark/frontend/cs/r1cs" + "github.com/consensys/gnark/std/rangecheck" +) + +type MyCircuit struct { + X frontend.Variable `gnark:",public"` + Y frontend.Variable `gnark:",public"` + Z frontend.Variable `gnark:",public"` + DoRangeCheck bool +} + +func (circuit *MyCircuit) Define(api frontend.API) error { + api.AssertIsEqual(circuit.Z, api.Add(circuit.X, circuit.Y)) + if true || circuit.DoRangeCheck { + rangeChecker := rangecheck.New(api) + rangeChecker.Check(circuit.X, 8) + } + return nil +} + +type Groth16ProofData struct { + Proof []string `json:"proof"` + Inputs []string `json:"inputs"` +} + +func TestGroth16(t *testing.T) { + + circuit := MyCircuit{DoRangeCheck: false} + + r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + if err != nil { + panic(err) + } + pk, vk, err := groth16.Setup(r1cs) + if err != nil { + panic(err) + } + + buf := new(bytes.Buffer) + err = vk.ExportSolidity(buf) + if err != nil { + panic(err) + } + content := buf.String() + + contractFile, err := os.Create("VerifierGroth16.sol") + if err != nil { + panic(err) + } + w := bufio.NewWriter(contractFile) + // write the new content to the writer + _, err = w.Write([]byte(content)) + if err != nil { + panic(err) + } + contractFile.Close() + + assignment := MyCircuit{ + X: 1, + Y: 2, + Z: 3, + } + + witness, _ := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) + proof, _ := groth16.Prove(r1cs, pk, witness) + + const fpSize = 4 * 8 + buf = new(bytes.Buffer) + proof.WriteRawTo(buf) + proofBytes := buf.Bytes() + + proofs := make([]string, 8) + // Print out the proof + for i := 0; i < 8; i++ { + proofs[i] = "0x" + hex.EncodeToString(proofBytes[i*fpSize:(i+1)*fpSize]) + } + + publicWitness, _ := witness.Public() + publicWitnessBytes, _ := publicWitness.MarshalBinary() + publicWitnessBytes = publicWitnessBytes[12:] // We cut off the first 12 bytes because they encode length information + + inputs := make([]string, 3) + // Print out the public witness bytes + for i := 0; i < 3; i++ { + inputs[i] = "0x" + hex.EncodeToString(publicWitnessBytes[i*fpSize:(i+1)*fpSize]) + } + + // Create the data struct and populate it + data := Groth16ProofData{ + Proof: proofs, + Inputs: inputs, + } + + // Marshal the data into JSON + jsonData, err := json.MarshalIndent(data, "", " ") + if err != nil { + fmt.Println("Error marshalling to JSON:", err) + return + } + + // Write the JSON to a file + err = ioutil.WriteFile("groth16_proof_data.json", jsonData, 0644) + if err != nil { + fmt.Println("Error writing to file:", err) + } +} diff --git a/plonky2x/verifier/system/plonk.go b/plonky2x/verifier/system/plonk.go index 3885a268c..38655d2cb 100644 --- a/plonky2x/verifier/system/plonk.go +++ b/plonky2x/verifier/system/plonk.go @@ -11,6 +11,7 @@ import ( "time" "github.com/consensys/gnark-crypto/ecc" + groth16Bn254 "github.com/consensys/gnark/backend/groth16/bn254" "github.com/consensys/gnark/backend/plonk" "github.com/consensys/gnark/backend/witness" "github.com/consensys/gnark/constraint" @@ -19,22 +20,19 @@ import ( "github.com/consensys/gnark/test" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" - "github.com/rs/zerolog/log" - "go.uber.org/zap" + "github.com/rs/zerolog" - plonk_bn254 "github.com/consensys/gnark/backend/plonk/bn254" gnark_verifier_types "github.com/succinctlabs/gnark-plonky2-verifier/types" "github.com/succinctlabs/gnark-plonky2-verifier/variables" - "github.com/succinctlabs/succinctx/gnarkx/types" ) type PlonkSystem struct { - logger *zap.Logger + logger zerolog.Logger circuitPath string dataPath string } -func NewPlonkSystem(logger *zap.Logger, circuitPath string, dataPath string) *PlonkSystem { +func NewPlonkSystem(logger zerolog.Logger, circuitPath string, dataPath string) *PlonkSystem { return &PlonkSystem{ logger: logger, circuitPath: circuitPath, @@ -43,7 +41,7 @@ func NewPlonkSystem(logger *zap.Logger, circuitPath string, dataPath string) *Pl } func (s *PlonkSystem) Compile() error { - s.logger.Info("starting compiling verifier circuit") + s.logger.Info().Msg("starting compiling verifier circuit") r1cs, pk, vk, err := s.CompileVerifierCircuit() if err != nil { @@ -55,22 +53,22 @@ func (s *PlonkSystem) Compile() error { return errors.Wrap(err, "save verifier circuit") } - s.logger.Info("successfully compiled verifier circuit") + s.logger.Info().Msg("successfully compiled verifier circuit") return nil } func (s *PlonkSystem) Prove() error { - s.logger.Info("starting prove -- loading verifier circuit and proving key") + s.logger.Info().Msg("starting prove -- loading verifier circuit and proving key") // If the circuitPath is "" and not provided as part of the CLI flags, then we wait // for user input. if s.circuitPath == "" { - s.logger.Info("no circuitPath flag found, so user must input circuitPath via stdin") + s.logger.Info().Msg("no circuitPath flag found, so user must input circuitPath via stdin") reader := bufio.NewReader(os.Stdin) str, err := reader.ReadString('\n') if err != nil { - s.logger.Error("failed to parse the user provided circuitPath", zap.Error(err)) + return errors.Wrap(err, "read circuitPath from stdin") } trimmed := strings.TrimSuffix(str, "\n") s.circuitPath = trimmed @@ -90,13 +88,13 @@ func (s *PlonkSystem) Prove() error { return errors.Wrap(err, "create proof") } - s.logger.Info("successfully created proof") + s.logger.Info().Msg("successfully created proof") return nil } func (s *PlonkSystem) Verify() error { - s.logger.Info("starting verify -- loading verifier key, public witness, and proof") + s.logger.Info().Msg("starting verify -- loading verifier key, public witness, and proof") vk, err := s.LoadVerifierKey() if err != nil { @@ -118,13 +116,13 @@ func (s *PlonkSystem) Verify() error { return errors.Wrap(err, "verify proof") } - s.logger.Info("successfully verified proof") + s.logger.Info().Msg("successfully verified proof") return nil } func (s *PlonkSystem) Export() error { - s.logger.Info("starting export -- loading verifier key and exporting Verifier solidity") + s.logger.Info().Msg("starting export -- loading verifier key and exporting Verifier solidity") vk, err := s.LoadVerifierKey() if err != nil { @@ -136,7 +134,7 @@ func (s *PlonkSystem) Export() error { return errors.Wrap(err, "export Verifier solidity") } - s.logger.Info("successfully exported Verifier solidity") + s.logger.Info().Msg("successfully exported Verifier solidity") return nil } @@ -163,7 +161,7 @@ func (s *PlonkSystem) CompileVerifierCircuit() (constraint.ConstraintSystem, plo return nil, nil, nil, errors.Wrap(err, "compile verifier circuit") } - s.logger.Info("Running circuit setup") + s.logger.Info().Msg("Successfully compiled verifier circuit") start := time.Now() srs, err := test.NewKZGSRS(scs) if err != nil { @@ -174,7 +172,7 @@ func (s *PlonkSystem) CompileVerifierCircuit() (constraint.ConstraintSystem, plo return nil, nil, nil, err } elapsed := time.Since(start) - s.logger.Info("Successfully ran circuit setup", zap.String("time", elapsed.String())) + s.logger.Info().Msg("Successfully ran circuit setup in " + elapsed.String()) return scs, pk, vk, nil } @@ -188,16 +186,16 @@ func (s *PlonkSystem) SaveVerifierCircuit(r1cs constraint.ConstraintSystem, pk p } r1cs.WriteTo(r1csFile) r1csFile.Close() - s.logger.Debug("Successfully saved circuit constraints", zap.String("path", s.dataPath+"/r1cs.bin")) + s.logger.Info().Msg("Successfully saved circuit constraints to r1cs.bin") - s.logger.Info("Saving proving key", zap.String("path", s.dataPath+"/pk.bin")) + s.logger.Info().Msg("Saving proving key to pk.bin") pkFile, err := os.Create(s.dataPath + "/pk.bin") if err != nil { return errors.Wrap(err, "create pk file") } pk.WriteRawTo(pkFile) pkFile.Close() - s.logger.Debug("Successfully saved proving key", zap.String("path", s.dataPath+"/pk.bin")) + s.logger.Info().Msg("Successfully saved proving key to pk.bin") vkFile, err := os.Create(s.dataPath + "/vk.bin") if err != nil { @@ -205,12 +203,13 @@ func (s *PlonkSystem) SaveVerifierCircuit(r1cs constraint.ConstraintSystem, pk p } vk.WriteRawTo(vkFile) vkFile.Close() - s.logger.Debug("Successfully saved verifying key", zap.String("path", s.dataPath+"/vk.bin")) + s.logger.Info().Msg("Successfully saved verifying key to vk.bin") return nil } func (s *PlonkSystem) ProveCircuit(r1cs constraint.ConstraintSystem, pk plonk.ProvingKey) (plonk.Proof, witness.Witness, error) { + s.logger.Info().Msg("Loading verifier only circuit data and proof with public inputs in path " + s.circuitPath) verifierOnlyCircuitData := variables.DeserializeVerifierOnlyCircuitData( gnark_verifier_types.ReadVerifierOnlyCircuitData(s.circuitPath + "/verifier_only_circuit_data.json"), ) @@ -228,30 +227,29 @@ func (s *PlonkSystem) ProveCircuit(r1cs constraint.ConstraintSystem, pk plonk.Pr OutputHash: frontend.Variable(outputHash), } - s.logger.Debug("Generating witness") + s.logger.Info().Msg("Generating witness") start := time.Now() witness, err := frontend.NewWitness(assignment, ecc.BN254.ScalarField()) if err != nil { return nil, nil, errors.Wrap(err, "generate witness") } elapsed := time.Since(start) - s.logger.Debug("Successfully generated witness", zap.Duration("time", elapsed)) + s.logger.Info().Msg("Successfully generated witness in " + elapsed.String()) - s.logger.Debug("Creating proof") + s.logger.Info().Msg("Creating proof") start = time.Now() proof, err := plonk.Prove(r1cs, pk, witness) if err != nil { return nil, nil, errors.Wrap(err, "create proof") } elapsed = time.Since(start) - s.logger.Info("Successfully created proof", zap.Duration("time", elapsed)) + s.logger.Info().Msg("Successfully created proof in " + elapsed.String()) - _proof := proof.(*plonk_bn254.Proof) - log.Info().Msg("Saving proof to proof.json") - jsonProof, err := json.Marshal(types.ProofResult{ - // Output will be filled in by plonky2x CLI + _proof := proof.(*groth16Bn254.Proof) + s.logger.Info().Msg("Saving proof to proof.json") + jsonProof, err := json.Marshal(ProofResult{ Output: []byte{}, - Proof: _proof.MarshalSolidity(), + Proof: _proof.Ar.Marshal(), }) if err != nil { return nil, nil, errors.Wrap(err, "marshal proof") @@ -264,7 +262,7 @@ func (s *PlonkSystem) ProveCircuit(r1cs constraint.ConstraintSystem, pk plonk.Pr if _, err = proofFile.Write(jsonProof); err != nil { return nil, nil, errors.Wrap(err, "write proof file") } - s.logger.Info("Successfully saved proof") + s.logger.Info().Msg("Successfully saved proof") // Write proof with all the public inputs and save to disk. jsonProofWithWitness, err := json.Marshal(struct { @@ -276,7 +274,7 @@ func (s *PlonkSystem) ProveCircuit(r1cs constraint.ConstraintSystem, pk plonk.Pr InputHash: inputHash.Bytes(), OutputHash: outputHash.Bytes(), VerifierDigest: (verifierOnlyCircuitData.CircuitDigest).(*big.Int).Bytes(), - Proof: _proof.MarshalSolidity(), + Proof: _proof.Ar.Marshal(), }) if err != nil { return nil, nil, errors.Wrap(err, "marshal proof with witness") @@ -289,14 +287,14 @@ func (s *PlonkSystem) ProveCircuit(r1cs constraint.ConstraintSystem, pk plonk.Pr if _, err = proofFile.Write(jsonProofWithWitness); err != nil { return nil, nil, errors.Wrap(err, "write proof_with_witness file") } - s.logger.Info("Successfully saved proof_with_witness", zap.String("proofWithWitness", string(jsonProofWithWitness))) + s.logger.Info().Msg("Successfully saved proof_with_witness to proof_with_witness.json") publicWitness, err := witness.Public() if err != nil { return nil, nil, errors.Wrap(err, "get public witness") } - s.logger.Info("Saving public witness to public_witness.bin") + s.logger.Info().Msg("Saving public witness to public_witness.bin") witnessFile, err := os.Create("public_witness.bin") if err != nil { return nil, nil, errors.Wrap(err, "create public witness file") @@ -305,7 +303,7 @@ func (s *PlonkSystem) ProveCircuit(r1cs constraint.ConstraintSystem, pk plonk.Pr if _, err = publicWitness.WriteTo(witnessFile); err != nil { return nil, nil, errors.Wrap(err, "write public witness file") } - s.logger.Info("Successfully saved public witness") + s.logger.Info().Msg("Successfully saved public witness") return proof, publicWitness, nil } diff --git a/plonky2x/verifier/gnark_verifiers_test.go b/plonky2x/verifier/system/plonk_test.go similarity index 53% rename from plonky2x/verifier/gnark_verifiers_test.go rename to plonky2x/verifier/system/plonk_test.go index a53ef07f5..d3b3a2430 100644 --- a/plonky2x/verifier/gnark_verifiers_test.go +++ b/plonky2x/verifier/system/plonk_test.go @@ -1,7 +1,7 @@ // Useful reference files in gnark: // https://github.com/Consensys/gnark-solidity-checker/blob/main/cmd/templates.go // https://github.com/Consensys/gnark/blob/cfe83dbce12428ad0b095bcc33de55c6a9121949/test/assert_solidity.go#L60-L77 -package main +package system import ( "bufio" @@ -14,119 +14,13 @@ import ( "testing" "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/backend/plonk" plonk_bn254 "github.com/consensys/gnark/backend/plonk/bn254" "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/consensys/gnark/frontend/cs/scs" - "github.com/consensys/gnark/std/rangecheck" "github.com/consensys/gnark/test" ) -type MyCircuit struct { - X frontend.Variable `gnark:",public"` - Y frontend.Variable `gnark:",public"` - Z frontend.Variable `gnark:",public"` - DoRangeCheck bool -} - -func (circuit *MyCircuit) Define(api frontend.API) error { - api.AssertIsEqual(circuit.Z, api.Add(circuit.X, circuit.Y)) - if true || circuit.DoRangeCheck { - rangeChecker := rangecheck.New(api) - rangeChecker.Check(circuit.X, 8) - } - return nil -} - -type Groth16ProofData struct { - Proof []string `json:"proof"` - Inputs []string `json:"inputs"` -} - -func TestGroth16(t *testing.T) { - - circuit := MyCircuit{DoRangeCheck: false} - - r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) - if err != nil { - panic(err) - } - pk, vk, err := groth16.Setup(r1cs) - if err != nil { - panic(err) - } - - buf := new(bytes.Buffer) - err = vk.ExportSolidity(buf) - if err != nil { - panic(err) - } - content := buf.String() - - contractFile, err := os.Create("VerifierGroth16.sol") - if err != nil { - panic(err) - } - w := bufio.NewWriter(contractFile) - // write the new content to the writer - _, err = w.Write([]byte(content)) - if err != nil { - panic(err) - } - contractFile.Close() - - assignment := MyCircuit{ - X: 1, - Y: 2, - Z: 3, - } - - witness, _ := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) - proof, _ := groth16.Prove(r1cs, pk, witness) - - const fpSize = 4 * 8 - buf = new(bytes.Buffer) - proof.WriteRawTo(buf) - proofBytes := buf.Bytes() - - proofs := make([]string, 8) - // Print out the proof - for i := 0; i < 8; i++ { - proofs[i] = "0x" + hex.EncodeToString(proofBytes[i*fpSize:(i+1)*fpSize]) - } - - publicWitness, _ := witness.Public() - publicWitnessBytes, _ := publicWitness.MarshalBinary() - publicWitnessBytes = publicWitnessBytes[12:] // We cut off the first 12 bytes because they encode length information - - inputs := make([]string, 3) - // Print out the public witness bytes - for i := 0; i < 3; i++ { - inputs[i] = "0x" + hex.EncodeToString(publicWitnessBytes[i*fpSize:(i+1)*fpSize]) - } - - // Create the data struct and populate it - data := Groth16ProofData{ - Proof: proofs, - Inputs: inputs, - } - - // Marshal the data into JSON - jsonData, err := json.MarshalIndent(data, "", " ") - if err != nil { - fmt.Println("Error marshalling to JSON:", err) - return - } - - // Write the JSON to a file - err = ioutil.WriteFile("groth16_proof_data.json", jsonData, 0644) - if err != nil { - fmt.Println("Error writing to file:", err) - } -} - type PlonkProofData struct { Proof string `json:"proof"` Inputs []string `json:"inputs"` diff --git a/plonky2x/verifier/system/x.go b/plonky2x/verifier/system/x.go deleted file mode 100644 index 4d8763be0..000000000 --- a/plonky2x/verifier/system/x.go +++ /dev/null @@ -1,67 +0,0 @@ -// ReadFrom attempts to decode a VerifyingKey from reader -// VerifyingKey must be encoded through WriteTo (compressed) or WriteRawTo (uncompressed) -// serialization format: -// https://github.com/zkcrypto/bellman/blob/fa9be45588227a8c6ec34957de3f68705f07bd92/src/groth16/mod.rs#L143 -// [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2,uint32(len(Kvk)),[Kvk]1 -func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) { - n, err := vk.readFrom(r) - if err != nil { - return n, err - } - var m int64 - m, err = vk.CommitmentKey.ReadFrom(r) - return m + n, err -} - -// UnsafeReadFrom has the same behavior as ReadFrom, except that it will not check that decode points -// are on the curve and in the correct subgroup. -func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) { - n, err := vk.readFrom(r, curve.NoSubgroupChecks()) - if err != nil { - return n, err - } - var m int64 - m, err = vk.CommitmentKey.UnsafeReadFrom(r) - return m + n, err -} - -func (vk *VerifyingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { - dec := curve.NewDecoder(r, decOptions...) - - // [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2 - if err := dec.Decode(&vk.G1.Alpha); err != nil { - return dec.BytesRead(), err - } - if err := dec.Decode(&vk.G1.Beta); err != nil { - return dec.BytesRead(), err - } - if err := dec.Decode(&vk.G2.Beta); err != nil { - return dec.BytesRead(), err - } - if err := dec.Decode(&vk.G2.Gamma); err != nil { - return dec.BytesRead(), err - } - if err := dec.Decode(&vk.G1.Delta); err != nil { - return dec.BytesRead(), err - } - if err := dec.Decode(&vk.G2.Delta); err != nil { - return dec.BytesRead(), err - } - - // uint32(len(Kvk)),[Kvk]1 - if err := dec.Decode(&vk.G1.K); err != nil { - return dec.BytesRead(), err - } - var publicCommitted [][]uint64 - if err := dec.Decode(&publicCommitted); err != nil { - return dec.BytesRead(), err - } - vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - - // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 - if err := vk.Precompute(); err != nil { - return dec.BytesRead(), err - } - - return dec.BytesRead(), nil -} \ No newline at end of file