-
Notifications
You must be signed in to change notification settings - Fork 0
/
blockchain.js
179 lines (164 loc) · 4.57 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
const sha1 = require('sha1');
/**
* [START BLOCKCHAIN CONSTRUCTOR]
* Constructor function
*/
function blockchain() {
this.blocks = [];
this.balances = [];
this.blockSize = null;
this.transactions = [];
this.addBlock(10, '0000000000000000000000000000000000000000', '0000000000000000000000000000000000000000');
};
// [END BLOCKCHAIN CONSTRUCTOR]
/**
* [START VERIFY TRANSACTION]
* @param { object } balance.
* @param { object } transaction.
* @return { boolean } boolean.
* Verify transaction
*/
blockchain.prototype.verifyTransaction = function(balance, transaction) {
try {
// TODO: verify transaction validity
if (!transaction || transaction.length != 3) {
throw new Error("Invalid transaction");
}
if(balance > transaction[2]) return true;
else return false;
} catch (error) {
console.info(error);
return error;
}
};
// [END VERIFY TRANSACTION]
/**
* [START BLOCK HASH]
* @param { string } prevBlockHash.
* @param { object } blockTransactions.
* @param { number } nonce.
* @return { string } hash.
* Block hash
*/
blockchain.prototype.getHash = function(prevBlockHash, blockTransactions, nonce) {
try {
// TODO: get hash string
const dataString = prevBlockHash + nonce.toString() + JSON.stringify(blockTransactions);
const hash = sha1(dataString);
return hash;
} catch (error) {
console.info(error);
return error;
}
};
// [END BLOCK HASH]
/**
* [START GET NONCE]
* @param { string } prevBlockHash.
* @param { object } blockTransactions.
* @return { number } hash.
* Nonce number
*/
blockchain.prototype.getNonce = function(prevBlockHash, blockTransactions) {
try {
// TODO: get nonce number
let nonce = 0;
let hash = this.getHash(prevBlockHash, blockTransactions, nonce);
while (hash.substring(0, 4) !== '1234') {
nonce++;
hash = this.getHash(prevBlockHash, blockTransactions, nonce);
}
return nonce;
} catch (error) {
console.info(error);
return error;
}
};
// [END GET NONCE]
/**
* [START ADD BLOCK]
* @param { number } nonce.
* @param { string } prevBlockHash.
* @param { string } hash.
* @return { object } block.
* Add block
*/
blockchain.prototype.addBlock = function(nonce, prevBlockHash, hash) {
try {
const block = {
index: this.blocks.length + 1,
timestamp: Date.now(),
transactions: this.transactions,
nonce: nonce,
hash: hash,
prevBlockHash: prevBlockHash
};
this.transactions = [];
this.blocks.push(block);
return block;
} catch (error) {
console.info(error);
return error;
}
};
// [END ADD BLOCK]
/**
* [START INITIALIZE BLOCKCHAIN]
* @param { object } balances.
* @param { object } transactions.
* @param { number } blockSize.
* @return { string } string.
* Initialize blockchain
*/
blockchain.prototype.init = function(balances, transactions, blockSize) {
try {
// TODO: initialize blockchain with parameters
if (!balances || !transactions || !blockSize)
return console.info('Initialization failed!');
this.balances.push(...balances);
this.blockSize = blockSize;
for (let i = 0; i < transactions.length; i++) {
let isValid = this.verifyTransaction(this.balances[transactions[i][0]], transactions[i]);
if (!isValid) {
continue;
}
this.balances[transactions[i][0]] -= transactions[i][2];
this.balances[transactions[i][1]] += transactions[i][2];
this.transactions.push(transactions[i]);
if(this.transactions.length == blockSize) {
const prevBlockHash = this.blocks[this.blocks.length - 1].hash;
const nonce = this.getNonce(prevBlockHash, this.transactions);
const hash = this.getHash(prevBlockHash, this.transactions, nonce);
const block = this.addBlock(nonce, prevBlockHash, hash);
// this.transactions = [];
// console.info(`Block ${this.blocks.length - 1} added:\n${block}`);
}
};
return 'Initialization Complete!';
} catch (error) {
console.info(error);
return error;
}
};
// [END INITIALIZE BLOCKCHAIN]
/**
* [START GET ACCOUNT BALANCE]
* @param { number } index.
* @return { number } balance.
* Account balance
*/
blockchain.prototype.getAccountBalance = function(index) {
try {
// TODO: get account balance for a given index
if (index < 0 || index >= this.balances.length)
return console.info('Invalid index!');
const balance = this.balances[index];
if (!balance) return null;
else return balance;
} catch (error) {
console.info(error);
return error;
}
};
// [END GET ACCOUNT BALANCE]
module.exports = blockchain;