├── 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 |
106 |
107 |
108 |
109 | 110 | 111 |
112 | 113 |
114 | 115 | 116 |
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 |
106 |
107 |
108 |
109 | 110 | 111 |
112 | 113 |
114 | 115 | 116 |
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 | --------------------------------------------------------------------------------