dips/dip-0008/quorum_attack.py
Darren Tapp 55aa78cd1e Security Analysis (#55)
* This adds two sections to dip 0008.  The first section considers the security of Chain Locks and provides the calculations needed to evaluate the security.  The second added sections provides mitigations of situtaions when
attackers do not own the collatoral of the masternodes.

* Update dip-0008.md

* Fix hyperlinks

* Update dip-0008.md

* Update dip-0008.md

correction of word.

Co-Authored-By: UdjinM6 <UdjinM6@users.noreply.github.com>

* Update dip-0008.md

Need to make sure it's always big choose small.

Co-Authored-By: UdjinM6 <UdjinM6@users.noreply.github.com>

* Fixes inconsistantcy in gifs

* Update dip-0008/quorum_attack.py

fix tpyo

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008/quorum_attack.py

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008.md

Changing titles, todo change table.

Co-Authored-By: UdjinM6 <UdjinM6@users.noreply.github.com>

* Clarify table

This handles the edge case of witholding a ChainLock correctly, it takes 161 nodes to withold a ChainLock.
Also makes table clearer to read.

* Clarify malicious chainlock

Based on suggestions from AndyFreer a second paragraph is added to explain what can go wrong.

* Update dip-0008.md

Add line break.

Co-Authored-By: UdjinM6 <UdjinM6@users.noreply.github.com>

* Apply suggestions of thephez

The calculations were updated to refelct the fact that 161 masternodes are needed to withhold a chainlock
in a previous commit.  This commit updates the text and displayed formulas to reflect this fact.

We also alert the reader that we assume that all uncompromised nodes are behaiving as expected.  We include the effect of relaxing this
assumption, however the calculations are left to the reader.  The python function provided makes it easy.

* Fix two typos

* Update dip-0008.md

one missed 160->161

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008.md

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Correct C size in sumation formula

* Update dip-0008/quorum_attack.py

correct spelling

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008/quorum_attack.py

correct spelling

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008/quorum_attack.py

correct spelling

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008/quorum_attack.py

correct spelling

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008/quorum_attack.py

correct spelling

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008/quorum_attack.py

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008/quorum_attack.py

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008/quorum_attack.py

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008/quorum_attack.py

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008/quorum_attack.py

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008/quorum_attack.py

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008/quorum_attack.py

Co-Authored-By: thephez <thephez@users.noreply.github.com>

* Update dip-0008/quorum_attack.py

Co-Authored-By: thephez <thephez@users.noreply.github.com>

Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
Co-authored-by: thephez <thephez@users.noreply.github.com>
2020-01-02 13:43:01 -05:00

107 lines
3.4 KiB
Python
Executable file

#!/usr/bin/python
#This script was written by Darren Tapp and optimized by thephez
from decimal import Decimal
from math import log
from math import factorial as fac
from math import log1p
from math import exp
def binom(x, y):
try:
binom = fac(x) // fac(y) // fac(x - y)
except ValueError:
binom = 0
return binom
###This function takes inputs and outputs the probability
#of success in one trial
#pcalc is short for probability calculation
def pcalc(masternodes,quorumsize,attacksuccess,Byznodes):
SampleSpace = binom(masternodes,quorumsize)
pctemp=0
for x in range(attacksuccess, quorumsize+1):
pctemp = pctemp + binom(Byznodes,x)*binom(masternodes-Byznodes,quorumsize-x)
#at this juncture the answer is pctemp/SampleSpace
#but that will produce an overflow error. We use logarithms to
#calculate this value
return 10 ** (log(pctemp,10)- log(SampleSpace,10))
#Takes the probability of success in one trial and outputs the probability of success in 730 septillion trials
#730 septillion trials requires a septillion years of masternode quorum formation.
def ZettaYear(probability):
trials = 2*365*10 ** 21
return 1-exp(trials * log1p(-probability))
def MegaYear(probability):
trials = 2*365*10 ** 6
return 1-exp(trials * log1p(-probability))
##We evaluate the function pcalc(10,5,3,4)
##print pcalc(10,5,3,4)
##as a test vector
##The answer would be [binom(3,4)*binom(2,6)+(binom(4,4)*binom(1,6)]/binom(10,5)
##[4*15+1*6]/252 = 66/252
##print float(66)/252
##quorum size for ChainLocks
qs = 400
##Number of masternodes
mn = 5000
##Number of Byzantine nodes assuming 5000 nodes
Bft = [500,1000,1500]
##Threshold out of quorum of 400
thresh = 161
for j in range(0,3):
print "For ", mn, " masternodes with ", Bft[j],"Byzantine the chance of withholding a ChainLock in one trial is ", pcalc(mn,qs,thresh,Bft[j])
##Now change the # threshold
thresh = 240
for j in range(0,3):
print "For ", mn, " masternodes with ", Bft[j],"Byzantine the chance of producing a malicious ChainLock is ", pcalc(mn,qs,thresh,Bft[j])
#In the case of a smaller number of masternodes
mn=2000
##Number of Byzantine nodes assuming 2000 nodes
Bft = [240,400,600]
##Threshold out of quorum of 400
thresh = 161
for j in range(0,3):
print "For ", mn, " masternodes with ", Bft[j],"Byzantine the chance of withholding a ChainLock in one trial is ", pcalc(mn,qs,thresh,Bft[j])
##Now change the # threshold
thresh = 240
for j in range(0,3):
print "For ", mn, " masternodes with ", Bft[j],"Byzantine the chance of producing a malicious ChainLock is ", pcalc(mn,qs,thresh,Bft[j])
print "Security interpretation:"
print "For 5000 masternodes with 1500 Byzantine nodes the chance of producing a malicious ChainLock is ", pcalc(5000,400,240,1500)
print "Which means in a Zettayear the chances of a "
print "malicious chainlock is ", ZettaYear(pcalc(5000,400,240,1500))
print "In an extreme case the chance of quorum control with 40% of nodes:"
print "5000 Masternodes ", pcalc(5000,400,240,2000)
print "2000 Masternodes ", pcalc(2000,400,240,800)
print "In an even more extreme case the chance of quorum control with 50% of nodes:"
print "5000 Masternodes ", pcalc(5000,400,240,2500)
print "2000 Masternodes ", pcalc(2000,400,240,1000)
print MegaYear(pcalc(5000,400,240,2000))
print "For 2000 total nodes with 200 attacking , the chance of withholding a ChainLock is,", pcalc(2000,400,161,200)