Skip to content

Van Rossem integration#2

Draft
johnalotoski wants to merge 28 commits into
setup-for-hydrafrom
jmiller/dijkstra-integration
Draft

Van Rossem integration#2
johnalotoski wants to merge 28 commits into
setup-for-hydrafrom
jmiller/dijkstra-integration

Conversation

@johnalotoski
Copy link
Copy Markdown

  • WIP

@johnalotoski johnalotoski force-pushed the jmiller/dijkstra-integration branch from b5b5a01 to 9149a32 Compare May 27, 2026 01:33
@snarlysodboxer snarlysodboxer force-pushed the setup-for-hydra branch 11 times, most recently from c3abc83 to 05447e3 Compare May 27, 2026 05:26
johnalotoski and others added 17 commits May 27, 2026 01:22
Removes the three CardanoSolutions/* source-repository-package forks
(cardano-ledger, ouroboros-network, ouroboros-consensus) whose
GetDRepDelegations / NodeToClientV_21 / queryDRepDelegations patches
are now upstream in ouroboros-consensus 3.0.1, ouroboros-network 1.1,
and cardano-ledger-conway 1.22.1. Adds `blockio +serialblockio` to
drop the liburing system dependency.
Carries the bare scaffolding the rest of the integration needs:

- cardano-ledger-dijkstra added to package.yaml / ogmios.cabal so
  Dijkstra types (DijkstraEra, DijkstraNativeScript, DijkstraTxCert,
  etc.) are reachable from the project sources.
- New GADT arms ShelleyBasedEraDijkstra / AlonzoBasedEraDijkstra,
  matching IsAlonzoBasedEra instance, lift in ToShelleyBasedEra, and
  JSON arm in SomeShelleyEra so era dispatch tables can fan out to a
  Dijkstra branch.
- Minor follow-on touches in Ogmios.Data.Ledger and
  Ogmios.Data.Ledger.ScriptFailure to keep them compiling against the
  expanded singletons.
EraTranslation gains Upgrade instances for the Conway -> Dijkstra
boundary on BabbageTxOut, UTxO, and (Tx TopTx). The pre-bump
AlonzoTx Upgrade instance is removed in favour of the generic
ledger Tx, since AlonzoTx's kind picked up a TxLevel parameter in
cardano-ledger 1.20 and the old instance head no longer
kind-checks.

Data.Protocol.TxSubmission's mergeUtxo / union / withoutKeys /
inputs / outputs gain Dijkstra arms. Both mergeUtxo and union now
enumerate all nine (left, right) era combinations explicitly: the
prior wildcard fallbacks silently dropped the non-Dijkstra side's
UTxO entries whenever one side was Dijkstra, which lost mempool
output information across the Conway / Dijkstra boundary. Each
Babbage <-> Dijkstra crossing chains upgrade . upgrade through
Conway; each Conway <-> Dijkstra crossing is a single upgrade.
App.Protocol.TxSubmission's evaluateExecutionUnitsM gets the full
nine-way (UTxOIn*Era, GenTx*) case fan-out for the {Babbage, Conway,
Dijkstra} cross product, each cross-era arm chaining upgrade
appropriately (single upgrade on the Conway boundary, upgrade .
upgrade across the Babbage / Dijkstra boundary). The Dijkstra-era
script-evaluation branch is wired into clientStAcquired's selectEra
fall-through, and CanEvaluateScriptsInEra DijkstraEra plus
HoistQuery Praos DijkstraEra propagate through the callback chain.

App.Protocol.TxMonitor's inMultipleEras rotation drops Babbage as
the floor and adds GenTxIdDijkstra at the top of the search order;
keepRedundantConstraint is re-armed against
MostRecentEra (CardanoBlock crypto) ~ DijkstraEra so the next era
introduction will surface here as a build error.

Cardano.Network.Protocol.NodeToClient picks up a small Dijkstra
handler bit needed by the above.
New Ogmios.Data.Json.Dijkstra module providing the Dijkstra-side
JSON encoders, all era-polymorphic with TxCert era / NativeScript
era / PlutusPurpose AsIx era equality constraints to pin the era
where it matters:

  - encodeNativeScript / encodeScript / encodeTxOut
  - encodeDelegCert / encodeTxCert
  - encodeScriptPurposeItem / encodeScriptPurposeIndex
  - encodeGovAction
  - encodeContextError

Each follows the same shape as the corresponding Conway / Babbage
encoder, adding the new Dijkstra-only constructors as required:

  - DijkstraRequireGuard in encodeNativeScript
  - DijkstraGuarding in both script-purpose encoders (purpose:
    "guard")
  - PointerPresentInOutput in encodeContextError (pointer addresses
    are no longer supported in Dijkstra)
  - ReferenceInputsNotDisjointFromInputs in encodeContextError
    (newly surfaced in cardano-ledger-conway 1.22+)

The "parameters" field inside encodeGovAction's ParameterChange arm
is left as `error "TODO(dijkstra): encodePParamsUpdate for
Dijkstra"` for now; cardano-ledger-dijkstra introduces its own
DijkstraPParams (not ConwayPParams), and Conway's encodePParamsHKD
is itself a stub in this branch. A dedicated Dijkstra
encodePParamsUpdate will be filled in alongside the wider Conway
pparams work.
The five ...InAnyEra dispatchers gain their ShelleyBasedEraDijkstra
/ AlonzoBasedEraDijkstra arms, routed at the new
Ogmios.Data.Json.Dijkstra encoders:

  - encodeTxOutInAnyEra            -> Dijkstra.encodeTxOut
  - encodeValueInAnyEra            -> Mary.encodeValue
  - encodeScriptPurposeItemInAnyEra  -> Conway.encodeScriptPurposeItem
  - encodeScriptPurposeIndexInAnyEra -> Conway.encodeScriptPurposeIndex
  - encodeContextErrorInAnyEra       -> Conway.encodeContextError

(The latter three currently still call into Conway encoders; the
proper Dijkstra wiring is a follow-up — see the trailing WIP commit
for the inventory of remaining work.)
ouroboros-consensus 3.0.1 added a `MonadEvaluate m` requirement on
the mini-protocol client builders (localChainSync, localTxSubmission,
localTxMonitor, localStateQuery). Plumb the constraint through:

  - Ogmios.Control: the App newtype now derives MonadEvaluate so
    the constraint is satisfied at the top of the stack.
  - Ogmios.App.Health: MonadEvaluate added to connectHealthCheckClient.
  - Ogmios.App.Server.WebSocket: MonadEvaluate added to newWebSocketApp.
  - Cardano.Network.Protocol.NodeToClient.Trace: one-line type tweak
    flowing from the same surface.

Pure mechanical adaptation — no behavioural change.
cardano-ledger-shelley 1.18 removed the ShelleyTx record selectors
`body` / `wits` / `auxiliaryData` (they were renamed to
`stBody` / `stWits` / `stAuxData`, and the tx itself is now a newtype
wrapper around ShelleyTx). The era-generic accessors live in EraTx
as the lenses `bodyTxL` / `witsTxL` / `auxDataTxL`, which peer through
the wrapper transparently.

Switch Mary.encodeTx to use those lenses via `^.`, dropping the
no-longer-existing `Sh.body` / `Sh.wits` / `Sh.auxiliaryData`
references and the file-local `-Wno-*` pragma that was hiding the
broken state.
cardano-ledger-allegra 1.9 ships per-era COMPLETE pragmas for the
Timelock pattern synonyms (RequireSignature / RequireAllOf /
RequireAnyOf / RequireMOf / RequireTimeExpire / RequireTimeStart),
but only for the concrete Allegra / Mary / Alonzo / Babbage / Conway
eras. Our encodeTimelock is era-polymorphic (`forall era`), and GHC
won't apply any of the era-specific pragmas at a polymorphic call
site -- the patterns are exhaustive at runtime but GHC can't see it.

Authoring a new `{-# COMPLETE ... #-}` pragma in our module would
have been the cleanest answer, but GHC rejects "orphan" COMPLETE
pragmas (at least one of the listed patterns must be defined in the
same module, and all six of ours live in cardano-ledger). So instead,
add a wildcard arm that errors with an explanatory message. The
patterns above it are exhaustive in practice; the wildcard exists
only to satisfy GHC's incompleteness check at the polymorphic site,
and the file-local -Wno-incomplete-patterns pragma comes off.
Fills in three stubs that were left as `error "TODO(dijkstra)..."`
when the dep bump first landed, and migrates accessor shapes that
changed in cardano-ledger-alonzo 1.15:

  * encodeAuxiliaryData: now constructs the script map using the
    new `Al.NativeScript` constructor (the Alonzo script type was
    refactored from `TimelockScript` / `PlutusScript` to
    `NativeScript` / `PlutusScript`). The Plutus script path uses
    the new `mkBinaryPlutusScript` (now requires an explicit
    @maybe @era kind argument because its first type variable is
    the monad, not the era).
  * encodeBlock: `txSeqTxns` was renamed `alonzoBlockBodyTxs` and
    now yields the generic `Tx TopTx era` (a newtype wrapper);
    unwrap to `AlonzoTx` via `Al.unAlonzoTx` before passing to
    encodeTx.
  * encodeGenesis: AlonzoGenesis was restructured (commits
    dedf82e80 and 3f25fca23 of cardano-ledger). Cost models are
    now split: the V1 cost model lives on `UpgradeAlonzoPParams`
    (so HF-time, restricted to PlutusV1), while an optional
    `Maybe AlonzoExtraConfig` slot carries any extras for V2/V3
    etc. We union both sources into a single `CostModels` for
    the JSON output. The Word16/Word32 protocol-parameter
    accessors (`agMaxValSize` / `agCollateralPercentage` /
    `agMaxCollateralInputs`) use width-specific `encodeWord*`
    helpers in place of the pre-bump `encodeNatural`.

Drops the file-local -Wno-* pragma now that the stubs are real.
  * encodeBlock: `Al.txSeqTxns` → `Al.alonzoBlockBodyTxs`; the
    result is `Tx TopTx BabbageEra`, unwrap via `Ba.unBabbageTx`
    before encodeTx (Babbage's EraTx instance is
    `newtype Tx l BabbageEra = MkBabbageTx { unBabbageTx :: AlonzoTx l BabbageEra }`).
  * encodePParamsHKD body: fill in the stub. Several
    BabbagePParams fields tightened:
        - bppKeyDeposit / bppPoolDeposit / bppMinPoolCost are now
          `HKD f (CompactForm Coin)`; compose `encodeCoin .
          fromCompact` to recover `Coin`.
        - bppCoinsPerUTxOByte's inner `CoinPerByte` now wraps
          `CompactForm Coin`; insert `fromCompact` in the unCoin
          chain.
        - bppMaxValSize is now `Word32`; bppCollateralPercentage
          / bppMaxCollateralInputs are now `Word16`; swap the
          encoders accordingly.
    Also switch `bppMinFeeA` / `bppMinFeeB` (deprecated in
    cardano-ledger-babbage 1.13) to the non-deprecated
    `bppTxFeePerByte` (now CoinPerByte) / `bppTxFeeFixed` (now
    CompactForm Coin); both want the same fromCompact chain to
    bring back Coin for the JSON output.

Drops the file-local -Wno-* pragma now that the stub is real.
  * encodeBlock: `Al.txSeqTxns` → `Al.alonzoBlockBodyTxs`,
    unwrap with `Cn.unConwayTx` (Conway's EraTx instance is
    `newtype Tx l ConwayEra = MkConwayTx { unConwayTx :: AlonzoTx l ConwayEra }`).
  * encodeConstitution: `Cn.constitutionScript` was removed in
    cardano-ledger-conway 1.22; the replacement
    `constitutionScriptL` is itself deprecated in favour of
    `constitutionGuardrailsScriptHashL`. Use the non-deprecated
    lens via `^.`.
  * encodeContextError: add the missing
    `ReferenceInputsNotDisjointFromInputs` arm (new constructor
    in `ConwayContextError` in 1.22.1). The arm emits a brief
    user-facing message; the conflicting TxIns are not yet
    exposed in the JSON (consistent with the encodeText-only
    shape of the rest of this function).
  * encodePParamsHKD: same family of changes as Babbage --
    `fromCompact` chain inserted for all
    `THKD … (CompactForm Coin)` fields (cppKeyDeposit /
    cppPoolDeposit / cppMinPoolCost / cppGovActionDeposit /
    cppDRepDeposit / cppCoinsPerUTxOByte's inner CoinPerByte),
    and the deprecated `cppMinFeeA` / `cppMinFeeB` swapped for
    the non-deprecated `cppTxFeePerByte` / `cppTxFeeFixed`.

Drops the file-local -Wno-* pragma now that the stub is real.
Adds DijkstraEra to the Prelude's re-exports and extends the EraProto
type family with DijkstraEra ~ Praos StandardCrypto, so downstream
modules don't need to import it from Ouroboros.Consensus.Cardano.Block
or Cardano.Ledger.Api.Era directly.

Drops the now-redundant DijkstraEra imports from
App.Protocol.TxMonitor and App.Protocol.TxSubmission.
… split

cardano-ledger-alonzo 1.15 splits the old AlonzoGenesis cost-model
field: the PlutusV1 cost model now lives on AlonzoGenesisWrapper's
uappPlutusV1CostModel, with later language models pushed into the
optional uappExtraConfig.

withoutFutureParameters was previously stubbed against the removed
uappCostModels accessor. This restores a working decoder by reading
the V1 model directly from uappPlutusV1CostModel, pruning it against
sourceParamNames, and writing it back via record-update so that
extraConfig is preserved through the round-trip.
Adds Ogmios.Data.Json.Dijkstra.encodeUtxo, an era-polymorphic UTxO
encoder constrained to DijkstraNativeScript so it can replace
Babbage.encodeUtxo for the Dijkstra-era query arms in Query.hs.

ouroboros-network 1.1 ships a generic
`deriving newtype` ToJSON/FromJSON for `Point block` (and Tip) in
Ouroboros.Network.Block which now overlaps with the dedicated
CardanoBlock instances we keep in Ogmios.Data.Json.Orphans. Mark the
four orphan instances `{-# OVERLAPPING #-}` so call sites that import
this module still resolve to our hand-written encoders. The deeper
follow-up (moving these onto a newtype wrapper to drop the overlap
entirely) is noted in a TODO comment.
Replaces the broad
`{-# OPTIONS_GHC -Wno-unused-imports -Wno-incomplete-patterns
   -Wno-unused-matches -Wno-unused-top-binds -Wno-redundant-constraints
   -Wno-deprecations -Wno-dodgy-imports -Wno-dodgy-exports #-}`
suppression pragma with real wiring across the era-dispatch sites.

Major changes:

- 21 SomeShelleyEra ShelleyBasedEraDijkstra arms added across the
  parseQueryLedger* family (Constitution, ConstitutionalCommittee,
  DelegateRepresentatives, Epoch, EraStart, Tip, Treasury, Dump,
  Nonces, OperationalCertificates, ProjectedRewards,
  RewardAccountSummaries, LiveStakeDistribution, three UTxO
  variants, StakePoolsPerformances, RewardsProvenance, four
  StakePools sites). 16 route to QueryIfCurrentDijkstra; 3 still
  return Nothing pending Dijkstra-side encoders (PParams,
  GovernanceProposals, GovernanceProposalsByProposalReference) with
  inline TODOs explaining the missing surface.

- GetStakeDistribution -> GetStakeDistribution2 at all seven era
  call sites. encodePoolDistr migrates from
  Consensus.PoolDistr crypto to the ledger's SL.PoolDistr; the
  encoder additionally surfaces the new
  individualTotalPoolStake field as "totalStake".

- drepDeposit fromCompact: the DRepSummary "deposit" field now reads
  from CompactForm Coin through fromCompact, replacing the
  `error "TODO(dijkstra): drepDeposit CompactForm"` placeholder.

- The three GetUTxO* arms (Whole, ByAddress, ByTxIn) route through
  the new Dijkstra.encodeUtxo, removing the
  `NativeScript era ~ Timelock era` constraint mismatch that
  prevented Babbage.encodeUtxo from being reused.

- Native-script decoder rewritten as era-polymorphic
  `decodeNativeScript :: AllegraEraScript era => Json.Value -> Json.Parser (NativeScript era)`,
  using mkRequireSignature / mkRequireAllOf / mkRequireAnyOf /
  mkRequireMOf / mkTimeStart / mkTimeExpire builders. Replaces the
  41-line Allegra-Timelock-specific decodeTimeLock that was fatally
  broken by the Alonzo NativeScript constructor rename. The "native"
  branch of decodeScript now wraps via Ledger.Alonzo.NativeScript.

- decodeSerializedTransaction regains its era-tripwire constraint
  (`MostRecentEra (CardanoBlock crypto) ~ DijkstraEra`) and its
  _compilerWarning = keepRedundantConstraint binding, so a future
  post-Dijkstra era will trigger a compile error here.

- Accessor migrations: Ledger.raCredential ->
  Ledger.unAccountId . Ledger.aaId;
  Ledger.deserialiseRewardAccount ->
  Ledger.deserialiseAccountAddress.

- Module cleanup: AccountState exported/imported without
  constructors (the constructor surface moved upstream); dropped
  unused MostRecentEra-was alias, Data.Sequence.Strict re-import,
  duplicate Cardano.Ledger.State, Allegra/Shelley.Scripts qualified
  imports, and the Ouroboros.Consensus.Shelley.Ledger.Query.Types as
  Consensus qualifier. The decodeScript `Ledger.NativeScript era ~
  Timelock era` constraint is no longer needed.
Jimbo4350 and others added 10 commits May 27, 2026 01:23
Mechanical-only changes adjusting Ogmios.Data.Ledger.PredicateFailure
to the ledger / GHC9 surface used by cardano-ledger 1.20+:

- RewardAccount type alias was retired in favour of AccountAddress in
  Cardano.Ledger.Address. Track the rename in both the re-export
  block and the IncompleteWithdrawals withdrawals map.

- Hash was relocated out of Cardano.Ledger.Keys into the underlying
  Cardano.Crypto.Hash.Class module. Imports realigned accordingly.

- GHC9 no longer requires the tick on promoted DataKinds constructors
  in type-application position. Drop the tick on Witness, StakePool,
  Staking, ColdCommitteeRole, and DRepRole.

No behavioural changes; no stubs.
Extends the locally-defined CardanoEra sum with a Dijkstra
constructor, the matching "dijkstra" string in the ToJSON instance,
and the corresponding seventh EraIndex arm of eraIndexToCardanoEra.

Replaces the `error "TODO(dijkstra): eraIndexToCardanoEra Dijkstra
arm; needs Dijkstra added to CardanoEra type"` placeholder. Health
endpoints will now report era="dijkstra" once the node is past the
hard fork.
Replaces the era-by-era `error "TODO(dijkstra): ..."` stubs in
Ogmios.Data.Ledger.PredicateFailure.{Shelley,Allegra,Mary,Alonzo,
Babbage,Conway} with full bodies adapted to the upstream API.

Shared shape migrations applied across the eras:

- NonEmptySet -> Set (via Data.Set.NonEmpty.toSet) for
  BadInputsUTxO, WrongNetwork, WrongNetworkWithdrawal,
  UnspendableUTxONoDatumHash, MissingRequiredDatums,
  NotAllowedSupplementalDatums, MissingVKeyWitnessesUTXOW,
  MissingScriptWitnessesUTXOW, ScriptWitnessNotValidatingUTXOW,
  ExtraneousScriptWitnessesUTXOW, MalformedScriptWitnesses,
  MalformedReferenceScripts.
- NonEmpty -> [] (via toList) for OutputTooBigUTxO,
  OutputTooSmallUTxO, OutputBootAddrAttrsTooBig,
  BabbageOutputTooSmallUTxO, MissingRedeemers, ExtraRedeemers,
  InvalidWitnessesUTXOW, CollectErrors.
- NonEmptyMap -> Map (via NEMap.toMap) for ScriptsNotPaidUTxO's
  new (NonEmptyMap TxIn (TxOut era)) payload and the new
  ConwayIncompleteWithdrawals / ShelleyIncompleteWithdrawals
  payloads (extracting mismatchSupplied per entry).
- Width casts: Word32 -> Integer (toInteger) for MaxTxSizeUTxO;
  Word16 -> Natural (fromIntegral) for TooManyCollateralInputs.

Constructor surface changes:

- TriesToForgeADA arm removed (deleted from AllegraUtxoPredFailure
  and AlonzoUtxoPredFailure upstream).
- MissingRequiredSigners arm removed (deleted from
  AlonzoUtxowPredFailure upstream).
- WithdrawalsNotInRewardsDELEGS arm removed; the failure was
  promoted to ledger-level and now arrives as either
  ShelleyIncompleteWithdrawals or ShelleyWithdrawalsMissingAccounts
  in ShelleyLedgerPredFailure (matched in encodeLedgerFailure on
  every era; both fold into our IncompleteWithdrawals constructor
  with a follow-up TODO to introduce a dedicated
  WithdrawalsMissingAccounts variant).
- DelegateeNotRegisteredDELEG moved off ShelleyDelegsPredFailure
  (now a newtype around DelplFailure only) and lives on
  ShelleyDelegPredFailure; mapped to UnknownStakePool.
- InvalidPolicyHash deprecated in favour of
  InvalidGuardrailsScriptHash; arm renamed (same payload shape).
- New ScriptIntegrityHashMismatch ctor on AlonzoUtxowPredFailure /
  BabbageUtxowPredFailure / ConwayUtxowPredFailure: same Mismatch
  payload as PPViewHashesDontMatch (drops the extra StrictMaybe
  ByteString); both arms folded into our ScriptIntegrityHashMismatch
  variant.
- New UnelectedCommitteeVoters on ConwayGovPredFailure: mapped to
  UnknownVoters by wrapping each Credential HotCommitteeRole in
  Ledger.CommitteeVoter.
- New DepositIncorrectDELEG / RefundIncorrectDELEG on
  ConwayDelegPredFailure: mapped to DepositMismatch with the
  expected coin lifted from the Mismatch.
- New VRFKeyHashAlreadyRegistered on ShelleyPoolPredFailure:
  folded into UnknownStakePool referencing the conflicting poolId
  (TODO: introduce a dedicated VRFKeyConflict variant).
- New ConwayIncompleteWithdrawals / ConwayWithdrawalsMissingAccounts
  on ConwayLedgerPredFailure: same fold strategy as the Shelley
  variants.
- New CertsFailure WithdrawalsNotInRewardsCERTS on
  ConwayCertsPredFailure: unwrap via Ledger.unWithdrawals into
  IncompleteWithdrawals.

Address-shape migrations:

- RewardAccount pattern synonym -> AccountAddress data ctor in
  ConwayGovPredFailure's ProposalReturnAccountDoesNotExist /
  TreasuryWithdrawalReturnAccountsDoNotExist; the staking
  credential is now reached through `Ledger.unAccountId . aaId`.

Module cleanups: removed the file-level `{-# OPTIONS_GHC -Wno-* #-}`
suppression blocks; trimmed now-unused imports; dropped redundant
`Era era` constraints where the body no longer requires them.

`encodeUtxosFailure` in Alonzo and Babbage still has an
`error "TODO(dijkstra): ..."` placeholder for the per-era UTXOS
failure surface; otherwise this lands fully functional encoders
for every era's predicate-failure pipeline.
cardano-ledger-core 1.20 reshaped Ogmios.Data.Ledger.Rewards's
dependencies:

- SnapShot changed from `SnapShot stake delegs poolParams` to
  `SnapShot { ssActiveStake, ssTotalActiveStake,
  ssStakePoolsSnapShot }`. The new ssActiveStake is an ActiveStake
  newtype (VMap (Credential Staking) StakeWithDelegation) and
  ssTotalActiveStake is a precomputed NonZero Coin.
- mkPoolRewardInfo arity dropped from 9 to 8: the per-pool stake /
  delegs / stakePerPool aggregate has been collapsed into a new
  StakePoolSnapShot record which is now passed alongside the
  poolId.
- ChainAccountState replaced AccountState; `asReserves` was
  renamed to `casReserves`.
- StakeWithDelegation pairs each non-zero stake credential with
  its delegated pool, which is enough to rebuild the
  per-pool/per-credential breakdown.

Rewrite details:

- `SnapShot stake delegs poolParams` destructure switched to the
  new record-style binding on `ssActiveStake`,
  `ssTotalActiveStake`, `ssStakePoolsSnapShot`.
- `activeStake = sumAllStake stake` -> `unNonZero
  ssTotalActiveStake` (precomputed in the snapshot).
- `stakePerPool = sumStakePerPool delegs stake` and the
  `mkPoolRewardInfoCurry` pre-pass are gone -- mkPoolRewardInfo
  is now called per-pool inline with each entry's
  StakePoolSnapShot.
- `delegators` walks `unActiveStake ssActiveStake` directly using
  StakeWithDelegation { swdStake, swdDelegation } to insert
  (poolId -> credential -> balance) entries. Drops the prior
  `flipFold` helper.
- `pools` folds over `ssStakePoolsSnapShot` (VMap.toMap then
  Map.mapWithKey). For each (poolId, snap) we call
  `mkPoolRewardInfo pr availableRewards b (fromIntegral
  blocksCount) totalStake ssTotalActiveStake poolId snap`
  and pattern-match the Either StakeShare PoolRewardInfo result
  as before.
- `circulation` updated to use the new ChainAccountState accessor.

Behavioural note: the new wire output is now snapshot-accurate.
Pre-1.20 the old code iterated `poolParams` and `delegs` from the
go snapshot, which carried every registered pool / every
delegation regardless of stake. Upstream removed those fields;
ssStakePoolsSnapShot only contains pools with active stake in the
go snapshot, and ssActiveStake only contains credentials with
non-zero stake. As a result, registered-but-inactive pools and
zero-stake delegators no longer appear in the response. Since the
reward calculation itself is identical (drives off the same go
snapshot data), this drops only entries that were always
contributing zero anyway.

Imports trimmed accordingly: dropped Stake (..), sumAllStake,
sumStakePerPool, CompactForm (..), word64ToCoin, KeyRole (..),
AccountState (..); added ActiveStake (..), StakeWithDelegation (..),
casReserves, unNonZero, fromCompact.
…urface

encodePParamsHKD was stubbed against the pre-1.20 ShelleyPParams
shape. ShelleyPParams now wraps four fields in CompactForm Coin
(sppKeyDeposit, sppPoolDeposit, sppMinPoolCost, sppMinUTxOValue)
and the deprecated sppMinFeeA / sppMinFeeB accessors were replaced
by sppTxFeePerByte (HKD f CoinPerByte) / sppTxFeeFixed
(HKD f (CompactForm Coin)). Body restored with `fromCompact`
applied to the four CompactForm fields and the same
`encodeInteger . unCoin . fromCompact . Ledger.unCoinPerByte` /
`encodeCoin . fromCompact` chains already used by Babbage and
Conway.

encodeTx's metadata block was stubbed (`metadata = SNothing`).
Restored to its original liftA2-of-hash-and-labels body, using the
renamed `Sh.stBody` / `Sh.stAuxData` accessors (the Shelley.Tx
record fields shed their `body` / `auxiliaryData` / `wits` names
in favour of the `st*`-prefixed ones in cardano-ledger 1.20+).
The `_fmt` placeholder pattern is no longer needed -- un-prefixed
back to `fmt` now that it's threaded through encodeMetadata.

Dropped the file-level `{-# OPTIONS_GHC -Wno-redundant-constraints #-}`
pragma and its accompanying TODO -- both became moot once both
bodies were de-stubbed. Added `Cardano.Ledger.Compactible.fromCompact`
to the imports.
cardano-ledger 1.20 made two breaking changes that ripple through
Ogmios.Data.Json:

1. ApplyTxError is now a data family with per-era constructor
   names. The pre-1.20 single `ApplyTxError xs` data constructor
   is gone; each era exposes its own ApplyTxError data ctor in its
   own module (ShelleyApplyTxError, AllegraApplyTxError,
   MaryApplyTxError, AlonzoApplyTxError, BabbageApplyTxError,
   ConwayApplyTxError).
2. Core.Tx is now a newtype family per era wrapping the era's
   underlying tx type. For Alonzo / Babbage / Conway the wrapper
   is MkAlonzoTx / MkBabbageTx / MkConwayTx around AlonzoTx l era.
   Conway.encodeTx / Babbage.encodeTx / Alonzo.encodeTx still
   accept the underlying AlonzoTx, so the wrapper has to be peeled
   off with un{Era}Tx.

encodeSubmitTransactionError: each ApplyTxErr{Era} arm now
matches the era-specific data constructor by name
(ConwayApplyTxError / BabbageApplyTxError / AlonzoApplyTxError /
MaryApplyTxError / AllegraApplyTxError / ShelleyApplyTxError).

encodeTx: the Conway / Babbage / Alonzo arms run the unwrapped
tx through their per-era encoder via
`{Era}.encodeTx opts (un{Era}Tx x)`. Mary / Allegra / Shelley
encoders already take a Sh.Tx so their arms don't need an unwrap.

Imports adjusted accordingly: the broad
`Cardano.Ledger.Shelley.API (ApplyTxError (..))` import is
replaced by per-era qualified-ctor imports
(`ApplyTxError (ConwayApplyTxError)` etc.) and explicit
`un{Era}Tx` imports from each era's Tx module.

Note: this commit fixes the three reported type errors but the
file still has six incomplete-pattern errors against
`Sh{BlockByron,GenTxDijkstra,ApplyTxErrDijkstra,...}` that will
land in follow-up work along with a `Dijkstra.encodeTx` encoder
in Ogmios.Data.Json.Dijkstra.
Without these arms a Dijkstra-era roll-forward on the ChainSync
mini-protocol would fall through the existing `\case` over
`CardanoBlock` and crash the server. The same gap shows up on the
`GenTx` / `GenTxId` / `SubmitTransactionError` paths once the
hard-fork happens. This commit closes the happy path so Ogmios
keeps following the chain after the Dijkstra hard-fork.

Additions in Ogmios.Data.Json.Dijkstra:

- encodeBlock for `ShelleyBlock (Praos StandardCrypto) DijkstraEra`,
  mirroring Conway.encodeBlock: emits `type`, `era`, `id`, the
  Praos header (Babbage.encodeHeader), and a `transactions` array
  built from `txs ^. txSeqBlockBodyL` with each entry routed
  through encodeTx after unwrapping the per-era Tx newtype via
  `Di.unDijkstraTx`. Uses the era-polymorphic txSeqBlockBodyL
  lens rather than an `Al.alonzoBlockBodyTxs`-style accessor
  because Dijkstra has its own DijkstraBlockBody type.

- encodeTx (minimal, follow-up-flagged): emits the transaction's
  `id` (via txIdTxBody), `spends` (the Alonzo-style IsValid flag
  through `dtIsValid`), and optionally `cbor` (raw CBOR
  bytes) when `includeTransactionCbor` is set. The full
  body / witness / metadata destructuring against the new
  DijkstraTxBody surface (which has its own field accessors
  distinct from Conway's `ctbSpendInputs` / `ctbOutputs` /
  `atAuxData` etc.) is left for a follow-up; consumers needing
  detailed transaction fields can decode the `cbor` payload in
  the meantime.

Wirings in Ogmios.Data.Json:

- encodeBlock: `BlockDijkstra blk -> Dijkstra.encodeBlock opts blk`
- encodeSerializedTransaction: `GenTxDijkstra tx -> toCBOR tx`
- encodeTx: `GenTxDijkstra (ShelleyTx _ x) ->
              Dijkstra.encodeTx opts (unDijkstraTx x)`
- encodeGenTxId: `GenTxIdDijkstra (ShelleyTxId x) ->
                   Shelley.encodeTxId x`
- encodeSubmitTransactionError: `ApplyTxErrDijkstra{}` arm errors
  out -- Ogmios does not yet relay Dijkstra-era transactions, so
  this code path is intentionally unreachable; a proper
  Dijkstra.encodeLedgerFailure encoder follows the Dijkstra
  mempool-failure module work.

Imports:

- Ogmios.Data.Json.Dijkstra gains:
  `Cardano.Ledger.Block`, `Cardano.Ledger.Dijkstra.Tx`,
  `Ouroboros.Consensus.Shelley.Ledger.Block (ShelleyBlock (..))`,
  and the qualified `Ogmios.Data.Json.Babbage` re-export for
  `encodeHeader`.

- Ogmios.Data.Json gains the qualified `Ogmios.Data.Json.Dijkstra`
  import plus `Cardano.Ledger.Dijkstra.Tx (unDijkstraTx)`.

This unblocks ChainSync against a PV12 Dijkstra-era block.
Fill in the last six `error "TODO(dijkstra)..."` stubs left over from the
cardano-ledger 1.20+ / Dijkstra integration so that the test suite runs
to completion without crashing on stub calls.

- Ogmios.Data.Ledger.scriptPurposeInMostRecentEra: full body with the
  extra upgradePlutusPurposeAsIx step now that Dijkstra is the most
  recent era.
- Ogmios.Prelude.fromEraIndex: Dijkstra arm.
- Ogmios.Data.Json.Alonzo.encodePParamsHKD: full body, adjusted for
  CompactForm Coin fields and Word32/Word16 (was Natural) accessors in
  cardano-ledger-alonzo 1.18+; replaced deprecated appMinFeeA/B with
  appTxFeePerByte/Fixed.
- Ogmios.Data.Json.Dijkstra: encodePParams / encodePParamsUpdate /
  encodePParamsHKD added (mirrors Conway, plus refScript size limits,
  stride and multiplier). Wired into encodeGovAction ParameterChange.
- Ogmios.Data.Protocol.TxSubmission.inputs/outputs: GenTxDijkstra arms
  for ChainSync UTxO reconstruction.
- Ogmios.App.Protocol.TxSubmission babbageToConway: replaced the stubbed
  tx upgrade with `upgrade tx` now that the Upgrade (Tx TopTx) ConwayEra
  instance is in place.

Also fixes two pre-existing regressions surfaced by the test run:

- Ogmios.Data.Json.Query.decodeScript: restored the cbor/json branching
  for native scripts (was simplified during the per-era migration and
  ended up handing the wrapper object straight to decodeNativeScript,
  which then failed with "key 'clause' not found").
- cardano.json schema: extend Language enum with "plutus:v4" so
  EvaluateTransactionResponse's missingCostModels validates.
- test: fix Script_Native_0.json filename casing in JsonSpec.

Regenerates the JSON test vectors that drift with these changes.

cabal test unit -j4: 140 examples, 0 failures.
Co-authored-by: John Lotoski <john.lotoski@iohk.io>
Two validateNetworkQuery call sites shared the same subMethod
("genesisConfiguration"), so their goldens raced via parallel/forConcurrently
and last-writer-wins clobbered 000-009.json on every run. Add a tagged
variant of validateNetworkQuery that suffixes the goldens directory and spec
name, and use it to split the Shelley (n=10) and Alonzo (n=20) cases into
per-era subdirectories. Move the existing flat-layout fixtures into Alonzo/
and add the new Shelley/ fixtures.
@johnalotoski johnalotoski force-pushed the jmiller/dijkstra-integration branch from 9149a32 to 753183f Compare May 27, 2026 06:25
… why

`withFutureParameters` was iterating the *current* PV1 enum (~200 entries)
via `costModelParamNames`, which on cardano-ledger-core >= 1.18 trips the
new `guardNumberOfParameters` count check and crashes the
`queryNetwork/genesisConfiguration {era: alonzo}` handler. Switch to
`costModelInitParamNames` so the workaround pads to exactly the 166 entries
the new strict decoder expects.

Rewrite the surrounding comment to match the actual ledger behaviour:
the count check applies regardless of shape (array or map), the map form
additionally enforces the 166 init names by name, and `extraConfig`
parsing is lenient via `isLenient=True`.
@Jimbo4350 Jimbo4350 changed the title Dijkstra integration Van Rossem integration May 27, 2026
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.

2 participants