Skip to content

Complete Plutus V4 support and remove Conway hardcodes - #1452

Merged
carbolymer merged 1 commit into
masterfrom
mgalazyn/feature/plutus-v4-scripts
Oct 16, 2026
Merged

carbolymer merged 1 commit into
masterfrom
mgalazyn/feature/plutus-v4-scripts

Conversation

@carbolymer

@carbolymer carbolymer commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Context

The issue asks for cardano-cli to support Plutus V4 scripts:

Most of that work was merged with #1453.
It bumped cardano-api to 11.9.0.0, added the --*-plutus-script-v4 reference script flags to the Dijkstra commands, and let hash script read Plutus V4 scripts.
This PR covers the rest of the issue and builds on #1408.

hash script, transaction policyid --script-file and address build with --payment-script-file or --stake-script-file now read scripts through one helper, readAnyScriptHash.
It decodes the script in cardano-api's newest era (maxBound :: Some Era) and returns only the era-independent script hash.
So transaction policyid and address build now accept Plutus V4 scripts.
They also accept simple scripts with a guard, which used to stop them with toAllegraTimelock: RequireGuard is only supported from the Dijkstra era onwards.
They used to fail with "Plutus language PlutusScriptV4 is not supported in the Conway era", as hash script did before #1453.

A transaction output with a reference script in a Plutus language that the era does not support now fails with cardano-api's TxOutputReferenceScriptLanguageNotSupportedInEra error.
Before this change, readRefScript dropped such a script from the output without telling the user, for example a Plutus V4 script in a Conway transaction.
cardano-api's own check, validateTxOutsReferenceScripts, is not exported, so readRefScript repeats it with toScriptInEra.

The PR also removes two Conway hardcodes:

  • CARDANO_ERA=dijkstra crashed every command, --version included, with "Unknown era: dijkstra". The variable is now parsed with cardano-api's era enumeration and names, so every era cardano-api knows is accepted in any letter case, and an unknown value stops the command with an error that lists the valid eras.
  • The latest command group and the top-level node and query groups now use a MainnetEra alias, which is still Conway. At the hard fork only the alias changes, and the latest help text takes the era name from it.

Closes #1448.

One gap is outside cardano-cli: a Plutus V4 auxiliary script is dropped when a Dijkstra transaction is read back, until a cardano-ledger-dijkstra release with this change reaches CHaP:

How to trust this PR

The Plutus V4 changes have golden tests:

  • dijkstra transaction build-raw takes the V4 script file as a direct witness for all six script purposes, and debug transaction view shows plutus version: PlutusV4 for it.
  • hash script and transaction policyid give the same hash for the V4 script.
  • address build works with a V4 payment script and with a V4 stake script.
  • conway transaction build-raw with a V4 reference script fails with the new error.

The fixture v4-always-succeeds.plutus is an always-succeeds validator; compiled against PlutusLedgerApi.V4 it has the same bytes as the V3 version.
For V1, V2, V3 and native scripts, transaction policyid and address build give the same output as before.
The CARDANO_ERA fix and the guard-script case were checked by hand, before and after the change, and have no automated tests.
MainnetEra changes no output, and all help goldens are unchanged.

Checklist

  • Commit sequence broadly makes sense and commits have useful messages
  • New tests are added if needed and existing tests are updated. See Running tests for more details
  • Self-reviewed the diff
  • Changelog fragment added in .changes/

