Class: KZG::Setting

Inherits:
Object
  • Object
show all
Defined in:
lib/kzg/setting.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(g1_points, g2_points) ⇒ Setting

checked against. its group, or when g2_points is too short to verify with.

Parameters:

  • g1_points (Array(BLS::PointG1))
  • g2_points (Array(BLS::PointG2))

    at least [1]_2 and [s]_2, the two a proof is

Raises:

  • (KZG::Error)

    Occur when either array holds something other than the points of



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/kzg/setting.rb', line 13

def initialize(g1_points, g2_points)
  raise KZG::Error, "g1_points must be array." unless g1_points.is_a?(Array)
  raise KZG::Error, "g2_points must be array." unless g2_points.is_a?(Array)
  unless g1_points.all? { |g| g.is_a?(BLS::PointG1) }
    raise KZG::Error, "All elements of g1_points must be BLS::PointG1."
  end
  unless g2_points.all? { |g| g.is_a?(BLS::PointG2) }
    raise KZG::Error, "All elements of g2_points must be BLS::PointG2."
  end
  # valid_proof? reads g2_points[1], so a setting short of it can verify nothing. Refused
  # here rather than at verification time, where it is a nil that has travelled some way
  # from the setup that omitted it.
  if g2_points.length < 2
    raise KZG::Error, "g2_points must have at least 2 elements."
  end

  @g1_points = g1_points
  @g2_points = g2_points
end

Instance Attribute Details

#g1_pointsObject (readonly)

Returns the value of attribute g1_points.



6
7
8
# File 'lib/kzg/setting.rb', line 6

def g1_points
  @g1_points
end

#g2_pointsObject (readonly)

Returns the value of attribute g2_points.



6
7
8
# File 'lib/kzg/setting.rb', line 6

def g2_points
  @g2_points
end

Instance Method Details

#==(other) ⇒ Object



33
34
35
36
37
# File 'lib/kzg/setting.rb', line 33

def ==(other)
  return false unless other.is_a?(Setting)

  g1_points == other.g1_points && g2_points == other.g2_points
end

#valid_multi_proof?(commit_point, proof, x, y) ⇒ Boolean

Check a proof for a KZG commitment for an evaluation f(x) = y is a claim that does not verify, so a malformed x/y is false rather than an exception.

Parameters:

  • commit_point (BLS::PointG1)
  • proof (BLS::PointG1)
  • x (Array(Integer|BLS::Fr))
  • y (Array(Integer|BLS::Fr))

Returns:

  • (Boolean)

    verification result. A claim this method cannot interpolate through



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
# File 'lib/kzg/setting.rb', line 71

def valid_multi_proof?(commit_point, proof, x, y)
  return false unless g1_element?(commit_point) && g1_element?(proof)
  # Nothing is claimed over an empty set of points, and a y that does not pair up with an
  # x leaves the interpolation below indexing past the end of it.
  return false if x.empty? || x.length != y.length
  # Both commitments below take one setup point per coefficient, and z(x) is of degree
  # x.length, so it needs one G2 point more than there are x. A claim larger than that is
  # one this setting cannot weigh, rather than one it has weighed and rejected, but it
  # reaches here from whoever is being verified and so cannot raise either.
  if x.length > g1_points.length || x.length >= g2_points.length
    return false
  end

  x = x.map { |v| v.is_a?(BLS::Fr) ? v.value : v }
  y = y.map { |v| v.is_a?(BLS::Fr) ? v.value : v }
  # Interpolation through a repeated x is undefined, and lagrange_interpolate raises on
  # it. The x here comes from whoever the proof is being verified for, so a repeat has to
  # be reported as a failed proof instead of letting the exception escape. Compared after
  # reduction, since x and x + BLS::Curve::R are the same field element.
  return false if x.map { |v| BLS::Fr.new(v).value }.uniq.length < x.length

  # compute i(x)
  i_poly = Polynomial.lagrange_interpolate(x, y)
  # compute z(x)
  z_poly = Polynomial.zero_poly(x)
  # e([commitment - interpolation_polynomial(s)]^(-1), [1]) * e([proof],  [s^n - x^n]) = 1
  is = Commitment.new(self, i_poly).value
  lhs = BLS.partial_pairing((commit_point - is).negate, BLS::PointG2::BASE)
  z_commit =
    z_poly
      .coeffs
      .map
      .with_index do |c, i|
        c.value.zero? ? BLS::PointG2::ZERO : g2_points[i] * c
      end
      .inject(BLS::PointG2::ZERO, &:+)
  rhs = BLS.partial_pairing(proof, z_commit)
  exp = (lhs * rhs).final_exponentiate
  exp == BLS::Fp12::ONE
end

#valid_proof?(commit_point, proof, x, y) ⇒ Boolean

Check a proof for a KZG commitment for an evaluation f(x) = y

Parameters:

  • commit_point (BLS::PointG1)
  • proof (BLS::PointG1)
  • x (Integer|BLS::Fr)
  • y (Integer|BLS::Fr)

Returns:

  • (Boolean)

    verification result.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/kzg/setting.rb', line 45

def valid_proof?(commit_point, proof, x, y)
  return false unless g1_element?(commit_point) && g1_element?(proof)

  x = x.is_a?(BLS::Fr) ? x : BLS::Fr.new(x)
  y = y.is_a?(BLS::Fr) ? y : BLS::Fr.new(y)
  xg2 = x.value.zero? ? BLS::PointG2::ZERO : BLS::PointG2::BASE * x
  yg = y.value.zero? ? BLS::PointG1::ZERO : BLS::PointG1::BASE * y

  # e([commitment - y]^(-1), [1]) * e([proof],  [s - x]) = 1
  # partial_pairing rather than pairing: a proof at infinity, or a commitment that
  # cancels with [y], is a degenerate input a verifier can be handed and has to come out
  # as false rather than as a BLS::PairingError. e(O, Q) = e(P, O) = 1 leaves the
  # equation above intact.
  lhs = BLS.partial_pairing((commit_point - yg).negate, BLS::PointG2::BASE)
  rhs = BLS.partial_pairing(proof, g2_points[1] - xg2)
  exp = (lhs * rhs).final_exponentiate
  exp == BLS::Fp12::ONE
end