Added js blockchain class
This commit is contained in:
parent
28d3ee8c16
commit
bb067e7f0a
|
@ -102,3 +102,5 @@ ENV/
|
||||||
|
|
||||||
# PyCharm
|
# PyCharm
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
node_modules/
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
const crypto = require("crypto");
|
||||||
|
|
||||||
|
|
||||||
|
class Blockchain {
|
||||||
|
constructor() {
|
||||||
|
this.chain = [];
|
||||||
|
this.pendingTransactions = [];
|
||||||
|
this.newBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new block containing any outstanding transactions
|
||||||
|
*
|
||||||
|
* @param previousHash: the hash of the previous block
|
||||||
|
* @param nonce: the random string used to make this block hash satisfy the difficulty requirements
|
||||||
|
*/
|
||||||
|
newBlock(previousHash, nonce = null) {
|
||||||
|
let block = {
|
||||||
|
index: this.chain.length,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
transactions: this.pendingTransactions,
|
||||||
|
previousHash,
|
||||||
|
nonce
|
||||||
|
};
|
||||||
|
|
||||||
|
block.hash = this.hash(block);
|
||||||
|
|
||||||
|
console.log(`Created block ${block.index}`);
|
||||||
|
|
||||||
|
// Add the new block to the blockchain
|
||||||
|
this.chain.push(block);
|
||||||
|
|
||||||
|
// Reset pending transactions
|
||||||
|
this.pendingTransactions = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a SHA-256 hash of the block
|
||||||
|
* @param block
|
||||||
|
*/
|
||||||
|
hash(block) {
|
||||||
|
const blockString = JSON.stringify(block, Object.keys(block).sort());
|
||||||
|
return crypto.createHash("sha256").update(blockString).digest("hex");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the last block in the chain
|
||||||
|
*/
|
||||||
|
lastBlock() {
|
||||||
|
return this.chain.length && this.chain[this.chain.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a hash begins with a "difficulty" number of 0s
|
||||||
|
*
|
||||||
|
* @param hashOfBlock: the hash of the block (hex string)
|
||||||
|
* @param difficulty: an integer defining the difficulty
|
||||||
|
*/
|
||||||
|
powIsAcceptable(hashOfBlock, difficulty) {
|
||||||
|
return hashOfBlock.slice(0, difficulty) == "0".repeat(difficulty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a random 32 byte string
|
||||||
|
*/
|
||||||
|
nonce() {
|
||||||
|
return crypto.createHash("sha256").update(crypto.randomBytes(32)).digest("hex");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proof of Work mining algorithm
|
||||||
|
*
|
||||||
|
* We hash the block with random string until the hash begins with
|
||||||
|
* a "difficulty" number of 0s.
|
||||||
|
*
|
||||||
|
* @param _block: the block to be mined (defaults to the last block)
|
||||||
|
* @param difficulty: the mining difficulty to use
|
||||||
|
*/
|
||||||
|
proofOfWork(_block = null, difficulty = 4) {
|
||||||
|
const block = _block || this.lastBlock();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
block.nonce = this.nonce();
|
||||||
|
if (this.powIsAcceptable(this.hash(block), difficulty)) {
|
||||||
|
console.log("We mined a block!")
|
||||||
|
console.log(` - Block hash: ${this.hash(block)}`);
|
||||||
|
console.log(` - nonce: ${block.nonce}`);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const blockchain = new Blockchain();
|
||||||
|
blockchain.proofOfWork(null, 5);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"name": "blockchain",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"nodemon": "^1.19.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"dev": "nodemon blockchain.js"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue