// ==========================================================================
// Author: Tim Hsu
// Date: 9/11/2018
//
// Desc: Simplified version of a blockchain, not DLT (distributed ledger technology)
// Demonstrate creating a block, and chaining them together as you add block.
// The chain is supported by its hash and the previous block hash, which can
// be verified (as proof of work) to ensure data integrity
//
// References:
// https://hackernoon.com/learn-blockchains-by-building-one-117428612f46
// https://github.com/dvf/blockchain
// ==========================================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace Blockchain
{
class Block
{
public DateTime Timestamp { get; set; }
public string PrevHash { get; set; }
public string Content { get; set; }
}
class Blockchain
{
private string filepath = "\\BlockFolder";
private string filename = "\\INDEX";
public Blockchain()
{
// create folder
this.filepath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + this.filepath;
this.filename = this.filepath + this.filename;
Directory.CreateDirectory(filepath);
if (!File.Exists(filename))
CreateEmptyBlock("");
}
private void CreateEmptyBlock(string hash_str)
{
Block b = new Block()
{
Timestamp = DateTime.UtcNow,
PrevHash = hash_str,
Content = string.Empty
};
File.WriteAllText(filename, JsonConvert.SerializeObject(b));
}
public void AddBlock(Block b)
{
string json_str = File.ReadAllText(this.filename);
Block prev_block = JsonConvert.DeserializeObject<Block>(json_str);
// prepare and add new block
b.Timestamp = DateTime.UtcNow;
b.PrevHash = prev_block.PrevHash;
json_str = JsonConvert.SerializeObject(b);
string hash_str = Utility.ComputeSha256Hash(json_str);
File.WriteAllText(filename, json_str);
File.Move(filename, this.filepath + "\\" + hash_str);
CreateEmptyBlock(hash_str);
}
public Block GetBlock(int n) // n is how far back from dummy block
{
string json_str = File.ReadAllText(this.filename);
Block b = JsonConvert.DeserializeObject<Block>(json_str);
for (int i = 0; i < n; i++)
{
string filename = this.filepath + "\\" + b.PrevHash;
if (!File.Exists(filename))
return null;
json_str = File.ReadAllText(filename);
b = JsonConvert.DeserializeObject<Block>(json_str);
}
return b;
}
public bool VerifyBlockChain() // proof of work
{
try
{
string json_str = File.ReadAllText(this.filename);
Block b = JsonConvert.DeserializeObject<Block>(json_str);
do
{
string filename = this.filepath + "\\" + b.PrevHash;
if (!File.Exists(filename))
return false;
json_str = File.ReadAllText(filename);
string hash = Utility.ComputeSha256Hash(json_str);
if (b.PrevHash != hash)
return false;
b = JsonConvert.DeserializeObject<Block>(json_str);
}
while (!string.IsNullOrEmpty(b.PrevHash));
return true;
}
catch { }
return false;
}
}
}