commit
1369cac209
|
@ -102,3 +102,5 @@ ENV/
|
|||
|
||||
# PyCharm
|
||||
.idea/
|
||||
|
||||
node_modules/
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
const crypto = require("crypto");
|
||||
|
||||
|
||||
class Blockchain {
|
||||
constructor() {
|
||||
this.chain = [];
|
||||
this.pendingTransactions = [];
|
||||
this.newBlock();
|
||||
this.peers = new Set();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a node to our peer table
|
||||
*/
|
||||
addPeer(host) {
|
||||
this.peers.add(host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a node to our peer table
|
||||
*/
|
||||
getPeers() {
|
||||
return Array.from(this.peers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new block containing any outstanding transactions
|
||||
*/
|
||||
newBlock(previousHash, nonce = null) {
|
||||
let block = {
|
||||
index: this.chain.length,
|
||||
timestamp: new Date().toISOString(),
|
||||
transactions: this.pendingTransactions,
|
||||
previousHash,
|
||||
nonce
|
||||
};
|
||||
|
||||
block.hash = Blockchain.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
|
||||
*/
|
||||
static hash(block) {
|
||||
const blockString = JSON.stringify(block, Object.keys(block).sort());
|
||||
return crypto.createHash("sha256").update(blockString).digest("hex");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 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
|
||||
*/
|
||||
static powIsAcceptable(hashOfBlock, difficulty) {
|
||||
return hashOfBlock.slice(0, difficulty) === "0".repeat(difficulty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random 32 byte string
|
||||
*/
|
||||
static 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.
|
||||
*/
|
||||
mine(blockToMine = null, difficulty = 4) {
|
||||
const block = blockToMine || this.lastBlock();
|
||||
|
||||
while (true) {
|
||||
block.nonce = Blockchain.nonce();
|
||||
if (Blockchain.powIsAcceptable(Blockchain.hash(block), difficulty)) {
|
||||
console.log("We mined a block!")
|
||||
console.log(` - Block hash: ${Blockchain.hash(block)}`);
|
||||
console.log(` - nonce: ${block.nonce}`);
|
||||
return block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Blockchain;
|
|
@ -0,0 +1,37 @@
|
|||
const Blockchain = require("./blockchain");
|
||||
const {send} = require("micro");
|
||||
|
||||
const blockchain = new Blockchain();
|
||||
|
||||
|
||||
module.exports = async (request, response) => {
|
||||
const route = request.url;
|
||||
|
||||
// Keep track of the peers that have contacted us
|
||||
blockchain.addPeer(request.headers.host);
|
||||
|
||||
let output;
|
||||
|
||||
switch (route) {
|
||||
case "/new_block":
|
||||
output = blockchain.newBlock();
|
||||
break;
|
||||
|
||||
case "/last_block":
|
||||
output = blockchain.lastBlock();
|
||||
break;
|
||||
|
||||
case "/get_peers":
|
||||
output = blockchain.getPeers();
|
||||
break;
|
||||
|
||||
case "/submit_transaction":
|
||||
output = blockchain.addTransaction(transaction);
|
||||
break;
|
||||
|
||||
default:
|
||||
output = blockchain.lastBlock();
|
||||
|
||||
}
|
||||
send(response, 200, output);
|
||||
};
|
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": {
|
||||
"dev": "nodemon blockchain.js",
|
||||
"server": "micro-dev"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"micro": "^9.3.4",
|
||||
"micro-dev": "^3.0.0",
|
||||
"nodemon": "^1.19.0"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue