@leofcoin/chain 1.5.24 → 1.5.26
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/chain.js +148 -97
- package/exports/browser/{index-de7cd283.js → index-055d5584.js} +16 -2
- package/exports/browser/{index-329e0324-a0469bb9.js → index-329e0324-f8858eb6.js} +2 -2
- package/exports/browser/{messages-000b7f84-8465e629.js → messages-000b7f84-2f945543.js} +2 -2
- package/exports/browser/{node-browser-c27ce598.js → node-browser-ccafb3fc.js} +6 -4
- package/exports/browser/node-browser.js +2 -2
- package/exports/browser/workers/block-worker.js +32 -28
- package/exports/browser/workers/machine-worker.js +222 -233
- package/exports/browser/workers/{worker-156dda16.js → worker-5b02efbe.js} +10 -2
- package/exports/chain.d.ts +1 -0
- package/exports/chain.js +137 -86
- package/exports/contract.d.ts +1 -1
- package/exports/jobs/jobber.d.ts +1 -1
- package/exports/node.js +3 -1
- package/exports/state.d.ts +8 -2
- package/exports/transaction.d.ts +2 -2
- package/exports/version-control.d.ts +1 -1
- package/exports/workers/block-worker.js +32 -28
- package/exports/workers/machine-worker.js +222 -233
- package/exports/workers/{worker-156dda16.js → worker-5b02efbe.js} +10 -2
- package/package.json +2 -1
- package/exports/browser/index-329e0324-dcac6dff.js +0 -37
- package/exports/browser/index-b3d08518.js +0 -5703
- package/exports/browser/messages-000b7f84-8b18c4c6.js +0 -225
- package/exports/browser/node-browser-f8484520.js +0 -20987
package/exports/chain.js
CHANGED
|
@@ -12,7 +12,7 @@ const requestTimeout = 30000;
|
|
|
12
12
|
const syncTimeout = 30000;
|
|
13
13
|
class Protocol {
|
|
14
14
|
constructor() {
|
|
15
|
-
this.resolveTimeout =
|
|
15
|
+
this.resolveTimeout = 10000;
|
|
16
16
|
}
|
|
17
17
|
get limit() {
|
|
18
18
|
return limit;
|
|
@@ -41,11 +41,11 @@ class Transaction extends Protocol {
|
|
|
41
41
|
return new Promise(async (resolve, reject) => {
|
|
42
42
|
let size = 0;
|
|
43
43
|
const _transactions = [];
|
|
44
|
-
await Promise.all(transactions
|
|
45
|
-
.map(async (tx) => {
|
|
44
|
+
await Promise.all(transactions.map(async (tx) => {
|
|
46
45
|
tx = await new TransactionMessage(tx);
|
|
47
46
|
size += tx.encoded.length;
|
|
48
|
-
if (!formatBytes(size).includes('MB') ||
|
|
47
|
+
if (!formatBytes(size).includes('MB') ||
|
|
48
|
+
(formatBytes(size).includes('MB') && Number(formatBytes(size).split(' MB')[0]) <= 0.75))
|
|
49
49
|
_transactions.push({ ...tx.decoded, hash: await tx.hash() });
|
|
50
50
|
else
|
|
51
51
|
resolve(_transactions);
|
|
@@ -59,7 +59,7 @@ class Transaction extends Protocol {
|
|
|
59
59
|
* @returns {TransactionMessage}
|
|
60
60
|
*/
|
|
61
61
|
async promiseTransactions(transactions) {
|
|
62
|
-
transactions = await Promise.all(transactions.map(tx => new TransactionMessage(tx.encoded || tx)));
|
|
62
|
+
transactions = await Promise.all(transactions.map((tx) => new TransactionMessage(tx.encoded || tx)));
|
|
63
63
|
return transactions;
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
@@ -68,7 +68,7 @@ class Transaction extends Protocol {
|
|
|
68
68
|
* @returns {Object} {transaction.decoded, transaction.hash}
|
|
69
69
|
*/
|
|
70
70
|
async promiseTransactionsContent(transactions) {
|
|
71
|
-
transactions = await Promise.all(transactions.map(tx => new Promise(async (resolve, reject) => {
|
|
71
|
+
transactions = await Promise.all(transactions.map((tx) => new Promise(async (resolve, reject) => {
|
|
72
72
|
resolve({ ...tx.decoded, hash: await tx.hash() });
|
|
73
73
|
})));
|
|
74
74
|
return transactions;
|
|
@@ -81,7 +81,7 @@ class Transaction extends Protocol {
|
|
|
81
81
|
async #getNonceFallback(address) {
|
|
82
82
|
let transactions = await globalThis.transactionPoolStore.values();
|
|
83
83
|
transactions = await this.promiseTransactions(transactions);
|
|
84
|
-
transactions = transactions.filter(tx => tx.decoded.from === address);
|
|
84
|
+
transactions = transactions.filter((tx) => tx.decoded.from === address);
|
|
85
85
|
transactions = await this.promiseTransactionsContent(transactions);
|
|
86
86
|
// @ts-ignore
|
|
87
87
|
if (this.lastBlock?.hash && transactions.length === 0 && this.lastBlock.hash !== '0x0') {
|
|
@@ -92,11 +92,11 @@ class Transaction extends Protocol {
|
|
|
92
92
|
// tx = await peernet.get(tx, 'transaction')
|
|
93
93
|
// transactions.push(new TransactionMessage(tx))
|
|
94
94
|
// }
|
|
95
|
-
transactions = transactions.filter(tx => tx.from === address);
|
|
95
|
+
transactions = transactions.filter((tx) => tx.from === address);
|
|
96
96
|
while (transactions.length === 0 && block.decoded.index !== 0 && block.decoded.previousHash !== '0x0') {
|
|
97
97
|
block = await globalThis.blockStore.get(block.decoded.previousHash);
|
|
98
98
|
block = await new BlockMessage(block);
|
|
99
|
-
transactions = block.decoded.transactions.filter(tx => tx.from === address);
|
|
99
|
+
transactions = block.decoded.transactions.filter((tx) => tx.from === address);
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
if (transactions.length === 0)
|
|
@@ -110,7 +110,7 @@ class Transaction extends Protocol {
|
|
|
110
110
|
* @returns {Number} nonce
|
|
111
111
|
*/
|
|
112
112
|
async getNonce(address) {
|
|
113
|
-
if (!await globalThis.accountsStore.has(address)) {
|
|
113
|
+
if (!(await globalThis.accountsStore.has(address))) {
|
|
114
114
|
const nonce = await this.#getNonceFallback(address);
|
|
115
115
|
await globalThis.accountsStore.put(address, new TextEncoder().encode(String(nonce)));
|
|
116
116
|
}
|
|
@@ -119,7 +119,7 @@ class Transaction extends Protocol {
|
|
|
119
119
|
nonce = new TextDecoder().decode(nonce);
|
|
120
120
|
let transactions = await globalThis.transactionPoolStore.values();
|
|
121
121
|
transactions = await this.promiseTransactions(transactions);
|
|
122
|
-
transactions = transactions.filter(tx => tx.decoded.from === address);
|
|
122
|
+
transactions = transactions.filter((tx) => tx.decoded.from === address);
|
|
123
123
|
transactions = await this.promiseTransactionsContent(transactions);
|
|
124
124
|
for (const transaction of transactions) {
|
|
125
125
|
if (transaction.nonce > nonce)
|
|
@@ -136,7 +136,7 @@ class Transaction extends Protocol {
|
|
|
136
136
|
throw new Error(`a transaction with the same nonce already exists`);
|
|
137
137
|
let transactions = await globalThis.transactionPoolStore.values();
|
|
138
138
|
transactions = await this.promiseTransactions(transactions);
|
|
139
|
-
transactions = transactions.filter(tx => tx.decoded.from === address);
|
|
139
|
+
transactions = transactions.filter((tx) => tx.decoded.from === address);
|
|
140
140
|
for (const transaction of transactions) {
|
|
141
141
|
if (transaction.decoded.nonce > nonce)
|
|
142
142
|
throw new Error(`a transaction with a higher nonce already exists`);
|
|
@@ -215,8 +215,7 @@ class Contract extends Transaction {
|
|
|
215
215
|
constructor() {
|
|
216
216
|
super();
|
|
217
217
|
}
|
|
218
|
-
async init() {
|
|
219
|
-
}
|
|
218
|
+
async init() { }
|
|
220
219
|
/**
|
|
221
220
|
*
|
|
222
221
|
* @param {Address} creator
|
|
@@ -335,7 +334,10 @@ class Machine {
|
|
|
335
334
|
// browser env
|
|
336
335
|
pre = './';
|
|
337
336
|
}
|
|
338
|
-
this.worker = await new EasyWorker(pre + 'workers/machine-worker.js', {
|
|
337
|
+
this.worker = await new EasyWorker(pre + 'workers/machine-worker.js', {
|
|
338
|
+
serialization: 'advanced',
|
|
339
|
+
type: 'module'
|
|
340
|
+
});
|
|
339
341
|
this.worker.onmessage(this.#onmessage.bind(this));
|
|
340
342
|
// const blocks = await blockStore.values()
|
|
341
343
|
const contracts = await Promise.all([
|
|
@@ -361,7 +363,7 @@ class Machine {
|
|
|
361
363
|
return new Promise((resolve, reject) => {
|
|
362
364
|
// @ts-ignore
|
|
363
365
|
const id = randombytes(20).toString('hex');
|
|
364
|
-
const onmessage = message => {
|
|
366
|
+
const onmessage = (message) => {
|
|
365
367
|
pubsub.unsubscribe(id, onmessage);
|
|
366
368
|
if (message?.error)
|
|
367
369
|
reject(message.error);
|
|
@@ -393,7 +395,7 @@ class Machine {
|
|
|
393
395
|
if (await this.has(parameters[0]))
|
|
394
396
|
throw new Error(`duplicate contract @${parameters[0]}`);
|
|
395
397
|
let message;
|
|
396
|
-
if (!await globalThis.contractStore.has(parameters[0])) {
|
|
398
|
+
if (!(await globalThis.contractStore.has(parameters[0]))) {
|
|
397
399
|
message = await peernet.get(parameters[0], 'contract');
|
|
398
400
|
message = await new ContractMessage(message);
|
|
399
401
|
await globalThis.contractStore.put(await message.hash(), message.encoded);
|
|
@@ -402,7 +404,7 @@ class Machine {
|
|
|
402
404
|
message = await globalThis.contractStore.get(parameters[0]);
|
|
403
405
|
message = await new ContractMessage(message);
|
|
404
406
|
}
|
|
405
|
-
if (!await this.has(await message.hash()))
|
|
407
|
+
if (!(await this.has(await message.hash())))
|
|
406
408
|
await this.#runContract(message);
|
|
407
409
|
}
|
|
408
410
|
}
|
|
@@ -412,7 +414,7 @@ class Machine {
|
|
|
412
414
|
return new Promise((resolve, reject) => {
|
|
413
415
|
// @ts-ignore
|
|
414
416
|
const id = randombytes(20).toString('hex');
|
|
415
|
-
const onmessage = message => {
|
|
417
|
+
const onmessage = (message) => {
|
|
416
418
|
pubsub.unsubscribe(id, onmessage);
|
|
417
419
|
if (message?.error)
|
|
418
420
|
reject(new ExecutionError(message.error));
|
|
@@ -434,7 +436,7 @@ class Machine {
|
|
|
434
436
|
get(contract, method, parameters) {
|
|
435
437
|
return new Promise((resolve, reject) => {
|
|
436
438
|
const id = randombytes(20).toString();
|
|
437
|
-
const onmessage = message => {
|
|
439
|
+
const onmessage = (message) => {
|
|
438
440
|
pubsub.unsubscribe(id, onmessage);
|
|
439
441
|
resolve(message);
|
|
440
442
|
};
|
|
@@ -454,7 +456,7 @@ class Machine {
|
|
|
454
456
|
return new Promise((resolve, reject) => {
|
|
455
457
|
// @ts-ignore
|
|
456
458
|
const id = randombytes(20).toString('hex');
|
|
457
|
-
const onmessage = message => {
|
|
459
|
+
const onmessage = (message) => {
|
|
458
460
|
pubsub.unsubscribe(id, onmessage);
|
|
459
461
|
if (message?.error)
|
|
460
462
|
reject(message.error);
|
|
@@ -480,7 +482,7 @@ class Machine {
|
|
|
480
482
|
*/
|
|
481
483
|
async deleteAll() {
|
|
482
484
|
let hashes = await globalThis.contractStore.keys();
|
|
483
|
-
hashes = Object.keys(hashes).map(hash => this.delete(hash));
|
|
485
|
+
hashes = Object.keys(hashes).map((hash) => this.delete(hash));
|
|
484
486
|
return Promise.all(hashes);
|
|
485
487
|
}
|
|
486
488
|
}
|
|
@@ -496,7 +498,7 @@ class Jobber {
|
|
|
496
498
|
const timeout = setTimeout(() => {
|
|
497
499
|
reject('timeout');
|
|
498
500
|
}, this.timeout);
|
|
499
|
-
this.
|
|
501
|
+
this.destroy = () => {
|
|
500
502
|
clearTimeout(timeout);
|
|
501
503
|
this.busy = false;
|
|
502
504
|
resolve('stopped');
|
|
@@ -508,6 +510,7 @@ class Jobber {
|
|
|
508
510
|
resolve(result);
|
|
509
511
|
}
|
|
510
512
|
catch (error) {
|
|
513
|
+
clearTimeout(timeout);
|
|
511
514
|
reject(error);
|
|
512
515
|
}
|
|
513
516
|
});
|
|
@@ -521,6 +524,7 @@ class State extends Contract {
|
|
|
521
524
|
#resolving;
|
|
522
525
|
#resolveErrorCount;
|
|
523
526
|
#syncState;
|
|
527
|
+
#chainState;
|
|
524
528
|
#lastBlockInQue;
|
|
525
529
|
#syncErrorCount;
|
|
526
530
|
#blockHashMap;
|
|
@@ -530,6 +534,12 @@ class State extends Contract {
|
|
|
530
534
|
#totalSize;
|
|
531
535
|
#machine;
|
|
532
536
|
#loaded;
|
|
537
|
+
get state() {
|
|
538
|
+
return {
|
|
539
|
+
sync: this.#syncState,
|
|
540
|
+
chain: this.#chainState
|
|
541
|
+
};
|
|
542
|
+
}
|
|
533
543
|
get blockHashMap() {
|
|
534
544
|
return this.#blockHashMap.entries();
|
|
535
545
|
}
|
|
@@ -591,8 +601,10 @@ class State extends Contract {
|
|
|
591
601
|
}
|
|
592
602
|
constructor() {
|
|
593
603
|
super();
|
|
604
|
+
this.#lastResolvedTime = 0;
|
|
594
605
|
this.#resolving = false;
|
|
595
606
|
this.#resolveErrorCount = 0;
|
|
607
|
+
this.#chainState = 'loading';
|
|
596
608
|
this.#syncErrorCount = 0;
|
|
597
609
|
this.#blockHashMap = new Map();
|
|
598
610
|
this.#chainSyncing = false;
|
|
@@ -624,12 +636,28 @@ class State extends Contract {
|
|
|
624
636
|
* {Number}
|
|
625
637
|
*/
|
|
626
638
|
this.#totalTransactions = 0;
|
|
639
|
+
this.#chainStateHandler = () => {
|
|
640
|
+
return new globalThis.peernet.protos['peernet-response']({
|
|
641
|
+
response: this.#chainState
|
|
642
|
+
});
|
|
643
|
+
};
|
|
644
|
+
this.#lastBlockHandler = async () => {
|
|
645
|
+
return new globalThis.peernet.protos['peernet-response']({
|
|
646
|
+
response: { hash: this.#lastBlock?.hash, index: this.#lastBlock?.index }
|
|
647
|
+
});
|
|
648
|
+
};
|
|
649
|
+
this.#knownBlocksHandler = async () => {
|
|
650
|
+
return new globalThis.peernet.protos['peernet-response']({
|
|
651
|
+
response: { blocks: this.#blocks.map((block) => block.hash) }
|
|
652
|
+
});
|
|
653
|
+
};
|
|
627
654
|
this.#loadBlockTransactions = (transactions) => Promise.all(transactions.map((transaction) => new TransactionMessage(transaction)));
|
|
628
655
|
this.#getLastTransactions = async () => {
|
|
629
|
-
let lastTransactions = (await Promise.all(this.#blocks
|
|
630
|
-
.
|
|
631
|
-
.
|
|
632
|
-
|
|
656
|
+
let lastTransactions = (await Promise.all(this.#blocks
|
|
657
|
+
.filter((block) => block.loaded)
|
|
658
|
+
.slice(-128)
|
|
659
|
+
.map((block) => this.#loadBlockTransactions(block.transactions)))).reduce((all, transactions) => [...all, ...transactions], []);
|
|
660
|
+
return Promise.all(lastTransactions.map((transaction) => transaction.hash()));
|
|
633
661
|
};
|
|
634
662
|
}
|
|
635
663
|
async clearPool() {
|
|
@@ -644,12 +672,16 @@ class State extends Contract {
|
|
|
644
672
|
await globalThis.blockStore.clear();
|
|
645
673
|
await globalThis.transactionPoolStore.clear();
|
|
646
674
|
}
|
|
675
|
+
#chainStateHandler;
|
|
676
|
+
#lastBlockHandler;
|
|
677
|
+
#knownBlocksHandler;
|
|
647
678
|
async init() {
|
|
648
|
-
this.jobber = new Jobber(
|
|
679
|
+
this.jobber = new Jobber(this.resolveTimeout);
|
|
649
680
|
if (super.init)
|
|
650
681
|
await super.init();
|
|
651
|
-
await globalThis.peernet.addRequestHandler('lastBlock', this.#lastBlockHandler
|
|
652
|
-
await globalThis.peernet.addRequestHandler('knownBlocks', this.#knownBlocksHandler
|
|
682
|
+
await globalThis.peernet.addRequestHandler('lastBlock', this.#lastBlockHandler);
|
|
683
|
+
await globalThis.peernet.addRequestHandler('knownBlocks', this.#knownBlocksHandler);
|
|
684
|
+
await globalThis.peernet.addRequestHandler('chainState', this.#chainStateHandler);
|
|
653
685
|
try {
|
|
654
686
|
let localBlock;
|
|
655
687
|
try {
|
|
@@ -663,7 +695,10 @@ class State extends Contract {
|
|
|
663
695
|
if (localBlock && localBlock !== '0x0') {
|
|
664
696
|
localBlock = await globalThis.peernet.get(localBlock, 'block');
|
|
665
697
|
localBlock = await new BlockMessage(localBlock);
|
|
666
|
-
this.#lastBlock = {
|
|
698
|
+
this.#lastBlock = {
|
|
699
|
+
...localBlock.decoded,
|
|
700
|
+
hash: await localBlock.hash()
|
|
701
|
+
};
|
|
667
702
|
}
|
|
668
703
|
else {
|
|
669
704
|
if (globalThis.peernet?.connections.length > 0) {
|
|
@@ -704,12 +739,6 @@ class State extends Contract {
|
|
|
704
739
|
await globalThis.chainStore.put('lastBlock', hash);
|
|
705
740
|
globalThis.pubsub.publish('lastBlock', this.#lastBlock);
|
|
706
741
|
}
|
|
707
|
-
async #lastBlockHandler() {
|
|
708
|
-
return new globalThis.peernet.protos['peernet-response']({ response: { hash: this.#lastBlock?.hash, index: this.#lastBlock?.index } });
|
|
709
|
-
}
|
|
710
|
-
async #knownBlocksHandler() {
|
|
711
|
-
return new globalThis.peernet.protos['peernet-response']({ response: { blocks: this.#blocks.map((block) => block.hash) } });
|
|
712
|
-
}
|
|
713
742
|
getLatestBlock() {
|
|
714
743
|
// @ts-ignore
|
|
715
744
|
return this.#getLatestBlock();
|
|
@@ -722,7 +751,7 @@ class State extends Contract {
|
|
|
722
751
|
const { index } = block.decoded;
|
|
723
752
|
if (this.#blocks[index - 1] && this.#blocks[index - 1].hash !== block.hash)
|
|
724
753
|
throw `invalid block ${hash} @${index}`;
|
|
725
|
-
if (!await globalThis.peernet.has(hash))
|
|
754
|
+
if (!(await globalThis.peernet.has(hash)))
|
|
726
755
|
await globalThis.peernet.put(hash, block.encoded, 'block');
|
|
727
756
|
}
|
|
728
757
|
return block;
|
|
@@ -750,8 +779,6 @@ class State extends Contract {
|
|
|
750
779
|
this.#lastResolvedTime = Date.now();
|
|
751
780
|
}
|
|
752
781
|
catch (error) {
|
|
753
|
-
this.#resolving = false;
|
|
754
|
-
this.#chainSyncing = false;
|
|
755
782
|
throw new ResolveError(`block: ${hash}@${index}`);
|
|
756
783
|
}
|
|
757
784
|
return;
|
|
@@ -764,6 +791,8 @@ class State extends Contract {
|
|
|
764
791
|
if (this.#resolving)
|
|
765
792
|
return 'already resolving';
|
|
766
793
|
this.#resolving = true;
|
|
794
|
+
if (this.jobber.busy && this.jobber.destroy)
|
|
795
|
+
await this.jobber.destroy();
|
|
767
796
|
try {
|
|
768
797
|
await this.jobber.add(() => this.#resolveBlock(hash));
|
|
769
798
|
this.#resolving = false;
|
|
@@ -773,6 +802,7 @@ class State extends Contract {
|
|
|
773
802
|
catch (error) {
|
|
774
803
|
console.log({ error });
|
|
775
804
|
this.#resolveErrorCount += 1;
|
|
805
|
+
this.#resolving = false;
|
|
776
806
|
if (this.#resolveErrorCount < 3)
|
|
777
807
|
return this.resolveBlock(hash);
|
|
778
808
|
this.#resolveErrorCount = 0;
|
|
@@ -781,8 +811,8 @@ class State extends Contract {
|
|
|
781
811
|
}
|
|
782
812
|
async resolveBlocks() {
|
|
783
813
|
try {
|
|
784
|
-
if (this.jobber.busy && this.jobber.
|
|
785
|
-
await this.jobber.
|
|
814
|
+
if (this.jobber.busy && this.jobber.destroy) {
|
|
815
|
+
await this.jobber.destroy();
|
|
786
816
|
}
|
|
787
817
|
}
|
|
788
818
|
catch (error) {
|
|
@@ -798,10 +828,10 @@ class State extends Contract {
|
|
|
798
828
|
}
|
|
799
829
|
catch (error) {
|
|
800
830
|
console.log(error);
|
|
831
|
+
this.#chainSyncing = false;
|
|
832
|
+
this.#syncState = 'errored';
|
|
801
833
|
this.#resolveErrored = true;
|
|
802
|
-
this
|
|
803
|
-
this.#resolving = false;
|
|
804
|
-
this.restoreChain();
|
|
834
|
+
return this.restoreChain();
|
|
805
835
|
// console.log(e);
|
|
806
836
|
}
|
|
807
837
|
}
|
|
@@ -819,23 +849,24 @@ class State extends Contract {
|
|
|
819
849
|
this.#resolveErrored = true;
|
|
820
850
|
this.#resolveErrorCount += 1;
|
|
821
851
|
this.#resolving = false;
|
|
822
|
-
this.restoreChain();
|
|
852
|
+
return this.restoreChain();
|
|
823
853
|
// console.log(e);
|
|
824
854
|
}
|
|
825
855
|
}
|
|
856
|
+
destroyResolveJob() { }
|
|
826
857
|
async syncChain(lastBlock) {
|
|
827
|
-
if (!this.shouldSync)
|
|
858
|
+
if (!this.shouldSync)
|
|
828
859
|
return;
|
|
829
|
-
|
|
860
|
+
this.#syncState;
|
|
861
|
+
this.#chainSyncing = true;
|
|
830
862
|
try {
|
|
831
|
-
if (this.jobber.busy && this.jobber.
|
|
832
|
-
await this.jobber.
|
|
863
|
+
if (this.jobber.busy && this.jobber.destroy) {
|
|
864
|
+
await this.jobber.destroy();
|
|
833
865
|
}
|
|
834
866
|
}
|
|
835
867
|
catch (error) {
|
|
836
868
|
console.error(error);
|
|
837
869
|
}
|
|
838
|
-
this.#chainSyncing = true;
|
|
839
870
|
if (!lastBlock)
|
|
840
871
|
lastBlock = await this.#getLatestBlock();
|
|
841
872
|
console.log('starting sync');
|
|
@@ -850,7 +881,8 @@ class State extends Contract {
|
|
|
850
881
|
return this.syncChain(lastBlock);
|
|
851
882
|
this.#syncErrorCount = 0;
|
|
852
883
|
this.#chainSyncing = false;
|
|
853
|
-
|
|
884
|
+
this.#syncState = 'errored';
|
|
885
|
+
return this.#syncState;
|
|
854
886
|
}
|
|
855
887
|
if (lastBlock.index === this.#lastBlockInQue?.index)
|
|
856
888
|
this.#lastBlockInQue = undefined;
|
|
@@ -858,7 +890,8 @@ class State extends Contract {
|
|
|
858
890
|
this.#chainSyncing = false;
|
|
859
891
|
if (this.#lastBlockInQue)
|
|
860
892
|
return this.syncChain(this.#lastBlockInQue);
|
|
861
|
-
|
|
893
|
+
this.#syncState = 'synced';
|
|
894
|
+
return this.#syncState;
|
|
862
895
|
}
|
|
863
896
|
async #syncChain(lastBlock) {
|
|
864
897
|
try {
|
|
@@ -879,7 +912,7 @@ class State extends Contract {
|
|
|
879
912
|
console.log('ok');
|
|
880
913
|
let blocksSynced = localIndex > 0 ? (localIndex > index ? localIndex - index : index + -localIndex) : index;
|
|
881
914
|
globalThis.debug(`synced ${blocksSynced} ${blocksSynced > 1 ? 'blocks' : 'block'}`);
|
|
882
|
-
const start =
|
|
915
|
+
const start = this.#blocks.length - blocksSynced;
|
|
883
916
|
if (this.#machine)
|
|
884
917
|
await this.#loadBlocks(this.blocks.slice(start));
|
|
885
918
|
await this.updateState(new BlockMessage(this.#blocks[this.#blocks.length - 1]));
|
|
@@ -892,7 +925,9 @@ class State extends Contract {
|
|
|
892
925
|
}
|
|
893
926
|
async #getLatestBlock() {
|
|
894
927
|
let promises = [];
|
|
895
|
-
let data = await new globalThis.peernet.protos['peernet-request']({
|
|
928
|
+
let data = await new globalThis.peernet.protos['peernet-request']({
|
|
929
|
+
request: 'lastBlock'
|
|
930
|
+
});
|
|
896
931
|
let node = await globalThis.peernet.prepareMessage(data);
|
|
897
932
|
for (const peer of globalThis.peernet?.connections) {
|
|
898
933
|
// @ts-ignore
|
|
@@ -924,7 +959,9 @@ class State extends Contract {
|
|
|
924
959
|
latest = { ...message.decoded, hash };
|
|
925
960
|
const peer = promises[0].peer;
|
|
926
961
|
if (peer.connected && peer.version === this.version) {
|
|
927
|
-
let data = await new globalThis.peernet.protos['peernet-request']({
|
|
962
|
+
let data = await new globalThis.peernet.protos['peernet-request']({
|
|
963
|
+
request: 'knownBlocks'
|
|
964
|
+
});
|
|
928
965
|
let node = await globalThis.peernet.prepareMessage(data);
|
|
929
966
|
let message = await peer.request(node);
|
|
930
967
|
message = await new globalThis.peernet.protos['peernet-response'](message);
|
|
@@ -940,6 +977,7 @@ class State extends Contract {
|
|
|
940
977
|
* @param {Block[]} blocks
|
|
941
978
|
*/
|
|
942
979
|
async #loadBlocks(blocks) {
|
|
980
|
+
this.#chainState = 'loading';
|
|
943
981
|
let poolTransactionKeys = await globalThis.transactionPoolStore.keys();
|
|
944
982
|
for (const block of blocks) {
|
|
945
983
|
if (block && !block.loaded) {
|
|
@@ -992,6 +1030,7 @@ class State extends Contract {
|
|
|
992
1030
|
globalThis.pubsub.publish('block-loaded', { ...block });
|
|
993
1031
|
}
|
|
994
1032
|
}
|
|
1033
|
+
this.#chainState = 'loaded';
|
|
995
1034
|
return true;
|
|
996
1035
|
}
|
|
997
1036
|
promiseRequests(promises) {
|
|
@@ -1022,9 +1061,12 @@ class State extends Contract {
|
|
|
1022
1061
|
return true;
|
|
1023
1062
|
}
|
|
1024
1063
|
get shouldSync() {
|
|
1025
|
-
if (this
|
|
1026
|
-
|
|
1027
|
-
|
|
1064
|
+
if (this.#chainSyncing)
|
|
1065
|
+
return false;
|
|
1066
|
+
if (this.#resolveErrored ||
|
|
1067
|
+
this.#syncState === 'errored' ||
|
|
1068
|
+
this.#syncState === 'connectionless' ||
|
|
1069
|
+
(!this.canSync && this.#lastResolvedTime + this.resolveTimeout > Date.now()))
|
|
1028
1070
|
return true;
|
|
1029
1071
|
return false;
|
|
1030
1072
|
}
|
|
@@ -1044,7 +1086,7 @@ class VersionControl extends State {
|
|
|
1044
1086
|
super();
|
|
1045
1087
|
}
|
|
1046
1088
|
async init() {
|
|
1047
|
-
super.init && await super.init();
|
|
1089
|
+
super.init && (await super.init());
|
|
1048
1090
|
console.log('init');
|
|
1049
1091
|
try {
|
|
1050
1092
|
const version = await globalThis.chainStore.get('version');
|
|
@@ -1126,29 +1168,34 @@ class Chain extends VersionControl {
|
|
|
1126
1168
|
console.error(error);
|
|
1127
1169
|
}
|
|
1128
1170
|
const end = Date.now();
|
|
1129
|
-
console.log((
|
|
1171
|
+
console.log((end - start) / 1000 + ' s');
|
|
1130
1172
|
if (await this.hasTransactionToHandle())
|
|
1131
1173
|
return this.#runEpoch();
|
|
1132
1174
|
this.#runningEpoch = false;
|
|
1133
1175
|
// if (await this.hasTransactionToHandle() && !this.#runningEpoch) return this.#runEpoch()
|
|
1134
1176
|
}
|
|
1135
1177
|
async #setup() {
|
|
1136
|
-
const contracts = [
|
|
1178
|
+
const contracts = [
|
|
1179
|
+
{
|
|
1137
1180
|
address: addresses.contractFactory,
|
|
1138
1181
|
message: contractFactoryMessage
|
|
1139
|
-
},
|
|
1182
|
+
},
|
|
1183
|
+
{
|
|
1140
1184
|
address: addresses.nativeToken,
|
|
1141
1185
|
message: nativeTokenMessage
|
|
1142
|
-
},
|
|
1186
|
+
},
|
|
1187
|
+
{
|
|
1143
1188
|
address: addresses.validators,
|
|
1144
1189
|
message: validatorsMessage
|
|
1145
|
-
},
|
|
1190
|
+
},
|
|
1191
|
+
{
|
|
1146
1192
|
address: addresses.nameService,
|
|
1147
1193
|
message: nameServiceMessage
|
|
1148
|
-
}
|
|
1194
|
+
}
|
|
1195
|
+
];
|
|
1149
1196
|
await Promise.all(contracts.map(async ({ address, message }) => {
|
|
1150
1197
|
// @ts-ignore
|
|
1151
|
-
message = await new ContractMessage(Uint8Array.from(message.split(',').map(string => Number(string))));
|
|
1198
|
+
message = await new ContractMessage(Uint8Array.from(message.split(',').map((string) => Number(string))));
|
|
1152
1199
|
// @ts-ignore
|
|
1153
1200
|
await globalThis.contractStore.put(address, message.encoded);
|
|
1154
1201
|
}));
|
|
@@ -1170,7 +1217,7 @@ class Chain extends VersionControl {
|
|
|
1170
1217
|
return new BWMessage(globalThis.peernet.client.bw) || { up: 0, down: 0 };
|
|
1171
1218
|
});
|
|
1172
1219
|
// await globalThis.peernet.addRequestHandler('peerId', () => {
|
|
1173
|
-
// let node =
|
|
1220
|
+
// let node =
|
|
1174
1221
|
// globalThis.peernet.protos['peernet-response']({response: node.encoded})
|
|
1175
1222
|
// })
|
|
1176
1223
|
await globalThis.peernet.addRequestHandler('transactionPool', this.#transactionPoolHandler.bind(this));
|
|
@@ -1207,31 +1254,36 @@ class Chain extends VersionControl {
|
|
|
1207
1254
|
response = await new globalThis.peernet.protos['peernet-response'](new Uint8Array(Object.values(response)));
|
|
1208
1255
|
return response.decoded.response;
|
|
1209
1256
|
}
|
|
1257
|
+
async getPeerTransactionPool(peer) {
|
|
1258
|
+
const transactionsInPool = await this.#makeRequest(peer, 'transactionPool');
|
|
1259
|
+
// todo iterate vs getting all keys?
|
|
1260
|
+
const transactions = await globalThis.transactionPoolStore.keys();
|
|
1261
|
+
const transactionsToGet = [];
|
|
1262
|
+
for (const key of transactionsInPool) {
|
|
1263
|
+
!transactions.includes(key) &&
|
|
1264
|
+
!ignorelist.includes(key) &&
|
|
1265
|
+
transactionsToGet.push(transactionPoolStore.put(key, await peernet.get(key, 'transaction')));
|
|
1266
|
+
}
|
|
1267
|
+
return Promise.all(transactionsToGet);
|
|
1268
|
+
}
|
|
1210
1269
|
async #peerConnected(peer) {
|
|
1211
1270
|
// todo handle version changes
|
|
1212
1271
|
// for now just do nothing if version doesn't match
|
|
1213
1272
|
if (!peer.version || peer.version !== this.version)
|
|
1214
1273
|
return;
|
|
1215
1274
|
const lastBlock = await this.#makeRequest(peer, 'lastBlock');
|
|
1216
|
-
|
|
1217
|
-
const
|
|
1218
|
-
const transactionsToGet = [];
|
|
1219
|
-
for (const key of transactionsInPool) {
|
|
1220
|
-
if (!transactions.includes(key) && !ignorelist.includes(key))
|
|
1221
|
-
transactionsToGet.push(transactionPoolStore.put(key, (await peernet.get(key, 'transaction'))));
|
|
1222
|
-
}
|
|
1223
|
-
await Promise.all(transactionsToGet);
|
|
1275
|
+
const higherThenCurrentLocal = lastBlock.index > this.lastBlock?.index;
|
|
1276
|
+
const peerTransactionPool = (higherThenCurrentLocal && (await this.getPeerTransactionPool(peer))) || [];
|
|
1224
1277
|
if (Object.keys(lastBlock).length > 0) {
|
|
1225
|
-
if (!this.lastBlock ||
|
|
1278
|
+
if (!this.lastBlock || higherThenCurrentLocal) {
|
|
1226
1279
|
this.knownBlocks = await this.#makeRequest(peer, 'knownBlocks');
|
|
1227
1280
|
await this.syncChain(lastBlock);
|
|
1228
|
-
// if (await this.hasTransactionToHandle() && this.#participating) this.#runEpoch()
|
|
1229
1281
|
}
|
|
1230
1282
|
else if (!this.knownBlocks)
|
|
1231
1283
|
this.knownBlocks = await this.#makeRequest(peer, 'knownBlocks');
|
|
1232
1284
|
}
|
|
1233
|
-
if (this.#participating)
|
|
1234
|
-
this.#runEpoch();
|
|
1285
|
+
if (this.#participating && peerTransactionPool.length > 0)
|
|
1286
|
+
return this.#runEpoch();
|
|
1235
1287
|
}
|
|
1236
1288
|
#epochTimeout;
|
|
1237
1289
|
async #transactionPoolHandler() {
|
|
@@ -1310,7 +1362,7 @@ class Chain extends VersionControl {
|
|
|
1310
1362
|
// peerReputation(peerId)
|
|
1311
1363
|
// {bandwith: {up, down}, uptime}
|
|
1312
1364
|
this.#participating = true;
|
|
1313
|
-
if (!await this.staticCall(addresses.validators, 'has', [address])) {
|
|
1365
|
+
if (!(await this.staticCall(addresses.validators, 'has', [address]))) {
|
|
1314
1366
|
const rawTransaction = {
|
|
1315
1367
|
from: address,
|
|
1316
1368
|
to: addresses.validators,
|
|
@@ -1322,13 +1374,13 @@ class Chain extends VersionControl {
|
|
|
1322
1374
|
const transaction = await signTransaction(rawTransaction, globalThis.peernet.identity);
|
|
1323
1375
|
await this.sendTransaction(transaction);
|
|
1324
1376
|
}
|
|
1325
|
-
if (await this.hasTransactionToHandle() && !this.#runningEpoch && this.#participating)
|
|
1377
|
+
if ((await this.hasTransactionToHandle()) && !this.#runningEpoch && this.#participating)
|
|
1326
1378
|
await this.#runEpoch();
|
|
1327
1379
|
}
|
|
1328
1380
|
// todo filter tx that need to wait on prev nonce
|
|
1329
1381
|
async #createBlock(limit = this.transactionLimit) {
|
|
1330
1382
|
// vote for transactions
|
|
1331
|
-
if (await globalThis.transactionPoolStore.size() === 0)
|
|
1383
|
+
if ((await globalThis.transactionPoolStore.size()) === 0)
|
|
1332
1384
|
return;
|
|
1333
1385
|
let transactions = await globalThis.transactionPoolStore.values(this.transactionLimit);
|
|
1334
1386
|
for (const hash of await globalThis.transactionPoolStore.keys()) {
|
|
@@ -1421,7 +1473,7 @@ class Chain extends VersionControl {
|
|
|
1421
1473
|
}
|
|
1422
1474
|
}
|
|
1423
1475
|
}
|
|
1424
|
-
block.validators = block.validators.map(validator => {
|
|
1476
|
+
block.validators = block.validators.map((validator) => {
|
|
1425
1477
|
validator.reward = block.fees;
|
|
1426
1478
|
validator.reward = validator.reward.add(block.reward);
|
|
1427
1479
|
validator.reward = validator.reward.div(block.validators.length);
|
|
@@ -1439,8 +1491,7 @@ class Chain extends VersionControl {
|
|
|
1439
1491
|
// block.reward = block.reward.toString()
|
|
1440
1492
|
// block.fees = block.fees.toString()
|
|
1441
1493
|
try {
|
|
1442
|
-
block.transactions = await Promise.all(block.transactions
|
|
1443
|
-
.map(async (transaction) => {
|
|
1494
|
+
block.transactions = await Promise.all(block.transactions.map(async (transaction) => {
|
|
1444
1495
|
await globalThis.transactionPoolStore.delete(await transaction.hash());
|
|
1445
1496
|
return transaction.decoded;
|
|
1446
1497
|
}));
|
package/exports/contract.d.ts
CHANGED
package/exports/jobs/jobber.d.ts
CHANGED
package/exports/node.js
CHANGED
|
@@ -16,7 +16,9 @@ class Node {
|
|
|
16
16
|
stars: networks.leofcoin.peach.stars,
|
|
17
17
|
autoStart: false
|
|
18
18
|
}, password) {
|
|
19
|
-
this.#node = globalThis.Peernet
|
|
19
|
+
this.#node = globalThis.Peernet
|
|
20
|
+
? await new globalThis.Peernet(config, password)
|
|
21
|
+
: await new Peernet(config, password);
|
|
20
22
|
await nodeConfig(config);
|
|
21
23
|
globalThis.pubsub.subscribe('chain:ready', async () => {
|
|
22
24
|
// when autostart is false the node will only be started after the chain is ready (this is here so we can just use node for communication)
|
package/exports/state.d.ts
CHANGED
|
@@ -4,10 +4,15 @@ import Machine from './machine.js';
|
|
|
4
4
|
import Jobber from './jobs/jobber.js';
|
|
5
5
|
import { BlockHash } from './types.js';
|
|
6
6
|
declare type SyncState = 'syncing' | 'synced' | 'errored' | 'connectionless';
|
|
7
|
+
declare type ChainState = 'loading' | 'loaded';
|
|
7
8
|
export default class State extends Contract {
|
|
8
9
|
#private;
|
|
9
10
|
knownBlocks: BlockHash[];
|
|
10
11
|
jobber: Jobber;
|
|
12
|
+
get state(): {
|
|
13
|
+
sync: SyncState;
|
|
14
|
+
chain: ChainState;
|
|
15
|
+
};
|
|
11
16
|
get blockHashMap(): IterableIterator<[any, any]>;
|
|
12
17
|
get loaded(): boolean;
|
|
13
18
|
get resolving(): boolean;
|
|
@@ -35,8 +40,9 @@ export default class State extends Contract {
|
|
|
35
40
|
getLatestBlock(): Promise<BlockMessage['decoded']>;
|
|
36
41
|
getAndPutBlock(hash: string): Promise<BlockMessage>;
|
|
37
42
|
resolveBlock(hash: any): any;
|
|
38
|
-
resolveBlocks(): Promise<
|
|
39
|
-
restoreChain():
|
|
43
|
+
resolveBlocks(): Promise<any>;
|
|
44
|
+
restoreChain(): any;
|
|
45
|
+
destroyResolveJob(): void;
|
|
40
46
|
syncChain(lastBlock?: any): Promise<SyncState>;
|
|
41
47
|
promiseRequests(promises: any): Promise<unknown>;
|
|
42
48
|
get canSync(): boolean;
|