#!/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

qs = 400
##Number of masternodes
mn = 5000

##Number of Byzantine nodes assuming 5000 nodes
Bft = [250,500,1000,1500,1700,2000,2500]

##Threshold out of quorum of 400
thresh = 161

for j in range(0,7):
    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
print "\n"

for j in range(0,7):
    print "For ", mn, " masternodes with ", Bft[j],"Byzantine the chance of producing a malicious ChainLock is ", pcalc(mn,qs,thresh,Bft[j])

print "\n"

##quorum size for InstantSend
qs = 50
##Number of masternodes
mn = 5000

##Number of Byzantine nodes assuming 5000 nodes
Bft = [250,500,1000,1500,1700,2000,2500]

##Threshold out of quorum of 400
thresh = 21

for j in range(0,7):
    print "For ", mn, " masternodes with ", Bft[j],"Byzantine the chance of withholding an InstantSend lock in one trial is ", pcalc(mn,qs,thresh,Bft[j])

##Now change the # threshold
thresh = 30
print "\n"

for j in range(0,7):
    print "For ", mn, " masternodes with ", Bft[j],"Byzantine the chance of producing a malicious InstantSend lock is ", pcalc(mn,qs,thresh,Bft[j])