diff --git a/circuitexamples/factor.circuit b/circuitexamples/factor.circuit index 8bbb1b5..841ddd1 100644 --- a/circuitexamples/factor.circuit +++ b/circuitexamples/factor.circuit @@ -1,4 +1,4 @@ -func test(private a, private b, public c): +func main(private a, private b, public c): d = a * b equals(c, d) out = 1 * 1 diff --git a/circuitexamples/function.circuit b/circuitexamples/function.circuit index fc29edc..b1b3721 100644 --- a/circuitexamples/function.circuit +++ b/circuitexamples/function.circuit @@ -1,4 +1,4 @@ -func test(private s0, public s1): +func main(private s0, public s1): s2 = s0 * s0 s3 = s2 * s0 s4 = s3 + s0 diff --git a/wasm/README.md b/wasm/README.md index 5fdae15..a46fb91 100644 --- a/wasm/README.md +++ b/wasm/README.md @@ -1,6 +1,8 @@ # go-snark wasm *Warning: this is an ongoing experimentation* +WASM wrappers for zkSNARK Pinocchio & Groth16 protocols. + ## Wasm usage To compile to wasm, inside the `wasm` directory, execute: ``` diff --git a/wasm/go-snark-wasm-wrapper.go b/wasm/go-snark-wasm-wrapper.go index 44cc8b9..b924abc 100644 --- a/wasm/go-snark-wasm-wrapper.go +++ b/wasm/go-snark-wasm-wrapper.go @@ -7,6 +7,7 @@ import ( "github.com/arnaucube/go-snark" "github.com/arnaucube/go-snark/circuitcompiler" + "github.com/arnaucube/go-snark/groth16" "github.com/arnaucube/go-snark/wasm/utils" ) @@ -20,6 +21,8 @@ func main() { func registerCallbacks() { js.Global().Set("generateProofs", js.FuncOf(generateProofs)) js.Global().Set("verifyProofs", js.FuncOf(verifyProofs)) + js.Global().Set("grothGenerateProofs", js.FuncOf(grothGenerateProofs)) + js.Global().Set("grothVerifyProofs", js.FuncOf(grothVerifyProofs)) } func generateProofs(this js.Value, i []js.Value) interface{} { @@ -142,3 +145,124 @@ func verifyProofs(this js.Value, i []js.Value) interface{} { println("verifiedJson", string(verifiedJson)) return js.ValueOf(string(verifiedJson)) } + +func grothGenerateProofs(this js.Value, i []js.Value) interface{} { + var circuitStr utils.CircuitString + err := json.Unmarshal([]byte(i[0].String()), &circuitStr) + if err != nil { + println(i[0].String()) + println("error parsing circuit from stringified json") + } + circuit, err := utils.CircuitFromString(circuitStr) + if err != nil { + println("error " + err.Error()) + } + sj, err := json.Marshal(circuit) + if err != nil { + println("error " + err.Error()) + } + println("circuit", string(sj)) + + var setupStr utils.GrothSetupString + println(i[1].String()) + err = json.Unmarshal([]byte(i[1].String()), &setupStr) + if err != nil { + println("error parsing setup from stringified json") + } + setup, err := utils.GrothSetupFromString(setupStr) + if err != nil { + println("error " + err.Error()) + } + sj, err = json.Marshal(setup) + if err != nil { + println("error " + err.Error()) + } + println("set", string(sj)) + + var pxStr []string + err = json.Unmarshal([]byte(i[2].String()), &pxStr) + if err != nil { + println("error parsing pxStr from stringified json") + } + px, err := utils.ArrayStringToBigInt(pxStr) + if err != nil { + println(err.Error()) + } + sj, err = json.Marshal(px) + if err != nil { + println("error " + err.Error()) + } + println("px", string(sj)) + + var inputs circuitcompiler.Inputs + err = json.Unmarshal([]byte(i[3].String()), &inputs) + if err != nil { + println("error parsing inputs from stringified json") + } + w, err := circuit.CalculateWitness(inputs.Private, inputs.Public) + + proof, err := groth16.GenerateProofs(circuit, setup, w, px) + if err != nil { + println("error generating proof", err) + } + proofString := utils.GrothProofToString(proof) + proofJson, err := json.Marshal(proofString) + if err != nil { + println("error marshal proof to json", err) + } + println("proofJson", string(proofJson)) + return js.ValueOf(string(proofJson)) +} + +func grothVerifyProofs(this js.Value, i []js.Value) interface{} { + var circuitStr utils.CircuitString + err := json.Unmarshal([]byte(i[0].String()), &circuitStr) + if err != nil { + println(i[0].String()) + println("error parsing circuit from stringified json") + } + circuit, err := utils.CircuitFromString(circuitStr) + if err != nil { + println("error " + err.Error()) + } + + var setupStr utils.GrothSetupString + println(i[1].String()) + err = json.Unmarshal([]byte(i[1].String()), &setupStr) + if err != nil { + println("error parsing setup from stringified json") + } + setup, err := utils.GrothSetupFromString(setupStr) + if err != nil { + println("error " + err.Error()) + } + + var proofStr utils.GrothProofString + err = json.Unmarshal([]byte(i[2].String()), &proofStr) + if err != nil { + println(i[0].String()) + println("error parsing proof from stringified json") + } + proof, err := utils.GrothProofFromString(proofStr) + if err != nil { + println("error " + err.Error()) + } + + var publicInputs []*big.Int + err = json.Unmarshal([]byte(i[3].String()), &publicInputs) + if err != nil { + println(i[0].String()) + println("error parsing publicInputs from stringified json") + } + + verified := groth16.VerifyProof(circuit, setup, proof, publicInputs, false) + if err != nil { + println("error verifiyng proof", err) + } + verifiedJson, err := json.Marshal(verified) + if err != nil { + println("error marshal verified to json", err) + } + println("verifiedJson", string(verifiedJson)) + return js.ValueOf(string(verifiedJson)) +} diff --git a/wasm/go-snark.wasm b/wasm/go-snark.wasm index 9b56560..83d60bd 100755 Binary files a/wasm/go-snark.wasm and b/wasm/go-snark.wasm differ diff --git a/wasm/utils/utils.go b/wasm/utils/utils.go index afe36fb..7c31d81 100644 --- a/wasm/utils/utils.go +++ b/wasm/utils/utils.go @@ -6,6 +6,7 @@ import ( snark "github.com/arnaucube/go-snark" "github.com/arnaucube/go-snark/circuitcompiler" + "github.com/arnaucube/go-snark/groth16" ) // []*big.Int @@ -401,3 +402,163 @@ func ProofFromString(s ProofString) (snark.Proof, error) { } return p, nil } + +// groth +type GrothSetupString struct { + Pk struct { // Proving Key + BACDelta [][3]string + Z []string + G1 struct { + Alpha [3]string + Beta [3]string + Delta [3]string + At [][3]string + BACGamma [][3]string + } + G2 struct { + Beta [3][2]string + Gamma [3][2]string + Delta [3][2]string + BACGamma [][3][2]string + } + PowersTauDelta [][3]string + } + Vk struct { + IC [][3]string + G1 struct { + Alpha [3]string + } + G2 struct { + Beta [3][2]string + Gamma [3][2]string + Delta [3][2]string + } + } +} + +func GrothSetupToString(setup groth16.Setup) GrothSetupString { + var s GrothSetupString + s.Pk.BACDelta = Array3BigIntToString(setup.Pk.BACDelta) + s.Pk.Z = ArrayBigIntToString(setup.Pk.Z) + s.Pk.G1.Alpha = BigInt3ToString(setup.Pk.G1.Alpha) + s.Pk.G1.Beta = BigInt3ToString(setup.Pk.G1.Beta) + s.Pk.G1.Delta = BigInt3ToString(setup.Pk.G1.Delta) + s.Pk.G1.At = Array3BigIntToString(setup.Pk.G1.At) + s.Pk.G1.BACGamma = Array3BigIntToString(setup.Pk.G1.BACGamma) + s.Pk.G2.Beta = BigInt32ToString(setup.Pk.G2.Beta) + s.Pk.G2.Gamma = BigInt32ToString(setup.Pk.G2.Gamma) + s.Pk.G2.Delta = BigInt32ToString(setup.Pk.G2.Delta) + s.Pk.G2.BACGamma = Array32BigIntToString(setup.Pk.G2.BACGamma) + s.Pk.PowersTauDelta = Array3BigIntToString(setup.Pk.PowersTauDelta) + s.Vk.IC = Array3BigIntToString(setup.Vk.IC) + s.Vk.G1.Alpha = BigInt3ToString(setup.Vk.G1.Alpha) + s.Vk.G2.Beta = BigInt32ToString(setup.Vk.G2.Beta) + s.Vk.G2.Gamma = BigInt32ToString(setup.Vk.G2.Gamma) + s.Vk.G2.Delta = BigInt32ToString(setup.Vk.G2.Delta) + return s +} +func GrothSetupFromString(s GrothSetupString) (groth16.Setup, error) { + var o groth16.Setup + var err error + o.Pk.BACDelta, err = Array3StringToBigInt(s.Pk.BACDelta) + if err != nil { + return o, err + } + o.Pk.Z, err = ArrayStringToBigInt(s.Pk.Z) + if err != nil { + return o, err + } + o.Pk.G1.Alpha, err = String3ToBigInt(s.Pk.G1.Alpha) + if err != nil { + return o, err + } + o.Pk.G1.Beta, err = String3ToBigInt(s.Pk.G1.Beta) + if err != nil { + return o, err + } + o.Pk.G1.Delta, err = String3ToBigInt(s.Pk.G1.Delta) + if err != nil { + return o, err + } + o.Pk.G1.At, err = Array3StringToBigInt(s.Pk.G1.At) + if err != nil { + return o, err + } + o.Pk.G1.BACGamma, err = Array3StringToBigInt(s.Pk.G1.BACGamma) + if err != nil { + return o, err + } + o.Pk.G2.Beta, err = String32ToBigInt(s.Pk.G2.Beta) + if err != nil { + return o, err + } + o.Pk.G2.Gamma, err = String32ToBigInt(s.Pk.G2.Gamma) + if err != nil { + return o, err + } + o.Pk.G2.Delta, err = String32ToBigInt(s.Pk.G2.Delta) + if err != nil { + return o, err + } + o.Pk.G2.BACGamma, err = Array32StringToBigInt(s.Pk.G2.BACGamma) + if err != nil { + return o, err + } + o.Pk.PowersTauDelta, err = Array3StringToBigInt(s.Pk.PowersTauDelta) + if err != nil { + return o, err + } + o.Vk.IC, err = Array3StringToBigInt(s.Vk.IC) + if err != nil { + return o, err + } + o.Vk.G1.Alpha, err = String3ToBigInt(s.Vk.G1.Alpha) + if err != nil { + return o, err + } + o.Vk.G2.Beta, err = String32ToBigInt(s.Vk.G2.Beta) + if err != nil { + return o, err + } + o.Vk.G2.Gamma, err = String32ToBigInt(s.Vk.G2.Gamma) + if err != nil { + return o, err + } + o.Vk.G2.Delta, err = String32ToBigInt(s.Vk.G2.Delta) + if err != nil { + return o, err + } + return o, nil +} + +type GrothProofString struct { + PiA [3]string + PiB [3][2]string + PiC [3]string +} + +func GrothProofToString(p groth16.Proof) GrothProofString { + var s GrothProofString + s.PiA = BigInt3ToString(p.PiA) + s.PiB = BigInt32ToString(p.PiB) + s.PiC = BigInt3ToString(p.PiC) + return s +} +func GrothProofFromString(s GrothProofString) (groth16.Proof, error) { + var p groth16.Proof + var err error + + p.PiA, err = String3ToBigInt(s.PiA) + if err != nil { + return p, err + } + p.PiB, err = String32ToBigInt(s.PiB) + if err != nil { + return p, err + } + p.PiC, err = String3ToBigInt(s.PiC) + if err != nil { + return p, err + } + return p, nil +}