-
Notifications
You must be signed in to change notification settings - Fork 2.8k
/
Copy pathblockchain.js
105 lines (87 loc) · 2.64 KB
/
blockchain.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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
with RPoW and Mining Efficiency
*
* 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;