Made pairing impl python3-friendly

This commit is contained in:
vub 2017-02-07 08:39:28 -05:00
parent 2d1dd0227b
commit 00b990d219
5 changed files with 48 additions and 24 deletions

View File

@ -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)

View File

@ -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))

View File

@ -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):

View File

@ -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):

View File

@ -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')