agree, but i wonder if the simulation would be attacked by real attacker?
It was the Bitcointalk forum that inspired us to create Bitcointalksearch.org - Bitcointalk is an excellent site that should be the default page for anybody dealing in cryptocurrency, since it is a virtual gold-mine of data. However, our experience and user feedback led us create our site; Bitcointalk's search is slow, and difficult to get the results you need, because you need to log in first to find anything useful - furthermore, there are rate limiters for their search functionality.
The aim of our project is to create a faster website that yields more results and faster without having to create an account and eliminate the need to log in - your personal data, therefore, will never be in jeopardy since we are not asking for any of your data and you don't need to provide them to use our site with all of its capabilities.
We created this website with the sole purpose of users being able to search quickly and efficiently in the field of cryptocurrency so they will have access to the latest and most accurate information and thereby assisting the crypto-community at large.
function selfish(Nsim, PercentSelfish, MaxOrphanLen, PlotFlag, PauseValue, RndState)
% ------------------------------------------------------------------------------------------------------------
% function selfish()
% function selfish(Nsim, PercentSelfish, MaxOrphanLen, PlotFlag, PauseValue, RndState)
%
% This function simulates and ilustrates the selfish bitcoin mining.
%
% As we see, selfish mining works if the mining power of the selfish miner is more than one 3rd of the total
% mining power.
%
% Network propagation times are not modelled and are assumed to be zero (best case from selfish miner's
% perspective)
%
% Optional arguments:
% * Nsim (def.=100): Length of simulation time in terms of number of blocks on the public main blockchain
% * PercentSelfish (def.=40.586): Percent of the selfish miner's overall network hashing power
% * MaxOrphanLen (def.=5): Selfish miner will avoid creating orphans on main chain longer than this nb of blocks.
% * PlotFlag (def.=1=true): If set to =false or =0, no illustratetive plot will be made -> set =false for long simulations!
% * PauseValue (def.=inf): When plotting is active, this many seconds of waiting time is added after each block.
% Set =inf to require keypress after each block.
% For Non-Matlab, default = 0.1 [sec] and =inf is not supported.
% * RndState (def.=sum(100*clock)): set to a certain value (e.g. integer number) to set random seed.
%
% Example function calls:
% > selfish % run with default settings - good for learning and demonstration purposes <-- good for educational purposes
% > selfish(40, 48, 3, true, inf, 8) % short interactive simulation with limitation of the orphan lengths in the main chain <-- very good for educational purposes
% > selfish(200, 41, inf, true, 0.01, 1) % self-running simulation, watch while running. Certain random seed for reproducibility <-- very good for educational purposes
% > selfish(200, 41, inf, true, 0.01) % self-running simulation, watch while running. Random seed is different each time
% > selfish(1e4, 45, inf, false, false, 4) % run a long simulation without plotting during simulation time
% ------------------------------------------------------------------------------------------------------------
% Tested with Matlab R2007b, Octave 3.0.0 (Linux) and FreeMat 4.1.1 (Windows).
% Restriction for FreeMat: only works for PlotFlag=false
%
% Octave is open-source freeware, available for Windows and Linux.
% FreeMat is open-source freeware, available for Windows.
%
% If you start Octave (or Matlab or FreeMat), you see a command window (console).
% There you simply enter (where ">" denotes the console's command prompt):
% > cd the_path/where/this_file/is_located
% > selfish
%
% Note: In the comments of this file, the terms "selfish miner" and "attacker" are used interchangeably,
% they refer to the same thing.
% ------------------------------------------------------------------------------------------------------------
%
% License:
% --------
% * Use is permitted as long as the user has donated an amount that he/she considers reasonable, or if the
% user truly thinks that a donation is not required.
%
% * Reuse/modify/extend as you like, commercially or non-commercially.
%
% * The only condition is that you include this license condition in the source code, and include a reference
% to the original author and the bitcoin donation address both in the source code and being displayed
% by the running program.
%
% Bitcoin Donations to the author: 1MichaS16UMKFgNjanKrtfD51HpBkqPAwD (Michael_S at bitcointalk.org)
% ------------------------------------------------------------------------------------------------------------
global power_attack % selfish miner's hasing power share
global THR_orphanes_publish % max number of orpans that the selfish miner will create on the public main chain
global Pause_value % pause in seconds after each block, when plotting is active
ismatlab = false;
v=version;% typical Matlab version string: "7.5.0.338 (R2007b)"; typical Octave version string: "3.0.0"
if ~isempty(strfind(v,'R2')), % Matlab version string contains "R2" in it.
ismatlab = true;
end
%% 0 - Parameters (adjust to your liking)
% - - - - - Parameters that can be overruled by function arguments: - - - - -
% 0.1 - Change as desired: (may be overruled by function arguments)
%power_attack = 0.17; % between 0 and 1 (0.40586 yields 50% of the blocks, 0.5 yields 100%)
power_attack = 0.40586; % between 0 and 1 (0.40586 yields 50% of the blocks, 0.5% yields 100%)
%power_attack = 0.44; % between 0 and 1 (0.40586 yields 50% of the blocks, 0.5 yields 100%)
%power_attack = 0.51; % between 0 and 1 (0.40586 yields 50% of the blocks, 0.5 yields 100%)
% 0.2 - Change as desired: (may be overruled by function arguments)
% The selfish miner gets the highest yield when setting the following parameter to "inf", but this might be "impractical".
% Setting this to e.g. =5 or =10 gives a yield close to theoretical maximum while avoiding creation of too long orphans in the main chain.
% Hence, e.g. setting it to =5 might be a reasonable choice, to ensure that blocks of depth=6 in the public main chain are never orphaned by the selfish miner.
THR_orphanes_publish = 5; % (>=1) [best is =inf] If the attacker creates so many orphans in the main chain, he publishes before even more orphans are created.
%THR_orphanes_publish = inf; % (>=1) [best is =inf] If the attacker creates so many orphans in the main chain, he publishes before even more orphans are created.
% 0.3 - Change as desired: (may be overruled by function arguments)
N = 1e6; % number of blocks to be simulated
N = 1e5; % number of blocks to be simulated
N = 100; % number of blocks to be simulated
% 0.4 - Change as desired: (may be overruled by function arguments)
plot_flag = 1;% =1 for plotting illustrative block chain and interactive keypress; =0 for not plotting (faster).
% 0.5 - Change as desired: (may be overruled by function arguments)
try
rand('state', 1);% set random generator seed
rand('state', sum(100*clock));% set random generator seed
catch
% Freemat does understand the above format, but instead this:
seed(1,1);% set random generator seed
seed(sum(100*clock),sum(100*clock));% set random generator seed
end
% - - - - - Parameters that can NOT be overruled by function arguments: - - - - -
% 0.6 - Normally keep the "best" values!
THR_attack_give_up = 1; % (>=1) [best is =1] If main chain is so much longer than the own "secret" chain, then attacker gives up and adopts the main chain's blocks.
THR_attack_publish = inf; % (>=2) [best is =inf] If the attacker has so many secret blocks, he will publish them (e.g. to avoid loosing them due to checkpointing).
% ------------------------------------------------------------------------------------------------------------
% ------------------------------------------------------------------------------------------------------------
%% 1.1 - Overruling pre-set parameters with function arguments:
if exist('Nsim', 'var'),
N = Nsim;
end
if exist('PercentSelfish', 'var'),
power_attack = PercentSelfish/100;
end
if exist('MaxOrphanLen', 'var'),
THR_orphanes_publish = MaxOrphanLen;
end
if exist('PlotFlag', 'var'),
plot_flag = PlotFlag;
end
if ~exist('PauseValue', 'var'),
Pause_value = inf;
else
Pause_value = PauseValue;
end
if exist('RndState', 'var'),
try
rand('state', RndState);
catch
seed(RndState,RndState);
end
end
%% 1.2 - Pre-Processing
power_normal = 1-power_attack;% mining power (share of the total) of the normal (=honest) miners
gen_time_attack = 10/power_attack;% average time needed to generate a block, in minutes, by attacker
gen_time_normal = 10/power_normal;% average time needed to generate a block, in minutes, by normal (=honest) miners
N_force_terminate = ceil(1.1*N);% ceil(1.1*N) by default
%% 2 - Simulate
% Pre-allocate memory - this is important for simulation time:
blocks_won = NaN*ones(1,ceil(N_force_terminate)); % vector indicating which block was won by the selfish mining attacker
chn = blocks_won;% vector showing the normal (public) chain
cha = blocks_won;% vector showing the chain that the attacker works on
Nb_of_blocks_orphaned_by_attacker = NaN*ones(1,ceil(N_force_terminate));
cnt_event_orphaned = 0;% counter for the *nb of events* that a selfish miner published his secretly mined blocks and thereby orphans honestly mined coins.
kn = 0;% kn is the length of the "official" blockchain that the normal (=honest) miners work on
ka = 0;% ka is the number of mined blocks that the attacker's chain has in common with the official chain.
sa = 0;% sa is the number of blocks already mined secretly by the attacker
Time.Total = 0;% To output timestamps during the simulation, whenever a new block is found
time_next_attack = -gen_time_attack*log(rand());% time until attacker finds the next block
time_next_normal = -gen_time_normal*log(rand());% time until normal (=honest) miners find the next block
cnt_blocks.found_normal = 0;% counts nb of blocks found by honest miners
cnt_blocks.orphaned_normal = 0;% ...of which so many got orphaned (replaced) by blocks found by the selfish miner.
cnt_blocks.found_attack = 0;% counts nb of blocks found by selfish miner
cnt_blocks.orphaned_attack = 0;% ...of which so many got orphaned (replaced) by blocks found by the honest miners.
cnt_blocks.in_main_chain = 0;% counts the number of blocks in the (public) main chain.
if plot_flag, [hdn, hda] = plot_chain([0], [0]); end;% pro forma plot
while 1;
% --- Finding new block, depending on whether normal (=honest) miners or attacker find the next block:
if time_next_normal < time_next_attack,% the next block is found by the normal (=honest) miners
cnt_blocks.found_normal = cnt_blocks.found_normal + 1;
cnt_blocks.in_main_chain = cnt_blocks.in_main_chain + 1;
Time.Delta = time_next_normal;
Time.Total = Time.Total + Time.Delta;
kn = kn + 1;% official block chain grows by one block
blocks_won(kn) = 0;% block nb. kn found by the normal (=honest) miners [not final, might still be reverted later on]
chn(kn) = 0;
if sa == 0, % attacker has no secret blocks
cha(ka+1:kn) = 0;
ka = kn;% attacker stays at the official chain
sa = 0;% attacker stays at the official chain
time_next_attack = -gen_time_attack*log(rand());% time until attacker finds the next block
time_next_normal = -gen_time_normal*log(rand());% time until normal (=honest) miners find the next block
elseif kn >= ka + sa + THR_attack_give_up, % normal (=honest) miners have too many blocks, attacker gives up
cha(ka+1:kn-THR_attack_give_up) = 0.1;% attacker replaces his secret blocks by the official blocks
chn(ka+1:kn-THR_attack_give_up) = 0.1;% attacker replaces his secret blocks by the official blocks
cha(kn-THR_attack_give_up+1:kn) = 0;% attacker takes latest official block to his own chain
cnt_blocks.orphaned_attack = cnt_blocks.orphaned_attack + (kn-THR_attack_give_up-ka);
ka = kn;% attacker switches to the official chain
sa = 0;% attacker switches to the official chain
time_next_attack = -gen_time_attack*log(rand());% time until attacker finds the next block
time_next_normal = -gen_time_normal*log(rand());% time until normal (=honest) miners find the next block
else % attacker remains on his own chain
time_next_attack = time_next_attack - time_next_normal;% time until attacker finds the next block
time_next_normal = -gen_time_normal*log(rand());% time until normal (=honest) miners find the next block
end
else % the next block is found by the attacker
cnt_blocks.found_attack = cnt_blocks.found_attack + 1;
Time.Delta = time_next_attack;
Time.Total = Time.Total + Time.Delta;
sa = sa + 1;% attacker does not publish the block (yet), so the number of secret blocks is incremented
cha(ka+sa) = 2;
time_next_normal = time_next_normal - time_next_attack;% time until normal (=honest) miners find the next block
time_next_attack = -gen_time_attack*log(rand());% time until attacker finds the next block
end
if plot_flag, [hdn, hda] = plot_chain(chn(1:kn), cha(1:ka+sa), hdn, hda, Time, cnt_blocks, 'pause'); end % illustrate state of block chains
% --- Check out if the attacker publishes his secret blocks:
if sa >= THR_attack_publish || (sa >= 2 && ka+sa == kn+1),% 2nd condition means: normal (=honest) miners get too close, so publish before it is too late.
blocks_won(ka+1:ka+sa) = 1;% These blocks are (re-)credited to the attacker now
chn(ka+1:kn) = 1;% orphaned
chn(kn+1:ka+sa) = -1;% not orphaned
cha(ka+1:ka+sa) = chn(ka+1:ka+sa);
cnt_event_orphaned = cnt_event_orphaned + 1;
Nb_of_blocks_orphaned_by_attacker(cnt_event_orphaned) = kn-ka;
cnt_blocks.orphaned_normal = cnt_blocks.orphaned_normal + (kn-ka);
cnt_blocks.in_main_chain = cnt_blocks.in_main_chain + (ka+sa-kn);
kn = ka+sa; % attacker's secretly mined blocks become published and accepted by the normal (=honest) miners
ka = kn;% all blocks of the attacker are now in common with the normal chain.
sa = 0;% attacker has no secret blocks any more now.
time_next_attack = -gen_time_attack*log(rand());% time until attacker finds the next block
time_next_normal = -gen_time_normal*log(rand());% time until normal (=honest) miners find the next block
Time.Delta = 0;
if plot_flag, [hdn, hda] = plot_chain(chn(1:kn), cha(1:ka+sa), hdn, hda, Time, cnt_blocks, 'pause'); end % illustrate state of block chains
elseif sa >= 2 && kn-ka >= THR_orphanes_publish,% attacker publishes some blocks to avoid that even more orphans are created on the main chain
blocks_won(ka+1:ka+THR_orphanes_publish+1) = 1;% These blocks are published and (re-)credited to the attacker now
chn(ka+1:ka+THR_orphanes_publish) = 1;% selfishly mined blocks replacing honest blocks
chn(ka+THR_orphanes_publish+1) = -1;% another selfishly mined block, but not causing orphanes on the main chain
cha(ka+1:ka+THR_orphanes_publish+1) = chn(ka+1:ka+THR_orphanes_publish+1);
cnt_event_orphaned = cnt_event_orphaned + 1;
cnt_blocks.in_main_chain = cnt_blocks.in_main_chain + (ka+THR_orphanes_publish+1-kn);
Nb_of_blocks_orphaned_by_attacker(cnt_event_orphaned) = THR_orphanes_publish;
cnt_blocks.orphaned_normal = cnt_blocks.orphaned_normal + THR_orphanes_publish;
kn = ka + THR_orphanes_publish + 1;% attacker's secretly mined blocks become published and accepted by the normal (=honest) miners
ka = ka + THR_orphanes_publish + 1;% all blocks of the attacker are now in common with the normal chain.
sa = sa - THR_orphanes_publish - 1;% attacker has no secret blocks any more now.
time_next_normal = -gen_time_normal*log(rand());% time until normal (=honest) miners find the next block
Time.Delta = 0;
if plot_flag, [hdn, hda] = plot_chain(chn(1:kn), cha(1:ka+sa), hdn, hda, Time, cnt_blocks, 'pause'); end % illustrate state of block chains
end
% --- Termination condition(s) of the simulation:
if kn > N && sa == 0,% terminate if enough blocks were simulated and the attacker has no more secret blocks
break;
end
if ka+sa > N_force_terminate, % Force termination of the simulation. If attacker has more blocks than the normal (=honest) miners,
% publish them now to get the blocks credited, and then terminate the simulation.
if ka+sa > kn,
blocks_won(ka+1:ka+sa) = 1;% These blocks are credited to the attacker
chn(ka+1:kn) = 1;% orphaned
chn(kn+1:ka+sa) = -1;% not orphaned
cha(ka+1:ka+sa) = chn(ka+1:ka+sa);
cnt_event_orphaned = cnt_event_orphaned + 1;
Nb_of_blocks_orphaned_by_attacker(cnt_event_orphaned) = kn-ka;
kn = ka+sa; % attacker's secretly mined blocks become published and accepted by the normal (=honest) miners
Time.Delta = 0;
if plot_flag, [hdn, hda] = plot_chain(chn(1:kn), cha(1:ka+sa), hdn, hda, Time, cnt_blocks); end % illustrate state of block chains
end
break;
end
end% while 1
% Cut of the NaN entries from the results vector
blocks_won = blocks_won(1:kn);
Nb_of_blocks_orphaned_by_attacker = Nb_of_blocks_orphaned_by_attacker(1:cnt_event_orphaned);
%% 3 - Show results:
Number_of_blocks_simulated = kn %#ok
Percentage_mining_power_selfish_miner = power_attack*100 %#ok
Percentage_blocks_won_by_selfish_miner = sum(blocks_won)/length(blocks_won)*100 %#ok
Percentage_of_mainchain_blocks_orphaned_by_selfish_miner = sum(Nb_of_blocks_orphaned_by_attacker)/kn*100 %#ok
% Finally the histogram:
hfig=figure;
hist(Nb_of_blocks_orphaned_by_attacker,[1:max(2,max(Nb_of_blocks_orphaned_by_attacker))]); title('Lengths of Consecutive Blocks Orphaned on the Main Chain by the Selfish Miner'); xlabel('Event that this number of consecutive blocks were orphaned on the Main Chain'); ylabel('How often the rexpective event happened');
if ismatlab,% Octave does not understand the following formating
set(0,'units','pixels');
Pix_SS = get(0,'screensize');% info about the screen resolution in 'pixel'
set(hfig, 'position', [0.25*Pix_SS(3), 1, 0.5*Pix_SS(3), 0.45*Pix_SS(4)]);% [x, y, width, height]
end
%% -----------------------------------------------------------------------------------------------------------
%% ---------------------------------------------- SUB-FUNCTION -----------------------------------------------
%% -----------------------------------------------------------------------------------------------------------
function [hdn, hda] = plot_chain(chn, cha, hdn, hda, Time, cnt_blocks, pause_flag)
% chn = the normal chain, row vector
% cha = the chain of the attacker
% The elements of the vector have the following meaning:
% 0 = block was mined by normal (=honest) miners
% 0.1 = block was mined by normal (=honest) miners and overruled a block from the selfish miner
% 1 = block was mined by attacker and caused an orphan of the normal (=honest) miners
% -1 = block was mined by attacker and did not cause an orphan of the normal (=honest) miners
% 2 = (only in the attacker chain): secret block
global power_attack % selfish miner's hasing power share
global THR_orphanes_publish % max number of orpans that the selfish miner will create on the public main chain
global Pause_value % pause in seconds after each block, when plotting is active
ismatlab = false;
v=version;% typical Matlab version string: "7.5.0.338 (R2007b)"; typical Octave version string: "3.0.0"
if ~isempty(strfind(v,'R2')), % Matlab version string contains "R2" in it.
ismatlab = true;
end
if nargin > 2,
try
delete(hdn.n);
catch
disp('ERROR with this software! (maybe you are using FreeMat?)');
disp('Try running the function "selfish" with PlotFlag=false, or use Matlab or Octave for full plot support.');
disp(' ');
pause
return;
end
delete(hdn.d);
delete(hdn.o);
delete(hdn.m);
delete(hda.n);
delete(hda.d);
delete(hda.o);
delete(hda.m);
delete(hda.z);
delete(hdn.ti);
delete(hdn.dt);
delete(hdn.t1);
delete(hdn.t2);
delete(hdn.t3);
delete(hdn.t4);
delete(hdn.t5);
delete(hdn.t6);
delete(hdn.t7);
delete(hdn.t8);
delete(hdn.t9);
delete(hdn.t10);
delete(hdn.t11);
else % initial call
if ismatlab,% Octave does not understand the following formating
hfig = figure;
set(0,'units','pixels');
Pix_SS = get(0,'screensize');% info about the screen resolution in 'pixel'
set(hfig, 'position', [0, Pix_SS(4), Pix_SS(3), 0.3*Pix_SS(4)]);% [x, y, width, height]
else
disp(' ')
disp('*** Please manually change the width of the figure that will now appear, ***')
disp('*** to take the full screen width for best visual results! ***')
disp(' ')
disp('--> Press any key to continue <--')
pause
hfig = figure;
end
end
% Only display a window of 100 blocks:
len = max(length(chn), length(cha));
if len > 100,
chn = chn(len-99:end);
cha = cha(len-99:end);
end
chn_0 = chn; chn_0(chn_0==1)=999; chn_0(chn_0==-1)=999; chn_0(chn_0==0.1)=999;% 0: green
chn_d = chn; chn_d(chn_d==1)=999; chn_d(chn_d==-1)=999; chn_d(chn_d==0)=999; % 0: green
chn_1 = chn; chn_1(chn_1==0)=999; chn_1(chn_1==-1)=999; chn_1(chn_1==0.1)=999;% 1: red
chn_m = chn; chn_m(chn_m==1)=999; chn_m(chn_m== 0)=999; chn_m(chn_m==0.1)=999;% -1: pink
cha_0 = cha; cha_0(cha_0==1)=999; cha_0(cha_0==-1)=999; cha_0(cha_0==2)=999; cha_0(cha_0==0.1)=999;% 0: green
cha_d = cha; cha_d(cha_d==1)=999; cha_d(cha_d==-1)=999; cha_d(cha_d==2)=999; cha_d(cha_d==0)=999; % 0: green
cha_1 = cha; cha_1(cha_1==0)=999; cha_1(cha_1==-1)=999; cha_1(cha_1==2)=999; cha_1(cha_1==0.1)=999;% 1: red
cha_m = cha; cha_m(cha_m==1)=999; cha_m(cha_m== 0)=999; cha_m(cha_m==2)=999; cha_m(cha_m==0.1)=999;% -1: pink
cha_z = cha; cha_z(cha_z==0)=999; cha_z(cha_z==-1)=999; cha_z(cha_z==1)=999; cha_z(cha_z==0.1)=999;% 2: black
chn_0(chn_0==0) = 1;
chn_d(chn_d==0.1) = 1;
chn_m(chn_m==-1) = 1;
cha_0(cha_0==0) = 1;
cha_d(cha_d==0.1) = 1;
cha_m(cha_m==-1) = 1;
cha_z(cha_z==2) = 1;
if nargin > 2, % normal section
if ismatlab,
hdn.n = plot(2*chn_0,'gs', 'MarkerFaceColor','g'); hold on;
hdn.d = plot(2*chn_d,'cs', 'MarkerFaceColor','c'); hold on;
hdn.o = plot(2*chn_1,'rs', 'MarkerFaceColor','r'); hold on;
hdn.m = plot(2*chn_m,'ms', 'MarkerFaceColor','m'); hold on;
hda.n = plot(1*cha_0,'gs', 'MarkerFaceColor','g'); hold on;
hda.d = plot(1*cha_d,'cs', 'MarkerFaceColor','c'); hold on;
hda.o = plot(1*cha_1,'rs', 'MarkerFaceColor','r'); hold on;
hda.m = plot(1*cha_m,'ms', 'MarkerFaceColor','m'); hold on;
hda.z = plot(1*cha_z,'ks', 'MarkerFaceColor','k'); hold on;
else
hdn.n = plot(2*chn_0,'gs'); hold on;
hdn.d = plot(2*chn_d,'cs'); hold on;
hdn.o = plot(2*chn_1,'rs'); hold on;
hdn.m = plot(2*chn_m,'ms'); hold on;
hda.n = plot(1*cha_0,'gs'); hold on;
hda.d = plot(1*cha_d,'cs'); hold on;
hda.o = plot(1*cha_1,'rs'); hold on;
hda.m = plot(1*cha_m,'ms'); hold on;
hda.z = plot(1*cha_z,'ks'); hold on;
end
cnt_blk_tot = cnt_blocks.found_normal + cnt_blocks.found_attack;
hdn.ti = text(50,2.55,['Time = ',num2str(Time.Total),' min (Total blocks calculated = ', ...
num2str(cnt_blk_tot),' --> 1 block per ',num2str(Time.Total/cnt_blk_tot),' min)']);
hdn.dt = text(50,2.35,['Delta = ',num2str(Time.Delta),' min (Blocks on Main Chain = ', ...
num2str(cnt_blocks.in_main_chain),' --> 1 block per ',num2str(Time.Total/cnt_blocks.in_main_chain),' min)']);
hdn.t1 = text(50,1.80, 'Blocks calculated by...');
hdn.t2 = text(50,1.60, ['...honest miners: ', num2str(cnt_blocks.found_normal), ' (',num2str(cnt_blocks.found_normal/cnt_blk_tot*100),'%)']);
hdn.t3 = text(50,1.40, ['...selfish miner: ', num2str(cnt_blocks.found_attack), ' (',num2str(cnt_blocks.found_attack/cnt_blk_tot*100),'%)']);
hdn.t4 = text(50,1.20, ['...Total number: ', num2str(cnt_blk_tot),' (100%)']);
hdn.t5 = text(68,1.80, ['--> of which orphaned (i.e. mined in vain):']);
hdn.t6 = text(68,1.60, ['--> ',num2str(cnt_blocks.orphaned_normal),' (',num2str(cnt_blocks.orphaned_normal/cnt_blocks.found_normal*100),'%)']);
hdn.t7 = text(68,1.40, ['--> ',num2str(cnt_blocks.orphaned_attack),' (',num2str(cnt_blocks.orphaned_attack/cnt_blocks.found_attack*100),'%)']);
hdn.t8 = text(68,1.20, ['--> ',num2str(cnt_blocks.orphaned_normal+cnt_blocks.orphaned_attack), ...
' (',num2str((cnt_blocks.orphaned_normal+cnt_blocks.orphaned_attack)/cnt_blk_tot*100),'%)']);
hdn.t9 = text(50,0.67, ['Number of blocks that were found in current Main Chain by...']);
tmp_cnt_hon = cnt_blocks.found_normal - cnt_blocks.orphaned_normal;
tmp_cnt_sel = cnt_blocks.in_main_chain - tmp_cnt_hon;
hdn.t10 = text(50,0.47, ['...honest miners: ',num2str(tmp_cnt_hon),' (',num2str(tmp_cnt_hon/(tmp_cnt_hon+tmp_cnt_sel)*100),'%)']);
hdn.t11 = text(50,0.27, ['...selfish miners: ',num2str(tmp_cnt_sel),' (',num2str(tmp_cnt_sel/(tmp_cnt_hon+tmp_cnt_sel)*100),'%)']);
else % initialization section
if ismatlab,
hdn.n = plot(2*chn_0,'ws', 'MarkerFaceColor','w'); hold on;
hdn.d = plot(2*chn_d,'ws', 'MarkerFaceColor','w'); hold on;
hdn.o = plot(2*chn_1,'ws', 'MarkerFaceColor','w'); hold on;
hdn.m = plot(2*chn_m,'ws', 'MarkerFaceColor','w'); hold on;
hda.n = plot(1*cha_0,'ws', 'MarkerFaceColor','w'); hold on;
hda.d = plot(1*cha_d,'ws', 'MarkerFaceColor','w'); hold on;
hda.o = plot(1*cha_1,'ws', 'MarkerFaceColor','w'); hold on;
hda.m = plot(1*cha_m,'ws', 'MarkerFaceColor','w'); hold on;
hda.z = plot(1*cha_z,'ws', 'MarkerFaceColor','w'); hold on;
else
hdn.n = plot(2,'ws'); hold on;
hdn.d = plot(2,'ws'); hold on;
hdn.o = plot(2,'ws'); hold on;
hdn.m = plot(2,'ws'); hold on;
hda.n = plot(1,'ws'); hold on;
hda.d = plot(1,'ws'); hold on;
hda.o = plot(1,'ws'); hold on;
hda.m = plot(1,'ws'); hold on;
hda.z = plot(1,'ws'); hold on;
end
hdn.ti = text(50,2.35,[' ']);
hdn.dt = text(50,2.35,[' ']);
hdn.t1 = text(50,2.35,[' ']);
hdn.t2 = text(50,2.35,[' ']);
hdn.t3 = text(50,2.35,[' ']);
hdn.t4 = text(50,2.35,[' ']);
hdn.t5 = text(50,2.35,[' ']);
hdn.t6 = text(50,2.35,[' ']);
hdn.t7 = text(50,2.35,[' ']);
hdn.t8 = text(50,2.35,[' ']);
hdn.t9 = text(50,2.35,[' ']);
hdn.t10 = text(50,2.35,[' ']);
hdn.t11 = text(50,2.35,[' ']);
xlabel('block number');
ylabel('attacker''s chain (bottom) | public chain (top)');
title(['Selfish Miner''s Hashing Power = ',num2str(power_attack*100),'% of Total Network; Max. Length of Orphans Caused by Selfish Miner = ',num2str(THR_orphanes_publish),]);
text(5,1.80, 'Blockchain that the honest miners are working on (public Main Chain)');
text(5,1.13, 'Blockchain that the attacker (selfish miner) is working on (secret chain)');
text(75,0.37, 'by Michael\_S at bitcointalk.org');
text(75,0.17, '1MichaS16UMKFgNjanKrtfD51HpBkqPAwD');
axis([1 100 0 3]);
plot(5, 2.55, 'gs', 'MarkerFaceColor','g'); text(6,2.52,'Block mined by honest miner');
plot(5, 2.35, 'cs', 'MarkerFaceColor','c'); text(6,2.32,'Block first mined by selfish miner, then replaced by honest miner');
plot(5, 0.70, 'ms', 'MarkerFaceColor','m'); text(6,0.67,'Block mined by selfish miner (without replacement)');
plot(5, 0.50, 'rs', 'MarkerFaceColor','r'); text(6,0.47,'Block first mined by honest miner, then replaced by selfish miner');
plot(5, 0.30, 'ks', 'MarkerFaceColor','k'); text(6,0.27,'Block mined secretly by selfish miner, not yet published');
end
if nargin > 6,
if Pause_value==inf,
if ~ismatlab,
disp('--> Press any key to see next block (focus must be on console when you press the key) <--')
end
pause;
else
pause(Pause_value);
end
end
this.delay = Math.floor((Math.log(1-Math.random())/-1) * (1 / (this.ptotal)));
(height = 2016) Difficulty adjustment: from 1000 to 1441.9452528101006 (1.4419452528101004x)
btc.init(function(self) {
switch(self.id) {
case 0:
self.mine(0.31) // btcguild
break;
case 1:
self.mine(0.22)
break;
case 2:
self.mine(0.13)
break;
case 3:
self.mine(0.06)
break;
case 4:
self.mine(0.05)
break;
case 5:
self.mine(0.03)
break;
case 6:
self.mine(0.02)
break;
case 7:
self.mine(0.02)
break;
default:
if (self.id < 100)
self.mine(true);
else
self.mine(false);
break;
}
});