mirror of
https://github.com/status-im/research.git
synced 2025-01-12 16:14:08 +00:00
Added slasher exploit
This commit is contained in:
parent
bf111a8bd9
commit
6978ce98d4
@ -94,6 +94,40 @@ class Galois:
|
||||
def __repr__(self):
|
||||
return repr(self.val)
|
||||
|
||||
|
||||
# Modular division class
|
||||
|
||||
def mkModuloClass(n):
|
||||
|
||||
if pow(2, n, n) != 2:
|
||||
raise Exception("n must be prime!")
|
||||
|
||||
class Mod:
|
||||
val = 0
|
||||
|
||||
def __init__(self, val):
|
||||
self.val = val.val if isinstance(
|
||||
self.val, self.__class__) else val
|
||||
|
||||
def __add__(self, other):
|
||||
return self.__class__((self.val + other.val) % n)
|
||||
|
||||
def __mul__(self, other):
|
||||
return self.__class__((self.val * other.val) % n)
|
||||
|
||||
def __sub__(self, other):
|
||||
return self.__class__((self.val - other.val) % n)
|
||||
|
||||
def __div__(self, other):
|
||||
return self.__class__((self.val * other.val ** (n-2)) % n)
|
||||
|
||||
def __int__(self):
|
||||
return self.val
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self.val)
|
||||
return Mod
|
||||
|
||||
# Evaluates a polynomial in little-endian form, eg. x^2 + 3x + 2 = [2, 3, 1]
|
||||
# (normally I hate little-endian, but in this case dealing with polynomials
|
||||
# it's justified, since you get the nice property that p[n] is the nth degree
|
||||
|
43
slasher_withholding_exploit.py
Normal file
43
slasher_withholding_exploit.py
Normal file
@ -0,0 +1,43 @@
|
||||
def fac(n): return 1 if n==0 else n * fac(n-1)
|
||||
def choose(n,k): return fac(n) / fac(k) / fac(n-k)
|
||||
def prob(n,k,p): return choose(n,k) * p ** k * (1-p) ** (n-k)
|
||||
|
||||
def prob_lt(n,k,p): return sum([prob(n,i,p) for i in range(p)])
|
||||
|
||||
SIGS = 30
|
||||
ACTUALSIGS = 10
|
||||
POWRETURN = 0.03
|
||||
POSRETURN = 0.01
|
||||
|
||||
# Expected number of signatures on a block
|
||||
def ev(pos):
|
||||
return SIGS * pos
|
||||
|
||||
# Chance you have at least k sigs
|
||||
def at_least_k(pos, k):
|
||||
return sum([prob(SIGS, i, pos) for i in range(k, SIGS + 1)])
|
||||
|
||||
# Expected number of signatures on a block filtering all <k
|
||||
def ev_atleast_k(pos, k):
|
||||
total, subprob = 0, 0
|
||||
for i in range(k, SIGS + 1):
|
||||
p = prob(SIGS, i, pos)
|
||||
subprob += p
|
||||
total += i * p
|
||||
return total / subprob
|
||||
|
||||
def normal_mining_return(pow, pos):
|
||||
return pow * POWRETURN + ev(pos) * POSRETURN / ACTUALSIGS
|
||||
|
||||
def attack_mining_return(pow, pos, k):
|
||||
powtotal, postotal, subprob = 0, 0, 0
|
||||
# Case 1: mined PoW block, PoS at least k instances
|
||||
case_1_prob = pow * at_least_k(pos, k)
|
||||
subprob += case_1_prob
|
||||
postotal += case_1_prob * ev_atleast_k(pos, k) * POSRETURN / ACTUALSIGS
|
||||
powtotal += case_1_prob * POWRETURN
|
||||
# Case 2: mined PoW block, PoS less than k: discard
|
||||
# Case 3: others mined PoW block
|
||||
subprob += (1 - pow)
|
||||
postotal += (1 - pow) * ev(pos) * POSRETURN / ACTUALSIGS
|
||||
return powtotal / subprob + postotal / subprob
|
Loading…
x
Reference in New Issue
Block a user