@leofcoin/chain 1.10.21 → 1.10.22
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/README.md +21 -0
- package/exports/browser/beacon-wire.js +1 -1
- package/exports/browser/{browser-CCfR9KOM-BGMMnVsR.js → browser-CCfR9KOM-UO9mzy-j.js} +2 -2
- package/exports/browser/chain.js +55 -125
- package/exports/browser/client-DbZBfpG6-CYDyUGUC.js +5943 -0
- package/exports/browser/{connection-monitor-D-krNiRH.js → connection-monitor-DMGAhcC0.js} +111 -2
- package/exports/browser/{index-dTQVgkpf-DOL2rIjp.js → index-dTQVgkpf-C6SJ0ZYW.js} +2 -2
- package/exports/browser/{index-DCbLvMKL.js → index-dxD17Fom.js} +231 -227
- package/exports/browser/{messages-DCePyqKC-BSvJxDWZ.js → messages-DZYCxoZI-D6kIiLKF.js} +2 -2
- package/exports/browser/{node-browser-Ha4Lvntj.js → node-browser-BMfelxXV.js} +23 -7
- package/exports/browser/node-browser.js +2 -2
- package/exports/chain.js +54 -124
- package/exports/connection-monitor-h2L8vsS7.js +435 -0
- package/exports/connection-monitor.js +2 -324
- package/exports/node.js +3 -1
- package/package.json +5 -5
- package/exports/browser/client-DKKzPSlb-C_1ug6ux.js +0 -2401
package/README.md
CHANGED
|
@@ -6,6 +6,27 @@
|
|
|
6
6
|
|
|
7
7
|
- reachedOneZeroZero
|
|
8
8
|
|
|
9
|
+
## Cold-sync reliability
|
|
10
|
+
|
|
11
|
+
Both server and browser nodes guard provider discovery against fast negative
|
|
12
|
+
responses. A walk succeeds only after a connected peer confirms it provides
|
|
13
|
+
the requested hash; individual discovery requests retain the protocol request
|
|
14
|
+
timeout.
|
|
15
|
+
|
|
16
|
+
Chain content requests probe the exact requested store before requesting bytes
|
|
17
|
+
from a peer. A pending-only copy cannot act as a provider for the canonical
|
|
18
|
+
transaction store. Responses must use the expected codec and advertised hash;
|
|
19
|
+
the first valid response wins, and unavailable content fails explicitly.
|
|
20
|
+
|
|
21
|
+
Historical ancestry is resolved iteratively, finishing transaction dependencies
|
|
22
|
+
before requesting the next parent. Duplicate callers await the same resolution,
|
|
23
|
+
completed blocks survive retries, and missing or cyclic ancestry fails explicitly.
|
|
24
|
+
Only dependencies of the selected target tip are resolved; unrelated hashes in
|
|
25
|
+
a peer's `knownBlocks` inventory do not gate canonical catch-up.
|
|
26
|
+
Transaction bodies are hash-checked before entering the canonical transaction
|
|
27
|
+
store. Resolving data never applies it: canonical loading still uses the
|
|
28
|
+
serialized state writer and chain-link validation.
|
|
29
|
+
|
|
9
30
|
## Pending transaction propagation
|
|
10
31
|
|
|
11
32
|
Transactions enter the local pending pool before canonical confirmation. Peers
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as signTransaction, c as MultiWallet, d as createTransactionHash } from './index-
|
|
1
|
+
import { s as signTransaction, c as MultiWallet, d as createTransactionHash } from './index-dxD17Fom.js';
|
|
2
2
|
import { f as fromBase58 } from './index-CvKt4UDE.js';
|
|
3
3
|
import './browser-crypto-CH0ua22L.js';
|
|
4
4
|
import './sha2-BKcEJzgd.js';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { g as getDefaultExportFromCjs } from './node-browser-
|
|
1
|
+
import { g as getDefaultExportFromCjs } from './node-browser-BMfelxXV.js';
|
|
2
2
|
import './browser-crypto-CH0ua22L.js';
|
|
3
3
|
import './index-CvKt4UDE.js';
|
|
4
4
|
import './sha2-BKcEJzgd.js';
|
|
5
|
-
import './connection-monitor-
|
|
5
|
+
import './connection-monitor-DMGAhcC0.js';
|
|
6
6
|
|
|
7
7
|
function _mergeNamespaces$1(n, m) {
|
|
8
8
|
m.forEach(function (e) {
|
package/exports/browser/chain.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { F as FormatInterface, p as proto, a as proto$1, b as proto$2, T as TransactionMessage, j as jsonStringifyBigInt, c as jsonParseBigInt, C as ContractMessage, d as Codec } from './browser-crypto-CH0ua22L.js';
|
|
2
|
-
import { B as BlockMessage, L as LastBlockMessage,
|
|
3
|
-
import { M as MAX_TRANSACTION_BYTES, a as MAX_BLOCK_TRANSACTION_BYTES, b as MAX_BLOCK_TRANSACTIONS, c as MultiWallet, d as createTransactionHash, e as calculateFee, f as createContractMessage, s as signTransaction, r as randombytes, g as distributeTransactionFee, h as supportsTransactionFees, i as supportsMonetaryPolicy, v as validateBlockResourceLimits, j as calculateMonetaryPolicy, k as distributeAmount, l as aggregateValidatorFees, m as MONETARY_POLICY_AUTHORITY, n as contractFactoryMessage, o as nativeTokenMessage, p as validatorsMessage, q as nameServiceMessage, t as parseUnits, u as formatUnits } from './index-
|
|
2
|
+
import { P as Protocol, B as BlockMessage, L as LastBlockMessage, a as PROTOCOL_VERSION, R as REACHED_ONE_ZERO_ZERO, C as ConnectionMonitor, b as BWMessage, S as StateMessage } from './connection-monitor-DMGAhcC0.js';
|
|
3
|
+
import { M as MAX_TRANSACTION_BYTES, a as MAX_BLOCK_TRANSACTION_BYTES, b as MAX_BLOCK_TRANSACTIONS, c as MultiWallet, d as createTransactionHash, e as calculateFee, f as createContractMessage, s as signTransaction, r as randombytes, g as distributeTransactionFee, h as supportsTransactionFees, i as supportsMonetaryPolicy, v as validateBlockResourceLimits, j as calculateMonetaryPolicy, k as distributeAmount, l as aggregateValidatorFees, m as MONETARY_POLICY_AUTHORITY, n as contractFactoryMessage, o as nativeTokenMessage, p as validatorsMessage, q as nameServiceMessage, t as parseUnits, u as formatUnits } from './index-dxD17Fom.js';
|
|
4
4
|
import { f as fromBase58 } from './index-CvKt4UDE.js';
|
|
5
5
|
import { g as getDefaultExportFromCjs } from './_commonjsHelpers-B85MJLTf.js';
|
|
6
6
|
import { q as quorumThreshold } from './quorum-S_qdgiAY.js';
|
|
@@ -2915,29 +2915,6 @@ function requireSemver () {
|
|
|
2915
2915
|
var semverExports = requireSemver();
|
|
2916
2916
|
var semver = /*@__PURE__*/getDefaultExportFromCjs(semverExports);
|
|
2917
2917
|
|
|
2918
|
-
const limit = 1800;
|
|
2919
|
-
const transactionLimit = 2500;
|
|
2920
|
-
const requestTimeout = 3e4;
|
|
2921
|
-
const syncTimeout = 3e4;
|
|
2922
|
-
class Protocol {
|
|
2923
|
-
constructor(config) {
|
|
2924
|
-
this.resolveTimeout = 1e4;
|
|
2925
|
-
if (config?.resolveTimeout) this.resolveTimeout = config.resolveTimeout;
|
|
2926
|
-
}
|
|
2927
|
-
get limit() {
|
|
2928
|
-
return limit;
|
|
2929
|
-
}
|
|
2930
|
-
get transactionLimit() {
|
|
2931
|
-
return transactionLimit;
|
|
2932
|
-
}
|
|
2933
|
-
get requestTimeout() {
|
|
2934
|
-
return requestTimeout;
|
|
2935
|
-
}
|
|
2936
|
-
get syncTimeout() {
|
|
2937
|
-
return syncTimeout;
|
|
2938
|
-
}
|
|
2939
|
-
}
|
|
2940
|
-
|
|
2941
2918
|
const waitForCanonicalTransaction = (pubsub, transactionPool, hash) => new Promise((resolve, reject) => {
|
|
2942
2919
|
const completionTopic = `transaction.completed.${hash}`;
|
|
2943
2920
|
const cleanup = () => {
|
|
@@ -4304,6 +4281,15 @@ const validateChainLink = (localTip, incoming) => {
|
|
|
4304
4281
|
return "append";
|
|
4305
4282
|
};
|
|
4306
4283
|
|
|
4284
|
+
const resolveTransactionReference = async (expectedHash, transactionData) => {
|
|
4285
|
+
const transaction = transactionData instanceof TransactionMessage ? transactionData : new TransactionMessage(transactionData);
|
|
4286
|
+
const actualHash = await transaction.hash();
|
|
4287
|
+
if (actualHash !== expectedHash) {
|
|
4288
|
+
throw new Error(`Transaction hash mismatch: expected ${expectedHash}, got ${actualHash}`);
|
|
4289
|
+
}
|
|
4290
|
+
return transaction;
|
|
4291
|
+
};
|
|
4292
|
+
|
|
4307
4293
|
const debug$1 = createDebugger("leofcoin/state");
|
|
4308
4294
|
class State extends Contract {
|
|
4309
4295
|
constructor(config) {
|
|
@@ -4320,7 +4306,7 @@ class State extends Contract {
|
|
|
4320
4306
|
this.#totalSize = 0;
|
|
4321
4307
|
this.#canonicalStateQueue = new CanonicalStateQueue();
|
|
4322
4308
|
this.#loaded = false;
|
|
4323
|
-
this.#resolvingHashes = /* @__PURE__ */ new
|
|
4309
|
+
this.#resolvingHashes = /* @__PURE__ */ new Map();
|
|
4324
4310
|
this._wantList = [];
|
|
4325
4311
|
this.#chainStateHandler = () => {
|
|
4326
4312
|
return new globalThis.peernet.protos["peernet-response"]({
|
|
@@ -4576,7 +4562,8 @@ class State extends Contract {
|
|
|
4576
4562
|
if (!exists) {
|
|
4577
4563
|
const data = await peernet.get(hash, "transaction");
|
|
4578
4564
|
if (!data) throw new Error(`missing transaction data for ${hash}`);
|
|
4579
|
-
await
|
|
4565
|
+
const transaction = await resolveTransactionReference(hash, data);
|
|
4566
|
+
await transactionStore.put(hash, transaction.encoded);
|
|
4580
4567
|
}
|
|
4581
4568
|
const inPool = await transactionPoolStore.has(hash);
|
|
4582
4569
|
if (inPool) await transactionPoolStore.delete(hash);
|
|
@@ -4584,84 +4571,61 @@ class State extends Contract {
|
|
|
4584
4571
|
);
|
|
4585
4572
|
}
|
|
4586
4573
|
async #resolveBlock(hash) {
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
}
|
|
4598
|
-
if (this.#blocks[index]) {
|
|
4599
|
-
const previousHash = this.#blocks[index].previousHash;
|
|
4600
|
-
if (previousHash === localHash) return;
|
|
4601
|
-
if (previousHash !== "0x0") {
|
|
4602
|
-
return this.resolveBlock(previousHash);
|
|
4603
|
-
} else {
|
|
4604
|
-
return;
|
|
4574
|
+
const localHash = (await this.canonicalTip()).hash;
|
|
4575
|
+
const visited = /* @__PURE__ */ new Set();
|
|
4576
|
+
while (hash !== "0x0" && hash !== localHash) {
|
|
4577
|
+
if (visited.has(hash)) throw new ResolveError(`cyclic block ancestry at ${hash}`);
|
|
4578
|
+
visited.add(hash);
|
|
4579
|
+
const cachedIndex = this.#blockHashMap.get(hash);
|
|
4580
|
+
const cached = this.#blocks[cachedIndex];
|
|
4581
|
+
if (cached) {
|
|
4582
|
+
hash = cached.previousHash;
|
|
4583
|
+
continue;
|
|
4605
4584
|
}
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4585
|
+
try {
|
|
4586
|
+
const block = await this.getAndPutBlock(hash);
|
|
4587
|
+
await this.#resolveTransactions(block.decoded.transactions);
|
|
4588
|
+
const index = block.decoded.index;
|
|
4589
|
+
const size = block.encoded.byteLength;
|
|
4590
|
+
this.#totalSize += size;
|
|
4591
|
+
this.#blocks[index] = { hash, ...block.decoded };
|
|
4592
|
+
this.#blockHashMap.set(hash, index);
|
|
4593
|
+
debug$1(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
|
|
4594
|
+
globalThis.pubsub.publish("block-resolved", { hash, index });
|
|
4595
|
+
this.#lastResolved = this.#blocks[index];
|
|
4596
|
+
this.#lastResolvedTime = Date.now();
|
|
4597
|
+
hash = block.decoded.previousHash;
|
|
4598
|
+
} catch (error) {
|
|
4599
|
+
throw new ResolveError(`block: ${hash}`, { cause: error });
|
|
4612
4600
|
}
|
|
4613
|
-
promises.push(this.#resolveTransactions(block.decoded.transactions));
|
|
4614
|
-
await Promise.all(promises);
|
|
4615
|
-
index = block.decoded.index;
|
|
4616
|
-
const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
|
|
4617
|
-
this.#totalSize += size;
|
|
4618
|
-
this.#blocks[index] = { hash, ...block.decoded };
|
|
4619
|
-
this.#blockHashMap.set(hash, index);
|
|
4620
|
-
debug$1(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
|
|
4621
|
-
globalThis.pubsub.publish("block-resolved", { hash, index });
|
|
4622
|
-
this.#lastResolved = this.#blocks[index];
|
|
4623
|
-
this.#lastResolvedTime = Date.now();
|
|
4624
|
-
} catch (error) {
|
|
4625
|
-
throw new ResolveError(`block: ${hash}@${index}`, { cause: error });
|
|
4626
4601
|
}
|
|
4627
|
-
return;
|
|
4628
4602
|
}
|
|
4629
4603
|
async resolveBlock(hash) {
|
|
4630
4604
|
if (!hash) throw new Error(`expected hash, got: ${hash}`);
|
|
4631
4605
|
if (hash === "0x0") return;
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
const isEntering = this.#resolvingHashes.size === 1;
|
|
4606
|
+
const existing = this.#resolvingHashes.get(hash);
|
|
4607
|
+
if (existing) return existing;
|
|
4635
4608
|
this.#resolving = true;
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
} else {
|
|
4641
|
-
await this.#resolveBlock(hash);
|
|
4642
|
-
}
|
|
4643
|
-
try {
|
|
4644
|
-
const lastBlockHash = await globalThis.stateStore.get("lastBlock");
|
|
4645
|
-
if (lastBlockHash === hash) {
|
|
4609
|
+
const resolution = Promise.resolve().then(async () => {
|
|
4610
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
4611
|
+
try {
|
|
4612
|
+
await this.#resolveBlock(hash);
|
|
4646
4613
|
this.#resolveErrored = false;
|
|
4647
4614
|
return;
|
|
4615
|
+
} catch (error) {
|
|
4616
|
+
console.error(`block resolution attempt ${attempt + 1} failed for ${hash}`, error);
|
|
4617
|
+
if (attempt === 2) {
|
|
4618
|
+
if (!this.wantList.includes(hash)) this.wantList.push(hash);
|
|
4619
|
+
throw new ResolveError(`block: ${hash}`, { cause: error });
|
|
4620
|
+
}
|
|
4648
4621
|
}
|
|
4649
|
-
} catch (error) {
|
|
4650
4622
|
}
|
|
4651
|
-
}
|
|
4652
|
-
console.log({ error });
|
|
4653
|
-
this.#resolveErrorCount += 1;
|
|
4654
|
-
if (this.#resolveErrorCount < 3) {
|
|
4655
|
-
this.#resolvingHashes.delete(hash);
|
|
4656
|
-
return this.resolveBlock(hash);
|
|
4657
|
-
}
|
|
4658
|
-
this.#resolveErrorCount = 0;
|
|
4659
|
-
this.wantList.push(hash);
|
|
4660
|
-
throw new ResolveError(`block: ${hash}`, { cause: error });
|
|
4661
|
-
} finally {
|
|
4623
|
+
}).finally(() => {
|
|
4662
4624
|
this.#resolvingHashes.delete(hash);
|
|
4663
4625
|
if (this.#resolvingHashes.size === 0) this.#resolving = false;
|
|
4664
|
-
}
|
|
4626
|
+
});
|
|
4627
|
+
this.#resolvingHashes.set(hash, resolution);
|
|
4628
|
+
return resolution;
|
|
4665
4629
|
}
|
|
4666
4630
|
async resolveBlocks() {
|
|
4667
4631
|
if (this.#chainSyncing || this.#resolving) {
|
|
@@ -4798,24 +4762,6 @@ class State extends Contract {
|
|
|
4798
4762
|
return;
|
|
4799
4763
|
}
|
|
4800
4764
|
if (localStateHash !== remoteBlockHash) {
|
|
4801
|
-
if (this.wantList.length > 0) {
|
|
4802
|
-
debug$1(`Fetching ${this.wantList.length} blocks before resolving`);
|
|
4803
|
-
const getBatch = async (batch) => {
|
|
4804
|
-
const blocks2 = await Promise.all(
|
|
4805
|
-
batch.map(
|
|
4806
|
-
(hash) => this.getAndPutBlock(hash).catch((e) => {
|
|
4807
|
-
console.warn(`failed to fetch block ${hash}`, e);
|
|
4808
|
-
})
|
|
4809
|
-
)
|
|
4810
|
-
);
|
|
4811
|
-
const transactions = blocks2.filter((block) => Boolean(block)).flatMap((block) => block.decoded.transactions);
|
|
4812
|
-
return this.#resolveTransactions(transactions);
|
|
4813
|
-
};
|
|
4814
|
-
for (let i = 0; i < this.wantList.length; i += 50) {
|
|
4815
|
-
const batch = this.wantList.slice(i, i + 50);
|
|
4816
|
-
await getBatch(batch);
|
|
4817
|
-
}
|
|
4818
|
-
}
|
|
4819
4765
|
debug$1(`Resolving remote block: ${remoteBlockHash} @${remoteIndex} (differs from local state)`);
|
|
4820
4766
|
await this.resolveBlock(remoteBlockHash);
|
|
4821
4767
|
const blocksSynced = remoteIndex - localIndex;
|
|
@@ -5171,15 +5117,6 @@ const validateBlockEconomics = (block, calculatedFees, validatorFees = /* @__PUR
|
|
|
5171
5117
|
}
|
|
5172
5118
|
};
|
|
5173
5119
|
|
|
5174
|
-
const resolveTransactionReference = async (expectedHash, transactionData) => {
|
|
5175
|
-
const transaction = transactionData instanceof TransactionMessage ? transactionData : new TransactionMessage(transactionData);
|
|
5176
|
-
const actualHash = await transaction.hash();
|
|
5177
|
-
if (actualHash !== expectedHash) {
|
|
5178
|
-
throw new Error(`Transaction hash mismatch: expected ${expectedHash}, got ${actualHash}`);
|
|
5179
|
-
}
|
|
5180
|
-
return transaction;
|
|
5181
|
-
};
|
|
5182
|
-
|
|
5183
5120
|
const consensusSignableData = (validatorsAddress, type, message) => ({
|
|
5184
5121
|
from: String(message.from),
|
|
5185
5122
|
to: validatorsAddress,
|
|
@@ -6207,13 +6144,6 @@ class Chain extends VersionControl {
|
|
|
6207
6144
|
}
|
|
6208
6145
|
}
|
|
6209
6146
|
}
|
|
6210
|
-
if (this.wantList.length > 0) {
|
|
6211
|
-
const promises = await Promise.allSettled(this.wantList.map((hash) => peernet.get(hash, "block")));
|
|
6212
|
-
for (let i = promises.length - 1; i >= 0; i -= 1) {
|
|
6213
|
-
if (promises[i].status === "fulfilled") this.wantList.splice(i, 1);
|
|
6214
|
-
}
|
|
6215
|
-
if (this.wantList.length === 0) await this.triggerSync();
|
|
6216
|
-
}
|
|
6217
6147
|
try {
|
|
6218
6148
|
let stateInfo = await this.#makeRequest(peer, "stateInfo");
|
|
6219
6149
|
if (stateInfo instanceof Uint8Array) {
|