@carbolymer carbolymer self-assigned this Sep 25, 2026
@carbolymer
carbolymer force-pushed the mgalazyn/feature/plutus-v4-scripts branch from d8466db to 8ef9c2d Compare September 25, 2026 09:28
@carbolymer carbolymer changed the title Add Plutus V4 support Add Plutus V4 reference script witness flags Sep 25, 2026
@carbolymer
carbolymer force-pushed the mgalazyn/feature/plutus-v4-scripts branch from 8ef9c2d to d193e61 Compare September 25, 2026 13:33
@carbolymer
carbolymer force-pushed the mgalazyn/feature/plutus-v4-scripts branch 4 times, most recently from 01979c5 to 389f27d Compare October 9, 2026 10:47
@carbolymer
carbolymer changed the base branch from master to mgalazyn/feature/update-compatible-tx October 9, 2026 10:48
@carbolymer
carbolymer added this pull request to stack #1458 October 9, 2026 10:48
@carbolymer
carbolymer force-pushed the mgalazyn/feature/plutus-v4-scripts branch from 389f27d to d349d1d Compare October 14, 2026 16:54
@carbolymer
carbolymer removed this pull request from stack #1458 October 14, 2026 16:55
@carbolymer
carbolymer added this pull request to stack #1466 October 14, 2026 16:56
@carbolymer carbolymer linked an issue Oct 14, 2026 that may be closed by this pull request
3 tasks
@carbolymer
carbolymer force-pushed the mgalazyn/feature/plutus-v4-scripts branch from d349d1d to a76317a Compare October 15, 2026 06:31
@carbolymer carbolymer changed the title Add Plutus V4 reference script witness flags Complete Plutus V4 support for script readers and reference scripts Oct 15, 2026
@carbolymer
carbolymer force-pushed the mgalazyn/feature/plutus-v4-scripts branch from a76317a to c1fa806 Compare October 15, 2026 07:14
@carbolymer
carbolymer force-pushed the mgalazyn/feature/plutus-v4-scripts branch from c1fa806 to 1740c08 Compare October 15, 2026 07:54
@carbolymer carbolymer changed the title Complete Plutus V4 support for script readers and reference scripts Complete Plutus V4 support and remove Conway hardcodes Oct 15, 2026
@carbolymer
carbolymer force-pushed the mgalazyn/feature/plutus-v4-scripts branch from 1740c08 to 81df3c9 Compare October 15, 2026 08:09
@carbolymer
carbolymer force-pushed the mgalazyn/feature/plutus-v4-scripts branch from 81df3c9 to 642d7a0 Compare October 15, 2026 08:09
@carbolymer
carbolymer force-pushed the mgalazyn/feature/plutus-v4-scripts branch 2 times, most recently from 5411875 to f85ccf6 Compare October 15, 2026 08:33
@carbolymer
carbolymer marked this pull request as ready for review October 15, 2026 08:57
Copilot AI balanced review requested due to automatic review settings October 15, 2026 08:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

Static review found no blocking defects; the remaining diagnostic refinement is non-blocking, and tests were not executed.

1 open finding
What changed in this PR

Completes CLI-side Plutus V4 support following #1453 and centralizes era selection without changing the current mainnet default.

Changes:

  • Shares script hashing across hash, policy ID, and address commands.
  • Rejects unsupported reference-script languages and accepts all known CARDANO_ERA names.
  • Adds V4 regression tests, fixtures, and changelog entries.
