Transactions

This commit is contained in:
2019-08-20 21:25:13 +02:00
parent b0e397c66e
commit 6f3149cf3e
5 changed files with 80 additions and 14 deletions

View File

@@ -50,6 +50,7 @@
<Compile Include="BlockChain.cs" /> <Compile Include="BlockChain.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Transaction.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
@@ -9,25 +10,38 @@ namespace BasicBlockChain
public int Index { get; set; } public int Index { get; set; }
public DateTime Date { get; set; } public DateTime Date { get; set; }
public string PreviousHash { get; set; } public string PreviousHash { get; set; }
public string Data { get; set; } public List<Transaction> Transactions { get; } = new List<Transaction>();
public string Hash { get; set; } public string Hash { get; set; }
public int Nonce { get; set; } public int Nonce { get; set; }
public Block(DateTime date, Block previousBlock, string data) public Block(DateTime date, Block previousBlock, IList<Transaction> transactions)
{ {
Index = (previousBlock?.Index ?? -1) + 1; Index = (previousBlock?.Index ?? -1) + 1;
Date = date; Date = date;
PreviousHash = previousBlock?.Hash; PreviousHash = previousBlock?.Hash;
Data = data; if (transactions != null) { Transactions.AddRange(transactions); }
Nonce = 0; Nonce = 0;
Hash = CalculateHash(); Hash = CalculateHash();
} }
public string CalculateHash() private string GetData()
{ {
SHA256 sha256 = SHA256.Create(); VAR.Json.JsonWriter jsonWriter = new VAR.Json.JsonWriter(1);
return jsonWriter.Write(Transactions);
}
byte[] dataBytes = Encoding.UTF8.GetBytes(string.Format("{0}-{1}-{2}-{3}", Date, PreviousHash, Data, Nonce)); public string CalculateHash(string data = null, SHA256 sha256 = null)
{
if (sha256 == null) { sha256 = SHA256.Create(); }
if (data == null)
{
data = GetData();
}
byte[] dataBytes = Encoding.UTF8.GetBytes(string.Format("{0}-{1}-{2}-{3}",
Date,
PreviousHash,
data,
Nonce));
byte[] hashBytes = sha256.ComputeHash(dataBytes); byte[] hashBytes = sha256.ComputeHash(dataBytes);
string hash = Convert.ToBase64String(hashBytes); string hash = Convert.ToBase64String(hashBytes);
@@ -36,11 +50,13 @@ namespace BasicBlockChain
public void Mine(int difficulty) public void Mine(int difficulty)
{ {
SHA256 sha256 = SHA256.Create();
var leadingZeros = new string('0', difficulty); var leadingZeros = new string('0', difficulty);
string data = GetData();
while (Hash.Substring(0, difficulty) != leadingZeros) while (Hash.Substring(0, difficulty) != leadingZeros)
{ {
Nonce++; Nonce++;
Hash = CalculateHash(); Hash = CalculateHash(data, sha256);
} }
} }
} }

View File

