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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9efdb85768b3e83e464c61846a3cf712b8df989f20114875cb39a08558882736
4
- data.tar.gz: 39b4c2c8c6a7b77d9fba96e4e8ef297e249da0640b3eba81f18b1093dbc59011
3
+ metadata.gz: 1d030fcbbf815eafe9c538839946e6337c2e9c60f1bcce5de79172b453c96fe9
4
+ data.tar.gz: 68c3d99c0cb6fea2f16e3617df6d198cae2cb352f22cd66c982ba362731a778c
5
5
  SHA512:
6
- metadata.gz: 88f4f0e4cdd1fa1d954bc32d9546e3cf642f66200649629f3f1dc516970eed44467b6e7a753fafa1951180bcee9f9a6d4b4ce5d17d3427cb2ca0bd1873d39a6d
7
- data.tar.gz: 35cb803d35ec7ad8e728228779b2e69654bbebfeadc2e744a7a75889d174dd9d3d608c79712e230ddd432e416bf3051e7d16ad579c5d2c50fb1b23437f2c90c4
6
+ metadata.gz: a3cae69f35050d6dba026231c2d783204359140a94e406676fb178ff58cc1bdbe1a1e2e73124ea29679a4d5c3b95c22b0c5b90d1d7a2ea4c394bf9317b4926a4
7
+ data.tar.gz: 1d21a4db43881ce872e41954b116cee5603ee80a8b8e3b7e7b7efc01c317d9addb5c9cc78b07a84898279be41d0b941166ee6840e90be95e92929298e89f32ec
data/.rubocop.yml CHANGED
@@ -10,7 +10,7 @@ RSpec/ExampleLength:
10
10
  Metrics:
11
11
  Enabled: false
12
12
  RSpec/MultipleExpectations:
13
- Max: 5
13
+ Enabled: false
14
14
  Style/IfUnlessModifier:
15
15
  Enabled: false
16
16
  Style/WhileUntilModifier:
data/Gemfile CHANGED
@@ -12,4 +12,6 @@ gem 'rspec', '~> 3.0'
12
12
  gem 'prettier'
13
13
 
14
14
  gem 'rubocop-rake'
15
- gem 'rubocop-rspec'
15
+ gem 'rubocop-rspec'
16
+
17
+ gem 'parallel_tests'
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.
@@ -7,11 +7,19 @@ module KZG
7
7
 
8
8
  # Create commitment
9
9
  # @param [KZG::Setting] setting
10
- # @param [Array(Integer | BLS::Fr)] coeffs Coefficients of polynomial equation.
11
- def initialize(setting, polynomial, value)
10
+ # @param [KZG::Polynomial] polynomial
11
+ def initialize(setting, polynomial)
12
12
  @setting = setting
13
13
  @polynomial = polynomial
14
- @value = 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
- value =
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 = Array.new(2)
41
- divisor[0] = BLS::Fr.new(x).negate
42
- divisor[1] = BLS::Fr::ONE
43
- quotient_poly = polynomial.poly_long_div(divisor)
44
- Commitment.from_coeffs(setting, quotient_poly).value
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
@@ -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
- # Long polynomial division for two polynomials in coefficient form
56
- # @param [Array(BLS::Fr)] divisor Array of divisor.
57
- # @return [Array(BLS::Fr)]
58
- def poly_long_div(divisor)
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 = divisor.length - 1
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] / divisor[b_pos]
125
+ quot = a[a_pos] / other.coeffs[b_pos]
67
126
  i = b_pos
68
127
  while i >= 0
69
- tmp = quot * divisor[i]
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[BLS::PointG1]] g1s
9
- # @param [Array[BLS::PointG2]] g2s
8
+ # @param [Array(BLS::PointG1)] g1_points
9
+ # @param [Array(BLS::PointG2)] g2_points
10
10
  def initialize(g1_points, g2_points)
11
- if !g1_points.is_a?(Array) || !g2_points.is_a?(Array)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KZG
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
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.2.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-01-26 00:00:00.000000000 Z
11
+ date: 2023-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bls12-381