@leofcoin/chain 1.5.57 → 1.5.58

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
@@ -271,12 +271,9 @@ class Contract extends Transaction {
271
271
 
272
272
  // import State from './state'
273
273
  class Machine {
274
- #contracts;
275
- #nonces;
274
+ #contracts = {};
275
+ #nonces = {};
276
276
  constructor(blocks) {
277
- this.#contracts = {};
278
- this.#nonces = {};
279
- this.lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
280
277
  // @ts-ignore
281
278
  return this.#init(blocks);
282
279
  }
@@ -320,7 +317,6 @@ class Machine {
320
317
  break;
321
318
  }
322
319
  case 'machine-ready': {
323
- this.lastBlock = data.lastBlock;
324
320
  pubsub.publish('machine.ready', true);
325
321
  break;
326
322
  }
@@ -506,21 +502,44 @@ class Machine {
506
502
  });
507
503
  });
508
504
  }
509
- async nativeCalls() {
505
+ get nativeCalls() {
510
506
  return this.#askWorker('nativeCalls');
511
507
  }
512
- async nativeMints() {
508
+ get nativeMints() {
513
509
  return this.#askWorker('nativeMints');
514
510
  }
515
- async nativeBurns() {
511
+ get nativeBurns() {
516
512
  return this.#askWorker('nativeBurns');
517
513
  }
518
- async nativeTransfers() {
514
+ get nativeTransfers() {
519
515
  return this.#askWorker('nativeTransfers');
520
516
  }
521
- async totalTransactions() {
517
+ get totalTransactions() {
522
518
  return this.#askWorker('totalTransactions');
523
519
  }
520
+ get blocks() {
521
+ return this.getBlocks();
522
+ }
523
+ get lastBlock() {
524
+ return this.#askWorker('lastBlock');
525
+ }
526
+ get totalBlocks() {
527
+ return this.#askWorker('totalBlocks');
528
+ }
529
+ getBlocks(from, to) {
530
+ return this.#askWorker('blocks', { from, to });
531
+ }
532
+ getBlock(index) {
533
+ return this.#askWorker('block', index);
534
+ }
535
+ async addLoadedBlock(block) {
536
+ if (block.decoded)
537
+ block = { ...block.decoded, hahs: await block.hash() };
538
+ return this.#askWorker('addLoadedBlock', block);
539
+ }
540
+ async latestTransactions() {
541
+ return this.#askWorker('latestTransactions');
542
+ }
524
543
  async delete(hash) {
525
544
  return globalThis.contractStore.delete(hash);
526
545
  }
@@ -577,7 +596,6 @@ class State extends Contract {
577
596
  #syncErrorCount;
578
597
  #blockHashMap;
579
598
  #chainSyncing;
580
- #lastBlock;
581
599
  #blocks;
582
600
  #totalSize;
583
601
  #machine;
@@ -598,25 +616,31 @@ class State extends Contract {
598
616
  return this.#resolving;
599
617
  }
600
618
  get nativeMints() {
601
- return this.#machine.nativeMints();
619
+ return this.#machine.nativeMints;
602
620
  }
603
621
  get nativeBurns() {
604
- return this.#machine.nativeBurns();
622
+ return this.#machine.nativeBurns;
605
623
  }
606
624
  get nativeTransfers() {
607
- return this.#machine.nativeTransfers();
625
+ return this.#machine.nativeTransfers;
608
626
  }
609
627
  get totalTransactions() {
610
- return this.#machine.totalTransactions();
628
+ return this.#machine.totalTransactions;
611
629
  }
612
630
  get nativeCalls() {
613
- return this.#machine.nativeCalls();
631
+ return this.#machine.nativeCalls;
614
632
  }
615
633
  get blocks() {
616
- return [...this.#blocks];
634
+ return this.getBlocks();
617
635
  }
618
636
  get lastBlock() {
619
- return this.#lastBlock;
637
+ return this.#machine ? this.#machine.lastBlock : { index: 0, hash: '0x0', previousHash: '0x0' };
638
+ }
639
+ getBlock(index) {
640
+ return this.#machine.getBlock(index);
641
+ }
642
+ getBlocks(from, to) {
643
+ return this.#machine.getBlocks(from, to);
620
644
  }
621
645
  get totalSize() {
622
646
  return this.#totalSize;
@@ -633,7 +657,6 @@ class State extends Contract {
633
657
  this.#syncErrorCount = 0;
634
658
  this.#blockHashMap = new Map();
635
659
  this.#chainSyncing = false;
636
- this.#lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
637
660
  this.#blocks = [];
638
661
  this.knownBlocks = [];
639
662
  this.#totalSize = 0;
@@ -645,7 +668,7 @@ class State extends Contract {
645
668
  };
646
669
  this.#lastBlockHandler = async () => {
647
670
  return new globalThis.peernet.protos['peernet-response']({
648
- response: { hash: this.#lastBlock?.hash, index: this.#lastBlock?.index }
671
+ response: await this.lastBlock
649
672
  });
650
673
  };
651
674
  this.#knownBlocksHandler = async () => {
@@ -655,7 +678,7 @@ class State extends Contract {
655
678
  };
656
679
  this.#loadBlockTransactions = (transactions) => Promise.all(transactions.map((transaction) => new TransactionMessage(transaction)));
657
680
  this.#getLastTransactions = async () => {
658
- let lastTransactions = (await Promise.all(this.#blocks
681
+ let lastTransactions = (await Promise.all((await this.blocks)
659
682
  .filter((block) => block.loaded)
660
683
  .slice(-128)
661
684
  .map((block) => this.#loadBlockTransactions(block.transactions)))).reduce((all, transactions) => [...all, ...transactions], []);
@@ -685,35 +708,12 @@ class State extends Contract {
685
708
  await globalThis.peernet.addRequestHandler('knownBlocks', this.#knownBlocksHandler);
686
709
  await globalThis.peernet.addRequestHandler('chainState', this.#chainStateHandler);
687
710
  try {
688
- let localBlock;
689
- try {
690
- localBlock = await globalThis.chainStore.get('lastBlock');
691
- }
692
- catch {
693
- await globalThis.chainStore.put('lastBlock', '0x0');
694
- localBlock = await globalThis.chainStore.get('lastBlock');
695
- }
696
- localBlock = new TextDecoder().decode(localBlock);
697
- if (localBlock && localBlock !== '0x0') {
698
- localBlock = await globalThis.peernet.get(localBlock, 'block');
699
- localBlock = await new BlockMessage(localBlock);
700
- this.#lastBlock = {
701
- ...localBlock.decoded,
702
- hash: await localBlock.hash()
703
- };
704
- }
705
- else {
706
- if (globalThis.peernet?.connections.length > 0) {
707
- const latestBlock = await this.#getLatestBlock();
708
- await this.#syncChain(latestBlock);
709
- }
710
- }
711
+ await globalThis.chainStore.has('lastBlock');
711
712
  }
712
- catch (error) {
713
- console.log({ e: error });
714
- console.log({ e: error });
713
+ catch {
714
+ await globalThis.chainStore.put('lastBlock', '0x0');
715
715
  }
716
- globalThis.pubsub.publish('lastBlock', this.lastBlock);
716
+ globalThis.pubsub.publish('lastBlock', await this.lastBlock);
717
717
  // load local blocks
718
718
  try {
719
719
  this.knownBlocks = await blockStore.keys();
@@ -725,6 +725,9 @@ class State extends Contract {
725
725
  try {
726
726
  await this.resolveBlocks();
727
727
  this.#machine = await new Machine(this.#blocks);
728
+ const lastBlock = await this.#machine.lastBlock;
729
+ this.updateState(new BlockMessage(lastBlock));
730
+ this.#loaded = true;
728
731
  // await this.#loadBlocks(this.#blocks)
729
732
  }
730
733
  catch (error) {
@@ -736,10 +739,9 @@ class State extends Contract {
736
739
  }
737
740
  async updateState(message) {
738
741
  const hash = await message.hash();
739
- this.#lastBlock = { hash, ...message.decoded };
740
742
  // await this.state.updateState(message)
741
743
  await globalThis.chainStore.put('lastBlock', hash);
742
- globalThis.pubsub.publish('lastBlock', this.#lastBlock);
744
+ globalThis.pubsub.publish('lastBlock', message.encoded);
743
745
  }
744
746
  getLatestBlock() {
745
747
  // @ts-ignore
@@ -825,7 +827,6 @@ class State extends Contract {
825
827
  const hash = new TextDecoder().decode(localBlock);
826
828
  if (hash && hash !== '0x0') {
827
829
  await this.resolveBlock(hash);
828
- this.#lastBlock = this.#blocks[this.#blocks.length - 1];
829
830
  }
830
831
  }
831
832
  catch (error) {
@@ -843,7 +844,6 @@ class State extends Contract {
843
844
  await globalThis.chainStore.put('lastBlock', hash);
844
845
  if (hash && hash !== '0x0') {
845
846
  await this.resolveBlock(hash);
846
- this.#lastBlock = this.#blocks[this.#blocks.length - 1];
847
847
  }
848
848
  }
849
849
  catch (error) {
@@ -873,7 +873,7 @@ class State extends Contract {
873
873
  if (!lastBlock)
874
874
  lastBlock = await this.#getLatestBlock();
875
875
  console.log('starting sync');
876
- if (globalThis.peernet.connections.length === 0)
876
+ if (globalThis.peernet.peers.length === 0)
877
877
  return 'connectionless';
878
878
  try {
879
879
  await this.#syncChain(lastBlock);
@@ -907,18 +907,21 @@ class State extends Contract {
907
907
  promises = promises.filter(({ status, value }) => status === 'fulfilled' && !value.has);
908
908
  await Promise.allSettled(promises.map(({ value }) => this.getAndPutBlock(value.address)));
909
909
  }
910
- if (!this.#lastBlock || Number(this.#lastBlock.index) < Number(lastBlock.index)) {
910
+ const localBlock = await this.lastBlock;
911
+ if (!localBlock || Number(localBlock.index) < Number(lastBlock.index)) {
911
912
  // TODO: check if valid
912
- const localIndex = this.#lastBlock ? this.lastBlock.index : 0;
913
+ const localIndex = localBlock ? localBlock.index : 0;
913
914
  const index = lastBlock.index;
914
915
  await this.resolveBlock(lastBlock.hash);
915
916
  console.log('ok');
916
917
  let blocksSynced = localIndex > 0 ? (localIndex > index ? localIndex - index : index + -localIndex) : index;
917
918
  globalThis.debug(`synced ${blocksSynced} ${blocksSynced > 1 ? 'blocks' : 'block'}`);
918
- const start = this.#blocks.length - blocksSynced;
919
- if (this.#machine)
920
- await this.#loadBlocks(this.blocks.slice(start));
921
- await this.updateState(new BlockMessage(this.#blocks[this.#blocks.length - 1]));
919
+ const blocks = this.#blocks;
920
+ const start = blocks.length - blocksSynced;
921
+ if (this.#machine) {
922
+ await this.#loadBlocks(blocks.slice(start));
923
+ }
924
+ await this.updateState(new BlockMessage(blocks[blocks.length - 1]));
922
925
  }
923
926
  }
924
927
  catch (error) {
@@ -932,8 +935,6 @@ class State extends Contract {
932
935
  request: 'lastBlock'
933
936
  });
934
937
  let node = await globalThis.peernet.prepareMessage(data);
935
- console.log(node.encoded);
936
- console.log(node.encode());
937
938
  for (const id in globalThis.peernet.connections) {
938
939
  // @ts-ignore
939
940
  const peer = globalThis.peernet.connections[id];
@@ -996,11 +997,12 @@ class State extends Contract {
996
997
  await globalThis.transactionPoolStore.delete(await transaction.hash());
997
998
  console.log('removing invalid transaction');
998
999
  if (isExecutionError(error)) {
999
- console.log(`removing invalid block ${block.index}`);
1000
- await globalThis.blockStore.delete(await (await new BlockMessage(block)).hash());
1001
- const deletedBlock = blocks.splice(block.index, 1);
1002
- console.log(`removed block ${deletedBlock[0].index}`);
1003
- return this.#loadBlocks(blocks);
1000
+ console.log(error);
1001
+ // console.log(`removing invalid block ${block.index}`)
1002
+ // await globalThis.blockStore.delete(await (await new BlockMessage(block)).hash())
1003
+ // const deletedBlock = blocks.splice(block.index, 1)
1004
+ // console.log(`removed block ${deletedBlock[0].index}`)
1005
+ // return this.#loadBlocks(blocks)
1004
1006
  }
1005
1007
  console.log(error);
1006
1008
  return false;
@@ -1043,6 +1045,7 @@ class State extends Contract {
1043
1045
  transactions = transactions.filter((transaction) => !transaction.decoded.priority);
1044
1046
  await Promise.all(transactions.map((transaction) => this.#_executeTransaction(transaction)));
1045
1047
  this.#blocks[block.index - 1].loaded = true;
1048
+ await this.#machine.addLoadedBlock(block);
1046
1049
  // @ts-ignore
1047
1050
  globalThis.debug(`loaded block: ${block.hash} @${block.index}`);
1048
1051
  globalThis.pubsub.publish('block-loaded', { ...block });
@@ -1302,7 +1305,8 @@ class Chain extends VersionControl {
1302
1305
  if (!peer.version || peer.version !== this.version)
1303
1306
  return;
1304
1307
  const lastBlock = await this.#makeRequest(peer, 'lastBlock');
1305
- const higherThenCurrentLocal = !this.lastBlock?.index ? true : lastBlock.index > this.lastBlock?.index;
1308
+ const localBlock = await this.lastBlock;
1309
+ const higherThenCurrentLocal = !localBlock.index ? true : lastBlock.index > localBlock.index;
1306
1310
  const peerTransactionPool = (higherThenCurrentLocal && (await this.getPeerTransactionPool(peer))) || [];
1307
1311
  if (Object.keys(lastBlock).length > 0) {
1308
1312
  if (!this.lastBlock || higherThenCurrentLocal) {
@@ -1351,7 +1355,7 @@ class Chain extends VersionControl {
1351
1355
  }));
1352
1356
  const hash = await blockMessage.hash();
1353
1357
  await globalThis.blockStore.put(hash, blockMessage.encoded);
1354
- if (this.lastBlock.index < Number(blockMessage.decoded.index))
1358
+ if ((await this.lastBlock).index < Number(blockMessage.decoded.index))
1355
1359
  await this.updateState(blockMessage);
1356
1360
  globalThis.debug(`added block: ${hash}`);
1357
1361
  let promises = [];
@@ -1381,6 +1385,7 @@ class Chain extends VersionControl {
1381
1385
  // // await stateStore.put(contract, state)
1382
1386
  // console.log(state);
1383
1387
  // }
1388
+ // await this.machine.addLoadedBlock({ ...blockMessage.decoded, loaded: true, hash: await blockMessage.hash() })
1384
1389
  globalThis.pubsub.publish('block-processed', blockMessage.decoded);
1385
1390
  }
1386
1391
  catch (error) {
@@ -1437,15 +1442,12 @@ class Chain extends VersionControl {
1437
1442
  // exclude failing tx
1438
1443
  transactions = await this.promiseTransactions(transactions);
1439
1444
  transactions = transactions.sort((a, b) => a.nonce - b.nonce);
1445
+ const latestTransactions = await this.machine.latestTransactions();
1440
1446
  for (let transaction of transactions) {
1441
1447
  const hash = await transaction.hash();
1442
1448
  const doubleTransactions = [];
1443
- for (const block of this.blocks) {
1444
- for (const transaction of block.transactions) {
1445
- if (transaction.hash === hash) {
1446
- doubleTransactions.push(hash);
1447
- }
1448
- }
1449
+ if (latestTransactions.includes(hash)) {
1450
+ doubleTransactions.push(hash);
1449
1451
  }
1450
1452
  if (doubleTransactions.length > 0) {
1451
1453
  await globalThis.transactionPoolStore.delete(hash);
@@ -1516,12 +1518,13 @@ class Chain extends VersionControl {
1516
1518
  return validator;
1517
1519
  });
1518
1520
  // block.validators = calculateValidatorReward(block.validators, block.fees)
1519
- block.index = this.lastBlock?.index;
1521
+ const localBlock = await this.lastBlock;
1522
+ block.index = localBlock.index;
1520
1523
  if (block.index === undefined)
1521
1524
  block.index = 0;
1522
1525
  else
1523
1526
  block.index += 1;
1524
- block.previousHash = this.lastBlock?.hash || '0x0';
1527
+ block.previousHash = localBlock.hash || '0x0';
1525
1528
  // block.timestamp = Date.now()
1526
1529
  // block.reward = block.reward.toString()
1527
1530
  // block.fees = block.fees.toString()
@@ -1534,7 +1537,8 @@ class Chain extends VersionControl {
1534
1537
  const hash = await blockMessage.hash();
1535
1538
  await globalThis.peernet.put(hash, blockMessage.encoded, 'block');
1536
1539
  await this.updateState(blockMessage);
1537
- globalThis.debug(`created block: ${hash}`);
1540
+ await this.machine.addLoadedBlock({ ...blockMessage.decoded, loaded: true, hash: await blockMessage.hash() });
1541
+ globalThis.debug(`created block: ${hash} @${block.index}`);
1538
1542
  globalThis.peernet.publish('add-block', blockMessage.encoded);
1539
1543
  globalThis.pubsub.publish('add-block', blockMessage.decoded);
1540
1544
  }
@@ -2,11 +2,6 @@ import EasyWorker from '@vandeurenglenn/easy-worker';
2
2
  export default class Machine {
3
3
  #private;
4
4
  worker: EasyWorker;
5
- lastBlock: {
6
- index: number;
7
- hash: string;
8
- previousHash: string;
9
- };
10
5
  constructor(blocks: any);
11
6
  /**
12
7
  *
@@ -18,11 +13,18 @@ export default class Machine {
18
13
  execute(contract: any, method: any, parameters: any): Promise<any>;
19
14
  get(contract: any, method: any, parameters?: any): Promise<any>;
20
15
  has(address: any): Promise<unknown>;
21
- nativeCalls(): Promise<unknown>;
22
- nativeMints(): Promise<unknown>;
23
- nativeBurns(): Promise<unknown>;
24
- nativeTransfers(): Promise<unknown>;
25
- totalTransactions(): Promise<unknown>;
16
+ get nativeCalls(): Promise<any>;
17
+ get nativeMints(): Promise<any>;
18
+ get nativeBurns(): Promise<any>;
19
+ get nativeTransfers(): Promise<any>;
20
+ get totalTransactions(): Promise<any>;
21
+ get blocks(): Promise<[]>;
22
+ get lastBlock(): Promise<any>;
23
+ get totalBlocks(): Promise<any>;
24
+ getBlocks(from?: any, to?: any): Promise<[]>;
25
+ getBlock(index: any): Promise<any>;
26
+ addLoadedBlock(block: any): Promise<any>;
27
+ latestTransactions(): Promise<any>;
26
28
  delete(hash: any): Promise<void>;
27
29
  /**
28
30
  *
@@ -16,17 +16,19 @@ export default class State extends Contract {
16
16
  get blockHashMap(): IterableIterator<[any, any]>;
17
17
  get loaded(): boolean;
18
18
  get resolving(): boolean;
19
- get nativeMints(): Promise<unknown>;
20
- get nativeBurns(): Promise<unknown>;
21
- get nativeTransfers(): Promise<unknown>;
22
- get totalTransactions(): Promise<unknown>;
23
- get nativeCalls(): Promise<unknown>;
24
- get blocks(): any[];
25
- get lastBlock(): {
19
+ get nativeMints(): Promise<any>;
20
+ get nativeBurns(): Promise<any>;
21
+ get nativeTransfers(): Promise<any>;
22
+ get totalTransactions(): Promise<any>;
23
+ get nativeCalls(): Promise<any>;
24
+ get blocks(): Promise<[]>;
25
+ get lastBlock(): Promise<any> | {
26
26
  index: number;
27
27
  hash: string;
28
28
  previousHash: string;
29
29
  };
30
+ getBlock(index: any): Promise<any>;
31
+ getBlocks(from?: any, to?: any): Promise<[]>;
30
32
  get totalSize(): number;
31
33
  get machine(): Machine;
32
34
  constructor(config: any);
@@ -0,0 +1,33 @@
1
+ import { base58String } from '@vandeurenglenn/base58';
2
+ export type Address = base58String;
3
+ export type BlockHash = base58String;
4
+ interface Transaction {
5
+ to: Address;
6
+ from: Address;
7
+ method: String;
8
+ params: string[];
9
+ nonce: Number;
10
+ }
11
+ interface RawTransaction extends Transaction {
12
+ timestamp: Number;
13
+ }
14
+ export interface globalMessage {
15
+ sender: Address;
16
+ call: Function;
17
+ staticCall: Function;
18
+ delegate: Function;
19
+ staticDelegate: Function;
20
+ }
21
+ export declare type BlockInMemory = {
22
+ index: number;
23
+ transactions: RawTransaction[];
24
+ loaded?: Boolean;
25
+ };
26
+ export declare type RawBlock = {
27
+ index: number;
28
+ transactions: RawTransaction[];
29
+ };
30
+ export declare type ChainConfig = {
31
+ resolveTimeout?: number;
32
+ };
33
+ export {};
@@ -21,7 +21,7 @@ const run = async (blocks) => {
21
21
  console.log(`loaded block: ${hash} @${index} ${formatBytes(size)}`);
22
22
  // todo we don't want this, need shared state
23
23
  block.decoded.transactions = block.decoded.transactions.sort((a, b) => a.nonce - b.nonce);
24
- resolve({ ...block.decoded, blockInfo: { hash, size, index } });
24
+ resolve({ ...block.decoded, hash, blockInfo: { hash, size, index } });
25
25
  })
26
26
  )
27
27
  );