- avoid code duplication on cmd - interface for proof systempull/10/head
@ -1,4 +1,4 @@ |
|||
package circuitcompiler |
|||
package circuit |
|||
|
|||
import ( |
|||
"bufio" |
@ -1,4 +1,4 @@ |
|||
package circuitcompiler |
|||
package circuit |
|||
|
|||
import ( |
|||
"bufio" |
@ -0,0 +1,98 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"bytes" |
|||
"fmt" |
|||
"log" |
|||
"math/big" |
|||
"os" |
|||
|
|||
"github.com/urfave/cli" |
|||
|
|||
"github.com/arnaucube/go-snark/circuit" |
|||
"github.com/arnaucube/go-snark/proof" |
|||
"github.com/arnaucube/go-snark/r1csqap" |
|||
) |
|||
|
|||
func compile(context *cli.Context) error { |
|||
circuitPath := context.Args().Get(0) |
|||
|
|||
// load compiled
|
|||
circuitFile, err := os.Open(circuitPath) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
parser := circuit.NewParser(circuitFile) |
|||
cir, err := parser.Parse() |
|||
if err != nil { |
|||
return err |
|||
} |
|||
log.Printf("circuit: %v\n", cir) |
|||
|
|||
// load inputs
|
|||
var inputs circuit.Inputs |
|||
if err := loadFromFile(privateFileName, &inputs.Private); err != nil { |
|||
return err |
|||
} |
|||
if err := loadFromFile(publicFileName, &inputs.Public); err != nil { |
|||
return err |
|||
} |
|||
|
|||
// calculate witness
|
|||
w, err := cir.CalculateWitness(inputs.Private, inputs.Public) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
log.Printf("w: %v\n", w) |
|||
|
|||
// flat code to R1CS
|
|||
a, b, c := cir.GenerateR1CS() |
|||
log.Printf("a: %v\n", a) |
|||
log.Printf("b: %v\n", b) |
|||
log.Printf("c: %v\n", c) |
|||
|
|||
// R1CS to QAP
|
|||
alphas, betas, gammas, zx := proof.Utils.PF.R1CSToQAP(a, b, c) |
|||
log.Printf("alphas: %v\n", alphas) |
|||
log.Printf("betas: %v\n", betas) |
|||
log.Printf("gammas: %v\n", gammas) |
|||
log.Printf("zx: %v\n", zx) |
|||
|
|||
ax, bx, cx, px := proof.Utils.PF.CombinePolynomials(w, alphas, betas, gammas) |
|||
|
|||
hx := proof.Utils.PF.DivisorPolynomial(px, zx) |
|||
|
|||
// hx==px/zx so px==hx*zx
|
|||
// assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx))
|
|||
if !r1csqap.BigArraysEqual(px, proof.Utils.PF.Mul(hx, zx)) { |
|||
return fmt.Errorf("px != hx*zx") |
|||
} |
|||
|
|||
// p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
|
|||
abc := proof.Utils.PF.Sub(proof.Utils.PF.Mul(ax, bx), cx) |
|||
// assert.Equal(t, abc, px)
|
|||
if !r1csqap.BigArraysEqual(abc, px) { |
|||
return fmt.Errorf("abc != px") |
|||
} |
|||
|
|||
hz := proof.Utils.PF.Mul(hx, zx) |
|||
if !r1csqap.BigArraysEqual(abc, hz) { |
|||
return fmt.Errorf("abc != hz") |
|||
} |
|||
// assert.Equal(t, abc, hz)
|
|||
|
|||
div, rem := proof.Utils.PF.Div(px, zx) |
|||
if !r1csqap.BigArraysEqual(hx, div) { |
|||
return fmt.Errorf("hx != div") |
|||
} |
|||
// assert.Equal(t, hx, div)
|
|||
// assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
|
|||
for _, r := range rem { |
|||
if !bytes.Equal(r.Bytes(), big.NewInt(int64(0)).Bytes()) { |
|||
return fmt.Errorf("error:error: px/zx rem not equal to zeros") |
|||
} |
|||
} |
|||
|
|||
// save circuit
|
|||
return saveToFile(compiledFileName, cir) |
|||
} |
@ -0,0 +1,63 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"log" |
|||
|
|||
"github.com/arnaucube/go-snark/circuit" |
|||
"github.com/arnaucube/go-snark/proof" |
|||
"github.com/urfave/cli" |
|||
) |
|||
|
|||
func generate(context *cli.Context) error { |
|||
// load circuit
|
|||
var cir circuit.Circuit |
|||
if err := loadFromFile(compiledFileName, &cir); err != nil { |
|||
return err |
|||
} |
|||
log.Printf("circuit: %v\n", cir) |
|||
|
|||
// load inputs
|
|||
var inputs circuit.Inputs |
|||
if err := loadFromFile(privateFileName, &inputs.Private); err != nil { |
|||
return err |
|||
} |
|||
if err := loadFromFile(publicFileName, &inputs.Public); err != nil { |
|||
return err |
|||
} |
|||
|
|||
// calculate witness
|
|||
w, err := cir.CalculateWitness(inputs.Private, inputs.Public) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
log.Printf("w: %v\n", w) |
|||
|
|||
// load setup
|
|||
setup, err := newSetup() |
|||
if err != nil { |
|||
return err |
|||
} |
|||
if err := loadFromFile(setupFileName, setup); err != nil { |
|||
return err |
|||
} |
|||
log.Printf("setup: %v\n", setup) |
|||
|
|||
// R1CS to QAP
|
|||
alphas, betas, gammas, _ := proof.Utils.PF.R1CSToQAP( |
|||
cir.R1CS.A, |
|||
cir.R1CS.B, |
|||
cir.R1CS.C) |
|||
_, _, _, px := proof.Utils.PF.CombinePolynomials(w, alphas, betas, gammas) |
|||
hx := proof.Utils.PF.DivisorPolynomial(px, setup.Z()) |
|||
log.Printf("hx: %v\n", hx) |
|||
|
|||
// generate proof
|
|||
proof, err := setup.Generate(cir, w, px) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
log.Printf("proof: %v\n", proof) |
|||
|
|||
// save proof
|
|||
return saveToFile(proofFileName, proof) |
|||
} |
@ -0,0 +1,45 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"bytes" |
|||
"encoding/json" |
|||
"io" |
|||
"os" |
|||
) |
|||
|
|||
func loadFromReader(r io.Reader, obj interface{}) error { |
|||
buf := new(bytes.Buffer) |
|||
if _, err := buf.ReadFrom(r); err != nil { |
|||
return err |
|||
} |
|||
return json.Unmarshal(buf.Bytes(), obj) |
|||
} |
|||
|
|||
func loadFromFile(path string, obj interface{}) error { |
|||
f, err := os.Open(path) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
defer f.Close() |
|||
return loadFromReader(f, obj) |
|||
} |
|||
|
|||
func saveToWriter(w io.Writer, obj interface{}) error { |
|||
b, err := json.MarshalIndent(obj, "", " ") |
|||
if err != nil { |
|||
return err |
|||
} |
|||
if _, err := w.Write(b); err != nil { |
|||
return err |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func saveToFile(path string, obj interface{}) error { |
|||
f, err := os.Create(path) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
defer f.Close() |
|||
return saveToWriter(f, obj) |
|||
} |
@ -1,509 +1,106 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"bufio" |
|||
"bytes" |
|||
"encoding/json" |
|||
"errors" |
|||
"fmt" |
|||
"io/ioutil" |
|||
"log" |
|||
"math/big" |
|||
"os" |
|||
|
|||
snark "github.com/arnaucube/go-snark" |
|||
"github.com/arnaucube/go-snark/circuitcompiler" |
|||
"github.com/arnaucube/go-snark/groth16" |
|||
"github.com/arnaucube/go-snark/r1csqap" |
|||
"github.com/urfave/cli" |
|||
|
|||
"github.com/arnaucube/go-snark/proof" |
|||
) |
|||
|
|||
func panicErr(err error) { |
|||
if err != nil { |
|||
panic(err) |
|||
} |
|||
} |
|||
const ( |
|||
compiledFileName = "compiled.json" |
|||
setupFileName = "setup.json" |
|||
privateFileName = "private.json" |
|||
publicFileName = "public.json" |
|||
proofFileName = "proof.json" |
|||
) |
|||
|
|||
const ( |
|||
proofSystemPinocchio = iota |
|||
proofSystemGroth16 |
|||
) |
|||
|
|||
var proofSystem int |
|||
|
|||
var commands = []cli.Command{ |
|||
{ |
|||
Name: "compile", |
|||
Aliases: []string{}, |
|||
Usage: "compile a circuit", |
|||
Action: CompileCircuit, |
|||
Action: compile, |
|||
}, |
|||
{ |
|||
Name: "trustedsetup", |
|||
Name: "setup", |
|||
Aliases: []string{}, |
|||
Usage: "generate trusted setup for a circuit", |
|||
Action: TrustedSetup, |
|||
Action: setup, |
|||
}, |
|||
{ |
|||
Name: "genproofs", |
|||
Name: "generate", |
|||
Aliases: []string{}, |
|||
Usage: "generate the snark proofs", |
|||
Action: GenerateProofs, |
|||
Action: generate, |
|||
}, |
|||
{ |
|||
Name: "verify", |
|||
Aliases: []string{}, |
|||
Usage: "verify the snark proofs", |
|||
Action: VerifyProofs, |
|||
}, |
|||
{ |
|||
Name: "groth16", |
|||
Aliases: []string{}, |
|||
Usage: "use groth16 protocol", |
|||
Subcommands: []cli.Command{ |
|||
{ |
|||
Name: "trustedsetup", |
|||
Aliases: []string{}, |
|||
Usage: "generate trusted setup for a circuit", |
|||
Action: Groth16TrustedSetup, |
|||
}, |
|||
{ |
|||
Name: "genproofs", |
|||
Aliases: []string{}, |
|||
Usage: "generate the snark proofs", |
|||
Action: Groth16GenerateProofs, |
|||
}, |
|||
{ |
|||
Name: "verify", |
|||
Aliases: []string{}, |
|||
Usage: "verify the snark proofs", |
|||
Action: Groth16VerifyProofs, |
|||
}, |
|||
}, |
|||
Action: verify, |
|||
}, |
|||
} |
|||
|
|||
func main() { |
|||
app := cli.NewApp() |
|||
app.Name = "go-snarks-cli" |
|||
app.Version = "0.0.3-alpha" |
|||
app.Flags = []cli.Flag{ |
|||
cli.StringFlag{Name: "config"}, |
|||
} |
|||
app.Commands = commands |
|||
|
|||
err := app.Run(os.Args) |
|||
if err != nil { |
|||
log.Fatal(err) |
|||
} |
|||
} |
|||
|
|||
func CompileCircuit(context *cli.Context) error { |
|||
fmt.Println("cli") |
|||
|
|||
circuitPath := context.Args().Get(0) |
|||
|
|||
// read circuit file
|
|||
circuitFile, err := os.Open(circuitPath) |
|||
panicErr(err) |
|||
|
|||
// parse circuit code
|
|||
parser := circuitcompiler.NewParser(bufio.NewReader(circuitFile)) |
|||
circuit, err := parser.Parse() |
|||
panicErr(err) |
|||
fmt.Println("\ncircuit data:", circuit) |
|||
|
|||
// read privateInputs file
|
|||
privateInputsFile, err := ioutil.ReadFile("privateInputs.json") |
|||
panicErr(err) |
|||
// read publicInputs file
|
|||
publicInputsFile, err := ioutil.ReadFile("publicInputs.json") |
|||
panicErr(err) |
|||
|
|||
// parse inputs from inputsFile
|
|||
var inputs circuitcompiler.Inputs |
|||
err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private) |
|||
panicErr(err) |
|||
err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public) |
|||
panicErr(err) |
|||
|
|||
// calculate wittness
|
|||
w, err := circuit.CalculateWitness(inputs.Private, inputs.Public) |
|||
panicErr(err) |
|||
fmt.Println("\nwitness", w) |
|||
|
|||
// flat code to R1CS
|
|||
fmt.Println("\ngenerating R1CS from flat code") |
|||
a, b, c := circuit.GenerateR1CS() |
|||
fmt.Println("\nR1CS:") |
|||
fmt.Println("a:", a) |
|||
fmt.Println("b:", b) |
|||
fmt.Println("c:", c) |
|||
|
|||
// R1CS to QAP
|
|||
alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c) |
|||
fmt.Println("qap") |
|||
fmt.Println(alphas) |
|||
fmt.Println(betas) |
|||
fmt.Println(gammas) |
|||
|
|||
ax, bx, cx, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas) |
|||
|
|||
hx := snark.Utils.PF.DivisorPolynomial(px, zx) |
|||
|
|||
// hx==px/zx so px==hx*zx
|
|||
// assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx))
|
|||
if !r1csqap.BigArraysEqual(px, snark.Utils.PF.Mul(hx, zx)) { |
|||
panic(errors.New("px != hx*zx")) |
|||
} |
|||
|
|||
// p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
|
|||
abc := snark.Utils.PF.Sub(snark.Utils.PF.Mul(ax, bx), cx) |
|||
// assert.Equal(t, abc, px)
|
|||
if !r1csqap.BigArraysEqual(abc, px) { |
|||
panic(errors.New("abc != px")) |
|||
} |
|||
hz := snark.Utils.PF.Mul(hx, zx) |
|||
if !r1csqap.BigArraysEqual(abc, hz) { |
|||
panic(errors.New("abc != hz")) |
|||
} |
|||
// assert.Equal(t, abc, hz)
|
|||
|
|||
div, rem := snark.Utils.PF.Div(px, zx) |
|||
if !r1csqap.BigArraysEqual(hx, div) { |
|||
panic(errors.New("hx != div")) |
|||
func initProofSystem() error { |
|||
switch p := os.Getenv("PROOF_SYSTEM"); p { |
|||
case "", "PINOCCHIO": |
|||
proofSystem = proofSystemPinocchio |
|||
case "GROTH16": |
|||
proofSystem = proofSystemGroth16 |
|||
default: |
|||
return fmt.Errorf("proof system not supported: %v", p) |
|||
} |
|||
// assert.Equal(t, hx, div)
|
|||
// assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
|
|||
for _, r := range rem { |
|||
if !bytes.Equal(r.Bytes(), big.NewInt(int64(0)).Bytes()) { |
|||
panic(errors.New("error:error: px/zx rem not equal to zeros")) |
|||
} |
|||
} |
|||
|
|||
// store circuit to json
|
|||
jsonData, err := json.Marshal(circuit) |
|||
panicErr(err) |
|||
// store setup into file
|
|||
jsonFile, err := os.Create("compiledcircuit.json") |
|||
panicErr(err) |
|||
defer jsonFile.Close() |
|||
jsonFile.Write(jsonData) |
|||
jsonFile.Close() |
|||
fmt.Println("Compiled Circuit data written to ", jsonFile.Name()) |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func TrustedSetup(context *cli.Context) error { |
|||
// open compiledcircuit.json
|
|||
compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json") |
|||
panicErr(err) |
|||
var circuit circuitcompiler.Circuit |
|||
json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit) |
|||
panicErr(err) |
|||
|
|||
// read privateInputs file
|
|||
privateInputsFile, err := ioutil.ReadFile("privateInputs.json") |
|||
panicErr(err) |
|||
// read publicInputs file
|
|||
publicInputsFile, err := ioutil.ReadFile("publicInputs.json") |
|||
panicErr(err) |
|||
|
|||
// parse inputs from inputsFile
|
|||
var inputs circuitcompiler.Inputs |
|||
err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private) |
|||
panicErr(err) |
|||
err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public) |
|||
panicErr(err) |
|||
|
|||
// calculate wittness
|
|||
w, err := circuit.CalculateWitness(inputs.Private, inputs.Public) |
|||
panicErr(err) |
|||
|
|||
// R1CS to QAP
|
|||
alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C) |
|||
fmt.Println("qap") |
|||
fmt.Println(alphas) |
|||
fmt.Println(betas) |
|||
fmt.Println(gammas) |
|||
|
|||
// calculate trusted setup
|
|||
setup, err := snark.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas) |
|||
panicErr(err) |
|||
fmt.Println("\nt:", setup.Toxic.T) |
|||
|
|||
// remove setup.Toxic
|
|||
var tsetup snark.Setup |
|||
tsetup.Pk = setup.Pk |
|||
tsetup.Vk = setup.Vk |
|||
tsetup.G1T = setup.G1T |
|||
tsetup.G2T = setup.G2T |
|||
|
|||
// store setup to json
|
|||
jsonData, err := json.Marshal(tsetup) |
|||
panicErr(err) |
|||
// store setup into file
|
|||
jsonFile, err := os.Create("trustedsetup.json") |
|||
panicErr(err) |
|||
defer jsonFile.Close() |
|||
jsonFile.Write(jsonData) |
|||
jsonFile.Close() |
|||
fmt.Println("Trusted Setup data written to ", jsonFile.Name()) |
|||
return nil |
|||
} |
|||
|
|||
func GenerateProofs(context *cli.Context) error { |
|||
// open compiledcircuit.json
|
|||
compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json") |
|||
panicErr(err) |
|||
var circuit circuitcompiler.Circuit |
|||
json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit) |
|||
panicErr(err) |
|||
|
|||
// open trustedsetup.json
|
|||
trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json") |
|||
panicErr(err) |
|||
var trustedsetup snark.Setup |
|||
json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup) |
|||
panicErr(err) |
|||
|
|||
// read privateInputs file
|
|||
privateInputsFile, err := ioutil.ReadFile("privateInputs.json") |
|||
panicErr(err) |
|||
// read publicInputs file
|
|||
publicInputsFile, err := ioutil.ReadFile("publicInputs.json") |
|||
panicErr(err) |
|||
// parse inputs from inputsFile
|
|||
var inputs circuitcompiler.Inputs |
|||
err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private) |
|||
panicErr(err) |
|||
err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public) |
|||
panicErr(err) |
|||
|
|||
// calculate wittness
|
|||
w, err := circuit.CalculateWitness(inputs.Private, inputs.Public) |
|||
panicErr(err) |
|||
fmt.Println("witness", w) |
|||
|
|||
// flat code to R1CS
|
|||
a := circuit.R1CS.A |
|||
b := circuit.R1CS.B |
|||
c := circuit.R1CS.C |
|||
// R1CS to QAP
|
|||
alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(a, b, c) |
|||
_, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas) |
|||
hx := snark.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z) |
|||
|
|||
fmt.Println(circuit) |
|||
fmt.Println(trustedsetup.G1T) |
|||
fmt.Println(hx) |
|||
fmt.Println(w) |
|||
proof, err := snark.GenerateProofs(circuit, trustedsetup, w, px) |
|||
panicErr(err) |
|||
|
|||
fmt.Println("\n proofs:") |
|||
fmt.Println(proof) |
|||
|
|||
// store proofs to json
|
|||
jsonData, err := json.Marshal(proof) |
|||
panicErr(err) |
|||
// store proof into file
|
|||
jsonFile, err := os.Create("proofs.json") |
|||
panicErr(err) |
|||
defer jsonFile.Close() |
|||
jsonFile.Write(jsonData) |
|||
jsonFile.Close() |
|||
fmt.Println("Proofs data written to ", jsonFile.Name()) |
|||
return nil |
|||
} |
|||
|
|||
func VerifyProofs(context *cli.Context) error { |
|||
// open proofs.json
|
|||
proofsFile, err := ioutil.ReadFile("proofs.json") |
|||
panicErr(err) |
|||
var proof snark.Proof |
|||
json.Unmarshal([]byte(string(proofsFile)), &proof) |
|||
panicErr(err) |
|||
|
|||
// open compiledcircuit.json
|
|||
compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json") |
|||
panicErr(err) |
|||
var circuit circuitcompiler.Circuit |
|||
json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit) |
|||
panicErr(err) |
|||
|
|||
// open trustedsetup.json
|
|||
trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json") |
|||
panicErr(err) |
|||
var trustedsetup snark.Setup |
|||
json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup) |
|||
panicErr(err) |
|||
|
|||
// read publicInputs file
|
|||
publicInputsFile, err := ioutil.ReadFile("publicInputs.json") |
|||
panicErr(err) |
|||
var publicSignals []*big.Int |
|||
err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals) |
|||
panicErr(err) |
|||
|
|||
verified := snark.VerifyProof(circuit, trustedsetup, proof, publicSignals, true) |
|||
if !verified { |
|||
fmt.Println("ERROR: proofs not verified") |
|||
} else { |
|||
fmt.Println("Proofs verified") |
|||
func newSetup() (proof.Setup, error) { |
|||
var s proof.Setup |
|||
switch proofSystem { |
|||
case proofSystemPinocchio: |
|||
s = &proof.PinocchioSetup{} |
|||
case proofSystemGroth16: |
|||
s = &proof.Groth16Setup{} |
|||
default: |
|||
return nil, fmt.Errorf("proof system not supported: %v", proofSystem) |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func Groth16TrustedSetup(context *cli.Context) error { |
|||
// open compiledcircuit.json
|
|||
compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json") |
|||
panicErr(err) |
|||
var circuit circuitcompiler.Circuit |
|||
json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit) |
|||
panicErr(err) |
|||
|
|||
// read privateInputs file
|
|||
privateInputsFile, err := ioutil.ReadFile("privateInputs.json") |
|||
panicErr(err) |
|||
// read publicInputs file
|
|||
publicInputsFile, err := ioutil.ReadFile("publicInputs.json") |
|||
panicErr(err) |
|||
|
|||
// parse inputs from inputsFile
|
|||
var inputs circuitcompiler.Inputs |
|||
err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private) |
|||
panicErr(err) |
|||
err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public) |
|||
panicErr(err) |
|||
|
|||
// calculate wittness
|
|||
w, err := circuit.CalculateWitness(inputs.Private, inputs.Public) |
|||
panicErr(err) |
|||
|
|||
// R1CS to QAP
|
|||
alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C) |
|||
fmt.Println("qap") |
|||
fmt.Println(alphas) |
|||
fmt.Println(betas) |
|||
fmt.Println(gammas) |
|||
|
|||
// calculate trusted setup
|
|||
setup, err := groth16.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas) |
|||
panicErr(err) |
|||
fmt.Println("\nt:", setup.Toxic.T) |
|||
|
|||
// remove setup.Toxic
|
|||
var tsetup groth16.Setup |
|||
tsetup.Pk = setup.Pk |
|||
tsetup.Vk = setup.Vk |
|||
|
|||
// store setup to json
|
|||
jsonData, err := json.Marshal(tsetup) |
|||
panicErr(err) |
|||
// store setup into file
|
|||
jsonFile, err := os.Create("trustedsetup.json") |
|||
panicErr(err) |
|||
defer jsonFile.Close() |
|||
jsonFile.Write(jsonData) |
|||
jsonFile.Close() |
|||
fmt.Println("Trusted Setup data written to ", jsonFile.Name()) |
|||
return nil |
|||
return s, nil |
|||
} |
|||
|
|||
func Groth16GenerateProofs(context *cli.Context) error { |
|||
// open compiledcircuit.json
|
|||
compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json") |
|||
panicErr(err) |
|||
var circuit circuitcompiler.Circuit |
|||
json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit) |
|||
panicErr(err) |
|||
|
|||
// open trustedsetup.json
|
|||
trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json") |
|||
panicErr(err) |
|||
var trustedsetup groth16.Setup |
|||
json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup) |
|||
panicErr(err) |
|||
|
|||
// read privateInputs file
|
|||
privateInputsFile, err := ioutil.ReadFile("privateInputs.json") |
|||
panicErr(err) |
|||
// read publicInputs file
|
|||
publicInputsFile, err := ioutil.ReadFile("publicInputs.json") |
|||
panicErr(err) |
|||
// parse inputs from inputsFile
|
|||
var inputs circuitcompiler.Inputs |
|||
err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private) |
|||
panicErr(err) |
|||
err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public) |
|||
panicErr(err) |
|||
|
|||
// calculate wittness
|
|||
w, err := circuit.CalculateWitness(inputs.Private, inputs.Public) |
|||
panicErr(err) |
|||
fmt.Println("witness", w) |
|||
|
|||
// flat code to R1CS
|
|||
a := circuit.R1CS.A |
|||
b := circuit.R1CS.B |
|||
c := circuit.R1CS.C |
|||
// R1CS to QAP
|
|||
alphas, betas, gammas, _ := groth16.Utils.PF.R1CSToQAP(a, b, c) |
|||
_, _, _, px := groth16.Utils.PF.CombinePolynomials(w, alphas, betas, gammas) |
|||
hx := groth16.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z) |
|||
|
|||
fmt.Println(circuit) |
|||
fmt.Println(trustedsetup.Pk.PowersTauDelta) |
|||
fmt.Println(hx) |
|||
fmt.Println(w) |
|||
proof, err := groth16.GenerateProofs(circuit, trustedsetup, w, px) |
|||
panicErr(err) |
|||
|
|||
fmt.Println("\n proofs:") |
|||
fmt.Println(proof) |
|||
|
|||
// store proofs to json
|
|||
jsonData, err := json.Marshal(proof) |
|||
panicErr(err) |
|||
// store proof into file
|
|||
jsonFile, err := os.Create("proofs.json") |
|||
panicErr(err) |
|||
defer jsonFile.Close() |
|||
jsonFile.Write(jsonData) |
|||
jsonFile.Close() |
|||
fmt.Println("Proofs data written to ", jsonFile.Name()) |
|||
return nil |
|||
func newProof() (proof.Proof, error) { |
|||
var p proof.Proof |
|||
switch proofSystem { |
|||
case proofSystemPinocchio: |
|||
p = &proof.PinocchioProof{} |
|||
case proofSystemGroth16: |
|||
p = &proof.Groth16Proof{} |
|||
default: |
|||
return nil, fmt.Errorf("proof system not supported: %v", proofSystem) |
|||
} |
|||
return p, nil |
|||
} |
|||
|
|||
func Groth16VerifyProofs(context *cli.Context) error { |
|||
// open proofs.json
|
|||
proofsFile, err := ioutil.ReadFile("proofs.json") |
|||
panicErr(err) |
|||
var proof groth16.Proof |
|||
json.Unmarshal([]byte(string(proofsFile)), &proof) |
|||
panicErr(err) |
|||
|
|||
// open compiledcircuit.json
|
|||
compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json") |
|||
panicErr(err) |
|||
var circuit circuitcompiler.Circuit |
|||
json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit) |
|||
panicErr(err) |
|||
|
|||
// open trustedsetup.json
|
|||
trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json") |
|||
panicErr(err) |
|||
var trustedsetup groth16.Setup |
|||
json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup) |
|||
panicErr(err) |
|||
|
|||
// read publicInputs file
|
|||
publicInputsFile, err := ioutil.ReadFile("publicInputs.json") |
|||
panicErr(err) |
|||
var publicSignals []*big.Int |
|||
err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals) |
|||
panicErr(err) |
|||
|
|||
verified := groth16.VerifyProof(circuit, trustedsetup, proof, publicSignals, true) |
|||
if !verified { |
|||
fmt.Println("ERROR: proofs not verified") |
|||
} else { |
|||
fmt.Println("Proofs verified") |
|||
func main() { |
|||
if err := initProofSystem(); err != nil { |
|||
panic(err) |
|||
} |
|||
app := cli.NewApp() |
|||
app.Name = "go-snark" |
|||
app.Version = "0.0.3-alpha" |
|||
app.Flags = []cli.Flag{ |
|||
cli.StringFlag{Name: "config"}, |
|||
} |
|||
app.Commands = commands |
|||
if err := app.Run(os.Args); err != nil { |
|||
panic(err) |
|||
} |
|||
return nil |
|||
} |
@ -0,0 +1,53 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"log" |
|||
|
|||
"github.com/arnaucube/go-snark/circuit" |
|||
"github.com/arnaucube/go-snark/proof" |
|||
"github.com/urfave/cli" |
|||
) |
|||
|
|||
func setup(context *cli.Context) error { |
|||
// load circuit
|
|||
var cir circuit.Circuit |
|||
if err := loadFromFile(compiledFileName, &cir); err != nil { |
|||
return err |
|||
} |
|||
log.Printf("circuit: %v\n", cir) |
|||
|
|||
// load inputs
|
|||
var inputs circuit.Inputs |
|||
if err := loadFromFile(privateFileName, &inputs.Private); err != nil { |
|||
return err |
|||
} |
|||
if err := loadFromFile(publicFileName, &inputs.Public); err != nil { |
|||
return err |
|||
} |
|||
|
|||
// calculate witness
|
|||
w, err := cir.CalculateWitness(inputs.Private, inputs.Public) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
log.Printf("w: %v\n", w) |
|||
|
|||
// R1CS to QAP
|
|||
alphas, betas, gammas, _ := proof.Utils.PF.R1CSToQAP( |
|||
cir.R1CS.A, |
|||
cir.R1CS.B, |
|||
cir.R1CS.C) |
|||
|
|||
// calculate trusted setup
|
|||
setup, err := newSetup() |
|||
if err != nil { |
|||
return err |
|||
} |
|||
if err := setup.Init(len(w), cir, alphas, betas, gammas); err != nil { |
|||
return err |
|||
} |
|||
log.Printf("setup: %v\n", setup) |
|||
|
|||
// save setup
|
|||
return saveToFile(setupFileName, setup) |
|||
} |
@ -0,0 +1,50 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"fmt" |
|||
"log" |
|||
|
|||
"github.com/arnaucube/go-snark/circuit" |
|||
"github.com/urfave/cli" |
|||
) |
|||
|
|||
func verify(context *cli.Context) error { |
|||
// load circuit
|
|||
var cir circuit.Circuit |
|||
if err := loadFromFile(compiledFileName, &cir); err != nil { |
|||
return err |
|||
} |
|||
log.Printf("circuit: %v\n", cir) |
|||
|
|||
// load inputs
|
|||
var inputs circuit.Inputs |
|||
if err := loadFromFile(publicFileName, &inputs.Public); err != nil { |
|||
return err |
|||
} |
|||
|
|||
// load setup
|
|||
setup, err := newSetup() |
|||
if err != nil { |
|||
return err |
|||
} |
|||
if err := loadFromFile(setupFileName, setup); err != nil { |
|||
return err |
|||
} |
|||
log.Printf("setup: %v\n", setup) |
|||
|
|||
// load proof
|
|||
proof, err := newProof() |
|||
if err != nil { |
|||
return err |
|||
} |
|||
if err := loadFromFile(proofFileName, proof); err != nil { |
|||
return err |
|||
} |
|||
|
|||
// verify proof
|
|||
if ok := setup.Verify(cir, proof, inputs.Public, true); !ok { |
|||
return fmt.Errorf("verif KO") |
|||
} |
|||
log.Printf("verif OK\n") |
|||
return nil |
|||
} |
@ -0,0 +1,47 @@ |
|||
package proof |
|||
|
|||
import ( |
|||
"math/big" |
|||
|
|||
"github.com/arnaucube/go-snark/bn128" |
|||
"github.com/arnaucube/go-snark/circuit" |
|||
"github.com/arnaucube/go-snark/fields" |
|||
"github.com/arnaucube/go-snark/r1csqap" |
|||
) |
|||
|
|||
type utils struct { |
|||
Bn bn128.Bn128 |
|||
FqR fields.Fq |
|||
PF r1csqap.PolynomialField |
|||
} |
|||
|
|||
// Utils is the data structure holding the BN128, FqR Finite Field over R, PolynomialField, that will be used inside the snarks operations
|
|||
var Utils = prepareUtils() |
|||
|
|||
func prepareUtils() utils { |
|||
bn, err := bn128.NewBn128() |
|||
if err != nil { |
|||
panic(err) |
|||
} |
|||
// new Finite Field
|
|||
fqR := fields.NewFq(bn.R) |
|||
// new Polynomial Field
|
|||
pf := r1csqap.NewPolynomialField(fqR) |
|||
|
|||
return utils{ |
|||
Bn: bn, |
|||
FqR: fqR, |
|||
PF: pf, |
|||
} |
|||
} |
|||
|
|||
// Proof is
|
|||
type Proof interface{} |
|||
|
|||
// Setup is
|
|||
type Setup interface { |
|||
Z() []*big.Int |
|||
Init(witnessLength int, circuit circuit.Circuit, alphas, betas, gammas [][]*big.Int) error |
|||
Generate(circuit circuit.Circuit, w []*big.Int, px []*big.Int) (Proof, error) |
|||
Verify(circuit circuit.Circuit, proof Proof, publicSignals []*big.Int, debug bool) bool |
|||
} |
@ -1,185 +0,0 @@ |
|||
package r1csqapFloat |
|||
|
|||
import "math/big" |
|||
|
|||
func Transpose(matrix [][]*big.Float) [][]*big.Float { |
|||
var r [][]*big.Float |
|||
for i := 0; i < len(matrix[0]); i++ { |
|||
var row []*big.Float |
|||
for j := 0; j < len(matrix); j++ { |
|||
row = append(row, matrix[j][i]) |
|||
} |
|||
r = append(r, row) |
|||
} |
|||
return r |
|||
} |
|||
|
|||
func ArrayOfBigZeros(num int) []*big.Float { |
|||
bigZero := big.NewFloat(float64(0)) |
|||
var r []*big.Float |
|||
for i := 0; i < num; i++ { |
|||
r = append(r, bigZero) |
|||
} |
|||
return r |
|||
} |
|||
|
|||
func PolMul(a, b []*big.Float) []*big.Float { |
|||
r := ArrayOfBigZeros(len(a) + len(b) - 1) |
|||
for i := 0; i < len(a); i++ { |
|||
for j := 0; j < len(b); j++ { |
|||
r[i+j] = new(big.Float).Add( |
|||
r[i+j], |
|||
new(big.Float).Mul(a[i], b[j])) |
|||
} |
|||
} |
|||
return r |
|||
} |
|||
|
|||
func PolDiv(a, b []*big.Float) ([]*big.Float, []*big.Float) { |
|||
// https://en.wikipedia.org/wiki/Division_algorithm
|
|||
r := ArrayOfBigZeros(len(a) - len(b) + 1) |
|||
rem := a |
|||
for len(rem) >= len(b) { |
|||
l := new(big.Float).Quo(rem[len(rem)-1], b[len(b)-1]) |
|||
pos := len(rem) - len(b) |
|||
r[pos] = l |
|||
aux := ArrayOfBigZeros(pos) |
|||
aux1 := append(aux, l) |
|||
aux2 := PolSub(rem, PolMul(b, aux1)) |
|||
rem = aux2[:len(aux2)-1] |
|||
} |
|||
return r, rem |
|||
} |
|||
|
|||
func max(a, b int) int { |
|||
if a > b { |
|||
return a |
|||
} |
|||
return b |
|||
} |
|||
|
|||
func PolAdd(a, b []*big.Float) []*big.Float { |
|||
r := ArrayOfBigZeros(max(len(a), len(b))) |
|||
for i := 0; i < len(a); i++ { |
|||
r[i] = new(big.Float).Add(r[i], a[i]) |
|||
} |
|||
for i := 0; i < len(b); i++ { |
|||
r[i] = new(big.Float).Add(r[i], b[i]) |
|||
} |
|||
return r |
|||
} |
|||
|
|||
func PolSub(a, b []*big.Float) []*big.Float { |
|||
r := ArrayOfBigZeros(max(len(a), len(b))) |
|||
for i := 0; i < len(a); i++ { |
|||
r[i] = new(big.Float).Add(r[i], a[i]) |
|||
} |
|||
for i := 0; i < len(b); i++ { |
|||
bneg := new(big.Float).Mul(b[i], big.NewFloat(float64(-1))) |
|||
r[i] = new(big.Float).Add(r[i], bneg) |
|||
} |
|||
return r |
|||
|
|||
} |
|||
|
|||
func FloatPow(a *big.Float, e int) *big.Float { |
|||
if e == 0 { |
|||
return big.NewFloat(float64(1)) |
|||
} |
|||
result := new(big.Float).Copy(a) |
|||
for i := 0; i < e-1; i++ { |
|||
result = new(big.Float).Mul(result, a) |
|||
} |
|||
return result |
|||
} |
|||
|
|||
func PolEval(v []*big.Float, x *big.Float) *big.Float { |
|||
r := big.NewFloat(float64(0)) |
|||
for i := 0; i < len(v); i++ { |
|||
xi := FloatPow(x, i) |
|||
elem := new(big.Float).Mul(v[i], xi) |
|||
r = new(big.Float).Add(r, elem) |
|||
} |
|||
return r |
|||
} |
|||
|
|||
func NewPolZeroAt(pointPos, totalPoints int, height *big.Float) []*big.Float { |
|||
fac := 1 |
|||
for i := 1; i < totalPoints+1; i++ { |
|||
if i != pointPos { |
|||
fac = fac * (pointPos - i) |
|||
} |
|||
} |
|||
facBig := big.NewFloat(float64(fac)) |
|||
hf := new(big.Float).Quo(height, facBig) |
|||
r := []*big.Float{hf} |
|||
for i := 1; i < totalPoints+1; i++ { |
|||
if i != pointPos { |
|||
ineg := big.NewFloat(float64(-i)) |
|||
b1 := big.NewFloat(float64(1)) |
|||
r = PolMul(r, []*big.Float{ineg, b1}) |
|||
} |
|||
} |
|||
return r |
|||
} |
|||
|
|||
func LagrangeInterpolation(v []*big.Float) []*big.Float { |
|||
// https://en.wikipedia.org/wiki/Lagrange_polynomial
|
|||
var r []*big.Float |
|||
for i := 0; i < len(v); i++ { |
|||
r = PolAdd(r, NewPolZeroAt(i+1, len(v), v[i])) |
|||
} |
|||
//
|
|||
return r |
|||
} |
|||
|
|||
func R1CSToQAP(a, b, c [][]*big.Float) ([][]*big.Float, [][]*big.Float, [][]*big.Float, []*big.Float) { |
|||
aT := Transpose(a) |
|||
bT := Transpose(b) |
|||
cT := Transpose(c) |
|||
var alphas [][]*big.Float |
|||
for i := 0; i < len(aT); i++ { |
|||
alphas = append(alphas, LagrangeInterpolation(aT[i])) |
|||
} |
|||
var betas [][]*big.Float |
|||
for i := 0; i < len(bT); i++ { |
|||
betas = append(betas, LagrangeInterpolation(bT[i])) |
|||
} |
|||
var gammas [][]*big.Float |
|||
for i := 0; i < len(cT); i++ { |
|||
gammas = append(gammas, LagrangeInterpolation(cT[i])) |
|||
} |
|||
z := []*big.Float{big.NewFloat(float64(1))} |
|||
for i := 1; i < len(aT[0])+1; i++ { |
|||
ineg := big.NewFloat(float64(-i)) |
|||
b1 := big.NewFloat(float64(1)) |
|||
z = PolMul(z, []*big.Float{ineg, b1}) |
|||
} |
|||
return alphas, betas, gammas, z |
|||
} |
|||
|
|||
func CombinePolynomials(r []*big.Float, ap, bp, cp [][]*big.Float) ([]*big.Float, []*big.Float, []*big.Float, []*big.Float) { |
|||
var alpha []*big.Float |
|||
for i := 0; i < len(r); i++ { |
|||
m := PolMul([]*big.Float{r[i]}, ap[i]) |
|||
alpha = PolAdd(alpha, m) |
|||
} |
|||
var beta []*big.Float |
|||
for i := 0; i < len(r); i++ { |
|||
m := PolMul([]*big.Float{r[i]}, bp[i]) |
|||
beta = PolAdd(beta, m) |
|||
} |
|||
var gamma []*big.Float |
|||
for i := 0; i < len(r); i++ { |
|||
m := PolMul([]*big.Float{r[i]}, cp[i]) |
|||
gamma = PolAdd(gamma, m) |
|||
} |
|||
|
|||
px := PolSub(PolMul(alpha, beta), gamma) |
|||
return alpha, beta, gamma, px |
|||
} |
|||
|
|||
func DivisorPolinomial(px, z []*big.Float) []*big.Float { |
|||
quo, _ := PolDiv(px, z) |
|||
return quo |
|||
} |
@ -1,137 +0,0 @@ |
|||
package r1csqapFloat |
|||
|
|||
import ( |
|||
"fmt" |
|||
"math/big" |
|||
"testing" |
|||
|
|||
"github.com/stretchr/testify/assert" |
|||
) |
|||
|
|||
func TestTranspose(t *testing.T) { |
|||
b0 := big.NewFloat(float64(0)) |
|||
b1 := big.NewFloat(float64(1)) |
|||
bFive := big.NewFloat(float64(5)) |
|||
a := [][]*big.Float{ |
|||
[]*big.Float{b0, b1, b0, b0, b0, b0}, |
|||
[]*big.Float{b0, b0, b0, b1, b0, b0}, |
|||
[]*big.Float{b0, b1, b0, b0, b1, b0}, |
|||
[]*big.Float{bFive, b0, b0, b0, b0, b1}, |
|||
} |
|||
aT := Transpose(a) |
|||
assert.Equal(t, aT, [][]*big.Float{ |
|||
[]*big.Float{b0, b0, b0, bFive}, |
|||
[]*big.Float{b1, b0, b1, b0}, |
|||
[]*big.Float{b0, b0, b0, b0}, |
|||
[]*big.Float{b0, b1, b0, b0}, |
|||
[]*big.Float{b0, b0, b1, b0}, |
|||
[]*big.Float{b0, b0, b0, b1}, |
|||
}) |
|||
} |
|||
|
|||
func TestPol(t *testing.T) { |
|||
b0 := big.NewFloat(float64(0)) |
|||
b1 := big.NewFloat(float64(1)) |
|||
// b1neg := big.NewFloat(float64(-1))
|
|||
// b2 := big.NewFloat(float64(2))
|
|||
b2neg := big.NewFloat(float64(-2)) |
|||
b3 := big.NewFloat(float64(3)) |
|||
b4 := big.NewFloat(float64(4)) |
|||
b5 := big.NewFloat(float64(5)) |
|||
b6 := big.NewFloat(float64(6)) |
|||
b16 := big.NewFloat(float64(16)) |
|||
|
|||
a := []*big.Float{b1, b0, b5} |
|||
b := []*big.Float{b3, b0, b1} |
|||
|
|||
// polynomial multiplication
|
|||
c := PolMul(a, b) |
|||
assert.Equal(t, c, []*big.Float{b3, b0, b16, b0, b5}) |
|||
|
|||
// polynomial addition
|
|||
c = PolAdd(a, b) |
|||
assert.Equal(t, c, []*big.Float{b4, b0, b6}) |
|||
|
|||
// polynomial subtraction
|
|||
c = PolSub(a, b) |
|||
assert.Equal(t, c, []*big.Float{b2neg, b0, b4}) |
|||
|
|||
// FloatPow
|
|||
p := FloatPow(big.NewFloat(float64(5)), 3) |
|||
assert.Equal(t, p, big.NewFloat(float64(125))) |
|||
p = FloatPow(big.NewFloat(float64(5)), 0) |
|||
assert.Equal(t, p, big.NewFloat(float64(1))) |
|||
|
|||
// NewPolZeroAt
|
|||
r := NewPolZeroAt(3, 4, b4) |
|||
assert.Equal(t, PolEval(r, big.NewFloat(3)), b4) |
|||
r = NewPolZeroAt(2, 4, b3) |
|||
assert.Equal(t, PolEval(r, big.NewFloat(2)), b3) |
|||
} |
|||
|
|||
func TestLagrangeInterpolation(t *testing.T) { |
|||
b0 := big.NewFloat(float64(0)) |
|||
b5 := big.NewFloat(float64(5)) |
|||
a := []*big.Float{b0, b0, b0, b5} |
|||
alpha := LagrangeInterpolation(a) |
|||
|
|||
assert.Equal(t, PolEval(alpha, big.NewFloat(4)), b5) |
|||
aux, _ := PolEval(alpha, big.NewFloat(3)).Int64() |
|||
assert.Equal(t, aux, int64(0)) |
|||
|
|||
} |
|||
|
|||
func TestR1CSToQAP(t *testing.T) { |
|||
b0 := big.NewFloat(float64(0)) |
|||
b1 := big.NewFloat(float64(1)) |
|||
b3 := big.NewFloat(float64(3)) |
|||
b5 := big.NewFloat(float64(5)) |
|||
b9 := big.NewFloat(float64(9)) |
|||
b27 := big.NewFloat(float64(27)) |
|||
b30 := big.NewFloat(float64(30)) |
|||
b35 := big.NewFloat(float64(35)) |
|||
a := [][]*big.Float{ |
|||
[]*big.Float{b0, b1, b0, b0, b0, b0}, |
|||
[]*big.Float{b0, b0, b0, b1, b0, b0}, |
|||
[]*big.Float{b0, b1, b0, b0, b1, b0}, |
|||
[]*big.Float{b5, b0, b0, b0, b0, b1}, |
|||
} |
|||
b := [][]*big.Float{ |
|||
[]*big.Float{b0, b1, b0, b0, b0, b0}, |
|||
[]*big.Float{b0, b1, b0, b0, b0, b0}, |
|||
[]*big.Float{b1, b0, b0, b0, b0, b0}, |
|||
[]*big.Float{b1, b0, b0, b0, b0, b0}, |
|||
} |
|||
c := [][]*big.Float{ |
|||
[]*big.Float{b0, b0, b0, b1, b0, b0}, |
|||
[]*big.Float{b0, b0, b0, b0, b1, b0}, |
|||
[]*big.Float{b0, b0, b0, b0, b0, b1}, |
|||
[]*big.Float{b0, b0, b1, b0, b0, b0}, |
|||
} |
|||
// alphas, betas, gammas
|
|||
alphas, betas, gammas, zx := R1CSToQAP(a, b, c) |
|||
fmt.Println(alphas) |
|||
fmt.Println(betas) |
|||
fmt.Println(gammas) |
|||
fmt.Print("Z(x): ") |
|||
fmt.Println(zx) |
|||
zexpected := []*big.Float{big.NewFloat(float64(24)), big.NewFloat(float64(-50)), big.NewFloat(float64(35)), big.NewFloat(float64(-10)), big.NewFloat(float64(1))} |
|||
assert.Equal(t, zx, zexpected) |
|||
|
|||
// witness
|
|||
w := []*big.Float{b1, b3, b35, b9, b27, b30} |
|||
fmt.Print("w: ") |
|||
fmt.Println(w) |
|||
// QAP A(x), B(x), C(x)
|
|||
ax, bx, cx, px := CombinePolynomials(w, alphas, betas, gammas) |
|||
fmt.Print("A(x), B(x), C(x), P(x): ") |
|||
fmt.Println(ax) |
|||
fmt.Println(bx) |
|||
fmt.Println(cx) |
|||
fmt.Println(px) |
|||
|
|||
hx := DivisorPolinomial(px, zx) |
|||
fmt.Print("H(x): ") |
|||
fmt.Println(hx) |
|||
|
|||
} |