@leocuvee/turtlecoin-utils 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +27 -0
- package/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.idea/inspectionProfiles/Project_Default.xml +7 -0
- package/.idea/misc.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/turtlecoin-utils.iml +12 -0
- package/.idea/vcs.xml +6 -0
- package/.travis.yml +11 -0
- package/CONTRIBUTING.md +3 -0
- package/LICENSE +674 -0
- package/README.md +203 -0
- package/config.json +7 -0
- package/docs/.nojekyll +0 -0
- package/docs/CNAME +1 -0
- package/docs/assets/css/main.css +2321 -0
- package/docs/assets/images/icons.png +0 -0
- package/docs/assets/images/icons@2x.png +0 -0
- package/docs/assets/images/widgets.png +0 -0
- package/docs/assets/images/widgets@2x.png +0 -0
- package/docs/assets/js/main.js +1 -0
- package/docs/assets/js/search.js +3 -0
- package/docs/classes/address.html +964 -0
- package/docs/classes/addressprefix.html +431 -0
- package/docs/classes/block.html +965 -0
- package/docs/classes/blocktemplate.html +695 -0
- package/docs/classes/cryptonote.html +1137 -0
- package/docs/classes/ed25519.keypair.html +400 -0
- package/docs/classes/ed25519.keys.html +373 -0
- package/docs/classes/extranoncetag.extranoncedata.html +454 -0
- package/docs/classes/extranoncetag.extranoncepaymentid.html +453 -0
- package/docs/classes/extranoncetag.iextranonce.html +347 -0
- package/docs/classes/extratag.extramergedmining.html +494 -0
- package/docs/classes/extratag.extranonce.html +530 -0
- package/docs/classes/extratag.extrapadding.html +456 -0
- package/docs/classes/extratag.extrapublickey.html +460 -0
- package/docs/classes/extratag.iextratag.html +355 -0
- package/docs/classes/levinpacket.html +674 -0
- package/docs/classes/levinpayloads.handshake.html +731 -0
- package/docs/classes/levinpayloads.ilevinpayload.html +318 -0
- package/docs/classes/levinpayloads.liteblock.html +494 -0
- package/docs/classes/levinpayloads.missingtransactions.html +494 -0
- package/docs/classes/levinpayloads.newblock.html +540 -0
- package/docs/classes/levinpayloads.newtransactions.html +402 -0
- package/docs/classes/levinpayloads.peerentry.html +610 -0
- package/docs/classes/levinpayloads.ping.html +450 -0
- package/docs/classes/levinpayloads.rawblock.html +344 -0
- package/docs/classes/levinpayloads.requestchain.html +402 -0
- package/docs/classes/levinpayloads.requestgetobjects.html +448 -0
- package/docs/classes/levinpayloads.requesttxpool.html +402 -0
- package/docs/classes/levinpayloads.responsechain.html +494 -0
- package/docs/classes/levinpayloads.responsegetobjects.html +540 -0
- package/docs/classes/levinpayloads.timedsync.html +540 -0
- package/docs/classes/multisig.html +930 -0
- package/docs/classes/multisigmessage.html +694 -0
- package/docs/classes/parentblock.html +347 -0
- package/docs/classes/transaction.html +925 -0
- package/docs/classes/transactioninputs.coinbaseinput.html +390 -0
- package/docs/classes/transactioninputs.itransactioninput.html +321 -0
- package/docs/classes/transactioninputs.keyinput.html +459 -0
- package/docs/classes/transactionoutputs.itransactionoutput.html +317 -0
- package/docs/classes/transactionoutputs.keyoutput.html +422 -0
- package/docs/enums/extranoncetag.noncetagtype.html +246 -0
- package/docs/enums/extratag.extratagtype.html +280 -0
- package/docs/enums/levinprotocol.commandtype.html +391 -0
- package/docs/enums/transactioninputs.inputtype.html +246 -0
- package/docs/enums/transactionoutputs.outputtype.html +229 -0
- package/docs/globals.html +238 -0
- package/docs/index.html +271 -0
- package/docs/interfaces/interfaces.config.html +590 -0
- package/docs/interfaces/interfaces.daemonblocktemplateresponse.html +323 -0
- package/docs/interfaces/interfaces.generatedinput.html +304 -0
- package/docs/interfaces/interfaces.generatedoutput.html +285 -0
- package/docs/interfaces/interfaces.inputkeys.html +304 -0
- package/docs/interfaces/interfaces.ipreparedtransaction.html +268 -0
- package/docs/interfaces/interfaces.output.html +399 -0
- package/docs/interfaces/interfaces.preparedringsignature.html +377 -0
- package/docs/interfaces/interfaces.preparedtransaction.html +329 -0
- package/docs/interfaces/interfaces.randomoutput.html +285 -0
- package/docs/interfaces/interfaces.transactionrecipient.html +285 -0
- package/docs/interfaces/multisiginterfaces.partialkeyimage.html +277 -0
- package/docs/interfaces/multisiginterfaces.partialsigningkey.html +277 -0
- package/docs/modules/ed25519.html +195 -0
- package/docs/modules/extranoncetag.html +208 -0
- package/docs/modules/extratag.html +216 -0
- package/docs/modules/interfaces.html +231 -0
- package/docs/modules/levinpayloads.html +247 -0
- package/docs/modules/levinprotocol.html +191 -0
- package/docs/modules/multisiginterfaces.html +195 -0
- package/docs/modules/transactioninputs.html +208 -0
- package/docs/modules/transactionoutputs.html +204 -0
- package/index.d.ts +417 -0
- package/index.js +1508 -0
- package/lib/base58.js +220 -0
- package/lib/biginteger.js +1591 -0
- package/lib/blocktemplate.js +408 -0
- package/lib/crypto.js +19698 -0
- package/lib/mnemonic.js +1204 -0
- package/lib/nacl-fast-cn.js +608 -0
- package/lib/ringsigs.js +24262 -0
- package/lib/sha3.js +477 -0
- package/package.json +58 -0
- package/src/Address.ts +433 -0
- package/src/AddressPrefix.ts +117 -0
- package/src/Block.ts +556 -0
- package/src/BlockTemplate.ts +289 -0
- package/src/Common.ts +105 -0
- package/src/Config.ts +66 -0
- package/src/CryptoNote.ts +1072 -0
- package/src/LevinPacket.ts +366 -0
- package/src/Multisig.ts +600 -0
- package/src/MultisigMessage.ts +374 -0
- package/src/ParentBlock.ts +39 -0
- package/src/Transaction.ts +628 -0
- package/src/Types/ED25519.ts +187 -0
- package/src/Types/IExtraNonce.ts +225 -0
- package/src/Types/IExtraTag.ts +507 -0
- package/src/Types/ITransaction.ts +230 -0
- package/src/Types/ITransactionInput.ts +190 -0
- package/src/Types/ITransactionOutput.ts +108 -0
- package/src/Types/LevinPayloads.ts +1576 -0
- package/src/Types/MultisigInterfaces.ts +65 -0
- package/src/Types/PortableStorage.ts +289 -0
- package/src/Types.ts +36 -0
- package/src/index.ts +36 -0
- package/test/template.json +6 -0
- package/test/test.js +1457 -0
- package/tests/blocktemplate.json +6 -0
- package/tests/tests.js +215 -0
- package/tsconfig.json +15 -0
- package/tslint.json +36 -0
- package/typedoc.json +10 -0
- package/webpack.config.js +15 -0
package/src/Block.ts
ADDED
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
// Copyright (c) 2018-2020, The TurtleCoin Developers
|
|
2
|
+
//
|
|
3
|
+
// Please see the included LICENSE file for more information.
|
|
4
|
+
|
|
5
|
+
import * as ConfigInterface from './Config';
|
|
6
|
+
import {Transaction} from './Transaction';
|
|
7
|
+
import {ParentBlock} from './ParentBlock';
|
|
8
|
+
import {TransactionInputs, TransactionOutputs, TurtleCoinCrypto} from './Types';
|
|
9
|
+
import {Reader, Writer} from 'bytestream-helper';
|
|
10
|
+
import Config = ConfigInterface.Interfaces.Config;
|
|
11
|
+
|
|
12
|
+
/** @ignore */
|
|
13
|
+
const Config = require('../config.json');
|
|
14
|
+
|
|
15
|
+
/** @ignore */
|
|
16
|
+
interface Cache {
|
|
17
|
+
blob: string;
|
|
18
|
+
hash: string;
|
|
19
|
+
longBlob: string;
|
|
20
|
+
longHash: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Represents a TurtleCoin Block
|
|
25
|
+
*/
|
|
26
|
+
export class Block {
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The size of the block in bytes
|
|
30
|
+
*/
|
|
31
|
+
public get size(): number {
|
|
32
|
+
return this.toBuffer().length;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The height of the block
|
|
37
|
+
*/
|
|
38
|
+
public get height(): number {
|
|
39
|
+
if (this.m_minerTransaction.inputs.length !== 0) {
|
|
40
|
+
return (this.m_minerTransaction.inputs[0] as TransactionInputs.CoinbaseInput).blockIndex;
|
|
41
|
+
} else {
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The nonce of the block
|
|
48
|
+
*/
|
|
49
|
+
public get nonce(): number {
|
|
50
|
+
const writer = new Writer();
|
|
51
|
+
writer.uint32_t(this.m_nonce, true);
|
|
52
|
+
const reader = new Reader(writer.buffer);
|
|
53
|
+
return reader.uint32_t().toJSNumber();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public set nonce(value: number) {
|
|
57
|
+
if (value > 0xFFFFFFFF) {
|
|
58
|
+
throw new Error('value exceeds uint32_t maximum');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const writer = new Writer();
|
|
62
|
+
writer.uint32_t(value);
|
|
63
|
+
const reader = new Reader(writer.buffer);
|
|
64
|
+
this.m_nonce = reader.uint32_t(true).toJSNumber();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The transactions hashes (non-coinbase) included in the block
|
|
69
|
+
*/
|
|
70
|
+
public get transactions(): string[] {
|
|
71
|
+
return this.m_transactions;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The base transaction branch of the block
|
|
76
|
+
*/
|
|
77
|
+
public get baseTransactionBranch(): string[] {
|
|
78
|
+
const transactions = [this.m_minerTransaction.hash].concat(this.transactions);
|
|
79
|
+
|
|
80
|
+
return TurtleCoinCrypto.tree_branch(transactions);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The transaction tree hash of the block
|
|
85
|
+
*/
|
|
86
|
+
public get transactionTreeHash(): { hash: string, count: number } {
|
|
87
|
+
const transactions = [this.m_minerTransaction.hash].concat(this.transactions);
|
|
88
|
+
|
|
89
|
+
const treeHash = TurtleCoinCrypto.tree_hash(transactions);
|
|
90
|
+
|
|
91
|
+
return {hash: treeHash, count: transactions.length};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The merkle root of the block
|
|
96
|
+
*/
|
|
97
|
+
public get merkleRoot(): string {
|
|
98
|
+
const writer = new Writer();
|
|
99
|
+
|
|
100
|
+
writer.varint(this.m_majorVersion);
|
|
101
|
+
writer.varint(this.m_minorVersion);
|
|
102
|
+
|
|
103
|
+
if (this.m_majorVersion < this.m_activateParentBlockVersion) {
|
|
104
|
+
writer.varint(this.m_timestamp.getTime() / 1000);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
writer.hash(this.m_previousBlockHash);
|
|
108
|
+
|
|
109
|
+
if (this.m_majorVersion < this.m_activateParentBlockVersion) {
|
|
110
|
+
writer.uint32_t(this.m_nonce, true);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
writer.hash(this.transactionTreeHash.hash);
|
|
114
|
+
writer.varint(this.transactionTreeHash.count);
|
|
115
|
+
|
|
116
|
+
return getBlockHash(writer.buffer);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* The major block version
|
|
121
|
+
*/
|
|
122
|
+
public get majorVersion(): number {
|
|
123
|
+
return this.m_majorVersion;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public set majorVersion(majorVersion: number) {
|
|
127
|
+
this.m_majorVersion = majorVersion;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* The minor block version
|
|
132
|
+
*/
|
|
133
|
+
public get minorVersion(): number {
|
|
134
|
+
return this.m_minorVersion;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public set minorVersion(minorVersion: number) {
|
|
138
|
+
this.m_minorVersion = minorVersion;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* The block hash (id)
|
|
143
|
+
*/
|
|
144
|
+
public get hash(): string {
|
|
145
|
+
const blob = this.toHashingBuffer();
|
|
146
|
+
|
|
147
|
+
if (this.m_cache.blob === blob.toString('hex') && this.m_cache.hash) {
|
|
148
|
+
return this.m_cache.hash;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
this.m_cache.blob = blob.toString('hex');
|
|
152
|
+
|
|
153
|
+
this.m_cache.hash = getBlockHash(blob);
|
|
154
|
+
|
|
155
|
+
return this.m_cache.hash;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The block PoW hash
|
|
160
|
+
*/
|
|
161
|
+
public get longHash(): string {
|
|
162
|
+
const blob = this.toHashingBuffer(true);
|
|
163
|
+
|
|
164
|
+
if (this.m_cache.longBlob === blob.toString('hex') && this.m_cache.longHash) {
|
|
165
|
+
return this.m_cache.longHash;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
this.m_cache.longBlob = blob.toString('hex');
|
|
169
|
+
|
|
170
|
+
this.m_cache.longHash = getBlockPoWHash(blob, this.m_majorVersion);
|
|
171
|
+
|
|
172
|
+
return this.m_cache.longHash;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* The timestamp of the block
|
|
177
|
+
*/
|
|
178
|
+
public get timestamp(): Date {
|
|
179
|
+
return this.m_timestamp;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
public set timestamp(timestamp: Date) {
|
|
183
|
+
this.m_timestamp = timestamp;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* The previous block hash of the block
|
|
188
|
+
*/
|
|
189
|
+
public get previousBlockHash(): string {
|
|
190
|
+
return this.m_previousBlockHash;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
public set previousBlockHash(previousBlockHash: string) {
|
|
194
|
+
this.m_previousBlockHash = previousBlockHash;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* The miner (coinbase) transaction of the block
|
|
199
|
+
*/
|
|
200
|
+
public get minerTransaction(): Transaction {
|
|
201
|
+
return this.m_minerTransaction;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
public set minerTransaction(minerTransaction: Transaction) {
|
|
205
|
+
this.m_minerTransaction = minerTransaction;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* The parent block of the block
|
|
210
|
+
*/
|
|
211
|
+
public get parentBlock(): ParentBlock {
|
|
212
|
+
return this.m_parentBlock;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
public set parentBlock(parentBlock: ParentBlock) {
|
|
216
|
+
this.m_parentBlock = parentBlock;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Defines what major block version activates the use of parent blocks
|
|
221
|
+
*/
|
|
222
|
+
public get activateParentBlockVersion(): number {
|
|
223
|
+
return this.m_activateParentBlockVersion;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
public set activateParentBlockVersion(activateParentBlockVersion: number) {
|
|
227
|
+
this.m_activateParentBlockVersion = activateParentBlockVersion;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Creates a new instance of a block from the data supplied
|
|
232
|
+
* @param data the raw block data to decode
|
|
233
|
+
* @param [config] the configuration that may define the major block version to activate parent block usage
|
|
234
|
+
* @returns the new block object
|
|
235
|
+
*/
|
|
236
|
+
public static from(data: Buffer | string, config?: Config): Block {
|
|
237
|
+
const activateParentBlockVersion =
|
|
238
|
+
(config && config.activateParentBlockVersion
|
|
239
|
+
&& typeof config.activateParentBlockVersion !== 'undefined') ?
|
|
240
|
+
config.activateParentBlockVersion : 2;
|
|
241
|
+
|
|
242
|
+
const block = new Block();
|
|
243
|
+
|
|
244
|
+
const reader = new Reader(data);
|
|
245
|
+
|
|
246
|
+
block.m_majorVersion = reader.varint().toJSNumber();
|
|
247
|
+
block.m_minorVersion = reader.varint().toJSNumber();
|
|
248
|
+
|
|
249
|
+
if (block.m_majorVersion >= activateParentBlockVersion) {
|
|
250
|
+
block.m_previousBlockHash = reader.hash();
|
|
251
|
+
block.m_parentBlock.majorVersion = reader.varint().toJSNumber();
|
|
252
|
+
block.m_parentBlock.minorVersion = reader.varint().toJSNumber();
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
block.m_timestamp = new Date(reader.varint().toJSNumber() * 1000);
|
|
256
|
+
|
|
257
|
+
if (block.m_majorVersion >= activateParentBlockVersion) {
|
|
258
|
+
block.m_parentBlock.previousBlockHash = reader.hash();
|
|
259
|
+
} else {
|
|
260
|
+
block.m_previousBlockHash = reader.hash();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
block.m_nonce = reader.uint32_t(true).toJSNumber();
|
|
264
|
+
|
|
265
|
+
if (block.m_majorVersion >= activateParentBlockVersion) {
|
|
266
|
+
block.m_parentBlock.transactionCount = reader.varint().toJSNumber();
|
|
267
|
+
|
|
268
|
+
const baseTransactionBranchDepth = TurtleCoinCrypto.tree_depth(block.m_parentBlock.transactionCount);
|
|
269
|
+
|
|
270
|
+
for (let i = 0; i < baseTransactionBranchDepth; i++) {
|
|
271
|
+
block.m_parentBlock.baseTransactionBranch.push(reader.hash());
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
block.m_parentBlock.minerTransaction.version = reader.varint().toJSNumber();
|
|
275
|
+
block.m_parentBlock.minerTransaction.unlockTime = reader.varint();
|
|
276
|
+
|
|
277
|
+
const p_inputs = reader.varint().toJSNumber();
|
|
278
|
+
|
|
279
|
+
for (let i = 0; i < p_inputs; i++) {
|
|
280
|
+
if (reader.uint8_t().toJSNumber() === TransactionInputs.InputType.COINBASE) {
|
|
281
|
+
block.m_parentBlock.minerTransaction.inputs.push(
|
|
282
|
+
new TransactionInputs.CoinbaseInput(reader.varint().toJSNumber()),
|
|
283
|
+
);
|
|
284
|
+
} else {
|
|
285
|
+
throw new Error('Non-coinbase input found in parent block miner transaction');
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const p_outputs = reader.varint().toJSNumber();
|
|
290
|
+
|
|
291
|
+
for (let i = 0; i < p_outputs; i++) {
|
|
292
|
+
const amount = reader.varint();
|
|
293
|
+
const type = reader.uint8_t().toJSNumber();
|
|
294
|
+
if (type === TransactionOutputs.OutputType.KEY) {
|
|
295
|
+
block.m_parentBlock.minerTransaction.outputs.push(
|
|
296
|
+
new TransactionOutputs.KeyOutput(amount, reader.hash()),
|
|
297
|
+
);
|
|
298
|
+
} else {
|
|
299
|
+
throw new Error('Unknown output type detected');
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const p_extraLength = reader.varint().toJSNumber();
|
|
304
|
+
|
|
305
|
+
const p_extra = reader.bytes(p_extraLength);
|
|
306
|
+
|
|
307
|
+
block.m_parentBlock.minerTransaction.parseExtra(p_extra);
|
|
308
|
+
|
|
309
|
+
if (block.m_parentBlock.minerTransaction.version >= 2) {
|
|
310
|
+
block.m_parentBlock.minerTransaction.ignoredField = reader.varint().toJSNumber();
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const blockchainBranchDepth = (block.m_parentBlock.minerTransaction.mergedMining) ?
|
|
314
|
+
block.m_parentBlock.minerTransaction.mergedMining.depth : 0;
|
|
315
|
+
|
|
316
|
+
for (let i = 0; i < blockchainBranchDepth; i++) {
|
|
317
|
+
block.m_parentBlock.blockchainBranch.push(reader.hash());
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
block.m_minerTransaction.version = reader.varint().toJSNumber();
|
|
322
|
+
block.m_minerTransaction.unlockTime = reader.varint();
|
|
323
|
+
|
|
324
|
+
const inputs = reader.varint().toJSNumber();
|
|
325
|
+
|
|
326
|
+
for (let i = 0; i < inputs; i++) {
|
|
327
|
+
if (reader.uint8_t().toJSNumber() === TransactionInputs.InputType.COINBASE) {
|
|
328
|
+
block.m_minerTransaction.inputs.push(
|
|
329
|
+
new TransactionInputs.CoinbaseInput(reader.varint().toJSNumber()),
|
|
330
|
+
);
|
|
331
|
+
} else {
|
|
332
|
+
throw new Error('Non-coinbase input found in miner transaction');
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const outputs = reader.varint().toJSNumber();
|
|
337
|
+
|
|
338
|
+
for (let i = 0; i < outputs; i++) {
|
|
339
|
+
const amount = reader.varint();
|
|
340
|
+
const type = reader.uint8_t().toJSNumber();
|
|
341
|
+
if (type === TransactionOutputs.OutputType.KEY) {
|
|
342
|
+
block.m_minerTransaction.outputs.push(
|
|
343
|
+
new TransactionOutputs.KeyOutput(amount, reader.hash()),
|
|
344
|
+
);
|
|
345
|
+
} else {
|
|
346
|
+
throw new Error('Unknown output type detected');
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const extraLength = reader.varint().toJSNumber();
|
|
351
|
+
|
|
352
|
+
const extra = reader.bytes(extraLength);
|
|
353
|
+
|
|
354
|
+
block.m_minerTransaction.parseExtra(extra);
|
|
355
|
+
|
|
356
|
+
const txnCount = reader.varint().toJSNumber();
|
|
357
|
+
|
|
358
|
+
for (let i = 0; i < txnCount; i++) {
|
|
359
|
+
block.m_transactions.push(reader.hash());
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (reader.unreadBytes > 0) {
|
|
363
|
+
throw new RangeError('Unhandled data in block blob detected');
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return block;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
protected m_majorVersion: number = 0;
|
|
370
|
+
protected m_minorVersion: number = 0;
|
|
371
|
+
protected m_timestamp: Date = new Date();
|
|
372
|
+
protected m_previousBlockHash: string = ''.padStart(64, '0');
|
|
373
|
+
protected m_parentBlock: ParentBlock = new ParentBlock();
|
|
374
|
+
protected m_nonce: number = 0;
|
|
375
|
+
protected m_minerTransaction: Transaction = new Transaction();
|
|
376
|
+
protected m_transactions: string[] = [];
|
|
377
|
+
protected m_activateParentBlockVersion: number = Config.activateParentBlockVersion || 2;
|
|
378
|
+
protected m_cache: Cache = {
|
|
379
|
+
blob: '',
|
|
380
|
+
hash: '',
|
|
381
|
+
longBlob: '',
|
|
382
|
+
longHash: '',
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Returns a Buffer representation of the block
|
|
387
|
+
* @returns the resulting Buffer
|
|
388
|
+
*/
|
|
389
|
+
public toBuffer(): Buffer {
|
|
390
|
+
const writer = new Writer();
|
|
391
|
+
|
|
392
|
+
writer.varint(this.m_majorVersion);
|
|
393
|
+
writer.varint(this.m_minorVersion);
|
|
394
|
+
|
|
395
|
+
if (this.m_majorVersion >= this.m_activateParentBlockVersion) {
|
|
396
|
+
writer.hash(this.m_previousBlockHash);
|
|
397
|
+
writer.varint(this.m_parentBlock.majorVersion);
|
|
398
|
+
writer.varint(this.m_parentBlock.minorVersion);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
writer.varint(this.m_timestamp.getTime() / 1000);
|
|
402
|
+
|
|
403
|
+
if (this.m_majorVersion >= this.m_activateParentBlockVersion) {
|
|
404
|
+
writer.hash(this.m_parentBlock.previousBlockHash);
|
|
405
|
+
} else {
|
|
406
|
+
writer.hash(this.m_previousBlockHash);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
writer.uint32_t(this.m_nonce, true);
|
|
410
|
+
|
|
411
|
+
if (this.m_majorVersion >= this.m_activateParentBlockVersion) {
|
|
412
|
+
writer.varint(this.m_parentBlock.transactionCount);
|
|
413
|
+
|
|
414
|
+
if (Array.isArray(this.m_parentBlock.baseTransactionBranch)) {
|
|
415
|
+
this.m_parentBlock.baseTransactionBranch.forEach((branch) => {
|
|
416
|
+
writer.hash(branch);
|
|
417
|
+
});
|
|
418
|
+
} else {
|
|
419
|
+
writer.hash(this.m_parentBlock.baseTransactionBranch);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
writer.write(this.m_parentBlock.minerTransaction.toBuffer(true));
|
|
423
|
+
|
|
424
|
+
if (this.m_parentBlock.minerTransaction.version >= 2) {
|
|
425
|
+
writer.varint(this.m_parentBlock.minerTransaction.ignoredField);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
this.m_parentBlock.blockchainBranch.forEach((branch) => {
|
|
429
|
+
writer.hash(branch);
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
writer.write(this.m_minerTransaction.toBuffer(true));
|
|
434
|
+
|
|
435
|
+
writer.varint(this.m_transactions.length);
|
|
436
|
+
|
|
437
|
+
this.m_transactions.forEach((hash) => {
|
|
438
|
+
writer.hash(hash);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
return writer.buffer;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Returns a hexadecimal (blob) representation of the block
|
|
446
|
+
* @returns the hexadecimal representation of the block
|
|
447
|
+
*/
|
|
448
|
+
public toString(): string {
|
|
449
|
+
return this.toBuffer().toString('hex');
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Returns a Buffer representation of the data for hashing (mining) the block
|
|
454
|
+
* @param [headerOnly] whether to return just the header or the full block
|
|
455
|
+
* @returns the hashing buffer
|
|
456
|
+
*/
|
|
457
|
+
public toHashingBuffer(headerOnly: boolean = false): Buffer {
|
|
458
|
+
const writer = new Writer();
|
|
459
|
+
|
|
460
|
+
writer.varint(this.m_majorVersion);
|
|
461
|
+
writer.varint(this.m_minorVersion);
|
|
462
|
+
|
|
463
|
+
if (this.m_majorVersion >= this.m_activateParentBlockVersion) {
|
|
464
|
+
writer.hash(this.m_previousBlockHash);
|
|
465
|
+
} else {
|
|
466
|
+
writer.varint(this.m_timestamp.getTime() / 1000);
|
|
467
|
+
writer.hash(this.m_previousBlockHash);
|
|
468
|
+
writer.uint32_t(this.m_nonce, true);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
writer.hash(this.transactionTreeHash.hash);
|
|
472
|
+
|
|
473
|
+
writer.varint(this.transactionTreeHash.count);
|
|
474
|
+
|
|
475
|
+
if (this.m_majorVersion >= this.m_activateParentBlockVersion) {
|
|
476
|
+
if (headerOnly) {
|
|
477
|
+
writer.clear();
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
writer.varint(this.m_parentBlock.majorVersion);
|
|
481
|
+
writer.varint(this.m_parentBlock.minorVersion);
|
|
482
|
+
writer.varint(this.m_timestamp.getTime() / 1000);
|
|
483
|
+
writer.hash(this.m_parentBlock.previousBlockHash);
|
|
484
|
+
writer.uint32_t(this.m_nonce, true);
|
|
485
|
+
|
|
486
|
+
const treeHash = TurtleCoinCrypto.tree_hash_from_branch(
|
|
487
|
+
this.m_parentBlock.baseTransactionBranch,
|
|
488
|
+
this.m_parentBlock.minerTransaction.hash,
|
|
489
|
+
0,
|
|
490
|
+
);
|
|
491
|
+
|
|
492
|
+
writer.hash(treeHash);
|
|
493
|
+
|
|
494
|
+
writer.varint(this.m_parentBlock.transactionCount);
|
|
495
|
+
|
|
496
|
+
if (headerOnly) {
|
|
497
|
+
return writer.buffer;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
this.m_parentBlock.baseTransactionBranch.forEach((branch) => {
|
|
501
|
+
writer.hash(branch);
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
writer.write(this.m_parentBlock.minerTransaction.toBuffer());
|
|
505
|
+
|
|
506
|
+
if (this.m_parentBlock.minerTransaction.version >= 2) {
|
|
507
|
+
writer.varint(this.m_parentBlock.minerTransaction.ignoredField);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
this.m_parentBlock.blockchainBranch.forEach((branch) => {
|
|
511
|
+
writer.hash(branch);
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
return writer.buffer;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Returns a hexadecimal (blob) representation of the data for hashing (mining) the block
|
|
520
|
+
* @param [headerOnly] whether to return just the header or the full block
|
|
521
|
+
* @returns the hexadecimal (blob) representation of the hashing buffer
|
|
522
|
+
*/
|
|
523
|
+
public toHashingString(headerOnly: boolean = false): string {
|
|
524
|
+
return this.toHashingBuffer(headerOnly).toString('hex');
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/** @ignore */
|
|
529
|
+
function getBlockHash(data: Buffer): string {
|
|
530
|
+
const writer = new Writer();
|
|
531
|
+
|
|
532
|
+
writer.varint(data.length);
|
|
533
|
+
writer.write(data);
|
|
534
|
+
|
|
535
|
+
return TurtleCoinCrypto.cn_fast_hash(writer.blob);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/** @ignore */
|
|
539
|
+
function getBlockPoWHash(data: Buffer, majorVersion: number): string {
|
|
540
|
+
const blob = data.toString('hex');
|
|
541
|
+
|
|
542
|
+
switch (majorVersion) {
|
|
543
|
+
case 1:
|
|
544
|
+
case 2:
|
|
545
|
+
case 3:
|
|
546
|
+
return TurtleCoinCrypto.cn_slow_hash_v0(blob);
|
|
547
|
+
case 4:
|
|
548
|
+
return TurtleCoinCrypto.cn_lite_slow_hash_v1(blob);
|
|
549
|
+
case 5:
|
|
550
|
+
return TurtleCoinCrypto.cn_turtle_lite_slow_hash_v2(blob);
|
|
551
|
+
case 6:
|
|
552
|
+
return TurtleCoinCrypto.chukwa_slow_hash(blob);
|
|
553
|
+
default:
|
|
554
|
+
throw new Error('Unhandled major block version');
|
|
555
|
+
}
|
|
556
|
+
}
|