@leofcoin/chain 1.10.4 → 1.10.5

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.
@@ -8575,6 +8575,7 @@ class Machine {
8575
8575
  break;
8576
8576
  }
8577
8577
  case "machine-ready": {
8578
+ this.readyResolve(this);
8578
8579
  pubsub.publish("machine.ready", true);
8579
8580
  break;
8580
8581
  }
@@ -8770,7 +8771,6 @@ class Machine {
8770
8771
  }
8771
8772
  };
8772
8773
  this.worker.postMessage(message);
8773
- this.readyResolve(this);
8774
8774
  });
8775
8775
  }
8776
8776
  async #runContract(contractMessage) {
@@ -9297,15 +9297,18 @@ class State extends Contract {
9297
9297
  }
9298
9298
  async getAndPutBlock(hash) {
9299
9299
  let block = await globalThis.peernet.get(hash, "block");
9300
- if (block !== void 0) {
9301
- if (!(block instanceof Uint8Array)) {
9302
- block = new Uint8Array(Object.values(block));
9303
- }
9304
- block = await new BlockMessage(block);
9305
- const { index } = block.decoded;
9306
- if (this.#blocks[index] && this.#blocks[index].hash !== block.hash) throw `invalid block ${hash} @${index}`;
9307
- if (!await globalThis.peernet.has(hash)) await globalThis.peernet.put(hash, block.encoded, "block");
9308
- }
9300
+ if (block === void 0 || block === null) {
9301
+ throw new ResolveError(`block data unavailable for ${hash}`);
9302
+ }
9303
+ if (!(block instanceof Uint8Array)) block = new Uint8Array(Object.values(block));
9304
+ block = await new BlockMessage(block);
9305
+ const resolvedHash = await block.hash();
9306
+ if (resolvedHash !== hash) throw new ResolveError(`block hash mismatch: requested ${hash}, received ${resolvedHash}`);
9307
+ const { index } = block.decoded;
9308
+ if (this.#blocks[index] && this.#blocks[index].hash !== resolvedHash) {
9309
+ throw new ResolveError(`conflicting block ${resolvedHash} @${index}`);
9310
+ }
9311
+ if (!await globalThis.peernet.has(hash)) await globalThis.peernet.put(hash, block.encoded, "block");
9309
9312
  return block;
9310
9313
  }
9311
9314
  async #resolveTransactions(transactions) {
@@ -10178,6 +10181,40 @@ const verifyConsensusMessage = async (validatorsAddress, type, message, network)
10178
10181
  }
10179
10182
  };
10180
10183
 
10184
+ const nextBlockIndex = (lastIndex) => Number(lastIndex ?? -1) + 1;
10185
+ const proposalDelay = ({
10186
+ now,
10187
+ lastBlockTimestamp = 0,
10188
+ lastProposalAt = 0,
10189
+ blockTime
10190
+ }) => {
10191
+ const canonicalBase = Math.min(lastBlockTimestamp, now);
10192
+ const nextFromCanonicalBlock = canonicalBase > 0 ? canonicalBase + blockTime : 0;
10193
+ const nextFromLocalAttempt = lastProposalAt > 0 ? lastProposalAt + blockTime : 0;
10194
+ return Math.max(0, Math.max(nextFromCanonicalBlock, nextFromLocalAttempt) - now);
10195
+ };
10196
+
10197
+ const compareTransactionNonces = (left, right) => {
10198
+ const leftNonce = BigInt(left ?? 0);
10199
+ const rightNonce = BigInt(right ?? 0);
10200
+ if (leftNonce < rightNonce) return -1;
10201
+ if (leftNonce > rightNonce) return 1;
10202
+ return 0;
10203
+ };
10204
+ const pruneCanonicalTransactions = async (transactions, latestTransactionHashes, isStored, removePending) => {
10205
+ const latest = new Set(latestTransactionHashes);
10206
+ const pending = [];
10207
+ for (const transaction of transactions) {
10208
+ const hash = await transaction.hash();
10209
+ if (latest.has(hash) || await isStored(hash)) {
10210
+ await removePending(hash);
10211
+ continue;
10212
+ }
10213
+ pending.push({ transaction, hash });
10214
+ }
10215
+ return pending;
10216
+ };
10217
+
10181
10218
  const debug = createDebugger("leofcoin/chain");
