Thought I would explore basic block chain structure to get a better feel from the ground up as a technology.
First up I needed a way to build hashes, for this I use the built in C# SHA256 library. Its a little ugly to use so I wrapped in in a simple extension function.
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using static System.Text.Encoding;
namespace BasicBlock
{
public static class Hashing
{
public static string ToHash(this string stringToHash)
=> SHA256
.Create()
.ComputeHash(UTF8.GetBytes(stringToHash))
.ToHashString();
private static string ToHashString(this byte[] hash)
=> hash
.Aggregate(
new StringBuilder(),
(builder, nextByte) => builder.Append(nextByte.ToString("X2")))
.ToString();
}
}
So we convert the supplied string into a byte array so we can compute the hash. The resulting byte array is then converted into hex string representation with some LINQ fun.
Next up an interface for objects that support hashing for the block chain. The payload for the block will be generic as you will see shortly.
namespace BasicBlock
{
public interface IHashable
{
string Hash { get; }
}
}
So now the block, not actually a lot of code. It takes a generic payload hence the generic type signatures and the requirement for the payload to be hashable.
public class Block<T> : IHashable
where T : IHashable
{
public const string NullHash = "0";
public static readonly Block<T> GenesisBlock = new Block<T>();
private Block()
{
TimeStamp = Now.ToUniversalTime();
PreviousBlock = null;
Payload = default(T);
Hash = CreateHash(TimeStamp, null, Payload);
}
private Block(
DateTime timeStamp,
Block<T> previousBlock,
T payload,
string blockHash)
{
TimeStamp = timeStamp;
PreviousBlock = previousBlock;
Payload = payload;
Hash = blockHash;
}
public DateTime TimeStamp { get; }
public Block<T> PreviousBlock { get; }
public T Payload { get; }
public string Hash { get; }
public Block<T> AddBlock(T payload)
{
var timestamo = Now.ToUniversalTime();
var blockHash = CreateHash(timestamo, Hash, payload);
return new Block<T>(Now.ToUniversalTime(), this, payload, blockHash);
}
public Block<T> AddBlock(
DateTime timeStamp,
Block<T> previousBlock,
T payload,
string blockHash)
{
return new Block<T>(timeStamp, this, payload, blockHash);
}
private static string CreateHash(
DateTime timeStamp,
string previousBlockHash,
IHashable payload)
=> new StringBuilder()
.Append(timeStamp.ToString())
.Append(previousBlockHash ?? NullHash)
.Append(payload?.Hash ?? NullHash)
.ToString()
.ToHash();
}
}
So a few simple house keeping immutable properties, it is assumed that any payload is also immutable.
Finally a simple example payload, turns the chain into a notebook.
namespace BasicBlock
{
public class Notepad : IHashable
{
public Notepad(string title, string note)
{
Title = title;
Note = note;
}
public string Title { get; }
public string Note { get; }
public string Hash => (Title + Note).ToHash();
}
}
I will look at some simple node server code when I get some time. For now it feels solid enough.
Happy coding
Woz