Skip to content
Closed
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,7 @@ dist-newstyle

## Claude Code (symlink created by the devShell shellHook)
/.claude

## Local dev scripts (patch-nix-deps.sh stays tracked)
/scripts/*
!/scripts/patch-nix-deps.sh
23 changes: 12 additions & 11 deletions cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ repository cardano-haskell-packages
d4a35cd3121aa00d18544bb0ac01c3e1691d618f462c46129271bccf39f7e8ee

index-state:
, hackage.haskell.org 2026-05-08T22:40:19Z
, cardano-haskell-packages 2026-05-08T13:26:45Z
, hackage.haskell.org 2026-08-14T13:38:07Z
, cardano-haskell-packages 2026-09-16T23:53:07Z

packages:
./
Expand Down Expand Up @@ -46,16 +46,15 @@ package direct-sqlite
flags: +nomutex

constraints:
, any.cardano-node == 11.0.1
, any.cardano-node == 11.1.1

, any.cardano-ledger-conway >= 1.22.1.0
, any.cardano-ledger-conway >= 1.23

, any.ouroboros-consensus ^>= 3.0.1
, any.ouroboros-network ^>= 1.1
, any.ouroboros-consensus ^>= 4.2.1
, any.ouroboros-network ^>= 1.2

, any.io-classes ^>= 1.8
, any.formatting == 7.2.0
, any.validation < 1.2
, any.text source

-- Use serial block IO instead of io_uring to avoid requiring liburing
Expand All @@ -71,14 +70,16 @@ allow-newer:
, io-classes:time

-- NOTE update hash using
-- nix-prefetch-git https://github.com/CardanoSolutions/ogmios.git --rev <tag> --fetch-submodules --quiet | jq '.hash' | tail -c +9 | head -c -2
-- nix-prefetch-git https://github.com/IntersectMBO/ogmios.git --rev <tag> --fetch-submodules --quiet | jq '.hash' | tail -c +9 | head -c -2
--
source-repository-package
type: git
location: https://github.com/CardanoSolutions/ogmios
--sha256: xkOfOdX6Dxi7+VW78Tk3n3MoguIg39pKdxiNVfdeEwE=
tag: ae876badb138f42dcd6d2389734b0c15502684ed
location: https://github.com/IntersectMBO/ogmios
--sha256: sha256-1VptE6HSuT2U+NMw7HLb5X1PqqrYpsOkl4tWHk5ygG4=
tag: ed9efbad7b06193b00c13fb8102dcd0d8ff63647
subdir:
server/modules/fast-bech32
server/modules/contra-tracers

source-repository-package
type: git
Expand Down
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.

14 changes: 11 additions & 3 deletions kupo.cabal

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

2 changes: 2 additions & 0 deletions package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ library:
- bytestring
- cardano-crypto-class
- cardano-crypto-wrapper
- cardano-data
- cardano-ledger-allegra
- cardano-ledger-alonzo
- cardano-ledger-api
Expand All @@ -71,6 +72,7 @@ library:
- cardano-ledger-byron
- cardano-ledger-conway
- cardano-ledger-core
- cardano-ledger-dijkstra
- cardano-ledger-mary
- cardano-ledger-shelley
- cardano-slotting
Expand Down
3 changes: 2 additions & 1 deletion src/Kupo/Control/MonadLog.hs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import Control.Monad.Class.MonadTime
)
import Control.Tracer
( Tracer (..)
, mkTracer
, natTracer
, nullTracer
, traceWith
Expand Down Expand Up @@ -135,7 +136,7 @@ withTracers h version tracers action = do
:: Writer
-> TMVar IO ()
-> Tracer IO SomeMsg
tracer say lock = Tracer $ \someMsg@(SomeMsg minSeverity _ msg) -> do
tracer say lock = mkTracer $ \someMsg@(SomeMsg minSeverity _ msg) -> do
let severity = getSeverityAnnotation msg
when (severity >= minSeverity) $ liftIO $ withTMVar lock $ \() -> do
threadId <- myThreadId
Expand Down
103 changes: 81 additions & 22 deletions src/Kupo/Data/Cardano.hs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ import qualified Cardano.Ledger.Alonzo.Core as Ledger
import qualified Cardano.Ledger.Alonzo.TxWits as Ledger
import qualified Cardano.Ledger.Babbage.Core as Ledger
import qualified Cardano.Ledger.Block as Ledger
import qualified Cardano.Ledger.Dijkstra.Core as Ledger
import qualified Data.OMap.Strict as OMap
import qualified Data.Set as Set

-- IsBlock
Expand Down Expand Up @@ -194,9 +196,26 @@ instance IsBlock Block where
foldrWithIndex (\ix -> fn ix . TransactionBabbage) result (txs ^. Ledger.txSeqBlockBodyL)
BlockConway (ShelleyBlock (Ledger.Block _ txs) _) ->
foldrWithIndex (\ix -> fn ix . TransactionConway) result (txs ^. Ledger.txSeqBlockBodyL)
BlockDijkstra _ ->
-- We don't support Dijkstra blocks.
error "kupo: Dijkstra blocks are not supported."
BlockDijkstra (ShelleyBlock (Ledger.Block _ txs) _) ->
foldrWithIndex (\ix -> fn ix . TransactionDijkstra . rejectSubTransactions) result (txs ^. Ledger.txSeqBlockBodyL)
where
-- Dijkstra introduces nested transactions: a top-level transaction may
-- carry sub-transactions, each with its own id, inputs and outputs but
-- no phase-2 validity flag or collateral of its own. Kupo folds one flat
-- sequence of transactions per block and stores the resulting index on
-- every output reference, so how sub-transactions are numbered (and how
-- a phase-2 invalid parent affects them) is a design decision that has
-- not been made yet. Until it is, fail loudly rather than silently
-- dropping their inputs and outputs from the index.
rejectSubTransactions
:: Ledger.Tx Ledger.TopTx DijkstraEra
-> Ledger.Tx Ledger.TopTx DijkstraEra
rejectSubTransactions tx
| OMap.null (tx ^. Ledger.bodyTxL . Ledger.subTransactionsTxBodyL) =
tx
| otherwise =
error $ "kupo: Dijkstra transaction " <> show (Ledger.txIdTx @DijkstraEra tx)
<> " carries sub-transactions, which kupo does not index yet."

spentInputs
:: Transaction
Expand All @@ -211,22 +230,28 @@ instance IsBlock Block where
TransactionMary tx ->
tx ^. Ledger.bodyTxL . Ledger.inputsTxBodyL
TransactionAlonzo tx ->
case tx ^. Ledger.isValidTxL of
Ledger.IsValid True ->
case tx ^. Ledger.isPhase2ValidTxL of
Ledger.Phase2Valid ->
tx ^. Ledger.bodyTxL . Ledger.inputsTxBodyL
Ledger.IsValid False ->
Ledger.Phase2Invalid ->
tx ^. Ledger.bodyTxL . Ledger.collateralInputsTxBodyL
TransactionBabbage tx ->
case tx ^. Ledger.isValidTxL of
Ledger.IsValid True ->
case tx ^. Ledger.isPhase2ValidTxL of
Ledger.Phase2Valid ->
tx ^. Ledger.bodyTxL . Ledger.inputsTxBodyL
Ledger.IsValid False ->
Ledger.Phase2Invalid ->
tx ^. Ledger.bodyTxL . Ledger.collateralInputsTxBodyL
TransactionConway tx ->
case tx ^. Ledger.isValidTxL of
Ledger.IsValid True ->
case tx ^. Ledger.isPhase2ValidTxL of
Ledger.Phase2Valid ->
tx ^. Ledger.bodyTxL . Ledger.inputsTxBodyL
Ledger.Phase2Invalid ->
tx ^. Ledger.bodyTxL . Ledger.collateralInputsTxBodyL
TransactionDijkstra tx ->
case tx ^. Ledger.isPhase2ValidTxL of
Ledger.Phase2Valid ->
tx ^. Ledger.bodyTxL . Ledger.inputsTxBodyL
Ledger.IsValid False ->
Ledger.Phase2Invalid ->
tx ^. Ledger.bodyTxL . Ledger.collateralInputsTxBodyL
where
transformByron (Ledger.Byron.TxInUtxo txId ix) =
Expand Down Expand Up @@ -276,10 +301,10 @@ instance IsBlock Block where
outs = body ^. Ledger.outputsTxBodyL
meta = tx ^. Ledger.auxDataTxL & strictMaybe emptyMetadata fromAlonzoMetadata
in
case tx ^. Ledger.isValidTxL of
Ledger.IsValid True ->
case tx ^. Ledger.isPhase2ValidTxL of
Ledger.Phase2Valid ->
traverseAndTransform fromAlonzoOutput txId meta 0 outs
Ledger.IsValid False ->
Ledger.Phase2Invalid ->
[]
TransactionBabbage tx ->
let
Expand All @@ -288,10 +313,10 @@ instance IsBlock Block where
outs = body ^. Ledger.outputsTxBodyL
meta = tx ^. Ledger.auxDataTxL & strictMaybe emptyMetadata fromBabbageMetadata
in
case tx ^. Ledger.isValidTxL of
Ledger.IsValid True ->
case tx ^. Ledger.isPhase2ValidTxL of
Ledger.Phase2Valid ->
traverseAndTransform fromBabbageOutput txId meta 0 outs
Ledger.IsValid False ->
Ledger.Phase2Invalid ->
-- From Babbage's formal specification:
--
-- Note that the new collOuts function generates a single output
Expand All @@ -309,14 +334,31 @@ instance IsBlock Block where
outs = body ^. Ledger.outputsTxBodyL
meta = tx ^. Ledger.auxDataTxL & strictMaybe emptyMetadata fromConwayMetadata
in
case tx ^. Ledger.isValidTxL of
Ledger.IsValid True ->
traverseAndTransform identity txId meta 0 outs
Ledger.IsValid False ->
case tx ^. Ledger.isPhase2ValidTxL of
Ledger.Phase2Valid ->
traverseAndTransform fromConwayOutput txId meta 0 outs
Ledger.Phase2Invalid ->
-- From Conway formal specification:
--
-- Note that the new collOuts function generates a single output
-- with an index |txouts{txb}|.
let start = fromIntegral (length outs) in
case body ^. Ledger.collateralReturnTxBodyL of
SNothing ->
[]
SJust r ->
traverseAndTransform fromConwayOutput txId meta start (r :<| mempty)
TransactionDijkstra tx ->
let
body = tx ^. Ledger.bodyTxL
txId = Ledger.txIdTxBody @DijkstraEra body
outs = body ^. Ledger.outputsTxBodyL
meta = tx ^. Ledger.auxDataTxL & strictMaybe emptyMetadata identity
in
case tx ^. Ledger.isPhase2ValidTxL of
Ledger.Phase2Valid ->
traverseAndTransform identity txId meta 0 outs
Ledger.Phase2Invalid ->
let start = fromIntegral (length outs) in
case body ^. Ledger.collateralReturnTxBodyL of
SNothing ->
Expand Down Expand Up @@ -383,6 +425,8 @@ instance IsBlock Block where
fromBabbageData <$> Ledger.unTxDats (tx ^. Ledger.witsTxL . Ledger.datsTxWitsL)
TransactionConway tx ->
fromConwayData <$> Ledger.unTxDats (tx ^. Ledger.witsTxL . Ledger.datsTxWitsL)
TransactionDijkstra tx ->
fromDijkstraData <$> Ledger.unTxDats (tx ^. Ledger.witsTxL . Ledger.datsTxWitsL)

witnessedScripts
:: Transaction
Expand Down Expand Up @@ -415,6 +459,13 @@ instance IsBlock Block where
& scriptsFromOutputs
(fromBabbageOutput <$> tx ^. Ledger.bodyTxL . Ledger.outputsTxBodyL)
TransactionConway tx ->
( fromConwayScript <$> tx ^. Ledger.witsTxL . Ledger.scriptTxWitsL
) & strictMaybe identity
(scriptFromAlonzoAuxiliaryData fromConwayScript)
(tx ^. Ledger.auxDataTxL)
& scriptsFromOutputs
(fromConwayOutput <$> tx ^. Ledger.bodyTxL . Ledger.outputsTxBodyL)
TransactionDijkstra tx ->
( tx ^. Ledger.witsTxL . Ledger.scriptTxWitsL
) & strictMaybe identity
(scriptFromAlonzoAuxiliaryData identity)
Expand Down Expand Up @@ -470,6 +521,12 @@ instance IsBlock Block where
SJust auxData ->
let meta = fromConwayMetadata auxData
in Just (hashMetadata meta, meta)
TransactionDijkstra tx ->
case tx ^. Ledger.auxDataTxL of
SNothing ->
Nothing
SJust auxData ->
Just (hashMetadata auxData, auxData)

spendRedeemer
:: Transaction
Expand All @@ -491,3 +548,5 @@ instance IsBlock Block where
Just (RedeemersBabbage (tx ^. Ledger.witsTxL . Ledger.rdmrsTxWitsL))
TransactionConway tx ->
Just (RedeemersConway (tx ^. Ledger.witsTxL . Ledger.rdmrsTxWitsL))
TransactionDijkstra tx ->
Just (RedeemersDisjkstra (tx ^. Ledger.witsTxL . Ledger.rdmrsTxWitsL))
Loading
Loading