├── Circuitcompiler
├── Programm.go
├── Programm_test.go
├── R1CS.go
├── circuit.go
├── circuit_test.go
├── client.go
├── factorHandling.go
├── factorHandling_test.go
├── gate.go
├── gateContainer.go
├── hub.go
├── lexer.go
├── lexer_test.go
├── parser.go
├── parser_test.go
├── rune_stack.go
├── server.go
├── visualizer.go
├── visualizer_test.go
├── web_g6
│ ├── favicon.ico
│ ├── g6.min.js
│ ├── index.html
│ └── index.js
└── web_vivagraph
│ ├── favicon.ico
│ ├── index.html
│ ├── index.js
│ └── vivagraph.js
├── LICENSE
├── README.md
├── main.go
├── pairing
├── bn256.go
├── bn256_test.go
├── constants.go
├── curve.go
├── example_test.go
├── gfp12.go
├── gfp2.go
├── gfp6.go
├── main_test.go
├── optate.go
└── twist.go
├── testPrograms
└── codes.go
├── utils
├── avl.go
├── fft.go
├── fft_test.go
├── finiteField.go
├── finiteField_test.go
├── parallelize.go
├── polynomialField.go
├── polynomialField_test.go
├── sparsePolynomial.go
├── sparsePolynomial_test.go
├── utils.go
└── utils_test.go
└── zkSNARK
├── groth16.go
└── groth16_test.go
/Circuitcompiler/Programm_test.go:
--------------------------------------------------------------------------------
1 | package Circuitcompiler
2 |
3 | import (
4 | "fmt"
5 | "github.com/mottla/go-R1CS-Compiler/testPrograms"
6 | "github.com/mottla/go-R1CS-Compiler/utils"
7 | "github.com/stretchr/testify/assert"
8 | "math/big"
9 | "testing"
10 | )
11 |
12 | func TestStaticIfProgram(t *testing.T) {
13 | code := `
14 | func main(x field,y field)(field) {
15 | if 2>3 {
16 | return x*x
17 | }
18 | if 2>3 {
19 | return y*y
20 | }else if 5!=5{
21 | return x*x*x
22 | }else if 5==5{
23 | x=y*y
24 | }
25 | return x*x
26 | }
27 |
28 | `
29 | p := Parse(code)
30 | container := p.Execute()
31 |
32 | gates := container.OrderedGates()
33 | fmt.Println("\n generating R1CS")
34 | r1cs := p.GatesToR1CS(gates)
35 | fmt.Printf("number of gates %v, witness length %v \n ", r1cs.NumberOfGates, r1cs.WitnessLength)
36 | //
37 | fmt.Println(r1cs.L)
38 | fmt.Println(r1cs.R)
39 | fmt.Println(r1cs.O)
40 | }
41 |
42 | func TestArrayProgram(t *testing.T) {
43 | code := `
44 | func main(x bool,z field) (field) {
45 | var caa = [2]field{33,44}
46 | var ca = [2][2]field{ caa, [2]field{55,44}}
47 | z = z*ca[1][1]
48 | ca[1][1] = 66
49 | z = z*ca[1][1]
50 | z = z*z
51 | return z
52 | }
53 | `
54 | program := Parse(code)
55 | container := program.Execute()
56 |
57 | gates := container.OrderedGates()
58 | fmt.Println("\n generating R1CS")
59 | r1cs := program.GatesToR1CS(gates)
60 | fmt.Printf("number of gates %v, witness length %v \n ", r1cs.NumberOfGates, r1cs.WitnessLength)
61 | //
62 | fmt.Println(r1cs.L)
63 | fmt.Println(r1cs.R)
64 | fmt.Println(r1cs.O)
65 | inputs := CombineInputs(program.GetMainCircuit().InputIdentifiers, []*big.Int{big.NewInt(int64(27)), big.NewInt(int64(27))})
66 |
67 | fmt.Println("input")
68 | fmt.Println(inputs)
69 |
70 | w, err := CalculateTrace(r1cs, inputs)
71 | assert.NoError(t, err)
72 | fmt.Printf("witness len %v \n ", len(w))
73 | fmt.Println(w)
74 | }
75 |
76 | func TestForProgram(t *testing.T) {
77 | code := `
78 | func main(x field,z field,y func(x bool)(bool))(func(a field)(bool)) {
79 | #x,z = test()
80 | var c = 5
81 | var mul5 = mul(5)
82 | x = mul5(square(x))
83 | x = (square(x)-1)*square(x)
84 | x = (square(x)-1)*square(x)
85 | return func(a field)(bool) { return true }
86 | }
87 | func a()(func(c bool)(bool)) {
88 | return func(a bool)(bool){return true}
89 | }
90 | func square(x field)(field){ return x*x }
91 | func mul(a field,b field)(field){return b*a }
92 | func test()(bool,field){
93 | return true,3
94 | }
95 | `
96 | program := Parse(code)
97 | container := program.Execute()
98 |
99 | gates := container.OrderedGates()
100 | fmt.Println("\n generating R1CS")
101 | r1cs := program.GatesToR1CS(gates)
102 | fmt.Printf("number of gates %v, witness length %v \n ", r1cs.NumberOfGates, r1cs.WitnessLength)
103 | //
104 | fmt.Println(r1cs.L)
105 | fmt.Println(r1cs.R)
106 | fmt.Println(r1cs.O)
107 | inputs := CombineInputs(program.GetMainCircuit().InputIdentifiers, []*big.Int{big.NewInt(int64(3)), big.NewInt(int64(5)), big.NewInt(int64(7))})
108 |
109 | fmt.Println("input")
110 | fmt.Println(inputs)
111 |
112 | w, err := CalculateTrace(r1cs, inputs)
113 | assert.NoError(t, err)
114 | fmt.Printf("witness len %v \n ", len(w))
115 | fmt.Println(w)
116 | }
117 |
118 | func TestFibonacciPrograms(t *testing.T) {
119 | for _, test := range testPrograms.TestFibonacci {
120 | if test.Skip {
121 | continue
122 | }
123 |
124 | fmt.Println("\n unreduced")
125 | utils.PrintWithLineNumbering(test.Code)
126 | program := Parse(test.Code)
127 |
128 | container := program.Execute()
129 | gates := container.OrderedGates()
130 | fmt.Println("\n generating R1CS")
131 | r1cs := program.GatesToR1CS(gates)
132 | fmt.Printf("number of gates %v, witness length %v \n ", r1cs.NumberOfGates, r1cs.WitnessLength)
133 | //
134 | fmt.Println(r1cs.L)
135 | fmt.Println(r1cs.R)
136 | fmt.Println(r1cs.O)
137 |
138 | for _, io := range test.IO {
139 | inputs := CombineInputs(program.GetMainCircuit().InputIdentifiers, io.Inputs)
140 |
141 | fmt.Println("input")
142 | fmt.Println(inputs)
143 |
144 | w, err := CalculateTrace(r1cs, inputs)
145 | assert.NoError(t, err)
146 | fmt.Printf("witness len %v \n ", len(w))
147 | fmt.Println(w)
148 |
149 | }
150 | }
151 | }
152 |
153 | func TestSudokuPrograms(t *testing.T) {
154 |
155 | for _, test := range testPrograms.TestSudoku {
156 | if test.Skip {
157 | continue
158 | }
159 |
160 | fmt.Println("\n unreduced")
161 | utils.PrintWithLineNumbering(test.Code)
162 | program := Parse(test.Code)
163 |
164 | container := program.Execute()
165 | gates := container.OrderedGates()
166 | fmt.Println("\n generating R1CS")
167 | r1cs := program.GatesToR1CS(gates)
168 | fmt.Printf("number of gates %v, witness length %v \n ", r1cs.NumberOfGates, r1cs.WitnessLength)
169 | //
170 | //fmt.Println(r1cs.L)
171 | //fmt.Println(r1cs.R)
172 | //fmt.Println(r1cs.O)
173 |
174 | for _, io := range test.IO {
175 | strs := []string{}
176 | ArrayStringBuild([]int64{9, 9}, "sudoku", &strs)
177 |
178 | inputs := CombineInputs(strs, io.Inputs)
179 |
180 | fmt.Println("input")
181 | fmt.Println(inputs)
182 |
183 | w, err := CalculateTrace(r1cs, inputs)
184 | assert.NoError(t, err)
185 | fmt.Printf("witness len %v \n ", len(w))
186 | fmt.Println(w)
187 |
188 | }
189 | }
190 | }
191 |
192 | //seems to have trouble when the field size is to small
193 | //func TestFixedBaseExponentiation(t *testing.T) {
194 | //
195 | // var codeGen = func(exponent string) string {
196 | // return fmt.Sprintf(`
197 | // func main( x) {
198 | // public{
199 | // x
200 | // }
201 | // return x**%v
202 | // }
203 | //
204 | //`, exponent)
205 | // }
206 | //
207 | // for i := 0; i < 10; i++ {
208 | // exponent, _ := utils.Field.ArithmeticField.Rand()
209 | // code := codeGen(exponent.String())
210 | //
211 | // program := Parse(code, true)
212 | //
213 | // container := program.Execute()
214 | // gates := container.OrderedGates()
215 | // r1cs := program.GatesToR1CS(gates)
216 | // for j := 0; j < 10; j++ {
217 | // base, _ := utils.Field.ArithmeticField.Rand()
218 | // expected := utils.Field.ArithmeticField.Exp(base, exponent)
219 | // inputs := CombineInputs(program.GetMainCircuit().InputIdentifiers, []*big.Int{base})
220 | // w, err := CalculateTrace(r1cs, inputs)
221 | // assert.NoError(t, err)
222 | // assert.Equal(t, w[len(w)-1], expected)
223 | // }
224 | // }
225 | //
226 | //}
227 |
--------------------------------------------------------------------------------
/Circuitcompiler/R1CS.go:
--------------------------------------------------------------------------------
1 | package Circuitcompiler
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "github.com/mottla/go-R1CS-Compiler/utils"
7 | "math/big"
8 | )
9 |
10 | type R1CS struct {
11 | //indexMap maps each variable to its position in the witness trace
12 | indexMap map[string]int
13 | WitnessLength, NumberOfGates int
14 | //splitMap maps each variable (which is split into its bit represants at some point in the code) onto the positions
15 | //of the its bits in the indexMap
16 | splitmap map[string][]int
17 | L []utils.Poly
18 | R []utils.Poly
19 | O []utils.Poly
20 | triggers []func(witness *[]*big.Int, set utils.FastBool, indexMap map[string]int) bool
21 | }
22 | type R1CSSparse struct {
23 | indexMap map[string]int
24 | splitmap map[string][]int
25 | WitnessLength, NumberOfGates int
26 | L []*utils.AvlTree
27 | R []*utils.AvlTree
28 | O []*utils.AvlTree
29 | }
30 | type R1CSsPARSETransposed struct {
31 | indexMap map[string]int
32 | WitnessLength, NumberOfGates int
33 | L []*utils.AvlTree
34 | R []*utils.AvlTree
35 | O []*utils.AvlTree
36 | }
37 | type R1CSTransposed struct {
38 | indexMap map[string]int
39 | WitnessLength, NumberOfGates int
40 | L []utils.Poly
41 | R []utils.Poly
42 | O []utils.Poly
43 | }
44 |
45 | func (er1cs *R1CSSparse) TransposeSparse() (transposed *R1CSsPARSETransposed) {
46 | transposed = &R1CSsPARSETransposed{}
47 | transposed.indexMap = er1cs.indexMap
48 | transposed.NumberOfGates = er1cs.NumberOfGates
49 | transposed.WitnessLength = er1cs.WitnessLength
50 |
51 | transposed.L = utils.TransposeSparse(er1cs.L, er1cs.WitnessLength)
52 | transposed.R = utils.TransposeSparse(er1cs.R, er1cs.WitnessLength)
53 | transposed.O = utils.TransposeSparse(er1cs.O, er1cs.WitnessLength)
54 |
55 | return
56 | }
57 |
58 | func (er1cs *R1CS) Transpose() (transposed *R1CSTransposed) {
59 | transposed = &R1CSTransposed{}
60 | transposed.indexMap = er1cs.indexMap
61 | transposed.NumberOfGates = er1cs.NumberOfGates
62 | transposed.WitnessLength = er1cs.WitnessLength
63 | transposed.L = utils.Transpose(er1cs.L)
64 | transposed.R = utils.Transpose(er1cs.R)
65 | transposed.O = utils.Transpose(er1cs.O)
66 | return
67 | }
68 |
69 | func (er1cs *R1CSTransposed) R1CSToEAP_FFT(fft *utils.FFT_PrecomputedParas, pf *utils.PolynomialField, tau *big.Int) (Ai_Tau, Ri_Tau, Oi_Tau []*big.Int) {
70 |
71 | lT := er1cs.L
72 | rT := er1cs.R
73 | oT := er1cs.O
74 |
75 | gates := fft.Size
76 | lagreangeBasesAtTau := make(utils.Poly, er1cs.NumberOfGates)
77 | zeta := pf.EvalPoly(fft.Domain, tau)
78 |
79 | lambda := pf.F.Div(zeta, new(big.Int).SetInt64(int64(gates)))
80 | rho := fft.RootOfUnitys[0]
81 |
82 | lagreangeBasesAtTau[0] = pf.F.Div(lambda, pf.F.Sub(tau, rho))
83 |
84 | for i := 1; i < er1cs.NumberOfGates; i++ {
85 | lambda = pf.F.Mul(lambda, fft.RootOfUnity)
86 | index := ((gates >> 1) + i) % gates
87 | //inv,_ := pf.Div(utils.Poly{bigOne},utils.Poly{fft.RootOfUnitys[ index], bigOne})
88 | lagreangeBasesAtTau[i] = pf.F.Div(lambda, pf.F.Add(fft.RootOfUnitys[index], tau))
89 | }
90 | Ai_Tau, Ri_Tau, Oi_Tau = make([]*big.Int, er1cs.WitnessLength), make([]*big.Int, er1cs.WitnessLength), make([]*big.Int, er1cs.WitnessLength)
91 |
92 | for i := 0; i < er1cs.WitnessLength; i++ {
93 | Ai_Tau[i] = pf.F.ScalarProduct(lT[i], lagreangeBasesAtTau)
94 |
95 | Ri_Tau[i] = pf.F.ScalarProduct(rT[i], lagreangeBasesAtTau)
96 |
97 | Oi_Tau[i] = pf.F.ScalarProduct(oT[i], lagreangeBasesAtTau)
98 | }
99 | return
100 | }
101 |
102 | ////note that invDFFT and DFFT increase the size of the input array to the next power of two
103 | //func (er1cs *R1CSTransposed) R1CSToEAP_FFT(fft *utils.FFT_PrecomputedParas) (lPoly, rPoly, oPoly []utils.Poly) {
104 | //
105 | // pf := utils.Field.PolynomialField
106 | //
107 | // lT := er1cs.L
108 | // rT := er1cs.R
109 | // oT := er1cs.O
110 | // gates := fft.Size
111 | // lagreangeBases := make([]utils.Poly, gates)
112 | // invGateNumber := pf.F.Inverse(new(big.Int).SetInt64(int64(gates)))
113 | // lambda := pf.MulScalar(fft.Domain, invGateNumber)
114 | // rho := fft.RootOfUnitys[gates>>1]
115 | // var rest utils.Poly
116 | // lagreangeBases[0], rest = pf.Div(lambda, utils.Poly{rho, bigOne})
117 | // if !utils.IsZeroArray(rest) {
118 | // panic("no rest")
119 | // }
120 | //
121 | // for i := 1; i < gates; i++ {
122 | // lambda = pf.MulScalar(lambda, fft.RootOfUnity)
123 | // index := ((gates >> 1) + i) % gates
124 | // //inv,_ := pf.Div(utils.Poly{bigOne},utils.Poly{fft.RootOfUnitys[ index], bigOne})
125 | // lagreangeBases[i], _ = pf.Div(lambda, utils.Poly{fft.RootOfUnitys[index], bigOne})
126 | // }
127 | //
128 | // for i := 0; i < er1cs.WitnessLength; i++ {
129 | //
130 | // lPoly = append(lPoly, pf.AddPolynomials(pf.LinearCombine(lagreangeBases, lT[i])))
131 | //
132 | // rPoly = append(rPoly, pf.AddPolynomials(pf.LinearCombine(lagreangeBases, rT[i])))
133 | //
134 | // oPoly = append(oPoly, pf.AddPolynomials(pf.LinearCombine(lagreangeBases, oT[i])))
135 | // }
136 | // return
137 | //}
138 |
139 | func CalculateTrace(r1cs *R1CS, input []InputArgument) (witness []*big.Int, err error) {
140 |
141 | witness = utils.ArrayOfBigZeros(len(r1cs.indexMap))
142 | set := utils.NewFastBool()
143 |
144 | invIndexMap := make(map[int]string)
145 | for k, v := range r1cs.indexMap {
146 | invIndexMap[v] = k
147 | }
148 |
149 | var setWitness = func(index int, value *big.Int) {
150 | witness[index] = utils.Field.ArithmeticField.Affine(value)
151 | set.Set(index)
152 |
153 | //go over the list of self triggering funktions
154 | var remain []func(witness *[]*big.Int, set utils.FastBool, indexMap map[string]int) bool
155 | for i := 0; i < len(r1cs.triggers); i++ {
156 | //we evaluate the trigger function. if it detects, that all values are there it
157 | //needs to compute some values, it does so, and returns true.
158 | //from then on, we dont need it anymore and throw it away
159 | if !(r1cs.triggers[i])(&witness, set, r1cs.indexMap) {
160 | remain = append(remain, r1cs.triggers[i])
161 | }
162 | }
163 | r1cs.triggers = remain
164 |
165 | }
166 | setWitness(0, big.NewInt(int64(1)))
167 |
168 | for _, v := range input {
169 | setWitness(r1cs.indexMap[v.identifier], v.value)
170 | }
171 |
172 | zero := big.NewInt(int64(0))
173 |
174 | getKnownsAndUnknowns := func(array []*big.Int) (knowns []*big.Int, unknownsAtIndices []int) {
175 |
176 | knowns = utils.ArrayOfBigZeros(len(array))
177 | for j, val := range array {
178 | if val.Cmp(zero) != 0 {
179 | if !set.IsSet(j) {
180 | unknownsAtIndices = append(unknownsAtIndices, j)
181 | } else {
182 | knowns[j] = val
183 | }
184 | }
185 | }
186 | return
187 | }
188 |
189 | sum := func(array []*big.Int) *big.Int {
190 | return utils.Field.ArithmeticField.ScalarProduct(array, witness)
191 | }
192 |
193 | for i := 0; i < len(r1cs.L); i++ {
194 | gatesLeftInputs := r1cs.L[i]
195 | gatesRightInputs := r1cs.R[i]
196 | gatesOutputs := r1cs.O[i]
197 |
198 | leftKnowns, leftUnknowns := getKnownsAndUnknowns(gatesLeftInputs)
199 | rightKnowns, rightUnknowns := getKnownsAndUnknowns(gatesRightInputs)
200 |
201 | outKnowns, outUnknowns := getKnownsAndUnknowns(gatesOutputs)
202 |
203 | if len(leftUnknowns)+len(rightUnknowns)+len(outUnknowns) > 1 {
204 | return witness, errors.New(fmt.Sprintf("at gate %v:computing more then one unknown in Gate assignment is not possible", i))
205 | }
206 |
207 | // (a*x + b + c..) (d+e+..) = (F+g+..) we solve for x
208 | if len(leftUnknowns) == 1 {
209 | sumright := sum(rightKnowns)
210 | sumOut := sum(outKnowns)
211 | if sumright.Cmp(zero) == 0 && sumOut.Cmp(zero) == 0 {
212 | return witness, errors.New(fmt.Sprintf("at gate %v: the equation x*x = 0 is does not allow to determine x", i))
213 | }
214 | //result := utils.Field.ArithmeticField.Sub(sum(outKnowns), new(bn256.G1).ScalarBaseMult(sum(exponentKnowns)).X())
215 | result := utils.Field.ArithmeticField.Div(sumOut, sumright)
216 | result = utils.Field.ArithmeticField.Sub(result, sum(leftKnowns))
217 | result = utils.Field.ArithmeticField.Div(result, gatesLeftInputs[leftUnknowns[0]]) //divide by a
218 | setWitness(leftUnknowns[0], result)
219 | continue
220 | }
221 | // (a + b + c..) (d+e*x+..) = (F+g+..) we solve for x
222 | if len(rightUnknowns) == 1 {
223 | sumleft := sum(leftKnowns)
224 | sounOut := sum(outKnowns)
225 | if sumleft.Cmp(zero) == 0 && sounOut.Cmp(zero) == 0 {
226 | // 0 * a = 0
227 | // a cannot be determined
228 | return witness, errors.New(fmt.Sprintf("at gate %v: the equation 0 * x = 0 is does not allow to determine x", i))
229 | }
230 | //if sumleft.Cmp(zero) == 0 && sounOut.Cmp(zero) != 0 {
231 | // // 0 * a = 0
232 | // // a cannot be determined
233 | // return nil, errors.New(fmt.Sprintf("at gate %v:the summation of Lexer inputs cannot be 0 if the unknown is in R", i))
234 | //}
235 | result := utils.Field.ArithmeticField.Div(sounOut, sumleft)
236 | result = utils.Field.ArithmeticField.Sub(result, sum(rightKnowns))
237 | result = utils.Field.ArithmeticField.Div(result, gatesRightInputs[rightUnknowns[0]]) //divide by a
238 | setWitness(rightUnknowns[0], result)
239 | continue
240 | }
241 |
242 | // (a + b + c..) (d+e+..) = (F+x*g+..) we solve for x
243 | if len(outUnknowns) == 1 {
244 |
245 | result := utils.Field.ArithmeticField.Mul(sum(rightKnowns), sum(leftKnowns))
246 | result = utils.Field.ArithmeticField.Sub(result, sum(outKnowns))
247 | result = utils.Field.ArithmeticField.Div(result, gatesOutputs[outUnknowns[0]]) //divide by a
248 | setWitness(outUnknowns[0], result)
249 | continue
250 | }
251 | //we computed the unkown and now check if the ER1C is satisfied
252 | leftKnowns, leftUnknowns = getKnownsAndUnknowns(gatesLeftInputs)
253 | rightKnowns, rightUnknowns = getKnownsAndUnknowns(gatesRightInputs)
254 | outKnowns, outUnknowns = getKnownsAndUnknowns(gatesOutputs)
255 |
256 | if len(leftUnknowns)+len(rightUnknowns)+len(outUnknowns) != 0 {
257 | return witness, errors.New(fmt.Sprintf("at gate %v some unknowns remain", i))
258 |
259 | }
260 | //now check if the gate is satisfiable
261 | result := utils.Field.ArithmeticField.Mul(sum(rightKnowns), sum(leftKnowns))
262 | if result.Cmp(sum(outKnowns)) != 0 {
263 | return witness, errors.New(fmt.Sprintf("at equality gate %v there is unequality. %v != %v .We cannot process", i, result.String(), sum(outKnowns).String()))
264 | }
265 |
266 | }
267 |
268 | return
269 | }
270 |
--------------------------------------------------------------------------------
/Circuitcompiler/circuit_test.go:
--------------------------------------------------------------------------------
1 | package Circuitcompiler
2 |
3 | var CircuitCorrectnessTest = []string{
4 | `
5 | func main( a,b,c) {
6 | var a[] = {1,b,3,a}
7 | var k = a[a[0]*8/8]
8 | foo(a)
9 | var d = foo(a)
10 | return k * b *d
11 | }
12 | func foo(a){
13 | return a}
14 | `,
15 | }
16 |
17 | //func TestPrintTree(t *testing.T) {
18 | //
19 | // for _, test := range CircuitCorrectnessTest {
20 | //
21 | // program := Parse(test, true)
22 | //
23 | // fmt.Println("\n unreduced")
24 | // fmt.Println(test)
25 | //
26 | // container := program.Execute()
27 | // gates := container.orderedmGates
28 | // for _, g := range gates {
29 | // fmt.Printf("\n %v", g)
30 | // }
31 | //
32 | // //fmt.Println("\n generating R1CS")
33 | // //r1cs := program.GatesToR1CS(gates)
34 | // //fmt.Println(r1cs.Lexer)
35 | // //fmt.Println(r1cs.R)
36 | // //fmt.Println(r1cs.O)
37 | //
38 | // }
39 | //
40 | //}
41 |
--------------------------------------------------------------------------------
/Circuitcompiler/client.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package Circuitcompiler
6 |
7 | import (
8 | "bytes"
9 | "log"
10 | "net/http"
11 | "time"
12 |
13 | "github.com/gorilla/websocket"
14 | )
15 |
16 | const (
17 | // Time allowed to write a message to the peer.
18 | writeWait = 10 * time.Second
19 |
20 | // Time allowed to read the next pong message from the peer.
21 | pongWait = 60 * time.Second
22 |
23 | // Send pings to peer with this period. Must be less than pongWait.
24 | pingPeriod = (pongWait * 9) / 10
25 |
26 | // Maximum message size allowed from peer.
27 | maxMessageSize = 512
28 | )
29 |
30 | var (
31 | newline = []byte{'\n'}
32 | space = []byte{' '}
33 | )
34 |
35 | var upgrader = websocket.Upgrader{
36 | ReadBufferSize: 1024,
37 | WriteBufferSize: 1024,
38 | }
39 |
40 | // Client is a middleman between the websocket connection and the hub.
41 | type Client struct {
42 | hub *Hub
43 |
44 | // The websocket connection.
45 | conn *websocket.Conn
46 |
47 | // Buffered channel of outbound messages.
48 | send chan interface{}
49 | }
50 |
51 | // readPump pumps messages from the websocket connection to the hub.
52 | //
53 | // The application runs readPump in a per-connection goroutine. The application
54 | // ensures that there is at most one reader on a connection by executing all
55 | // reads from this goroutine.
56 | func (c *Client) readPump() {
57 | defer func() {
58 | c.hub.unregister <- c
59 | c.conn.Close()
60 | }()
61 | c.conn.SetReadLimit(maxMessageSize)
62 | c.conn.SetReadDeadline(time.Now().Add(pongWait))
63 | c.conn.SetPongHandler(func(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
64 | for {
65 | _, message, err := c.conn.ReadMessage()
66 | if err != nil {
67 | if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
68 | log.Printf("error: %v", err)
69 | }
70 | break
71 | }
72 | message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))
73 | c.hub.broadcast <- message
74 | }
75 | }
76 |
77 | // writePump pumps messages from the hub to the websocket connection.
78 | //
79 | // A goroutine running writePump is started for each connection. The
80 | // application ensures that there is at most one writer to a connection by
81 | // executing all writes from this goroutine.
82 | func (c *Client) writePump() {
83 | ticker := time.NewTicker(pingPeriod)
84 | defer func() {
85 | ticker.Stop()
86 | c.conn.Close()
87 | }()
88 | for {
89 | select {
90 | case message, ok := <-c.send:
91 |
92 | c.conn.SetWriteDeadline(time.Now().Add(writeWait))
93 | if !ok {
94 | // The hub closed the channel.
95 | c.conn.WriteMessage(websocket.CloseMessage, []byte{})
96 | return
97 | }
98 |
99 | err := c.conn.WriteJSON(message) //NextWriter(websocket.TextMessage)
100 | if err != nil {
101 | return
102 | }
103 |
104 | case <-ticker.C:
105 | c.conn.SetWriteDeadline(time.Now().Add(writeWait))
106 | if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil {
107 | return
108 | }
109 | }
110 | }
111 | }
112 |
113 | // serveWs handles websocket requests from the peer.
114 | func serveWs(hub *Hub, w http.ResponseWriter, r *http.Request) {
115 | conn, err := upgrader.Upgrade(w, r, nil)
116 | if err != nil {
117 | log.Println(err)
118 | return
119 | }
120 | client := &Client{hub: hub, conn: conn, send: make(chan interface{}, 256)}
121 | client.hub.register <- client
122 |
123 | // Allow collection of memory referenced by the caller by doing all work in
124 | // new goroutines.
125 | go client.writePump()
126 | go client.readPump()
127 | }
128 |
--------------------------------------------------------------------------------
/Circuitcompiler/factorHandling.go:
--------------------------------------------------------------------------------
1 | package Circuitcompiler
2 |
3 | import (
4 | "crypto/sha256"
5 | "fmt"
6 | "github.com/mottla/go-R1CS-Compiler/utils"
7 | "math/big"
8 | "sort"
9 | "strings"
10 | )
11 |
12 | var bigZero = big.NewInt(0)
13 | var bigOne = big.NewInt(1)
14 |
15 | func (f Tokens) Len() int {
16 | return len(f)
17 | }
18 |
19 | func (f Tokens) Swap(i, j int) {
20 | f[i], f[j] = f[j], f[i]
21 | }
22 |
23 | func (f Tokens) Less(i, j int) bool {
24 | if strings.Compare(f[i].String(), f[j].String()) < 0 {
25 | return false
26 | }
27 | return true
28 | }
29 | func (f Token) CopyAndSetMultiplicative(v *big.Int) (n Token) {
30 | n = f.copy()
31 | n.value = v
32 | return
33 | }
34 |
35 | func (f Tokens) containsArgument() bool {
36 | if len(f) == 0 {
37 | return false
38 | }
39 | //if len(f) != 1 {
40 | // panic("not expected")
41 | //}
42 | for _, v := range f {
43 | if v.isArgument {
44 | return true
45 | }
46 | }
47 | return false
48 | }
49 |
50 | func (f Token) Negate() (n Token) {
51 | return f.CopyAndSetMultiplicative(new(big.Int).Neg(f.value))
52 | }
53 | func (f Tokens) Negate() (n Tokens) {
54 | n = make(Tokens, len(f))
55 | for i, v := range f {
56 | n[i] = v.Negate()
57 | }
58 | return
59 | }
60 | func (t Token) toFactors() Tokens {
61 | if t.value == nil {
62 | t.value = bigOne
63 | }
64 | return Tokens{t}
65 | }
66 |
67 | func (f Tokens) clone() (res Tokens) {
68 | res = make(Tokens, len(f))
69 | for k, v := range f {
70 | res[k] = v.copy()
71 | }
72 | return
73 | }
74 |
75 | func extractGCD(f Tokens) (Tokens, *big.Int) {
76 |
77 | gcd := f[0].value
78 | for i := 1; i < len(f); i++ {
79 | gcd = new(big.Int).GCD(nil, nil, f[i].value, gcd)
80 | }
81 | for i := 0; i < len(f); i++ {
82 | f[i].value = new(big.Int).Div(f[i].value, gcd)
83 |
84 | }
85 | return f, gcd
86 |
87 | }
88 |
89 | func hashFactorsToBig(f Tokens) *big.Int {
90 | sha := sha256.New()
91 | for _, fac := range f {
92 | sha.Write([]byte(fac.String()))
93 | }
94 | return new(big.Int).SetBytes(sha.Sum(nil))
95 | }
96 |
97 | func (fac Tokens) factorSignature() string {
98 | h := hashFactorsToBig(fac)
99 | return h.String()[:16]
100 | }
101 |
102 | func extractConstant(leftFactors, rightFactors Tokens) (gcd *big.Int, extractedLeftFactors, extractedRightFactors Tokens) {
103 |
104 | mulL, facL := factorSignature(leftFactors)
105 | mulR, facR := factorSignature(rightFactors)
106 |
107 | res := utils.Field.ArithmeticField.Mul(mulL, mulR)
108 |
109 | return res, facL, facR
110 | }
111 |
112 | func factorSignature(facs Tokens) (gcd *big.Int, extractedRightFactors Tokens) {
113 | facs = facs.clone()
114 | facs, gcd = extractGCD(facs)
115 | sort.Sort(facs)
116 | return gcd, facs
117 | }
118 |
119 | //multiplies factor elements and returns the result
120 | //in case the Tokens do not hold any constants and all inputs are distinct, the extractedConstants will be the concatenation of left+right
121 | func mulFactors(leftFactors, rightFactors Tokens) (result Tokens) {
122 |
123 | if len(leftFactors) < len(rightFactors) {
124 | tmp := leftFactors
125 | leftFactors = rightFactors
126 | rightFactors = tmp
127 | }
128 |
129 | for i, left := range leftFactors {
130 |
131 | for _, right := range rightFactors {
132 |
133 | leftFactors[i] = leftFactors[i].CopyAndSetMultiplicative(mulType(right.value, left.value, right.Type))
134 |
135 | }
136 | }
137 | return leftFactors
138 | }
139 | func mulFactor(factors Tokens, multipl Token) (result Tokens) {
140 |
141 | for i, left := range factors {
142 |
143 | factors[i] = factors[i].CopyAndSetMultiplicative(mulType(multipl.value, left.value, left.Type))
144 |
145 | }
146 | return factors
147 | }
148 | func divideFactors(leftFactors Tokens, rightFactor Token) (result Tokens) {
149 |
150 | for i, left := range leftFactors {
151 |
152 | leftFactors[i] = leftFactors[i].CopyAndSetMultiplicative(divType(rightFactor.value, left.value, left.Type))
153 |
154 | }
155 | return leftFactors
156 | }
157 |
158 | //adds two Tokens to one iff they are both are constants or of the same variable
159 | func (in *Tokens) Add(a Token) {
160 |
161 | for i, v := range *in {
162 | if v.equalDescription(a) {
163 | (*in)[i].value = addType(v.value, a.value, a.Type)
164 | return
165 | }
166 | }
167 | *in = append(*in, a)
168 |
169 | return
170 |
171 | }
172 |
173 | //returns the reduced sum of two input factor arrays
174 | //if no reduction was done, it returns the concatenation of the input arrays
175 | func (this Tokens) AddFactors(with Tokens) Tokens {
176 |
177 | for _, facRight := range with {
178 | this.Add(facRight)
179 | }
180 |
181 | return this
182 | }
183 |
184 | func (from Tokens) primitiveReturnfunction() (gives *function) {
185 | if len(from) == 0 {
186 | return &function{}
187 | }
188 | if len(from) == 1 {
189 | return from[0].primitiveReturnfunction()
190 | }
191 |
192 | return combineFunctions(Token{
193 | Type: ArithmeticOperatorToken,
194 | Identifier: "+",
195 | }, from[0].primitiveReturnfunction(), from[1:].primitiveReturnfunction(), &function{})
196 |
197 | }
198 |
199 | func combineConstraints(operation string, lc, rc *Task) *Task {
200 | c := &Task{
201 | Description: Token{
202 | Type: ArithmeticOperatorToken,
203 | Identifier: operation,
204 | },
205 | Inputs: []*Task{lc, rc}}
206 | return c
207 | }
208 |
209 | func combineFunctions(operation Token, l, r, context *function) *function {
210 |
211 | rmp := NewCircuit("", context)
212 | if len(l.OutputTypes) != 1 {
213 | panic("")
214 | }
215 | if eq, err := l.hasEqualDescription(r); !eq {
216 | panic(err)
217 | }
218 | if operation.Type == BinaryComperatorToken || operation.Type == BooleanOperatorToken {
219 | rmp.OutputTypes = []returnTypes{{
220 | typ: Token{
221 | Type: BOOL,
222 | },
223 | }}
224 | } else {
225 | rmp.OutputTypes = l.OutputTypes
226 | }
227 |
228 | idL, idR := "l", "r"
229 | rmp.functions[idL] = l
230 | rmp.functions[idR] = r
231 | rmp.taskStack.add(&Task{
232 | Description: operation,
233 | Inputs: []*Task{
234 | {
235 | Description: Token{
236 | Type: FUNCTION_CALL,
237 | Identifier: idL,
238 | },
239 | }, {
240 | Description: Token{
241 | Type: FUNCTION_CALL,
242 | Identifier: idR,
243 | },
244 | }},
245 | })
246 | return rmp
247 | }
248 |
249 | func checkRangeValidity(in *big.Int, tokenType TokenType) bool {
250 | switch tokenType {
251 | case BOOL:
252 | if v := in.Uint64(); v > 1 {
253 | panic(fmt.Sprintf("boolean expected, got %v", v))
254 | }
255 | case U8:
256 | if v := in.Uint64(); v > 1<<8 {
257 | panic(fmt.Sprintf("Uint8 expected, got %v", v))
258 | }
259 |
260 | case U16:
261 | if v := in.Uint64(); v > 1<<16 {
262 | panic(fmt.Sprintf("Uint16 expected, got %v", v))
263 | }
264 |
265 | case U32:
266 | if v := in.Uint64(); v > 1<<32 {
267 | panic(fmt.Sprintf("uint32 expected, got %v", v))
268 | }
269 |
270 | case U64: //cannot be reached. since uint64 conversion would fail anyway
271 | if v := in.Uint64(); v > ^uint64(1) {
272 | panic(fmt.Sprintf("uint64 expected, got %v", v))
273 | }
274 | case FIELD:
275 |
276 | }
277 | return true
278 | }
279 | func addType(l, r *big.Int, tokenType TokenType) *big.Int {
280 | checkRangeValidity(l, tokenType)
281 | checkRangeValidity(r, tokenType)
282 | switch tokenType {
283 | case BOOL:
284 | return new(big.Int).Xor(l, r)
285 | case U8:
286 | ll, rr := l.Uint64(), r.Uint64()
287 |
288 | return new(big.Int).SetUint64(uint64(uint8(ll) + uint8(rr)))
289 |
290 | case U16:
291 | ll, rr := l.Uint64(), r.Uint64()
292 |
293 | return new(big.Int).SetUint64(uint64(uint16(ll) + uint16(rr)))
294 |
295 | case U32:
296 | ll, rr := l.Uint64(), r.Uint64()
297 |
298 | return new(big.Int).SetUint64(uint64(uint32(ll) + uint32(rr)))
299 |
300 | case U64: //cannot be reached. since uint64 conversion would fail anyway
301 | ll, rr := l.Uint64(), r.Uint64()
302 |
303 | return new(big.Int).SetUint64(ll + rr)
304 |
305 | case FIELD:
306 | return utils.Field.ArithmeticField.Add(l, r)
307 |
308 | case DecimalNumberToken:
309 |
310 | return utils.Field.ArithmeticField.Add(l, r)
311 | }
312 | panic("")
313 | }
314 |
315 | func mulType(l, r *big.Int, tokenType TokenType) *big.Int {
316 | checkRangeValidity(l, tokenType)
317 | checkRangeValidity(r, tokenType)
318 | switch tokenType {
319 | case BOOL:
320 | return utils.Field.ArithmeticField.Mul(l, r)
321 | case U8:
322 | ll, rr := l.Uint64(), r.Uint64()
323 |
324 | return new(big.Int).SetUint64(uint64(uint8(ll) * uint8(rr)))
325 |
326 | case U16:
327 | ll, rr := l.Uint64(), r.Uint64()
328 |
329 | return new(big.Int).SetUint64(uint64(uint16(ll) * uint16(rr)))
330 |
331 | case U32:
332 | ll, rr := l.Uint64(), r.Uint64()
333 |
334 | return new(big.Int).SetUint64(uint64(uint32(ll) * uint32(rr)))
335 |
336 | case U64: //cannot be reached. since uint64 conversion would fail anyway
337 | ll, rr := l.Uint64(), r.Uint64()
338 |
339 | return new(big.Int).SetUint64(ll * rr)
340 |
341 | case FIELD:
342 | return utils.Field.ArithmeticField.Mul(l, r)
343 | case DecimalNumberToken:
344 | return utils.Field.ArithmeticField.Mul(l, r)
345 | }
346 | panic("")
347 | }
348 | func divType(l, r *big.Int, tokenType TokenType) *big.Int {
349 | checkRangeValidity(l, tokenType)
350 | checkRangeValidity(r, tokenType)
351 | switch tokenType {
352 | case BOOL:
353 | return utils.Field.ArithmeticField.Div(l, r)
354 | case U8:
355 | ll, rr := l.Uint64(), r.Uint64()
356 |
357 | return new(big.Int).SetUint64(uint64(uint8(ll) / uint8(rr)))
358 |
359 | case U16:
360 | ll, rr := l.Uint64(), r.Uint64()
361 |
362 | return new(big.Int).SetUint64(uint64(uint16(ll) / uint16(rr)))
363 |
364 | case U32:
365 | ll, rr := l.Uint64(), r.Uint64()
366 |
367 | return new(big.Int).SetUint64(uint64(uint32(ll) / uint32(rr)))
368 |
369 | case U64: //cannot be reached. since uint64 conversion would fail anyway
370 | ll, rr := l.Uint64(), r.Uint64()
371 |
372 | return new(big.Int).SetUint64(ll / rr)
373 |
374 | case FIELD:
375 | return utils.Field.ArithmeticField.Div(l, r)
376 | case DecimalNumberToken:
377 |
378 | }
379 | panic("")
380 | }
381 |
--------------------------------------------------------------------------------
/Circuitcompiler/factorHandling_test.go:
--------------------------------------------------------------------------------
1 | package Circuitcompiler
2 |
3 | import (
4 | "fmt"
5 | "math/big"
6 | "testing"
7 | )
8 |
9 | //Tokens are essential to identify, if a specific Gate has been computed already
10 | //eg. if we can extract a factor from a Gate that is independent of commutativity, multiplicativitz we will do much better, in finding and reusing old outputs do
11 | //minimize the multiplication Gate number
12 | // for example the Gate a*b == Gate b*a hence, we only need to compute one of both.
13 |
14 | func TestNewFactors(t *testing.T) {
15 | tks := Tokens{Token{
16 | Type: FIELD,
17 | Identifier: "",
18 | value: bigOne,
19 |
20 | isArgument: false,
21 |
22 | readInLine: 0,
23 | }}
24 | tks.Add(tks[0])
25 |
26 | tks.Add(Token{
27 | Type: FIELD,
28 | Identifier: "a",
29 | value: bigOne,
30 |
31 | isArgument: true,
32 | readInLine: 0,
33 | })
34 | fmt.Println(tks[0].String())
35 | tks.Add(Token{
36 | Type: FIELD,
37 | Identifier: "a",
38 | value: bigOne,
39 | isArgument: true,
40 | readInLine: 0,
41 | })
42 | fmt.Println(tks[0].String())
43 | tks.AddFactors(tks)
44 | fmt.Println(tks[0].String())
45 | fmt.Println(big.NewInt(0))
46 | }
47 |
48 | func TestToken_CopyAndSetMultiplicative(t *testing.T) {
49 | var a = 42
50 | var b = func() int { return a }
51 | a = 12
52 | fmt.Println(b())
53 |
54 | var c = []int{a, a}
55 | a = 3
56 | fmt.Println(c[1])
57 | }
58 |
--------------------------------------------------------------------------------
/Circuitcompiler/gate.go:
--------------------------------------------------------------------------------
1 | package Circuitcompiler
2 |
3 | import (
4 | "fmt"
5 | "github.com/mottla/go-R1CS-Compiler/utils"
6 | "math/big"
7 | "sort"
8 | )
9 |
10 | type Gate struct {
11 | identifier string
12 | leftIns Tokens //leftIns and RightIns after addition gates have been reduced. only multiplication gates remain
13 | rightIns Tokens
14 | outIns Tokens
15 | //extractedConstants *big.Int
16 | noNewOutput bool
17 |
18 | computeYourselfe func(witness *[]*big.Int, set utils.FastBool, indexMap map[string]int) bool
19 | }
20 |
21 | func (g Gate) String() string {
22 | return fmt.Sprintf("Gate: %v with left %v right %v out %v", g.identifier, g.leftIns, g.rightIns, g.outIns)
23 | }
24 |
25 | func (gate *Gate) ID() (id string) {
26 | //TODO should we include the multiplicative in the hash?
27 | if gate.identifier == "" {
28 | return gate.setAndGetID()
29 | }
30 | return gate.identifier
31 | }
32 |
33 | func (gate *Gate) setAndGetID() (id string) {
34 | //TODO rethink
35 | //a*b = c
36 | //b*a = c
37 | //b= a^-1 * c
38 | //a*b *c^-1 = 1
39 | sort.Sort(gate.leftIns)
40 | sort.Sort(gate.rightIns)
41 | l := hashFactorsToBig(gate.leftIns)
42 | r := hashFactorsToBig(gate.rightIns)
43 | //we Add the hashes of the multiplication part. a cheap way to consider the commutativity in the id creation to avoid duplicates such as a*b and b*a
44 | lr := new(big.Int).Add(l, r)
45 | sort.Sort(gate.outIns)
46 | o := hashFactorsToBig(gate.outIns)
47 | lr = new(big.Int).Mul(lr, o)
48 | gate.identifier = lr.String()[:16]
49 | return gate.identifier
50 | }
51 |
52 | // id * id^-1 = 1
53 | func inverseGate(id Tokens) (g *Gate) {
54 | g = &Gate{
55 | leftIns: id,
56 | outIns: Token{
57 | Type: DecimalNumberToken,
58 | }.toFactors(),
59 | }
60 | g.rightIns = Token{Identifier: g.ID()}.toFactors()
61 | return
62 | }
63 |
64 | func multiplicationGate(left, right Tokens) (g *Gate) {
65 | g = &Gate{
66 | leftIns: left,
67 | rightIns: right,
68 | }
69 | g.outIns = Token{Identifier: g.ID()}.toFactors()
70 | return
71 | }
72 |
73 | //ensures that either left*right=0
74 | func zeroConstraintGate(left, right Tokens) (g *Gate) {
75 | g = &Gate{
76 | leftIns: left,
77 | rightIns: right,
78 | noNewOutput: true,
79 | }
80 | return
81 | }
82 |
83 | // a/b = c -> a = b*c
84 | func divisionGate(a, b Tokens) (g *Gate) {
85 | g = &Gate{
86 | leftIns: b,
87 | outIns: a,
88 | }
89 | g.rightIns = Token{Identifier: g.ID()}.toFactors()
90 | return
91 | }
92 |
93 | // (1-id)* id = 0
94 | func zeroOrOneGate(id string) (g *Gate) {
95 | one := Token{
96 | Type: ARGUMENT,
97 | value: bigOne,
98 | }
99 |
100 | g = &Gate{
101 | leftIns: Tokens{one,
102 | Token{
103 | Identifier: id,
104 | }.Negate(),
105 | },
106 | rightIns: Token{
107 | Identifier: id,
108 | }.toFactors(),
109 | identifier: id,
110 | }
111 | return
112 | }
113 |
114 | // a xor b = c as arithmetic circuit (asserting that a,b \in {0,1}
115 | // 2a*b = a + b - c
116 | func xorGate(a, b Token) (g *Gate) {
117 |
118 | var mGate = new(Gate)
119 | //some dangerous stuff is happening here.. check later dude
120 | mGate.leftIns = Tokens{a.CopyAndSetMultiplicative(new(big.Int).Mul(a.value, big.NewInt(2)))}
121 | mGate.rightIns = Tokens{b}
122 | mGate.outIns = Tokens{a, b}
123 |
124 | xor := Token{Identifier: mGate.ID(), value: bigOne}
125 |
126 | mGate.outIns = append(mGate.outIns, xor.Negate())
127 |
128 | return mGate
129 | }
130 |
131 | // a or b = c as arithmetic circuit (asserting that a,b \in {0,1}
132 | // a*b = a + b - c
133 | func orGate(a, b Token) (g *Gate) {
134 |
135 | var mGate = new(Gate)
136 |
137 | mGate.leftIns = Tokens{a}
138 | mGate.rightIns = Tokens{b}
139 | mGate.outIns = Tokens{a, b}
140 |
141 | xor := Token{Identifier: mGate.ID(), value: bigOne}
142 | mGate.outIns = append(mGate.outIns, xor.Negate())
143 |
144 | return mGate
145 | }
146 |
147 | //left * 1 = right
148 | func equalityGate(left, right Tokens) (g *Gate) {
149 | one := Token{
150 | Type: DecimalNumberToken,
151 | }.toFactors()
152 | g = &Gate{
153 | leftIns: left,
154 | rightIns: one,
155 | outIns: right,
156 | noNewOutput: true,
157 | }
158 | return
159 | }
160 |
161 | // (in1+in2+... )*1 = newOut
162 | func summationGate(in Tokens) (g *Gate) {
163 | one := Token{
164 | Type: DecimalNumberToken,
165 | }.toFactors()
166 | g = &Gate{
167 | leftIns: in,
168 | rightIns: one,
169 | }
170 | g.outIns = Token{Identifier: g.ID()}.toFactors()
171 | return
172 | }
173 |
174 | func (gate *Gate) minimizeR1CSDescriptiveComplexity() {
175 |
176 | //g^(e1+e2+..) + (r1+r2+..)*(l1+l2+..) = (c1+c2+..)
177 | //if g^e is 0, we can try if the constraint
178 | //l * 1/c = 1/r or
179 | //r * 1/c = 1/l or
180 | //r * 1/c = 1/l or
181 | //1/r*1/l=1/c
182 | //is the better represenant regarding bit complexity
183 |
184 | }
185 |
--------------------------------------------------------------------------------
/Circuitcompiler/gateContainer.go:
--------------------------------------------------------------------------------
1 | package Circuitcompiler
2 |
3 | type gateContainer struct {
4 | orderedmGates []*Gate
5 | computedFactors map[string]bool
6 | splittedElements map[string][]string
7 | }
8 |
9 | func newGateContainer() *gateContainer {
10 | return &gateContainer{
11 | orderedmGates: []*Gate{},
12 | computedFactors: make(map[string]bool),
13 | splittedElements: map[string][]string{}, //the array stores the indices of the zeroOrOne check gates
14 | }
15 | }
16 | func (g *gateContainer) OrderedGates() []*Gate {
17 | return g.orderedmGates
18 | }
19 |
20 | func (g *gateContainer) completeFunction(f Tokens) {
21 |
22 | //if len f is 1, we can simpl
23 | //todo single number call is outdated
24 | if f == nil || len(f) == 0 || !f.containsArgument() {
25 | return
26 | }
27 | //if the function {..return x*1} , we dont introduce a new gate, as knowledge proof of a multiplication with 1 is trivial and not necessary
28 | if len(f) == 1 && (f[0].value == nil || f[0].value.Cmp(bigOne) == 0) {
29 | return
30 | }
31 | //the function returned but had a extracted constant
32 | // example
33 | //main (x,y){
34 | //var x = y*y*3
35 | //return 4*x }
36 | // x will be set as y*y, and the 3 will be stored aside. each time we access x, we include the 3
37 | // if we now return, we get the factor 12. we expect the prover to perform the computation x*12
38 | // Note that some optimization still could be done here. if a gate is not used by others, we could multiply the factor into it
39 | // insteead of creating a new addition gate
40 | g.Add(summationGate(f))
41 |
42 | }
43 |
44 | func (g *gateContainer) contains(tok string) bool {
45 | _, ex := g.computedFactors[tok]
46 | return ex
47 | }
48 |
49 | func (g *gateContainer) Add(gate *Gate) (id Token) {
50 |
51 | if !gate.leftIns.containsArgument() && !gate.rightIns.containsArgument() && !gate.outIns.containsArgument() {
52 | //panic("gate where no input is an argument?")
53 | }
54 |
55 | if !g.contains(gate.ID()) {
56 | g.computedFactors[gate.ID()] = true
57 | g.orderedmGates = append(g.orderedmGates, gate)
58 | } else {
59 | //fmt.Println("saved reuse of "+gate.String())
60 | }
61 | var ty TokenType
62 | if gate.rightIns != nil {
63 | ty = gate.rightIns[0].Type
64 | }
65 | if gate.leftIns != nil {
66 | ty |= gate.leftIns[0].Type
67 | }
68 | if gate.outIns != nil {
69 | ty |= gate.outIns[0].Type
70 | }
71 | return Token{
72 | //todo note that thats bs
73 | Type: ty,
74 | Identifier: gate.ID(),
75 | isArgument: true,
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/Circuitcompiler/hub.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package Circuitcompiler
6 |
7 | import (
8 | "fmt"
9 | "time"
10 | )
11 |
12 | // Hub maintains the set of active clients and broadcasts messages to the
13 | // clients.
14 | type Hub struct {
15 | // Registered clients.
16 | clients map[*Client]bool
17 |
18 | // Inbound messages from the clients.
19 | broadcast chan interface{}
20 |
21 | // Register requests from the clients.
22 | register chan *Client
23 |
24 | // Unregister requests from clients.
25 | unregister chan *Client
26 | }
27 |
28 | func newHub() *Hub {
29 | return &Hub{
30 | broadcast: make(chan interface{}),
31 | register: make(chan *Client),
32 | unregister: make(chan *Client),
33 | clients: make(map[*Client]bool),
34 | }
35 | }
36 |
37 | func newAddNodeMsg() addNodeAndLinksMsg {
38 | return addNodeAndLinksMsg{Typeus: "addNode", Links: []int{}}
39 | }
40 |
41 | type addNodeAndLinksMsg struct {
42 | Typeus string `json:"type"`
43 | Id int `json:"id"`
44 | Links []int `json:"connections"`
45 | }
46 |
47 | func newAgentStateMsg() agentStateMsg {
48 | return agentStateMsg{Typeus: "stateChanged", ColorCha: []colorChange{}, AddLinks: []linkChange{}, RemLinks: []linkChange{}}
49 | }
50 |
51 | type agentStateMsg struct {
52 | Typeus string `json:"type"`
53 | ColorCha []colorChange `json:"colorChange"`
54 | AddLinks []linkChange `json:"linkAdd"`
55 | RemLinks []linkChange `json:"linkRem"`
56 | }
57 | type colorChange struct {
58 | Id string `json:"target"`
59 | Color string `json:"color"`
60 | Label string `json:"label"`
61 | }
62 | type linkChange struct {
63 | Target string `json:"target"`
64 | Source string `json:"source"`
65 | }
66 | type agentState struct {
67 | colC colorChange
68 | addL linkChange
69 | remL linkChange
70 | }
71 |
72 | func (h *Hub) run() {
73 |
74 | tkr := time.NewTicker(time.Second * 15)
75 |
76 | for {
77 | select {
78 | case client := <-h.register:
79 | fmt.Println("Client registered")
80 | h.clients[client] = true
81 | //go start(h)
82 | panic("asdf")
83 | case client := <-h.unregister:
84 | fmt.Println("Client tries to unregister")
85 | if _, ok := h.clients[client]; ok {
86 | delete(h.clients, client)
87 | close(client.send)
88 |
89 | fmt.Println("Client unregistered")
90 | }
91 | case message := <-h.broadcast:
92 |
93 | switch cast := message.(type) {
94 | case addNodeAndLinksMsg:
95 | for client := range h.clients {
96 | select {
97 | case client.send <- message:
98 | default:
99 | close(client.send)
100 | delete(h.clients, client)
101 | }
102 | }
103 | case agentStateMsg:
104 | for client := range h.clients {
105 | select {
106 | case client.send <- message:
107 | default:
108 | close(client.send)
109 | delete(h.clients, client)
110 | }
111 | }
112 | case []byte:
113 | fmt.Printf("byte messag type dude %v", string(cast))
114 |
115 | for client := range h.clients {
116 | select {
117 | case client.send <- string(cast):
118 | default:
119 | close(client.send)
120 | delete(h.clients, client)
121 | }
122 | }
123 | default:
124 | fmt.Printf("dunno this messag type dude ")
125 |
126 | }
127 | case c := <-tkr.C:
128 | for client := range h.clients {
129 | select {
130 | case client.send <- c.Local().UTC().String():
131 | //case client.send <- []byte(`{"num":6,"strs":["a","b"]}`):
132 | default:
133 | close(client.send)
134 | delete(h.clients, client)
135 | }
136 | }
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/Circuitcompiler/lexer_test.go:
--------------------------------------------------------------------------------
1 | package Circuitcompiler
2 |
3 | import (
4 | "fmt"
5 | "math/big"
6 | "testing"
7 | )
8 |
9 | func TestHexNumberState(t *testing.T) {
10 | v, b := new(big.Int).SetString("ABB", 16)
11 | if !b {
12 | panic("asdf")
13 | }
14 | println(v)
15 | v, b = new(big.Int).SetString("AbB", 16)
16 | if !b {
17 | panic("asdf")
18 | }
19 | println(v.String())
20 | }
21 | func Test_LexerError2(t *testing.T) {
22 | //code2 := `def main(a):
23 | // for(a = 3; a<3; a+=1){
24 | // var d = (c * (1+b) * k)
25 | // }
26 | // return d `
27 | //
28 | code := `
29 | var a u64
30 |
31 | `
32 |
33 | fmt.Println(code)
34 | l := New(code, ProbablyWhitespaceState)
35 | l.Start()
36 | tok, done := l.NextToken()
37 | for !done {
38 | fmt.Printf("%v , %q \n", tok.Type, tok.Identifier)
39 | tok, done = l.NextToken()
40 | }
41 |
42 | fmt.Println("done")
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/Circuitcompiler/parser_test.go:
--------------------------------------------------------------------------------
1 | package Circuitcompiler
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 | )
7 |
8 | func TestBuild(t *testing.T) {
9 | c := []string{}
10 | ArrayStringBuild([]int64{2, 3, 4}, "", &c)
11 | fmt.Println(c)
12 | }
13 |
14 | func TestParser_PrepareFunctionHeader(t *testing.T) {
15 | code := `
16 | func test(a field, b func(a field))(field,field) {
17 |
18 | }
19 | `
20 | parser := NewParser(code, false)
21 | toks := parser.stackAllTokens()
22 | functionInput, rest := splitAtFirstHighestStringType(toks[3:], "{")
23 | fmt.Println(rest)
24 | fk := NewCircuit("", nil)
25 | parser.PrepareFunctionSignature(fk, functionInput)
26 | fmt.Println(fk)
27 | }
28 |
29 | func TestArray(t *testing.T) {
30 | code := `a[4][3]`
31 | parser := NewParser(code, false)
32 | toks := parser.stackAllTokens()
33 | toks = toks[:len(toks)-1]
34 | ct := Task{}
35 | parser.parseExpression(toks, NewCircuit("", &function{}), &Task{})
36 | fmt.Println(ct)
37 | }
38 | func TestNewParse(t *testing.T) {
39 | code := `
40 | func main(x bool[4][5],y bool)(field) {
41 | bool[4][3] in = [[4,1,1],[1,1,1],[1,1,1],[1,1,1]]
42 | return x[1][1]*in[0][0]
43 | }
44 | `
45 | p := Parse(code)
46 | container := p.Execute()
47 |
48 | gates := container.OrderedGates()
49 | fmt.Println("\n generating R1CS")
50 | r1cs := p.GatesToR1CS(gates)
51 | fmt.Printf("number of gates %v, witness length %v \n ", r1cs.NumberOfGates, r1cs.WitnessLength)
52 | //
53 | fmt.Println(r1cs.L)
54 | fmt.Println(r1cs.R)
55 | fmt.Println(r1cs.O)
56 | }
57 |
58 | func TestNewParse2(t *testing.T) {
59 | code := `
60 | func mul(x bool,y bool)(bool){
61 | return x*y
62 | }
63 |
64 | func mul2(x bool,y bool)(bool,bool){
65 | return x*x,y*y
66 | }
67 |
68 | func mul3(x bool,y func(x bool,y bool)(bool) )(field){
69 | return y(x,x)
70 | }
71 |
72 | func main(x bool,y field)(field) {
73 | #func m5(x bool)(bool){return mul(5,x)}
74 | x,x = mul2(x,x)
75 | return mul3(x,mul)
76 | }
77 |
78 | `
79 | p := Parse(code)
80 | container := p.Execute()
81 |
82 | gates := container.OrderedGates()
83 | fmt.Println("\n generating R1CS")
84 | r1cs := p.GatesToR1CS(gates)
85 | fmt.Printf("number of gates %v, witness length %v \n ", r1cs.NumberOfGates, r1cs.WitnessLength)
86 | //
87 | fmt.Println(r1cs.L)
88 | fmt.Println(r1cs.R)
89 | fmt.Println(r1cs.O)
90 | }
91 |
92 | //only to see the difference between the split funcitons
93 | func TestParser_SplitAt(t *testing.T) {
94 | toks := []Token{
95 | {
96 | Identifier: "a",
97 | },
98 | {
99 | Identifier: "b",
100 | },
101 | {
102 | Identifier: "c",
103 | },
104 | {
105 | Identifier: "a",
106 | },
107 | {
108 | Identifier: "e",
109 | },
110 | {
111 | Identifier: ")",
112 | },
113 | {
114 | Identifier: "a",
115 | },
116 | }
117 |
118 | fmt.Println(splitTokensAtFirstString(toks, ")"))
119 |
120 | fmt.Println(splitAt(toks, ")"))
121 |
122 | fmt.Println(splitAtClosingBrackets(toks))
123 |
124 | }
125 |
126 | //only to see the difference between the split funcitons
127 | func TestParser_StripOfBrackets(t *testing.T) {
128 | toks := []Token{
129 | {
130 | Identifier: "(",
131 | },
132 | {
133 | Identifier: "b",
134 | },
135 | {
136 | Identifier: "c",
137 | },
138 | {
139 | Identifier: "a",
140 | },
141 | {
142 | Identifier: "e",
143 | },
144 | {
145 | Identifier: "g",
146 | },
147 | {
148 | Identifier: ")",
149 | },
150 | }
151 | fmt.Println(toks)
152 | fmt.Println(stripOfBrackets(toks))
153 | }
154 |
--------------------------------------------------------------------------------
/Circuitcompiler/rune_stack.go:
--------------------------------------------------------------------------------
1 | package Circuitcompiler
2 |
3 | type runeNode struct {
4 | r rune
5 | next *runeNode
6 | }
7 |
8 | type runeStack struct {
9 | start *runeNode
10 | linebreaksOnStack int
11 | }
12 |
13 | func newRuneStack() runeStack {
14 | return runeStack{}
15 | }
16 |
17 | func (s *runeStack) push(r rune) {
18 | node := &runeNode{r: r}
19 | if s.start == nil {
20 | s.start = node
21 | } else {
22 | node.next = s.start
23 | s.start = node
24 | }
25 |
26 | }
27 |
28 | func (s *runeStack) pop() rune {
29 | if s.start == nil {
30 | return EOFRune
31 | } else {
32 | n := s.start
33 | s.start = n.next
34 | return n.r
35 | }
36 | }
37 |
38 | func (s *runeStack) clear() {
39 | s.start = nil
40 | }
41 |
--------------------------------------------------------------------------------
/Circuitcompiler/server.go:
--------------------------------------------------------------------------------
1 | package Circuitcompiler
2 |
3 | import (
4 | "log"
5 | "net/http"
6 | )
7 |
8 | func StartServer(addr *string) *Hub {
9 | hub := newHub()
10 | go hub.run()
11 |
12 | http.Handle("/", http.FileServer(http.Dir("./Circuitcompiler/web_vivagraph")))
13 |
14 | http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
15 | serveWs(hub, w, r)
16 | })
17 | go func() {
18 | err := http.ListenAndServe(*addr, nil)
19 | if err != nil {
20 |
21 | log.Fatal("ListenAndServe: ", err)
22 | }
23 | }()
24 |
25 | return hub
26 | }
27 |
--------------------------------------------------------------------------------
/Circuitcompiler/visualizer.go:
--------------------------------------------------------------------------------
1 | package Circuitcompiler
2 |
3 | //func start(hub *Hub) {
4 | //
5 | // code := testPrograms.TestPrograms[3]
6 | //
7 | // program := Parse(code.Code, true)
8 | // container := program.Execute()
9 | // gates := container.OrderedGates()
10 | // res := newAgentStateMsg()
11 | //
12 | // for _, g := range gates {
13 | //
14 | // //if g.gateType == additionGate {
15 | // // res.ColorCha = append(res.ColorCha, colorChange{
16 | // // Id: g.identifier,
17 | // // Color: "#FFD6E7",
18 | // // Label: "+",
19 | // // })
20 | // //}
21 | // //if g.gateType == multiplicationGate {
22 | // res.ColorCha = append(res.ColorCha, colorChange{
23 | // Id: g.identifier,
24 | // Color: "#AAD8D8",
25 | // Label: "x",
26 | // })
27 | // //}
28 | //
29 | // for _, l := range g.leftIns {
30 | //
31 | // if l.Typ.Type == DecimalNumberToken {
32 | // res.ColorCha = append(res.ColorCha, colorChange{
33 | // Id: g.identifier,
34 | // Color: "#F6C3B7",
35 | // //Label: l.String(),
36 | // })
37 | // }
38 | //
39 | // res.AddLinks = append(res.AddLinks, linkChange{
40 | // Target: g.identifier,
41 | // Source: l.Typ.Identifier,
42 | // })
43 | // }
44 | // for _, l := range g.rightIns {
45 | // if l.Typ.Type == DecimalNumberToken {
46 | // res.ColorCha = append(res.ColorCha, colorChange{
47 | // Id: g.identifier,
48 | // Color: "#BDEFDB",
49 | // //Label: l.String(),
50 | // })
51 | // }
52 | //
53 | // res.AddLinks = append(res.AddLinks, linkChange{
54 | // Target: g.identifier,
55 | // Source: l.Typ.Identifier,
56 | // })
57 | // }
58 | // for _, l := range g.outIns {
59 | //
60 | // res.AddLinks = append(res.AddLinks, linkChange{
61 | // Target: g.identifier,
62 | // Source: l.Typ.Identifier,
63 | // })
64 | // }
65 | //
66 | // }
67 | // hub.broadcast <- res
68 | //
69 | // return
70 | //}
71 |
--------------------------------------------------------------------------------
/Circuitcompiler/visualizer_test.go:
--------------------------------------------------------------------------------
1 | package Circuitcompiler
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "testing"
7 | )
8 |
9 | var addr = flag.String("addr", "127.0.0.1:8081", "http service address")
10 |
11 | func Test(t *testing.T) {
12 | StartServer(addr)
13 | fmt.Println("Server is running")
14 | <-make(chan bool)
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/Circuitcompiler/web_g6/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mottla/go-R1CS-Compiler/031a8c5ac1b75340dc9acd45c86b2b7166091d8a/Circuitcompiler/web_g6/favicon.ico
--------------------------------------------------------------------------------
/Circuitcompiler/web_g6/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | VivaGraphs webgl dynamic graph test page
6 |
7 |
8 |
9 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/Circuitcompiler/web_g6/index.js:
--------------------------------------------------------------------------------
1 | /*global Viva*/
2 | var colors = [
3 | 0x1f77b4ff, 0xaec7e8ff,
4 | 0xff7f0eff, 0xffbb78ff,
5 | 0x2ca02cff, 0x98df8aff,
6 | 0xd62728ff, 0xff9896ff,
7 | 0x9467bdff, 0xc5b0d5ff,
8 | 0x8c564bff, 0xc49c94ff,
9 | 0xe377c2ff, 0xf7b6d2ff,
10 | 0x7f7f7fff, 0xc7c7c7ff,
11 | 0xbcbd22ff, 0xdbdb8dff,
12 | 0x17becfff, 0x9edae5ff
13 | ];
14 |
15 |
16 |
17 | function onLoad() {
18 |
19 | const container = document.getElementById('graph1');
20 | const width = container.scrollWidth;
21 | const height = container.scrollHeight || 500;
22 | const graph = new G6.Graph({
23 | container: 'graph1',
24 | width,
25 | height,
26 | modes: {
27 | default: ['drag-canvas', 'drag-node', 'zoom-canvas'],
28 | },
29 | animate: true,
30 | defaultNode: {
31 | size: 20,
32 | style: {
33 | lineWidth: 2,
34 | stroke: '#5B8FF9',
35 | fill: '#C6E5FF',
36 | },
37 | },
38 | defaultEdge: {
39 | size: 2,
40 | color: '#e2e2e2',
41 | style: {
42 | endArrow: {
43 | path: 'M 0,0 L 8,4 L 8,-4 Z',
44 | fill: '#e2e2e2',
45 | },
46 | },
47 | },layout: {
48 | type: 'gForce',
49 | gpuEnable : true,
50 | // nodeStrength: 30,
51 | //collideStrength: 0.7,
52 | // alphaDecay: 0.01,
53 | // preventOverlap: true,
54 | maxIteration: 1000,
55 | },
56 |
57 | });
58 | const model = {
59 | id: 'node',
60 | label: 'node',
61 | address: 'cq',
62 | x: 200,
63 | y: 150,
64 | style: {
65 | fill: 'blue',
66 | },
67 | size: 100,
68 | };
69 | const model2 = {
70 | id: 'node2',
71 | label: 'node',
72 | address: 'cq',
73 | x: 200,
74 | y: 150,
75 | style: {
76 | fill: 'red',
77 | },
78 | size: 100,
79 | };
80 | graph.addItem('node', model);
81 | const g = graph.findById('node2')
82 | if (g == undefined) {
83 | graph.addItem('node', model2);
84 | graph.addItem('edge', {source: 'node', target: 'node2'})
85 | graph.addItem('edge', {source: 'node', target: 'node2'})
86 | }
87 |
88 |
89 | graph.render()
90 | const forceLayout = graph.get('layoutController').layoutMethod;
91 | graph.on('node:dragstart', function (e) {
92 | graph.layout();
93 | refreshDragedNodePosition(e);
94 | });
95 | graph.on('node:drag', function (e) {
96 | forceLayout.execute();
97 | refreshDragedNodePosition(e);
98 | });
99 | graph.on('node:dragend', function (e) {
100 | e.item.get('model').fx = null;
101 | e.item.get('model').fy = null;
102 | });
103 |
104 | if (typeof window !== 'undefined')
105 | window.onresize = () => {
106 | if (!graph || graph.get('destroyed')) return;
107 | if (!container || !container.scrollWidth || !container.scrollHeight) return;
108 | graph.changeSize(container.scrollWidth, container.scrollHeight);
109 | };
110 |
111 |
112 | function refreshDragedNodePosition(e) {
113 | const model = e.item.get('model');
114 | model.fx = e.x;
115 | model.fy = e.y;
116 | }
117 |
118 |
119 | var conn;
120 | var msg = document.getElementById("msg");
121 | var log = document.getElementById("log");
122 |
123 | function appendLog(item) {
124 | var doScroll = log.scrollTop > log.scrollHeight - log.clientHeight - 1;
125 | log.appendChild(item);
126 | if (doScroll) {
127 | log.scrollTop = log.scrollHeight - log.clientHeight;
128 | }
129 | }
130 |
131 | document.getElementById("form").onsubmit = function () {
132 | if (!conn) {
133 | return false;
134 | }
135 | if (!msg.value) {
136 | return false;
137 | }
138 | conn.send(msg.value);
139 | msg.value = "";
140 | return false;
141 | };
142 |
143 |
144 | if (window["WebSocket"]) {
145 | conn = new WebSocket("ws://" + document.location.host + "/ws");
146 | conn.onclose = function (evt) {
147 | var item = document.createElement("div");
148 | item.innerHTML = "Connection closed.";
149 | appendLog(item);
150 | };
151 |
152 | conn.onmessage = function (evt) {
153 |
154 |
155 | var msg = JSON.parse(evt.data);
156 |
157 |
158 | switch (msg.type) {
159 | case "message":
160 | var messages = msg.text.split('\n');
161 | for (var i = 0; i < messages.length; i++) {
162 | var item = document.createElement("div");
163 | item.innerText = messages[i];
164 | appendLog(item);
165 | }
166 | break;
167 |
168 | case "stateChanged":
169 | console.log("Put a message here.")
170 |
171 | for (var i = 0; i < msg.linkAdd.length; i++) {
172 | if (graph.findById(msg.linkAdd[i].target) == undefined) {
173 | graph.addItem('node', {id: '' + msg.linkAdd[i].target,});
174 | }
175 | if (graph.findById(msg.linkAdd[i].source) == undefined) {
176 | graph.addItem('node', {id: '' + msg.linkAdd[i].source,});
177 | }
178 |
179 | const e = graph.findById('edge' + msg.linkAdd[i].target + msg.linkAdd[i].source)
180 | if (e != undefined) {
181 | e.update({type: 'arc', curveOffset: (((e.getTarget()).getEdges()).length) * 10})
182 | graph.addItem('edge', {
183 | source: '' + msg.linkAdd[i].source,
184 | target: '' + msg.linkAdd[i].target,
185 | type: 'arc',
186 | curveOffset: (((e.getTarget()).getEdges()).length) * -10,
187 | });
188 |
189 | } else {
190 | graph.addItem('edge', {
191 | id: 'edge' + msg.linkAdd[i].target + msg.linkAdd[i].source,
192 | source: '' + msg.linkAdd[i].source,
193 | target: '' + msg.linkAdd[i].target,
194 |
195 | });
196 | }
197 | }
198 | for (var i = 0; i < msg.colorChange.length; i++) {
199 | const e = graph.findById('' + msg.colorChange[i].target)
200 | if (e != undefined) {
201 | e.update({
202 | label: msg.colorChange[i].label,
203 | style : {color : msg.colorChange[i].color},
204 |
205 | })
206 | }
207 | }
208 | graph.refresh();
209 | break;
210 | case
211 | "graph"
212 | :
213 |
214 | var item = document.createElement("div");
215 | item.innerText = "graph " + msg.type;
216 | appendLog(item);
217 | break;
218 | default:
219 | var item = document.createElement("div");
220 | item.innerText = msg;
221 | appendLog(item);
222 | break;
223 | }
224 | }
225 | ;
226 |
227 |
228 |
229 | } else {
230 | var item = document.createElement("div");
231 | item.innerHTML = "Your browser does not support WebSockets.";
232 | appendLog(item);
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/Circuitcompiler/web_vivagraph/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mottla/go-R1CS-Compiler/031a8c5ac1b75340dc9acd45c86b2b7166091d8a/Circuitcompiler/web_vivagraph/favicon.ico
--------------------------------------------------------------------------------
/Circuitcompiler/web_vivagraph/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | VivaGraphs webgl dynamic graph test page
6 |
7 |
8 |
9 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
117 |
118 |
119 |
120 |
121 |
Use Shift + Mouse to draw rectangle and select nodes
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/Circuitcompiler/web_vivagraph/index.js:
--------------------------------------------------------------------------------
1 | /*global Viva*/
2 | var colors = [
3 | 0x1f77b4ff, 0xaec7e8ff,
4 | 0xff7f0eff, 0xffbb78ff,
5 | 0x2ca02cff, 0x98df8aff,
6 | 0xd62728ff, 0xff9896ff,
7 | 0x9467bdff, 0xc5b0d5ff,
8 | 0x8c564bff, 0xc49c94ff,
9 | 0xe377c2ff, 0xf7b6d2ff,
10 | 0x7f7f7fff, 0xc7c7c7ff,
11 | 0xbcbd22ff, 0xdbdb8dff,
12 | 0x17becfff, 0x9edae5ff
13 | ];
14 |
15 |
16 | function beginRemoveNodesLoop(graph) {
17 | var nodesLeft = [];
18 | graph.forEachNode(function (node) {
19 | nodesLeft.push(node.id);
20 | });
21 |
22 | var removeInterval = setInterval(function () {
23 | var nodesCount = nodesLeft.length;
24 |
25 | if (nodesCount > 0) {
26 | var nodeToRemove = Math.min((Math.random() * nodesCount) << 0, nodesCount - 1);
27 |
28 | graph.removeNode(nodesLeft[nodeToRemove]);
29 | nodesLeft.splice(nodeToRemove, 1);
30 | }
31 |
32 | if (nodesCount === 0) {
33 | clearInterval(removeInterval);
34 | setTimeout(function () {
35 | beginAddNodesLoop(graph);
36 | }, 100);
37 | }
38 | }, 100);
39 | }
40 |
41 | function beginAddNodesLoop(graph) {
42 | var i = 0, m = 10, n = 50;
43 | var addInterval = setInterval(function () {
44 | graph.beginUpdate();
45 |
46 | for (var j = 0; j < m; ++j) {
47 | var node = i + j * n;
48 | if (i > 0) {
49 | graph.addLink(node, i - 1 + j * n);
50 | }
51 | if (j > 0) {
52 | graph.addLink(node, i + (j - 1) * n);
53 | }
54 | }
55 | i++;
56 | graph.endUpdate();
57 |
58 | if (i >= n) {
59 | clearInterval(addInterval);
60 | setTimeout(function () {
61 | beginRemoveNodesLoop(graph);
62 | }, 10000);
63 | }
64 | }, 100);
65 | }
66 |
67 | function onLoad() {
68 | var conn;
69 | var msg = document.getElementById("msg");
70 | var log = document.getElementById("log");
71 |
72 | function appendLog(item) {
73 | var doScroll = log.scrollTop > log.scrollHeight - log.clientHeight - 1;
74 | log.appendChild(item);
75 | if (doScroll) {
76 | log.scrollTop = log.scrollHeight - log.clientHeight;
77 | }
78 | }
79 |
80 | document.getElementById("form").onsubmit = function () {
81 | if (!conn) {
82 | return false;
83 | }
84 | if (!msg.value) {
85 | return false;
86 | }
87 | conn.send(msg.value);
88 | msg.value = "";
89 | return false;
90 | };
91 |
92 |
93 | var graph = Viva.Graph.graph();
94 |
95 | var layout = Viva.Graph.Layout.forceDirected(graph, {
96 | springLength: 40,
97 | springCoeff: 0.0001,
98 | dragCoeff: 0.09,
99 | gravity: -3,
100 | theta: 0.08
101 | });
102 |
103 | var graphics = Viva.Graph.View.webglGraphics();
104 | graphics
105 | .node(function (node) {
106 | return Viva.Graph.View.webglSquare(20, 0xc49c94ff);
107 | })
108 | .link(function (link) {
109 | return Viva.Graph.View.webglLine(colors[(Math.random() * colors.length) << 0]);
110 | });
111 |
112 | var renderer = Viva.Graph.View.renderer(graph,
113 | {
114 | layout: layout,
115 | graphics: graphics,
116 | container: document.getElementById('graph1'),
117 | renderLinks: true
118 | });
119 | var multiSelectOverlay;
120 | renderer.run(50);
121 |
122 | //graph.addLink(1, 2)
123 | //beginAddNodesLoop(graph);
124 | l = layout;
125 |
126 | j = 1000;
127 |
128 | if (window["WebSocket"]) {
129 | conn = new WebSocket("ws://" + document.location.host + "/ws");
130 | conn.onclose = function (evt) {
131 | var item = document.createElement("div");
132 | item.innerHTML = "Connection closed.";
133 | appendLog(item);
134 | };
135 |
136 | document.addEventListener('keydown', function(e) {
137 | if (e.which === 16 && !multiSelectOverlay) { // shift key
138 | multiSelectOverlay = startMultiSelect(graph, renderer, layout);
139 | }
140 | });
141 | document.addEventListener('keyup', function(e) {
142 | if (e.which === 16 && multiSelectOverlay) {
143 | multiSelectOverlay.destroy();
144 | multiSelectOverlay = null;
145 | }
146 | });
147 |
148 | conn.onmessage = function (evt) {
149 |
150 |
151 | var msg = JSON.parse(evt.data);
152 |
153 |
154 | switch (msg.type) {
155 | case "message":
156 | var messages = msg.text.split('\n');
157 | for (var i = 0; i < messages.length; i++) {
158 | var item = document.createElement("div");
159 | item.innerText = messages[i];
160 | appendLog(item);
161 | }
162 | break;
163 |
164 | case "stateChanged":
165 | for (var i = 0; i < msg.linkAdd.length; i++) {
166 | if (!graph.getNode(msg.linkAdd[i].target)) {
167 | graph.addNode(msg.linkAdd[i].target);
168 | }
169 | if (!graph.getNode(msg.linkAdd[i].source)) {
170 | graph.addNode(msg.linkAdd[i].source);
171 | }
172 | if (!graph.getLink(msg.linkAdd[i].target, msg.linkAdd[i].source)) {
173 | graph.addLink(msg.linkAdd[i].target, msg.linkAdd[i].source);
174 | }
175 | }
176 |
177 | for (var i = 0; i < msg.linkRem.length; i++) {
178 | // var link = graph.hasLink(msg.linkRem[i].id, msg.linkRem[i].link)
179 | // graph.removeLink(link);
180 | }
181 | for (var i = 0; i < msg.colorChange.length; i++) {
182 | // var nod = graphics.getNodeUI(msg.colorChange[i].id);
183 | // nod.color = msg.colorChange[i].color;
184 | }
185 | renderer.rerender()
186 |
187 | break;
188 | case "graph":
189 |
190 | var item = document.createElement("div");
191 | item.innerText = "graph " + msg.type;
192 | appendLog(item);
193 | break;
194 | default:
195 | var item = document.createElement("div");
196 | item.innerText = msg;
197 | appendLog(item);
198 | break;
199 | }
200 | };
201 |
202 | } else {
203 | var item = document.createElement("div");
204 | item.innerHTML = "Your browser does not support WebSockets.";
205 | appendLog(item);
206 | }
207 | }
208 |
209 | function startMultiSelect(graph, renderer, layout) {
210 | var graphics = renderer.getGraphics();
211 | var domOverlay = document.querySelector('.graph-overlay');
212 | var overlay = createOverlay(domOverlay);
213 | overlay.onAreaSelected(handleAreaSelected);
214 |
215 | return overlay;
216 |
217 | function handleAreaSelected(area) {
218 | // For the sake of this demo we are using silly O(n) implementation.
219 | // Could be improved with spatial indexing if required.
220 | var topLeft = graphics.transformClientToGraphCoordinates({
221 | x: area.x,
222 | y: area.y
223 | });
224 |
225 | var bottomRight = graphics.transformClientToGraphCoordinates({
226 | x: area.x + area.width,
227 | y: area.y + area.height
228 | });
229 |
230 | graph.forEachNode(higlightIfInside);
231 | renderer.rerender();
232 |
233 |
234 |
235 | function higlightIfInside(node) {
236 | var nodeUI = graphics.getNodeUI(node.id);
237 | if (isInside(node.id, topLeft, bottomRight)) {
238 | nodeUI.color = 0xFFA500ff;
239 | nodeUI.size = 20;
240 | }
241 | // else {
242 | // nodeUI.color = 0x009ee8ff;
243 | // nodeUI.size = 10;
244 | // }
245 | }
246 |
247 | function isInside(nodeId, topLeft, bottomRight) {
248 | var nodePos = layout.getNodePosition(nodeId);
249 | return (topLeft.x < nodePos.x && nodePos.x < bottomRight.x &&
250 | topLeft.y < nodePos.y && nodePos.y < bottomRight.y);
251 | }
252 | }
253 | }
254 |
255 | function createOverlay(overlayDom) {
256 | var selectionClasName = 'graph-selection-indicator';
257 | var selectionIndicator = overlayDom.querySelector('.' + selectionClasName);
258 | if (!selectionIndicator) {
259 | selectionIndicator = document.createElement('div');
260 | selectionIndicator.className = selectionClasName;
261 | overlayDom.appendChild(selectionIndicator);
262 | }
263 |
264 | var notify = [];
265 | var dragndrop = Viva.Graph.Utils.dragndrop(overlayDom);
266 | var selectedArea = {
267 | x: 0,
268 | y: 0,
269 | width: 0,
270 | height: 0
271 | };
272 | var startX = 0;
273 | var startY = 0;
274 |
275 | dragndrop.onStart(function(e) {
276 | startX = selectedArea.x = e.clientX;
277 | startY = selectedArea.y = e.clientY;
278 | selectedArea.width = selectedArea.height = 0;
279 |
280 | updateSelectedAreaIndicator();
281 | selectionIndicator.style.display = 'block';
282 | });
283 |
284 | dragndrop.onDrag(function(e) {
285 | recalculateSelectedArea(e);
286 | updateSelectedAreaIndicator();
287 | notifyAreaSelected();
288 | });
289 |
290 | dragndrop.onStop(function() {
291 | selectionIndicator.style.display = 'none';
292 | });
293 |
294 | overlayDom.style.display = 'block';
295 |
296 | return {
297 | onAreaSelected: function(cb) {
298 | notify.push(cb);
299 | },
300 | destroy: function () {
301 | overlayDom.style.display = 'none';
302 | dragndrop.release();
303 | }
304 | };
305 |
306 | function notifyAreaSelected() {
307 | notify.forEach(function(cb) {
308 | cb(selectedArea);
309 | });
310 | }
311 |
312 | function recalculateSelectedArea(e) {
313 | selectedArea.width = Math.abs(e.clientX - startX);
314 | selectedArea.height = Math.abs(e.clientY - startY);
315 | selectedArea.x = Math.min(e.clientX, startX);
316 | selectedArea.y = Math.min(e.clientY, startY);
317 | }
318 |
319 | function updateSelectedAreaIndicator() {
320 | selectionIndicator.style.left = selectedArea.x + 'px';
321 | selectionIndicator.style.top = selectedArea.y + 'px';
322 | selectionIndicator.style.width = selectedArea.width + 'px';
323 | selectionIndicator.style.height = selectedArea.height + 'px';
324 | }
325 | }
326 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # go-R1CS Compiler
2 |
3 | **UNDER CONSTRUCTION**
4 |
5 |
6 | **Circuit Language**
7 | A subset of Golang (with slight modifications), suitable for the creation of Non-Interactive Succinct Arguments, such as zkSNARKs.
8 | This projects goal is to provide a compiler that translates Go-code into R1CS, which is the compilation target
9 | and starting point for various zkSNARK constructions.
10 |
11 | -This compiler currently supports the creation of Groth16 zkSNARKs.
12 |
13 | -Comes with JS graph rendering support to visualize the generated arithmetic circuit if needed.
14 |
15 | # Language
16 |
17 | ## main
18 |
19 | as in Go, every program starts with the function 'main'
20 |
21 | ```
22 | func main(){
23 | #this is a comment
24 | }
25 | ```
26 |
27 | main can be fed with an arbitrary amount of single arguments and n-dimensional static size arrays of single values.
28 | Main does not support functions as inputs.
29 |
30 | ```
31 | func main(a bool,b [2]uint32, c field, d uint64){
32 |
33 | }
34 | ```
35 |
36 | ## Declare public inputs
37 |
38 | In order to declare, which of the Main-Function inputs will be part of the public statement of the SNARK, write
39 |
40 | ```
41 | func main(a bool,b [2][3]uint32, c field, d uint64){
42 | public{
43 | a,
44 | b[1][1],
45 | c
46 | }
47 | }
48 | ```
49 |
50 |
51 | ## variables
52 |
53 | Variable assignment and overloading follows the same logic as in Golang:
54 |
55 | ```
56 | var a = 42*17 # is now a field type element
57 | # var a = x*x -> Error- variable a already declared
58 | # a = true -> type missmatch. Field expected, got bool
59 | var b = uint32(235)
60 |
61 | #declare array
62 | var c = [2]uint32{b,b+2}
63 |
64 | #declare function. Functions can return functions or take them as arguments
65 | var d = func(x field, b func()(bool) , c [4]bool)( func()(field)) {
66 | return 42
67 | }
68 |
69 | }
70 | ```
71 |
72 |
73 | ## Function preloading
74 |
75 | At this point we extended Go by this cool functionality.
76 | One now can partially preload a function
77 |
78 | ```
79 | func main(x field){
80 | var multiply = func(a field,b field)(field){return a*b}
81 | var multiplyBy5 = multiply(5)
82 | multiplyBy5(x) #is now the same as multiply(5,x)
83 | }
84 | ```
85 |
86 | ## Operations
87 |
88 | | Operator | Description | Remark |
89 | |----------|:-------------:|------:|
90 | | + | addition | |
91 | | * | multiplication | |
92 | | - | subtraction | |
93 | | / | division| |
94 | | ** | exponentiation | *|
95 | | << | left shift| * |
96 | | >> | right-shift | * |
97 | | <<< | rotate-left | * |
98 | | >>> | rotate-right | * |
99 | | & | bitwise-and | |
100 | | | | bitwise-or | |
101 | | ^ | bitwise-xor | |
102 | | == | equality | |
103 | | != | un-equality | |
104 |
105 | *rhs must be fixed at compile-time
106 |
107 |
108 | ## if-else if-else
109 |
110 | in order to create braching conditions, write:
111 |
112 | ```
113 | if expression1{
114 | ...
115 | }else if expression2{
116 | ...
117 | }else if expression3{
118 | ...
119 | }else{
120 | ...
121 | }
122 | ```
123 |
124 | note that we currently only support static decidable branching conditions
125 |
126 | ## arrays
127 |
128 | tba.
129 |
130 | # SNARK stuff
131 |
132 | ## euquality assertion gate
133 |
134 | in order to create an equality assertion constraint write
135 |
136 | ```
137 | equal(expression1,expression2)
138 | ```
139 |
140 | example: in order to prove knowledge of a square root of some input y, write
141 |
142 | ```
143 | func main(x field,y field){
144 | public{y}
145 | equal(x*x,y)
146 | }
147 | ```
148 |
149 | ## split
150 |
151 | to split a value into its bit representatives write
152 |
153 | ```
154 | SPLIT(x)
155 | ```
156 |
157 | now the i'th bit of x can be accessed with x[i], where x[0] is the least significant bit
158 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "github.com/mottla/go-R1CS-Compiler/Circuitcompiler"
7 | )
8 |
9 | var addr = flag.String("addr", "127.0.0.1:8081", "http service address")
10 |
11 | func main() {
12 | fmt.Println("asdf")
13 | Circuitcompiler.StartServer(addr)
14 | fmt.Println("Server is running")
15 | <-make(chan bool)
16 | }
17 |
--------------------------------------------------------------------------------
/pairing/bn256_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package bn256
6 |
7 | import (
8 | "bytes"
9 | "crypto/rand"
10 | "fmt"
11 | "math/big"
12 | "testing"
13 | )
14 |
15 | func TestGFp2Invert(t *testing.T) {
16 | pool := new(bnPool)
17 |
18 | a := newGFp2(pool)
19 | a.x.SetString("23423492374", 10)
20 | a.y.SetString("12934872398472394827398470", 10)
21 |
22 | inv := newGFp2(pool)
23 | inv.Invert(a, pool)
24 |
25 | b := newGFp2(pool).Mul(inv, a, pool)
26 | if b.x.Int64() != 0 || b.y.Int64() != 1 {
27 | t.Fatalf("bad result for a^-1*a: %s %s", b.x, b.y)
28 | }
29 |
30 | a.Put(pool)
31 | b.Put(pool)
32 | inv.Put(pool)
33 |
34 | if c := pool.Count(); c > 0 {
35 | t.Errorf("Pool count non-zero: %d\n", c)
36 | }
37 | }
38 |
39 | func isZero(n *big.Int) bool {
40 | return new(big.Int).Mod(n, P).Int64() == 0
41 | }
42 |
43 | func isOne(n *big.Int) bool {
44 | return new(big.Int).Mod(n, P).Int64() == 1
45 | }
46 |
47 | func TestGFp6Invert(t *testing.T) {
48 | pool := new(bnPool)
49 |
50 | a := newGFp6(pool)
51 | a.x.x.SetString("239487238491", 10)
52 | a.x.y.SetString("2356249827341", 10)
53 | a.y.x.SetString("082659782", 10)
54 | a.y.y.SetString("182703523765", 10)
55 | a.z.x.SetString("978236549263", 10)
56 | a.z.y.SetString("64893242", 10)
57 |
58 | inv := newGFp6(pool)
59 | inv.Invert(a, pool)
60 |
61 | b := newGFp6(pool).Mul(inv, a, pool)
62 | if !isZero(b.x.x) ||
63 | !isZero(b.x.y) ||
64 | !isZero(b.y.x) ||
65 | !isZero(b.y.y) ||
66 | !isZero(b.z.x) ||
67 | !isOne(b.z.y) {
68 | t.Fatalf("bad result for a^-1*a: %s", b)
69 | }
70 |
71 | a.Put(pool)
72 | b.Put(pool)
73 | inv.Put(pool)
74 |
75 | if c := pool.Count(); c > 0 {
76 | t.Errorf("Pool count non-zero: %d\n", c)
77 | }
78 | }
79 |
80 | func TestGFp12Invert(t *testing.T) {
81 | pool := new(bnPool)
82 |
83 | a := newGFp12(pool)
84 | a.x.x.x.SetString("239846234862342323958623", 10)
85 | a.x.x.y.SetString("2359862352529835623", 10)
86 | a.x.y.x.SetString("928836523", 10)
87 | a.x.y.y.SetString("9856234", 10)
88 | a.x.z.x.SetString("235635286", 10)
89 | a.x.z.y.SetString("5628392833", 10)
90 | a.y.x.x.SetString("252936598265329856238956532167968", 10)
91 | a.y.x.y.SetString("23596239865236954178968", 10)
92 | a.y.y.x.SetString("95421692834", 10)
93 | a.y.y.y.SetString("236548", 10)
94 | a.y.z.x.SetString("924523", 10)
95 | a.y.z.y.SetString("12954623", 10)
96 |
97 | inv := newGFp12(pool)
98 | inv.Invert(a, pool)
99 |
100 | b := newGFp12(pool).Mul(inv, a, pool)
101 | if !isZero(b.x.x.x) ||
102 | !isZero(b.x.x.y) ||
103 | !isZero(b.x.y.x) ||
104 | !isZero(b.x.y.y) ||
105 | !isZero(b.x.z.x) ||
106 | !isZero(b.x.z.y) ||
107 | !isZero(b.y.x.x) ||
108 | !isZero(b.y.x.y) ||
109 | !isZero(b.y.y.x) ||
110 | !isZero(b.y.y.y) ||
111 | !isZero(b.y.z.x) ||
112 | !isOne(b.y.z.y) {
113 | t.Fatalf("bad result for a^-1*a: %s", b)
114 | }
115 |
116 | a.Put(pool)
117 | b.Put(pool)
118 | inv.Put(pool)
119 |
120 | if c := pool.Count(); c > 0 {
121 | t.Errorf("Pool count non-zero: %d\n", c)
122 | }
123 | }
124 |
125 | func TestCurveImpl(t *testing.T) {
126 | pool := new(bnPool)
127 |
128 | g := &curvePoint{
129 | pool.Get().SetInt64(1),
130 | pool.Get().SetInt64(-2),
131 | pool.Get().SetInt64(1),
132 | pool.Get().SetInt64(0),
133 | }
134 |
135 | x := pool.Get().SetInt64(32498273234)
136 | X := newCurvePoint(pool).Mul(g, x, pool)
137 |
138 | y := pool.Get().SetInt64(98732423523)
139 | Y := newCurvePoint(pool).Mul(g, y, pool)
140 |
141 | s1 := newCurvePoint(pool).Mul(X, y, pool).MakeAffine(pool)
142 | s2 := newCurvePoint(pool).Mul(Y, x, pool).MakeAffine(pool)
143 |
144 | if s1.x.Cmp(s2.x) != 0 ||
145 | s2.x.Cmp(s1.x) != 0 {
146 | t.Errorf("DH points don't match: (%s, %s) (%s, %s)", s1.x, s1.y, s2.x, s2.y)
147 | }
148 |
149 | pool.Put(x)
150 | X.Put(pool)
151 | pool.Put(y)
152 | Y.Put(pool)
153 | s1.Put(pool)
154 | s2.Put(pool)
155 | g.Put(pool)
156 |
157 | if c := pool.Count(); c > 0 {
158 | t.Errorf("Pool count non-zero: %d\n", c)
159 | }
160 | }
161 |
162 | func TestOrderG1(t *testing.T) {
163 | g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
164 | fmt.Println(g.CurvePoints())
165 | g = g.ScalarBaseMult(Order)
166 | fmt.Println(g.String())
167 | if !g.p.IsInfinity() {
168 | t.Error("G1 has incorrect order")
169 | }
170 |
171 | one := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
172 | g.Add(g, one)
173 | g.p.MakeAffine(nil)
174 | if g.p.x.Cmp(one.p.x) != 0 || g.p.y.Cmp(one.p.y) != 0 {
175 | t.Errorf("1+0 != 1 in G1")
176 | }
177 | }
178 |
179 | func TestOrderG2(t *testing.T) {
180 | g := new(G2).ScalarBaseMult(Order)
181 | if !g.p.IsInfinity() {
182 | t.Error("G2 has incorrect order")
183 | }
184 |
185 | one := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
186 | g.Add(g, one)
187 | g.p.MakeAffine(nil)
188 | if g.p.x.x.Cmp(one.p.x.x) != 0 ||
189 | g.p.x.y.Cmp(one.p.x.y) != 0 ||
190 | g.p.y.x.Cmp(one.p.y.x) != 0 ||
191 | g.p.y.y.Cmp(one.p.y.y) != 0 {
192 | t.Errorf("1+0 != 1 in G2")
193 | }
194 | }
195 |
196 | func TestOrderGT(t *testing.T) {
197 | gt := Pair(&G1{curveGen}, &G2{twistGen})
198 | g := new(GT).ScalarMult(gt, Order)
199 | if !g.p.IsOne() {
200 | t.Error("GT has incorrect order")
201 | }
202 | }
203 | func TestBnPool_Get(t *testing.T) {
204 | a, p1, _ := RandomG1(rand.Reader)
205 | b, p2, _ := RandomG2(rand.Reader)
206 | e1 := Pair(p1, p2)
207 |
208 | e2 := Pair(&G1{curveGen}, &G2{twistGen})
209 | e2.ScalarMult(e2, a.Mul(a, b))
210 | //e2.ScalarMult(e2, b)
211 |
212 | minusE2 := new(GT).Neg(e2)
213 | e1.Add(e1, minusE2)
214 |
215 | if !e1.p.IsOne() {
216 | t.Fatalf("bad pairing result: %s", e1)
217 | }
218 | }
219 |
220 | func TestBilinearity(t *testing.T) {
221 | for i := 0; i < 2; i++ {
222 | a, p1, _ := RandomG1(rand.Reader)
223 | b, p2, _ := RandomG2(rand.Reader)
224 | e1 := Pair(p1, p2)
225 |
226 | e2 := Pair(&G1{curveGen}, &G2{twistGen})
227 | e2.ScalarMult(e2, a)
228 | e2.ScalarMult(e2, b)
229 |
230 | minusE2 := new(GT).Neg(e2)
231 | e1.Add(e1, minusE2)
232 |
233 | if !e1.p.IsOne() {
234 | t.Fatalf("bad pairing result: %s", e1)
235 | }
236 | }
237 | }
238 |
239 | func TestG1Marshal(t *testing.T) {
240 | g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
241 | form := g.Marshal()
242 | _, err := new(G1).Unmarshal(form)
243 | if err != nil {
244 | t.Fatalf("failed to unmarshal")
245 | }
246 |
247 | g.ScalarBaseMult(Order)
248 | form = g.Marshal()
249 |
250 | g2 := new(G1)
251 | if _, err = g2.Unmarshal(form); err != nil {
252 | t.Fatalf("failed to unmarshal ∞")
253 | }
254 | if !g2.p.IsInfinity() {
255 | t.Fatalf("∞ unmarshaled incorrectly")
256 | }
257 | }
258 |
259 | func TestG2Marshal(t *testing.T) {
260 | g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
261 | form := g.Marshal()
262 | _, err := new(G2).Unmarshal(form)
263 | if err != nil {
264 | t.Fatalf("failed to unmarshal")
265 | }
266 |
267 | g.ScalarBaseMult(Order)
268 | form = g.Marshal()
269 | g2 := new(G2)
270 | if _, err = g2.Unmarshal(form); err != nil {
271 | t.Fatalf("failed to unmarshal ∞")
272 | }
273 | if !g2.p.IsInfinity() {
274 | t.Fatalf("∞ unmarshaled incorrectly")
275 | }
276 | }
277 |
278 | func TestG1Identity(t *testing.T) {
279 | g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(0))
280 | if !g.p.IsInfinity() {
281 | t.Error("failure")
282 | }
283 | }
284 |
285 | func TestG2Identity(t *testing.T) {
286 | g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(0))
287 | if !g.p.IsInfinity() {
288 | t.Error("failure")
289 | }
290 | }
291 |
292 | func TestTripartiteDiffieHellman(t *testing.T) {
293 | a, _ := rand.Int(rand.Reader, Order)
294 | b, _ := rand.Int(rand.Reader, Order)
295 | c, _ := rand.Int(rand.Reader, Order)
296 |
297 | pa := new(G1)
298 | pa.Unmarshal(new(G1).ScalarBaseMult(a).Marshal())
299 | qa := new(G2)
300 | qa.Unmarshal(new(G2).ScalarBaseMult(a).Marshal())
301 | pb := new(G1)
302 | pb.Unmarshal(new(G1).ScalarBaseMult(b).Marshal())
303 | qb := new(G2)
304 | qb.Unmarshal(new(G2).ScalarBaseMult(b).Marshal())
305 | pc := new(G1)
306 | pc.Unmarshal(new(G1).ScalarBaseMult(c).Marshal())
307 | qc := new(G2)
308 | qc.Unmarshal(new(G2).ScalarBaseMult(c).Marshal())
309 |
310 | k1 := Pair(pb, qc)
311 | k1.ScalarMult(k1, a)
312 | k1Bytes := k1.Marshal()
313 |
314 | k2 := Pair(pc, qa)
315 | k2.ScalarMult(k2, b)
316 | k2Bytes := k2.Marshal()
317 |
318 | k3 := Pair(pa, qb)
319 | k3.ScalarMult(k3, c)
320 | k3Bytes := k3.Marshal()
321 |
322 | if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) {
323 | t.Errorf("keys didn't agree")
324 | }
325 | }
326 |
327 | func BenchmarkPairing(b *testing.B) {
328 | for i := 0; i < b.N; i++ {
329 | Pair(&G1{curveGen}, &G2{twistGen})
330 | }
331 | }
332 |
--------------------------------------------------------------------------------
/pairing/constants.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package bn256
6 |
7 | import (
8 | "math/big"
9 | )
10 |
11 | func bigFromBase10(s string) *big.Int {
12 | n, _ := new(big.Int).SetString(s, 10)
13 | return n
14 | }
15 |
16 | // u is the BN parameter that determines the prime: 1868033³.
17 | var u = bigFromBase10("4965661367192848881")
18 |
19 | // p is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1.
20 | var P = bigFromBase10("21888242871839275222246405745257275088696311157297823662689037894645226208583")
21 |
22 | // Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1.
23 | var Order = bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617")
24 |
25 | // xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+9.
26 | var xiToPMinus1Over6 = &gfP2{bigFromBase10("16469823323077808223889137241176536799009286646108169935659301613961712198316"), bigFromBase10("8376118865763821496583973867626364092589906065868298776909617916018768340080")}
27 |
28 | // xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+9.
29 | var xiToPMinus1Over3 = &gfP2{bigFromBase10("10307601595873709700152284273816112264069230130616436755625194854815875713954"), bigFromBase10("21575463638280843010398324269430826099269044274347216827212613867836435027261")}
30 |
31 | // xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+9.
32 | var xiToPMinus1Over2 = &gfP2{bigFromBase10("3505843767911556378687030309984248845540243509899259641013678093033130930403"), bigFromBase10("2821565182194536844548159561693502659359617185244120367078079554186484126554")}
33 |
34 | // xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+9.
35 | var xiToPSquaredMinus1Over3 = bigFromBase10("21888242871839275220042445260109153167277707414472061641714758635765020556616")
36 |
37 | // xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+9 (a cubic root of unity, mod p).
38 | var xiTo2PSquaredMinus2Over3 = bigFromBase10("2203960485148121921418603742825762020974279258880205651966")
39 |
40 | // xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+9 (a cubic root of -1, mod p).
41 | var xiToPSquaredMinus1Over6 = bigFromBase10("21888242871839275220042445260109153167277707414472061641714758635765020556617")
42 |
43 | // xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+9.
44 | var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19937756971775647987995932169929341994314640652964949448313374472400716661030"), bigFromBase10("2581911344467009335267311115468803099551665605076196740867805258568234346338")}
45 |
--------------------------------------------------------------------------------
/pairing/curve.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package bn256
6 |
7 | import (
8 | "math/big"
9 | )
10 |
11 | // curvePoint implements the elliptic curve y²=x³+3. Points are kept in
12 | // Jacobian form and t=z² when valid. G₁ is the set of points of this curve on
13 | // GF(p).
14 | type curvePoint struct {
15 | x, y, z, t *big.Int
16 | }
17 |
18 | var curveB = new(big.Int).SetInt64(3)
19 |
20 | // curveGen is the generator of G₁.
21 | var curveGen = &curvePoint{
22 | new(big.Int).SetInt64(1),
23 | new(big.Int).SetInt64(2),
24 | new(big.Int).SetInt64(1),
25 | new(big.Int).SetInt64(1),
26 | }
27 |
28 | func newCurvePoint(pool *bnPool) *curvePoint {
29 | return &curvePoint{
30 | pool.Get(),
31 | pool.Get(),
32 | pool.Get(),
33 | pool.Get(),
34 | }
35 | }
36 |
37 | func (c *curvePoint) String() string {
38 | c.MakeAffine(new(bnPool))
39 | return "(" + c.x.String() + ", " + c.y.String() + ")"
40 | }
41 |
42 | func (c *curvePoint) Put(pool *bnPool) {
43 | pool.Put(c.x)
44 | pool.Put(c.y)
45 | pool.Put(c.z)
46 | pool.Put(c.t)
47 | }
48 |
49 | func (c *curvePoint) Set(a *curvePoint) {
50 | c.x.Set(a.x)
51 | c.y.Set(a.y)
52 | c.z.Set(a.z)
53 | c.t.Set(a.t)
54 | }
55 |
56 | // IsOnCurve returns true iff c is on the curve where c must be in affine form.
57 | func (c *curvePoint) IsOnCurve() bool {
58 | yy := new(big.Int).Mul(c.y, c.y)
59 | xxx := new(big.Int).Mul(c.x, c.x)
60 | xxx.Mul(xxx, c.x)
61 | yy.Sub(yy, xxx)
62 | yy.Sub(yy, curveB)
63 | if yy.Sign() < 0 || yy.Cmp(P) >= 0 {
64 | yy.Mod(yy, P)
65 | }
66 | return yy.Sign() == 0
67 | }
68 |
69 | func (c *curvePoint) SetInfinity() {
70 | c.z.SetInt64(0)
71 | }
72 |
73 | func (c *curvePoint) IsInfinity() bool {
74 | return c.z.Sign() == 0
75 | }
76 |
77 | func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) {
78 | if a.IsInfinity() {
79 | c.Set(b)
80 | return
81 | }
82 | if b.IsInfinity() {
83 | c.Set(a)
84 | return
85 | }
86 |
87 | // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
88 |
89 | // Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2]
90 | // by [u1:s1:z1·z2] and [u2:s2:z1·z2]
91 | // where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³
92 | z1z1 := pool.Get().Mul(a.z, a.z)
93 | z1z1.Mod(z1z1, P)
94 | z2z2 := pool.Get().Mul(b.z, b.z)
95 | z2z2.Mod(z2z2, P)
96 | u1 := pool.Get().Mul(a.x, z2z2)
97 | u1.Mod(u1, P)
98 | u2 := pool.Get().Mul(b.x, z1z1)
99 | u2.Mod(u2, P)
100 |
101 | t := pool.Get().Mul(b.z, z2z2)
102 | t.Mod(t, P)
103 | s1 := pool.Get().Mul(a.y, t)
104 | s1.Mod(s1, P)
105 |
106 | t.Mul(a.z, z1z1)
107 | t.Mod(t, P)
108 | s2 := pool.Get().Mul(b.y, t)
109 | s2.Mod(s2, P)
110 |
111 | // Compute x = (2h)²(s²-u1-u2)
112 | // where s = (s2-s1)/(u2-u1) is the slope of the line through
113 | // (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below.
114 | // This is also:
115 | // 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1)
116 | // = r² - j - 2v
117 | // with the notations below.
118 | h := pool.Get().Sub(u2, u1)
119 | xEqual := h.Sign() == 0
120 |
121 | t.Add(h, h)
122 | // i = 4h²
123 | i := pool.Get().Mul(t, t)
124 | i.Mod(i, P)
125 | // j = 4h³
126 | j := pool.Get().Mul(h, i)
127 | j.Mod(j, P)
128 |
129 | t.Sub(s2, s1)
130 | yEqual := t.Sign() == 0
131 | if xEqual && yEqual {
132 | c.Double(a, pool)
133 | return
134 | }
135 | r := pool.Get().Add(t, t)
136 |
137 | v := pool.Get().Mul(u1, i)
138 | v.Mod(v, P)
139 |
140 | // t4 = 4(s2-s1)²
141 | t4 := pool.Get().Mul(r, r)
142 | t4.Mod(t4, P)
143 | t.Add(v, v)
144 | t6 := pool.Get().Sub(t4, j)
145 | c.x.Sub(t6, t)
146 |
147 | // Set y = -(2h)³(s1 + s*(x/4h²-u1))
148 | // This is also
149 | // y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j
150 | t.Sub(v, c.x) // t7
151 | t4.Mul(s1, j) // t8
152 | t4.Mod(t4, P)
153 | t6.Add(t4, t4) // t9
154 | t4.Mul(r, t) // t10
155 | t4.Mod(t4, P)
156 | c.y.Sub(t4, t6)
157 |
158 | // Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2
159 | t.Add(a.z, b.z) // t11
160 | t4.Mul(t, t) // t12
161 | t4.Mod(t4, P)
162 | t.Sub(t4, z1z1) // t13
163 | t4.Sub(t, z2z2) // t14
164 | c.z.Mul(t4, h)
165 | c.z.Mod(c.z, P)
166 |
167 | pool.Put(z1z1)
168 | pool.Put(z2z2)
169 | pool.Put(u1)
170 | pool.Put(u2)
171 | pool.Put(t)
172 | pool.Put(s1)
173 | pool.Put(s2)
174 | pool.Put(h)
175 | pool.Put(i)
176 | pool.Put(j)
177 | pool.Put(r)
178 | pool.Put(v)
179 | pool.Put(t4)
180 | pool.Put(t6)
181 | }
182 |
183 | func (c *curvePoint) Double(a *curvePoint, pool *bnPool) {
184 | // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
185 | A := pool.Get().Mul(a.x, a.x)
186 | A.Mod(A, P)
187 | B := pool.Get().Mul(a.y, a.y)
188 | B.Mod(B, P)
189 | C_ := pool.Get().Mul(B, B)
190 | C_.Mod(C_, P)
191 |
192 | t := pool.Get().Add(a.x, B)
193 | t2 := pool.Get().Mul(t, t)
194 | t2.Mod(t2, P)
195 | t.Sub(t2, A)
196 | t2.Sub(t, C_)
197 | d := pool.Get().Add(t2, t2)
198 | t.Add(A, A)
199 | e := pool.Get().Add(t, A)
200 | f := pool.Get().Mul(e, e)
201 | f.Mod(f, P)
202 |
203 | t.Add(d, d)
204 | c.x.Sub(f, t)
205 |
206 | t.Add(C_, C_)
207 | t2.Add(t, t)
208 | t.Add(t2, t2)
209 | c.y.Sub(d, c.x)
210 | t2.Mul(e, c.y)
211 | t2.Mod(t2, P)
212 | c.y.Sub(t2, t)
213 |
214 | t.Mul(a.y, a.z)
215 | t.Mod(t, P)
216 | c.z.Add(t, t)
217 |
218 | pool.Put(A)
219 | pool.Put(B)
220 | pool.Put(C_)
221 | pool.Put(t)
222 | pool.Put(t2)
223 | pool.Put(d)
224 | pool.Put(e)
225 | pool.Put(f)
226 | }
227 |
228 | func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint {
229 | sum := newCurvePoint(pool)
230 | sum.SetInfinity()
231 | t := newCurvePoint(pool)
232 |
233 | for i := scalar.BitLen(); i >= 0; i-- {
234 | t.Double(sum, pool)
235 | if scalar.Bit(i) != 0 {
236 | sum.Add(t, a, pool)
237 | } else {
238 | sum.Set(t)
239 | }
240 | }
241 |
242 | c.Set(sum)
243 | sum.Put(pool)
244 | t.Put(pool)
245 | return c
246 | }
247 |
248 | // MakeAffine converts c to affine form and returns c. If c is ∞, then it sets
249 | // c to 0 : 1 : 0.
250 | func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint {
251 | if words := c.z.Bits(); len(words) == 1 && words[0] == 1 {
252 | return c
253 | }
254 | if c.IsInfinity() {
255 | c.x.SetInt64(0)
256 | c.y.SetInt64(1)
257 | c.z.SetInt64(0)
258 | c.t.SetInt64(0)
259 | return c
260 | }
261 | zInv := pool.Get().ModInverse(c.z, P)
262 | t := pool.Get().Mul(c.y, zInv)
263 | t.Mod(t, P)
264 | zInv2 := pool.Get().Mul(zInv, zInv)
265 | zInv2.Mod(zInv2, P)
266 | c.y.Mul(t, zInv2)
267 | c.y.Mod(c.y, P)
268 | t.Mul(c.x, zInv2)
269 | t.Mod(t, P)
270 | c.x.Set(t)
271 | c.z.SetInt64(1)
272 | c.t.SetInt64(1)
273 |
274 | pool.Put(zInv)
275 | pool.Put(t)
276 | pool.Put(zInv2)
277 |
278 | return c
279 | }
280 |
281 | func (c *curvePoint) Negative(a *curvePoint) {
282 | c.x.Set(a.x)
283 | c.y.Neg(a.y)
284 | c.z.Set(a.z)
285 | c.t.SetInt64(0)
286 | }
287 |
--------------------------------------------------------------------------------
/pairing/example_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package bn256
6 |
7 | import (
8 | "crypto/rand"
9 | )
10 |
11 | func ExamplePair() {
12 | // This implements the tripartite Diffie-Hellman algorithm from "A One
13 | // Round Protocol for Tripartite Diffie-Hellman", A. Joux.
14 | // http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf
15 |
16 | // Each of three parties, a, b and c, generate a private value.
17 | a, _ := rand.Int(rand.Reader, Order)
18 | b, _ := rand.Int(rand.Reader, Order)
19 | c, _ := rand.Int(rand.Reader, Order)
20 |
21 | // Then each party calculates g₁ and g₂ times their private value.
22 | pa := new(G1).ScalarBaseMult(a)
23 | qa := new(G2).ScalarBaseMult(a)
24 |
25 | pb := new(G1).ScalarBaseMult(b)
26 | qb := new(G2).ScalarBaseMult(b)
27 |
28 | pc := new(G1).ScalarBaseMult(c)
29 | qc := new(G2).ScalarBaseMult(c)
30 |
31 | // Now each party exchanges its public values with the other two and
32 | // all parties can calculate the shared key.
33 | k1 := Pair(pb, qc)
34 | k1.ScalarMult(k1, a)
35 |
36 | k2 := Pair(pc, qa)
37 | k2.ScalarMult(k2, b)
38 |
39 | k3 := Pair(pa, qb)
40 | k3.ScalarMult(k3, c)
41 |
42 | // k1, k2 and k3 will all be equal.
43 | }
44 |
--------------------------------------------------------------------------------
/pairing/gfp12.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package bn256
6 |
7 | // For details of the algorithms used, see "Multiplication and Squaring on
8 | // Pairing-Friendly Fields, Devegili et al.
9 | // http://eprint.iacr.org/2006/471.pdf.
10 |
11 | import (
12 | "math/big"
13 | )
14 |
15 | // gfP12 implements the field of size p¹² as a quadratic extension of gfP6
16 | // where ω²=τ.
17 | type gfP12 struct {
18 | x, y *gfP6 // value is xω + y
19 | }
20 |
21 | func newGFp12(pool *bnPool) *gfP12 {
22 | return &gfP12{newGFp6(pool), newGFp6(pool)}
23 | }
24 |
25 | func (e *gfP12) String() string {
26 | return "(" + e.x.String() + "," + e.y.String() + ")"
27 | }
28 |
29 | func (e *gfP12) Put(pool *bnPool) {
30 | e.x.Put(pool)
31 | e.y.Put(pool)
32 | }
33 |
34 | func (e *gfP12) Set(a *gfP12) *gfP12 {
35 | e.x.Set(a.x)
36 | e.y.Set(a.y)
37 | return e
38 | }
39 |
40 | func (e *gfP12) SetZero() *gfP12 {
41 | e.x.SetZero()
42 | e.y.SetZero()
43 | return e
44 | }
45 |
46 | func (e *gfP12) SetOne() *gfP12 {
47 | e.x.SetZero()
48 | e.y.SetOne()
49 | return e
50 | }
51 |
52 | func (e *gfP12) Minimal() {
53 | e.x.Minimal()
54 | e.y.Minimal()
55 | }
56 |
57 | func (e *gfP12) IsZero() bool {
58 | e.Minimal()
59 | return e.x.IsZero() && e.y.IsZero()
60 | }
61 |
62 | func (e *gfP12) IsOne() bool {
63 | e.Minimal()
64 | return e.x.IsZero() && e.y.IsOne()
65 | }
66 |
67 | func (e *gfP12) Conjugate(a *gfP12) *gfP12 {
68 | e.x.Negative(a.x)
69 | e.y.Set(a.y)
70 | return a
71 | }
72 |
73 | func (e *gfP12) Negative(a *gfP12) *gfP12 {
74 | e.x.Negative(a.x)
75 | e.y.Negative(a.y)
76 | return e
77 | }
78 |
79 | // Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p
80 | func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 {
81 | e.x.Frobenius(a.x, pool)
82 | e.y.Frobenius(a.y, pool)
83 | e.x.MulScalar(e.x, xiToPMinus1Over6, pool)
84 | return e
85 | }
86 |
87 | // FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p²
88 | func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 {
89 | e.x.FrobeniusP2(a.x)
90 | e.x.MulGFP(e.x, xiToPSquaredMinus1Over6)
91 | e.y.FrobeniusP2(a.y)
92 | return e
93 | }
94 |
95 | func (e *gfP12) Add(a, b *gfP12) *gfP12 {
96 | e.x.Add(a.x, b.x)
97 | e.y.Add(a.y, b.y)
98 | return e
99 | }
100 |
101 | func (e *gfP12) Sub(a, b *gfP12) *gfP12 {
102 | e.x.Sub(a.x, b.x)
103 | e.y.Sub(a.y, b.y)
104 | return e
105 | }
106 |
107 | func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 {
108 | tx := newGFp6(pool)
109 | tx.Mul(a.x, b.y, pool)
110 | t := newGFp6(pool)
111 | t.Mul(b.x, a.y, pool)
112 | tx.Add(tx, t)
113 |
114 | ty := newGFp6(pool)
115 | ty.Mul(a.y, b.y, pool)
116 | t.Mul(a.x, b.x, pool)
117 | t.MulTau(t, pool)
118 | e.y.Add(ty, t)
119 | e.x.Set(tx)
120 |
121 | tx.Put(pool)
122 | ty.Put(pool)
123 | t.Put(pool)
124 | return e
125 | }
126 |
127 | func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 {
128 | e.x.Mul(e.x, b, pool)
129 | e.y.Mul(e.y, b, pool)
130 | return e
131 | }
132 |
133 | func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 {
134 | sum := newGFp12(pool)
135 | sum.SetOne()
136 | t := newGFp12(pool)
137 |
138 | for i := power.BitLen() - 1; i >= 0; i-- {
139 | t.Square(sum, pool)
140 | if power.Bit(i) != 0 {
141 | sum.Mul(t, a, pool)
142 | } else {
143 | sum.Set(t)
144 | }
145 | }
146 |
147 | c.Set(sum)
148 |
149 | sum.Put(pool)
150 | t.Put(pool)
151 |
152 | return c
153 | }
154 |
155 | func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 {
156 | // Complex squaring algorithm
157 | v0 := newGFp6(pool)
158 | v0.Mul(a.x, a.y, pool)
159 |
160 | t := newGFp6(pool)
161 | t.MulTau(a.x, pool)
162 | t.Add(a.y, t)
163 | ty := newGFp6(pool)
164 | ty.Add(a.x, a.y)
165 | ty.Mul(ty, t, pool)
166 | ty.Sub(ty, v0)
167 | t.MulTau(v0, pool)
168 | ty.Sub(ty, t)
169 |
170 | e.y.Set(ty)
171 | e.x.Double(v0)
172 |
173 | v0.Put(pool)
174 | t.Put(pool)
175 | ty.Put(pool)
176 |
177 | return e
178 | }
179 |
180 | func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 {
181 | // See "Implementing cryptographic pairings", M. Scott, section 3.2.
182 | // ftp://136.206.11.249/pub/crypto/pairings.pdf
183 | t1 := newGFp6(pool)
184 | t2 := newGFp6(pool)
185 |
186 | t1.Square(a.x, pool)
187 | t2.Square(a.y, pool)
188 | t1.MulTau(t1, pool)
189 | t1.Sub(t2, t1)
190 | t2.Invert(t1, pool)
191 |
192 | e.x.Negative(a.x)
193 | e.y.Set(a.y)
194 | e.MulScalar(e, t2, pool)
195 |
196 | t1.Put(pool)
197 | t2.Put(pool)
198 |
199 | return e
200 | }
201 |
--------------------------------------------------------------------------------
/pairing/gfp2.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package bn256
6 |
7 | // For details of the algorithms used, see "Multiplication and Squaring on
8 | // Pairing-Friendly Fields, Devegili et al.
9 | // http://eprint.iacr.org/2006/471.pdf.
10 |
11 | import (
12 | "math/big"
13 | )
14 |
15 | // gfP2 implements a field of size p² as a quadratic extension of the base
16 | // field where i²=-1.
17 | type gfP2 struct {
18 | x, y *big.Int // value is xi+y.
19 | }
20 |
21 | func newGFp2(pool *bnPool) *gfP2 {
22 | return &gfP2{pool.Get(), pool.Get()}
23 | }
24 |
25 | func (e *gfP2) String() string {
26 | x := new(big.Int).Mod(e.x, P)
27 | y := new(big.Int).Mod(e.y, P)
28 | return "(" + x.String() + "," + y.String() + ")"
29 | }
30 |
31 | func (e *gfP2) copy() *gfP2 {
32 | return &gfP2{new(big.Int).Set(e.x), new(big.Int).Set(e.y)}
33 | }
34 |
35 | func (e *gfP2) Put(pool *bnPool) {
36 | pool.Put(e.x)
37 | pool.Put(e.y)
38 | }
39 |
40 | func (e *gfP2) Set(a *gfP2) *gfP2 {
41 | e.x.Set(a.x)
42 | e.y.Set(a.y)
43 | return e
44 | }
45 |
46 | func (e *gfP2) SetZero() *gfP2 {
47 | e.x.SetInt64(0)
48 | e.y.SetInt64(0)
49 | return e
50 | }
51 |
52 | func (e *gfP2) SetOne() *gfP2 {
53 | e.x.SetInt64(0)
54 | e.y.SetInt64(1)
55 | return e
56 | }
57 |
58 | func (e *gfP2) Minimal() {
59 | if e.x.Sign() < 0 || e.x.Cmp(P) >= 0 {
60 | e.x.Mod(e.x, P)
61 | }
62 | if e.y.Sign() < 0 || e.y.Cmp(P) >= 0 {
63 | e.y.Mod(e.y, P)
64 | }
65 | }
66 |
67 | func (e *gfP2) IsZero() bool {
68 | return e.x.Sign() == 0 && e.y.Sign() == 0
69 | }
70 |
71 | func (e *gfP2) IsOne() bool {
72 | if e.x.Sign() != 0 {
73 | return false
74 | }
75 | words := e.y.Bits()
76 | return len(words) == 1 && words[0] == 1
77 | }
78 |
79 | func (e *gfP2) Conjugate(a *gfP2) *gfP2 {
80 | e.y.Set(a.y)
81 | e.x.Neg(a.x)
82 | return e
83 | }
84 |
85 | func (e *gfP2) Negative(a *gfP2) *gfP2 {
86 | e.x.Neg(a.x)
87 | e.y.Neg(a.y)
88 | return e
89 | }
90 |
91 | func (e *gfP2) Add(a, b *gfP2) *gfP2 {
92 | e.x.Add(a.x, b.x)
93 | e.y.Add(a.y, b.y)
94 | return e
95 | }
96 |
97 | func (e *gfP2) Sub(a, b *gfP2) *gfP2 {
98 | e.x.Sub(a.x, b.x)
99 | e.y.Sub(a.y, b.y)
100 | return e
101 | }
102 |
103 | func (e *gfP2) Double(a *gfP2) *gfP2 {
104 | e.x.Lsh(a.x, 1)
105 | e.y.Lsh(a.y, 1)
106 | return e
107 | }
108 |
109 | func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 {
110 | sum := newGFp2(pool)
111 | sum.SetOne()
112 | t := newGFp2(pool)
113 |
114 | for i := power.BitLen() - 1; i >= 0; i-- {
115 | t.Square(sum, pool)
116 | if power.Bit(i) != 0 {
117 | sum.Mul(t, a, pool)
118 | } else {
119 | sum.Set(t)
120 | }
121 | }
122 |
123 | c.Set(sum)
124 |
125 | sum.Put(pool)
126 | t.Put(pool)
127 |
128 | return c
129 | }
130 |
131 | // See "Multiplication and Squaring in Pairing-Friendly Fields",
132 | // http://eprint.iacr.org/2006/471.pdf
133 | func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 {
134 | tx := pool.Get().Mul(a.x, b.y)
135 | t := pool.Get().Mul(b.x, a.y)
136 | tx.Add(tx, t)
137 | tx.Mod(tx, P)
138 |
139 | ty := pool.Get().Mul(a.y, b.y)
140 | t.Mul(a.x, b.x)
141 | ty.Sub(ty, t)
142 | e.y.Mod(ty, P)
143 | e.x.Set(tx)
144 |
145 | pool.Put(tx)
146 | pool.Put(ty)
147 | pool.Put(t)
148 |
149 | return e
150 | }
151 |
152 | func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 {
153 | e.x.Mul(a.x, b)
154 | e.y.Mul(a.y, b)
155 | return e
156 | }
157 |
158 | // MulXi sets e=ξa where ξ=i+9 and then returns e.
159 | func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 {
160 | // (xi+y)(i+3) = (9x+y)i+(9y-x)
161 | tx := pool.Get().Lsh(a.x, 3)
162 | tx.Add(tx, a.x)
163 | tx.Add(tx, a.y)
164 |
165 | ty := pool.Get().Lsh(a.y, 3)
166 | ty.Add(ty, a.y)
167 | ty.Sub(ty, a.x)
168 |
169 | e.x.Set(tx)
170 | e.y.Set(ty)
171 |
172 | pool.Put(tx)
173 | pool.Put(ty)
174 |
175 | return e
176 | }
177 |
178 | func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 {
179 | // Complex squaring algorithm:
180 | // (xi+b)² = (x+y)(y-x) + 2*i*x*y
181 | t1 := pool.Get().Sub(a.y, a.x)
182 | t2 := pool.Get().Add(a.x, a.y)
183 | ty := pool.Get().Mul(t1, t2)
184 | ty.Mod(ty, P)
185 |
186 | t1.Mul(a.x, a.y)
187 | t1.Lsh(t1, 1)
188 |
189 | e.x.Mod(t1, P)
190 | e.y.Set(ty)
191 |
192 | pool.Put(t1)
193 | pool.Put(t2)
194 | pool.Put(ty)
195 |
196 | return e
197 | }
198 |
199 | func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 {
200 | // See "Implementing cryptographic pairings", M. Scott, section 3.2.
201 | // ftp://136.206.11.249/pub/crypto/pairings.pdf
202 | t := pool.Get()
203 | t.Mul(a.y, a.y)
204 | t2 := pool.Get()
205 | t2.Mul(a.x, a.x)
206 | t.Add(t, t2)
207 |
208 | inv := pool.Get()
209 | inv.ModInverse(t, P)
210 |
211 | e.x.Neg(a.x)
212 | e.x.Mul(e.x, inv)
213 | e.x.Mod(e.x, P)
214 |
215 | e.y.Mul(a.y, inv)
216 | e.y.Mod(e.y, P)
217 |
218 | pool.Put(t)
219 | pool.Put(t2)
220 | pool.Put(inv)
221 |
222 | return e
223 | }
224 |
225 | func (e *gfP2) Real() *big.Int {
226 | return e.x
227 | }
228 |
229 | func (e *gfP2) Imag() *big.Int {
230 | return e.y
231 | }
232 |
--------------------------------------------------------------------------------
/pairing/gfp6.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package bn256
6 |
7 | // For details of the algorithms used, see "Multiplication and Squaring on
8 | // Pairing-Friendly Fields, Devegili et al.
9 | // http://eprint.iacr.org/2006/471.pdf.
10 |
11 | import (
12 | "math/big"
13 | )
14 |
15 | // gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ
16 | // and ξ=i+9.
17 | type gfP6 struct {
18 | x, y, z *gfP2 // value is xτ² + yτ + z
19 | }
20 |
21 | func newGFp6(pool *bnPool) *gfP6 {
22 | return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)}
23 | }
24 |
25 | func (e *gfP6) String() string {
26 | return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")"
27 | }
28 |
29 | func (e *gfP6) Put(pool *bnPool) {
30 | e.x.Put(pool)
31 | e.y.Put(pool)
32 | e.z.Put(pool)
33 | }
34 |
35 | func (e *gfP6) Set(a *gfP6) *gfP6 {
36 | e.x.Set(a.x)
37 | e.y.Set(a.y)
38 | e.z.Set(a.z)
39 | return e
40 | }
41 |
42 | func (e *gfP6) SetZero() *gfP6 {
43 | e.x.SetZero()
44 | e.y.SetZero()
45 | e.z.SetZero()
46 | return e
47 | }
48 |
49 | func (e *gfP6) SetOne() *gfP6 {
50 | e.x.SetZero()
51 | e.y.SetZero()
52 | e.z.SetOne()
53 | return e
54 | }
55 |
56 | func (e *gfP6) Minimal() {
57 | e.x.Minimal()
58 | e.y.Minimal()
59 | e.z.Minimal()
60 | }
61 |
62 | func (e *gfP6) IsZero() bool {
63 | return e.x.IsZero() && e.y.IsZero() && e.z.IsZero()
64 | }
65 |
66 | func (e *gfP6) IsOne() bool {
67 | return e.x.IsZero() && e.y.IsZero() && e.z.IsOne()
68 | }
69 |
70 | func (e *gfP6) Negative(a *gfP6) *gfP6 {
71 | e.x.Negative(a.x)
72 | e.y.Negative(a.y)
73 | e.z.Negative(a.z)
74 | return e
75 | }
76 |
77 | func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 {
78 | e.x.Conjugate(a.x)
79 | e.y.Conjugate(a.y)
80 | e.z.Conjugate(a.z)
81 |
82 | e.x.Mul(e.x, xiTo2PMinus2Over3, pool)
83 | e.y.Mul(e.y, xiToPMinus1Over3, pool)
84 | return e
85 | }
86 |
87 | // FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z
88 | func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 {
89 | // τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3)
90 | e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3)
91 | // τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3)
92 | e.y.MulScalar(a.y, xiToPSquaredMinus1Over3)
93 | e.z.Set(a.z)
94 | return e
95 | }
96 |
97 | func (e *gfP6) Add(a, b *gfP6) *gfP6 {
98 | e.x.Add(a.x, b.x)
99 | e.y.Add(a.y, b.y)
100 | e.z.Add(a.z, b.z)
101 | return e
102 | }
103 |
104 | func (e *gfP6) Sub(a, b *gfP6) *gfP6 {
105 | e.x.Sub(a.x, b.x)
106 | e.y.Sub(a.y, b.y)
107 | e.z.Sub(a.z, b.z)
108 | return e
109 | }
110 |
111 | func (e *gfP6) Double(a *gfP6) *gfP6 {
112 | e.x.Double(a.x)
113 | e.y.Double(a.y)
114 | e.z.Double(a.z)
115 | return e
116 | }
117 |
118 | func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 {
119 | // "Multiplication and Squaring on Pairing-Friendly Fields"
120 | // Section 4, Karatsuba method.
121 | // http://eprint.iacr.org/2006/471.pdf
122 |
123 | v0 := newGFp2(pool)
124 | v0.Mul(a.z, b.z, pool)
125 | v1 := newGFp2(pool)
126 | v1.Mul(a.y, b.y, pool)
127 | v2 := newGFp2(pool)
128 | v2.Mul(a.x, b.x, pool)
129 |
130 | t0 := newGFp2(pool)
131 | t0.Add(a.x, a.y)
132 | t1 := newGFp2(pool)
133 | t1.Add(b.x, b.y)
134 | tz := newGFp2(pool)
135 | tz.Mul(t0, t1, pool)
136 |
137 | tz.Sub(tz, v1)
138 | tz.Sub(tz, v2)
139 | tz.MulXi(tz, pool)
140 | tz.Add(tz, v0)
141 |
142 | t0.Add(a.y, a.z)
143 | t1.Add(b.y, b.z)
144 | ty := newGFp2(pool)
145 | ty.Mul(t0, t1, pool)
146 | ty.Sub(ty, v0)
147 | ty.Sub(ty, v1)
148 | t0.MulXi(v2, pool)
149 | ty.Add(ty, t0)
150 |
151 | t0.Add(a.x, a.z)
152 | t1.Add(b.x, b.z)
153 | tx := newGFp2(pool)
154 | tx.Mul(t0, t1, pool)
155 | tx.Sub(tx, v0)
156 | tx.Add(tx, v1)
157 | tx.Sub(tx, v2)
158 |
159 | e.x.Set(tx)
160 | e.y.Set(ty)
161 | e.z.Set(tz)
162 |
163 | t0.Put(pool)
164 | t1.Put(pool)
165 | tx.Put(pool)
166 | ty.Put(pool)
167 | tz.Put(pool)
168 | v0.Put(pool)
169 | v1.Put(pool)
170 | v2.Put(pool)
171 | return e
172 | }
173 |
174 | func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 {
175 | e.x.Mul(a.x, b, pool)
176 | e.y.Mul(a.y, b, pool)
177 | e.z.Mul(a.z, b, pool)
178 | return e
179 | }
180 |
181 | func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 {
182 | e.x.MulScalar(a.x, b)
183 | e.y.MulScalar(a.y, b)
184 | e.z.MulScalar(a.z, b)
185 | return e
186 | }
187 |
188 | // MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ
189 | func (e *gfP6) MulTau(a *gfP6, pool *bnPool) {
190 | tz := newGFp2(pool)
191 | tz.MulXi(a.x, pool)
192 | ty := newGFp2(pool)
193 | ty.Set(a.y)
194 | e.y.Set(a.z)
195 | e.x.Set(ty)
196 | e.z.Set(tz)
197 | tz.Put(pool)
198 | ty.Put(pool)
199 | }
200 |
201 | func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 {
202 | v0 := newGFp2(pool).Square(a.z, pool)
203 | v1 := newGFp2(pool).Square(a.y, pool)
204 | v2 := newGFp2(pool).Square(a.x, pool)
205 |
206 | c0 := newGFp2(pool).Add(a.x, a.y)
207 | c0.Square(c0, pool)
208 | c0.Sub(c0, v1)
209 | c0.Sub(c0, v2)
210 | c0.MulXi(c0, pool)
211 | c0.Add(c0, v0)
212 |
213 | c1 := newGFp2(pool).Add(a.y, a.z)
214 | c1.Square(c1, pool)
215 | c1.Sub(c1, v0)
216 | c1.Sub(c1, v1)
217 | xiV2 := newGFp2(pool).MulXi(v2, pool)
218 | c1.Add(c1, xiV2)
219 |
220 | c2 := newGFp2(pool).Add(a.x, a.z)
221 | c2.Square(c2, pool)
222 | c2.Sub(c2, v0)
223 | c2.Add(c2, v1)
224 | c2.Sub(c2, v2)
225 |
226 | e.x.Set(c2)
227 | e.y.Set(c1)
228 | e.z.Set(c0)
229 |
230 | v0.Put(pool)
231 | v1.Put(pool)
232 | v2.Put(pool)
233 | c0.Put(pool)
234 | c1.Put(pool)
235 | c2.Put(pool)
236 | xiV2.Put(pool)
237 |
238 | return e
239 | }
240 |
241 | func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 {
242 | // See "Implementing cryptographic pairings", M. Scott, section 3.2.
243 | // ftp://136.206.11.249/pub/crypto/pairings.pdf
244 |
245 | // Here we can give a short explanation of how it works: let j be a cubic root of
246 | // unity in GF(p²) so that 1+j+j²=0.
247 | // Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
248 | // = (xτ² + yτ + z)(Cτ²+Bτ+A)
249 | // = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm).
250 | //
251 | // On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
252 | // = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy)
253 | //
254 | // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz)
255 | t1 := newGFp2(pool)
256 |
257 | A := newGFp2(pool)
258 | A.Square(a.z, pool)
259 | t1.Mul(a.x, a.y, pool)
260 | t1.MulXi(t1, pool)
261 | A.Sub(A, t1)
262 |
263 | B := newGFp2(pool)
264 | B.Square(a.x, pool)
265 | B.MulXi(B, pool)
266 | t1.Mul(a.y, a.z, pool)
267 | B.Sub(B, t1)
268 |
269 | C_ := newGFp2(pool)
270 | C_.Square(a.y, pool)
271 | t1.Mul(a.x, a.z, pool)
272 | C_.Sub(C_, t1)
273 |
274 | F := newGFp2(pool)
275 | F.Mul(C_, a.y, pool)
276 | F.MulXi(F, pool)
277 | t1.Mul(A, a.z, pool)
278 | F.Add(F, t1)
279 | t1.Mul(B, a.x, pool)
280 | t1.MulXi(t1, pool)
281 | F.Add(F, t1)
282 |
283 | F.Invert(F, pool)
284 |
285 | e.x.Mul(C_, F, pool)
286 | e.y.Mul(B, F, pool)
287 | e.z.Mul(A, F, pool)
288 |
289 | t1.Put(pool)
290 | A.Put(pool)
291 | B.Put(pool)
292 | C_.Put(pool)
293 | F.Put(pool)
294 |
295 | return e
296 | }
297 |
--------------------------------------------------------------------------------
/pairing/main_test.go:
--------------------------------------------------------------------------------
1 | package bn256
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 |
7 | "crypto/rand"
8 | )
9 |
10 | func TestRandomG2Marshal(t *testing.T) {
11 | for i := 0; i < 10; i++ {
12 | n, g2, err := RandomG2(rand.Reader)
13 | if err != nil {
14 | t.Error(err)
15 | continue
16 | }
17 | t.Logf("%v: %x\n", n, g2.Marshal())
18 | }
19 | }
20 |
21 | func TestBnPool_Count(t *testing.T) {
22 | _, g1, _ := RandomG1(rand.Reader)
23 | _, g2, _ := RandomG2(rand.Reader)
24 | g1clone := new(G1)
25 | g1clone.p.Set(g1.p)
26 | g2clone := new(G2)
27 | g2clone.p.Set(g2.p)
28 |
29 | a37 := g1.ScalarBaseMult(bigFromBase10("37"))
30 | pair1 := Pair(a37, g2)
31 | fmt.Println(pair1)
32 |
33 | pair2 := Pair(g1clone, g2clone)
34 | fmt.Println(pair2.ScalarMult(pair2, bigFromBase10("37")))
35 |
36 | //new(GT).ScalarMult()
37 | //
38 | //for i := int64(0); i < 10; i++ {
39 | // fmt.Println(g1.Marshal())
40 | // g1.ScalarBaseMult(new(big.Int).SetInt64(i))
41 | //}
42 |
43 | }
44 | func TestOneGT(t *testing.T) {
45 | a1 := new(G1).ScalarBaseMult(bigFromBase10("1"))
46 | fmt.Println(a1)
47 | a2 := new(G2).ScalarBaseMult(bigFromBase10("1"))
48 | fmt.Println(a2.CurvePoints())
49 |
50 | }
51 | func TestPairings(t *testing.T) {
52 | a1 := new(G1).ScalarBaseMult(bigFromBase10("1"))
53 | a2 := new(G1).ScalarBaseMult(bigFromBase10("2"))
54 | a37 := new(G1).ScalarBaseMult(bigFromBase10("37"))
55 | an1 := new(G1).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616"))
56 |
57 | b0 := new(G2).ScalarBaseMult(bigFromBase10("0"))
58 | b1 := new(G2).ScalarBaseMult(bigFromBase10("1"))
59 | b2 := new(G2).ScalarBaseMult(bigFromBase10("2"))
60 | b27 := new(G2).ScalarBaseMult(bigFromBase10("27"))
61 | b999 := new(G2).ScalarBaseMult(bigFromBase10("999"))
62 | bn1 := new(G2).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616"))
63 |
64 | p1 := Pair(a1, b1)
65 | pn1 := Pair(a1, bn1)
66 | np1 := Pair(an1, b1)
67 | if pn1.String() != np1.String() {
68 | t.Error("Pairing mismatch: e(a, -b) != e(-a, b)")
69 | }
70 | if !PairingCheck([]*G1{a1, an1}, []*G2{b1, b1}) {
71 | t.Error("MultiAte check gave false negative!")
72 | }
73 | p0 := new(GT).Add(p1, pn1)
74 | p0_2 := Pair(a1, b0)
75 | if p0.String() != p0_2.String() {
76 | t.Error("Pairing mismatch: e(a, b) * e(a, -b) != 1")
77 | }
78 | p0_3 := new(GT).ScalarMult(p1, bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617"))
79 | if p0.String() != p0_3.String() {
80 | t.Error("Pairing mismatch: e(a, b) has wrong order")
81 | }
82 | p2 := Pair(a2, b1)
83 | p2_2 := Pair(a1, b2)
84 | p2_3 := new(GT).ScalarMult(p1, bigFromBase10("2"))
85 | if p2.String() != p2_2.String() {
86 | t.Error("Pairing mismatch: e(a, b * 2) != e(a * 2, b)")
87 | }
88 | if p2.String() != p2_3.String() {
89 | t.Error("Pairing mismatch: e(a, b * 2) != e(a, b) ** 2")
90 | }
91 | if p2.String() == p1.String() {
92 | t.Error("Pairing is degenerate!")
93 | }
94 | if PairingCheck([]*G1{a1, a1}, []*G2{b1, b1}) {
95 | t.Error("MultiAte check gave false positive!")
96 | }
97 | p999 := Pair(a37, b27)
98 | p999_2 := Pair(a1, b999)
99 | if p999.String() != p999_2.String() {
100 | t.Error("Pairing mismatch: e(a * 37, b * 27) != e(a, b * 999)")
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/pairing/optate.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package bn256
6 |
7 | func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
8 | // See the mixed addition algorithm from "Faster Computation of the
9 | // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
10 |
11 | B := newGFp2(pool).Mul(p.x, r.t, pool)
12 |
13 | D := newGFp2(pool).Add(p.y, r.z)
14 | D.Square(D, pool)
15 | D.Sub(D, r2)
16 | D.Sub(D, r.t)
17 | D.Mul(D, r.t, pool)
18 |
19 | H := newGFp2(pool).Sub(B, r.x)
20 | I := newGFp2(pool).Square(H, pool)
21 |
22 | E := newGFp2(pool).Add(I, I)
23 | E.Add(E, E)
24 |
25 | J := newGFp2(pool).Mul(H, E, pool)
26 |
27 | L1 := newGFp2(pool).Sub(D, r.y)
28 | L1.Sub(L1, r.y)
29 |
30 | V := newGFp2(pool).Mul(r.x, E, pool)
31 |
32 | rOut = newTwistPoint(pool)
33 | rOut.x.Square(L1, pool)
34 | rOut.x.Sub(rOut.x, J)
35 | rOut.x.Sub(rOut.x, V)
36 | rOut.x.Sub(rOut.x, V)
37 |
38 | rOut.z.Add(r.z, H)
39 | rOut.z.Square(rOut.z, pool)
40 | rOut.z.Sub(rOut.z, r.t)
41 | rOut.z.Sub(rOut.z, I)
42 |
43 | t := newGFp2(pool).Sub(V, rOut.x)
44 | t.Mul(t, L1, pool)
45 | t2 := newGFp2(pool).Mul(r.y, J, pool)
46 | t2.Add(t2, t2)
47 | rOut.y.Sub(t, t2)
48 |
49 | rOut.t.Square(rOut.z, pool)
50 |
51 | t.Add(p.y, rOut.z)
52 | t.Square(t, pool)
53 | t.Sub(t, r2)
54 | t.Sub(t, rOut.t)
55 |
56 | t2.Mul(L1, p.x, pool)
57 | t2.Add(t2, t2)
58 | a = newGFp2(pool)
59 | a.Sub(t2, t)
60 |
61 | c = newGFp2(pool)
62 | c.MulScalar(rOut.z, q.y)
63 | c.Add(c, c)
64 |
65 | b = newGFp2(pool)
66 | b.SetZero()
67 | b.Sub(b, L1)
68 | b.MulScalar(b, q.x)
69 | b.Add(b, b)
70 |
71 | B.Put(pool)
72 | D.Put(pool)
73 | H.Put(pool)
74 | I.Put(pool)
75 | E.Put(pool)
76 | J.Put(pool)
77 | L1.Put(pool)
78 | V.Put(pool)
79 | t.Put(pool)
80 | t2.Put(pool)
81 |
82 | return
83 | }
84 |
85 | func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
86 | // See the doubling algorithm for a=0 from "Faster Computation of the
87 | // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
88 |
89 | A := newGFp2(pool).Square(r.x, pool)
90 | B := newGFp2(pool).Square(r.y, pool)
91 | C_ := newGFp2(pool).Square(B, pool)
92 |
93 | D := newGFp2(pool).Add(r.x, B)
94 | D.Square(D, pool)
95 | D.Sub(D, A)
96 | D.Sub(D, C_)
97 | D.Add(D, D)
98 |
99 | E := newGFp2(pool).Add(A, A)
100 | E.Add(E, A)
101 |
102 | G := newGFp2(pool).Square(E, pool)
103 |
104 | rOut = newTwistPoint(pool)
105 | rOut.x.Sub(G, D)
106 | rOut.x.Sub(rOut.x, D)
107 |
108 | rOut.z.Add(r.y, r.z)
109 | rOut.z.Square(rOut.z, pool)
110 | rOut.z.Sub(rOut.z, B)
111 | rOut.z.Sub(rOut.z, r.t)
112 |
113 | rOut.y.Sub(D, rOut.x)
114 | rOut.y.Mul(rOut.y, E, pool)
115 | t := newGFp2(pool).Add(C_, C_)
116 | t.Add(t, t)
117 | t.Add(t, t)
118 | rOut.y.Sub(rOut.y, t)
119 |
120 | rOut.t.Square(rOut.z, pool)
121 |
122 | t.Mul(E, r.t, pool)
123 | t.Add(t, t)
124 | b = newGFp2(pool)
125 | b.SetZero()
126 | b.Sub(b, t)
127 | b.MulScalar(b, q.x)
128 |
129 | a = newGFp2(pool)
130 | a.Add(r.x, E)
131 | a.Square(a, pool)
132 | a.Sub(a, A)
133 | a.Sub(a, G)
134 | t.Add(B, B)
135 | t.Add(t, t)
136 | a.Sub(a, t)
137 |
138 | c = newGFp2(pool)
139 | c.Mul(rOut.z, r.t, pool)
140 | c.Add(c, c)
141 | c.MulScalar(c, q.y)
142 |
143 | A.Put(pool)
144 | B.Put(pool)
145 | C_.Put(pool)
146 | D.Put(pool)
147 | E.Put(pool)
148 | G.Put(pool)
149 | t.Put(pool)
150 |
151 | return
152 | }
153 |
154 | func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) {
155 | a2 := newGFp6(pool)
156 | a2.x.SetZero()
157 | a2.y.Set(a)
158 | a2.z.Set(b)
159 | a2.Mul(a2, ret.x, pool)
160 | t3 := newGFp6(pool).MulScalar(ret.y, c, pool)
161 |
162 | t := newGFp2(pool)
163 | t.Add(b, c)
164 | t2 := newGFp6(pool)
165 | t2.x.SetZero()
166 | t2.y.Set(a)
167 | t2.z.Set(t)
168 | ret.x.Add(ret.x, ret.y)
169 |
170 | ret.y.Set(t3)
171 |
172 | ret.x.Mul(ret.x, t2, pool)
173 | ret.x.Sub(ret.x, a2)
174 | ret.x.Sub(ret.x, ret.y)
175 | a2.MulTau(a2, pool)
176 | ret.y.Add(ret.y, a2)
177 |
178 | a2.Put(pool)
179 | t3.Put(pool)
180 | t2.Put(pool)
181 | t.Put(pool)
182 | }
183 |
184 | // sixuPlus2NAF is 6u+2 in non-adjacent form.
185 | var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0,
186 | 0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 1,
187 | 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1,
188 | 1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, 1, 1}
189 |
190 | // miller implements the Miller loop for calculating the Optimal Ate pairing.
191 | // See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf
192 | func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 {
193 | ret := newGFp12(pool)
194 | ret.SetOne()
195 |
196 | aAffine := newTwistPoint(pool)
197 | aAffine.Set(q)
198 | aAffine.MakeAffine(pool)
199 |
200 | bAffine := newCurvePoint(pool)
201 | bAffine.Set(p)
202 | bAffine.MakeAffine(pool)
203 |
204 | minusA := newTwistPoint(pool)
205 | minusA.Negative(aAffine, pool)
206 |
207 | r := newTwistPoint(pool)
208 | r.Set(aAffine)
209 |
210 | r2 := newGFp2(pool)
211 | r2.Square(aAffine.y, pool)
212 |
213 | for i := len(sixuPlus2NAF) - 1; i > 0; i-- {
214 | a, b, c, newR := lineFunctionDouble(r, bAffine, pool)
215 | if i != len(sixuPlus2NAF)-1 {
216 | ret.Square(ret, pool)
217 | }
218 |
219 | mulLine(ret, a, b, c, pool)
220 | a.Put(pool)
221 | b.Put(pool)
222 | c.Put(pool)
223 | r.Put(pool)
224 | r = newR
225 |
226 | switch sixuPlus2NAF[i-1] {
227 | case 1:
228 | a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool)
229 | case -1:
230 | a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool)
231 | default:
232 | continue
233 | }
234 |
235 | mulLine(ret, a, b, c, pool)
236 | a.Put(pool)
237 | b.Put(pool)
238 | c.Put(pool)
239 | r.Put(pool)
240 | r = newR
241 | }
242 |
243 | // In order to calculate Q1 we have to convert q from the sextic twist
244 | // to the full GF(p^12) group, apply the Frobenius there, and convert
245 | // back.
246 | //
247 | // The twist isomorphism is (x', y') -> (xω², yω³). If we consider just
248 | // x for a moment, then after applying the Frobenius, we have x̄ω^(2p)
249 | // where x̄ is the conjugate of x. If we are going to apply the inverse
250 | // isomorphism we need a value with a single coefficient of ω² so we
251 | // rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of
252 | // p, 2p-2 is a multiple of six. Therefore we can rewrite as
253 | // x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the
254 | // ω².
255 | //
256 | // A similar argument can be made for the y value.
257 |
258 | q1 := newTwistPoint(pool)
259 | q1.x.Conjugate(aAffine.x)
260 | q1.x.Mul(q1.x, xiToPMinus1Over3, pool)
261 | q1.y.Conjugate(aAffine.y)
262 | q1.y.Mul(q1.y, xiToPMinus1Over2, pool)
263 | q1.z.SetOne()
264 | q1.t.SetOne()
265 |
266 | // For Q2 we are applying the p² Frobenius. The two conjugations cancel
267 | // out and we are left only with the factors from the isomorphism. In
268 | // the case of x, we end up with a pure number which is why
269 | // xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We
270 | // ignore this to end up with -Q2.
271 |
272 | minusQ2 := newTwistPoint(pool)
273 | minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3)
274 | minusQ2.y.Set(aAffine.y)
275 | minusQ2.z.SetOne()
276 | minusQ2.t.SetOne()
277 |
278 | r2.Square(q1.y, pool)
279 | a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool)
280 | mulLine(ret, a, b, c, pool)
281 | a.Put(pool)
282 | b.Put(pool)
283 | c.Put(pool)
284 | r.Put(pool)
285 | r = newR
286 |
287 | r2.Square(minusQ2.y, pool)
288 | a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool)
289 | mulLine(ret, a, b, c, pool)
290 | a.Put(pool)
291 | b.Put(pool)
292 | c.Put(pool)
293 | r.Put(pool)
294 | r = newR
295 |
296 | aAffine.Put(pool)
297 | bAffine.Put(pool)
298 | minusA.Put(pool)
299 | r.Put(pool)
300 | r2.Put(pool)
301 |
302 | return ret
303 | }
304 |
305 | // finalExponentiation computes the (p¹²-1)/Order-th power of an element of
306 | // GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from
307 | // http://cryptojedi.org/papers/dclxvi-20100714.pdf)
308 | func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 {
309 | t1 := newGFp12(pool)
310 |
311 | // This is the p^6-Frobenius
312 | t1.x.Negative(in.x)
313 | t1.y.Set(in.y)
314 |
315 | inv := newGFp12(pool)
316 | inv.Invert(in, pool)
317 | t1.Mul(t1, inv, pool)
318 |
319 | t2 := newGFp12(pool).FrobeniusP2(t1, pool)
320 | t1.Mul(t1, t2, pool)
321 |
322 | fp := newGFp12(pool).Frobenius(t1, pool)
323 | fp2 := newGFp12(pool).FrobeniusP2(t1, pool)
324 | fp3 := newGFp12(pool).Frobenius(fp2, pool)
325 |
326 | fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
327 | fu.Exp(t1, u, pool)
328 | fu2.Exp(fu, u, pool)
329 | fu3.Exp(fu2, u, pool)
330 |
331 | y3 := newGFp12(pool).Frobenius(fu, pool)
332 | fu2p := newGFp12(pool).Frobenius(fu2, pool)
333 | fu3p := newGFp12(pool).Frobenius(fu3, pool)
334 | y2 := newGFp12(pool).FrobeniusP2(fu2, pool)
335 |
336 | y0 := newGFp12(pool)
337 | y0.Mul(fp, fp2, pool)
338 | y0.Mul(y0, fp3, pool)
339 |
340 | y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
341 | y1.Conjugate(t1)
342 | y5.Conjugate(fu2)
343 | y3.Conjugate(y3)
344 | y4.Mul(fu, fu2p, pool)
345 | y4.Conjugate(y4)
346 |
347 | y6 := newGFp12(pool)
348 | y6.Mul(fu3, fu3p, pool)
349 | y6.Conjugate(y6)
350 |
351 | t0 := newGFp12(pool)
352 | t0.Square(y6, pool)
353 | t0.Mul(t0, y4, pool)
354 | t0.Mul(t0, y5, pool)
355 | t1.Mul(y3, y5, pool)
356 | t1.Mul(t1, t0, pool)
357 | t0.Mul(t0, y2, pool)
358 | t1.Square(t1, pool)
359 | t1.Mul(t1, t0, pool)
360 | t1.Square(t1, pool)
361 | t0.Mul(t1, y1, pool)
362 | t1.Mul(t1, y0, pool)
363 | t0.Square(t0, pool)
364 | t0.Mul(t0, t1, pool)
365 |
366 | inv.Put(pool)
367 | t1.Put(pool)
368 | t2.Put(pool)
369 | fp.Put(pool)
370 | fp2.Put(pool)
371 | fp3.Put(pool)
372 | fu.Put(pool)
373 | fu2.Put(pool)
374 | fu3.Put(pool)
375 | fu2p.Put(pool)
376 | fu3p.Put(pool)
377 | y0.Put(pool)
378 | y1.Put(pool)
379 | y2.Put(pool)
380 | y3.Put(pool)
381 | y4.Put(pool)
382 | y5.Put(pool)
383 | y6.Put(pool)
384 |
385 | return t0
386 | }
387 |
388 | func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 {
389 | e := miller(a, b, pool)
390 | ret := finalExponentiation(e, pool)
391 | e.Put(pool)
392 |
393 | if a.IsInfinity() || b.IsInfinity() {
394 | ret.SetOne()
395 | }
396 | return ret
397 | }
398 |
--------------------------------------------------------------------------------
/pairing/twist.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package bn256
6 |
7 | import (
8 | "math/big"
9 | )
10 |
11 | // twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are
12 | // kept in Jacobian form and t=z² when valid. The group G₂ is the set of
13 | // n-torsion points of this curve over GF(p²) (where n = Order)
14 | type twistPoint struct {
15 | x, y, z, t *gfP2
16 | }
17 |
18 | var twistB = &gfP2{
19 | bigFromBase10("266929791119991161246907387137283842545076965332900288569378510910307636690"),
20 | bigFromBase10("19485874751759354771024239261021720505790618469301721065564631296452457478373"),
21 | }
22 |
23 | // twistGen is the generator of group G₂.
24 | var twistGen = &twistPoint{
25 | &gfP2{
26 | bigFromBase10("11559732032986387107991004021392285783925812861821192530917403151452391805634"),
27 | bigFromBase10("10857046999023057135944570762232829481370756359578518086990519993285655852781"),
28 | },
29 | &gfP2{
30 | bigFromBase10("4082367875863433681332203403145435568316851327593401208105741076214120093531"),
31 | bigFromBase10("8495653923123431417604973247489272438418190587263600148770280649306958101930"),
32 | },
33 | &gfP2{
34 | bigFromBase10("0"),
35 | bigFromBase10("1"),
36 | },
37 | &gfP2{
38 | bigFromBase10("0"),
39 | bigFromBase10("1"),
40 | },
41 | }
42 |
43 | func newTwistPoint(pool *bnPool) *twistPoint {
44 | return &twistPoint{
45 | newGFp2(pool),
46 | newGFp2(pool),
47 | newGFp2(pool),
48 | newGFp2(pool),
49 | }
50 | }
51 |
52 | func (c *twistPoint) String() string {
53 | return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")"
54 | }
55 |
56 | func (c *twistPoint) Put(pool *bnPool) {
57 | c.x.Put(pool)
58 | c.y.Put(pool)
59 | c.z.Put(pool)
60 | c.t.Put(pool)
61 | }
62 |
63 | func (c *twistPoint) Set(a *twistPoint) {
64 | c.x.Set(a.x)
65 | c.y.Set(a.y)
66 | c.z.Set(a.z)
67 | c.t.Set(a.t)
68 | }
69 |
70 | // IsOnCurve returns true iff c is on the curve where c must be in affine form.
71 | func (c *twistPoint) IsOnCurve() bool {
72 | pool := new(bnPool)
73 | yy := newGFp2(pool).Square(c.y, pool)
74 | xxx := newGFp2(pool).Square(c.x, pool)
75 | xxx.Mul(xxx, c.x, pool)
76 | yy.Sub(yy, xxx)
77 | yy.Sub(yy, twistB)
78 | yy.Minimal()
79 |
80 | if yy.x.Sign() != 0 || yy.y.Sign() != 0 {
81 | return false
82 | }
83 | cneg := newTwistPoint(pool)
84 | cneg.Mul(c, Order, pool)
85 | return cneg.z.IsZero()
86 | }
87 |
88 | func (c *twistPoint) SetInfinity() {
89 | c.z.SetZero()
90 | }
91 |
92 | func (c *twistPoint) IsInfinity() bool {
93 | return c.z.IsZero()
94 | }
95 |
96 | func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) {
97 | // For additional comments, see the same function in curve.go.
98 |
99 | if a.IsInfinity() {
100 | c.Set(b)
101 | return
102 | }
103 | if b.IsInfinity() {
104 | c.Set(a)
105 | return
106 | }
107 |
108 | // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
109 | z1z1 := newGFp2(pool).Square(a.z, pool)
110 | z2z2 := newGFp2(pool).Square(b.z, pool)
111 | u1 := newGFp2(pool).Mul(a.x, z2z2, pool)
112 | u2 := newGFp2(pool).Mul(b.x, z1z1, pool)
113 |
114 | t := newGFp2(pool).Mul(b.z, z2z2, pool)
115 | s1 := newGFp2(pool).Mul(a.y, t, pool)
116 |
117 | t.Mul(a.z, z1z1, pool)
118 | s2 := newGFp2(pool).Mul(b.y, t, pool)
119 |
120 | h := newGFp2(pool).Sub(u2, u1)
121 | xEqual := h.IsZero()
122 |
123 | t.Add(h, h)
124 | i := newGFp2(pool).Square(t, pool)
125 | j := newGFp2(pool).Mul(h, i, pool)
126 |
127 | t.Sub(s2, s1)
128 | yEqual := t.IsZero()
129 | if xEqual && yEqual {
130 | c.Double(a, pool)
131 | return
132 | }
133 | r := newGFp2(pool).Add(t, t)
134 |
135 | v := newGFp2(pool).Mul(u1, i, pool)
136 |
137 | t4 := newGFp2(pool).Square(r, pool)
138 | t.Add(v, v)
139 | t6 := newGFp2(pool).Sub(t4, j)
140 | c.x.Sub(t6, t)
141 |
142 | t.Sub(v, c.x) // t7
143 | t4.Mul(s1, j, pool) // t8
144 | t6.Add(t4, t4) // t9
145 | t4.Mul(r, t, pool) // t10
146 | c.y.Sub(t4, t6)
147 |
148 | t.Add(a.z, b.z) // t11
149 | t4.Square(t, pool) // t12
150 | t.Sub(t4, z1z1) // t13
151 | t4.Sub(t, z2z2) // t14
152 | c.z.Mul(t4, h, pool)
153 |
154 | z1z1.Put(pool)
155 | z2z2.Put(pool)
156 | u1.Put(pool)
157 | u2.Put(pool)
158 | t.Put(pool)
159 | s1.Put(pool)
160 | s2.Put(pool)
161 | h.Put(pool)
162 | i.Put(pool)
163 | j.Put(pool)
164 | r.Put(pool)
165 | v.Put(pool)
166 | t4.Put(pool)
167 | t6.Put(pool)
168 | }
169 |
170 | func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
171 | // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
172 | A := newGFp2(pool).Square(a.x, pool)
173 | B := newGFp2(pool).Square(a.y, pool)
174 | C_ := newGFp2(pool).Square(B, pool)
175 |
176 | t := newGFp2(pool).Add(a.x, B)
177 | t2 := newGFp2(pool).Square(t, pool)
178 | t.Sub(t2, A)
179 | t2.Sub(t, C_)
180 | d := newGFp2(pool).Add(t2, t2)
181 | t.Add(A, A)
182 | e := newGFp2(pool).Add(t, A)
183 | f := newGFp2(pool).Square(e, pool)
184 |
185 | t.Add(d, d)
186 | c.x.Sub(f, t)
187 |
188 | t.Add(C_, C_)
189 | t2.Add(t, t)
190 | t.Add(t2, t2)
191 | c.y.Sub(d, c.x)
192 | t2.Mul(e, c.y, pool)
193 | c.y.Sub(t2, t)
194 |
195 | t.Mul(a.y, a.z, pool)
196 | c.z.Add(t, t)
197 |
198 | A.Put(pool)
199 | B.Put(pool)
200 | C_.Put(pool)
201 | t.Put(pool)
202 | t2.Put(pool)
203 | d.Put(pool)
204 | e.Put(pool)
205 | f.Put(pool)
206 | }
207 |
208 | func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint {
209 | sum := newTwistPoint(pool)
210 | sum.SetInfinity()
211 | t := newTwistPoint(pool)
212 |
213 | for i := scalar.BitLen(); i >= 0; i-- {
214 | t.Double(sum, pool)
215 | if scalar.Bit(i) != 0 {
216 | sum.Add(t, a, pool)
217 | } else {
218 | sum.Set(t)
219 | }
220 | }
221 |
222 | c.Set(sum)
223 | sum.Put(pool)
224 | t.Put(pool)
225 | return c
226 | }
227 |
228 | // MakeAffine converts c to affine form and returns c. If c is ∞, then it sets
229 | // c to 0 : 1 : 0.
230 | func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint {
231 | if c.z.IsOne() {
232 | return c
233 | }
234 | if c.IsInfinity() {
235 | c.x.SetZero()
236 | c.y.SetOne()
237 | c.z.SetZero()
238 | c.t.SetZero()
239 | return c
240 | }
241 | zInv := newGFp2(pool).Invert(c.z, pool)
242 | t := newGFp2(pool).Mul(c.y, zInv, pool)
243 | zInv2 := newGFp2(pool).Square(zInv, pool)
244 | c.y.Mul(t, zInv2, pool)
245 | t.Mul(c.x, zInv2, pool)
246 | c.x.Set(t)
247 | c.z.SetOne()
248 | c.t.SetOne()
249 |
250 | zInv.Put(pool)
251 | t.Put(pool)
252 | zInv2.Put(pool)
253 |
254 | return c
255 | }
256 |
257 | func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) {
258 | c.x.Set(a.x)
259 | c.y.SetZero()
260 | c.y.Sub(c.y, a.y)
261 | c.z.Set(a.z)
262 | c.t.SetZero()
263 | }
264 |
--------------------------------------------------------------------------------
/testPrograms/codes.go:
--------------------------------------------------------------------------------
1 | package testPrograms
2 |
3 | import "math/big"
4 |
5 | type InOut struct {
6 | Inputs []*big.Int
7 | Result *big.Int
8 | }
9 |
10 | type TraceCorrectnessTest struct {
11 | Skip bool
12 | Code string
13 | IO []InOut
14 | }
15 |
16 | var bigNumberResult1, _ = new(big.Int).SetString("2297704271284150716235246193843898764109352875", 10)
17 | var pubkeyOf42OnBn256_G1, _ = new(big.Int).SetString("4312786488925573964619847916436127219510912864504589785209181363209026354996", 10)
18 |
19 | var sudoku = func() []*big.Int {
20 | field := [9][9]int64{
21 | {9, 5, 7, 6, 1, 3, 2, 8, 4},
22 | {4, 8, 3, 2, 5, 7, 1, 9, 6},
23 | {6, 1, 2, 8, 4, 9, 5, 3, 7},
24 | {1, 7, 8, 3, 6, 4, 9, 5, 2},
25 | {5, 2, 4, 9, 7, 1, 3, 6, 8},
26 | {3, 6, 9, 5, 2, 8, 7, 4, 1},
27 | {8, 4, 5, 7, 9, 2, 6, 1, 3},
28 | {2, 9, 1, 4, 3, 6, 8, 7, 5},
29 | {7, 3, 6, 1, 8, 5, 4, 2, 9},
30 | }
31 | res := []*big.Int{}
32 | for i := 0; i < 9; i++ {
33 | for j := 0; j < 9; j++ {
34 | res = append(res, new(big.Int).SetInt64(field[i][j]))
35 | }
36 | }
37 | return res
38 | }
39 |
40 | var TestFibonacci = []TraceCorrectnessTest{
41 | {
42 | Skip: false,
43 | IO: []InOut{{
44 | Inputs: []*big.Int{big.NewInt(int64(3))},
45 | }},
46 |
47 | Code: `
48 | func main(x field) field{
49 | return (1*Fibonacci(8,dyn))*(x*x)*dyn[3]
50 | }
51 | var dyn = [9]field{1,1,0,0,0,0,0,0,0}
52 |
53 | func Fibonacci(a field, dyn [9]field) field{
54 | var i = 12
55 | for (i = 2 ; i 2 {
398 | if self.left.Height() > self.right.Height() {
399 | self = self.rotate_right()
400 | } else {
401 | self = self.rotate_left()
402 | }
403 | }
404 | return self
405 | }
406 |
407 | func (self *AvlNode) Put(key uint, value *big.Int, insert func(old, new *big.Int) *big.Int) (_ *AvlNode, updated bool) {
408 | if self == nil {
409 | return &AvlNode{key: key, value: insert(big.NewInt(0), value), height: 1}, false
410 | }
411 |
412 | if self.key == key {
413 | self.value = insert(self.value, value)
414 | return self, true
415 | }
416 |
417 | if key < (self.key) {
418 | self.left, updated = self.left.Put(key, value, insert)
419 | } else {
420 | self.right, updated = self.right.Put(key, value, insert)
421 | }
422 | if !updated {
423 | self.height += 1
424 | return self.balance(), updated
425 | }
426 | return self, updated
427 | }
428 |
429 | func (self *AvlNode) Remove(key uint) (_ *AvlNode, value *big.Int, err error) {
430 | if self == nil {
431 | return nil, nil, errors.New(fmt.Sprintf("not found %v", key))
432 | }
433 |
434 | if self.key == (key) {
435 | if self.left != nil && self.right != nil {
436 | if self.left.Size() < self.right.Size() {
437 | lmd := self.right.lmd()
438 | lmd.left = self.left
439 | return self.right, self.value, nil
440 | } else {
441 | rmd := self.left.rmd()
442 | rmd.right = self.right
443 | return self.left, self.value, nil
444 | }
445 | } else if self.left == nil {
446 | return self.right, self.value, nil
447 | } else if self.right == nil {
448 | return self.left, self.value, nil
449 | } else {
450 | return nil, self.value, nil
451 | }
452 | }
453 | if key < (self.key) {
454 | self.left, value, err = self.left.Remove(key)
455 | } else {
456 | self.right, value, err = self.right.Remove(key)
457 | }
458 | if err != nil {
459 | return self.balance(), value, err
460 | }
461 | return self, value, err
462 | }
463 |
464 | func (self *AvlNode) Height() int {
465 | if self == nil {
466 | return 0
467 | }
468 | return self.height
469 | }
470 |
471 | func (self *AvlNode) Size() int {
472 | if self == nil {
473 | return 0
474 | }
475 | return 1 + self.left.Size() + self.right.Size()
476 | }
477 |
478 | func (self *AvlNode) Key() uint {
479 | return self.key
480 | }
481 |
482 | func (self *AvlNode) Value() *big.Int {
483 | return self.value
484 | }
485 |
486 | func (self *AvlNode) Left() *AvlNode {
487 | if self.left == nil {
488 | return nil
489 | }
490 | return self.left
491 | }
492 |
493 | func (self *AvlNode) Right() *AvlNode {
494 | if self.right == nil {
495 | return nil
496 | }
497 | return self.right
498 | }
499 |
500 | func (self *AvlNode) _md(side func(*AvlNode) *AvlNode) *AvlNode {
501 | if self == nil {
502 | return nil
503 | } else if side(self) != nil {
504 | return side(self)._md(side)
505 | } else {
506 | return self
507 | }
508 | }
509 |
510 | func (self *AvlNode) lmd() *AvlNode {
511 | return self._md(func(node *AvlNode) *AvlNode { return node.left })
512 | }
513 |
514 | func (self *AvlNode) rmd() *AvlNode {
515 | return self._md(func(node *AvlNode) *AvlNode { return node.right })
516 | }
517 |
--------------------------------------------------------------------------------
/utils/fft.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "math/big"
5 | "math/bits"
6 | )
7 |
8 | type FFT_PrecomputedParas struct {
9 | RootOfUnity *big.Int
10 | RootOfUnitys_SquareSteps []*big.Int // w,w^2,w^4,w^8..
11 | RootOfUnity_inv *big.Int
12 | RootOfUnity_invs_SquareSteps []*big.Int // w^-1,w^-2,w^-4,w^-8..
13 | RootOfUnitys []*big.Int // 1,w,w^2,w^3,w^4..,
14 | RootOfUnity_invs []*big.Int // 1,w^-1,w^-2,w^-3,w^-4..
15 | Size int //number of points we want to consider, rounded to the next power of two
16 | pf *PolynomialField
17 | Domain Poly //p(x) = x^size - 1
18 | }
19 |
20 | func (pf *PolynomialField) PrepareFFT(length int) *FFT_PrecomputedParas {
21 |
22 | if v, ex := pf.fftPras[NextPowerOfTwo(length)]; ex {
23 | return v
24 | }
25 |
26 | paras := new(FFT_PrecomputedParas)
27 | paras.pf = pf
28 | adicity := AdicityBig(new(big.Int).Sub(pf.F.Q, bigOne))
29 | //for bn256
30 | //The factors of p-1 = 2^28 * 3^2 * 13 * 29 * 983 * 11003 * 237073 * 405928799 * 1670836401704629 * 13818364434197438864469338081
31 | //this root of untiy is 5^(3^2 * 13 * 29 * 983 * 11003 * 237073 * 405928799 * 1670836401704629 * 13818364434197438864469338081)
32 | //note that 5 is the lowest number, that is not a factor of p-1.
33 | rootOfUnity, _ := new(big.Int).SetString("19103219067921713944291392827692070036145651957329286315305642004821462161904", 10)
34 | //now find the closest possible power of two, to fill up the datapoints
35 | bit := bits.Len(uint(NextPowerOfTwo(length)))
36 | // 1000 = 1 << 3, so we remove 1 from bit
37 | bit = bit - 1
38 | if adicity < bit {
39 | panic("field has two low adicity to support fft for that many values")
40 | }
41 | paras.Size = 1 << bit
42 | paras.Domain = ArrayOfBigZeros(paras.Size + 1)
43 | paras.Domain[paras.Size] = new(big.Int).SetInt64(1)
44 | paras.Domain[0] = pf.F.Neg(new(big.Int).SetInt64(1)) // -1
45 | //now determine the root of unity
46 | // exponent = c*2^(adicity-(bit+1))
47 | // now for any k in Field, (k^(exponent))^2^(bit+1)==1 mod P
48 | //fmt.Println(c.String())
49 | //exponent := new(big.Int).Lsh(new(big.Int).SetInt64(1), uint(adicity-bit))
50 |
51 | //alphaSqrt := pf.F.Exp(rootOfUnity, exponent)
52 | //fmt.Println(alphaSqrt.String())
53 | alpha := pf.F.ExpInt(rootOfUnity, 1<<(adicity-bit))
54 | alphaInv := pf.F.Inverse(alpha)
55 | if pf.F.Exp(alpha, new(big.Int).Lsh(new(big.Int).SetInt64(1), uint(bit))).Cmp(bigOne) != 0 {
56 | panic("(k^(exponent))^2^(bit+1) != 1 mod P ")
57 | }
58 |
59 | bigAlphas_SS := make([]*big.Int, bit)
60 | bigAlphas_Inv_SS := make([]*big.Int, bit)
61 | bigAlphas_Inv := make([]*big.Int, 1<<(bit))
62 | bigAlphas := make([]*big.Int, 1<<(bit))
63 |
64 | bigAlphas_SS[0] = alpha
65 | bigAlphas_Inv_SS[0] = alphaInv
66 | for i := 1; i < bit; i++ {
67 | bigAlphas_SS[i] = pf.F.Mul(bigAlphas_SS[i-1], bigAlphas_SS[i-1])
68 | bigAlphas_Inv_SS[i] = pf.F.Mul(bigAlphas_Inv_SS[i-1], bigAlphas_Inv_SS[i-1])
69 | }
70 |
71 | bigAlphas[0] = new(big.Int).SetInt64(1)
72 | bigAlphas_Inv[0] = new(big.Int).SetInt64(1)
73 | bigAlphas[1<<(bit-1)] = pf.F.Neg(bigAlphas[0])
74 | bigAlphas_Inv[1<<(bit-1)] = pf.F.Neg(bigAlphas_Inv[0])
75 | for i := 1; i < 1<<(bit-1); i++ {
76 | bigAlphas[i] = pf.F.Mul(bigAlphas[i-1], alpha)
77 | bigAlphas_Inv[i] = pf.F.Mul(bigAlphas_Inv[i-1], alphaInv)
78 | bigAlphas[i+(1<<(bit-1))] = pf.F.Neg(bigAlphas[i])
79 | bigAlphas_Inv[i+(1<<(bit-1))] = pf.F.Neg(bigAlphas_Inv[i])
80 | }
81 |
82 | paras.RootOfUnity = alpha
83 | paras.RootOfUnity_inv = alphaInv
84 | paras.RootOfUnity_invs_SquareSteps = bigAlphas_Inv_SS
85 | paras.RootOfUnitys_SquareSteps = bigAlphas_SS
86 | paras.RootOfUnitys = bigAlphas
87 | paras.RootOfUnity_invs = bigAlphas_Inv
88 |
89 | if pf.F.Exp(bigAlphas_SS[len(bigAlphas_SS)-1], new(big.Int).SetInt64(2)).Cmp(bigOne) != 0 {
90 | panic("cannot happen")
91 | }
92 | pf.fftPras[NextPowerOfTwo(length)] = paras
93 | return paras
94 | }
95 |
96 | //input an array of datapoints, returns the coefficients of a polynomial that
97 | //interpolates the data at the roots of unity
98 | func (pf *PolynomialField) InvDFFT(ValuesAtRoots []*big.Int, shift *big.Int) (coefficients Poly) {
99 | p := pf.PrepareFFT(len(ValuesAtRoots))
100 |
101 | c1 := make(chan []*big.Int)
102 | go p._dfft(p.RootOfUnity_invs_SquareSteps, p.RootOfUnity_invs, ExtendArrayWithZeros(ValuesAtRoots, p.Size), c1)
103 | coefficients = <-c1
104 | div := new(big.Int).SetInt64(int64(len(coefficients)))
105 | for i, v := range coefficients {
106 | coefficients[i] = p.pf.F.Div(v, div)
107 | }
108 | return p.pf.shift(shift, true, coefficients)
109 | //return coefficients
110 | }
111 |
112 | func (pf *PolynomialField) DFFT(polynomial Poly, shift *big.Int) (evaluatedAtRoots []*big.Int) {
113 | p := pf.PrepareFFT(len(polynomial))
114 | c1 := make(chan []*big.Int)
115 | extd := ExtendArrayWithZeros(polynomial, p.Size)
116 |
117 | go p._dfft(p.RootOfUnitys_SquareSteps, p.RootOfUnitys, p.pf.shift(shift, false, extd), c1)
118 | return <-c1
119 | }
120 |
121 | func (p *FFT_PrecomputedParas) _dfft(bigAlphas_SS, bigAlphas, data []*big.Int, in chan []*big.Int) {
122 | if len(data) == 1 {
123 | in <- data
124 | return
125 | }
126 | even := []*big.Int{}
127 | odd := []*big.Int{}
128 | for k := range data {
129 | if k%2 == 1 {
130 | odd = append(odd, data[k])
131 | } else {
132 | even = append(even, data[k])
133 | }
134 | }
135 |
136 | removeUneven := make([]*big.Int, 0, len(bigAlphas)/2)
137 | for k, v := range bigAlphas {
138 | if k%2 == 0 {
139 | removeUneven = append(removeUneven, v)
140 | }
141 | }
142 | c1, c2 := make(chan []*big.Int, 1), make(chan []*big.Int, 1)
143 |
144 | go p._dfft(bigAlphas_SS[1:], removeUneven, even, c1)
145 | go p._dfft(bigAlphas_SS[1:], removeUneven, odd, c2)
146 | y, y2 := <-c1, <-c2
147 |
148 | res := make([]*big.Int, len(data))
149 | for k := 0; k < len(data)/2; k++ {
150 | wy := p.pf.F.Mul(bigAlphas[k], y2[k])
151 | res[k] = p.pf.F.Add(y[k], wy)
152 | res[k+(len(data)/2)] = p.pf.F.Sub(y[k], wy)
153 | }
154 | in <- res
155 | return
156 | }
157 |
--------------------------------------------------------------------------------
/utils/fft_test.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 | bn256 "github.com/mottla/go-R1CS-Compiler/pairing"
6 | "github.com/stretchr/testify/assert"
7 | "math/big"
8 | "testing"
9 | "time"
10 | )
11 |
12 | func TestPolynomialField_Mul(t *testing.T) {
13 | // new Finite Field
14 | var Npoints = 1 << 10
15 | r := new(big.Int).Set(bn256.Order)
16 | f := NewFiniteField(r)
17 | // new Polynomial Field
18 | pf := NewPolynomialField(f)
19 |
20 | var err error
21 |
22 | for runs := 0; runs < 1; runs++ {
23 | Ypoints := make([]*big.Int, Npoints)
24 | Zpoints := make([]*big.Int, Npoints)
25 | for i := 0; i < Npoints; i++ {
26 | Ypoints[i], err = f.Rand()
27 | assert.Nil(t, err)
28 | Zpoints[i], err = f.Rand()
29 | assert.Nil(t, err)
30 | }
31 | tt := time.Now()
32 | fmt.Println("Lagrange Interpolation...")
33 | l1 := pf.LagrangeInterpolation_RootOfUnity(ExtendArrayWithZeros(Ypoints, NextPowerOfTwo(Npoints)*2))
34 | l2 := pf.LagrangeInterpolation_RootOfUnity(ExtendArrayWithZeros(Zpoints, NextPowerOfTwo(Npoints)*2))
35 | fmt.Println("Lagrange Interpolation took ", time.Since(tt))
36 |
37 | tt = time.Now()
38 | fmt.Println("FFT Interpolation...")
39 | f1 := pf.InvDFFT(ExtendArrayWithZeros(Ypoints, NextPowerOfTwo(Npoints)*2), nil)
40 | f2 := pf.InvDFFT(ExtendArrayWithZeros(Zpoints, NextPowerOfTwo(Npoints)*2), nil)
41 | fmt.Println("FFT Interpolation took ", time.Since(tt))
42 |
43 | tt = time.Now()
44 | fmt.Println("FFT Multiplication...")
45 | mulFFT := pf.MulFFT(l1, l2)
46 | fmt.Println("Multiplication took ", time.Since(tt))
47 | mulFFTF := pf.MulFFT(f1, f2)
48 | fftPara := pf.fftPras[NextPowerOfTwo(Npoints)*2]
49 | assert.True(t, BigArraysEqual(mulFFT, mulFFTF))
50 | for i := 0; i < Npoints; i++ {
51 | if f.EvalPoly(mulFFT, fftPara.RootOfUnitys[i]).Cmp(f.Mul(Ypoints[i], Zpoints[i])) != 0 {
52 | t.Fail()
53 | fmt.Println("fail")
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/utils/finiteField.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "bytes"
5 | "crypto/rand"
6 | "fmt"
7 | "math/big"
8 | )
9 |
10 | type Fields struct {
11 | ArithmeticField Fq
12 | PolynomialField PolynomialField
13 | }
14 |
15 | //var Field = PrepareFields(big.NewInt(601), big.NewInt(601))
16 |
17 | //PrepareFields For prime r, in order to prove statements about F_r-arithmetic circuit
18 | //satisfiability, one instantiates (G, P, V ) using an elliptic curve E defined over some finite field F_q , where the
19 | //group E(F_q) of F_q-rational points has order r = #E(F q ) (or, more generally, r divides #E(F q )).
20 | func PrepareFields(r *big.Int) Fields {
21 | // new Finite Field
22 | fqR := NewFiniteField(r)
23 |
24 | return Fields{
25 | ArithmeticField: fqR,
26 | PolynomialField: *NewPolynomialField(fqR),
27 | }
28 | }
29 |
30 | type baseLengthPair struct {
31 | baseIndex, Length int
32 | }
33 |
34 | // Fq is the Z field over modulus Q
35 | type Fq struct {
36 | Q *big.Int // Q
37 |
38 | }
39 |
40 | // NewFiniteField generates a new Fq
41 | func NewFiniteField(order *big.Int) Fq {
42 | if !order.ProbablyPrime(20) {
43 | panic(fmt.Sprint(order, "is not prime"))
44 | }
45 | return Fq{
46 | order,
47 | }
48 | }
49 |
50 | // Zero returns a Zero value on the Fq
51 | func (fq Fq) Zero() *big.Int {
52 | return big.NewInt(int64(0))
53 | }
54 |
55 | // One returns a One value on the Fq
56 | func (fq Fq) One() *big.Int {
57 | return big.NewInt(int64(1))
58 | }
59 |
60 | func (fq Fq) StringToFieldElement(a string) (v *big.Int, s bool) {
61 | v, s = new(big.Int).SetString(a, 10)
62 |
63 | return v.Mod(v, fq.Q), s
64 | }
65 |
66 | func (fq Fq) ScalarProduct(l, r []*big.Int) (sum *big.Int) {
67 | if len(l) != len(r) {
68 | panic("vector lengths missmatch")
69 | }
70 | return fq.scalarProduct(l, r)
71 | }
72 | func (fq Fq) scalarProduct(l, r []*big.Int) (sum *big.Int) {
73 | if len(l) == 0 {
74 | return bigZero
75 | }
76 | return fq.Add(new(big.Int).Mul(l[0], r[0]), fq.ScalarProduct(l[1:], r[1:]))
77 | }
78 |
79 | // Add performs an addition on the Fq
80 | func (fq Fq) Add(a, b *big.Int) *big.Int {
81 | r := new(big.Int).Add(a, b)
82 | return new(big.Int).Mod(r, fq.Q)
83 | // return r
84 | }
85 |
86 | // Double performs a doubling on the Fq
87 | func (fq Fq) Double(a *big.Int) *big.Int {
88 | r := new(big.Int).Add(a, a)
89 | return new(big.Int).Mod(r, fq.Q)
90 | // return r
91 | }
92 |
93 | // Sub performs a subtraction on the Fq
94 | func (fq Fq) Sub(a, b *big.Int) *big.Int {
95 | r := new(big.Int).Sub(a, b)
96 | return new(big.Int).Mod(r, fq.Q)
97 | // return r
98 | }
99 |
100 | // Neg returns the additive inverse -a over Fq
101 | func (fq Fq) Neg(a *big.Int) *big.Int {
102 | m := new(big.Int).Neg(a)
103 | return new(big.Int).Mod(m, fq.Q)
104 | // return m
105 | }
106 |
107 | // Mul performs a multiplication on the Fq
108 | func (fq Fq) Mul(a, b *big.Int) *big.Int {
109 | m := new(big.Int).Mul(a, b)
110 | return new(big.Int).Mod(m, fq.Q)
111 | // return m
112 | }
113 |
114 | // Inverse returns the inverse on the Fq
115 | func (fq Fq) Inverse(a *big.Int) *big.Int {
116 | if a.Cmp(bigZero) == 0 {
117 | return a
118 | }
119 | return new(big.Int).ModInverse(a, fq.Q)
120 |
121 | }
122 |
123 | // Div performs the division over the finite field
124 | func (fq Fq) Div(a, b *big.Int) *big.Int {
125 | d := fq.Mul(a, fq.Inverse(b))
126 | return new(big.Int).Mod(d, fq.Q)
127 | }
128 |
129 | // Square performs a square operation on the Fq
130 | func (fq Fq) Square(a *big.Int) *big.Int {
131 | m := new(big.Int).Mul(a, a)
132 | return new(big.Int).Mod(m, fq.Q)
133 | }
134 |
135 | // Exp performs the exponential over Fq
136 | //unsafe when e is negative
137 | func (fq Fq) Exp(base *big.Int, e *big.Int) *big.Int {
138 | return new(big.Int).Exp(base, e, fq.Q)
139 | }
140 |
141 | // Exp performs the exponential over Fq
142 | func (fq Fq) ExpInt(base *big.Int, e int64) *big.Int {
143 | return fq.Exp(base, new(big.Int).SetInt64(e))
144 | }
145 |
146 | //EvalPoly Evaluates a polynomial v at position x, using the Horners Rule
147 | func (fq Fq) EvalPoly(v Poly, x *big.Int) *big.Int {
148 |
149 | if x.Cmp(bigZero) == 0 {
150 | return new(big.Int).Set(v[0])
151 | }
152 | if !v.IsSparse() {
153 | return fq.evalPoly_horner(v, x)
154 | }
155 | //for i := int64(1); i < int64(len(v)); i++ {
156 | // if v[i].Cmp(bigZero) != 0 {
157 | // //note since we expect the polynomials to be sparse, we compute the x^i straight away.. maybe incremental would still be more efficient
158 | // r = fq.Add(r, fq.Mul(v[i], fq.Exp(x, big.NewInt(i))))
159 | // }
160 | //}
161 | return fq.evalSparsePoly(v, x)
162 | }
163 |
164 | //EvalPoly Evaluates a sparse polynomial
165 | func (fq Fq) evalSparsePoly(poly Poly, at *big.Int) (result *big.Int) {
166 |
167 | //tree that stores intermediate results of exponent ladder. Key is the exponent. value is at^key
168 | alredyComputedExponents := NewAvlTree()
169 | alredyComputedExponents.InsertNoOverwriteAllowed(1, at)
170 | result = new(big.Int).SetInt64(0)
171 | for deg, coefficient := range poly {
172 | if coefficient.Cmp(bigZero) == 0 {
173 | continue
174 | }
175 | rem := uint(deg)
176 | q := uint(0)
177 | nextPower := new(big.Int).SetInt64(1)
178 | //apply a greedy algorithm to tackle the knapsack problem we face her. we want to create the
179 | //next power by reusing already computed powers, starting from the biggest.
180 | //example: we want x^15, we have x^8,x^3,x
181 | //we get x^15 = (x^8)^1 * (x^3)^2 * (x)^1
182 | for _, highestAlreadyComputedExponent := range alredyComputedExponents.DecendingNodes() {
183 | q, rem = euclid(rem, highestAlreadyComputedExponent.Key)
184 | vv := fq.ExpInt(highestAlreadyComputedExponent.Value, int64(q))
185 | alredyComputedExponents.Insert(q*highestAlreadyComputedExponent.Key, vv)
186 | nextPower = fq.Mul(nextPower, vv)
187 | if rem == 0 {
188 | break
189 | }
190 | }
191 | result = fq.Add(result, fq.Mul(coefficient, nextPower))
192 | }
193 | return result
194 | }
195 |
196 | //EvalPoly Evaluates a polynomial v at position x, using the Horners Rule
197 | func (fq Fq) evalPoly_horner(v []*big.Int, x *big.Int) *big.Int {
198 | if len(v) == 1 {
199 | return v[0]
200 | }
201 | return fq.Add(fq.Mul(fq.EvalPoly(v[1:], x), x), v[0])
202 |
203 | }
204 |
205 | //AdicityBig returns the biggest power of 2, that divides the input i.e. 2^n | in
206 | func AdicityBig(input *big.Int) (twoadicity int) {
207 | bits := fmt.Sprintf("%b", input)
208 | ad := 0
209 | for len(bits) != 0 && string(bits[len(bits)-1]) == "0" {
210 | bits = bits[:len(bits)-1]
211 | ad += 1
212 | }
213 | return ad
214 | }
215 |
216 | //this is the same function as above, but imperative style. the speed difference turned out to be marginally better this way, however FAR LESS ELEGANT
217 | //WE KEEP THIS AS REMINDER HOW SHIT IMPERATIVE PROGRAMMING IS
218 | //func (fq Fq) EvalPoly3(v []*big.Int, x *big.Int) *big.Int {
219 | // r := new(big.Int).Set(v[len(v)-1])
220 | // for i := len(v)-2; i >= 0; i-- {
221 | // if v[i].Cmp(bigZero) != 0 {
222 | // //note since we expect the polynomials to be sparse, we compute the x^i straight away.. maybe incremental would still be more efficient
223 | // r = fq.Add(fq.MulNaive(r, x),v[i])
224 | // }
225 | //
226 | // }
227 | // return r
228 | //}
229 |
230 | func (fq Fq) Rand() (*big.Int, error) {
231 |
232 | // twoexp := new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(maxbits)), nil)
233 | // MaxInt := new(big.Int).Sub(twoexp, big.NewInt(1))
234 | //rand
235 | maxbits := fq.Q.BitLen()
236 | b := make([]byte, (maxbits/8)-1)
237 | // b := make([]byte, 3)
238 | // b := make([]byte, 3)
239 | _, err := rand.Read(b)
240 | if err != nil {
241 | return nil, err
242 | }
243 | r := new(big.Int).SetBytes(b)
244 | rq := new(big.Int).Mod(r, fq.Q)
245 |
246 | // return r over q, nil
247 | return rq, nil
248 | }
249 |
250 | func (fq Fq) IsZero(a *big.Int) bool {
251 | return bytes.Equal(a.Bytes(), fq.Zero().Bytes())
252 | }
253 |
254 | func (fq Fq) Copy(a *big.Int) *big.Int {
255 | return new(big.Int).Mod(a, fq.Q)
256 | }
257 |
258 | func (fq Fq) Affine(a *big.Int) *big.Int {
259 | nq := fq.Neg(fq.Q)
260 |
261 | aux := a
262 | if aux.Cmp(big.NewInt(int64(0))) == -1 { // negative value
263 | if aux.Cmp(nq) != 1 { // aux less or equal nq
264 | aux = new(big.Int).Mod(aux, fq.Q)
265 | }
266 | if aux.Cmp(big.NewInt(int64(0))) == -1 { // negative value
267 | aux = new(big.Int).Add(aux, fq.Q)
268 | }
269 | } else {
270 | if aux.Cmp(fq.Q) != -1 { // aux greater or equal nq
271 | aux = new(big.Int).Mod(aux, fq.Q)
272 | }
273 | }
274 | return aux
275 | }
276 |
277 | func (fq Fq) Equal(a, b *big.Int) bool {
278 | aAff := fq.Affine(a)
279 | bAff := fq.Affine(b)
280 | return bytes.Equal(aAff.Bytes(), bAff.Bytes())
281 | }
282 |
--------------------------------------------------------------------------------
/utils/finiteField_test.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 | bn256 "github.com/mottla/go-R1CS-Compiler/pairing"
6 | "math/big"
7 | "testing"
8 |
9 | "github.com/stretchr/testify/assert"
10 | )
11 |
12 | func iToBig(a int) *big.Int {
13 | return big.NewInt(int64(a))
14 | }
15 |
16 | func iiToBig(a, b int) [2]*big.Int {
17 | return [2]*big.Int{iToBig(a), iToBig(b)}
18 | }
19 |
20 | func iiiToBig(a, b int) [2]*big.Int {
21 | return [2]*big.Int{iToBig(a), iToBig(b)}
22 | }
23 |
24 | func TestBigIsOdd(t *testing.T) {
25 | assert.True(t, BigIsOdd(big.NewInt(int64(7))))
26 | assert.True(t, BigIsOdd(big.NewInt(int64(57356245))))
27 | assert.False(t, BigIsOdd(big.NewInt(int64(3264356723562))), true)
28 | }
29 | func TestFq1(t *testing.T) {
30 | fq1 := NewFiniteField(iToBig(7))
31 |
32 | res := fq1.Add(iToBig(4), iToBig(4))
33 | assert.Equal(t, iToBig(1), fq1.Affine(res))
34 |
35 | res = fq1.Double(iToBig(5))
36 | assert.Equal(t, iToBig(3), fq1.Affine(res))
37 |
38 | res = fq1.Sub(iToBig(5), iToBig(7))
39 | assert.Equal(t, iToBig(5), fq1.Affine(res))
40 |
41 | res = fq1.Neg(iToBig(5))
42 | assert.Equal(t, iToBig(2), fq1.Affine(res))
43 |
44 | res = fq1.Mul(iToBig(5), iToBig(11))
45 | assert.Equal(t, iToBig(6), fq1.Affine(res))
46 |
47 | res = fq1.Inverse(iToBig(4))
48 | assert.Equal(t, iToBig(2), res)
49 |
50 | res = fq1.Square(iToBig(5))
51 | assert.Equal(t, iToBig(4), res)
52 | }
53 |
54 | func TestAdicityBig(t *testing.T) {
55 | r := new(big.Int).Set(bn256.Order)
56 | //r := new(big.Int).SetInt64(929)
57 | r = r.Sub(r, bigOne)
58 | fmt.Println(r)
59 | fmt.Printf("%b", r)
60 | fmt.Println()
61 | fmt.Println(AdicityBig(r))
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/utils/parallelize.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "runtime"
5 | "sync"
6 | )
7 |
8 | // Parallelize process in parallel the work function
9 | func Parallelize(nbIterations int, work func(int, int), maxCpus ...int) {
10 |
11 | nbTasks := runtime.NumCPU()
12 | if len(maxCpus) == 1 {
13 | nbTasks = maxCpus[0]
14 | }
15 | nbIterationsPerCpus := nbIterations / nbTasks
16 |
17 | // more CPUs than tasks: a CPU will work on exactly one iteration
18 | if nbIterationsPerCpus < 1 {
19 | nbIterationsPerCpus = 1
20 | nbTasks = nbIterations
21 | }
22 |
23 | var wg sync.WaitGroup
24 |
25 | extraTasks := nbIterations - (nbTasks * nbIterationsPerCpus)
26 | extraTasksOffset := 0
27 |
28 | for i := 0; i < nbTasks; i++ {
29 | wg.Add(1)
30 | _start := i*nbIterationsPerCpus + extraTasksOffset
31 | _end := _start + nbIterationsPerCpus
32 | if extraTasks > 0 {
33 | _end++
34 | extraTasks--
35 | extraTasksOffset++
36 | }
37 | go func() {
38 | work(_start, _end)
39 | wg.Done()
40 | }()
41 | }
42 |
43 | wg.Wait()
44 | }
45 |
--------------------------------------------------------------------------------
/utils/sparsePolynomial.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 | "math/big"
6 | )
7 |
8 | // Mul multiplies two polinomials over the Finite Field
9 | func (fq Fq) MulSparse(a, b *AvlTree) *AvlTree {
10 | r := NewAvlTree()
11 |
12 | for L := range a.ChannelNodes(true) {
13 | for R := range b.ChannelNodes(true) {
14 |
15 | r.Put(L.Key+R.Key, fq.Mul(R.Value, L.Value), fq.Add)
16 | }
17 | }
18 | return r
19 | }
20 |
21 | // Mul multiplies a sparse polynomail with a scalar over the Finite Field
22 | func (fq Fq) MulSparseScalar(a *AvlTree, scalar *big.Int) *AvlTree {
23 | a = a.Clone()
24 | for L := range a.ChannelNodes(true) {
25 | a.Put(L.Key, scalar, fq.Mul)
26 | }
27 | return a
28 | }
29 |
30 | type Entry struct {
31 | Key uint
32 | Value *big.Int
33 | }
34 |
35 | // Div divides two polinomials over the Finite Field, returning the result and the remainder
36 | func (fq Fq) DivideSparse(a, b *AvlTree) (result, rem *AvlTree) {
37 | result = NewAvlTree()
38 | rem = a.Clone()
39 | maxA, maxB := rem.MaxNode(), b.MaxNode()
40 | for ; maxA != nil && maxB != nil && maxA.Key() >= maxB.Key(); maxA = rem.MaxNode() {
41 | l := fq.Div(maxA.Value(), maxB.Value())
42 | pos := maxA.Key() - maxB.Key()
43 | aux := NewAvlTree()
44 | aux.InsertNoOverwriteAllowed(pos, l)
45 | result.InsertNoOverwriteAllowed(pos, l)
46 | mul := fq.MulSparse(b, aux)
47 | rem = fq.SubToSparse(rem, mul)
48 | }
49 | return result, rem
50 | }
51 |
52 | // Add adds two polinomials over the Finite Field
53 | func (a *AvlTree) Clone() *AvlTree {
54 | r := NewAvlTree()
55 |
56 | for v := range a.ChannelNodes(false) {
57 | r.Insert(v.Key, v.Value)
58 | }
59 |
60 | return r
61 | }
62 |
63 | func (fq Fq) AddToSparse(a, b *AvlTree) *AvlTree {
64 | //r := NewAvlTree()
65 |
66 | //for v := range a.ChannelNodes(false) {
67 | // r.Put(v.Key, v.Value, fq.Add)
68 | //}
69 | a = a.Clone()
70 | for v := range b.ChannelNodes(false) {
71 | a.Put(v.Key, v.Value, fq.Add)
72 | }
73 | return a
74 | }
75 |
76 | //EvalPoly Evaluates a sparse polynomial
77 | func (fq Fq) EvalSparsePoly(poly *AvlTree, at *big.Int) (result *big.Int) {
78 | //get the number of bits of the highest degree
79 | nBits := len(fmt.Sprintf("%b", poly.MaxNode().Key()))
80 | if nBits < poly.Size() {
81 | //fmt.Println("WARN, ur polynomial is not very sparse. a casual array type polynomial becomes more efficient at some point. not necessarily in this case however.")
82 | }
83 | if at.Cmp(bigZero) == 0 {
84 | if v, b := poly.Get(0); b == nil {
85 | return new(big.Int).Set(v)
86 | }
87 | return big.NewInt(0)
88 | }
89 | //tree that stores intermediate results of exponent ladder. Key is the exponent. value is at^key
90 | alredyComputedExponents := NewAvlTree()
91 | alredyComputedExponents.InsertNoOverwriteAllowed(1, at)
92 | result = new(big.Int).SetInt64(0)
93 | for j := range poly.ChannelNodes(true) {
94 | rem := j.Key
95 | q := uint(0)
96 | nextPower := new(big.Int).SetInt64(1)
97 | //apply a greedy algorithm to tackle the knapsack problem we face her. we want to create the
98 | //next power by reusing already computed powers, starting from the biggest.
99 | //example: we want x^15, we have x^8,x^3,x
100 | //we get x^15 = (x^8)^1 * (x^3)^2 * (x)^1
101 | for _, highestAlreadyComputedExponent := range alredyComputedExponents.DecendingNodes() {
102 | q, rem = euclid(rem, highestAlreadyComputedExponent.Key)
103 | vv := fq.ExpInt(highestAlreadyComputedExponent.Value, int64(q))
104 | alredyComputedExponents.Insert(q*highestAlreadyComputedExponent.Key, vv)
105 | nextPower = fq.Mul(nextPower, vv)
106 | if rem == 0 {
107 | break
108 | }
109 | }
110 | result = fq.Add(result, fq.Mul(j.Value, nextPower))
111 | }
112 | return result
113 | }
114 |
115 | // Sub subtracts two polinomials over the Finite Field
116 | func (fq Fq) SubToSparse(a, b *AvlTree) *AvlTree {
117 |
118 | a = a.Clone()
119 | for v := range b.ChannelNodes(false) {
120 | a.Put(v.Key, fq.Neg(v.Value), fq.Add)
121 | }
122 | return a
123 | }
124 |
125 | //LagrangeInterpolation performs the Lagrange Interpolation / Lagrange Polynomials operation
126 | func (pf PolynomialField) InterpolateSparseArray(dataArray *AvlTree, degree int) (polynom *AvlTree) {
127 | // https://en.wikipedia.org/wiki/Lagrange_polynomial
128 | if dataArray.MaxPower() >= uint(degree) {
129 | panic("interpolation degree cannot be smaller then highest degree in the polynomial")
130 | }
131 | var base = func(pointPos, totalPoints int) (r *AvlTree) {
132 |
133 | if v, ex := pf.bases[baseLengthPair{baseIndex: pointPos, Length: totalPoints}]; ex {
134 | return v
135 | }
136 | //r = NewAvlTree()
137 | facBig := big.NewInt(1)
138 |
139 | for i := 0; i < pointPos; i++ {
140 | facBig = pf.F.Mul(facBig, big.NewInt(int64(pointPos-i)))
141 | }
142 | for i := pointPos + 1; i < totalPoints; i++ {
143 | facBig = pf.F.Mul(facBig, big.NewInt(int64(pointPos-i)))
144 | }
145 |
146 | r = NewSparseArrayWith(uint(0), new(big.Int).SetInt64(1))
147 | for i := 0; i < totalPoints; i++ {
148 | if i != pointPos {
149 | r = pf.F.MulSparse(r, NewSparseArrayFromArray([]*big.Int{big.NewInt(int64(-i)), big.NewInt(int64(1))}))
150 | }
151 | }
152 | hf := pf.F.Inverse(facBig)
153 | r = pf.F.MulSparseScalar(r, hf)
154 | pf.mutex.Lock()
155 | pf.bases[baseLengthPair{baseIndex: pointPos, Length: totalPoints}] = r
156 | pf.mutex.Unlock()
157 | return r
158 | }
159 | //if IsZeroArray(dataArray.ToArray(degree)){
160 | // //at position -1 we store the all zero polynomial
161 | // if v,ex:=f.bases[baseLengthPair{baseIndex: -1,Length: degree}];ex{
162 | // return v
163 | // }
164 | // p:= PolynomialField{
165 | // F: f,
166 | // }
167 | // DomainPoly := NewSparseArrayFromArray(p.DomainPolynomial(degree))
168 | // f.bases[baseLengthPair{baseIndex: -1,Length: degree}]= DomainPoly
169 | // return DomainPoly
170 | //}
171 | polynom = NewAvlTree()
172 | for v := range dataArray.ChannelNodes(true) {
173 | prod := pf.F.MulSparseScalar(base(int(v.Key), degree), v.Value)
174 | polynom = pf.F.AddToSparse(polynom, prod)
175 | }
176 | return polynom
177 | }
178 | func (f Fq) SparseScalarProduct(a *AvlTree, b []*big.Int) (res *big.Int) {
179 | res = big.NewInt(0)
180 | for v := range a.ChannelNodes(true) {
181 | res = res.Add(res, f.Mul(v.Value, b[v.Key]))
182 | }
183 | return
184 | }
185 |
186 | func (f Fq) Combine(a *AvlTree, w []*big.Int) (scaledPolynomial *AvlTree) {
187 | for v := range a.ChannelNodes(true) {
188 | a.Put(v.Key, w[v.Key], f.Mul)
189 | }
190 | return a
191 | }
192 |
193 | //
194 | func (f Fq) LinearCombine(polynomials []*AvlTree, w []*big.Int) (scaledPolynomials []*AvlTree) {
195 | scaledPolynomials = make([]*AvlTree, len(w))
196 | for i := 0; i < len(w); i++ {
197 | scaledPolynomials[i] = f.MulSparseScalar(polynomials[i], w[i])
198 |
199 | }
200 | return
201 | }
202 | func (f Fq) AddPolynomials(polynomials []*AvlTree) (sumPoly *AvlTree) {
203 | sumPoly = NewAvlTree()
204 | for i := 0; i < len(polynomials); i++ {
205 | sumPoly = f.AddToSparse(sumPoly, polynomials[i])
206 | }
207 | return
208 | }
209 |
210 | func TransposeSparse(matrix []*AvlTree, witness int) (tra []*AvlTree) {
211 | r := make([]*AvlTree, witness)
212 | for i := 0; i < witness; i++ {
213 | r[i] = NewAvlTree()
214 | }
215 | for y, tree := range matrix {
216 | //if k := int(tree.MaxPower()); k > max {
217 | // max = k
218 | //}
219 | for val := range tree.ChannelNodes(true) {
220 | //for int(val.Key)+1 > len(r) {
221 | // r = append(r, NewAvlTree())
222 | //}
223 | r[int(val.Key)].InsertNoOverwriteAllowed(uint(y), val.Value)
224 | }
225 | }
226 | return r
227 | }
228 |
--------------------------------------------------------------------------------
/utils/sparsePolynomial_test.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 | bn256 "github.com/mottla/go-R1CS-Compiler/pairing"
6 | "github.com/stretchr/testify/assert"
7 | "math/big"
8 | "math/rand"
9 | "testing"
10 | "time"
11 | )
12 |
13 | func TestEval(t *testing.T) {
14 | // new Finite Field
15 |
16 | f := NewFiniteField(bn256.Order)
17 | at, _ := f.Rand()
18 | //at := big.NewInt(0)
19 | order := 150000
20 | //1 is 100% of the coefficients are 0
21 | sparsityPercent := 0.9
22 | a := ArrayOfBigZeros(order)
23 |
24 | for i := 0; i < order; i += 1 + rand.Intn(int(float64(order)*sparsityPercent)) {
25 | a[i], _ = f.Rand()
26 | }
27 |
28 | before := time.Now()
29 |
30 | sparseA := NewAvlTree()
31 |
32 | for _, v := range rand.Perm(len(a)) {
33 | //fmt.Println(v,a[v])
34 | sparseA.Insert(uint(v), a[v])
35 | //fmt.Println(sparseA.String())
36 | }
37 |
38 | before = time.Now()
39 | sparseAt := f.EvalSparsePoly(sparseA, at)
40 | fmt.Println("evaluate sparse took", time.Since(before))
41 |
42 | before = time.Now()
43 | classic := f.EvalPoly(a, at)
44 | fmt.Println("evaluate classic took", time.Since(before))
45 |
46 | //fmt.Println(f.EvalSparsePoly(sparseC,b16).String())
47 | if sparseAt.Cmp(classic) != 0 {
48 | t.Error(fmt.Sprintf("classic poly %v and sparse poly %v evaluation differ. At leas one of both must be wrong", sparseAt.String(), classic.String()))
49 | }
50 |
51 | for i := 0; i < 10; i++ {
52 | at, _ = f.Rand()
53 | sparseAt = f.EvalSparsePoly(sparseA, at)
54 | classic = f.EvalPoly(a, at)
55 | if sparseAt.Cmp(classic) != 0 {
56 | t.Error(fmt.Sprintf("classic poly %v and sparse poly %v evaluation differ. At leas one of both must be wrong", sparseAt.String(), classic.String()))
57 | }
58 |
59 | }
60 | }
61 |
62 | func TestMultiply(t *testing.T) {
63 | // new Finite Field
64 |
65 | f := NewFiniteField(bn256.Order)
66 | at, _ := f.Rand()
67 |
68 | order := 3000
69 | //1 is 100% of the coefficients are 0
70 | sparsityPercent := 0.1
71 | a := ArrayOfBigZeros(order)
72 | b := ArrayOfBigZeros(order)
73 | for i := 0; i < order; i += 1 + rand.Intn(int(float64(order)*sparsityPercent)) {
74 | a[i], _ = f.Rand()
75 | //a[i]=big.NewInt(int64(1))
76 | }
77 | for i := 0; i < order; i += 1 + rand.Intn(int(float64(order)*sparsityPercent)) {
78 | //b[i]=big.NewInt(int64(1))
79 | b[i], _ = f.Rand()
80 | }
81 | // new Polynomial Field
82 | pf := NewPolynomialField(f)
83 |
84 | before := time.Now()
85 | c := pf.MulNaive(a, b)
86 | fmt.Println("multiply with horner took", time.Since(before))
87 | sparseA := NewAvlTree()
88 | sparseB := NewAvlTree()
89 |
90 | for _, v := range rand.Perm(len(a)) {
91 | sparseA.Insert(uint(v), a[v])
92 | }
93 | for _, v := range rand.Perm(len(b)) {
94 | sparseB.Insert(uint(v), b[v])
95 | }
96 | before = time.Now()
97 | sparseC := f.MulSparse(sparseA, sparseB)
98 | fmt.Println("multiply sparse took", time.Since(before))
99 | before = time.Now()
100 | sparseAt := f.EvalSparsePoly(sparseC, at)
101 | fmt.Println("evaluate sparse took", time.Since(before))
102 |
103 | before = time.Now()
104 | classic := f.EvalPoly(c, at)
105 | fmt.Println("evaluate classic took", time.Since(before))
106 |
107 | //fmt.Println(f.EvalSparsePoly(sparseC,b16).String())
108 | if sparseAt.Cmp(classic) != 0 {
109 | t.Error(fmt.Sprintf("classic poly %v and sparse poly %v evaluation differ. At leas one of both must be wrong", sparseAt.String(), classic.String()))
110 | }
111 |
112 | }
113 |
114 | func TestAdd(t *testing.T) {
115 | // new Finite Field
116 |
117 | f := NewFiniteField(bn256.Order)
118 | at, _ := f.Rand()
119 |
120 | order := 100000
121 | //1 is 100% of the coefficients are 0
122 | sparsityPercent := 0.1
123 | a := ArrayOfBigZeros(order)
124 | b := ArrayOfBigZeros(order)
125 | for i := 0; i < order; i += 1 + rand.Intn(int(float64(order)*sparsityPercent)) {
126 | a[i], _ = f.Rand()
127 | }
128 | for i := 0; i < order; i += 1 + rand.Intn(int(float64(order)*sparsityPercent)) {
129 | b[i], _ = f.Rand()
130 | }
131 | // new Polynomial Field
132 | pf := NewPolynomialField(f)
133 |
134 | before := time.Now()
135 | c := pf.Add(a, b)
136 | fmt.Println("add classic took", time.Since(before))
137 |
138 | sparseA := NewAvlTree()
139 | sparseB := NewAvlTree()
140 |
141 | for _, v := range rand.Perm(len(a)) {
142 | sparseA.Insert(uint(v), a[v])
143 | //sparseA.Insert(uint(v), big.NewInt(int64(v)))
144 | }
145 |
146 | for _, v := range rand.Perm(len(b)) {
147 | sparseB.Insert(uint(v), b[v])
148 | //sparseB.Insert(uint(v), big.NewInt(int64(v)))
149 | }
150 | before = time.Now()
151 | sparseC := f.AddToSparse(sparseA, sparseB)
152 | fmt.Println("add sparse took", time.Since(before))
153 |
154 | before = time.Now()
155 | sparseAt := f.EvalSparsePoly(sparseC, at)
156 | fmt.Println("evaluate sparse took", time.Since(before))
157 |
158 | before = time.Now()
159 | classic := f.EvalPoly(c, at)
160 | fmt.Println("evaluate classic took", time.Since(before))
161 |
162 | //fmt.Println(f.EvalSparsePoly(sparseC,b16).String())
163 | if sparseAt.Cmp(classic) != 0 {
164 | t.Error(fmt.Sprintf("classic poly %v and sparse poly %v evaluation differ. At leas one of both must be wrong", sparseAt.String(), classic.String()))
165 | }
166 |
167 | }
168 |
169 | func TestSub(t *testing.T) {
170 | // new Finite Field
171 |
172 | f := NewFiniteField(bn256.Order)
173 | at, _ := f.Rand()
174 |
175 | order := 10000
176 | //1 is 100% of the coefficients are 0
177 | sparsityPercent := 0.1
178 | a := ArrayOfBigZeros(order)
179 | b := ArrayOfBigZeros(order)
180 | for i := 0; i < order; i += 1 + rand.Intn(int(float64(order)*sparsityPercent)) {
181 | a[i], _ = f.Rand()
182 | }
183 | for i := 0; i < order; i += 1 + rand.Intn(int(float64(order)*sparsityPercent)) {
184 | b[i], _ = f.Rand()
185 | }
186 | // new Polynomial Field
187 | pf := NewPolynomialField(f)
188 |
189 | before := time.Now()
190 | c := pf.Sub(a, b)
191 | fmt.Println("sub classic took", time.Since(before))
192 |
193 | sparseA := NewAvlTree()
194 | sparseB := NewAvlTree()
195 | for _, v := range rand.Perm(len(a)) {
196 | sparseA.Insert(uint(v), a[v])
197 | }
198 |
199 | for _, v := range rand.Perm(len(b)) {
200 | sparseB.Insert(uint(v), b[v])
201 | }
202 | before = time.Now()
203 | sparseC := f.SubToSparse(sparseA, sparseB)
204 | fmt.Println("sub sparse took", time.Since(before))
205 | before = time.Now()
206 | sparseAt := f.EvalSparsePoly(sparseC, at)
207 | fmt.Println("evaluate sparse took", time.Since(before))
208 |
209 | before = time.Now()
210 | classic := f.EvalPoly(c, at)
211 | fmt.Println("evaluate classic took", time.Since(before))
212 |
213 | //fmt.Println(f.EvalSparsePoly(sparseC,b16).String())
214 | if sparseAt.Cmp(classic) != 0 {
215 | t.Error(fmt.Sprintf("classic poly %v and sparse poly %v evaluation differ. At leas one of both must be wrong", sparseAt.String(), classic.String()))
216 | }
217 |
218 | }
219 | func TestSub2(t *testing.T) {
220 | // new Finite Field
221 |
222 | f := NewFiniteField(bn256.Order)
223 | at, _ := f.Rand()
224 |
225 | order := 2000
226 | sparsityPercent := 0.4
227 | a := ArrayOfBigZeros(order * 2)
228 | b := ArrayOfBigZeros(order)
229 | for i := 0; i < order*2; i += 1 + rand.Intn(int(float64(order)*sparsityPercent)) {
230 | a[i], _ = f.Rand()
231 | //a[i]=big.NewInt(int64(i))
232 | }
233 | for i := 0; i < order; i += 1 + rand.Intn(int(float64(order)*sparsityPercent)) {
234 | b[i], _ = f.Rand()
235 | //b[i]=big.NewInt(int64(i))
236 | }
237 | //a[0]=big.NewInt(-1)
238 | //a[1]=big.NewInt(0)
239 | //a[2]=big.NewInt(2)
240 | //b[0]=big.NewInt(0)
241 | //b[1]=big.NewInt(1)
242 | before := time.Now()
243 | sparseA := NewAvlTree()
244 | sparseB := NewAvlTree()
245 | for _, v := range rand.Perm(len(a)) {
246 | sparseA.Insert(uint(v), a[v])
247 | }
248 |
249 | for _, v := range rand.Perm(len(b)) {
250 | sparseB.Insert(uint(v), b[v])
251 | }
252 |
253 | before = time.Now()
254 | classic2 := f.EvalSparsePoly(sparseA, at)
255 | cDivSparse := f.SubToSparse(sparseA, sparseB)
256 | fmt.Println("sub sparse took", time.Since(before))
257 |
258 | //sparseA - sparseB= cDivSparse
259 | cd := f.AddToSparse(cDivSparse, sparseB)
260 |
261 | classic1 := f.EvalSparsePoly(cd, at)
262 |
263 | //fmt.Println(f.EvalSparsePoly(sparseC,b16).String())
264 | if classic1.Cmp(classic2) != 0 {
265 | t.Error(fmt.Sprintf("classic poly %v and sparse poly %v evaluation differ. At leas one of both must be wrong", classic1.String(), classic2.String()))
266 | }
267 |
268 | }
269 |
270 | //note that something weird happens with common division if sparsity increases.
271 | //could not find out whats the issue
272 | func TestDivide2(t *testing.T) {
273 | // new Finite Field
274 |
275 | f := NewFiniteField(bn256.Order)
276 | at, _ := f.Rand()
277 |
278 | polyField := &PolynomialField{F: f}
279 | order := 300
280 | sparsityPercent := 0.01
281 | a := ArrayOfBigZeros(order * 2)
282 | b := ArrayOfBigZeros(order)
283 | for i := 0; i < order*2; i += 1 + rand.Intn(int(float64(order)*sparsityPercent)) {
284 | a[i], _ = f.Rand()
285 | //a[i]=big.NewInt(int64(i))
286 | }
287 | for i := 0; i < order; i += 1 + rand.Intn(int(float64(order)*sparsityPercent)) {
288 | b[i], _ = f.Rand()
289 | //b[i]=big.NewInt(int64(i))
290 | }
291 | before := time.Now()
292 | sparseA := NewAvlTree()
293 | sparseB := NewAvlTree()
294 | for _, v := range rand.Perm(len(a)) {
295 | sparseA.Insert(uint(v), a[v])
296 | }
297 |
298 | for _, v := range rand.Perm(len(b)) {
299 | sparseB.Insert(uint(v), b[v])
300 | }
301 |
302 | before = time.Now()
303 | cDivSparse, rem2 := f.DivideSparse(sparseA, sparseB)
304 | fmt.Println("sparse division took", time.Since(before))
305 |
306 | before = time.Now()
307 | cdiv, crem := polyField.Div(a, b)
308 | fmt.Println("classic division took", time.Since(before))
309 |
310 | //sparseA=CdivSparece*sparseB +rem2
311 | mul := f.MulSparse(cDivSparse, sparseB)
312 | cd := f.AddToSparse(mul, rem2)
313 |
314 | reconstructed := f.EvalSparsePoly(cd, at)
315 | sparseEvaluated := f.EvalSparsePoly(sparseA, at)
316 |
317 | re := polyField.MulNaive(cdiv, b)
318 | re = polyField.Add(re, crem)
319 | reEval := f.EvalPoly(re, at)
320 | //fmt.Println(f.EvalSparsePoly(sparseC,b16).String())
321 | if reconstructed.Cmp(sparseEvaluated) != 0 || reEval.Cmp(sparseEvaluated) != 0 {
322 | t.Error(fmt.Sprintf("classic poly %v and sparse poly %v evaluation and %v classic division differ. At leas one of both must be wrong", reconstructed.String(), sparseEvaluated.String(), reEval.String()))
323 | }
324 |
325 | }
326 |
327 | func TestDivide(t *testing.T) {
328 | // new Finite Field
329 |
330 | f := NewFiniteField(bn256.Order)
331 | at, _ := f.Rand()
332 |
333 | order := 2000
334 | sparsityPercent := 0.1
335 | a := ArrayOfBigZeros(order * 2)
336 | b := ArrayOfBigZeros(order)
337 | for i := 0; i < order*2; i += 1 + rand.Intn(1+int(float64(order)*sparsityPercent)) {
338 | a[i], _ = f.Rand()
339 | //a[i]=big.NewInt(int64(i))
340 | }
341 | for i := 0; i < order; i += 1 + rand.Intn(1+int(float64(order)*sparsityPercent)) {
342 | b[i], _ = f.Rand()
343 | //b[i]=big.NewInt(int64(i))
344 | }
345 |
346 | before := time.Now()
347 | sparseA := NewAvlTree()
348 | sparseB := NewAvlTree()
349 | for _, v := range rand.Perm(len(a)) {
350 | sparseA.Insert(uint(v), a[v])
351 | }
352 |
353 | for _, v := range rand.Perm(len(b)) {
354 | sparseB.Insert(uint(v), b[v])
355 | }
356 |
357 | before = time.Now()
358 | cDivSparse, rem2 := f.DivideSparse(sparseA, sparseB)
359 | fmt.Println("sparse division took", time.Since(before))
360 |
361 | //sparseA:sparseB=CdivSparece +rem2
362 | cd := f.AddToSparse(f.MulSparse(cDivSparse, sparseB), rem2)
363 | classic1 := f.EvalSparsePoly(cd, at)
364 | classic2 := f.EvalSparsePoly(sparseA, at)
365 |
366 | //fmt.Println(f.EvalSparsePoly(sparseC,b16).String())
367 | if classic1.Cmp(classic2) != 0 {
368 | t.Error(fmt.Sprintf("classic poly %v and sparse poly %v evaluation differ. At leas one of both must be wrong", classic1.String(), classic2.String()))
369 | }
370 | }
371 |
372 | func TestSparseLagrangeInterpolation(t *testing.T) {
373 | // new Finite Field
374 | var Npoints = 250
375 | sparsityPercent := 0.8
376 | f := NewFiniteField(bn256.Order)
377 | // new Polynomial Field
378 | pf := NewPolynomialField(f)
379 |
380 | var err error
381 |
382 | Xpoints := make([]*big.Int, Npoints)
383 | for i := 0; i < Npoints; i++ {
384 | Xpoints[i] = new(big.Int).SetInt64(int64(i))
385 | }
386 |
387 | Ypoints := ArrayOfBigZeros(Npoints)
388 |
389 | for i := 0; i < Npoints; i += 1 + rand.Intn(1+int(float64(Npoints)*sparsityPercent)) {
390 | Ypoints[i], err = f.Rand()
391 | assert.Nil(t, err)
392 | }
393 |
394 | sparse := NewSparseArrayFromArray(Ypoints)
395 | sparse = pf.InterpolateSparseArray(sparse, Npoints)
396 | alpha := pf.LagrangeInterpolation(Ypoints)
397 | for i := Npoints - 1; i >= 0; i-- {
398 | if f.EvalPoly(alpha, Xpoints[i]).Cmp(Ypoints[i]) != 0 {
399 | t.Error("fail")
400 | }
401 | val := f.EvalSparsePoly(sparse, Xpoints[i])
402 | //fmt.Println(sparse)
403 | if val.Cmp(Ypoints[i]) != 0 {
404 | t.Error(fmt.Sprintf("fail sparse %v. Got %v", i, val.String()))
405 | }
406 |
407 | }
408 |
409 | }
410 |
--------------------------------------------------------------------------------
/utils/utils.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 | bn256 "github.com/mottla/go-R1CS-Compiler/pairing"
6 | "math"
7 | "math/big"
8 | "strings"
9 | )
10 |
11 | var bigZero = big.NewInt(int64(0))
12 | var bigOne = big.NewInt(int64(1))
13 |
14 | //Todo I dont like this pubic accessible thing here
15 | var Field = PrepareFields(bn256.Order)
16 |
17 | //var Field = PrepareFields(new(big.Int).SetInt64(1009))
18 |
19 | // Transpose transposes the *big.Int matrix
20 | func Transpose(matrix []Poly) []Poly {
21 | r := make([]Poly, len(matrix[0]))
22 | for x := range r {
23 | r[x] = make(Poly, len(matrix))
24 | }
25 | for y, s := range matrix {
26 | for x, e := range s {
27 | r[x][y] = e
28 | }
29 | }
30 | return r
31 | }
32 |
33 | // ArrayOfBigZeros creates a *big.Int array with n elements to zero
34 | func ArrayOfBigZeros(num int) Poly {
35 |
36 | var r = make(Poly, num, num)
37 | for i := 0; i < num; i++ {
38 | r[i] = bigZero
39 | }
40 | return r
41 | }
42 | func BigArraysEqual(a, b []*big.Int) bool {
43 | if len(a) != len(b) {
44 | return false
45 | }
46 | for i := 0; i < len(a); i++ {
47 | if a[i].Cmp(b[i]) != 0 {
48 | return false
49 | }
50 | }
51 | return true
52 | }
53 |
54 | func IsZeroArray(a []*big.Int) bool {
55 | for i := 0; i < len(a); i++ {
56 | if a[i].Cmp(bigZero) != 0 {
57 | return false
58 | }
59 | }
60 | return true
61 | }
62 | func BigIsOdd(n *big.Int) bool {
63 | return n.Bit(0) == 1
64 | }
65 |
66 | func MaxInt(a, b int) int {
67 | if a > b {
68 | return a
69 | }
70 | return b
71 | }
72 |
73 | //checks if a integer is a power of 2
74 | //From Henry Warrens Hackers Delight
75 | func IsPowerTwo(in uint64) bool {
76 | if in == 0 {
77 | return false
78 | }
79 | n := in & (in - 1)
80 | if n == 0 {
81 | return true
82 | }
83 | return false
84 | }
85 |
86 | func Equal(a, b int) int {
87 | if a == b {
88 | return 1
89 | }
90 | return 0
91 | }
92 |
93 | func NextPowerOfTwo(n int) int {
94 | p := int(1)
95 | if (n & (n - 1)) == 0 {
96 | return n
97 | }
98 | for p < n {
99 | p <<= 1
100 | }
101 | return p
102 | }
103 | func Addicity(n int) int {
104 | p := int(1)
105 | ad := 0
106 | for p&n == 0 {
107 | n = n >> 1
108 | ad += 1
109 | }
110 | return ad
111 | }
112 |
113 | //euclid returns q,r s.t. a=bq+r
114 | func euclid(a, b uint) (q, r uint) {
115 | return a / b, a % b
116 | }
117 | func maximum(a ...int) int {
118 | if len(a) == 0 {
119 | return math.MinInt64
120 | }
121 | return MaxInt(a[0], maximum(a[1:]...))
122 |
123 | }
124 |
125 | func AbsInt(i int) int {
126 | if i < 0 {
127 | return -i
128 | }
129 | return i
130 | }
131 | func ExtendArrayWithZeros(in []*big.Int, desiredLength int) []*big.Int {
132 | if len(in) < desiredLength {
133 | rest := desiredLength - len(in)
134 | //fmt.Printf("\npolysize %v, filled up to next power of two 2^%v. Add %v dummy values", len(polynomial), bit, rest)
135 | in = append(in, ArrayOfBigZeros(rest)...)
136 | }
137 | return in
138 | }
139 |
140 | //returns the absolute value of a signed int and a flag telling if the input was positive or not
141 | //this implementation is awesome and fast (see Henry S Warren, Hackers's Delight)
142 | func Abs(n int) (val int, positive bool) {
143 | y := n >> 63
144 | return (n ^ y) - y, y == 0
145 | }
146 |
147 | type FastBool struct {
148 | val *big.Int
149 | }
150 |
151 | func NewFastBool() FastBool {
152 | return FastBool{val: new(big.Int)}
153 | }
154 |
155 | func (fb FastBool) Set(pos int) {
156 | fb.val.SetBit(fb.val, pos, 1)
157 | }
158 | func (fb FastBool) IsSet(pos int) bool {
159 | if fb.val.Bit(pos) == 1 {
160 | return true
161 | }
162 | return false
163 | }
164 |
165 | //the go a%b return negative representants too.. that sucks so much
166 | func Mod(a, b int) int {
167 | r := a % b
168 | if r < 0 {
169 | r += b
170 | }
171 | return r
172 | }
173 |
174 | func PrintWithLineNumbering(s string) {
175 | y := func(c rune) bool {
176 | return c == '\n'
177 | }
178 | testArray := strings.FieldsFunc(s, y)
179 | for i, w := range testArray {
180 | fmt.Println(i, w)
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/utils/utils_test.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 | )
7 |
8 | func TestNextPowerOfTwo(t *testing.T) {
9 | for i := 0; i < 63; i++ {
10 | if NextPowerOfTwo(1<= len(Li) {
145 | panic("to moany public parameters")
146 | }
147 |
148 | fmt.Println("Performing Scalar Point Multiplications...")
149 | before = time.Now()
150 |
151 | // generate trapdoor
152 | setup.Toxic.Kalpha, err = fields.ArithmeticField.Rand()
153 | if err != nil {
154 | panic("random failed")
155 | }
156 | setup.Toxic.Kbeta, err = fields.ArithmeticField.Rand()
157 | if err != nil {
158 | panic("random failed")
159 | }
160 | setup.Toxic.Kgamma, err = fields.ArithmeticField.Rand()
161 | if err != nil {
162 | panic("random failed")
163 | }
164 | setup.Toxic.Kdelta, err = fields.ArithmeticField.Rand()
165 | if err != nil {
166 | panic("random failed")
167 | }
168 |
169 | //the domain poly over the roots of unity is realy simple
170 | Domain := FFT_Paras.Domain
171 |
172 | setup.Pk.Domain = FFT_Paras.Domain
173 |
174 | Dx := fields.ArithmeticField.EvalPoly(Domain, setup.Toxic.x)
175 | invDelta := fields.ArithmeticField.Inverse(setup.Toxic.Kdelta)
176 | invgamma := fields.ArithmeticField.Inverse(setup.Toxic.Kgamma)
177 | Dx_div_delta := fields.ArithmeticField.Mul(invDelta, Dx)
178 |
179 | // encrypt x values with curve generators
180 | // x^i times D(x) divided by delta
181 | var powersXDomaindivDelta = []*bn256.G1{g1ScalarBaseMultiply(Dx_div_delta)}
182 | var powersX_onG = []*bn256.G1{g1ScalarBaseMultiply(big.NewInt(1))}
183 | var powersX_onH = []*bn256.G2{g2ScalarBaseMultiply(big.NewInt(1))}
184 |
185 | //G^{x^i}
186 | xi := new(big.Int).Set(setup.Toxic.x)
187 | for i := 1; i < gates; i++ {
188 |
189 | if i < gates-1 {
190 | powersXDomaindivDelta = append(powersXDomaindivDelta, g1ScalarBaseMultiply(fields.ArithmeticField.Mul(xi, Dx_div_delta)))
191 | }
192 |
193 | powersX_onG = append(powersX_onG, g1ScalarBaseMultiply(xi))
194 | powersX_onH = append(powersX_onH, g2ScalarBaseMultiply(xi))
195 | // x^i -> x^{i+1}
196 | xi = fields.ArithmeticField.Mul(xi, setup.Toxic.x)
197 | }
198 |
199 | setup.Pk.G1.PowersX = powersX_onG
200 | setup.Pk.G2.PowersX = powersX_onH
201 | setup.Pk.G1.PowersX_Domain_Delta = powersXDomaindivDelta
202 |
203 | setup.Pk.G1.Alpha = g1ScalarBaseMultiply(setup.Toxic.Kalpha)
204 | setup.Pk.G1.Beta = g1ScalarBaseMultiply(setup.Toxic.Kbeta)
205 | setup.Pk.G1.Delta = g1ScalarBaseMultiply(setup.Toxic.Kdelta)
206 |
207 | setup.Pk.G2.Beta = g2ScalarBaseMultiply(setup.Toxic.Kbeta)
208 | setup.Pk.G2.Gamma = g2ScalarBaseMultiply(setup.Toxic.Kgamma)
209 | setup.Pk.G2.Delta = g2ScalarBaseMultiply(setup.Toxic.Kdelta)
210 |
211 | var wk = func(start, end int) {
212 | for i := start; i < end; i++ {
213 | // Li(x)
214 |
215 | // g^{Li(x)}
216 | setup.Pk.G1.Lix[i] = g1ScalarBaseMultiply(Li[i])
217 |
218 | // Ri(x)
219 |
220 | // h^{Ri(x)}
221 | setup.Pk.G2.Rix[i] = g2ScalarBaseMultiply(Ri[i])
222 | // g^{Ri(x)}
223 | setup.Pk.G1.Rix[i] = g1ScalarBaseMultiply(Ri[i])
224 |
225 | // Oi(x)
226 |
227 | //{alpha * Ri(x) + beta * Li(x) + Oi(x) }
228 | ter := fields.ArithmeticField.Mul(setup.Toxic.Kalpha, Ri[i])
229 | ter = fields.ArithmeticField.Add(ter, fields.ArithmeticField.Mul(setup.Toxic.Kbeta, Li[i]))
230 | ter = fields.ArithmeticField.Add(ter, Oi[i])
231 |
232 | if i < publicinputs {
233 | ter = fields.ArithmeticField.Mul(invgamma, ter)
234 | //g^ {alpha * Ri(x) + beta * Li(x) + Oi(x) }/ gamma
235 | setup.Pk.G1.RLO_DivGamma[i] = g1ScalarBaseMultiply(ter)
236 | } else {
237 | ter = fields.ArithmeticField.Mul(invDelta, ter)
238 | //g^ {alpha * Ri(x) + beta * Li(x) + Oi(x) }/ delta
239 | setup.Pk.G1.RLO_DivDelta[i-publicinputs] = g1ScalarBaseMultiply(ter)
240 | }
241 | }
242 | }
243 | utils.Parallelize(witnessLength, wk)
244 |
245 | //precompute e(g^alpha,h^beta)
246 | setup.Pk.eGHalphaBeta = bn256.Pair(setup.Pk.G1.Alpha, setup.Pk.G2.Beta)
247 | fmt.Println("Scalar Point Multiplications done in ", time.Since(before))
248 | return setup, nil
249 | }
250 |
251 | // GenerateProofs generates all the parameters to proof the zkSNARK from the function, Setup and the Witness
252 | func GenerateProofs(publicInputs int, provingKey *Pk, witnessTrace []*big.Int, hx []*big.Int) (*Proof, error) {
253 |
254 | var proof = new(Proof)
255 | //load the field divened over the curve bn256 order
256 | fields := utils.Field
257 |
258 | //generate random r,s
259 | r, err := fields.ArithmeticField.Rand()
260 | if err != nil {
261 | panic("random failed")
262 | }
263 | s, err := fields.ArithmeticField.Rand()
264 | if err != nil {
265 | panic("random failed")
266 | }
267 |
268 | //first element of A, g^L0(x)*a0
269 |
270 | proof.PiA = new(bn256.G1).ScalarMult(provingKey.G1.Lix[0], witnessTrace[0])
271 |
272 | //first element of B, h^L0(x)*a0
273 | proof.PiB = new(bn256.G2).ScalarMult(provingKey.G2.Rix[0], witnessTrace[0])
274 |
275 | //element of C, g^R0(x)*a0
276 | tmpR := new(bn256.G1).ScalarMult(provingKey.G1.Rix[0], witnessTrace[0])
277 |
278 | proof.PiC = new(bn256.G1).ScalarMult(provingKey.G1.RLO_DivDelta[0], witnessTrace[publicInputs])
279 |
280 | var QxDx_div_delta = new(bn256.G1).ScalarMult(provingKey.G1.PowersX_Domain_Delta[0], hx[0])
281 |
282 | for i := 1; i < len(provingKey.G1.PowersX_Domain_Delta); i++ {
283 | tmp := new(bn256.G1).ScalarMult(provingKey.G1.PowersX_Domain_Delta[i], hx[i])
284 | QxDx_div_delta.Add(QxDx_div_delta, tmp)
285 | }
286 |
287 | for i := 1; i < len(witnessTrace); i++ {
288 | //proof element A
289 | proof.PiA.Add(proof.PiA, new(bn256.G1).ScalarMult(provingKey.G1.Lix[i], witnessTrace[i]))
290 |
291 | //proof element C right part
292 | tmpR.Add(tmpR, new(bn256.G1).ScalarMult(provingKey.G1.Rix[i], witnessTrace[i]))
293 |
294 | //proof element B
295 | proof.PiB.Add(proof.PiB, new(bn256.G2).ScalarMult(provingKey.G2.Rix[i], witnessTrace[i]))
296 |
297 | if i > publicInputs {
298 | //proof element C
299 | proof.PiC.Add(proof.PiC, new(bn256.G1).ScalarMult(provingKey.G1.RLO_DivDelta[i-publicInputs], witnessTrace[i]))
300 | }
301 |
302 | }
303 | //add the alpha and r*delta therm to proof element A
304 | proof.PiA.Add(proof.PiA, provingKey.G1.Alpha)
305 | c1 := proof.PiA.Copy()
306 | proof.PiA.Add(proof.PiA, new(bn256.G1).ScalarMult(provingKey.G1.Delta, r))
307 |
308 | //add the beta and s*delta therm to proof element A
309 | proof.PiB.Add(proof.PiB, provingKey.G2.Beta)
310 | proof.PiB.Add(proof.PiB, new(bn256.G2).ScalarMult(provingKey.G2.Delta, s))
311 |
312 | //add the Q(x)D(x)/delta therm to the proof element C
313 | proof.PiC.Add(proof.PiC, QxDx_div_delta)
314 |
315 | proof.PiC.Add(proof.PiC, new(bn256.G1).ScalarMult(c1, s))
316 | proof.PiC.Add(proof.PiC, new(bn256.G1).ScalarMult(new(bn256.G1).Add(tmpR, provingKey.G1.Beta), r))
317 |
318 | proof.PiC.Add(proof.PiC, new(bn256.G1).ScalarMult(provingKey.G1.Delta, fields.ArithmeticField.Mul(r, s)))
319 |
320 | return proof, nil
321 | }
322 |
323 | // VerifyProof verifies over the BN256 the Pairings of the Proof
324 | func VerifyProof(pk *Pk, proof *Proof, publicSignals []*big.Int) bool {
325 | //note that the trivial cases should be rejected to
326 |
327 | if len(publicSignals) != len(pk.G1.RLO_DivGamma) {
328 | fmt.Println("❌ groth16 verification not passed. Signal length wrong")
329 | return false
330 | }
331 |
332 | icPubl := new(bn256.G1).ScalarMult(pk.G1.RLO_DivGamma[0], publicSignals[0])
333 | for i := 1; i < len(publicSignals); i++ {
334 | icPubl.Add(icPubl, new(bn256.G1).ScalarMult(pk.G1.RLO_DivGamma[i], publicSignals[i]))
335 | }
336 |
337 | a := bn256.Pair(proof.PiA, proof.PiB)
338 |
339 | b := pk.eGHalphaBeta
340 | c := bn256.Pair(icPubl, pk.G2.Gamma)
341 | d := bn256.Pair(proof.PiC, pk.G2.Delta)
342 |
343 | bc := new(bn256.GT).Add(b, c)
344 | bcd := new(bn256.GT).Add(bc, d)
345 |
346 | if bytes.Equal(a.Marshal(), bcd.Marshal()) {
347 | fmt.Println("✓ groth16 verification passed")
348 | return true
349 | }
350 | fmt.Println("❌ groth16 verification not passed.")
351 | return false
352 |
353 | }
354 |
--------------------------------------------------------------------------------
/zkSNARK/groth16_test.go:
--------------------------------------------------------------------------------
1 | package zkSNARK
2 |
3 | import (
4 | "fmt"
5 | "github.com/mottla/go-R1CS-Compiler/Circuitcompiler"
6 | "github.com/mottla/go-R1CS-Compiler/testPrograms"
7 | "github.com/stretchr/testify/assert"
8 | "testing"
9 | "time"
10 | )
11 |
12 | func TestGenerateAndVerifyProof_FFT(t *testing.T) {
13 |
14 | for _, test := range testPrograms.TestPrograms {
15 | if test.Skip {
16 | continue
17 | }
18 |
19 | program := Circuitcompiler.Parse(test.Code, true)
20 |
21 | fmt.Println("Code>>")
22 | fmt.Println(test.Code)
23 |
24 | before := time.Now()
25 | fmt.Println("Generating SRS...")
26 | tt := time.Now()
27 | container := program.Execute()
28 | gates := container.OrderedGates()
29 | fmt.Println("Parsing into arithmetic circuit took ", time.Since(tt))
30 | fmt.Println("Generating R1CS...")
31 | tt = time.Now()
32 | r1cs := program.GatesToR1CS(gates)
33 | fmt.Println("Parsing arithmetic circuit into R1CS took ", time.Since(tt))
34 | trasposedR1Cs := r1cs.Transpose()
35 | //fmt.Println(r1cs.L)
36 | //fmt.Println(r1cs.R)
37 | //fmt.Println(r1cs.O)
38 | fmt.Println("Number of gates ", r1cs.NumberOfGates)
39 | setup, err := GenerateTrustedSetup_FFT(program.GlobalInputCount(), trasposedR1Cs)
40 | fmt.Println("SRS generation time elapsed:", time.Since(before))
41 | assert.NoError(t, err)
42 |
43 | for _, io := range test.IO {
44 | fmt.Println("Start Proof Generation...")
45 | inputs := Circuitcompiler.CombineInputs(program.GetMainCircuit().ArgumentIdentifiers, io.Inputs)
46 |
47 | tt = time.Now()
48 | fmt.Println("Compute trace...")
49 | trace, err := Circuitcompiler.CalculateTrace(r1cs, inputs)
50 | fmt.Println("Compute trace took ", time.Since(tt))
51 |
52 | assert.NoError(t, err)
53 |
54 | tt = time.Now()
55 | fmt.Println("Compute divisor polynomial H(x)... ")
56 | hx := CombinePolynomials_Efficient(setup.fftParas, trace, trasposedR1Cs)
57 | fmt.Println("Compute divisor polynomial H(x) took ", time.Since(tt))
58 | //pf := utils.Field.PolynomialField
59 | //f := utils.Field.ArithmeticField
60 | //var bigZero = big.NewInt(int64(0))
61 | //v := new(big.Int).SetInt64(1)
62 |
63 | //for i := uint(0); i < uint(r1cs.NumberOfGates); i++ {
64 | // L := pf.EvalPoly(pf.MulNaive(hx, setup.fftParas.Domain), v)
65 | // v = f.MulNaive(v, setup.fftParas.RootOfUnity)
66 | // if L.Cmp(bigZero) != 0 {
67 | // t.Error("Px must be zero ate each gate")
68 | // }
69 | //}
70 |
71 | before := time.Now()
72 | proof, err := GenerateProofs(program.GlobalInputCount(), &setup.Pk, trace, hx)
73 | fmt.Println("proof generation time elapsed:", time.Since(before))
74 | assert.Nil(t, err)
75 | before = time.Now()
76 | assert.True(t, VerifyProof(&setup.Pk, proof, trace[:program.GlobalInputCount()]))
77 | fmt.Println("verify proof time elapsed:", time.Since(before))
78 | fmt.Println("Proof Elements: ", proof)
79 | }
80 | }
81 | }
82 |
83 | //func TestGenerateAndVerifyProof_sparse(t *testing.T) {
84 | //
85 | // for _, test := range testPrograms.TestPrograms {
86 | // if test.Skip {
87 | // continue
88 | // }
89 | //
90 | // program := Circuitcompiler.Parse(test.Code, true)
91 | //
92 | // fmt.Println("Code>>")
93 | // fmt.Println(test.Code)
94 | //
95 | // before := time.Now()
96 | // fmt.Println("Generating CRS...")
97 | // gates := program.Execute()
98 | //
99 | // fmt.Println("\n generating R1CS")
100 | // r1cs := program.GatesToSparseR1CS(gates, true)
101 | //
102 | // //r1csSparse := program.GatesToSparseR1CS(gates, true)
103 | // //transposedR1csSparse := r1csSparse.TransposeSparse()
104 | // trasposedR1Cs := r1cs.TransposeSparse()
105 | // fmt.Println(r1cs.L)
106 | // fmt.Println(r1cs.R)
107 | // fmt.Println(r1cs.O)
108 | //
109 | // //fmt.Println(l)
110 | // //fmt.Println(r)
111 | // //fmt.Println(e)
112 | // //fmt.Println(o)
113 | //
114 | // setup, err := GenerateTrustedSetupSparse(program.GlobalInputCount(), trasposedR1Cs)
115 | // fmt.Println("CRS generation time elapsed:", time.Since(before))
116 | // assert.NoError(t, err)
117 | //
118 | // for _, io := range test.IO {
119 | // inputs := Circuitcompiler.CombineInputs(program.PublicInputs, io.InputIdentifiers)
120 | // w, err := Circuitcompiler.CalculateTrace_sparse(r1cs, inputs)
121 | //
122 | // assert.NoError(t, err)
123 | // //wsparse, werr := Circuitcompiler.CalculateTrace_sparse(r1csSparse, inputs)
124 | // //assert.NoError(t, werr)
125 | //
126 | // fmt.Println("input")
127 | // fmt.Println(inputs)
128 | // fmt.Println("witness")
129 | // fmt.Println(w)
130 | // //fmt.Println(wsparse)
131 | // //assert.Equal(t, io.result, w[len(w)-1])
132 | // // CombineSparsePolynomials(program.Fields, w, transposedR1csSparse)
133 | // px := CombineSparsePolynomials(w, trasposedR1Cs)
134 | // //mf3,px3 := CombinePolynomials3(program.Fields,w,trasposedR1Cs)
135 | // //mSparse,pSparse := CombineSparsePolynomials(program.Fields,wSparse,r1csSparse)
136 | //
137 | // //assert.Equal(t, px, px3)
138 | // //assert.Equal(t, mf2, mf3)
139 | // var bigZero = big.NewInt(int64(0))
140 | //
141 | // //Test if P(x) is indeed 0 at each gate index
142 | // for i := 0; i < len(gates); i++ {
143 | // if bigZero.Cmp(utils.Field.ArithmeticField.EvalSparsePoly(px, new(big.Int).SetInt64(int64(i)))) != 0 {
144 | // t.Error(fmt.Sprintf("Px must be zero ae gate %v", i))
145 | // }
146 | // }
147 | //
148 | // before := time.Now()
149 | // proof, err := GenerateProof_Sparse(program.GlobalInputCount(), &setup.Pk, w, px)
150 | //
151 | // fmt.Println("proof generation time elapsed:", time.Since(before))
152 | // assert.Nil(t, err)
153 | // before = time.Now()
154 | // assert.True(t, VerifyProof(&setup.Pk, proof, w[:program.GlobalInputCount()], true))
155 | // fmt.Println("verify proof time elapsed:", time.Since(before))
156 | // fmt.Println("Proof Elements: ", proof)
157 | // }
158 | //
159 | // }
160 | //
161 | //}
162 |
163 | //func TestGenerateAndVerifyProof_both(t *testing.T) {
164 | //
165 | // for _, test := range testPrograms.TestPrograms {
166 | // if test.Skip {
167 | // continue
168 | // }
169 | //
170 | // program := Circuitcompiler.Parse(test.Code, true)
171 | //
172 | // fmt.Println("Code>>")
173 | // fmt.Println(test.Code)
174 | //
175 | // fmt.Println("Translating Program...")
176 | // gates := program.Execute()
177 | // r1cs := program.GatesToR1CS(gates, false)
178 | // fmt.Printf("number of gates %v, witness length %v \n ", r1cs.NumberOfGates, r1cs.WitnessLength)
179 | // //fmt.Println(r1cs.L)
180 | // //fmt.Println(r1cs.R)
181 | // //fmt.Println(r1cs.E)
182 | // //fmt.Println(r1cs.O)
183 | // trasposedR1Cs := r1cs.Transpose()
184 | //
185 | // before := time.Now()
186 | // setup, err := GenerateTrustedSetup(program.GlobalInputCount(), trasposedR1Cs)
187 | // fmt.Println("classic CRS generation time elapsed:", time.Since(before))
188 | // assert.NoError(t, err)
189 | //
190 | // r1csSparse := program.GatesToSparseR1CS(gates, false)
191 | // transposedR1csSparse := r1csSparse.TransposeSparse()
192 | //
193 | // before = time.Now()
194 | // setupSparse, erro := GenerateTrustedSetupSparse(program.GlobalInputCount(), transposedR1csSparse)
195 | // fmt.Println("sparse CRS generation time elapsed:", time.Since(before))
196 | // assert.NoError(t, erro)
197 | //
198 | // for _, io := range test.IO {
199 | // inputs := Circuitcompiler.CombineInputs(program.PublicInputs, io.InputIdentifiers)
200 | // w, err := Circuitcompiler.CalculateTrace(r1cs, inputs)
201 | // assert.NoError(t, err)
202 | // wsparse, werr := Circuitcompiler.CalculateTrace_sparse(r1csSparse, inputs)
203 | // assert.NoError(t, werr)
204 | //
205 | // fmt.Println("input")
206 | // fmt.Println(inputs)
207 | // fmt.Println("witness")
208 | // fmt.Println(w)
209 | // //fmt.Println(wsparse)
210 | // assert.Equal(t, wsparse[:len(wsparse)-1], w[:len(wsparse)-1])
211 | // // CombineSparsePolynomials(program.Fields, w, transposedR1csSparse)
212 | // px := CombinePolynomials2(w, trasposedR1Cs)
213 | //
214 | // //mf3,px3 := CombinePolynomials3(program.Fields,w,trasposedR1Cs)
215 | // pSparse := CombineSparsePolynomials(wsparse, transposedR1csSparse)
216 | // fmt.Println("PX es")
217 | // assert.Equal(t, px, pSparse.ToArray(len(px)))
218 | //
219 | // var bigZero = big.NewInt(int64(0))
220 | //
221 | // //Test if P(x) is indeed 0 at each gate index
222 | // for i := 0; i < r1cs.NumberOfGates; i++ {
223 | // if bigZero.Cmp(utils.Field.ArithmeticField.EvalPoly(px, new(big.Int).SetInt64(int64(i)))) != 0 {
224 | // t.Error("Px must be zero ate each gate")
225 | // }
226 | // if bigZero.Cmp(utils.Field.ArithmeticField.EvalSparsePoly(pSparse, new(big.Int).SetInt64(int64(i)))) != 0 {
227 | // t.Error(fmt.Sprintf("Px must be zero ae gate %v", i))
228 | // }
229 | // at, _ := utils.Field.ArithmeticField.Rand()
230 | // if utils.Field.ArithmeticField.EvalPoly(px, at).Cmp(utils.Field.ArithmeticField.EvalSparsePoly(pSparse, at)) != 0 {
231 | // t.Error("unequal ")
232 | // }
233 | // }
234 | //
235 | // before := time.Now()
236 | // proof, err := GenerateProofs(program.GlobalInputCount(), &setup.Pk, w, px)
237 | // fmt.Println("proof classic generation time elapsed:", time.Since(before))
238 | // assert.Nil(t, err)
239 | //
240 | // before = time.Now()
241 | // proofSpares, err := GenerateProof_Sparse(program.GlobalInputCount(), &setupSparse.Pk, wsparse, pSparse)
242 | // fmt.Println("proof spare generation time elapsed:", time.Since(before))
243 | // assert.Nil(t, err)
244 | //
245 | // before = time.Now()
246 | // assert.True(t, VerifyProof(&setup.Pk, proof, w[:program.GlobalInputCount()], true))
247 | // fmt.Println("verify classic proof time elapsed:", time.Since(before))
248 | // fmt.Println("Proof Elements: ", proof)
249 | //
250 | // before = time.Now()
251 | // assert.True(t, VerifyProof(&setupSparse.Pk, proofSpares, wsparse[:program.GlobalInputCount()], true))
252 | // fmt.Println("verify sparse proof time elapsed:", time.Since(before))
253 | // fmt.Println("Proof Elements: ", proofSpares)
254 | // }
255 | //
256 | // }
257 | //
258 | //}
259 |
--------------------------------------------------------------------------------