@leofcoin/chain 1.6.1 → 1.6.3
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/exports/browser/{browser-Ei0BXMlu-C0woTcHa.js → browser-Ei0BXMlu-9eQR3AGp.js} +2 -2
- package/exports/browser/chain.js +678 -661
- package/exports/browser/{client-A009z8av-Ssch8Yea.js → client-A009z8av-DavUUkay.js} +4 -4
- package/exports/browser/{_polyfill-node.child_process-CblghArn.js → index-Bz6K16zr.js} +6 -2003
- package/exports/browser/{index-G74WLzL7-BnLRqHoy.js → index-G74WLzL7-d1Vs_wqe.js} +2 -2
- package/exports/browser/{index-YQrIDBUQ-APwDgUUG.js → index-YQrIDBUQ-CbL47K_x.js} +2 -2
- package/exports/browser/{messages-lWRTai7t-DJnHZSdM.js → messages-lWRTai7t-Cs3eU5Cb.js} +2 -2
- package/exports/browser/{node-browser-CeM_F-HL.js → node-browser-CC3grAN3.js} +4 -4
- package/exports/browser/node-browser.js +2 -2
- package/exports/browser/workers/block-worker.js +1 -1
- package/exports/browser/workers/machine-worker.js +348 -349
- package/exports/browser/workers/{worker-CbAak_hM.js → worker-CFrwP8cD.js} +1 -4
- package/exports/chain.js +2 -2
- package/exports/workers/block-worker.js +1 -1
- package/exports/workers/machine-worker.js +348 -349
- package/exports/workers/{worker-CbAak_hM.js → worker-CFrwP8cD.js} +1 -4
- package/package.json +27 -56
- package/exports/browser/_polyfill-node.url-BLK_MhDf.js +0 -1196
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { E as EasyWorker, B as BigNumber, C as ContractMessage, T as TransactionMessage } from './worker-
|
|
2
|
-
import { randomUUID } from 'crypto';
|
|
1
|
+
import { E as EasyWorker, B as BigNumber, C as ContractMessage, T as TransactionMessage } from './worker-CFrwP8cD.js';
|
|
3
2
|
|
|
4
3
|
const byteFormats = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
5
4
|
const formatBytes = (bytes, decimals = 2) => {
|
|
@@ -103,351 +102,351 @@ class LittlePubSub {
|
|
|
103
102
|
}
|
|
104
103
|
}
|
|
105
104
|
|
|
106
|
-
const pubsub = new LittlePubSub();
|
|
107
|
-
const worker = new EasyWorker();
|
|
108
|
-
|
|
109
|
-
const contractFactoryMessage = bytecodes.contractFactory;
|
|
110
|
-
const nativeTokenMessage = bytecodes.nativeToken;
|
|
111
|
-
const nameServiceMessage = bytecodes.nameService;
|
|
112
|
-
const validatorsMessage = bytecodes.validators;
|
|
113
|
-
|
|
114
|
-
const latestTransactions = [];
|
|
115
|
-
let nativeCalls = 0;
|
|
116
|
-
let nativeBurns = 0;
|
|
117
|
-
let nativeMints = 0;
|
|
118
|
-
let nativeTransfers = 0;
|
|
119
|
-
let totalTransactions = 0;
|
|
120
|
-
|
|
121
|
-
let blocks = [];
|
|
122
|
-
let contracts = {};
|
|
123
|
-
const _ = {};
|
|
124
|
-
|
|
125
|
-
globalThis.BigNumber = BigNumber;
|
|
126
|
-
|
|
127
|
-
let lastBlock = { index: -1, hash: '0x0', previousHash: '0x0' };
|
|
128
|
-
|
|
129
|
-
const debug = (message) => {
|
|
130
|
-
worker.postMessage({
|
|
131
|
-
type: 'debug',
|
|
132
|
-
message
|
|
133
|
-
});
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
const has = (address) => {
|
|
137
|
-
return contracts[address] ? true : false
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
const get = ({ contract, method, params }) => {
|
|
141
|
-
let result;
|
|
142
|
-
if (params?.length > 0) {
|
|
143
|
-
result = contracts[contract][method](...params);
|
|
144
|
-
} else {
|
|
145
|
-
result = contracts[contract][method];
|
|
146
|
-
}
|
|
147
|
-
return result
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
const resolveContract = (address) => askFor('contract', address);
|
|
151
|
-
|
|
152
|
-
const respond = (id, value) => {
|
|
153
|
-
worker.postMessage({
|
|
154
|
-
type: 'response',
|
|
155
|
-
value,
|
|
156
|
-
id
|
|
157
|
-
});
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
_.runContract = async ({ decoded, hash, encoded }, state) => {
|
|
161
|
-
const params = decoded.constructorParameters;
|
|
162
|
-
try {
|
|
163
|
-
const func = new Function(new TextDecoder().decode(decoded.contract));
|
|
164
|
-
const Contract = func();
|
|
165
|
-
|
|
166
|
-
if (state) params.push(state);
|
|
167
|
-
|
|
168
|
-
globalThis.msg = createMessage(decoded.creator, hash);
|
|
169
|
-
contracts[hash] = await new Contract(...params);
|
|
170
|
-
|
|
171
|
-
debug(`loaded contract: ${hash} size: ${formatBytes(encoded.length)}`);
|
|
172
|
-
} catch (e) {
|
|
173
|
-
console.log(e);
|
|
174
|
-
worker.postMessage({
|
|
175
|
-
type: 'contractError',
|
|
176
|
-
message: e.message,
|
|
177
|
-
hash
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
_.execute = async ({ contract, method, params }) => {
|
|
183
|
-
try {
|
|
184
|
-
let result;
|
|
185
|
-
|
|
186
|
-
// don't execute the method on a proxy
|
|
187
|
-
if (contracts[contract].fallback) {
|
|
188
|
-
result = await contracts[contract].fallback(method, params);
|
|
189
|
-
} else {
|
|
190
|
-
result = await contracts[contract][method](...params);
|
|
191
|
-
}
|
|
192
|
-
// state.put(result)
|
|
193
|
-
return result
|
|
194
|
-
} catch (e) {
|
|
195
|
-
console.log({ e });
|
|
196
|
-
throw new Error(
|
|
197
|
-
`error: ${e.message}
|
|
198
|
-
contract: ${contract}
|
|
199
|
-
method: ${method}
|
|
200
|
-
params: ${JSON.stringify(params, null, '\t')}
|
|
201
|
-
`
|
|
202
|
-
)
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
const createMessage = (sender = globalThis.peerid, contract) => {
|
|
207
|
-
return {
|
|
208
|
-
contract,
|
|
209
|
-
sender,
|
|
210
|
-
call: _.execute,
|
|
211
|
-
staticCall: get
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
const _executeTransaction = async (transaction) => {
|
|
216
|
-
const hash = await new TransactionMessage(transaction).hash();
|
|
217
|
-
if (latestTransactions.includes(hash)) {
|
|
218
|
-
throw new Error(`double transaction found: ${hash} in block ${block.index}`)
|
|
219
|
-
} else {
|
|
220
|
-
latestTransactions.push(hash);
|
|
221
|
-
const { from, to, method, params, nonce } = transaction;
|
|
222
|
-
globalThis.msg = createMessage(from);
|
|
223
|
-
|
|
224
|
-
await _.execute({ contract: to, method, params });
|
|
225
|
-
if (to === nativeToken$2) {
|
|
226
|
-
nativeCalls += 1;
|
|
227
|
-
if (method === 'burn') nativeBurns += 1;
|
|
228
|
-
if (method === 'mint') nativeMints += 1;
|
|
229
|
-
if (method === 'transfer') nativeTransfers += 1;
|
|
230
|
-
}
|
|
231
|
-
totalTransactions += 1;
|
|
232
|
-
|
|
233
|
-
worker.postMessage({
|
|
234
|
-
type: 'transactionLoaded',
|
|
235
|
-
result: {
|
|
236
|
-
hash,
|
|
237
|
-
from,
|
|
238
|
-
nonce: String(nonce)
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
_.init = async (message) => {
|
|
245
|
-
let { peerid, fromState, state } = message;
|
|
246
|
-
globalThis.peerid = peerid;
|
|
247
|
-
console.log({ fromState });
|
|
248
|
-
if (fromState) {
|
|
249
|
-
lastBlock = message.lastBlock;
|
|
250
|
-
const setState = async (address, state) => {
|
|
251
|
-
const contractBytes = await resolveContract(address);
|
|
252
|
-
const contract = await new ContractMessage(contractBytes);
|
|
253
|
-
|
|
254
|
-
await _.runContract({ hash: address, decoded: contract.decoded, encoded: contract.encoded }, state);
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
const entries = Object.entries(state);
|
|
258
|
-
if (entries.length > 0) {
|
|
259
|
-
const promises = [];
|
|
260
|
-
for (const [address, value] of entries) {
|
|
261
|
-
promises.push(setState(address, value));
|
|
262
|
-
}
|
|
263
|
-
await Promise.all(promises);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const promises = [];
|
|
267
|
-
if (!contracts[addresses.contractFactory]) promises.push(setState(addresses.contractFactory));
|
|
268
|
-
if (!contracts[addresses.nameService]) promises.push(setState(addresses.nameService));
|
|
269
|
-
if (!contracts[addresses.validators]) promises.push(setState(addresses.validators));
|
|
270
|
-
if (!contracts[addresses.nativeToken]) promises.push(setState(addresses.nativeToken));
|
|
271
|
-
// contracts = await Promise.all(
|
|
272
|
-
// contracts.map(async (contract) => {
|
|
273
|
-
// contract = await new ContractMessage(new Uint8Array(contract.split(',')))
|
|
274
|
-
// await _.runContract({ decoded: contract.decoded, encoded: contract.encoded, hash: await contract.hash() })
|
|
275
|
-
// return contract
|
|
276
|
-
// })
|
|
277
|
-
// )
|
|
278
|
-
await Promise.all(promises);
|
|
279
|
-
} else {
|
|
280
|
-
await Promise.all(
|
|
281
|
-
[contractFactoryMessage, nativeTokenMessage, nameServiceMessage, validatorsMessage].map(async (contract) => {
|
|
282
|
-
contract = await new ContractMessage(new Uint8Array(contract.split(',')));
|
|
283
|
-
return _.runContract({ decoded: contract.decoded, encoded: contract.encoded, hash: await contract.hash() })
|
|
284
|
-
})
|
|
285
|
-
);
|
|
286
|
-
console.log({ blocks: message.blocks });
|
|
287
|
-
if (message.blocks?.length > 0) {
|
|
288
|
-
let pre;
|
|
289
|
-
|
|
290
|
-
try {
|
|
291
|
-
const importee = await import('url');
|
|
292
|
-
const url = importee.default;
|
|
293
|
-
if (url) pre = url.fileURLToPath(new URL('.', import.meta.url));
|
|
294
|
-
} catch {
|
|
295
|
-
// browser env
|
|
296
|
-
pre = './';
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
let _worker = await new EasyWorker(pre + 'block-worker.js', {
|
|
300
|
-
serialization: 'advanced',
|
|
301
|
-
type: 'module'
|
|
302
|
-
});
|
|
303
|
-
blocks = await _worker.once(message.blocks);
|
|
304
|
-
_worker = null;
|
|
305
|
-
// blocks = unique(globalThis.blocks ? globalThis : [], blocks)
|
|
306
|
-
// for (let i = 0; i < blocks.length; i++) {
|
|
307
|
-
|
|
308
|
-
// }
|
|
309
|
-
for (const block of blocks) {
|
|
310
|
-
// we only revalidate the latest 24 blocks
|
|
311
|
-
// every 24 blocks a snapshot is taken and stored in state
|
|
312
|
-
// this means contracts will be restored from this state
|
|
313
|
-
// this also means devs NEED to make sure the state can be restored
|
|
314
|
-
// on contract deploy an error will be thrown if state wasn't recoverable
|
|
315
|
-
if (block.index > 24) {
|
|
316
|
-
const transactionCount = blocks[block.index - 1].transactions.length;
|
|
317
|
-
latestTransactions.splice(-(transactionCount - 1), latestTransactions.length);
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (!block.loaded && !fromState) {
|
|
321
|
-
const priority = block.transactions.filter((transaction) => transaction.priority);
|
|
322
|
-
if (priority.length > 0)
|
|
323
|
-
await Promise.all(
|
|
324
|
-
priority.sort((a, b) => a.nonce - b.nonce).map((transaction) => _executeTransaction(transaction))
|
|
325
|
-
);
|
|
326
|
-
|
|
327
|
-
await Promise.all(
|
|
328
|
-
block.transactions
|
|
329
|
-
.filter((transaction) => !transaction.priority)
|
|
330
|
-
.map(async (transaction) => _executeTransaction(transaction))
|
|
331
|
-
);
|
|
332
|
-
}
|
|
333
|
-
block.loaded = true;
|
|
334
|
-
worker.postMessage({
|
|
335
|
-
type: 'debug',
|
|
336
|
-
message: `loaded transactions for block: ${block.blockInfo.hash} @${block.blockInfo.index} ${formatBytes(
|
|
337
|
-
block.blockInfo.size
|
|
338
|
-
)}`
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
if (blocks.length > 0) {
|
|
343
|
-
lastBlock = blocks[blocks.length - 1];
|
|
344
|
-
}
|
|
345
|
-
globalThis.blocks = blocks;
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
worker.postMessage({ type: 'machine-ready', lastBlock });
|
|
350
|
-
|
|
351
|
-
// worker.postMessage({blocks});
|
|
352
|
-
};
|
|
353
|
-
|
|
354
|
-
_.addLoadedBlock = (block) => {
|
|
355
|
-
blocks[block.index - 1] = block;
|
|
356
|
-
lastBlock = blocks[blocks.length - 1];
|
|
357
|
-
return true
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
_.loadBlock = (block) => {
|
|
361
|
-
// todo validate here and deprecate addLoadedBlock
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
const askFor = (question, input) =>
|
|
365
|
-
new Promise((resolve) => {
|
|
366
|
-
const id = randomUUID();
|
|
367
|
-
pubsub.subscribe(id, resolve);
|
|
368
|
-
worker.postMessage({
|
|
369
|
-
type: 'ask',
|
|
370
|
-
question,
|
|
371
|
-
input,
|
|
372
|
-
id
|
|
373
|
-
});
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
const runTask = async (id, taskName, input) => {
|
|
377
|
-
try {
|
|
378
|
-
const result = await _[taskName](input);
|
|
379
|
-
respond(id, result);
|
|
380
|
-
} catch (e) {
|
|
381
|
-
worker.postMessage({
|
|
382
|
-
type: `${taskName}Error`,
|
|
383
|
-
message: e.message,
|
|
384
|
-
id
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
worker.onmessage(({ id, type, input }) => {
|
|
390
|
-
if (pubsub.hasSubscribers(id)) {
|
|
391
|
-
pubsub.publish(id, input);
|
|
392
|
-
return
|
|
393
|
-
}
|
|
394
|
-
switch (type) {
|
|
395
|
-
case 'init':
|
|
396
|
-
runTask(id, 'init', input);
|
|
397
|
-
break
|
|
398
|
-
case 'run':
|
|
399
|
-
runTask(id, 'runContract', input);
|
|
400
|
-
break
|
|
401
|
-
case 'execute':
|
|
402
|
-
runTask(id, 'execute', input);
|
|
403
|
-
break
|
|
404
|
-
case 'addLoadedBlock':
|
|
405
|
-
runTask(id, 'addLoadedBlock', input);
|
|
406
|
-
break
|
|
407
|
-
case 'nativeCalls':
|
|
408
|
-
respond(id, nativeCalls);
|
|
409
|
-
break
|
|
410
|
-
case 'contracts':
|
|
411
|
-
respond(id, contracts);
|
|
412
|
-
break
|
|
413
|
-
case 'nativeMints':
|
|
414
|
-
respond(id, nativeMints);
|
|
415
|
-
break
|
|
416
|
-
case 'nativeBurns':
|
|
417
|
-
respond(id, nativeBurns);
|
|
418
|
-
break
|
|
419
|
-
case 'nativeTransfers':
|
|
420
|
-
respond(id, nativeTransfers);
|
|
421
|
-
break
|
|
422
|
-
case 'totalTransfers':
|
|
423
|
-
respond(id, totalTransfers);
|
|
424
|
-
break
|
|
425
|
-
case 'totalBlocks':
|
|
426
|
-
respond(id, blocks.length);
|
|
427
|
-
break
|
|
428
|
-
case 'blocks':
|
|
429
|
-
respond(id, input ? blocks.slice(input.from, input.to) : blocks);
|
|
430
|
-
break
|
|
431
|
-
case 'block':
|
|
432
|
-
respond(id, blocks[input - 1]);
|
|
433
|
-
break
|
|
434
|
-
case 'lastBlock':
|
|
435
|
-
respond(id, lastBlock);
|
|
436
|
-
break
|
|
437
|
-
case 'latestTransactions':
|
|
438
|
-
respond(id, latestTransactions);
|
|
439
|
-
break
|
|
440
|
-
case 'totalTransactions':
|
|
441
|
-
respond(id, totalTransactions);
|
|
442
|
-
break
|
|
443
|
-
case 'has':
|
|
444
|
-
respond(id, has(input.address));
|
|
445
|
-
break
|
|
446
|
-
case 'get':
|
|
447
|
-
respond(id, get(input));
|
|
448
|
-
break
|
|
449
|
-
default:
|
|
450
|
-
console.log(`machine-worker: unsupported taskType: ${type}`);
|
|
451
|
-
break
|
|
452
|
-
}
|
|
105
|
+
const pubsub = new LittlePubSub();
|
|
106
|
+
const worker = new EasyWorker();
|
|
107
|
+
|
|
108
|
+
const contractFactoryMessage = bytecodes.contractFactory;
|
|
109
|
+
const nativeTokenMessage = bytecodes.nativeToken;
|
|
110
|
+
const nameServiceMessage = bytecodes.nameService;
|
|
111
|
+
const validatorsMessage = bytecodes.validators;
|
|
112
|
+
|
|
113
|
+
const latestTransactions = [];
|
|
114
|
+
let nativeCalls = 0;
|
|
115
|
+
let nativeBurns = 0;
|
|
116
|
+
let nativeMints = 0;
|
|
117
|
+
let nativeTransfers = 0;
|
|
118
|
+
let totalTransactions = 0;
|
|
119
|
+
|
|
120
|
+
let blocks = [];
|
|
121
|
+
let contracts = {};
|
|
122
|
+
const _ = {};
|
|
123
|
+
|
|
124
|
+
globalThis.BigNumber = BigNumber;
|
|
125
|
+
|
|
126
|
+
let lastBlock = { index: -1, hash: '0x0', previousHash: '0x0' };
|
|
127
|
+
|
|
128
|
+
const debug = (message) => {
|
|
129
|
+
worker.postMessage({
|
|
130
|
+
type: 'debug',
|
|
131
|
+
message
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const has = (address) => {
|
|
136
|
+
return contracts[address] ? true : false
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const get = ({ contract, method, params }) => {
|
|
140
|
+
let result;
|
|
141
|
+
if (params?.length > 0) {
|
|
142
|
+
result = contracts[contract][method](...params);
|
|
143
|
+
} else {
|
|
144
|
+
result = contracts[contract][method];
|
|
145
|
+
}
|
|
146
|
+
return result
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const resolveContract = (address) => askFor('contract', address);
|
|
150
|
+
|
|
151
|
+
const respond = (id, value) => {
|
|
152
|
+
worker.postMessage({
|
|
153
|
+
type: 'response',
|
|
154
|
+
value,
|
|
155
|
+
id
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
_.runContract = async ({ decoded, hash, encoded }, state) => {
|
|
160
|
+
const params = decoded.constructorParameters;
|
|
161
|
+
try {
|
|
162
|
+
const func = new Function(new TextDecoder().decode(decoded.contract));
|
|
163
|
+
const Contract = func();
|
|
164
|
+
|
|
165
|
+
if (state) params.push(state);
|
|
166
|
+
|
|
167
|
+
globalThis.msg = createMessage(decoded.creator, hash);
|
|
168
|
+
contracts[hash] = await new Contract(...params);
|
|
169
|
+
|
|
170
|
+
debug(`loaded contract: ${hash} size: ${formatBytes(encoded.length)}`);
|
|
171
|
+
} catch (e) {
|
|
172
|
+
console.log(e);
|
|
173
|
+
worker.postMessage({
|
|
174
|
+
type: 'contractError',
|
|
175
|
+
message: e.message,
|
|
176
|
+
hash
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
_.execute = async ({ contract, method, params }) => {
|
|
182
|
+
try {
|
|
183
|
+
let result;
|
|
184
|
+
|
|
185
|
+
// don't execute the method on a proxy
|
|
186
|
+
if (contracts[contract].fallback) {
|
|
187
|
+
result = await contracts[contract].fallback(method, params);
|
|
188
|
+
} else {
|
|
189
|
+
result = await contracts[contract][method](...params);
|
|
190
|
+
}
|
|
191
|
+
// state.put(result)
|
|
192
|
+
return result
|
|
193
|
+
} catch (e) {
|
|
194
|
+
console.log({ e });
|
|
195
|
+
throw new Error(
|
|
196
|
+
`error: ${e.message}
|
|
197
|
+
contract: ${contract}
|
|
198
|
+
method: ${method}
|
|
199
|
+
params: ${JSON.stringify(params, null, '\t')}
|
|
200
|
+
`
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const createMessage = (sender = globalThis.peerid, contract) => {
|
|
206
|
+
return {
|
|
207
|
+
contract,
|
|
208
|
+
sender,
|
|
209
|
+
call: _.execute,
|
|
210
|
+
staticCall: get
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const _executeTransaction = async (transaction) => {
|
|
215
|
+
const hash = await new TransactionMessage(transaction).hash();
|
|
216
|
+
if (latestTransactions.includes(hash)) {
|
|
217
|
+
throw new Error(`double transaction found: ${hash} in block ${block.index}`)
|
|
218
|
+
} else {
|
|
219
|
+
latestTransactions.push(hash);
|
|
220
|
+
const { from, to, method, params, nonce } = transaction;
|
|
221
|
+
globalThis.msg = createMessage(from);
|
|
222
|
+
|
|
223
|
+
await _.execute({ contract: to, method, params });
|
|
224
|
+
if (to === nativeToken$2) {
|
|
225
|
+
nativeCalls += 1;
|
|
226
|
+
if (method === 'burn') nativeBurns += 1;
|
|
227
|
+
if (method === 'mint') nativeMints += 1;
|
|
228
|
+
if (method === 'transfer') nativeTransfers += 1;
|
|
229
|
+
}
|
|
230
|
+
totalTransactions += 1;
|
|
231
|
+
|
|
232
|
+
worker.postMessage({
|
|
233
|
+
type: 'transactionLoaded',
|
|
234
|
+
result: {
|
|
235
|
+
hash,
|
|
236
|
+
from,
|
|
237
|
+
nonce: String(nonce)
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
_.init = async (message) => {
|
|
244
|
+
let { peerid, fromState, state } = message;
|
|
245
|
+
globalThis.peerid = peerid;
|
|
246
|
+
console.log({ fromState });
|
|
247
|
+
if (fromState) {
|
|
248
|
+
lastBlock = message.lastBlock;
|
|
249
|
+
const setState = async (address, state) => {
|
|
250
|
+
const contractBytes = await resolveContract(address);
|
|
251
|
+
const contract = await new ContractMessage(contractBytes);
|
|
252
|
+
|
|
253
|
+
await _.runContract({ hash: address, decoded: contract.decoded, encoded: contract.encoded }, state);
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const entries = Object.entries(state);
|
|
257
|
+
if (entries.length > 0) {
|
|
258
|
+
const promises = [];
|
|
259
|
+
for (const [address, value] of entries) {
|
|
260
|
+
promises.push(setState(address, value));
|
|
261
|
+
}
|
|
262
|
+
await Promise.all(promises);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const promises = [];
|
|
266
|
+
if (!contracts[addresses.contractFactory]) promises.push(setState(addresses.contractFactory));
|
|
267
|
+
if (!contracts[addresses.nameService]) promises.push(setState(addresses.nameService));
|
|
268
|
+
if (!contracts[addresses.validators]) promises.push(setState(addresses.validators));
|
|
269
|
+
if (!contracts[addresses.nativeToken]) promises.push(setState(addresses.nativeToken));
|
|
270
|
+
// contracts = await Promise.all(
|
|
271
|
+
// contracts.map(async (contract) => {
|
|
272
|
+
// contract = await new ContractMessage(new Uint8Array(contract.split(',')))
|
|
273
|
+
// await _.runContract({ decoded: contract.decoded, encoded: contract.encoded, hash: await contract.hash() })
|
|
274
|
+
// return contract
|
|
275
|
+
// })
|
|
276
|
+
// )
|
|
277
|
+
await Promise.all(promises);
|
|
278
|
+
} else {
|
|
279
|
+
await Promise.all(
|
|
280
|
+
[contractFactoryMessage, nativeTokenMessage, nameServiceMessage, validatorsMessage].map(async (contract) => {
|
|
281
|
+
contract = await new ContractMessage(new Uint8Array(contract.split(',')));
|
|
282
|
+
return _.runContract({ decoded: contract.decoded, encoded: contract.encoded, hash: await contract.hash() })
|
|
283
|
+
})
|
|
284
|
+
);
|
|
285
|
+
console.log({ blocks: message.blocks });
|
|
286
|
+
if (message.blocks?.length > 0) {
|
|
287
|
+
let pre;
|
|
288
|
+
|
|
289
|
+
try {
|
|
290
|
+
const importee = await import('url');
|
|
291
|
+
const url = importee.default;
|
|
292
|
+
if (url) pre = url.fileURLToPath(new URL('.', import.meta.url));
|
|
293
|
+
} catch {
|
|
294
|
+
// browser env
|
|
295
|
+
pre = './';
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
let _worker = await new EasyWorker(pre + 'block-worker.js', {
|
|
299
|
+
serialization: 'advanced',
|
|
300
|
+
type: 'module'
|
|
301
|
+
});
|
|
302
|
+
blocks = await _worker.once(message.blocks);
|
|
303
|
+
_worker = null;
|
|
304
|
+
// blocks = unique(globalThis.blocks ? globalThis : [], blocks)
|
|
305
|
+
// for (let i = 0; i < blocks.length; i++) {
|
|
306
|
+
|
|
307
|
+
// }
|
|
308
|
+
for (const block of blocks) {
|
|
309
|
+
// we only revalidate the latest 24 blocks
|
|
310
|
+
// every 24 blocks a snapshot is taken and stored in state
|
|
311
|
+
// this means contracts will be restored from this state
|
|
312
|
+
// this also means devs NEED to make sure the state can be restored
|
|
313
|
+
// on contract deploy an error will be thrown if state wasn't recoverable
|
|
314
|
+
if (block.index > 24) {
|
|
315
|
+
const transactionCount = blocks[block.index - 1].transactions.length;
|
|
316
|
+
latestTransactions.splice(-(transactionCount - 1), latestTransactions.length);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (!block.loaded && !fromState) {
|
|
320
|
+
const priority = block.transactions.filter((transaction) => transaction.priority);
|
|
321
|
+
if (priority.length > 0)
|
|
322
|
+
await Promise.all(
|
|
323
|
+
priority.sort((a, b) => a.nonce - b.nonce).map((transaction) => _executeTransaction(transaction))
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
await Promise.all(
|
|
327
|
+
block.transactions
|
|
328
|
+
.filter((transaction) => !transaction.priority)
|
|
329
|
+
.map(async (transaction) => _executeTransaction(transaction))
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
block.loaded = true;
|
|
333
|
+
worker.postMessage({
|
|
334
|
+
type: 'debug',
|
|
335
|
+
message: `loaded transactions for block: ${block.blockInfo.hash} @${block.blockInfo.index} ${formatBytes(
|
|
336
|
+
block.blockInfo.size
|
|
337
|
+
)}`
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (blocks.length > 0) {
|
|
342
|
+
lastBlock = blocks[blocks.length - 1];
|
|
343
|
+
}
|
|
344
|
+
globalThis.blocks = blocks;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
worker.postMessage({ type: 'machine-ready', lastBlock });
|
|
349
|
+
|
|
350
|
+
// worker.postMessage({blocks});
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
_.addLoadedBlock = (block) => {
|
|
354
|
+
blocks[block.index - 1] = block;
|
|
355
|
+
lastBlock = blocks[blocks.length - 1];
|
|
356
|
+
return true
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
_.loadBlock = (block) => {
|
|
360
|
+
// todo validate here and deprecate addLoadedBlock
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const askFor = (question, input) =>
|
|
364
|
+
new Promise((resolve) => {
|
|
365
|
+
const id = globalThis.crypto.randomUUID();
|
|
366
|
+
pubsub.subscribe(id, resolve);
|
|
367
|
+
worker.postMessage({
|
|
368
|
+
type: 'ask',
|
|
369
|
+
question,
|
|
370
|
+
input,
|
|
371
|
+
id
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
const runTask = async (id, taskName, input) => {
|
|
376
|
+
try {
|
|
377
|
+
const result = await _[taskName](input);
|
|
378
|
+
respond(id, result);
|
|
379
|
+
} catch (e) {
|
|
380
|
+
worker.postMessage({
|
|
381
|
+
type: `${taskName}Error`,
|
|
382
|
+
message: e.message,
|
|
383
|
+
id
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
worker.onmessage(({ id, type, input }) => {
|
|
389
|
+
if (pubsub.hasSubscribers(id)) {
|
|
390
|
+
pubsub.publish(id, input);
|
|
391
|
+
return
|
|
392
|
+
}
|
|
393
|
+
switch (type) {
|
|
394
|
+
case 'init':
|
|
395
|
+
runTask(id, 'init', input);
|
|
396
|
+
break
|
|
397
|
+
case 'run':
|
|
398
|
+
runTask(id, 'runContract', input);
|
|
399
|
+
break
|
|
400
|
+
case 'execute':
|
|
401
|
+
runTask(id, 'execute', input);
|
|
402
|
+
break
|
|
403
|
+
case 'addLoadedBlock':
|
|
404
|
+
runTask(id, 'addLoadedBlock', input);
|
|
405
|
+
break
|
|
406
|
+
case 'nativeCalls':
|
|
407
|
+
respond(id, nativeCalls);
|
|
408
|
+
break
|
|
409
|
+
case 'contracts':
|
|
410
|
+
respond(id, contracts);
|
|
411
|
+
break
|
|
412
|
+
case 'nativeMints':
|
|
413
|
+
respond(id, nativeMints);
|
|
414
|
+
break
|
|
415
|
+
case 'nativeBurns':
|
|
416
|
+
respond(id, nativeBurns);
|
|
417
|
+
break
|
|
418
|
+
case 'nativeTransfers':
|
|
419
|
+
respond(id, nativeTransfers);
|
|
420
|
+
break
|
|
421
|
+
case 'totalTransfers':
|
|
422
|
+
respond(id, totalTransfers);
|
|
423
|
+
break
|
|
424
|
+
case 'totalBlocks':
|
|
425
|
+
respond(id, blocks.length);
|
|
426
|
+
break
|
|
427
|
+
case 'blocks':
|
|
428
|
+
respond(id, input ? blocks.slice(input.from, input.to) : blocks);
|
|
429
|
+
break
|
|
430
|
+
case 'block':
|
|
431
|
+
respond(id, blocks[input - 1]);
|
|
432
|
+
break
|
|
433
|
+
case 'lastBlock':
|
|
434
|
+
respond(id, lastBlock);
|
|
435
|
+
break
|
|
436
|
+
case 'latestTransactions':
|
|
437
|
+
respond(id, latestTransactions);
|
|
438
|
+
break
|
|
439
|
+
case 'totalTransactions':
|
|
440
|
+
respond(id, totalTransactions);
|
|
441
|
+
break
|
|
442
|
+
case 'has':
|
|
443
|
+
respond(id, has(input.address));
|
|
444
|
+
break
|
|
445
|
+
case 'get':
|
|
446
|
+
respond(id, get(input));
|
|
447
|
+
break
|
|
448
|
+
default:
|
|
449
|
+
console.log(`machine-worker: unsupported taskType: ${type}`);
|
|
450
|
+
break
|
|
451
|
+
}
|
|
453
452
|
});
|