r1cs to qap over finite field

This commit is contained in:
arnaucube
2018-12-02 19:13:18 +01:00
parent e889b8b7dc
commit b1df15a497
16 changed files with 1060 additions and 45 deletions

View File

@@ -0,0 +1,145 @@
package r1csqapFloat
import (
"math/big"
)
func Transpose(matrix [][]*big.Float) [][]*big.Float {
var r [][]*big.Float
for i := 0; i < len(matrix[0]); i++ {
var row []*big.Float
for j := 0; j < len(matrix); j++ {
row = append(row, matrix[j][i])
}
r = append(r, row)
}
return r
}
func ArrayOfBigZeros(num int) []*big.Float {
bigZero := big.NewFloat(float64(0))
var r []*big.Float
for i := 0; i < num; i++ {
r = append(r, bigZero)
}
return r
}
func PolMul(a, b []*big.Float) []*big.Float {
r := ArrayOfBigZeros(len(a) + len(b) - 1)
for i := 0; i < len(a); i++ {
for j := 0; j < len(b); j++ {
r[i+j] = new(big.Float).Add(
r[i+j],
new(big.Float).Mul(a[i], b[j]))
}
}
return r
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func PolAdd(a, b []*big.Float) []*big.Float {
r := ArrayOfBigZeros(max(len(a), len(b)))
for i := 0; i < len(a); i++ {
r[i] = new(big.Float).Add(r[i], a[i])
}
for i := 0; i < len(b); i++ {
r[i] = new(big.Float).Add(r[i], b[i])
}
return r
}
func PolSub(a, b []*big.Float) []*big.Float {
r := ArrayOfBigZeros(max(len(a), len(b)))
for i := 0; i < len(a); i++ {
r[i] = new(big.Float).Add(r[i], a[i])
}
for i := 0; i < len(b); i++ {
bneg := new(big.Float).Mul(b[i], big.NewFloat(float64(-1)))
r[i] = new(big.Float).Add(r[i], bneg)
}
return r
}
func FloatPow(a *big.Float, e int) *big.Float {
if e == 0 {
return big.NewFloat(float64(1))
}
result := new(big.Float).Copy(a)
for i := 0; i < e-1; i++ {
result = new(big.Float).Mul(result, a)
}
return result
}
func PolEval(v []*big.Float, x *big.Float) *big.Float {
r := big.NewFloat(float64(0))
for i := 0; i < len(v); i++ {
xi := FloatPow(x, i)
elem := new(big.Float).Mul(v[i], xi)
r = new(big.Float).Add(r, elem)
}
return r
}
func NewPolZeroAt(pointPos, totalPoints int, height *big.Float) []*big.Float {
fac := 1
for i := 1; i < totalPoints+1; i++ {
if i != pointPos {
fac = fac * (pointPos - i)
}
}
facBig := big.NewFloat(float64(fac))
hf := new(big.Float).Quo(height, facBig)
r := []*big.Float{hf}
for i := 1; i < totalPoints+1; i++ {
if i != pointPos {
ineg := big.NewFloat(float64(-i))
b1 := big.NewFloat(float64(1))
r = PolMul(r, []*big.Float{ineg, b1})
}
}
return r
}
func LagrangeInterpolation(v []*big.Float) []*big.Float {
// https://en.wikipedia.org/wiki/Lagrange_polynomial
var r []*big.Float
for i := 0; i < len(v); i++ {
r = PolAdd(r, NewPolZeroAt(i+1, len(v), v[i]))
}
//
return r
}
func R1CSToQAP(a, b, c [][]*big.Float) ([][]*big.Float, [][]*big.Float, [][]*big.Float, []*big.Float) {
aT := Transpose(a)
bT := Transpose(b)
cT := Transpose(c)
var alpha [][]*big.Float
for i := 0; i < len(aT); i++ {
alpha = append(alpha, LagrangeInterpolation(aT[i]))
}
var beta [][]*big.Float
for i := 0; i < len(bT); i++ {
beta = append(beta, LagrangeInterpolation(bT[i]))
}
var gamma [][]*big.Float
for i := 0; i < len(cT); i++ {
gamma = append(gamma, LagrangeInterpolation(cT[i]))
}
z := []*big.Float{big.NewFloat(float64(1))}
for i := 1; i < len(aT[0])+1; i++ {
ineg := big.NewFloat(float64(-i))
b1 := big.NewFloat(float64(1))
z = PolMul(z, []*big.Float{ineg, b1})
}
return alpha, beta, gamma, z
}

View File

@@ -0,0 +1,112 @@
package r1csqapFloat
import (
"fmt"
"math/big"
"testing"
"github.com/stretchr/testify/assert"
)
func TestTranspose(t *testing.T) {
b0 := big.NewFloat(float64(0))
b1 := big.NewFloat(float64(1))
bFive := big.NewFloat(float64(5))
a := [][]*big.Float{
[]*big.Float{b0, b1, b0, b0, b0, b0},
[]*big.Float{b0, b0, b0, b1, b0, b0},
[]*big.Float{b0, b1, b0, b0, b1, b0},
[]*big.Float{bFive, b0, b0, b0, b0, b1},
}
aT := Transpose(a)
assert.Equal(t, aT, [][]*big.Float{
[]*big.Float{b0, b0, b0, bFive},
[]*big.Float{b1, b0, b1, b0},
[]*big.Float{b0, b0, b0, b0},
[]*big.Float{b0, b1, b0, b0},
[]*big.Float{b0, b0, b1, b0},
[]*big.Float{b0, b0, b0, b1},
})
}
func TestPol(t *testing.T) {
b0 := big.NewFloat(float64(0))
b1 := big.NewFloat(float64(1))
// b1neg := big.NewFloat(float64(-1))
// b2 := big.NewFloat(float64(2))
b2neg := big.NewFloat(float64(-2))
b3 := big.NewFloat(float64(3))
b4 := big.NewFloat(float64(4))
b5 := big.NewFloat(float64(5))
b6 := big.NewFloat(float64(6))
b16 := big.NewFloat(float64(16))
a := []*big.Float{b1, b0, b5}
b := []*big.Float{b3, b0, b1}
// polynomial multiplication
c := PolMul(a, b)
assert.Equal(t, c, []*big.Float{b3, b0, b16, b0, b5})
// polynomial addition
c = PolAdd(a, b)
assert.Equal(t, c, []*big.Float{b4, b0, b6})
// polynomial subtraction
c = PolSub(a, b)
assert.Equal(t, c, []*big.Float{b2neg, b0, b4})
// FloatPow
p := FloatPow(big.NewFloat(float64(5)), 3)
assert.Equal(t, p, big.NewFloat(float64(125)))
p = FloatPow(big.NewFloat(float64(5)), 0)
assert.Equal(t, p, big.NewFloat(float64(1)))
// NewPolZeroAt
r := NewPolZeroAt(3, 4, b4)
assert.Equal(t, PolEval(r, big.NewFloat(3)), b4)
r = NewPolZeroAt(2, 4, b3)
assert.Equal(t, PolEval(r, big.NewFloat(2)), b3)
}
func TestLagrangeInterpolation(t *testing.T) {
b0 := big.NewFloat(float64(0))
b5 := big.NewFloat(float64(5))
a := []*big.Float{b0, b0, b0, b5}
alpha := LagrangeInterpolation(a)
assert.Equal(t, PolEval(alpha, big.NewFloat(4)), b5)
aux, _ := PolEval(alpha, big.NewFloat(3)).Int64()
assert.Equal(t, aux, int64(0))
}
func TestR1CSToQAP(t *testing.T) {
b0 := big.NewFloat(float64(0))
b1 := big.NewFloat(float64(1))
b5 := big.NewFloat(float64(5))
a := [][]*big.Float{
[]*big.Float{b0, b1, b0, b0, b0, b0},
[]*big.Float{b0, b0, b0, b1, b0, b0},
[]*big.Float{b0, b1, b0, b0, b1, b0},
[]*big.Float{b5, b0, b0, b0, b0, b1},
}
b := [][]*big.Float{
[]*big.Float{b0, b1, b0, b0, b0, b0},
[]*big.Float{b0, b1, b0, b0, b0, b0},
[]*big.Float{b1, b0, b0, b0, b0, b0},
[]*big.Float{b1, b0, b0, b0, b0, b0},
}
c := [][]*big.Float{
[]*big.Float{b0, b0, b0, b1, b0, b0},
[]*big.Float{b0, b0, b0, b0, b1, b0},
[]*big.Float{b0, b0, b0, b0, b0, b1},
[]*big.Float{b0, b0, b1, b0, b0, b0},
}
alpha, beta, gamma, z := R1CSToQAP(a, b, c)
fmt.Println(alpha)
fmt.Println(beta)
fmt.Println(gamma)
fmt.Println(z)
}