Repository navigation
feat(canton-create): keep the ledger across a Splice bump and add a reset command - #269
Conversation
- down stops the dApp, the app's own services and the Wallet Gateway through stop_services; - what down does is unchanged; the script header already says Docker itself is left running.
…the gateway's stores - reset stops the services, then drops the LocalNet with its volumes; - it deletes .wallet-gateway/, whose parties and sessions only the dropped ledger had; - the usage text, the docs and the token PROVENANCE recipe name it.
- the menu gains Stack reset; - it asks y/N before dropping anything.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Note
Copilot was unable to complete this review at the selected tier due to model policy or plan restrictions.
🟡 Changes recommended
The change still has unresolved review findings: a user-facing script message uses confusing internal subcommand names, and the localnet config now hard-fails with an unhandled Docker/daemon error that produces a stack trace instead of a clear actionable message.
2 open issues
What changed in this PR
This pull request updates the canton-create LocalNet workflow to prevent broken starts after a pinned Splice bump when an older ledger is still present in Docker, and adds a dedicated reset command (plus menu entry) to fully drop the ledger and Wallet Gateway state. Documentation and tests are updated to reflect the new workflow.
Changes:
- Make
upstop early after a Splice tag change if old LocalNet volumes still exist, and direct users toreset. - Add
resetto stop relevant services, drop the LocalNet (including volumes), and delete Wallet Gateway stores; add an interactive “Stack reset” menu option with confirmation. - Update docs and tests around the new Splice-bump guard and reset flow.
This pull request requires changes.
Unresolved review comments:
- (moderate, votes: 2)
localnet-config.mjs: Docker volume probing during config prep should handle “Docker not installed/daemon unavailable” more gracefully (avoid stack traces; emit an actionable message). - (moderate, votes: 1)
dev-stack.sh:resetis destructive but isn’t meaningfully exercised by automated tests beyond argument parsing; add a small test that fakesdocker/canton-barebonesand covers the y/N confirmation path. - (nit, votes: 2)
dev-stack.sh: error messaging should prefer the user-facingpnpm stack ...commands rather than internal subcommand names (up/reset) to avoid confusion.
| File | Summary |
|---|---|
| example-dapps/token-vesting/vendor/PROVENANCE.md | Update LocalNet reset/recovery instructions to use pnpm stack reset. |
| example-dapps/amulet-vesting/daml/README.md | Document the Splice-bump refusal behavior and updated reset guidance. |
| CONTRIBUTING.md | Document the new reset command in local dev workflows. |
| CLAUDE.md | Record the operational rule: Splice bump + old ledger requires reset. |
| canton-create/scaffold/localnet/scripts/localnet-config.test.mjs | Add coverage for Splice-bump detection and refusal when old volumes exist. |
| canton-create/scaffold/localnet/scripts/localnet-config.mjs | Implement Splice-move detection and Docker volume check; return a dedicated status for up to handle. |
| canton-create/scaffold/localnet/scripts/dev-stack.test.mjs | Extend argument parsing tests to include the new reset action. |
| canton-create/scaffold/localnet/scripts/dev-stack.sh | Add reset, wire up behavior to the new exit status, and add menu option with confirmation. |
| canton-create/scaffold/localnet/README.md | Explain pnpm stack reset and the new “stop after Splice bump” behavior. |
| architecture.md | Update repo-level command documentation to include reset and the new guard behavior. |
Review effort: Balanced
up after a Splice bump and add a reset command
- after a Splice bump, the LocalNet runs the new release on the old ledger, upgraded in place; - that ledger keeps the Amulet its DSO voted in last, but build-dar took the release's newest; - so up stopped at deploy-dar (KNOWN_PACKAGE_VERSION), and a new version failed at prepare; - build-dar now asks the LocalNet's Scan for the Amulet it runs and builds against that one; - with no LocalNet answering, it still builds on the release's newest DARs; - up builds once Scan answers, no longer before the LocalNet starts; - when the Splice tag moves while the old ledger is still in Docker, up ends with a warning; - the warning links splice-upgrade.md, which moves the ledger to the new Amulet with one DSO vote.
- the Tap and the Amulet split before a grant named AmuletRules by the package id Scan returns; - that id pins the Amulet package the contract was created on; - a DSO vote on a new Amulet re-creates AmuletRules, but still on the old package; - within 24 h Splice unvets the old package, and the participant then refuses both commands; - so moving a LocalNet to a new Amulet took a second vote to keep the Tap and grants working; - by package name, the participant runs the Amulet it vets and upgrades the contract on use; - the disclosed contract keeps Scan's template id, the one its blob was created with; - tested live on a fresh ledger, and in place before the vote, after it and after the unvet.
780ca0c to
812bcb2
Compare
up after a Splice bump and add a reset commandreset command
gabitoesmiapodo
left a comment
There was a problem hiding this comment.
LGTM.
I discarded most things from an "adversarial review", but this could be worth addressing before merge, or maybe an issue created for it.
- The upgrade warning prints once, at the end of
up. If any step fails first, it never shows again. It also never shows up in the--jsonoutput.
- localnet-config.mjs settles the marker in the LocalNet dir before it moves the config - Docker reporting no volumes drops it; Docker not answering keeps it - only a move to a newer Splice tag marks; an older one does not - dev-stack.sh reads the marker, not exit status 3, so every error of an up carries the warning - the first up that finishes shows it and removes the marker; reset removes it too - the --json error and done events carry it in warnings - the warning names the contract only when the project has one
- warn records each warning, and the error and done events list them in the order given - the upgrade warning stays last, where the human log prints it - without warnings the list stays absent, so the stream is unchanged
- an EXIT trap reports the stop the way die does, naming the exit status when bash gives one - the run still ends with its own status, a signal included; die and done disarm the trap - bash 3.2 gives an unbound variable status 0 in the trap, so the trap exits 1 then
- json_string escapes tab, carriage return and newline as JSON does - every other control character gets a \u escape, built with printf -v so no fork runs
- a reset that succeeds removes the Wallet Gateway's stores - a reset that fails keeps them
- the localnet layer row lists the splice-upgrade.md it ships - build-dar falls back to the release's newest DARs when no LocalNet Scan answers