File Description
cardano-cli/​test/​cardano-cli-golden/​Test/​Golden/​Shelley/​Transaction/​Build.hs Tests V4 policy IDs.
cardano-cli/​test/​cardano-cli-golden/​Test/​Golden/​Shelley/​Address/​Build.hs Tests V4 payment and stake addresses.
cardano-cli/​test/​cardano-cli-golden/​Test/​Golden/​Hash/​Hash.hs Tests V4 script hashing.
cardano-cli/​test/​cardano-cli-golden/​Test/​Golden/​Dijkstra/​Transaction/​BuildRaw.hs Tests all six V4 witness purposes.
cardano-cli/​test/​cardano-cli-golden/​Test/​Golden/​Conway/​Transaction/​ReferenceScript.hs Tests unsupported reference-script rejection.
cardano-cli/​test/​cardano-cli-golden/​files/​input/​dijkstra/​plutus/​v4-always-succeeds.plutus Adds V4 script fixture.
cardano-cli/​test/​cardano-cli-golden/​files/​golden/​dijkstra/​transaction/​build-raw-plutus-v4-script-witnesses.out Records V4 transaction output.
cardano-cli/​test/​cardano-cli-golden/​files/​golden/​dijkstra/​plutus/​v4-always-succeeds.hash Records expected script hash.
cardano-cli/​test/​cardano-cli-golden/​files/​golden/​dijkstra/​address/​build-stake-script-v4.addr Records V4 stake-script address.
cardano-cli/​test/​cardano-cli-golden/​files/​golden/​dijkstra/​address/​build-payment-script-v4.addr Records V4 payment-script address.
cardano-cli/​test/​cardano-cli-golden/​files/​golden/​conway/​transaction/​build-raw-reference-script-unsupported-language.out Records rejection diagnostic.
cardano-cli/​src/​Cardano/​CLI/​Read.hs Adds newest-era script-hash reader.
cardano-cli/​src/​Cardano/​CLI/​Option.hs Uses mainnet alias for top-level commands.
cardano-cli/​src/​Cardano/​CLI/​EraIndependent/​Hash/​Run.hs Uses shared hash reader.
cardano-cli/​src/​Cardano/​CLI/​EraIndependent/​Address/​Run.hs Uses shared reader for script credentials.
cardano-cli/​src/​Cardano/​CLI/​EraBased/​Transaction/​Run.hs Uses shared reader for policy IDs.
cardano-cli/​src/​Cardano/​CLI/​EraBased/​Option.hs Defines mainnet alias and derives help text.
cardano-cli/​src/​Cardano/​CLI/​Environment.hs Parses known eras case-insensitively.
cardano-cli/​src/​Cardano/​CLI/​Compatible/​Transaction/​TxOut.hs Rejects unsupported reference scripts.
cardano-cli/​cardano-cli.cabal Registers new test modules.
.changes/​reference-script-unsupported-language.yml Documents reference-script rejection.
.changes/​plutus-v4-script-witnesses.yml Documents V4 regression coverage.
.changes/​plutus-v4-script-readers.yml Documents expanded script-reader support.
.changes/​cardano_era_all_eras.yml Documents environment-era parsing.
.changes/​20261015_120100_cardano-cli_mateusz.galazyn_read-any-script-hash.yml Documents shared reader and era alias.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +142 to +145
scriptInEra <-
fromMaybeCli
(TxOutputReferenceScriptLanguageNotSupportedInEra script (anyCardanoEra $ toCardanoEra sbe))
$ toScriptInEra sbe script

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The rejection itself is correct: a native script with a guard is only valid from Dijkstra onwards, so a Conway output cannot carry it, and the transaction is rejected at build time.
The message names the script language because cardano-api's toScriptInEra only returns Nothing, and its simpleScriptHasGuard check is not exported.
A guard-specific message is better added in cardano-api than by copying that traversal into cardano-cli, so I'm leaving it as is here.

@carbolymer
carbolymer force-pushed the mgalazyn/feature/plutus-v4-scripts branch from f85ccf6 to b1a7451 Compare October 16, 2026 10:30
@carbolymer
carbolymer force-pushed the mgalazyn/feature/plutus-v4-scripts branch 2 times, most recently from b149a30 to e972489 Compare October 16, 2026 12:30
Base automatically changed from mgalazyn/feature/update-compatible-tx to master October 16, 2026 12:30
A transaction output whose reference script is in a Plutus language the
era does not support used to lose the script silently. Fail with
cardano-api's `TxOutputReferenceScriptLanguageNotSupportedInEra` error
instead, using the same `toScriptInEra` check as cardano-api's
`validateTxOutsReferenceScripts`, which is not exported.

Read script files for `hash script`, `transaction policyid` and
`address build` `--payment-script-file` and `--stake-script-file` in
cardano-api's newest era, so they accept Plutus V4 scripts instead of
failing with "not supported in the Conway era".

Add Plutus V4 golden tests:
- a V4 script file as a direct witness for all six script purposes in
  `dijkstra transaction build-raw`, checked with `debug transaction view`
- hashing a V4 script with `hash script`
- `transaction policyid` and `address build` with a V4 script
- the error for a V4 reference script in a Conway transaction

Parse `CARDANO_ERA` by reusing cardano-api's era enumeration and
rendering instead of a hand-written string table, so newer eras such as
dijkstra are accepted. An unknown value still stops the command,
now with an error that lists the valid eras.

The latest command group and the top-level node and query command groups
follow the era running on mainnet. A MainnetEra alias names that choice,
so the hard fork changes one line.
@carbolymer
carbolymer force-pushed the mgalazyn/feature/plutus-v4-scripts branch from e972489 to 74d9021 Compare October 16, 2026 12:30
@carbolymer
carbolymer merged commit 3aecd3d into master Oct 16, 2026
16 checks passed
@carbolymer
carbolymer deleted the mgalazyn/feature/plutus-v4-scripts branch October 16, 2026 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ensure Plutus V4 scripts can be deserialised by cardano-cli

3 participants