Transactions
This commit is contained in:
@@ -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" />
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
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