Skip to content

Instantly share code, notes, and snippets.

@tomasvdw
Created April 11, 2018 09:30
Show Gist options
  • Save tomasvdw/73504065c3baa7e8c9701f7893e43290 to your computer and use it in GitHub Desktop.
Save tomasvdw/73504065c3baa7e8c9701f7893e43290 to your computer and use it in GitHub Desktop.
Selfish mining simulator
# Simulation of Selfish mining with gamma=0
# gamma=0 assumes a nearly full connected topology.
# We simulate a selfish pool p and h who mines honest
# As Gamma=0, we do not need to simulate more then two miners
# Tomas van der Wansem
import random;
ROUNDS = 10000000
# size of pool relative to total
ALPHA = 0.39
# difficulty factor; reduces blocks found at the same time
DIFF = 0.01
class State:
def __init__(self, selfish):
# pool gains and honest gains
self.p_gains = 0
self.h_gains = 0
# blockcount of pool and honest chains
self.p_len = 0
self.h_len = 0
# the number of blocks shared between the two chains
self.shared_len = 0
self.selfish = selfish
# Execute a single round
# where both h and p attempt to find a block
# and try to propagate
def find_hash(self, r_h, r_p):
# update both chains and assume gains until blocks are staled
if r_p < ALPHA * DIFF:
self.p_gains += 1
self.p_len += 1
if r_h < (1 - ALPHA) * DIFF:
self.h_gains += 1
self.h_len += 1
if self.selfish:
self.propagate_selfish()
else:
self.propagate_honest()
# p and h are both honest.
# Used for comparison
def propagate_honest(self):
if self.p_len > self.h_len:
# publish
# stale blocks reduce gain
self.h_gains -= (self.h_len - self.shared_len)
self.h_len = self.p_len
self.shared_len = self.p_len
elif self.h_len > self.p_len:
# publish
# stale blocks reduce gain
self.p_gains -= (self.p_len - self.shared_len)
self.p_len = self.h_len
self.shared_len = self.h_len
else:
# two chains competing
pass
# Selfish mining; from algorithm 1 of the paper
def propagate_selfish(self):
if self.p_len > self.h_len:
if self.shared_len < self.h_len:
# we had two competing chains which we now overtook
# publish
# stale blocks reduce gain
self.h_gains -= (self.h_len - self.shared_len)
self.h_len = self.p_len
self.shared_len = self.p_len
else:
# Don't publish our block as we are selfish
pass
elif self.h_len > self.p_len:
# honest miners win
# orphaned blocks reduce gain
self.p_gains -= (self.p_len - self.shared_len)
self.p_len = self.h_len
self.shared_len = self.h_len
else:
# two chains competing
pass
s_h = State(False)
s_s = State(True)
for i in range(0,ROUNDS):
r_h = random.random()
r_p = random.random()
s_s.find_hash(r_h,r_p)
s_h.find_hash(r_h,r_p)
print "Selfish"
print "p_gain = " + str(s_s.p_gains)
print "h_gain = " + str(s_s.h_gains)
print "p_gain = " + str(s_s.p_gains/float(s_s.p_gains+s_s.h_gains))
print "Honest"
print "p_gain = " + str(s_h.p_gains)
print "h_gain = " + str(s_h.h_gains)
print "p_gain = " + str(s_h.p_gains/float(s_h.p_gains+s_h.h_gains))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment