go-snark/circuitcompiler/circuit.go
circuitcompiler/circuit.goRaw
1package circuitcompiler
2
3import (
4 "errors"
5 "math/big"
6 "strconv"
7
8 "github.com/arnaucube/go-snark/r1csqap"
9)
10
11type Circuit struct {
12 NVars int
13 NPublic int
14 NSignals int
15 Inputs []string
16 Signals []string
17 Witness []*big.Int
18 Constraints []Constraint
19 R1CS struct {
20 A [][]*big.Int
21 B [][]*big.Int
22 C [][]*big.Int
23 }
24}
25type Constraint struct {
26 // v1 op v2 = out
27 Op string
28 V1 string
29 V2 string
30 Out string
31 Literal string
32
33 Inputs []string // in func delcaration case
34}
35
36func indexInArray(arr []string, e string) int {
37 for i, a := range arr {
38 if a == e {
39 return i
40 }
41 }
42 return -1
43}
44func isValue(a string) (bool, int) {
45 v, err := strconv.Atoi(a)
46 if err != nil {
47 return false, 0
48 }
49 return true, v
50}
51func insertVar(arr []*big.Int, signals []string, v string, used map[string]bool) ([]*big.Int, map[string]bool) {
52 isVal, value := isValue(v)
53 valueBigInt := big.NewInt(int64(value))
54 if isVal {
55 arr[0] = new(big.Int).Add(arr[0], valueBigInt)
56 } else {
57 if !used[v] {
58 panic(errors.New("using variable before it's set"))
59 }
60 arr[indexInArray(signals, v)] = new(big.Int).Add(arr[indexInArray(signals, v)], big.NewInt(int64(1)))
61 }
62 return arr, used
63}
64
65func (circ *Circuit) GenerateR1CS() ([][]*big.Int, [][]*big.Int, [][]*big.Int) {
66 // from flat code to R1CS
67
68 var a [][]*big.Int
69 var b [][]*big.Int
70 var c [][]*big.Int
71
72 used := make(map[string]bool)
73 for _, constraint := range circ.Constraints {
74
75 aConstraint := r1csqap.ArrayOfBigZeros(len(circ.Signals))
76 bConstraint := r1csqap.ArrayOfBigZeros(len(circ.Signals))
77 cConstraint := r1csqap.ArrayOfBigZeros(len(circ.Signals))
78
79 // if existInArray(constraint.Out) {
80 if used[constraint.Out] {
81 panic(errors.New("out variable already used: " + constraint.Out))
82 }
83 used[constraint.Out] = true
84 if constraint.Op == "in" {
85 for i := 0; i < len(constraint.Inputs); i++ {
86 aConstraint[indexInArray(circ.Signals, constraint.Out)] = new(big.Int).Add(aConstraint[indexInArray(circ.Signals, constraint.Out)], big.NewInt(int64(1)))
87 aConstraint, used = insertVar(aConstraint, circ.Signals, constraint.Out, used)
88 bConstraint[0] = big.NewInt(int64(1))
89
90 }
91 continue
92
93 } else if constraint.Op == "+" {
94 cConstraint[indexInArray(circ.Signals, constraint.Out)] = big.NewInt(int64(1))
95 aConstraint, used = insertVar(aConstraint, circ.Signals, constraint.V1, used)
96 aConstraint, used = insertVar(aConstraint, circ.Signals, constraint.V2, used)
97 bConstraint[0] = big.NewInt(int64(1))
98 } else if constraint.Op == "*" {
99 cConstraint[indexInArray(circ.Signals, constraint.Out)] = big.NewInt(int64(1))
100 aConstraint, used = insertVar(aConstraint, circ.Signals, constraint.V1, used)
101 bConstraint, used = insertVar(bConstraint, circ.Signals, constraint.V2, used)
102 }
103
104 a = append(a, aConstraint)
105 b = append(b, bConstraint)
106 c = append(c, cConstraint)
107
108 }
109 return a, b, c
110}