@leofcoin/workers 1.4.7 → 1.4.10
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/package.json +1 -1
- package/src/block-worker.js +1 -3
- package/src/machine-worker.js +159 -163
package/package.json
CHANGED
package/src/block-worker.js
CHANGED
|
@@ -22,9 +22,7 @@ const run = async (blocks) => {
|
|
|
22
22
|
const hash = await block.hash()
|
|
23
23
|
const index = block.decoded.index
|
|
24
24
|
console.log(`loaded block: ${hash} @${index} ${formatBytes(size)}`)
|
|
25
|
-
|
|
26
|
-
block.decoded.transactions = block.decoded.transactions.sort((a, b) => a.nonce - b.nonce)
|
|
27
|
-
resolve({ ...block.decoded, blockInfo: { hash, size, index } })
|
|
25
|
+
resolve({ ...block.decoded, hash, blockInfo: { hash, size, index } })
|
|
28
26
|
})
|
|
29
27
|
)
|
|
30
28
|
)
|
package/src/machine-worker.js
CHANGED
|
@@ -9,6 +9,9 @@ const contractFactoryMessage = bytecodes.contractFactory
|
|
|
9
9
|
const nativeTokenMessage = bytecodes.nativeToken
|
|
10
10
|
const nameServiceMessage = bytecodes.nameService
|
|
11
11
|
const validatorsMessage = bytecodes.validators
|
|
12
|
+
|
|
13
|
+
const latestTransactions = []
|
|
14
|
+
|
|
12
15
|
let nativeCalls = 0
|
|
13
16
|
let nativeBurns = 0
|
|
14
17
|
let nativeMints = 0
|
|
@@ -19,8 +22,13 @@ let totalBurnAmount = 0
|
|
|
19
22
|
let totalMintAmount = 0
|
|
20
23
|
let totalTransferAmount = 0
|
|
21
24
|
|
|
25
|
+
let blocks = []
|
|
26
|
+
let contracts = {}
|
|
27
|
+
const _ = {}
|
|
28
|
+
|
|
22
29
|
globalThis.BigNumber = BigNumber
|
|
23
|
-
|
|
30
|
+
|
|
31
|
+
let lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' }
|
|
24
32
|
|
|
25
33
|
const unique = (arr) =>
|
|
26
34
|
arr.filter((el, pos, arr) => {
|
|
@@ -31,7 +39,7 @@ const has = (address) => {
|
|
|
31
39
|
return contracts[address] ? true : false
|
|
32
40
|
}
|
|
33
41
|
|
|
34
|
-
const get = (contract, method, params) => {
|
|
42
|
+
const get = ({ contract, method, params }) => {
|
|
35
43
|
let result
|
|
36
44
|
if (params?.length > 0) {
|
|
37
45
|
result = contracts[contract][method](...params)
|
|
@@ -41,7 +49,7 @@ const get = (contract, method, params) => {
|
|
|
41
49
|
return result
|
|
42
50
|
}
|
|
43
51
|
|
|
44
|
-
|
|
52
|
+
_.runContract = async ({ decoded, hash, encoded }) => {
|
|
45
53
|
const params = decoded.constructorParameters
|
|
46
54
|
try {
|
|
47
55
|
const func = new Function(new TextDecoder().decode(decoded.contract))
|
|
@@ -63,7 +71,7 @@ const runContract = async ({ decoded, hash, encoded }) => {
|
|
|
63
71
|
}
|
|
64
72
|
}
|
|
65
73
|
|
|
66
|
-
|
|
74
|
+
_.execute = async ({ contract, method, params }) => {
|
|
67
75
|
try {
|
|
68
76
|
let result
|
|
69
77
|
// don't execute the method on a proxy
|
|
@@ -88,26 +96,54 @@ const execute = async (contract, method, params) => {
|
|
|
88
96
|
const createMessage = (sender = globalThis.peerid) => {
|
|
89
97
|
return {
|
|
90
98
|
sender,
|
|
91
|
-
call: execute,
|
|
99
|
+
call: _.execute,
|
|
92
100
|
staticCall: get
|
|
93
101
|
}
|
|
94
102
|
}
|
|
95
103
|
|
|
96
|
-
const
|
|
104
|
+
const _executeTransaction = async (transaction) => {
|
|
105
|
+
const hash = await new TransactionMessage(transaction).hash()
|
|
106
|
+
if (latestTransactions.includes(hash)) {
|
|
107
|
+
throw new Error(`double transaction found: ${hash} in block ${block.index}`)
|
|
108
|
+
} else {
|
|
109
|
+
latestTransactions.push(hash)
|
|
110
|
+
const { from, to, method, params, nonce } = transaction
|
|
111
|
+
globalThis.msg = createMessage(from)
|
|
112
|
+
|
|
113
|
+
await _.execute({ contract: to, method, params })
|
|
114
|
+
if (to === nativeToken) {
|
|
115
|
+
nativeCalls += 1
|
|
116
|
+
if (method === 'burn') nativeBurns += 1
|
|
117
|
+
if (method === 'mint') nativeMints += 1
|
|
118
|
+
if (method === 'transfer') nativeTransfers += 1
|
|
119
|
+
}
|
|
120
|
+
totalTransactions += 1
|
|
121
|
+
|
|
122
|
+
worker.postMessage({
|
|
123
|
+
type: 'transactionLoaded',
|
|
124
|
+
result: {
|
|
125
|
+
hash,
|
|
126
|
+
from,
|
|
127
|
+
nonce: String(nonce)
|
|
128
|
+
}
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
_.init = async (message) => {
|
|
134
|
+
let { contracts, peerid } = message
|
|
97
135
|
globalThis.peerid = peerid
|
|
98
136
|
contracts = [contractFactoryMessage, nativeTokenMessage, nameServiceMessage, validatorsMessage]
|
|
99
137
|
|
|
100
138
|
contracts = await Promise.all(
|
|
101
139
|
contracts.map(async (contract) => {
|
|
102
140
|
contract = await new ContractMessage(new Uint8Array(contract.split(',')))
|
|
103
|
-
await runContract({ decoded: contract.decoded, encoded: contract.encoded, hash: await contract.hash() })
|
|
141
|
+
await _.runContract({ decoded: contract.decoded, encoded: contract.encoded, hash: await contract.hash() })
|
|
104
142
|
return contract
|
|
105
143
|
})
|
|
106
144
|
)
|
|
107
145
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (blocks?.length > 0) {
|
|
146
|
+
if (message.blocks?.length > 0) {
|
|
111
147
|
let pre
|
|
112
148
|
|
|
113
149
|
try {
|
|
@@ -123,68 +159,47 @@ const _init = async ({ contracts, blocks, peerid }) => {
|
|
|
123
159
|
serialization: 'advanced',
|
|
124
160
|
type: 'module'
|
|
125
161
|
})
|
|
126
|
-
blocks = await _worker.once(blocks)
|
|
162
|
+
blocks = await _worker.once(message.blocks)
|
|
127
163
|
_worker = null
|
|
128
164
|
// blocks = unique(globalThis.blocks ? globalThis : [], blocks)
|
|
129
165
|
// for (let i = 0; i < blocks.length; i++) {
|
|
130
166
|
|
|
131
167
|
// }
|
|
132
168
|
for (const block of blocks) {
|
|
133
|
-
|
|
169
|
+
// we only revalidate the latest 24 blocks
|
|
170
|
+
// every 24 blocks a snapshot is taken and stored in state
|
|
171
|
+
// this means contracts will be restored from this state
|
|
172
|
+
// this also means devs NEED to make sure the state can be restored
|
|
173
|
+
// on contract deploy an error will be thrown if state wasn't recoverable
|
|
174
|
+
if (block.index > 24) {
|
|
175
|
+
const transactionCount = blocks[block.index - 1].transactions.length
|
|
176
|
+
latestTransactions.splice(-(transactionCount - 1), latestTransactions.length)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (!block.loaded) {
|
|
180
|
+
const priority = block.transactions.filter((transaction) => transaction.priority)
|
|
181
|
+
if (priority.length > 0)
|
|
182
|
+
await Promise.all(
|
|
183
|
+
priority.sort((a, b) => a.nonce - b.nonce).map((transaction) => _executeTransaction(transaction))
|
|
184
|
+
)
|
|
185
|
+
|
|
134
186
|
await Promise.all(
|
|
135
|
-
block.transactions
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
globalThis.msg = createMessage(from)
|
|
139
|
-
|
|
140
|
-
try {
|
|
141
|
-
await execute(to, method, params)
|
|
142
|
-
if (to === nativeToken) {
|
|
143
|
-
nativeCalls += 1
|
|
144
|
-
if (method === 'burn') nativeBurns += 1
|
|
145
|
-
if (method === 'mint') nativeMints += 1
|
|
146
|
-
if (method === 'transfer') nativeTransfers += 1
|
|
147
|
-
}
|
|
148
|
-
totalTransactions += 1
|
|
149
|
-
|
|
150
|
-
worker.postMessage({
|
|
151
|
-
type: 'transactionLoaded',
|
|
152
|
-
result: {
|
|
153
|
-
hash: await new TransactionMessage(transaction).hash(),
|
|
154
|
-
from,
|
|
155
|
-
nonce: String(nonce)
|
|
156
|
-
}
|
|
157
|
-
})
|
|
158
|
-
} catch (error) {
|
|
159
|
-
throw error
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
})
|
|
187
|
+
block.transactions
|
|
188
|
+
.filter((transaction) => !transaction.priority)
|
|
189
|
+
.map(async (transaction) => _executeTransaction(transaction))
|
|
163
190
|
)
|
|
164
|
-
block.loaded = true
|
|
165
|
-
worker.postMessage({
|
|
166
|
-
type: 'debug',
|
|
167
|
-
message: `loaded transactions for block: ${block.blockInfo.hash} @${block.blockInfo.index} ${formatBytes(
|
|
168
|
-
block.blockInfo.size
|
|
169
|
-
)}`
|
|
170
|
-
})
|
|
171
|
-
} catch (error) {
|
|
172
|
-
worker.postMessage({
|
|
173
|
-
type: 'error',
|
|
174
|
-
message: error.message
|
|
175
|
-
})
|
|
176
191
|
}
|
|
192
|
+
block.loaded = true
|
|
193
|
+
worker.postMessage({
|
|
194
|
+
type: 'debug',
|
|
195
|
+
message: `loaded transactions for block: ${block.blockInfo.hash} @${block.blockInfo.index} ${formatBytes(
|
|
196
|
+
block.blockInfo.size
|
|
197
|
+
)}`
|
|
198
|
+
})
|
|
177
199
|
}
|
|
178
200
|
|
|
179
201
|
if (blocks.length > 0) {
|
|
180
202
|
lastBlock = blocks[blocks.length - 1]
|
|
181
|
-
// todo blocks already loaded as blockmessage so use it!
|
|
182
|
-
lastBlock = await new BlockMessage(lastBlock)
|
|
183
|
-
|
|
184
|
-
lastBlock = {
|
|
185
|
-
...lastBlock.decoded,
|
|
186
|
-
hash: await lastBlock.hash()
|
|
187
|
-
}
|
|
188
203
|
}
|
|
189
204
|
globalThis.blocks = blocks
|
|
190
205
|
}
|
|
@@ -194,113 +209,94 @@ const _init = async ({ contracts, blocks, peerid }) => {
|
|
|
194
209
|
// worker.postMessage({blocks});
|
|
195
210
|
}
|
|
196
211
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
id
|
|
220
|
-
})
|
|
221
|
-
} else if (e.type === 'nativeMints') {
|
|
222
|
-
worker.postMessage({
|
|
223
|
-
type: 'response',
|
|
224
|
-
value: nativeMints,
|
|
225
|
-
id
|
|
226
|
-
})
|
|
227
|
-
} else if (e.type === 'nativeTransfers') {
|
|
228
|
-
worker.postMessage({
|
|
229
|
-
type: 'response',
|
|
230
|
-
value: nativeTransfers,
|
|
231
|
-
id
|
|
232
|
-
})
|
|
233
|
-
} else if (e.type === 'totalTransfers') {
|
|
212
|
+
_.addLoadedBlock = (block) => {
|
|
213
|
+
blocks[block.index - 1] = block
|
|
214
|
+
return true
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
_.loadBlock = (block) => {
|
|
218
|
+
// todo validate here and deprecate addLoadedBlock
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const respond = (id, value) => {
|
|
222
|
+
worker.postMessage({
|
|
223
|
+
type: 'response',
|
|
224
|
+
value,
|
|
225
|
+
id
|
|
226
|
+
})
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const runTask = async (id, taskName, input) => {
|
|
230
|
+
try {
|
|
231
|
+
const result = await _[taskName](input)
|
|
232
|
+
respond(id, result)
|
|
233
|
+
} catch (e) {
|
|
234
234
|
worker.postMessage({
|
|
235
|
-
type:
|
|
236
|
-
|
|
235
|
+
type: `${taskName}Error`,
|
|
236
|
+
message: e.message,
|
|
237
237
|
id
|
|
238
238
|
})
|
|
239
239
|
}
|
|
240
|
-
if (e.type === 'has') {
|
|
241
|
-
try {
|
|
242
|
-
const value = await has(e.input.address)
|
|
243
|
-
worker.postMessage({
|
|
244
|
-
type: 'response',
|
|
245
|
-
id,
|
|
246
|
-
value
|
|
247
|
-
})
|
|
248
|
-
} catch (error) {
|
|
249
|
-
worker.postMessage({
|
|
250
|
-
type: 'hasError',
|
|
251
|
-
message: error.message,
|
|
252
|
-
id
|
|
253
|
-
})
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
if (e.type === 'run') {
|
|
257
|
-
try {
|
|
258
|
-
const value = await runContract(e.input)
|
|
259
|
-
worker.postMessage({
|
|
260
|
-
type: 'response',
|
|
261
|
-
id,
|
|
262
|
-
value
|
|
263
|
-
})
|
|
264
|
-
} catch (e) {
|
|
265
|
-
worker.postMessage({
|
|
266
|
-
type: 'runError',
|
|
267
|
-
message: e.message,
|
|
268
|
-
id
|
|
269
|
-
})
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
if (e.type === 'get') {
|
|
273
|
-
try {
|
|
274
|
-
const value = await get(e.input.contract, e.input.method, e.input.params)
|
|
275
|
-
worker.postMessage({
|
|
276
|
-
type: 'response',
|
|
277
|
-
id,
|
|
278
|
-
value
|
|
279
|
-
})
|
|
280
|
-
} catch (e) {
|
|
281
|
-
worker.postMessage({
|
|
282
|
-
type: 'fetchError',
|
|
283
|
-
message: e.message,
|
|
284
|
-
id
|
|
285
|
-
})
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
if (e.type === 'execute') {
|
|
289
|
-
try {
|
|
290
|
-
const value = await execute(e.input.contract, e.input.method, e.input.params)
|
|
291
|
-
worker.postMessage({
|
|
292
|
-
type: 'response',
|
|
293
|
-
id,
|
|
294
|
-
value
|
|
295
|
-
})
|
|
296
|
-
} catch (e) {
|
|
297
|
-
worker.postMessage({
|
|
298
|
-
type: 'executionError',
|
|
299
|
-
message: e.message,
|
|
300
|
-
id
|
|
301
|
-
})
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
240
|
}
|
|
305
241
|
|
|
306
|
-
worker.onmessage((
|
|
242
|
+
worker.onmessage(({ id, type, input }) => {
|
|
243
|
+
switch (type) {
|
|
244
|
+
case 'init':
|
|
245
|
+
runTask(id, 'init', input)
|
|
246
|
+
break
|
|
247
|
+
case 'run':
|
|
248
|
+
runTask(id, 'runContract', input)
|
|
249
|
+
break
|
|
250
|
+
case 'execute':
|
|
251
|
+
runTask(id, 'execute', input)
|
|
252
|
+
break
|
|
253
|
+
case 'addLoadedBlock':
|
|
254
|
+
runTask(id, 'addLoadedBlock', input)
|
|
255
|
+
break
|
|
256
|
+
case 'nativeCalls':
|
|
257
|
+
respond(id, nativeCalls)
|
|
258
|
+
break
|
|
259
|
+
case 'contracts':
|
|
260
|
+
respond(id, contracts)
|
|
261
|
+
break
|
|
262
|
+
case 'nativeMints':
|
|
263
|
+
respond(id, nativeMints)
|
|
264
|
+
break
|
|
265
|
+
case 'nativeBurns':
|
|
266
|
+
respond(id, nativeBurns)
|
|
267
|
+
break
|
|
268
|
+
case 'nativeTransfers':
|
|
269
|
+
respond(id, nativeTransfers)
|
|
270
|
+
break
|
|
271
|
+
case 'totalTransfers':
|
|
272
|
+
respond(id, totalTransfers)
|
|
273
|
+
break
|
|
274
|
+
case 'totalBlocks':
|
|
275
|
+
respond(id, blocks.length)
|
|
276
|
+
break
|
|
277
|
+
case 'blocks':
|
|
278
|
+
respond(id, input ? blocks.slice(input.from, input.to) : blocks)
|
|
279
|
+
break
|
|
280
|
+
case 'block':
|
|
281
|
+
respond(id, blocks[input - 1])
|
|
282
|
+
break
|
|
283
|
+
case 'lastBlock':
|
|
284
|
+
respond(id, blocks[blocks.length - 1])
|
|
285
|
+
break
|
|
286
|
+
case 'latestTransactions':
|
|
287
|
+
respond(id, latestTransactions)
|
|
288
|
+
break
|
|
289
|
+
case 'totalTransactions':
|
|
290
|
+
respond(id, totalTransactions)
|
|
291
|
+
break
|
|
292
|
+
case 'has':
|
|
293
|
+
respond(id, has(input.address))
|
|
294
|
+
break
|
|
295
|
+
case 'get':
|
|
296
|
+
respond(id, get(input))
|
|
297
|
+
break
|
|
298
|
+
default:
|
|
299
|
+
console.log(`machine-worker: unsupported taskType: ${type}`)
|
|
300
|
+
break
|
|
301
|
+
}
|
|
302
|
+
})
|