@leofcoin/lib 0.4.13 → 1.0.0
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/dist/lib.js +76 -0
- package/package.json +20 -58
- package/rollup.config.js +11 -7
- package/src/addresses.json +6 -0
- package/src/bytecodes.json +6 -0
- package/src/lib.js +62 -0
- package/.travis.yml +0 -25
- package/README.md +0 -9
- package/deploy.js +0 -8
- package/index.js +0 -745
- package/src/block.js +0 -70
- package/src/chain.js +0 -350
- package/src/errors.js +0 -19
- package/src/hash.js +0 -60
- package/src/index.js +0 -3
- package/src/params.js +0 -18
- package/src/transaction.js +0 -205
- package/test/index.js +0 -106
package/src/block.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import Transaction from './transaction'
|
|
2
|
-
import ipldLfc from 'ipld-lfc';
|
|
3
|
-
|
|
4
|
-
const { LFCNode, util } = ipldLfc
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @extends {Transaction}
|
|
9
|
-
* @example
|
|
10
|
-
* const block = new Block()
|
|
11
|
-
*/
|
|
12
|
-
export default class Block extends Transaction {
|
|
13
|
-
constructor() {
|
|
14
|
-
super()
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
getDifficulty(hash) {
|
|
18
|
-
return parseInt(hash.substring(0, 8), 16);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
goodBlock(block, difficulty){
|
|
22
|
-
return new Promise(async (resolve, reject) => {
|
|
23
|
-
block.hash = await this.blockHash(block);
|
|
24
|
-
if (parseInt(block.hash.substring(0, 8), 16) >= difficulty) {
|
|
25
|
-
block.nonce++
|
|
26
|
-
block = await this.goodBlock(block, difficulty)
|
|
27
|
-
}
|
|
28
|
-
resolve(block)
|
|
29
|
-
})
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async validateBlock(previousBlock, block, difficulty, unspent) {
|
|
33
|
-
const valid = await ipldLfc.util.isValid(block)
|
|
34
|
-
if (!valid) return await ipldLfc.util.validate(block)
|
|
35
|
-
// console.log(block, previousBlock);
|
|
36
|
-
if (previousBlock.index + 1 !== block.index) return this.BlockError('index');
|
|
37
|
-
if (!previousBlock.hash) {
|
|
38
|
-
previousBlock = await new LFCNode(previousBlock)
|
|
39
|
-
previousBlock = previousBlock.toJSON()
|
|
40
|
-
previousBlock.hash = await util.cid(util.serialize(previousBlock))
|
|
41
|
-
previousBlock.hash = previousBlock.hash.toBaseEncodedString()
|
|
42
|
-
}
|
|
43
|
-
console.log(await this.blockHash(block), block.hash);
|
|
44
|
-
if (previousBlock.hash !== block.prevHash) throw this.BlockError('prevhash');
|
|
45
|
-
if (await this.blockHash(block) !== block.hash) return this.BlockError('hash');
|
|
46
|
-
if (this.getDifficulty(block.hash) > difficulty) return this.BlockError('difficulty');
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return this.validateTransactions(block.transactions, unspent);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Create a new genesis block
|
|
54
|
-
*/
|
|
55
|
-
async newGenesisDAGNode(difficulty = 1, address = Buffer.alloc(32).toString('hex')) {
|
|
56
|
-
let block = {
|
|
57
|
-
index: 0,
|
|
58
|
-
prevHash: Buffer.alloc(47).toString('hex'),
|
|
59
|
-
time: Math.floor(new Date().getTime() / 1000),
|
|
60
|
-
transactions: [
|
|
61
|
-
// ms.unspent(network, [], wallet.account()).create(index: 0, amount: consensusSubsidy(0), address)
|
|
62
|
-
],
|
|
63
|
-
nonce: 0
|
|
64
|
-
}
|
|
65
|
-
block.hash = await blockHash(block);
|
|
66
|
-
block = await this.goodBlock(block, difficulty)
|
|
67
|
-
const node = new LFCNode(block)
|
|
68
|
-
return node;
|
|
69
|
-
}
|
|
70
|
-
}
|
package/src/chain.js
DELETED
|
@@ -1,350 +0,0 @@
|
|
|
1
|
-
import { GENESISBLOCK, genesisCID, consensusSubsidyInterval, reward } from './params'
|
|
2
|
-
import Block from './block'
|
|
3
|
-
|
|
4
|
-
const invalidTransactions = {};
|
|
5
|
-
|
|
6
|
-
globalThis.chain = globalThis.chain || [
|
|
7
|
-
GENESISBLOCK
|
|
8
|
-
];
|
|
9
|
-
|
|
10
|
-
globalThis.mempool = globalThis.mempool || [];
|
|
11
|
-
globalThis.blockHashSet = globalThis.blockHashSet || [];
|
|
12
|
-
|
|
13
|
-
const filterPeers = (peers, localPeer) => {
|
|
14
|
-
const set = []
|
|
15
|
-
return peers.reduce((p, c) => {
|
|
16
|
-
if (set.indexOf(c.peer) === -1 && c.peer !== localPeer) {
|
|
17
|
-
set.push(c.peer)
|
|
18
|
-
p.push(c)
|
|
19
|
-
}
|
|
20
|
-
return p
|
|
21
|
-
}, [])
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @extends {Block}
|
|
26
|
-
* @example
|
|
27
|
-
* const chain = new Chain()
|
|
28
|
-
*/
|
|
29
|
-
export default class Chain extends Block {
|
|
30
|
-
constructor() {
|
|
31
|
-
super()
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
get chain() { return globalThis.chain }
|
|
35
|
-
|
|
36
|
-
get mempool() { return globalThis.mempool }
|
|
37
|
-
|
|
38
|
-
get blockHashSet() { return globalThis.blockHashSet }
|
|
39
|
-
|
|
40
|
-
// TODO: needs 3 nodes running
|
|
41
|
-
invalidTransaction(data) {
|
|
42
|
-
// console.log(data.data.toString());
|
|
43
|
-
data = JSON.parse(data.data.toString());
|
|
44
|
-
if (!invalidTransactions[data.tx]) invalidTransactions[data.tx] = 0;
|
|
45
|
-
++invalidTransactions[data.tx]
|
|
46
|
-
const count = invalidTransactions[data.tx];
|
|
47
|
-
if (count === 3) {
|
|
48
|
-
const memIndex = mempool.indexOf(data)
|
|
49
|
-
mempool.splice(memIndex, 1)
|
|
50
|
-
delete invalidTransactions[data.tx];
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @param {number} height
|
|
56
|
-
*/
|
|
57
|
-
consensusSubsidy(height) {
|
|
58
|
-
// console.log(height);
|
|
59
|
-
const quarterlings = height / consensusSubsidyInterval;
|
|
60
|
-
if (quarterlings >= 256) {
|
|
61
|
-
return 0;
|
|
62
|
-
}
|
|
63
|
-
//subsidy is lowered by 12.5 %, approx every year
|
|
64
|
-
const minus = quarterlings >= 1 ? (quarterlings * (reward / 256)) : 0;
|
|
65
|
-
return reward - minus;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async getTransactions(withMempool = true, index = 0) {
|
|
69
|
-
const _chain = [...chain];
|
|
70
|
-
if (index === chain.length - 1) return []
|
|
71
|
-
_chain.slice(index + 1, chain.length - 1)
|
|
72
|
-
let transactions = _chain.reduce((transactions, block) => [ ...transactions, ...block.transactions], []);
|
|
73
|
-
if (withMempool) transactions = transactions.concat(mempool);
|
|
74
|
-
let _transactions = []
|
|
75
|
-
// TODO: deprecated, get/put should be handled in core
|
|
76
|
-
for (const tx of transactions) {
|
|
77
|
-
const {multihash} = tx
|
|
78
|
-
if (multihash) {
|
|
79
|
-
let value;
|
|
80
|
-
if (leofcoin.api.transaction) value = await leofcoin.api.transaction.get(multihash)
|
|
81
|
-
_transactions.push(value)
|
|
82
|
-
} else {
|
|
83
|
-
_transactions.push(tx)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
return _transactions
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
async getTransactionsForAddress(address, index = 0) {
|
|
91
|
-
const transactions = await this.getTransactions(false, index);
|
|
92
|
-
return transactions.filter(tx => tx.inputs.find(i => i.address === address) ||
|
|
93
|
-
tx.outputs.find(o => o.address === address));
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
*
|
|
98
|
-
* @param {string} withMempool - with or without mempool inclusion
|
|
99
|
-
* @param {number} index - block height to start from
|
|
100
|
-
*/
|
|
101
|
-
async getUnspent(withMempool = false, index = 0) {
|
|
102
|
-
const transactions = await this.getTransactions(withMempool, index);
|
|
103
|
-
// Find all inputs with their tx ids
|
|
104
|
-
const inputs = transactions.reduce((inputs, tx) => inputs.concat(tx.inputs), []);
|
|
105
|
-
|
|
106
|
-
// Find all outputs with their tx ids
|
|
107
|
-
const outputs = transactions.reduce((outputs, tx) =>
|
|
108
|
-
outputs.concat(tx.outputs.map(output => Object.assign({}, output, {tx: tx.id}))), []);
|
|
109
|
-
|
|
110
|
-
// Figure out which outputs are unspent
|
|
111
|
-
const unspent = outputs.filter(output =>
|
|
112
|
-
typeof inputs.find(input => input.tx === output.tx && input.index === output.index && input.amount === output.amount) === 'undefined');
|
|
113
|
-
return unspent;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* @param {String} address - wallet address
|
|
118
|
-
* @param {number} index - block height to start from
|
|
119
|
-
*/
|
|
120
|
-
async getUnspentForAddress(address = null, index = 0) {
|
|
121
|
-
const unspent = await this.getUnspent(true, index)
|
|
122
|
-
return unspent.filter(u => u.address === address);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* @param {String} address - wallet address
|
|
127
|
-
* @param {Number} index - Block index to get balance after
|
|
128
|
-
*/
|
|
129
|
-
async getBalanceForAddress(address = null, index) {
|
|
130
|
-
// debug(`Getting balance for ${address}`)
|
|
131
|
-
const unspent = await this.getUnspentForAddress(address, index)
|
|
132
|
-
const amount = unspent.reduce((acc, u) => acc + u.amount , 0);
|
|
133
|
-
// debug(`Got ${amount} for ${address}`)
|
|
134
|
-
return amount
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* @deprecated Use getTransactionsForAddress(addr, index) instead
|
|
139
|
-
*
|
|
140
|
-
* @param {string} address - wallet address
|
|
141
|
-
* @param {number} index - block height to start from
|
|
142
|
-
*
|
|
143
|
-
* @return {number} balance
|
|
144
|
-
*/
|
|
145
|
-
async getBalanceForAddressAfter(address = null, index = 0) {
|
|
146
|
-
// debug(`Getting balance for ${address} @${index}`)
|
|
147
|
-
const unspent = await this.getUnspentForAddress(address, index)
|
|
148
|
-
const amount = unspent.reduce((acc, u) => acc + u.amount , 0);
|
|
149
|
-
// debug(`Got ${amount} for ${address} @${index}`)
|
|
150
|
-
return amount
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
median(array) {
|
|
154
|
-
array.sort((a,b) => a - b)
|
|
155
|
-
|
|
156
|
-
var half = Math.floor(array.length / 2);
|
|
157
|
-
|
|
158
|
-
if(array.length % 2)
|
|
159
|
-
return array[half];
|
|
160
|
-
else
|
|
161
|
-
return (array[half - 1] + array[half]) / 2.0;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
difficulty() {
|
|
165
|
-
// TODO: lower difficulty when transactionpool contain more then 500 tx ?
|
|
166
|
-
// TODO: raise difficulty when pool is empty
|
|
167
|
-
|
|
168
|
-
// or
|
|
169
|
-
|
|
170
|
-
// TODO: implement iTX (instant transaction)
|
|
171
|
-
// iTX is handled by multiple peers, itx is chained together by their hashes
|
|
172
|
-
// by handlng a tx as itx the block well be converted into a iRootBlock
|
|
173
|
-
// this results into smaller chains (tangles, tails) which should improve
|
|
174
|
-
// resolving transactions, wallet amounts etc ...
|
|
175
|
-
const start = chain.length >= 128 ? (chain.length - 128) : 0;
|
|
176
|
-
const blocks = chain.slice(start, (chain.length - 1)).reverse();
|
|
177
|
-
const stamps = [];
|
|
178
|
-
for (var i = 0; i < blocks.length; i++) {
|
|
179
|
-
if (blocks[i + 1]) {
|
|
180
|
-
stamps.push(blocks[i].time - blocks[i + 1].time);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
if (stamps.length === 0) {
|
|
184
|
-
stamps.push(10);
|
|
185
|
-
}
|
|
186
|
-
let blocksMedian = this.median(stamps) || 10;
|
|
187
|
-
const offset = blocksMedian / 10
|
|
188
|
-
// offset for quick recovery
|
|
189
|
-
if (blocksMedian < 10) {
|
|
190
|
-
blocksMedian -= (offset / 2);
|
|
191
|
-
} else if (blocksMedian > 10) {
|
|
192
|
-
blocksMedian += (offset * 2);
|
|
193
|
-
}
|
|
194
|
-
if (blocksMedian < 0) blocksMedian = -blocksMedian
|
|
195
|
-
console.log(`Average Block Time: ${blocksMedian}`);
|
|
196
|
-
console.log(`Difficulty: ${10 / blocksMedian}`);
|
|
197
|
-
return (10000 / (10 / blocksMedian));
|
|
198
|
-
};//10000
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Get the transactions for the next Block
|
|
203
|
-
*
|
|
204
|
-
* @return {object} transactions
|
|
205
|
-
*/
|
|
206
|
-
async nextBlockTransactions() {
|
|
207
|
-
|
|
208
|
-
try {
|
|
209
|
-
const unspent = await this.getUnspent(false);
|
|
210
|
-
return mempool.filter(async transaction => {
|
|
211
|
-
const multihash = transaction.multihash
|
|
212
|
-
const value = await leofcoin.api.transaction.get(multihash)
|
|
213
|
-
try {
|
|
214
|
-
await this.validateTransaction(multihash, value.toJSON(), unspent);
|
|
215
|
-
return value.toJSON()
|
|
216
|
-
} catch (e) {
|
|
217
|
-
globalThis.pubsub.publish('invalid-transaction', Buffer.from(JSON.stringify(transaction)));
|
|
218
|
-
console.error(e);
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
} catch (e) {
|
|
222
|
-
throw new Error(e)
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
longestChain() {
|
|
227
|
-
return new Promise(async (resolve, reject) => {
|
|
228
|
-
try {
|
|
229
|
-
// TODO: peernet.id => peer.id
|
|
230
|
-
let peers = await filterPeers([...peernet.peers], peernet.id)
|
|
231
|
-
let set = []
|
|
232
|
-
const request = new globalThis.peernet.protos['peernet-request']({
|
|
233
|
-
request: 'lastBlock'
|
|
234
|
-
})
|
|
235
|
-
|
|
236
|
-
for (const peer of peers) {
|
|
237
|
-
const to = peernet._getPeerId(peer.id)
|
|
238
|
-
if (to) {
|
|
239
|
-
const node = await peernet.prepareMessage(to, request.encoded)
|
|
240
|
-
let response = await peer.request(node.encoded)
|
|
241
|
-
const proto = new globalThis.peernet.protos['peernet-message'](Buffer.from(response.data))
|
|
242
|
-
response = new globalThis.peernet.protos['peernet-response'](Buffer.from(proto.decoded.data))
|
|
243
|
-
const block = JSON.parse(response.decoded.response)
|
|
244
|
-
set.push({peer, block})
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
let localIndex
|
|
248
|
-
let localHash
|
|
249
|
-
try {
|
|
250
|
-
const index = await chainStore.get('localIndex')
|
|
251
|
-
const hash = await chainStore.get('localBlock')
|
|
252
|
-
localIndex = Number(index.toString())
|
|
253
|
-
localHash = hash.toString()
|
|
254
|
-
} catch (e) {
|
|
255
|
-
localIndex = 0;
|
|
256
|
-
localHash = genesisCID;
|
|
257
|
-
await chainStore.put('localIndex', 0)
|
|
258
|
-
await chainStore.put('localBlock', genesisCID)
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
set = set.reduce((p, c) => {
|
|
262
|
-
if (Number(c.height) > Number(p.height)) {
|
|
263
|
-
c.seen = 1
|
|
264
|
-
return c
|
|
265
|
-
} else if (Number(c.height) === Number(p.height)) {
|
|
266
|
-
p.seen += 1
|
|
267
|
-
}
|
|
268
|
-
return p
|
|
269
|
-
}, { height: localIndex, hash: localHash, seen: 0})
|
|
270
|
-
|
|
271
|
-
// temp
|
|
272
|
-
// if (_blocks.seen < 2) {
|
|
273
|
-
// _blocks = history[_blocks.block.index - 1]
|
|
274
|
-
//
|
|
275
|
-
// }
|
|
276
|
-
// const localIndex = await chainStore.get('localIndex')
|
|
277
|
-
// const localHash = await chainStore.get('localBlock')
|
|
278
|
-
return resolve({index: set.height, hash: set.hash})
|
|
279
|
-
|
|
280
|
-
} catch (e) {
|
|
281
|
-
console.warn(e);
|
|
282
|
-
// debug(e)
|
|
283
|
-
reject(e)
|
|
284
|
-
}
|
|
285
|
-
})
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Resolve latest block from the longest chain.
|
|
290
|
-
* @return Promise(resolve(block))
|
|
291
|
-
*/
|
|
292
|
-
lastBlock() {
|
|
293
|
-
return new Promise(async (resolve, reject) => {
|
|
294
|
-
const result = await this.longestChain();
|
|
295
|
-
|
|
296
|
-
resolve(result); // retrieve links
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* @param {String} address
|
|
302
|
-
* @return {Function} newBlock
|
|
303
|
-
*/
|
|
304
|
-
async nextBlock(address) {
|
|
305
|
-
let transactions;
|
|
306
|
-
let previousBlock;
|
|
307
|
-
try {
|
|
308
|
-
previousBlock = await this.lastBlock()
|
|
309
|
-
|
|
310
|
-
if (previousBlock.index > chain.length - 1) {
|
|
311
|
-
await leofcoin.api.chain.sync()
|
|
312
|
-
previousBlock = await this.lastBlock()
|
|
313
|
-
}
|
|
314
|
-
if (!previousBlock.index) previousBlock = chain[chain.length - 1]
|
|
315
|
-
transactions = await this.nextBlockTransactions();
|
|
316
|
-
} catch (e) {
|
|
317
|
-
previousBlock = GENESISBLOCK
|
|
318
|
-
previousBlock.hash = genesisCID
|
|
319
|
-
transactions = await this.nextBlockTransactions();
|
|
320
|
-
} finally {
|
|
321
|
-
// console.log(transactions, previousBlock, address);
|
|
322
|
-
return await this.newBlock({transactions, previousBlock, address});
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Create new block
|
|
328
|
-
*
|
|
329
|
-
* @param {Array} transactions - transactions
|
|
330
|
-
* @param {Object} previousBlock - previousBlock
|
|
331
|
-
* @param {String} address - address
|
|
332
|
-
* @return {Object} index, prevHash, time, transactions, nonce
|
|
333
|
-
*/
|
|
334
|
-
async newBlock({transactions = [], previousBlock, address}) {
|
|
335
|
-
const index = previousBlock.index + 1
|
|
336
|
-
const minedTx = await this.createRewardTransaction(address, this.consensusSubsidy(index))
|
|
337
|
-
transactions.push(minedTx.toJSON());
|
|
338
|
-
this.data = {
|
|
339
|
-
index,
|
|
340
|
-
prevHash: previousBlock.hash,
|
|
341
|
-
time: Math.floor(new Date().getTime() / 1000),
|
|
342
|
-
transactions,
|
|
343
|
-
nonce: 0
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
this.data.hash = await this.blockHash({...this.data});
|
|
347
|
-
|
|
348
|
-
return this.data;
|
|
349
|
-
}
|
|
350
|
-
}
|
package/src/errors.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
const invalid = (name, text) => new Error(`Invalid ${name}: ${text}`);
|
|
2
|
-
// TODO: show notification
|
|
3
|
-
/**
|
|
4
|
-
* @example
|
|
5
|
-
* const errors = new Errors()
|
|
6
|
-
*/
|
|
7
|
-
export default class Errors {
|
|
8
|
-
BlockError(text) {
|
|
9
|
-
return invalid('block', text)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
TransactionError(text) {
|
|
13
|
-
return invalid('transaction', text)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
MinerWarning(text) {
|
|
17
|
-
new Error(`warning @Miner: ${text}`)
|
|
18
|
-
}
|
|
19
|
-
}
|
package/src/hash.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import IPLDLFCTx from 'ipld-lfc-tx'
|
|
2
|
-
import ipldLfc from 'ipld-lfc'
|
|
3
|
-
import CID from 'cids'
|
|
4
|
-
import Errors from './errors'
|
|
5
|
-
import cryptoJs from 'crypto-js';
|
|
6
|
-
|
|
7
|
-
const { LFCNode, util } = ipldLfc
|
|
8
|
-
const {SHA256} = cryptoJs
|
|
9
|
-
|
|
10
|
-
const _SHA256 = (object) => {
|
|
11
|
-
return SHA256(JSON.stringify(object)).toString();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @extends {Validator}
|
|
16
|
-
* @example
|
|
17
|
-
* const hash = new Hash()
|
|
18
|
-
*/
|
|
19
|
-
export default class Hash extends Errors {
|
|
20
|
-
constructor() {
|
|
21
|
-
super()
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
hashFromMultihash(multihash) {
|
|
25
|
-
const cid = new CID(multihash.replace('/ipfs/', ''))
|
|
26
|
-
return cid.multihash.slice(cid.prefix.length / 2).toString('hex')
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
multihashFromHash(hash) {
|
|
30
|
-
const cid = new CID(1, 'leofcoin-block', Buffer.from(`1d40${hash}`, 'hex'), 'base58btc');
|
|
31
|
-
return cid.toBaseEncodedString();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async blockHash(block) {
|
|
35
|
-
const cid = await util.cid(await util.serialize(await new LFCNode({...block})))
|
|
36
|
-
return cid.toBaseEncodedString();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Generate transaction hash
|
|
41
|
-
*
|
|
42
|
-
* @param {object} transaction {id, type, inputs, outputs}
|
|
43
|
-
*/
|
|
44
|
-
async transactionHash(transaction) {
|
|
45
|
-
const tx = await new IPLDLFCTx.LFCTx(transaction)
|
|
46
|
-
const cid = await IPLDLFCTx.util.cid(await tx.serialize())
|
|
47
|
-
return cid.toBaseEncodedString()
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Generate transaction input hash
|
|
52
|
-
*
|
|
53
|
-
* @param {object} transactionInput {transaction, index, amount, address}
|
|
54
|
-
*/
|
|
55
|
-
transactionInputHash(transactionInput) {
|
|
56
|
-
const {tx, index, amount, address} = transactionInput;
|
|
57
|
-
return _SHA256({tx, index, amount, address});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
}
|
package/src/index.js
DELETED
package/src/params.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export const reward = 150;
|
|
2
|
-
export const consensusSubsidyInterval = 52500;
|
|
3
|
-
export const consensusSubsidyPercentage = 12.5; // quarterlings
|
|
4
|
-
export const genesisCID = 'zsNS6wZiHSc2QPHmjV8TMNn798b4Kp9jpjsBNeUkPhaJTza3GosWUgE72Jy3X9jKMrFCcDni7Pq4yXogQN4TcAfrPmTXFt';
|
|
5
|
-
export const GENESISBS58 = 'EKBqhKsFG14thpzEKUbbb94WG9a1p9sm82YQ2YwK6wkme4C1df2dMwggnDgh74zZsBx2UbWi1qDQLysrrU3YKJ6V73sLtASepYieNpx8Fwjxyjh6xWNYToTNbNkp1geiSWq6fne7Npf37HCZVmi';
|
|
6
|
-
export const GENESISBLOCK = {
|
|
7
|
-
index: 0,
|
|
8
|
-
prevHash: Buffer.alloc(47).toString('hex'),
|
|
9
|
-
time: 1590240964,
|
|
10
|
-
transactions: [],
|
|
11
|
-
nonce: 1077701
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* network (hardcoded for now)
|
|
16
|
-
* @dev change to 'leofcoin:olivia' for testnet
|
|
17
|
-
*/
|
|
18
|
-
export const network = 'leofcoin'
|