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.
-
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