@tokamak-private-dapps/private-state-cli 2.4.1 → 2.4.2
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/CHANGELOG.md +5 -0
- package/README.md +11 -4
- package/agents.md +6 -5
- package/lib/private-state-cli-command-registry.mjs +6 -5
- package/lib/runtime.mjs +25 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 2.4.2 - 2026-05-30
|
|
6
|
+
|
|
7
|
+
- Changed channel workspace recovery guidance so CLI help, guide output, agent instructions, and documentation direct
|
|
8
|
+
users to registered workspace mirrors before explicit RPC genesis rebuilds.
|
|
9
|
+
|
|
5
10
|
## 2.4.1 - 2026-05-30
|
|
6
11
|
|
|
7
12
|
- Classified `UnexpectedCurrentRootVector()` submit reverts as stale channel-root failures with recovery hints that
|
package/README.md
CHANGED
|
@@ -199,7 +199,14 @@ unless the user explicitly understands the compliance implications. Prefer a sel
|
|
|
199
199
|
|
|
200
200
|
Workspace recovery commands use saved recovery indexes by default. If the local channel workspace is missing,
|
|
201
201
|
corrupted, or does not contain a usable index, `channel recover-workspace` stops with an explicit error instead of
|
|
202
|
-
silently replaying logs from channel genesis.
|
|
202
|
+
silently replaying logs from channel genesis. When the channel has a registered workspace mirror, recover from the
|
|
203
|
+
mirror first:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
private-state-cli channel recover-workspace --channel-name <CHANNEL> --network mainnet --source mirror
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Use `channel recover-workspace --source rpc --from-genesis` only when no compatible workspace mirror is available and
|
|
203
210
|
you intentionally want to rebuild channel workspace state from the channel creation block:
|
|
204
211
|
|
|
205
212
|
```bash
|
|
@@ -226,9 +233,9 @@ existing history, while `--from-genesis` overwrites it with one full genesis-to-
|
|
|
226
233
|
by replaying from the channel's genesis block because no prior recovery index can exist for a new channel.
|
|
227
234
|
|
|
228
235
|
`channel join` refreshes stale channel workspace state through the saved recovery index before submitting the
|
|
229
|
-
registration transaction. For a channel that was created elsewhere,
|
|
230
|
-
|
|
231
|
-
saved index instead of silently replaying from genesis.
|
|
236
|
+
registration transaction. For a channel that was created elsewhere, recover from a registered workspace mirror first.
|
|
237
|
+
Use `channel recover-workspace --source rpc --from-genesis` only when no compatible mirror is available; later joins
|
|
238
|
+
and wallet commands resume from the saved index instead of silently replaying from genesis.
|
|
232
239
|
|
|
233
240
|
Wallet commands that need channel state, including `wallet recover-workspace`, `wallet get-meta`,
|
|
234
241
|
`wallet get-channel-fund`, and `wallet get-notes`, refresh stale local channel workspaces through saved recovery
|
package/agents.md
CHANGED
|
@@ -37,12 +37,13 @@ activity or as a bridge-wide disclosure rule for every DApp.
|
|
|
37
37
|
`private-state-cli set rpc --network <NETWORK> --rpc-url <URL> --provider <PROVIDER>`, or with explicit
|
|
38
38
|
`--log-requests-per-second` and `--block-range-cap` values when the provider is not built in.
|
|
39
39
|
- A workspace recovery index is the saved block pointer and state-root hash that lets the CLI resume log scanning
|
|
40
|
-
without replaying the channel from its creation block. If it is missing,
|
|
41
|
-
because genesis replay can take much longer.
|
|
40
|
+
without replaying the channel from its creation block. If it is missing, check whether the channel has a registered
|
|
41
|
+
workspace mirror before explaining or using `--from-genesis`, because genesis replay can take much longer.
|
|
42
42
|
- Before guiding a user to run `channel recover-workspace --source rpc --from-genesis`, explain that RPC genesis
|
|
43
|
-
recovery can be very slow because it scans channel logs from the creation block.
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
recovery can be very slow because it scans channel logs from the creation block. Run or suggest
|
|
44
|
+
`channel get-meta --channel-name <CHANNEL> --network <NETWORK>` first; if `workspaceMirror` is set, try
|
|
45
|
+
`channel recover-workspace --channel-name <CHANNEL> --network <NETWORK> --source mirror`. Use RPC genesis replay only
|
|
46
|
+
when no compatible workspace mirror is available.
|
|
46
47
|
- When the user asks about gas use, transaction fees, transaction cost, or USD cost for private-state CLI commands, run
|
|
47
48
|
`private-state-cli help transaction-fees --network <NETWORK> --json` and answer from the returned `rows`. If the
|
|
48
49
|
network is unclear, ask which network to use. Do not tell the user to ask the developer unless the command fails after
|
|
@@ -210,7 +210,7 @@ export const PRIVATE_STATE_CLI_FIELD_CATALOG = Object.freeze({
|
|
|
210
210
|
fromGenesis: {
|
|
211
211
|
label: "Scan From Genesis",
|
|
212
212
|
type: "checkbox",
|
|
213
|
-
hint: "Requires --source rpc.
|
|
213
|
+
hint: "Requires --source rpc. Use only when no compatible workspace mirror is available and a full genesis replay is intentional.",
|
|
214
214
|
option: "--from-genesis",
|
|
215
215
|
optional: true,
|
|
216
216
|
},
|
|
@@ -233,7 +233,7 @@ export const PRIVATE_STATE_CLI_FIELD_CATALOG = Object.freeze({
|
|
|
233
233
|
type: "select",
|
|
234
234
|
options: ["rpc", "mirror"],
|
|
235
235
|
valueLabel: "<rpc|mirror>",
|
|
236
|
-
hint: "
|
|
236
|
+
hint: "Use mirror first when a channel workspace mirror is registered. If omitted, the CLI uses rpc and resumes from the local recovery index when available.",
|
|
237
237
|
option: "--source",
|
|
238
238
|
optional: true,
|
|
239
239
|
},
|
|
@@ -429,12 +429,13 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
429
429
|
optionalFields: ["source", "fromGenesis", "outputRaw", "publishWorkspaceMirror", "leaderAccount", "output", "force"],
|
|
430
430
|
usage: "--channel-name, --network, optional --source, optional --from-genesis, optional --output-raw, optional --publish-workspace-mirror with --leader-account and --output, optional --force",
|
|
431
431
|
help: [
|
|
432
|
-
"
|
|
432
|
+
"When a channel workspace mirror is registered, try --source mirror before an explicit RPC genesis rebuild",
|
|
433
433
|
"--source mirror validates the channel leader's registered checkpoint manifest, downloads only the needed checkpoint or delta bundle, and then replays RPC logs to latest",
|
|
434
|
+
"If --source is omitted, the CLI uses rpc and resumes RPC log scanning from the workspace recovery index when available",
|
|
434
435
|
"RPC recovery writes a usable channel workspace checkpoint after each RPC log chunk, so interrupted runs can resume from the last completed chunk",
|
|
435
436
|
"Mirror recovery uses a matching delta bundle when available; otherwise a newer verified full checkpoint replaces the local checkpoint before RPC catch-up",
|
|
436
437
|
"Fails instead of falling back to genesis when no usable recovery index exists",
|
|
437
|
-
"Use --source rpc --from-genesis
|
|
438
|
+
"Use --source rpc --from-genesis only when no compatible workspace mirror is available and you intentionally want to replay logs from channel genesis",
|
|
438
439
|
"--output-raw with --source rpc appends raw JSON-RPC request and response history to method-specific JSON files under the channel workspace rpcCallHistory directory; eth_getLogs is split by event",
|
|
439
440
|
"--from-genesis moves the existing local channel workspace to workspace-rebuild-backups before writing the current-format workspace; local secrets are preserved",
|
|
440
441
|
"--publish-workspace-mirror writes manifest.json, checkpoint.zip, and any needed delta bundle after recovery",
|
|
@@ -524,7 +525,7 @@ export const PRIVATE_STATE_CLI_COMMANDS = Object.freeze([
|
|
|
524
525
|
usage: "--channel-name, --network, --account, --wallet-secret-path, --acknowledge-action-impact",
|
|
525
526
|
help: [
|
|
526
527
|
"Refreshes the local channel workspace through the saved recovery index before joining when the scan fits the 7,200-block pre-command budget",
|
|
527
|
-
"Fails instead of replaying from genesis;
|
|
528
|
+
"Fails instead of replaying from genesis; recover from a registered workspace mirror first, and use channel recover-workspace --source rpc --from-genesis only when no compatible mirror is available",
|
|
528
529
|
"--wallet-secret-path is read once for channel-bound L2 spending-key derivation and is not stored in the wallet workspace",
|
|
529
530
|
"Pays any join toll directly from the L1 wallet, not from bridge-deposited balance",
|
|
530
531
|
"Prints the immutable policy snapshot before first registration",
|
package/lib/runtime.mjs
CHANGED
|
@@ -2061,7 +2061,8 @@ async function syncChannelWorkspace({
|
|
|
2061
2061
|
throw new Error([
|
|
2062
2062
|
`Workspace recovery index is missing or unusable for channel ${channelName} on ${networkNameFromChainId(network.chainId)}.`,
|
|
2063
2063
|
"The CLI will not fall back to replaying channel logs from genesis unless explicitly requested.",
|
|
2064
|
-
|
|
2064
|
+
`If a workspace mirror is registered, run channel recover-workspace --channel-name ${channelName} --network ${networkNameFromChainId(network.chainId)} --source mirror first.`,
|
|
2065
|
+
`Use channel recover-workspace --channel-name ${channelName} --network ${networkNameFromChainId(network.chainId)} --source rpc --from-genesis only when no compatible mirror is available.`,
|
|
2065
2066
|
].join(" "));
|
|
2066
2067
|
}
|
|
2067
2068
|
const workspaceBase = {
|
|
@@ -3873,12 +3874,14 @@ async function inspectGuideChannel({ channelName, network, provider, artifactsIn
|
|
|
3873
3874
|
bridgeResources.bridgeAbiManifest.contracts.channelManager.abi,
|
|
3874
3875
|
provider,
|
|
3875
3876
|
);
|
|
3876
|
-
const [joinToll, refundSchedule] = await Promise.all([
|
|
3877
|
+
const [joinToll, refundSchedule, workspaceMirror] = await Promise.all([
|
|
3877
3878
|
channelManager.joinToll(),
|
|
3878
3879
|
readChannelRefundSchedule(channelManager),
|
|
3880
|
+
readChannelWorkspaceMirror({ bridgeCore, channelId }),
|
|
3879
3881
|
]);
|
|
3880
3882
|
result.onchain.joinTollBaseUnits = joinToll.toString();
|
|
3881
3883
|
result.onchain.refundSchedule = refundSchedule;
|
|
3884
|
+
result.onchain.workspaceMirror = workspaceMirror;
|
|
3882
3885
|
}
|
|
3883
3886
|
} catch (error) {
|
|
3884
3887
|
result.error = error.message;
|
|
@@ -4054,9 +4057,19 @@ function applyGuideNextAction(guide) {
|
|
|
4054
4057
|
return;
|
|
4055
4058
|
}
|
|
4056
4059
|
if (guide.selectors.channelName && guide.state.channel?.onchain?.exists && !guide.state.channel?.local?.workspaceExists) {
|
|
4060
|
+
const workspaceMirror = typeof guide.state.channel.onchain.workspaceMirror === "string"
|
|
4061
|
+
? guide.state.channel.onchain.workspaceMirror.trim()
|
|
4062
|
+
: "";
|
|
4063
|
+
if (workspaceMirror) {
|
|
4064
|
+
setGuideNextAction(guide, {
|
|
4065
|
+
command: `channel recover-workspace --channel-name ${guide.selectors.channelName} --network ${guide.selectors.network} --source mirror`,
|
|
4066
|
+
why: "The channel has a registered workspace mirror. Use mirror recovery before considering an explicit RPC genesis rebuild.",
|
|
4067
|
+
});
|
|
4068
|
+
return;
|
|
4069
|
+
}
|
|
4057
4070
|
setGuideNextAction(guide, {
|
|
4058
4071
|
command: `channel recover-workspace --channel-name ${guide.selectors.channelName} --network ${guide.selectors.network} --source rpc --from-genesis`,
|
|
4059
|
-
why: "The channel exists on-chain, but the local channel workspace has not been recovered yet
|
|
4072
|
+
why: "The channel exists on-chain, but the local channel workspace has not been recovered yet and no workspace mirror is registered. RPC genesis rebuild is the remaining explicit bootstrap path.",
|
|
4060
4073
|
});
|
|
4061
4074
|
return;
|
|
4062
4075
|
}
|
|
@@ -11802,7 +11815,9 @@ function buildRecoveryHints(error, args = {}) {
|
|
|
11802
11815
|
}
|
|
11803
11816
|
|
|
11804
11817
|
if (error?.code === CLI_ERROR_CODES.STALE_WORKSPACE) {
|
|
11805
|
-
hints.push(`private-state-cli channel
|
|
11818
|
+
hints.push(`private-state-cli channel get-meta --channel-name ${channelName} --network ${networkName}`);
|
|
11819
|
+
hints.push(`if workspaceMirror is set: private-state-cli channel recover-workspace --channel-name ${channelName} --network ${networkName} --source mirror`);
|
|
11820
|
+
hints.push(`otherwise use indexed RPC recovery: private-state-cli channel recover-workspace --channel-name ${channelName} --network ${networkName}`);
|
|
11806
11821
|
hints.push(`private-state-cli help guide --network ${networkName} --channel-name ${channelName}`);
|
|
11807
11822
|
}
|
|
11808
11823
|
|
|
@@ -11810,7 +11825,9 @@ function buildRecoveryHints(error, args = {}) {
|
|
|
11810
11825
|
error?.code === CLI_ERROR_CODES.STALE_CHANNEL_ROOT
|
|
11811
11826
|
|| message.includes("UnexpectedCurrentRootVector")
|
|
11812
11827
|
) {
|
|
11813
|
-
hints.push(`private-state-cli channel
|
|
11828
|
+
hints.push(`private-state-cli channel get-meta --channel-name ${channelName} --network ${networkName}`);
|
|
11829
|
+
hints.push(`if workspaceMirror is set: private-state-cli channel recover-workspace --channel-name ${channelName} --network ${networkName} --source mirror`);
|
|
11830
|
+
hints.push(`otherwise use indexed RPC recovery: private-state-cli channel recover-workspace --channel-name ${channelName} --network ${networkName}`);
|
|
11814
11831
|
if (walletName !== "<WALLET>") {
|
|
11815
11832
|
hints.push(`private-state-cli wallet get-notes --wallet ${walletName} --network ${networkName}`);
|
|
11816
11833
|
}
|
|
@@ -11818,7 +11835,9 @@ function buildRecoveryHints(error, args = {}) {
|
|
|
11818
11835
|
}
|
|
11819
11836
|
|
|
11820
11837
|
if (message.includes("Workspace recovery index is missing or unusable")) {
|
|
11821
|
-
hints.push(`private-state-cli channel
|
|
11838
|
+
hints.push(`private-state-cli channel get-meta --channel-name ${channelName} --network ${networkName}`);
|
|
11839
|
+
hints.push(`if workspaceMirror is set: private-state-cli channel recover-workspace --channel-name ${channelName} --network ${networkName} --source mirror`);
|
|
11840
|
+
hints.push(`only if no compatible workspace mirror is available: private-state-cli channel recover-workspace --channel-name ${channelName} --network ${networkName} --source rpc --from-genesis`);
|
|
11822
11841
|
}
|
|
11823
11842
|
|
|
11824
11843
|
if (message.includes("Wallet note recovery index is missing or unusable")) {
|
package/package.json
CHANGED