package bitcoinattackmodel; /** * * @author Kooooooj */ public class BitcoinAttackModel { public static void main(String[] args) { int honestBlocks = 0, attackBlocks = 0;//counts profit of honest and attack int currentHonestChain = 0, currentAttackChain = 0;//number of blocks not yet accepted double attackPercent = .3333, honestPercent = 1-attackPercent;//relative percentages of the network double raceOdds = .0;//odds that an honest miner builds off of the attacker's block. Typical range 0 to .5. Can be as high as 1. double oddsPerStep = 0.00001;//small number to discourage simultaneous mining of blocks by attacker and honest. Will run faster with larger values but could be less accurate long maxSteps = 1000000000L;//exit condition. Program will exit eariler with smaller values but will use a smaller data set long currentStep = 0;//counter while(currentStep < maxSteps) { currentStep++; if(Math.random() < oddsPerStep * attackPercent) {//attackers found a block if(currentAttackChain>0 && currentAttackChain == currentHonestChain){ //attackers found the block. They *always* build off of the attack chain attackBlocks+=currentAttackChain + 1;//they get the old chain plus the added block currentAttackChain = 0; currentHonestChain = 0; } else{ currentAttackChain++;//only get to start a new chain if we didn't just resolve a race } // System.out.println("Attack found a block. Current Attack Chain of " + currentAttackChain + " blocks."); } if(Math.random() < oddsPerStep * honestPercent) {//honest found a block if(currentAttackChain>0 && currentAttackChain==currentHonestChain){//there's a race condition in place System.out.println("Race!!"); if(Math.random() < raceOdds){//honest miners mined on top of the attack chain attackBlocks+=currentAttackChain;//accept the attack block } else{//honest miners mined on top of the honest chain; attackers lost the race honestBlocks += currentHonestChain; } currentAttackChain = 0; currentHonestChain = 0; } currentHonestChain++;//race (if any) has been resolved. Note the new block System.out.println("Honest found a block. Current Honest Chain of " + currentHonestChain + " blocks\t\tCurrent Stats: " + attackBlocks + " : " + honestBlocks + ", " + attackBlocks/((double)honestBlocks+attackBlocks)); } if(currentHonestChain>0 && currentAttackChain ==0){ honestBlocks+=currentHonestChain; currentHonestChain = 0; currentAttackChain = 0; // System.out.println("Honest block accepted. " + honestBlocks + " honest blocks found"); } if(currentAttackChain > 1 && currentAttackChain - currentHonestChain == 1){ attackBlocks += currentAttackChain; // System.out.println("Attacker orphaned " + currentHonestChain + " blocks"); currentAttackChain = 0; currentHonestChain = 0; } } System.out.println("Attacker mined " + attackBlocks + " blocks while honest mined " + honestBlocks); System.out.println("Attacker's percentage is " + ((double)attackBlocks/(attackBlocks + honestBlocks)) + " while expected was " + attackPercent); } }