-
Notifications
You must be signed in to change notification settings - Fork 0
/
block.js
96 lines (83 loc) · 3.95 KB
/
block.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
/**
* Block class
* The Block class is a main component into any Blockchain platform,
* it will store the data and act as a dataset for your application.
* The class will expose a method to validate the data... The body of
* the block will contain an Object that contain the data to be stored,
* the data should be stored encoded.
* All the exposed methods should return a Promise to allow all the methods
* run asynchronous.
*/
const SHA256 = require('crypto-js/sha256');
const hex2ascii = require('hex2ascii');
class Block {
// Constructor - argument data will be the object containing the transaction data
constructor(data){
this.hash = null; // Hash of the block
this.height = 0; // Block Height (consecutive number of each block)
this.body = Buffer(JSON.stringify(data)).toString('hex'); // Will contain the transactions stored in the block, by default it will encode the data
this.time = 0; // Timestamp for the Block creation
this.previousBlockHash = null; // Reference to the previous Block Hash
}
/**
* validate() method will validate if the block has been tampered or not.
* Been tampered means that someone from outside the application tried to change
* values in the block data as a consequence the hash of the block should be different.
* Steps:
* 1. Return a new promise to allow the method be called asynchronous.
* 2. Save the in auxiliary variable the current hash of the block (`this` represent the block object)
* 3. Recalculate the hash of the entire block (Use SHA256 from crypto-js library)
* 4. Compare if the auxiliary hash value is different from the calculated one.
* 5. Resolve true or false depending if it is valid or not.
* Note: to access the class values inside a Promise code you need to create an auxiliary value `let self = this;`
*/
validate() {
let self = this;
return new Promise((resolve, reject) => {
// Save in auxiliary variable the current block hash
const current_hash = self.hash
// Remove the hash from the block
self.hash = null;
// Recalculate the hash of the Block
const recalculated_hash = SHA256(JSON.stringify(self)).toString();
// Comparing if the hashes changed
// Returning the Block is valid
if (current_hash === recalculated_hash) {
resolve(self);
}
// Returning the Block is not valid
else {
reject(Error("Block has been tampered!"));
}
});
}
/**
* Auxiliary Method to return the block body (decoding the data)
* Steps:
*
* 1. Use hex2ascii module to decode the data
* 2. Because data is a javascript object use JSON.parse(string) to get the Javascript Object
* 3. Resolve with the data and make sure that you don't need to return the data for the `genesis block`
* or Reject with an error.
*/
getBData() {
let self = this;
return new Promise((resolve, reject) => {
// Getting the encoded data saved in the Block
const encoded_data = self.body;
// Decoding the data to retrieve the JSON representation of the object
const decoded_data = JSON.parse(hex2ascii(encoded_data));
// Parse the data to an object to be retrieve.
self.body = decoded_data;
// Resolve with the data if the object isn't the Genesis block
if (self.body.data !== 'Genesis Block') {
resolve(self);
}
else {
// Returning the Genesis Block
reject(Error("Genesis Block!"));
}
});
}
}
module.exports.Block = Block; // Exposing the Block class as a module