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.

164 lines
4.2 KiB

  1. package kzg
  2. import (
  3. "bytes"
  4. "crypto/rand"
  5. "math/big"
  6. "testing"
  7. "github.com/stretchr/testify/assert"
  8. )
  9. func randBI() *big.Int {
  10. maxbits := 256
  11. b := make([]byte, (maxbits/8)-1)
  12. _, err := rand.Read(b)
  13. if err != nil {
  14. panic(err)
  15. }
  16. r := new(big.Int).SetBytes(b)
  17. return new(big.Int).Mod(r, Q)
  18. }
  19. func neg(a *big.Int) *big.Int {
  20. return new(big.Int).Neg(a)
  21. }
  22. func TestPolynomial(t *testing.T) {
  23. b0 := big.NewInt(int64(0))
  24. b1 := big.NewInt(int64(1))
  25. b2 := big.NewInt(int64(2))
  26. b3 := big.NewInt(int64(3))
  27. b4 := big.NewInt(int64(4))
  28. b5 := big.NewInt(int64(5))
  29. b6 := big.NewInt(int64(6))
  30. b16 := big.NewInt(int64(16))
  31. a := []*big.Int{b1, b0, b5}
  32. b := []*big.Int{b3, b0, b1}
  33. // new Finite Field
  34. r, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10) //nolint:lll
  35. assert.True(nil, ok)
  36. // polynomial multiplication
  37. o := polynomialMul(a, b)
  38. assert.Equal(t, o, []*big.Int{b3, b0, b16, b0, b5})
  39. // polynomial division
  40. quo, rem := polynomialDiv(a, b)
  41. assert.Equal(t, quo[0].Int64(), int64(5))
  42. // check the rem result without modulo
  43. assert.Equal(t, new(big.Int).Sub(rem[0], r).Int64(), int64(-14))
  44. c := []*big.Int{neg(b4), b0, neg(b2), b1}
  45. d := []*big.Int{neg(b3), b1}
  46. quo2, rem2 := polynomialDiv(c, d)
  47. assert.Equal(t, quo2, []*big.Int{b3, b1, b1})
  48. assert.Equal(t, rem2[0].Int64(), int64(5))
  49. // polynomial addition
  50. o = polynomialAdd(a, b)
  51. assert.Equal(t, o, []*big.Int{b4, b0, b6})
  52. // polynomial subtraction
  53. o1 := polynomialSub(a, b)
  54. o2 := polynomialSub(b, a)
  55. o = polynomialAdd(o1, o2)
  56. assert.True(t, bytes.Equal(b0.Bytes(), o[0].Bytes()))
  57. assert.True(t, bytes.Equal(b0.Bytes(), o[1].Bytes()))
  58. assert.True(t, bytes.Equal(b0.Bytes(), o[2].Bytes()))
  59. c = []*big.Int{b5, b6, b1}
  60. d = []*big.Int{b1, b3}
  61. o = polynomialSub(c, d)
  62. assert.Equal(t, o, []*big.Int{b4, b3, b1})
  63. // NewPolZeroAt
  64. o = newPolZeroAt(3, 4, b4)
  65. assert.Equal(t, polynomialEval(o, big.NewInt(3)), b4)
  66. o = newPolZeroAt(2, 4, b3)
  67. assert.Equal(t, polynomialEval(o, big.NewInt(2)), b3)
  68. // polynomialEval
  69. // p(x) = x^3 + x + 5
  70. p := []*big.Int{
  71. big.NewInt(5),
  72. big.NewInt(1), // x^1
  73. big.NewInt(0), // x^2
  74. big.NewInt(1), // x^3
  75. }
  76. assert.Equal(t, "x³ + x¹ + 5", PolynomialToString(p))
  77. assert.Equal(t, "35", polynomialEval(p, big.NewInt(3)).String())
  78. assert.Equal(t, "1015", polynomialEval(p, big.NewInt(10)).String())
  79. assert.Equal(t, "16777477", polynomialEval(p, big.NewInt(256)).String())
  80. assert.Equal(t, "125055", polynomialEval(p, big.NewInt(50)).String())
  81. assert.Equal(t, "7", polynomialEval(p, big.NewInt(1)).String())
  82. }
  83. func BenchmarkArithmetic(b *testing.B) {
  84. // generate arrays with bigint
  85. var p, q []*big.Int
  86. for i := 0; i < 1000; i++ {
  87. pi := randBI()
  88. p = append(p, pi)
  89. }
  90. for i := 1000 - 1; i >= 0; i-- {
  91. q = append(q, p[i])
  92. }
  93. b.Run("polynomialSub", func(b *testing.B) {
  94. for i := 0; i < b.N; i++ {
  95. polynomialSub(p, q)
  96. }
  97. })
  98. b.Run("polynomialMul", func(b *testing.B) {
  99. for i := 0; i < b.N; i++ {
  100. polynomialMul(p, q)
  101. }
  102. })
  103. b.Run("polynomialDiv", func(b *testing.B) {
  104. for i := 0; i < b.N; i++ {
  105. polynomialDiv(p, q)
  106. }
  107. })
  108. }
  109. func TestLagrangeInterpolation(t *testing.T) {
  110. x0 := big.NewInt(3)
  111. y0 := big.NewInt(35)
  112. x1 := big.NewInt(10)
  113. y1 := big.NewInt(1015)
  114. x2 := big.NewInt(256)
  115. y2 := big.NewInt(16777477)
  116. x3 := big.NewInt(50)
  117. y3 := big.NewInt(125055)
  118. xs := []*big.Int{x0, x1, x2, x3}
  119. ys := []*big.Int{y0, y1, y2, y3}
  120. p, err := LagrangeInterpolation(xs, ys)
  121. assert.Nil(t, err)
  122. assert.Equal(t, "x³ + x¹ + 5", PolynomialToString(p))
  123. assert.Equal(t, y0, polynomialEval(p, x0))
  124. assert.Equal(t, y1, polynomialEval(p, x1))
  125. assert.Equal(t, y2, polynomialEval(p, x2))
  126. }
  127. func TestZeroPolynomial(t *testing.T) {
  128. x0 := big.NewInt(1)
  129. x1 := big.NewInt(40)
  130. x2 := big.NewInt(512)
  131. xs := []*big.Int{x0, x1, x2}
  132. z := zeroPolynomial(xs)
  133. assert.Equal(t, "x³ "+
  134. "+ 21888242871839275222246405745257275088548364400416034343698204186575808495064x² "+
  135. "+ 21032x¹ + 21888242871839275222246405745257275088548364400416034343698204186575808475137",
  136. PolynomialToString(z))
  137. assert.Equal(t, "0", polynomialEval(z, x0).String())
  138. assert.Equal(t, "0", polynomialEval(z, x1).String())
  139. assert.Equal(t, "0", polynomialEval(z, x2).String())
  140. }