diff --git a/README.md b/README.md index be7f939..7fabbb6 100644 --- a/README.md +++ b/README.md @@ -204,6 +204,16 @@ publicSignalsVerif := []*big.Int{b35Verif} assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true)) ``` +##### Verify Proof generated from [snarkjs](https://github.com/iden3/snarkjs) +Is possible with `go-snark` to verify proofs generated by `snarkjs` + +Example: +```go +verified, err := VerifyFromCircom("circom-test/verification_key.json", "circom-test/proof.json", "circom-test/public.json") +assert.Nil(t, err) +assert.True(t, verified) +``` + ## Versions History of versions & tags of this project: diff --git a/cli/main.go b/cli/main.go index 1130d74..e589b77 100644 --- a/cli/main.go +++ b/cli/main.go @@ -15,7 +15,7 @@ import ( "github.com/arnaucube/go-snark/circuitcompiler" "github.com/arnaucube/go-snark/groth16" "github.com/arnaucube/go-snark/r1csqap" - "github.com/arnaucube/go-snark/wasm/utils" + "github.com/arnaucube/go-snark/utils" "github.com/urfave/cli" ) diff --git a/externalVerif/README.md b/externalVerif/README.md new file mode 100644 index 0000000..a75fdc5 --- /dev/null +++ b/externalVerif/README.md @@ -0,0 +1,12 @@ +# go-snark /externalVerif +Utilities to verify zkSNARK proofs generated by other tools. + +## Verify Proof generated from [snarkjs](https://github.com/iden3/snarkjs) +Is possible with `go-snark` to verify proofs generated by `snarkjs` + +Example: +```go +verified, err := VerifyFromCircom("circom-test/verification_key.json", "circom-test/proof.json", "circom-test/public.json") +assert.Nil(t, err) +assert.True(t, verified) +``` diff --git a/externalVerif/circom-test/circuit.circom b/externalVerif/circom-test/circuit.circom new file mode 100644 index 0000000..7546c53 --- /dev/null +++ b/externalVerif/circom-test/circuit.circom @@ -0,0 +1,8 @@ +template Multiplier() { + signal private input a; + signal private input b; + signal output c; + c <== a*b; +} + +component main = Multiplier(); diff --git a/externalVerif/circom-test/circuit.json b/externalVerif/circom-test/circuit.json new file mode 100644 index 0000000..1533a1b --- /dev/null +++ b/externalVerif/circom-test/circuit.json @@ -0,0 +1,74 @@ +{ + "mainCode": "{\n}\n", + "signalName2Idx": { + "one": 0, + "main.a": 2, + "main.b": 3, + "main.c": 1 + }, + "components": [ + { + "name": "main", + "params": {}, + "template": "Multiplier", + "inputSignals": 2 + } + ], + "componentName2Idx": { + "main": 0 + }, + "signals": [ + { + "names": [ + "one" + ], + "triggerComponents": [] + }, + { + "names": [ + "main.c" + ], + "triggerComponents": [] + }, + { + "names": [ + "main.a" + ], + "triggerComponents": [ + 0 + ] + }, + { + "names": [ + "main.b" + ], + "triggerComponents": [ + 0 + ] + } + ], + "constraints": [ + [ + { + "2": "21888242871839275222246405745257275088548364400416034343698204186575808495616" + }, + { + "3": "1" + }, + { + "1": "21888242871839275222246405745257275088548364400416034343698204186575808495616" + } + ] + ], + "templates": { + "Multiplier": "function(ctx) {\n ctx.setSignal(\"c\", [], bigInt(ctx.getSignal(\"a\", [])).mul(bigInt(ctx.getSignal(\"b\", []))).mod(__P__));\n ctx.assert(ctx.getSignal(\"c\", []), bigInt(ctx.getSignal(\"a\", [])).mul(bigInt(ctx.getSignal(\"b\", []))).mod(__P__));\n}\n" + }, + "functions": {}, + "nPrvInputs": 2, + "nPubInputs": 0, + "nInputs": 2, + "nOutputs": 1, + "nVars": 4, + "nConstants": 0, + "nSignals": 4 +} \ No newline at end of file diff --git a/externalVerif/circom-test/input.json b/externalVerif/circom-test/input.json new file mode 100644 index 0000000..c7e0fc6 --- /dev/null +++ b/externalVerif/circom-test/input.json @@ -0,0 +1 @@ +{"a": 3, "b": 11} diff --git a/externalVerif/circom-test/proof.json b/externalVerif/circom-test/proof.json new file mode 100644 index 0000000..4218677 --- /dev/null +++ b/externalVerif/circom-test/proof.json @@ -0,0 +1,27 @@ +{ + "pi_a": [ + "18388960469390566286541775203573681018272060202314500468244373257908579233056", + "7618815753031896296145768956584956596571516464117106968297323458939823682730", + "1" + ], + "pi_b": [ + [ + "17050824088966017765399151386329118398626450147519924253020767437783796544260", + "19912572158122217836152914282050675315049542075120224143747749799495268338155" + ], + [ + "20465264120227255663865054937863503553147947378051666554617444700075602812731", + "18655251778322805691388473632530173510779859979743695956359151230786651584957" + ], + [ + "1", + "0" + ] + ], + "pi_c": [ + "1422784641124790360586256228365363101120672643204565045434023905594849706813", + "8557716062509065082036904136615813135951258906799509331823365499907603810450", + "1" + ], + "protocol": "groth" +} \ No newline at end of file diff --git a/externalVerif/circom-test/proving_key.json b/externalVerif/circom-test/proving_key.json new file mode 100644 index 0000000..3cc4273 --- /dev/null +++ b/externalVerif/circom-test/proving_key.json @@ -0,0 +1,221 @@ +{ + "protocol": "groth", + "nVars": 4, + "nPublic": 1, + "domainBits": 2, + "domainSize": 4, + "polsA": [ + { + "1": "1" + }, + { + "2": "1" + }, + { + "0": "21888242871839275222246405745257275088548364400416034343698204186575808495616" + }, + {} + ], + "polsB": [ + {}, + {}, + {}, + { + "0": "1" + } + ], + "polsC": [ + {}, + { + "0": "21888242871839275222246405745257275088548364400416034343698204186575808495616" + }, + {}, + {} + ], + "A": [ + [ + "16145916318196730299582072104388453231952213805668281741813587224450782397538", + "4434505318477484327659527264104806919103674231447634885054368605283938696207", + "1" + ], + [ + "10618406967550056457559358662746625591602641004174976323307214433994084907915", + "1843236360452735081347085412539192450068665510574800388201121698908391533923", + "1" + ], + [ + "1208972877970123411566574123860641832032384890981476033353526096830198333194", + "777503551507025252294438107100944741641946695980350712141258191590862204805", + "1" + ], + [ + "0", + "1", + "0" + ] + ], + "B1": [ + [ + "0", + "1", + "0" + ], + [ + "0", + "1", + "0" + ], + [ + "0", + "1", + "0" + ], + [ + "1208972877970123411566574123860641832032384890981476033353526096830198333194", + "21110739320332249969951967638156330347054364461317472950547779703054364003778", + "1" + ] + ], + "B2": [ + [ + [ + "0", + "0" + ], + [ + "1", + "0" + ], + [ + "0", + "0" + ] + ], + [ + [ + "0", + "0" + ], + [ + "1", + "0" + ], + [ + "0", + "0" + ] + ], + [ + [ + "0", + "0" + ], + [ + "1", + "0" + ], + [ + "0", + "0" + ] + ], + [ + [ + "9283666785342556550467669770956850930982548182701254051508520248901282197973", + "11369378229277445316894458966429873744779877313900506577160370623273013178252" + ], + [ + "10625777544326349817513295021482494426101347915428005055375725845993157551870", + "21401790227434807639472120486932615400751346915707967674912972446672152512583" + ], + [ + "1", + "0" + ] + ] + ], + "C": [ + null, + null, + [ + "18545397130363256321926549041639729743141431075318462370025152832852939073307", + "2616861286119881509516846668252666108741377487742351180864484963773522850295", + "1" + ], + [ + "2525636894222523143142808451978966577881491159416335121257094078801746645235", + "16535861715720884910945782094658684127457731006848459401043529763859412916301", + "1" + ] + ], + "vk_alfa_1": [ + "16068200068882411629410035093795608526771554471937479213726134794660780102550", + "20501676791339890155108177259376873296876233680064261776170683533526889207340", + "1" + ], + "vk_beta_1": [ + "5365573823291502335794132193185274277974617763863996013954364593194136465016", + "11644349101388223784378896360832586557929271772024496470708905460439243894584", + "1" + ], + "vk_delta_1": [ + "15680151079584844532489259722917096938769907841931133291928746685613811358733", + "16784279394546603697881462850128771845781623009095957214568117820968443242506", + "1" + ], + "vk_beta_2": [ + [ + "13973091636763944887728510851169742544309374663995476311690518173988838518856", + "12903946180439304546475897520537621821375470264150438270817301786763517825250" + ], + [ + "370374369234123593044872519351942112043402224488849374153134091815693350697", + "17423079115073430837335625309232513526393852743032331213038909731579295753224" + ], + [ + "1", + "0" + ] + ], + "vk_delta_2": [ + [ + "1192908377564945353343974763532707545526009748811618581810344379529229172159", + "10373868200341234689659697947697825014338252335089936445608341428888724327154" + ], + [ + "6258644116885726740914814071115026921733331135830050167672544002787860516536", + "2784479362505735918824286514153638713518597314121639212447411360814573899319" + ], + [ + "1", + "0" + ] + ], + "hExps": [ + [ + "1137454402546542017796495169973321459788661791339116580816039119135416491226", + "10581992627412174102808274058339351114019966039682644500297077873241797449624", + "1" + ], + [ + "3253811140290017934039655168718326971539049766532829948316663892796117200680", + "3496418280903365070403555364992889823060908616232765866481366503085657668823", + "1" + ], + [ + "7426424892372059053157891943364774187577620238460342150964457392480230669997", + "14261604113665464620229095737623968407326243628348811684313201927885047569756", + "1" + ], + [ + "14706800931196014592083141709960980909656368788497354451613143286705158867076", + "8321358240716309588423491516494287064322707776658072083979021495463106099808", + "1" + ], + [ + "21560594640856118286219580794351895174554979903538723611152363886530011848778", + "15512645592267656573910252616175869133748229079507420222439452334013754939136", + "1" + ] + ] +} \ No newline at end of file diff --git a/externalVerif/circom-test/public.json b/externalVerif/circom-test/public.json new file mode 100644 index 0000000..bf20309 --- /dev/null +++ b/externalVerif/circom-test/public.json @@ -0,0 +1,3 @@ +[ + "33" +] \ No newline at end of file diff --git a/externalVerif/circom-test/verification_key.json b/externalVerif/circom-test/verification_key.json new file mode 100644 index 0000000..0088c4d --- /dev/null +++ b/externalVerif/circom-test/verification_key.json @@ -0,0 +1,93 @@ +{ + "protocol": "groth", + "nPublic": 1, + "IC": [ + [ + "13238385840837109667936052879696151554096578146827286302729161004449442572510", + "7229895880483697230987627368481585486229758623816305076929725978466335833042", + "1" + ], + [ + "14970768730171390202518134018231251321095352434740566553215758534237407624223", + "11858341424183782282346697815973277820477089967861765360499368718702428507405", + "1" + ] + ], + "vk_alfa_1": [ + "16068200068882411629410035093795608526771554471937479213726134794660780102550", + "20501676791339890155108177259376873296876233680064261776170683533526889207340", + "1" + ], + "vk_beta_2": [ + [ + "13973091636763944887728510851169742544309374663995476311690518173988838518856", + "12903946180439304546475897520537621821375470264150438270817301786763517825250" + ], + [ + "370374369234123593044872519351942112043402224488849374153134091815693350697", + "17423079115073430837335625309232513526393852743032331213038909731579295753224" + ], + [ + "1", + "0" + ] + ], + "vk_gamma_2": [ + [ + "20123714298473938437207866646336289719062614610167653880378271328974655580609", + "13002533616763316572747276872341370962409012236118399865958073576789163874362" + ], + [ + "9275552728819724842865155645402980221399400114914205138826048710506018574007", + "9767402488181356088371101345613657976874749415205606884811092820466492903357" + ], + [ + "1", + "0" + ] + ], + "vk_delta_2": [ + [ + "1192908377564945353343974763532707545526009748811618581810344379529229172159", + "10373868200341234689659697947697825014338252335089936445608341428888724327154" + ], + [ + "6258644116885726740914814071115026921733331135830050167672544002787860516536", + "2784479362505735918824286514153638713518597314121639212447411360814573899319" + ], + [ + "1", + "0" + ] + ], + "vk_alfabeta_12": [ + [ + [ + "5808968930823264229923553886264093087733079723496081749582815497064726636649", + "15704206953123342065158329174314435955575427797267883688615695147218681260603" + ], + [ + "2019376182570496317125733151845779676488434395598091282285101061771413397585", + "5033120379874305142732026662367866621873812132639805141544817513451132976303" + ], + [ + "6413062281604814018100947958938305639421600365853645030429871508055751771332", + "16501101898595852943280641675936242756163761586970222679114350546638012990295" + ] + ], + [ + [ + "7994355756858823685828118366797930607512610071147093396079158087328554257367", + "12608941378902474737301318807093065779176013217938745808277102463837219428790" + ], + [ + "7722352178656099663978033703115542396108273285932660670008724291332590018773", + "18402524427751774707431639562944919677540025075739837574780127622149131456184" + ], + [ + "8237540863924877742345165686185155147152873047203223764861378545202201950314", + "885942718772685438966081900822373900701293300627890502324305030525329921651" + ] + ] + ] +} \ No newline at end of file diff --git a/externalVerif/circom-test/witness.json b/externalVerif/circom-test/witness.json new file mode 100644 index 0000000..81becc6 --- /dev/null +++ b/externalVerif/circom-test/witness.json @@ -0,0 +1,6 @@ +[ + "1", + "33", + "3", + "11" +] \ No newline at end of file diff --git a/externalVerif/circomVerifier.go b/externalVerif/circomVerifier.go new file mode 100644 index 0000000..5e835eb --- /dev/null +++ b/externalVerif/circomVerifier.go @@ -0,0 +1,90 @@ +package externalVerif + +import ( + "encoding/json" + "fmt" + "io/ioutil" + + "github.com/arnaucube/go-snark/groth16" + "github.com/arnaucube/go-snark/utils" +) + +type CircomProof struct { + PiA [3]string `json:"pi_a"` + PiB [3][2]string `json:"pi_b"` + PiC [3]string `json:"pi_c"` +} +type CircomVk struct { + IC [][3]string `json:"IC"` + Alpha1 [3]string `json:"vk_alfa_1"` + Beta2 [3][2]string `json:"vk_beta_2"` + Gamma2 [3][2]string `json:"vk_gamma_2"` + Delta2 [3][2]string `json:"vk_delta_2"` + AlphaBeta12 [2][3][2]string `json:"vk_alpfabeta_12"` // not really used, for the moment in go-snarks calculed in verification time +} + +func VerifyFromCircom(vkPath, proofPath, publicSignalsPath string) (bool, error) { + // open verification_key.json + vkFile, err := ioutil.ReadFile(vkPath) + if err != nil { + return false, err + } + var circomVk CircomVk + json.Unmarshal([]byte(string(vkFile)), &circomVk) + if err != nil { + return false, err + } + + var strVk utils.GrothVkString + strVk.IC = circomVk.IC + strVk.G1.Alpha = circomVk.Alpha1 + strVk.G2.Beta = circomVk.Beta2 + strVk.G2.Gamma = circomVk.Gamma2 + strVk.G2.Delta = circomVk.Delta2 + vk, err := utils.GrothVkFromString(strVk) + if err != nil { + return false, err + } + fmt.Println("vk parsed:", vk) + + // open proof.json + proofsFile, err := ioutil.ReadFile(proofPath) + if err != nil { + return false, err + } + var circomProof CircomProof + json.Unmarshal([]byte(string(proofsFile)), &circomProof) + if err != nil { + return false, err + } + + strProof := utils.GrothProofString{ + PiA: circomProof.PiA, + PiB: circomProof.PiB, + PiC: circomProof.PiC, + } + proof, err := utils.GrothProofFromString(strProof) + if err != nil { + return false, err + } + fmt.Println("proof parsed:", proof) + + // open public.json + publicFile, err := ioutil.ReadFile(publicSignalsPath) + if err != nil { + return false, err + } + var publicStr []string + json.Unmarshal([]byte(string(publicFile)), &publicStr) + if err != nil { + return false, err + } + publicSignals, err := utils.ArrayStringToBigInt(publicStr) + if err != nil { + return false, err + } + fmt.Println("publicSignals parsed:", publicSignals) + + verified := groth16.VerifyProof(vk, proof, publicSignals, true) + return verified, nil +} diff --git a/externalVerif/circomVerifier_test.go b/externalVerif/circomVerifier_test.go new file mode 100644 index 0000000..9872d41 --- /dev/null +++ b/externalVerif/circomVerifier_test.go @@ -0,0 +1,13 @@ +package externalVerif + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestVerifyFromCircom(t *testing.T) { + verified, err := VerifyFromCircom("circom-test/verification_key.json", "circom-test/proof.json", "circom-test/public.json") + assert.Nil(t, err) + assert.True(t, verified) +} diff --git a/wasm/utils/utils.go b/utils/base10parsers.go similarity index 91% rename from wasm/utils/utils.go rename to utils/base10parsers.go index 2fe21f6..06464c4 100644 --- a/wasm/utils/utils.go +++ b/utils/base10parsers.go @@ -398,37 +398,39 @@ func ProofFromString(s ProofString) (snark.Proof, error) { } // 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 +type GrothPkString 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 +} +type GrothVkString struct { + IC [][3]string + G1 struct { + Alpha [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 - } + G2 struct { + Beta [3][2]string + Gamma [3][2]string + Delta [3][2]string } } +type GrothSetupString struct { + Pk GrothPkString + Vk GrothVkString +} func GrothSetupToString(setup groth16.Setup) GrothSetupString { var s GrothSetupString @@ -451,6 +453,31 @@ func GrothSetupToString(setup groth16.Setup) GrothSetupString { s.Vk.G2.Delta = BigInt32ToString(setup.Vk.G2.Delta) return s } +func GrothVkFromString(s GrothVkString) (groth16.Vk, error) { + var vk groth16.Vk + var err error + vk.IC, err = Array3StringToBigInt(s.IC) + if err != nil { + return vk, err + } + vk.G1.Alpha, err = String3ToBigInt(s.G1.Alpha) + if err != nil { + return vk, err + } + vk.G2.Beta, err = String32ToBigInt(s.G2.Beta) + if err != nil { + return vk, err + } + vk.G2.Gamma, err = String32ToBigInt(s.G2.Gamma) + if err != nil { + return vk, err + } + vk.G2.Delta, err = String32ToBigInt(s.G2.Delta) + if err != nil { + return vk, err + } + return vk, nil +} func GrothSetupFromString(s GrothSetupString) (groth16.Setup, error) { var o groth16.Setup var err error diff --git a/utils/hexparsers.go b/utils/hexparsers.go new file mode 100644 index 0000000..848e273 --- /dev/null +++ b/utils/hexparsers.go @@ -0,0 +1,562 @@ +package utils + +import ( + "errors" + "fmt" + "math/big" + + snark "github.com/arnaucube/go-snark" + "github.com/arnaucube/go-snark/circuitcompiler" + "github.com/arnaucube/go-snark/groth16" +) + +// []*big.Int +func ArrayBigIntToHex(b []*big.Int) []string { + var o []string + for i := 0; i < len(b); i++ { + o = append(o, fmt.Sprintf("%x", b[i])) + } + return o +} +func ArrayHexToBigInt(s []string) ([]*big.Int, error) { + var px []*big.Int + for i := 0; i < len(s); i++ { + param, ok := new(big.Int).SetString(s[i], 16) + if !ok { + return nil, errors.New("error parsing px from pxHex") + } + px = append(px, param) + } + return px, nil +} + +// [3]*big.Int +func Hex3ToBigInt(s [3]string) ([3]*big.Int, error) { + var o [3]*big.Int + for i := 0; i < len(s); i++ { + param, ok := new(big.Int).SetString(s[i], 16) + if !ok { + return o, errors.New("error parsing [3]*big.Int from [3]string") + } + o[i] = param + } + return o, nil +} +func BigInt3ToHex(b [3]*big.Int) [3]string { + var o [3]string + o[0] = fmt.Sprintf("%x", b[0]) + o[1] = fmt.Sprintf("%x", b[1]) + o[2] = fmt.Sprintf("%x", b[2]) + return o +} + +// [][3]*big.Int +func Array3HexToBigInt(s [][3]string) ([][3]*big.Int, error) { + var o [][3]*big.Int + for i := 0; i < len(s); i++ { + parsed, err := Hex3ToBigInt(s[i]) + if err != nil { + return o, err + } + o = append(o, parsed) + } + return o, nil +} +func Array3BigIntToHex(b [][3]*big.Int) [][3]string { + var o [][3]string + for i := 0; i < len(b); i++ { + o = append(o, BigInt3ToHex(b[i])) + } + return o +} + +func Hex2ToBigInt(s [2]string) ([2]*big.Int, error) { + var o [2]*big.Int + for i := 0; i < len(s); i++ { + param, ok := new(big.Int).SetString(s[i], 16) + if !ok { + return o, errors.New("error parsing [2]*big.Int from [2]string") + } + o[i] = param + } + return o, nil +} + +// [3][2]*big.Int +func Hex32ToBigInt(s [3][2]string) ([3][2]*big.Int, error) { + var o [3][2]*big.Int + var err error + + o[0], err = Hex2ToBigInt(s[0]) + if err != nil { + return o, err + } + o[1], err = Hex2ToBigInt(s[1]) + if err != nil { + return o, err + } + o[2], err = Hex2ToBigInt(s[2]) + if err != nil { + return o, err + } + return o, nil +} +func BigInt32ToHex(b [3][2]*big.Int) [3][2]string { + var o [3][2]string + o[0][0] = fmt.Sprintf("%x", b[0][0]) + o[0][1] = fmt.Sprintf("%x", b[0][1]) + o[1][0] = fmt.Sprintf("%x", b[1][0]) + o[1][1] = fmt.Sprintf("%x", b[1][1]) + o[2][0] = fmt.Sprintf("%x", b[2][0]) + o[2][1] = fmt.Sprintf("%x", b[2][1]) + return o +} + +// [][3][2]*big.Int +func Array32HexToBigInt(s [][3][2]string) ([][3][2]*big.Int, error) { + var o [][3][2]*big.Int + for i := 0; i < len(s); i++ { + parsed, err := Hex32ToBigInt(s[i]) + if err != nil { + return o, err + } + o = append(o, parsed) + } + return o, nil +} +func Array32BigIntToHex(b [][3][2]*big.Int) [][3][2]string { + var o [][3][2]string + for i := 0; i < len(b); i++ { + o = append(o, BigInt32ToHex(b[i])) + } + return o +} + +// Setup +type PkHex struct { + G1T [][3]string + A [][3]string + B [][3][2]string + C [][3]string + Kp [][3]string + Ap [][3]string + Bp [][3]string + Cp [][3]string + Z []string +} +type VkHex struct { + Vka [3][2]string + Vkb [3]string + Vkc [3][2]string + IC [][3]string + G1Kbg [3]string + G2Kbg [3][2]string + G2Kg [3][2]string + Vkz [3][2]string +} +type SetupHex struct { + Pk PkHex + Vk VkHex +} + +func SetupToHex(setup snark.Setup) SetupHex { + var s SetupHex + s.Pk.G1T = Array3BigIntToHex(setup.Pk.G1T) + s.Pk.A = Array3BigIntToHex(setup.Pk.A) + s.Pk.B = Array32BigIntToHex(setup.Pk.B) + s.Pk.C = Array3BigIntToHex(setup.Pk.C) + s.Pk.Kp = Array3BigIntToHex(setup.Pk.Kp) + s.Pk.Ap = Array3BigIntToHex(setup.Pk.Ap) + s.Pk.Bp = Array3BigIntToHex(setup.Pk.Bp) + s.Pk.Cp = Array3BigIntToHex(setup.Pk.Cp) + s.Pk.Z = ArrayBigIntToHex(setup.Pk.Z) + s.Vk.Vka = BigInt32ToHex(setup.Vk.Vka) + s.Vk.Vkb = BigInt3ToHex(setup.Vk.Vkb) + s.Vk.Vkc = BigInt32ToHex(setup.Vk.Vkc) + s.Vk.IC = Array3BigIntToHex(setup.Vk.IC) + s.Vk.G1Kbg = BigInt3ToHex(setup.Vk.G1Kbg) + s.Vk.G2Kbg = BigInt32ToHex(setup.Vk.G2Kbg) + s.Vk.G2Kg = BigInt32ToHex(setup.Vk.G2Kg) + s.Vk.Vkz = BigInt32ToHex(setup.Vk.Vkz) + return s +} +func SetupFromHex(s SetupHex) (snark.Setup, error) { + var o snark.Setup + var err error + o.Pk.G1T, err = Array3HexToBigInt(s.Pk.G1T) + if err != nil { + return o, err + } + o.Pk.A, err = Array3HexToBigInt(s.Pk.A) + if err != nil { + return o, err + } + o.Pk.B, err = Array32HexToBigInt(s.Pk.B) + if err != nil { + return o, err + } + o.Pk.C, err = Array3HexToBigInt(s.Pk.C) + if err != nil { + return o, err + } + o.Pk.Kp, err = Array3HexToBigInt(s.Pk.Kp) + if err != nil { + return o, err + } + o.Pk.Ap, err = Array3HexToBigInt(s.Pk.Ap) + if err != nil { + return o, err + } + o.Pk.Bp, err = Array3HexToBigInt(s.Pk.Bp) + if err != nil { + return o, err + } + o.Pk.Cp, err = Array3HexToBigInt(s.Pk.Cp) + if err != nil { + return o, err + } + o.Pk.Z, err = ArrayHexToBigInt(s.Pk.Z) + if err != nil { + return o, err + } + + o.Vk.Vka, err = Hex32ToBigInt(s.Vk.Vka) + if err != nil { + return o, err + } + o.Vk.Vkb, err = Hex3ToBigInt(s.Vk.Vkb) + if err != nil { + return o, err + } + o.Vk.Vkc, err = Hex32ToBigInt(s.Vk.Vkc) + if err != nil { + return o, err + } + o.Vk.IC, err = Array3HexToBigInt(s.Vk.IC) + if err != nil { + return o, err + } + o.Vk.G1Kbg, err = Hex3ToBigInt(s.Vk.G1Kbg) + if err != nil { + return o, err + } + o.Vk.G2Kbg, err = Hex32ToBigInt(s.Vk.G2Kbg) + if err != nil { + return o, err + } + o.Vk.G2Kg, err = Hex32ToBigInt(s.Vk.G2Kg) + if err != nil { + return o, err + } + o.Vk.Vkz, err = Hex32ToBigInt(s.Vk.Vkz) + if err != nil { + return o, err + } + + return o, nil + +} + +// circuit +type CircuitHex struct { + NVars int + NPublic int + NSignals int + PrivateInputs []string + PublicInputs []string + Signals []string + Witness []string + Constraints []circuitcompiler.Constraint + R1CS struct { + A [][]string + B [][]string + C [][]string + } +} + +func ArrayArrayBigIntToHex(b [][]*big.Int) [][]string { + var o [][]string + for i := 0; i < len(b); i++ { + o = append(o, ArrayBigIntToHex(b[i])) + } + return o +} +func ArrayArrayHexToBigInt(s [][]string) ([][]*big.Int, error) { + var o [][]*big.Int + for i := 0; i < len(s); i++ { + parsed, err := ArrayHexToBigInt(s[i]) + if err != nil { + return o, err + } + o = append(o, parsed) + } + return o, nil +} +func CircuitToHex(c circuitcompiler.Circuit) CircuitHex { + var cs CircuitHex + cs.NVars = c.NVars + cs.NPublic = c.NPublic + cs.NSignals = c.NSignals + cs.PrivateInputs = c.PrivateInputs + cs.PublicInputs = c.PublicInputs + cs.Signals = c.Signals + cs.Witness = ArrayBigIntToHex(c.Witness) + cs.Constraints = c.Constraints + cs.R1CS.A = ArrayArrayBigIntToHex(c.R1CS.A) + cs.R1CS.B = ArrayArrayBigIntToHex(c.R1CS.B) + cs.R1CS.C = ArrayArrayBigIntToHex(c.R1CS.C) + return cs +} +func CircuitFromHex(cs CircuitHex) (circuitcompiler.Circuit, error) { + var c circuitcompiler.Circuit + var err error + c.NVars = cs.NVars + c.NPublic = cs.NPublic + c.NSignals = cs.NSignals + c.PrivateInputs = cs.PrivateInputs + c.PublicInputs = cs.PublicInputs + c.Signals = cs.Signals + c.Witness, err = ArrayHexToBigInt(cs.Witness) + if err != nil { + return c, err + } + c.Constraints = cs.Constraints + c.R1CS.A, err = ArrayArrayHexToBigInt(cs.R1CS.A) + if err != nil { + return c, err + } + c.R1CS.B, err = ArrayArrayHexToBigInt(cs.R1CS.B) + if err != nil { + return c, err + } + c.R1CS.C, err = ArrayArrayHexToBigInt(cs.R1CS.C) + if err != nil { + return c, err + } + return c, nil +} + +// Proof +type ProofHex struct { + PiA [3]string + PiAp [3]string + PiB [3][2]string + PiBp [3]string + PiC [3]string + PiCp [3]string + PiH [3]string + PiKp [3]string +} + +func ProofToHex(p snark.Proof) ProofHex { + var s ProofHex + s.PiA = BigInt3ToHex(p.PiA) + s.PiAp = BigInt3ToHex(p.PiAp) + s.PiB = BigInt32ToHex(p.PiB) + s.PiBp = BigInt3ToHex(p.PiBp) + s.PiC = BigInt3ToHex(p.PiC) + s.PiCp = BigInt3ToHex(p.PiCp) + s.PiH = BigInt3ToHex(p.PiH) + s.PiKp = BigInt3ToHex(p.PiKp) + return s +} +func ProofFromHex(s ProofHex) (snark.Proof, error) { + var p snark.Proof + var err error + + p.PiA, err = Hex3ToBigInt(s.PiA) + if err != nil { + return p, err + } + p.PiAp, err = Hex3ToBigInt(s.PiAp) + if err != nil { + return p, err + } + p.PiB, err = Hex32ToBigInt(s.PiB) + if err != nil { + return p, err + } + p.PiBp, err = Hex3ToBigInt(s.PiBp) + if err != nil { + return p, err + } + p.PiC, err = Hex3ToBigInt(s.PiC) + if err != nil { + return p, err + } + p.PiCp, err = Hex3ToBigInt(s.PiCp) + if err != nil { + return p, err + } + p.PiH, err = Hex3ToBigInt(s.PiH) + if err != nil { + return p, err + } + p.PiKp, err = Hex3ToBigInt(s.PiKp) + if err != nil { + return p, err + } + return p, nil +} + +// groth +type GrothPkHex 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 +} +type GrothVkHex struct { + IC [][3]string + G1 struct { + Alpha [3]string + } + G2 struct { + Beta [3][2]string + Gamma [3][2]string + Delta [3][2]string + } +} +type GrothSetupHex struct { + Pk GrothPkHex + Vk GrothVkHex +} + +func GrothSetupToHex(setup groth16.Setup) GrothSetupHex { + var s GrothSetupHex + s.Pk.BACDelta = Array3BigIntToHex(setup.Pk.BACDelta) + s.Pk.Z = ArrayBigIntToHex(setup.Pk.Z) + s.Pk.G1.Alpha = BigInt3ToHex(setup.Pk.G1.Alpha) + s.Pk.G1.Beta = BigInt3ToHex(setup.Pk.G1.Beta) + s.Pk.G1.Delta = BigInt3ToHex(setup.Pk.G1.Delta) + s.Pk.G1.At = Array3BigIntToHex(setup.Pk.G1.At) + s.Pk.G1.BACGamma = Array3BigIntToHex(setup.Pk.G1.BACGamma) + s.Pk.G2.Beta = BigInt32ToHex(setup.Pk.G2.Beta) + s.Pk.G2.Gamma = BigInt32ToHex(setup.Pk.G2.Gamma) + s.Pk.G2.Delta = BigInt32ToHex(setup.Pk.G2.Delta) + s.Pk.G2.BACGamma = Array32BigIntToHex(setup.Pk.G2.BACGamma) + s.Pk.PowersTauDelta = Array3BigIntToHex(setup.Pk.PowersTauDelta) + s.Vk.IC = Array3BigIntToHex(setup.Vk.IC) + s.Vk.G1.Alpha = BigInt3ToHex(setup.Vk.G1.Alpha) + s.Vk.G2.Beta = BigInt32ToHex(setup.Vk.G2.Beta) + s.Vk.G2.Gamma = BigInt32ToHex(setup.Vk.G2.Gamma) + s.Vk.G2.Delta = BigInt32ToHex(setup.Vk.G2.Delta) + return s +} +func GrothSetupFromHex(s GrothSetupHex) (groth16.Setup, error) { + var o groth16.Setup + var err error + o.Pk.BACDelta, err = Array3HexToBigInt(s.Pk.BACDelta) + if err != nil { + return o, err + } + o.Pk.Z, err = ArrayHexToBigInt(s.Pk.Z) + if err != nil { + return o, err + } + o.Pk.G1.Alpha, err = Hex3ToBigInt(s.Pk.G1.Alpha) + if err != nil { + return o, err + } + o.Pk.G1.Beta, err = Hex3ToBigInt(s.Pk.G1.Beta) + if err != nil { + return o, err + } + o.Pk.G1.Delta, err = Hex3ToBigInt(s.Pk.G1.Delta) + if err != nil { + return o, err + } + o.Pk.G1.At, err = Array3HexToBigInt(s.Pk.G1.At) + if err != nil { + return o, err + } + o.Pk.G1.BACGamma, err = Array3HexToBigInt(s.Pk.G1.BACGamma) + if err != nil { + return o, err + } + o.Pk.G2.Beta, err = Hex32ToBigInt(s.Pk.G2.Beta) + if err != nil { + return o, err + } + o.Pk.G2.Gamma, err = Hex32ToBigInt(s.Pk.G2.Gamma) + if err != nil { + return o, err + } + o.Pk.G2.Delta, err = Hex32ToBigInt(s.Pk.G2.Delta) + if err != nil { + return o, err + } + o.Pk.G2.BACGamma, err = Array32HexToBigInt(s.Pk.G2.BACGamma) + if err != nil { + return o, err + } + o.Pk.PowersTauDelta, err = Array3HexToBigInt(s.Pk.PowersTauDelta) + if err != nil { + return o, err + } + o.Vk.IC, err = Array3HexToBigInt(s.Vk.IC) + if err != nil { + return o, err + } + o.Vk.G1.Alpha, err = Hex3ToBigInt(s.Vk.G1.Alpha) + if err != nil { + return o, err + } + o.Vk.G2.Beta, err = Hex32ToBigInt(s.Vk.G2.Beta) + if err != nil { + return o, err + } + o.Vk.G2.Gamma, err = Hex32ToBigInt(s.Vk.G2.Gamma) + if err != nil { + return o, err + } + o.Vk.G2.Delta, err = Hex32ToBigInt(s.Vk.G2.Delta) + if err != nil { + return o, err + } + return o, nil +} + +type GrothProofHex struct { + PiA [3]string + PiB [3][2]string + PiC [3]string +} + +func GrothProofToHex(p groth16.Proof) GrothProofHex { + var s GrothProofHex + s.PiA = BigInt3ToHex(p.PiA) + s.PiB = BigInt32ToHex(p.PiB) + s.PiC = BigInt3ToHex(p.PiC) + return s +} +func GrothProofFromHex(s GrothProofHex) (groth16.Proof, error) { + var p groth16.Proof + var err error + + p.PiA, err = Hex3ToBigInt(s.PiA) + if err != nil { + return p, err + } + p.PiB, err = Hex32ToBigInt(s.PiB) + if err != nil { + return p, err + } + p.PiC, err = Hex3ToBigInt(s.PiC) + if err != nil { + return p, err + } + return p, nil +} diff --git a/wasm/go-snark-wasm-wrapper.go b/wasm/go-snark-wasm-wrapper.go index 370fbe4..3b3a76a 100644 --- a/wasm/go-snark-wasm-wrapper.go +++ b/wasm/go-snark-wasm-wrapper.go @@ -8,7 +8,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" + "github.com/arnaucube/go-snark/utils" ) func main() { diff --git a/wasm/go-snark.wasm b/wasm/go-snark.wasm index 8a6c3b5..694f428 100755 Binary files a/wasm/go-snark.wasm and b/wasm/go-snark.wasm differ