Created
August 19, 2018 10:38
-
-
Save MichalZalecki/450bffb7b6361589b070b60b2c3eccfa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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