You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
4.5 KiB

  1. package kzg
  2. import (
  3. "fmt"
  4. "math/big"
  5. bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
  6. )
  7. // TrustedSetup also named Reference String
  8. type TrustedSetup struct {
  9. Tau1 []*bn256.G1
  10. Tau2 []*bn256.G2
  11. }
  12. // NewTrustedSetup returns a new trusted setup. This step should be done in a
  13. // secure & distributed way
  14. func NewTrustedSetup(l int) (*TrustedSetup, error) {
  15. // compute random s
  16. s, err := randBigInt()
  17. if err != nil {
  18. return nil, err
  19. }
  20. // Notation: [x]₁=xG ∈ 𝔾₁, [x]₂=xH ∈ 𝔾₂
  21. // τ₁: [x₀]₁, [x₁]₁, [x₂]₁, ..., [x n₋₁]₁
  22. // τ₂: [x₀]₂, [x₁]₂, [x₂]₂, ..., [x n₋₁]₂
  23. // sPow := make([]*big.Int, l)
  24. tauG1 := make([]*bn256.G1, l)
  25. tauG2 := make([]*bn256.G2, l)
  26. for i := 0; i < l; i++ {
  27. sPow := fExp(s, big.NewInt(int64(i)))
  28. tauG1[i] = new(bn256.G1).ScalarBaseMult(sPow)
  29. tauG2[i] = new(bn256.G2).ScalarBaseMult(sPow)
  30. }
  31. return &TrustedSetup{tauG1, tauG2}, nil
  32. }
  33. // Commit generates the commitment to the polynomial p(x)
  34. func Commit(ts *TrustedSetup, p []*big.Int) *bn256.G1 {
  35. c := evaluateG1(ts, p)
  36. return c
  37. }
  38. func evaluateG1(ts *TrustedSetup, p []*big.Int) *bn256.G1 {
  39. c := new(bn256.G1).ScalarMult(ts.Tau1[0], p[0])
  40. for i := 1; i < len(p); i++ {
  41. sp := new(bn256.G1).ScalarMult(ts.Tau1[i], p[i])
  42. c = new(bn256.G1).Add(c, sp)
  43. }
  44. return c
  45. }
  46. //nolint:deadcode,unused
  47. func evaluateG2(ts *TrustedSetup, p []*big.Int) *bn256.G2 {
  48. c := new(bn256.G2).ScalarMult(ts.Tau2[0], p[0])
  49. for i := 1; i < len(p); i++ {
  50. sp := new(bn256.G2).ScalarMult(ts.Tau2[i], p[i])
  51. c = new(bn256.G2).Add(c, sp)
  52. }
  53. return c
  54. }
  55. // EvaluationProof generates the evaluation proof
  56. func EvaluationProof(ts *TrustedSetup, p []*big.Int, z, y *big.Int) (*bn256.G1, error) {
  57. n := polynomialSub(p, []*big.Int{y}) // p-y
  58. // n := p // we can omit y (p(z))
  59. d := []*big.Int{fNeg(z), big.NewInt(1)} // x-z
  60. q, rem := polynomialDiv(n, d)
  61. if compareBigIntArray(rem, arrayOfZeroes(len(rem))) {
  62. return nil,
  63. fmt.Errorf("remainder should be 0, instead is %d", rem)
  64. }
  65. // proof: e = [q(t)]₁
  66. e := evaluateG1(ts, q)
  67. return e, nil
  68. }
  69. // Verify computes the KZG commitment verification
  70. func Verify(ts *TrustedSetup, c, proof *bn256.G1, z, y *big.Int) bool {
  71. s2 := ts.Tau2[1] // [t]₂ = sG ∈ 𝔾₂ = Tau2[1]
  72. zG2Neg := new(bn256.G2).Neg(
  73. new(bn256.G2).ScalarBaseMult(z)) // [z]₂ = zG ∈ 𝔾₂
  74. // [t]₂ - [z]₂
  75. sz := new(bn256.G2).Add(s2, zG2Neg)
  76. yG1Neg := new(bn256.G1).Neg(
  77. new(bn256.G1).ScalarBaseMult(y)) // [y]₁ = yG ∈ 𝔾₁
  78. // c - [y]₁
  79. cy := new(bn256.G1).Add(c, yG1Neg)
  80. h := new(bn256.G2).ScalarBaseMult(big.NewInt(1)) // H ∈ 𝔾₂
  81. // e(proof, [t]₂ - [z]₂) == e(c - [y]₁, H)
  82. e1 := bn256.Pair(proof, sz)
  83. e2 := bn256.Pair(cy, h)
  84. return e1.String() == e2.String()
  85. }
  86. //
  87. // Batch proofs
  88. //
  89. // EvaluationBatchProof generates the evalutation proof for the given list of points
  90. func EvaluationBatchProof(ts *TrustedSetup, p []*big.Int, zs, ys []*big.Int) (*bn256.G1, error) {
  91. if len(zs) != len(ys) {
  92. return nil, fmt.Errorf("len(zs)!=len(ys), %d!=%d", len(zs), len(ys))
  93. }
  94. if len(p) <= len(zs)+1 {
  95. return nil, fmt.Errorf("polynomial p(x) can not be of degree"+
  96. " equal or smaller than the number of given points+1."+
  97. " Polynomial p(x) degree: %d, number of points: %d",
  98. len(p), len(zs))
  99. }
  100. // z(x) = (x-z0)(x-z1)...(x-zn)
  101. z := zeroPolynomial(zs)
  102. // I(x) = Lagrange interpolation through (z0, y0), (z1, y1), ...
  103. i, err := LagrangeInterpolation(zs, ys)
  104. if err != nil {
  105. return nil, err
  106. }
  107. // q(x) = ( p(x) - I(x) ) / z(x)
  108. pMinusI := polynomialSub(p, i)
  109. q, rem := polynomialDiv(pMinusI, z)
  110. if compareBigIntArray(rem, arrayOfZeroes(len(rem))) {
  111. return nil,
  112. fmt.Errorf("remainder should be 0, instead is %d", rem)
  113. }
  114. // proof: e = [q(t)]₁
  115. e := evaluateG1(ts, q)
  116. return e, nil
  117. }
  118. // VerifyBatchProof computes the KZG batch proof commitment verification
  119. func VerifyBatchProof(ts *TrustedSetup, c, proof *bn256.G1, zs, ys []*big.Int) bool {
  120. // [z(s)]₂
  121. z := zeroPolynomial(zs)
  122. zG2 := evaluateG2(ts, z) // [z(t)]₂ = z(t) G ∈ 𝔾₂
  123. // I(x) = Lagrange interpolation through (z0, y0), (z1, y1), ...
  124. i, err := LagrangeInterpolation(zs, ys)
  125. if err != nil {
  126. return false
  127. }
  128. // [i(t)]₁
  129. iG1 := evaluateG1(ts, i) // [i(t)]₁ = i(t) G ∈ 𝔾₁
  130. // c - [i(t)]₁
  131. iG1Neg := new(bn256.G1).Neg(iG1)
  132. ciG1 := new(bn256.G1).Add(c, iG1Neg)
  133. h := new(bn256.G2).ScalarBaseMult(big.NewInt(1)) // H ∈ 𝔾₂
  134. // e(proof, [z(t)]₂) == e(c - [I(t)]₁, H)
  135. e1 := bn256.Pair(proof, zG2)
  136. e2 := bn256.Pair(ciG1, h)
  137. return e1.String() == e2.String()
  138. }