-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
84 lines (70 loc) · 2.58 KB
/
index.ts
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
import { Crypto } from 'cryptojs';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Block } from './block';
export class NaiveBlockChain {
public blockchain: BehaviorSubject<Block[]>;
constructor() {
this.blockchain = new BehaviorSubject([this.generateGenesisBlock()]);
}
/**
* Generate original unique block.
*/
private generateGenesisBlock() {
return new Block(0, "0", Date.now(), "Genesis Block", "89eb0ac031a63d2421cd05a2fbe41f3ea35f5c3712ca839cbf6b85c4ee07b7a3");
}
/**
* SHA256 encode the contents of a block
* @param index
* @param previousHash
* @param timestamp
* @param data
*/
private calculateHash(index: number, previousHash: String, timestamp: number, data: String) {
return Crypto.SHA256(`${index}${previousHash}${timestamp}${data}`);
}
/**
* Utility wrapper function for calculateHash
* @param block
*/
private calculateHashForBlock(block: Block) {
return this.calculateHash(block.index, block.previousHash, block.timestamp, block.data);
}
/**
* Validate block to ensure it belongs in the chain
* @param newBlock
* @param previousBlock
*/
private isValidNewBlock(newBlock: Block, previousBlock: Block) {
if(previousBlock.index + 1 !== newBlock.index) {
throw new Error('Invalid Index');
}
if(previousBlock.hash !== newBlock.previousHash) {
throw new Error('Invalid previous hash');
}
if(this.calculateHashForBlock(newBlock) !== newBlock.hash) {
throw new Error(`Invalid hash- expected: ${this.calculateHashForBlock(newBlock)}, received ${newBlock.hash}`);
}
return true;
}
/**
* Generates a new block and causes the chain to emit it's new overall value.
* @param blockData
*/
public generateNextBlock(blockData) {
let newBlock, newChain;
const currentChain = this.blockchain.getValue(),
[lastBlock] = currentChain.slice(-1),
nextIndex = (lastBlock.index + 1),
timestamp = Date.now(),
hash = this.calculateHash(nextIndex, lastBlock.hash, timestamp, blockData);
newBlock = new Block(nextIndex, lastBlock.hash, timestamp, blockData, hash);
if(this.isValidNewBlock(newBlock, lastBlock)) {
newChain = currentChain.concat([newBlock]);
console.info('New block added');
this.blockchain.next(newChain);
return newBlock;
} else {
return false;
}
}
}