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