예제 #1
0
def prove_low_degree(values,
                     root_of_unity,
                     maxdeg_plus_1,
                     modulus,
                     exclude_multiples_of=0):
    f = PrimeField(modulus)
    print('Proving %d values are degree <= %d' % (len(values), maxdeg_plus_1))

    # If the degree we are checking for is less than or equal to 32,
    # use the polynomial directly as a proof
    if maxdeg_plus_1 <= 16:
        print('Produced FRI proof')
        return [[x.to_bytes(32, 'big') for x in values]]

    # Calculate the set of x coordinates
    xs = get_power_cycle(root_of_unity, modulus)
    assert len(values) == len(xs)

    # Put the values into a Merkle tree. This is the root that the
    # proof will be checked against
    m = merkelize(values)

    # Select a pseudo-random x coordinate
    special_x = int.from_bytes(m[1], 'big') % modulus

    # Calculate the "column" at that x coordinate
    # (see https://vitalik.ca/general/2017/11/22/starks_part_2.html)
    # We calculate the column by Lagrange-interpolating each row, and not
    # directly from the polynomial, as this is more efficient
    quarter_len = len(xs) // 4
    x_polys = f.multi_interp_4(
        [[xs[i + quarter_len * j] for j in range(4)]
         for i in range(quarter_len)],
        [[values[i + quarter_len * j] for j in range(4)]
         for i in range(quarter_len)])
    column = [f.eval_quartic(p, special_x) for p in x_polys]
    m2 = merkelize(column)

    # Pseudo-randomly select y indices to sample
    ys = get_pseudorandom_indices(m2[1],
                                  len(column),
                                  40,
                                  exclude_multiples_of=exclude_multiples_of)

    # Compute the Merkle branches for the values in the polynomial and the column
    branches = []
    for y in ys:
        branches.append(
            [mk_branch(m2, y)] +
            [mk_branch(m, y + (len(xs) // 4) * j) for j in range(4)])

    # This component of the proof
    o = [m2[1], branches]

    # Recurse...
    return [o] + prove_low_degree(column,
                                  f.exp(root_of_unity, 4),
                                  maxdeg_plus_1 // 4,
                                  modulus,
                                  exclude_multiples_of=exclude_multiples_of)
예제 #2
0
def verify_low_degree_proof(merkle_root, root_of_unity, proof, maxdeg_plus_1, modulus, exclude_multiples_of=0):
    f = PrimeField(modulus)

    # Calculate which root of unity we're working with
    testval = root_of_unity
    roudeg = 1
    while testval != 1:
        roudeg *= 2
        testval = (testval * testval) % modulus

    # Powers of the given root of unity 1, p, p**2, p**3 such that p**4 = 1
    quartic_roots_of_unity = [1,
                              f.exp(root_of_unity, roudeg // 4),
                              f.exp(root_of_unity, roudeg // 2),
                              f.exp(root_of_unity, roudeg * 3 // 4)]

    # Verify the recursive components of the proof
    for prf in proof[:-1]:
        root2, branches = prf
        print('Verifying degree <= %d' % maxdeg_plus_1)

        # Calculate the pseudo-random x coordinate
        special_x = int.from_bytes(merkle_root, 'big') % modulus

        # Calculate the pseudo-randomly sampled y indices
        ys = get_pseudorandom_indices(root2, roudeg // 4, 40,
                                      exclude_multiples_of=exclude_multiples_of)

        # For each y coordinate, get the x coordinates on the row, the values on
        # the row, and the value at that y from the column
        xcoords = []
        rows = []
        columnvals = []
        for i, y in enumerate(ys):
            # The x coordinates from the polynomial
            x1 = f.exp(root_of_unity, y)
            xcoords.append([(quartic_roots_of_unity[j] * x1) % modulus for j in range(4)])

            # The values from the original polynomial
            row = [verify_branch(merkle_root, y + (roudeg // 4) * j, prf)
                   for j, prf in zip(range(4), branches[i][1:])]
            rows.append(row)

            columnvals.append(verify_branch(root2, y, branches[i][0]))

        # Verify for each selected y coordinate that the four points from the
        # polynomial and the one point from the column that are on that y 
        # coordinate are on the same deg < 4 polynomial
        polys = f.multi_interp_4(xcoords, rows)

        for p, c in zip(polys, columnvals):
            assert f.eval_quartic(p, special_x) == c

        # Update constants to check the next proof
        merkle_root = root2
        root_of_unity = f.exp(root_of_unity, 4)
        maxdeg_plus_1 //= 4
        roudeg //= 4

    # Verify the direct components of the proof
    data = [int.from_bytes(x, 'big') for x in proof[-1]]
    print('Verifying degree <= %d' % maxdeg_plus_1)
    assert maxdeg_plus_1 <= 16

    # Check the Merkle root matches up
    mtree = merkelize(data)
    assert mtree[1] == merkle_root

    # Check the degree of the data
    powers = get_power_cycle(root_of_unity, modulus)
    if exclude_multiples_of:
        pts = [x for x in range(len(data)) if x % exclude_multiples_of]
    else:
        pts = range(len(data))

    poly = f.lagrange_interp([powers[x] for x in pts[:maxdeg_plus_1]],
                             [data[x] for x in pts[:maxdeg_plus_1]])
    for x in pts[maxdeg_plus_1:]:
        assert f.eval_poly_at(poly, powers[x]) == data[x]   

    print('FRI proof verified')
    return True
예제 #3
0
from permuted_tree import merkelize, mk_branch, verify_branch, blake, mk_multi_branch, verify_multi_branch
from poly_utils import PrimeField
import time
from fft import fft
from fri import prove_low_degree, verify_low_degree_proof
from utils import get_power_cycle, get_pseudorandom_indices, is_a_power_of_2

modulus = 2**256 - 2**32 * 351 + 1
f = PrimeField(modulus)
nonresidue = 7

spot_check_security_factor = 80
extension_factor = 8

# Compute a MIMC permutation for some number of steps
def mimc(inp, steps, round_constants):
    start_time = time.time()
    for i in range(steps-1):
        inp = (inp**3 + round_constants[i % len(round_constants)]) % modulus
    print("MIMC computed in %.4f sec" % (time.time() - start_time))
    return inp

# Generate a STARK for a MIMC calculation
def mk_mimc_proof(inp, steps, round_constants):
    start_time = time.time()
    # Some constraints to make our job easier
    assert steps <= 2**32 // extension_factor
    assert is_a_power_of_2(steps) and is_a_power_of_2(len(round_constants))
    assert len(round_constants) < steps

    precision = steps * extension_factor
예제 #4
0
import hashlib
from poly_utils import PrimeField
from time import time
import sys
import gmpy2

#
# Proof of concept implementation for Eth1 simple custody
#
# https://notes.ethereum.org/1Rn2MwsoSWuEUHTnaRgLcw
#

# BLS12_381 curve modulus
MODULUS = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001

primefield = PrimeField(MODULUS)

# Proof of custody parameters
N = 15  # bits

DOMAIN = list(range(N))


def hash(x):
    if isinstance(x, bytes):
        return hashlib.sha256(x).digest()
    elif isinstance(x, blst.P1):
        return hash(x.compress())
    elif isinstance(x, int):
        return hash(x.to_bytes(32, "little"))
    b = b""
예제 #5
0
from py_ecc import optimized_bls12_381 as b
from fft import fft
from poly_utils import PrimeField
from multicombs import lincomb
import os
import hashlib
import random
import time

WIDTH = 16
DEPTH = 3

MODULUS = b.curve_order

field = PrimeField(MODULUS)

# Root of unity for a given evaluation domain size
root_of_unity_candidates = {
    512:
    12531186154666751577774347439625638674013361494693625348921624593362229945844,
    256:
    21071158244812412064791010377580296085971058123779034548857891862303448703672,
    128:
    3535074550574477753284711575859241084625659976293648650204577841347885064712,
    64:
    6460039226971164073848821215333189185736442942708452192605981749202491651199,
    32:
    32311457133713125762627935188100354218453688428796477340173861531654182464166,
    16:
    35811073542294463015946892559272836998938171743018714161809767624935956676211
}