@leofcoin/chain 1.4.73 → 1.4.75

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/chain.js CHANGED
@@ -1,242 +1,18 @@
1
1
  import { formatBytes, BigNumber, formatUnits, parseUnits } from '@leofcoin/utils';
2
+ import { TransactionMessage, BlockMessage, ContractMessage, BWMessage, BWRequestMessage } from '@leofcoin/messages';
2
3
  import addresses, { contractFactory, nativeToken, validators, nameService } from '@leofcoin/addresses';
4
+ import { calculateFee, createContractMessage, contractFactoryMessage, nativeTokenMessage, validatorsMessage, nameServiceMessage, signTransaction } from '@leofcoin/lib';
5
+ import PQueue from 'p-queue';
3
6
  import { randombytes } from '@leofcoin/crypto';
4
7
  import EasyWorker from '@vandeurenglenn/easy-worker';
5
- import { ContractMessage, TransactionMessage, BlockMessage, BWMessage, BWRequestMessage } from '@leofcoin/messages';
6
- import { calculateFee, createContractMessage, contractFactoryMessage, nativeTokenMessage, validatorsMessage, nameServiceMessage, signTransaction } from '@leofcoin/lib';
7
- import pako from 'pako';
8
-
9
- // import State from './state'
10
- class Machine {
11
- #contracts = {};
12
- #nonces = {};
13
- lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
14
- constructor(blocks) {
15
- return this.#init(blocks);
16
- }
17
- #createMessage(sender = peernet.selectedAccount) {
18
- return {
19
- sender,
20
- call: this.execute,
21
- staticCall: this.get.bind(this)
22
- };
23
- }
24
- async #onmessage(data) {
25
- switch (data.type) {
26
- case 'contractError': {
27
- console.warn(`removing contract ${await data.hash()}`);
28
- await contractStore.delete(await data.hash());
29
- break;
30
- }
31
- case 'initError': {
32
- console.error(`init error: ${data.message}`);
33
- break;
34
- }
35
- case 'executionError': {
36
- // console.warn(`error executing transaction ${data.message}`);
37
- pubsub.publish(data.id, { error: data.message });
38
- break;
39
- }
40
- case 'debug': {
41
- for (const message of data.messages)
42
- debug(message);
43
- break;
44
- }
45
- case 'machine-ready': {
46
- this.lastBlock = data.lastBlock;
47
- pubsub.publish('machine.ready', true);
48
- break;
49
- }
50
- case 'response': {
51
- pubsub.publish(data.id, data.value || false);
52
- break;
53
- }
54
- }
55
- }
56
- async #init(blocks) {
57
- return new Promise(async (resolve) => {
58
- const machineReady = () => {
59
- pubsub.unsubscribe('machine.ready', machineReady);
60
- resolve(this);
61
- };
62
- pubsub.subscribe('machine.ready', machineReady);
63
- this.worker = await new EasyWorker('node_modules/@leofcoin/workers/src/machine-worker.js', { serialization: 'advanced', type: 'module' });
64
- this.worker.onmessage(this.#onmessage.bind(this));
65
- // const blocks = await blockStore.values()
66
- const contracts = await Promise.all([
67
- contractStore.get(contractFactory),
68
- contractStore.get(nativeToken),
69
- contractStore.get(validators),
70
- contractStore.get(nameService)
71
- ]);
72
- const message = {
73
- type: 'init',
74
- input: {
75
- contracts,
76
- blocks,
77
- peerid: peernet.peerId
78
- }
79
- };
80
- this.worker.postMessage(message);
81
- });
82
- }
83
- async #runContract(contractMessage) {
84
- const hash = await contractMessage.hash();
85
- return new Promise((resolve, reject) => {
86
- const id = randombytes(20).toString('hex');
87
- const onmessage = message => {
88
- pubsub.unsubscribe(id, onmessage);
89
- if (message?.error)
90
- reject(message.error);
91
- else
92
- resolve(message);
93
- };
94
- pubsub.subscribe(id, onmessage);
95
- this.worker.postMessage({
96
- type: 'run',
97
- id,
98
- input: {
99
- decoded: contractMessage.decoded,
100
- encoded: contractMessage.encoded,
101
- hash
102
- }
103
- });
104
- });
105
- }
106
- /**
107
- *
108
- * @param {Address} contract
109
- * @param {String} method
110
- * @param {Array} parameters
111
- * @returns Promise<message>
112
- */
113
- async execute(contract, method, parameters) {
114
- try {
115
- if (contract === contractFactory && method === 'registerContract') {
116
- if (await this.has(parameters[0]))
117
- throw new Error(`duplicate contract @${parameters[0]}`);
118
- let message;
119
- if (!await contractStore.has(parameters[0])) {
120
- message = await peernet.get(parameters[0], 'contract');
121
- message = await new ContractMessage(message);
122
- await contractStore.put(await message.hash(), message.encoded);
123
- }
124
- if (!message) {
125
- message = await contractStore.get(parameters[0]);
126
- message = await new ContractMessage(message);
127
- }
128
- if (!await this.has(await message.hash()))
129
- await this.#runContract(message);
130
- }
131
- }
132
- catch (error) {
133
- throw new Error(`contract deployment failed for ${parameters[0]}\n${error.message}`);
134
- }
135
- return new Promise((resolve, reject) => {
136
- const id = randombytes(20).toString('hex');
137
- const onmessage = message => {
138
- pubsub.unsubscribe(id, onmessage);
139
- if (message?.error)
140
- reject(message.error);
141
- else
142
- resolve(message);
143
- };
144
- pubsub.subscribe(id, onmessage);
145
- this.worker.postMessage({
146
- type: 'execute',
147
- id,
148
- input: {
149
- contract,
150
- method,
151
- params: parameters
152
- }
153
- });
154
- });
155
- }
156
- get(contract, method, parameters) {
157
- return new Promise((resolve, reject) => {
158
- const id = randombytes(20).toString();
159
- const onmessage = message => {
160
- pubsub.unsubscribe(id, onmessage);
161
- resolve(message);
162
- };
163
- pubsub.subscribe(id, onmessage);
164
- this.worker.postMessage({
165
- type: 'get',
166
- id,
167
- input: {
168
- contract,
169
- method,
170
- params: parameters
171
- }
172
- });
173
- });
174
- }
175
- async has(address) {
176
- return new Promise((resolve, reject) => {
177
- const id = randombytes(20).toString('hex');
178
- const onmessage = message => {
179
- pubsub.unsubscribe(id, onmessage);
180
- if (message?.error)
181
- reject(message.error);
182
- else
183
- resolve(message);
184
- };
185
- pubsub.subscribe(id, onmessage);
186
- this.worker.postMessage({
187
- type: 'has',
188
- id,
189
- input: {
190
- address
191
- }
192
- });
193
- });
194
- }
195
- async delete(hash) {
196
- return contractStore.delete(hash);
197
- }
198
- /**
199
- *
200
- * @returns Promise
201
- */
202
- async deleteAll() {
203
- let hashes = await contractStore.get();
204
- hashes = Object.keys(hashes).map(hash => this.delete(hash));
205
- return Promise.all(hashes);
206
- }
207
- }
208
-
209
- class State {
210
- constructor() {
211
- // return this.#init()
212
- }
213
- // async #init() {
214
- // const state = await stateStore.get()
215
- // for (const [key, value] of Object.entries(state)) {
216
- //
217
- // }
218
- //
219
- // return this
220
- // }
221
- async put(key, value, isCompressed = true) {
222
- value = isCompressed ? value : await pako.deflate(value);
223
- await stateStore.put(key, value);
224
- }
225
- async get(key, isCompressed = true) {
226
- const value = await stateStore.get(key);
227
- return isCompressed = pako.inflate(value) ;
228
- }
229
- updateState(block) {
230
- // block.decoded.index
231
- // this.#isUpdateNeeded()
232
- }
233
- }
234
8
 
