forked from Zondax/multi-party-sig
-
Notifications
You must be signed in to change notification settings - Fork 0
/
polynomial.go
61 lines (50 loc) · 1.62 KB
/
polynomial.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package polynomial
import (
"crypto/rand"
"github.com/sa8/multi-party-sig/pkg/math/curve"
"github.com/sa8/multi-party-sig/pkg/math/sample"
)
// Polynomial represents f(X) = a₀ + a₁⋅X + … + aₜ⋅Xᵗ.
type Polynomial struct {
group curve.Curve
coefficients []curve.Scalar
}
// NewPolynomial generates a Polynomial f(X) = secret + a₁⋅X + … + aₜ⋅Xᵗ,
// with coefficients in ℤₚ, and degree t.
func NewPolynomial(group curve.Curve, degree int, constant curve.Scalar) *Polynomial {
polynomial := &Polynomial{
group: group,
coefficients: make([]curve.Scalar, degree+1),
}
// if the constant is nil, we interpret it as 0.
if constant == nil {
constant = group.NewScalar()
}
polynomial.coefficients[0] = constant
for i := 1; i <= degree; i++ {
polynomial.coefficients[i] = sample.Scalar(rand.Reader, group)
}
return polynomial
}
// Evaluate evaluates a polynomial in a given variable index
// We use Horner's method: https://en.wikipedia.org/wiki/Horner%27s_method
func (p *Polynomial) Evaluate(index curve.Scalar) curve.Scalar {
if index.IsZero() {
panic("attempt to leak secret")
}
result := p.group.NewScalar()
// reverse order
for i := len(p.coefficients) - 1; i >= 0; i-- {
// bₙ₋₁ = bₙ * x + aₙ₋₁
result.Mul(index).Add(p.coefficients[i])
}
return result
}
// Constant returns a reference to the constant coefficient of the polynomial.
func (p *Polynomial) Constant() curve.Scalar {
return p.group.NewScalar().Set(p.coefficients[0])
}
// Degree is the highest power of the Polynomial.
func (p *Polynomial) Degree() uint32 {
return uint32(len(p.coefficients)) - 1
}