using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading; using System.Windows.Markup; namespace WpfBlockChanApp { internal struct ReturnOption { public bool isValid; public Block value; public ReturnOption(bool isValid, Block value) { this.isValid = isValid; this.value = value; } } static class Blockchain { public static List Chain { get; set; } public static Mutex chainMutax = new Mutex(); readonly static int diffAdjustInterval = 10; readonly static long timeExpected = 100_000; public static bool Compute { get; set; } static Block GetLatestBlock() { return Chain[Chain.Count - 1]; } static ReturnOption GetSomeBlock(int lastAdjustBlock) { if(lastAdjustBlock + diffAdjustInterval > Chain.Count) { return new(false, Chain[0]); } ReturnOption ret = new(true, Chain[lastAdjustBlock]); return ret; } public static ReturnOption ComputeBlock(string data) { Block lastBlock = GetLatestBlock(); int index = lastBlock.Index + 1; string previousHash = lastBlock.Hash; int difficulty = lastBlock.Difficulty; int lastAdjustBlock = lastBlock.LastAdjustBlock; var previousAdjustmentBlock = GetSomeBlock(lastAdjustBlock); if (previousAdjustmentBlock.isValid) { long timeTaken = lastBlock.Timestamp - previousAdjustmentBlock.value.Timestamp; if (timeTaken < (timeExpected / 2)) difficulty += 1; // povečanje težavnosti else if (timeTaken > (timeExpected * 2)) difficulty -= 1; // pomanjšanje težavnosti lastAdjustBlock = index; } var newBlock = new Block(index, previousHash, data, difficulty, lastAdjustBlock); while (newBlock.MatchDifficulty()) { if (!Compute) return new ( false, newBlock ); newBlock.Nonce++; newBlock.Hash = newBlock.CalculateHash(); } return new( true, newBlock ); } public static bool AddBlock(Block block) { Block previusBlock = GetLatestBlock(); if (block.PreviousHash != previusBlock.Hash) return false; if (block.Hash != block.CalculateHash()) return false; if (block.Index != previusBlock.Index + 1) return false; chainMutax.WaitOne(); Chain.Add(block); chainMutax.ReleaseMutex(); return true; } public static bool IsValid(List chain) { for (int i = 1; i < chain.Count; i++) { Block currentBlock = chain[i]; Block previusBlock = chain[i - 1]; if (currentBlock.PreviousHash != previusBlock.Hash) return false; if (currentBlock.Hash != currentBlock.CalculateHash()) return false; if (currentBlock.Index != previusBlock.Index + 1) return false; if (currentBlock.Timestamp > previusBlock.Timestamp + 60_000) return false; } return true; } public static bool Evaluete(List chain1, List chain2) { List result = new List(); double chain1Dif = 0; foreach (var item in chain1) { chain1Dif += Math.Pow(2, item.Difficulty); } double chain2Dif = 0; foreach (var item in chain2) { chain2Dif += Math.Pow(2, item.Difficulty); } return (chain1Dif > chain2Dif) ? false : true; } } }