@leofcoin/chain 1.4.74 → 1.4.76

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.
@@ -1818,11 +1818,38 @@ class Machine {
1818
1818
  }
1819
1819
  }
1820
1820
 
1821
- const queue = new PQueue({ concurrency: 1, throwOnTimeout: true });
1821
+ class Jobber {
1822
+ timeout;
1823
+ busy = false;
1824
+ stop;
1825
+ constructor(timeout) {
1826
+ this.timeout = timeout;
1827
+ }
1828
+ add(fn) {
1829
+ this.busy = true;
1830
+ return new Promise(async (resolve, reject) => {
1831
+ const timeout = setTimeout(() => {
1832
+ reject('timeout');
1833
+ }, this.timeout);
1834
+ this.stop = () => {
1835
+ clearTimeout(timeout);
1836
+ this.busy = false;
1837
+ resolve('stopped');
1838
+ };
1839
+ const result = await fn();
1840
+ clearTimeout(timeout);
1841
+ this.busy = false;
1842
+ resolve(result);
1843
+ });
1844
+ }
1845
+ }
1846
+
1847
+ new PQueue({ concurrency: 1, throwOnTimeout: true });
1822
1848
  class State extends Contract {
1823
1849
  #resolveErrored;
1824
1850
  #lastResolvedTime;
1825
1851
  #lastResolved;
1852
+ #resolving = false;
1826
1853
  #resolveErrorCount = 0;
1827
1854
  #syncState;
1828
1855
  #lastBlockInQue;
@@ -1831,9 +1858,16 @@ class State extends Contract {
1831
1858
  #chainSyncing = false;
1832
1859
  #lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
1833
1860
  #blocks = [];
1834
- #knownBlocks = [];
1861
+ knownBlocks = [];
1835
1862
  #totalSize = 0;
1836
1863
  #machine;
1864
+ #loaded = false;
1865
+ get loaded() {
1866
+ return this.#loaded;
1867
+ }
1868
+ get resolving() {
1869
+ return this.#resolving;
1870
+ }
1837
1871
  /**
1838
1872
  * amount the native token has been iteracted with
1839
1873
  */
@@ -1888,6 +1922,7 @@ class State extends Contract {
1888
1922
  super();
1889
1923
  }
1890
1924
  async init() {
1925
+ this.jobber = new Jobber(30_000);
1891
1926
  if (super.init)
1892
1927
  await super.init();
1893
1928
  await globalThis.peernet.addRequestHandler('lastBlock', this.#lastBlockHandler.bind(this));
@@ -1960,38 +1995,69 @@ class State extends Contract {
1960
1995
  return;
1961
1996
  }
1962
1997
  }
1963
- const block = await this.getAndPutBlock(hash);
1964
- index = block.decoded.index;
1965
- const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
1966
- this.#totalSize += size;
1967
- this.#blocks[index] = { hash, ...block.decoded };
1968
- this.#blockHashMap.set(hash, index);
1969
- globalThis.debug(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
1970
- this.#lastResolved = this.#blocks[index];
1971
- this.#lastResolvedTime = Date.now();
1998
+ try {
1999
+ const block = await this.getAndPutBlock(hash);
2000
+ index = block.decoded.index;
2001
+ const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
2002
+ this.#totalSize += size;
2003
+ this.#blocks[index] = { hash, ...block.decoded };
2004
+ this.#blockHashMap.set(hash, index);
2005
+ globalThis.debug(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
2006
+ this.#lastResolved = this.#blocks[index];
2007
+ this.#lastResolvedTime = Date.now();
2008
+ }
2009
+ catch (error) {
2010
+ this.#resolving = false;
2011
+ this.#chainSyncing = false;
2012
+ throw new Error('resolve error');
2013
+ }
1972
2014
  return;
1973
2015
  }
1974
2016
  async resolveBlock(hash) {
2017
+ if (this.#resolveErrorCount === 3)
2018
+ this.#resolveErrorCount = 0;
1975
2019
  if (!hash)
1976
2020
  throw new Error(`expected hash, got: ${hash}`);
1977
2021
  if (hash === '0x0')
1978
2022
  return;
1979
- await queue.add(() => this.#resolveBlock(hash));
1980
- if (!this.#blockHashMap.has(this.#lastResolved.previousHash) && this.#lastResolved.previousHash !== '0x0')
1981
- return this.resolveBlock(this.#lastResolved.previousHash);
1982
- return;
2023
+ if (this.#resolving)
2024
+ return 'already resolving';
2025
+ this.#resolving = true;
2026
+ try {
2027
+ await this.jobber.add(() => this.#resolveBlock(hash));
2028
+ this.#resolving = false;
2029
+ if (!this.#blockHashMap.has(this.#lastResolved.previousHash) && this.#lastResolved.previousHash !== '0x0')
2030
+ return this.resolveBlock(this.#lastResolved.previousHash);
2031
+ }
2032
+ catch (error) {
2033
+ this.#resolveErrorCount += 1;
2034
+ if (this.#resolveErrorCount < 3)
2035
+ return this.resolveBlock(hash);
2036
+ else
2037
+ throw new Error('resolve errored');
2038
+ }
1983
2039
  }
1984
2040
  async resolveBlocks() {
2041
+ try {
2042
+ if (this.jobber.busy && this.jobber.stop) {
2043
+ await this.jobber.stop();
2044
+ }
2045
+ }
2046
+ catch (error) {
2047
+ console.error(error);
2048
+ }
1985
2049
  try {
1986
2050
  const localBlock = await globalThis.chainStore.get('lastBlock');
1987
2051
  const hash = new TextDecoder().decode(localBlock);
1988
- if (hash && hash !== '0x0')
2052
+ if (hash && hash !== '0x0') {
1989
2053
  await this.resolveBlock(hash);
1990
- this.#lastBlock = this.#blocks[this.#blocks.length - 1];
2054
+ this.#lastBlock = this.#blocks[this.#blocks.length - 1];
2055
+ }
1991
2056
  }
1992
2057
  catch {
1993
2058
  this.#resolveErrored = true;
1994
2059
  this.#resolveErrorCount += 1;
2060
+ this.#resolving = false;
1995
2061
  // console.log(e);
1996
2062
  }
1997
2063
  }
@@ -1999,7 +2065,15 @@ class State extends Contract {
1999
2065
  if (!this.shouldSync) {
2000
2066
  return;
2001
2067
  }
2002
- await queue.clear();
2068
+ try {
2069
+ if (this.jobber.busy && this.jobber.stop) {
2070
+ await this.jobber.stop();
2071
+ }
2072
+ }
2073
+ catch (error) {
2074
+ console.error(error);
2075
+ }
2076
+ // await queue.clear()
2003
2077
  this.#chainSyncing = true;
2004
2078
  if (!lastBlock)
2005
2079
  lastBlock = await this.#getLatestBlock();
@@ -2027,9 +2101,9 @@ class State extends Contract {
2027
2101
  }
2028
2102
  async #syncChain(lastBlock) {
2029
2103
  try {
2030
- if (this.#knownBlocks?.length === Number(lastBlock.index) + 1) {
2104
+ if (this.knownBlocks?.length === Number(lastBlock.index) + 1) {
2031
2105
  let promises = [];
2032
- promises = await Promise.allSettled(this.#knownBlocks.map(async (address) => {
2106
+ promises = await Promise.allSettled(this.knownBlocks.map(async (address) => {
2033
2107
  const has = await globalThis.peernet.has(address, 'block');
2034
2108
  return { has, address };
2035
2109
  }));
@@ -2061,15 +2135,16 @@ class State extends Contract {
2061
2135
  let node = await globalThis.peernet.prepareMessage(data);
2062
2136
  for (const peer of globalThis.peernet?.connections) {
2063
2137
  if (peer.connected && peer.version === this.version) {
2064
- promises.push(async () => {
2138
+ const task = async () => {
2065
2139
  try {
2066
2140
  const result = await peer.request(node.encoded);
2067
- return { result, peer };
2141
+ return { result: Uint8Array.from(Object.values(result)), peer };
2068
2142
  }
2069
2143
  catch (error) {
2070
2144
  throw error;
2071
2145
  }
2072
- });
2146
+ };
2147
+ promises.push(task());
2073
2148
  }
2074
2149
  }
2075
2150
  promises = await this.promiseRequests(promises);
@@ -2090,7 +2165,7 @@ class State extends Contract {
2090
2165
  let node = await globalThis.peernet.prepareMessage(data);
2091
2166
  let message = await peer.request(node);
2092
2167
  message = await new globalThis.peernet.protos['peernet-response'](message);
2093
- this.#knownBlocks = message.decoded.response;
2168
+ this.knownBlocks = message.decoded.response;
2094
2169
  }
2095
2170
  }
2096
2171
  return latest;
@@ -2103,6 +2178,8 @@ class State extends Contract {
2103
2178
  let poolTransactionKeys = await globalThis.transactionPoolStore.keys();
2104
2179
  for (const block of blocks) {
2105
2180
  if (block && !block.loaded) {
2181
+ if (block.index === 0)
2182
+ this.#loaded = true;
2106
2183
  for (const transaction of block.transactions) {
2107
2184
  if (poolTransactionKeys.includes(transaction.hash))
2108
2185
  await globalThis.transactionPoolStore.delete(transaction.hash);
@@ -2141,7 +2218,8 @@ class State extends Contract {
2141
2218
  clearTimeout(timeout);
2142
2219
  if (promises.length > 0) {
2143
2220
  promises = promises.map(async ({ value }) => {
2144
- const node = await new globalThis.peernet.protos['peernet-response'](value);
2221
+ console.log(value);
2222
+ const node = await new globalThis.peernet.protos['peernet-response'](value.result);
2145
2223
  return { value: node.decoded.response, peer: value.peer };
2146
2224
  });
2147
2225
  promises = await Promise.all(promises);
@@ -2319,8 +2397,8 @@ class Chain extends State {
2319
2397
  return;
2320
2398
  const lastBlock = await this.#makeRequest(peer, 'lastBlock');
2321
2399
  if (Object.keys(lastBlock).length > 0) {
2322
- if (!this.lastBlock || !this.blocks[this.blocks.length - 1].loaded || lastBlock && lastBlock.index > this.lastBlock?.index) {
2323
- // this.#knownBlocks = await this.#makeRequest(peer, 'knownBlocks')
2400
+ if (!this.lastBlock || !this.blocks[this.blocks.length - 1]?.loaded || lastBlock && lastBlock.index > this.lastBlock?.index || !this.loaded && !this.resolving) {
2401
+ this.knownBlocks = await this.#makeRequest(peer, 'knownBlocks');
2324
2402
  await this.syncChain(lastBlock);
2325
2403
  // if (await this.hasTransactionToHandle() && this.#participating) this.#runEpoch()
2326
2404
  }
package/exports/chain.js CHANGED
@@ -444,11 +444,38 @@ class Machine {
444
444
  }
445
445
  }
446
446
 
447
- const queue = new PQueue({ concurrency: 1, throwOnTimeout: true });
447
+ class Jobber {
448
+ timeout;
449
+ busy = false;
450
+ stop;
451
+ constructor(timeout) {
452
+ this.timeout = timeout;
453
+ }
454
+ add(fn) {
455
+ this.busy = true;
456
+ return new Promise(async (resolve, reject) => {
457
+ const timeout = setTimeout(() => {
458
+ reject('timeout');
459
+ }, this.timeout);
460
+ this.stop = () => {
461
+ clearTimeout(timeout);
462
+ this.busy = false;
463
+ resolve('stopped');
464
+ };
465
+ const result = await fn();
466
+ clearTimeout(timeout);
467
+ this.busy = false;
468
+ resolve(result);
469
+ });
470
+ }
471
+ }
472
+
473
+ new PQueue({ concurrency: 1, throwOnTimeout: true });
448
474
  class State extends Contract {
449
475
  #resolveErrored;
450
476
  #lastResolvedTime;
451
477
  #lastResolved;
478
+ #resolving = false;
452
479
  #resolveErrorCount = 0;
453
480
  #syncState;
454
481
  #lastBlockInQue;
@@ -457,9 +484,16 @@ class State extends Contract {
457
484
  #chainSyncing = false;
458
485
  #lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
459
486
  #blocks = [];
460
- #knownBlocks = [];
487
+ knownBlocks = [];
461
488
  #totalSize = 0;
462
489
  #machine;
490
+ #loaded = false;
491
+ get loaded() {
492
+ return this.#loaded;
493
+ }
494
+ get resolving() {
495
+ return this.#resolving;
496
+ }
463
497
  /**
464
498
  * amount the native token has been iteracted with
465
499
  */
@@ -514,6 +548,7 @@ class State extends Contract {
514
548
  super();
515
549
  }
516
550
  async init() {
551
+ this.jobber = new Jobber(30_000);
517
552
  if (super.init)
518
553
  await super.init();
519
554
  await globalThis.peernet.addRequestHandler('lastBlock', this.#lastBlockHandler.bind(this));
@@ -586,38 +621,69 @@ class State extends Contract {
586
621
  return;
587
622
  }
588
623
  }
589
- const block = await this.getAndPutBlock(hash);
590
- index = block.decoded.index;
591
- const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
592
- this.#totalSize += size;
593
- this.#blocks[index] = { hash, ...block.decoded };
594
- this.#blockHashMap.set(hash, index);
595
- globalThis.debug(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
596
- this.#lastResolved = this.#blocks[index];
597
- this.#lastResolvedTime = Date.now();
624
+ try {
625
+ const block = await this.getAndPutBlock(hash);
626
+ index = block.decoded.index;
627
+ const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
628
+ this.#totalSize += size;
629
+ this.#blocks[index] = { hash, ...block.decoded };
630
+ this.#blockHashMap.set(hash, index);
631
+ globalThis.debug(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
632
+ this.#lastResolved = this.#blocks[index];
633
+ this.#lastResolvedTime = Date.now();
634
+ }
635
+ catch (error) {
636
+ this.#resolving = false;
637
+ this.#chainSyncing = false;
638
+ throw new Error('resolve error');
639
+ }
598
640
  return;
599
641
  }
600
642
  async resolveBlock(hash) {
643
+ if (this.#resolveErrorCount === 3)
644
+ this.#resolveErrorCount = 0;
601
645
  if (!hash)
602
646
  throw new Error(`expected hash, got: ${hash}`);
603
647
  if (hash === '0x0')
604
648
  return;
605
- await queue.add(() => this.#resolveBlock(hash));
606
- if (!this.#blockHashMap.has(this.#lastResolved.previousHash) && this.#lastResolved.previousHash !== '0x0')
607
- return this.resolveBlock(this.#lastResolved.previousHash);
608
- return;
649
+ if (this.#resolving)
650
+ return 'already resolving';
651
+ this.#resolving = true;
652
+ try {
653
+ await this.jobber.add(() => this.#resolveBlock(hash));
654
+ this.#resolving = false;
655
+ if (!this.#blockHashMap.has(this.#lastResolved.previousHash) && this.#lastResolved.previousHash !== '0x0')
656
+ return this.resolveBlock(this.#lastResolved.previousHash);
657
+ }
658
+ catch (error) {
659
+ this.#resolveErrorCount += 1;
660
+ if (this.#resolveErrorCount < 3)
661
+ return this.resolveBlock(hash);
662
+ else
663
+ throw new Error('resolve errored');
664
+ }
609
665
  }
610
666
  async resolveBlocks() {
667
+ try {
668
+ if (this.jobber.busy && this.jobber.stop) {
669
+ await this.jobber.stop();
670
+ }
671
+ }
672
+ catch (error) {
673
+ console.error(error);
674
+ }
611
675
  try {
612
676
  const localBlock = await globalThis.chainStore.get('lastBlock');
613
677
  const hash = new TextDecoder().decode(localBlock);
614
- if (hash && hash !== '0x0')
678
+ if (hash && hash !== '0x0') {
615
679
  await this.resolveBlock(hash);
616
- this.#lastBlock = this.#blocks[this.#blocks.length - 1];
680
+ this.#lastBlock = this.#blocks[this.#blocks.length - 1];
681
+ }
617
682
  }
618
683
  catch {
619
684
  this.#resolveErrored = true;
620
685
  this.#resolveErrorCount += 1;
686
+ this.#resolving = false;
621
687
  // console.log(e);
622
688
  }
623
689
  }
@@ -625,7 +691,15 @@ class State extends Contract {
625
691
  if (!this.shouldSync) {
626
692
  return;
627
693
  }
628
- await queue.clear();
694
+ try {
695
+ if (this.jobber.busy && this.jobber.stop) {
696
+ await this.jobber.stop();
697
+ }
698
+ }
699
+ catch (error) {
700
+ console.error(error);
701
+ }
702
+ // await queue.clear()
629
703
  this.#chainSyncing = true;
630
704
  if (!lastBlock)
631
705
  lastBlock = await this.#getLatestBlock();
@@ -653,9 +727,9 @@ class State extends Contract {
653
727
  }
654
728
  async #syncChain(lastBlock) {
655
729
  try {
656
- if (this.#knownBlocks?.length === Number(lastBlock.index) + 1) {
730
+ if (this.knownBlocks?.length === Number(lastBlock.index) + 1) {
657
731
  let promises = [];
658
- promises = await Promise.allSettled(this.#knownBlocks.map(async (address) => {
732
+ promises = await Promise.allSettled(this.knownBlocks.map(async (address) => {
659
733
  const has = await globalThis.peernet.has(address, 'block');
660
734
  return { has, address };
661
735
  }));
@@ -687,15 +761,16 @@ class State extends Contract {
687
761
  let node = await globalThis.peernet.prepareMessage(data);
688
762
  for (const peer of globalThis.peernet?.connections) {
689
763
  if (peer.connected && peer.version === this.version) {
690
- promises.push(async () => {
764
+ const task = async () => {
691
765
  try {
692
766
  const result = await peer.request(node.encoded);
693
- return { result, peer };
767
+ return { result: Uint8Array.from(Object.values(result)), peer };
694
768
  }
695
769
  catch (error) {
696
770
  throw error;
697
771
  }
698
- });
772
+ };
773
+ promises.push(task());
699
774
  }
700
775
  }
701
776
  promises = await this.promiseRequests(promises);
@@ -716,7 +791,7 @@ class State extends Contract {
716
791
  let node = await globalThis.peernet.prepareMessage(data);
717
792
  let message = await peer.request(node);
718
793
  message = await new globalThis.peernet.protos['peernet-response'](message);
719
- this.#knownBlocks = message.decoded.response;
794
+ this.knownBlocks = message.decoded.response;
720
795
  }
721
796
  }
722
797
  return latest;
@@ -729,6 +804,8 @@ class State extends Contract {
729
804
  let poolTransactionKeys = await globalThis.transactionPoolStore.keys();
730
805
  for (const block of blocks) {
731
806
  if (block && !block.loaded) {
807
+ if (block.index === 0)
808
+ this.#loaded = true;
732
809
  for (const transaction of block.transactions) {
733
810
  if (poolTransactionKeys.includes(transaction.hash))
734
811
  await globalThis.transactionPoolStore.delete(transaction.hash);
@@ -767,7 +844,8 @@ class State extends Contract {
767
844
  clearTimeout(timeout);
768
845
  if (promises.length > 0) {
769
846
  promises = promises.map(async ({ value }) => {
770
- const node = await new globalThis.peernet.protos['peernet-response'](value);
847
+ console.log(value);
848
+ const node = await new globalThis.peernet.protos['peernet-response'](value.result);
771
849
  return { value: node.decoded.response, peer: value.peer };
772
850
  });
773
851
  promises = await Promise.all(promises);
@@ -945,8 +1023,8 @@ class Chain extends State {
945
1023
  return;
946
1024
  const lastBlock = await this.#makeRequest(peer, 'lastBlock');
947
1025
  if (Object.keys(lastBlock).length > 0) {
948
- if (!this.lastBlock || !this.blocks[this.blocks.length - 1].loaded || lastBlock && lastBlock.index > this.lastBlock?.index) {
949
- // this.#knownBlocks = await this.#makeRequest(peer, 'knownBlocks')
1026
+ if (!this.lastBlock || !this.blocks[this.blocks.length - 1]?.loaded || lastBlock && lastBlock.index > this.lastBlock?.index || !this.loaded && !this.resolving) {
1027
+ this.knownBlocks = await this.#makeRequest(peer, 'knownBlocks');
950
1028
  await this.syncChain(lastBlock);
951
1029
  // if (await this.hasTransactionToHandle() && this.#participating) this.#runEpoch()
952
1030
  }
@@ -0,0 +1,7 @@
1
+ export default class Jobber {
2
+ timeout: EpochTimeStamp;
3
+ busy: boolean;
4
+ stop: Function;
5
+ constructor(timeout: any);
6
+ add(fn: any): Promise<unknown>;
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leofcoin/chain",
3
- "version": "1.4.74",
3
+ "version": "1.4.76",
4
4
  "description": "Official javascript implementation",
5
5
  "exports": {
6
6
  "./node": "./exports/node.js",
@@ -1,3 +0,0 @@
1
- export default class SyncJob {
2
- constructor();
3
- }