Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F10615286
weierstrass_prover.sage
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Subscribers
None
weierstrass_prover.sage
View Options
# Prover implementation for Weierstrass curves of the form
# y^2 = x^3 + A * x + B, specifically with a = 0 and b = 7, with group laws
# operating on affine and Jacobian coordinates, including the point at infinity
# represented by a 4th variable in coordinates.
load
(
"group_prover.sage"
)
class
affinepoint
:
def
__init__
(
self
,
x
,
y
,
infinity
=
0
):
self
.
x
=
x
self
.
y
=
y
self
.
infinity
=
infinity
def
__str__
(
self
):
return
"affinepoint(x=
%s
,y=
%s
,inf=
%s
)"
%
(
self
.
x
,
self
.
y
,
self
.
infinity
)
class
jacobianpoint
:
def
__init__
(
self
,
x
,
y
,
z
,
infinity
=
0
):
self
.
X
=
x
self
.
Y
=
y
self
.
Z
=
z
self
.
Infinity
=
infinity
def
__str__
(
self
):
return
"jacobianpoint(X=
%s
,Y=
%s
,Z=
%s
,inf=
%s
)"
%
(
self
.
X
,
self
.
Y
,
self
.
Z
,
self
.
Infinity
)
def
point_at_infinity
():
return
jacobianpoint
(
1
,
1
,
1
,
1
)
def
negate
(
p
):
if
p
.
__class__
==
affinepoint
:
return
affinepoint
(
p
.
x
,
-
p
.
y
)
if
p
.
__class__
==
jacobianpoint
:
return
jacobianpoint
(
p
.
X
,
-
p
.
Y
,
p
.
Z
)
assert
(
False
)
def
on_weierstrass_curve
(
A
,
B
,
p
):
"""Return a set of zero-expressions for an affine point to be on the curve"""
return
constraints
(
zero
=
{
p
.
x
^
3
+
A
*
p
.
x
+
B
-
p
.
y
^
2
:
'on_curve'
})
def
tangential_to_weierstrass_curve
(
A
,
B
,
p12
,
p3
):
"""Return a set of zero-expressions for ((x12,y12),(x3,y3)) to be a line that is tangential to the curve at (x12,y12)"""
return
constraints
(
zero
=
{
(
p12
.
y
-
p3
.
y
)
*
(
p12
.
y
*
2
)
-
(
p12
.
x
^
2
*
3
+
A
)
*
(
p12
.
x
-
p3
.
x
):
'tangential_to_curve'
})
def
colinear
(
p1
,
p2
,
p3
):
"""Return a set of zero-expressions for ((x1,y1),(x2,y2),(x3,y3)) to be collinear"""
return
constraints
(
zero
=
{
(
p1
.
y
-
p2
.
y
)
*
(
p1
.
x
-
p3
.
x
)
-
(
p1
.
y
-
p3
.
y
)
*
(
p1
.
x
-
p2
.
x
):
'colinear_1'
,
(
p2
.
y
-
p3
.
y
)
*
(
p2
.
x
-
p1
.
x
)
-
(
p2
.
y
-
p1
.
y
)
*
(
p2
.
x
-
p3
.
x
):
'colinear_2'
,
(
p3
.
y
-
p1
.
y
)
*
(
p3
.
x
-
p2
.
x
)
-
(
p3
.
y
-
p2
.
y
)
*
(
p3
.
x
-
p1
.
x
):
'colinear_3'
})
def
good_affine_point
(
p
):
return
constraints
(
nonzero
=
{
p
.
x
:
'nonzero_x'
,
p
.
y
:
'nonzero_y'
})
def
good_jacobian_point
(
p
):
return
constraints
(
nonzero
=
{
p
.
X
:
'nonzero_X'
,
p
.
Y
:
'nonzero_Y'
,
p
.
Z
^
6
:
'nonzero_Z'
})
def
good_point
(
p
):
return
constraints
(
nonzero
=
{
p
.
Z
^
6
:
'nonzero_X'
})
def
finite
(
p
,
*
affine_fns
):
con
=
good_point
(
p
)
+
constraints
(
zero
=
{
p
.
Infinity
:
'finite_point'
})
if
p
.
Z
!=
0
:
return
con
+
reduce
(
lambda
a
,
b
:
a
+
b
,
(
f
(
affinepoint
(
p
.
X
/
p
.
Z
^
2
,
p
.
Y
/
p
.
Z
^
3
))
for
f
in
affine_fns
),
con
)
else
:
return
con
def
infinite
(
p
):
return
constraints
(
nonzero
=
{
p
.
Infinity
:
'infinite_point'
})
def
law_jacobian_weierstrass_add
(
A
,
B
,
pa
,
pb
,
pA
,
pB
,
pC
):
"""Check whether the passed set of coordinates is a valid Jacobian add, given assumptions"""
assumeLaw
=
(
good_affine_point
(
pa
)
+
good_affine_point
(
pb
)
+
good_jacobian_point
(
pA
)
+
good_jacobian_point
(
pB
)
+
on_weierstrass_curve
(
A
,
B
,
pa
)
+
on_weierstrass_curve
(
A
,
B
,
pb
)
+
finite
(
pA
)
+
finite
(
pB
)
+
constraints
(
nonzero
=
{
pa
.
x
-
pb
.
x
:
'different_x'
}))
require
=
(
finite
(
pC
,
lambda
pc
:
on_weierstrass_curve
(
A
,
B
,
pc
)
+
colinear
(
pa
,
pb
,
negate
(
pc
))))
return
(
assumeLaw
,
require
)
def
law_jacobian_weierstrass_double
(
A
,
B
,
pa
,
pb
,
pA
,
pB
,
pC
):
"""Check whether the passed set of coordinates is a valid Jacobian doubling, given assumptions"""
assumeLaw
=
(
good_affine_point
(
pa
)
+
good_affine_point
(
pb
)
+
good_jacobian_point
(
pA
)
+
good_jacobian_point
(
pB
)
+
on_weierstrass_curve
(
A
,
B
,
pa
)
+
on_weierstrass_curve
(
A
,
B
,
pb
)
+
finite
(
pA
)
+
finite
(
pB
)
+
constraints
(
zero
=
{
pa
.
x
-
pb
.
x
:
'equal_x'
,
pa
.
y
-
pb
.
y
:
'equal_y'
}))
require
=
(
finite
(
pC
,
lambda
pc
:
on_weierstrass_curve
(
A
,
B
,
pc
)
+
tangential_to_weierstrass_curve
(
A
,
B
,
pa
,
negate
(
pc
))))
return
(
assumeLaw
,
require
)
def
law_jacobian_weierstrass_add_opposites
(
A
,
B
,
pa
,
pb
,
pA
,
pB
,
pC
):
assumeLaw
=
(
good_affine_point
(
pa
)
+
good_affine_point
(
pb
)
+
good_jacobian_point
(
pA
)
+
good_jacobian_point
(
pB
)
+
on_weierstrass_curve
(
A
,
B
,
pa
)
+
on_weierstrass_curve
(
A
,
B
,
pb
)
+
finite
(
pA
)
+
finite
(
pB
)
+
constraints
(
zero
=
{
pa
.
x
-
pb
.
x
:
'equal_x'
,
pa
.
y
+
pb
.
y
:
'opposite_y'
}))
require
=
infinite
(
pC
)
return
(
assumeLaw
,
require
)
def
law_jacobian_weierstrass_add_infinite_a
(
A
,
B
,
pa
,
pb
,
pA
,
pB
,
pC
):
assumeLaw
=
(
good_affine_point
(
pa
)
+
good_affine_point
(
pb
)
+
good_jacobian_point
(
pA
)
+
good_jacobian_point
(
pB
)
+
on_weierstrass_curve
(
A
,
B
,
pb
)
+
infinite
(
pA
)
+
finite
(
pB
))
require
=
finite
(
pC
,
lambda
pc
:
constraints
(
zero
=
{
pc
.
x
-
pb
.
x
:
'c.x=b.x'
,
pc
.
y
-
pb
.
y
:
'c.y=b.y'
}))
return
(
assumeLaw
,
require
)
def
law_jacobian_weierstrass_add_infinite_b
(
A
,
B
,
pa
,
pb
,
pA
,
pB
,
pC
):
assumeLaw
=
(
good_affine_point
(
pa
)
+
good_affine_point
(
pb
)
+
good_jacobian_point
(
pA
)
+
good_jacobian_point
(
pB
)
+
on_weierstrass_curve
(
A
,
B
,
pa
)
+
infinite
(
pB
)
+
finite
(
pA
))
require
=
finite
(
pC
,
lambda
pc
:
constraints
(
zero
=
{
pc
.
x
-
pa
.
x
:
'c.x=a.x'
,
pc
.
y
-
pa
.
y
:
'c.y=a.y'
}))
return
(
assumeLaw
,
require
)
def
law_jacobian_weierstrass_add_infinite_ab
(
A
,
B
,
pa
,
pb
,
pA
,
pB
,
pC
):
assumeLaw
=
(
good_affine_point
(
pa
)
+
good_affine_point
(
pb
)
+
good_jacobian_point
(
pA
)
+
good_jacobian_point
(
pB
)
+
infinite
(
pA
)
+
infinite
(
pB
))
require
=
infinite
(
pC
)
return
(
assumeLaw
,
require
)
laws_jacobian_weierstrass
=
{
'add'
:
law_jacobian_weierstrass_add
,
'double'
:
law_jacobian_weierstrass_double
,
'add_opposite'
:
law_jacobian_weierstrass_add_opposites
,
'add_infinite_a'
:
law_jacobian_weierstrass_add_infinite_a
,
'add_infinite_b'
:
law_jacobian_weierstrass_add_infinite_b
,
'add_infinite_ab'
:
law_jacobian_weierstrass_add_infinite_ab
}
def
check_exhaustive_jacobian_weierstrass
(
name
,
A
,
B
,
branches
,
formula
,
p
):
"""Verify an implementation of addition of Jacobian points on a Weierstrass curve, by executing and validating the result for every possible addition in a prime field"""
F
=
Integers
(
p
)
print
(
"Formula
%s
on Z
%i
:"
%
(
name
,
p
))
points
=
[]
for
x
in
range
(
0
,
p
):
for
y
in
range
(
0
,
p
):
point
=
affinepoint
(
F
(
x
),
F
(
y
))
r
,
e
=
concrete_verify
(
on_weierstrass_curve
(
A
,
B
,
point
))
if
r
:
points
.
append
(
point
)
for
za
in
range
(
1
,
p
):
for
zb
in
range
(
1
,
p
):
for
pa
in
points
:
for
pb
in
points
:
for
ia
in
range
(
2
):
for
ib
in
range
(
2
):
pA
=
jacobianpoint
(
pa
.
x
*
F
(
za
)
^
2
,
pa
.
y
*
F
(
za
)
^
3
,
F
(
za
),
ia
)
pB
=
jacobianpoint
(
pb
.
x
*
F
(
zb
)
^
2
,
pb
.
y
*
F
(
zb
)
^
3
,
F
(
zb
),
ib
)
for
branch
in
range
(
0
,
branches
):
assumeAssert
,
assumeBranch
,
pC
=
formula
(
branch
,
pA
,
pB
)
pC
.
X
=
F
(
pC
.
X
)
pC
.
Y
=
F
(
pC
.
Y
)
pC
.
Z
=
F
(
pC
.
Z
)
pC
.
Infinity
=
F
(
pC
.
Infinity
)
r
,
e
=
concrete_verify
(
assumeAssert
+
assumeBranch
)
if
r
:
match
=
False
for
key
in
laws_jacobian_weierstrass
:
assumeLaw
,
require
=
laws_jacobian_weierstrass
[
key
](
A
,
B
,
pa
,
pb
,
pA
,
pB
,
pC
)
r
,
e
=
concrete_verify
(
assumeLaw
)
if
r
:
if
match
:
print
(
" multiple branches for (
%s
,
%s
,
%s
,
%s
) + (
%s
,
%s
,
%s
,
%s
)"
%
(
pA
.
X
,
pA
.
Y
,
pA
.
Z
,
pA
.
Infinity
,
pB
.
X
,
pB
.
Y
,
pB
.
Z
,
pB
.
Infinity
))
else
:
match
=
True
r
,
e
=
concrete_verify
(
require
)
if
not
r
:
print
(
" failure in branch
%i
for (
%s
,
%s
,
%s
,
%s
) + (
%s
,
%s
,
%s
,
%s
) = (
%s
,
%s
,
%s
,
%s
):
%s
"
%
(
branch
,
pA
.
X
,
pA
.
Y
,
pA
.
Z
,
pA
.
Infinity
,
pB
.
X
,
pB
.
Y
,
pB
.
Z
,
pB
.
Infinity
,
pC
.
X
,
pC
.
Y
,
pC
.
Z
,
pC
.
Infinity
,
e
))
print
()
def
check_symbolic_function
(
R
,
assumeAssert
,
assumeBranch
,
f
,
A
,
B
,
pa
,
pb
,
pA
,
pB
,
pC
):
assumeLaw
,
require
=
f
(
A
,
B
,
pa
,
pb
,
pA
,
pB
,
pC
)
return
check_symbolic
(
R
,
assumeLaw
,
assumeAssert
,
assumeBranch
,
require
)
def
check_symbolic_jacobian_weierstrass
(
name
,
A
,
B
,
branches
,
formula
):
"""Verify an implementation of addition of Jacobian points on a Weierstrass curve symbolically"""
R
.<
ax
,
bx
,
ay
,
by
,
Az
,
Bz
,
Ai
,
Bi
>
=
PolynomialRing
(
QQ
,
8
,
order
=
'invlex'
)
lift
=
lambda
x
:
fastfrac
(
R
,
x
)
ax
=
lift
(
ax
)
ay
=
lift
(
ay
)
Az
=
lift
(
Az
)
bx
=
lift
(
bx
)
by
=
lift
(
by
)
Bz
=
lift
(
Bz
)
Ai
=
lift
(
Ai
)
Bi
=
lift
(
Bi
)
pa
=
affinepoint
(
ax
,
ay
,
Ai
)
pb
=
affinepoint
(
bx
,
by
,
Bi
)
pA
=
jacobianpoint
(
ax
*
Az
^
2
,
ay
*
Az
^
3
,
Az
,
Ai
)
pB
=
jacobianpoint
(
bx
*
Bz
^
2
,
by
*
Bz
^
3
,
Bz
,
Bi
)
res
=
{}
for
key
in
laws_jacobian_weierstrass
:
res
[
key
]
=
[]
print
(
"Formula "
+
name
+
":"
)
count
=
0
for
branch
in
range
(
branches
):
assumeFormula
,
assumeBranch
,
pC
=
formula
(
branch
,
pA
,
pB
)
pC
.
X
=
lift
(
pC
.
X
)
pC
.
Y
=
lift
(
pC
.
Y
)
pC
.
Z
=
lift
(
pC
.
Z
)
pC
.
Infinity
=
lift
(
pC
.
Infinity
)
for
key
in
laws_jacobian_weierstrass
:
res
[
key
]
.
append
((
check_symbolic_function
(
R
,
assumeFormula
,
assumeBranch
,
laws_jacobian_weierstrass
[
key
],
A
,
B
,
pa
,
pb
,
pA
,
pB
,
pC
),
branch
))
for
key
in
res
:
print
(
"
%s
:"
%
key
)
val
=
res
[
key
]
for
x
in
val
:
if
x
[
0
]
is
not
None
:
print
(
" branch
%i
:
%s
"
%
(
x
[
1
],
x
[
0
]))
print
()
File Metadata
Details
Attached
Mime Type
text/x-python
Expires
Sat, Nov 23, 10:03 (23 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4559233
Default Alt Text
weierstrass_prover.sage (9 KB)
Attached To
rSTAGING Bitcoin ABC staging
Event Timeline
Log In to Comment