Summary
No related issue.
Upgraded in place to a new Splice release, an existing LocalNet keeps the Amulet its DSO voted in last, while
build-darbuilt the contract against the release's newest one, so the amulet example broke on that ledger. #260's bump to Splice 0.9.4 is such a bump.build-darnow builds against the Amulet the LocalNet runs, soupkeeps working on the old ledger. It then ends with a warning that linkssplice-upgrade.md, which moves the ledger to the new Amulet with one DSO vote. A newresetstarts over on a fresh ledger instead.Changes
build-darasks the LocalNet's Scan which Amulet it runs and builds against that one; with no LocalNet answering, it builds on the release's newest DARs, as before;upbuilds the DAR once Scan answers, no longer before the LocalNet starts;upends with a warning that linkssplice-upgrade.md;splice-upgrade.md: moves the ledger to the new release's Amulet with one DSO vote;AmuletRulesby package name, so the Tap and grants keep working once Splice unvets the old Amulet;reset: stops the dApp, the app's own services and the Wallet Gateway, drops the LocalNet with its volumes, and deletes the gateway's stores;Acceptance criteria
upstarts on the old ledger, deploys the contract built against the Amulet that ledger runs, and ends with a warning that linkssplice-upgrade.md;splice-upgrade.mdmoves the ledger to the new Amulet with one vote, and the amulet example keeps working after Splice unvets the old one;upstarts on the new Splice with no warning;resetdrops the ledger and the Wallet Gateway's stores, without a prompt from the command line and after y/N from the menu;resetand the warning apply to every app.Test plan
Automated tests
node --test "canton-create/scaffold/*/scripts/*.test.mjs"andpnpm -C example-dapps/amulet-vesting test;Manual verification
pnpm dev:amulet-vesting uponce, thenpnpm dev:amulet-vesting down;.canton-localnet/canton-barebones.config.json, setsplice.tagto0.9.4, whichuptakes for a Splice bump;pnpm dev:amulet-vesting up: expect the config back on the pinned0.8.1, the stack up on the same ledger, and a closing warning that linkssplice-upgrade.md;pnpm dev:amulet-vesting reset, thenpnpm dev:amulet-vesting up;A real bump ran end to end with #260's changes, on a ledger born on Splice 0.8.1:
upkept the ledger and redeployed the same DAR, the guide's one vote moved it to the new Amulet, and the vesting flow passed before the vote, after it, and after Splice unvetted the old Amulet.Breaking changes
None.
Checklist
Screenshots
An existing LocalNet once #260 moves it to Splice 0.9.4, recorded from this branch's scripts with Docker, canton-barebones, Scan and the services faked, so waits take seconds.
upkeeps the old ledger and ends with a warning that linkssplice-upgrade.mdreset, with no promptndrops nothingreset,upstarts on a fresh ledger, with no warning