235
9
  const limit = 1800;
236
10
  const transactionLimit = 1800;
237
11
  const requestTimeout = 30_000;
238
12
  const syncTimeout = 30_000;
239
13
  class Protocol {
14
+ version;
15
+ resolveTimeout = 30_000;
240
16
  get limit() {
241
17
  return limit;
242
18
  }
@@ -425,6 +201,8 @@ class Contract extends Transaction {
425
201
  constructor() {
426
202
  super();
427
203
  }
204
+ async init() {
205
+ }
428
206
  /**
429
207
  *
430
208
  * @param {Address} creator
@@ -466,98 +244,588 @@ class Contract extends Transaction {
466
244
  }
467
245
  }
468
246
 
469
- globalThis.BigNumber = BigNumber;
470
- // check if browser or local
471
- class Chain extends Contract {
472
- #lastBlockInQue;
473
- #syncErrorCount = 0;
474
- version;
475
- #resolveErrored;
476
- #state;
477
- #lastResolved;
478
- #slotTime = 10000;
479
- id;
480
- utils;
481
- /** {Address[]} */
482
- #validators = [];
483
- /** {Block[]} */
484
- #blocks = [];
485
- #blockHashMap = new Map();
486
- #machine;
487
- /** {Boolean} */
488
- #runningEpoch = false;
489
- /** {Boolean} */
490
- #chainSyncing = false;
491
- /** {Number} */
492
- #totalSize = 0;
493
- /**
494
- * {Block} {index, hash, previousHash}
495
- */
496
- #lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
497
- /**
498
- * amount the native token has been iteracted with
499
- */
500
- #nativeCalls = 0;
501
- /**
502
- * amount the native token has been iteracted with
503
- */
504
- #nativeTransfers = 0;
505
- /**
506
- * amount of native token burned
507
- * {Number}
508
- */
509
- #nativeBurns = 0;
510
- /**
511
- * amount of native tokens minted
512
- * {Number}
513
- */
514
- #nativeMints = 0;
515
- /**
516
- * total amount of transactions
517
- * {Number}
518
- */
519
- #totalTransactions = 0;
520
- #participants = [];
247
+ // import State from './state'
248
+ class Machine {
249
+ #contracts = {};
250
+ #nonces = {};
251
+ lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
252
+ constructor(blocks) {
253
+ return this.#init(blocks);
254
+ }
255
+ #createMessage(sender = peernet.selectedAccount) {
256
+ return {
257
+ sender,
258
+ call: this.execute,
259
+ staticCall: this.get.bind(this)
260
+ };
261
+ }
262
+ async #onmessage(data) {
263
+ switch (data.type) {
264
+ case 'contractError': {
265
+ console.warn(`removing contract ${await data.hash()}`);
266
+ await contractStore.delete(await data.hash());
267
+ break;
268
+ }
269
+ case 'initError': {
270
+ console.error(`init error: ${data.message}`);
271
+ break;
272
+ }
273
+ case 'executionError': {
274
+ // console.warn(`error executing transaction ${data.message}`);
275
+ pubsub.publish(data.id, { error: data.message });
276
+ break;
277
+ }
278
+ case 'debug': {
279
+ for (const message of data.messages)
280
+ debug(message);
281
+ break;
282
+ }
283
+ case 'machine-ready': {
284
+ this.lastBlock = data.lastBlock;
285
+ pubsub.publish('machine.ready', true);
286
+ break;
287
+ }
288
+ case 'response': {
289
+ pubsub.publish(data.id, data.value || false);
290
+ break;
291
+ }
292
+ }
293
+ }
294
+ async #init(blocks) {
295
+ return new Promise(async (resolve) => {
296
+ const machineReady = () => {
297
+ pubsub.unsubscribe('machine.ready', machineReady);
298
+ resolve(this);
299
+ };
300
+ pubsub.subscribe('machine.ready', machineReady);
301
+ this.worker = await new EasyWorker('node_modules/@leofcoin/workers/src/machine-worker.js', { serialization: 'advanced', type: 'module' });
302
+ this.worker.onmessage(this.#onmessage.bind(this));
303
+ // const blocks = await blockStore.values()
304
+ const contracts = await Promise.all([
305
+ contractStore.get(contractFactory),
306
+ contractStore.get(nativeToken),
307
+ contractStore.get(validators),
308
+ contractStore.get(nameService)
309
+ ]);
310
+ const message = {
311
+ type: 'init',
312
+ input: {
313
+ contracts,
314
+ blocks,
315
+ peerid: peernet.peerId
316
+ }
317
+ };
318
+ this.worker.postMessage(message);
319
+ });
320
+ }
321
+ async #runContract(contractMessage) {
322
+ const hash = await contractMessage.hash();
323
+ return new Promise((resolve, reject) => {
324
+ const id = randombytes(20).toString('hex');
325
+ const onmessage = message => {
326
+ pubsub.unsubscribe(id, onmessage);
327
+ if (message?.error)
328
+ reject(message.error);
329
+ else
330
+ resolve(message);
331
+ };
332
+ pubsub.subscribe(id, onmessage);
333
+ this.worker.postMessage({
334
+ type: 'run',
335
+ id,
336
+ input: {
337
+ decoded: contractMessage.decoded,
338
+ encoded: contractMessage.encoded,
339
+ hash
340
+ }
341
+ });
342
+ });
343
+ }
344
+ /**
345
+ *
346
+ * @param {Address} contract
347
+ * @param {String} method
348
+ * @param {Array} parameters
349
+ * @returns Promise<message>
350
+ */
351
+ async execute(contract, method, parameters) {
352
+ try {
353
+ if (contract === contractFactory && method === 'registerContract') {
354
+ if (await this.has(parameters[0]))
355
+ throw new Error(`duplicate contract @${parameters[0]}`);
356
+ let message;
357
+ if (!await contractStore.has(parameters[0])) {
358
+ message = await peernet.get(parameters[0], 'contract');
359
+ message = await new ContractMessage(message);
360
+ await contractStore.put(await message.hash(), message.encoded);
361
+ }
362
+ if (!message) {
363
+ message = await contractStore.get(parameters[0]);
364
+ message = await new ContractMessage(message);
365
+ }
366
+ if (!await this.has(await message.hash()))
367
+ await this.#runContract(message);
368
+ }
369
+ }
370
+ catch (error) {
371
+ throw new Error(`contract deployment failed for ${parameters[0]}\n${error.message}`);
372
+ }
373
+ return new Promise((resolve, reject) => {
374
+ const id = randombytes(20).toString('hex');
375
+ const onmessage = message => {
376
+ pubsub.unsubscribe(id, onmessage);
377
+ if (message?.error)
378
+ reject(message.error);
379
+ else
380
+ resolve(message);
381
+ };
382
+ pubsub.subscribe(id, onmessage);
383
+ this.worker.postMessage({
384
+ type: 'execute',
385
+ id,
386
+ input: {
387
+ contract,
388
+ method,
389
+ params: parameters
390
+ }
391
+ });
392
+ });
393
+ }
394
+ get(contract, method, parameters) {
395
+ return new Promise((resolve, reject) => {
396
+ const id = randombytes(20).toString();
397
+ const onmessage = message => {
398
+ pubsub.unsubscribe(id, onmessage);
399
+ resolve(message);
400
+ };
401
+ pubsub.subscribe(id, onmessage);
402
+ this.worker.postMessage({
403
+ type: 'get',
404
+ id,
405
+ input: {
406
+ contract,
407
+ method,
408
+ params: parameters
409
+ }
410
+ });
411
+ });
412
+ }
413
+ async has(address) {
414
+ return new Promise((resolve, reject) => {
415
+ const id = randombytes(20).toString('hex');
416
+ const onmessage = message => {
417
+ pubsub.unsubscribe(id, onmessage);
418
+ if (message?.error)
419
+ reject(message.error);
420
+ else
421
+ resolve(message);
422
+ };
423
+ pubsub.subscribe(id, onmessage);
424
+ this.worker.postMessage({
425
+ type: 'has',
426
+ id,
427
+ input: {
428
+ address
429
+ }
430
+ });
431
+ });
432
+ }
433
+ async delete(hash) {
434
+ return contractStore.delete(hash);
435
+ }
436
+ /**
437
+ *
438
+ * @returns Promise
439
+ */
440
+ async deleteAll() {
441
+ let hashes = await contractStore.get();
442
+ hashes = Object.keys(hashes).map(hash => this.delete(hash));
443
+ return Promise.all(hashes);
444
+ }
445
+ }
446
+
447
+ const queue = new PQueue({ concurrency: 1, throwOnTimeout: true });
448
+ class State extends Contract {
449
+ #resolveErrored;
450
+ #lastResolvedTime;
451
+ #lastResolved;
452
+ #resolving = false;
453
+ #resolveErrorCount = 0;
454
+ #syncState;
455
+ #lastBlockInQue;
456
+ #syncErrorCount = 0;
457
+ #blockHashMap = new Map();
458
+ #chainSyncing = false;
459
+ #lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
460
+ #blocks = [];
461
+ #knownBlocks = [];
462
+ #totalSize = 0;
463
+ #machine;
464
+ /**
465
+ * amount the native token has been iteracted with
466
+ */
467
+ #nativeCalls = 0;
468
+ /**
469
+ * amount the native token has been iteracted with
470
+ */
471
+ #nativeTransfers = 0;
472
+ /**
473
+ * amount of native token burned
474
+ * {Number}
475
+ */
476
+ #nativeBurns = 0;
477
+ /**
478
+ * amount of native tokens minted
479
+ * {Number}
480
+ */
481
+ #nativeMints = 0;
482
+ /**
483
+ * total amount of transactions
484
+ * {Number}
485
+ */
486
+ #totalTransactions = 0;
487
+ get nativeMints() {
488
+ return this.#nativeMints;
489
+ }
490
+ get nativeBurns() {
491
+ return this.#nativeBurns;
492
+ }
493
+ get nativeTransfers() {
494
+ return this.#nativeTransfers;
495
+ }
496
+ get totalTransactions() {
497
+ return this.#totalTransactions;
498
+ }
499
+ get nativeCalls() {
500
+ return this.#nativeCalls;
501
+ }
502
+ get blocks() {
503
+ return [...this.#blocks];
504
+ }
505
+ get lastBlock() {
506
+ return this.#lastBlock;
507
+ }
508
+ get totalSize() {
509
+ return this.#totalSize;
510
+ }
511
+ get machine() {
512
+ return this.#machine;
513
+ }
514
+ constructor() {
515
+ super();
516
+ }
517
+ async init() {
518
+ if (super.init)
519
+ await super.init();
520
+ await globalThis.peernet.addRequestHandler('lastBlock', this.#lastBlockHandler.bind(this));
521
+ await globalThis.peernet.addRequestHandler('knownBlocks', this.#knownBlocksHandler.bind(this));
522
+ try {
523
+ let localBlock;
524
+ try {
525
+ localBlock = await globalThis.chainStore.get('lastBlock');
526
+ }
527
+ catch {
528
+ await globalThis.chainStore.put('lastBlock', '0x0');
529
+ localBlock = await globalThis.chainStore.get('lastBlock');
530
+ }
531
+ localBlock = new TextDecoder().decode(localBlock);
532
+ if (localBlock && localBlock !== '0x0') {
533
+ localBlock = await globalThis.peernet.get(localBlock, 'block');
534
+ localBlock = await new BlockMessage(localBlock);
535
+ this.#lastBlock = { ...localBlock.decoded, hash: await localBlock.hash() };
536
+ }
537
+ else {
538
+ if (globalThis.peernet?.connections.length > 0) {
539
+ const latestBlock = await this.#getLatestBlock();
540
+ await this.#syncChain(latestBlock);
541
+ }
542
+ }
543
+ }
544
+ catch (error) {
545
+ console.log({ e: error });
546
+ }
547
+ // load local blocks
548
+ await this.resolveBlocks();
549
+ this.#machine = await new Machine(this.#blocks);
550
+ await this.#loadBlocks(this.#blocks);
551
+ }
552
+ async updateState(message) {
553
+ const hash = await message.hash();
554
+ this.#lastBlock = { hash, ...message.decoded };
555
+ // await this.state.updateState(message)
556
+ await globalThis.chainStore.put('lastBlock', hash);
557
+ }
558
+ async #lastBlockHandler() {
559
+ return new globalThis.peernet.protos['peernet-response']({ response: { hash: this.#lastBlock?.hash, index: this.#lastBlock?.index } });
560
+ }
561
+ async #knownBlocksHandler() {
562
+ return new globalThis.peernet.protos['peernet-response']({ response: { blocks: this.#blocks.map((block) => block.hash) } });
563
+ }
564
+ getLatestBlock() {
565
+ return this.#getLatestBlock();
566
+ }
567
+ async getAndPutBlock(hash) {
568
+ // todo peernet resolves undefined blocks....
569
+ let block = await globalThis.peernet.get(hash, 'block');
570
+ if (block !== undefined) {
571
+ block = await new BlockMessage(block);
572
+ const { index } = block.decoded;
573
+ if (this.#blocks[index] && this.#blocks[index].hash !== block.hash)
574
+ throw `invalid block ${hash} @${index}`;
575
+ if (!await globalThis.peernet.has(hash, 'block'))
576
+ await globalThis.peernet.put(hash, block.encoded, 'block');
577
+ }
578
+ return block;
579
+ }
580
+ async #resolveBlock(hash) {
581
+ let index = this.#blockHashMap.get(hash);
582
+ if (this.#blocks[index]) {
583
+ if (this.#blocks[index].previousHash !== '0x0') {
584
+ return this.resolveBlock(this.#blocks[index].previousHash);
585
+ }
586
+ else {
587
+ return;
588
+ }
589
+ }
590
+ const block = await this.getAndPutBlock(hash);
591
+ index = block.decoded.index;
592
+ const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
593
+ this.#totalSize += size;
594
+ this.#blocks[index] = { hash, ...block.decoded };
595
+ this.#blockHashMap.set(hash, index);
596
+ globalThis.debug(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
597
+ this.#lastResolved = this.#blocks[index];
598
+ this.#lastResolvedTime = Date.now();
599
+ return;
600
+ }
601
+ async resolveBlock(hash) {
602
+ if (!hash)
603
+ throw new Error(`expected hash, got: ${hash}`);
604
+ if (hash === '0x0')
605
+ return;
606
+ if (this.#resolving)
607
+ return 'already resolving';
608
+ this.#resolving = true;
609
+ await queue.add(() => this.#resolveBlock(hash));
610
+ this.#resolving = false;
611
+ if (!this.#blockHashMap.has(this.#lastResolved.previousHash) && this.#lastResolved.previousHash !== '0x0')
612
+ return this.resolveBlock(this.#lastResolved.previousHash);
613
+ return;
614
+ }
615
+ async resolveBlocks() {
616
+ try {
617
+ const localBlock = await globalThis.chainStore.get('lastBlock');
618
+ const hash = new TextDecoder().decode(localBlock);
619
+ if (hash && hash !== '0x0')
620
+ await this.resolveBlock(hash);
621
+ this.#lastBlock = this.#blocks[this.#blocks.length - 1];
622
+ }
623
+ catch {
624
+ this.#resolveErrored = true;
625
+ this.#resolveErrorCount += 1;
626
+ this.#resolving = false;
627
+ // console.log(e);
628
+ }
629
+ }
630
+ async syncChain(lastBlock) {
631
+ if (!this.shouldSync) {
632
+ return;
633
+ }
634
+ await queue.clear();
635
+ this.#chainSyncing = true;
636
+ if (!lastBlock)
637
+ lastBlock = await this.#getLatestBlock();
638
+ console.log('starting sync');
639
+ if (globalThis.peernet.connections.length === 0)
640
+ return 'connectionless';
641
+ try {
642
+ await this.#syncChain(lastBlock);
643
+ }
644
+ catch (error) {
645
+ this.#syncErrorCount += 1;
646
+ if (this.#syncErrorCount < 3)
647
+ await this.#syncChain(lastBlock);
648
+ this.#chainSyncing = false;
649
+ this.#syncErrorCount = 0;
650
+ return 'errored';
651
+ }
652
+ if (lastBlock.index === this.#lastBlockInQue?.index)
653
+ this.#lastBlockInQue = undefined;
654
+ this.#syncErrorCount = 0;
655
+ this.#chainSyncing = false;
656
+ if (this.#lastBlockInQue)
657
+ return this.syncChain(this.#lastBlockInQue);
658
+ return 'synced';
659
+ }
660
+ async #syncChain(lastBlock) {
661
+ try {
662
+ if (this.#knownBlocks?.length === Number(lastBlock.index) + 1) {
663
+ let promises = [];
664
+ promises = await Promise.allSettled(this.#knownBlocks.map(async (address) => {
665
+ const has = await globalThis.peernet.has(address, 'block');
666
+ return { has, address };
667
+ }));
668
+ promises = promises.filter(({ status, value }) => status === 'fulfilled' && !value.has);
669
+ await Promise.allSettled(promises.map(({ value }) => this.getAndPutBlock(value.address)));
670
+ }
671
+ if (!this.#lastBlock || Number(this.#lastBlock.index) < Number(lastBlock.index)) {
672
+ // TODO: check if valid
673
+ const localIndex = this.#lastBlock ? this.lastBlock.index : 0;
674
+ const index = lastBlock.index;
675
+ await this.resolveBlock(lastBlock.hash);
676
+ console.log('ok');
677
+ let blocksSynced = localIndex > 0 ? (localIndex > index ? localIndex - index : index - localIndex) : index;
678
+ globalThis.debug(`synced ${blocksSynced} ${blocksSynced > 1 ? 'blocks' : 'block'}`);
679
+ const start = (this.#blocks.length - blocksSynced) - 1;
680
+ if (this.#machine)
681
+ await this.#loadBlocks(this.blocks.slice(start));
682
+ await this.updateState(new BlockMessage(this.#blocks[this.#blocks.length - 1]));
683
+ }
684
+ }
685
+ catch (error) {
686
+ console.log(error);
687
+ throw error;
688
+ }
689
+ }
690
+ async #getLatestBlock() {
691
+ let promises = [];
692
+ let data = await new globalThis.peernet.protos['peernet-request']({ request: 'lastBlock' });
693
+ let node = await globalThis.peernet.prepareMessage(data);
694
+ for (const peer of globalThis.peernet?.connections) {
695
+ if (peer.connected && peer.version === this.version) {
696
+ promises.push(async () => {
697
+ try {
698
+ const result = await peer.request(node.encoded);
699
+ return { result, peer };
700
+ }
701
+ catch (error) {
702
+ throw error;
703
+ }
704
+ });
705
+ }
706
+ }
707
+ promises = await this.promiseRequests(promises);
708
+ let latest = { index: 0, hash: '0x0', previousHash: '0x0' };
709
+ promises = promises.sort((a, b) => b.index - a.index);
710
+ if (promises.length > 0)
711
+ latest = promises[0].value;
712
+ if (latest.hash && latest.hash !== '0x0') {
713
+ let message = await globalThis.peernet.get(latest.hash, 'block');
714
+ message = await new BlockMessage(message);
715
+ const hash = await message.hash();
716
+ if (hash !== latest.hash)
717
+ throw new Error('invalid block @getLatestBlock');
718
+ latest = { ...message.decoded, hash };
719
+ const peer = promises[0].peer;
720
+ if (peer.connected && peer.version === this.version) {
721
+ let data = await new globalThis.peernet.protos['peernet-request']({ request: 'knownBlocks' });
722
+ let node = await globalThis.peernet.prepareMessage(data);
723
+ let message = await peer.request(node);
724
+ message = await new globalThis.peernet.protos['peernet-response'](message);
725
+ this.#knownBlocks = message.decoded.response;
726
+ }
727
+ }
728
+ return latest;
729
+ }
730
+ /**
731
+ *
732
+ * @param {Block[]} blocks
733
+ */
734
+ async #loadBlocks(blocks) {
735
+ let poolTransactionKeys = await globalThis.transactionPoolStore.keys();
736
+ for (const block of blocks) {
737
+ if (block && !block.loaded) {
738
+ for (const transaction of block.transactions) {
739
+ if (poolTransactionKeys.includes(transaction.hash))
740
+ await globalThis.transactionPoolStore.delete(transaction.hash);
741
+ try {
742
+ await this.#machine.execute(transaction.to, transaction.method, transaction.params);
743
+ if (transaction.to === nativeToken) {
744
+ this.#nativeCalls += 1;
745
+ if (transaction.method === 'burn')
746
+ this.#nativeBurns += 1;
747
+ if (transaction.method === 'mint')
748
+ this.#nativeMints += 1;
749
+ if (transaction.method === 'transfer')
750
+ this.#nativeTransfers += 1;
751
+ }
752
+ this.#totalTransactions += 1;
753
+ }
754
+ catch (error) {
755
+ console.log(error);
756
+ return false;
757
+ }
758
+ }
759
+ this.#blocks[block.index].loaded = true;
760
+ globalThis.debug(`loaded block: ${block.hash} @${block.index}`);
761
+ }
762
+ }
763
+ return true;
764
+ }
765
+ promiseRequests(promises) {
766
+ return new Promise(async (resolve, reject) => {
767
+ const timeout = setTimeout(() => {
768
+ resolve([{ index: 0, hash: '0x0' }]);
769
+ globalThis.debug('sync timed out');
770
+ }, this.requestTimeout);
771
+ promises = await Promise.allSettled(promises);
772
+ promises = promises.filter(({ status }) => status === 'fulfilled');
773
+ clearTimeout(timeout);
774
+ if (promises.length > 0) {
775
+ promises = promises.map(async ({ value }) => {
776
+ const node = await new globalThis.peernet.protos['peernet-response'](value);
777
+ return { value: node.decoded.response, peer: value.peer };
778
+ });
779
+ promises = await Promise.all(promises);
780
+ resolve(promises);
781
+ }
782
+ else {
783
+ resolve([]);
784
+ }
785
+ });
786
+ }
787
+ get canSync() {
788
+ if (this.#chainSyncing)
789
+ return false;
790
+ return true;
791
+ }
792
+ get shouldSync() {
793
+ if (this.canSync ||
794
+ this.#resolveErrored ||
795
+ !this.canSync && this.#lastResolvedTime + this.resolveTimeout > new Date().getTime())
796
+ return true;
797
+ return false;
798
+ }
799
+ async triggerSync() {
800
+ const latest = await this.#getLatestBlock();
801
+ return this.syncChain(latest);
802
+ }
803
+ }
804
+
805
+ globalThis.BigNumber = BigNumber;
806
+ // check if browser or local
807
+ class Chain extends State {
808
+ #state;
809
+ #slotTime = 10000;
810
+ id;
811
+ utils;
812
+ /** {Address[]} */
813
+ #validators = [];
814
+ /** {Boolean} */
815
+ #runningEpoch = false;
816
+ #participants = [];
521
817
  #participating = false;
522
818
  #jail = [];
523
- #knownBlocks = [];
524
819
  constructor() {
525
820
  super();
526
821
  return this.#init();
527
822
  }
528
- get nativeMints() {
529
- return this.#nativeMints;
530
- }
531
- get nativeBurns() {
532
- return this.#nativeBurns;
533
- }
534
- get nativeTransfers() {
535
- return this.#nativeTransfers;
536
- }
537
- get totalTransactions() {
538
- return this.#totalTransactions;
539
- }
540
- get nativeCalls() {
541
- return this.#nativeCalls;
542
- }
543
- get totalSize() {
544
- return this.#totalSize;
545
- }
546
- get lib() {
547
- return lib;
548
- }
549
- get lastBlock() {
550
- return this.#lastBlock;
551
- }
552
823
  get nativeToken() {
553
824
  return addresses.nativeToken;
554
825
  }
555
826
  get validators() {
556
827
  return [...this.#validators];
557
828
  }
558
- get blocks() {
559
- return [...this.#blocks];
560
- }
561
829
  async hasTransactionToHandle() {
562
830
  const size = await globalThis.transactionPoolStore.size();
563
831
  if (size > 0)
@@ -607,71 +875,6 @@ class Chain extends Contract {
607
875
  console.log('handle native contracts');
608
876
  // handle native contracts
609
877
  }
610
- promiseRequests(promises) {
611
- return new Promise(async (resolve, reject) => {
612
- const timeout = setTimeout(() => {
613
- resolve([{ index: 0, hash: '0x0' }]);
614
- globalThis.debug('sync timed out');
615
- }, this.requestTimeout);
616
- promises = await Promise.allSettled(promises);
617
- promises = promises.filter(({ status }) => status === 'fulfilled');
618
- clearTimeout(timeout);
619
- if (promises.length > 0) {
620
- promises = promises.map(async ({ value }) => {
621
- const node = await new globalThis.peernet.protos['peernet-response'](value.result);
622
- return { value: node.decoded.response, peer: value.peer };
623
- });
624
- promises = await Promise.all(promises);
625
- resolve(promises);
626
- }
627
- else {
628
- resolve([]);
629
- }
630
- });
631
- }
632
- getLatestBlock() {
633
- return this.#getLatestBlock();
634
- }
635
- async #getLatestBlock() {
636
- let promises = [];
637
- let data = await new globalThis.peernet.protos['peernet-request']({ request: 'lastBlock' });
638
- let node = await globalThis.peernet.prepareMessage(data);
639
- for (const peer of globalThis.peernet?.connections) {
640
- if (peer.connected && peer.version === this.version) {
641
- promises.push(async () => {
642
- try {
643
- const result = await peer.request(node.encoded);
644
- return { result, peer };
645
- }
646
- catch (error) {
647
- throw error;
648
- }
649
- });
650
- }
651
- }
652
- promises = await this.promiseRequests(promises);
653
- let latest = { index: 0, hash: '0x0', previousHash: '0x0' };
654
- promises = promises.sort((a, b) => b.index - a.index);
655
- if (promises.length > 0)
656
- latest = promises[0].value;
657
- if (latest.hash && latest.hash !== '0x0') {
658
- let message = await globalThis.peernet.get(latest.hash, 'block');
659
- message = await new BlockMessage(message);
660
- const hash = await message.hash();
661
- if (hash !== latest.hash)
662
- throw new Error('invalid block @getLatestBlock');
663
- latest = { ...message.decoded, hash };
664
- const peer = promises[0].peer;
665
- if (peer.connected && peer.version === this.version) {
666
- let data = await new globalThis.peernet.protos['peernet-request']({ request: 'knownBlocks' });
667
- let node = await globalThis.peernet.prepareMessage(data);
668
- let message = await peer.request(node);
669
- message = await new globalThis.peernet.protos['peernet-response'](message);
670
- this.#knownBlocks = message.decoded.response;
671
- }
672
- }
673
- return latest;
674
- }
675
878
  async #clearPool() {
676
879
  await globalThis.transactionPoolStore.clear();
677
880
  }
@@ -703,7 +906,7 @@ class Chain extends Contract {
703
906
  if (!initialized)
704
907
  await this.#setup();
705
908
  this.utils = { BigNumber, formatUnits, parseUnits };
706
- this.#state = new State();
909
+ // this.#state = new State()
707
910
  await globalThis.peernet.addRequestHandler('bw-request-message', () => {
708
911
  return new BWMessage(globalThis.peernet.client.bw) || { up: 0, down: 0 };
709
912
  });
@@ -713,43 +916,13 @@ class Chain extends Contract {
713
916
  // })
714
917
  await globalThis.peernet.addRequestHandler('transactionPool', this.#transactionPoolHandler.bind(this));
715
918
  await globalThis.peernet.addRequestHandler('version', this.#versionHandler.bind(this));
716
- await globalThis.peernet.addRequestHandler('lastBlock', this.#lastBlockHandler.bind(this));
717
- await globalThis.peernet.addRequestHandler('knownBlocks', this.#knownBlocksHandler.bind(this));
718
919
  globalThis.peernet.subscribe('add-block', this.#addBlock.bind(this));
719
920
  globalThis.peernet.subscribe('invalid-transaction', this.#invalidTransaction.bind(this));
720
921
  globalThis.peernet.subscribe('send-transaction', this.#sendTransaction.bind(this));
721
922
  globalThis.peernet.subscribe('validator:timeout', this.#validatorTimeout.bind(this));
722
923
  globalThis.pubsub.subscribe('peer:connected', this.#peerConnected.bind(this));
723
924
  // todo some functions rely on state
724
- try {
725
- let localBlock;
726
- try {
727
- localBlock = await globalThis.chainStore.get('lastBlock');
728
- }
729
- catch {
730
- await globalThis.chainStore.put('lastBlock', '0x0');
731
- localBlock = await globalThis.chainStore.get('lastBlock');
732
- }
733
- localBlock = new TextDecoder().decode(localBlock);
734
- if (localBlock && localBlock !== '0x0') {
735
- localBlock = await globalThis.peernet.get(localBlock, 'block');
736
- localBlock = await new BlockMessage(localBlock);
737
- this.#lastBlock = { ...localBlock.decoded, hash: await localBlock.hash() };
738
- }
739
- else {
740
- if (globalThis.peernet?.connections.length > 0) {
741
- const latestBlock = await this.#getLatestBlock();
742
- await this.#syncChain(latestBlock);
743
- }
744
- }
745
- }
746
- catch (error) {
747
- console.log({ e: error });
748
- }
749
- // load local blocks
750
- await this.resolveBlocks();
751
- this.#machine = await new Machine(this.#blocks);
752
- await this.#loadBlocks(this.#blocks);
925
+ await super.init();
753
926
  globalThis.globalThis.pubsub.publish('chain:ready', true);
754
927
  return this;
755
928
  }
@@ -763,82 +936,6 @@ class Chain extends Contract {
763
936
  }, validatorInfo.timeout);
764
937
  this.#jail.push(validatorInfo.address);
765
938
  }
766
- async triggerSync() {
767
- const latest = await this.#getLatestBlock();
768
- return this.syncChain(latest);
769
- }
770
- async syncChain(lastBlock) {
771
- if (!lastBlock)
772
- lastBlock = await this.#getLatestBlock();
773
- if (this.#chainSyncing) {
774
- console.log('already syncing');
775
- if (!this.#lastBlockInQue || lastBlock.index > this.#lastBlockInQue.index)
776
- this.#lastBlockInQue = lastBlock;
777
- return 'syncing';
778
- }
779
- console.log('starting sync');
780
- this.#chainSyncing = true;
781
- const syncPromise = (lastBlock) => new Promise(async (resolve, reject) => {
782
- const timeout = setTimeout(() => {
783
- this.#chainSyncing = false;
784
- this.#syncErrorCount = 0;
785
- reject('timedOut');
786
- }, 60000);
787
- try {
788
- await this.#syncChain(lastBlock);
789
- clearTimeout(timeout);
790
- resolve(true);
791
- }
792
- catch (error) {
793
- clearTimeout(timeout);
794
- reject(error);
795
- }
796
- });
797
- if (globalThis.peernet.connections.length === 0)
798
- return 'connectionless';
799
- try {
800
- await syncPromise(lastBlock);
801
- }
802
- catch (error) {
803
- console.log(error);
804
- this.#syncErrorCount += 1;
805
- if (this.#syncErrorCount < 3)
806
- await syncPromise(lastBlock);
807
- this.#chainSyncing = false;
808
- this.#syncErrorCount = 0;
809
- return 'errored';
810
- }
811
- if (lastBlock.index === this.#lastBlockInQue?.index)
812
- this.#lastBlockInQue = undefined;
813
- this.#syncErrorCount = 0;
814
- this.#chainSyncing = false;
815
- if (this.#lastBlockInQue)
816
- return this.syncChain(this.#lastBlockInQue);
817
- return 'synced';
818
- }
819
- async #syncChain(lastBlock) {
820
- if (this.#knownBlocks?.length === Number(lastBlock.index) + 1) {
821
- let promises = [];
822
- promises = await Promise.allSettled(this.#knownBlocks.map(async (address) => {
823
- const has = await globalThis.peernet.has(address, 'block');
824
- return { has, address };
825
- }));
826
- promises = promises.filter(({ status, value }) => status === 'fulfilled' && !value.has);
827
- await Promise.allSettled(promises.map(({ value }) => this.getAndPutBlock(value.address)));
828
- }
829
- if (!this.lastBlock || Number(this.lastBlock.index) < Number(lastBlock.index)) {
830
- // TODO: check if valid
831
- const localIndex = this.lastBlock ? this.lastBlock.index : 0;
832
- const index = lastBlock.index;
833
- await this.resolveBlock(lastBlock.hash);
834
- let blocksSynced = localIndex > 0 ? (localIndex > index ? localIndex - index : index - localIndex) : index;
835
- globalThis.debug(`synced ${blocksSynced} ${blocksSynced > 1 ? 'blocks' : 'block'}`);
836
- const start = (this.#blocks.length - blocksSynced) - 1;
837
- if (this.#machine)
838
- await this.#loadBlocks(this.blocks.slice(start));
839
- await this.#updateState(new BlockMessage(this.#blocks[this.#blocks.length - 1]));
840
- }
841
- }
842
939
  async #prepareRequest(request) {
843
940
  let node = await new globalThis.peernet.protos['peernet-request']({ request });
844
941
  return globalThis.peernet.prepareMessage(node);
@@ -854,12 +951,10 @@ class Chain extends Contract {
854
951
  return;
855
952
  const lastBlock = await this.#makeRequest(peer, 'lastBlock');
856
953
  if (Object.keys(lastBlock).length > 0) {
857
- if (this.#resolveErrored || !this.#lastBlock || lastBlock && lastBlock.index > this.#lastBlock?.index) {
954
+ if (!this.lastBlock || !this.blocks[this.blocks.length - 1].loaded || lastBlock && lastBlock.index > this.lastBlock?.index) {
858
955
  // this.#knownBlocks = await this.#makeRequest(peer, 'knownBlocks')
859
- this.#resolveErrored = false;
860
956
  await this.syncChain(lastBlock);
861
- if (await this.hasTransactionToHandle() && !this.#resolveErrored && this.#participating)
862
- this.#runEpoch();
957
+ // if (await this.hasTransactionToHandle() && this.#participating) this.#runEpoch()
863
958
  }
864
959
  }
865
960
  }
@@ -871,110 +966,10 @@ class Chain extends Contract {
871
966
  async #versionHandler() {
872
967
  return new globalThis.peernet.protos['peernet-response']({ response: { version: this.version } });
873
968
  }
874
- async #lastBlockHandler() {
875
- return new globalThis.peernet.protos['peernet-response']({ response: { hash: this.#lastBlock?.hash, index: this.#lastBlock?.index } });
876
- }
877
- async #knownBlocksHandler() {
878
- return new globalThis.peernet.protos['peernet-response']({ response: { blocks: this.#blocks.map((block) => block.hash) } });
879
- }
880
- async getAndPutBlock(hash) {
881
- // todo peernet resolves undefined blocks....
882
- let block = await globalThis.peernet.get(hash, 'block');
883
- if (block !== undefined) {
884
- block = await new BlockMessage(block);
885
- const { index } = block.decoded;
886
- if (this.#blocks[index] && this.#blocks[index].hash !== block.hash)
887
- throw `invalid block ${hash} @${index}`;
888
- if (!await globalThis.peernet.has(hash, 'block'))
889
- await globalThis.peernet.put(hash, block.encoded, 'block');
890
- }
891
- return block;
892
- }
893
- async resolveBlock(hash) {
894
- if (!hash)
895
- throw new Error(`expected hash, got: ${hash}`);
896
- if (hash === '0x0')
897
- return;
898
- const index = this.#blockHashMap.get(hash);
899
- if (this.#blocks[index]) {
900
- if (this.#blocks[index].previousHash !== '0x0') {
901
- return this.resolveBlock(this.#blocks[index].previousHash);
902
- }
903
- else {
904
- return;
905
- }
906
- }
907
- try {
908
- const block = await this.getAndPutBlock(hash);
909
- const { previousHash, index } = block.decoded;
910
- const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
911
- this.#totalSize += size;
912
- this.#blocks[index] = { hash, ...block.decoded };
913
- this.#blockHashMap.set(hash, index);
914
- console.log(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
915
- this.#lastResolved = Date.now();
916
- if (previousHash !== '0x0') {
917
- return this.resolveBlock(previousHash);
918
- }
919
- }
920
- catch (error) {
921
- this.#resolveErrored = true;
922
- console.error(error);
923
- }
924
- }
925
- async resolveBlocks() {
926
- try {
927
- const localBlock = await globalThis.chainStore.get('lastBlock');
928
- const hash = new TextDecoder().decode(localBlock);
929
- if (hash && hash !== '0x0')
930
- await this.resolveBlock(hash);
931
- this.#lastBlock = this.#blocks[this.#blocks.length - 1];
932
- }
933
- catch {
934
- await globalThis.chainStore.put('lastBlock', new TextEncoder().encode('0x0'));
935
- return this.resolveBlocks();
936
- // console.log(e);
937
- }
938
- }
939
- /**
940
- *
941
- * @param {Block[]} blocks
942
- */
943
- async #loadBlocks(blocks) {
944
- let poolTransactionKeys = await globalThis.transactionPoolStore.keys();
945
- for (const block of blocks) {
946
- if (block && !block.loaded) {
947
- for (const transaction of block.transactions) {
948
- if (poolTransactionKeys.includes(transaction.hash))
949
- await globalThis.transactionPoolStore.delete(transaction.hash);
950
- try {
951
- await this.#machine.execute(transaction.to, transaction.method, transaction.params);
952
- if (transaction.to === nativeToken) {
953
- this.#nativeCalls += 1;
954
- if (transaction.method === 'burn')
955
- this.#nativeBurns += 1;
956
- if (transaction.method === 'mint')
957
- this.#nativeMints += 1;
958
- if (transaction.method === 'transfer')
959
- this.#nativeTransfers += 1;
960
- }
961
- this.#totalTransactions += 1;
962
- }
963
- catch (error) {
964
- console.log(error);
965
- return false;
966
- }
967
- }
968
- this.#blocks[block.index].loaded = true;
969
- globalThis.debug(`loaded block: ${block.hash} @${block.index}`);
970
- }
971
- }
972
- return true;
973
- }
974
969
  async #executeTransaction({ hash, from, to, method, params, nonce }) {
975
970
  try {
976
- let result = await this.#machine.execute(to, method, params, from, nonce);
977
- // if (!result) result = this.#machine.state
971
+ let result = await this.machine.execute(to, method, params);
972
+ // if (!result) result = this.machine.state
978
973
  globalThis.pubsub.publish(`transaction.completed.${hash}`, { status: 'fulfilled', hash });
979
974
  return result || 'no state change';
980
975
  }
@@ -992,7 +987,7 @@ class Chain extends Contract {
992
987
  const hash = await blockMessage.hash();
993
988
  await globalThis.blockStore.put(hash, blockMessage.encoded);
994
989
  if (this.lastBlock.index < blockMessage.decoded.index)
995
- await this.#updateState(blockMessage);
990
+ await this.updateState(blockMessage);
996
991
  globalThis.debug(`added block: ${hash}`);
997
992
  let promises = [];
998
993
  let contracts = [];
@@ -1014,7 +1009,7 @@ class Chain extends Contract {
1014
1009
  }
1015
1010
  // todo finish state
1016
1011
  // for (const contract of contracts) {
1017
- // const state = await this.#machine.get(contract, 'state')
1012
+ // const state = await this.machine.get(contract, 'state')
1018
1013
  // // await stateStore.put(contract, state)
1019
1014
  // console.log(state);
1020
1015
  // }
@@ -1024,12 +1019,6 @@ class Chain extends Contract {
1024
1019
  console.log({ e: error });
1025
1020
  }
1026
1021
  }
1027
- async #updateState(message) {
1028
- const hash = await message.hash();
1029
- this.#lastBlock = { hash, ...message.decoded };
1030
- // await this.state.updateState(message)
1031
- await globalThis.chainStore.put('lastBlock', hash);
1032
- }
1033
1022
  async participate(address) {
1034
1023
  // TODO: validate participant
1035
1024
  // hold min amount of 50k ART for 7 days
@@ -1077,7 +1066,7 @@ class Chain extends Contract {
1077
1066
  for (let transaction of transactions) {
1078
1067
  const hash = await transaction.hash();
1079
1068
  const doubleTransactions = [];
1080
- for (const block of this.#blocks) {
1069
+ for (const block of this.blocks) {
1081
1070
  for (const transaction of block.transactions) {
1082
1071
  if (transaction.hash === hash) {
1083
1072
  doubleTransactions.push(hash);
@@ -1168,7 +1157,7 @@ class Chain extends Contract {
1168
1157
  let blockMessage = await new BlockMessage(block);
1169
1158
  const hash = await blockMessage.hash();
1170
1159
  await globalThis.peernet.put(hash, blockMessage.encoded, 'block');
1171
- await this.#updateState(blockMessage);
1160
+ await this.updateState(blockMessage);
1172
1161
  globalThis.debug(`created block: ${hash}`);
1173
1162
  globalThis.peernet.publish('add-block', blockMessage.encoded);
1174
1163
  globalThis.pubsub.publish('add-block', blockMessage.decoded);
@@ -1177,7 +1166,7 @@ class Chain extends Contract {
1177
1166
  console.log(error);
1178
1167
  throw new Error(`invalid block ${block}`);
1179
1168
  }
1180
- // data = await this.#machine.execute(to, method, params)
1169
+ // data = await this.machine.execute(to, method, params)
1181
1170
  // transactionStore.put(message.hash, message.encoded)
1182
1171
  }
1183
1172
  async #sendTransaction(transaction) {
@@ -1241,7 +1230,7 @@ class Chain extends Contract {
1241
1230
  */
1242
1231
  internalCall(sender, contract, method, parameters) {
1243
1232
  globalThis.msg = this.#createMessage(sender);
1244
- return this.#machine.execute(contract, method, parameters);
1233
+ return this.machine.execute(contract, method, parameters);
1245
1234
  }
1246
1235
  /**
1247
1236
  *
@@ -1252,19 +1241,19 @@ class Chain extends Contract {
1252
1241
  */
1253
1242
  call(contract, method, parameters) {
1254
1243
  globalThis.msg = this.#createMessage();
1255
- return this.#machine.execute(contract, method, parameters);
1244
+ return this.machine.execute(contract, method, parameters);
1256
1245
  }
1257
1246
  staticCall(contract, method, parameters) {
1258
1247
  globalThis.msg = this.#createMessage();
1259
- return this.#machine.get(contract, method, parameters);
1248
+ return this.machine.get(contract, method, parameters);
1260
1249
  }
1261
1250
  delegate(contract, method, parameters) {
1262
1251
  globalThis.msg = this.#createMessage();
1263
- return this.#machine.execute(contract, method, parameters);
1252
+ return this.machine.execute(contract, method, parameters);
1264
1253
  }
1265
1254
  staticDelegate(contract, method, parameters) {
1266
1255
  globalThis.msg = this.#createMessage();
1267
- return this.#machine.get(contract, method, parameters);
1256
+ return this.machine.get(contract, method, parameters);
1268
1257
  }
1269
1258
  mint(to, amount) {
1270
1259
  return this.call(addresses.nativeToken, 'mint', [to, amount]);
@@ -1279,7 +1268,7 @@ class Chain extends Contract {
1279
1268
  return this.staticCall(addresses.contractFactory, 'contracts');
1280
1269
  }
1281
1270
  deleteAll() {
1282
- return this.#machine.deleteAll();
1271
+ return this.machine.deleteAll();
1283
1272
  }
1284
1273
  /**
1285
1274
  * lookup an address for a registered name using the builtin nameService