@parity/product-deploy 0.11.0 → 0.12.0-rc.1
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/bin/bulletin-bootstrap +23 -1
- package/dist/auth-config.js +3 -3
- package/dist/bug-report.js +4 -4
- package/dist/{chunk-JWMHCW74.js → chunk-2NF6QIDF.js} +1 -1
- package/dist/{chunk-53BU4X2R.js → chunk-52F2ETEG.js} +12 -2
- package/dist/{chunk-O4I37F5K.js → chunk-5BE5PQH6.js} +55 -12
- package/dist/{chunk-7RYEYWYO.js → chunk-BH7DJ5IW.js} +1 -1
- package/dist/{chunk-SES7CGNY.js → chunk-BXW5MBBY.js} +1 -1
- package/dist/{chunk-HLXRVFKL.js → chunk-FVPRBTHT.js} +38 -1
- package/dist/{chunk-TE2YKRYY.js → chunk-GGXK4DDN.js} +2 -2
- package/dist/{chunk-UUJFLJKY.js → chunk-OOGXTHVQ.js} +158 -61
- package/dist/{chunk-QDHLTSEO.js → chunk-PXEFWMJP.js} +2 -2
- package/dist/{chunk-7E33R3OQ.js → chunk-VIZ6GBQE.js} +1 -1
- package/dist/{chunk-HTZGBUZA.js → chunk-W2OSH4GD.js} +3 -3
- package/dist/{chunk-MRQPJLPS.js → chunk-XVQICFTB.js} +22 -1
- package/dist/chunk-probe.d.ts +43 -1
- package/dist/chunk-probe.js +11 -5
- package/dist/commands/login.js +11 -11
- package/dist/commands/logout.js +4 -4
- package/dist/commands/transfer.js +4 -4
- package/dist/commands/whoami.js +3 -3
- package/dist/deploy-actors.js +6 -6
- package/dist/deploy.d.ts +45 -1
- package/dist/deploy.js +17 -11
- package/dist/dotns.d.ts +33 -1
- package/dist/dotns.js +14 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +18 -12
- package/dist/manifest/publish.js +12 -12
- package/dist/memory-report.js +2 -2
- package/dist/merkle.js +11 -11
- package/dist/personhood/bootstrap.js +4 -4
- package/dist/personhood/people-client.js +4 -4
- package/dist/personhood/reprove.js +19 -2
- package/dist/pool.d.ts +11 -1
- package/dist/pool.js +9 -1
- package/dist/run-state.js +1 -1
- package/dist/sss-allowance-cache.js +4 -4
- package/dist/storage-signer.d.ts +28 -3
- package/dist/storage-signer.js +13 -11
- package/dist/telemetry.js +2 -2
- package/dist/version-check.js +3 -3
- package/package.json +1 -1
- package/tools/release-retry-wrapper.mjs +6 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
preflightSssAllowance
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-BH7DJ5IW.js";
|
|
4
4
|
import {
|
|
5
5
|
statementSigningAccount
|
|
6
6
|
} from "./chunk-GRPLHUYC.js";
|
|
@@ -31,16 +31,18 @@ import {
|
|
|
31
31
|
} from "./chunk-S7EM5VMW.js";
|
|
32
32
|
import {
|
|
33
33
|
setDeployContext
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-W2OSH4GD.js";
|
|
35
35
|
import {
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
getBestBlockNumber,
|
|
37
|
+
probeChunks,
|
|
38
|
+
probeFinalityGap
|
|
39
|
+
} from "./chunk-FVPRBTHT.js";
|
|
38
40
|
import {
|
|
39
41
|
packSection
|
|
40
42
|
} from "./chunk-C2TS5MER.js";
|
|
41
43
|
import {
|
|
42
44
|
resolveStorageSigner
|
|
43
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-PXEFWMJP.js";
|
|
44
46
|
import {
|
|
45
47
|
createSlotAccountSigner,
|
|
46
48
|
requestResourceAllocation
|
|
@@ -49,7 +51,7 @@ import {
|
|
|
49
51
|
STALE_SESSION_MESSAGE,
|
|
50
52
|
getPeopleChainEndpoints,
|
|
51
53
|
hasPersistedSession
|
|
52
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-2NF6QIDF.js";
|
|
53
55
|
import {
|
|
54
56
|
CLI_NAME
|
|
55
57
|
} from "./chunk-TSPERKUS.js";
|
|
@@ -62,7 +64,7 @@ import {
|
|
|
62
64
|
parseDomainName,
|
|
63
65
|
popStatusName,
|
|
64
66
|
verifyNonceAdvanced
|
|
65
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-5BE5PQH6.js";
|
|
66
68
|
import {
|
|
67
69
|
derivePoolAccounts,
|
|
68
70
|
detectTestnet,
|
|
@@ -70,7 +72,7 @@ import {
|
|
|
70
72
|
fetchPoolAuthorizations,
|
|
71
73
|
isAuthorizationSufficient,
|
|
72
74
|
selectAccount
|
|
73
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-XVQICFTB.js";
|
|
74
76
|
import {
|
|
75
77
|
VERSION,
|
|
76
78
|
captureWarning,
|
|
@@ -84,7 +86,7 @@ import {
|
|
|
84
86
|
truncateAddress,
|
|
85
87
|
withDeploySpan,
|
|
86
88
|
withSpan
|
|
87
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-52F2ETEG.js";
|
|
88
90
|
import {
|
|
89
91
|
DEFAULT_ENV_ID,
|
|
90
92
|
getPopSelfServeConfig,
|
|
@@ -339,27 +341,58 @@ async function waitForBulletinAuthorization(ss58, opts = {}) {
|
|
|
339
341
|
client.destroy();
|
|
340
342
|
}
|
|
341
343
|
}
|
|
342
|
-
async function
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
{
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
344
|
+
async function withTransientRetry(attempt, opts = {}) {
|
|
345
|
+
const { retries = 2, delayMs = 1e3 } = opts;
|
|
346
|
+
const debug = Boolean(process.env.DOT_DEBUG);
|
|
347
|
+
let lastErr;
|
|
348
|
+
for (let i = 0; i <= retries; i++) {
|
|
349
|
+
try {
|
|
350
|
+
return await attempt();
|
|
351
|
+
} catch (e) {
|
|
352
|
+
if (e instanceof BulletinSlotAuthError) throw e;
|
|
353
|
+
lastErr = e;
|
|
354
|
+
if (i < retries) {
|
|
355
|
+
if (debug) {
|
|
356
|
+
console.error(
|
|
357
|
+
`[slot-signer] transient error (attempt ${i + 1}/${retries + 1}): ${e instanceof Error ? e.message : String(e)}`
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
361
|
+
}
|
|
362
|
+
}
|
|
358
363
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
return
|
|
364
|
+
throw lastErr;
|
|
365
|
+
}
|
|
366
|
+
async function getSlotSignerProvider(signer, ss58) {
|
|
367
|
+
return withTransientRetry(async () => {
|
|
368
|
+
const primary = BULLETIN_ENDPOINTS[0];
|
|
369
|
+
console.log(` Connecting to Bulletin (slot signer): ${primary}`);
|
|
370
|
+
const client = createPolkadotClient(getWsProvider(
|
|
371
|
+
BULLETIN_ENDPOINTS,
|
|
372
|
+
{ heartbeatTimeout: WS_HEARTBEAT_TIMEOUT_MS, onStatusChanged: makeBulletinStatusHandler(primary) }
|
|
373
|
+
));
|
|
374
|
+
const unsafeApi = client.getUnsafeApi();
|
|
375
|
+
let auth;
|
|
376
|
+
let currentBlock;
|
|
377
|
+
try {
|
|
378
|
+
[auth, currentBlock] = await Promise.all([
|
|
379
|
+
unsafeApi.query.TransactionStorage.Authorizations.getValue(Enum("Account", ss58)),
|
|
380
|
+
client.getFinalizedBlock()
|
|
381
|
+
]);
|
|
382
|
+
} catch (e) {
|
|
383
|
+
client.destroy();
|
|
384
|
+
throw e;
|
|
385
|
+
}
|
|
386
|
+
const result = isBulletinAuthActive(auth, currentBlock.number);
|
|
387
|
+
if (!result.active) {
|
|
388
|
+
client.destroy();
|
|
389
|
+
throw new BulletinSlotAuthError(result.reason, ss58, result.expiration);
|
|
390
|
+
}
|
|
391
|
+
console.log(` Using slot signer: ${ss58} (authorized until block ${result.expiration})`);
|
|
392
|
+
setDeployAttribute("deploy.signer.mode", "slot");
|
|
393
|
+
setDeployAttribute("deploy.signer.address", truncateAddress(ss58));
|
|
394
|
+
return { client, unsafeApi, signer, ss58 };
|
|
395
|
+
});
|
|
363
396
|
}
|
|
364
397
|
|
|
365
398
|
// src/deploy.ts
|
|
@@ -400,15 +433,28 @@ var MAX_RECONNECTIONS = parseInt(process.env.BULLETIN_MAX_RECONNECTIONS ?? "3",
|
|
|
400
433
|
var CHUNK_TIMEOUT_MS = parseInt(process.env.BULLETIN_CHUNK_TIMEOUT_MS ?? "180000", 10);
|
|
401
434
|
var CHUNK_MORTALITY_PERIOD = (() => {
|
|
402
435
|
const v = parseInt(process.env.BULLETIN_CHUNK_MORTALITY_PERIOD ?? "", 10);
|
|
403
|
-
return Number.isFinite(v) && v > 0 ? v :
|
|
436
|
+
return Number.isFinite(v) && v > 0 ? v : 64;
|
|
404
437
|
})();
|
|
438
|
+
var CHUNK_LIVENESS_MAX_WAIT_MS = parseInt(process.env.BULLETIN_CHUNK_LIVENESS_MAX_WAIT_MS ?? "60000", 10);
|
|
439
|
+
var CHUNK_LIVENESS_POLL_MS = 5e3;
|
|
405
440
|
var RETRY_BASE_DELAY_MS = 2e3;
|
|
406
441
|
var RETRY_MAX_DELAY_MS = 15e3;
|
|
407
442
|
var WS_HEARTBEAT_TIMEOUT_MS = 3e5;
|
|
408
|
-
var GRANDPA_NATURAL_WAIT_MS = parseInt(process.env.BULLETIN_GRANDPA_NATURAL_WAIT_MS ?? "
|
|
443
|
+
var GRANDPA_NATURAL_WAIT_MS = parseInt(process.env.BULLETIN_GRANDPA_NATURAL_WAIT_MS ?? "210000", 10);
|
|
409
444
|
var GRANDPA_REUPLOAD_POLL_MS = 5e3;
|
|
410
|
-
var GRANDPA_REUPLOAD_TIMEOUT_MS =
|
|
445
|
+
var GRANDPA_REUPLOAD_TIMEOUT_MS = parseInt(process.env.BULLETIN_GRANDPA_REUPLOAD_TIMEOUT_MS ?? "120000", 10);
|
|
411
446
|
var GRANDPA_REUPLOAD_MAX_ROUNDS = 3;
|
|
447
|
+
var GRANDPA_LAGGING_WAIT_MS = parseInt(process.env.BULLETIN_GRANDPA_LAGGING_WAIT_MS ?? "90000", 10);
|
|
448
|
+
async function pollUntilFinalized(cids, timeoutMs, client) {
|
|
449
|
+
const start = Date.now();
|
|
450
|
+
while (Date.now() - start < timeoutMs && cids.size > 0) {
|
|
451
|
+
await new Promise((r) => setTimeout(r, GRANDPA_REUPLOAD_POLL_MS));
|
|
452
|
+
const poll = await probeChunks([...cids], { client, atFinalized: true });
|
|
453
|
+
for (const r of poll) {
|
|
454
|
+
if (r.present === true) cids.delete(r.cid);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
412
458
|
var RETRY_BUDGET_MAX_EVENTS = parseInt(process.env.BULLETIN_RETRY_BUDGET_MAX ?? "5", 10);
|
|
413
459
|
var RETRY_BUDGET_WINDOW_MS = parseInt(process.env.BULLETIN_RETRY_BUDGET_WINDOW_MS ?? "30000", 10);
|
|
414
460
|
function retryBudgetExhausted(history, maxEvents, windowMs, now = Date.now()) {
|
|
@@ -621,6 +667,12 @@ function formatTransferModeStorageSignerLine(workerAddress) {
|
|
|
621
667
|
function formatTransferModeDotnsLine(alreadyOwned, dotName, recipient) {
|
|
622
668
|
return alreadyOwned ? ` DotNS: you already own ${dotName} \u2014 content update needs your phone signature (no transfer)` : ` DotNS: will register ${dotName} and transfer it to your account ${recipient}`;
|
|
623
669
|
}
|
|
670
|
+
function describeSlotFallbackReason(e) {
|
|
671
|
+
if (e instanceof BulletinSlotAuthError) {
|
|
672
|
+
return e.reason === "expired" && e.expiration != null ? `expired at block ${e.expiration}` : "no on-chain authorization found";
|
|
673
|
+
}
|
|
674
|
+
return e instanceof Error ? e.message : String(e);
|
|
675
|
+
}
|
|
624
676
|
function selectStorageReconnect(options) {
|
|
625
677
|
if (options.storageSigner && options.storageSignerAddress) {
|
|
626
678
|
let useSlot = true;
|
|
@@ -631,12 +683,8 @@ function selectStorageReconnect(options) {
|
|
|
631
683
|
} catch (e) {
|
|
632
684
|
useSlot = false;
|
|
633
685
|
setDeployAttribute("deploy.signer.mode", "pool-fallback");
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
reason = e.reason === "expired" && e.expiration != null ? `expired at block ${e.expiration}` : "no on-chain authorization found";
|
|
637
|
-
} else {
|
|
638
|
-
reason = e instanceof Error ? e.message : String(e);
|
|
639
|
-
}
|
|
686
|
+
const reason = describeSlotFallbackReason(e);
|
|
687
|
+
setDeployAttribute("deploy.signer.fallback_reason", reason);
|
|
640
688
|
console.warn(
|
|
641
689
|
`\u26A0 Bulletin allowance slot not usable: ${reason}
|
|
642
690
|
Falling back to the shared pool account for storage (fine on testnet).
|
|
@@ -713,6 +761,26 @@ function watchTransaction(tx, signer, txOpts, onSuccess, { label = "transaction"
|
|
|
713
761
|
});
|
|
714
762
|
});
|
|
715
763
|
}
|
|
764
|
+
function reconcileTimedOutChunk(opts) {
|
|
765
|
+
const { originalNonce, currentNonce, nonceHeuristicValid, cidPresentAtBest } = opts;
|
|
766
|
+
if (cidPresentAtBest === true) return true;
|
|
767
|
+
if (nonceHeuristicValid && originalNonce !== void 0 && originalNonce < currentNonce) return true;
|
|
768
|
+
return false;
|
|
769
|
+
}
|
|
770
|
+
async function waitForChainLiveness(client, lastHeight, timeoutMs, pollMs = CHUNK_LIVENESS_POLL_MS) {
|
|
771
|
+
if (lastHeight == null) return getBestBlockNumber(client);
|
|
772
|
+
const deadline = Date.now() + timeoutMs;
|
|
773
|
+
let height = lastHeight;
|
|
774
|
+
while (Date.now() < deadline) {
|
|
775
|
+
const h = await getBestBlockNumber(client);
|
|
776
|
+
if (h == null) return height;
|
|
777
|
+
height = h;
|
|
778
|
+
if (height > lastHeight) return height;
|
|
779
|
+
await new Promise((r) => setTimeout(r, pollMs));
|
|
780
|
+
}
|
|
781
|
+
return height;
|
|
782
|
+
}
|
|
783
|
+
var __waitForChainLivenessForTest = waitForChainLiveness;
|
|
716
784
|
async function storeChunk(unsafeApi, signer, chunkBytes, nonce, ss58, opts = {}) {
|
|
717
785
|
const cid = createCID(chunkBytes, CID_CONFIG.codec, CID_CONFIG.hashCode);
|
|
718
786
|
const tx = unsafeApi.tx.TransactionStorage.store_with_cid_config({ cid: { codec: BigInt(CID_CONFIG.codec), hashing: toHashingEnum(CID_CONFIG.hashCode) }, data: chunkBytes });
|
|
@@ -1062,8 +1130,14 @@ async function storeChunkedContent(chunks, { client: existingClient, unsafeApi:
|
|
|
1062
1130
|
try {
|
|
1063
1131
|
const currentNonce = await _fetchNonce(BULLETIN_ENDPOINTS, ss58);
|
|
1064
1132
|
const originalNonce = assignedNonces.get(fail.index);
|
|
1065
|
-
|
|
1066
|
-
|
|
1133
|
+
let cidPresentAtBest = null;
|
|
1134
|
+
try {
|
|
1135
|
+
const [probe] = await probeChunks([failCid.toString()], { client });
|
|
1136
|
+
cidPresentAtBest = probe.present === true ? true : null;
|
|
1137
|
+
} catch {
|
|
1138
|
+
}
|
|
1139
|
+
if (reconcileTimedOutChunk({ originalNonce, currentNonce, nonceHeuristicValid: !perRetryChanged, cidPresentAtBest })) {
|
|
1140
|
+
console.log(` Chunk ${fail.index}: reconcile found it already included (nonce ${originalNonce}\u2192${currentNonce}${cidPresentAtBest ? ", CID present at best-block" : ""}) \u2014 skipping resubmit`);
|
|
1067
1141
|
stored[fail.index] = { cid: createCID(fail.chunkData, CID_CONFIG.codec, 18), len: fail.chunkData.length, viaFallback: true };
|
|
1068
1142
|
nonceAdvanceIndices.add(fail.index);
|
|
1069
1143
|
assignedNonces.delete(fail.index);
|
|
@@ -1071,6 +1145,11 @@ async function storeChunkedContent(chunks, { client: existingClient, unsafeApi:
|
|
|
1071
1145
|
retried = true;
|
|
1072
1146
|
break;
|
|
1073
1147
|
}
|
|
1148
|
+
const heightBefore = await getBestBlockNumber(client);
|
|
1149
|
+
const heightAfter = await waitForChainLiveness(client, heightBefore, CHUNK_LIVENESS_MAX_WAIT_MS);
|
|
1150
|
+
if (heightBefore != null && heightAfter != null && heightAfter <= heightBefore) {
|
|
1151
|
+
console.log(` Chunk ${fail.index}: chain still frozen at block ${heightBefore} after ${(CHUNK_LIVENESS_MAX_WAIT_MS / 1e3).toFixed(0)}s wait \u2014 resubmitting anyway`);
|
|
1152
|
+
}
|
|
1074
1153
|
const retryNonce = originalNonce ?? currentNonce;
|
|
1075
1154
|
const result2 = await storeChunk(unsafeApi, signer, fail.chunkData, retryNonce, ss58, { fetchNonce: fetchNonceOverride });
|
|
1076
1155
|
stored[fail.index] = result2;
|
|
@@ -1662,23 +1741,27 @@ async function storeDirectoryV2(directoryPath, opts = {}) {
|
|
|
1662
1741
|
let missingCids = new Set(finalityResults.filter((r) => r.present === false).map((r) => r.cid));
|
|
1663
1742
|
setDeployAttribute("deploy.probe.finality_miss_count", missingCids.size);
|
|
1664
1743
|
let reuploadCount = 0;
|
|
1744
|
+
let laggingFinalityCount = 0;
|
|
1665
1745
|
if (missingCids.size === 0) {
|
|
1666
1746
|
console.log(` \u2713 All ${grandpaCids.length} chunks finalised`);
|
|
1667
1747
|
} else {
|
|
1668
1748
|
console.log(` ${missingCids.size} chunks not yet finalised \u2014 waiting up to ${GRANDPA_NATURAL_WAIT_MS / 1e3}s for natural finalisation`);
|
|
1669
1749
|
for (const cid of missingCids) console.log(` ${cid.slice(0, 20)}\u2026`);
|
|
1670
1750
|
const waitStart = Date.now();
|
|
1671
|
-
|
|
1672
|
-
await new Promise((r) => setTimeout(r, GRANDPA_REUPLOAD_POLL_MS));
|
|
1673
|
-
const poll = await probeChunks([...missingCids], { client: phaseALiveProvider.client, atFinalized: true });
|
|
1674
|
-
for (const r of poll) {
|
|
1675
|
-
if (r.present === true) missingCids.delete(r.cid);
|
|
1676
|
-
}
|
|
1677
|
-
}
|
|
1751
|
+
await pollUntilFinalized(missingCids, GRANDPA_NATURAL_WAIT_MS, phaseALiveProvider.client);
|
|
1678
1752
|
if (missingCids.size === 0) {
|
|
1679
1753
|
const elapsed = Math.round((Date.now() - waitStart) / 1e3);
|
|
1680
1754
|
console.log(` \u2713 All ${grandpaCids.length} chunks finalised (waited ${elapsed}s)`);
|
|
1681
1755
|
} else {
|
|
1756
|
+
const stillMissing = [...missingCids];
|
|
1757
|
+
const { reallyMissing, lagging } = await probeFinalityGap(stillMissing, { client: phaseALiveProvider.client });
|
|
1758
|
+
const laggingCids = new Set(lagging);
|
|
1759
|
+
laggingFinalityCount = laggingCids.size;
|
|
1760
|
+
missingCids = new Set(reallyMissing);
|
|
1761
|
+
setDeployAttribute("deploy.probe.finality_lagging_count", laggingFinalityCount);
|
|
1762
|
+
if (laggingCids.size > 0) {
|
|
1763
|
+
console.log(` ${laggingCids.size} chunk(s) present in best-block but finality-lagging \u2014 will NOT re-upload, waiting for GRANDPA (bounded)`);
|
|
1764
|
+
}
|
|
1682
1765
|
const rootHashCode = 18;
|
|
1683
1766
|
const rootChunkLinks = phaseB.chunks.map((c) => ({
|
|
1684
1767
|
cid: createCID(c, CID_CONFIG.codec, rootHashCode),
|
|
@@ -1737,14 +1820,7 @@ async function storeDirectoryV2(directoryPath, opts = {}) {
|
|
|
1737
1820
|
}
|
|
1738
1821
|
throw e;
|
|
1739
1822
|
}
|
|
1740
|
-
|
|
1741
|
-
while (Date.now() - reuploadStart < GRANDPA_REUPLOAD_TIMEOUT_MS && missingCids.size > 0) {
|
|
1742
|
-
await new Promise((r) => setTimeout(r, GRANDPA_REUPLOAD_POLL_MS));
|
|
1743
|
-
const poll = await probeChunks([...missingCids], { client: phaseALiveProvider.client, atFinalized: true });
|
|
1744
|
-
for (const r of poll) {
|
|
1745
|
-
if (r.present === true) missingCids.delete(r.cid);
|
|
1746
|
-
}
|
|
1747
|
-
}
|
|
1823
|
+
await pollUntilFinalized(missingCids, GRANDPA_REUPLOAD_TIMEOUT_MS, phaseALiveProvider.client);
|
|
1748
1824
|
}
|
|
1749
1825
|
if (missingCids.size > 0) {
|
|
1750
1826
|
const stuck = [...missingCids][0];
|
|
@@ -1752,7 +1828,21 @@ async function storeDirectoryV2(directoryPath, opts = {}) {
|
|
|
1752
1828
|
`Deploy verification failed: ${missingCids.size} chunk(s) not finalised after ${GRANDPA_REUPLOAD_MAX_ROUNDS} re-upload round(s) (first: ${stuck.slice(0, 20)}\u2026). The chain may have dropped chunks due to a persistent fork. Re-run deploy.`
|
|
1753
1829
|
);
|
|
1754
1830
|
}
|
|
1755
|
-
|
|
1831
|
+
if (reuploadCount > 0) {
|
|
1832
|
+
console.log(` \u2713 All ${grandpaCids.length - laggingFinalityCount} chunks finalised after re-upload`);
|
|
1833
|
+
} else {
|
|
1834
|
+
console.log(` \u2713 No chunks genuinely missing from best-block \u2014 skipped re-upload entirely`);
|
|
1835
|
+
}
|
|
1836
|
+
if (laggingCids.size > 0) {
|
|
1837
|
+
await pollUntilFinalized(laggingCids, GRANDPA_LAGGING_WAIT_MS, phaseALiveProvider.client);
|
|
1838
|
+
if (laggingCids.size === 0) {
|
|
1839
|
+
console.log(` \u2713 finality-lagging chunk(s) caught up`);
|
|
1840
|
+
} else {
|
|
1841
|
+
console.warn(
|
|
1842
|
+
` \u26A0 ${laggingCids.size} chunk(s) still not finalised after extended wait, but confirmed present in best-block \u2014 deploy succeeds; finality pending asynchronously`
|
|
1843
|
+
);
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1756
1846
|
}
|
|
1757
1847
|
}
|
|
1758
1848
|
setDeployAttribute("deploy.probe.finality_miss_reupload_count", reuploadCount);
|
|
@@ -1833,11 +1923,14 @@ async function storeDirectoryV2(directoryPath, opts = {}) {
|
|
|
1833
1923
|
console.log(` Final root check: ${storageCid}`);
|
|
1834
1924
|
const rootProbe = await probeChunks([storageCid], { client: phaseALiveProvider.client, atFinalized: true });
|
|
1835
1925
|
if (rootProbe[0]?.present === false) {
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1926
|
+
const { reallyMissing } = await probeFinalityGap([storageCid], { client: phaseALiveProvider.client });
|
|
1927
|
+
if (reallyMissing.length > 0) {
|
|
1928
|
+
throw new Error(
|
|
1929
|
+
`Deploy verification failed: DAG-PB root ${storageCid.slice(0, 20)}\u2026 not finalised and not present in best-block. The chain may have evicted the root extrinsic. Re-run deploy.`
|
|
1930
|
+
);
|
|
1931
|
+
}
|
|
1932
|
+
console.log(` Root confirmed present in best-block (finality-lagging, #1049) \u2014 treating as success.`);
|
|
1933
|
+
} else if (rootProbe[0]?.present === true) {
|
|
1841
1934
|
console.log(` \u2713 Root finalised on chain`);
|
|
1842
1935
|
} else {
|
|
1843
1936
|
console.log(` Root re-check inconclusive (RPC error) \u2014 GRANDPA probe above already verified; continuing.`);
|
|
@@ -3008,6 +3101,7 @@ export {
|
|
|
3008
3101
|
isBulletinAuthActive,
|
|
3009
3102
|
pollUntilBulletinAuthorized,
|
|
3010
3103
|
waitForBulletinAuthorization,
|
|
3104
|
+
withTransientRetry,
|
|
3011
3105
|
getSlotSignerProvider,
|
|
3012
3106
|
friendlyChainError,
|
|
3013
3107
|
DEFAULT_BULLETIN_RPC,
|
|
@@ -3039,6 +3133,9 @@ export {
|
|
|
3039
3133
|
formatStorageSignerLine,
|
|
3040
3134
|
formatTransferModeStorageSignerLine,
|
|
3041
3135
|
formatTransferModeDotnsLine,
|
|
3136
|
+
describeSlotFallbackReason,
|
|
3137
|
+
reconcileTimedOutChunk,
|
|
3138
|
+
__waitForChainLivenessForTest,
|
|
3042
3139
|
storeFile,
|
|
3043
3140
|
__assignDenseNoncesForTest,
|
|
3044
3141
|
storeChunkedContent,
|
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
} from "./chunk-5FLTDWWP.js";
|
|
5
5
|
import {
|
|
6
6
|
DOT_PRODUCT_ID
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2NF6QIDF.js";
|
|
8
8
|
import {
|
|
9
9
|
DEFAULT_MNEMONIC
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-5BE5PQH6.js";
|
|
11
11
|
|
|
12
12
|
// src/deploy-actors.ts
|
|
13
13
|
var DEFAULT_WORKER_SURI = DEFAULT_MNEMONIC;
|
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
classifyErrorArea,
|
|
3
3
|
isInteractive,
|
|
4
4
|
promptYesNo
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-VIZ6GBQE.js";
|
|
6
6
|
import {
|
|
7
7
|
VERSION,
|
|
8
8
|
getCurrentSentryTraceId,
|
|
9
9
|
resolveIssueRepoSlug
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-52F2ETEG.js";
|
|
11
11
|
import {
|
|
12
12
|
package_default
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-BXW5MBBY.js";
|
|
14
14
|
|
|
15
15
|
// src/bug-report.ts
|
|
16
16
|
import { execSync, execFileSync } from "child_process";
|
|
@@ -37,6 +37,15 @@ function isAuthorizationSufficient(auth, currentBlock) {
|
|
|
37
37
|
function accountsNeedingAuthorization(auths, currentBlock) {
|
|
38
38
|
return auths.filter((a) => !isAuthorizationSufficient(a, currentBlock));
|
|
39
39
|
}
|
|
40
|
+
var BULLETIN_BLOCK_TIME_SECS = 6;
|
|
41
|
+
var BULLETIN_BLOCKS_PER_DAY = Math.floor(86400 / BULLETIN_BLOCK_TIME_SECS);
|
|
42
|
+
function accountsNeedingReauthorization(auths, currentBlock, bufferBlocks = BULLETIN_BLOCKS_PER_DAY) {
|
|
43
|
+
const deadline = currentBlock + bufferBlocks;
|
|
44
|
+
return auths.filter((a) => !isAuthorizationSufficient(a, deadline));
|
|
45
|
+
}
|
|
46
|
+
function isAutoReauthorizeAllowed(env) {
|
|
47
|
+
return env?.network !== "mainnet" && env?.bulletinAutoAuthorize === true;
|
|
48
|
+
}
|
|
40
49
|
function selectAccount(authorizations, random = Math.random, pinnedIndex) {
|
|
41
50
|
if (pinnedIndex != null) {
|
|
42
51
|
const pinned = authorizations.find((a) => a.index === pinnedIndex);
|
|
@@ -164,13 +173,21 @@ async function bootstrapPool(bulletinRpc, poolSize = 10, mnemonic, opts = {}) {
|
|
|
164
173
|
printAuthStatus(a, currentBlock);
|
|
165
174
|
}
|
|
166
175
|
console.log("");
|
|
167
|
-
const
|
|
176
|
+
const reauthBufferBlocks = opts.reauthBufferBlocks ?? 0;
|
|
177
|
+
const needsAuth = accountsNeedingReauthorization(auths, currentBlock, reauthBufferBlocks);
|
|
168
178
|
if (needsAuth.length === 0) {
|
|
169
179
|
console.log("All pool accounts are authorized. Nothing to do.");
|
|
170
180
|
return;
|
|
171
181
|
}
|
|
172
182
|
console.log(`${needsAuth.length} account(s) need authorization.
|
|
173
183
|
`);
|
|
184
|
+
if (reauthBufferBlocks > 0 && !opts.allowAutoReauthorize) {
|
|
185
|
+
const details = needsAuth.map((a) => ` [${a.index}] ${a.address} \u2014 expires @${a.expiration} (current block ${currentBlock})`).join("\n");
|
|
186
|
+
throw new Error(
|
|
187
|
+
`Auto-reauthorize is testnet-only (see isAutoReauthorizeAllowed / environments.json bulletinAutoAuthorize) and this call was not cleared to write. ${needsAuth.length} account(s) need reauthorization within the ${reauthBufferBlocks}-block buffer:
|
|
188
|
+
${details}`
|
|
189
|
+
);
|
|
190
|
+
}
|
|
174
191
|
let authorizerSigner;
|
|
175
192
|
const keyring = new Keyring({ type: "sr25519" });
|
|
176
193
|
if (opts.authorizerMnemonic) {
|
|
@@ -228,6 +245,10 @@ export {
|
|
|
228
245
|
derivePoolAccounts,
|
|
229
246
|
isAuthorizationSufficient,
|
|
230
247
|
accountsNeedingAuthorization,
|
|
248
|
+
BULLETIN_BLOCK_TIME_SECS,
|
|
249
|
+
BULLETIN_BLOCKS_PER_DAY,
|
|
250
|
+
accountsNeedingReauthorization,
|
|
251
|
+
isAutoReauthorizeAllowed,
|
|
231
252
|
selectAccount,
|
|
232
253
|
fetchPoolAuthorizations,
|
|
233
254
|
isTestnetSpecName,
|
package/dist/chunk-probe.d.ts
CHANGED
|
@@ -29,9 +29,51 @@ declare function _decodeStorageValue(hex: string | null | undefined): {
|
|
|
29
29
|
index: number;
|
|
30
30
|
} | null;
|
|
31
31
|
declare function probeChunks(cids: string[], options: ChainProbeOptions): Promise<ChunkProbeResult[]>;
|
|
32
|
+
/**
|
|
33
|
+
* Splits cids that are missing at finalised head into two buckets, using a
|
|
34
|
+
* best-block probe result for each cid:
|
|
35
|
+
* - `lagging`: present at best-block. GRANDPA just hasn't caught up yet
|
|
36
|
+
* (#1049) — these were never lost and must NEVER be re-uploaded.
|
|
37
|
+
* - `reallyMissing`: absent at best-block too (or the best-block probe
|
|
38
|
+
* itself failed, `present === null`) — genuinely dropped, or we
|
|
39
|
+
* couldn't determine presence at all. Either way, re-upload is the
|
|
40
|
+
* safe default: treating an indeterminate result as "lagging" risks
|
|
41
|
+
* silently skipping a chunk that's actually gone.
|
|
42
|
+
*
|
|
43
|
+
* Pure function — no chain I/O — so it's directly unit-testable against a
|
|
44
|
+
* mocked ChunkProbeResult array without a client.
|
|
45
|
+
*/
|
|
46
|
+
declare function classifyFinalityGap(missingAtFinalized: string[], bestBlockResults: ChunkProbeResult[]): {
|
|
47
|
+
reallyMissing: string[];
|
|
48
|
+
lagging: string[];
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Composite, chain-touching version of classifyFinalityGap (#1049): probes
|
|
52
|
+
* `missingAtFinalized` at best-block, retries once on an indeterminate
|
|
53
|
+
* result (present === null), then classifies. Any caller that finds cids
|
|
54
|
+
* missing at finalised head should route through this — not re-implement
|
|
55
|
+
* the probe/retry/classify sequence inline — so the "finalised-head absence
|
|
56
|
+
* is not proof of loss" policy stays consistent everywhere it's checked
|
|
57
|
+
* (the GRANDPA finality-check phase and the pre-setContenthash root
|
|
58
|
+
* re-check both use it).
|
|
59
|
+
*/
|
|
60
|
+
declare function probeFinalityGap(missingAtFinalized: string[], options: ChainProbeOptions): Promise<{
|
|
61
|
+
reallyMissing: string[];
|
|
62
|
+
lagging: string[];
|
|
63
|
+
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Best (non-finalised) block height, via `chain_getHeader`. Used by the
|
|
66
|
+
* initial chunk-upload retry loop (#1051) to detect a frozen chain — no new
|
|
67
|
+
* blocks since the last check — so it can wait instead of resubmitting into
|
|
68
|
+
* a stall (which just manufactures same-nonce collisions once the chain
|
|
69
|
+
* resumes). Returns `null` on any RPC failure or malformed response; callers
|
|
70
|
+
* must treat `null` as "can't tell" and fail open (proceed as if live)
|
|
71
|
+
* rather than blocking forever on a single bad peer.
|
|
72
|
+
*/
|
|
73
|
+
declare function getBestBlockNumber(client: any): Promise<number | null>;
|
|
32
74
|
/** Reset session-level caches. Used in tests only. */
|
|
33
75
|
declare function _resetProbeSession(): void;
|
|
34
76
|
/** Pre-set metadataChecked so tests don't need a real metadata RPC mock. Used in tests only. */
|
|
35
77
|
declare function _bypassMetadataCheckForTest(): void;
|
|
36
78
|
|
|
37
|
-
export { ChainProbeCrossValidationError, ChainProbeMetadataError, type ChainProbeOptions, type ChunkProbeFailureReason, type ChunkProbeResult, _bypassMetadataCheckForTest, _decodeStorageValue, _resetProbeSession, probeChunks };
|
|
79
|
+
export { ChainProbeCrossValidationError, ChainProbeMetadataError, type ChainProbeOptions, type ChunkProbeFailureReason, type ChunkProbeResult, _bypassMetadataCheckForTest, _decodeStorageValue, _resetProbeSession, classifyFinalityGap, getBestBlockNumber, probeChunks, probeFinalityGap };
|
package/dist/chunk-probe.js
CHANGED
|
@@ -4,15 +4,21 @@ import {
|
|
|
4
4
|
_bypassMetadataCheckForTest,
|
|
5
5
|
_decodeStorageValue,
|
|
6
6
|
_resetProbeSession,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
classifyFinalityGap,
|
|
8
|
+
getBestBlockNumber,
|
|
9
|
+
probeChunks,
|
|
10
|
+
probeFinalityGap
|
|
11
|
+
} from "./chunk-FVPRBTHT.js";
|
|
12
|
+
import "./chunk-52F2ETEG.js";
|
|
13
|
+
import "./chunk-BXW5MBBY.js";
|
|
11
14
|
export {
|
|
12
15
|
ChainProbeCrossValidationError,
|
|
13
16
|
ChainProbeMetadataError,
|
|
14
17
|
_bypassMetadataCheckForTest,
|
|
15
18
|
_decodeStorageValue,
|
|
16
19
|
_resetProbeSession,
|
|
17
|
-
|
|
20
|
+
classifyFinalityGap,
|
|
21
|
+
getBestBlockNumber,
|
|
22
|
+
probeChunks,
|
|
23
|
+
probeFinalityGap
|
|
18
24
|
};
|
package/dist/commands/login.js
CHANGED
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
} from "../chunk-J7CYVTAW.js";
|
|
4
4
|
import {
|
|
5
5
|
waitForBulletinAuthorization
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-OOGXTHVQ.js";
|
|
7
7
|
import {
|
|
8
8
|
preflightSssAllowance
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-BH7DJ5IW.js";
|
|
10
10
|
import {
|
|
11
11
|
statementSigningAccount
|
|
12
12
|
} from "../chunk-GRPLHUYC.js";
|
|
@@ -15,11 +15,11 @@ import "../chunk-IW3X2MJF.js";
|
|
|
15
15
|
import "../chunk-KOSF5FDO.js";
|
|
16
16
|
import "../chunk-J3NIXHZZ.js";
|
|
17
17
|
import "../chunk-S7EM5VMW.js";
|
|
18
|
-
import "../chunk-
|
|
19
|
-
import "../chunk-
|
|
20
|
-
import "../chunk-
|
|
18
|
+
import "../chunk-W2OSH4GD.js";
|
|
19
|
+
import "../chunk-VIZ6GBQE.js";
|
|
20
|
+
import "../chunk-FVPRBTHT.js";
|
|
21
21
|
import "../chunk-C2TS5MER.js";
|
|
22
|
-
import "../chunk-
|
|
22
|
+
import "../chunk-PXEFWMJP.js";
|
|
23
23
|
import "../chunk-JQKKMUCT.js";
|
|
24
24
|
import {
|
|
25
25
|
BULLETIN_RESOURCE,
|
|
@@ -36,15 +36,15 @@ import {
|
|
|
36
36
|
getAuthClient,
|
|
37
37
|
getPeopleChainEndpoints,
|
|
38
38
|
resolveBulletinEndpoints
|
|
39
|
-
} from "../chunk-
|
|
39
|
+
} from "../chunk-2NF6QIDF.js";
|
|
40
40
|
import {
|
|
41
41
|
CLI_NAME
|
|
42
42
|
} from "../chunk-TSPERKUS.js";
|
|
43
|
-
import "../chunk-
|
|
43
|
+
import "../chunk-5BE5PQH6.js";
|
|
44
44
|
import "../chunk-SI2ZUOYD.js";
|
|
45
|
-
import "../chunk-
|
|
46
|
-
import "../chunk-
|
|
47
|
-
import "../chunk-
|
|
45
|
+
import "../chunk-XVQICFTB.js";
|
|
46
|
+
import "../chunk-52F2ETEG.js";
|
|
47
|
+
import "../chunk-BXW5MBBY.js";
|
|
48
48
|
import {
|
|
49
49
|
loadEnvironments
|
|
50
50
|
} from "../chunk-JSYQ3JQS.js";
|
package/dist/commands/logout.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
clearSssAllowanceCache
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-BH7DJ5IW.js";
|
|
4
4
|
import "../chunk-GRPLHUYC.js";
|
|
5
5
|
import "../chunk-JQKKMUCT.js";
|
|
6
6
|
import "../chunk-5FLTDWWP.js";
|
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
} from "../chunk-RIRDBSBG.js";
|
|
10
10
|
import {
|
|
11
11
|
getAuthClient
|
|
12
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-2NF6QIDF.js";
|
|
13
13
|
import "../chunk-TSPERKUS.js";
|
|
14
|
-
import "../chunk-
|
|
15
|
-
import "../chunk-
|
|
14
|
+
import "../chunk-52F2ETEG.js";
|
|
15
|
+
import "../chunk-BXW5MBBY.js";
|
|
16
16
|
import "../chunk-JSYQ3JQS.js";
|
|
17
17
|
import "../chunk-ZOC4GITL.js";
|
|
18
18
|
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
DEFAULT_MNEMONIC,
|
|
6
6
|
DotNS
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-5BE5PQH6.js";
|
|
8
8
|
import "../chunk-SI2ZUOYD.js";
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
11
|
-
import "../chunk-
|
|
9
|
+
import "../chunk-XVQICFTB.js";
|
|
10
|
+
import "../chunk-52F2ETEG.js";
|
|
11
|
+
import "../chunk-BXW5MBBY.js";
|
|
12
12
|
import {
|
|
13
13
|
getPopSelfServeConfig,
|
|
14
14
|
loadEnvironments,
|
package/dist/commands/whoami.js
CHANGED
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
STALE_SESSION_MESSAGE,
|
|
3
3
|
getAuthClient,
|
|
4
4
|
hasPersistedSession
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-2NF6QIDF.js";
|
|
6
6
|
import {
|
|
7
7
|
CLI_NAME
|
|
8
8
|
} from "../chunk-TSPERKUS.js";
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
9
|
+
import "../chunk-52F2ETEG.js";
|
|
10
|
+
import "../chunk-BXW5MBBY.js";
|
|
11
11
|
import "../chunk-JSYQ3JQS.js";
|
|
12
12
|
import "../chunk-ZOC4GITL.js";
|
|
13
13
|
|