-
Notifications
You must be signed in to change notification settings - Fork 0
/
privateChain.js
116 lines (107 loc) · 4.38 KB
/
privateChain.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
106
107
108
109
110
111
112
113
114
115
116
/* ===== SHA256 with Crypto-js ===============================
| Learn more: Crypto-js: https://github.com/brix/crypto-js |
| =========================================================*/
const SHA256 = require('crypto-js/sha256');
const levelDB = require('./levelDb');
const Block = require('./block');
/* ===== Blockchain Class ==========================
| Class with a constructor for new blockchain |
| ================================================*/
class PrivateChain {
constructor(){
//Get block height from levelDB
this.getBlockHeight().then(height => {
//Check if block height is 0
console.log('Height of Blockchain: ' + height);
if (height === -1) {
//Create the Genesis Block - The first block in the blockchain
this.addBlock(
new Block('First block in the chain - Genesis block')
).then(() => console.log('Genesis Block created!'))
.then(() => this.addBlock(new Block('Second Block')))
.then(() => this.addBlock(new Block('Third Block')))
.then(() => this.addBlock(new Block('Fourth Block')))
.then(() => this.addBlock(new Block('Fifth Block')))
.then(() => this.addBlock(new Block('Sixth Block')))
.then(() => this.addBlock(new Block('Seventh Block')))
.then(() => this.addBlock(new Block('Eight Block')))
.then(() => this.addBlock(new Block('Ninth Block')))
.then(() => this.addBlock(new Block('Tenth Block')))
}
});
};
// Add new block
async addBlock(newBlock){
//Get block height from levelDB
const height = await this.getBlockHeight();
newBlock.height = height + 1;
//Generate block timestamp
newBlock.time = new Date().getTime().toString().slice(0, -3);
//Check if the Block is not Genesis Block
if (newBlock.height > 0) {
//Get the block
const prevBlock = await this.getBlock(height.toString());
//Get previous block's hash
newBlock.previousBlockHash = prevBlock.hash;
console.log('Previous Hash: ' + newBlock.previousBlockHash)
}
//Generate hash for the new block.
newBlock.hash = SHA256(JSON.stringify(newBlock)).toString();
console.log('Next Hash: ' + newBlock.hash);
//Save the block created to levelDB
await levelDB.addLevelDBBlock(newBlock.height.toString(), JSON.stringify(newBlock))
};
// Get block height
async getBlockHeight(){
//Return block height from levelDB
let blockHeight = await levelDB.getLevelBlockHeight();
return blockHeight;
};
// get block
async getBlock(blockHeight){
//Return block data from levelDB
let block = await levelDB.getLevelBlock(blockHeight);
return block;
};
// validate block
async validateBlock(blockHeight){
// Get block height from levelDB
const block = await this.getBlock(blockHeight);
// get block hash
let blockHash = block.hash;
// remove block hash to test block integrity
block.hash = '';
// generate block hash
let validBlockHash = SHA256(JSON.stringify(block)).toString();
// Compare
if (blockHash === validBlockHash) {
return true;
} else {
console.log('Block #'+blockHeight+' invalid hash:\n'+blockHash+'<>'+ validBlockHash);
return false;
}
};
// Validate blockchain
async validateChain(){
let errorLog = [];
let chain = await this.getBlockHeight();
for (var i = 0; i < chain.length-1; i++) {
// validate block
const validBlock = await this.validateBlock(i);
if (!validBlock)errorLog.push(i);
// compare blocks hash link
let blockHash = await chain[i].hash;
let previousHash = await chain[i+1].previousBlockHash;
if (blockHash!==previousHash) {
errorLog.push(i);
}
}
if (errorLog.length > 0) {
console.log('Block errors = ' + errorLog.length);
console.log('Blocks: '+errorLog);
} else {
console.log('No errors detected');
}
};
}
module.exports = PrivateChain;