Skip to content

Instantly share code, notes, and snippets.

@JeremyRubin
Created February 12, 2021 21:05
Show Gist options
  • Save JeremyRubin/9c25b3a947661ea297824dbf18decac5 to your computer and use it in GitHub Desktop.
Save JeremyRubin/9c25b3a947661ea297824dbf18decac5 to your computer and use it in GitHub Desktop.
import numpy as np
TRIALS = 10000
MARS_DIST_LIGHT_MINUTES_MAX = 22
RTT = MARS_DIST_LIGHT_MINUTES_MAX*60*2
gen = lambda mins: list(np.round(np.random.exponential(mins*60, TRIALS)))
# Assume miner_1 has 50% hashrate and miner_2 has 50%... find blocks every 20 mins each
# alternative: Assume miner_1 has 90% and miner_2 has 10%... find blocks 10/0.9 and 10/0.1
miner_1 = gen(10/0.5)
miner_2 = gen(10/0.5)
SECONDS = int(60*10*TRIALS*2)
log = [[(None, None), (None, None)] for x in range(SECONDS)]
height_1 = 0
height_2 = 0
time = list(range(SECONDS))
height_at_time_1 = [0]*SECONDS
height_at_time_2 = [0]*SECONDS
blocks_1 = [None]*TRIALS
blocks_2 = [None]*TRIALS
m_1_streak = 0
m_2_streak = 0
orphans_1 = 0
orphans_2 = 0
orphans_1_t = [0]*SECONDS
orphans_2_t = [0]*SECONDS
try:
for i in range(len(log)):
(m_1_transmitted_height, m_1_n_blocks), (m_2_transmitted_height, m_2_n_blocks) = log[i]
update_1 = None
# Check to see if the transmitted height from miner 2 exceeds that at miner 1
# If it does, take the best height.
if m_2_transmitted_height:
if m_2_transmitted_height > height_1:
# give up this block (otherwise non-memoryless process)
miner_1.pop()
m_1_streak = 0
update_1 = m_2_transmitted_height
for k in range(m_2_transmitted_height - m_2_n_blocks, m_2_transmitted_height+1):
if blocks_1[k] == 1:
orphans_1 += 1
blocks_1[k] = 2
# Check to see if the transmitted height from miner 1 exceeds that at miner 2
# If it does, take the best height.
if m_1_transmitted_height:
if m_1_transmitted_height > height_2:
# give up this block (otherwise non-memoryless process)
miner_2.pop()
height_2 = m_1_transmitted_height
m_2_streak = 0
for k in range(m_1_transmitted_height - m_1_n_blocks, m_1_transmitted_height+1):
if blocks_2[k] == 2:
orphans_2 += 1
blocks_2[k] = 1
if update_1 is not None:
height_1 = update_1
if miner_1[-1] <= 0:
# Miner 1 has found a block
height_1 += 1
# send message to miner 2, arrives later
log[i+RTT//2][0] = (height_1, m_1_streak)
blocks_1[height_1] = 1
miner_1.pop()
m_1_streak += 1
else:
miner_1[-1] -= 1
if miner_2[-1] <= 0:
# Miner 2 has found a block
height_2 += 1
# send message to miner 1, arrives later
log[i+RTT//2][1] = (height_2, m_2_streak)
blocks_2[height_2] = 2
miner_2.pop()
m_2_streak += 1
else:
miner_2[-1] -= 1
height_at_time_1[i] = height_1
height_at_time_2[i] = height_2
orphans_1_t[i] = orphans_1
orphans_2_t[i] = orphans_2
except Exception as e:
print(e)
print("Consensus Worked: ", blocks_1 == blocks_2)
from matplotlib import pyplot as plt
#plt.plot(time, height_at_time_1)
#plt.plot(time, height_at_time_2)
rel_time = np.array(time) / 10 / 60
plt.plot(rel_time, orphans_1_t, label="orphans 1")
plt.plot(rel_time, orphans_2_t, label="orphans 2")
plt.plot(range(TRIALS), np.cumsum(list(map(lambda x: x == 1, blocks_1))), label="blocks 1")
plt.plot(range(TRIALS), np.cumsum(list(map(lambda x: x == 2, blocks_1))), label="blocks 2")
plt.legend()
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment