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);
}
}