Skip to content

feat(runtime): gate the tblock correction on a runtime upgrade - #2002

Merged
gilescope merged 13 commits into
release/node-1.0.3from
ozgb-1.0.2-runtime-upgrade
Aug 13, 2026
Merged

feat(runtime): gate the tblock correction on a runtime upgrade#2002
gilescope merged 13 commits into
release/node-1.0.3from
ozgb-1.0.2-runtime-upgrade

Conversation

@ozgb

@ozgb ozgb commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Overview

Modifies the fix for #1924 so it's triggered via a runtime upgrade rather than a timestamp.

Also includes #1900, to prepare for the upcoming hard-fork release (Node 2.1.0)

🗹 TODO before merging

  • Ready
  • Rebuild metadata

📌 Submission Checklist

  • All commits are signed off (git commit -s) for the DCO
  • Changes are backward-compatible (or flagged if breaking)
  • Pull request description explains why the change is needed
  • Self-reviewed the diff
  • I have included a change file, or skipped for this reason:
  • If the changes introduce a new feature, I have bumped the node minor version
  • Update documentation (if relevant)
  • Updated AGENTS.md if build commands, architecture, or workflows changed
  • No new todos introduced

🧪 Testing Evidence

Please describe any additional testing aside from CI:

  • Additional tests are provided (if possible)

🔱 Fork Strategy

  • Node Runtime Update
  • Node Client Update
  • Other:
  • N/A

Links

#1924

The tblock correction — verifying a block's first ledger transaction at
`parent_block_time + 12s` so historical blocks still import — switched itself
off at a hardcoded date. That date had to be pushed back indefinitely or
syncing from genesis would break, and both it and the offset were
consensus-critical values read from node config, where one validator with a
different `default.toml` verifies historical blocks differently from its peers.

Gate it on the on-chain runtime instead. Version 1 of the `Ledger8Bridge`
`apply_transaction` and `validate_guaranteed_execution` host functions applies
the correction; version 2, added here, does not. Historical blocks replay
against whichever runtime was on-chain at that height, so pre-upgrade wasm
imports v1 and still corrects, while every block from the `set_code` onward is
verified against its own timestamp.

The offset is hardcoded at 12s (`slot_duration_secs * (1 + MaxSkippedSlots)`,
fixed for every chain the correction can apply to), and
`tblock_correction_offset` / `tblock_correction_disable_after` are removed from
node config along with the externalities extension that carried them.

`spec_version` is bumped to 001_000_002. All validators must run node 1.0.2
before the upgrade is enacted — an older node cannot instantiate a runtime that
imports `ext_ledger_8_bridge_apply_transaction_version_2`.

Issue: #1924

Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
@ozgb
ozgb requested a review from a team as a code owner August 6, 2026 12:34
ozgb and others added 3 commits August 6, 2026 13:34
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
Signed-off-by: Tomasz Bartos <tomasz.bartos@shielded.io>
Co-authored-by: Lech Głowiak <LGLO@users.noreply.github.com>
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
# Conflicts:
#	metadata/static/midnight_metadata.scale
#	metadata/static/midnight_metadata_2.1.0.scale
#	runtime/src/lib.rs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6b68321a31

ℹ️ 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".

Comment thread ledger/src/versions/common/mod.rs
Comment thread partner-chains/demo/runtime/src/lib.rs
Included accidentally via a bad merge conflict resolution

Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
@datadog-official

This comment has been minimized.

Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4576164f43

ℹ️ 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".

Comment thread runtime/src/lib.rs Outdated
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
@ozgb ozgb added the bot:ai-assisted Authored or substantially edited by an AI agent label Aug 6, 2026
ozgb added 2 commits August 10, 2026 16:31
The strict cache key carried `block_context.tblock`, but `well_formed` is
called with `well_formed_tblock(...)`, which skews a block's first transaction
to `parent_block_time + 12s` under host-function v1 and leaves it alone under
v2. Both versions can run in one process — historical replay against the
pre-upgrade wasm alongside current blocks, and the pallet tests that call v1
directly while driving v2 through the current runtime — so whichever populated
the cache first could hand the other a `VerifiedTransaction` verified at the
wrong timestamp.

Key on the resolved timestamp instead, via a single `strict_cache_key` helper
shared by both key sites, and read the tblock back off the key when calling
`well_formed` so the key and the verification cannot drift apart. The versions
only get separate entries where they actually verify differently; when the
correction is inert they still share one.

