kzg 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/Gemfile +3 -1
- data/README.md +23 -1
- data/lib/kzg/commitment.rb +29 -17
- data/lib/kzg/polynomial.rb +84 -8
- data/lib/kzg/setting.rb +36 -5
- data/lib/kzg/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d030fcbbf815eafe9c538839946e6337c2e9c60f1bcce5de79172b453c96fe9
|
4
|
+
data.tar.gz: 68c3d99c0cb6fea2f16e3617df6d198cae2cb352f22cd66c982ba362731a778c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3cae69f35050d6dba026231c2d783204359140a94e406676fb178ff58cc1bdbe1a1e2e73124ea29679a4d5c3b95c22b0c5b90d1d7a2ea4c394bf9317b4926a4
|
7
|
+
data.tar.gz: 1d21a4db43881ce872e41954b116cee5603ee80a8b8e3b7e7b7efc01c317d9addb5c9cc78b07a84898279be41d0b941166ee6840e90be95e92929298e89f32ec
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -61,7 +61,19 @@ The committer can compute proof that the value of the polynomial (f(x)) for any
|
|
61
61
|
proof = commitment.compute_proof(35)
|
62
62
|
```
|
63
63
|
|
64
|
-
This proof is point in the `BLS::PointG1`.
|
64
|
+
This proof is a point in the `BLS::PointG1`.
|
65
|
+
|
66
|
+
#### Multi proof
|
67
|
+
|
68
|
+
A multi-proof for disclosing multiple x values is created as follows:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
x = [1, 2, 3]
|
72
|
+
|
73
|
+
multi_proof = commitment.compute_multi_proof(x)
|
74
|
+
```
|
75
|
+
|
76
|
+
This proof is a point in the `BLS::PointG1`.
|
65
77
|
|
66
78
|
### Verify
|
67
79
|
|
@@ -73,6 +85,16 @@ y = 808951170278371
|
|
73
85
|
setting.valid_proof?(commitment.value, proof, x, y)
|
74
86
|
```
|
75
87
|
|
88
|
+
#### Multi proof
|
89
|
+
|
90
|
+
The validity of multiple proofs disclosing more than one value can be verified as follows:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
x = [1, 2, 3]
|
94
|
+
y = [55, 9217, 280483]
|
95
|
+
setting.valid_multi_proof?(commitment.value, multi_proof, x, y)
|
96
|
+
```
|
97
|
+
|
76
98
|
### Use as vector commitment
|
77
99
|
|
78
100
|
When used as a Vector commitment, the value to be committed is encoded in a polynomial expression as the evaluated value of the polynomial.
|
data/lib/kzg/commitment.rb
CHANGED
@@ -7,11 +7,19 @@ module KZG
|
|
7
7
|
|
8
8
|
# Create commitment
|
9
9
|
# @param [KZG::Setting] setting
|
10
|
-
# @param [
|
11
|
-
def initialize(setting, polynomial
|
10
|
+
# @param [KZG::Polynomial] polynomial
|
11
|
+
def initialize(setting, polynomial)
|
12
12
|
@setting = setting
|
13
13
|
@polynomial = polynomial
|
14
|
-
@value =
|
14
|
+
@value =
|
15
|
+
polynomial
|
16
|
+
.coeffs
|
17
|
+
.map
|
18
|
+
.with_index do |c, i|
|
19
|
+
c = c.is_a?(BLS::Fr) ? c : BLS::Fr.new(c)
|
20
|
+
c.value.zero? ? BLS::PointG1::ZERO : setting.g1_points[i] * c
|
21
|
+
end
|
22
|
+
.inject(&:+)
|
15
23
|
end
|
16
24
|
|
17
25
|
# Create commitment using coefficients.
|
@@ -22,26 +30,30 @@ module KZG
|
|
22
30
|
raise KZG::Error,
|
23
31
|
"coeffs length is greater than the number of secret parameters."
|
24
32
|
end
|
25
|
-
|
26
|
-
coeffs
|
27
|
-
.map
|
28
|
-
.with_index do |c, i|
|
29
|
-
c = c.is_a?(BLS::Fr) ? c : BLS::Fr.new(c)
|
30
|
-
c.value.zero? ? BLS::PointG1::ZERO : setting.g1_points[i] * c
|
31
|
-
end
|
32
|
-
.inject(&:+)
|
33
|
-
Commitment.new(setting, KZG::Polynomial.new(coeffs), value)
|
33
|
+
Commitment.new(setting, KZG::Polynomial.new(coeffs))
|
34
34
|
end
|
35
35
|
|
36
36
|
# Compute KZG proof for polynomial in coefficient form at position x.
|
37
37
|
# @param [Integer] x Position
|
38
38
|
# @return [BLS::PointG1] Proof.
|
39
39
|
def compute_proof(x)
|
40
|
-
divisor =
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
divisor = Polynomial.new([BLS::Fr.new(x).negate, BLS::Fr::ONE])
|
41
|
+
quotient_poly = polynomial / divisor
|
42
|
+
Commitment.new(setting, quotient_poly).value
|
43
|
+
end
|
44
|
+
|
45
|
+
# Compute KZG multi proof using list of x coordinate.
|
46
|
+
# @param [Array(Integer)] x An array of x coordinate.
|
47
|
+
# @return [BLS::PointG1]
|
48
|
+
def compute_multi_proof(x)
|
49
|
+
y = x.map { |i| polynomial.eval_at(i) }
|
50
|
+
# compute i(x)
|
51
|
+
i_poly = Polynomial.lagrange_interpolate(x, y)
|
52
|
+
# compute z(x)
|
53
|
+
z_poly = Polynomial.zero_poly(x)
|
54
|
+
# compute q(x) = (p(x) - i(x)) / z(x)
|
55
|
+
quotient_poly = (polynomial - i_poly) / z_poly
|
56
|
+
Commitment.new(setting, quotient_poly).value
|
45
57
|
end
|
46
58
|
end
|
47
59
|
end
|
data/lib/kzg/polynomial.rb
CHANGED
@@ -37,6 +37,15 @@ module KZG
|
|
37
37
|
Polynomial.new(coeffs)
|
38
38
|
end
|
39
39
|
|
40
|
+
# Create polynomial from array of x coordinate like f(x) = (x - x0)(x - x1)...(x - xn)
|
41
|
+
# @param [Array(Integer)] x An array of x coordinate.
|
42
|
+
# @return [KZG::Polynomial]
|
43
|
+
def self.zero_poly(x)
|
44
|
+
poleis =
|
45
|
+
x.map { |v| Polynomial.new([BLS::Fr.new(v).negate, BLS::Fr::ONE]) }
|
46
|
+
poleis[1..].inject(poleis.first) { |result, poly| result * poly }
|
47
|
+
end
|
48
|
+
|
40
49
|
# Evaluate polynomial for given +x+ using Horner's method.
|
41
50
|
# @param [Integer | BLS::Fr] x
|
42
51
|
# @return [BLS::Fr] Evaluated value.
|
@@ -52,21 +61,71 @@ module KZG
|
|
52
61
|
last
|
53
62
|
end
|
54
63
|
|
55
|
-
#
|
56
|
-
# @param [
|
57
|
-
# @return [
|
58
|
-
|
64
|
+
# Returns a new polynomial that is the sum of the given polynomial and this polynomial.
|
65
|
+
# @param [KZG::Polynomial] other
|
66
|
+
# @return [KZG::Polynomial] Sum of polynomial.
|
67
|
+
# @raise ArgumentError
|
68
|
+
def add(other)
|
69
|
+
unless other.is_a?(Polynomial)
|
70
|
+
raise ArgumentError, "add target must be Polynomial"
|
71
|
+
end
|
72
|
+
|
73
|
+
sum = process(coeffs, other.coeffs) { |a, b| a + b }
|
74
|
+
Polynomial.new(sum)
|
75
|
+
end
|
76
|
+
alias + add
|
77
|
+
|
78
|
+
# Returns a new polynomial subtracting the given polynomial from self.
|
79
|
+
# @param [KZG::Polynomial] other
|
80
|
+
# @return [KZG::Polynomial] Subtracted polynomial.
|
81
|
+
# @raise ArgumentError
|
82
|
+
def sub(other)
|
83
|
+
unless other.is_a?(Polynomial)
|
84
|
+
raise ArgumentError, "subtract target must be Polynomial"
|
85
|
+
end
|
86
|
+
|
87
|
+
Polynomial.new(process(coeffs, other.coeffs) { |a, b| a - b })
|
88
|
+
end
|
89
|
+
alias - sub
|
90
|
+
|
91
|
+
# Return a new polynomial that multiply self and the given polynomial.
|
92
|
+
# @param [KZG::Polynomial] other Other polynomial
|
93
|
+
# @return [KZG::Polynomial] Multiplied polynomial
|
94
|
+
# @return ArgumentError
|
95
|
+
def multiply(other)
|
96
|
+
unless other.is_a?(Polynomial)
|
97
|
+
raise ArgumentError, "multiply target must be Polynomial"
|
98
|
+
end
|
99
|
+
new_coeffs = Array.new(coeffs.length + other.coeffs.length - 1)
|
100
|
+
coeffs.each.with_index do |a, i|
|
101
|
+
other.coeffs.each.with_index do |b, j|
|
102
|
+
k = i + j
|
103
|
+
new_coeffs[k] = a * b + (new_coeffs[k] || BLS::Fr::ZERO)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
Polynomial.new(new_coeffs)
|
107
|
+
end
|
108
|
+
alias * multiply
|
109
|
+
|
110
|
+
# Return a new polynomial that divide self and the given polynomial, i.e. self / other.
|
111
|
+
# @param [KZG::Polynomial] other Other polynomial
|
112
|
+
# @return [KZG::Polynomial] Divided polynomial
|
113
|
+
# @return ArgumentError
|
114
|
+
def div(other)
|
115
|
+
unless other.is_a?(Polynomial)
|
116
|
+
raise ArgumentError, "divide target must be Polynomial"
|
117
|
+
end
|
59
118
|
a = coeffs.dup
|
60
119
|
a_pos = a.length - 1
|
61
|
-
b_pos =
|
120
|
+
b_pos = other.coeffs.length - 1
|
62
121
|
diff = a_pos - b_pos
|
63
122
|
quotient_poly = []
|
64
123
|
|
65
124
|
while diff >= 0
|
66
|
-
quot = a[a_pos] /
|
125
|
+
quot = a[a_pos] / other.coeffs[b_pos]
|
67
126
|
i = b_pos
|
68
127
|
while i >= 0
|
69
|
-
tmp = quot *
|
128
|
+
tmp = quot * other.coeffs[i]
|
70
129
|
tmp2 = a[diff + i] - tmp
|
71
130
|
a[diff + i] = tmp2
|
72
131
|
i -= 1
|
@@ -75,7 +134,24 @@ module KZG
|
|
75
134
|
a_pos -= 1
|
76
135
|
diff -= 1
|
77
136
|
end
|
78
|
-
quotient_poly
|
137
|
+
Polynomial.new(quotient_poly)
|
138
|
+
end
|
139
|
+
alias / div
|
140
|
+
|
141
|
+
def ==(other)
|
142
|
+
return false unless other.is_a?(Polynomial)
|
143
|
+
coeffs == other.coeffs
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
def process(a, b)
|
149
|
+
length = [a.length, b.length].max
|
150
|
+
length.times.map do |i|
|
151
|
+
c1 = i < a.length ? a[i] : BLS::Fr::ZERO
|
152
|
+
c2 = i < b.length ? b[i] : BLS::Fr::ZERO
|
153
|
+
yield(c1, c2)
|
154
|
+
end
|
79
155
|
end
|
80
156
|
end
|
81
157
|
end
|
data/lib/kzg/setting.rb
CHANGED
@@ -5,12 +5,10 @@ module KZG
|
|
5
5
|
class Setting
|
6
6
|
attr_reader :g1_points, :g2_points
|
7
7
|
|
8
|
-
# @param [Array
|
9
|
-
# @param [Array
|
8
|
+
# @param [Array(BLS::PointG1)] g1_points
|
9
|
+
# @param [Array(BLS::PointG2)] g2_points
|
10
10
|
def initialize(g1_points, g2_points)
|
11
|
-
|
12
|
-
raise KZG::Error, "g1_points and g2_points must be array."
|
13
|
-
end
|
11
|
+
raise KZG::Error, "g1_points must be array." unless g1_points.is_a?(Array)
|
14
12
|
unless g1_points.all? { |g| g.is_a?(BLS::PointG1) }
|
15
13
|
raise KZG::Error, "All elements of g1_points must be BLS::PointG1."
|
16
14
|
end
|
@@ -48,5 +46,38 @@ module KZG
|
|
48
46
|
exp = (lhs * rhs).final_exponentiate
|
49
47
|
exp == BLS::Fq12::ONE
|
50
48
|
end
|
49
|
+
|
50
|
+
# Check a proof for a KZG commitment for an evaluation f(x) = y
|
51
|
+
# @param [BLS::PointG1] commit_point
|
52
|
+
# @param [BLS::PointG1] proof
|
53
|
+
# @param [Array(Integer|BLS::Fr)] x
|
54
|
+
# @param [Array(Integer|BLS::Fr)] y
|
55
|
+
def valid_multi_proof?(commit_point, proof, x, y)
|
56
|
+
x = x.map { |v| v.is_a?(BLS::Fr) ? v.value : v }
|
57
|
+
y = y.map { |v| v.is_a?(BLS::Fr) ? v.value : v }
|
58
|
+
# compute i(x)
|
59
|
+
i_poly = Polynomial.lagrange_interpolate(x, y)
|
60
|
+
# compute z(x)
|
61
|
+
z_poly = Polynomial.zero_poly(x)
|
62
|
+
# e([commitment - interpolation_polynomial(s)]^(-1), [1]) * e([proof], [s^n - x^n]) = 1
|
63
|
+
is = Commitment.new(self, i_poly).value
|
64
|
+
lhs =
|
65
|
+
BLS.pairing(
|
66
|
+
(commit_point - is).negate,
|
67
|
+
BLS::PointG2::BASE,
|
68
|
+
with_final_exp: false
|
69
|
+
)
|
70
|
+
z_commit =
|
71
|
+
z_poly
|
72
|
+
.coeffs
|
73
|
+
.map
|
74
|
+
.with_index do |c, i|
|
75
|
+
c.value.zero? ? BLS::PointG2::ZERO : g2_points[i] * c
|
76
|
+
end
|
77
|
+
.inject(&:+)
|
78
|
+
rhs = BLS.pairing(proof, z_commit, with_final_exp: false)
|
79
|
+
exp = (lhs * rhs).final_exponentiate
|
80
|
+
exp == BLS::Fq12::ONE
|
81
|
+
end
|
51
82
|
end
|
52
83
|
end
|
data/lib/kzg/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kzg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- azuchi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bls12-381
|