Made pairing impl python3-friendly
This commit is contained in:
parent
2d1dd0227b
commit
00b990d219
|
@ -2,14 +2,16 @@
|
||||||
# in the randao-based single-chain Casper.
|
# in the randao-based single-chain Casper.
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
# Reward for mining a block with nonzero skips
|
||||||
|
NON_PRIMARY_REWARD = 0.5
|
||||||
# Penalty for mining a dunkle
|
# Penalty for mining a dunkle
|
||||||
DUNKLE_PENALTY = 1
|
DUNKLE_PENALTY = 0.75
|
||||||
# Penalty to a main-chain block which has a dunkle as a sister
|
# Penalty to a main-chain block which has a dunkle as a sister
|
||||||
DUNKLE_SISTER_PENALTY = 0.8
|
DUNKLE_SISTER_PENALTY = 0.375
|
||||||
|
|
||||||
# Attacker stake power (out of 100). Try setting this value to any
|
# Attacker stake power (out of 100). Try setting this value to any
|
||||||
# amount, even values above 50!
|
# amount, even values above 50!
|
||||||
attacker_share = 40
|
attacker_share = 60
|
||||||
|
|
||||||
# A simulated Casper randao
|
# A simulated Casper randao
|
||||||
def randao_successor(parent, index):
|
def randao_successor(parent, index):
|
||||||
|
@ -78,7 +80,7 @@ class Chain():
|
||||||
self.randao = new_randao
|
self.randao = new_randao
|
||||||
self.time += skips
|
self.time += skips
|
||||||
self.length += 1
|
self.length += 1
|
||||||
self.me += 1
|
self.me += NON_PRIMARY_REWARD if skips else 1
|
||||||
|
|
||||||
def extend_them(self, skips):
|
def extend_them(self, skips):
|
||||||
new_randao = randao_successor(self.randao, skips)
|
new_randao = randao_successor(self.randao, skips)
|
||||||
|
@ -86,7 +88,7 @@ class Chain():
|
||||||
self.randao = new_randao
|
self.randao = new_randao
|
||||||
self.time += skips
|
self.time += skips
|
||||||
self.length += 1
|
self.length += 1
|
||||||
self.them += 1
|
self.them += NON_PRIMARY_REWARD if skips else 1
|
||||||
|
|
||||||
def add_my_dunkles(self, n):
|
def add_my_dunkles(self, n):
|
||||||
self.me -= n * DUNKLE_PENALTY
|
self.me -= n * DUNKLE_PENALTY
|
||||||
|
@ -96,7 +98,8 @@ class Chain():
|
||||||
self.them -= n * DUNKLE_PENALTY
|
self.them -= n * DUNKLE_PENALTY
|
||||||
self.me -= n * DUNKLE_SISTER_PENALTY
|
self.me -= n * DUNKLE_SISTER_PENALTY
|
||||||
|
|
||||||
|
my_total_loss = 0
|
||||||
|
their_total_loss = 0
|
||||||
|
|
||||||
for strat_id in range(2**len(scenarios)):
|
for strat_id in range(2**len(scenarios)):
|
||||||
# Strategy map: scenario to 0 = publish, 1 = selfish-validate
|
# Strategy map: scenario to 0 = publish, 1 = selfish-validate
|
||||||
|
@ -105,7 +108,7 @@ for strat_id in range(2**len(scenarios)):
|
||||||
# 0 = don't reveal until the "main chain" looks like it's close to catching up
|
# 0 = don't reveal until the "main chain" looks like it's close to catching up
|
||||||
insta_reveal = strat_id % 2
|
insta_reveal = strat_id % 2
|
||||||
|
|
||||||
print 'Testing strategy: %r, insta_reveal: %d', (strategy, insta_reveal)
|
print 'Testing strategy: %r, insta_reveal: %d' % (strategy, insta_reveal)
|
||||||
|
|
||||||
pubchain = Chain(randao=random.randrange(10**20))
|
pubchain = Chain(randao=random.randrange(10**20))
|
||||||
|
|
||||||
|
@ -167,5 +170,11 @@ for strat_id in range(2**len(scenarios)):
|
||||||
pass
|
pass
|
||||||
# print 'Score deltas: me %.2f them %.2f, time delta %d' % (pubchain.me - old_me, pubchain.them - old_them, time - old_time)
|
# print 'Score deltas: me %.2f them %.2f, time delta %d' % (pubchain.me - old_me, pubchain.them - old_them, time - old_time)
|
||||||
|
|
||||||
gf = (pubchain.them - 100000. * (100 - attacker_share) / 100) / (pubchain.me - 100000 * attacker_share / 100)
|
my_loss = 100000 * attacker_share / 100 - pubchain.me
|
||||||
|
their_loss = 100000 * (100 - attacker_share) / 100 - pubchain.them
|
||||||
|
my_total_loss += my_loss
|
||||||
|
their_total_loss += their_loss
|
||||||
|
gf = their_loss / my_loss if my_loss > 0 else 999.99
|
||||||
print 'My revenue: %d, their revenue: %d, griefing factor %.2f' % (pubchain.me, pubchain.them, gf)
|
print 'My revenue: %d, their revenue: %d, griefing factor %.2f' % (pubchain.me, pubchain.them, gf)
|
||||||
|
|
||||||
|
print 'Total griefing factor: %.2f' % (their_total_loss / my_total_loss)
|
||||||
|
|
|
@ -17,8 +17,8 @@ b12 = FQ12([3] + [0] * 11)
|
||||||
# Generator for curve over FQ
|
# Generator for curve over FQ
|
||||||
G1 = (FQ(1), FQ(2))
|
G1 = (FQ(1), FQ(2))
|
||||||
# Generator for twisted curve over FQ2
|
# Generator for twisted curve over FQ2
|
||||||
G2 = (FQ2([16260673061341949275257563295988632869519996389676903622179081103440260644990L, 11559732032986387107991004021392285783925812861821192530917403151452391805634L]),
|
G2 = (FQ2([16260673061341949275257563295988632869519996389676903622179081103440260644990, 11559732032986387107991004021392285783925812861821192530917403151452391805634]),
|
||||||
FQ2([15530828784031078730107954109694902500959150953518636601196686752670329677317L, 4082367875863433681332203403145435568316851327593401208105741076214120093531L]))
|
FQ2([15530828784031078730107954109694902500959150953518636601196686752670329677317, 4082367875863433681332203403145435568316851327593401208105741076214120093531]))
|
||||||
|
|
||||||
# Check that a point is on the curve defined by y**2 == x**3 + b
|
# Check that a point is on the curve defined by y**2 == x**3 + b
|
||||||
def is_on_curve(pt, b):
|
def is_on_curve(pt, b):
|
||||||
|
@ -62,9 +62,9 @@ def multiply(pt, n):
|
||||||
elif n == 1:
|
elif n == 1:
|
||||||
return pt
|
return pt
|
||||||
elif not n % 2:
|
elif not n % 2:
|
||||||
return multiply(double(pt), n / 2)
|
return multiply(double(pt), n // 2)
|
||||||
else:
|
else:
|
||||||
return add(multiply(double(pt), int(n / 2)), pt)
|
return add(multiply(double(pt), int(n // 2)), pt)
|
||||||
|
|
||||||
# Check that the G1 curve works fine
|
# Check that the G1 curve works fine
|
||||||
assert add(add(double(G1), G1), G1) == double(double(G1))
|
assert add(add(double(G1), G1), G1) == double(double(G1))
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
import sys
|
import sys
|
||||||
sys.setrecursionlimit(10000)
|
sys.setrecursionlimit(10000)
|
||||||
|
|
||||||
|
# python3 compatibility
|
||||||
|
try:
|
||||||
|
foo = long
|
||||||
|
except:
|
||||||
|
long = int
|
||||||
|
|
||||||
# The prime modulus of the field
|
# The prime modulus of the field
|
||||||
field_modulus = 21888242871839275222246405745257275088696311157297823662689037894645226208583
|
field_modulus = 21888242871839275222246405745257275088696311157297823662689037894645226208583
|
||||||
# See, it's prime!
|
# See, it's prime!
|
||||||
|
@ -61,20 +67,26 @@ class FQ():
|
||||||
assert isinstance(on, (int, long))
|
assert isinstance(on, (int, long))
|
||||||
return FQ(self.n * inv(on, field_modulus) % field_modulus)
|
return FQ(self.n * inv(on, field_modulus) % field_modulus)
|
||||||
|
|
||||||
|
def __truediv__(self, other):
|
||||||
|
return self.__div__(other)
|
||||||
|
|
||||||
def __rdiv__(self, other):
|
def __rdiv__(self, other):
|
||||||
on = other.n if isinstance(other, FQ) else other
|
on = other.n if isinstance(other, FQ) else other
|
||||||
assert isinstance(on, (int, long)), on
|
assert isinstance(on, (int, long)), on
|
||||||
return FQ(inv(self.n, field_modulus) * on % field_modulus)
|
return FQ(inv(self.n, field_modulus) * on % field_modulus)
|
||||||
|
|
||||||
|
def __rtruediv__(self, other):
|
||||||
|
return self.__rdiv__(other)
|
||||||
|
|
||||||
def __pow__(self, other):
|
def __pow__(self, other):
|
||||||
if other == 0:
|
if other == 0:
|
||||||
return FQ(1)
|
return FQ(1)
|
||||||
elif other == 1:
|
elif other == 1:
|
||||||
return FQ(self.n)
|
return FQ(self.n)
|
||||||
elif other % 2 == 0:
|
elif other % 2 == 0:
|
||||||
return (self * self) ** (other / 2)
|
return (self * self) ** (other // 2)
|
||||||
else:
|
else:
|
||||||
return ((self * self) ** int(other / 2)) * self
|
return ((self * self) ** int(other // 2)) * self
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, FQ):
|
if isinstance(other, FQ):
|
||||||
|
@ -166,15 +178,18 @@ class FQP():
|
||||||
assert isinstance(other, self.__class__)
|
assert isinstance(other, self.__class__)
|
||||||
return self * other.inv()
|
return self * other.inv()
|
||||||
|
|
||||||
|
def __truediv__(self, other):
|
||||||
|
return self.__div__(other)
|
||||||
|
|
||||||
def __pow__(self, other):
|
def __pow__(self, other):
|
||||||
if other == 0:
|
if other == 0:
|
||||||
return self.__class__([1] + [0] * (self.degree - 1))
|
return self.__class__([1] + [0] * (self.degree - 1))
|
||||||
elif other == 1:
|
elif other == 1:
|
||||||
return self.__class__(self.coeffs)
|
return self.__class__(self.coeffs)
|
||||||
elif other % 2 == 0:
|
elif other % 2 == 0:
|
||||||
return (self * self) ** (other / 2)
|
return (self * self) ** (other // 2)
|
||||||
else:
|
else:
|
||||||
return ((self * self) ** int(other / 2)) * self
|
return ((self * self) ** int(other // 2)) * self
|
||||||
|
|
||||||
# Extended euclidean algorithm used to find the modular inverse
|
# Extended euclidean algorithm used to find the modular inverse
|
||||||
def inv(self):
|
def inv(self):
|
||||||
|
|
|
@ -62,7 +62,7 @@ def miller_loop(Q, P):
|
||||||
R = add(R, Q1)
|
R = add(R, Q1)
|
||||||
f = f * linefunc(R, nQ2, P)
|
f = f * linefunc(R, nQ2, P)
|
||||||
# R = add(R, nQ2) This line is in many specifications but it technically does nothing
|
# R = add(R, nQ2) This line is in many specifications but it technically does nothing
|
||||||
return f ** ((field_modulus ** 12 - 1) / curve_order)
|
return f ** ((field_modulus ** 12 - 1) // curve_order)
|
||||||
|
|
||||||
# Pairing computation
|
# Pairing computation
|
||||||
def pairing(Q, P):
|
def pairing(Q, P):
|
||||||
|
|
|
@ -3,22 +3,22 @@ from bn128_pairing import pairing, neg, G2, G1, multiply, FQ12, curve_order
|
||||||
p1 = pairing(G2, G1)
|
p1 = pairing(G2, G1)
|
||||||
pn1 = pairing(G2, neg(G1))
|
pn1 = pairing(G2, neg(G1))
|
||||||
assert p1 * pn1 == FQ12.one()
|
assert p1 * pn1 == FQ12.one()
|
||||||
print 'Pairing check against negative in G1 passed'
|
print('Pairing check against negative in G1 passed')
|
||||||
np1 = pairing(neg(G2), G1)
|
np1 = pairing(neg(G2), G1)
|
||||||
assert p1 * np1 == FQ12.one()
|
assert p1 * np1 == FQ12.one()
|
||||||
assert pn1 == np1
|
assert pn1 == np1
|
||||||
print 'Pairing check against negative in G2 passed'
|
print('Pairing check against negative in G2 passed')
|
||||||
assert p1 ** curve_order == FQ12.one()
|
assert p1 ** curve_order == FQ12.one()
|
||||||
print 'Pairing output has correct order'
|
print('Pairing output has correct order')
|
||||||
p2 = pairing(G2, multiply(G1, 2))
|
p2 = pairing(G2, multiply(G1, 2))
|
||||||
assert p1 * p1 == p2
|
assert p1 * p1 == p2
|
||||||
print 'Pairing bilinearity in G1 passed'
|
print('Pairing bilinearity in G1 passed')
|
||||||
assert p1 != p2 and p1 != np1 and p2 != np1
|
assert p1 != p2 and p1 != np1 and p2 != np1
|
||||||
print 'Pairing is non-degenerate'
|
print('Pairing is non-degenerate')
|
||||||
po2 = pairing(multiply(G2, 2), G1)
|
po2 = pairing(multiply(G2, 2), G1)
|
||||||
assert p1 * p1 == po2
|
assert p1 * p1 == po2
|
||||||
print 'Pairing bilinearity in G2 passed'
|
print('Pairing bilinearity in G2 passed')
|
||||||
p3 = pairing(multiply(G2, 27), multiply(G1, 37))
|
p3 = pairing(multiply(G2, 27), multiply(G1, 37))
|
||||||
po3 = pairing(G2, multiply(G1, 999))
|
po3 = pairing(G2, multiply(G1, 999))
|
||||||
assert p3 == po3
|
assert p3 == po3
|
||||||
print 'Composite check passed'
|
print('Composite check passed')
|
||||||
|
|
Loading…
Reference in New Issue