Last active
May 2, 2018 22:23
-
-
Save sgbett/a7cc67469a53609da2a5eab68b4024a6 to your computer and use it in GitHub Desktop.
Selfish mine stats
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# Dependancies: | |
# gem install random_variate_generator | |
require 'random_variate_generator' | |
class Block | |
attr_accessor :real_interval, :interval, :timestamp | |
end | |
@all_blocks = [] | |
def mine_block(difficulty,timestamp,alpha=1.0) | |
block = Block.new | |
#simulates poisson process for 1 block per 10 mins by using exponential randoms, adjusted for difficulty/hash | |
block.real_interval = RandomVariateGenerator::Random.exponential(lambda: alpha/(10)) | |
block.interval = difficulty * block.real_interval | |
block.timestamp = timestamp + 60*block.interval | |
@all_blocks << block | |
block | |
end | |
def iterate(iterations,alpha) | |
d = 1.0 #starting difficulty | |
#stats | |
sm_won = 0 | |
hm_won = 0 | |
sm_orphans = 0 | |
hm_orphans = 0 | |
#potential forks being contested | |
selfish_chain = [] | |
honest_chain = [] | |
timestamp = Time.now | |
start_time = timestamp | |
i=0; while (i += 1) < iterations do | |
#first see when HM would find a block | |
honest_block = mine_block(d,timestamp,(1-alpha)) | |
honest_chain << honest_block | |
selfish_block ||= mine_block(d,timestamp,alpha) | |
#if SM block would arrive first start building private chain until their next block would be found after the HM block | |
while selfish_block.timestamp < honest_block.timestamp | |
selfish_chain << selfish_block | |
selfish_block = mine_block(d,selfish_chain.last.timestamp,alpha) | |
end | |
if (selfish_chain.count - honest_chain.count) > 1 | |
#sm keeps on private mining | |
elsif (selfish_chain.count - honest_chain.count) == 1 | |
#SM is only 1 block ahead so orphans HM to cause them to reorg | |
sm_won += selfish_chain.count | |
hm_orphans += honest_chain.count | |
selfish_chain = [] | |
honest_chain = [] | |
elsif selfish_chain.count == honest_chain.count | |
#chain is forked SM/HM tied both work on their own block (assuming gamma zero) | |
else | |
#HM chain is longer, then SM gives up and starts on public chain tip again | |
hm_won += honest_chain.count | |
sm_orphans += selfish_chain.count | |
selfish_block = nil | |
selfish_chain = [] | |
honest_chain = [] | |
end | |
total_orphans = sm_orphans + hm_orphans | |
total_mined = sm_won + hm_won | |
total_blocks = total_orphans + total_mined | |
d = 1 - (1.0 * total_orphans / total_blocks) if total_blocks > 0 | |
timestamp = honest_block.timestamp | |
end | |
puts "#{alpha},#{total_mined},#{hm_won},#{sm_won},#{(expected = (alpha*(timestamp - start_time)/600)).to_i},#{total_orphans}" | |
end | |
puts "alpha,total_mined,hm_won,sm_won,sm_expected,orphans" | |
(1..49).each do |a| | |
iterate(100000,a*0.01) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There is a problem with the following scenario:
while Loop 1 (this part is fine wait for loop 2)
------------H1
-----S1
Selfish miner found 1 block before honest miner block, so chain counts are even, keep going no rewards.
while Loop 2
------------H1------------H2
-----S1---------S2
Selfish miner finds another block S2 before honest miner H2.
In your code now you still consider both chains even, so again no change, no rewards, no orphans.
But in REAL selfish mining algorithm selfish miner would publish both S2 and S1 as soon as S2 is mined. H1 would get orphaned, H2 would not exist yet. (optionally they can also publish S1 when H1 is found but makes no difference if gamma=0)
Selfish miner is ahead of honest when S2 is found with a private branch length ==2. They publish and orphan H1 and get 2 rewards. But your code does not do this, instead you add on H2 as well and they keep going and then if next loop H3 is before the S3 block you would have honest get 3 rewards and selfish 2 orphans. This is incorrect.
So the above error will throw off all of your statistics.