Replies: 23 comments 10 replies
-
Clearly, Note that If If we use p_{2,1}(g^x), |
Beta Was this translation helpful? Give feedback.
-
from field import FieldElement
from channel import Channel
from polynomial import interpolate_poly, X,prod 公式: $$ C_0=1, C_{n+1}=\frac{2(2n+1)}{n+2}C_n $$ a = [FieldElement(1),FieldElement(1)] # C(1) = 1
for i in range(1,100):
numerator = FieldElement(2) * (FieldElement(2)*i + 1)
denominator = i + 2
a.append((numerator * a[-1]) / denominator)
g = FieldElement.generator() ** ((3*2**30) // 128)
G = [g**i for i in range(128)]
f = interpolate_poly(G[:101], a)
assert f(g**100) == 1555040254 w = FieldElement.generator()
h = w ** ((2 ** 30 * 3) // 1024)
H = [h ** i for i in range(1024)]
eval_domain = [w * h for h in H]
f_eval = [f(d) for d in eval_domain] p0 = (f - 1) / (X - 1)
p1 = (f - 1555040254) / (X - g**100) M_points = [(g**i, FieldElement(i)) for i in range(100)]
M = interpolate_poly([p[0] for p in M_points], [p[1] for p in M_points])
def catalan_constraint(x):
return f(g * x) * (M + 2) - (FieldElement(2)*(FieldElement(2)*M+1) * f(x))
p2_numerator = catalan_constraint(X)
p2_denominator = prod([X - g**i for i in range(100)])
p2 = p2_numerator / p2_denominator def get_CP(channel):
alpha0 = channel.receive_random_field_element()
alpha1 = channel.receive_random_field_element()
alpha2 = channel.receive_random_field_element()
# ignore alpha0 because it will always be 0
return p0 + alpha1*p1 + alpha2*p2 test_channel = Channel()
CP_test = get_CP(test_channel)
CP_test(h**888) 595485781 |
Beta Was this translation helpful? Give feedback.
-
Select a public ploynomial
These contrait can be expressed by quotient ploynomials.
Here is the code. t = [FieldElement(1)]
for i in range(127):
n = i
t.append(t[-1] * (4 * FieldElement(n) + 2) / (FieldElement(n) + 2))
print(t[0], t[1], t[2])
print(t[100].val) # 1555040254
g = FieldElement.generator() ** (3 * 2**23) # for 128 points
points = [g**i for i in range(2**7)]
f = interpolate_poly(points, t)
idx = [FieldElement(i) for i in range(2**7)] # ploy(g^n) -> n
i = interpolate_poly(points, idx)
# constrait 1
p0 = (f - 1) / (X - g**0)
# constrait 2
p1 = (f - 1555040254) / (X - g**100)
# constriat 3
numer = f * (4 * i(X) + 2) - f(g * X) * (i(X) + 2)
print(i(g).val)
print(f(g).val)
print(f(g**2).val)
p2 = numer / ((X**128 - 1) / (X - g**127))
print("deg p0 =", p0.degree())
print("deg p1 =", p1.degree())
print("deg p2 =", p2.degree())
h_gen = FieldElement.generator() ** ((2**30 * 3) // 1024) # extend to 1024
h = [h_gen**i for i in range(1024)]
domain = [FieldElement.generator() * x for x in h]
ev = [f.eval(d) for d in domain]
mt = MerkleTree(ev)
channel = Channel()
channel.send(mt.root)
alpha0 = channel.receive_random_field_element()
alpha1 = channel.receive_random_field_element()
alpha2 = channel.receive_random_field_element()
CP = alpha0 * p0 + alpha1 * p1 + alpha2 * p2
print(CP(h_gen**111).val)
|
Beta Was this translation helpful? Give feedback.
-
最开始,将卡特兰数的递推公式转化为适合 STARK 协议的算术约束。接着,构建多项式并计算 composition polynomial 在指定点的值。 算术化约束: 下面是代码 from channel import Channel
from field import FieldElement
from merkle import MerkleTree
from polynomial import interpolate_poly, Polynomial, X
def generate_catalan_sequence(n):
c = [1]
for i in range(n):
c.append(c[-1] * 2 * (2*i + 1) // (i + 2))
return c
def setup_domain(size, subgroup_size):
generator = FieldElement.generator()
g = generator ** (3 * 2**20 // subgroup_size)
return [g**i for i in range(size)]
def create_polynomial(points, values):
return interpolate_poly(points, [FieldElement(v) for v in values])
def create_composition_polynomial(f, g, target_value):
p0 = (f - 1) / (X - 1)
p1 = (f - target_value) / (X - g**100)
M_x = [g**i for i in range(100)]
M_y = [2*(2*FieldElement(i)+1)/(FieldElement(i)+2) for i in range(100)]
M = interpolate_poly(M_x, M_y)
p2 = (f(g*X) - M(X)*f(X)) / Polynomial.prod([X - g**i for i in range(100)])
return p0, p1, p2
def get_composition_polynomial(channel, p0, p1, p2):
return sum(channel.receive_random_field_element() * p for p in [p0, p1, p2])
def main():
# Setup
catalan = generate_catalan_sequence(128)
g_domain = setup_domain(128, 128)
h_domain = setup_domain(1024, 1024)
# Create and verify polynomial
f = create_polynomial(g_domain, catalan)
assert f(g_domain[100]) == catalan[100]
# Evaluate polynomial and create Merkle tree
evaluations = [f.eval(d) for d in [FieldElement.generator()*x for x in h_domain]]
merkle_tree = MerkleTree(evaluations)
# Create composition polynomial
p0, p1, p2 = create_composition_polynomial(f, g_domain[1], catalan[100])
# Channel operations
channel = Channel()
channel.send(merkle_tree.root)
CP = get_composition_polynomial(channel, p0, p1, p2)
# Test results
print('deg CP:', CP.degree())
print('CP(h^111):', CP(h_domain[111]))
print('CP(h^888):', CP(h_domain[888]))
if __name__ == "__main__":
main() |
Beta Was this translation helpful? Give feedback.
-
from channel import Channel
from field import FieldElement
from merkle import MerkleTree
from polynomial import interpolate_poly, Polynomial, X, prod c=[1]
t=[FieldElement(1)]
for i in range(127):
c.append(c[-1]*2*(2*i+1)//(i+2))
t.append(FieldElement(c[-1]))
assert t[100]==1555040254 g = FieldElement.generator() ** (3 * 2**20)
points = [ g**i for i in range(128) ]
f = interpolate_poly(points, t)
assert f(g**100)==t[100] h_gen = FieldElement.generator() ** ((3 * 2**20)//1024)
h = [ h_gen**i for i in range(1024) ]
domain = [FieldElement.generator()*x for x in h]
ev = [f.eval(d) for d in domain]
mt = MerkleTree(ev)
ch = Channel()
ch.send(mt.root) numer0 = f - 1
denom0 = X - 1
p0 = numer0 / denom0 numer1 = f - 1555040254
denom1 = X - g**100
p1 = numer1 / denom1 # find a function M to remove `i` in the constraint
M_x = points[0:100]
M_y = [2*(2*FieldElement(i)+1)/(FieldElement(i)+2) for i in range(100)]
M = interpolate_poly(M_x, M_y) numer2 = f(g*X)-M(X)*f(X)
denom2 = prod([(X - g**i) for i in range(100)])
p2 = numer2 / denom2 print('deg p0:', p0.degree())
print('deg p1:', p1.degree())
print('deg p2:', p2.degree())
def get_CP(channel):
alpha0 = channel.receive_random_field_element()
alpha1 = channel.receive_random_field_element()
alpha2 = channel.receive_random_field_element()
return alpha0*p0 + alpha1*p1 + alpha2*p2
test_channel = Channel()
CP_test = get_CP(test_channel)
print('deg CP_test:', CP_test.degree())
print('CP_test(111):', CP_test(h_gen**111))
print('CP_test(888):', CP_test(h_gen**888))
|
Beta Was this translation helpful? Give feedback.
-
我不是数学专业,基础太差,不了解很多名词需要恶补,最初是看不懂题目的,好在结合几位高人已经交出的作业,以及不断回看过去的几节课,加上把 stark101 给的 jupyterLab 例题过了几遍,终于搞明白题目在问什么,以及为什么要用这些步骤,收获很大! 由于水平限制,一定有不少错误以及概念的理解不到位,请老师们见谅 首先导入所需库,这些库是 stark101 仓库中 Stark101-part1.ipynb 与 Stark101-part2.ipynb 导入过的库,也是后面编程中需要用到的。
卡特兰数的递推公式是: 由此可以递推出所有的值,由于后续会用到 g 的阶是 128 ,便按照卡特兰数公式按序计算出 128 个值写入一个 list ,最后验证了第 100 项值为 1555040254
将 a 列表在域 g 上转化成一个多项式,用到了拉格朗日插值定理库(除以 128 的目的是希望使 g 在乘以自己 128 次后回到 1 )
按教程验证阶数是否正确
在 stark101 part2 中,我们需要将一个数列的三个约束转化为 三个多项式
由于第三个多项式中有其他变量,需要用拉格朗日插值定理将数列转化为多项式
最后,验证composition polynomials 在 ( h^{111} ) 上的取值 ( p(h^{111}) )
|
Beta Was this translation helpful? Give feedback.
-
解题思路和STARK101中的整体思路类似:
构建数列: # 1. get C
c = [FieldElement(1)]
for i in range(128):
c.append(c[i] * 2 * (2 * i + 1) / (i + 2))
print("c[100] = " + str(c[100]))
# c[100]=1555040254 选取小域g并构建f # 2. get G, G size is 128
g = FieldElement.generator() ** (3 * 2**30 / 128)
G = []
for i in range(128):
G.append(g**i)
# 3. get f
f = interpolate_poly(G, c[:-1]) 选取大域h并扩张 # 4. get H, H size is 1024
w = FieldElement.generator()
h = w ** ((3 * (2**30)) // 1024)
H = [h**i for i in range(1024)]
eval_domain = [w * x for x in H] 在这里因为引入了额外的变量,所以需要通过一个function 对其进行一个映射,映射到g内。 # 5. ploy(g^n) -> n
T = interpolate_poly([g**i for i in range(128)], [FieldElement(p) for p in range(128)])
# 6. constrait p0,p1,p2
numer0 = f - 1
denom0 = X - 1
p0 = numer0 / denom0
numer1 = f - 1555040254
denom1 = X - g**100
p1 = numer1 / denom1
numer2 = f(g * X) * (T(X) + 2) - (2 * (2 * T(X) + 1) * f(X))
denom2 = (X**128 - 1) / (X - g**127)
p2 = numer2 / denom2 最后打印结果即可 def get_cp(channel, p0, p1, p2):
alpha0 = channel.receive_random_field_element()
alpha1 = channel.receive_random_field_element()
alpha2 = channel.receive_random_field_element()
return alpha0 * p0 + alpha1 * p1 + alpha2 * p2
channel = Channel()
cp = get_cp(channel, p0, p1, p2)
print("cp(h*888) = " + str(cp(h**888)))
print("cp(g*111) = " + str(cp(g**111))) |
Beta Was this translation helpful? Give feedback.
-
其中 from channel import Channel
from field import FieldElement
from merkle import MerkleTree
from polynomial import interpolate_poly, X, prod
# 小域 g size 取 128,大域 h size 取 1024
g = FieldElement.generator() ** (3 * 2**30 // 128)
G = [g ** i for i in range(128)]
w = FieldElement.generator()
h = w ** ((3 * 2**30) // 1024)
H = [h ** i for i in range(1024)]
eval_domain = [w * x for x in H]
f = interpolate_poly(G[:101], a)
f_eval = [f(d) for d in eval_domain]
mt = MerkleTree(f_eval)
test_channel = Channel()
test_channel.send(mt.root)
assert f(g**100) == 1555040254
# constrait 1
numer0 = f - 1
denom0 = X - 1
p0 = numer0 / denom0
# constrait 2
numer1 = f - 1555040254
denom1 = X - g**100
p1 = numer1 / denom1
# constrait 3
# 将自然数其映射到有限域,(由点集合插值得到多项式 M )
M = interpolate_poly(
[g**i for i in range(100)],
[2*(2*FieldElement(i)+1)/(FieldElement(i)+2) for i in range(100)])
p2_numerator = f(g * X) - M(X) * f(X)
p2_denominator = prod([X - g**i for i in range(100)])
p2 = p2_numerator / p2_denominator
def get_CP(channel):
alpha0 = channel.receive_random_field_element()
alpha1 = channel.receive_random_field_element()
alpha2 = channel.receive_random_field_element()
return alpha0 * p0 + alpha1*p1 + alpha2*p2
CP_test = get_CP(test_channel)
assert CP_test(g**111) == CP_test(h**888)
print(f'g**111 {CP_test(g**111).val}')
print(f'h**888 {CP_test(h**888).val}') g^111 723710509 |
Beta Was this translation helpful? Give feedback.
-
//拷贝 @0x-stan程序,并尝试修改 //小域 g size 取 128,大域 h size 取 1024 w = FieldElement.generator() f = interpolate_poly(G[:100], a) test_channel = Channel() assert f(g**99) == 1555040254 // constrait 1 // constrait 2 // constrait 3 // 将自然数其映射到有限域,(由点集合插值得到多项式 M ) p2_numerator = M1(x)*f(g * X) - M2(X) * f(X) def get_CP(channel):
CP_test = get_CP(test_channel) |
Beta Was this translation helpful? Give feedback.
-
其中$M(x)$是$g^i$和$\frac{2*(2*n+1)}{n+2}$的拉格朗日插值多项式 from field import FieldElement
from polynomial import interpolate_poly,X,prod
from channel import Channel
#construct Cattelan series
a = [FieldElement(1)]
t=[]
for n in range(127):
a.append(FieldElement(2)*(FieldElement(2)*n+FieldElement(1))*FieldElement.inverse(n+FieldElement(2))*a[-1])
assert a[100]== 1555040254
#construct big field H
c=FieldElement.generator()
h=c**((2**30*3)//1024)
H=[h**i for i in range(1024)]
eval_domain_h = [c * x for x in H]
#construct small field G
c=FieldElement.generator()
g=c**((3*2**30)//128)
G=[g**i for i in range(128)]
eval_domain_g=[c*x for x in G]
#get interpolate_polynomial
f = interpolate_poly(G, a)
assert f(G[100]==a[100])
#extend
f_eval = [f(d) for d in eval_domain_h]
#get p0 and p1
p0 = (f - 1) / (X - 1)
p1 = (f - 1555040254) / (X - g**100)
#get p2
M_y = [FieldElement(2)*(2*FieldElement(i)+FieldElement(1))*FieldElement.inverse((FieldElement(i)+2)) for i in range(127)]
M = interpolate_poly(G[:-1], M_y)
numerator = f(g*X)-M(X)*f(X)
denominator =prod([X-g**n for n in range(127)])
p2 = numerator / denominator
channel=Channel()
#get CP(x)
alpha0 = channel.receive_random_field_element()
alpha1 = channel.receive_random_field_element()
alpha2 = channel.receive_random_field_element()
CP=alpha0*p0+alpha0*p1+alpha2*p2
print(CP(h**888))
#-501161392 |
Beta Was this translation helpful? Give feedback.
-
from channel import Channel def part0():
|
Beta Was this translation helpful? Give feedback.
-
from channel import Channel 生成卡特兰数for i in range(0,100): print("t:",t)print("len t:",len(t)) print(FieldElement.k_modulus)生成我们需要插值的x轴上的点的生成元,是一个乘法循环群,阶为128g=FieldElement.generator()(3*2(23)) print(FieldElement.generator())points = [g**i for i in range(128)] print("乘法循环群中的元素",points)print(len(points[:-1]))插值得到代数次数为 100的多项式p = interpolate_poly(points[:101], t) h_gen=FieldElement.generator()(3*2(20)) print(h**1024)生成陪集domain = [FieldElement.generator() * x for x in h_points] print(domain)将证明转化为另一种形式生成f(x)-1numer0 = p - Polynomial([FieldElement(1)]) 生成x-1demo0 = Polynomial.gen_linear_term(FieldElement(1)) 构造多项式 f(x)-1/(x-g^0)q0, r0 = numer0.qdiv(demo0) print("q0 degree:", q0.degree())构造多项式 f(x)-1555040254numer1 = p - Polynomial([FieldElement(1555040254)]) numer1print(t[100])print(numer1.degree())构造多项式x-g^(100)demo1 = Polynomial.gen_linear_term(points[100]) demo1构造多项式 f(x)-2338775057/(x-g^1022)q1, r1 = numer1.qdiv(demo1) 构造单项式g*xinner_poly1 = Polynomial([FieldElement(0), points[1]]) 计算f(g*x)composition = p.compose(inner_poly1) 构造多项式 2*(2*x+1)/(x+2)temp_x=points[0:100] transition_xtemp_t=[2*(2*FieldElement(i)+1)/(FieldElement(i)+2) for i in range(0,100)] temp_f=interpolate_poly(temp_x,temp_t) transition_f构造 f(gx)-transition_ff(x)T_f=composition-temp_f*p T_f构造多项式 (x-g^0)...(x-g^99)factors=[Polynomial.gen_linear_term(points[i]) for i in range(0,100)] 构造多项式f(gx)-2(2*x+1)/(x+2)*f(x)pp,pr=T_f.qdiv(prod_factors) pp=T_f/prod_factorsch = Channel() print("p(h^{111})=",cp.eval(domain[111])) print("p(h^{888})=",cp.eval(domain[888])) |
Beta Was this translation helpful? Give feedback.
-
from channel import Channel
from field import FieldElement
from merkle import MerkleTree
from polynomial import interpolate_poly, Polynomial, X, prod
t = [FieldElement(1)]
# calc catalan function
small_domain_size = 128
val_100 = 1555040254
for i in range(small_domain_size - 1):
t.append(t[-1] * 2 * (FieldElement(2)*i+1) / (2+i))
assert t[100] == val_100
large_domain_size = 1024
# prepare small domain
g = FieldElement.generator() ** (3 * 2 ** 30//small_domain_size)
G = [g ** i for i in range(small_domain_size)]
# prepare large domain
h = FieldElement.generator() ** ((3 * 2 ** 30) // large_domain_size)
H = [h ** i for i in range(large_domain_size)]
domain = [FieldElement.generator() * x for x in H]
f = interpolate_poly(G, t)
ev = [f.eval(d) for d in domain]
assert f(g**100) == val_100
# make constraints
p0 = (f - 1) / (X - g**0)
p1 = (f - val_100) / (X - g**100)
# special: make 'n' polynomial
N = [FieldElement(i) for i in range(100)]
fn = interpolate_poly(G[:100], N)
assert fn(g**99) == 99
# make a transfer
# f(gx) = 2 * (2n+1) / (n + 2) * f(x) => (n + 2) * f(gx) = 2 * (2n+1) * f(x)
# let n = fn(X)
numer = (fn(X) + 2) * f(g*X) - (4*fn(X)+2) * f
lst = [(X - g**i) for i in range(100)]
denom = prod(lst)
p2 = numer / denom
print("deg p0 = ", p0.degree())
print("deg p1 = ", p1.degree())
print("deg p2 = ", p2.degree())
# get Composition Polynomial
mt = MerkleTree(ev)
ch = Channel()
ch.send(mt.root)
alpha0 = ch.receive_random_field_element()
alpha1 = ch.receive_random_field_element()
alpha2 = ch.receive_random_field_element()
print('alpha0 = ', alpha0)
print('alpha1 = ', alpha1)
print('alpha2 = ', alpha2)
cp = alpha0 * p0 + alpha1 * p1 + alpha2 * p2
print('deg cp:', cp.degree())
print('cp(g^111):', cp(g**111).val)
print('cp(h^888):', cp(h**888).val)
assert cp(g**111).val == cp(h**888).val
print('cp(h^111):', cp(h**111).val) |
Beta Was this translation helpful? Give feedback.
-
from channel import Channel 计算卡特兰数列def calculate_catalan_sequence(size, val_100): assert t[100]==1555040254 准备域def prepare_domain(size): 插值并求值def interpolate_and_evaluate(G, t, domain): 构造约束条件def make_constraints(f, g, g0, g100, val_100): 构造第一个约束多项式p0 = (f - 1) / (X - g0) 构造第二个约束多项式p1 = (f - val_100) / (X - g100) 构造辅助多项式fnN = [FieldElement(i) for i in range(100)] 构造第三个约束多项式numer = (fn(X) + 2) * f(g * X) - (4 * fn(X) + 2) * f return p0, p1, p2, fn 获取组合多项式def get_composition_polynomial(p0, p1, p2, ch): 接收随机系数alpha0 = ch.receive_random_field_element() 构造组合多项式return alpha0 * p0 + alpha1 * p1 + alpha2 * p2 if name == "main": 计算卡特兰数列t = calculate_catalan_sequence(small_domain_size, expect_value_100) 准备小域G和大域HG = prepare_domain(small_domain_size) f, ev = interpolate_and_evaluate(G, t, domain) 构造约束条件p0, p1, p2, fn = make_constraints(f, G[1], G[0], G[100], expect_value_100) 打印约束多项式的度print(f"deg p0 = {p0.degree()}") 构建Merkle树mt = MerkleTree(ev) 获取组合多项式cp = get_composition_polynomial(p0, p1, p2, ch) 打印结果assert cp(G[111]).val == cp(H[888]).val |
Beta Was this translation helpful? Give feedback.
-
思路是构造三个约束:
以下给出代码和每一步的注释: # import field lib
from field import FieldElement
# import polynomial lib
from polynomial import interpolate_poly,X,prod
# import channel lib
from channel import Channel
# import merkle tree
from merkle import MerkleTree
# transcript
channel=Channel()
## trace
# initial state: C_0 = 1
a = [FieldElement(1)]
t=[]
# length of a must equals length of G
for n in range(128 - 1):
# C_(n+1) = 2 * (2 * n + 1) / (n + 2) * C_n
a.append(FieldElement(2)*(FieldElement(2)*n+FieldElement(1))*FieldElement.inverse(n+FieldElement(2))*a[-1])
assert a[100]== 1555040254
## domain
# generate large domain H of size 1024
c=FieldElement.generator()
h=c**((3*2**30)//1024)
H=[h**i for i in range(1024)]
eval_domain_h = [c * x for x in H]
# generate small domain G of size 128
c=FieldElement.generator()
g=c**((3*2**30)//128)
G=[g**i for i in range(128)]
eval_domain_g=[c * x for x in G]
## polynomial and evaluations
# interpolate a on G
f = interpolate_poly(G, a)
assert f(G[100]) == a[100] # check f(100) = a[100]
# LDE by RS encoding on coset of large domain H
f_eval = [f(d) for d in eval_domain_h]
eval_oracle = MerkleTree(f_eval) # commit f_eval
channel.send(eval_oracle.root) # write commmitment to transcript
## constraints
# constrain f(0) == 1 and f(100) == 1555040254
p0 = (f - 1) / (X - 1)
p1 = (f - 1555040254) / (X - g**100)
# constrain C_(n+1) = 2 * (2 * n + 1) / (n + 2) * C_n
M_y = [FieldElement(2)*(2*FieldElement(i)+FieldElement(1))*FieldElement.inverse((FieldElement(i)+2)) for i in range(127)]
M = interpolate_poly(G[:-1], M_y)
# quotient of p2
numerator = f(g*X)-M(X)*f(X)
denominator = (X ** 128 - 1) / (X - g ** 127) # due to (X - 1)(X - g)...(X - g ** 127) == (X ** 128 - 1)
p2 = numerator / denominator
# get CP(x)
alphas = [channel.receive_random_field_element() for _ in range(3)]
CP = alphas[0] * p0 + alphas[1] * p1 + alphas[2] * p2
print(CP(h**111))
# 831670508 |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
Note:首先打开https://github.com/starkware-industries/stark101 安装相关库或者在线使用Jupyter Notebook. 个人不理解的部分特别标注:
例如:
另:
Code:from channel import Channel
from field import FieldElement
from merkle import MerkleTree
from polynomial import interpolate_poly, X, prod
# generate catalan series
c=[FieldElement(1)]
for i in range(127):
c.append(c[-1]*(4* FieldElement(i)+2)/(FieldElement(i)+2))
# generate small size=128 domain G
# generate big size=1024 domain H
## interpolate with the small size domain
g = FieldElement.generator() ** (3 * 2**30 // 128)
G = [g ** i for i in range(128)]
f = interpolate_poly(G, c)
w = FieldElement.generator()
h = w ** ((3 * 2**30) // 1024)
H = [h ** i for i in range(1024)]
eval_domain = [w * x for x in H]
f_eval = [f(d) for d in eval_domain]
mt = MerkleTree(f_eval)
test_channel = Channel()
test_channel.send(mt.root)
# px 0+1+2
numer0 = f - 1
denom0 = X - 1
p0 = numer0 / denom0
numer1 = f - 1555040254
denom1 = X - g**100
p1 = numer1 / denom1
# 将自然数其映射到有限域,(由点集合插值得到多项式 M )
M = interpolate_poly(
[g**i for i in range(100)],
[2*(2*FieldElement(i)+1)/(FieldElement(i)+2) for i in range(100)])
p2_numerator = f(g * X) - M(X) * f(X)
p2_denominator = prod([X - g**i for i in range(100)])
p2 = p2_numerator / p2_denominator
def get_CP(channel):
alpha0 = channel.receive_random_field_element()
alpha1 = channel.receive_random_field_element()
alpha2 = channel.receive_random_field_element()
return alpha0 * p0 + alpha1*p1 + alpha2*p2
CP_test = get_CP(test_channel)
print(f'h**111 {CP_test(h**111).val}')
print(f'h**888 {CP_test(h**888).val}') |
Beta Was this translation helpful? Give feedback.
-
1.求trace from field import FieldElement
f = [FieldElement(1)]
for i in range(1,128):
numer = FieldElement(2) * FieldElement(2 * i - 1) * f[i - 1]
denom = FieldElement(i + 1)
f.append(numer / denom)
f[100] 得到f[100] = 1555040254 2.在128domain上插值 from polynomial import interpolate_poly, X
g = FieldElement.generator() ** ((2 ** 30 * 3) // 128)
G = [g ** i for i in range(128)]
c = interpolate_poly(G, f) 3.将domain blowup到1024 w = FieldElement.generator()
h = w ** ((2 ** 30 * 3) // 1024)
H = [h ** i for i in range(1024)]
eval_domain = [w * x for x in H]
f_eval = [c(d) for d in eval_domain] 4.求三个约束的polynomial numer0 = c - 1
denom0 = X - g ** 0
p0 = numer0 / denom0
numer1 = c - 1555040254
denom1 = X - g ** 100
p1 = numer1 / denom1
N = [FieldElement(i) for i in range(128)]
n = interpolate_poly(G, N)
numer2 = c * (4 * n(X) + 2) - c(g * X) * (n(X) + 2)
denom2 = (X**128 - 1) / (X - g**127)
p2 = numer2 / denom2 5.组合约束求出CP from channel import Channel
channel = Channel()
alpha0 = channel.receive_random_field_element()
alpha1 = channel.receive_random_field_element()
alpha2 = channel.receive_random_field_element()
CP = alpha0 * p0 + alpha1 * p1 + alpha2 * p2
print(CP(w * h ** 111)) 得到h**111点的值为1125323761 |
Beta Was this translation helpful? Give feedback.
-
准备工作# 参考stark101,引入要用到的库
from channel import Channel
from field import FieldElement
from polynomial import interpolate_poly, X, prod
from merkle import MerkleTree
# 初始化 channel
channel = Channel()
# 找到 100对应的 2的幂
target_n = 100
expand = 8
nearest_pow2 = 1 << (target_n-1).bit_length() if target_n > 0 else 1
small_size = nearest_pow2
large_size = nearest_pow2 * expand
print("Nearest power of 2:", nearest_pow2)
print("small size:", small_size, "large size:", large_size)
计算Catalan数列
catalan_series = [FieldElement(1)]
fe1 = FieldElement(1)
fe2 = FieldElement(2)
for i in range(nearest_pow2 - 1):
fen = FieldElement(i)
Cn = catalan_series[i]
Cnadd1 = fe2 * (fe2 * fen + fe1) / (fen + fe2) * Cn
catalan_series.append(Cnadd1)
print("C_100 =", catalan_series[100])
assert catalan_series[100]==1555040254
计算用到的域小域G: size = 128 大域H: size = 1024 乘一个协因子$w$,原因(待Review):
g = FieldElement.generator() ** ((2 ** 30 * 3) // small_size)
print('small g:', g, 'g ^',small_size, '=', g**small_size)
h = FieldElement.generator() ** ((2 ** 30 * 3) // large_size)
print('large h:', h, 'h ^',large_size, '=', h**large_size)
G = [g ** i for i in range(small_size)]
H = [h ** i for i in range(large_size)]
w = FieldElement.generator()
H = [w * hh for hh in H]
拉格朗日插值并计算扩展域上的值f = interpolate_poly(G, catalan_series)
f_eval = [f(hh) for hh in H] 设置随机数种子f_merkle = MerkleTree(f_eval)
channel.send(f_merkle.root) 边界约束p0 = (f - catalan_series[0]) / (X - G[0])
p1 = (f - catalan_series[100]) / (X - G[100]) 递推关系约束根据公式: 即: 即: 因此,需要获得一个n的表达式,满足:
$p_2(x) = \frac{(n(x)+2)f(gx)-2(2*n(x)+1)*f(x)}{\prod \limits_{i=0}^{100}(x - g^{i})}$ 另一种方式,扩展到全域,分母可以简化: $p_2(x) = \frac{(n(x)+2)f(gx)-2(2*n(x)+1)*f(x)}{(x^{128}-1)/(x-g^{127})}$ # part
n = interpolate_poly(G[:target_n], [FieldElement(i) for i in range(target_n)])
p2_numerator = (n(X) + fe2) * f(g*X) - fe2 * (fe2 * n(X) + fe1) * f(X)
p2_denominator = prod([X - g**i for i in range(target_n)])
p2_part = p2_numerator / p2_denominator
# full
n = interpolate_poly(G, [FieldElement(i) for i in range(small_size)])
p2_numerator = (n(X) + fe2) * f(g*X) - fe2 * (fe2 * n(X) + fe1) * f(X)
# p2_numerator = fe2 * (fe2 * n(X) + fe1) * f(X) - (n(X) + fe2) * f(g*X)
p2_denominator = (X**128 - 1) / (X-g**127)
p2_full = p2_numerator / p2_denominator
print("p0 degree:", p0.degree())
print("p1 degree:", p1.degree())
print("p2 part degree:", p2_part.degree())
print("p2 full degree:", p2_full.degree())
构造CPalpha0 = channel.receive_random_field_element()
alpha1 = channel.receive_random_field_element()
alpha2 = channel.receive_random_field_element()
print('alpha0 =', alpha0)
print('alpha1 =', alpha1)
print('alpha2 =', alpha2)
CP_part = p0 + alpha1 * p1 + alpha2 * p2_part
CP_full = p0 + alpha1 * p1 + alpha2 * p2_full
print('CP_part degree:', CP_part.degree())
print('CP_full degree:', CP_full.degree())
计算结果print('part h111:', CP_part(h**111).val)
print('part h888:', CP_part(h**888).val)
print('full h111:', CP_full(h**111).val)
print('full h888:', CP_full(h**888).val)
|
Beta Was this translation helpful? Give feedback.
-
from field import FieldElement
a = [FieldElement(1)]
for i in range(1, 100):
a.append(a[-1] * 2 * (2 * i + 1) / (i + 2))
assert len(a) == 100, '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(1, 100):
assert a[i] == a[i-1] * 2 * (2 * i + 1) / (i + 2), f'The FibonacciSq recursion rule does not apply for index {i}'
assert a[99] == FieldElement(1555040254), 'Wrong last element!'
print('Success!')
g = FieldElement.generator() ** (3 * 2 ** 23)
G = [g ** i for i in range(128)]
assert g.is_order(128), 'The generator g is of wrong order.'
b = FieldElement(1)
for i in range(127):
assert b == G[i], 'The i-th place in G is not equal to the i-th power of g.'
b = b * g
assert b != FieldElement(1), f'g is of order {i + 1}'
if b * g == FieldElement(1):
print('Success!')
else:
print('g is of order > 1024')
from polynomial import interpolate_poly
f = interpolate_poly(G[:-28], a)
w = FieldElement.generator()
h = w ** ((2 ** 30 * 3) // 1024)
H = [h ** i for i in range(1024)]
eval_domain = [w * x for x in H]
from hashlib import sha256
assert len(set(eval_domain)) == len(eval_domain)
w = FieldElement.generator()
f_eval = [f(d) for d in eval_domain]
from polynomial import interpolate_poly, X, prod
numer0 = f - FieldElement(1)
denom0 = X - g ** 0
p0,r0 = numer0.qdiv(denom0) // constraint 0
numer1 = f - FieldElement(1555040254)
denom1 = X - g**99
p1, r1 = numer1.qdiv(denom1) // constraint 1
lst = [(X - g**i) for i in range(99)]
pr = prod(lst) * (X + 2)
M_points = [(g**i, FieldElement(i)) for i in range(99)]
M = interpolate_poly([p[0] for p in M_points], [p[1] for p in M_points])
def catalan_constraint(x):
return f(g * x) * (M + 3) - f(x) * (FieldElement(2)*(FieldElement(2)*M+3))
p2_numerator = catalan_constraint(X) // constrain 2
p2_denominator = prod([X - g**i for i in range(99)])
p2, r22 = p2_numerator.qdiv(p2_denominator)
def get_CP(channel):
alpha0 = channel.receive_random_field_element()
alpha1 = channel.receive_random_field_element()
alpha2 = channel.receive_random_field_element()
return alpha0 * p0 + alpha1 * p1 + alpha2 * p2
def CP_eval(channel):
CP = get_CP(channel)
return [CP(d) for d in eval_domain]
from channel import Channel
test_channel = Channel()
CP_test = get_CP(test_channel)
print(CP_test(111)) //963694142
print(CP_test(888)) //-1381902967 |
Beta Was this translation helpful? Give feedback.
-
有手就行,注意channel一定要先send merkel root,再用它的randomness来构造CP from field import FieldElement
from channel import Channel
from polynomial import interpolate_poly, X, prod
from merkle import MerkleTree
from channel import Channel
a = [FieldElement(1), FieldElement(3141592)]
while len(a) < 1023:
a.append(a[-2] * a[-2] + a[-1] * a[-1])
a = [FieldElement(1)]
for i in range(100):
a.append(FieldElement(2) * (FieldElement(2) * FieldElement(i) + 1) * FieldElement(i+2).inverse() * a[i])
assert a[-1] == 1555040254
g = FieldElement.generator() ** ((3*2**30) // 128)
G = [g**i for i in range(128)]
f = interpolate_poly(G[:len(a)], a)
assert f(g**100) == 1555040254
w = FieldElement.generator()
h = w ** ((2 ** 30 * 3) // 1024)
H = [h ** i for i in range(1024)]
eval_domain = [w * h for h in H]
f_eval = [f(d) for d in eval_domain]
f_merkle = MerkleTree(f_eval)
channel = Channel()
channel.send(f_merkle.root)
assert (f - 1) % (X - G[0]) == 0
assert (f - 1555040254) % (X - G[100]) == 0
p0 = (f - 1) / (X - G[0])
p1 = (f - 1555040254) / (X - G[100])
l = interpolate_poly([g**i for i in range(100)], [FieldElement(i) for i in range(100)])
numerator = f(g * X) * (l + 2) - (FieldElement(2) * (FieldElement(2) * l + 1) * f(X))
denominator = prod([X - g**i for i in range(100)])
assert numerator % denominator == 0
p2 = numerator / denominator
def get_CP(channel):
alpha0 = channel.receive_random_field_element()
alpha1 = channel.receive_random_field_element()
alpha2 = channel.receive_random_field_element()
return alpha0*p0 + alpha1*p1 + alpha2*p2
cp = get_CP(channel)
cp(h ** 111) 732987908 |
Beta Was this translation helpful? Give feedback.
-
from channel import Channel
from field import FieldElement
from merkle import MerkleTree
from polynomial import interpolate_poly, X, prod
// 计算卡特兰数列
def calculate_catalan_sequence(size, val_100):
t = [FieldElement(1)]
for i in range(size - 1):
t.append(t[-1] * 2 * (FieldElement(2) * i + 1) / (i + 2))
assert t[100] == val_100
return t
c=[1]
t=[FieldElement(1)]
for i in range(127):
c.append(c[-1]2(2*i+1)//(i+2))
t.append(FieldElement(c[-1]))
assert t[100]==1555040254
// 准备域
def prepare_domain(size):
generator = FieldElement.generator()
g = generator ** (3 * 2 ** 30 // size)
return [g ** i for i in range(size)]
// 插值并求值
def interpolate_and_evaluate(G, t, domain):
f = interpolate_poly(G, t)
return f, [f.eval(d) for d in domain]
// 构造约束条件
def make_constraints(f, g, g0, g100, val_100):
// 构造第一个约束多项式
p0 = (f - 1) / (X - g0)
// 构造第二个约束多项式
p1 = (f - val_100) / (X - g100)
// 构造辅助多项式fn
N = [FieldElement(i) for i in range(100)]
fn = interpolate_poly(G[:100], N)
assert fn(g ** 99) == 99
// 构造第三个约束多项式
numer = (fn(X) + 2) * f(g * X) - (4 * fn(X) + 2) * f
alpha = prod([(X - g ** i) for i in range(100)])
p2 = numer / alpha
return p0, p1, p2, fn
// 获取组合多项式
def get_composition_polynomial(p0, p1, p2, ch):
ch.send(mt.root)
// 接收随机系数
alpha0 = ch.receive_random_field_element()
alpha1 = ch.receive_random_field_element()
alpha2 = ch.receive_random_field_element()
// 构造组合多项式
return alpha0 * p0 + alpha1 * p1 + alpha2 * p2
if name == "main":
small_domain_size = 128
large_domain_size = 1024
expect_value_100 = 1555040254
// 计算卡特兰数列
t = calculate_catalan_sequence(small_domain_size, expect_value_100)
// 准备小域G和大域H
G = prepare_domain(small_domain_size)
H = prepare_domain(large_domain_size)
domain = [FieldElement.generator() * x for x in H]
f, ev = interpolate_and_evaluate(G, t, domain)
assert f(G[100]) == expect_value_100
// 构造约束条件
p0, p1, p2, fn = make_constraints(f, G[1], G[0], G[100], expect_value_100)
// 打印约束多项式的度
print(f"deg p0 = {p0.degree()}")
print(f"deg p1 = {p1.degree()}")
print(f"deg p2 = {p2.degree()}")
// 构建Merkle树
mt = MerkleTree(ev)
ch = Channel()
// 获取组合多项式
cp = get_composition_polynomial(p0, p1, p2, ch)
// 打印结果
assert cp(G[111]).val == cp(H[888]).val
print(f'cp(g111): {cp(G[111]).val}')
print(f'cp(h888): {cp(H[888]).val}')
print(f'cp(h**111): {cp(H[111]).val}') |
Beta Was this translation helpful? Give feedback.
-
太难了,之前没有这方面的基础,我尽量在做,也参考了其他人的作业和课件,可能有错误,没必要太参考我的答案 思路导入sagemath库
copy stark101有限域相同设置并计算n=127内catalan数 # 定义有限域的模数
k_modulus = 3 * 2**30 + 1
# 创建有限域 F_(3 * 2**30 + 1)
F = GF(k_modulus, name='a')
def Catalan(pre, n):
return F(2)*(F(2)*n+1)/(n+2)*pre
# 定义一个生成元
generator_val = 5
generator = F(generator_val)
C_0 = F(1)
elements = [C_0]
for i in range(127):
elements.append(Catalan(elements[-1], i))
assert elements[100] == 1555040254 使用lagrange插值得到插值多项式 # 创建多项式环
R = PolynomialRing(F, 'x')
X = R.gen()
def interpolate_poly(x_values, y_values):
"""
Returns a polynomial of degree < len(x_values) that evaluates to y_values[i] on x_values[i] for
all i.
"""
assert len(x_values) == len(y_values)
points = list(zip(x_values, y_values))
poly = R.lagrange_polynomial(points)
return poly
g = generator **((k_modulus - 1)//128)
points = [g**i for i in range(128)]
# 得到插值多项式
f = interpolate_poly(points, elements)
# Catalan约束所需多项式
i = interpolate_poly(points, [F(i) for i in range(128)]) 定义并打印约束,约束是分式形式,需要证明他们都是多项式 # 证明满足多项式的3个约束
# constraint 1
p0 = (f - 1)/ (X - g**0)
# constraint 2
p1 = (f - 1555040254)/ (X - g**100)
prod = 1
for j in range(128):
prod *= (X - g**j)
assert (prod == (X**128 - 1))
# constraint 3
nu = (f(g*X)*(i(X) + 2) - f(X)*(2*(2*i(X) + 1)))
de = (X**128 - 1)/((X - g**127)*(X - g**126))
p2 = nu/de
print(p0)
print(p1)
print(p2)
"""
output:
2241441300*x^126 + 969514308*x^125 + 286576041*x^124 + ...
2241441300*x^126 + 3032696846*x^125 + 3043428958*x^124 + ...
2151462736*x^128 + 1234103371*x^127 + 3011284354*x^126 + ...
""" 转换为证明CP是一个多项式,使用有限域中随机值初始化三个约束,组合起来得到Composition polynomial并在扩展域上验证取值 alpha0 = R.random_element()
alpha1 = R.random_element()
alpha2 = R.random_element()
CP = alpha0*p0 + alpha1*p1 + alpha2*p2
h = generator**((k_modulus - 1)//1024)
print(CP(h**111))
print(CP(h**888))
print(CP(g**111))
assert (CP(g**77) == CP(h**(77*8)))
"""
output:
1304884559
1758307133
1758307133
""" |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Add-on
Stark101课程中前2节主要叙述整个课程所需要的基本组件和算术化过程,为后续FRI打基础。非常抱歉分享的时候出现点小问题,利用 Singleton bound证明RS code的最小汉明距离时脑子有点抽,应该是次数为$k-1$ 的多项式,这里重新推理一下:
考虑RS码的最小汉明距离:$d=\Delta(u,v)$ 。其实是长度为 n 的两个多项式「值向量」的差异。由于RS码的消息(多项式) $p(X)$ 的次数 $\le k-1$ ,根据代数基本定理我们知道,其在 $\mathbb{F}_p$ 上的零点个数也要 $\le k-1$ 。那么在大小为 $n$ 的有限集合上取值,非零点的个数 $\ge n-k+1$ 。于是码字的汉明重量 $w\ge n-k+1$ 。又由于线性码的最小汉明距离和最小汉明重量是等价的,所以码字的汉明最小汉明距离 $d\ge n-k+1$ 。而根据 Singleton Bound $[n,k]$ -线性码的最小汉明距离 $d\le n-k+1$ ,因此 RS 码的最小汉明距离等于 $n-k+1$ 。
(分享的时候误说成$\le k$ 次多项式,因此少了个 + 1。非常抱歉!
这是分享的内容笔记,希望共学的同志和老师们指正,非常感谢!
Quiz
卡特兰数(Catalan number)是一种经典的组合数学问题,它在计算机科学、统计学和物理学等领域中有着广泛的应用。
它的其中一种定义为:有一个大小为$n\times n$ 方格图左下角为
(0, 0)
, 右上角为n, n
,从左下角开始每次都只能向右或者向上走一单位,不走到对角线上方(但可以触碰)的情况下到达右上角有多少可能的路径?递推公式为:
Hint: 注意上述递推公式的 n ,仅在自然数取值时有效。当插值到多项式$f(X)$ 的时候定义域使用的是乘法子群元素,而 $\frac{2(2n+1)}{n+2}$ 部分仍然还是自然数取值,因此此处需要特别处理。
现在,在STARK101 toturial 同样的有限域设置下,Prover 想给 Verifier 证明卡特兰数列第100项的数字为1555040254。请您对上述计算约束做算术化。
文字说明思路,以及给出最终 composition poly 在$h^{111}$ 上的取值 $p(h^{111})$ (或者吉利点 $p(h^{888})$ 也行) 作为 proof of work。(小域 $\langle g\rangle$ size取 128,大域 $\langle h\rangle$ size取 1024)
Beta Was this translation helpful? Give feedback.
All reactions