forked from BCEssentials/DIY-Blockchain
-
Notifications
You must be signed in to change notification settings - Fork 0
/
validation.js
91 lines (79 loc) · 2.51 KB
/
validation.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
"use strict";
const { createHash } = require("crypto");
const signing = require("./signing");
/**
* A simple validation function for transactions. Accepts a transaction
* and returns true or false. It should reject transactions that:
* - have negative amounts
* - were improperly signed
* - have been modified since signing
*/
const isValidTransaction = (transaction) => {
if (transaction.amount < 0) return false;
if (
!signing.verify(
transaction.source,
transaction.source + transaction.recipient + transaction.amount,
transaction.signature
)
)
return false;
return true;
};
/**
* Validation function for blocks. Accepts a block and returns true or false.
* It should reject blocks if:
* - their hash or any other properties were altered
* - they contain any invalid transactions
*/
const isValidBlock = (block) => {
const transactionString = block.transactions
.map((t) => t.signature)
.toString();
const toHash = block.previousHash + transactionString + block.nonce;
if (block.hash !== createHash("sha512").update(toHash).digest("hex")) {
return false;
}
if (!block.transactions.every(isValidTransaction)) return false;
return true;
};
/**
* One more validation function. Accepts a blockchain, and returns true
* or false. It should reject any blockchain that:
* - is a missing genesis block
* - has any block besides genesis with a null hash
* - has any block besides genesis with a previousHash that does not match
* the previous hash
* - contains any invalid blocks
* - contains any invalid transactions
*/
const isValidChain = (blockchain) => {
if (blockchain.blocks[0].previousHash !== null) {
return false;
}
for (let i = 1; i < blockchain.blocks.length; i++) {
if (blockchain.blocks[i].previousHash !== blockchain.blocks[i - 1].hash)
return false;
}
for (let i = 1; i < blockchain.blocks.length; i++) {
if (!isValidBlock(blockchain.blocks[i])) return false;
}
return blockchain.blocks
.map((b) => b.transactions)
.reduce((flat, t) => flat.concat(t), [])
.every(isValidTransaction);
};
/**
* This last one is just for fun. Become a hacker and tamper with the passed in
* blockchain, mutating it for your own nefarious purposes. This should
* (in theory) make the blockchain fail later validation checks;
*/
const breakChain = (blockchain) => {
blockchain.blocks[1].transactions[0].amount = 576579;
};
module.exports = {
isValidTransaction,
isValidBlock,
isValidChain,
breakChain,
};