Transactions
This commit is contained in:
@@ -50,6 +50,7 @@
|
||||
<Compile Include="BlockChain.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Transaction.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
|
||||
@@ -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<Transaction> Transactions { get; } = new List<Transaction>();
|
||||
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<Transaction> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Transaction> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Transaction> { new Transaction("VAR", "NAM", 10_000_000) });
|
||||
nullCoin.AddBlock(new DateTime(2000, 1, 3), new List<Transaction> { new Transaction("NAM", "VAR", 5_000_000) });
|
||||
nullCoin.AddBlock(new DateTime(2000, 1, 4), new List<Transaction> { 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();
|
||||
}
|
||||
|
||||
16
BasicBlockChain/Transaction.cs
Normal file
16
BasicBlockChain/Transaction.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user