@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.
- package/exports/browser/chain.js +80 -36
- package/exports/chain.js +80 -36
- package/package.json +5 -5
package/exports/browser/chain.js
CHANGED
|
@@ -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
|
|
9301
|
-
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
|
|
9306
|
-
|
|
9307
|
-
|
|
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(
|
|
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 && (
|
|
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
|
-
|
|
10582
|
-
const
|
|
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
|
-
|
|
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
|
|
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
|
|
11221
|
-
|
|
11222
|
-
|
|
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
|
|
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
|
|
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
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
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(
|
|
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 && (
|
|
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
|
-
|
|
2677
|
-
const
|
|
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
|
-
|
|
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
|
|
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
|
|
3316
|
-
|
|
3317
|
-
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
77
|
-
"@leofcoin/workers": "^1.5.
|
|
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",
|