Michael_S
Sr. Member
Offline
Activity: 278
Merit: 251
Bitcoin-Note-and-Voucher-Printing-Empowerer
|
|
May 31, 2014, 03:05:40 PM |
|
I wrote an educational simulator (ca. 500 lines of code incl. many comments) that simulates and visualizes the selfish mining. It runs under Matlab (commercial - nicest graphics) and Octave (freeware open source Linux/Windows, also works nicely). "FreeMat" (open source freeware for Windows) is also supported, but the nice graphical illustration does not work (yet). The simulator displays the chain of blocks that are mined, dynamically, like a film. You can have it run automatically (e.g. every 0.1 seconds one new block is displayed) or interactively (keypress after each block). The tool visualizes both the "public" blockchain, as well as the "secret" chain that the selfish miner is working on. Blocks get different colors, depending on whether they have been mined by the honest miners or the selfish miner, and whether they caused any orphans. So you can also see how often selfish miners create orphans on the public blockchain, and how long they are. Sometimes they are really long! At the end of the simulation, you get some statistics concerning the orphans created on the public blockchain (histogram about how often orphans of different lengths have been created). The simulator can be configured in that the selfish miner self-restricts itself to not create any orphans longer than a pre-defined maximum. This of course reduces the income that the selfish miner can generate. Also various other configuration variables exist (e.g. the selfish miner's share of max. hash rate, of course). Network propagation times are NOT modeled, the focus is to investigate, illustrate and understand the basic principles of selfish mining. Also long simulations can be performed and graphic outputs disabled, thereby simulation of 1 Million blocks takes only a few seconds on Matlab on a >7 years old PC (FreeMat and Octave is by a factor 10 to 100 slower as it seems). Here are some screenshots: Enjoy! (and donate whatever you consider reasonable) Here's the source code - copy-paste to text editor and save as file "selfish.m": 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 <press Enter> % % 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<NOPTS> Percentage_mining_power_selfish_miner = power_attack*100 %#ok<NOPTS> Percentage_blocks_won_by_selfish_miner = sum(blocks_won)/length(blocks_won)*100 %#ok<NOPTS> Percentage_of_mainchain_blocks_orphaned_by_selfish_miner = sum(Nb_of_blocks_orphaned_by_attacker)/kn*100 %#ok<NOPTS>
% 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
|