@leofcoin/chain 1.10.3 → 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/{browser-BOiH47em-CNA0837Q.js → browser-D-r0O9Qn-BUd-PxvP.js} +2 -2
- package/exports/browser/{browser-BuaFyOQj-BCgu_5S8.js → browser-_hiyXwPp-CeZtoaRo.js} +2 -2
- package/exports/browser/chain.js +90 -46
- package/exports/browser/{client-B2wkkpij-CXdxWu9W.js → client-U5AYtQje-DAQ00fHP.js} +4 -4
- package/exports/browser/{constants-CUoFxEp2.js → constants-CVkCJ-VS.js} +490 -221
- package/exports/browser/{index-s61gSKAd-DUkaInec.js → index-BD0Anx7_-D-zybnw-.js} +2 -2
- package/exports/browser/{messages-CZ-3jxiD-BQAqB9Vv.js → messages-Dr5w-bq6-D-moQFGj.js} +2 -2
- package/exports/browser/{node-browser-Cveo6mdM.js → node-browser-D5TgXCwx.js} +11 -7
- package/exports/browser/node-browser.js +2 -2
- package/exports/browser/workers/block-worker.js +1 -1
- package/exports/browser/workers/machine-worker.js +9 -9
- package/exports/browser/workers/{worker-jeGMMCte-BwFbyiks.js → worker-CZqErLI7-BxofVJAn.js} +490 -221
- package/exports/chain.js +80 -36
- package/exports/workers/block-worker.js +1 -1
- package/exports/workers/machine-worker.js +9 -9
- package/exports/workers/{worker-jeGMMCte-BwFbyiks.js → worker-CZqErLI7-BxofVJAn.js} +490 -221
- package/package.json +9 -9
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();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as EasyWorker, F as FormatInterface, p as proto$3, i as index$3, a as index$2, b as proto$2 } from './worker-
|
|
1
|
+
import { E as EasyWorker, F as FormatInterface, p as proto$3, i as index$3, a as index$2, b as proto$2 } from './worker-CZqErLI7-BxofVJAn.js';
|
|
2
2
|
|
|
3
3
|
class ValidatorMessage extends FormatInterface {
|
|
4
4
|
get messageName() {
|