1 | var crypto = require('crypto');
|
2 | var fs = require('fs');
|
3 | var cryptoLib = require('../lib/crypto.js');
|
4 | var transactionsLib = require('../lib/transactions.js');
|
5 | var accounts = require('./account.js');
|
6 | var ByteBuffer = require('bytebuffer');
|
7 |
|
8 | var sender = accounts.account(cryptoLib.generateSecret());
|
9 |
|
10 | function getBytes(block) {
|
11 | var size = 4 + 4 + 8 + 4 + 8 + 8 + 8 + 4 + 32 + 32 + 64;
|
12 |
|
13 | var bb = new ByteBuffer(size, true);
|
14 | bb.writeInt(block.version);
|
15 | bb.writeInt(block.timestamp);
|
16 |
|
17 | if (block.previousBlock) {
|
18 | var pb = bignum(block.previousBlock).toBuffer({size: '8'});
|
19 |
|
20 | for (var i = 0; i < 8; i++) {
|
21 | bb.writeByte(pb[i]);
|
22 | }
|
23 | } else {
|
24 | for (var i = 0; i < 8; i++) {
|
25 | bb.writeByte(0);
|
26 | }
|
27 | }
|
28 |
|
29 | bb.writeInt(block.numberOfTransactions);
|
30 | bb.writeLong(block.totalAmount);
|
31 | bb.writeLong(block.totalFee);
|
32 | bb.writeLong(block.reward);
|
33 |
|
34 | bb.writeInt(block.payloadLength);
|
35 |
|
36 | var payloadHashBuffer = new Buffer(block.payloadHash, 'hex');
|
37 | for (var i = 0; i < payloadHashBuffer.length; i++) {
|
38 | bb.writeByte(payloadHashBuffer[i]);
|
39 | }
|
40 |
|
41 | var generatorPublicKeyBuffer = new Buffer(block.generatorPublicKey, 'hex');
|
42 | for (var i = 0; i < generatorPublicKeyBuffer.length; i++) {
|
43 | bb.writeByte(generatorPublicKeyBuffer[i]);
|
44 | }
|
45 |
|
46 | if (block.blockSignature) {
|
47 | var blockSignatureBuffer = new Buffer(block.blockSignature, 'hex');
|
48 | for (var i = 0; i < blockSignatureBuffer.length; i++) {
|
49 | bb.writeByte(blockSignatureBuffer[i]);
|
50 | }
|
51 | }
|
52 |
|
53 | bb.flip();
|
54 | var b = bb.toBuffer();
|
55 |
|
56 | return b;
|
57 | }
|
58 |
|
59 | module.exports = {
|
60 | new: function (genesisAccount, dapp, accountsFile) {
|
61 | var payloadLength = 0,
|
62 | payloadHash = crypto.createHash('sha256'),
|
63 | transactions = [],
|
64 | totalAmount = 0,
|
65 | delegates = [];
|
66 |
|
67 |
|
68 | if (accountsFile && fs.existsSync(accountsFile)) {
|
69 | var lines = fs.readFileSync(accountsFile, 'utf8').split('\n');
|
70 | for (var i in lines) {
|
71 | var parts = lines[i].split('\t');
|
72 | if (parts.length != 2) {
|
73 | console.error('Invalid recipient balance format');
|
74 | process.exit(1);
|
75 | }
|
76 | var trs = {
|
77 | type: 0,
|
78 | amount: Number(parts[1]) * 100000000,
|
79 | fee: 0,
|
80 | timestamp: 0,
|
81 | recipientId: parts[0],
|
82 | senderId: sender.address,
|
83 | senderPublicKey: sender.keypair.publicKey
|
84 | };
|
85 | totalAmount += trs.amount;
|
86 |
|
87 | var bytes = transactionsLib.getTransactionBytes(trs);
|
88 | trs.signature = cryptoLib.sign(sender.keypair, bytes);
|
89 | bytes = transactionsLib.getTransactionBytes(trs);
|
90 | trs.id = cryptoLib.getId(bytes);
|
91 |
|
92 | transactions.push(trs);
|
93 | }
|
94 | } else {
|
95 | var balanceTransaction = {
|
96 | type: 0,
|
97 | amount: 10000000000000000,
|
98 | fee: 0,
|
99 | timestamp: 0,
|
100 | recipientId: genesisAccount.address,
|
101 | senderId: sender.address,
|
102 | senderPublicKey: sender.keypair.publicKey
|
103 | };
|
104 |
|
105 | totalAmount += balanceTransaction.amount;
|
106 |
|
107 | var bytes = transactionsLib.getTransactionBytes(balanceTransaction);
|
108 | balanceTransaction.signature = cryptoLib.sign(sender.keypair, bytes);
|
109 | bytes = transactionsLib.getTransactionBytes(balanceTransaction);
|
110 | balanceTransaction.id = cryptoLib.getId(bytes);
|
111 |
|
112 | transactions.push(balanceTransaction);
|
113 | }
|
114 |
|
115 |
|
116 | for (var i = 0; i < 101; i++) {
|
117 | var delegate = accounts.account(cryptoLib.generateSecret());
|
118 | delegates.push(delegate);
|
119 |
|
120 | var username = "asch_g" + (i+1);
|
121 |
|
122 | var transaction = {
|
123 | type: 2,
|
124 | amount: 0,
|
125 | fee: 0,
|
126 | timestamp: 0,
|
127 | recipientId: null,
|
128 | senderId: delegate.address,
|
129 | senderPublicKey: delegate.keypair.publicKey,
|
130 | asset: {
|
131 | delegate: {
|
132 | username: username
|
133 | }
|
134 | }
|
135 | }
|
136 |
|
137 | bytes = transactionsLib.getTransactionBytes(transaction);
|
138 | transaction.signature = cryptoLib.sign(sender.keypair, bytes);
|
139 | bytes = transactionsLib.getTransactionBytes(transaction);
|
140 | transaction.id = cryptoLib.getId(bytes);
|
141 |
|
142 | transactions.push(transaction);
|
143 | }
|
144 |
|
145 |
|
146 | var votes = delegates.map(function (delegate) {
|
147 | return "+" + delegate.keypair.publicKey;
|
148 | });
|
149 |
|
150 | var voteTransaction = {
|
151 | type: 3,
|
152 | amount: 0,
|
153 | fee: 0,
|
154 | timestamp: 0,
|
155 | recipientId: null,
|
156 | senderId: genesisAccount.address,
|
157 | senderPublicKey: genesisAccount.keypair.publicKey,
|
158 | asset: {
|
159 | vote: {
|
160 | votes: votes
|
161 | }
|
162 | }
|
163 | }
|
164 |
|
165 | bytes = transactionsLib.getTransactionBytes(voteTransaction);
|
166 | voteTransaction.signature = cryptoLib.sign(genesisAccount.keypair, bytes);
|
167 | bytes = transactionsLib.getTransactionBytes(voteTransaction);
|
168 | voteTransaction.id = cryptoLib.getId(bytes);
|
169 |
|
170 | transactions.push(voteTransaction);
|
171 |
|
172 | var dappTransaction = null;
|
173 | if (dapp) {
|
174 | dappTransaction = {
|
175 | type: 5,
|
176 | amount: 0,
|
177 | fee: 0,
|
178 | timestamp: 0,
|
179 | recipientId: null,
|
180 | senderId: genesisAccount.address,
|
181 | senderPublicKey: genesisAccount.keypair.publicKey,
|
182 | asset: {
|
183 | dapp: dapp
|
184 | }
|
185 | };
|
186 |
|
187 | bytes = transactionsLib.getTransactionBytes(dappTransaction);
|
188 | dappTransaction.signature = cryptoLib.sign(genesisAccount.keypair, bytes);
|
189 | bytes = transactionsLib.getTransactionBytes(dappTransaction);
|
190 | dappTransaction.id = cryptoLib.getId(bytes);
|
191 |
|
192 | transactions.push(dappTransaction);
|
193 | }
|
194 |
|
195 | transactions = transactions.sort(function compare(a, b) {
|
196 | if (a.type != b.type) {
|
197 | if (a.type == 1) {
|
198 | return 1;
|
199 | }
|
200 | if (b.type == 1) {
|
201 | return -1;
|
202 | }
|
203 | return a.type - b.type;
|
204 | }
|
205 | if (a.amount != b.amount) {
|
206 | return a.amount - b.amount;
|
207 | }
|
208 | return a.id.localeCompare(b.id);
|
209 | });
|
210 |
|
211 | transactions.forEach(function (tx) {
|
212 | bytes = transactionsLib.getTransactionBytes(tx);
|
213 | payloadLength += bytes.length;
|
214 | payloadHash.update(bytes);
|
215 | });
|
216 |
|
217 | payloadHash = payloadHash.digest();
|
218 |
|
219 | var block = {
|
220 | version: 0,
|
221 | totalAmount: totalAmount,
|
222 | totalFee: 0,
|
223 | reward: 0,
|
224 | payloadHash: payloadHash.toString('hex'),
|
225 | timestamp: 0,
|
226 | numberOfTransactions: transactions.length,
|
227 | payloadLength: payloadLength,
|
228 | previousBlock: null,
|
229 | generatorPublicKey: sender.keypair.publicKey,
|
230 | transactions: transactions,
|
231 | height: 1
|
232 | };
|
233 |
|
234 | bytes = getBytes(block);
|
235 | block.blockSignature = cryptoLib.sign(sender.keypair, bytes);
|
236 | bytes = getBytes(block);
|
237 | block.id = cryptoLib.getId(bytes);
|
238 |
|
239 | return {
|
240 | block: block,
|
241 | dapp: dappTransaction,
|
242 | delegates: delegates
|
243 | };
|
244 | },
|
245 |
|
246 | from: function (genesisBlock, genesisAccount, dapp) {
|
247 | for (var i in genesisBlock.transactions) {
|
248 | var tx = genesisBlock.transactions[i];
|
249 |
|
250 | if (tx.type == 5) {
|
251 | if (tx.asset.dapp.name == dapp.name) {
|
252 | throw new Error("DApp with name '" + dapp.name + "' already exists in genesis block");
|
253 | }
|
254 |
|
255 | if (tx.asset.dapp.git == dapp.git) {
|
256 | throw new Error("DApp with git '" + dapp.git + "' already exists in genesis block");
|
257 | }
|
258 |
|
259 | if (tx.asset.dapp.link == dapp.link) {
|
260 | throw new Error("DApp with link '" + dapp.link + "' already exists in genesis block");
|
261 | }
|
262 | }
|
263 | }
|
264 |
|
265 | var dappTransaction = {
|
266 | type: 5,
|
267 | amount: 0,
|
268 | fee: 0,
|
269 | timestamp: 0,
|
270 | recipientId: null,
|
271 | senderId: genesisAccount.address,
|
272 | senderPublicKey: genesisAccount.keypair.publicKey,
|
273 | asset: {
|
274 | dapp: dapp
|
275 | }
|
276 | };
|
277 |
|
278 | var bytes = transactionsLib.getTransactionBytes(dappTransaction);
|
279 | dappTransaction.signature = cryptoLib.sign(genesisAccount.keypair, bytes);
|
280 | bytes = transactionsLib.getTransactionBytes(dappTransaction);
|
281 | dappTransaction.id = cryptoLib.getId(bytes);
|
282 |
|
283 | genesisBlock.payloadLength += bytes.length;
|
284 | var payloadHash = crypto.createHash('sha256').update(new Buffer(genesisBlock.payloadHash, 'hex'));
|
285 | payloadHash.update(bytes);
|
286 | genesisBlock.payloadHash = payloadHash.digest().toString('hex');
|
287 |
|
288 | genesisBlock.transactions.push(dappTransaction);
|
289 | genesisBlock.numberOfTransactions += 1;
|
290 | genesisBlock.generatorPublicKey = sender.keypair.publicKey;
|
291 |
|
292 | bytes = getBytes(genesisBlock);
|
293 | genesisBlock.blockSignature = cryptoLib.sign(sender.keypair, bytes);
|
294 | bytes = getBytes(genesisBlock);
|
295 | genesisBlock.id = cryptoLib.getId(bytes);
|
296 |
|
297 | return {
|
298 | block: genesisBlock,
|
299 | dapp: dappTransaction
|
300 | };
|
301 | }
|
302 | }
|