def calculate_lagrange_polynomials(x_values): """ Given the x_values for evaluating some polynomials, it computes part of the lagrange polynomials required to interpolate a polynomial over this domain. """ lagrange_polynomials = [] monomials = [ Polynomial.monomial(1, FieldElement.one()) - Polynomial.monomial(0, x) for x in x_values ] numerator = prod(monomials) for j in tqdm(range(len(x_values))): # In the denominator, we have: # (x_j-x_0)(x_j-x_1)...(x_j-x_{j-1})(x_j-x_{j+1})...(x_j-x_{len(X)-1}) denominator = prod( [x_values[j] - x for i, x in enumerate(x_values) if i != j]) # Numerator is a bit more complicated, since we need to compute a poly multiplication here. # Similarly to the denominator, we have: # (x-x_0)(x-x_1)...(x-x_{j-1})(x-x_{j+1})...(x-x_{len(X)-1}) cur_poly, _ = numerator.qdiv(monomials[j].scalar_mul(denominator)) lagrange_polynomials.append(cur_poly) return lagrange_polynomials
def test_field_div(): for _ in range(100): t = FieldElement.random_element(exclude_elements=[FieldElement.zero()]) t_inv = FieldElement.one() / t assert t_inv == t.inverse() assert t_inv * t == FieldElement.one()
def test_field_operations(): # Check pow, mul, and the modular operations t = FieldElement(2).pow(30) * FieldElement(3) + FieldElement(1) assert t == FieldElement(0)
def __init__(self, coefficients, var='x'): # Internally storing the coefficients in self.poly, least-significant (i.e. free term) # first, so $9 - 3x^2 + 19x^5$ is represented internally by the list [9, 0, -3, 0, 0, 19]. # Note that coefficients is copied, so the caller may freely modify the given argument. self.poly = remove_trailing_elements(coefficients, FieldElement.zero()) self.var = var
def X(cls): """ Returns the polynomial x. """ return cls([FieldElement.zero(), FieldElement.one()])
def trim_trailing_zeros(p): """ Removes zeros from the end of a list. """ return remove_trailing_elements(p, FieldElement.zero())
def gen_linear_term(point): """ Generates the polynomial (x-p) for a given point p. """ return Polynomial([FieldElement.zero() - point, FieldElement.one()])
def monomial(degree, coefficient): """ Constructs the monomial coefficient * x**degree. """ return Polynomial([FieldElement.zero()] * degree + [coefficient])
def __sub__(self, other): other = Polynomial.typecast(other) return Polynomial( two_lists_tuple_operation(self.poly, other.poly, operator.sub, FieldElement.zero()))
def test_prod(): g = FieldElement.generator()**((FieldElement.k_modulus - 1) // 1024) assert X**1024 - 1 == prod([(X - g**i) for i in range(1024)])
# a STARK proving mechanism # from StarkWare101 Workshop # in San Fransisco, 2/17/20 ########## # PART 1 # ########## # first step is to create a list of length 1023 # first two elements are FieldElement objects # representing 1 and 3141592 respectively. a = [FieldElement(1), FieldElement(3141592)] while len(a) < 1023: a.append(a[-2] * a[-2] + a[-1] * a[-1]) # quick unit test to verify a[] constructed properly assert len(a) == 1023, 'The trace must consist of exactly 1023 elements.' assert a[0] == FieldElement(1), 'The first element in the trace must be the unit element.' for i in range(2, 1023): assert a[i] == a[i - 1] * a[i - 1] + a[i - 2] * a[i - 2], f'The FibonacciSq recursion rule does not apply for index {i}' assert a[1022] == FieldElement(2338775057), 'Wrong last element!' print('Success!') # need a generator from field element class # need to generator a group of size 1024 g = FieldElement.generator() ** (3 * 2 ** 20)