diff --git a/BasicBlockChain/BasicBlockChain.csproj b/BasicBlockChain/BasicBlockChain.csproj
index 425c00d..ba0825e 100644
--- a/BasicBlockChain/BasicBlockChain.csproj
+++ b/BasicBlockChain/BasicBlockChain.csproj
@@ -50,6 +50,7 @@
+
diff --git a/BasicBlockChain/Block.cs b/BasicBlockChain/Block.cs
index d92b4f3..643403f 100644
--- a/BasicBlockChain/Block.cs
+++ b/BasicBlockChain/Block.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
@@ -9,25 +10,38 @@ namespace BasicBlockChain
public int Index { get; set; }
public DateTime Date { get; set; }
public string PreviousHash { get; set; }
- public string Data { get; set; }
+ public List Transactions { get; } = new List();
public string Hash { get; set; }
public int Nonce { get; set; }
- public Block(DateTime date, Block previousBlock, string data)
+ public Block(DateTime date, Block previousBlock, IList transactions)
{
Index = (previousBlock?.Index ?? -1) + 1;
Date = date;
PreviousHash = previousBlock?.Hash;
- Data = data;
+ if (transactions != null) { Transactions.AddRange(transactions); }
Nonce = 0;
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);
string hash = Convert.ToBase64String(hashBytes);
@@ -36,11 +50,13 @@ namespace BasicBlockChain
public void Mine(int difficulty)
{
+ SHA256 sha256 = SHA256.Create();
var leadingZeros = new string('0', difficulty);
+ string data = GetData();
while (Hash.Substring(0, difficulty) != leadingZeros)
{
Nonce++;
- Hash = CalculateHash();
+ Hash = CalculateHash(data, sha256);
}
}
}
diff --git a/BasicBlockChain/BlockChain.cs b/BasicBlockChain/BlockChain.cs
index 69e1a34..3f34b3c 100644
--- a/BasicBlockChain/BlockChain.cs
+++ b/BasicBlockChain/BlockChain.cs
@@ -11,16 +11,16 @@ namespace BasicBlockChain
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);
Difficulty = difficulty;
Chain.Add(genesisBlock);
}
- public void AddData(DateTime date, string data)
+ public void AddBlock(DateTime date, IList transactions)
{
Block lastBlock = Chain.Last();
- Block newBlock = new Block(date, lastBlock, data);
+ Block newBlock = new Block(date, lastBlock, transactions);
newBlock.Mine(Difficulty);
Chain.Add(newBlock);
}
@@ -40,5 +40,30 @@ namespace BasicBlockChain
}
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;
+ }
}
}
diff --git a/BasicBlockChain/Program.cs b/BasicBlockChain/Program.cs
index 42c4dd2..3d27a7e 100644
--- a/BasicBlockChain/Program.cs
+++ b/BasicBlockChain/Program.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace BasicBlockChain
{
@@ -13,9 +14,9 @@ namespace BasicBlockChain
Console.WriteLine("#### Mining BlockChain with sample data");
var startTime = DateTime.UtcNow;
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.AddData(new DateTime(2000, 1, 3), "{ sender: NAM, receiver: VAR, amount: 5.00}");
- nullCoin.AddData(new DateTime(2000, 1, 4), "{ sender: NAM, receiver: VAR, amount: 5.00}");
+ nullCoin.AddBlock(new DateTime(2000, 1, 2), new List { new Transaction("VAR", "NAM", 10_000_000) });
+ nullCoin.AddBlock(new DateTime(2000, 1, 3), new List { new Transaction("NAM", "VAR", 5_000_000) });
+ nullCoin.AddBlock(new DateTime(2000, 1, 4), new List { new Transaction("NAM", "VAR", 5_000_000) });
Console.WriteLine(jsonWriter.Write(nullCoin));
var endTime = DateTime.UtcNow;
Console.WriteLine($"Duration: {endTime - startTime}");
@@ -23,14 +24,21 @@ namespace BasicBlockChain
// Verify
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
Console.WriteLine();
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));
// Verify
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();
}
diff --git a/BasicBlockChain/Transaction.cs b/BasicBlockChain/Transaction.cs
new file mode 100644
index 0000000..39e4750
--- /dev/null
+++ b/BasicBlockChain/Transaction.cs
@@ -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;
+ }
+ }
+}