github.com/consensys/gnark@v0.11.0/test/assert_solidity.go (about) 1 package test 2 3 import ( 4 "encoding/hex" 5 "os" 6 "os/exec" 7 "path/filepath" 8 "strconv" 9 10 fr_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/fr" 11 "github.com/consensys/gnark/backend" 12 "github.com/consensys/gnark/backend/solidity" 13 "github.com/consensys/gnark/backend/witness" 14 ) 15 16 // solidityVerification checks that the exported solidity contract can verify the proof 17 // and that the proof is valid. 18 // It uses gnark-solidity-checker see test.WithSolidity option. 19 func (assert *Assert) solidityVerification(b backend.ID, vk solidity.VerifyingKey, 20 proof any, 21 validPublicWitness witness.Witness, 22 opts []solidity.ExportOption, 23 ) { 24 if !SolcCheck || len(validPublicWitness.Vector().(fr_bn254.Vector)) == 0 { 25 return // nothing to check, will make solc fail. 26 } 27 assert.t.Helper() 28 29 // make temp dir 30 tmpDir, err := os.MkdirTemp("", "gnark-solidity-check*") 31 assert.NoError(err) 32 defer os.RemoveAll(tmpDir) 33 34 // export solidity contract 35 fSolidity, err := os.Create(filepath.Join(tmpDir, "gnark_verifier.sol")) 36 assert.NoError(err) 37 38 err = vk.ExportSolidity(fSolidity, opts...) 39 assert.NoError(err) 40 41 err = fSolidity.Close() 42 assert.NoError(err) 43 44 // generate assets 45 // gnark-solidity-checker generate --dir tmpdir --solidity contract_g16.sol 46 cmd := exec.Command("gnark-solidity-checker", "generate", "--dir", tmpDir, "--solidity", "gnark_verifier.sol") 47 assert.t.Log("running ", cmd.String()) 48 out, err := cmd.CombinedOutput() 49 assert.NoError(err, string(out)) 50 51 // len(vk.K) - 1 == len(publicWitness) + len(commitments) 52 numOfCommitments := vk.NbPublicWitness() - len(validPublicWitness.Vector().(fr_bn254.Vector)) 53 54 checkerOpts := []string{"verify"} 55 if b == backend.GROTH16 { 56 checkerOpts = append(checkerOpts, "--groth16") 57 } else if b == backend.PLONK { 58 checkerOpts = append(checkerOpts, "--plonk") 59 } else { 60 panic("not implemented") 61 } 62 63 // proof to hex 64 _proof, ok := proof.(interface{ MarshalSolidity() []byte }) 65 if !ok { 66 panic("proof does not implement MarshalSolidity()") 67 } 68 69 proofStr := hex.EncodeToString(_proof.MarshalSolidity()) 70 71 if numOfCommitments > 0 { 72 checkerOpts = append(checkerOpts, "--commitment", strconv.Itoa(numOfCommitments)) 73 } 74 75 // public witness to hex 76 bPublicWitness, err := validPublicWitness.MarshalBinary() 77 assert.NoError(err) 78 // that's quite dirty... 79 // first 4 bytes -> nbPublic 80 // next 4 bytes -> nbSecret 81 // next 4 bytes -> nb elements in the vector (== nbPublic + nbSecret) 82 bPublicWitness = bPublicWitness[12:] 83 publicWitnessStr := hex.EncodeToString(bPublicWitness) 84 85 checkerOpts = append(checkerOpts, "--dir", tmpDir) 86 checkerOpts = append(checkerOpts, "--nb-public-inputs", strconv.Itoa(len(validPublicWitness.Vector().(fr_bn254.Vector)))) 87 checkerOpts = append(checkerOpts, "--proof", proofStr) 88 checkerOpts = append(checkerOpts, "--public-inputs", publicWitnessStr) 89 90 // verify proof 91 // gnark-solidity-checker verify --dir tmdir --groth16 --nb-public-inputs 1 --proof 1234 --public-inputs dead 92 cmd = exec.Command("gnark-solidity-checker", checkerOpts...) 93 assert.t.Log("running ", cmd.String()) 94 out, err = cmd.CombinedOutput() 95 assert.NoError(err, string(out)) 96 }