- avoid code duplication on cmd - interface for proof systempull/10/head
@ -1,4 +1,4 @@ |
|||||
package circuitcompiler |
|
||||
|
package circuit |
||||
|
|
||||
import ( |
import ( |
||||
"bufio" |
"bufio" |
@ -1,4 +1,4 @@ |
|||||
package circuitcompiler |
|
||||
|
package circuit |
||||
|
|
||||
import ( |
import ( |
||||
"bufio" |
"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 |
package main |
||||
|
|
||||
import ( |
import ( |
||||
"bufio" |
|
||||
"bytes" |
|
||||
"encoding/json" |
|
||||
"errors" |
|
||||
"fmt" |
"fmt" |
||||
"io/ioutil" |
|
||||
"log" |
|
||||
"math/big" |
|
||||
"os" |
"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/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{ |
var commands = []cli.Command{ |
||||
{ |
{ |
||||
Name: "compile", |
Name: "compile", |
||||
Aliases: []string{}, |
Aliases: []string{}, |
||||
Usage: "compile a circuit", |
Usage: "compile a circuit", |
||||
Action: CompileCircuit, |
|
||||
|
Action: compile, |
||||
}, |
}, |
||||
{ |
{ |
||||
Name: "trustedsetup", |
|
||||
|
Name: "setup", |
||||
Aliases: []string{}, |
Aliases: []string{}, |
||||
Usage: "generate trusted setup for a circuit", |
Usage: "generate trusted setup for a circuit", |
||||
Action: TrustedSetup, |
|
||||
|
Action: setup, |
||||
}, |
}, |
||||
{ |
{ |
||||
Name: "genproofs", |
|
||||
|
Name: "generate", |
||||
Aliases: []string{}, |
Aliases: []string{}, |
||||
Usage: "generate the snark proofs", |
Usage: "generate the snark proofs", |
||||
Action: GenerateProofs, |
|
||||
|
Action: generate, |
||||
}, |
}, |
||||
{ |
{ |
||||
Name: "verify", |
Name: "verify", |
||||
Aliases: []string{}, |
Aliases: []string{}, |
||||
Usage: "verify the snark proofs", |
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 |
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) |
|
||||
|
|
||||
} |
|