@leofcoin/chain 1.10.18 → 1.10.19
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.
|
@@ -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-DCbLvMKL.js';
|
|
2
2
|
import { f as fromBase58 } from './index-CvKt4UDE.js';
|
|
3
3
|
import './browser-crypto-CH0ua22L.js';
|
|
4
4
|
import './sha2-BKcEJzgd.js';
|
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
2
|
import { B as BlockMessage, L as LastBlockMessage, P as PROTOCOL_VERSION, R as REACHED_ONE_ZERO_ZERO, C as ConnectionMonitor, a as BWMessage, S as StateMessage } from './connection-monitor-D-krNiRH.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-
|
|
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-DCbLvMKL.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';
|
|
@@ -3233,7 +3233,8 @@ class ContractRegistry {
|
|
|
3233
3233
|
*/
|
|
3234
3234
|
async registerNameInNameService(name, hash, chain, signer) {
|
|
3235
3235
|
({
|
|
3236
|
-
from: await signer.address
|
|
3236
|
+
from: await signer.address,
|
|
3237
|
+
to: addresses.nameService});
|
|
3237
3238
|
}
|
|
3238
3239
|
/**
|
|
3239
3240
|
* Get a base contract by name
|
|
@@ -5260,6 +5261,73 @@ const assertHashFormatState = async (chainStore, stateStore) => {
|
|
|
5260
5261
|
}
|
|
5261
5262
|
};
|
|
5262
5263
|
|
|
5264
|
+
const CHAIN_ID_SCHEMA = "leofcoin:chain-identity:v1";
|
|
5265
|
+
const GENESIS_CONTRACT_NAMES = ["contractFactory", "nativeToken", "nameService", "validators"];
|
|
5266
|
+
const assertChainId = (value) => {
|
|
5267
|
+
if (typeof value !== "string" || !/^lfc:[0-9a-f]{64}$/.test(value))
|
|
5268
|
+
throw new Error("Invalid chain ID; expected lfc: followed by 64 lowercase hex characters");
|
|
5269
|
+
return value;
|
|
5270
|
+
};
|
|
5271
|
+
const createChainIdentity = async (network, contracts) => {
|
|
5272
|
+
if (typeof network !== "string" || !/^[a-z0-9][a-z0-9:-]{0,79}$/.test(network))
|
|
5273
|
+
throw new Error("Invalid genesis network namespace");
|
|
5274
|
+
const genesisContracts = {};
|
|
5275
|
+
for (const name of GENESIS_CONTRACT_NAMES) {
|
|
5276
|
+
const hash = contracts?.[name];
|
|
5277
|
+
if (typeof hash !== "string" || !/^[A-Z2-7]{32,128}$/.test(hash))
|
|
5278
|
+
throw new Error(`Invalid genesis contract hash: ${name}`);
|
|
5279
|
+
genesisContracts[name] = hash;
|
|
5280
|
+
}
|
|
5281
|
+
const bytes = new TextEncoder().encode(JSON.stringify({ schema: CHAIN_ID_SCHEMA, network, genesisContracts }));
|
|
5282
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes);
|
|
5283
|
+
const chainId = "lfc:" + [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
5284
|
+
return { schema: CHAIN_ID_SCHEMA, chainId, network, genesisContracts };
|
|
5285
|
+
};
|
|
5286
|
+
const verifyChainIdentity = async (value) => {
|
|
5287
|
+
const identity = value;
|
|
5288
|
+
if (!identity || identity.schema !== CHAIN_ID_SCHEMA)
|
|
5289
|
+
throw new Error("Unsupported chain identity response");
|
|
5290
|
+
const verified = await createChainIdentity(identity.network, identity.genesisContracts);
|
|
5291
|
+
if (verified.chainId !== assertChainId(identity.chainId))
|
|
5292
|
+
throw new Error("Chain ID does not match its genesis contracts");
|
|
5293
|
+
return verified;
|
|
5294
|
+
};
|
|
5295
|
+
const findChainPresence = async (chainId, peerIds, requestIdentity, timeoutMs = 3e3) => {
|
|
5296
|
+
assertChainId(chainId);
|
|
5297
|
+
const peers = [...new Set(peerIds)].slice(0, 16);
|
|
5298
|
+
const matches = [];
|
|
5299
|
+
let responded = 0;
|
|
5300
|
+
let unavailable = 0;
|
|
5301
|
+
await Promise.all(peers.map(async (peerId) => {
|
|
5302
|
+
let timer;
|
|
5303
|
+
try {
|
|
5304
|
+
const result = await Promise.race([
|
|
5305
|
+
Promise.resolve().then(() => requestIdentity(peerId)),
|
|
5306
|
+
new Promise((_, reject) => {
|
|
5307
|
+
timer = setTimeout(() => reject(new Error("Chain identity request timed out")), timeoutMs);
|
|
5308
|
+
})
|
|
5309
|
+
]);
|
|
5310
|
+
const identity = await verifyChainIdentity(result);
|
|
5311
|
+
responded++;
|
|
5312
|
+
if (identity.chainId === chainId)
|
|
5313
|
+
matches.push(peerId);
|
|
5314
|
+
} catch {
|
|
5315
|
+
unavailable++;
|
|
5316
|
+
} finally {
|
|
5317
|
+
clearTimeout(timer);
|
|
5318
|
+
}
|
|
5319
|
+
}));
|
|
5320
|
+
return {
|
|
5321
|
+
chainId,
|
|
5322
|
+
status: matches.length ? "found" : !peers.length || unavailable ? "unknown" : "not-observed",
|
|
5323
|
+
checkedPeers: peers.length,
|
|
5324
|
+
respondedPeers: responded,
|
|
5325
|
+
unavailablePeers: unavailable,
|
|
5326
|
+
matchingPeers: matches.sort(),
|
|
5327
|
+
scope: "reachable peers only; offline or undiscovered chains may still exist"
|
|
5328
|
+
};
|
|
5329
|
+
};
|
|
5330
|
+
|
|
5263
5331
|
const debug = createDebugger("leofcoin/chain");
|
|
5264
5332
|
class Chain extends VersionControl {
|
|
5265
5333
|
constructor(config) {
|
|
@@ -5527,6 +5595,32 @@ class Chain extends VersionControl {
|
|
|
5527
5595
|
get nativeToken() {
|
|
5528
5596
|
return addresses.nativeToken;
|
|
5529
5597
|
}
|
|
5598
|
+
/** Immutable bundled genesis identity, independent of the current chain tip. */
|
|
5599
|
+
getChainIdentity() {
|
|
5600
|
+
return createChainIdentity(globalThis.peernet?.network || "leofcoin:peach", addresses);
|
|
5601
|
+
}
|
|
5602
|
+
async findChain(chainId) {
|
|
5603
|
+
assertChainId(chainId);
|
|
5604
|
+
const local = await this.getChainIdentity();
|
|
5605
|
+
if (local.chainId === chainId) return {
|
|
5606
|
+
chainId,
|
|
5607
|
+
status: "found",
|
|
5608
|
+
foundViaLocalNode: true,
|
|
5609
|
+
checkedPeers: 0,
|
|
5610
|
+
respondedPeers: 0,
|
|
5611
|
+
unavailablePeers: 0,
|
|
5612
|
+
matchingPeers: [],
|
|
5613
|
+
scope: "local node; not proof of a globally available or finalized chain"
|
|
5614
|
+
};
|
|
5615
|
+
const peers = Object.entries(globalThis.peernet?.connections || {}).filter(([, peer]) => peer.connected && typeof peer.request === "function");
|
|
5616
|
+
return {
|
|
5617
|
+
...await findChainPresence(chainId, peers.map(([id]) => id), async (id) => {
|
|
5618
|
+
const peer = peers.find(([peerId]) => peerId === id)?.[1];
|
|
5619
|
+
return this.#makeRequest(peer, "chainIdentity");
|
|
5620
|
+
}),
|
|
5621
|
+
foundViaLocalNode: false
|
|
5622
|
+
};
|
|
5623
|
+
}
|
|
5530
5624
|
get validators() {
|
|
5531
5625
|
return [...this.#validators];
|
|
5532
5626
|
}
|
|
@@ -5821,6 +5915,10 @@ class Chain extends VersionControl {
|
|
|
5821
5915
|
});
|
|
5822
5916
|
await globalThis.peernet.addRequestHandler("transactionPool", this.#transactionPoolHandler.bind(this));
|
|
5823
5917
|
await globalThis.peernet.addRequestHandler("version", this.#versionHandler.bind(this));
|
|
5918
|
+
await globalThis.peernet.addRequestHandler(
|
|
5919
|
+
"chainIdentity",
|
|
5920
|
+
async () => new globalThis.peernet.protos["peernet-response"]({ response: await this.getChainIdentity() })
|
|
5921
|
+
);
|
|
5824
5922
|
await globalThis.peernet.addRequestHandler("stateInfo", async () => {
|
|
5825
5923
|
const lastblock = await this.lastBlock || { index: 0, hash: "0x0", previousHash: "0x0" };
|
|
5826
5924
|
const values = this.machine?.states?.info || {};
|
package/exports/chain.js
CHANGED
|
@@ -14,6 +14,7 @@ import { P as PROTOCOL_VERSION, R as REACHED_ONE_ZERO_ZERO } from './constants-D
|
|
|
14
14
|
import ConnectionMonitor from './connection-monitor.js';
|
|
15
15
|
import { q as quorumThreshold } from './quorum-S_qdgiAY.js';
|
|
16
16
|
import { assertHashFormatState } from './hash-format-state.js';
|
|
17
|
+
import { createChainIdentity, assertChainId, findChainPresence } from '@leofcoin/lib/chain-identity';
|
|
17
18
|
import '@leofcoin/networks';
|
|
18
19
|
|
|
19
20
|
const limit = 1800;
|
|
@@ -2477,6 +2478,32 @@ class Chain extends VersionControl {
|
|
|
2477
2478
|
get nativeToken() {
|
|
2478
2479
|
return addresses.nativeToken;
|
|
2479
2480
|
}
|
|
2481
|
+
/** Immutable bundled genesis identity, independent of the current chain tip. */
|
|
2482
|
+
getChainIdentity() {
|
|
2483
|
+
return createChainIdentity(globalThis.peernet?.network || "leofcoin:peach", addresses);
|
|
2484
|
+
}
|
|
2485
|
+
async findChain(chainId) {
|
|
2486
|
+
assertChainId(chainId);
|
|
2487
|
+
const local = await this.getChainIdentity();
|
|
2488
|
+
if (local.chainId === chainId) return {
|
|
2489
|
+
chainId,
|
|
2490
|
+
status: "found",
|
|
2491
|
+
foundViaLocalNode: true,
|
|
2492
|
+
checkedPeers: 0,
|
|
2493
|
+
respondedPeers: 0,
|
|
2494
|
+
unavailablePeers: 0,
|
|
2495
|
+
matchingPeers: [],
|
|
2496
|
+
scope: "local node; not proof of a globally available or finalized chain"
|
|
2497
|
+
};
|
|
2498
|
+
const peers = Object.entries(globalThis.peernet?.connections || {}).filter(([, peer]) => peer.connected && typeof peer.request === "function");
|
|
2499
|
+
return {
|
|
2500
|
+
...await findChainPresence(chainId, peers.map(([id]) => id), async (id) => {
|
|
2501
|
+
const peer = peers.find(([peerId]) => peerId === id)?.[1];
|
|
2502
|
+
return this.#makeRequest(peer, "chainIdentity");
|
|
2503
|
+
}),
|
|
2504
|
+
foundViaLocalNode: false
|
|
2505
|
+
};
|
|
2506
|
+
}
|
|
2480
2507
|
get validators() {
|
|
2481
2508
|
return [...this.#validators];
|
|
2482
2509
|
}
|
|
@@ -2771,6 +2798,10 @@ class Chain extends VersionControl {
|
|
|
2771
2798
|
});
|
|
2772
2799
|
await globalThis.peernet.addRequestHandler("transactionPool", this.#transactionPoolHandler.bind(this));
|
|
2773
2800
|
await globalThis.peernet.addRequestHandler("version", this.#versionHandler.bind(this));
|
|
2801
|
+
await globalThis.peernet.addRequestHandler(
|
|
2802
|
+
"chainIdentity",
|
|
2803
|
+
async () => new globalThis.peernet.protos["peernet-response"]({ response: await this.getChainIdentity() })
|
|
2804
|
+
);
|
|
2774
2805
|
await globalThis.peernet.addRequestHandler("stateInfo", async () => {
|
|
2775
2806
|
const lastblock = await this.lastBlock || { index: 0, hash: "0x0", previousHash: "0x0" };
|
|
2776
2807
|
const values = this.machine?.states?.info || {};
|