Issue: #1924

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>
@ozgb
ozgb changed the base branch from release/node-1.0.2 to release/node-1.0.3 August 11, 2026 12:15
ozgb added 4 commits August 11, 2026 13:21
The pinned Debian versions (jq, curl, ca-certificates, vim, unzip) have
been superseded in the bookworm archive, so apt-get install fails with
exit code 100 and takes down the Local Environment Tests job.

Cherry-picks the Dockerfile hunk from f04a980 (#1865) on main, which
dropped the pins and bumped the node:22-slim digest.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
The pinned midnight-reserve-contracts revision invokes
`bunx @blaze-cardano/blueprint@latest`, which now resolves to 0.9.0. That
generator emits `import { TypedScript } from "@blaze-cardano/tx"`, a symbol
only present from tx@0.15.0 — but the contracts' bun.lock pins tx@0.14.1, so
`bun cli deploy` dies with "Export named 'TypedScript' not found".

Backport of midnight-reserve-contracts 424f7f94 until the pinned contracts
revision is bumped past it.

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>
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
@gilescope
gilescope merged commit 026b31e into release/node-1.0.3 Aug 13, 2026
30 checks passed
@gilescope
gilescope deleted the ozgb-1.0.2-runtime-upgrade branch August 13, 2026 05:05
efekrbas pushed a commit to efekrbas/midnight-node that referenced this pull request Aug 19, 2026
…ghtntwrk#2031)

* feat(runtime): gate the tblock correction on a runtime upgrade

The tblock correction — verifying a block's first ledger transaction at
`parent_block_time + 12s` so historical blocks still import — switched itself
off at a hardcoded date. That date had to be pushed back indefinitely or
syncing from genesis would break, and both it and the offset were
consensus-critical values read from node config, where one validator with a
different `default.toml` verifies historical blocks differently from its peers.

Gate it on the on-chain runtime instead. Version 1 of the `Ledger8Bridge`
`apply_transaction` and `validate_guaranteed_execution` host functions applies
the correction; version 2, added here, does not. Historical blocks replay
against whichever runtime was on-chain at that height, so pre-upgrade wasm
imports v1 and still corrects, while every block from the `set_code` onward is
verified against its own timestamp. The `Ledger9Bridge` host functions never
skew: every ledger-9 block is produced after the upgrade that closed the
loophole.

The offset is hardcoded at 12s (`slot_duration_secs * (1 + MaxSkippedSlots)`,
fixed for every chain the correction can apply to), and
`tblock_correction_offset` / `tblock_correction_disable_after` are removed from
node config along with the externalities extension that carried them.

Backport of midnightntwrk#2002 onto main. `spec_version` is not bumped here — main's runtime
is already at 002_001_000, a new spec version in its own right. All validators
must run a node that exports
`ext_ledger_8_bridge_apply_transaction_version_2` before that upgrade is
enacted; an older node cannot instantiate a runtime importing it.

The pallet's version-1 tests do not carry over: the pallet runs ledger 9, whose
host functions have no version 1. The split is covered by the
`well_formed_tblock` and `strict_cache_key` unit tests in `midnight-node-ledger`.

Issue: midnightntwrk#1924

Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>

* fix(ledger): key the strict cache on the tblock well_formed was given

The strict cache key carried `block_context.tblock`, but `well_formed` is
called with `well_formed_tblock(...)`, which skews a block's first transaction
to `parent_block_time + 12s` under host-function v1 and leaves it alone under
v2. Both versions can run in one process — historical replay against the
pre-upgrade wasm alongside current blocks, and the pallet tests that call v1
directly while driving v2 through the current runtime — so whichever populated
the cache first could hand the other a `VerifiedTransaction` verified at the
wrong timestamp.

Key on the resolved timestamp instead, via a single `strict_cache_key` helper
shared by both key sites, and read the tblock back off the key when calling
`well_formed` so the key and the verification cannot drift apart. The versions
only get separate entries where they actually verify differently; when the
correction is inert they still share one.

Issue: midnightntwrk#1924

Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>

* fix(toolkit): add support for the 1.0.3 runtime

The block fetcher rejects any `spec_version` it does not know, so blocks produced by the 1.0.3
runtime (`001_000_003`) fail with `UnsupportedBlockVersion`. Bundle that runtime's metadata and
map it like the others.

Backport of midnightntwrk#2002 (189e581).

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>
@ozgb ozgb mentioned this pull request Aug 21, 2026
15 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:ai-assisted Authored or substantially edited by an AI agent skip-changes-check-all

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants