Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
67 changes: 57 additions & 10 deletions cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,52 @@ repository cardano-haskell-packages
-- update either of these.
index-state:
-- Bump this if you need newer packages from Hackage
, hackage.haskell.org 2026-05-18T17:14:36Z
, hackage.haskell.org 2026-06-29T22:49:53Z
-- Bump this if you need newer packages from CHaP
, cardano-haskell-packages 2026-05-18T13:56:34Z

active-repositories:
, :rest
, cardano-haskell-packages:override
, cardano-haskell-packages 2026-07-02T10:10:00Z

packages: .

-- kes-agent on branch f-f/allow-crypto-class-2.5
source-repository-package
type: git
location: https://github.com/f-f/kes-agent.git
tag: 32c1ed675d22a30735d9f22f7afa436a3ef3e64a
--sha256: sha256-o7hFX1JnraS6Xq0WoXQwd9Z8GsPPv0Ls2DWvZ08o0ZU=
subdir:
kes-agent
kes-agent-crypto

-- cardano-ledger on master 2026-06-30
source-repository-package
type: git
location: https://github.com/IntersectMBO/cardano-ledger.git
tag: e9827fdc3def69c02fe826fdf46e2a412620ef98
--sha256: sha256-bVR1ZFs1VDc7ag2QEpSf5rVj1mdBCB/Ag7nhj00UXQE=
subdir:
eras/allegra/impl
eras/alonzo/impl
eras/babbage/impl
eras/byron/chain/executable-spec
eras/byron/crypto
eras/byron/ledger/executable-spec
eras/byron/ledger/impl
eras/conway/impl
eras/dijkstra/impl
eras/mary/impl
eras/shelley/impl
eras/shelley/test-suite
eras/shelley-ma/test-suite
libs/cardano-data
libs/cardano-ledger-api
libs/cardano-ledger-binary
libs/cardano-ledger-core
libs/cardano-protocol
libs/cardano-protocol-tpraos
libs/non-integral
libs/small-steps
libs/vector-map

-- We want to always build the test-suites and benchmarks
tests: true
benchmarks: true
Expand All @@ -47,13 +83,24 @@ if os (windows)
constraints:
tasty <1.5.4,