10182
10219
  class Chain extends VersionControl {
10183
10220
  constructor(config) {
@@ -10185,6 +10222,8 @@ class Chain extends VersionControl {
10185
10222
  this.#slotTime = 1e4;
10186
10223
  this.#blockTime = 6e3;
10187
10224
  // 6 second target block time
10225
+ /** Wall-clock time of the last local proposal attempt. */
10226
+ this.#lastProposalAt = 0;
10188
10227
  this.#epochLength = 10;
10189
10228
  this.utils = {};
10190
10229
  /** {Address[]} */
@@ -10400,6 +10439,7 @@ class Chain extends VersionControl {
10400
10439
  #state;
10401
10440
  #slotTime;
10402
10441
  #blockTime;
10442
+ #lastProposalAt;
10403
10443
  #epochLength;
10404
10444
  #validators;
10405
10445
  #runningEpoch;
@@ -10473,10 +10513,10 @@ class Chain extends VersionControl {
10473
10513
  globalThis.peernet?.network || "leofcoin"
10474
10514
  );
10475
10515
  }
10476
- async #getConsensusValidators(nextBlockIndex) {
10516
+ async #getConsensusValidators(nextBlockIndex2) {
10477
10517
  const localBlock = await this.lastBlock;
10478
10518
  const localIndex = localBlock?.index !== void 0 ? Number(localBlock.index) : -1;
10479
- if (Array.isArray(localBlock?.validators) && localBlock.validators.length > 0 && (nextBlockIndex === void 0 || nextBlockIndex === localIndex + 1)) {
10519
+ if (Array.isArray(localBlock?.validators) && localBlock.validators.length > 0 && (nextBlockIndex2 === void 0 || nextBlockIndex2 === localIndex + 1)) {
10480
10520
  return [
10481
10521
  ...new Set(
10482
10522
  localBlock.validators.map((validator) => validator.address).filter((address) => Boolean(address))
@@ -10567,9 +10607,7 @@ class Chain extends VersionControl {
10567
10607
  async #runEpoch() {
10568
10608
  if (this.#runningEpoch) return;
10569
10609
  this.#runningEpoch = true;
10570
- console.log("epoch");
10571
10610
  const validators = await this.#getConsensusValidators();
10572
- console.log({ validators });
10573
10611
  if (this.#isJailed(peernet.selectedAccount)) {
10574
10612
  this.#runningEpoch = false;
10575
10613
  return;
@@ -10578,8 +10616,16 @@ class Chain extends VersionControl {
10578
10616
  this.#runningEpoch = false;
10579
10617
  return;
10580
10618
  }
10581
- const localBlock = await this.lastBlock;
10582
- const nextIndex = (localBlock?.index !== void 0 ? Number(localBlock.index) : -1) + 1;
10619
+ let localBlock = await this.lastBlock;
10620
+ const delay = proposalDelay({
10621
+ now: Date.now(),
10622
+ lastBlockTimestamp: Number(localBlock?.timestamp ?? 0),
10623
+ lastProposalAt: this.#lastProposalAt,
10624
+ blockTime: this.#blockTime
10625
+ });
10626
+ if (delay > 0) await this.#sleep(delay);
10627
+ localBlock = await this.lastBlock;
10628
+ const nextIndex = nextBlockIndex(localBlock?.index);
10583
10629
  const proposerIdx = (nextIndex + this.#consensusRound) % validators.length;
10584
10630
  const isProposer = validators[proposerIdx] === peernet.selectedAccount;
10585
10631
  if (!isProposer) {
@@ -10599,18 +10645,13 @@ class Chain extends VersionControl {
10599
10645
  clearTimeout(this.#roundTimer);
10600
10646
  this.#roundTimer = null;
10601
10647
  }
10602
- const start = Date.now();
10648
+ this.#lastProposalAt = Date.now();
10603
10649
  try {
10604
10650
  await this.#createBlock();
10605
10651
  } catch (error) {
10606
10652
  console.error(error);
10607
10653
  }
10608
- const end = Date.now();
10609
- console.log((end - start) / 1e3 + " s");
10610
- const elapsed = end - start;
10611
- const remaining = this.#blockTime - elapsed;
10612
10654
  const hasMore = await this.hasTransactionToHandle();
10613
- if (!hasMore && remaining > 0) await this.#sleep(remaining);
10614
10655
  this.#runningEpoch = false;
10615
10656
  if (hasMore && !this.#proposalInFlight) return this.#runEpoch();
10616
10657
  }
@@ -10889,6 +10930,10 @@ class Chain extends VersionControl {
10889
10930
  return Promise.all(transactionsToGet);
10890
10931
  }
10891
10932
  async #peerConnected(peerId) {
10933
+ if (typeof peerId !== "string" || !peerId.trim() || peerId === "undefined") {
10934
+ debug("ignored peer connection without a valid peer id");
10935
+ return;
10936
+ }
10892
10937
  debug(`peer connected: ${peerId}`);
10893
10938
  const peer = peernet.getConnection(peerId);
10894
10939
  if (!peer) {
@@ -11100,7 +11145,7 @@ class Chain extends VersionControl {
11100
11145
  if (a.decoded.priority !== b.decoded.priority) {
11101
11146
  return (b.decoded.priority ? 1 : 0) - (a.decoded.priority ? 1 : 0);
11102
11147
  }
11103
- const nonceDiff = (a.decoded?.nonce ?? 0) - (b.decoded?.nonce ?? 0);
11148
+ const nonceDiff = compareTransactionNonces(a.decoded?.nonce, b.decoded?.nonce);
11104
11149
  if (nonceDiff !== 0) return nonceDiff;
11105
11150
  return 0;
11106
11151
  });
@@ -11198,7 +11243,6 @@ class Chain extends VersionControl {
11198
11243
  // todo filter tx that need to wait on prev nonce
11199
11244
  async #createBlock(limit = this.transactionLimit) {
11200
11245
  if (this.#proposalInFlight) return;
11201
- console.log(await globalThis.transactionPoolStore.size());
11202
11246
  if (await globalThis.transactionPoolStore.size() === 0) return;
11203
11247
  let transactions = await globalThis.transactionPoolStore.values(this.transactionLimit);
11204
11248
  if (Object.keys(transactions)?.length === 0) return;
@@ -11217,29 +11261,29 @@ class Chain extends VersionControl {
11217
11261
  };
11218
11262
  const latestTransactions = await this.machine.latestTransactions();
11219
11263
  transactions = await this.promiseTransactions(transactions);
11220
- const allTransactions = transactions.sort((a, b) => {
11221
- if (a.decoded.priority !== b.decoded.priority) {
11222
- return (b.decoded.priority ? 1 : 0) - (a.decoded.priority ? 1 : 0);
11264
+ const pendingTransactions = await pruneCanonicalTransactions(
11265
+ transactions,
11266
+ latestTransactions,
11267
+ (hash) => globalThis.transactionStore.has(hash),
11268
+ (hash) => globalThis.transactionPoolStore.delete(hash)
11269
+ );
11270
+ const allTransactions = pendingTransactions.sort((a, b) => {
11271
+ if (a.transaction.decoded.priority !== b.transaction.decoded.priority) {
11272
+ return (b.transaction.decoded.priority ? 1 : 0) - (a.transaction.decoded.priority ? 1 : 0);
11223
11273
  }
11224
- const nonceDiff = (a.decoded?.nonce ?? 0) - (b.decoded?.nonce ?? 0);
11274
+ const nonceDiff = compareTransactionNonces(a.transaction.decoded?.nonce, b.transaction.decoded?.nonce);
11225
11275
  if (nonceDiff !== 0) return nonceDiff;
11226
11276
  return 0;
11227
11277
  });
11228
- for (const transaction of allTransactions) {
11278
+ for (const { transaction, hash } of allTransactions) {
11229
11279
  await this.validateTransactionSignature(transaction);
11230
- const hash = await transaction.hash();
11231
- if (latestTransactions.includes(hash) || await globalThis.transactionStore.has(hash)) {
11232
- continue;
11233
- }
11234
11280
  block.transactions.push(hash);
11235
11281
  block.fees += BigInt(await calculateFee(transaction.decoded));
11236
11282
  await globalThis.peernet.put(hash, transaction.encoded, "transaction");
11237
11283
  }
11238
11284
  if (block.transactions.length === 0) return;
11239
11285
  const localBlock = await this.lastBlock;
11240
- block.index = localBlock.index;
11241
- if (block.index === void 0) block.index = 0;
11242
- else block.index += 1;
11286
+ block.index = nextBlockIndex(localBlock?.index);
11243
11287
  block.previousHash = localBlock.hash || "0x0";
11244
11288
  const canonicalValidators = await this.staticCall(addresses.validators, "validators");
11245
11289
  const sortedValidators = [...canonicalValidators].sort();
package/exports/chain.js CHANGED
@@ -670,6 +670,7 @@ class Machine {
670
670
  break;
671
671
  }
672
672
  case "machine-ready": {
673
+ this.readyResolve(this);
673
674
  pubsub.publish("machine.ready", true);
674
675
  break;
675
676
  }
@@ -865,7 +866,6 @@ class Machine {
865
866
  }
866
867
  };
867
868
  this.worker.postMessage(message);
868
- this.readyResolve(this);
869
869
  });
870
870
  }
871
871
  async #runContract(contractMessage) {
@@ -1392,15 +1392,18 @@ class State extends Contract {
1392
1392
  }
1393
1393
  async getAndPutBlock(hash) {
1394
1394
  let block = await globalThis.peernet.get(hash, "block");
1395
- if (block !== void 0) {
1396
- if (!(block instanceof Uint8Array)) {
1397
- block = new Uint8Array(Object.values(block));
1398
- }
1399
- block = await new BlockMessage(block);
1400
- const { index } = block.decoded;
1401
- if (this.#blocks[index] && this.#blocks[index].hash !== block.hash) throw `invalid block ${hash} @${index}`;
1402
- if (!await globalThis.peernet.has(hash)) await globalThis.peernet.put(hash, block.encoded, "block");
1403
- }
1395
+ if (block === void 0 || block === null) {
1396
+ throw new ResolveError(`block data unavailable for ${hash}`);
1397
+ }
1398
+ if (!(block instanceof Uint8Array)) block = new Uint8Array(Object.values(block));
1399
+ block = await new BlockMessage(block);
1400
+ const resolvedHash = await block.hash();
1401
+ if (resolvedHash !== hash) throw new ResolveError(`block hash mismatch: requested ${hash}, received ${resolvedHash}`);
1402
+ const { index } = block.decoded;
1403
+ if (this.#blocks[index] && this.#blocks[index].hash !== resolvedHash) {
1404
+ throw new ResolveError(`conflicting block ${resolvedHash} @${index}`);
1405
+ }
1406
+ if (!await globalThis.peernet.has(hash)) await globalThis.peernet.put(hash, block.encoded, "block");
1404
1407
  return block;
1405
1408
  }
1406
1409
  async #resolveTransactions(transactions) {
@@ -2273,6 +2276,40 @@ const verifyConsensusMessage = async (validatorsAddress, type, message, network)
2273
2276
  }
2274
2277
  };
2275
2278
 
2279
+ const nextBlockIndex = (lastIndex) => Number(lastIndex ?? -1) + 1;
2280
+ const proposalDelay = ({
2281
+ now,
2282
+ lastBlockTimestamp = 0,
2283
+ lastProposalAt = 0,
2284
+ blockTime
2285
+ }) => {
2286
+ const canonicalBase = Math.min(lastBlockTimestamp, now);
2287
+ const nextFromCanonicalBlock = canonicalBase > 0 ? canonicalBase + blockTime : 0;
2288
+ const nextFromLocalAttempt = lastProposalAt > 0 ? lastProposalAt + blockTime : 0;
2289
+ return Math.max(0, Math.max(nextFromCanonicalBlock, nextFromLocalAttempt) - now);
2290
+ };
2291
+
2292
+ const compareTransactionNonces = (left, right) => {
2293
+ const leftNonce = BigInt(left ?? 0);
2294
+ const rightNonce = BigInt(right ?? 0);
2295
+ if (leftNonce < rightNonce) return -1;
2296
+ if (leftNonce > rightNonce) return 1;
2297
+ return 0;
2298
+ };
2299
+ const pruneCanonicalTransactions = async (transactions, latestTransactionHashes, isStored, removePending) => {
2300
+ const latest = new Set(latestTransactionHashes);
2301
+ const pending = [];
2302
+ for (const transaction of transactions) {
2303
+ const hash = await transaction.hash();
2304
+ if (latest.has(hash) || await isStored(hash)) {
2305
+ await removePending(hash);
2306
+ continue;
2307
+ }
2308
+ pending.push({ transaction, hash });
2309
+ }
2310
+ return pending;
2311
+ };
2312
+
2276
2313
  const debug = createDebugger("leofcoin/chain");
2277
2314
  class Chain extends VersionControl {
2278
2315
  constructor(config) {
@@ -2280,6 +2317,8 @@ class Chain extends VersionControl {
2280
2317
  this.#slotTime = 1e4;
2281
2318
  this.#blockTime = 6e3;
2282
2319
  // 6 second target block time
2320
+ /** Wall-clock time of the last local proposal attempt. */
2321
+ this.#lastProposalAt = 0;
2283
2322
  this.#epochLength = 10;
2284
2323
  this.utils = {};
2285
2324
  /** {Address[]} */
@@ -2495,6 +2534,7 @@ class Chain extends VersionControl {
2495
2534
  #state;
2496
2535
  #slotTime;
2497
2536
  #blockTime;
2537
+ #lastProposalAt;
2498
2538
  #epochLength;
2499
2539
  #validators;
2500
2540
  #runningEpoch;
@@ -2568,10 +2608,10 @@ class Chain extends VersionControl {
2568
2608
  globalThis.peernet?.network || "leofcoin"
2569
2609
  );
2570
2610
  }
2571
- async #getConsensusValidators(nextBlockIndex) {
2611
+ async #getConsensusValidators(nextBlockIndex2) {
2572
2612
  const localBlock = await this.lastBlock;
2573
2613
  const localIndex = localBlock?.index !== void 0 ? Number(localBlock.index) : -1;
2574
- if (Array.isArray(localBlock?.validators) && localBlock.validators.length > 0 && (nextBlockIndex === void 0 || nextBlockIndex === localIndex + 1)) {
2614
+ if (Array.isArray(localBlock?.validators) && localBlock.validators.length > 0 && (nextBlockIndex2 === void 0 || nextBlockIndex2 === localIndex + 1)) {
2575
2615
  return [
2576
2616
  ...new Set(
2577
2617
  localBlock.validators.map((validator) => validator.address).filter((address) => Boolean(address))
@@ -2662,9 +2702,7 @@ class Chain extends VersionControl {
2662
2702
  async #runEpoch() {
2663
2703
  if (this.#runningEpoch) return;
2664
2704
  this.#runningEpoch = true;
2665
- console.log("epoch");
2666
2705
  const validators = await this.#getConsensusValidators();
2667
- console.log({ validators });
2668
2706
  if (this.#isJailed(peernet.selectedAccount)) {
2669
2707
  this.#runningEpoch = false;
2670
2708
  return;
@@ -2673,8 +2711,16 @@ class Chain extends VersionControl {
2673
2711
  this.#runningEpoch = false;
2674
2712
  return;
2675
2713
  }
2676
- const localBlock = await this.lastBlock;
2677
- const nextIndex = (localBlock?.index !== void 0 ? Number(localBlock.index) : -1) + 1;
2714
+ let localBlock = await this.lastBlock;
2715
+ const delay = proposalDelay({
2716
+ now: Date.now(),
2717
+ lastBlockTimestamp: Number(localBlock?.timestamp ?? 0),
2718
+ lastProposalAt: this.#lastProposalAt,
2719
+ blockTime: this.#blockTime
2720
+ });
2721
+ if (delay > 0) await this.#sleep(delay);
2722
+ localBlock = await this.lastBlock;
2723
+ const nextIndex = nextBlockIndex(localBlock?.index);
2678
2724
  const proposerIdx = (nextIndex + this.#consensusRound) % validators.length;
2679
2725
  const isProposer = validators[proposerIdx] === peernet.selectedAccount;
2680
2726
  if (!isProposer) {
@@ -2694,18 +2740,13 @@ class Chain extends VersionControl {
2694
2740
  clearTimeout(this.#roundTimer);
2695
2741
  this.#roundTimer = null;
2696
2742
  }
2697
- const start = Date.now();
2743
+ this.#lastProposalAt = Date.now();
2698
2744
  try {
2699
2745
  await this.#createBlock();
2700
2746
  } catch (error) {
2701
2747
  console.error(error);
2702
2748
  }
2703
- const end = Date.now();
2704
- console.log((end - start) / 1e3 + " s");
2705
- const elapsed = end - start;
2706
- const remaining = this.#blockTime - elapsed;
2707
2749
  const hasMore = await this.hasTransactionToHandle();
2708
- if (!hasMore && remaining > 0) await this.#sleep(remaining);
2709
2750
  this.#runningEpoch = false;
2710
2751
  if (hasMore && !this.#proposalInFlight) return this.#runEpoch();
2711
2752
  }
@@ -2984,6 +3025,10 @@ class Chain extends VersionControl {
2984
3025
  return Promise.all(transactionsToGet);
2985
3026
  }
2986
3027
  async #peerConnected(peerId) {
3028
+ if (typeof peerId !== "string" || !peerId.trim() || peerId === "undefined") {
3029
+ debug("ignored peer connection without a valid peer id");
3030
+ return;
3031
+ }
2987
3032
  debug(`peer connected: ${peerId}`);
2988
3033
  const peer = peernet.getConnection(peerId);
2989
3034
  if (!peer) {
@@ -3195,7 +3240,7 @@ class Chain extends VersionControl {
3195
3240
  if (a.decoded.priority !== b.decoded.priority) {
3196
3241
  return (b.decoded.priority ? 1 : 0) - (a.decoded.priority ? 1 : 0);
3197
3242
  }
3198
- const nonceDiff = (a.decoded?.nonce ?? 0) - (b.decoded?.nonce ?? 0);
3243
+ const nonceDiff = compareTransactionNonces(a.decoded?.nonce, b.decoded?.nonce);
3199
3244
  if (nonceDiff !== 0) return nonceDiff;
3200
3245
  return 0;
3201
3246
  });
@@ -3293,7 +3338,6 @@ class Chain extends VersionControl {
3293
3338
  // todo filter tx that need to wait on prev nonce
3294
3339
  async #createBlock(limit = this.transactionLimit) {
3295
3340
  if (this.#proposalInFlight) return;
3296
- console.log(await globalThis.transactionPoolStore.size());
3297
3341
  if (await globalThis.transactionPoolStore.size() === 0) return;
3298
3342
  let transactions = await globalThis.transactionPoolStore.values(this.transactionLimit);
3299
3343
  if (Object.keys(transactions)?.length === 0) return;
@@ -3312,29 +3356,29 @@ class Chain extends VersionControl {
3312
3356
  };
3313
3357
  const latestTransactions = await this.machine.latestTransactions();
3314
3358
  transactions = await this.promiseTransactions(transactions);
3315
- const allTransactions = transactions.sort((a, b) => {
3316
- if (a.decoded.priority !== b.decoded.priority) {
3317
- return (b.decoded.priority ? 1 : 0) - (a.decoded.priority ? 1 : 0);
3359
+ const pendingTransactions = await pruneCanonicalTransactions(
3360
+ transactions,
3361
+ latestTransactions,
3362
+ (hash) => globalThis.transactionStore.has(hash),
3363
+ (hash) => globalThis.transactionPoolStore.delete(hash)
3364
+ );
3365
+ const allTransactions = pendingTransactions.sort((a, b) => {
3366
+ if (a.transaction.decoded.priority !== b.transaction.decoded.priority) {
3367
+ return (b.transaction.decoded.priority ? 1 : 0) - (a.transaction.decoded.priority ? 1 : 0);
3318
3368
  }
3319
- const nonceDiff = (a.decoded?.nonce ?? 0) - (b.decoded?.nonce ?? 0);
3369
+ const nonceDiff = compareTransactionNonces(a.transaction.decoded?.nonce, b.transaction.decoded?.nonce);
3320
3370
  if (nonceDiff !== 0) return nonceDiff;
3321
3371
  return 0;
3322
3372
  });
3323
- for (const transaction of allTransactions) {
3373
+ for (const { transaction, hash } of allTransactions) {
3324
3374
  await this.validateTransactionSignature(transaction);
3325
- const hash = await transaction.hash();
3326
- if (latestTransactions.includes(hash) || await globalThis.transactionStore.has(hash)) {
3327
- continue;
3328
- }
3329
3375
  block.transactions.push(hash);
3330
3376
  block.fees += BigInt(await calculateFee(transaction.decoded));
3331
3377
  await globalThis.peernet.put(hash, transaction.encoded, "transaction");
3332
3378
  }
3333
3379
  if (block.transactions.length === 0) return;
3334
3380
  const localBlock = await this.lastBlock;
3335
- block.index = localBlock.index;
3336
- if (block.index === void 0) block.index = 0;
3337
- else block.index += 1;
3381
+ block.index = nextBlockIndex(localBlock?.index);
3338
3382
  block.previousHash = localBlock.hash || "0x0";
3339
3383
  const canonicalValidators = await this.staticCall(addresses.validators, "validators");
3340
3384
  const sortedValidators = [...canonicalValidators].sort();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leofcoin/chain",
3
- "version": "1.10.4",
3
+ "version": "1.10.5",
4
4
  "description": "Official javascript implementation",
5
5
  "private": false,
6
6
  "exports": {
@@ -62,19 +62,19 @@
62
62
  "tslib": "^2.8.1"
63
63
  },
64
64
  "dependencies": {
65
- "@leofcoin/addresses": "^1.0.59",
65
+ "@leofcoin/addresses": "^1.0.60",
66
66
  "@leofcoin/codecs": "^1.1.4",
67
67
  "@leofcoin/contracts": "^0.1.21",
68
68
  "@leofcoin/crypto": "^0.2.41",
69
69
  "@leofcoin/errors": "^1.0.30",
70
- "@leofcoin/lib": "^1.3.3",
70
+ "@leofcoin/lib": "^1.3.4",
71
71
  "@leofcoin/messages": "^1.6.1",
72
72
  "@leofcoin/multi-wallet": "^3.1.9",
73
73
  "@leofcoin/networks": "^1.1.30",
74
74
  "@leofcoin/peernet": "^1.2.26",
75
75
  "@leofcoin/storage": "^3.5.38",
76
- "@leofcoin/utils": "^1.1.44",
77
- "@leofcoin/workers": "^1.5.33",
76
+ "@leofcoin/utils": "^1.1.45",
77
+ "@leofcoin/workers": "^1.5.34",
78
78
  "@vandeurenglenn/base58": "^1.1.9",
79
79
  "@vandeurenglenn/easy-worker": "^1.0.3",
80
80
  "@vandeurenglenn/typed-array-utils": "^1.2.0",