@@ -11,16 +11,16 @@ namespace BasicBlockChain
public BlockChain(DateTime? genesisDate = null, int difficulty = 2) public BlockChain(DateTime? genesisDate = null, int difficulty = 2)
{ {
Block genesisBlock = new Block(genesisDate ?? DateTime.UtcNow, null, "{}"); Block genesisBlock = new Block(genesisDate ?? DateTime.UtcNow, null, null);
genesisBlock.Mine(difficulty); genesisBlock.Mine(difficulty);
Difficulty = difficulty; Difficulty = difficulty;
Chain.Add(genesisBlock); Chain.Add(genesisBlock);
} }
public void AddData(DateTime date, string data) public void AddBlock(DateTime date, IList<Transaction> transactions)
{ {
Block lastBlock = Chain.Last(); Block lastBlock = Chain.Last();
Block newBlock = new Block(date, lastBlock, data); Block newBlock = new Block(date, lastBlock, transactions);
newBlock.Mine(Difficulty); newBlock.Mine(Difficulty);
Chain.Add(newBlock); Chain.Add(newBlock);
} }
@@ -40,5 +40,30 @@ namespace BasicBlockChain
} }
return true; return true;
} }
public long GetMicroCoinBalance(string receiver)
{
long microCoinBalance = 0;
for (int i = 0; i < Chain.Count; i++)
{
for (int j = 0; j < Chain[i].Transactions.Count; j++)
{
var transaction = Chain[i].Transactions[j];
if (transaction.Sender == receiver)
{
microCoinBalance -= transaction.MicroCoinAmount;
}
if (transaction.Receiver == receiver)
{
microCoinBalance += transaction.MicroCoinAmount;
}
}
}
return microCoinBalance;
}
} }
} }

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
namespace BasicBlockChain namespace BasicBlockChain
{ {
@@ -13,9 +14,9 @@ namespace BasicBlockChain
Console.WriteLine("#### Mining BlockChain with sample data"); Console.WriteLine("#### Mining BlockChain with sample data");
var startTime = DateTime.UtcNow; var startTime = DateTime.UtcNow;
BlockChain nullCoin = new BlockChain(genesisDate: new DateTime(2000, 1, 1), difficulty: 2); BlockChain nullCoin = new BlockChain(genesisDate: new DateTime(2000, 1, 1), difficulty: 2);
nullCoin.AddData(new DateTime(2000, 1, 2), "{ sender: VAR, receiver: NAM, amount: 10.00}"); nullCoin.AddBlock(new DateTime(2000, 1, 2), new List<Transaction> { new Transaction("VAR", "NAM", 10_000_000) });
nullCoin.AddData(new DateTime(2000, 1, 3), "{ sender: NAM, receiver: VAR, amount: 5.00}"); nullCoin.AddBlock(new DateTime(2000, 1, 3), new List<Transaction> { new Transaction("NAM", "VAR", 5_000_000) });
nullCoin.AddData(new DateTime(2000, 1, 4), "{ sender: NAM, receiver: VAR, amount: 5.00}"); nullCoin.AddBlock(new DateTime(2000, 1, 4), new List<Transaction> { new Transaction("NAM", "VAR", 5_000_000) });
Console.WriteLine(jsonWriter.Write(nullCoin)); Console.WriteLine(jsonWriter.Write(nullCoin));
var endTime = DateTime.UtcNow; var endTime = DateTime.UtcNow;
Console.WriteLine($"Duration: {endTime - startTime}"); Console.WriteLine($"Duration: {endTime - startTime}");
@@ -23,14 +24,21 @@ namespace BasicBlockChain
// Verify // Verify
Console.WriteLine("BlockChain is Valid? {0}", nullCoin.Verify() ? "True" : "False"); Console.WriteLine("BlockChain is Valid? {0}", nullCoin.Verify() ? "True" : "False");
// Show balance
Console.WriteLine("Balance of \"{0}\": {1}", "VAR", nullCoin.GetMicroCoinBalance("VAR"));
Console.WriteLine("Balance of \"{0}\": {1}", "NAM", nullCoin.GetMicroCoinBalance("NAM"));
// Tamper with the data // Tamper with the data
Console.WriteLine(); Console.WriteLine();
Console.WriteLine("#### Tampering with the data"); Console.WriteLine("#### Tampering with the data");
nullCoin.Chain[1].Data = "{ sender: VAR, receiver: NAM, amount: 1000.00}"; nullCoin.Chain[1].Transactions.Clear();
nullCoin.Chain[1].Transactions.Add(new Transaction("VAR", "NAM", 1000_000_000));
Console.WriteLine(jsonWriter.Write(nullCoin)); Console.WriteLine(jsonWriter.Write(nullCoin));
// Verify // Verify
Console.WriteLine("BlockChain is Valid? {0}", nullCoin.Verify() ? "True" : "False"); Console.WriteLine("BlockChain is Valid? {0}", nullCoin.Verify() ? "True" : "False");
Console.WriteLine("Balance of \"{0}\": {1}", "VAR", nullCoin.GetMicroCoinBalance("VAR"));
Console.WriteLine("Balance of \"{0}\": {1}", "NAM", nullCoin.GetMicroCoinBalance("NAM"));
Console.Read(); Console.Read();
} }

View File

@@ -0,0 +1,16 @@
namespace BasicBlockChain
{
public class Transaction
{
public string Sender { get; set; }
public string Receiver { get; set; }
public long MicroCoinAmount { get; set; }
public Transaction(string sender, string receiver, long microCoinAmount)
{
Sender = sender;
Receiver = receiver;
MicroCoinAmount = microCoinAmount;
}
}
}