-- ouroboros-network dependency after introducing `bracketKeepAlive` (PR#5371)
-- on latest main branch
source-repository-package
type: git
location: https://github.com/IntersectMBO/ouroboros-network
tag: e8d59d8a219563760fc21ba5bc86fab77d886742
--sha256: sha256-ElgaE5JeDTPfyDQnyZs5ZlOdzlnZYl7z1OgkzCBJjek=
location: https://github.com/IntersectMBO/ouroboros-network.git
tag: 0a614a36c8969e53fd6a1c3890b36da5aff3b0a2
--sha256: sha256-p32/Y6jXwiSwa0yVspdx246KHaCBmqe2zB+UpxudeJc=
subdir:
ouroboros-network
cardano-diffusion
network-mux

-- plutus on branch master
source-repository-package
type: git
location: https://github.com/IntersectMBO/plutus.git
tag: b1db04cc425fab303ac3b79d7140dc2a17f29e6d
--sha256: sha256-XtYzjNVx4+IGWpgm+p/YTf56DrJtK0I98umZCTE3U80=
subdir:
plutus-core
plutus-ledger-api
plutus-tx
1 change: 1 addition & 0 deletions cabal/newer-ghcs.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ if impl (ghc >= 9.14)
, serialise:base
, serialise:containers
, serialise:time
, tdigest:base
, with-utf8:base
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
### Breaking

- Renamed `Ouroboros.Consensus.Protocol.Praos.Views.LedgerView` to `PraosLedgerView`,
with the fields renamed from `lv*` to `plv*`.
- Removed `PraosEnvelopeError` from the exports of `Ouroboros.Consensus.Shelley.Protocol.Praos`.
- `EnvelopeCheckError (Praos c)` and `EnvelopeCheckError (TPraos c)` are both now
`Ouroboros.Consensus.Shelley.Protocol.EnvelopeChecks.EnvelopeError`.
- Removed modules `Ouroboros.Consensus.Protocol.Praos.Header` and
`Ouroboros.Consensus.Protocol.Praos.VRF`. They are now provided by the `cardano-protocol` package (as `Cardano.Protocol.Praos.BlockHeader` and `Cardano.Protocol.Praos.VRF`); import from there instead.

### Non-Breaking

- Add module `Ouroboros.Consensus.Shelley.Protocol.EnvelopeChecks`; consolidates
envelope-check logic previously inlined in `Ouroboros.Consensus.Shelley.Protocol.{Praos,TPraos}`.
- Add `forecastToPraosLedgerView` to `Ouroboros.Consensus.Protocol.Praos.Views`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
### Breaking

- Change `ShelleyBasedEra` class superclass constraints:
- change `SL.ApplyBlock era` to `SL.ApplyTick era`.
- change `SL.GetLedgerView era` to `SL.EraForecast era`.
- remove `NoThunks (PredicateFailure (EraRule "BBODY" era))`.
- `ShelleyCompatible proto era` has three new superclass constraints:
- `EncCBORGroup (SL.BlockBody era)`,
- `SL.EraBlockHeader (ShelleyProtocolHeader proto) era`,
- `SL.ApplyBlock (ShelleyProtocolHeader proto) era`.
- Remove `ShelleyCompatible (TPraos c) BabbageEra`, `ShelleyCompatible (TPraos c) ConwayEra`,
and `ShelleyCompatible (TPraos c) DijkstraEra` instances from `Ouroboros.Consensus.Shelley.HFEras`.
These eras now run under Praos only.
- Remove the `ProtocolHeaderSupportsLedger` class from `Ouroboros.Consensus.Shelley.Protocol.Abstract`.
- `LedgerSupportsProtocol (ShelleyBlock (TPraos crypto) era)` instance now requires `SL.ShelleyEraForecast era`.
- `LedgerSupportsProtocol (ShelleyBlock (Praos crypto) era)` instance no longer requires
`ShelleyCompatible (TPraos crypto) era` and instead requires `SL.EraForecast era`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### Breaking

- `protocolInfoCardano`, `protocolInfoShelley` and `protocolInfoTPraosShelleyBased`
now take an additional initial argument `SomeHasFS m` and returns
inside `m`. Their callback for creating blocks also returns values in `m`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
### Breaking

- The constraint on the following functions tightens from `Applicative m` to `Monad m`:
- `Ouroboros.Consensus.Storage.ImmutableDB.Impl.defaultArgs`
- `Ouroboros.Consensus.Storage.LedgerDB.Args.defaultArgs`
- `Ouroboros.Consensus.Storage.VolatileDB.Impl.defaultArgs`
- `Ouroboros.Consensus.Storage.PerasCertDB.Impl.defaultArgs`
- `Ouroboros.Consensus.Storage.PerasVoteDB.Impl.defaultArgs`
- `Ouroboros.Consensus.Storage.ChainDB.Impl.Args.updateTracer`
- `Ouroboros.Consensus.Storage.ChainDB.Impl.fromChainDbEnv`
- `Ouroboros.Consensus.Util.Enclose.encloseWith`
- `Ouroboros.Consensus.Storage.LedgerDB.decorateReplayTracerWithGoal`
- `Ouroboros.Consensus.Storage.LedgerDB.decorateReplayTracerWithStart`
- `Ouroboros.Consensus.Network.NodeToClient.showTracers`,
`Ouroboros.Consensus.Network.NodeToNode.showTracers`, and
`Ouroboros.Consensus.Node.Tracers.showTracers` now require `Monad m`.
- Remove the `NoThunks FsPath` orphan instance from `Ouroboros.Consensus.Util.Orphans`;
it is now provided upstream by `cardano-ledger` (`Cardano.Ledger.Orphans` in
`cardano-ledger-core`).
- Remove the orphan `Measure ()` instance from
`Ouroboros.Consensus.Ledger.SupportsMempool`.
- `HasBLSContext` instances for `SIGN` and `VRF` now use `minSigPoPDST` as their base context.
- Upgrade lower bounds for Node 11.1 integration of upstream packages `cardano-base`,
`cardano-ledger`, `kes-agent`, `ouroboros-network`, `validation`

### Non-Breaking

- Add `Ouroboros.Network.Tx.HasRawTxId` instances for the transaction-id type of every block:
`ByronBlock`, `ShelleyBlock`, `HardForkBlock`, `DualBlock`, and `SimpleBlock`.
To match, the `RunNode` class now has a `HasRawTxId (TxId (GenTx blk))` superclass.
- The Shelley ledger queries `GetFilteredDelegationsAndRewardAccounts`,
`GetStakeDelegDeposits`, `GetFilteredVoteDelegatees` and `GetPoolDistr2` are now
answered by the corresponding `cardano-ledger` functions
(`queryStakePoolDelegsAndRewards`, `queryAccountsDeposits`, `queryDRepDelegatees`,
`querySetSnapshotStakePoolDistr`) instead of being implemented in consensus. The
query results have not changed.
12 changes: 6 additions & 6 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 12 additions & 5 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,18 @@
{
devShells = rec {
default = ghc96;
ghc96 = hydraJobs.native.haskell96.devShell;
# Disabled because Plutus panics on it
# ghc96-ipe = hydraJobs.native.haskell96.devShellIPE;
ghc914 = hydraJobs.native.haskell914.devShell;
ghc914-ipe = hydraJobs.native.haskell914.devShellIPE;
ghc96 = import ./nix/shell.nix {
inherit inputs pkgs;
hsPkgs = pkgs.hsPkgs;
};
ghc914 = import ./nix/shell.nix {
inherit inputs pkgs;
hsPkgs = pkgs.hsPkgs.projectVariants.ghc914;
};
ghc914-ipe = import ./nix/shell.nix {
inherit inputs pkgs;
hsPkgs = pkgs.hsPkgs.projectVariants.ghc914.projectVariants.ipe;
};

agda-spec = pkgs.agda-spec.shell;

Expand Down
168 changes: 168 additions & 0 deletions ouroboros-consensus-cardano/app/check-tx-upgrade.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- | A minimal executable that probes the transaction-id fidelity of the
-- Babbage->Conway era /upgrade/, to explain the following report:
--
-- * The node's ledger is in Conway.
-- * A transaction submitted over LocalTxSubmission tagged as __Babbage__ is
-- rejected.
-- * The /same/ transaction submitted tagged as __Conway__ is accepted.
--
-- A Babbage-tagged transaction is upgraded to Conway inside the mempool by
-- @hardForkInjectTxs@ (the Babbage->Conway 'InjectTx', reproduced verbatim as
-- 'babbageToConwayInjection'); a Conway-tagged transaction skips that step and
-- is validated directly. So any difference between the two paths comes entirely
-- from the upgrade.
--
-- The mempool and consensus assume the upgrade is /transaction-id preserving/
-- (see the invariant on @OneEraGenTxId@ in
-- 'Ouroboros.Consensus.HardFork.Combinator.AcrossEras'): a client signs the
-- transaction id of the era it built for, so if the upgrade changed the id, the
-- witnesses a client signed for the Babbage id would no longer match the id the
-- Conway ledger derives — which is exactly the shape of the report.
--
-- This program builds one transaction body (with a non-empty input set, so that
-- any set/encoding differences between the eras are exercised) and prints three
-- transaction ids:
--
-- 1. the Babbage-tagged tx id (what a client signs on the Babbage path)
-- 2. the id after Babbage->Conway upgrade (what the Conway ledger checks against)
-- 3. the native Conway-tagged tx id (what a client signs on the Conway path)
--
-- If (1) and (2) differ, the upgrade is not id-preserving and witnesses signed
-- on the Babbage path cannot verify after the upgrade — a concrete root cause
-- for the report. If all three agree, the id is stable and the cause lies
-- elsewhere.
module Main (main) where

import Cardano.Ledger.BaseTypes (TxIx (..))
import qualified Cardano.Ledger.Core as SL
import Cardano.Ledger.TxIn (TxIn (..))
import Control.Monad (when)
import Control.Monad.Except (runExcept)
import Data.SOP.BasicFunctors ((:.:) (Comp), unComp)
import qualified Data.Set as Set
import Lens.Micro ((&), (.~))
import Ouroboros.Consensus.HardFork.Combinator.InjectTxs
( InjectTx
, injectTxWith
, pattern InjectTx
)
import Ouroboros.Consensus.Shelley.Eras (BabbageEra, ConwayEra)
import Ouroboros.Consensus.Shelley.HFEras
( StandardBabbageBlock
, StandardConwayBlock
)
import Ouroboros.Consensus.Shelley.Ledger.Mempool
( GenTx (ShelleyTx)
, mkShelleyTx
)
import Ouroboros.Consensus.Shelley.ShelleyHFC ()
import System.Exit (exitFailure)

-- | The Babbage->Conway transaction injection.
--
-- This is a copy of @translateTxBabbageToConwayWrapper@ from
-- 'Ouroboros.Consensus.Cardano.CanHardFork' (which is not exported). It is one
-- link of the @InPairs InjectTx@ chain returned by @hardForkInjectTxs@; the
-- mempool walks that chain to step a transaction forward, one era at a time,
-- until it reaches the era the ledger currently sits in.
--
-- The @'SL.TranslationContext' ConwayEra@ (a @ConwayGenesis@) is threaded
-- through only to match the shape of the real node code: the transaction-level
-- Conway translation is a pure CBOR round-trip and never forces it. We
-- therefore leave it 'undefined' — see 'main'.
babbageToConwayInjection ::
SL.TranslationContext ConwayEra ->
InjectTx StandardBabbageBlock StandardConwayBlock
babbageToConwayInjection ctxt =
InjectTx $ fmap unComp . eitherToMaybe . runExcept . SL.translateEra ctxt . Comp
where
eitherToMaybe = either (const Nothing) Just

-- | Build a basic (invalid) transaction carrying a single input. The input's tx
-- id is stable and era-independent, so the Babbage and Conway transactions below
-- have identical /content/.
mkTxWithInput ::
forall era.
SL.EraTx era =>
TxIn ->
SL.Tx SL.TopTx era
mkTxWithInput input =
SL.mkBasicTx (SL.mkBasicTxBody & SL.inputsTxBodyL .~ Set.singleton input)

main :: IO ()
main = do
let -- A single synthetic input, reusing the id of a basic empty tx.
dummyInput :: TxIn
dummyInput =
TxIn
(SL.txIdTx (SL.mkBasicTx SL.mkBasicTxBody :: SL.Tx SL.TopTx BabbageEra))
(TxIx 0)

babbageGenTx :: GenTx StandardBabbageBlock
babbageGenTx = mkShelleyTx (mkTxWithInput dummyInput)

conwayNativeGenTx :: GenTx StandardConwayBlock
conwayNativeGenTx = mkShelleyTx (mkTxWithInput dummyInput)

-- A minimal (empty) body, for comparison. Note this still contains the
-- always-present (here empty) inputs set, so it does not isolate set
-- encoding; it shows the Babbage and Conway body encoders differ even at
-- their smallest.
emptyBabbageId = case mkShelleyTx (SL.mkBasicTx SL.mkBasicTxBody) :: GenTx StandardBabbageBlock of
ShelleyTx i _ -> i
emptyConwayId = case mkShelleyTx (SL.mkBasicTx SL.mkBasicTxBody) :: GenTx StandardConwayBlock of
ShelleyTx i _ -> i

-- Never forced by the transaction-level translation (see the haddock on
-- 'babbageToConwayInjection').
conwayCtxt :: SL.TranslationContext ConwayEra
conwayCtxt = undefined

case injectTxWith (babbageToConwayInjection conwayCtxt) babbageGenTx of
Nothing -> do
putStrLn "NOT UPGRADEABLE: the Babbage tx cannot be upgraded to Conway."
exitFailure
Just upgradedGenTx -> do
let ShelleyTx babbageId _ = babbageGenTx
ShelleyTx upgradedId _ = upgradedGenTx
ShelleyTx nativeId _ = conwayNativeGenTx

putStrLn "Transaction ids (identical body content, one input, differing only in era tag / path):"
putStrLn $ " 1. Babbage-tagged : " ++ show babbageId
putStrLn $ " 2. after Babbage->Conway : " ++ show upgradedId
putStrLn $ " 3. native Conway-tagged : " ++ show nativeId
putStrLn ""
putStrLn "Minimal empty body, for comparison:"
putStrLn $ " Babbage-tagged : " ++ show emptyBabbageId
putStrLn $ " native Conway-tagged : " ++ show emptyConwayId
putStrLn ""
putStrLn $ " upgrade preserves tx id (1 == 2) : " ++ show (babbageId == upgradedId)
putStrLn $ " upgraded == native Conway (2 == 3) : " ++ show (upgradedId == nativeId)
putStrLn $ " empty body id agrees across eras : " ++ show (emptyBabbageId == emptyConwayId)
putStrLn ""
if babbageId /= upgradedId
then
putStrLn $
"ID-CHANGING UPGRADE: the upgrade changes the tx id; witnesses signed over the "
++ "Babbage id (1) cannot verify against the Conway-derived id (2)."
else
if upgradedId == nativeId
then
putStrLn $
"FULLY STABLE: the upgrade preserves the id AND matches a native Conway tx. "
++ "The report's cause lies elsewhere."
else
putStrLn $
"SPLIT ENCODING: the upgrade preserves the Babbage bytes/id (1 == 2), but a "
++ "native Conway tx of identical content has a different id (2 /= 3): the "
++ "Babbage and Conway CBOR encodings of a transaction differ. So the "
++ "Babbage-tagged and Conway-tagged submissions are byte-different "
++ "transactions, and the upgraded tx carries legacy Babbage-format bytes. Any "
++ "Conway validation or downstream check sensitive to that encoding will treat "
++ "them differently -- the likely root of the report."
when (upgradedId == nativeId && babbageId == upgradedId) $
putStrLn "(No path divergence observed for this transaction.)"

This file was deleted.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Loading