126 lines
3.9 KiB
C#
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;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|