From 6978ce98d4a9eb3baf106df001e5cfc0a11aa3fa Mon Sep 17 00:00:00 2001 From: Vitalik Buterin Date: Sat, 6 Sep 2014 23:00:50 -0400 Subject: [PATCH] Added slasher exploit --- erasure_code/share.py | 34 +++++++++++++++++++++++++++ slasher_withholding_exploit.py | 43 ++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 slasher_withholding_exploit.py diff --git a/erasure_code/share.py b/erasure_code/share.py index 2d8bf45..37e154c 100644 --- a/erasure_code/share.py +++ b/erasure_code/share.py @@ -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 diff --git a/slasher_withholding_exploit.py b/slasher_withholding_exploit.py new file mode 100644 index 0000000..16e94f5 --- /dev/null +++ b/slasher_withholding_exploit.py @@ -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