-
Notifications
You must be signed in to change notification settings - Fork 26
/
fk20_multi.go
133 lines (119 loc) · 4.07 KB
/
fk20_multi.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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
133
// Original: https://github.com/ethereum/research/blob/master/kzg_data_availability/fk20_multi.py
//go:build !bignum_pure && !bignum_hol256
// +build !bignum_pure,!bignum_hol256
package kzg
import (
"fmt"
"github.com/protolambda/go-kzg/bls"
)
// FK20 Method to compute all proofs
// Toeplitz multiplication via http://www.netlib.org/utk/people/JackDongarra/etemplates/node384.html
// Multi proof method
// For a polynomial of size n, let w be a n-th root of unity. Then this method will return
// k=n/l KZG proofs for the points
//
// proof[0]: w^(0*l + 0), w^(0*l + 1), ... w^(0*l + l - 1)
// proof[0]: w^(0*l + 0), w^(0*l + 1), ... w^(0*l + l - 1)
// ...
// proof[i]: w^(i*l + 0), w^(i*l + 1), ... w^(i*l + l - 1)
// ...
func (ks *FK20MultiSettings) FK20Multi(polynomial []bls.Fr) []bls.G1Point {
n := uint64(len(polynomial))
n2 := n * 2
if ks.MaxWidth < n2 {
panic(fmt.Errorf("KZGSettings are set to MaxWidth %d but got half polynomial of length %d",
ks.MaxWidth, n))
}
hExtFFT := make([]bls.G1Point, n2, n2)
for i := uint64(0); i < n2; i++ {
bls.CopyG1(&hExtFFT[i], &bls.ZeroG1)
}
var tmp bls.G1Point
for i := uint64(0); i < ks.chunkLen; i++ {
toeplitzCoeffs := ks.toeplitzCoeffsStepStrided(polynomial, i, ks.chunkLen)
hExtFFTFile := ks.ToeplitzPart2(toeplitzCoeffs, ks.xExtFFTFiles[i])
for j := uint64(0); j < n2; j++ {
bls.AddG1(&tmp, &hExtFFT[j], &hExtFFTFile[j])
bls.CopyG1(&hExtFFT[j], &tmp)
}
}
h := ks.ToeplitzPart3(hExtFFT)
out, err := ks.FFTG1(h, false)
if err != nil {
panic(err)
}
return out
}
// FK20 multi-proof method, optimized for dava availability where the top half of polynomial
// coefficients == 0
func (ks *FK20MultiSettings) FK20MultiDAOptimized(polynomial []bls.Fr) []bls.G1Point {
n2 := uint64(len(polynomial))
if ks.MaxWidth < n2 {
panic(fmt.Errorf("KZGSettings are set to MaxWidth %d but got polynomial of length %d",
ks.MaxWidth, n2))
}
n := n2 / 2
for i := n; i < n2; i++ {
if !bls.EqualZero(&polynomial[i]) {
panic("bad input, second half should be zeroed")
}
}
k := n / ks.chunkLen
k2 := k * 2
hExtFFT := make([]bls.G1Point, k2, k2)
for i := uint64(0); i < k2; i++ {
bls.CopyG1(&hExtFFT[i], &bls.ZeroG1)
}
reducedPoly := polynomial[:n]
var tmp bls.G1Point
for i := uint64(0); i < ks.chunkLen; i++ {
toeplitzCoeffs := ks.toeplitzCoeffsStepStrided(reducedPoly, i, ks.chunkLen)
//debugFrs(fmt.Sprintf("toeplitz_coefficients %d:", i), toeplitzCoeffs)
//DebugG1s(fmt.Sprintf("xext_fft file %d:", i), ks.xExtFFTFiles[i])
hExtFFTFile := ks.ToeplitzPart2(toeplitzCoeffs, ks.xExtFFTFiles[i])
//DebugG1s(fmt.Sprintf("hext_fft file %d:", i), hExtFFTFile)
for j := uint64(0); j < k2; j++ {
bls.AddG1(&tmp, &hExtFFT[j], &hExtFFTFile[j])
bls.CopyG1(&hExtFFT[j], &tmp)
}
//DebugG1s(fmt.Sprintf("hext_fft %d:", i), hExtFFT)
}
//DebugG1s("hext_fft final", hExtFFT)
h := ks.ToeplitzPart3(hExtFFT)
//DebugG1s("h", h)
// TODO: maybe use a G1 version of the DAS extension FFT to perform the h -> output conversion?
// Now redo the padding before final step.
// Instead of copying h into a new extended array, just reuse the old capacity.
h = h[:k2]
for i := k; i < k2; i++ {
bls.CopyG1(&h[i], &bls.ZeroG1)
}
out, err := ks.FFTG1(h, false)
if err != nil {
panic(err)
}
return out
}
// Computes all the KZG proofs for data availability checks. This involves sampling on the double domain
// and reordering according to reverse bit order
func (ks *FK20MultiSettings) DAUsingFK20Multi(polynomial []bls.Fr) []bls.G1Point {
n := uint64(len(polynomial))
if n > ks.MaxWidth/2 {
panic("expected poly contents not bigger than half the size of the FK20-multi settings")
}
if !bls.IsPowerOfTwo(n) {
panic("expected poly length to be power of two")
}
n2 := n * 2
extendedPolynomial := make([]bls.Fr, n2, n2)
for i := uint64(0); i < n; i++ {
bls.CopyFr(&extendedPolynomial[i], &polynomial[i])
}
for i := n; i < n2; i++ {
bls.CopyFr(&extendedPolynomial[i], &bls.ZERO)
}
allProofs := ks.FK20MultiDAOptimized(extendedPolynomial)
// change to reverse bit order.
reverseBitOrderG1(allProofs)
return allProofs
}