Skip to content

Instantly share code, notes, and snippets.

@MichalZalecki
Created August 19, 2018 10:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MichalZalecki/450bffb7b6361589b070b60b2c3eccfa to your computer and use it in GitHub Desktop.
Save MichalZalecki/450bffb7b6361589b070b60b2c3eccfa to your computer and use it in GitHub Desktop.
import { performance } from "perf_hooks";
import { SHA256 as sha256 } from "crypto-js";
function calculateTarget(difficulty: number): number {
return Math.ceil(2 ** 256 / difficulty);
}
function padLeft(str: string, to: number, chr: string): string {
return str.length < to ? padLeft(chr + str, to, chr) : str;
}
class Block {
public hash: string;
public nonce: number = 0;
constructor(
public index: number,
public prevHash: string,
public timestamp: number,
public data: any,
public difficulty: number,
) {
this.hash = this.calculateHash();
}
calculateHash(): string {
return sha256(
this.index +
this.prevHash +
this.timestamp +
JSON.stringify(this.data)
).toString();
}
mine() {
const target = calculateTarget(this.difficulty);
while (
parseInt(sha256(this.hash + this.nonce).toString(), 16) > target
) {
this.nonce++;
}
}
}
class Blockchain {
public difficulty = 10000;
public blocks: Block[] = [
new Block(0, "", Date.now(), "Genesis block!", 0)
];
isBlockValid(block: Block): boolean {
const prev = this.blocks[block.index - 1];
if (block.prevHash !== prev.hash) return false;
const target = calculateTarget(block.difficulty);
if (parseInt(sha256(block.calculateHash() + block.nonce).toString(), 16) > target) return false;
return true;
}
isBlockchainValid(): boolean {
for (let i = 1; i < this.blocks.length; i++) {
if (!this.isBlockValid(this.blocks[i])) return false;
}
return true;
}
addBlock(block: Block) {
if (!this.isBlockValid(block)) throw new Error("Invalid block");
this.blocks.push(block);
}
}
const blockchain = new Blockchain();
const start = performance.now();
for (let i = 1; i <= 10; i++) {
const prev = blockchain.blocks[blockchain.blocks.length - 1];
const block = new Block(i, prev.hash, Date.now(), { amount: i * 100 }, blockchain.difficulty);
console.log(`Mining block #${i}`);
block.mine();
blockchain.addBlock(block);
}
// blockchain.blocks[2].data = { amount: 99999999999999 }
console.log(blockchain.isBlockchainValid());
console.log((performance.now() - start) / 1000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment