chore: backport a month of maintenance from main - #2110
Conversation
* security: bump npm to version with stronger defaults and be explicit about version number. Signed-off-by: Giles Cope <gilescope@gmail.com> * fix: push file down to where used Signed-off-by: Giles Cope <gilescope@gmail.com> * ci: pin to explicit node version and bump major Signed-off-by: Giles Cope <gilescope@gmail.com> * feat: versions in global arg Signed-off-by: Giles Cope <gilescope@gmail.com> --------- Signed-off-by: Giles Cope <gilescope@gmail.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
…#2044) * chore(deps): bump actions/attest-build-provenance from 4.1.1 to 4.2.2 Bumps [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance) from 4.1.1 to 4.2.2. - [Release notes](https://github.com/actions/attest-build-provenance/releases) - [Changelog](https://github.com/actions/attest-build-provenance/blob/main/RELEASE.md) - [Commits](actions/attest-build-provenance@0f67c3f...4d10147) --- updated-dependencies: - dependency-name: actions/attest-build-provenance dependency-version: 4.2.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * rename action Co-authored-by: Squirrel <giles.cope@shielded.io> Signed-off-by: Squirrel <giles.cope@shielded.io> * fix: update sha also Signed-off-by: Giles Cope <gilescope@gmail.com> --------- Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: Squirrel <giles.cope@shielded.io> Signed-off-by: Giles Cope <gilescope@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Squirrel <giles.cope@shielded.io> Co-authored-by: Giles Cope <gilescope@gmail.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.85.8 to 2.85.11. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](taiki-e/install-action@cb33e69...7f4eb89) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.85.11 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.9.1 to 2.9.2. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](Swatinem/rust-cache@c193711...6323deb) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-version: 2.9.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
) * chore: stop duplicating binaries and res/ in a second image layer The node and toolkit images copied files as root, then ran `chown -R` over the same paths. chown rewrites every file, so buildkit stored a second full copy in the chown layer -- 210MB on the node image (a 133M binary plus the 74M res/ tree), and the toolkit-js tree on the toolkit image. Copy with `COPY --chown=appuser:appuser` instead (appuser moved above the COPYs in both base Dockerfiles) and leave `chown` covering only the directories that `RUN mkdir` creates. Assisted-by: Claude:claude-opus-5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * chore: add PR link to image layer dedup change file Assisted-by: Claude:claude-opus-5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> --------- Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* chore(deps): land the safe subset of the pending major bumps Clears four of the nine major updates queued on the Renovate dependency dashboard (#1090) in one PR: - actions/cache/save v4 -> v6.1.0 (ESM migration only; inputs unchanged) - azure/setup-kubectl v4.0.1 -> v5.1.0 (node24 runtime, dl.k8s.io) - contract-compiler base node:22-slim -> node:24-slim; @types/node 22 -> 24 in util/toolkit-js, which already targets @tsconfig/node24. Still Debian bookworm, so the pinned apt package set is unaffected. - paritytech/srtool: track the whole `<rust>-<srtool>` tag in one ARG. The old split ARG made renovate read `0.18.4` as the image version and offer `1.93.0` as a "v1 major", which resolves to a tag that does not exist. The remaining five are left alone on purpose - see the PR body. Assisted-by: Claude:claude-opus-5 claude-code Signed-off-by: Giles Cope <gilescope@gmail.com> * fix: outstanding issues Signed-off-by: Giles Cope <gilescope@gmail.com> * chore(deps): take docker/compose v5 with buildx; revert typescript 7 compose v5.0.0 removed its internal buildkit builder and delegates `build:` to Docker Bake, so the buildx plugin is now installed alongside the compose plugin in the CI base image - earthly injects a bare docker CLI with no bundled plugins, and local-env's compose file has a `build:` service. Verified by building the contract-compiler image with compose v5.5.0 + buildx v0.36.1 through the bake path. TypeScript 7 comes back out. It passed every build-time check in util/toolkit-js - tsc, all four compact variants - and then failed at runtime in CI, taking out +rebuild-genesis-state and all four Toolkit E2E jobs: Error loading configuration '/toolkit-js/test/contract/contract.config.ts' .. Unexpected error while compiling TypeScript configuration Cannot read properties of undefined (reading 'fileExists') @midnight-ntwrk/compact-js-command declares ts-node ^10.9.2 and its ConfigCompiler uses it to compile contract.config.ts at run time; ts-node drives the JavaScript compiler API that the native port does not expose. So ts-node was the blocker after all - reaching in transitively through one of our own packages, which is why it was invisible in package.json and to tsc. The `types: ["node"]` tsconfig line that TS 7 needed goes with it. Also adds the change file for the whole backlog sweep. Assisted-by: Claude:claude-opus-5 claude-code Signed-off-by: Giles Cope <gilescope@gmail.com> * Update renovate-major-backlog.md Signed-off-by: Squirrel <giles.cope@shielded.io> --------- Signed-off-by: Giles Cope <gilescope@gmail.com> Signed-off-by: Squirrel <giles.cope@shielded.io> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* feat(local-env): add non-validator archive node Signed-off-by: Tomasz Bartos <tomasz.bartos@shielded.io> * chore: mark 55a7680 as AI-assisted The archive-node commit was drafted with AI assistance; adding the marker required by AGENTS.md as a follow-up rather than amending, per the repository's no-force-push rule. Assisted-by: Claude:claude-fable-5 Signed-off-by: Tomasz Bartos <tomasz.bartos@shielded.io> * docs(local-env): document the non-validator archive node in topology guides The startup-phases table in local-environment/README.md and the node-keys guide in configurations/readme.md still described a five-validator stack. Document midnight-node-6: non-validator archive follower, its published ports (30338 p2p / 9945 RPC / 9620 Prometheus), its persistent volume, and that it carries no keys and is skipped by validator-discovering tooling. Assisted-by: Claude:claude-fable-5 Signed-off-by: Tomasz Bartos <tomasz.bartos@shielded.io> * chore: move archive-node change file into the node component The release archive/reset workflow only handles changes/node, changes/toolkit, and changes/runtime; a file left in the legacy top-level changes/added/ is never archived or reset and would be re-emitted in subsequent release notes. Assisted-by: Claude:claude-fable-5 Signed-off-by: Tomasz Bartos <tomasz.bartos@shielded.io> --------- Signed-off-by: Tomasz Bartos <tomasz.bartos@shielded.io> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* fix: toolkit update-ledger-parameters erroneous param re-use Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * docs: add pr link to change file Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> --------- Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 4.2.0 to 4.3.0. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](docker/setup-buildx-action@bb05f3f...37fe631) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-version: 4.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
Bumps [midnightntwrk/upload-sarif-github-action](https://github.com/midnightntwrk/upload-sarif-github-action) from b747f959d898a4ffdcc2cea4e2daafc61a0c33e9 to 362d0346b194663004cb371e8e8523bd1c910917. - [Release notes](https://github.com/midnightntwrk/upload-sarif-github-action/releases) - [Changelog](https://github.com/midnightntwrk/upload-sarif-github-action/blob/main/CHANGELOG.md) - [Commits](midnightntwrk/upload-sarif-github-action@b747f95...362d034) --- updated-dependencies: - dependency-name: midnightntwrk/upload-sarif-github-action dependency-version: 362d0346b194663004cb371e8e8523bd1c910917 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
…the next block instead (#1980) * fix: c2m-bridge hardening: do not skip failed transfers and retry in the next block instead Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io> * Simplify handle_transfers Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io> * Be specific that the only situation of partially processed Cardano transaction is Reserve part has been processed by the ICS part has not Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io> * Update changes files Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io> * Update TransferHandlerError docs with SCALE explanation Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io> * Fix comments Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io> --------- Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.85.11 to 2.86.3. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](taiki-e/install-action@7f4eb89...5b4d68e) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.86.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
…bust (#2032) * fix(local-env): make qanet from-genesis and fork-network full mode robust Two maintenance fixes to local-environment tooling flagged in review of #2023: - qanet.network.yaml: uncomment the SEED_PHRASE references (node1-12) so `run qanet --from-genesis` discovers its validators. qanet was the only well-known network with these commented out, so from-genesis always threw "none of the seed env vars are set ()" even when seeds were provided. The node still reads keys only from the generated *_SEED_FILE mounts, so snapshot/fork bring-up is unaffected. - fork-network.yml: drive `full` upgrade mode as its two phases (image-upgrade then governance-runtime-upgrade --skip-run) with the runtime step's RPC endpoint probe in between, instead of the all-in-one full-upgrade command that hardcodes ws://127.0.0.1:9950. This makes full mode resolve a reachable endpoint (published port or node1's docker bridge IP) on self-hosted runners where the loopback -> published-port path is black-holed, completing the follow-up noted in the runtime-mode fix. Assisted-by: Claude:claude-4.8-opus Signed-off-by: Justin Frevert <justinfrevert@gmail.com> * chore: add PR link to local-env fix change files Assisted-by: Claude:claude-opus-5 Signed-off-by: Justin Frevert <justinfrevert@gmail.com> --------- Signed-off-by: Justin Frevert <justinfrevert@gmail.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* Give local-env to downstream consumers Signed-off-by: Justin Frevert <justinfrevert@gmail.com> * changes file, tests Signed-off-by: Justin Frevert <justinfrevert@gmail.com> * pr comments Signed-off-by: Justin Frevert <justinfrevert@gmail.com> * chore: add local environment change tag Signed-off-by: Justin Frevert <justinfrevert@gmail.com> * fix: preserve manifest image on partial rollouts Only refresh the fork manifest image when the primary validator is rolled, preventing node-specific canaries from advertising an incompatible image to downstream consumers. Assisted-by: Codex:GPT-5 Signed-off-by: Justin Frevert <justinfrevert@gmail.com> * chore: remove unrelated warp change file Assisted-by: Codex:GPT-5 Signed-off-by: Justin Frevert <justinfrevert@gmail.com> * fix: harden fork manifest generation Parse OCI image tags without confusing registry ports or digests, validate manifest namespaces, and document local-only WebSocket endpoints for security scanning. Assisted-by: Codex:GPT-5 Signed-off-by: Justin Frevert <justinfrevert@gmail.com> * fix: place scanner suppressions inline OpenGrep applies nosemgrep annotations only to findings on the same source line. Assisted-by: Codex:GPT-5 Signed-off-by: Justin Frevert <justinfrevert@gmail.com> * chore: remove ineffective scanner annotations The repository scan uploads all OpenGrep results and does not honor inline annotations. Track the reviewed local-only cases through GitHub code-scanning dismissals instead. Assisted-by: Codex:GPT-5 Signed-off-by: Justin Frevert <justinfrevert@gmail.com> --------- Signed-off-by: Justin Frevert <justinfrevert@gmail.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.86.3 to 2.86.7. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](taiki-e/install-action@5b4d68e...b6ff580) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.86.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* ci: derive image publish targets from the repository
CI's registry, image name and OCI source label were hardcoded to
midnightntwrk's namespaces. This repo gets cloned into private forks,
and those clones inherit org runners and secrets, so their CI starts and
publishes -- into midnightntwrk's registries, including the public
ghcr.io/midnightntwrk mirror and the shared latest-{amd64,arm64} tags.
Take the target from the repo instead:
- Earthfile gains four global ARGs next to CACHE_KEY/CI --
GHCR_REGISTRY, GHCR_REGISTRY_PUBLIC, IMAGE_REPO and IMAGE_SOURCE_URL --
replacing the per-target `ENV GHCR_REGISTRY=...` lines. GHCR_REGISTRY
is read nowhere at runtime, only inside the Earthfile, so nothing is
lost by dropping the ENVs.
- GHCR_REGISTRY_PUBLIC defaults to GHCR_REGISTRY and the mirror push sits
behind `IF [ "$GHCR_REGISTRY_PUBLIC" != "$GHCR_REGISTRY" ]`, so only a
repo that deliberately sets a different public namespace can publish
publicly. (A duplicate tag in one SAVE IMAGE list is a hard error in
Earthly 0.8, hence the IF rather than a self-cancelling duplicate.)
- .envrc forwards all four to earthly via EARTHLY_BUILD_ARGS, appended
the same way CI=true already is, so every invocation that sources it
picks them up and no workflow has to repeat the derivation. Local runs
have no GITHUB_REPOSITORY and keep the ARG defaults.
- Workflows derive GHCR_REGISTRY at workflow-level env and expose
node_image / toolkit_image (+ _public) as job outputs, so the ~20
downstream image references shrink to `<image>:<tag>`. The composite
actions already take node-image/toolkit-image inputs and are unchanged.
- Publishing outside the current repo's namespace is gated on being the
canonical repo rather than retargeted: main.yml's two root publish jobs
(every other job needs them), the Docker Hub push in
build-publish-contract-precompiles.yml, and release-image.yml, which
refuses rather than skips because its downstream jobs are guarded with
`!cancelled() && !failure()` and would run through a skipped dependency.
Also two repo-agnostic CI fixes found alongside:
- A failed Docker Hub login no longer fails the build. It is pull-side
rate-limit relief for docker.io base images only, but the
`if [ -n "$DOCKERHUB_TOKEN" ]` guard made a bad credential fatal to
+test, +test-toolkit, the local-env targets and the SBOM scan jobs.
- changes_check.yml's GHCR login used `registry: ghcr.io/midnight-ntwrk`,
a path-qualified value docker/login-action never accepted; it wants a
registry host.
Behaviour for midnightntwrk/midnight-node is unchanged: rendering every
new reference with the canonical values reproduces the previous file
byte-for-byte. The one intentional exception is the OCI source label on
the benchmarks and toolkit images, which pointed at
midnight-ntwrk/artifacts while the CI image pointed at
midnightntwrk/midnight-node; all three now share IMAGE_SOURCE_URL.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* ci: publish from any repo, not just the canonical one
The previous commit closed the leak into midnightntwrk's registries by
gating main.yml and release-image.yml on being the canonical repo:
`if: github.repository == 'midnightntwrk/midnight-node'` on main.yml's
two root publish jobs, and a "Refuse to publish from a fork" `exit 1` in
release-image.yml's validate-inputs. Right for the leak, but too blunt:
a private clone merging to main gets no images at all and cannot cut a
release.
Image names already derive from
${GHCR_REGISTRY}/${GITHUB_REPOSITORY#*/}, so two clones of midnight-node
publish to distinct GHCR images and each repo's artifacts can be
access-controlled independently. Only these two workflows opted out.
So drop both gates and apply the derivation the rest of CI already uses:
- Both files get the workflow-level GHCR_REGISTRY / GHCR_REGISTRY_PUBLIC
env block from continuous-integration.yml, and expose node_image /
toolkit_image as job outputs (publish-amd64, prepare-release) since
the `env` context is not available in a reusable workflow's `with:`.
- Every reference to the private ghcr.io/midnight-ntwrk namespace becomes
${GHCR_REGISTRY}/${IMAGE_REPO}. The image basename follows the repo
name too, so a fork publishes <owner>/<its-repo> rather than a
same-named image in its own namespace.
- The Earthly `Run build` steps need no change: they source .envrc, which
already forwards GHCR_REGISTRY/IMAGE_REPO as build args. What was
hardcoded is the hand-written docker/gh plumbing around them.
Three things stay gated on the canonical repo, because they are things a
fork genuinely cannot do rather than things it should do differently:
- The public ghcr.io/midnightntwrk mirror. On a fork GHCR_REGISTRY_PUBLIC
equals GHCR_REGISTRY, so the mirror steps would collapse onto refs the
build already pushed -- re-creating identical indexes and attesting one
digest twice under two subject names.
- Docker Hub. `midnightntwrk` there is a Docker Hub org login, not a
GitHub owner, so there is no derivable equivalent and a fork has
neither the namespace nor the secrets.
- Every actions/attest step, including the private-namespace ones.
actions/attest requires GitHub Enterprise Cloud for a private or
internal repo, so on a fork they hard-fail; and with the default
push-to-registry: false they would write attestations bearing
upstream's subject-name into the fork's own store. This also covers
srtool-build.yml's three attest steps, which only checked
`release-tag != ''` and would otherwise start firing on a fork now that
release-image.yml can call them.
Semantically the mirror group could test GHCR_REGISTRY_PUBLIC !=
GHCR_REGISTRY instead, mirroring the Earthfile, but the `env` context is
not available in a job-level `if:`, so the mirror-only SBOM jobs cannot
express it. One predicate everywhere is simpler and works uniformly.
Net effect on a fork: it builds and pushes to its own GHCR namespace,
creates its own draft/release, and silently skips mirror, Hub and
attestations.
Behaviour for midnightntwrk/midnight-node is unchanged. Rendering every
reference in the three files with the canonical values reproduces HEAD's
set of image references exactly, and every added `if:` is the repo check
ANDed onto the condition that was already there, so all of them evaluate
true upstream.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* fix(ci): don't fail main.yml on a Docker Hub login failure
Two fixes the canonical-repo gates were masking, both now reachable
because main.yml and release-image.yml run from any repo.
main.yml's two `Login to DockerHub` steps have no continue-on-error and
a fork has no Docker Hub credentials, so they hard-fail before anything
else in the job runs. The login is pull-side rate-limit relief for
docker.io base images only -- the same bug and the same fix as the
Earthfile and sbom-scan-image.yml logins in the previous commit.
release-image.yml's prepare-release login has the same shape and gets
the same treatment.
Season's SEASON_VAR_NODE_DOCKER_IMAGE / _TOOLKIT_DOCKER_IMAGE were bare
Docker Hub strings baked into the release-notes body. Harmless to CI,
but a fork's own release notes would tell readers to pull upstream's
images. Point them at ${GHCR_REGISTRY_PUBLIC}, the publicly pullable
equivalent, which on a fork resolves to that fork's namespace.
The Season change does alter the canonical repo's release notes: they
now name ghcr.io/midnightntwrk/midnight-node{,-toolkit} instead of the
Docker Hub image. Both are published for every release, so the notes
stay accurate.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* fix(ci): pass image refs into run blocks via env, not template expansion
zizmor flagged 14 "code injection via template expansion" findings on
continuous-integration.yml, all of them `${{ }}` expanded directly into
a `run:` block -- the pattern AGENTS.md already tells us not to use.
Seven of the expansions predate this branch (the `*_image_tag` halves).
The other seven are the `*_image` halves added when image names moved
from hardcoded literals to job outputs, which also rewrote the lines and
so brought the whole set into this PR's diff.
The exposure is real rather than theoretical. Both halves derive from
`node/Cargo.toml`'s version field, read with
grep -m 1 'version =' node/Cargo.toml | awk '{print $3}' | tr -d '"'
and this workflow runs on `pull_request`, so a fork controls that file.
A version string containing shell metacharacters lands inside a command
substitution on a self-hosted runner. Passing the value through `env:`
puts it in the process environment instead of the script text, so it can
no longer be parsed as shell.
Converted four step blocks -- the two `Check for existing images` steps,
`Check Genesis Rebuild` and `Run metadata check` -- plus one more the
scanner did not report, the indexer job's CONTENT_HASH, which this branch
introduced in the same style. No `${{ }}` expansion remains inside any
run block in this file.
Values are unchanged: each expression moves verbatim into `env:` and the
script references it as a shell variable, so the resulting image refs and
build args are identical.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* ci: namespace the CI base image by repository too
The CI base image was left with a literal `midnight-node-ci` name while
every other image moved to `$IMAGE_REPO`. GHCR_REGISTRY only isolates by
*owner*, so two clones under one owner write the same
`$GHCR_REGISTRY/midnight-node-ci:$RUST_VERSION-$COMPACTC_VERSION-$ARCH`
and the later run silently replaces the earlier image.
Scope, to be accurate about it: nothing builds *from* that reference.
`prep-no-copy` FROMs `midnightntwrk/midnight-node-ci` on Docker Hub, so
the GHCR copy is a staging artifact that only the canonical repo goes on
to mirror. The collision therefore corrupts a staging image rather than
anyone's build inputs today. It stops being harmless the moment either
the FROM is pointed at GHCR or a clone uncomments the local-build path
just above it, so name it correctly now rather than rely on that.
IMAGE_REPO defaults to midnight-node, so the canonical reference stays
`midnight-node-ci` byte-for-byte; only the workflow's pull side needed
updating to match, and the Docker Hub tags stay literal inside the branch
that only the canonical repo takes.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* fix(ci): don't carry the public image name in a job output
`push-combined-manifest` failed with "invalid reference format": the
`IMAGE` env it builds the manifest from arrived empty, so the command ran
as `imagetools create -t ":2.1.0-<hash>"`.
The `run` job's log gives the reason:
##[warning]Skip output 'node_image_public' since it may contain secret.
##[warning]Skip output 'toolkit_image_public' since it may contain secret.
Actions refuses to propagate a job output whose value contains a
registered secret. DOCKERHUB_MIDNIGHTNTWRK_USER is the literal string
"midnightntwrk", which is a substring of
ghcr.io/midnightntwrk/midnight-node, so both public outputs were dropped
and resolved to "".
This is a regression from this branch. main had `IMAGE:` as a hardcoded
literal, which never travelled through the outputs machinery; deriving it
put it there for the first time. The private name survives only because
midnight-ntwrk is hyphenated and so does not contain the secret -- which
is why `node_image` works and `node_image_public` does not.
Recompute the public name in the two steps that consume it, from the
workflow-level GHCR_REGISTRY_PUBLIC and $GITHUB_REPOSITORY, and drop the
two job outputs plus the step outputs feeding them. Nothing else read
them. Renders to the same ghcr.io/midnightntwrk/midnight-node{,-toolkit}
the literals used, and a fork still gets its own namespace.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* ci: add '{}' for readability
Co-authored-by: Squirrel <giles.cope@shielded.io>
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
---------
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
Co-authored-by: Squirrel <giles.cope@shielded.io>
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
…2025) * chore(deps): route dependabot/renovate PRs to canonical bot:* labels Dependabot's default labels (dependencies, github_actions, ...) diverge from the org label standard; label each ecosystem bot:dependencies / bot:github-actions. Assisted-by: Claude <noreply@anthropic.com> * fix(ci): exempt the canonical bot labels from changes checks changes_check matches labels with contains() over a fromJSON array, which is an exact element match, so 'dependencies' does not match 'bot:dependencies'. Routing Dependabot to the canonical labels would therefore have dropped the exemption and failed the link check on bot PRs touching non-ignored files. The legacy names stay listed for now: both label sets currently exist on the repo, so in-flight bot PRs still carry the old ones. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Chris Ferry <chris.ferry@shielded.io> * docs(changes): add change file for PR 2025 Required by the changes check, which wants both a PR link and an issue link. DCO Remediation Commit for Chris Ferry <chris.ferry@shielded.io> I, Chris Ferry <chris.ferry@shielded.io>, hereby add my Signed-off-by to this commit: 2a8e13b Signed-off-by: Chris Ferry <chris.ferry@shielded.io> Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Signed-off-by: Chris Ferry <chris.ferry@shielded.io> Co-authored-by: justinfrevert <81839854+justinfrevert@users.noreply.github.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* refactor(ledger): give each ledger generation its own copy of the wrapper
`ledger/src/versions/common/**` was compiled twice through a
`#[path = "versions"]` module-parameterization trick — once bound to the
ledger-8 crates, once to the ledger-9 crates — with `super::` resolving
differently in each instantiation. A reader of a file under `versions/common/`
could not tell which ledger crate `mn_ledger_local` referred to, and an edit
meant for one generation silently applied to both.
Each generation now owns its files under `ledger/src/ledger_8/` and
`ledger/src/ledger_9/`, with absolute `crate::ledger_N::…` imports so every
file states the generation it binds. `ledger/src/common/` — the SCALE types
crossing the runtime/client interface, version-independent by design and
compiled once — becomes `ledger/src/boundary/`, so no folder is called
`common` any more. All `#[path]` and `#[allow(clippy::duplicate_mod)]`
scaffolding is gone from `lib.rs`.
No behaviour change: rustc already emitted both instantiations, so this only
makes the existing duplication visible in the source tree. There was no
non-test version branching in the shared half to reinterpret, public paths
(`ledger_8::…`, `ledger_9::…`, `latest::…`, `types::…`, `host_api::…`) are
unchanged, and the only edits outside `ledger/src/{lib.rs,ledger_8,ledger_9}`
are two `common::` -> `boundary::` import lines in `host_api/`.
Normalising the version path away, `diff -r src/ledger_8 src/ledger_9` leaves
exactly five differing files — `error_ext.rs`, `guaranteed_validation.rs`,
`post_block_update.rs`, `system_tx.rs`, and `mod.rs`'s crate aliases,
`CRATE_NAME` and `TransactionSignature`. Everything else is identical, which
is the check this layout buys.
Issue: #1768
Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* chore: add PR link to ledger split change file
Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* chore: rebuild metadata for the renamed ledger module paths
`scale-info`'s `#[derive(TypeInfo)]` records `module_path!()` in each type's
`Path`, so the runtime metadata embeds Rust module paths verbatim. Moving the
ledger wrapper into per-generation directories therefore changes the metadata's
type registry even though nothing about the SCALE encoding moved, and
`+check-metadata` byte-diffs the blob.
Decoding every `midnight_node_ledger`-rooted path out of the old and new blobs
gives 18 renames, 18 unchanged type names, and nothing added or removed:
common::types::{Op, Tx, UtxoInfo}
-> boundary::types::{Op, Tx, UtxoInfo}
ledger_9::common::types::{DeserializationError, DisjointCheckErrorCode,
EffectsCheckErrorCode, FeeCalculationErrorCode, InvalidError, LedgerApiError,
MalformedContractDeployErrorCode, MalformedError, MalformedZswapErrorCode,
SequencingCheckErrorCode, SerializationError, SystemTransactionError,
TransactionApplicationErrorCode, TransactionError, ZswapInvalidErrorCode}
-> ledger_9::types::{...}
The whole blob shrinks by exactly 99 bytes (148858 -> 148759), which is the
arithmetic of those renames and nothing else: 15 paths drop the `common`
segment (-7 bytes each, one compact length prefix plus six characters) and 3
grow from `common` to `boundary` (+2 bytes each).
No variant, discriminant, field, or field order changed -- `boundary/types.rs`
is a 100% rename of `common/types.rs`, and `ledger_9/types.rs` differs from the
`versions/common/types.rs` it came from by a single `use` line. Anything already
encoded on chain still decodes identically; only the names a fresh subxt codegen
emits are different.
`midnight_metadata_2.1.0.scale` is regenerated alongside `midnight_metadata.scale`
because the two are the same blob (that file tracks main rather than the release
it names).
Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* chore: rebuild metadata
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* docs: generation -> version
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* chore: rebuild metadata
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* chore: rebuild metadata
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
---------
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
… cache on mainnet (#1938) * perf(toolkit): faster resilient chain sync and replay, working wallet cache on mainnet Signed-off-by: Jacek Kurkowski <jacek.kurkowski@shielded.io> * chore: add PR link to change file Signed-off-by: Jacek Kurkowski <jacek.kurkowski@shielded.io> * fix(toolkit): gate relaxed replay verification on state-root presence Signed-off-by: Jacek Kurkowski <jacek.kurkowski@shielded.io> * fix(toolkit): verify genesis transactions fully during replay Signed-off-by: Jacek Kurkowski <jacek.kurkowski@shielded.io> * fix(toolkit): skip balancing re-check during replay Signed-off-by: Jacek Kurkowski <jacek.kurkowski@shielded.io> * fix(toolkit): trim comments, bound tip re-check, restore cache at any height Signed-off-by: Jacek Kurkowski <jacek.kurkowski@shielded.io> --------- Signed-off-by: Jacek Kurkowski <jacek.kurkowski@shielded.io> Co-authored-by: Fenton Haslam <50406962+Fentonhaslam@users.noreply.github.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
…e helpers (#2074) * chore(ledger-helpers): drop unreferenced files `versions/block_context/pre_ledger_8.rs` is dead: nothing has declared it as a module since ledger 8 became the oldest supported generation. The two `fork/contract_operation_*.rs` files are empty (0 bytes) and equally unreferenced. Assisted-by: Claude:claude-opus-5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * refactor(ledger-helpers): give each ledger version its own copy of the helpers `ledger/helpers/src/versions/common/**` was compiled twice via a `#[path = "versions"]` module-parameterization trick, once bound to the ledger-8 crates and once to the ledger-9 crates, with `super::` resolving differently in each instantiation. A reader of a file under `versions/common/` could not tell which ledger crate `mn_ledger` referred to, and an edit meant for one version silently applied to both — the same footgun #2059 removed one layer down. Each version now has its own directory, `ledger_8/` and `ledger_9/`, with absolute `crate::ledger_N::…` imports so every file states the version it binds. The two inline modules in `lib.rs` become the respective `mod.rs` files, and the version-specific single files are renamed to line up across the two trees: versions/block_context/post_ledger_8.rs -> ledger_N/block_context.rs versions/ecdsa_unimpl.rs -> ledger_8/ecdsa.rs versions/test_utilities_compat.rs -> ledger_8/test_utilities_local.rs versions/ecdsa_wallet_tests.rs -> ledger_9/ecdsa_wallet_tests.rs `ledger_9/ecdsa.rs` and `ledger_9/test_utilities_local.rs` are new one-line re-exports of what `lib.rs` used to alias inline, so the two directories hold the same filenames and `diff -r` is meaningful. No behaviour change: rustc already emitted both instantiations. Public paths are unchanged (`pub use common::*;` already flattened `common` away), so no consumer needed an edit and the runtime metadata is untouched. The same 150 unit tests and 2 doctests run, under the same names minus the `common::` segment. Assisted-by: Claude:claude-opus-5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * chore: add PR link to ledger-helpers change file Assisted-by: Claude:claude-opus-5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * fix(ledger-helpers): carry the relaxed-replay changes into the ledger 9 context `perf(toolkit): faster resilient chain sync and replay` (#1938) landed on main after this branch copied `versions/common/context.rs`. The rebase applied it to `ledger_8/context.rs` (the rename target) but the `ledger_9` copy is a fresh add, so it silently kept the old code: no `state_root()`, no `strictness_for`/`update_from_tx_with_strictness`, no `StateRootUnavailable` fail-closed root check and no `replay_stats` counters. Since the crate root re-exports `ledger_9` as the latest version, that is the copy every caller actually gets. Assisted-by: Claude:claude-opus-5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> --------- Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
…ers (#2075) * refactor(toolkit): give each ledger version its own copy of the builders `tx_generator/builder/builders/common/**` and `commands/fork/common/**` were each compiled twice via a `#[path = "common"] pub mod inner { … }` trick, once bound to the ledger-8 helpers and once to the ledger-9 helpers, with `ledger_helpers_local` resolving differently in each instantiation. A reader of a file under `common/` could not tell which ledger version it was looking at, and an edit meant for one version silently applied to both. This finishes the job #2059 and the ledger-helpers split started. Each version now has its own directory — `builders/{ledger_8,ledger_9}/` and `commands/fork/{ledger_8,ledger_9}/` — and each file names its own version with a `use midnight_node_ledger_helpers::ledger_N as ledger_helpers_local;` line, so the two copies stay byte-identical apart from that one word and `diff -r` can police them. The only genuine divergence left is `builders/*/mod.rs`, which carries the per-version `serialize_tx`. The `inner` wrapper module is gone (nothing referenced it), so every external path — `builders::ledger_8::SingleTxBuilder`, `fork::ledger_9::show_wallet`, … — is unchanged, as is the CLI surface. `impl_encoded_zswap_conversions!` stays in `builders/mod.rs`: `ledger_storage` still aliases to `ledger_storage_ledger_8` in both versions, so duplicating the impls per version would still hit E0119. With this, `grep -r '#\[path' --include='*.rs'` over the workspace returns nothing, and no directory is compiled more than once. Assisted-by: Claude:claude-opus-5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * chore: add PR link to toolkit change file Assisted-by: Claude:claude-opus-5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> --------- Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.86.7 to 2.87.0. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](taiki-e/install-action@b6ff580...37f7c57) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.87.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
Bumps [anchore/sbom-action/download-syft](https://github.com/anchore/sbom-action) from 0.24.0 to 0.24.1. - [Release notes](https://github.com/anchore/sbom-action/releases) - [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md) - [Commits](anchore/sbom-action@e22c389...aa80c8c) --- updated-dependencies: - dependency-name: anchore/sbom-action/download-syft dependency-version: 0.24.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
* fix: bump ledger 8 to 8.1.2 and ledger 9 to 9.1.0.0-rc.5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * chore: add pr link to change files Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * Update changes/node/changed/bump-ledger-9.1.0.0-rc.5.md Co-authored-by: Lech Głowiak <LGLO@users.noreply.github.com> Signed-off-by: Squirrel <giles.cope@shielded.io> * Apply suggestion from @gilescope Signed-off-by: Squirrel <giles.cope@shielded.io> --------- Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> Signed-off-by: Squirrel <giles.cope@shielded.io> Co-authored-by: Squirrel <giles.cope@shielded.io> Co-authored-by: Lech Głowiak <LGLO@users.noreply.github.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
…ck migration (#2079) * fix(runtime): enter safe mode instead of freezing on failed multi-block migration A failed MBM previously left the migration cursor Stuck forever: only inherents were admitted into blocks and can_set_code rejected runtime upgrades - a permanent liveness failure with no on-chain recovery on a standalone chain. Upstream's EnterSafeModeOnFailedMigration returns KeepStuck and does not help (paritytech/polkadot-sdk#12921). Add pallet-safe-mode at the reserved index 20 and a custom FailedMigrationHandler that enters safe mode indefinitely and returns ForceUnstuck (falling back to freezing if entry fails). While in safe mode, BaseCallFilter admits only the inherents (required for block validity) and the existing governance allowlist, so governance can ship a fixed runtime and force_exit safe mode. Zero behavior change until a migration actually fails. CurrencyWaiver's hold Reason is retargeted from pallet_session's HoldReason to the composite RuntimeHoldReason to satisfy safe-mode's Currency bound; deposits are disabled, so it stays typecheck-only. Assisted-by: Claude:claude-fable-5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * fix(runtime): whitelist federated motion calls in safe mode The collectives dispatch an approved proposal with their (non-Root) Members origin, which goes through BaseCallFilter. Without FederatedAuthority::motion_approve in the safe-mode whitelist neither body could record an approval, so no motion could ever be closed to dispatch a fixed runtime as Root - the recovery flow this change exists to provide. Whitelist motion_approve and motion_revoke; both are origin-gated to the collective proportion origins, so this adds no exposure for signed or unsigned traffic. Add an end-to-end regression test driving the full recovery flow while in post-failure safe mode: propose/vote/close in both collectives, motion_close dispatching System::authorize_upgrade as Root, then force_exit. The test fails without the whitelist fix. Addresses PR review feedback. Assisted-by: Claude:claude-fable-5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * chore: rebuild metadata Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * chore: rebuild metadata Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> --------- Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
…4.1 (#2089) Bumps [anchore/scan-action/download-grype](https://github.com/anchore/scan-action) from 7.4.0 to 7.4.1. - [Release notes](https://github.com/anchore/scan-action/releases) - [Changelog](https://github.com/anchore/scan-action/blob/main/RELEASE.md) - [Commits](anchore/scan-action@e116508...8964e60) --- updated-dependencies: - dependency-name: anchore/scan-action/download-grype dependency-version: 7.4.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
…ht in #2059 renames `ledger/src/versions/common/**` onto `ledger_8/` but *adds* the `ledger_9/` copy, so ledger_8 arrives with this branch's content while ledger_9 arrives with main's. That pulled `serialize_ledger_snapshot` and `import_ledger_snapshot` into `ledger_9/mod.rs` — both from #1650 (warp-sync ledger arena), one of the 16 commits #2023 deliberately excluded. They reference `crate::SnapshotImportError`, which #1650 defines in `ledger/src/lib.rs` and this branch therefore does not have, so the workspace did not compile. Nothing calls either function on this branch. Removing them restores the parity #2059 is about: `diff -r ledger/src/ledger_8 ledger/src/ledger_9` now differs only in the version-binding aliases and docs. Assisted-by: Claude:claude-opus-5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
…raits (#2080) * fix: split system transaction executor into per-pallet allow-listed traits Replace the single MidnightSystemTransactionExecutor trait with MidnightSystemTransactionCNightExecutor and MidnightSystemTransactionBridgeExecutor, so pallet-cnight-observation and pallet-c2m-bridge can each only submit the SystemTransaction variants they actually construct, instead of being able to pass through any variant the ledger recognizes. Each new trait is backed by a dedicated ledger host function (apply_cnight_system_transaction / apply_bridge_system_transaction) that deserializes once and checks its allow-list before applying, rather than a separate classifier call ahead of apply_system_transaction. The governance extrinsic path is rebuilt the same way onto a new apply_governance_system_transaction host function. The previous apply_system_transaction and is_governance_allowed_system_tx host functions are kept in place, unused by new code, since they remain part of the node<->runtime ABI for already-published runtime WASM and historical block replay. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * chore: add PR link to system-tx-executor-allow-lists change file Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * chore: rebuild metadata Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * chore: rebuild metadata Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * chore: rebuild metadata Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * fix: switch system tx apply log to debug Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> * docs: remove comment Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com> --------- Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6e9e4f33d4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Signed-off-by: Squirrel <giles.cope@shielded.io>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
#1851) Signed-off-by: Lech Głowiak <lech.glowiak@shielded.io>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Giles Cope <gilescope@gmail.com>
|
The 3 are now included. Apologies for including incorrect babe docs, these have been reverted in the last commit. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 402b3555cf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Awesome work @gilescope ! |
Overview
Follow-up to #2023, which brought
release/node-2.1.0in line withmainup toe029b0a9a. This picks up the 39 commits that have landed onmainsince(
e029b0a9a..24e296a2a): 7 are already on the branch as individual backports(#1999, #2031, #2030, #2022, #2012, #2054, and the #2062 revert), 27 come
across and 5 do not.
Selection follows #2023's rule — a fix or maintenance change comes across, a
feature does not, with an exception for anything that makes the hardfork itself
testable — widened in three places by explicit request:
midnightntwrk's registries.
are no-behaviour-change, but leaving them out makes every later backport that
touches
ledger/,ledger/helpers/orutil/toolkit/src/tx_generator/builderconflict on paths rather than content.
Why these belong on a mainnet release
multi-block migration (
VersionedMigration<1,2>, plus feat: reset Dust state and re-apply cNight UTxOs during migration #2012's cNIGHT dustre-apply). Today a failure leaves the cursor
Stuck: only inherents areadmitted and
can_set_coderejects upgrades, with no on-chain recovery on astandalone chain. fix(runtime): enter safe mode instead of freezing on failed multi-block migration #2079 enters safe mode and force-unstucks instead.
checkpoint past a transfer that failed execution or serialization, retrying it
in the next block instead.
snapshots were never saved below ledger 9, so every mainnet run replayed from
genesis. Mainnet is ledger 8, which is exactly what the fork rehearsal
replays.
The 5 exclusions
feat: report BABE key presence in the keystore— BABE-family; #2023 excluded all 12 BABE commits and this branch has no BABE consensus.Update version to v3.0.0— would renumber this release..github/ISSUE_TEMPLATE/from the default branch..claude/skills/create-bug— no product effect.mainchecking out this branch's beta.1 metadata blob.None carries exclusion risk.
Commits were applied in
main's order, which satisfies every orderingconstraint on its own: #2047 needs #2021 first (both touch
tree-cache-guard/save), #2086 needs #2044 and #2048 first (attest pin, imagelayers), and #1938 sits between #2059 and #2074 so the pre- and post-split
ledger/helperspaths resolve themselves.Deviations from a straight cherry-pick
ledger_9— fixed in a follow-up commit.The refactor renames
ledger/src/versions/common/**ontoledger_8/butadds the
ledger_9/copy, so ledger_8 arrives with this branch's contentwhile ledger_9 arrives with
main's. That pulledserialize_ledger_snapshotand
import_ledger_snapshotintoledger_9/mod.rs, both from Add ledger arena for warp sync #1650(warp-sync ledger arena) — one of the 16 commits chore: backport ledger 8->9 hardfork plus two months of maintenance #2023 excluded. They
reference
crate::SnapshotImportError, which Add ledger arena for warp sync #1650 defines inledger/src/lib.rsand this branch does not have, so the workspace did notcompile. Nothing calls either function here; removing them restores the
parity refactor(ledger): give each ledger version its own wrapper #2059 is about (
diff -r ledger/src/ledger_8 ledger/src/ledger_9nowdiffers only in version-binding aliases and docs). This is the one commit
in the stack that is not a pick — please review it directly.
authority_keysscaffolding. Its
runtime/src/lib.rshunk carries thesidechain_slot_number/sidechain_status/slot_configtest modulesalongside
failed_mbm_recovery; the first three needpallet_consensus_engineand were left out.
runtime/src/migrations.rsis empty on this branch apartfrom its header, so the whole of
main's file came into the conflict — onlyEnterSafeModeAndUnstuckOnFailedMigrationwas taken. Theauthority_keysscaffolding that came with it is explicitly dead ("nothing here is wired into
SingleBlockMigrations"), is unrelated to this fix, and needs apub mod authority_keysthis branch's vendored partner-chains does not have.SafeModetakes pallet index 20, which is free here.configurations/readme.mddeleted. That file does not existon this branch: it was created by feat(local-environment): prepare for several BABE scenarios #1828, one of the excluded BABE commits, and
documents AURA→BABE keystore scenarios. Only its
midnight-node-6paragraphwas relevant, and that is already in
local-environment/README.md, which tookthe incoming version.
metadata/static/*.scaleconflicts resolved to ours — see theTODO below.
midnight_metadata_3.0.0.scaleis deliberately not createdhere; it belongs to Update version to v3.0.0 #2085, which is excluded.
Routine conflict classes were resolved by #2023's standing rules: the local-env
contract-compiler Dockerfile kept ours, since this branch deliberately unpins the
apt versions upstream keeps bumping.
🗹 TODO before merging
/bot rebuild-metadata— fix: c2m-bridge hardening: do not skip failed transfers and retry in the next block instead #1980 (bridge checkpoint variant), fix(runtime): enter safe mode instead of freezing on failed multi-block migration #2079(
SafeModeat pallet index 20) and refactor(ledger): give each ledger version its own wrapper #2059 all move the metadata surface,and every
.scaleconflict was resolved to ours, somidnight_metadata.scaleandmidnight_metadata_2.1.0.scaleare stale.📌 Submission Checklist
git commit -s) for the DCO🧪 Testing Evidence
Run locally against the full 28-commit stack:
cargo check --workspace --all-targets— cleancargo fmt --all --check— cleancargo clippy --workspace --all-targets— cleanThe first
cargo checkis what caught deviation (1): it failed withunresolved import crate::SnapshotImportErrorinledger/src/ledger_9/mod.rs,which is how the #1650 leak was found rather than shipped.
Not run locally, left to CI:
hardfork_e2e(needs a branch-builtNODE_IMAGE;with it unset the test resolves to the registry's
latest-mainand exercisesmain, not this branch) and the Local Environment Tests.🔱 Fork Strategy
Two runtime-visible items:
pallet-safe-modeat index 20 and swaps theFailedMigrationHandler. Until a migration actually fails, behaviour isunchanged. Once one does, the chain keeps producing blocks with user calls
filtered to inherents plus the governance allowlist, so governance can ship a
fixed runtime and
force_exit.BridgeDataCheckpoint::TxReserveTransfervariant so a checkpoint can sitbetween the two transfers of one Cardano transaction.
Both need the metadata rebuild noted above.
#2096 is a consensus-relevant ledger bump. 8.1.2 accepts strictly less than
8.1.1, so it must be deployed before any peer relies on the stricter decoding.
Links
33fce6874..e029b0a9a)e029b0a9a..24e296a2aonmainAssisted-by: Claude:claude-opus-5