Skip to content

Instantly share code, notes, and snippets.

@maxpert
Last active July 30, 2018 08:40
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save maxpert/bb488b2024ae92b0b3ab65c77113eef1 to your computer and use it in GitHub Desktop.
51873 Blockchain

A toy blockchain implementation made for fun.

Implements:

  • Basic in-memory blockchain
  • Basic Proof of work
  • Methods to serialize/deserialize complete chain

Again none of this is supposed to be production ready.

const crypto = require('crypto');
let blockchain = [];
class BlockchainError extends Error {
constructor(message) {
super(message);
Error.captureStackTrace(this, this.constructor);
}
}
function sha256(value) {
return crypto.createHash('sha256', '').update(`${value}`).digest("hex")
}
function hash(parent_hash, timestamp, data) {
return sha256(`${parent_hash}-${timestamp}-${JSON.stringify(data)}`);
}
function append({parent_hash, timestamp, data}) {
if (!(parent_hash && timestamp && data)) {
throw new Error('Invalid block');
}
if (blockchain.length) {
const lastBlock = blockchain[blockchain.length - 1];
if (lastBlock.hash !== parent_hash) {
throw new BlockchainError(`Can not append child for ${parent_hash} after ${lastBlock.parent_hash}`)
}
}
blockchain.push({
parent_hash,
timestamp,
data,
hash: hash(parent_hash, timestamp, data)
});
return true;
}
function proven(str) {
return str.startsWith("51873");
}
function proofOfWork(previous) {
let next = previous + 1;
let hash = sha256(next);
while (!proven(hash)) {
hash = sha256(++next);
}
return next;
}
function mine(payload) {
while (true) {
try {
const lastBlock = blockchain[blockchain.length - 1];
const proof = proofOfWork(lastBlock.data.proof);
const newBlock = {
parent_hash: lastBlock.hash,
timestamp: new Date().getTime(),
data: {
proof,
payload,
proof_digest: sha256(proof)
}
};
appended = append(newBlock);
return newBlock;
} catch (e) {
if (e instanceof BlockchainError) {
continue;
}
throw e;
}
}
}
function boot() {
if (blockchain.length === 0) {
append({
parent_hash: "~",
timestamp: new Date().getTime(),
data: {
proof: 0,
payload: []
}
});
}
}
function serialize() {
return JSON.stringify(blockchain);
}
function deserialize(val) {
blockchain = JSON.parse(val);
}
function size() {
return blockchain.length;
}
module.exports = {
mine,
boot,
serialize,
deserialize,
size
};
const blockchain = require('./blockchain');
blockchain.boot();
while (true) {
console.log(
blockchain.mine([])
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment