126 lines
3.9 KiB
C#

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<Block> 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<Block> 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<Block> chain1, List<Block> chain2)
{
List<Block> result = new List<Block>();
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;
}
}
}