From 9cfc1f53d61ce4b568f65be631fca49f5acbf5c8 Mon Sep 17 00:00:00 2001 From: kolam Date: Tue, 1 Sep 2026 16:41:54 -0400 Subject: [PATCH 01/45] Update ouroboros-network, ouroboros-consensus, cardano-api, cardano-cli and cardano-rpc for 11.2 release. * Replace leiosKernelTracer/leiosPeerTracer (removed) with the new Peras tracers, all wired and documented: perasCertDiffusionInbound/Outbound and perasVoteDiffusionInbound/Outbound under Peras.{Cert,Vote}.{Inbound,Outbound}, perasCertInclusion under Peras.Cert.Inclusion and perasVoteForging under Peras.Vote.Forging (the last two need distinct prefixes because both use the inner name RulesDecision) * Remove ObjectDiffusion inbound/outbound helpers from Consensus.hs (TraceObjectDiffusionInbound/Outbound no longer exported) * ExtValidationError has two new constructors: ExtValidationErrorPerasEpochContextResolver and ExtValidationErrorPerasCertInBlock; add pattern matches and Show (PerasError blk) constraint to all affected LogFormatting instances (TraceEvent, TraceAddBlockEvent, TraceValidationEvent, TraceInitChainSelEvent, TraceForgeEvent, ExtValidationError) * PerasVoteDB.TraceEvent now requires Show (PerasCert blk) instead of StandardHash blk for its LogFormatting instance * Drop stale tracing namespace registrations for removed tracers in Consistency.hs and Documentation.hs * Replace deprecated caseByronOrShelleyBasedEra with inEonForEra in tx-generator * Import mkNodeKernelAccess and NodeKernelAccess from Cardano.Rpc.Server.NodeKernelAccess in Run.hs * Update TraceRpc constructor names in Rpc.hs * Fix incomplete pattern match in namespaceFor for TraceRpcSync: add TraceRpcFetchBlockNotFound and TraceRpcNodeKernelAccessUnavailable * Rename StakeKeyAlreadyRegisteredDELEG to DelegAccountAlreadyRegistered * Bump plutus-scripts-bench bounds to cardano-api ^>=11.8 and plutus-* ^>=1.71 and its version to 1.0.6.0; tx-generator now requires plutus-scripts-bench ^>= 1.0.6 * Add PlutusV4 cost model values in emptyDijkstraGenesis (Dijkstra.hs) * Integrate ouroboros-consensus tracing * Integrate latest Dijkstra genesis changes --- bench/locli/locli.cabal | 2 +- .../plutus-scripts-bench.cabal | 10 +- .../Benchmarking/GeneratorTx/NodeToNode.hs | 11 +- .../src/Cardano/Benchmarking/Script/Core.hs | 2 +- .../src/Cardano/Benchmarking/Tracer.hs | 4 +- .../Cardano/TxGenerator/ProtocolParameters.hs | 4 +- bench/tx-generator/tx-generator.cabal | 12 +- cabal.project | 140 +- ...61008_102852_koslambrou_bump_deps_11_2.yml | 5 + .../cardano-node-chairman.cabal | 4 +- cardano-node/ChangeLog.md | 14 + cardano-node/cardano-node.cabal | 36 +- .../Cardano/Node/Configuration/LedgerDB.hs | 4 +- .../src/Cardano/Node/Configuration/POM.hs | 12 +- cardano-node/src/Cardano/Node/Orphans.hs | 5 +- .../src/Cardano/Node/Protocol/Byron.hs | 3 - .../src/Cardano/Node/Protocol/Cardano.hs | 2 +- .../src/Cardano/Node/Protocol/Dijkstra.hs | 78 +- .../src/Cardano/Node/Protocol/Shelley.hs | 4 - .../src/Cardano/Node/Protocol/Types.hs | 3 +- cardano-node/src/Cardano/Node/Queries.hs | 97 +- cardano-node/src/Cardano/Node/Run.hs | 15 +- .../src/Cardano/Node/TraceConstraints.hs | 8 +- cardano-node/src/Cardano/Node/Tracing.hs | 3 +- .../src/Cardano/Node/Tracing/Consistency.hs | 15 +- .../src/Cardano/Node/Tracing/Documentation.hs | 24 +- .../src/Cardano/Node/Tracing/Era/Byron.hs | 221 -- .../src/Cardano/Node/Tracing/Era/HardFork.hs | 372 -- .../src/Cardano/Node/Tracing/Era/Shelley.hs | 1970 ----------- .../src/Cardano/Node/Tracing/Formatting.hs | 84 - .../src/Cardano/Node/Tracing/Render.hs | 283 -- .../src/Cardano/Node/Tracing/Tracers.hs | 35 +- .../Tracing/Tracers/BlockReplayProgress.hs | 121 - .../Cardano/Node/Tracing/Tracers/ChainDB.hs | 3044 ----------------- .../Cardano/Node/Tracing/Tracers/Consensus.hs | 2510 -------------- .../Tracers/ConsensusStartupException.hs | 37 - .../Cardano/Node/Tracing/Tracers/HasIssuer.hs | 83 - .../Cardano/Node/Tracing/Tracers/KESInfo.hs | 186 - .../Node/Tracing/Tracers/LedgerMetrics.hs | 2 +- .../Node/Tracing/Tracers/NodeToNode.hs | 3 +- .../src/Cardano/Node/Tracing/Tracers/Rpc.hs | 44 +- .../Cardano/Node/Tracing/Tracers/Startup.hs | 7 - cardano-node/src/Cardano/Node/Types.hs | 14 + ...61008_102852_koslambrou_bump_deps_11_2.yml | 5 + cardano-submit-api/cardano-submit-api.cabal | 8 +- ...61008_102852_koslambrou_bump_deps_11_2.yml | 6 + cardano-testnet/cardano-testnet.cabal | 14 +- .../src/Testnet/Components/Configuration.hs | 2 +- cardano-testnet/src/Testnet/Defaults.hs | 23 + .../files/golden/version_cmd.cli | 6 +- .../Cardano/Testnet/Test/Node/Shutdown.hs | 2 +- .../Cardano/Testnet/Test/Rpc/FollowTip.hs | 64 +- .../Cardano/Testnet/Test/Rpc/SearchUtxos.hs | 3 +- .../Cardano/Testnet/Test/Rpc/Transaction.hs | 3 +- cardano-tracer/cardano-tracer.cabal | 8 +- .../src/Cardano/Tracer/Acceptors/Client.hs | 3 + .../src/Cardano/Tracer/Acceptors/Server.hs | 3 + .../test/Cardano/Tracer/Test/Forwarder.hs | 3 + flake.lock | 14 +- flake.nix | 7 +- nix/TODO.org | 4 - nix/haskell.nix | 71 + nix/nixos/tests/cardano-node-dbtools.nix | 76 +- nix/pkgs.nix | 21 + nix/workbench/backend/runner.nix | 16 +- nix/workbench/genesis/genesis-jq.sh | 27 +- .../genesis/zero/genesis/dijkstra.json | 15 +- trace-forward/src/Trace/Forward/Forwarding.hs | 9 +- trace-forward/trace-forward.cabal | 4 +- 69 files changed, 648 insertions(+), 9302 deletions(-) create mode 100644 cardano-node-chairman/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml delete mode 100644 cardano-node/src/Cardano/Node/Tracing/Era/Byron.hs delete mode 100644 cardano-node/src/Cardano/Node/Tracing/Era/HardFork.hs delete mode 100644 cardano-node/src/Cardano/Node/Tracing/Era/Shelley.hs delete mode 100644 cardano-node/src/Cardano/Node/Tracing/Formatting.hs delete mode 100644 cardano-node/src/Cardano/Node/Tracing/Render.hs delete mode 100644 cardano-node/src/Cardano/Node/Tracing/Tracers/BlockReplayProgress.hs delete mode 100644 cardano-node/src/Cardano/Node/Tracing/Tracers/ChainDB.hs delete mode 100644 cardano-node/src/Cardano/Node/Tracing/Tracers/Consensus.hs delete mode 100644 cardano-node/src/Cardano/Node/Tracing/Tracers/ConsensusStartupException.hs delete mode 100644 cardano-node/src/Cardano/Node/Tracing/Tracers/HasIssuer.hs delete mode 100644 cardano-node/src/Cardano/Node/Tracing/Tracers/KESInfo.hs create mode 100644 cardano-submit-api/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml create mode 100644 cardano-testnet/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml delete mode 100644 nix/TODO.org diff --git a/bench/locli/locli.cabal b/bench/locli/locli.cabal index 0dc2ca15045..9c83fd21d9d 100644 --- a/bench/locli/locli.cabal +++ b/bench/locli/locli.cabal @@ -128,7 +128,7 @@ library , hashable , optparse-applicative , ouroboros-consensus:ouroboros-consensus - , ouroboros-network:api ^>= 1.2 + , ouroboros-network:api ^>= 2.0 , sop-core , split , sqlite-easy >= 1.1.0.1 diff --git a/bench/plutus-scripts-bench/plutus-scripts-bench.cabal b/bench/plutus-scripts-bench/plutus-scripts-bench.cabal index 9d81a5b16a0..45c75343465 100644 --- a/bench/plutus-scripts-bench/plutus-scripts-bench.cabal +++ b/bench/plutus-scripts-bench/plutus-scripts-bench.cabal @@ -1,6 +1,6 @@ cabal-version: 3.0 name: plutus-scripts-bench -version: 1.0.5.0 +version: 1.0.6.0 synopsis: Plutus scripts used for benchmarking description: Plutus scripts used for benchmarking. category: Cardano, @@ -86,10 +86,10 @@ library -- IOG dependencies -------------------------- build-depends: - , cardano-api ^>=11.7 - , plutus-ledger-api ^>=1.65 - , plutus-tx ^>=1.65 - , plutus-tx-plugin ^>=1.65 + , cardano-api ^>=11.11 + , plutus-ledger-api ^>=1.71 + , plutus-tx ^>=1.71 + , plutus-tx-plugin ^>=1.71 ------------------------ -- Non-IOG dependencies diff --git a/bench/tx-generator/src/Cardano/Benchmarking/GeneratorTx/NodeToNode.hs b/bench/tx-generator/src/Cardano/Benchmarking/GeneratorTx/NodeToNode.hs index 97d4cdff188..a8d836adacb 100644 --- a/bench/tx-generator/src/Cardano/Benchmarking/GeneratorTx/NodeToNode.hs +++ b/bench/tx-generator/src/Cardano/Benchmarking/GeneratorTx/NodeToNode.hs @@ -37,10 +37,10 @@ import Ouroboros.Network.KeepAlive import Ouroboros.Network.Magic import Ouroboros.Network.Mux (MiniProtocolCb (..), OuroborosApplication (..), OuroborosBundle, RunMiniProtocol (..)) +import Ouroboros.Network.PerasSupport (PerasSupport (..)) import Ouroboros.Network.PeerSelection.PeerSharing (PeerSharing (..)) import Ouroboros.Network.PeerSelection.PeerSharing.Codec (decodeRemoteAddress, encodeRemoteAddress) -import Ouroboros.Network.PerasSupport (PerasSupport (..)) import Ouroboros.Network.Protocol.BlockFetch.Client (BlockFetchClient (..), blockFetchClientPeer) import Ouroboros.Network.Protocol.Handshake.Version (simpleSingletonVersions) @@ -156,17 +156,16 @@ benchmarkConnectTxSubmit EnvConsts { .. } handshakeTracer submissionTracer codec (cTxSubmission2Codec myCodecs) channel (txSubmissionClientPeer myTxSubClient) + , NtN.perasCertDiffusionProtocol = InitiatorProtocolOnly $ MiniProtocolCb $ \_ctx _channel -> + pure ((), Nothing) + , NtN.perasVoteDiffusionProtocol = InitiatorProtocolOnly $ MiniProtocolCb $ \_ctx _channel -> + pure ((), Nothing) , NtN.peerSharingProtocol = InitiatorProtocolOnly $ MiniProtocolCb $ \_ctx channel -> runPeer mempty (cPeerSharingCodec myCodecs) channel (peerSharingClientPeer peerSharingClientNull) - -- TODO Peras is not supported here - , NtN.perasCertDiffusionProtocol = InitiatorProtocolOnly $ MiniProtocolCb $ \_ctx _channel -> - error "tx-generator: Peras cert diffusion is unsupported" - , NtN.perasVoteDiffusionProtocol = InitiatorProtocolOnly $ MiniProtocolCb $ \_ctx _channel -> - error "tx-generator: Peras vote diffusion is unsupported" } n2nVer n2nData diff --git a/bench/tx-generator/src/Cardano/Benchmarking/Script/Core.hs b/bench/tx-generator/src/Cardano/Benchmarking/Script/Core.hs index f20e9c5725b..45bfa7f3638 100644 --- a/bench/tx-generator/src/Cardano/Benchmarking/Script/Core.hs +++ b/bench/tx-generator/src/Cardano/Benchmarking/Script/Core.hs @@ -172,7 +172,7 @@ queryEra = do AnyCardanoEra era <- mapExceptT liftIO . modifyError (Env.TxGenError . TxGenError . show) $ queryNodeLocalState localNodeConnectInfo (SpecificPoint $ chainTipToChainPoint chainTip) QueryCurrentEra - caseByronOrShelleyBasedEra + inEonForEra (liftTxGenError $ TxGenError "queryEra Byron not supported") (return . AnyShelleyBasedEra) era diff --git a/bench/tx-generator/src/Cardano/Benchmarking/Tracer.hs b/bench/tx-generator/src/Cardano/Benchmarking/Tracer.hs index 08fd74ae013..1d8343b2216 100644 --- a/bench/tx-generator/src/Cardano/Benchmarking/Tracer.hs +++ b/bench/tx-generator/src/Cardano/Benchmarking/Tracer.hs @@ -39,6 +39,7 @@ import Cardano.Node.Tracing.NodeInfo () import Ouroboros.Network.IOManager (IOManager) import qualified Ouroboros.Network.Protocol.TxSubmission2.Type as TxSubmission import Ouroboros.Network.Tracing () +import Network.Mux.Tracing () import Control.Exception (SomeException (..)) import Control.Monad (forM, guard) @@ -51,7 +52,6 @@ import Data.Maybe (fromMaybe) import qualified Data.Text as Text import Data.Time.Clock import GHC.Generics -import Network.Mux.Tracing () import qualified Network.TypedProtocol.Codec as TypedProtocol import Trace.Forward.Forwarding (InitForwardingConfig (..), initForwardingDelayed) @@ -182,7 +182,7 @@ configSilent :: ConfigOption configSilent = ConfSeverity (SeverityF Nothing) initialTraceConfig :: TraceConfig -initialTraceConfig = emptyTraceConfig +initialTraceConfig = emptyTraceConfig { tcOptions = Map.fromList [ ([], [configSilent]) , setMaxDetail TracerNameBench diff --git a/bench/tx-generator/src/Cardano/TxGenerator/ProtocolParameters.hs b/bench/tx-generator/src/Cardano/TxGenerator/ProtocolParameters.hs index bfb31bf7626..d16c77e200e 100644 --- a/bench/tx-generator/src/Cardano/TxGenerator/ProtocolParameters.hs +++ b/bench/tx-generator/src/Cardano/TxGenerator/ProtocolParameters.hs @@ -326,7 +326,7 @@ requireParam paramName = maybe (Left $ PpceMissingParameter paramName) mkProtVer :: (Natural, Word32) -> Either ProtocolParametersConversionError Ledger.ProtVer mkProtVer (majorProtVer, minorProtVer) = maybeToRight (PpceVersionInvalid majorProtVer) $ - (`Ledger.ProtVer` minorProtVer) <$> Ledger.mkVersion majorProtVer + (`Ledger.ProtVer` fromIntegral minorProtVer) <$> Ledger.mkVersion majorProtVer -- Duplicated from "cardano-api" module "Cardano.Api.Internal.ProtocolParameters" boundRationalEither @@ -528,7 +528,7 @@ fromShelleyCommonPParams fromShelleyCommonPParams pp = ProtocolParameters { protocolParamProtocolVersion = case pp ^. ppProtocolVersionL of - Ledger.ProtVer a b -> (Ledger.getVersion a, b) + Ledger.ProtVer a b -> (Ledger.getVersion a, fromIntegral b) , protocolParamMaxBlockHeaderSize = fromIntegral $ pp ^. ppMaxBHSizeL , protocolParamMaxBlockBodySize = fromIntegral $ pp ^. ppMaxBBSizeL , protocolParamMaxTxSize = fromIntegral $ pp ^. ppMaxTxSizeL diff --git a/bench/tx-generator/tx-generator.cabal b/bench/tx-generator/tx-generator.cabal index 875a0c799e3..fc662da2f21 100644 --- a/bench/tx-generator/tx-generator.cabal +++ b/bench/tx-generator/tx-generator.cabal @@ -30,7 +30,7 @@ common with-library -- It makes sure, we only depend on that package if it is buildable. -- The tx-generator will fall back to pre-serialized Plutus scripts if this package is not present. if flag(withplutuslib) && !(impl(ghc <9.6) || impl(ghc >=9.7)) - build-depends: plutus-scripts-bench ^>= 1.0.5 + build-depends: plutus-scripts-bench ^>= 1.0.6 cpp-options: -DWITH_LIBRARY common maybe-unix @@ -116,13 +116,13 @@ library , attoparsec-aeson , base16-bytestring , bytestring - , cardano-api ^>= 11.7 + , cardano-api ^>= 11.11 , cardano-binary - , cardano-cli ^>= 11.2.2 + , cardano-cli ^>= 11.6 , cardano-crypto-class , cardano-crypto-wrapper , cardano-data - , cardano-diffusion ^>= 1.1.1 + , cardano-diffusion ^>= 1.3 , cardano-git-rev ^>= 0.2.2 , cardano-ledger-alonzo , cardano-ledger-api @@ -149,8 +149,8 @@ library , network-mux , network-uri , optparse-applicative - , ouroboros-consensus:{ouroboros-consensus, cardano, diffusion} >= 4.2.0.1 - , ouroboros-network:{api, framework, tracing, ouroboros-network, protocols} >= 1.1 + , ouroboros-consensus:{ouroboros-consensus, cardano, diffusion} ^>= 5.2 + , ouroboros-network:{api, framework, ouroboros-network, protocols, tracing} >= 1.3 , plutus-ledger-api , plutus-tx , random diff --git a/cabal.project b/cabal.project index a5ebe6bf99d..7f2eccc5557 100644 --- a/cabal.project +++ b/cabal.project @@ -13,18 +13,17 @@ repository cardano-haskell-packages -- See CONTRIBUTING for information about these, including some Nix commands -- you need to run if you change them index-state: - , hackage.haskell.org 2026-08-14T13:38:07Z - , cardano-haskell-packages 2026-09-22T20:39:47Z + , hackage.haskell.org 2026-09-29T11:48:37Z + , cardano-haskell-packages 2026-10-27T09:47:50Z constraints: -- haskell.nix patch does not work for 1.6.8 - -- grapesy currently depends on crypton-x509-system (>=1.6 && <1.7) , any.crypton-x509-system < 1.6.8 || >= 1.7 - -- haskell.nix tries to use 0.7.1.5 for some reason , any.proto-lens >= 0.7.1.7 -- https://github.com/channable/alfred-margaret/pull/76 , any.alfred-margaret < 2.1.1.0 || > 2.1.1.0 + , any.grapesy >= 1.2.1 -- acts has a finitary flag; disabling it avoids pulling in finitary entirely, -- which sidesteps the GHC type-checker plugin incompatibility with @@ -48,9 +47,8 @@ packages: bench/trace-schemas/scripts/schema-gen trace-forward --- Shipped as a release binary but not a dependency of any local package, so it --- has to be added to the install plan explicitly. -extra-packages: dmq-node >= 0.7.0.0 +-- Needed when cross compiling +extra-packages: dmq-node program-options ghc-options: -Werror @@ -65,15 +63,9 @@ package cryptonite -- generation is dubious. Set the flag so we use /dev/urandom by default. flags: -support_rdrand -package snap-server - flags: -openssl - package bitvec flags: -simd -package cardano-diffusion - flags: +optparse-applicative-fork - -- Find libsnappy through pkg-config instead of LIBRARY_PATH. On Windows, -- LIBRARY_PATH pointing at MSYS2's clang64/lib makes GHC pick up its libc++.a -- instead of the one bundled with GHC, which crashes Template Haskell. @@ -85,91 +77,75 @@ if os(windows) package plutus-scripts-bench haddock-options: "--optghc=-fplugin-opt=PlutusTx.Plugin:defer-errors" --- There is a suspected bug in `cabal` (https://github.com/haskell/cabal/issues/11663) --- that can be worked around with the following allow-newer stanzas -allow-newer: - , io-sim:time - , io-classes:time - --- cabal-allow-newer begin if impl(ghc >= 9.14) + -- some-1.1 adds EqP/OrdP superclasses to GEq/GCompare, which plutus-core + -- 1.71.0.0 is not written against: + -- + -- Universe/Core.hs:755:10: error: [GHC-39999] + -- Could not deduce 'Data.EqP.EqP (ValueOf uni)' + -- arising from the superclasses of an instance declaration + -- + -- some-1.0.6 is what every other compiler resolves to and it already allows + -- base < 4.23, so it is usable on 9.14; the solver simply prefers the newest. + -- Pin it rather than relaxing dependent-sum's some >= 1.0.4 && < 1.0.7 bound. + constraints: + , any.some < 1.1 + + -- GHC 9.14.1 ships base-4.22, template-haskell-2.24, containers-0.8, + -- time-1.15 and ghc-9.14.1. Every entry below is a dependency whose upper + -- bound predates one of those and has no release on Hackage/CHaP that admits + -- it, so the solver has no plan without the relaxation. allow-newer: - , async-timer:unliftio-core - , attoparsec-iso8601:time + -- base < 4.22 , bytestring-trie:base - , canonical-json:containers , cborg:base - , cborg:containers - , cborg-json:aeson , cborg-json:base , compact:base - , crypton-connection:tls + , ekg-json:base + , http-api-data:base + , serialise:base + , servant-server:base + , tdigest:base + , with-utf8:base + -- template-haskell < 2.24 + , safe-wild-cards:template-haskell + , serdoc-core:template-haskell + -- containers < 0.8 + , canonical-json:containers + , cborg:containers , dependent-map:containers - , diff-containers:base , dictionary-sharing:containers - , dmq-node:containers - , dmq-node:time - , ekg-json:aeson - , ekg-json:text , ekg-prometheus-adapter:containers - , ekg-wai:time - , errors:transformers-compat - , fs-sim:QuickCheck - , grapesy:aeson - , grapesy:base - , grapesy:containers - , grapesy:time-manager - , grapesy:tls - , grpc-spec:aeson - , grpc-spec:base - , grpc-spec:containers - , iohk-monitoring:contra-tracer , lens-family:containers , lens-family-core:containers - , locli:ouroboros-network - , microstache:aeson - , monad-control:transformers-compat - , nothunks:containers - , nothunks:time - , optparse-generic:time - , partial-order:containers - , pipes-safe:containers - , pipes-safe:mtl - , pipes-safe:primitive - , pipes-safe:transformers , prometheus:containers - , safe-wild-cards:template-haskell - , serdoc-core:template-haskell - , serialise:base , serialise:containers + -- time < 1.15 + , ekg-wai:time , serialise:time - , servant:QuickCheck - , servant:base - , servant-server:aeson - , servant-server:attoparsec - , servant-server:base - , servant-server:base-compat - , servant-server:base64-bytestring - , servant-server:bytestring - , servant-server:containers - , servant-server:http-api-data - , servant-server:http-types - , servant-server:network - , servant-server:servant - , servant-server:text - , servant-server:transformers - , servant-server:warp - , strict-checked-vars:io-classes - , strict-stm:base - , strict-stm:io-classes - , tdigest:base - , time-locale-compat:time - , tracer-transformers:contra-tracer + -- io-classes: io-sim requires ^>=1.11 while cardano-node and + -- ouroboros-network cap at ^>=1.8 || ^>=1.9. On 9.14 every older io-sim is + -- excluded by base < 4.22, so the solver is forced to io-classes 1.11 and + -- all of these bounds have to give way together. + , blockio:io-classes + , cardano-diffusion:io-classes + , cardano-node:io-classes + , cardano-node-chairman:io-classes + , fs-api:io-classes + , fs-sim:io-classes + , kes-agent:io-classes + , lsm-tree:io-classes + , network-mux:io-classes + , ouroboros-consensus:io-classes + , ouroboros-network:io-classes + -- Other + , cborg-json:aeson + , kes-agent:aeson , vary:aeson - , with-utf8:base --- cabal-allow-newer end + , errors:transformers-compat + , monad-control:transformers-compat + , servant-server:http-api-data -- IMPORTANT -- Do NOT add more source-repository-package stanzas here unless they are strictly -- temporary! Please read the section in CONTRIBUTING about updating dependencies. - diff --git a/cardano-node-chairman/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml b/cardano-node-chairman/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml new file mode 100644 index 00000000000..c828358e7bd --- /dev/null +++ b/cardano-node-chairman/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml @@ -0,0 +1,5 @@ +pr: 6677 +kind: + - maintenance +description: | + Bumped `cardano-cli` to 11.3 and `cardano-crypto-class` to 2.6 for the 11.2 release. diff --git a/cardano-node-chairman/cardano-node-chairman.cabal b/cardano-node-chairman/cardano-node-chairman.cabal index 86723446f1c..ac993ae33ae 100644 --- a/cardano-node-chairman/cardano-node-chairman.cabal +++ b/cardano-node-chairman/cardano-node-chairman.cabal @@ -67,7 +67,7 @@ test-suite chairman-tests build-depends: , cardano-api , cardano-testnet - , cardano-crypto-class ^>=2.5 + , cardano-crypto-class ^>=2.6 , data-default-class , filepath , hedgehog @@ -86,5 +86,5 @@ test-suite chairman-tests ghc-options: -threaded -rtsopts "-with-rtsopts=-N -T" build-tool-depends: cardano-node:cardano-node - , cardano-cli:cardano-cli ^>= 11.2.2 + , cardano-cli:cardano-cli ^>= 11.6 , cardano-node-chairman:cardano-node-chairman diff --git a/cardano-node/ChangeLog.md b/cardano-node/ChangeLog.md index 222f37bfac2..7c012c7f71e 100644 --- a/cardano-node/ChangeLog.md +++ b/cardano-node/ChangeLog.md @@ -10,6 +10,20 @@ `main` now runs under `withCP65001` and `withUtf8`. ([#6711](https://github.com/IntersectMBO/cardano-node/issues/6711)) +- Tracing changes visible to log consumers, now that the consensus tracing + instances are used instead of the node's own copy: + - mempool rejections always carry `errdetails`; + - the detailed `"tx"` field of mempool traces is now the CBOR in hex; + - new namespaces `Mempool.CapacityChanged`, + `Snapshot.ConfiguredSnapshotPolicy`, `Snapshot.ImplausibleSnapshotPolicy`, + `RPC.SubmitService.ReadMempool.Span` and + `RPC.SubmitService.WatchMempool.Span`; + - the Peras certificate inclusion and vote forging tracers are wired, under + `Peras.Cert.Inclusion` and `Peras.Vote.Forging`; + - the ledger predicate failure kind for an already-registered delegation + account is now `DelegAccountAlreadyRegistered`. + ([#6677](https://github.com/IntersectMBO/cardano-node/pull/6677)) + - `slotsMissed_int` no longer counts the slots that elapse while block forging is disabled. While forging is off there is no forging thread, hence no leadership check events at all, so `Forge.Stats` kept the last slot it had diff --git a/cardano-node/cardano-node.cabal b/cardano-node/cardano-node.cabal index 9ffd04918be..88f036858d8 100644 --- a/cardano-node/cardano-node.cabal +++ b/cardano-node/cardano-node.cabal @@ -99,21 +99,11 @@ library Cardano.Node.Tracing.Consistency Cardano.Node.Tracing.DefaultTraceConfig Cardano.Node.Tracing.Documentation - Cardano.Node.Tracing.Era.Byron - Cardano.Node.Tracing.Era.HardFork - Cardano.Node.Tracing.Era.Shelley - Cardano.Node.Tracing.Formatting Cardano.Node.Tracing.NodeInfo Cardano.Node.Tracing.NodeStartupInfo - Cardano.Node.Tracing.Render Cardano.Node.Tracing.StateRep Cardano.Node.Tracing.Tracers - Cardano.Node.Tracing.Tracers.BlockReplayProgress - Cardano.Node.Tracing.Tracers.ChainDB - Cardano.Node.Tracing.Tracers.Consensus - Cardano.Node.Tracing.Tracers.ConsensusStartupException Cardano.Node.Tracing.Tracers.ForgingStats - Cardano.Node.Tracing.Tracers.KESInfo Cardano.Node.Tracing.Tracers.LedgerMetrics Cardano.Node.Tracing.Tracers.NodeToClient Cardano.Node.Tracing.Tracers.NodeToNode @@ -121,7 +111,6 @@ library Cardano.Node.Tracing.Tracers.Resources Cardano.Node.Tracing.Tracers.Rpc Cardano.Node.Tracing.Tracers.Shutdown - Cardano.Node.Tracing.Tracers.HasIssuer Cardano.Node.Tracing.Tracers.Startup Cardano.Node.Types @@ -133,26 +122,22 @@ library , async , base16-bytestring , bytestring - , cardano-api ^>= 11.7 - , cardano-data - , cardano-crypto-class ^>=2.5 + , cardano-api ^>= 11.11 + , cardano-crypto-class ^>=2.6 , cardano-crypto-wrapper , cardano-git-rev ^>=0.2.2 , cardano-ledger-alonzo - , cardano-ledger-allegra , cardano-ledger-api - , cardano-ledger-babbage - , cardano-ledger-binary >= 1.9.1.0 + , cardano-ledger-binary ^>= 1.10.1 , cardano-ledger-byron - , cardano-ledger-conway >= 1.22.1.0 + , cardano-ledger-conway >= 1.24 , cardano-ledger-core , cardano-ledger-dijkstra , cardano-ledger-shelley , cardano-prelude - , cardano-protocol ^>= 0.1 - , cardano-protocol-tpraos >= 1.4 + , cardano-protocol ^>= 0.2 , cardano-slotting >= 0.2 - , cardano-rpc ^>= 11.4 + , cardano-rpc ^>= 11.5 , cborg ^>= 0.2.4 , containers , contra-tracer >= 0.2.1 @@ -167,7 +152,6 @@ library , hashable , hostname , io-classes:{io-classes,strict-stm,si-timers} ^>= 1.8 || ^>= 1.9 - , kes-agent ^>=1.3 , microlens , mmap , network-mux @@ -176,19 +160,17 @@ library , network-mux >= 0.8 , nothunks , optparse-applicative - , ouroboros-consensus:{ouroboros-consensus, lsm, cardano, diffusion, protocol} ^>= 4.2.0.1 - , ouroboros-network:{api, ouroboros-network, orphan-instances, framework, protocols, tracing} ^>= 1.2 - , cardano-diffusion:{api, cardano-diffusion, tracing, orphan-instances} ^>=1.1.1 + , ouroboros-consensus:{ouroboros-consensus, lsm, cardano, diffusion, protocol, tracing} ^>= 5.2 + , ouroboros-network:{api, ouroboros-network, orphan-instances, framework, protocols, tracing} ^>= 2.0 + , cardano-diffusion:{api, cardano-diffusion, tracing, orphan-instances} ^>=1.3 , prettyprinter , prettyprinter-ansi-terminal - , psqueues , random , resource-registry , safe-exceptions , sop-core -- avoid stm-2.5.2 https://github.com/haskell/stm/issues/76 , stm <2.5.2 || >=2.5.3 - , strict-sop-core , sop-core , sop-extras , text >= 2.0 diff --git a/cardano-node/src/Cardano/Node/Configuration/LedgerDB.hs b/cardano-node/src/Cardano/Node/Configuration/LedgerDB.hs index 04ce0bebb0e..752225e0b65 100644 --- a/cardano-node/src/Cardano/Node/Configuration/LedgerDB.hs +++ b/cardano-node/src/Cardano/Node/Configuration/LedgerDB.hs @@ -9,7 +9,6 @@ module Cardano.Node.Configuration.LedgerDB ( DeprecatedOptions (..), LedgerDbConfiguration (..), LedgerDbSelectorFlag (..), - Gigabytes, noDeprecatedOptions, selectorToArgs, ) where @@ -22,7 +21,7 @@ import Ouroboros.Consensus.Storage.LedgerDB.Snapshots import qualified Ouroboros.Consensus.Storage.LedgerDB.V2.InMemory as InMemory import qualified Ouroboros.Consensus.Storage.LedgerDB.V2.LSM as LSM -import qualified Data.Aeson.Types as Aeson (FromJSON) +import qualified Data.Aeson as Aeson import Data.Maybe (fromMaybe) import Data.Proxy import System.Random (StdGen) @@ -86,3 +85,4 @@ selectorToArgs (V2LSM fp fpExport) fastStoragePath = (fromMaybe "lsm" fp) fpExport fastStoragePath + LSM.DiskCacheAll diff --git a/cardano-node/src/Cardano/Node/Configuration/POM.hs b/cardano-node/src/Cardano/Node/Configuration/POM.hs index 3b6de2bea52..d4bbd2cbbe9 100644 --- a/cardano-node/src/Cardano/Node/Configuration/POM.hs +++ b/cardano-node/src/Cardano/Node/Configuration/POM.hs @@ -53,6 +53,7 @@ import Ouroboros.Consensus.Storage.LedgerDB.Snapshots (NumOfDiskSnapsh mithrilSnapshotPolicyArgs) import Ouroboros.Network.Diffusion.Configuration as Configuration import qualified Ouroboros.Network.Diffusion.Configuration as Ouroboros +import Ouroboros.Network.Hashable (mkSaltIO) import qualified Ouroboros.Network.Mux as Mux import Ouroboros.Network.OrphanInstances () import qualified Ouroboros.Network.PeerSelection.Governor as PeerSelection @@ -74,7 +75,6 @@ import Data.Yaml (decodeFileThrow) import GHC.Generics (Generic) import Options.Applicative import System.FilePath (takeDirectory, ()) -import System.Random (randomIO) import Generic.Data (gmappend) import Generic.Data.Orphans () @@ -213,7 +213,7 @@ data NodeConfiguration -- -- * `NoResponderCoreAffinity` corresponds to `Ouroboros.Network.Mux.noBindForkPolicy` -- * `ResponderCoreAffinity` corresponds to `Ouroboros.Network.Mux.responderForkPolicy` --- with a `randomIO` generated salt and `getNumCapabilities`. +-- with a `mkSaltIO` generated salt and `getNumCapabilities`. -- data ResponderCoreAffinityPolicy = NoResponderCoreAffinity | ResponderCoreAffinity deriving (Eq, Show, Generic, FromJSON) @@ -221,7 +221,7 @@ data ResponderCoreAffinityPolicy = NoResponderCoreAffinity | ResponderCoreAffini getForkPolicy :: Hashable peerAddr => ResponderCoreAffinityPolicy -> IO (Mux.ForkPolicy peerAddr) getForkPolicy = \case NoResponderCoreAffinity -> pure Mux.noBindForkPolicy - ResponderCoreAffinity -> Mux.responderForkPolicy <$> randomIO <*> getNumCapabilities + ResponderCoreAffinity -> Mux.responderForkPolicy <$> mkSaltIO <*> getNumCapabilities data PartialNodeConfiguration = PartialNodeConfiguration @@ -499,9 +499,9 @@ instance FromJSON PartialNodeConfiguration where mTopLevelSnapNum <- snapNum v let topLevelOptionsSet = - zip [ void mTopLevelSnapInterval - , void mTopLevelSnapNum] - ["SnapshotInterval", "NumOfDiskSnapshots"] + zip + [void mTopLevelSnapInterval, void mTopLevelSnapNum] + ["SnapshotInterval", "NumOfDiskSnapshots"] deprecatedOpts = DeprecatedOptions [ y | (x, y) <- topLevelOptionsSet, isJust x ] mLedgerDB <- v .:? "LedgerDB" diff --git a/cardano-node/src/Cardano/Node/Orphans.hs b/cardano-node/src/Cardano/Node/Orphans.hs index fdbde6766be..7cc16a229f3 100644 --- a/cardano-node/src/Cardano/Node/Orphans.hs +++ b/cardano-node/src/Cardano/Node/Orphans.hs @@ -21,6 +21,7 @@ import Ouroboros.Consensus.Protocol.Praos.Common (PraosCredentialsSour import Ouroboros.Consensus.Storage.LedgerDB.Snapshots (Flag (..)) import Ouroboros.Network.SizeInBytes (SizeInBytes (..)) +import qualified Data.List.NonEmpty as NE import Data.Aeson.Types import Data.String (IsString (..)) import qualified Data.Text as Text @@ -80,6 +81,6 @@ instance HasTypeProxy (PraosCredentialsSource StandardCrypto) where -- TODO(11.0): consider moving to `cardano-api` instance HasTextEnvelope (PraosCredentialsSource StandardCrypto) where - textEnvelopeType _ = - "PraosCredentialsSource_" + textEnvelopeTypes _ = + NE.singleton $ "PraosCredentialsSource_" <> fromString (Crypto.algorithmNameKES (Proxy @(KES StandardCrypto))) diff --git a/cardano-node/src/Cardano/Node/Protocol/Byron.hs b/cardano-node/src/Cardano/Node/Protocol/Byron.hs index 9a8550ab47e..eddb6a77c45 100644 --- a/cardano-node/src/Cardano/Node/Protocol/Byron.hs +++ b/cardano-node/src/Cardano/Node/Protocol/Byron.hs @@ -26,9 +26,6 @@ import qualified Cardano.Crypto.Hash as Crypto import qualified Cardano.Crypto.Hashing as Byron.Crypto import Cardano.Crypto.ProtocolMagic (RequiresNetworkMagic) import Cardano.Node.Protocol.Types -import Cardano.Node.Tracing.Era.Byron () -import Cardano.Node.Tracing.Era.HardFork () -import Cardano.Node.Tracing.Tracers.ChainDB () import Cardano.Node.Types as Node import Cardano.Prelude (canonicalDecodePretty) import Ouroboros.Consensus.Cardano diff --git a/cardano-node/src/Cardano/Node/Protocol/Cardano.hs b/cardano-node/src/Cardano/Node/Protocol/Cardano.hs index 731c889a968..423a4a2e544 100644 --- a/cardano-node/src/Cardano/Node/Protocol/Cardano.hs +++ b/cardano-node/src/Cardano/Node/Protocol/Cardano.hs @@ -191,7 +191,7 @@ mkSomeConsensusProtocolCardano NodeByronProtocolConfiguration { } , Consensus.cardanoProtocolVersion = if npcExperimentalHardForksEnabled then ProtVer (natVersion @12) 0 - else ProtVer (natVersion @11) 0 + else ProtVer (natVersion @11) 1 -- The remaining arguments specify the parameters needed to transition between two eras , Consensus.cardanoLedgerTransitionConfig = Ledger.mkLatestTransitionConfig diff --git a/cardano-node/src/Cardano/Node/Protocol/Dijkstra.hs b/cardano-node/src/Cardano/Node/Protocol/Dijkstra.hs index 39c146ed50c..cbab873f01e 100644 --- a/cardano-node/src/Cardano/Node/Protocol/Dijkstra.hs +++ b/cardano-node/src/Cardano/Node/Protocol/Dijkstra.hs @@ -14,16 +14,24 @@ import Cardano.Api import qualified Cardano.Crypto.Hash.Class as Crypto import Cardano.Ledger.BaseTypes import qualified Cardano.Ledger.Binary as L +import Cardano.Ledger.Coin (CoinPerByte (..), CompactForm (..)) +import Cardano.Ledger.Core (MaxPledgeLeverage (..)) import Cardano.Ledger.Dijkstra.Genesis (DijkstraGenesis (..)) import qualified Cardano.Ledger.Dijkstra.Genesis as Dijkstra import Cardano.Ledger.Dijkstra.PParams +import Cardano.Ledger.Plutus.ExUnits (ExUnits (..), OrdExUnits (..)) +import qualified Cardano.Ledger.Plutus.CostModels as L +import qualified Cardano.Ledger.Plutus.Language as L import Cardano.Node.Orphans () import Cardano.Node.Protocol.Shelley (GenesisReadError, readGenesisAny) import Cardano.Node.Types +import Cardano.Slotting.Slot (SlotInterval (..)) import qualified Data.ByteString.Lazy as LB - -import Data.Maybe (fromMaybe) +import Data.Int +import qualified Data.Map.Strict as Map +import Data.Maybe (fromMaybe) +import Data.Word readGenesisMaybe :: Maybe GenesisFile -> Maybe GenesisHash @@ -35,15 +43,67 @@ readGenesisMaybe Nothing _ = do genesisHash = GenesisHash (Crypto.hashWith id $ LB.toStrict $ L.serialize (L.natVersion @11) emptyDijkstraGenesis) return (dijkstraGenesis, genesisHash) +-- PlutusV4 uses the same parameter set as PlutusV3. +-- Language index 3 corresponds to PlutusV4. +plutusV4CostModel :: Map.Map Word8 [Int64] +plutusV4CostModel = Map.singleton 3 plutusV4ExampleValues + +plutusV4ExampleValues :: [Int64] +plutusV4ExampleValues = + [ 205665, 812, 1, 1, 1000, 571, 0, 1, 1000, 24177, 4, 1, 1000, 32, 117366, 10475 + , 4, 23000, 100, 23000, 100, 23000, 100, 23000, 100, 23000, 100, 23000, 100, 100 + , 100, 23000, 100, 19537, 32, 175354, 32, 46417, 4, 221973, 511, 0, 1, 89141, 32 + , 497525, 14068, 4, 2, 196500, 453240, 220, 0, 1, 1, 1000, 28662, 4, 2, 245000 + , 216773, 62, 1, 1060367, 12586, 1, 208512, 421, 1, 187000, 1000, 52998, 1, 80436 + , 32, 43249, 32, 1000, 32, 80556, 1, 57667, 4, 1000, 10, 197145, 156, 1, 197145 + , 156, 1, 204924, 473, 1, 208896, 511, 1, 52467, 32, 64832, 32, 65493, 32, 22558 + , 32, 16563, 32, 76511, 32, 196500, 453240, 220, 0, 1, 1, 69522, 11687, 0, 1, 60091 + , 32, 196500, 453240, 220, 0, 1, 1, 196500, 453240, 220, 0, 1, 1, 1159724, 392670 + , 0, 2, 806990, 30482, 4, 1927926, 82523, 4, 265318, 0, 4, 0, 85931, 32, 205665, 812 + , 1, 1, 41182, 32, 212342, 32, 31220, 32, 32696, 32, 43357, 32, 32247, 32, 38314, 32 + , 35190005, 10, 57996947, 18975, 10, 39121781, 32260, 10, 23000, 100, 23000, 100, 832808 + , 18, 3209094, 6, 331451, 1, 65990684, 23097, 18, 114242, 18, 94393407, 87060, 18, 16420089 + , 18, 2145798, 36, 3795345, 12, 889023, 1, 204237282, 23271, 36, 129165, 36, 189977790 + , 85902, 36, 33012864, 36, 388443360, 1, 401885761, 72, 2331379, 72, 1927926, 82523 + , 4, 117366, 10475, 4, 1292075, 24469, 74, 0, 1, 936157, 49601, 237, 0, 1 + ] + emptyDijkstraGenesis :: DijkstraGenesis emptyDijkstraGenesis = - let upgradePParamsDef = UpgradeDijkstraPParams - { udppMaxRefScriptSizePerBlock = 1048576 - , udppMaxRefScriptSizePerTx = 204800 - , udppRefScriptCostStride = unsafeNonZero 25600 - , udppRefScriptCostMultiplier = fromMaybe (error "impossible") $ boundRational 1.2 - } - in DijkstraGenesis { dgUpgradePParams = upgradePParamsDef } + case L.mkCostModelsLenient plutusV4CostModel >>= Map.lookup L.PlutusV4 . L.costModelsValid of + Nothing -> error "emptyDijkstraGenesis: missing PlutusV4 cost model in default cost models." + Just costModel -> + let upgradePParamsDef = + UpgradeDijkstraPParams + { udppMaxRefScriptSizePerBlock = 1048576 + , udppMaxRefScriptSizePerTx = 204800 + , udppRefScriptCostStride = unsafeNonZero 25600 + , udppRefScriptCostMultiplier = fromMaybe (error "impossible") $ boundRational 1.2 + , udppMaxPledgeLeverage = MaxPledgeLeverage SNothing + , udppMinPoolMargin = minBound + , udppPlutusV4CostModel = costModel + , udppLeiosAnnouncementPeriodLength = Milliseconds32 1000 + , udppLeiosVotePeriodLength = Milliseconds32 1000 + , udppLeiosDiffusionPeriodLength = Milliseconds32 1000 + , udppLeiosCommitteeSize = 1 + , udppLeiosQuorumStakeThreshold = minBound + , udppMaxEndorserBlockReferencesSize = 0 + , udppMaxEndorserBlockTxsSize = 0 + , udppMaxEndorserBlockExUnits = OrdExUnits (ExUnits 0 0) + , udppMaxRefScriptSizePerEndorserBlock = 0 + , udppPerasMinCandidateBlockAge = SlotInterval 0 + -- The healing factor must be strictly positive. + , udppPerasHealingFactor = fromMaybe (error "impossible") $ boundRational 0.5 + , udppPerasCertBoost = 0 + , udppPerasTargetCommitteeSize = 1 + , udppPerasBootstrapRound = SNothing + , udppPerasQuorumThresholdSafetyMargin = minBound + -- No pricing logic uses these yet, they are enabled by a later + -- intra-era hard fork within the Dijkstra era. + , udppRefInputsCostPerMultiAssetPolicy = Coin 0 + , udppRefInputsCostPerDatumByte = CoinPerByte (CompactCoin 0) + } + in DijkstraGenesis { dgUpgradePParams = upgradePParamsDef } readGenesis :: GenesisFile diff --git a/cardano-node/src/Cardano/Node/Protocol/Shelley.hs b/cardano-node/src/Cardano/Node/Protocol/Shelley.hs index f2cd44972e5..dd968371b12 100644 --- a/cardano-node/src/Cardano/Node/Protocol/Shelley.hs +++ b/cardano-node/src/Cardano/Node/Protocol/Shelley.hs @@ -34,10 +34,6 @@ import Cardano.Ledger.Keys (coerceKeyRole) import qualified Cardano.Ledger.Shelley.Genesis as Shelley import Cardano.Node.Orphans () import Cardano.Node.Protocol.Types -import Cardano.Node.Tracing.Era.HardFork () -import Cardano.Node.Tracing.Era.Shelley () -import Cardano.Node.Tracing.Formatting () -import Cardano.Node.Tracing.Tracers.ChainDB () import Cardano.Node.Types import qualified Ouroboros.Consensus.Cardano as Consensus import Ouroboros.Consensus.HardFork.Combinator.AcrossEras () diff --git a/cardano-node/src/Cardano/Node/Protocol/Types.hs b/cardano-node/src/Cardano/Node/Protocol/Types.hs index 42fa4d46ef2..03629b1c04b 100644 --- a/cardano-node/src/Cardano/Node/Protocol/Types.hs +++ b/cardano-node/src/Cardano/Node/Protocol/Types.hs @@ -14,8 +14,9 @@ module Cardano.Node.Protocol.Types import qualified Cardano.Api as Api import Cardano.Node.Orphans () -import Cardano.Node.Queries (HasKESInfo, HasKESMetricsData) +import Cardano.Node.Queries (HasKESMetricsData) import Cardano.Node.TraceConstraints (TraceConstraints) +import Ouroboros.Consensus.Tracing (HasKESInfo) import Ouroboros.Network.Block (HeaderHash) import Control.DeepSeq (NFData) diff --git a/cardano-node/src/Cardano/Node/Queries.hs b/cardano-node/src/Cardano/Node/Queries.hs index 65391519c84..6f74173da65 100644 --- a/cardano-node/src/Cardano/Node/Queries.hs +++ b/cardano-node/src/Cardano/Node/Queries.hs @@ -11,12 +11,9 @@ {-# LANGUAGE UndecidableInstances #-} module Cardano.Node.Queries - ( ConvertTxId (..) - -- * KES - , MaxKESEvolutions (..) + ( -- * KES + MaxKESEvolutions (..) , OperationalCertStartKESPeriod (..) - , GetKESInfo(..) - , HasKESInfo(..) , KESMetricsData (..) , HasKESMetricsData (..) -- * General ledger @@ -38,28 +35,22 @@ module Cardano.Node.Queries import qualified Cardano.Chain.Block as Byron import qualified Cardano.Chain.UTxO as Byron -import qualified Cardano.Crypto.Hash as Crypto -import qualified Cardano.Crypto.Hashing as Byron.Crypto import Cardano.Crypto.KES.Class (Period) import Cardano.Ledger.BaseTypes (StrictMaybe (..), fromSMaybe) import qualified Cardano.Ledger.Conway.State as Conway -import qualified Cardano.Ledger.Hashes as Ledger import qualified Cardano.Ledger.Shelley.LedgerState as Shelley import qualified Cardano.Ledger.State as Ledger -import qualified Cardano.Ledger.TxIn as Ledger import Cardano.Network.NodeToClient (LocalConnectionId) import Cardano.Network.NodeToNode (RemoteAddress, RemoteConnectionId) import Cardano.Protocol.TPraos.OCert (KESPeriod (..)) -import Ouroboros.Consensus.Block (ForgeStateInfo, ForgeStateUpdateError) +import Ouroboros.Consensus.Block (ForgeStateInfo) import Ouroboros.Consensus.Byron.Ledger.Block (ByronBlock) import qualified Ouroboros.Consensus.Byron.Ledger.Block as Byron import qualified Ouroboros.Consensus.Byron.Ledger.Ledger as Byron -import Ouroboros.Consensus.Byron.Ledger.Mempool (TxId (..)) import qualified Ouroboros.Consensus.Cardano as Cardano import qualified Ouroboros.Consensus.Cardano.Block as Cardano import Ouroboros.Consensus.HardFork.Combinator -import Ouroboros.Consensus.HardFork.Combinator.AcrossEras (OneEraForgeStateInfo (..), - OneEraForgeStateUpdateError (..)) +import Ouroboros.Consensus.HardFork.Combinator.AcrossEras (OneEraForgeStateInfo (..)) import Ouroboros.Consensus.HardFork.Combinator.Embed.Unary import Ouroboros.Consensus.Ledger.Abstract (EmptyMK) import Ouroboros.Consensus.Ledger.Extended (ExtLedgerState) @@ -67,7 +58,6 @@ import Ouroboros.Consensus.Node (NodeKernel (..)) import qualified Ouroboros.Consensus.Protocol.Ledger.HotKey as HotKey import qualified Ouroboros.Consensus.Shelley.Ledger as Shelley import Ouroboros.Consensus.Shelley.Ledger.Block (ShelleyBlock) -import Ouroboros.Consensus.Shelley.Ledger.Mempool (TxId (..)) import Ouroboros.Consensus.Shelley.Node () import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB import Ouroboros.Consensus.TypeFamilyWrappers @@ -75,7 +65,6 @@ import Ouroboros.Consensus.Util.Orphans () import qualified Ouroboros.Network.AnchoredFragment as AF import Control.Monad.STM (atomically) -import Data.ByteString (ByteString) import Data.Foldable (foldMap') import Data.IORef (IORef, newIORef, readIORef, writeIORef) import qualified Data.Map.Strict as Map @@ -86,33 +75,6 @@ import Data.SOP.Functors import Data.Word (Word64) import Lens.Micro ((^.)) --- --- * TxId -> ByteString projection --- --- | Convert a transaction ID to raw bytes. -class ConvertTxId blk where - txIdToRawBytes :: TxId (GenTx blk) -> ByteString - -instance ConvertTxId ByronBlock where - txIdToRawBytes (ByronTxId txId) = Byron.Crypto.abstractHashToBytes txId - txIdToRawBytes (ByronDlgId dlgId) = Byron.Crypto.abstractHashToBytes dlgId - txIdToRawBytes (ByronUpdateProposalId upId) = - Byron.Crypto.abstractHashToBytes upId - txIdToRawBytes (ByronUpdateVoteId voteId) = - Byron.Crypto.abstractHashToBytes voteId - -instance ConvertTxId (ShelleyBlock protocol c) where - txIdToRawBytes (ShelleyTxId txId) = - Crypto.hashToBytes . Ledger.extractHash . Ledger.unTxId $ txId - -instance All ConvertTxId xs - => ConvertTxId (HardForkBlock xs) where - txIdToRawBytes = - hcollapse - . hcmap (Proxy @ConvertTxId) (K . txIdToRawBytes . unwrapGenTxId) - . getOneEraGenTxId - . getHardForkGenTxId - -- -- * KES -- @@ -123,30 +85,6 @@ newtype MaxKESEvolutions = MaxKESEvolutions Word64 -- | The start KES period of the configured operational certificate. newtype OperationalCertStartKESPeriod = OperationalCertStartKESPeriod Period --- --- * HasKESInfo --- -class HasKESInfo blk where - getKESInfo :: Proxy blk -> ForgeStateUpdateError blk -> Maybe HotKey.KESInfo - getKESInfo _ _ = Nothing - -instance HasKESInfo (ShelleyBlock protocol era) where - getKESInfo _ (HotKey.KESCouldNotEvolve ki _) = Just ki - getKESInfo _ (HotKey.KESKeyAlreadyPoisoned ki _) = Just ki - -instance HasKESInfo ByronBlock - -instance All HasKESInfo xs => HasKESInfo (HardForkBlock xs) where - getKESInfo _ = - hcollapse - . hcmap (Proxy @HasKESInfo) getOne - . getOneEraForgeStateUpdateError - where - getOne :: forall blk. HasKESInfo blk - => WrapForgeStateUpdateError blk - -> K (Maybe HotKey.KESInfo) blk - getOne = K . getKESInfo (Proxy @blk) . unwrapForgeStateUpdateError - -- -- * KESMetricsData -- @@ -203,33 +141,6 @@ instance All HasKESMetricsData xs => HasKESMetricsData (HardForkBlock xs) where -> K KESMetricsData blk getOne = K . getKESMetricsData (Proxy @blk) . unwrapForgeStateInfo --- --- * GetKESInfo --- -class GetKESInfo blk where - getKESInfoFromStateInfo :: Proxy blk -> ForgeStateInfo blk -> Maybe HotKey.KESInfo - getKESInfoFromStateInfo _ _ = Nothing - -instance GetKESInfo (ShelleyBlock protocol era) where - getKESInfoFromStateInfo _ = Just - -instance GetKESInfo ByronBlock - -instance All GetKESInfo xs => GetKESInfo (HardForkBlock xs) where - getKESInfoFromStateInfo _ forgeStateInfo = - case forgeStateInfo of - CurrentEraLacksBlockForging _ -> Nothing - CurrentEraForgeStateUpdated currentEraForgeStateInfo -> - hcollapse - . hcmap (Proxy @GetKESInfo) getOne - . getOneEraForgeStateInfo - $ currentEraForgeStateInfo - where - getOne :: forall blk. GetKESInfo blk - => WrapForgeStateInfo blk - -> K (Maybe HotKey.KESInfo) blk - getOne = K . getKESInfoFromStateInfo (Proxy @blk) . unwrapForgeStateInfo - -- -- * General ledger -- diff --git a/cardano-node/src/Cardano/Node/Run.hs b/cardano-node/src/Cardano/Node/Run.hs index acf6dbcb9de..97e08bf2f12 100644 --- a/cardano-node/src/Cardano/Node/Run.hs +++ b/cardano-node/src/Cardano/Node/Run.hs @@ -51,7 +51,7 @@ import Cardano.Node.Protocol.Types import Cardano.Node.Queries import Cardano.Rpc.Server import Cardano.Rpc.Server.Config -import Data.IORef +import Cardano.Rpc.Server.NodeKernelAccess (NodeKernelAccess, mkNodeKernelAccess) import Cardano.Node.Startup import Cardano.Node.TraceConstraints (TraceConstraints) import Cardano.Node.Tracing (Tracers (..)) @@ -147,6 +147,7 @@ import Data.IP (IP (..), isMatchedTo, makeAddrRange, toIPv4, toIPv6, t import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map import Data.Maybe (catMaybes, fromMaybe, mapMaybe) +import Data.IORef (IORef, newIORef, writeIORef) import Data.Monoid (Last (..)) import Data.Proxy (Proxy (..)) import qualified Data.Set as Set @@ -497,6 +498,7 @@ handleSimpleNode blockType shelleyGenesisHash pInfo mkBlockForging tracers forgi useBootstrapVar ledgerPeerSnapshotPathVar ledgerPeerSnapshotVar rpcConfigVar rnNodeKernelHook nodeArgs registry nodeKernel + -- populate node kernel access for RPC server mkNodeKernelAccess (rpcTracer tracers) shelleyGenesisHash @@ -644,9 +646,11 @@ updateBlockForging :: Tracer IO (StartupTrace blk) -> NodeConfiguration -> IO () updateBlockForging startupTracer kesAgentTracer forgingStateVar blockType nodeKernel nc = do - eitherSomeProtocol <- runExceptT $ mkConsensusProtocol - (ncProtocolConfig nc) - (Just (ncProtocolFiles nc)) + eitherSomeProtocol <- + runExceptT $ + mkConsensusProtocol + (ncProtocolConfig nc) + (Just (ncProtocolFiles nc)) case eitherSomeProtocol of Left err -> case wasFileRemovedFromScope err of @@ -660,7 +664,7 @@ updateBlockForging startupTracer kesAgentTracer forgingStateVar blockType nodeKe case Api.reflBlockType blockType blockType' of Just Refl -> do -- TODO: check if runP' has changed - (_, mkBlockForging) <- Api.protocolInfo runP' + (_, mkBlockForging) <- Api.protocolInfo @IO runP' blockForging <- mkBlockForging kesAgentTracer let enabled = not (null blockForging) -- Only an off-to-on transition starts a new run of slots for @@ -770,7 +774,6 @@ updateLedgerPeerSnapshot startupTracer NodeConfiguration { ncConsensusMode } net | otherwise -> oops $ "NetworkMagic " <> showT networkMagic <> " doesn't match " <> "peer snapshot NetworkMagic " <> showT magic - LedgerPeerSnapshotV2 {} -> oops "Unsupported legacy peer snapshot version." case afterSlot of Always -> do traceL $ LedgerPeerSnapshotLoaded fileSlot diff --git a/cardano-node/src/Cardano/Node/TraceConstraints.hs b/cardano-node/src/Cardano/Node/TraceConstraints.hs index 2dca935692a..1e40df5f469 100644 --- a/cardano-node/src/Cardano/Node/TraceConstraints.hs +++ b/cardano-node/src/Cardano/Node/TraceConstraints.hs @@ -10,11 +10,7 @@ module Cardano.Node.TraceConstraints (TraceConstraints) where import Cardano.Ledger.Credential import Cardano.Ledger.Keys import Cardano.Logging (LogFormatting) -import Cardano.Node.Queries (ConvertTxId, GetKESInfo (..), HasKESInfo (..), - HasKESMetricsData (..), LedgerQueries) -import Cardano.Node.Tracing.Tracers.HasIssuer (HasIssuer) -import Cardano.Node.Tracing.Tracers.KESInfo () -import qualified Cardano.Node.Tracing.Tracers.Consensus as ConsensusTracers +import Cardano.Node.Queries (HasKESMetricsData (..), LedgerQueries) import Cardano.Protocol.Crypto (StandardCrypto) import Ouroboros.Consensus.Block (BlockProtocol, CannotForge, ForgeStateUpdateError, GetHeader, HasHeader, Header, HeaderHash) @@ -27,6 +23,8 @@ import Ouroboros.Consensus.Peras.SelectView import Ouroboros.Consensus.Protocol.Abstract (ReasonForSwitch, SelectView, SelectViewReasonForSwitch, TiebreakerView, ValidationErr) import Ouroboros.Consensus.Shelley.Ledger.Mempool (GenTx) +import Ouroboros.Consensus.Tracing (ConvertTxId, GetKESInfo (..), HasIssuer, + HasKESInfo (..)) import Ouroboros.Network.Block (Serialised) import Data.Aeson diff --git a/cardano-node/src/Cardano/Node/Tracing.hs b/cardano-node/src/Cardano/Node/Tracing.hs index 127a1e75ce0..f9d10ca046c 100644 --- a/cardano-node/src/Cardano/Node/Tracing.hs +++ b/cardano-node/src/Cardano/Node/Tracing.hs @@ -14,8 +14,6 @@ import qualified Cardano.Network.Diffusion as Cardano.Diffusion import Cardano.Node.Handlers.Shutdown (ShutdownTrace) import Cardano.Node.Startup (NodeInfo, NodeStartupInfo, StartupTrace (..)) import Cardano.Node.Tracing.StateRep (NodeState) -import Cardano.Node.Tracing.Tracers.ConsensusStartupException - (ConsensusStartupException (..)) import Cardano.Node.Tracing.Tracers.LedgerMetrics (LedgerMetrics) import Cardano.Node.Tracing.Tracers.NodeVersion (NodeVersionTrace) import Cardano.Rpc.Server (TraceRpc) @@ -23,6 +21,7 @@ import qualified Ouroboros.Consensus.Network.NodeToClient as NodeToClient import qualified Ouroboros.Consensus.Network.NodeToNode as NodeToNode import qualified Ouroboros.Consensus.Node.Tracers as Consensus import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB +import Ouroboros.Consensus.Tracing (ConsensusStartupException (..)) import Ouroboros.Network.ConnectionId import Prelude (IO) diff --git a/cardano-node/src/Cardano/Node/Tracing/Consistency.hs b/cardano-node/src/Cardano/Node/Tracing/Consistency.hs index 7929bf76cb9..05da334f321 100644 --- a/cardano-node/src/Cardano/Node/Tracing/Consistency.hs +++ b/cardano-node/src/Cardano/Node/Tracing/Consistency.hs @@ -31,12 +31,7 @@ import Cardano.Node.Handlers.Shutdown (ShutdownTrace) import Cardano.Node.Startup import Cardano.Node.Tracing.DefaultTraceConfig (defaultCardanoConfig) import Cardano.Node.Tracing.Documentation (docTracersFirstPhase) -import Cardano.Node.Tracing.Formatting () import qualified Cardano.Node.Tracing.StateRep as SR -import Cardano.Node.Tracing.Tracers.BlockReplayProgress -import Cardano.Node.Tracing.Tracers.Consensus (ClientMetrics) -import Cardano.Node.Tracing.Tracers.ConsensusStartupException -import Cardano.Node.Tracing.Tracers.KESInfo () import Cardano.Node.Tracing.Tracers.LedgerMetrics (LedgerMetrics) import Cardano.Node.Tracing.Tracers.NodeToClient () import Cardano.Node.Tracing.Tracers.NodeToNode () @@ -64,11 +59,15 @@ import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.PerasCert (Per TracePerasCertDiffusionInbound, TracePerasCertDiffusionOutbound) import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.PerasVote (PerasVoteDiffusion, TracePerasVoteDiffusionInbound, TracePerasVoteDiffusionOutbound) +import Ouroboros.Consensus.Peras.Cert.Inclusion.Trace (TracePerasCertInclusionEvent) +import Ouroboros.Consensus.Peras.Voting.Trace (TracePerasVoteForgingEvent) import Ouroboros.Consensus.Node.GSM import Ouroboros.Consensus.Node.Tracers (TraceForgeEvent) import qualified Ouroboros.Consensus.Protocol.Ledger.HotKey as HotKey import Ouroboros.Consensus.Protocol.Praos.AgentClient (KESAgentClientTrace) import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB +import Ouroboros.Consensus.Tracing (ClientMetrics, ConsensusStartupException, + ReplayBlockStats) import Ouroboros.Network.Block (Point (..), SlotNo, Tip) import qualified Ouroboros.Network.BlockFetch.ClientState as BlockFetch import Ouroboros.Network.BlockFetch.Decision.Trace (TraceDecisionEvent) @@ -234,6 +233,10 @@ getAllNamespaces = perasVoteDiffusionNS = map (nsGetTuple . nsReplacePrefix ["Peras", "Vote", "Remote"]) (allNamespaces :: [Namespace (BlockFetch.TraceLabelPeer peer (TraceSendRecv (PerasVoteDiffusion blk)))]) + perasCertInclusionNS = map (nsGetTuple . nsReplacePrefix ["Peras", "Cert", "Inclusion"]) + (allNamespaces :: [Namespace (TracePerasCertInclusionEvent blk)]) + perasVoteForgingNS = map (nsGetTuple . nsReplacePrefix ["Peras", "Vote", "Forging"]) + (allNamespaces :: [Namespace (TracePerasVoteForgingEvent blk)]) localTxSubmissionServerNS = map (nsGetTuple . nsReplacePrefix ["TxSubmission", "LocalServer"]) (allNamespaces :: [Namespace @@ -481,6 +484,8 @@ getAllNamespaces = <> perasVoteOutboundNS <> perasCertDiffusionNS <> perasVoteDiffusionNS + <> perasCertInclusionNS + <> perasVoteForgingNS -- NodeToClient <> keepAliveClientNS <> chainSyncNS diff --git a/cardano-node/src/Cardano/Node/Tracing/Documentation.hs b/cardano-node/src/Cardano/Node/Tracing/Documentation.hs index c6198bd361d..f36f74b810d 100644 --- a/cardano-node/src/Cardano/Node/Tracing/Documentation.hs +++ b/cardano-node/src/Cardano/Node/Tracing/Documentation.hs @@ -39,16 +39,10 @@ import Cardano.Node.Configuration.TopologyP2P () import Cardano.Node.Handlers.Shutdown (ShutdownTrace) import Cardano.Node.Startup import Cardano.Node.Tracing.DefaultTraceConfig (defaultCardanoConfig) -import Cardano.Node.Tracing.Formatting () import Cardano.Node.Tracing.NodeInfo () import Cardano.Node.Tracing.NodeStartupInfo () import qualified Cardano.Node.Tracing.StateRep as SR -import Cardano.Node.Tracing.Tracers.BlockReplayProgress -import Cardano.Node.Tracing.Tracers.ChainDB -import Cardano.Node.Tracing.Tracers.Consensus -import Cardano.Node.Tracing.Tracers.ConsensusStartupException import Cardano.Node.Tracing.Tracers.ForgingStats (ForgingStats) -import Cardano.Node.Tracing.Tracers.KESInfo () import Cardano.Node.Tracing.Tracers.LedgerMetrics (LedgerMetrics) import Cardano.Node.Tracing.Tracers.NodeToClient () import Cardano.Node.Tracing.Tracers.NodeToNode () @@ -76,11 +70,14 @@ import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.PerasCert (Per TracePerasCertDiffusionInbound, TracePerasCertDiffusionOutbound) import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.PerasVote (PerasVoteDiffusion, TracePerasVoteDiffusionInbound, TracePerasVoteDiffusionOutbound) +import Ouroboros.Consensus.Peras.Cert.Inclusion.Trace (TracePerasCertInclusionEvent) +import Ouroboros.Consensus.Peras.Voting.Trace (TracePerasVoteForgingEvent) import Ouroboros.Consensus.Node.GSM (TraceGsmEvent) import qualified Ouroboros.Consensus.Node.Tracers as Consensus import qualified Ouroboros.Consensus.Protocol.Ledger.HotKey as HotKey import Ouroboros.Consensus.Protocol.Praos.AgentClient (KESAgentClientTrace) import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB +import Ouroboros.Consensus.Tracing import Ouroboros.Network.Block (Point (..), Serialised, SlotNo, Tip) import qualified Ouroboros.Network.BlockFetch.ClientState as BlockFetch import Ouroboros.Network.BlockFetch.Decision.Trace (TraceDecisionEvent) @@ -518,6 +515,19 @@ docTracersFirstPhase condConfigFileName = do Logging.Trace IO (BlockFetch.TraceLabelPeer peer (TraceSendRecv (PerasVoteDiffusion blk)))) + perasCertInclusionTr <- mkCardanoTracer + trBase trForward mbTrEKG + ["Peras", "Cert", "Inclusion"] + configureTracers configReflection trConfig [perasCertInclusionTr] + perasCertInclusionTrDoc <- documentTracer (perasCertInclusionTr :: + Logging.Trace IO (TracePerasCertInclusionEvent blk)) + + perasVoteForgingTr <- mkCardanoTracer + trBase trForward mbTrEKG + ["Peras", "Vote", "Forging"] + configureTracers configReflection trConfig [perasVoteForgingTr] + perasVoteForgingTrDoc <- documentTracer (perasVoteForgingTr :: + Logging.Trace IO (TracePerasVoteForgingEvent blk)) -- Node to client @@ -841,6 +851,8 @@ docTracersFirstPhase condConfigFileName = do <> perasVoteOutboundTrDoc <> perasCertDiffusionTrDoc <> perasVoteDiffusionTrDoc + <> perasCertInclusionTrDoc + <> perasVoteForgingTrDoc -- NodeToClient <> keepAliveClientTrDoc <> chainSyncTrDoc diff --git a/cardano-node/src/Cardano/Node/Tracing/Era/Byron.hs b/cardano-node/src/Cardano/Node/Tracing/Era/Byron.hs deleted file mode 100644 index 4414faa10df..00000000000 --- a/cardano-node/src/Cardano/Node/Tracing/Era/Byron.hs +++ /dev/null @@ -1,221 +0,0 @@ -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE UndecidableInstances #-} - -{-# OPTIONS_GHC -Wno-orphans #-} -{-# OPTIONS_GHC -Wno-unused-imports #-} - -module Cardano.Node.Tracing.Era.Byron () where - --- TODO: Temporary hack for toJSON instances --- Will be moved when old tracing will be removed -import Cardano.Api (textShow) - -import Cardano.Chain.Block (ABlockOrBoundaryHdr (..), AHeader (..), - ChainValidationError (..), delegationCertificate) -import Ouroboros.Consensus.Protocol.PBFT (PBft, PBftTiebreakerView(..)) -import Cardano.Chain.Byron.API (ApplyMempoolPayloadErr (..)) -import Cardano.Chain.Delegation (delegateVK) -import Cardano.Crypto.Signing (VerificationKey) -import Cardano.Logging -import Cardano.Node.Tracing.Render (renderTxId) -import Ouroboros.Consensus.Block (Header) -import Ouroboros.Consensus.Block.EBB (fromIsEBB) -import Ouroboros.Consensus.Byron.Ledger (ByronBlock (..), - ByronOtherHeaderEnvelopeError (..), TxId (..), byronHeaderRaw) -import Ouroboros.Consensus.Byron.Ledger.Inspect (ByronLedgerUpdate (..), - ProtocolUpdate (..), UpdateState (..)) -import Ouroboros.Consensus.Ledger.SupportsMempool (GenTx, txId) -import Ouroboros.Consensus.Util.Condense (condense) -import Ouroboros.Network.Block (blockHash, blockNo, blockSlot) - -import Data.Aeson (Value (String), (.=)) -import Data.ByteString (ByteString) -import qualified Data.Set as Set -import qualified Data.Text as Text - -{- HLINT ignore "Use :" -} - --- --- | instances of @LogFormatting@ --- --- NOTE: this list is sorted by the unqualified name of the outermost type. - -instance LogFormatting ApplyMempoolPayloadErr where - forMachine _dtal (MempoolTxErr utxoValidationErr) = - mconcat - [ "kind" .= String "MempoolTxErr" - , "error" .= String (textShow utxoValidationErr) - ] - forMachine _dtal (MempoolDlgErr delegScheduleError) = - mconcat - [ "kind" .= String "MempoolDlgErr" - , "error" .= String (textShow delegScheduleError) - ] - forMachine _dtal (MempoolUpdateProposalErr iFaceErr) = - mconcat - [ "kind" .= String "MempoolUpdateProposalErr" - , "error" .= String (textShow iFaceErr) - ] - forMachine _dtal (MempoolUpdateVoteErr iFaceErrr) = - mconcat - [ "kind" .= String "MempoolUpdateVoteErr" - , "error" .= String (textShow iFaceErrr) - ] - -instance LogFormatting ByronLedgerUpdate where - forMachine dtal (ByronUpdatedProtocolUpdates protocolUpdates) = - mconcat - [ "kind" .= String "ByronUpdatedProtocolUpdates" - , "protocolUpdates" .= map (forMachine dtal) protocolUpdates - ] - -instance LogFormatting ProtocolUpdate where - forMachine dtal (ProtocolUpdate updateVersion updateState) = - mconcat - [ "kind" .= String "ProtocolUpdate" - , "protocolUpdateVersion" .= updateVersion - , "protocolUpdateState" .= forMachine dtal updateState - ] - -instance LogFormatting UpdateState where - forMachine _dtal updateState = case updateState of - UpdateRegistered slot -> - mconcat - [ "kind" .= String "UpdateRegistered" - , "slot" .= slot - ] - UpdateActive votes -> - mconcat - [ "kind" .= String "UpdateActive" - , "votes" .= map (Text.pack . show) (Set.toList votes) - ] - UpdateConfirmed slot -> - mconcat - [ "kind" .= String "UpdateConfirmed" - , "slot" .= slot - ] - UpdateStablyConfirmed endorsements -> - mconcat - [ "kind" .= String "UpdateStablyConfirmed" - , "endorsements" .= map (Text.pack . show) (Set.toList endorsements) - ] - UpdateCandidate slot epoch -> - mconcat - [ "kind" .= String "UpdateCandidate" - , "slot" .= slot - , "epoch" .= epoch - ] - UpdateStableCandidate transitionEpoch -> - mconcat - [ "kind" .= String "UpdateStableCandidate" - , "transitionEpoch" .= transitionEpoch - ] - -instance LogFormatting (GenTx ByronBlock) where - forMachine dtal tx = - mconcat $ - ( "txid" .= (Text.take 8 . renderTxId $ txId tx) ) - : [ "tx" .= condense tx | dtal == DDetailed ] - -instance LogFormatting ChainValidationError where - forMachine _dtal ChainValidationBoundaryTooLarge = - mconcat - [ "kind" .= String "ChainValidationBoundaryTooLarge" ] - forMachine _dtal ChainValidationBlockAttributesTooLarge = - mconcat - [ "kind" .= String "ChainValidationBlockAttributesTooLarge" ] - forMachine _dtal (ChainValidationBlockTooLarge _ _) = - mconcat - [ "kind" .= String "ChainValidationBlockTooLarge" ] - forMachine _dtal ChainValidationHeaderAttributesTooLarge = - mconcat - [ "kind" .= String "ChainValidationHeaderAttributesTooLarge" ] - forMachine _dtal (ChainValidationHeaderTooLarge _ _) = - mconcat - [ "kind" .= String "ChainValidationHeaderTooLarge" ] - forMachine _dtal (ChainValidationDelegationPayloadError err) = - mconcat - [ "kind" .= String err ] - forMachine _dtal (ChainValidationInvalidDelegation _ _) = - mconcat - [ "kind" .= String "ChainValidationInvalidDelegation" ] - forMachine _dtal (ChainValidationGenesisHashMismatch _ _) = - mconcat - [ "kind" .= String "ChainValidationGenesisHashMismatch" ] - forMachine _dtal (ChainValidationExpectedGenesisHash _ _) = - mconcat - [ "kind" .= String "ChainValidationExpectedGenesisHash" ] - forMachine _dtal (ChainValidationExpectedHeaderHash _ _) = - mconcat - [ "kind" .= String "ChainValidationExpectedHeaderHash" ] - forMachine _dtal (ChainValidationInvalidHash _ _) = - mconcat - [ "kind" .= String "ChainValidationInvalidHash" ] - forMachine _dtal (ChainValidationMissingHash _) = - mconcat - [ "kind" .= String "ChainValidationMissingHash" ] - forMachine _dtal (ChainValidationUnexpectedGenesisHash _) = - mconcat - [ "kind" .= String "ChainValidationUnexpectedGenesisHash" ] - forMachine _dtal (ChainValidationInvalidSignature _) = - mconcat - [ "kind" .= String "ChainValidationInvalidSignature" ] - forMachine _dtal (ChainValidationDelegationSchedulingError _) = - mconcat - [ "kind" .= String "ChainValidationDelegationSchedulingError" ] - forMachine _dtal (ChainValidationProtocolMagicMismatch _ _) = - mconcat - [ "kind" .= String "ChainValidationProtocolMagicMismatch" ] - forMachine _dtal ChainValidationSignatureLight = - mconcat - [ "kind" .= String "ChainValidationSignatureLight" ] - forMachine _dtal (ChainValidationTooManyDelegations _) = - mconcat - [ "kind" .= String "ChainValidationTooManyDelegations" ] - forMachine _dtal (ChainValidationUpdateError _ _) = - mconcat - [ "kind" .= String "ChainValidationUpdateError" ] - forMachine _dtal (ChainValidationUTxOValidationError _) = - mconcat - [ "kind" .= String "ChainValidationUTxOValidationError" ] - forMachine _dtal (ChainValidationProofValidationError _) = - mconcat - [ "kind" .= String "ChainValidationProofValidationError" ] - - -instance LogFormatting (Header ByronBlock) where - forMachine _dtal b = - mconcat $ - [ "kind" .= String "ByronBlock" - , "hash" .= condense (blockHash b) - , "slotNo" .= condense (blockSlot b) - , "blockNo" .= condense (blockNo b) - ] <> - case byronHeaderRaw b of - ABOBBoundaryHdr{} -> [] - ABOBBlockHdr h -> - [ "delegate" .= condense (headerSignerVk h) ] - where - headerSignerVk :: AHeader ByteString -> VerificationKey - headerSignerVk = - delegateVK . delegationCertificate . headerSignature - - -instance LogFormatting ByronOtherHeaderEnvelopeError where - forMachine _dtal (UnexpectedEBBInSlot slot) = - mconcat - [ "kind" .= String "UnexpectedEBBInSlot" - , "slot" .= slot - ] - -instance LogFormatting PBftTiebreakerView where - forMachine _dtal (PBftTiebreakerView isEBB) = - mconcat - [ "kind" .= String "PBftSelectView" - , "isEBB" .= fromIsEBB isEBB - ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Era/HardFork.hs b/cardano-node/src/Cardano/Node/Tracing/Era/HardFork.hs deleted file mode 100644 index 66300579bc4..00000000000 --- a/cardano-node/src/Cardano/Node/Tracing/Era/HardFork.hs +++ /dev/null @@ -1,372 +0,0 @@ -{-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DerivingStrategies #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE StandaloneDeriving #-} -{-# LANGUAGE TypeApplications #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE UndecidableInstances #-} - -{-# OPTIONS_GHC -Wno-orphans #-} - -module Cardano.Node.Tracing.Era.HardFork () - where - -import Cardano.Logging -import Cardano.Slotting.Slot (EpochSize (..)) -import Ouroboros.Consensus.Block (BlockProtocol, CannotForge, ForgeStateInfo, - ForgeStateUpdateError, PerasWeight (..)) -import Ouroboros.Consensus.BlockchainTime (getSlotLength) -import Ouroboros.Consensus.Cardano.Condense () -import Ouroboros.Consensus.HardFork.Combinator -import Ouroboros.Consensus.HardFork.Combinator.AcrossEras (EraMismatch (..), - OneEraCannotForge (..), OneEraEnvelopeErr (..), OneEraForgeStateInfo (..), - OneEraForgeStateUpdateError (..), OneEraLedgerError (..), - OneEraLedgerUpdate (..), OneEraLedgerWarning (..), OneEraTiebreakerView (..), - OneEraValidationErr (..), mkEraMismatch) -import Ouroboros.Consensus.HardFork.Combinator.Condense () -import Ouroboros.Consensus.HardFork.History - (EraParams (eraEpochSize, eraSafeZone, eraSlotLength), SafeZone) -import Ouroboros.Consensus.HardFork.History.EraParams (EraParams (EraParams)) -import Ouroboros.Consensus.HeaderValidation (OtherHeaderEnvelopeError) -import Ouroboros.Consensus.Ledger.Abstract (LedgerError) -import Ouroboros.Consensus.Ledger.Inspect (LedgerUpdate, LedgerWarning) -import Ouroboros.Consensus.Ledger.SupportsMempool (ApplyTxErr) -import Ouroboros.Consensus.Peras.SelectView -import Ouroboros.Consensus.Protocol.Abstract (TiebreakerView, ValidationErr) -import Ouroboros.Consensus.TypeFamilyWrappers -import Ouroboros.Consensus.Util.Condense (Condense (..)) - -import Data.Aeson -import Data.Proxy (Proxy (..)) -import Data.SOP (All, Compose, K (K)) -import Data.SOP.Strict - - --- --- instances for Header HardForkBlock --- - -instance All (LogFormatting `Compose` Header) xs => LogFormatting (Header (HardForkBlock xs)) where - forMachine dtal = - hcollapse - . hcmap (Proxy @(LogFormatting `Compose` Header)) (K . forMachine dtal) - . getOneEraHeader - . getHardForkHeader - - --- --- instances for GenTx HardForkBlock --- - -instance All (Compose LogFormatting GenTx) xs => LogFormatting (GenTx (HardForkBlock xs)) where - forMachine dtal = - hcollapse - . hcmap (Proxy @(LogFormatting `Compose` GenTx)) (K . forMachine dtal) - . getOneEraGenTx - . getHardForkGenTx - - --- --- instances for HardForkApplyTxErr --- - -instance All (LogFormatting `Compose` WrapApplyTxErr) xs => LogFormatting (HardForkApplyTxErr xs) where - forMachine dtal (HardForkApplyTxErrFromEra err) = forMachine dtal err - forMachine _dtal (HardForkApplyTxErrWrongEra mismatch) = - mconcat - [ "kind" .= String "HardForkApplyTxErrWrongEra" - , "currentEra" .= ledgerEraName - , "txEra" .= otherEraName - ] - where - EraMismatch {ledgerEraName, otherEraName} = mkEraMismatch mismatch - -instance All (LogFormatting `Compose` WrapApplyTxErr) xs => LogFormatting (OneEraApplyTxErr xs) where - forMachine dtal = - hcollapse - . hcmap (Proxy @(LogFormatting `Compose` WrapApplyTxErr)) (K . forMachine dtal) - . getOneEraApplyTxErr - -instance LogFormatting (ApplyTxErr blk) => LogFormatting (WrapApplyTxErr blk) where - forMachine dtal = forMachine dtal . unwrapApplyTxErr - - --- --- instances for HardForkLedgerError --- - -instance All (LogFormatting `Compose` WrapLedgerErr) xs => LogFormatting (HardForkLedgerError xs) where - forMachine dtal (HardForkLedgerErrorFromEra err) = forMachine dtal err - - forMachine _dtal (HardForkLedgerErrorWrongEra mismatch) = - mconcat - [ "kind" .= String "HardForkLedgerErrorWrongEra" - , "currentEra" .= ledgerEraName - , "blockEra" .= otherEraName - ] - where - EraMismatch {ledgerEraName, otherEraName} = mkEraMismatch mismatch - -instance All (LogFormatting `Compose` WrapLedgerErr) xs => LogFormatting (OneEraLedgerError xs) where - forMachine dtal = - hcollapse - . hcmap (Proxy @(LogFormatting `Compose` WrapLedgerErr)) (K . forMachine dtal) - . getOneEraLedgerError - -instance LogFormatting (LedgerError blk) => LogFormatting (WrapLedgerErr blk) where - forMachine dtal = forMachine dtal . unwrapLedgerErr - - --- --- instances for HardForkLedgerWarning --- - -instance ( All (LogFormatting `Compose` WrapLedgerWarning) xs - , All SingleEraBlock xs - ) => LogFormatting (HardForkLedgerWarning xs) where - forMachine dtal warning = case warning of - HardForkWarningInEra err -> forMachine dtal err - - HardForkWarningTransitionMismatch toEra eraParams epoch -> - mconcat - [ "kind" .= String "HardForkWarningTransitionMismatch" - , "toEra" .= condense toEra - , "eraParams" .= forMachine dtal eraParams - , "transitionEpoch" .= epoch - ] - - HardForkWarningTransitionInFinalEra fromEra epoch -> - mconcat - [ "kind" .= String "HardForkWarningTransitionInFinalEra" - , "fromEra" .= condense fromEra - , "transitionEpoch" .= epoch - ] - - HardForkWarningTransitionUnconfirmed toEra -> - mconcat - [ "kind" .= String "HardForkWarningTransitionUnconfirmed" - , "toEra" .= condense toEra - ] - - HardForkWarningTransitionReconfirmed fromEra toEra prevEpoch newEpoch -> - mconcat - [ "kind" .= String "HardForkWarningTransitionReconfirmed" - , "fromEra" .= condense fromEra - , "toEra" .= condense toEra - , "prevTransitionEpoch" .= prevEpoch - , "newTransitionEpoch" .= newEpoch - ] - -instance All (LogFormatting `Compose` WrapLedgerWarning) xs => LogFormatting (OneEraLedgerWarning xs) where - forMachine dtal = - hcollapse - . hcmap (Proxy @(LogFormatting `Compose` WrapLedgerWarning)) (K . forMachine dtal) - . getOneEraLedgerWarning - -instance LogFormatting (LedgerWarning blk) => LogFormatting (WrapLedgerWarning blk) where - forMachine dtal = forMachine dtal . unwrapLedgerWarning - -instance LogFormatting EraParams where - forMachine _dtal EraParams{ eraEpochSize, eraSlotLength, eraSafeZone} = - mconcat - [ "epochSize" .= unEpochSize eraEpochSize - , "slotLength" .= getSlotLength eraSlotLength - , "safeZone" .= eraSafeZone - ] - -deriving instance ToJSON SafeZone - - --- --- instances for HardForkLedgerUpdate --- - -instance ( All (LogFormatting `Compose` WrapLedgerUpdate) xs - , All SingleEraBlock xs - ) => LogFormatting (HardForkLedgerUpdate xs) where - forMachine dtal update = case update of - HardForkUpdateInEra err -> forMachine dtal err - - HardForkUpdateTransitionConfirmed fromEra toEra epoch -> - mconcat - [ "kind" .= String "HardForkUpdateTransitionConfirmed" - , "fromEra" .= condense fromEra - , "toEra" .= condense toEra - , "transitionEpoch" .= epoch - ] - - HardForkUpdateTransitionDone fromEra toEra epoch -> - mconcat - [ "kind" .= String "HardForkUpdateTransitionDone" - , "fromEra" .= condense fromEra - , "toEra" .= condense toEra - , "transitionEpoch" .= epoch - ] - - HardForkUpdateTransitionRolledBack fromEra toEra -> - mconcat - [ "kind" .= String "HardForkUpdateTransitionRolledBack" - , "fromEra" .= condense fromEra - , "toEra" .= condense toEra - ] - -instance All (LogFormatting `Compose` WrapLedgerUpdate) xs => LogFormatting (OneEraLedgerUpdate xs) where - forMachine dtal = - hcollapse - . hcmap (Proxy @(LogFormatting `Compose` WrapLedgerUpdate)) (K . forMachine dtal) - . getOneEraLedgerUpdate - -instance LogFormatting (LedgerUpdate blk) => LogFormatting (WrapLedgerUpdate blk) where - forMachine dtal = forMachine dtal . unwrapLedgerUpdate - - --- --- instances for HardForkEnvelopeErr --- - -instance All (LogFormatting `Compose` WrapEnvelopeErr) xs => LogFormatting (HardForkEnvelopeErr xs) where - forMachine dtal (HardForkEnvelopeErrFromEra err) = forMachine dtal err - - forMachine _dtal (HardForkEnvelopeErrWrongEra mismatch) = - mconcat - [ "kind" .= String "HardForkEnvelopeErrWrongEra" - , "currentEra" .= ledgerEraName - , "blockEra" .= otherEraName - ] - where - EraMismatch {ledgerEraName, otherEraName} = mkEraMismatch mismatch - -instance All (LogFormatting `Compose` WrapEnvelopeErr) xs => LogFormatting (OneEraEnvelopeErr xs) where - forMachine dtal = - hcollapse - . hcmap (Proxy @(LogFormatting `Compose` WrapEnvelopeErr)) (K . forMachine dtal) - . getOneEraEnvelopeErr - -instance LogFormatting (OtherHeaderEnvelopeError blk) => LogFormatting (WrapEnvelopeErr blk) where - forMachine dtal = forMachine dtal . unwrapEnvelopeErr - - --- --- instances for HardForkValidationErr --- - -instance All (LogFormatting `Compose` WrapValidationErr) xs => LogFormatting (HardForkValidationErr xs) where - forMachine dtal (HardForkValidationErrFromEra err) = forMachine dtal err - - forMachine _dtal (HardForkValidationErrWrongEra mismatch) = - mconcat - [ "kind" .= String "HardForkValidationErrWrongEra" - , "currentEra" .= ledgerEraName - , "blockEra" .= otherEraName - ] - where - EraMismatch {ledgerEraName, otherEraName} = mkEraMismatch mismatch - -instance All (LogFormatting `Compose` WrapValidationErr) xs => LogFormatting (OneEraValidationErr xs) where - forMachine dtal = - hcollapse - . hcmap (Proxy @(LogFormatting `Compose` WrapValidationErr)) (K . forMachine dtal) - . getOneEraValidationErr - -instance LogFormatting (ValidationErr (BlockProtocol blk)) => LogFormatting (WrapValidationErr blk) where - forMachine dtal = forMachine dtal . unwrapValidationErr - - --- --- instances for HardForkCannotForge --- - --- It's a type alias: --- type HardForkCannotForge xs = OneEraCannotForge xs - -instance All (LogFormatting `Compose` WrapCannotForge) xs => LogFormatting (OneEraCannotForge xs) where - forMachine dtal = - hcollapse - . hcmap (Proxy @(LogFormatting `Compose` WrapCannotForge)) - (K . forMachine dtal) - . getOneEraCannotForge - -instance LogFormatting (CannotForge blk) => LogFormatting (WrapCannotForge blk) where - forMachine dtal = forMachine dtal . unwrapCannotForge - - --- --- instances for HardForkForgeStateInfo --- - --- It's a type alias: --- type HardForkForgeStateInfo xs = OneEraForgeStateInfo xs - -instance All (LogFormatting `Compose` WrapForgeStateInfo) xs => LogFormatting (OneEraForgeStateInfo xs) where - forMachine dtal forgeStateInfo = - mconcat - [ "kind" .= String "HardForkForgeStateInfo" - , "forgeStateInfo" .= toJSON forgeStateInfo' - ] - where - forgeStateInfo' :: Object - forgeStateInfo' = - hcollapse - . hcmap (Proxy @(LogFormatting `Compose` WrapForgeStateInfo)) - (K . forMachine dtal) - . getOneEraForgeStateInfo - $ forgeStateInfo - -instance LogFormatting (ForgeStateInfo blk) => LogFormatting (WrapForgeStateInfo blk) where - forMachine dtal = forMachine dtal . unwrapForgeStateInfo - - --- --- instances for HardForkForgeStateUpdateError --- - --- It's a type alias: --- type HardForkForgeStateUpdateError xs = OneEraForgeStateUpdateError xs - -instance All (LogFormatting `Compose` WrapForgeStateUpdateError) xs => LogFormatting (OneEraForgeStateUpdateError xs) where - forMachine dtal forgeStateUpdateError = - mconcat - [ "kind" .= String "HardForkForgeStateUpdateError" - , "forgeStateUpdateError" .= toJSON forgeStateUpdateError' - ] - where - forgeStateUpdateError' :: Object - forgeStateUpdateError' = - hcollapse - . hcmap (Proxy @(LogFormatting `Compose` WrapForgeStateUpdateError)) - (K . forMachine dtal) - . getOneEraForgeStateUpdateError - $ forgeStateUpdateError - -instance LogFormatting (ForgeStateUpdateError blk) => LogFormatting (WrapForgeStateUpdateError blk) where - forMachine dtal = forMachine dtal . unwrapForgeStateUpdateError - --- --- instances for HardForkSelectView --- - -instance All (LogFormatting `Compose` WrapTiebreakerView) xs => LogFormatting (HardForkTiebreakerView xs) where - forMachine dtal = forMachine dtal . getHardForkTiebreakerView - -instance LogFormatting (TiebreakerView protocol) => LogFormatting (WeightedSelectView protocol) where - forMachine dtal sv = mconcat - [ "blockNo" .= wsvBlockNo sv - , "weightBoost" .= unPerasWeight (wsvWeightBoost sv) - , forMachine dtal (wsvTiebreaker sv) - ] - -instance All (LogFormatting `Compose` WrapTiebreakerView) xs => LogFormatting (OneEraTiebreakerView xs) where - forMachine dtal = - hcollapse - . hcmap (Proxy @(LogFormatting `Compose` WrapTiebreakerView)) - (K . forMachine dtal) - . getOneEraTiebreakerView - -instance LogFormatting (TiebreakerView (BlockProtocol blk)) => LogFormatting (WrapTiebreakerView blk) where - forMachine dtal = forMachine dtal . unwrapTiebreakerView diff --git a/cardano-node/src/Cardano/Node/Tracing/Era/Shelley.hs b/cardano-node/src/Cardano/Node/Tracing/Era/Shelley.hs deleted file mode 100644 index 16311d6cf64..00000000000 --- a/cardano-node/src/Cardano/Node/Tracing/Era/Shelley.hs +++ /dev/null @@ -1,1970 +0,0 @@ -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE DerivingStrategies #-} -{-# LANGUAGE DisambiguateRecordFields #-} -{-# LANGUAGE EmptyCase #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE UndecidableInstances #-} - -{-# OPTIONS_GHC -Wno-orphans #-} - -module Cardano.Node.Tracing.Era.Shelley () where - -import Cardano.Api (textShow) -import qualified Cardano.Api as Api -import Cardano.Api.Ledger (fromVRFVerKeyHash) - -import qualified Cardano.Crypto.Hash.Class as Crypto -import qualified Cardano.Crypto.VRF.Class as Crypto -import Cardano.Ledger.Allegra.Rules (AllegraUtxoPredFailure) -import qualified Cardano.Ledger.Allegra.Rules as Allegra -import qualified Cardano.Ledger.Allegra.Scripts as Allegra -import qualified Cardano.Ledger.Alonzo.Plutus.Evaluate as Alonzo -import Cardano.Ledger.Alonzo.Rules (AlonzoBbodyPredFailure, AlonzoUtxoPredFailure, - AlonzoUtxosPredFailure, AlonzoUtxowPredFailure (..)) -import qualified Cardano.Ledger.Alonzo.Rules as Alonzo -import Cardano.Ledger.Babbage.Rules (BabbageUtxoPredFailure, BabbageUtxowPredFailure) -import qualified Cardano.Ledger.Babbage.Rules as Babbage -import Cardano.Ledger.BaseTypes (Mismatch (..), activeSlotLog, strictMaybeToMaybe) -import Cardano.Ledger.Chain -import Cardano.Ledger.Conway.Governance (govActionIdToText) -import qualified Cardano.Ledger.Conway.Rules as Conway -import qualified Cardano.Ledger.Core as Ledger -import qualified Cardano.Ledger.Dijkstra.Rules as Dijkstra -import qualified Cardano.Ledger.Hashes as Hashes -import Cardano.Ledger.Shelley.API -import Cardano.Ledger.Shelley.Rules -import Cardano.Logging -import Cardano.Node.Queries (ConvertTxId) -import Cardano.Node.Tracing.Render (renderIncompleteWithdrawals, renderMissingRedeemers, - renderScriptHash, renderScriptIntegrityHash, renderTxId) -import qualified Cardano.Protocol.Crypto as Ledger -import Cardano.Protocol.TPraos.API (ChainTransitionError (ChainTransitionError)) -import Cardano.Protocol.TPraos.BlockHeader (LastAppliedBlock, labBlockNo) -import Cardano.Protocol.TPraos.OCert (KESPeriod (KESPeriod)) -import Cardano.Protocol.TPraos.Rules.OCert -import Cardano.Protocol.TPraos.Rules.Overlay -import Cardano.Protocol.TPraos.Rules.Prtcl - (PrtclPredicateFailure (OverlayFailure, UpdnFailure), - PrtlSeqFailure (WrongBlockNoPrtclSeq, WrongBlockSequencePrtclSeq, WrongSlotIntervalPrtclSeq)) -import Cardano.Protocol.TPraos.Rules.Updn (UpdnPredicateFailure) -import Cardano.Slotting.Block (BlockNo (..)) -import Ouroboros.Consensus.Ledger.SupportsMempool (txId) -import qualified Ouroboros.Consensus.Protocol.Praos as Praos -import qualified Ouroboros.Consensus.Protocol.Praos.Common as Praos -import Ouroboros.Consensus.Protocol.TPraos (TPraosCannotForge (..)) -import Ouroboros.Consensus.Shelley.Ledger hiding (TxId) -import qualified Ouroboros.Consensus.Shelley.Ledger as Consensus -import Ouroboros.Consensus.Shelley.Ledger.Inspect -import qualified Ouroboros.Consensus.Shelley.Protocol.EnvelopeChecks as Praos (EnvelopeError (..)) -import Ouroboros.Consensus.Util.Condense (condense) -import Ouroboros.Network.Block (SlotNo (..), blockHash, blockNo, blockSlot) -import Ouroboros.Network.Point (WithOrigin, withOriginToMaybe) - -import Control.DeepSeq (NFData) -import Data.Aeson (ToJSON (..), Value (..), (.=)) -import qualified Data.Aeson.Key as Aeson (fromText) -import qualified Data.Aeson.Types as Aeson -import qualified Data.ByteString.Base16 as B16 -import qualified Data.List.NonEmpty as NonEmpty -import qualified Data.Map as Map -import Data.Set (Set) -import qualified Data.Set as Set -import qualified Data.Set.NonEmpty as NonEmptySet -import Data.Text (Text) -import qualified Data.Text as Text -import qualified Data.Text.Encoding as Text.Encoding - -{- HLINT ignore "Use :" -} - --- --- | instances of @LogFormatting@ --- --- NOTE: this list is sorted in roughly topological order. - -instance - ( ConvertTxId (ShelleyBlock protocol era) - , ShelleyBasedEra era - ) => LogFormatting (GenTx (ShelleyBlock protocol era)) where - forMachine dtal tx = - mconcat $ - ( "txid" .= (Text.take 8 . renderTxId $ txId tx) ) - : [ "tx" .= condense tx | dtal == DDetailed ] - -kesPeriodValue :: KESPeriod -> Value -kesPeriodValue (KESPeriod period) = toJSON period - -instance LogFormatting (Set (Credential Staking)) where - forMachine _dtal creds = - mconcat [ "kind" .= String "StakeCreds" - , "stakeCreds" .= map toJSON (Set.toList creds) - ] - -instance LogFormatting (NonEmpty.NonEmpty (KeyHash Staking)) where - forMachine _dtal keyHashes = - mconcat [ "kind" .= String "StakingKeyHashes" - , "stakeKeyHashes" .= toJSON keyHashes - ] - -instance - ( LogFormatting (PredicateFailure (Ledger.EraRule "DELEG" era)) - , LogFormatting (PredicateFailure (Ledger.EraRule "POOL" era)) - , LogFormatting (PredicateFailure (Ledger.EraRule "GOVCERT" era)) - ) => LogFormatting (Conway.ConwayCertPredFailure era) where - forMachine dtal = mconcat . \case - Conway.DelegFailure f -> - [ "kind" .= String "DelegFailure " , "failure" .= forMachine dtal f ] - Conway.PoolFailure f -> - [ "kind" .= String "PoolFailure" , "failure" .= forMachine dtal f ] - Conway.GovCertFailure f -> - [ "kind" .= String "GovCertFailure" , "failure" .= forMachine dtal f ] - -instance LogFormatting (Conway.ConwayGovCertPredFailure era) where - forMachine _dtal = mconcat . \case - Conway.ConwayDRepAlreadyRegistered credential -> - [ "kind" .= String "ConwayDRepAlreadyRegistered" - , "credential" .= String (textShow credential) - , "error" .= String "DRep is already registered" - ] - Conway.ConwayDRepNotRegistered credential -> - [ "kind" .= String "ConwayDRepNotRegistered" - , "credential" .= String (textShow credential) - , "error" .= String "DRep is not registered" - ] - Conway.ConwayDRepIncorrectDeposit Mismatch {mismatchSupplied, mismatchExpected} -> - [ "kind" .= String "ConwayDRepIncorrectDeposit" - , "givenCoin" .= mismatchSupplied - , "expectedCoin" .= mismatchExpected - , "error" .= String "DRep delegation has incorrect deposit" - ] - Conway.ConwayCommitteeHasPreviouslyResigned coldCred -> - [ "kind" .= String "ConwayCommitteeHasPreviouslyResigned" - , "credential" .= String (textShow coldCred) - , "error" .= String "Committee has resigned" - ] - Conway.ConwayCommitteeIsUnknown coldCred -> - [ "kind" .= String "ConwayCommitteeIsUnknown" - , "credential" .= String (textShow coldCred) - , "error" .= String "Committee is Unknown" - ] - Conway.ConwayDRepIncorrectRefund Mismatch {mismatchSupplied, mismatchExpected} -> - [ "kind" .= String "ConwayDRepIncorrectRefund" - , "givenRefund" .= mismatchSupplied - , "expectedRefund" .= mismatchExpected - , "error" .= String "Refunds mismatch" - ] - - - -instance LogFormatting (Conway.ConwayDelegPredFailure era) where - forMachine _dtal = mconcat . \case - Conway.DelegateeStakePoolNotRegisteredDELEG poolID -> - [ "kind" .= String "DelegateeStakePoolNotRegisteredDELEG" - , "poolID" .= String (textShow poolID) - ] - Conway.IncorrectDepositDELEG coin -> - [ "kind" .= String "IncorrectDepositDELEG" - , "amount" .= coin - , "error" .= String "Incorrect deposit amount" - ] - Conway.StakeKeyRegisteredDELEG credential -> - [ "kind" .= String "StakeKeyRegisteredDELEG" - , "credential" .= String (textShow credential) - , "error" .= String "Stake key already registered" - ] - Conway.StakeKeyNotRegisteredDELEG credential -> - [ "kind" .= String "StakeKeyNotRegisteredDELEG" - , "amount" .= String (textShow credential) - , "error" .= String "Stake key not registered" - ] - Conway.StakeKeyHasNonZeroAccountBalanceDELEG coin -> - [ "kind" .= String "StakeKeyHasNonZeroAccountBalanceDELEG" - , "amount" .= coin - , "error" .= String "Stake key has non-zero account balance" - ] - Conway.DelegateeDRepNotRegisteredDELEG credential -> - [ "kind" .= String "DelegateeDRepNotRegisteredDELEG" - , "credential" .= String (textShow credential) - , "error" .= String "Delegated rep is not registered for provided stake key" - ] - Conway.DepositIncorrectDELEG Mismatch {mismatchSupplied, mismatchExpected} -> - [ "kind" .= String "DepositIncorrectDELEG" - , "givenRefund" .= mismatchSupplied - , "expectedRefund" .= mismatchExpected - , "error" .= String "Deposit mismatch" - ] - Conway.RefundIncorrectDELEG Mismatch {mismatchSupplied, mismatchExpected} -> - [ "kind" .= String "RefundIncorrectDELEG" - , "givenRefund" .= mismatchSupplied - , "expectedRefund" .= mismatchExpected - , "error" .= String "Refund mismatch" - ] - -instance - ( ShelleyCompatible protocol era - ) => LogFormatting (Header (ShelleyBlock protocol era)) where - forMachine _dtal b = mconcat - [ "kind" .= String "ShelleyBlock" - , "hash" .= condense (blockHash b) - , "slotNo" .= condense (blockSlot b) - , "blockNo" .= condense (blockNo b) --- , "delegate" .= condense (headerSignerVk h) - ] - -instance - ( Consensus.ShelleyBasedEra era - , LogFormatting (PredicateFailure (UTXO era)) - , LogFormatting (PredicateFailure (UTXOW era)) - , LogFormatting (PredicateFailure (Ledger.EraRule "LEDGER" era)) - , ToJSON (ApplyTxError era) - ) => LogFormatting (ApplyTxError era) where - forMachine _dtal err = - mconcat - [ "kind" .= String "ApplyTxError" - , "reason" .= toJSON err - ] - -instance - ( Ledger.Crypto era - ) => LogFormatting (TPraosCannotForge era) where - forMachine _dtal (TPraosCannotForgeKeyNotUsableYet wallClockPeriod keyStartPeriod) = - mconcat - [ "kind" .= String "TPraosCannotForgeKeyNotUsableYet" - , "keyStart" .= kesPeriodValue keyStartPeriod - , "wallClock" .= kesPeriodValue wallClockPeriod - ] - forMachine _dtal (TPraosCannotForgeWrongVRF genDlgVRFHash coreNodeVRFHash) = - mconcat - [ "kind" .= String "TPraosCannotLeadWrongVRF" - , "expected" .= genDlgVRFHash - , "actual" .= coreNodeVRFHash - ] - -instance - ( Consensus.ShelleyBasedEra era - , LogFormatting (PredicateFailure (UTXO era)) - , LogFormatting (PredicateFailure (UTXOW era)) - , LogFormatting (PredicateFailure (Ledger.EraRule "BBODY" era)) - , NFData (PredicateFailure (Ledger.EraRule "BBODY" era)) - ) => LogFormatting (BlockTransitionError era) where - forMachine dtal (BlockTransitionError fs) = - mconcat [ "kind" .= String "BlockTransitionError" - , "failures" .= fmap (forMachine dtal) fs - ] - -instance - ( Consensus.ShelleyBasedEra era - , ToJSON (Ledger.PParamsUpdate era) - ) => LogFormatting (ShelleyLedgerUpdate era) where - forMachine _dtal (ShelleyUpdatedPParams updates epochNo) = - mconcat [ "kind" .= String "ShelleyUpdatedProtocolUpdates" - , "updates" .= show updates - , "epochNo" .= show epochNo - ] - -instance - ( Ledger.Crypto crypto - ) => LogFormatting (ChainTransitionError crypto) where - forMachine dtal (ChainTransitionError fs) = - mconcat [ "kind" .= String "ChainTransitionError" - , "failures" .= fmap (forMachine dtal) fs - ] - -instance LogFormatting ChainPredicateFailure where - forMachine _dtal (HeaderSizeTooLargeCHAIN hdrSz maxHdrSz) = - mconcat [ "kind" .= String "HeaderSizeTooLarge" - , "headerSize" .= hdrSz - , "maxHeaderSize" .= maxHdrSz - ] - forMachine _dtal (BlockSizeTooLargeCHAIN blkSz maxBlkSz) = - mconcat [ "kind" .= String "BlockSizeTooLarge" - , "blockSize" .= blkSz - , "maxBlockSize" .= maxBlkSz - ] - forMachine _dtal (ObsoleteNodeCHAIN currentPtcl supportedPtcl) = - mconcat [ "kind" .= String "ObsoleteNode" - , "explanation" .= String explanation - , "currentProtocol" .= currentPtcl - , "supportedProtocol" .= supportedPtcl ] - where - explanation = mconcat - [ "A scheduled major protocol version change (hard fork) " - , "has taken place on the chain, but this node does not " - , "understand the new major protocol version. This node " - , "must be upgraded before it can continue with the new " - , "protocol version." - ] - -instance LogFormatting PrtlSeqFailure where - forMachine _dtal (WrongSlotIntervalPrtclSeq (SlotNo lastSlot) (SlotNo currSlot)) = - mconcat [ "kind" .= String "WrongSlotInterval" - , "lastSlot" .= lastSlot - , "currentSlot" .= currSlot - ] - forMachine _dtal (WrongBlockNoPrtclSeq lab currentBlockNo) = - mconcat [ "kind" .= String "WrongBlockNo" - , "lastAppliedBlockNo" .= showLastAppBlockNo lab - , "currentBlockNo" .= (String . textShow $ unBlockNo currentBlockNo) - ] - forMachine _dtal (WrongBlockSequencePrtclSeq lastAppliedHash currentHash) = - mconcat [ "kind" .= String "WrongBlockSequence" - , "lastAppliedBlockHash" .= String (textShow lastAppliedHash) - , "currentBlockHash" .= String (textShow currentHash) - ] - -instance - ( Consensus.ShelleyBasedEra era - , LogFormatting (PredicateFailure (UTXO era)) - , LogFormatting (PredicateFailure (UTXOW era)) - , LogFormatting (PredicateFailure (Ledger.EraRule "LEDGER" era)) - , LogFormatting (PredicateFailure (Ledger.EraRule "LEDGERS" era)) - ) => LogFormatting (ShelleyBbodyPredFailure era) where - forMachine _dtal (WrongBlockBodySizeBBODY Mismatch { mismatchSupplied = actualBodySz - , mismatchExpected = claimedBodySz }) = - mconcat [ "kind" .= String "WrongBlockBodySizeBBODY" - , "actualBlockBodySize" .= actualBodySz - , "claimedBlockBodySize" .= claimedBodySz - ] - forMachine _dtal (InvalidBodyHashBBODY Mismatch { mismatchSupplied = actualHash - , mismatchExpected = claimedHash }) = - mconcat [ "kind" .= String "InvalidBodyHashBBODY" - , "actualBodyHash" .= textShow actualHash - , "claimedBodyHash" .= textShow claimedHash - ] - forMachine dtal (LedgersFailure f) = forMachine dtal f - - -instance - ( Consensus.ShelleyBasedEra era - , LogFormatting (PredicateFailure (UTXO era)) - , LogFormatting (PredicateFailure (UTXOW era)) - , LogFormatting (PredicateFailure (Ledger.EraRule "LEDGER" era)) - ) => LogFormatting (ShelleyLedgersPredFailure era) where - forMachine dtal (LedgerFailure f) = forMachine dtal f - -instance LogFormatting Withdrawals where - forMachine _dtal (Withdrawals ws) = - mconcat ["kind" .= String "Withdrawals" - , "withdrawals" .= Aeson.object (map renderTuple $ Map.toList ws) - ] - where - renderTuple :: (Ledger.AccountAddress, Coin) -> Aeson.Pair - renderTuple (address, mismatch) = - Aeson.fromText (Api.serialiseAddress $ Api.fromShelleyStakeAddr address) .= show mismatch - -instance - ( Consensus.ShelleyBasedEra era - , LogFormatting (PredicateFailure (UTXO era)) - , LogFormatting (PredicateFailure (UTXOW era)) - , LogFormatting (PredicateFailure (Ledger.EraRule "DELEGS" era)) - , LogFormatting (PredicateFailure (Ledger.EraRule "UTXOW" era)) - ) => LogFormatting (ShelleyLedgerPredFailure era) where - forMachine dtal = \case - UtxowFailure f -> forMachine dtal f - DelegsFailure f -> forMachine dtal f - ShelleyWithdrawalsMissingAccounts withdrawals -> forMachine dtal withdrawals - ShelleyIncompleteWithdrawals payload -> - mconcat ["kind" .= String "ShelleyIncompleteWithdrawals" - , "withdrawals" .= renderIncompleteWithdrawals payload] - -instance - ( Api.ShelleyLedgerEra era ~ ledgerera - , Api.IsShelleyBasedEra era - , Consensus.ShelleyBasedEra ledgerera - , LogFormatting (Ledger.EraRuleFailure "PPUP" ledgerera) - , LogFormatting (PredicateFailure (Ledger.EraRule "UTXO" ledgerera)) - ) => LogFormatting (AlonzoUtxowPredFailure ledgerera) where - forMachine dtal (ShelleyInAlonzoUtxowPredFailure utxoPredFail) = - forMachine dtal utxoPredFail - forMachine _ (MissingRedeemers scripts) = - mconcat [ "kind" .= String "MissingRedeemers" - , "scripts" .= renderMissingRedeemers Api.shelleyBasedEra scripts - ] - forMachine _ (MissingRequiredDatums required received) = - mconcat [ "kind" .= String "MissingRequiredDatums" - , "required" .= map (Crypto.hashToTextAsHex . Hashes.extractHash) - (NonEmptySet.toList required) - , "received" .= map (Crypto.hashToTextAsHex . Hashes.extractHash) - (Set.toList received) - ] - forMachine _ (PPViewHashesDontMatch Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "PPViewHashesDontMatch" - , "fromTxBody" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchSupplied) - , "fromPParams" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchExpected) - ] - forMachine _ (UnspendableUTxONoDatumHash txins) = - mconcat [ "kind" .= String "MissingRequiredSigners" - , "txins" .= NonEmptySet.toList txins - ] - forMachine _ (NotAllowedSupplementalDatums disallowed acceptable) = - mconcat [ "kind" .= String "NotAllowedSupplementalDatums" - , "disallowed" .= NonEmptySet.toList disallowed - , "acceptable" .= Set.toList acceptable - ] - forMachine _ (ExtraRedeemers rdmrs) = - Api.forEraInEon - (Api.toCardanoEra (Api.shelleyBasedEra :: Api.ShelleyBasedEra era)) - mempty - (\alonzoOnwards -> - mconcat - [ "kind" .= String "ExtraRedeemers" - , "rdmrs" .= map (Api.toScriptIndex alonzoOnwards) (NonEmpty.toList rdmrs) - ] - ) - forMachine _ (ScriptIntegrityHashMismatch Mismatch {mismatchSupplied, mismatchExpected} mBytes) = - mconcat [ "kind" .= String "ScriptIntegrityHashMismatch" - , "supplied" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchSupplied) - , "expected" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchExpected) - , "hashHexPreimage" .= formatAsHex (strictMaybeToMaybe mBytes) - ] - -formatAsHex :: Maybe Crypto.ByteString -> String -formatAsHex Nothing = "" -formatAsHex (Just bs) = show bs - -instance - ( Consensus.ShelleyBasedEra era - , LogFormatting (PredicateFailure (UTXO era)) - , LogFormatting (PredicateFailure (Ledger.EraRule "UTXO" era)) - ) => LogFormatting (ShelleyUtxowPredFailure era) where - forMachine _dtal (InvalidWitnessesUTXOW wits') = - mconcat [ "kind" .= String "InvalidWitnessesUTXOW" - , "invalidWitnesses" .= map textShow (NonEmpty.toList wits') - ] - forMachine _dtal (MissingVKeyWitnessesUTXOW wits') = - mconcat [ "kind" .= String "MissingVKeyWitnessesUTXOW" - , "missingWitnesses" .= wits' - ] - forMachine _dtal (MissingScriptWitnessesUTXOW missingScripts) = - mconcat [ "kind" .= String "MissingScriptWitnessesUTXOW" - , "missingScripts" .= missingScripts - ] - forMachine _dtal (ScriptWitnessNotValidatingUTXOW failedScripts) = - mconcat [ "kind" .= String "ScriptWitnessNotValidatingUTXOW" - , "failedScripts" .= failedScripts - ] - forMachine dtal (UtxoFailure f) = forMachine dtal f - forMachine _dtal (MIRInsufficientGenesisSigsUTXOW genesisSigs) = - mconcat [ "kind" .= String "MIRInsufficientGenesisSigsUTXOW" - , "genesisSigs" .= genesisSigs - ] - forMachine _dtal (MissingTxBodyMetadataHash metadataHash) = - mconcat [ "kind" .= String "MissingTxBodyMetadataHash" - , "metadataHash" .= metadataHash - ] - forMachine _dtal (MissingTxMetadata txBodyMetadataHash) = - mconcat [ "kind" .= String "MissingTxMetadata" - , "txBodyMetadataHash" .= txBodyMetadataHash - ] - forMachine _dtal (ConflictingMetadataHash Mismatch { mismatchSupplied = txBodyMetadataHash - , mismatchExpected = fullMetadataHash }) = - mconcat [ "kind" .= String "ConflictingMetadataHash" - , "txBodyMetadataHash" .= txBodyMetadataHash - , "fullMetadataHash" .= fullMetadataHash - ] - forMachine _dtal InvalidMetadata = - mconcat [ "kind" .= String "InvalidMetadata" - ] - forMachine _dtal (ExtraneousScriptWitnessesUTXOW scriptHashes) = - mconcat [ "kind" .= String "ExtraneousScriptWitnessesUTXOW" - , "scriptHashes" .= Set.map renderScriptHash (NonEmptySet.toSet scriptHashes) - ] - -instance - ( Consensus.ShelleyBasedEra era - , LogFormatting (Ledger.EraRuleFailure "PPUP" era) - ) => LogFormatting (ShelleyUtxoPredFailure era) where - forMachine _dtal (BadInputsUTxO badInputs) = - mconcat [ "kind" .= String "BadInputsUTxO" - , "badInputs" .= badInputs - , "error" .= renderBadInputsUTxOErr (NonEmptySet.toSet badInputs) - ] - forMachine _dtal (ExpiredUTxO Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "ExpiredUTxO" - , "ttl" .= mismatchSupplied - , "slot" .= mismatchExpected ] - forMachine _dtal (MaxTxSizeUTxO Mismatch { mismatchSupplied = txsize - , mismatchExpected = maxtxsize }) = - mconcat [ "kind" .= String "MaxTxSizeUTxO" - , "size" .= txsize - , "maxSize" .= maxtxsize ] - -- TODO: Add the minimum allowed UTxO value to OutputTooSmallUTxO - forMachine _dtal (OutputTooSmallUTxO badOutputs) = - mconcat [ "kind" .= String "OutputTooSmallUTxO" - , "outputs" .= badOutputs - , "error" .= String - ( mconcat - [ "The output is smaller than the allow minimum " - , "UTxO value defined in the protocol parameters" - ] - ) - ] - forMachine _dtal (OutputBootAddrAttrsTooBig badOutputs) = - mconcat [ "kind" .= String "OutputBootAddrAttrsTooBig" - , "outputs" .= badOutputs - , "error" .= String "The Byron address attributes are too big" - ] - forMachine _dtal InputSetEmptyUTxO = - mconcat [ "kind" .= String "InputSetEmptyUTxO" ] - -- TODO are these arguments in the right order? - forMachine _dtal (FeeTooSmallUTxO Mismatch { mismatchSupplied = minfee - , mismatchExpected = txfee }) = - mconcat [ "kind" .= String "FeeTooSmallUTxO" - , "minimum" .= minfee - , "fee" .= txfee ] - forMachine _dtal (ValueNotConservedUTxO Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "ValueNotConservedUTxO" - , "consumed" .= mismatchSupplied - , "produced" .= mismatchExpected - , "error" .= renderValueNotConservedErr mismatchSupplied mismatchExpected - ] - forMachine dtal (UpdateFailure f) = forMachine dtal f - - forMachine _dtal (WrongNetwork network addrs) = - mconcat [ "kind" .= String "WrongNetwork" - , "network" .= network - , "addrs" .= addrs - ] - forMachine _dtal (WrongNetworkWithdrawal network addrs) = - mconcat [ "kind" .= String "WrongNetworkWithdrawal" - , "network" .= network - , "addrs" .= addrs - ] - -instance - ( Consensus.ShelleyBasedEra era - , ToJSON Allegra.ValidityInterval - , LogFormatting (Ledger.EraRuleFailure "PPUP" era) - ) => LogFormatting (AllegraUtxoPredFailure era) where - forMachine _dtal (Allegra.BadInputsUTxO badInputs) = - mconcat [ "kind" .= String "BadInputsUTxO" - , "badInputs" .= badInputs - , "error" .= renderBadInputsUTxOErr (NonEmptySet.toSet badInputs) - ] - forMachine _dtal (Allegra.OutsideValidityIntervalUTxO validityInterval slot) = - mconcat [ "kind" .= String "ExpiredUTxO" - , "validityInterval" .= validityInterval - , "slot" .= slot ] - forMachine _dtal (Allegra.MaxTxSizeUTxO Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "MaxTxSizeUTxO" - , "size" .= mismatchSupplied - , "maxSize" .= mismatchExpected ] - forMachine _dtal Allegra.InputSetEmptyUTxO = - mconcat [ "kind" .= String "InputSetEmptyUTxO" ] - forMachine _dtal (Allegra.FeeTooSmallUTxO Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "FeeTooSmallUTxO" - , "minimum" .= mismatchExpected - , "fee" .= mismatchSupplied ] - forMachine _dtal (Allegra.ValueNotConservedUTxO Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "ValueNotConservedUTxO" - , "consumed" .= mismatchSupplied - , "produced" .= mismatchExpected - , "error" .= renderValueNotConservedErr mismatchSupplied mismatchExpected - ] - forMachine _dtal (Allegra.WrongNetwork network addrs) = - mconcat [ "kind" .= String "WrongNetwork" - , "network" .= network - , "addrs" .= addrs - ] - forMachine _dtal (Allegra.WrongNetworkWithdrawal network addrs) = - mconcat [ "kind" .= String "WrongNetworkWithdrawal" - , "network" .= network - , "addrs" .= addrs - ] - -- TODO: Add the minimum allowed UTxO value to OutputTooSmallUTxO - forMachine _dtal (Allegra.OutputTooSmallUTxO badOutputs) = - mconcat [ "kind" .= String "OutputTooSmallUTxO" - , "outputs" .= badOutputs - , "error" .= String - ( mconcat - [ "The output is smaller than the allow minimum " - , "UTxO value defined in the protocol parameters" - ] - ) - ] - forMachine dtal (Allegra.UpdateFailure f) = forMachine dtal f - forMachine _dtal (Allegra.OutputBootAddrAttrsTooBig badOutputs) = - mconcat [ "kind" .= String "OutputBootAddrAttrsTooBig" - , "outputs" .= badOutputs - , "error" .= String "The Byron address attributes are too big" - ] - forMachine _dtal (Allegra.OutputTooBigUTxO badOutputs) = - mconcat [ "kind" .= String "OutputTooBigUTxO" - , "outputs" .= badOutputs - , "error" .= String "Too many asset ids in the tx output" - ] - -renderBadInputsUTxOErr :: Set TxIn -> Value -renderBadInputsUTxOErr txIns - | Set.null txIns = String "The transaction contains no inputs." - | otherwise = String "The transaction contains inputs that do not exist in the UTxO set." - -renderValueNotConservedErr :: Show val => val -> val -> Value -renderValueNotConservedErr consumed produced = String $ - "This transaction consumed " <> textShow consumed <> " but produced " <> textShow produced - -instance LogFormatting (ShelleyPpupPredFailure era) where - -- TODO are these arguments in the right order? - forMachine _dtal (NonGenesisUpdatePPUP Mismatch { mismatchSupplied = proposalKeys - , mismatchExpected = genesisKeys }) = - mconcat [ "kind" .= String "NonGenesisUpdatePPUP" - , "keys" .= proposalKeys Set.\\ genesisKeys ] - forMachine _dtal (PPUpdateWrongEpoch currEpoch intendedEpoch votingPeriod) = - mconcat [ "kind" .= String "PPUpdateWrongEpoch" - , "currentEpoch" .= currEpoch - , "intendedEpoch" .= intendedEpoch - , "votingPeriod" .= String (textShow votingPeriod) - ] - forMachine _dtal (PVCannotFollowPPUP badPv) = - mconcat [ "kind" .= String "PVCannotFollowPPUP" - , "badProtocolVersion" .= badPv - ] - - -instance - ( Consensus.ShelleyBasedEra era - , LogFormatting (PredicateFailure (Ledger.EraRule "DELPL" era)) - ) => LogFormatting (ShelleyDelegsPredFailure era) where - forMachine dtal (DelplFailure f) = forMachine dtal f - - -instance - ( LogFormatting (PredicateFailure (Ledger.EraRule "POOL" era)) - , LogFormatting (PredicateFailure (Ledger.EraRule "DELEG" era)) - ) => LogFormatting (ShelleyDelplPredFailure era) where - forMachine dtal (PoolFailure f) = forMachine dtal f - forMachine dtal (DelegFailure f) = forMachine dtal f - -instance LogFormatting (ShelleyDelegPredFailure era) where - forMachine _dtal (StakeKeyAlreadyRegisteredDELEG alreadyRegistered) = - mconcat [ "kind" .= String "StakeKeyAlreadyRegisteredDELEG" - , "credential" .= String (textShow alreadyRegistered) - , "error" .= String "Staking credential already registered" - ] - forMachine _dtal (StakeKeyNotRegisteredDELEG notRegistered) = - mconcat [ "kind" .= String "StakeKeyNotRegisteredDELEG" - , "credential" .= String (textShow notRegistered) - , "error" .= String "Staking credential not registered" - ] - forMachine _dtal (StakeKeyNonZeroAccountBalanceDELEG remBalance) = - mconcat [ "kind" .= String "StakeKeyNonZeroAccountBalanceDELEG" - , "remainingBalance" .= remBalance - ] - forMachine _dtal (StakeDelegationImpossibleDELEG unregistered) = - mconcat [ "kind" .= String "StakeDelegationImpossibleDELEG" - , "credential" .= String (textShow unregistered) - , "error" .= String "Cannot delegate this stake credential because it is not registered" - ] - forMachine _dtal WrongCertificateTypeDELEG = - mconcat [ "kind" .= String "WrongCertificateTypeDELEG" ] - forMachine _dtal (GenesisKeyNotInMappingDELEG (KeyHash genesisKeyHash)) = - mconcat [ "kind" .= String "GenesisKeyNotInMappingDELEG" - , "unknownKeyHash" .= String (textShow genesisKeyHash) - , "error" .= String "This genesis key is not in the delegation mapping" - ] - forMachine _dtal (DuplicateGenesisDelegateDELEG (KeyHash genesisKeyHash)) = - mconcat [ "kind" .= String "DuplicateGenesisDelegateDELEG" - , "duplicateKeyHash" .= String (textShow genesisKeyHash) - , "error" .= String "This genesis key has already been delegated to" - ] - forMachine _dtal (InsufficientForInstantaneousRewardsDELEG mirpot Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "InsufficientForInstantaneousRewardsDELEG" - , "pot" .= String (case mirpot of - ReservesMIR -> "Reserves" - TreasuryMIR -> "Treasury") - , "neededAmount" .= mismatchSupplied - , "reserves" .= mismatchExpected - ] - forMachine _dtal (MIRCertificateTooLateinEpochDELEG Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "MIRCertificateTooLateinEpochDELEG" - , "currentSlotNo" .= mismatchSupplied - , "mustBeSubmittedBeforeSlotNo" .= mismatchExpected - ] - forMachine _dtal (DuplicateGenesisVRFDELEG vrfKeyHash) = - mconcat [ "kind" .= String "DuplicateGenesisVRFDELEG" - , "keyHash" .= fromVRFVerKeyHash vrfKeyHash - ] - forMachine _dtal MIRTransferNotCurrentlyAllowed = - mconcat [ "kind" .= String "MIRTransferNotCurrentlyAllowed" - ] - forMachine _dtal MIRNegativesNotCurrentlyAllowed = - mconcat [ "kind" .= String "MIRNegativesNotCurrentlyAllowed" - ] - forMachine _dtal (InsufficientForTransferDELEG mirpot Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "DuplicateGenesisVRFDELEG" - , "pot" .= String (case mirpot of - ReservesMIR -> "Reserves" - TreasuryMIR -> "Treasury") - , "attempted" .= mismatchSupplied - , "available" .= mismatchExpected - ] - forMachine _dtal MIRProducesNegativeUpdate = - mconcat [ "kind" .= String "MIRProducesNegativeUpdate" - ] - forMachine _dtal (MIRNegativeTransfer mirpot coin) = - mconcat [ "kind" .= String "MIRProducesNegativeUpdate" - , "pot" .= String (case mirpot of - ReservesMIR -> "Reserves" - TreasuryMIR -> "Treasury") - , "coin" .= coin - ] - forMachine _dtal (DelegateeNotRegisteredDELEG targetPool) = - mconcat [ "kind" .= String "DelegateeNotRegisteredDELEG" - , "targetPool" .= targetPool - ] - -instance LogFormatting (ShelleyPoolPredFailure era) where - forMachine _dtal (StakePoolNotRegisteredOnKeyPOOL (KeyHash unregStakePool)) = - mconcat [ "kind" .= String "StakePoolNotRegisteredOnKeyPOOL" - , "unregisteredKeyHash" .= String (textShow unregStakePool) - , "error" .= String "This stake pool key hash is unregistered" - ] - forMachine _dtal (StakePoolRetirementWrongEpochPOOL - -- inspired by Ledger's Test.Cardano.Ledger.Generic.PrettyCore - -- but is it correct here? - Mismatch { mismatchExpected = currentEpoch } - Mismatch { mismatchSupplied = intendedRetireEpoch - , mismatchExpected = maxRetireEpoch}) = - mconcat [ "kind" .= String "StakePoolRetirementWrongEpochPOOL" - , "currentEpoch" .= String (textShow currentEpoch) - , "intendedRetirementEpoch" .= String (textShow intendedRetireEpoch) - , "maxEpochForRetirement" .= String (textShow maxRetireEpoch) - ] - -- TODO are these supplied in the right order? - forMachine _dtal (StakePoolCostTooLowPOOL Mismatch { mismatchSupplied = certCost - , mismatchExpected = protCost }) = - mconcat [ "kind" .= String "StakePoolCostTooLowPOOL" - , "certificateCost" .= String (textShow certCost) - , "protocolParCost" .= String (textShow protCost) - , "error" .= String "The stake pool cost is too low" - ] - forMachine _dtal (PoolMedataHashTooBig poolID hashSize) = - mconcat [ "kind" .= String "PoolMedataHashTooBig" - , "hashSize" .= String (textShow poolID) - , "poolID" .= String (textShow hashSize) - , "error" .= String "The stake pool metadata hash is too large" - ] - - forMachine _dtal (WrongNetworkPOOL Mismatch { mismatchSupplied = networkId - , mismatchExpected = listedNetworkId } poolId) = - mconcat [ "kind" .= String "WrongNetworkPOOL" - , "networkId" .= String (textShow networkId) - , "listedNetworkId" .= String (textShow listedNetworkId) - , "poolId" .= String (textShow poolId) - , "error" .= String "Wrong network ID in pool registration certificate" - ] - forMachine _dtal (VRFKeyHashAlreadyRegistered poolId vrfKeyHash) = - mconcat [ "kind" .= String "VRFKeyHashAlreadyRegistered" - , "poolId" .= String (textShow poolId) - , "vrfKeyHash" .= String (textShow vrfKeyHash) - , "error" .= String "Pool with the same VRF Key Hash is already registered" - ] - - -instance - ( Ledger.Crypto crypto - ) => LogFormatting (PrtclPredicateFailure crypto) where - forMachine dtal (OverlayFailure f) = forMachine dtal f - forMachine dtal (UpdnFailure f) = forMachine dtal f - - -instance - ( Ledger.Crypto crypto - ) => LogFormatting (OverlayPredicateFailure crypto) where - forMachine _dtal (UnknownGenesisKeyOVERLAY (KeyHash genKeyHash)) = - mconcat [ "kind" .= String "UnknownGenesisKeyOVERLAY" - , "unknownKeyHash" .= String (textShow genKeyHash) - ] - forMachine _dtal (VRFKeyBadLeaderValue seedNonce (SlotNo currSlotNo) prevHashNonce leaderElecVal) = - mconcat [ "kind" .= String "VRFKeyBadLeaderValueOVERLAY" - , "seedNonce" .= String (textShow seedNonce) - , "currentSlot" .= String (textShow currSlotNo) - , "previousHashAsNonce" .= String (textShow prevHashNonce) - , "leaderElectionValue" .= String (textShow leaderElecVal) - ] - forMachine _dtal (VRFKeyBadNonce seedNonce (SlotNo currSlotNo) prevHashNonce blockNonce) = - mconcat [ "kind" .= String "VRFKeyBadNonceOVERLAY" - , "seedNonce" .= String (textShow seedNonce) - , "currentSlot" .= String (textShow currSlotNo) - , "previousHashAsNonce" .= String (textShow prevHashNonce) - , "blockNonce" .= String (textShow blockNonce) - ] - forMachine _dtal (VRFKeyWrongVRFKey issuerHash regVRFKeyHash unregVRFKeyHash) = - mconcat [ "kind" .= String "VRFKeyWrongVRFKeyOVERLAY" - , "poolHash" .= textShow issuerHash - , "registeredVRFKeHash" .= textShow regVRFKeyHash - , "unregisteredVRFKeyHash" .= textShow unregVRFKeyHash - ] - --TODO: Pipe slot number with VRFKeyUnknown - forMachine _dtal (VRFKeyUnknown (KeyHash kHash)) = - mconcat [ "kind" .= String "VRFKeyUnknownOVERLAY" - , "keyHash" .= String (textShow kHash) - ] - forMachine _dtal (VRFLeaderValueTooBig leadElecVal weightOfDelegPool actSlotCoefff) = - mconcat [ "kind" .= String "VRFLeaderValueTooBigOVERLAY" - , "leaderElectionValue" .= String (textShow leadElecVal) - , "delegationPoolWeight" .= String (textShow weightOfDelegPool) - , "activeSlotCoefficient" .= String (textShow actSlotCoefff) - ] - forMachine _dtal (NotActiveSlotOVERLAY notActiveSlotNo) = - -- TODO: Elaborate on NotActiveSlot error - mconcat [ "kind" .= String "NotActiveSlotOVERLAY" - , "slot" .= String (textShow notActiveSlotNo) - ] - forMachine _dtal (WrongGenesisColdKeyOVERLAY actual expected) = - mconcat [ "kind" .= String "WrongGenesisColdKeyOVERLAY" - , "actual" .= actual - , "expected" .= expected ] - forMachine _dtal (WrongGenesisVRFKeyOVERLAY issuer actual expected) = - mconcat [ "kind" .= String "WrongGenesisVRFKeyOVERLAY" - , "issuer" .= issuer - , "actual" .= actual - , "expected" .= expected ] - forMachine dtal (OcertFailure f) = forMachine dtal f - - -instance LogFormatting OcertPredicateFailure where - forMachine _dtal (KESBeforeStartOCERT (KESPeriod oCertstart) (KESPeriod current)) = - mconcat [ "kind" .= String "KESBeforeStartOCERT" - , "opCertKESStartPeriod" .= String (textShow oCertstart) - , "currentKESPeriod" .= String (textShow current) - , "error" .= String - ( mconcat - [ "Your operational certificate's KES start period " - , "is before the KES current period." - ] - ) - ] - forMachine _dtal (KESAfterEndOCERT (KESPeriod current) (KESPeriod oCertstart) maxKESEvolutions) = - mconcat [ "kind" .= String "KESAfterEndOCERT" - , "currentKESPeriod" .= String (textShow current) - , "opCertKESStartPeriod" .= String (textShow oCertstart) - , "maxKESEvolutions" .= String (textShow maxKESEvolutions) - , "error" .= String - ( mconcat - [ "The operational certificate's KES start period is " - , "greater than the max number of KES + the KES current period" - ] - ) - ] - forMachine _dtal (CounterTooSmallOCERT lastKEScounterUsed currentKESCounter) = - mconcat [ "kind" .= String "CounterTooSmallOCert" - , "currentKESCounter" .= String (textShow currentKESCounter) - , "lastKESCounter" .= String (textShow lastKEScounterUsed) - , "error" .= String - ( mconcat - [ "The operational certificate's last KES counter is greater " - , "than the current KES counter." - ] - ) - ] - forMachine _dtal (InvalidSignatureOCERT oCertCounter oCertKESStartPeriod) = - mconcat [ "kind" .= String "InvalidSignatureOCERT" - , "opCertKESStartPeriod" .= String (textShow oCertKESStartPeriod) - , "opCertCounter" .= String (textShow oCertCounter) - ] - forMachine _dtal (InvalidKesSignatureOCERT currKESPeriod startKESPeriod expectedKESEvolutions err) = - mconcat [ "kind" .= String "InvalidKesSignatureOCERT" - , "opCertKESStartPeriod" .= String (textShow startKESPeriod) - , "opCertKESCurrentPeriod" .= String (textShow currKESPeriod) - , "opCertExpectedKESEvolutions" .= String (textShow expectedKESEvolutions) - , "error" .= err ] - forMachine _dtal (NoCounterForKeyHashOCERT (KeyHash stakePoolKeyHash)) = - mconcat [ "kind" .= String "NoCounterForKeyHashOCERT" - , "stakePoolKeyHash" .= String (textShow stakePoolKeyHash) - , "error" .= String "A counter was not found for this stake pool key hash" - ] - - -instance LogFormatting (UpdnPredicateFailure crypto) where - forMachine _dtal x = case x of {} -- no constructors - --------------------------------------------------------------------------------- --- Alonzo related --------------------------------------------------------------------------------- -instance - ( Consensus.ShelleyBasedEra era - , LogFormatting (PredicateFailure (Ledger.EraRule "UTXOS" era)) - ) => LogFormatting (AlonzoUtxoPredFailure era) where - forMachine _dtal (Alonzo.BadInputsUTxO badInputs) = - mconcat [ "kind" .= String "BadInputsUTxO" - , "badInputs" .= NonEmptySet.toSet badInputs - , "error" .= renderBadInputsUTxOErr (NonEmptySet.toSet badInputs) - ] - forMachine _dtal (Alonzo.OutsideValidityIntervalUTxO validtyInterval slot) = - mconcat [ "kind" .= String "ExpiredUTxO" - , "validityInterval" .= validtyInterval - , "slot" .= slot - ] - forMachine _dtal (Alonzo.MaxTxSizeUTxO Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "MaxTxSizeUTxO" - , "size" .= mismatchSupplied - , "maxSize" .= mismatchExpected - ] - forMachine _dtal Alonzo.InputSetEmptyUTxO = - mconcat [ "kind" .= String "InputSetEmptyUTxO" ] - forMachine _dtal (Alonzo.FeeTooSmallUTxO Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "FeeTooSmallUTxO" - , "minimum" .= mismatchExpected - , "fee" .= mismatchSupplied - ] - forMachine _dtal (Alonzo.ValueNotConservedUTxO Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "ValueNotConservedUTxO" - , "consumed" .= mismatchSupplied - , "produced" .= mismatchExpected - , "error" .= renderValueNotConservedErr mismatchSupplied mismatchExpected - ] - forMachine _dtal (Alonzo.WrongNetwork network addrs) = - mconcat [ "kind" .= String "WrongNetwork" - , "network" .= network - , "addrs" .= addrs - ] - forMachine _dtal (Alonzo.WrongNetworkWithdrawal network addrs) = - mconcat [ "kind" .= String "WrongNetworkWithdrawal" - , "network" .= network - , "addrs" .= addrs - ] - forMachine _dtal (Alonzo.OutputTooSmallUTxO badOutputs) = - mconcat [ "kind" .= String "OutputTooSmallUTxO" - , "outputs" .= badOutputs - , "error" .= String - ( mconcat - [ "The output is smaller than the allow minimum " - , "UTxO value defined in the protocol parameters" - ] - ) - ] - forMachine dtal (Alonzo.UtxosFailure predFailure) = - forMachine dtal predFailure - forMachine _dtal (Alonzo.OutputBootAddrAttrsTooBig txouts) = - mconcat [ "kind" .= String "OutputBootAddrAttrsTooBig" - , "outputs" .= txouts - , "error" .= String "The Byron address attributes are too big" - ] - forMachine _dtal (Alonzo.OutputTooBigUTxO badOutputs) = - mconcat [ "kind" .= String "OutputTooBigUTxO" - , "outputs" .= badOutputs - , "error" .= String "Too many asset ids in the tx output" - ] - forMachine _dtal (Alonzo.InsufficientCollateral computedBalance suppliedFee) = - mconcat [ "kind" .= String "InsufficientCollateral" - , "balance" .= computedBalance - , "txfee" .= suppliedFee - ] - forMachine _dtal (Alonzo.ScriptsNotPaidUTxO utxos) = - mconcat [ "kind" .= String "ScriptsNotPaidUTxO" - , "utxos" .= utxos - ] - forMachine _dtal (Alonzo.ExUnitsTooBigUTxO Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "ExUnitsTooBigUTxO" - , "maxexunits" .= mismatchExpected - , "exunits" .= mismatchSupplied - ] - forMachine _dtal (Alonzo.CollateralContainsNonADA inputs) = - mconcat [ "kind" .= String "CollateralContainsNonADA" - , "inputs" .= inputs - ] - forMachine _dtal (Alonzo.WrongNetworkInTxBody Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "WrongNetworkInTxBody" - , "networkid" .= mismatchExpected - , "txbodyNetworkId" .= mismatchSupplied - ] - forMachine _dtal (Alonzo.OutsideForecast slotNum) = - mconcat [ "kind" .= String "OutsideForecast" - , "slot" .= slotNum - ] - forMachine _dtal (Alonzo.TooManyCollateralInputs Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "TooManyCollateralInputs" - , "max" .= mismatchExpected - , "inputs" .= mismatchSupplied - ] - forMachine _dtal Alonzo.NoCollateralInputs = - mconcat [ "kind" .= String "NoCollateralInputs" ] - -instance - ( ToJSON (Alonzo.CollectError ledgerera) - , LogFormatting (Ledger.EraRuleFailure "PPUP" ledgerera) - ) => LogFormatting (AlonzoUtxosPredFailure ledgerera) where - forMachine _ (Alonzo.ValidationTagMismatch isValidating reason) = - mconcat [ "kind" .= String "ValidationTagMismatch" - , "isvalidating" .= isValidating - , "reason" .= reason - ] - forMachine _ (Alonzo.CollectErrors errors) = - mconcat [ "kind" .= String "CollectErrors" - , "errors" .= errors - ] - forMachine dtal (Alonzo.UpdateFailure pFailure) = - forMachine dtal pFailure - -instance - ( Ledger.Era era - , Show (PredicateFailure (Ledger.EraRule "LEDGERS" era)) - ) => LogFormatting (AlonzoBbodyPredFailure era) where - forMachine _ err = mconcat [ "kind" .= String "AlonzoBbodyPredFail" - , "error" .= String (textShow err) - ] --------------------------------------------------------------------------------- --- Babbage related --------------------------------------------------------------------------------- - - -instance - ( Ledger.Era era - , LogFormatting (AlonzoUtxoPredFailure era) - , ToJSON (Ledger.TxOut era) - ) => LogFormatting (BabbageUtxoPredFailure era) where - forMachine v err = - case err of - Babbage.AlonzoInBabbageUtxoPredFailure alonzoFail -> - forMachine v alonzoFail - - Babbage.IncorrectTotalCollateralField provided declared -> - mconcat [ "kind" .= String "IncorrectTotalCollateralField" - , "collateralProvided" .= provided - , "collateralDeclared" .= declared - ] - -- The transaction contains outputs that are too small - Babbage.BabbageOutputTooSmallUTxO outputs -> - mconcat [ "kind" .= String "OutputTooSmall" - , "outputs" .= outputs - ] - - Babbage.BabbageNonDisjointRefInputs nonDisjointInputs -> - mconcat [ "kind" .= String "BabbageNonDisjointRefInputs" - , "outputs" .= nonDisjointInputs - ] - -instance - ( Api.ShelleyLedgerEra era ~ ledgerera - , Api.IsShelleyBasedEra era - , Ledger.Era ledgerera - , ShelleyBasedEra ledgerera - , LogFormatting (Ledger.EraRuleFailure "PPUP" ledgerera) - , LogFormatting (ShelleyUtxowPredFailure ledgerera) - , LogFormatting (PredicateFailure (Ledger.EraRule "UTXO" ledgerera)) - ) => LogFormatting (BabbageUtxowPredFailure ledgerera) where - forMachine v err = - case err of - Babbage.AlonzoInBabbageUtxowPredFailure alonzoFail -> - forMachine v alonzoFail - Babbage.UtxoFailure utxoFail -> - forMachine v utxoFail - -- TODO: Plutus team needs to expose a better error type. - Babbage.MalformedScriptWitnesses s -> - mconcat [ "kind" .= String "MalformedScriptWitnesses" - , "scripts" .= s - ] - Babbage.MalformedReferenceScripts s -> - mconcat [ "kind" .= String "MalformedReferenceScripts" - , "scripts" .= s - ] - Babbage.ScriptIntegrityHashMismatch Mismatch {mismatchSupplied, mismatchExpected} mBytes -> - mconcat [ "kind" .= String "ScriptIntegrityHashMismatch" - , "supplied" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchSupplied) - , "expected" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchExpected) - , "hashHexPreimage" .= formatAsHex (strictMaybeToMaybe mBytes) - ] --------------------------------------------------------------------------------- --- Conway related --------------------------------------------------------------------------------- - -instance - ( Ledger.Era era - , Show (PredicateFailure (Ledger.EraRule "LEDGERS" era)) - ) => LogFormatting (Conway.ConwayBbodyPredFailure era) where - forMachine _ err = mconcat [ "kind" .= String "ConwayBbodyPredFail" - , "error" .= String (textShow err) - ] - -instance - ( Consensus.ShelleyBasedEra era - , LogFormatting (PredicateFailure (Ledger.EraRule "UTXOW" era)) - , LogFormatting (PredicateFailure (Ledger.EraRule "GOV" era)) - , LogFormatting (PredicateFailure (Ledger.EraRule "CERTS" era)) - ) => LogFormatting (Conway.ConwayLedgerPredFailure era) where - forMachine v (Conway.ConwayUtxowFailure f) = forMachine v f - forMachine _ (Conway.ConwayWithdrawalsMissingAccounts missingWithdrawals) = - mconcat [ "kind" .= String "ConwayWithdrawalsMissingAccounts" - , "withdrawals" .= unWithdrawals missingWithdrawals - ] - forMachine _ (Conway.ConwayIncompleteWithdrawals incompleteWithdrawals) = - mconcat [ "kind" .= String "ConwayIncompleteWithdrawals" - , "withdrawals" .= renderIncompleteWithdrawals incompleteWithdrawals - ] - forMachine _ (Conway.ConwayTxRefScriptsSizeTooBig Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "ConwayTxRefScriptsSizeTooBig" - , "actual" .= mismatchSupplied - , "limit" .= mismatchExpected - ] - forMachine v (Conway.ConwayCertsFailure f) = forMachine v f - forMachine v (Conway.ConwayGovFailure f) = forMachine v f - forMachine v (Conway.ConwayWdrlNotDelegatedToDRep f) = forMachine v f - forMachine _ (Conway.ConwayTreasuryValueMismatch Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "ConwayTreasuryValueMismatch" - , "actual" .= mismatchExpected - , "submittedInTx" .= mismatchSupplied - ] - forMachine _ (Conway.ConwayMempoolFailure message) = - mconcat [ "kind" .= String "ConwayMempoolFailure" - , "actual" .= message - ] - -instance - ( Consensus.ShelleyBasedEra era - ) => LogFormatting (Conway.ConwayGovPredFailure era) where - forMachine _ (Conway.GovActionsDoNotExist govActionIds) = - mconcat [ "kind" .= String "GovActionsDoNotExist" - , "govActionId" .= map govActionIdToText (NonEmpty.toList govActionIds) - ] - forMachine _ (Conway.MalformedProposal govAction) = - mconcat [ "kind" .= String "MalformedProposal" - , "govAction" .= govAction - ] - forMachine _ (Conway.ProposalProcedureNetworkIdMismatch rewardAcnt network) = - mconcat [ "kind" .= String "ProposalProcedureNetworkIdMismatch" - , "rewardAccount" .= toJSON rewardAcnt - , "expectedNetworkId" .= toJSON network - ] - forMachine _ (Conway.TreasuryWithdrawalsNetworkIdMismatch rewardAcnts network) = - mconcat [ "kind" .= String "TreasuryWithdrawalsNetworkIdMismatch" - , "rewardAccounts" .= toJSON rewardAcnts - , "expectedNetworkId" .= toJSON network - ] - forMachine _ (Conway.ProposalDepositIncorrect Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "ProposalDepositIncorrect" - , "deposit" .= mismatchSupplied - , "expectedDeposit" .= mismatchExpected - ] - forMachine _ (Conway.DisallowedVoters govActionIdToVoter) = - mconcat [ "kind" .= String "DisallowedVoters" - , "govActionIdToVoter" .= NonEmpty.toList govActionIdToVoter - ] - forMachine _ (Conway.VotersDoNotExist creds) = - mconcat [ "kind" .= String "VotersDoNotExist" - , "credentials" .= creds - ] - forMachine _ (Conway.ConflictingCommitteeUpdate creds) = - mconcat [ "kind" .= String "ConflictingCommitteeUpdate" - , "credentials" .= creds - ] - forMachine _ (Conway.ExpirationEpochTooSmall credsToEpoch) = - mconcat [ "kind" .= String "ExpirationEpochTooSmall" - , "credentialsToEpoch" .= credsToEpoch - ] - forMachine _ (Conway.InvalidPrevGovActionId proposalProcedure) = - mconcat [ "kind" .= String "InvalidPrevGovActionId" - , "proposalProcedure" .= proposalProcedure - ] - forMachine _ (Conway.VotingOnExpiredGovAction actions) = - mconcat [ "kind" .= String "VotingOnExpiredGovAction" - , "action" .= actions - ] - forMachine _ (Conway.ProposalCantFollow prevGovActionId Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "ProposalCantFollow" - , "prevGovActionId" .= prevGovActionId - , "protVer" .= mismatchSupplied - , "prevProtVer" .= mismatchExpected - ] - forMachine _ (Conway.DisallowedProposalDuringBootstrap proposal) = - mconcat [ "kind" .= String "DisallowedProposalDuringBootstrap" - , "proposal" .= proposal - ] - forMachine _ (Conway.DisallowedVotesDuringBootstrap votes) = - mconcat [ "kind" .= String "DisallowedVotesDuringBootstrap" - , "votes" .= votes - ] - forMachine _ (Conway.ZeroTreasuryWithdrawals govAction) = - mconcat [ "kind" .= String "ZeroTreasuryWithdrawals" - , "govAction" .= govAction - ] - forMachine _ (Conway.ProposalReturnAccountDoesNotExist account) = - mconcat [ "kind" .= String "ProposalReturnAccountDoesNotExist" - , "invalidAccount" .= account - ] - forMachine _ (Conway.TreasuryWithdrawalReturnAccountsDoNotExist accounts) = - mconcat [ "kind" .= String "TreasuryWithdrawalReturnAccountsDoNotExist" - , "invalidAccounts" .= accounts - ] - - forMachine _ (Conway.UnelectedCommitteeVoters voters) = - mconcat [ "kind" .= String "UnelectedCommitteeVoters" - , "unelectedCommitteeVoters" .= voters - ] - forMachine _ (Conway.InvalidGuardrailsScriptHash actualPolicyHash expectedPolicyHash) = - mconcat [ "kind" .= String "InvalidPolicyHash" - , "actualPolicyHash" .= actualPolicyHash - , "expectedPolicyHash" .= expectedPolicyHash - ] - - -instance - ( Consensus.ShelleyBasedEra era - , LogFormatting (PredicateFailure (Ledger.EraRule "CERT" era)) - ) => LogFormatting (Conway.ConwayCertsPredFailure era) where - forMachine _ (Conway.WithdrawalsNotInRewardsCERTS rs) = - mconcat [ "kind" .= String "WithdrawalsNotInRewardsCERTS" - , "rewardAccounts" .= unWithdrawals rs - ] - forMachine dtal (Conway.CertFailure certFailure) = - forMachine dtal certFailure - -instance - ( Consensus.ShelleyBasedEra ledgerera - , LogFormatting (PredicateFailure (Ledger.EraRule "UTXOW" ledgerera)) - , LogFormatting (PredicateFailure (Ledger.EraRule "ENTITIES" ledgerera)) - , LogFormatting (PredicateFailure (Ledger.EraRule "GOV" ledgerera)) - , Show (PredicateFailure (Ledger.EraRule "SUBLEDGERS" ledgerera)) - ) => LogFormatting (Dijkstra.DijkstraLedgerPredFailure ledgerera) where - forMachine v (Dijkstra.DijkstraUtxowFailure f) = forMachine v f - forMachine v (Dijkstra.DijkstraEntitiesFailure f) = forMachine v f - forMachine v (Dijkstra.DijkstraGovFailure f) = forMachine v f - forMachine _ (Dijkstra.DijkstraTreasuryValueMismatch Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "DijkstraTreasuryValueMismatch" - , "actual" .= mismatchExpected - , "submittedInTx" .= mismatchSupplied - ] - forMachine _ (Dijkstra.DijkstraTxRefScriptsSizeTooBig Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "DijkstraTxRefScriptsSizeTooBig" - , "actual" .= mismatchSupplied - , "limit" .= mismatchExpected - ] - -- Sub-transaction failures are rendered via 'Show' until the nested - -- transaction tooling stabilises. - forMachine _ (Dijkstra.DijkstraSubLedgersFailure f) = - mconcat [ "kind" .= String "DijkstraSubLedgersFailure" - , "error" .= String (textShow f) - ] - -instance - ( LogFormatting (PredicateFailure (Ledger.EraRule "CERTS" ledgerera)) - ) => LogFormatting (Dijkstra.EntitiesPredFailure ledgerera) where - forMachine v (Dijkstra.CertsFailure f) = forMachine v f - forMachine _ (Dijkstra.MissingAccountsInWithdrawals withdrawals) = - mconcat [ "kind" .= String "MissingAccountsInWithdrawals" - , "withdrawals" .= unWithdrawals withdrawals - ] - forMachine _ (Dijkstra.IncompleteWithdrawals incompleteWithdrawals) = - mconcat [ "kind" .= String "IncompleteWithdrawals" - , "withdrawals" .= String (textShow incompleteWithdrawals) - ] - forMachine _ (Dijkstra.ExceededBalancesInWithdrawals accounts) = - mconcat [ "kind" .= String "ExceededBalancesInWithdrawals" - , "accounts" .= String (textShow accounts) - ] - forMachine _ (Dijkstra.MissingAccountsInDirectDeposits directDeposits) = - mconcat [ "kind" .= String "MissingAccountsInDirectDeposits" - , "directDeposits" .= String (textShow directDeposits) - ] - forMachine _ (Dijkstra.WrongNetworkInWithdrawals network accounts) = - mconcat [ "kind" .= String "WrongNetworkInWithdrawals" - , "network" .= network - , "accounts" .= NonEmptySet.toSet accounts - ] - forMachine _ (Dijkstra.WrongNetworkInDirectDeposits network accounts) = - mconcat [ "kind" .= String "WrongNetworkInDirectDeposits" - , "network" .= network - , "accounts" .= NonEmptySet.toSet accounts - ] - -instance - ( Consensus.ShelleyBasedEra ledgerera - , LogFormatting (PredicateFailure (Ledger.EraRule "LEDGER" ledgerera)) - ) => LogFormatting (Dijkstra.DijkstraMempoolPredFailure ledgerera) where - forMachine v (Dijkstra.LedgerFailure f) = forMachine v f - forMachine _ (Dijkstra.MempoolFailure message) = - mconcat [ "kind" .= String "DijkstraMempoolFailure" - , "actual" .= message - ] - forMachine _ Dijkstra.AllInputsAreSpent = - mconcat [ "kind" .= String "AllInputsAreSpent" ] - -instance - ( Consensus.ShelleyBasedEra era - ) => LogFormatting (Dijkstra.DijkstraGovPredFailure era) where - forMachine _ (Dijkstra.GovActionsDoNotExist govActionIds) = - mconcat [ "kind" .= String "GovActionsDoNotExist" - , "govActionId" .= map govActionIdToText (NonEmpty.toList govActionIds) - ] - forMachine _ (Dijkstra.MalformedProposal govAction) = - mconcat [ "kind" .= String "MalformedProposal" - , "govAction" .= govAction - ] - forMachine _ (Dijkstra.ProposalProcedureNetworkIdMismatch account network) = - mconcat [ "kind" .= String "ProposalProcedureNetworkIdMismatch" - , "rewardAccount" .= toJSON account - , "expectedNetworkId" .= toJSON network - ] - forMachine _ (Dijkstra.TreasuryWithdrawalsNetworkIdMismatch accounts network) = - mconcat [ "kind" .= String "TreasuryWithdrawalsNetworkIdMismatch" - , "rewardAccounts" .= NonEmptySet.toSet accounts - , "expectedNetworkId" .= toJSON network - ] - forMachine _ (Dijkstra.ProposalDepositIncorrect Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "ProposalDepositIncorrect" - , "deposit" .= mismatchSupplied - , "expectedDeposit" .= mismatchExpected - ] - forMachine _ (Dijkstra.DisallowedVoters govActionIdToVoter) = - mconcat [ "kind" .= String "DisallowedVoters" - , "govActionIdToVoter" .= NonEmpty.toList govActionIdToVoter - ] - forMachine _ (Dijkstra.ConflictingCommitteeUpdate creds) = - mconcat [ "kind" .= String "ConflictingCommitteeUpdate" - , "credentials" .= NonEmptySet.toSet creds - ] - forMachine _ (Dijkstra.ExpirationEpochTooSmall credsToEpoch) = - mconcat [ "kind" .= String "ExpirationEpochTooSmall" - , "credentialsToEpoch" .= String (textShow credsToEpoch) - ] - forMachine _ (Dijkstra.InvalidPrevGovActionId proposalProcedure) = - mconcat [ "kind" .= String "InvalidPrevGovActionId" - , "proposalProcedure" .= proposalProcedure - ] - forMachine _ (Dijkstra.VotingOnExpiredGovAction actions) = - mconcat [ "kind" .= String "VotingOnExpiredGovAction" - , "action" .= actions - ] - forMachine _ (Dijkstra.ProposalCantFollow prevGovActionId Mismatch {mismatchSupplied, mismatchExpected}) = - mconcat [ "kind" .= String "ProposalCantFollow" - , "prevGovActionId" .= prevGovActionId - , "protVer" .= mismatchSupplied - , "prevProtVer" .= mismatchExpected - ] - forMachine _ (Dijkstra.InvalidGuardrailsScriptHash actualScriptHash expectedScriptHash) = - mconcat [ "kind" .= String "InvalidGuardrailsScriptHash" - , "actualGuardrailsScriptHash" .= actualScriptHash - , "expectedGuardrailsScriptHash" .= expectedScriptHash - ] - forMachine _ (Dijkstra.DisallowedProposalDuringBootstrap proposal) = - mconcat [ "kind" .= String "DisallowedProposalDuringBootstrap" - , "proposal" .= proposal - ] - forMachine _ (Dijkstra.DisallowedVotesDuringBootstrap votes) = - mconcat [ "kind" .= String "DisallowedVotesDuringBootstrap" - , "votes" .= votes - ] - forMachine _ (Dijkstra.VotersDoNotExist voters) = - mconcat [ "kind" .= String "VotersDoNotExist" - , "voters" .= NonEmpty.toList voters - ] - forMachine _ (Dijkstra.ZeroTreasuryWithdrawals govAction) = - mconcat [ "kind" .= String "ZeroTreasuryWithdrawals" - , "govAction" .= govAction - ] - forMachine _ (Dijkstra.ProposalReturnAccountDoesNotExist account) = - mconcat [ "kind" .= String "ProposalReturnAccountDoesNotExist" - , "invalidAccount" .= account - ] - forMachine _ (Dijkstra.TreasuryWithdrawalReturnAccountsDoNotExist accounts) = - mconcat [ "kind" .= String "TreasuryWithdrawalReturnAccountsDoNotExist" - , "invalidAccounts" .= NonEmpty.toList accounts - ] - forMachine _ (Dijkstra.UnelectedCommitteeVoters voters) = - mconcat [ "kind" .= String "UnelectedCommitteeVoters" - , "unelectedCommitteeVoters" .= NonEmpty.toList voters - ] - -instance LogFormatting (Dijkstra.DijkstraGovCertPredFailure era) where - forMachine _dtal = mconcat . \case - Dijkstra.DijkstraDRepAlreadyRegistered credential -> - [ "kind" .= String "DijkstraDRepAlreadyRegistered" - , "credential" .= String (textShow credential) - , "error" .= String "DRep is already registered" - ] - Dijkstra.DijkstraDRepNotRegistered credential -> - [ "kind" .= String "DijkstraDRepNotRegistered" - , "credential" .= String (textShow credential) - , "error" .= String "DRep is not registered" - ] - Dijkstra.DijkstraDRepIncorrectDeposit Mismatch {mismatchSupplied, mismatchExpected} -> - [ "kind" .= String "DijkstraDRepIncorrectDeposit" - , "givenCoin" .= mismatchSupplied - , "expectedCoin" .= mismatchExpected - , "error" .= String "DRep registration has incorrect deposit amount" - ] - Dijkstra.DijkstraCommitteeHasPreviouslyResigned coldCred -> - [ "kind" .= String "DijkstraCommitteeHasPreviouslyResigned" - , "credential" .= String (textShow coldCred) - , "error" .= String "Committee member has previously resigned" - ] - Dijkstra.DijkstraDRepIncorrectRefund Mismatch {mismatchSupplied, mismatchExpected} -> - [ "kind" .= String "DijkstraDRepIncorrectRefund" - , "givenRefund" .= mismatchSupplied - , "expectedRefund" .= mismatchExpected - , "error" .= String "Refund amount is incorrect" - ] - Dijkstra.DijkstraCommitteeIsUnknown coldCred -> - [ "kind" .= String "DijkstraCommitteeIsUnknown" - , "credential" .= String (textShow coldCred) - , "error" .= String "Committee member is unknown" - ] - -instance - ( Ledger.Era era - , Show (PredicateFailure (Ledger.EraRule "LEDGERS" era)) - ) => LogFormatting (Dijkstra.DijkstraBbodyPredFailure era) where - forMachine _ err = mconcat [ "kind" .= String "DijkstraBbodyPredFail" - , "error" .= String (textShow err) - ] - -instance - ( Api.ShelleyLedgerEra era ~ ledgerera - , Api.IsShelleyBasedEra era - , Consensus.ShelleyBasedEra ledgerera - , LogFormatting (PredicateFailure (Ledger.EraRule "UTXOS" ledgerera)) - ) => LogFormatting (Dijkstra.DijkstraUtxoPredFailure ledgerera) where - forMachine dtal = \case - Dijkstra.UtxosFailure utxosPredFailure -> forMachine dtal utxosPredFailure - Dijkstra.BadInputsUTxO badInputs -> - mconcat [ "kind" .= String "BadInputsUTxO" - , "badInputs" .= NonEmptySet.toSet badInputs - , "error" .= renderBadInputsUTxOErr (NonEmptySet.toSet badInputs) - ] - Dijkstra.OutsideValidityIntervalUTxO validityInterval slot -> - mconcat [ "kind" .= String "ExpiredUTxO" - , "validityInterval" .= validityInterval - , "slot" .= slot - ] - Dijkstra.MaxTxSizeUTxO Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "MaxTxSizeUTxO" - , "size" .= mismatchSupplied - , "maxSize" .= mismatchExpected - ] - Dijkstra.InputSetEmptyUTxO -> - mconcat [ "kind" .= String "InputSetEmptyUTxO" ] - Dijkstra.FeeTooSmallUTxO Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "FeeTooSmallUTxO" - , "minimum" .= mismatchExpected - , "fee" .= mismatchSupplied - ] - Dijkstra.ValueNotConservedUTxO Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "ValueNotConservedUTxO" - , "consumed" .= mismatchSupplied - , "produced" .= mismatchExpected - , "error" .= renderValueNotConservedErr mismatchSupplied mismatchExpected - ] - Dijkstra.WrongNetwork network addrs -> - mconcat [ "kind" .= String "WrongNetwork" - , "network" .= network - , "addrs" .= NonEmptySet.toSet addrs - ] - Dijkstra.OutputBootAddrAttrsTooBig badOutputs -> - mconcat [ "kind" .= String "OutputBootAddrAttrsTooBig" - , "outputs" .= badOutputs - , "error" .= String "The Byron address attributes are too big" - ] - Dijkstra.OutputTooBigUTxO badOutputs -> - mconcat [ "kind" .= String "OutputTooBigUTxO" - , "outputs" .= badOutputs - , "error" .= String "The tokens in the tx output take up too much space" - ] - Dijkstra.InsufficientCollateral computedBalance suppliedFee -> - mconcat [ "kind" .= String "InsufficientCollateral" - , "balance" .= computedBalance - , "txfee" .= suppliedFee - ] - Dijkstra.ScriptsNotPaidUTxO utxos -> - mconcat [ "kind" .= String "ScriptsNotPaidUTxO" - , "utxos" .= String (textShow utxos) - ] - Dijkstra.ExUnitsTooBigUTxO Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "ExUnitsTooBigUTxO" - , "maxexunits" .= mismatchExpected - , "exunits" .= mismatchSupplied - ] - Dijkstra.CollateralContainsNonADA inputs -> - mconcat [ "kind" .= String "CollateralContainsNonADA" - , "inputs" .= inputs - ] - Dijkstra.WrongNetworkInTxBody Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "WrongNetworkInTxBody" - , "networkid" .= mismatchExpected - , "txbodyNetworkId" .= mismatchSupplied - ] - Dijkstra.OutsideForecast slotNum -> - mconcat [ "kind" .= String "OutsideForecast" - , "slot" .= slotNum - ] - Dijkstra.TooManyCollateralInputs Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "TooManyCollateralInputs" - , "max" .= mismatchExpected - , "inputs" .= mismatchSupplied - ] - Dijkstra.NoCollateralInputs -> - mconcat [ "kind" .= String "NoCollateralInputs" ] - Dijkstra.IncorrectTotalCollateralField provided declared -> - mconcat [ "kind" .= String "UnequalCollateralReturn" - , "collateralProvided" .= provided - , "collateralDeclared" .= declared - ] - Dijkstra.BabbageOutputTooSmallUTxO outputs -> - mconcat [ "kind" .= String "BabbageOutputTooSmall" - , "outputs" .= outputs - ] - Dijkstra.BabbageNonDisjointRefInputs nonDisjointInputs -> - mconcat [ "kind" .= String "BabbageNonDisjointRefInputs" - , "outputs" .= nonDisjointInputs - ] - Dijkstra.PtrPresentInCollateralReturn output -> - mconcat [ "kind" .= String "PtrPresentInCollateralReturn" - , "output" .= output - ] - Dijkstra.WithdrawalsExceedAccountBalance accounts -> - mconcat [ "kind" .= String "WithdrawalsExceedAccountBalance" - , "accounts" .= String (textShow accounts) - ] - -instance - ( Api.ShelleyLedgerEra era ~ ledgerera - , Api.IsShelleyBasedEra era - , Consensus.ShelleyBasedEra ledgerera - , LogFormatting (PredicateFailure (Ledger.EraRule "UTXO" ledgerera)) - ) => LogFormatting (Dijkstra.DijkstraUtxowPredFailure ledgerera) where - forMachine dtal = \case - Dijkstra.UtxoFailure utxoPredFail -> forMachine dtal utxoPredFail - Dijkstra.InvalidWitnessesUTXOW ws -> - mconcat [ "kind" .= String "InvalidWitnessesUTXOW" - , "invalidWitnesses" .= map textShow (NonEmpty.toList ws) - ] - Dijkstra.MissingVKeyWitnessesUTXOW ws -> - mconcat [ "kind" .= String "MissingVKeyWitnessesUTXOW" - , "missingWitnesses" .= NonEmptySet.toSet ws - ] - Dijkstra.MissingScriptWitnessesUTXOW scripts -> - mconcat [ "kind" .= String "MissingScriptWitnessesUTXOW" - , "missingScripts" .= NonEmptySet.toSet scripts - ] - Dijkstra.ScriptWitnessNotValidatingUTXOW failedScripts -> - mconcat [ "kind" .= String "ScriptWitnessNotValidatingUTXOW" - , "failedScripts" .= NonEmptySet.toSet failedScripts - ] - Dijkstra.MissingTxBodyMetadataHash hash -> - mconcat [ "kind" .= String "MissingTxMetadata" - , "txBodyMetadataHash" .= hash - ] - Dijkstra.MissingTxMetadata hash -> - mconcat [ "kind" .= String "MissingTxMetadata" - , "txBodyMetadataHash" .= hash - ] - Dijkstra.ConflictingMetadataHash Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "ConflictingMetadataHash" - , "txBodyMetadataHash" .= mismatchSupplied - , "fullMetadataHash" .= mismatchExpected - ] - Dijkstra.InvalidMetadata -> - mconcat [ "kind" .= String "InvalidMetadata" - ] - Dijkstra.ExtraneousScriptWitnessesUTXOW scripts -> - mconcat [ "kind" .= String "InvalidWitnessesUTXOW" - , "extraneousScripts" .= Set.map renderScriptHash (NonEmptySet.toSet scripts) - ] - Dijkstra.MissingRedeemers scripts -> - mconcat [ "kind" .= String "MissingRedeemers" - , "scripts" .= renderMissingRedeemers Api.shelleyBasedEra scripts - ] - Dijkstra.MissingRequiredDatums required received -> - mconcat [ "kind" .= String "MissingRequiredDatums" - , "required" .= map (Crypto.hashToTextAsHex . Hashes.extractHash) - (NonEmptySet.toList required) - , "received" .= map (Crypto.hashToTextAsHex . Hashes.extractHash) - (Set.toList received) - ] - Dijkstra.NotAllowedSupplementalDatums disallowed acceptable -> - mconcat [ "kind" .= String "NotAllowedSupplementalDatums" - , "disallowed" .= NonEmptySet.toList disallowed - , "acceptable" .= Set.toList acceptable - ] - Dijkstra.PPViewHashesDontMatch Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "PPViewHashesDontMatch" - , "fromTxBody" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchSupplied) - , "fromPParams" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchExpected) - ] - Dijkstra.UnspendableUTxONoDatumHash ins -> - mconcat [ "kind" .= String "MissingRequiredSigners" - , "txins" .= NonEmptySet.toList ins - ] - Dijkstra.ExtraRedeemers rs -> - Api.forEraInEon - (Api.toCardanoEra Api.shelleyBasedEra) - mempty - (\alonzoOnwards -> - mconcat - [ "kind" .= String "ExtraRedeemers" - , "rdmrs" .= map (Api.toScriptIndex alonzoOnwards) (NonEmpty.toList rs) - ] - ) - Dijkstra.MalformedScriptWitnesses scripts -> - mconcat [ "kind" .= String "MalformedScriptWitnesses" - , "scripts" .= NonEmptySet.toSet scripts - ] - Dijkstra.MalformedReferenceScripts scripts -> - mconcat [ "kind" .= String "MalformedReferenceScripts" - , "scripts" .= NonEmptySet.toSet scripts - ] - Dijkstra.ScriptIntegrityHashMismatch Mismatch {mismatchSupplied, mismatchExpected} mBytes -> - mconcat [ "kind" .= String "ScriptIntegrityHashMismatch" - , "supplied" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchSupplied) - , "expected" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchExpected) - , "hashHexPreimage" .= formatAsHex (strictMaybeToMaybe mBytes) - ] - Dijkstra.MissingRequiredGuards guards -> - mconcat [ "kind" .= String "MissingRequiredGuards" - , "guards" .= map textShow (NonEmptySet.toList guards) - ] - Dijkstra.MalformedGuardDatums guards -> - mconcat [ "kind" .= String "MalformedGuardDatums" - , "guards" .= map textShow (NonEmptySet.toList guards) - ] - -instance - ( Ledger.Crypto crypto - ) => LogFormatting (Praos.PraosValidationErr crypto) where - forMachine _ err' = - case err' of - Praos.VRFKeyUnknown unknownKeyHash -> - mconcat [ "kind" .= String "VRFKeyUnknown" - , "vrfKey" .= unknownKeyHash - ] - Praos.VRFKeyWrongVRFKey stakePoolKeyHash registeredVrfForSaidStakepool wrongKeyHashInBlockHeader -> - mconcat [ "kind" .= String "VRFKeyWrongVRFKey" - , "stakePoolKeyHash" .= stakePoolKeyHash - , "stakePoolVrfKey" .= registeredVrfForSaidStakepool - , "blockHeaderVrfKey" .= wrongKeyHashInBlockHeader - ] - Praos.VRFKeyBadProof slotNo nonce vrfCalculatedVal-> - mconcat [ "kind" .= String "VRFKeyBadProof" - , "slotNumberUsedInVrfCalculation" .= slotNo - , "nonceUsedInVrfCalculation" .= nonce - , "calculatedVrfValue" .= String (textShow vrfCalculatedVal) - ] - Praos.VRFLeaderValueTooBig leaderValue sigma f-> - mconcat [ "kind" .= String "VRFLeaderValueTooBig" - , "leaderValue" .= leaderValue - , "sigma" .= sigma - , "f" .= activeSlotLog f - ] - Praos.KESBeforeStartOCERT startKesPeriod currKesPeriod -> - mconcat [ "kind" .= String "KESBeforeStartOCERT" - , "opCertStartingKesPeriod" .= kesPeriodValue startKesPeriod - , "currentKesPeriod" .= kesPeriodValue currKesPeriod - ] - Praos.KESAfterEndOCERT currKesPeriod startKesPeriod maxKesKeyEvos -> - mconcat [ "kind" .= String "KESAfterEndOCERT" - , "opCertStartingKesPeriod" .= kesPeriodValue startKesPeriod - , "currentKesPeriod" .= kesPeriodValue currKesPeriod - , "maxKesKeyEvolutions" .= maxKesKeyEvos - ] - Praos.CounterTooSmallOCERT lastCounter currentCounter -> - mconcat [ "kind" .= String "CounterTooSmallOCERT" - , "lastCounter" .= lastCounter - , "currentCounter" .= currentCounter - ] - Praos.CounterOverIncrementedOCERT lastCounter currentCounter -> - mconcat [ "kind" .= String "CounterOverIncrementedOCERT" - , "lastCounter" .= lastCounter - , "currentCounter" .= currentCounter - ] - Praos.InvalidSignatureOCERT counter oCertStartKesPeriod err -> - mconcat [ "kind" .= String "InvalidSignatureOCERT" - , "counter" .= counter - , "opCertStartingKesPeriod" .= kesPeriodValue oCertStartKesPeriod - , "error" .= err - ] - Praos.InvalidKesSignatureOCERT currentKesPeriod opCertStartKesPeriod expectedKesEvos maxKesEvos err -> - mconcat [ "kind" .= String "InvalidKesSignatureOCERT" - , "currentKesPeriod" .= currentKesPeriod - , "opCertStartingKesPeriod" .= opCertStartKesPeriod - , "expectedKesEvolutions" .= expectedKesEvos - , "maximumKesEvos" .= maxKesEvos - , "error" .= err - ] - Praos.NoCounterForKeyHashOCERT stakePoolKeyHash-> - mconcat [ "kind" .= String "NoCounterForKeyHashOCERT" - , "stakePoolKeyHash" .= stakePoolKeyHash - ] - -instance LogFormatting (Praos.PraosCannotForge crypto) where - forMachine _ (Praos.PraosCannotForgeKeyNotUsableYet currentKesPeriod startingKesPeriod) = - mconcat [ "kind" .= String "PraosCannotForgeKeyNotUsableYet" - , "currentKesPeriod" .= kesPeriodValue currentKesPeriod - , "opCertStartingKesPeriod" .= kesPeriodValue startingKesPeriod - ] - -instance LogFormatting Praos.EnvelopeError where - forMachine _ err' = - case err' of - Praos.ObsoleteNode maxPtclVersionFromPparams blkHeaderPtclVersion -> - mconcat [ "kind" .= String "ObsoleteNode" - , "maxMajorProtocolVersion" .= maxPtclVersionFromPparams - , "headerProtocolVersion" .= blkHeaderPtclVersion - ] - Praos.HeaderSizeTooLarge headerSize ledgerViewMaxHeaderSize -> - mconcat [ "kind" .= String "HeaderSizeTooLarge" - , "maxHeaderSize" .= ledgerViewMaxHeaderSize - , "headerSize" .= headerSize - ] - Praos.BlockSizeTooLarge blockSize ledgerViewMaxBlockSize -> - mconcat [ "kind" .= String "BlockSizeTooLarge" - , "maxBlockSize" .= ledgerViewMaxBlockSize - , "blockSize" .= blockSize - ] - -instance - ( ToJSON (Alonzo.CollectError ledgerera) - ) => LogFormatting (Conway.ConwayUtxosPredFailure ledgerera) where - forMachine _ (Conway.ValidationTagMismatch isValidating reason) = - mconcat [ "kind" .= String "ValidationTagMismatch" - , "isvalidating" .= isValidating - , "reason" .= reason - ] - forMachine _ (Conway.CollectErrors errors) = - mconcat [ "kind" .= String "CollectErrors" - , "errors" .= errors - ] - --- We define this bogus instance as it is required by some of the --- 'LogFormatting' instances in this module -instance LogFormatting (Ledger.VoidEraRule rule era) where - -- NOTE: There are no values of type 'Ledger.VoidEraRule rule era' - forMachine _ = \case - -instance - ( Api.ShelleyLedgerEra era ~ ledgerera - , Api.IsShelleyBasedEra era - , Consensus.ShelleyBasedEra ledgerera - , LogFormatting (PredicateFailure (Ledger.EraRule "UTXOS" ledgerera)) - ) => LogFormatting (Conway.ConwayUtxoPredFailure ledgerera) where - forMachine dtal = \case - Conway.UtxosFailure utxosPredFailure -> forMachine dtal utxosPredFailure - Conway.BadInputsUTxO badInputs -> - mconcat [ "kind" .= String "BadInputsUTxO" - , "badInputs" .= NonEmptySet.toSet badInputs - , "error" .= renderBadInputsUTxOErr (NonEmptySet.toSet badInputs) - ] - Conway.OutsideValidityIntervalUTxO validityInterval slot -> - mconcat [ "kind" .= String "ExpiredUTxO" - , "validityInterval" .= validityInterval - , "slot" .= slot - ] - Conway.MaxTxSizeUTxO Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "MaxTxSizeUTxO" - , "size" .= mismatchSupplied - , "maxSize" .= mismatchExpected - ] - Conway.InputSetEmptyUTxO -> - mconcat [ "kind" .= String "InputSetEmptyUTxO" ] - Conway.FeeTooSmallUTxO Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "FeeTooSmallUTxO" - , "minimum" .= mismatchExpected - , "fee" .= mismatchSupplied - ] - Conway.ValueNotConservedUTxO Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "ValueNotConservedUTxO" - , "consumed" .= mismatchSupplied - , "produced" .= mismatchExpected - , "error" .= renderValueNotConservedErr mismatchSupplied mismatchExpected - ] - Conway.WrongNetwork network addrs -> - mconcat [ "kind" .= String "WrongNetwork" - , "network" .= network - , "addrs" .= addrs - ] - Conway.WrongNetworkWithdrawal network addrs -> - mconcat [ "kind" .= String "WrongNetworkWithdrawal" - , "network" .= network - , "addrs" .= addrs - ] - Conway.OutputTooSmallUTxO badOutputs -> - mconcat [ "kind" .= String "OutputTooSmallUTxO" - , "outputs" .= badOutputs - , "error" .= String - ( mconcat - [ "The output is smaller than the allow minimum " - , "UTxO value defined in the protocol parameters" - ] - ) - ] - Conway.OutputBootAddrAttrsTooBig badOutputs -> - mconcat [ "kind" .= String "OutputBootAddrAttrsTooBig" - , "outputs" .= badOutputs - , "error" .= String "The Byron address attributes are too big" - ] - Conway.OutputTooBigUTxO badOutputs -> - mconcat [ "kind" .= String "OutputTooBigUTxO" - , "outputs" .= badOutputs - , "error" .= String "Too many asset ids in the tx output" - ] - Conway.InsufficientCollateral computedBalance suppliedFee -> - mconcat [ "kind" .= String "InsufficientCollateral" - , "balance" .= computedBalance - , "txfee" .= suppliedFee - ] - Conway.ScriptsNotPaidUTxO utxos -> - mconcat [ "kind" .= String "ScriptsNotPaidUTxO" - , "utxos" .= utxos - ] - Conway.ExUnitsTooBigUTxO Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "ExUnitsTooBigUTxO" - , "maxexunits" .= mismatchExpected - , "exunits" .= mismatchSupplied - ] - Conway.CollateralContainsNonADA inputs -> - mconcat [ "kind" .= String "CollateralContainsNonADA" - , "inputs" .= inputs - ] - Conway.WrongNetworkInTxBody Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "WrongNetworkInTxBody" - , "networkid" .= mismatchExpected - , "txbodyNetworkId" .= mismatchSupplied - ] - Conway.OutsideForecast slotNum -> - mconcat [ "kind" .= String "OutsideForecast" - , "slot" .= slotNum - ] - Conway.TooManyCollateralInputs Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "TooManyCollateralInputs" - , "max" .= mismatchExpected - , "inputs" .= mismatchSupplied - ] - Conway.NoCollateralInputs -> - mconcat [ "kind" .= String "NoCollateralInputs" ] - Conway.IncorrectTotalCollateralField provided declared -> - mconcat [ "kind" .= String "UnequalCollateralReturn" - , "collateralProvided" .= provided - , "collateralDeclared" .= declared - ] - Conway.BabbageOutputTooSmallUTxO outputs -> - mconcat [ "kind" .= String "BabbageOutputTooSmall" - , "outputs" .= outputs - ] - Conway.BabbageNonDisjointRefInputs nonDisjointInputs -> - mconcat [ "kind" .= String "BabbageNonDisjointRefInputs" - , "outputs" .= nonDisjointInputs - ] - -instance - ( Api.ShelleyLedgerEra era ~ ledgerera - , Api.IsShelleyBasedEra era - , Consensus.ShelleyBasedEra ledgerera - , LogFormatting (PredicateFailure (Ledger.EraRule "UTXO" ledgerera)) - ) => LogFormatting (Conway.ConwayUtxowPredFailure ledgerera) where - forMachine dtal = \case - Conway.UtxoFailure utxoPredFail -> forMachine dtal utxoPredFail - Conway.InvalidWitnessesUTXOW ws -> - mconcat [ "kind" .= String "InvalidWitnessesUTXOW" - , "invalidWitnesses" .= map textShow (NonEmpty.toList ws) - ] - Conway.MissingVKeyWitnessesUTXOW ws -> - mconcat [ "kind" .= String "MissingVKeyWitnessesUTXOW" - , "missingWitnesses" .= ws - ] - Conway.MissingScriptWitnessesUTXOW scripts -> - mconcat [ "kind" .= String "MissingScriptWitnessesUTXOW" - , "missingScripts" .= scripts - ] - Conway.ScriptWitnessNotValidatingUTXOW failedScripts -> - mconcat [ "kind" .= String "ScriptWitnessNotValidatingUTXOW" - , "failedScripts" .= failedScripts - ] - Conway.MissingTxBodyMetadataHash hash -> - mconcat [ "kind" .= String "MissingTxMetadata" - , "txBodyMetadataHash" .= hash - ] - Conway.MissingTxMetadata hash -> - mconcat [ "kind" .= String "MissingTxMetadata" - , "txBodyMetadataHash" .= hash - ] - Conway.ConflictingMetadataHash Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "ConflictingMetadataHash" - , "txBodyMetadataHash" .= mismatchSupplied - , "fullMetadataHash" .= mismatchExpected - ] - Conway.InvalidMetadata -> - mconcat [ "kind" .= String "InvalidMetadata" - ] - Conway.ExtraneousScriptWitnessesUTXOW scripts -> - mconcat [ "kind" .= String "InvalidWitnessesUTXOW" - , "extraneousScripts" .= Set.map renderScriptHash (NonEmptySet.toSet scripts) - ] - Conway.MissingRedeemers scripts -> - mconcat [ "kind" .= String "MissingRedeemers" - , "scripts" .= renderMissingRedeemers Api.shelleyBasedEra scripts - ] - Conway.MissingRequiredDatums required received -> - mconcat [ "kind" .= String "MissingRequiredDatums" - , "required" .= map (Crypto.hashToTextAsHex . Hashes.extractHash) - (NonEmptySet.toList required) - , "received" .= map (Crypto.hashToTextAsHex . Hashes.extractHash) - (Set.toList received) - ] - Conway.NotAllowedSupplementalDatums disallowed acceptable -> - mconcat [ "kind" .= String "NotAllowedSupplementalDatums" - , "disallowed" .= NonEmptySet.toList disallowed - , "acceptable" .= Set.toList acceptable - ] - Conway.PPViewHashesDontMatch Mismatch {mismatchSupplied, mismatchExpected} -> - mconcat [ "kind" .= String "PPViewHashesDontMatch" - , "fromTxBody" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchSupplied) - , "fromPParams" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchExpected) - ] - Conway.UnspendableUTxONoDatumHash ins -> - mconcat [ "kind" .= String "MissingRequiredSigners" - , "txins" .= NonEmptySet.toList ins - ] - Conway.ExtraRedeemers rs -> - Api.forEraInEon - (Api.toCardanoEra Api.shelleyBasedEra) - mempty - (\alonzoOnwards -> - mconcat - [ "kind" .= String "ExtraRedeemers" - , "rdmrs" .= map (Api.toScriptIndex alonzoOnwards) (NonEmpty.toList rs) - ] - ) - Conway.MalformedScriptWitnesses scripts -> - mconcat [ "kind" .= String "MalformedScriptWitnesses" - , "scripts" .= scripts - ] - Conway.MalformedReferenceScripts scripts -> - mconcat [ "kind" .= String "MalformedReferenceScripts" - , "scripts" .= scripts - ] - Conway.ScriptIntegrityHashMismatch Mismatch {mismatchSupplied, mismatchExpected} mBytes -> - mconcat [ "kind" .= String "ScriptIntegrityHashMismatch" - , "supplied" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchSupplied) - , "expected" .= renderScriptIntegrityHash (strictMaybeToMaybe mismatchExpected) - , "hashHexPreimage" .= formatAsHex (strictMaybeToMaybe mBytes) - ] - -instance LogFormatting (Praos.PraosTiebreakerView crypto) where - forMachine _dtal Praos.PraosTiebreakerView { - ptvSlotNo - , ptvIssuer - , ptvIssueNo - , ptvTieBreakVRF - } = - mconcat [ "kind" .= String "PraosTiebreakerView" - , "slotNo" .= ptvSlotNo - , "issuerHash" .= hashKey ptvIssuer - , "issueNo" .= ptvIssueNo - , "tieBreakVRF" .= renderVRF ptvTieBreakVRF - ] - where - renderVRF = Text.Encoding.decodeUtf8 . B16.encode . Crypto.getOutputVRFBytes - --------------------------------------------------------------------------------- --- Helper functions --------------------------------------------------------------------------------- - -showLastAppBlockNo :: WithOrigin LastAppliedBlock -> Text -showLastAppBlockNo wOblk = case withOriginToMaybe wOblk of - Nothing -> "Genesis Block" - Just blk -> textShow . unBlockNo $ labBlockNo blk diff --git a/cardano-node/src/Cardano/Node/Tracing/Formatting.hs b/cardano-node/src/Cardano/Node/Tracing/Formatting.hs deleted file mode 100644 index a0c947aca64..00000000000 --- a/cardano-node/src/Cardano/Node/Tracing/Formatting.hs +++ /dev/null @@ -1,84 +0,0 @@ -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeApplications #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE UndecidableInstances #-} - -{-# OPTIONS_GHC -Wno-orphans #-} - -module Cardano.Node.Tracing.Formatting - ( - ) where - -import Cardano.Logging (LogFormatting (..)) -import Cardano.Node.Tracing.Render (renderHeaderHashForDetails) -import Ouroboros.Consensus.Block (ConvertRawHash (..), Header, RealPoint, realPointHash, - realPointSlot) -import qualified Ouroboros.Network.AnchoredFragment as AF -import Ouroboros.Network.Block - -import Data.Aeson (Value (String), toJSON, (.=)) -import Data.Proxy (Proxy (..)) -import Data.Void (Void) - --- | Derives ConvertRawHash for Header blk from ConvertRawHash blk. --- Safe because HeaderHash (Header blk) = HeaderHash blk. -instance ConvertRawHash blk => ConvertRawHash (Header blk) where - type HashSize (Header blk) = HashSize blk - toShortRawHash _ = toShortRawHash (Proxy @blk) - unsafeFromShortRawHash _ = unsafeFromShortRawHash (Proxy @blk) - --- | A bit of a weird one, but needed because some of the very general --- consensus interfaces are sometimes instantiated to 'Void', when there are --- no cases needed. --- -instance LogFormatting Void where - forMachine _dtal _x = mempty - -instance LogFormatting () where - forMachine _dtal _x = mempty - -instance LogFormatting SlotNo where - forMachine _dtal slot = - mconcat [ "kind" .= String "SlotNo" - , "slot" .= toJSON (unSlotNo slot) ] - -instance forall blk. ConvertRawHash blk - => LogFormatting (Point blk) where - forMachine _dtal GenesisPoint = - mconcat - [ "kind" .= String "GenesisPoint" ] - forMachine dtal (BlockPoint slot h) = - mconcat - [ "kind" .= String "BlockPoint" - , "slot" .= toJSON (unSlotNo slot) - , "headerHash" .= renderHeaderHashForDetails (Proxy @blk) dtal h - ] - -instance ConvertRawHash blk - => LogFormatting (RealPoint blk) where - forMachine dtal p = mconcat - [ "kind" .= String "Point" - , "slot" .= unSlotNo (realPointSlot p) - , "hash" .= renderHeaderHashForDetails (Proxy @blk) dtal (realPointHash p) - ] - -instance (ConvertRawHash blk) => LogFormatting (AF.Anchor blk) where - forMachine dtal = \case - AF.AnchorGenesis -> mconcat - [ "kind" .= String "AnchorGenesis" ] - AF.Anchor slot hash bno -> mconcat - [ "kind" .= String "Anchor" - , "slot" .= toJSON (unSlotNo slot) - , "headerHash" .= renderHeaderHashForDetails (Proxy @blk) dtal hash - , "blockNo" .= toJSON (unBlockNo bno) - ] - -instance (ConvertRawHash blk, HasHeader blk) => LogFormatting (AF.AnchoredFragment blk) where - forMachine dtal frag = mconcat - [ "kind" .= String "AnchoredFragment" - , "anchor" .= forMachine dtal (AF.anchor frag) - , "headPoint" .= forMachine dtal (AF.headPoint frag) - , "length" .= toJSON (AF.length frag) - ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Render.hs b/cardano-node/src/Cardano/Node/Tracing/Render.hs deleted file mode 100644 index 0462c48032e..00000000000 --- a/cardano-node/src/Cardano/Node/Tracing/Render.hs +++ /dev/null @@ -1,283 +0,0 @@ -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeApplications #-} - -module Cardano.Node.Tracing.Render - ( renderChunkNo - , renderHeaderHash - , renderHeaderHashForDetails - , renderChainHash - , renderTipBlockNo - , renderTipHash - , condenseT - , showT - , renderPoint - , renderPointAsPhrase - , renderPointForDetails - , renderRealPoint - , renderRealPointAsPhrase - , renderSlotNo - , renderTip - , renderTipForDetails - , renderTxId - , renderTxIdForDetails - , renderWithOrigin - , renderScriptHash - , renderScriptIntegrityHash - , renderScriptPurpose - , renderMissingRedeemers - , renderIncompleteWithdrawals - ) where - -import qualified Cardano.Api as Api - -import qualified Cardano.Crypto.Hash.Class as Crypto -import Cardano.Ledger.Alonzo.Scripts (AlonzoPlutusPurpose (..), AsItem (..), - PlutusPurpose) -import qualified Cardano.Ledger.Alonzo.Tx as Alonzo -import Cardano.Ledger.BaseTypes (Mismatch (..), Relation (..)) -import Cardano.Ledger.Conway.Scripts (ConwayPlutusPurpose (..)) -import qualified Cardano.Ledger.Core as Ledger -import Cardano.Ledger.Dijkstra.Scripts (DijkstraPlutusPurpose (..)) -import qualified Cardano.Ledger.Hashes as Hashes -import Cardano.Logging -import Cardano.Node.Queries (ConvertTxId (..)) -import Cardano.Slotting.Slot (SlotNo (..), WithOrigin (..)) -import Ouroboros.Consensus.Block (BlockNo (..), ConvertRawHash (..), RealPoint (..)) -import Ouroboros.Consensus.Block.Abstract (Point (..)) -import Ouroboros.Consensus.Ledger.SupportsMempool (GenTx, TxId) -import qualified Ouroboros.Consensus.Storage.ImmutableDB.API as ImmDB -import Ouroboros.Consensus.Storage.ImmutableDB.Chunks.Internal (ChunkNo (..)) -import Ouroboros.Consensus.Util.Condense (Condense, condense) -import Ouroboros.Network.Block (ChainHash (..), HeaderHash, StandardHash, Tip, - getTipPoint) - -import Data.Aeson ((.=)) -import qualified Data.Aeson as Aeson -import qualified Data.Aeson.Key as Aeson -import qualified Data.Aeson.Types as Aeson -import qualified Data.ByteString.Base16 as B16 -import Data.List.NonEmpty (NonEmpty) -import qualified Data.List.NonEmpty as NonEmpty -import Data.Map.NonEmpty (NonEmptyMap) -import qualified Data.Map.NonEmpty as NonEmptyMap -import Data.Proxy (Proxy (..)) -import Data.Text (Text) -import qualified Data.Text as Text -import qualified Data.Text.Encoding as Text - - -condenseT :: Condense a => a -> Text -condenseT = Text.pack . condense - -renderChunkNo :: ChunkNo -> Text -renderChunkNo = Text.pack . show . unChunkNo - -renderTipBlockNo :: ImmDB.Tip blk -> Text -renderTipBlockNo = Text.pack . show . unBlockNo . ImmDB.tipBlockNo - -renderTipHash :: StandardHash blk => ImmDB.Tip blk -> Text -renderTipHash tInfo = Text.pack . show $ ImmDB.tipHash tInfo - -renderTxIdForDetails - :: ConvertTxId blk - => DetailLevel - -> TxId (GenTx blk) - -> Text -renderTxIdForDetails dtal = trimHashTextForDetails dtal . renderTxId - -renderTxId :: ConvertTxId blk => TxId (GenTx blk) -> Text -renderTxId = Text.decodeLatin1 . B16.encode . txIdToRawBytes - -renderWithOrigin :: (a -> Text) -> WithOrigin a -> Text -renderWithOrigin _ Origin = "origin" -renderWithOrigin render (At a) = render a - -renderSlotNo :: SlotNo -> Text -renderSlotNo = Text.pack . show . unSlotNo - -renderRealPoint - :: forall blk. - ConvertRawHash blk - => RealPoint blk - -> Text -renderRealPoint (RealPoint slotNo headerHash) = - renderHeaderHash (Proxy @blk) headerHash - <> "@" - <> renderSlotNo slotNo - --- | Render a short phrase describing a 'RealPoint'. --- e.g. "62292d753b2ee7e903095bc5f10b03cf4209f456ea08f55308e0aaab4350dda4 at --- slot 39920" -renderRealPointAsPhrase - :: forall blk. - ConvertRawHash blk - => RealPoint blk - -> Text -renderRealPointAsPhrase (RealPoint slotNo headerHash) = - renderHeaderHash (Proxy @blk) headerHash - <> " at slot " - <> renderSlotNo slotNo - -renderPointForDetails - :: forall blk. - ConvertRawHash blk - => DetailLevel - -> Point blk - -> Text -renderPointForDetails dtal point = - case point of - GenesisPoint -> "genesis (origin)" - BlockPoint slot h -> - renderHeaderHashForDetails (Proxy @blk) dtal h - <> "@" - <> renderSlotNo slot - -renderPoint :: ConvertRawHash blk => Point blk -> Text -renderPoint = renderPointForDetails DDetailed - --- | Render a short phrase describing a 'Point'. --- e.g. "62292d753b2ee7e903095bc5f10b03cf4209f456ea08f55308e0aaab4350dda4 at --- slot 39920" or "genesis (origin)" in the case of a genesis point. -renderPointAsPhrase :: forall blk. ConvertRawHash blk => Point blk -> Text -renderPointAsPhrase point = - case point of - GenesisPoint -> "genesis (origin)" - BlockPoint slot h -> - renderHeaderHash (Proxy @blk) h - <> " at slot " - <> renderSlotNo slot - -renderTipForDetails - :: ConvertRawHash blk - => DetailLevel - -> Tip blk - -> Text -renderTipForDetails dtal = renderPointForDetails dtal . getTipPoint - -renderTip :: ConvertRawHash blk => Tip blk -> Text -renderTip = renderTipForDetails DDetailed - -renderHeaderHashForDetails - :: ConvertRawHash blk - => proxy blk - -> DetailLevel - -> HeaderHash blk - -> Text -renderHeaderHashForDetails p dtal = - trimHashTextForDetails dtal . renderHeaderHash p - - --- | Hex encode and render a 'HeaderHash' as text. -renderHeaderHash :: ConvertRawHash blk => proxy blk -> HeaderHash blk -> Text -renderHeaderHash p = Text.decodeLatin1 . B16.encode . toRawHash p - -renderChainHash :: (HeaderHash blk -> Text) -> ChainHash blk -> Text -renderChainHash _ GenesisHash = "GenesisHash" -renderChainHash p (BlockHash hash) = p hash - -trimHashTextForDetails :: DetailLevel -> Text -> Text -trimHashTextForDetails dtal = - case dtal of - DMinimal -> Text.take 7 - _ -> id - -renderScriptIntegrityHash :: Maybe Alonzo.ScriptIntegrityHash -> Aeson.Value -renderScriptIntegrityHash (Just witPPDataHash) = - Aeson.String . Crypto.hashToTextAsHex $ Hashes.extractHash witPPDataHash -renderScriptIntegrityHash Nothing = Aeson.Null - - -renderMissingRedeemers :: forall era. () - => Api.ShelleyBasedEra era - -> NonEmpty (PlutusPurpose AsItem (Api.ShelleyLedgerEra era), Ledger.ScriptHash) - -> Aeson.Value -renderMissingRedeemers sbe scripts = Aeson.object $ NonEmpty.toList $ NonEmpty.map renderTuple scripts - where - renderTuple :: () - => (PlutusPurpose AsItem (Api.ShelleyLedgerEra era), Ledger.ScriptHash) - -> Aeson.Pair - renderTuple (scriptPurpose, sHash) = - Aeson.fromText (renderScriptHash sHash) .= renderScriptPurpose sbe scriptPurpose - -renderIncompleteWithdrawals :: forall payload. Show payload - => NonEmptyMap Ledger.AccountAddress (Mismatch RelEQ payload) - -> Aeson.Value -renderIncompleteWithdrawals payload = - Aeson.object $ map renderTuple $ NonEmptyMap.toList payload - where - renderTuple :: (Ledger.AccountAddress, Mismatch RelEQ payload) -> Aeson.Pair - renderTuple (address, mismatch) = - Aeson.fromText (Api.serialiseAddress $ Api.fromShelleyStakeAddr address) .= show mismatch - -renderScriptHash :: Ledger.ScriptHash -> Text -renderScriptHash = Api.serialiseToRawBytesHexText . Api.fromShelleyScriptHash - -renderScriptPurpose :: () - => Api.ShelleyBasedEra era - -> PlutusPurpose AsItem (Api.ShelleyLedgerEra era) - -> Aeson.Value -renderScriptPurpose sbe = - Api.forEraInEon - (Api.toCardanoEra sbe) - (const Aeson.Null) - (\case - Api.AlonzoEraOnwardsAlonzo -> renderAlonzoPlutusPurpose - Api.AlonzoEraOnwardsBabbage -> renderAlonzoPlutusPurpose - Api.AlonzoEraOnwardsConway -> renderConwayPlutusPurpose - Api.AlonzoEraOnwardsDijkstra -> renderDijkstraPlutusPurpose - ) - -renderAlonzoPlutusPurpose :: () - => Aeson.ToJSON (Ledger.TxCert era) - => AlonzoPlutusPurpose AsItem era - -> Aeson.Value -renderAlonzoPlutusPurpose = \case - AlonzoSpending (AsItem txin) -> - Aeson.object ["spending" .= Api.fromShelleyTxIn txin] - AlonzoMinting pid -> - Aeson.object ["minting" .= Aeson.toJSON pid] - AlonzoWithdrawing (AsItem rwdAcct) -> - Aeson.object ["withdrawing" .= Aeson.String (Api.serialiseAddress $ Api.fromShelleyStakeAddr rwdAcct)] - AlonzoCertifying cert -> - Aeson.object ["certifying" .= Aeson.toJSON cert] - -renderConwayPlutusPurpose :: () - => (Ledger.EraPParams era, Aeson.ToJSON (Ledger.TxCert era)) - => ConwayPlutusPurpose AsItem era - -> Aeson.Value -renderConwayPlutusPurpose = \case - ConwaySpending (AsItem txin) -> - Aeson.object ["spending" .= Api.fromShelleyTxIn txin] - ConwayMinting pid -> - Aeson.object ["minting" .= Aeson.toJSON pid] - ConwayWithdrawing (AsItem rwdAcct) -> - Aeson.object ["withdrawing" .= Aeson.String (Api.serialiseAddress $ Api.fromShelleyStakeAddr rwdAcct)] - ConwayCertifying cert -> - Aeson.object ["certifying" .= Aeson.toJSON cert] - ConwayVoting voter -> - Aeson.object ["voting" .= Aeson.toJSON voter] - ConwayProposing proposal -> - Aeson.object ["proposing" .= Aeson.toJSON proposal] - -renderDijkstraPlutusPurpose :: () - => (Ledger.EraPParams era, Aeson.ToJSON (Ledger.TxCert era)) - => DijkstraPlutusPurpose AsItem era - -> Aeson.Value -renderDijkstraPlutusPurpose = \case - DijkstraSpending (AsItem txin) -> - Aeson.object ["spending" .= Api.fromShelleyTxIn txin] - DijkstraMinting pid -> - Aeson.object ["minting" .= Aeson.toJSON pid] - DijkstraWithdrawing (AsItem rwdAcct) -> - Aeson.object ["withdrawing" .= Aeson.String (Api.serialiseAddress $ Api.fromShelleyStakeAddr rwdAcct)] - DijkstraCertifying cert -> - Aeson.object ["certifying" .= Aeson.toJSON cert] - DijkstraVoting voter -> - Aeson.object ["voting" .= Aeson.toJSON voter] - DijkstraProposing proposal -> - Aeson.object ["proposing" .= Aeson.toJSON proposal] - DijkstraGuarding sHash -> - Aeson.object ["guarding" .= Aeson.toJSON sHash] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers.hs index fe9f4a279f6..9d131d4ef89 100644 --- a/cardano-node/src/Cardano/Node/Tracing/Tracers.hs +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers.hs @@ -27,13 +27,8 @@ import Cardano.Node.Queries (NodeKernelData) import Cardano.Node.TraceConstraints import Cardano.Node.Tracing import Cardano.Node.Tracing.Consistency (checkNodeTraceConfiguration') -import Cardano.Node.Tracing.Formatting () import qualified Cardano.Node.Tracing.StateRep as SR -import Cardano.Node.Tracing.Tracers.BlockReplayProgress -import Cardano.Node.Tracing.Tracers.ChainDB -import Cardano.Node.Tracing.Tracers.Consensus import Cardano.Node.Tracing.Tracers.ForgingStats (ForgingStateVar, calcForgeStats) -import Cardano.Node.Tracing.Tracers.KESInfo import Cardano.Node.Tracing.Tracers.LedgerMetrics () import Cardano.Node.Tracing.Tracers.NodeToClient () import Cardano.Node.Tracing.Tracers.NodeToNode () @@ -52,6 +47,7 @@ import qualified Ouroboros.Consensus.Node.Run as Consensus import qualified Ouroboros.Consensus.Node.Tracers as Consensus import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB import qualified Ouroboros.Consensus.Storage.LedgerDB as LedgerDB +import Ouroboros.Consensus.Tracing import Ouroboros.Network.Block import qualified Ouroboros.Network.BlockFetch.ClientState as BlockFetch import Ouroboros.Network.ConnectionId (ConnectionId) @@ -65,7 +61,6 @@ import Network.Mux.Trace (TraceLabelPeer (..)) import qualified Network.Mux.Trace as Mux import Network.Mux.Tracing () - -- | Construct tracers for all system components. -- mkDispatchTracers @@ -376,6 +371,16 @@ mkConsensusTracers configReflection trBase trForward mbTrEKG _trDataPoint trConf ["Peras", "Vote", "Outbound"] configureTracers configReflection trConfig [txPerasVoteOut] + !perasCertInclusionTr <- mkCardanoTracer + trBase trForward mbTrEKG + ["Peras", "Cert", "Inclusion"] + configureTracers configReflection trConfig [perasCertInclusionTr] + + !perasVoteForgingTr <- mkCardanoTracer + trBase trForward mbTrEKG + ["Peras", "Vote", "Forging"] + configureTracers configReflection trConfig [perasVoteForgingTr] + pure $ Consensus.Tracers { Consensus.chainSyncClientTracer = mkTracer $ traceWith chainSyncClientTr @@ -428,10 +433,18 @@ mkConsensusTracers configReflection trBase trForward mbTrEKG _trDataPoint trConf traceWith txLogicTracer , Consensus.txCountersTracer = mkTracer $ traceWith txCountersTracer - , Consensus.perasCertDiffusionInboundTracer = mkTracer $ traceWith txPerasCertIn - , Consensus.perasCertDiffusionOutboundTracer = mkTracer $ traceWith txPerasCertOut - , Consensus.perasVoteDiffusionInboundTracer = mkTracer $ traceWith txPerasVoteIn - , Consensus.perasVoteDiffusionOutboundTracer = mkTracer $ traceWith txPerasVoteOut + , Consensus.perasCertDiffusionInboundTracer = mkTracer $ + traceWith txPerasCertIn + , Consensus.perasCertDiffusionOutboundTracer = mkTracer $ + traceWith txPerasCertOut + , Consensus.perasVoteDiffusionInboundTracer = mkTracer $ + traceWith txPerasVoteIn + , Consensus.perasVoteDiffusionOutboundTracer = mkTracer $ + traceWith txPerasVoteOut + , Consensus.perasCertInclusionTracer = mkTracer $ + traceWith perasCertInclusionTr + , Consensus.perasVoteForgingTracer = mkTracer $ + traceWith perasVoteForgingTr } mkNodeToClientTracers :: forall blk. @@ -741,7 +754,7 @@ mkDiffusionTracers configReflection trBase trForward mbTrEKG _trDataPoint trConf traceWith localInboundGovernorTr , Diffusion.dtInboundGovernorTransitionTracer = mkTracer $ traceWith inboundGovernorTransitionsTr - , Diffusion.dtLocalConnectionManagerTracer = mkTracer $ + , Diffusion.dtLocalConnectionManagerTracer = mkTracer $ traceWith localConnectionManagerTr , Diffusion.dtLocalServerTracer = mkTracer $ traceWith localServerTr diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/BlockReplayProgress.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/BlockReplayProgress.hs deleted file mode 100644 index 209d1e633ac..00000000000 --- a/cardano-node/src/Cardano/Node/Tracing/Tracers/BlockReplayProgress.hs +++ /dev/null @@ -1,121 +0,0 @@ -{-# LANGUAGE BangPatterns #-} -{-# LANGUAGE RecordWildCards #-} -{-# LANGUAGE TupleSections #-} - -module Cardano.Node.Tracing.Tracers.BlockReplayProgress - ( withReplayedBlock - , ReplayBlockStats(..) - ) where - -import Cardano.Api (textShow) - -import Cardano.Logging -import Ouroboros.Consensus.Block (SlotNo, realPointSlot) -import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB -import qualified Ouroboros.Consensus.Storage.LedgerDB as LedgerDB -import Ouroboros.Network.Block (pointSlot, unSlotNo) -import Ouroboros.Network.Point (withOrigin) - -import Control.Concurrent.MVar -import Data.Aeson (Value (String), (.=)) -import Data.Text (pack) -import Numeric (showFFloat) - - -newtype ReplayBlockState = ReplayBlockState - { -- | Last slot for which a `ReplayBlockStats` message has been issued. - rpsLastSlot :: Maybe SlotNo - } - -data ReplayBlockStats = ReplayBlockStats - { rpsCurSlot :: SlotNo - , rpsGoalSlot :: SlotNo - } - -initialReplayBlockState :: ReplayBlockState -initialReplayBlockState = ReplayBlockState {rpsLastSlot = Nothing} - -progressForMachine :: ReplayBlockStats -> Double -progressForMachine (ReplayBlockStats curSlot goalSlot) = - (fromIntegral (unSlotNo curSlot) * 100.0) / fromIntegral (unSlotNo $ max curSlot goalSlot) - -progressForHuman :: ReplayBlockStats -> Double -progressForHuman = round2 . progressForMachine where - round2 :: Double -> Double - round2 num = - let - f :: Int - f = round $ num * 100 - in fromIntegral f / 100 - --------------------------------------------------------------------------------- --- ReplayBlockStats Tracer --------------------------------------------------------------------------------- - -instance LogFormatting ReplayBlockStats where - forMachine _ stats = - mconcat - [ "kind" .= String "ReplayBlockStats" - , "progress" .= String (pack $ show $ progressForMachine stats) - ] - - forHuman stats@ReplayBlockStats {..} = - "Replayed block: slot " - <> textShow (unSlotNo rpsCurSlot) - <> " out of " - <> textShow (unSlotNo rpsGoalSlot) - <> ". Progress: " - <> pack (showFFloat (Just 2) (progressForHuman stats) mempty) - <> "%" - - asMetrics stats = - [DoubleM "blockReplayProgress" (progressForMachine stats)] - -instance MetaTrace ReplayBlockStats where - namespaceFor ReplayBlockStats {} = Namespace [] ["LedgerReplay"] - - severityFor (Namespace _ ["LedgerReplay"]) _ = Just Info - severityFor _ _ = Nothing - - documentFor (Namespace _ ["LedgerReplay"]) = Just - "Counts block replays and calculates the percent." - documentFor _ = Nothing - - metricsDocFor (Namespace _ ["LedgerReplay"]) = - [("blockReplayProgress", "Progress in percent")] - metricsDocFor _ = [] - - allNamespaces = - [ Namespace [] ["LedgerReplay"] - ] - -withReplayedBlock :: Trace IO ReplayBlockStats - -> IO (Trace IO (ChainDB.TraceEvent blk)) -withReplayedBlock tr = do - var <- newMVar initialReplayBlockState - contramapMCond tr (process var) - where - process :: MVar ReplayBlockState - -> (LoggingContext, Either TraceControl (ChainDB.TraceEvent blk)) - -> IO (Maybe (LoggingContext, Either TraceControl ReplayBlockStats)) - process var (ctx, Right msg) = modifyMVar var $ \st -> do - let !(!st', mbStats) = mbProduceBlockStats msg st - pure (st', fmap ((ctx,) . Right) mbStats) - process _ (ctx, Left control) = pure (Just (ctx, Left control)) - - mbProduceBlockStats :: ChainDB.TraceEvent blk -> ReplayBlockState -> (ReplayBlockState, Maybe ReplayBlockStats) - mbProduceBlockStats - (ChainDB.TraceLedgerDBEvent - (LedgerDB.LedgerReplayEvent - (LedgerDB.TraceReplayProgressEvent - (LedgerDB.ReplayedBlock curSlot [] _ (LedgerDB.ReplayGoal replayToSlot))))) - st@(ReplayBlockState mLastSlot) = - let curSlotNo = realPointSlot curSlot - goalSlotNo = withOrigin 0 id $ pointSlot replayToSlot - stats = ReplayBlockStats curSlotNo goalSlotNo - progressFor soFar goal = progressForHuman (ReplayBlockStats soFar goal) - shouldEmit = maybe True (\lastSlot -> progressFor curSlotNo goalSlotNo - progressFor lastSlot goalSlotNo >= 0.01) mLastSlot - in if shouldEmit - then (ReplayBlockState (Just curSlotNo), Just stats) - else (st, Nothing) - mbProduceBlockStats _ st = (st, Nothing) diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/ChainDB.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/ChainDB.hs deleted file mode 100644 index a87ac6781b7..00000000000 --- a/cardano-node/src/Cardano/Node/Tracing/Tracers/ChainDB.hs +++ /dev/null @@ -1,3044 +0,0 @@ -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE RecordWildCards #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeApplications #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE UndecidableInstances #-} - -{-# OPTIONS_GHC -Wno-deprecations #-} -{-# OPTIONS_GHC -Wno-orphans #-} - -module Cardano.Node.Tracing.Tracers.ChainDB - ( withAddedToCurrentChainEmptyLimited - , fragmentChainDensity - ) where - -import Cardano.Logging -import Cardano.Node.Tracing.Era.Byron () -import Cardano.Node.Tracing.Era.Shelley () -import Cardano.Node.Tracing.Formatting () -import Cardano.Node.Tracing.Render -import Cardano.Node.Tracing.Tracers.HasIssuer -import Cardano.Prelude (maximumDef) -import Ouroboros.Consensus.Block -import Ouroboros.Consensus.HardFork.Combinator.Abstract.CanHardFork -import Ouroboros.Consensus.HardFork.Combinator.Abstract.SingleEraBlock -import Ouroboros.Consensus.HardFork.Combinator.Info -import Ouroboros.Consensus.HardFork.Combinator.Protocol.ChainSel -import Ouroboros.Consensus.HeaderValidation (HeaderEnvelopeError (..), HeaderError (..), - OtherHeaderEnvelopeError) -import Ouroboros.Consensus.Ledger.Abstract (LedgerError) -import Ouroboros.Consensus.Ledger.Extended (ExtValidationError (..)) -import Ouroboros.Consensus.Ledger.Inspect (InspectLedger, LedgerEvent (..)) -import Ouroboros.Consensus.Ledger.SupportsProtocol (LedgerSupportsProtocol) -import Ouroboros.Consensus.Peras.SelectView -import Ouroboros.Consensus.Protocol.Abstract (Comparing (..), ReasonForSwitch, - SelectViewReasonForSwitch (..), TiebreakerView, ValidationErr) -import qualified Ouroboros.Consensus.Protocol.PBFT as PBFT -import Ouroboros.Consensus.Protocol.Praos.Common -import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB -import qualified Ouroboros.Consensus.Storage.ImmutableDB as ImmDB -import Ouroboros.Consensus.Storage.ImmutableDB.Chunks.Internal (chunkNoToInt) -import qualified Ouroboros.Consensus.Storage.ImmutableDB.Impl.Types as ImmDB -import qualified Ouroboros.Consensus.Storage.LedgerDB as LedgerDB -import qualified Ouroboros.Consensus.Storage.LedgerDB.Snapshots as LedgerDB -import qualified Ouroboros.Consensus.Storage.LedgerDB.V2.Backend as V2 -import qualified Ouroboros.Consensus.Storage.LedgerDB.V2.InMemory as InMemory -import qualified Ouroboros.Consensus.Storage.LedgerDB.V2.LSM as LSM -import qualified Ouroboros.Consensus.Storage.PerasCertDB as PerasCertDB -import qualified Ouroboros.Consensus.Storage.PerasVoteDB as PerasVoteDB -import qualified Ouroboros.Consensus.Storage.VolatileDB as VolDB -import Ouroboros.Consensus.TypeFamilyWrappers -import Ouroboros.Consensus.Util.Condense (condense) -import Ouroboros.Consensus.Util.Enclose -import qualified Ouroboros.Network.AnchoredFragment as AF -import Ouroboros.Network.Block (MaxSlotNo (..)) - -import Data.Aeson (Object, ToJSON, Value (Object, String), object, toJSON, (.=)) -import qualified Data.ByteString.Base16 as B16 -import Data.Int (Int64) -import qualified Data.List.NonEmpty as NonEmpty -import Data.SOP (All, K (..), hcmap, hcollapse) -import Data.Text (Text) -import qualified Data.Text as Text -import qualified Data.Text.Encoding as Text -import Data.Typeable (Typeable, cast) -import Data.Void (absurd) -import Data.Word (Word64) -import Numeric (showFFloat) - --- {-# ANN module ("HLint: ignore Redundant bracket" :: Text) #-} - --- A limiter that is not coming from configuration, because it carries a special filter -withAddedToCurrentChainEmptyLimited - :: Trace IO (ChainDB.TraceEvent blk) - -> IO (Trace IO (ChainDB.TraceEvent blk)) -withAddedToCurrentChainEmptyLimited tr = do - ltr <- limitFrequency 1.25 "AddedToCurrentChainLimiter" mempty tr - pure $ routingTrace (selecting ltr) tr - where - selecting - ltr - (ChainDB.TraceAddBlockEvent (ChainDB.AddedToCurrentChain events _ _ _ _)) = - if null events - then pure ltr - else pure tr - selecting _ _ = pure tr - - --- -------------------------------------------------------------------------------- --- -- ChainDB Tracer --- -------------------------------------------------------------------------------- - -instance ( LogFormatting (Header blk) - , LogFormatting (LedgerEvent blk) - , LogFormatting (RealPoint blk) - , LogFormatting (WeightedSelectView (BlockProtocol blk)) - , ConvertRawHash blk - , ConvertRawHash (Header blk) - , LedgerSupportsProtocol blk - , InspectLedger blk - , HasIssuer blk - , LogFormatting (ReasonForSwitch (TiebreakerView (BlockProtocol blk))) - ) => LogFormatting (ChainDB.TraceEvent blk) where - forHuman ChainDB.TraceLastShutdownUnclean = - "ChainDB is not clean. Validating all immutable chunks" - forHuman (ChainDB.TracePerasVoteDbEvent v) = forHuman v - forHuman (ChainDB.TraceAddBlockEvent v) = forHuman v - forHuman (ChainDB.TraceFollowerEvent v) = forHuman v - forHuman (ChainDB.TraceCopyToImmutableDBEvent v) = forHuman v - forHuman (ChainDB.TraceGCEvent v) = forHuman v - forHuman (ChainDB.TraceInitChainSelEvent v) = forHuman v - forHuman (ChainDB.TraceOpenEvent v) = forHuman v - forHuman (ChainDB.TraceIteratorEvent v) = forHuman v - forHuman (ChainDB.TraceLedgerDBEvent v) = forHuman v - forHuman (ChainDB.TraceImmutableDBEvent v) = forHuman v - forHuman (ChainDB.TraceVolatileDBEvent v) = forHuman v - forHuman (ChainDB.TraceChainSelStarvationEvent ev) = case ev of - ChainDB.ChainSelStarvation RisingEdge -> - "Chain Selection was starved." - ChainDB.ChainSelStarvation (FallingEdgeWith pt) -> - "Chain Selection was unstarved by " <> renderRealPoint pt - forHuman (ChainDB.TracePerasCertDbEvent ev) = forHuman ev - forHuman (ChainDB.TraceAddPerasCertEvent ev) = forHuman ev - - forMachine _ ChainDB.TraceLastShutdownUnclean = - mconcat [ "kind" .= String "LastShutdownUnclean" ] - forMachine dtal (ChainDB.TraceChainSelStarvationEvent (ChainDB.ChainSelStarvation edge)) = - mconcat [ "kind" .= String "ChainSelStarvation" - , case edge of - RisingEdge -> "risingEdge" .= True - FallingEdgeWith pt -> "fallingEdge" .= forMachine dtal pt - ] - forMachine details (ChainDB.TracePerasVoteDbEvent v) = - forMachine details v - forMachine details (ChainDB.TraceAddBlockEvent v) = - forMachine details v - forMachine details (ChainDB.TraceFollowerEvent v) = - forMachine details v - forMachine details (ChainDB.TraceCopyToImmutableDBEvent v) = - forMachine details v - forMachine details (ChainDB.TraceGCEvent v) = - forMachine details v - forMachine details (ChainDB.TraceInitChainSelEvent v) = - forMachine details v - forMachine details (ChainDB.TraceOpenEvent v) = - forMachine details v - forMachine details (ChainDB.TraceIteratorEvent v) = - forMachine details v - forMachine details (ChainDB.TraceLedgerDBEvent v) = - forMachine details v - forMachine details (ChainDB.TraceImmutableDBEvent v) = - forMachine details v - forMachine details (ChainDB.TraceVolatileDBEvent v) = - forMachine details v - forMachine details (ChainDB.TracePerasCertDbEvent v) = - forMachine details v - forMachine details (ChainDB.TraceAddPerasCertEvent v) = - forMachine details v - - - asMetrics ChainDB.TraceLastShutdownUnclean = [] - asMetrics (ChainDB.TraceChainSelStarvationEvent _) = [] - asMetrics (ChainDB.TracePerasVoteDbEvent v) = asMetrics v - asMetrics (ChainDB.TraceAddBlockEvent v) = asMetrics v - asMetrics (ChainDB.TraceFollowerEvent v) = asMetrics v - asMetrics (ChainDB.TraceCopyToImmutableDBEvent v) = asMetrics v - asMetrics (ChainDB.TraceGCEvent v) = asMetrics v - asMetrics (ChainDB.TraceInitChainSelEvent v) = asMetrics v - asMetrics (ChainDB.TraceOpenEvent v) = asMetrics v - asMetrics (ChainDB.TraceIteratorEvent v) = asMetrics v - asMetrics (ChainDB.TraceLedgerDBEvent v) = asMetrics v - asMetrics (ChainDB.TraceImmutableDBEvent v) = asMetrics v - asMetrics (ChainDB.TraceVolatileDBEvent v) = asMetrics v - asMetrics (ChainDB.TracePerasCertDbEvent v) = asMetrics v - asMetrics (ChainDB.TraceAddPerasCertEvent v) = asMetrics v - - -instance MetaTrace (ChainDB.TraceEvent blk) where - namespaceFor ChainDB.TraceLastShutdownUnclean = - Namespace [] ["LastShutdownUnclean"] - namespaceFor ChainDB.TraceChainSelStarvationEvent{} = - Namespace [] ["ChainSelStarvationEvent"] - namespaceFor (ChainDB.TracePerasVoteDbEvent ev) = - nsPrependInner "PerasVoteDbEvent" (namespaceFor ev) - namespaceFor (ChainDB.TraceAddBlockEvent ev) = - nsPrependInner "AddBlockEvent" (namespaceFor ev) - namespaceFor (ChainDB.TraceFollowerEvent ev) = - nsPrependInner "FollowerEvent" (namespaceFor ev) - namespaceFor (ChainDB.TraceCopyToImmutableDBEvent ev) = - nsPrependInner "CopyToImmutableDBEvent" (namespaceFor ev) - namespaceFor (ChainDB.TraceGCEvent ev) = - nsPrependInner "GCEvent" (namespaceFor ev) - namespaceFor (ChainDB.TraceInitChainSelEvent ev) = - nsPrependInner "InitChainSelEvent" (namespaceFor ev) - namespaceFor (ChainDB.TraceOpenEvent ev) = - nsPrependInner "OpenEvent" (namespaceFor ev) - namespaceFor (ChainDB.TraceIteratorEvent ev) = - nsPrependInner "IteratorEvent" (namespaceFor ev) - namespaceFor (ChainDB.TraceLedgerDBEvent ev) = - nsPrependInner "LedgerEvent" (namespaceFor ev) - namespaceFor (ChainDB.TraceImmutableDBEvent ev) = - nsPrependInner "ImmDbEvent" (namespaceFor ev) - namespaceFor (ChainDB.TraceVolatileDBEvent ev) = - nsPrependInner "VolatileDbEvent" (namespaceFor ev) - namespaceFor (ChainDB.TracePerasCertDbEvent ev) = - nsPrependInner "PerasCertDbEvent" (namespaceFor ev) - namespaceFor (ChainDB.TraceAddPerasCertEvent ev) = - nsPrependInner "AddPerasCertEvent" (namespaceFor ev) - - severityFor (Namespace _ ["LastShutdownUnclean"]) _ = Just Info - severityFor (Namespace _ ["ChainSelStarvationEvent"]) _ = Just Debug - severityFor (Namespace out ("AddBlockEvent" : tl)) (Just (ChainDB.TraceAddBlockEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("AddBlockEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (ChainDB.TraceAddBlockEvent blk)) Nothing - severityFor (Namespace out ("FollowerEvent" : tl)) (Just (ChainDB.TraceFollowerEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("FollowerEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (ChainDB.TraceFollowerEvent blk)) Nothing - severityFor (Namespace out ("CopyToImmutableDBEvent" : tl)) (Just (ChainDB.TraceCopyToImmutableDBEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("CopyToImmutableDBEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (ChainDB.TraceCopyToImmutableDBEvent blk)) Nothing - severityFor (Namespace out ("GCEvent" : tl)) (Just (ChainDB.TraceGCEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("GCEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (ChainDB.TraceGCEvent blk)) Nothing - severityFor (Namespace out ("InitChainSelEvent" : tl)) (Just (ChainDB.TraceInitChainSelEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("InitChainSelEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (ChainDB.TraceInitChainSelEvent blk)) Nothing - severityFor (Namespace out ("OpenEvent" : tl)) (Just (ChainDB.TraceOpenEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("OpenEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (ChainDB.TraceOpenEvent blk)) Nothing - severityFor (Namespace out ("IteratorEvent" : tl)) (Just (ChainDB.TraceIteratorEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("IteratorEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (ChainDB.TraceIteratorEvent blk)) Nothing - severityFor (Namespace out ("LedgerEvent" : tl)) (Just (ChainDB.TraceLedgerDBEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("LedgerEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (LedgerDB.TraceEvent blk)) Nothing - severityFor (Namespace out ("ImmDbEvent" : tl)) (Just (ChainDB.TraceImmutableDBEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("ImmDbEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (ImmDB.TraceEvent blk)) Nothing - severityFor (Namespace out ("VolatileDbEvent" : tl)) (Just (ChainDB.TraceVolatileDBEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("VolatileDbEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (VolDB.TraceEvent blk)) Nothing - severityFor (Namespace out ("PerasVoteDbEvent" : tl)) (Just (ChainDB.TracePerasVoteDbEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("PerasVoteDbEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (PerasVoteDB.TraceEvent blk)) Nothing - severityFor (Namespace out ("PerasCertDbEvent" : tl)) (Just (ChainDB.TracePerasCertDbEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("PerasCertDbEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (PerasCertDB.TraceEvent blk)) Nothing - severityFor (Namespace out ("AddPerasCertEvent" : tl)) (Just (ChainDB.TraceAddPerasCertEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("AddPerasCertEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (ChainDB.TraceAddPerasCertEvent blk)) Nothing - severityFor _ns _ = Nothing - - privacyFor (Namespace _ ["LastShutdownUnclean"]) _ = Just Public - privacyFor (Namespace _ ["ChainSelStarvationEvent"]) _ = Just Public - privacyFor (Namespace out ("AddBlockEvent" : tl)) (Just (ChainDB.TraceAddBlockEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("AddBlockEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (ChainDB.TraceAddBlockEvent blk)) Nothing - privacyFor (Namespace out ("FollowerEvent" : tl)) (Just (ChainDB.TraceFollowerEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("FollowerEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (ChainDB.TraceFollowerEvent blk)) Nothing - privacyFor (Namespace out ("CopyToImmutableDBEvent" : tl)) (Just (ChainDB.TraceCopyToImmutableDBEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("CopyToImmutableDBEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (ChainDB.TraceCopyToImmutableDBEvent blk)) Nothing - privacyFor (Namespace out ("GCEvent" : tl)) (Just (ChainDB.TraceGCEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("GCEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (ChainDB.TraceGCEvent blk)) Nothing - privacyFor (Namespace out ("InitChainSelEvent" : tl)) (Just (ChainDB.TraceInitChainSelEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("InitChainSelEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (ChainDB.TraceInitChainSelEvent blk)) Nothing - privacyFor (Namespace out ("OpenEvent" : tl)) (Just (ChainDB.TraceOpenEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("OpenEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (ChainDB.TraceOpenEvent blk)) Nothing - privacyFor (Namespace out ("IteratorEvent" : tl)) (Just (ChainDB.TraceIteratorEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("IteratorEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (ChainDB.TraceIteratorEvent blk)) Nothing - privacyFor (Namespace out ("LedgerEvent" : tl)) (Just (ChainDB.TraceLedgerDBEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("LedgerEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (LedgerDB.TraceEvent blk)) Nothing - privacyFor (Namespace out ("ImmDbEvent" : tl)) (Just (ChainDB.TraceImmutableDBEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("ImmDbEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (ImmDB.TraceEvent blk)) Nothing - privacyFor (Namespace out ("VolatileDbEvent" : tl)) (Just (ChainDB.TraceVolatileDBEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("VolatileDbEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (VolDB.TraceEvent blk)) Nothing - privacyFor (Namespace out ("PerasVoteDbEvent" : tl)) (Just (ChainDB.TracePerasVoteDbEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("PerasVoteDbEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (PerasVoteDB.TraceEvent blk)) Nothing - privacyFor (Namespace out ("PerasCertDbEvent" : tl)) (Just (ChainDB.TracePerasCertDbEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("PerasCertDbEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (PerasCertDB.TraceEvent blk)) Nothing - privacyFor (Namespace out ("AddPerasCertEvent" : tl)) (Just (ChainDB.TraceAddPerasCertEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("AddPerasCertEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (ChainDB.TraceAddPerasCertEvent blk)) Nothing - privacyFor _ _ = Nothing - - detailsFor (Namespace _ ["LastShutdownUnclean"]) _ = Just DNormal - detailsFor (Namespace _ ["ChainSelStarvationEvent"]) _ = Just DNormal - detailsFor (Namespace out ("AddBlockEvent" : tl)) (Just (ChainDB.TraceAddBlockEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("AddBlockEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (ChainDB.TraceAddBlockEvent blk)) Nothing - detailsFor (Namespace out ("FollowerEvent" : tl)) (Just (ChainDB.TraceFollowerEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("FollowerEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (ChainDB.TraceFollowerEvent blk)) Nothing - detailsFor (Namespace out ("CopyToImmutableDBEvent" : tl)) (Just (ChainDB.TraceCopyToImmutableDBEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("CopyToImmutableDBEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (ChainDB.TraceCopyToImmutableDBEvent blk)) Nothing - detailsFor (Namespace out ("GCEvent" : tl)) (Just (ChainDB.TraceGCEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("GCEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (ChainDB.TraceGCEvent blk)) Nothing - detailsFor (Namespace out ("InitChainSelEvent" : tl)) (Just (ChainDB.TraceInitChainSelEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("InitChainSelEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (ChainDB.TraceInitChainSelEvent blk)) Nothing - detailsFor (Namespace out ("OpenEvent" : tl)) (Just (ChainDB.TraceOpenEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("OpenEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (ChainDB.TraceOpenEvent blk)) Nothing - detailsFor (Namespace out ("IteratorEvent" : tl)) (Just (ChainDB.TraceIteratorEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("IteratorEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (ChainDB.TraceIteratorEvent blk)) Nothing - detailsFor (Namespace out ("LedgerEvent" : tl)) (Just (ChainDB.TraceLedgerDBEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("LedgerEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (LedgerDB.TraceEvent blk)) Nothing - detailsFor (Namespace out ("ImmDbEvent" : tl)) (Just (ChainDB.TraceImmutableDBEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("ImmDbEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: (Namespace (ImmDB.TraceEvent blk))) Nothing - detailsFor (Namespace out ("VolatileDbEvent" : tl)) (Just (ChainDB.TraceVolatileDBEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("VolatileDbEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: (Namespace (VolDB.TraceEvent blk))) Nothing - detailsFor (Namespace out ("PerasVoteDbEvent" : tl)) (Just (ChainDB.TracePerasVoteDbEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("PerasVoteDbEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (PerasVoteDB.TraceEvent blk)) Nothing - detailsFor (Namespace out ("PerasCertDbEvent" : tl)) (Just (ChainDB.TracePerasCertDbEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("PerasCertDbEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (PerasCertDB.TraceEvent blk)) Nothing - detailsFor (Namespace out ("AddPerasCertEvent" : tl)) (Just (ChainDB.TraceAddPerasCertEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("AddPerasCertEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (ChainDB.TraceAddPerasCertEvent blk)) Nothing - detailsFor _ _ = Nothing - - metricsDocFor (Namespace out ("AddBlockEvent" : tl)) = - metricsDocFor (Namespace out tl :: Namespace (ChainDB.TraceAddBlockEvent blk)) - metricsDocFor (Namespace out ("FollowerEvent" : tl)) = - metricsDocFor (Namespace out tl :: Namespace (ChainDB.TraceFollowerEvent blk)) - metricsDocFor (Namespace out ("CopyToImmutableDBEvent" : tl)) = - metricsDocFor (Namespace out tl :: Namespace (ChainDB.TraceCopyToImmutableDBEvent blk)) - metricsDocFor (Namespace out ("GCEvent" : tl)) = - metricsDocFor (Namespace out tl :: Namespace (ChainDB.TraceGCEvent blk)) - metricsDocFor (Namespace out ("InitChainSelEvent" : tl)) = - metricsDocFor (Namespace out tl :: Namespace (ChainDB.TraceInitChainSelEvent blk)) - metricsDocFor (Namespace out ("OpenEvent" : tl)) = - metricsDocFor (Namespace out tl :: Namespace (ChainDB.TraceOpenEvent blk)) - metricsDocFor (Namespace out ("IteratorEvent" : tl)) = - metricsDocFor (Namespace out tl :: Namespace (ChainDB.TraceIteratorEvent blk)) - metricsDocFor (Namespace out ("LedgerEvent" : tl)) = - metricsDocFor (Namespace out tl :: Namespace (LedgerDB.TraceEvent blk)) - metricsDocFor (Namespace out ("ImmDbEvent" : tl)) = - metricsDocFor (Namespace out tl :: Namespace (ImmDB.TraceEvent blk)) - metricsDocFor (Namespace out ("VolatileDbEvent" : tl)) = - metricsDocFor (Namespace out tl :: Namespace (VolDB.TraceEvent blk)) - metricsDocFor _ = [] - - documentFor (Namespace _ ["LastShutdownUnclean"]) = Just $ mconcat - [ "Last shutdown of the node didn't leave the ChainDB directory in a clean" - , " state. Therefore, revalidating all the immutable chunks is necessary to" - , " ensure the correctness of the chain." - ] - documentFor (Namespace _ ["ChainSelStarvationEvent"]) = Just $ mconcat - [ "ChainSel is waiting for a next block to process, but there is no block in the queue." - , " Despite the name, it is a pretty normal (and frequent) event." - ] - documentFor (Namespace out ("AddBlockEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (ChainDB.TraceAddBlockEvent blk)) - documentFor (Namespace out ("FollowerEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (ChainDB.TraceFollowerEvent blk)) - documentFor (Namespace out ("CopyToImmutableDBEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (ChainDB.TraceCopyToImmutableDBEvent blk)) - documentFor (Namespace out ("GCEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (ChainDB.TraceGCEvent blk)) - documentFor (Namespace out ("InitChainSelEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (ChainDB.TraceInitChainSelEvent blk)) - documentFor (Namespace out ("OpenEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (ChainDB.TraceOpenEvent blk)) - documentFor (Namespace out ("IteratorEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (ChainDB.TraceIteratorEvent blk)) - documentFor (Namespace out ("LedgerEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (LedgerDB.TraceEvent blk)) - documentFor (Namespace out ("ImmDbEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (ImmDB.TraceEvent blk)) - documentFor (Namespace out ("VolatileDbEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (VolDB.TraceEvent blk)) - documentFor (Namespace out ("PerasVoteDbEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (PerasVoteDB.TraceEvent blk)) - documentFor (Namespace out ("PerasCertDbEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (PerasCertDB.TraceEvent blk)) - documentFor (Namespace out ("AddPerasCertEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (ChainDB.TraceAddPerasCertEvent blk)) - documentFor _ = Nothing - - allNamespaces = - Namespace [] ["LastShutdownUnclean"] - : Namespace [] ["ChainSelStarvationEvent"] - : (map (nsPrependInner "AddBlockEvent") - (allNamespaces :: [Namespace (ChainDB.TraceAddBlockEvent blk)]) - ++ map (nsPrependInner "FollowerEvent") - (allNamespaces :: [Namespace (ChainDB.TraceFollowerEvent blk)]) - ++ map (nsPrependInner "CopyToImmutableDBEvent") - (allNamespaces :: [Namespace (ChainDB.TraceCopyToImmutableDBEvent blk)]) - ++ map (nsPrependInner "GCEvent") - (allNamespaces :: [Namespace (ChainDB.TraceGCEvent blk)]) - ++ map (nsPrependInner "InitChainSelEvent") - (allNamespaces :: [Namespace (ChainDB.TraceInitChainSelEvent blk)]) - ++ map (nsPrependInner "OpenEvent") - (allNamespaces :: [Namespace (ChainDB.TraceOpenEvent blk)]) - ++ map (nsPrependInner "IteratorEvent") - (allNamespaces :: [Namespace (ChainDB.TraceIteratorEvent blk)]) - ++ map (nsPrependInner "LedgerEvent") - (allNamespaces :: [Namespace (LedgerDB.TraceEvent blk)]) - ++ map (nsPrependInner "ImmDbEvent") - (allNamespaces :: [Namespace (ImmDB.TraceEvent blk)]) - ++ map (nsPrependInner "VolatileDbEvent") - (allNamespaces :: [Namespace (VolDB.TraceEvent blk)]) - ++ map (nsPrependInner "PerasVoteDbEvent") - (allNamespaces :: [Namespace (PerasVoteDB.TraceEvent blk)]) - ++ map (nsPrependInner "PerasCertDbEvent") - (allNamespaces :: [Namespace (PerasCertDB.TraceEvent blk)]) - ++ map (nsPrependInner "AddPerasCertEvent") - (allNamespaces :: [Namespace (ChainDB.TraceAddPerasCertEvent blk)]) - ) - - --------------------------------------------------------------------------------- --- AddBlockEvent --------------------------------------------------------------------------------- - -instance LogFormatting (PraosReasonForSwitch c) where - forHuman (HigherOCert (Comparing ref cand)) = - "candidate has higher OCert (" <> showT cand <> ") than our selection (" <> showT ref <> ")" - forHuman (VRFTiebreak (Comparing ref cand)) = - "candidate has lower VRF (" <> showT cand <> ") than our selection (" <> showT ref <> ")" - forMachine _dtal (HigherOCert (Comparing ref cand)) = - mconcat [ "reason" .= String "HigherOCert", "our" .= String (showT ref), "candidate" .= String (showT cand) ] - forMachine _dtal (VRFTiebreak (Comparing ref cand)) = - mconcat [ "reason" .= String "VRFTiebreak", "our" .= String (showT ref), "candidate" .= String (showT cand) ] - -class (LogFormatting (ReasonForSwitch (TiebreakerView (BlockProtocol a))), SingleEraBlock a) => LFTBV a -instance (LogFormatting (ReasonForSwitch (TiebreakerView (BlockProtocol a))), SingleEraBlock a) => LFTBV a - -instance (All LFTBV xs, CanHardFork xs) => LogFormatting (OneEraReasonForSwitch xs) where - forHuman (OneEraReasonForSwitch ns) = - hcollapse $ hcmap (Proxy @LFTBV) msg ns - where - msg :: forall era. LFTBV era => WrapReasonForSwitch era -> K Text era - msg (WrapReasonForSwitch rs) = K $ - "in era " <> singleEraName (singleEraInfo (Proxy @era)) <> ": " <> forHuman rs - forMachine dtal (OneEraReasonForSwitch ns) = - hcollapse $ hcmap (Proxy @LFTBV) msg ns - where - msg :: forall era. LFTBV era => WrapReasonForSwitch era -> K Object era - msg (WrapReasonForSwitch rs) = K $ - forMachine dtal rs <> mconcat [ "era" .= String (singleEraName (singleEraInfo (Proxy @era))) ] - -instance LogFormatting (ReasonForSwitch (TiebreakerView proto)) => - LogFormatting (WeightedSelectViewReasonForSwitch proto) where - forHuman (Heavier (Comparing ref cand)) = - "candidate is heavier (" <> showT cand <> ") than our selection (" <> showT ref <> ")" - forHuman (WeightedSelectViewTiebreak reason) = forHuman reason - forMachine _dtal (Heavier (Comparing ref cand)) = - mconcat [ "reason" .= String "HigherOCert", "our" .= String (showT ref), "candidate" .= String (showT cand) ] - forMachine dtal (WeightedSelectViewTiebreak reason) = - forMachine dtal reason - -instance LogFormatting (ReasonForSwitch (TiebreakerView proto)) => - LogFormatting (Either (WithEmptyFragmentReasonForSwitch - (WeightedSelectView proto)) (SelectViewReasonForSwitch proto)) where - forHuman (Left CandidateIsNonEmpty) = "candidate is an extension of our selection" - forHuman (Left (BothAreNonEmpty a)) = forHuman a - forHuman (Right (Longer (Comparing ref cand))) = - "candidate is longer (" <> showT cand <> ") than our selection (" <> showT ref <> ")" - forHuman (Right (SelectViewTiebreak a)) = forHuman a - forMachine _dtal (Left CandidateIsNonEmpty) = - mconcat [ "reason" .= String "extension" ] - forMachine dtal (Left (BothAreNonEmpty a)) = forMachine dtal a - forMachine _dtal (Right (Longer (Comparing ref cand))) = - mconcat [ "reason" .= String "Longer", "our" .= String (showT ref), "candidate" .= String (showT cand) ] - forMachine dtal (Right (SelectViewTiebreak a)) = forMachine dtal a - -instance ( LogFormatting (Header blk) - , LogFormatting (LedgerEvent blk) - , LogFormatting (RealPoint blk) - , LogFormatting (WeightedSelectView (BlockProtocol blk)) - , LogFormatting (Either (WithEmptyFragmentReasonForSwitch (WeightedSelectView (BlockProtocol blk))) (SelectViewReasonForSwitch (BlockProtocol blk))) - , ConvertRawHash blk - , ConvertRawHash (Header blk) - , LedgerSupportsProtocol blk - , InspectLedger blk - , HasIssuer blk - ) => LogFormatting (ChainDB.TraceAddBlockEvent blk) where - forHuman (ChainDB.IgnoreBlockOlderThanImmTip pt) = - "Ignoring block older than ImmTip: " <> renderRealPointAsPhrase pt - forHuman (ChainDB.IgnoreBlockAlreadyInVolatileDB pt) = - "Ignoring block already in DB: " <> renderRealPointAsPhrase pt - forHuman (ChainDB.IgnoreInvalidBlock pt _reason) = - "Ignoring previously seen invalid block: " <> renderRealPointAsPhrase pt - forHuman (ChainDB.AddedBlockToQueue pt edgeSz) = - case edgeSz of - RisingEdge -> - "About to add block to queue: " <> renderRealPointAsPhrase pt - FallingEdgeWith sz -> - "Block added to queue: " <> renderRealPointAsPhrase pt <> ", queue size " <> condenseT sz - forHuman ChainDB.PoppingFromQueue = - "Popping block from queue" - forHuman (ChainDB.PoppedBlockFromQueue pt) = - "Popped block from queue: " <> renderRealPointAsPhrase pt - forHuman (ChainDB.StoreButDontChange pt) = - "Ignoring block: " <> renderRealPointAsPhrase pt - forHuman (ChainDB.TryAddToCurrentChain pt) = - "Block fits onto the current chain: " <> renderRealPointAsPhrase pt - forHuman (ChainDB.TrySwitchToAFork pt _) = - "Block fits onto some fork: " <> renderRealPointAsPhrase pt - forHuman (ChainDB.ChangingSelection pt) = - "Changing selection to: " <> renderPointAsPhrase pt - forHuman (ChainDB.AddedToCurrentChain es _ _ c _) = - "Chain extended, new tip: " <> renderPointAsPhrase (AF.headPoint c) <> - Text.concat [ "\nEvent: " <> showT e | e <- es ] - forHuman (ChainDB.SwitchedToAFork es _ _ c reasonForSwitch) = - "Switched to a fork, new tip: " <> renderPointAsPhrase (AF.headPoint c) <> - Text.concat [ "\nEvent: " <> showT e | e <- es ] <> - "\nReason: " <> forHuman reasonForSwitch - forHuman (ChainDB.AddBlockValidation ev') = forHuman ev' - forHuman (ChainDB.AddedBlockToVolatileDB pt _ _ enclosing) = - case enclosing of - RisingEdge -> "Chain about to add block " <> renderRealPointAsPhrase pt - FallingEdge -> "Chain added block " <> renderRealPointAsPhrase pt - forHuman (ChainDB.PipeliningEvent ev') = forHuman ev' - forHuman (ChainDB.AddedReprocessLoEBlocksToQueue edgeSz) = - case edgeSz of - RisingEdge -> - "About to add request to queue to reprocess blocks postponed by LoE." - FallingEdgeWith sz -> - "Added request to queue to reprocess blocks postponed by LoE" <> ", queue size " <> condenseT sz - forHuman ChainDB.PoppedReprocessLoEBlocksFromQueue = - "Poppped request from queue to reprocess blocks postponed by LoE." - forHuman ChainDB.ChainSelectionLoEDebug{} = - "ChainDB LoE debug event" - forMachine dtal (ChainDB.IgnoreBlockOlderThanImmTip pt) = - mconcat [ "kind" .= String "IgnoreBlockOlderThanImmTip" - , "block" .= forMachine dtal pt ] - forMachine dtal (ChainDB.IgnoreBlockAlreadyInVolatileDB pt) = - mconcat [ "kind" .= String "IgnoreBlockAlreadyInVolatileDB" - , "block" .= forMachine dtal pt ] - forMachine dtal (ChainDB.IgnoreInvalidBlock pt reason) = - mconcat [ "kind" .= String "IgnoreInvalidBlock" - , "block" .= forMachine dtal pt - , "reason" .= showT reason ] - forMachine dtal (ChainDB.AddedBlockToQueue pt edgeSz) = - mconcat [ "kind" .= String "AddedBlockToQueue" - , "block" .= forMachine dtal pt - , case edgeSz of - RisingEdge -> "risingEdge" .= True - FallingEdgeWith sz -> "queueSize" .= toJSON sz ] - forMachine _dtal ChainDB.PoppingFromQueue = - mconcat [ "kind" .= String "PoppingFromQueue" - ] - forMachine dtal (ChainDB.PoppedBlockFromQueue pt) = - mconcat [ "kind" .= String "TraceAddBlockEvent.PoppedBlockFromQueue" - , "block" .= forMachine dtal pt ] - forMachine dtal (ChainDB.StoreButDontChange pt) = - mconcat [ "kind" .= String "StoreButDontChange" - , "block" .= forMachine dtal pt ] - forMachine dtal (ChainDB.TryAddToCurrentChain pt) = - mconcat [ "kind" .= String "TryAddToCurrentChain" - , "block" .= forMachine dtal pt ] - forMachine dtal (ChainDB.TrySwitchToAFork pt _) = - mconcat [ "kind" .= String "TraceAddBlockEvent.TrySwitchToAFork" - , "block" .= forMachine dtal pt ] - forMachine dtal (ChainDB.ChangingSelection pt) = - mconcat [ "kind" .= String "TraceAddBlockEvent.ChangingSelection" - , "block" .= forMachine dtal pt ] - - forMachine DDetailed (ChainDB.AddedToCurrentChain events selChangedInfo base extended _) = - let ChainInformation { .. } = chainInformation selChangedInfo base extended 0 - tipBlockIssuerVkHashText :: Text - tipBlockIssuerVkHashText = - case tipBlockIssuerVerificationKeyHash of - NoBlockIssuer -> "NoBlockIssuer" - BlockIssuerVerificationKeyHash bs -> - Text.decodeLatin1 (B16.encode bs) - in mconcat $ - [ "kind" .= String "AddedToCurrentChain" - , "newtip" .= renderPointForDetails DDetailed (AF.headPoint extended) - , "newSuffixSelectView" .= forMachine DDetailed (ChainDB.newSuffixSelectView selChangedInfo) - ] - ++ [ "oldSuffixSelectView" .= forMachine DDetailed oldSuffixSelectView - | Just oldSuffixSelectView <- [ChainDB.oldSuffixSelectView selChangedInfo] - ] - ++ [ "headers" .= toJSON (forMachine DDetailed `map` addedHdrsNewChain base extended) - ] - ++ [ "events" .= toJSON (map (forMachine DDetailed) events) - | not (null events) ] - ++ [ "tipBlockHash" .= tipBlockHash - , "tipBlockParentHash" .= tipBlockParentHash - , "tipBlockIssuerVKeyHash" .= tipBlockIssuerVkHashText] - forMachine dtal (ChainDB.AddedToCurrentChain events selChangedInfo _base extended _) = - mconcat $ - [ "kind" .= String "AddedToCurrentChain" - , "newtip" .= renderPointForDetails dtal (AF.headPoint extended) - , "newSuffixSelectView" .= forMachine dtal (ChainDB.newSuffixSelectView selChangedInfo) - ] - ++ [ "oldSuffixSelectView" .= forMachine dtal oldSuffixSelectView - | Just oldSuffixSelectView <- [ChainDB.oldSuffixSelectView selChangedInfo] - ] - ++ [ "events" .= toJSON (map (forMachine dtal) events) - | not (null events) ] - forMachine DDetailed (ChainDB.SwitchedToAFork events selChangedInfo old new reasonForSwitch) = - let ChainInformation { .. } = chainInformation selChangedInfo old new 0 - tipBlockIssuerVkHashText :: Text - tipBlockIssuerVkHashText = - case tipBlockIssuerVerificationKeyHash of - NoBlockIssuer -> "NoBlockIssuer" - BlockIssuerVerificationKeyHash bs -> - Text.decodeLatin1 (B16.encode bs) - in mconcat $ - [ "kind" .= String "TraceAddBlockEvent.SwitchedToAFork" - , "newtip" .= renderPointForDetails DDetailed (AF.headPoint new) - , "newSuffixSelectView" .= forMachine DDetailed (ChainDB.newSuffixSelectView selChangedInfo) - ] - ++ [ "oldSuffixSelectView" .= forMachine DDetailed oldSuffixSelectView - | Just oldSuffixSelectView <- [ChainDB.oldSuffixSelectView selChangedInfo] - ] - ++ [ "headers" .= toJSON (forMachine DDetailed `map` addedHdrsNewChain old new) - ] - ++ [ "events" .= toJSON (map (forMachine DDetailed) events) - | not (null events) ] - ++ [ "tipBlockHash" .= tipBlockHash - , "tipBlockParentHash" .= tipBlockParentHash - , "tipBlockIssuerVKeyHash" .= tipBlockIssuerVkHashText] - ++ [ "reason" .= forMachine DDetailed reasonForSwitch ] - forMachine dtal (ChainDB.SwitchedToAFork events selChangedInfo _old new reasonForSwitch) = - mconcat $ - [ "kind" .= String "TraceAddBlockEvent.SwitchedToAFork" - , "newtip" .= renderPointForDetails dtal (AF.headPoint new) - , "newSuffixSelectView" .= forMachine dtal (ChainDB.newSuffixSelectView selChangedInfo) - ] - ++ [ "oldSuffixSelectView" .= forMachine dtal oldSuffixSelectView - | Just oldSuffixSelectView <- [ChainDB.oldSuffixSelectView selChangedInfo] - ] - ++ [ "events" .= toJSON (map (forMachine dtal) events) - | not (null events) ] - ++ [ "reason" .= forMachine dtal reasonForSwitch ] - - forMachine dtal (ChainDB.AddBlockValidation ev') = - forMachine dtal ev' - forMachine dtal (ChainDB.AddedBlockToVolatileDB pt (BlockNo bn) _ enclosing) = - mconcat $ [ "kind" .= String "AddedBlockToVolatileDB" - , "block" .= forMachine dtal pt - , "blockNo" .= showT bn ] - <> [ "risingEdge" .= True | RisingEdge <- [enclosing] ] - forMachine dtal (ChainDB.PipeliningEvent ev') = - forMachine dtal ev' - forMachine _dtal (ChainDB.AddedReprocessLoEBlocksToQueue edgeSz) = - mconcat [ "kind" .= String "AddedReprocessLoEBlocksToQueue" - , case edgeSz of - RisingEdge -> "risingEdge" .= True - FallingEdgeWith sz -> "queueSize" .= toJSON sz ] - forMachine _dtal ChainDB.PoppedReprocessLoEBlocksFromQueue = - mconcat [ "kind" .= String "PoppedReprocessLoEBlocksFromQueue" ] - forMachine dtal (ChainDB.ChainSelectionLoEDebug curChain loeFrag) = - case loeFrag of - ChainDB.LoEEnabled loeF -> - mconcat [ "kind" .= String "ChainSelectionLoEDebug" - , "curChain" .= headAndAnchor curChain - , "loeFrag" .= headAndAnchor loeF - ] - ChainDB.LoEDisabled -> - mconcat [ "kind" .= String "ChainSelectionLoEDebug" - , "curChain" .= headAndAnchor curChain - , "loeFrag" .= String "LoE is disabled" - ] - where - headAndAnchor frag = object - [ "anchor" .= forMachine dtal (AF.anchorPoint frag) - , "head" .= forMachine dtal (AF.headPoint frag) - ] - - - asMetrics (ChainDB.SwitchedToAFork _warnings selChangedInfo oldChain newChain _) = - let forkIt = not $ AF.withinFragmentBounds (AF.headPoint oldChain) - newChain - ChainInformation { .. } = chainInformation selChangedInfo oldChain newChain 0 - tipBlockIssuerVkHashText = - case tipBlockIssuerVerificationKeyHash of - NoBlockIssuer -> "NoBlockIssuer" - BlockIssuerVerificationKeyHash bs -> - Text.decodeLatin1 (B16.encode bs) - in [ DoubleM "density" (fromRational density) - , IntM "slotNum" (fromIntegral slots) - , IntM "blockNum" (fromIntegral blocks) - , IntM "slotInEpoch" (fromIntegral slotInEpoch) - , IntM "epoch" (fromIntegral (unEpochNo epoch)) - , CounterM "forks" (Just (if forkIt then 1 else 0)) - , PrometheusM "tipBlock" [("hash",tipBlockHash) - ,("parent_hash",tipBlockParentHash) - ,("issuer_VKey_hash", tipBlockIssuerVkHashText)] - ] - asMetrics (ChainDB.AddedToCurrentChain _warnings selChangedInfo oldChain newChain _) = - let ChainInformation { .. } = - chainInformation selChangedInfo oldChain newChain 0 - tipBlockIssuerVkHashText = - case tipBlockIssuerVerificationKeyHash of - NoBlockIssuer -> "NoBlockIssuer" - BlockIssuerVerificationKeyHash bs -> - Text.decodeLatin1 (B16.encode bs) - in [ DoubleM "density" (fromRational density) - , IntM "slotNum" (fromIntegral slots) - , IntM "blockNum" (fromIntegral blocks) - , IntM "slotInEpoch" (fromIntegral slotInEpoch) - , IntM "epoch" (fromIntegral (unEpochNo epoch)) - , PrometheusM "tipBlock" [("hash",tipBlockHash) - ,("parent_hash",tipBlockParentHash) - ,("issuer_verification_key_hash", tipBlockIssuerVkHashText)] - ] - asMetrics _ = [] - - -instance MetaTrace (ChainDB.TraceAddBlockEvent blk) where - namespaceFor ChainDB.IgnoreBlockOlderThanImmTip {} = - Namespace [] ["IgnoreBlockOlderThanImmTip"] - namespaceFor ChainDB.IgnoreBlockAlreadyInVolatileDB {} = - Namespace [] ["IgnoreBlockAlreadyInVolatileDB"] - namespaceFor ChainDB.IgnoreInvalidBlock {} = - Namespace [] ["IgnoreInvalidBlock"] - namespaceFor ChainDB.AddedBlockToQueue {} = - Namespace [] ["AddedBlockToQueue"] - namespaceFor ChainDB.PoppingFromQueue {} = - Namespace [] ["PoppingFromQueue"] - namespaceFor ChainDB.PoppedBlockFromQueue {} = - Namespace [] ["PoppedBlockFromQueue"] - namespaceFor ChainDB.AddedBlockToVolatileDB {} = - Namespace [] ["AddedBlockToVolatileDB"] - namespaceFor ChainDB.TryAddToCurrentChain {} = - Namespace [] ["TryAddToCurrentChain"] - namespaceFor ChainDB.TrySwitchToAFork {} = - Namespace [] ["TrySwitchToAFork"] - namespaceFor ChainDB.StoreButDontChange {} = - Namespace [] ["StoreButDontChange"] - namespaceFor ChainDB.AddedToCurrentChain {} = - Namespace [] ["AddedToCurrentChain"] - namespaceFor ChainDB.SwitchedToAFork {} = - Namespace [] ["SwitchedToAFork"] - namespaceFor ChainDB.ChangingSelection {} = - Namespace [] ["ChangingSelection"] - namespaceFor (ChainDB.AddBlockValidation ev') = - nsPrependInner "AddBlockValidation" (namespaceFor ev') - namespaceFor (ChainDB.PipeliningEvent ev') = - nsPrependInner "PipeliningEvent" (namespaceFor ev') - namespaceFor ChainDB.AddedReprocessLoEBlocksToQueue {} = - Namespace [] ["AddedReprocessLoEBlocksToQueue"] - namespaceFor ChainDB.PoppedReprocessLoEBlocksFromQueue = - Namespace [] ["PoppedReprocessLoEBlocksFromQueue"] - namespaceFor ChainDB.ChainSelectionLoEDebug {} = - Namespace [] ["ChainSelectionLoEDebug"] - - severityFor (Namespace _ ["IgnoreBlockOlderThanImmTip"]) _ = Just Info - severityFor (Namespace _ ["IgnoreBlockAlreadyInVolatileDB"]) _ = Just Info - severityFor (Namespace _ ["IgnoreInvalidBlock"]) _ = Just Info - severityFor (Namespace _ ["AddedBlockToQueue"]) _ = Just Debug - severityFor (Namespace _ ["AddedBlockToVolatileDB"]) _ = Just Debug - severityFor (Namespace _ ["PoppingFromQueue"]) _ = Just Debug - severityFor (Namespace _ ["PoppedBlockFromQueue"]) _ = Just Debug - severityFor (Namespace _ ["TryAddToCurrentChain"]) _ = Just Debug - severityFor (Namespace _ ["TrySwitchToAFork"]) _ = Just Info - severityFor (Namespace _ ["StoreButDontChange"]) _ = Just Debug - severityFor (Namespace _ ["ChangingSelection"]) _ = Just Debug - severityFor (Namespace _ ["AddedToCurrentChain"]) - (Just (ChainDB.AddedToCurrentChain events _ _ _ _)) = - Just $ maximumDef Notice (map sevLedgerEvent events) - severityFor (Namespace _ ["AddedToCurrentChain"]) Nothing = Just Notice - severityFor (Namespace _ ["SwitchedToAFork"]) - (Just (ChainDB.SwitchedToAFork events _ _ _ _)) = - Just $ maximumDef Notice (map sevLedgerEvent events) - severityFor (Namespace _ ["SwitchedToAFork"]) _ = - Just Notice - severityFor (Namespace out ("AddBlockValidation" : tl)) - (Just (ChainDB.AddBlockValidation ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace _ ("AddBlockValidation" : _tl)) Nothing = Just Notice - severityFor (Namespace out ("PipeliningEvent" : tl)) (Just (ChainDB.PipeliningEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("PipeliningEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (ChainDB.TracePipeliningEvent blk)) Nothing - severityFor (Namespace _ ["AddedReprocessLoEBlocksToQueue"]) _ = Just Debug - severityFor (Namespace _ ["PoppedReprocessLoEBlocksFromQueue"]) _ = Just Debug - severityFor (Namespace _ ["ChainSelectionLoEDebug"]) _ = Just Debug - severityFor _ _ = Nothing - - privacyFor (Namespace out ("AddBlockEvent" : tl)) (Just (ChainDB.AddBlockValidation ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("AddBlockEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (ChainDB.TraceValidationEvent blk)) Nothing - privacyFor (Namespace out ("PipeliningEvent" : tl)) (Just (ChainDB.PipeliningEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("PipeliningEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (ChainDB.TracePipeliningEvent blk)) Nothing - privacyFor _ _ = Just Public - - detailsFor (Namespace out ("AddBlockEvent" : tl)) (Just (ChainDB.AddBlockValidation ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("AddBlockEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (ChainDB.TraceValidationEvent blk)) Nothing - detailsFor (Namespace out ("PipeliningEvent" : tl)) (Just (ChainDB.PipeliningEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("PipeliningEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (ChainDB.TracePipeliningEvent blk)) Nothing - detailsFor _ _ = Just DNormal - - metricsDocFor (Namespace _ ["SwitchedToAFork"]) = - [ ( "density" - , mconcat - [ "The actual number of blocks created over the maximum expected number" - , " of blocks that could be created over the span of the last @k@ blocks." - ] - ) - , ( "slotNum" - , "Number of slots in this chain fragment." - ) - , ( "blockNum" - , "Number of blocks in this chain fragment." - ) - , ( "slotInEpoch" - , mconcat - [ "Relative slot number of the tip of the current chain within the" - , " epoch.." - ] - ) - , ( "epoch" - , "In which epoch is the tip of the current chain." - ) - , ( "forks" - , "counter for forks" - ) - , ( "tipBlock" - , "Values for hash, parent hash and issuer verification key hash" - ) - ] - - metricsDocFor (Namespace _ ["AddedToCurrentChain"]) = - [ ( "density" - , mconcat - [ "The actual number of blocks created over the maximum expected number" - , " of blocks that could be created over the span of the last @k@ blocks." - ] - ) - , ( "slotNum" - , "Number of slots in this chain fragment." - ) - , ( "blockNum" - , "Number of blocks in this chain fragment." - ) - , ( "slotInEpoch" - , mconcat - [ "Relative slot number of the tip of the current chain within the" - , " epoch.." - ] - ) - , ( "epoch" - , "In which epoch is the tip of the current chain." - ) - , ( "tipBlock" - , "Values for hash, parent hash and issuer verification key hash" - ) - ] - metricsDocFor _ = [] - - documentFor (Namespace _ ["IgnoreBlockOlderThanImmTip"]) = Just - "A block with a 'BlockNo' not newer than the immutable tip was ignored." - documentFor (Namespace _ ["IgnoreBlockAlreadyInVolatileDB"]) = Just - "A block that is already in the Volatile DB was ignored." - documentFor (Namespace _ ["IgnoreInvalidBlock"]) = Just - "A block that is invalid was ignored." - documentFor (Namespace _ ["AddedBlockToQueue"]) = Just $ mconcat - [ "The block was added to the queue and will be added to the ChainDB by" - , " the background thread. The size of the queue is included.." - ] - documentFor (Namespace _ ["AddedBlockToVolatileDB"]) = Just - "A block was added to the Volatile DB" - documentFor (Namespace _ ["PoppingFromQueue"]) = Just "" - documentFor (Namespace _ ["PoppedBlockFromQueue"]) = Just "" - documentFor (Namespace _ ["TryAddToCurrentChain"]) = Just $ mconcat - [ "The block fits onto the current chain, we'll try to use it to extend" - , " our chain." - ] - documentFor (Namespace _ ["TrySwitchToAFork"]) = Just $ mconcat - [ "The block fits onto some fork, we'll try to switch to that fork (if" - , " it is preferable to our chain)" - ] - documentFor (Namespace _ ["StoreButDontChange"]) = Just $ mconcat - [ "The block fits onto some fork, we'll try to switch to that fork (if" - , " it is preferable to our chain)." - ] - documentFor (Namespace _ ["ChangingSelection"]) = Just $ mconcat - [ "The new block fits onto the current chain (first" - , " fragment) and we have successfully used it to extend our (new) current" - , " chain (second fragment)." - ] - documentFor (Namespace _ ["AddedToCurrentChain"]) = Just $ mconcat - [ "The new block fits onto the current chain (first" - , " fragment) and we have successfully used it to extend our (new) current" - , " chain (second fragment)." - ] - documentFor (Namespace _out ["SwitchedToAFork"]) = Just $ mconcat - [ "The new block fits onto some fork and we have switched to that fork" - , " (second fragment), as it is preferable to our (previous) current chain" - , " (first fragment)." - ] - documentFor (Namespace out ("AddBlockValidation" : tl)) = - documentFor (Namespace out tl :: Namespace (ChainDB.TraceValidationEvent blk)) - documentFor (Namespace out ("PipeliningEvent" : tl)) = - documentFor (Namespace out tl :: Namespace (ChainDB.TracePipeliningEvent blk)) - documentFor _ = Nothing - - - allNamespaces = - [ Namespace [] ["IgnoreBlockOlderThanImmTip"] - , Namespace [] ["IgnoreBlockAlreadyInVolatileDB"] - , Namespace [] ["IgnoreInvalidBlock"] - , Namespace [] ["AddedBlockToQueue"] - , Namespace [] ["AddedBlockToVolatileDB"] - , Namespace [] ["PoppingFromQueue"] - , Namespace [] ["PoppedBlockFromQueue"] - , Namespace [] ["TryAddToCurrentChain"] - , Namespace [] ["TrySwitchToAFork"] - , Namespace [] ["StoreButDontChange"] - , Namespace [] ["ChangingSelection"] - , Namespace [] ["AddedToCurrentChain"] - , Namespace [] ["SwitchedToAFork"] - , Namespace [] ["AddedReprocessLoEBlocksToQueue"] - , Namespace [] ["PoppedReprocessLoEBlocksFromQueue"] - , Namespace [] ["ChainSelectionLoEDebug"] - ] - ++ map (nsPrependInner "PipeliningEvent") - (allNamespaces :: [Namespace (ChainDB.TracePipeliningEvent blk)]) - ++ map (nsPrependInner "AddBlockValidation") - (allNamespaces :: [Namespace (ChainDB.TraceValidationEvent blk)]) - --------------------------------------------------------------------------------- --- ChainDB TracePipeliningEvent --------------------------------------------------------------------------------- - -instance ( ConvertRawHash (Header blk) - , HasHeader (Header blk) - ) => LogFormatting (ChainDB.TracePipeliningEvent blk) where - forHuman (ChainDB.SetTentativeHeader hdr enclosing) = - case enclosing of - RisingEdge -> "About to set tentative header to " <> renderPointAsPhrase (blockPoint hdr) - FallingEdge -> "Set tentative header to " <> renderPointAsPhrase (blockPoint hdr) - forHuman (ChainDB.TrapTentativeHeader hdr) = - "Discovered trap tentative header " <> renderPointAsPhrase (blockPoint hdr) - forHuman (ChainDB.OutdatedTentativeHeader hdr) = - "Tentative header is now outdated " <> renderPointAsPhrase (blockPoint hdr) - - forMachine dtals (ChainDB.SetTentativeHeader hdr enclosing) = - mconcat $ [ "kind" .= String "SetTentativeHeader" - , "block" .= renderPointForDetails dtals (blockPoint hdr) ] - <> [ "risingEdge" .= True | RisingEdge <- [enclosing] ] - forMachine dtals (ChainDB.TrapTentativeHeader hdr) = - mconcat [ "kind" .= String "TrapTentativeHeader" - , "block" .= renderPointForDetails dtals (blockPoint hdr) ] - forMachine dtals (ChainDB.OutdatedTentativeHeader hdr) = - mconcat [ "kind" .= String "OutdatedTentativeHeader" - , "block" .= renderPointForDetails dtals (blockPoint hdr)] - -instance MetaTrace (ChainDB.TracePipeliningEvent blk) where - namespaceFor ChainDB.SetTentativeHeader {} = - Namespace [] ["SetTentativeHeader"] - namespaceFor ChainDB.TrapTentativeHeader {} = - Namespace [] ["TrapTentativeHeader"] - namespaceFor ChainDB.OutdatedTentativeHeader {} = - Namespace [] ["OutdatedTentativeHeader"] - - severityFor (Namespace _ ["SetTentativeHeader"]) _ = Just Debug - severityFor (Namespace _ ["TrapTentativeHeader"]) _ = Just Debug - severityFor (Namespace _ ["OutdatedTentativeHeader"]) _ = Just Debug - severityFor _ _ = Nothing - - documentFor (Namespace _ ["SetTentativeHeader"]) = Just - "A new tentative header got set" - documentFor (Namespace _ ["TrapTentativeHeader"]) = Just - "The body of tentative block turned out to be invalid." - documentFor (Namespace _ ["OutdatedTentativeHeader"]) = Just - "We selected a new (better) chain, which cleared the previous tentative header." - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["SetTentativeHeader"] - , Namespace [] ["TrapTentativeHeader"] - , Namespace [] ["OutdatedTentativeHeader"] - ] - - -addedHdrsNewChain :: HasHeader (Header blk) - => AF.AnchoredFragment (Header blk) - -> AF.AnchoredFragment (Header blk) - -> [Header blk] -addedHdrsNewChain fro to_ = - case AF.intersect fro to_ of - Just (_, _, _, s2 :: AF.AnchoredFragment (Header blk)) -> - AF.toOldestFirst s2 - Nothing -> [] -- No sense to do validation here. - --------------------------------------------------------------------------------- --- ChainDB TraceFollowerEvent --------------------------------------------------------------------------------- - -instance (ConvertRawHash blk, StandardHash blk) => - LogFormatting (ChainDB.TraceFollowerEvent blk) where - forHuman ChainDB.NewFollower = "A new Follower was created" - forHuman (ChainDB.FollowerNoLongerInMem _rrs) = mconcat - [ "The follower was in the 'FollowerInMem' state but its point is no longer on" - , " the in-memory chain fragment, so it has to switch to the" - , " 'FollowerInImmutableDB' state" - ] - forHuman (ChainDB.FollowerSwitchToMem point slot) = mconcat - [ "The follower was in the 'FollowerInImmutableDB' state and is switched to" - , " the 'FollowerInMem' state. Point: " <> showT point <> " slot: " <> showT slot - ] - forHuman (ChainDB.FollowerNewImmIterator point slot) = mconcat - [ "The follower is in the 'FollowerInImmutableDB' state but the iterator is" - , " exhausted while the ImmDB has grown, so we open a new iterator to" - , " stream these blocks too. Point: " <> showT point <> " slot: " <> showT slot - ] - - forMachine _dtal ChainDB.NewFollower = - mconcat [ "kind" .= String "NewFollower" ] - forMachine _dtal (ChainDB.FollowerNoLongerInMem _) = - mconcat [ "kind" .= String "FollowerNoLongerInMem" ] - forMachine _dtal (ChainDB.FollowerSwitchToMem _ _) = - mconcat [ "kind" .= String "FollowerSwitchToMem" ] - forMachine _dtal (ChainDB.FollowerNewImmIterator _ _) = - mconcat [ "kind" .= String "FollowerNewImmIterator" ] - -instance MetaTrace (ChainDB.TraceFollowerEvent blk) where - namespaceFor ChainDB.NewFollower = - Namespace [] ["NewFollower"] - namespaceFor ChainDB.FollowerNoLongerInMem {} = - Namespace [] ["FollowerNoLongerInMem"] - namespaceFor ChainDB.FollowerSwitchToMem {} = - Namespace [] ["FollowerSwitchToMem"] - namespaceFor ChainDB.FollowerNewImmIterator {} = - Namespace [] ["FollowerNewImmIterator"] - - severityFor (Namespace _ ["NewFollower"]) _ = Just Debug - severityFor (Namespace _ ["FollowerNoLongerInMem"]) _ = Just Debug - severityFor (Namespace _ ["FollowerSwitchToMem"]) _ = Just Debug - severityFor (Namespace _ ["FollowerNewImmIterator"]) _ = Just Debug - severityFor _ _ = Nothing - - documentFor (Namespace _ ["NewFollower"]) = Just - "A new follower was created." - documentFor (Namespace _ ["FollowerNoLongerInMem"]) = Just $ mconcat - [ "The follower was in 'FollowerInMem' state and is switched to" - , " the 'FollowerInImmutableDB' state." - ] - documentFor (Namespace _ ["FollowerSwitchToMem"]) = Just $ mconcat - [ "The follower was in the 'FollowerInImmutableDB' state and is switched to" - , " the 'FollowerInMem' state." - ] - documentFor (Namespace _ ["FollowerNewImmIterator"]) = Just $ mconcat - [ "The follower is in the 'FollowerInImmutableDB' state but the iterator is" - , " exhausted while the ImmDB has grown, so we open a new iterator to" - , " stream these blocks too." - ] - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["NewFollower"] - , Namespace [] ["FollowerNoLongerInMem"] - , Namespace [] ["FollowerSwitchToMem"] - , Namespace [] ["FollowerNewImmIterator"] - ] - - --------------------------------------------------------------------------------- --- ChainDB TraceCopyToImmutableDB --------------------------------------------------------------------------------- - -instance ConvertRawHash blk - => LogFormatting (ChainDB.TraceCopyToImmutableDBEvent blk) where - forHuman (ChainDB.CopiedBlockToImmutableDB pt) = - "Copied block " <> renderPointAsPhrase pt <> " to the ImmDB" - forHuman ChainDB.NoBlocksToCopyToImmutableDB = - "There are no blocks to copy to the ImmDB" - - forMachine dtals (ChainDB.CopiedBlockToImmutableDB pt) = - mconcat [ "kind" .= String "CopiedBlockToImmutableDB" - , "slot" .= forMachine dtals pt ] - forMachine _dtals ChainDB.NoBlocksToCopyToImmutableDB = - mconcat [ "kind" .= String "NoBlocksToCopyToImmutableDB" ] - -instance MetaTrace (ChainDB.TraceCopyToImmutableDBEvent blk) where - namespaceFor ChainDB.CopiedBlockToImmutableDB {} = - Namespace [] ["CopiedBlockToImmutableDB"] - namespaceFor ChainDB.NoBlocksToCopyToImmutableDB {} = - Namespace [] ["NoBlocksToCopyToImmutableDB"] - - severityFor (Namespace _ ["CopiedBlockToImmutableDB"]) _ = Just Debug - severityFor (Namespace _ ["NoBlocksToCopyToImmutableDB"]) _ = Just Debug - severityFor _ _ = Nothing - - documentFor (Namespace _ ["CopiedBlockToImmutableDB"]) = Just - "A block was successfully copied to the ImmDB." - documentFor (Namespace _ ["NoBlocksToCopyToImmutableDB"]) = Just - "There are no block to copy to the ImmDB." - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["CopiedBlockToImmutableDB"] - , Namespace [] ["NoBlocksToCopyToImmutableDB"] - ] - --- -------------------------------------------------------------------------------- --- -- ChainDB GCEvent --- -------------------------------------------------------------------------------- - -instance LogFormatting (ChainDB.TraceGCEvent blk) where - forHuman (ChainDB.PerformedGC slot) = - "Performed a garbage collection for " <> condenseT slot - forHuman (ChainDB.ScheduledGC slot _difft) = - "Scheduled a garbage collection for " <> condenseT slot - - forMachine dtals (ChainDB.PerformedGC slot) = - mconcat [ "kind" .= String "PerformedGC" - , "slot" .= forMachine dtals slot ] - forMachine dtals (ChainDB.ScheduledGC slot difft) = - mconcat $ [ "kind" .= String "ScheduledGC" - , "slot" .= forMachine dtals slot ] <> - [ "difft" .= String ((Text.pack . show) difft) | dtals >= DDetailed] - -instance MetaTrace (ChainDB.TraceGCEvent blk) where - namespaceFor ChainDB.PerformedGC {} = - Namespace [] ["PerformedGC"] - namespaceFor ChainDB.ScheduledGC {} = - Namespace [] ["ScheduledGC"] - - severityFor (Namespace _ ["PerformedGC"]) _ = Just Debug - severityFor (Namespace _ ["ScheduledGC"]) _ = Just Debug - severityFor _ _ = Nothing - - documentFor (Namespace _ ["PerformedGC"]) = Just - "A garbage collection for the given 'SlotNo' was performed." - documentFor (Namespace _ ["ScheduledGC"]) = Just $ mconcat - [ "A garbage collection for the given 'SlotNo' was scheduled to happen" - , " at the given time." - ] - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["PerformedGC"] - , Namespace [] ["ScheduledGC"] - ] - --- -------------------------------------------------------------------------------- --- -- TraceInitChainSelEvent --- -------------------------------------------------------------------------------- - -instance (ConvertRawHash blk, ConvertRawHash (Header blk), LedgerSupportsProtocol blk) - => LogFormatting (ChainDB.TraceInitChainSelEvent blk) where - forHuman (ChainDB.InitChainSelValidation v) = forHuman v - forHuman ChainDB.InitialChainSelected{} = - "Initial chain selected" - forHuman ChainDB.StartedInitChainSelection {} = - "Started initial chain selection" - - forMachine dtal (ChainDB.InitChainSelValidation v) = - forMachine dtal v - forMachine _dtal ChainDB.InitialChainSelected = - mconcat ["kind" .= String "Follower.InitialChainSelected"] - forMachine _dtal ChainDB.StartedInitChainSelection = - mconcat ["kind" .= String "Follower.StartedInitChainSelection"] - - asMetrics (ChainDB.InitChainSelValidation v) = asMetrics v - asMetrics ChainDB.InitialChainSelected = [] - asMetrics ChainDB.StartedInitChainSelection = [] - -instance MetaTrace (ChainDB.TraceInitChainSelEvent blk) where - namespaceFor ChainDB.InitialChainSelected {} = - Namespace [] ["InitialChainSelected"] - namespaceFor ChainDB.StartedInitChainSelection {} = - Namespace [] ["StartedInitChainSelection"] - namespaceFor (ChainDB.InitChainSelValidation ev') = - nsPrependInner "Validation" (namespaceFor ev') - - severityFor (Namespace _ ["InitialChainSelected"]) _ = Just Info - severityFor (Namespace _ ["StartedInitChainSelection"]) _ = Just Info - severityFor (Namespace out ("Validation" : tl)) - (Just (ChainDB.InitChainSelValidation ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("Validation" : tl)) Nothing = - severityFor (Namespace out tl :: - Namespace (ChainDB.TraceValidationEvent blk)) Nothing - severityFor _ _ = Nothing - - privacyFor (Namespace out ("Validation" : tl)) - (Just (ChainDB.InitChainSelValidation ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("Validation" : tl)) Nothing = - privacyFor (Namespace out tl :: - Namespace (ChainDB.TraceValidationEvent blk)) Nothing - privacyFor _ _ = Just Public - - detailsFor (Namespace out ("Validation" : tl)) - (Just (ChainDB.InitChainSelValidation ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("Validation" : tl)) Nothing = - detailsFor (Namespace out tl :: - Namespace (ChainDB.TraceValidationEvent blk)) Nothing - detailsFor _ _ = Just DNormal - - metricsDocFor (Namespace out ("Validation" : tl)) = - metricsDocFor (Namespace out tl :: Namespace (ChainDB.TraceValidationEvent blk)) - metricsDocFor _ = [] - - documentFor (Namespace _ ["InitialChainSelected"]) = Just - "A garbage collection for the given 'SlotNo' was performed." - documentFor (Namespace _ ["StartedInitChainSelection"]) = Just $ mconcat - [ "A garbage collection for the given 'SlotNo' was scheduled to happen" - , " at the given time." - ] - documentFor (Namespace o ("Validation" : tl)) = - documentFor (Namespace o tl :: Namespace (ChainDB.TraceValidationEvent blk)) - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["InitialChainSelected"] - , Namespace [] ["StartedInitChainSelection"] - ] - ++ map (nsPrependInner "Validation") - (allNamespaces :: [Namespace (ChainDB.TraceValidationEvent blk)]) - - - --------------------------------------------------------------------------------- --- ChainDB TraceValidationEvent --------------------------------------------------------------------------------- - -instance ( LedgerSupportsProtocol blk - , ConvertRawHash (Header blk) - , ConvertRawHash blk - , LogFormatting (RealPoint blk)) - => LogFormatting (ChainDB.TraceValidationEvent blk) where - forHuman (ChainDB.InvalidBlock err pt) = - "Invalid block " <> renderRealPointAsPhrase pt <> ": " <> showT err - forHuman (ChainDB.ValidCandidate c) = - "Valid candidate " <> renderPointAsPhrase (AF.headPoint c) - forHuman (ChainDB.UpdateLedgerDbTraceEvent - (LedgerDB.StartedPushingBlockToTheLedgerDb - (LedgerDB.PushStart start) - (LedgerDB.PushGoal goal) - (LedgerDB.Pushing curr))) = - let fromSlot = unSlotNo $ realPointSlot start - atSlot = unSlotNo $ realPointSlot curr - atDiff = atSlot - fromSlot - toSlot = unSlotNo $ realPointSlot goal - toDiff = toSlot - fromSlot - in - "Pushing ledger state for block " <> renderRealPointAsPhrase curr <> ". Progress: " <> - showProgressT (fromIntegral atDiff) (fromIntegral toDiff) <> "%" - - forMachine dtal (ChainDB.InvalidBlock err pt) = - mconcat [ "kind" .= String "InvalidBlock" - , "block" .= forMachine dtal pt - , "error" .= showT err ] - forMachine dtal (ChainDB.ValidCandidate c) = - mconcat [ "kind" .= String "ValidCandidate" - , "block" .= renderPointForDetails dtal (AF.headPoint c) ] - forMachine _dtal (ChainDB.UpdateLedgerDbTraceEvent - (LedgerDB.StartedPushingBlockToTheLedgerDb - (LedgerDB.PushStart start) - (LedgerDB.PushGoal goal) - (LedgerDB.Pushing curr))) = - mconcat [ "kind" .= String "UpdateLedgerDbTraceEvent.StartedPushingBlockToTheLedgerDb" - , "startingBlock" .= renderRealPoint start - , "currentBlock" .= renderRealPoint curr - , "targetBlock" .= renderRealPoint goal - ] - -instance MetaTrace (ChainDB.TraceValidationEvent blk) where - namespaceFor ChainDB.ValidCandidate {} = - Namespace [] ["ValidCandidate"] - namespaceFor ChainDB.InvalidBlock {} = - Namespace [] ["InvalidBlock"] - namespaceFor ChainDB.UpdateLedgerDbTraceEvent {} = - Namespace [] ["UpdateLedgerDb"] - - severityFor (Namespace _ ["ValidCandidate"]) _ = Just Info - severityFor (Namespace _ ["InvalidBlock"]) _ = Just Error - severityFor (Namespace _ ["UpdateLedgerDb"]) _ = Just Debug - severityFor _ _ = Nothing - - documentFor (Namespace _ ["ValidCandidate"]) = Just $ mconcat - [ "An event traced during validating performed while adding a block." - , " A candidate chain was valid." - ] - documentFor (Namespace _ ["InvalidBlock"]) = Just $ mconcat - [ "An event traced during validating performed while adding a block." - , " A point was found to be invalid." - ] - documentFor (Namespace _ ["UpdateLedgerDb"]) = Just "" - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["ValidCandidate"] - , Namespace [] ["InvalidBlock"] - , Namespace [] ["UpdateLedgerDb"] - ] - --------------------------------------------------------------------------------- --- TraceOpenEvent --------------------------------------------------------------------------------- - -instance ConvertRawHash blk - => LogFormatting (ChainDB.TraceOpenEvent blk) where - forHuman (ChainDB.OpenedDB immTip tip') = - "Opened db with immutable tip at " <> renderPointAsPhrase immTip <> - " and tip " <> renderPointAsPhrase tip' - forHuman (ChainDB.ClosedDB immTip tip') = - "Closed db with immutable tip at " <> renderPointAsPhrase immTip <> - " and tip " <> renderPointAsPhrase tip' - forHuman (ChainDB.OpenedImmutableDB immTip chunk) = - "Opened imm db with immutable tip at " <> renderPointAsPhrase immTip <> - " and chunk " <> showT chunk - forHuman (ChainDB.OpenedVolatileDB mx) = "Opened " <> case mx of - NoMaxSlotNo -> "empty Volatile DB" - MaxSlotNo mxx -> "Volatile DB with max slot seen " <> showT mxx - forHuman ChainDB.OpenedLgrDB = "Opened lgr db" - forHuman ChainDB.StartedOpeningDB = "Started opening Chain DB" - forHuman ChainDB.StartedOpeningImmutableDB = "Started opening Immutable DB" - forHuman ChainDB.StartedOpeningVolatileDB = "Started opening Volatile DB" - forHuman ChainDB.StartedOpeningLgrDB = "Started opening Ledger DB" - - forMachine dtal (ChainDB.OpenedDB immTip tip')= - mconcat [ "kind" .= String "OpenedDB" - , "immtip" .= forMachine dtal immTip - , "tip" .= forMachine dtal tip' ] - forMachine dtal (ChainDB.ClosedDB immTip tip') = - mconcat [ "kind" .= String "TraceOpenEvent.ClosedDB" - , "immtip" .= forMachine dtal immTip - , "tip" .= forMachine dtal tip' ] - forMachine dtal (ChainDB.OpenedImmutableDB immTip epoch) = - mconcat [ "kind" .= String "OpenedImmutableDB" - , "immtip" .= forMachine dtal immTip - , "epoch" .= String ((Text.pack . show) epoch) ] - forMachine _dtal (ChainDB.OpenedVolatileDB maxSlotN) = - mconcat [ "kind" .= String "OpenedVolatileDB" - , "maxSlotNo" .= String (showT maxSlotN) ] - forMachine _dtal ChainDB.OpenedLgrDB = - mconcat [ "kind" .= String "OpenedLgrDB" ] - forMachine _dtal ChainDB.StartedOpeningDB = - mconcat ["kind" .= String "StartedOpeningDB"] - forMachine _dtal ChainDB.StartedOpeningImmutableDB = - mconcat ["kind" .= String "StartedOpeningImmutableDB"] - forMachine _dtal ChainDB.StartedOpeningVolatileDB = - mconcat ["kind" .= String "StartedOpeningVolatileDB"] - forMachine _dtal ChainDB.StartedOpeningLgrDB = - mconcat ["kind" .= String "StartedOpeningLgrDB"] - -instance MetaTrace (ChainDB.TraceOpenEvent blk) where - namespaceFor ChainDB.OpenedDB {} = - Namespace [] ["OpenedDB"] - namespaceFor ChainDB.ClosedDB {} = - Namespace [] ["ClosedDB"] - namespaceFor ChainDB.OpenedImmutableDB {} = - Namespace [] ["OpenedImmutableDB"] - namespaceFor ChainDB.OpenedVolatileDB {} = - Namespace [] ["OpenedVolatileDB"] - namespaceFor ChainDB.OpenedLgrDB {} = - Namespace [] ["OpenedLgrDB"] - namespaceFor ChainDB.StartedOpeningDB {} = - Namespace [] ["StartedOpeningDB"] - namespaceFor ChainDB.StartedOpeningImmutableDB {} = - Namespace [] ["StartedOpeningImmutableDB"] - namespaceFor ChainDB.StartedOpeningVolatileDB {} = - Namespace [] ["StartedOpeningVolatileDB"] - namespaceFor ChainDB.StartedOpeningLgrDB {} = - Namespace [] ["StartedOpeningLgrDB"] - - severityFor (Namespace _ ["OpenedDB"]) _ = Just Info - severityFor (Namespace _ ["ClosedDB"]) _ = Just Info - severityFor (Namespace _ ["OpenedImmutableDB"]) _ = Just Info - severityFor (Namespace _ ["OpenedVolatileDB"]) _ = Just Info - severityFor (Namespace _ ["OpenedLgrDB"]) _ = Just Info - severityFor (Namespace _ ["StartedOpeningDB"]) _ = Just Info - severityFor (Namespace _ ["StartedOpeningImmutableDB"]) _ = Just Info - severityFor (Namespace _ ["StartedOpeningVolatileDB"]) _ = Just Info - severityFor (Namespace _ ["StartedOpeningLgrDB"]) _ = Just Info - severityFor _ _ = Nothing - - documentFor (Namespace _ ["OpenedDB"]) = Just - "The ChainDB was opened." - documentFor (Namespace _ ["ClosedDB"]) = Just - "The ChainDB was closed." - documentFor (Namespace _ ["OpenedImmutableDB"]) = Just - "The ImmDB was opened." - documentFor (Namespace _ ["OpenedVolatileDB"]) = Just - "The VolatileDB was opened." - documentFor (Namespace _ ["OpenedLgrDB"]) = Just - "The LedgerDB was opened." - documentFor (Namespace _ ["StartedOpeningDB"]) = Just - "The ChainDB is being opened." - documentFor (Namespace _ ["StartedOpeningImmutableDB"]) = Just - "The ImmDB is being opened." - documentFor (Namespace _ ["StartedOpeningVolatileDB"]) = Just - "The VolatileDB is being opened." - documentFor (Namespace _ ["StartedOpeningLgrDB"]) = Just - "The LedgerDB is being opened." - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["OpenedDB"] - , Namespace [] ["ClosedDB"] - , Namespace [] ["OpenedImmutableDB"] - , Namespace [] ["OpenedVolatileDB"] - , Namespace [] ["OpenedLgrDB"] - , Namespace [] ["StartedOpeningDB"] - , Namespace [] ["StartedOpeningImmutableDB"] - , Namespace [] ["StartedOpeningVolatileDB"] - , Namespace [] ["StartedOpeningLgrDB"] - ] - --------------------------------------------------------------------------------- --- IteratorEvent --------------------------------------------------------------------------------- - -instance ( StandardHash blk - , ConvertRawHash blk - ) => LogFormatting (ChainDB.TraceIteratorEvent blk) where - forHuman (ChainDB.UnknownRangeRequested ev') = forHuman ev' - forHuman (ChainDB.BlockMissingFromVolatileDB realPt) = mconcat - [ "This block is no longer in the VolatileDB because it has been garbage" - , " collected. It might now be in the ImmDB if it was part of the" - , " current chain. Block: " <> renderRealPoint realPt - ] - forHuman (ChainDB.StreamFromImmutableDB sFrom sTo) = mconcat - [ "Stream only from the ImmDB. StreamFrom:" <> showT sFrom - , " StreamTo: " <> showT sTo - ] - forHuman (ChainDB.StreamFromBoth sFrom sTo pts) = mconcat - [ "Stream from both the VolatileDB and the ImmDB." - , " StreamFrom: " <> showT sFrom <> " StreamTo: " <> showT sTo - , " Points: " <> showT (map renderRealPoint pts) - ] - forHuman (ChainDB.StreamFromVolatileDB sFrom sTo pts) = mconcat - [ "Stream only from the VolatileDB." - , " StreamFrom: " <> showT sFrom <> " StreamTo: " <> showT sTo - , " Points: " <> showT (map renderRealPoint pts) - ] - forHuman (ChainDB.BlockWasCopiedToImmutableDB pt) = mconcat - [ "This block has been garbage collected from the VolatileDB is now" - , " found and streamed from the ImmDB. Block: " <> renderRealPoint pt - ] - forHuman (ChainDB.BlockGCedFromVolatileDB pt) = mconcat - [ "This block no longer in the VolatileDB and isn't in the ImmDB" - , " either; it wasn't part of the current chain. Block: " <> renderRealPoint pt - ] - forHuman ChainDB.SwitchBackToVolatileDB = "SwitchBackToVolatileDB" - - forMachine _dtal (ChainDB.UnknownRangeRequested unkRange) = - mconcat [ "kind" .= String "UnknownRangeRequested" - , "range" .= String (showT unkRange) - ] - forMachine _dtal (ChainDB.StreamFromVolatileDB streamFrom streamTo realPt) = - mconcat [ "kind" .= String "StreamFromVolatileDB" - , "from" .= String (showT streamFrom) - , "to" .= String (showT streamTo) - , "point" .= String (Text.pack . show $ map renderRealPoint realPt) - ] - forMachine _dtal (ChainDB.StreamFromImmutableDB streamFrom streamTo) = - mconcat [ "kind" .= String "StreamFromImmutableDB" - , "from" .= String (showT streamFrom) - , "to" .= String (showT streamTo) - ] - forMachine _dtal (ChainDB.StreamFromBoth streamFrom streamTo realPt) = - mconcat [ "kind" .= String "StreamFromBoth" - , "from" .= String (showT streamFrom) - , "to" .= String (showT streamTo) - , "point" .= String (Text.pack . show $ map renderRealPoint realPt) - ] - forMachine _dtal (ChainDB.BlockMissingFromVolatileDB realPt) = - mconcat [ "kind" .= String "BlockMissingFromVolatileDB" - , "point" .= String (renderRealPoint realPt) - ] - forMachine _dtal (ChainDB.BlockWasCopiedToImmutableDB realPt) = - mconcat [ "kind" .= String "BlockWasCopiedToImmutableDB" - , "point" .= String (renderRealPoint realPt) - ] - forMachine _dtal (ChainDB.BlockGCedFromVolatileDB realPt) = - mconcat [ "kind" .= String "BlockGCedFromVolatileDB" - , "point" .= String (renderRealPoint realPt) - ] - forMachine _dtal ChainDB.SwitchBackToVolatileDB = - mconcat ["kind" .= String "SwitchBackToVolatileDB" - ] - -instance MetaTrace (ChainDB.TraceIteratorEvent blk) where - namespaceFor (ChainDB.UnknownRangeRequested ur) = - nsPrependInner "UnknownRangeRequested" (namespaceFor ur) - namespaceFor ChainDB.StreamFromVolatileDB {} = - Namespace [] ["StreamFromVolatileDB"] - namespaceFor ChainDB.StreamFromImmutableDB {} = - Namespace [] ["StreamFromImmutableDB"] - namespaceFor ChainDB.StreamFromBoth {} = - Namespace [] ["StreamFromBoth"] - namespaceFor ChainDB.BlockMissingFromVolatileDB {} = - Namespace [] ["BlockMissingFromVolatileDB"] - namespaceFor ChainDB.BlockWasCopiedToImmutableDB {} = - Namespace [] ["BlockWasCopiedToImmutableDB"] - namespaceFor ChainDB.BlockGCedFromVolatileDB {} = - Namespace [] ["BlockGCedFromVolatileDB"] - namespaceFor ChainDB.SwitchBackToVolatileDB {} = - Namespace [] ["SwitchBackToVolatileDB"] - - - severityFor (Namespace out ("UnknownRangeRequested" : tl)) - (Just (ChainDB.UnknownRangeRequested ur)) = - severityFor (Namespace out tl) (Just ur) - severityFor (Namespace out ("UnknownRangeRequested" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (ChainDB.UnknownRange blk)) Nothing - severityFor _ _ = Just Debug - - privacyFor (Namespace out ("UnknownRangeRequested" : tl)) - (Just (ChainDB.UnknownRangeRequested ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("UnknownRangeRequested" : tl)) Nothing = - privacyFor (Namespace out tl :: - Namespace (ChainDB.UnknownRange blk)) Nothing - privacyFor _ _ = Just Public - - detailsFor (Namespace out ("UnknownRangeRequested" : tl)) - (Just (ChainDB.UnknownRangeRequested ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("UnknownRangeRequested" : tl)) Nothing = - detailsFor (Namespace out tl :: - Namespace (ChainDB.UnknownRange blk)) Nothing - detailsFor _ _ = Just DNormal - - documentFor (Namespace out ("UnknownRangeRequested" : tl)) = - documentFor (Namespace out tl :: Namespace (ChainDB.UnknownRange blk)) - documentFor (Namespace _ ["StreamFromVolatileDB"]) = Just - "Stream only from the VolatileDB." - documentFor (Namespace _ ["StreamFromImmutableDB"]) = Just - "Stream only from the ImmDB." - documentFor (Namespace _ ["StreamFromBoth"]) = Just - "Stream from both the VolatileDB and the ImmDB." - documentFor (Namespace _ ["BlockMissingFromVolatileDB"]) = Just $ mconcat - [ "A block is no longer in the VolatileDB because it has been garbage" - , " collected. It might now be in the ImmDB if it was part of the" - , " current chain." - ] - documentFor (Namespace _ ["BlockWasCopiedToImmutableDB"]) = Just $ mconcat - [ "A block that has been garbage collected from the VolatileDB is now" - , " found and streamed from the ImmDB." - ] - documentFor (Namespace _ ["BlockGCedFromVolatileDB"]) = Just $ mconcat - [ "A block is no longer in the VolatileDB and isn't in the ImmDB" - , " either; it wasn't part of the current chain." - ] - documentFor (Namespace _ ["SwitchBackToVolatileDB"]) = Just $ mconcat - [ "We have streamed one or more blocks from the ImmDB that were part" - , " of the VolatileDB when initialising the iterator. Now, we have to look" - , " back in the VolatileDB again because the ImmDB doesn't have the" - , " next block we're looking for." - ] - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["StreamFromVolatileDB"] - , Namespace [] ["StreamFromImmutableDB"] - , Namespace [] ["StreamFromBoth"] - , Namespace [] ["BlockMissingFromVolatileDB"] - , Namespace [] ["BlockWasCopiedToImmutableDB"] - , Namespace [] ["BlockGCedFromVolatileDB"] - , Namespace [] ["SwitchBackToVolatileDB"] - ] - ++ map (nsPrependInner "UnknownRangeRequested") - (allNamespaces :: [Namespace (ChainDB.UnknownRange blk)]) - --------------------------------------------------------------------------------- --- UnknownRange --------------------------------------------------------------------------------- - -instance ( StandardHash blk - , ConvertRawHash blk - ) => LogFormatting (ChainDB.UnknownRange blk) where - forHuman (ChainDB.MissingBlock realPt) = - "The block at the given point was not found in the ChainDB." - <> renderRealPoint realPt - forHuman (ChainDB.ForkTooOld streamFrom) = - "The requested range forks off too far in the past" - <> showT streamFrom - - forMachine _dtal (ChainDB.MissingBlock realPt) = - mconcat [ "kind" .= String "MissingBlock" - , "point" .= String (renderRealPoint realPt) - ] - forMachine _dtal (ChainDB.ForkTooOld streamFrom) = - mconcat [ "kind" .= String "ForkTooOld" - , "from" .= String (showT streamFrom) - ] - -instance MetaTrace (ChainDB.UnknownRange blk) where - namespaceFor ChainDB.MissingBlock {} = Namespace [] ["MissingBlock"] - namespaceFor ChainDB.ForkTooOld {} = Namespace [] ["ForkTooOld"] - - severityFor _ _ = Just Debug - - documentFor (Namespace _ ["MissingBlock"]) = Just - "" - documentFor (Namespace _ ["ForkTooOld"]) = Just - "" - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["MissingBlock"] - , Namespace [] ["ForkTooOld"] - ] - --- -------------------------------------------------------------------------------- --- -- Peras --- -------------------------------------------------------------------------------- - -instance MetaTrace (PerasVoteDB.TraceEvent blk) where - namespaceFor (PerasVoteDB.AddVote {}) = Namespace [] ["AddVote"] - namespaceFor (PerasVoteDB.GarbageCollected {}) = Namespace [] ["GarbageCollected"] - allNamespaces = - [ Namespace [] ["AddVote"] - , Namespace [] ["GarbageCollected"] - ] - - severityFor _ _ = Just Info - privacyFor _ _ = Just Public - detailsFor _ _ = Just DNormal - - documentFor (Namespace _ ["AddVote"]) = Just "AddVote" - documentFor (Namespace _ ["GarbageCollected"]) = Just "GarbageCollected" - documentFor _ = Nothing - -instance StandardHash blk => LogFormatting (PerasVoteDB.TraceEvent blk) where - forHuman (PerasVoteDB.AddVote voteId _vote result) = - "Peras vote " <> Text.pack (show voteId) <> ": " <> Text.pack (show result) - forHuman (PerasVoteDB.GarbageCollected slotNo) = - "Peras vote DB garbage collected at slot " <> Text.pack (show slotNo) - - forMachine _dtal (PerasVoteDB.AddVote voteId _vote result) = - mconcat [ "kind" .= String "AddVote" - , "voteId" .= String (Text.pack $ show voteId) - , "result" .= String (Text.pack $ show result) - ] - forMachine _dtal (PerasVoteDB.GarbageCollected slotNo) = - mconcat [ "kind" .= String "GarbageCollected" - , "slot" .= String (Text.pack $ show slotNo) - ] - - asMetrics _ = [] - -instance MetaTrace (PerasCertDB.TraceEvent blk) where - namespaceFor (PerasCertDB.AddCert {}) = Namespace [] ["AddCert"] - namespaceFor (PerasCertDB.GarbageCollected _) = Namespace [] ["GarbageCollected"] - allNamespaces = - [ Namespace [] ["AddCert"] - , Namespace [] ["GarbageCollected"] - ] - - severityFor _ _ = Just Info - privacyFor _ _ = Just Public - detailsFor _ _ = Just DNormal - - documentFor (Namespace _ ["AddCert"]) = Just "AddCert" - documentFor (Namespace _ ["GarbageCollected"]) = Just "GarbageCollected" - documentFor _ = Nothing - -instance LogFormatting (PerasCertDB.TraceEvent blk) where - forHuman (PerasCertDB.AddCert roundNo _cert result) = - "Peras certificate for round " <> Text.pack (show roundNo) <> ": " <> Text.pack (show result) - forHuman (PerasCertDB.GarbageCollected slotNo) = - "Peras certificate DB garbage collected at slot " <> Text.pack (show slotNo) - - forMachine _dtal (PerasCertDB.AddCert roundNo _cert result) = - mconcat [ "kind" .= String "AddCert" - , "round" .= String (Text.pack $ show roundNo) - , "result" .= String (Text.pack $ show result) - ] - forMachine _dtal (PerasCertDB.GarbageCollected slotNo) = - mconcat [ "kind" .= String "GarbageCollected" - , "slot" .= String (Text.pack $ show slotNo) - ] - - asMetrics _ = [] - - --- -------------------------------------------------------------------------------- --- -- LedgerDB.TraceEvent --- -------------------------------------------------------------------------------- - -instance ( StandardHash blk - , ConvertRawHash blk) - => LogFormatting (LedgerDB.TraceEvent blk) where - - forMachine dtals (LedgerDB.LedgerDBSnapshotEvent ev) = forMachine dtals ev - forMachine dtals (LedgerDB.LedgerReplayEvent ev) = forMachine dtals ev - forMachine dtals (LedgerDB.LedgerDBForkerEvent ev) = forMachine dtals ev - forMachine dtals (LedgerDB.LedgerDBFlavorImplEvent ev) = forMachine dtals ev - - forHuman (LedgerDB.LedgerDBSnapshotEvent ev) = forHuman ev - forHuman (LedgerDB.LedgerReplayEvent ev) = forHuman ev - forHuman (LedgerDB.LedgerDBForkerEvent ev) = forHuman ev - forHuman (LedgerDB.LedgerDBFlavorImplEvent ev) = forHuman ev - -instance MetaTrace (LedgerDB.TraceEvent blk) where - - namespaceFor (LedgerDB.LedgerDBSnapshotEvent ev) = - nsPrependInner "Snapshot" (namespaceFor ev) - namespaceFor (LedgerDB.LedgerReplayEvent ev) = - nsPrependInner "Replay" (namespaceFor ev) - namespaceFor (LedgerDB.LedgerDBForkerEvent ev) = - nsPrependInner "Forker" (namespaceFor ev) - namespaceFor (LedgerDB.LedgerDBFlavorImplEvent ev) = - nsPrependInner "Flavor" (namespaceFor ev) - - severityFor (Namespace out ("Snapshot" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (LedgerDB.TraceSnapshotEvent blk)) Nothing - severityFor (Namespace out ("Snapshot" : tl)) (Just (LedgerDB.LedgerDBSnapshotEvent ev)) = - severityFor (Namespace out tl :: Namespace (LedgerDB.TraceSnapshotEvent blk)) (Just ev) - severityFor (Namespace out ("Replay" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (LedgerDB.TraceReplayEvent blk)) Nothing - severityFor (Namespace out ("Replay" : tl)) (Just (LedgerDB.LedgerReplayEvent ev)) = - severityFor (Namespace out tl :: Namespace (LedgerDB.TraceReplayEvent blk)) (Just ev) - severityFor (Namespace out ("Forker" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace LedgerDB.TraceForkerEventWithKey) Nothing - severityFor (Namespace out ("Forker" : tl)) (Just (LedgerDB.LedgerDBForkerEvent ev)) = - severityFor (Namespace out tl :: Namespace LedgerDB.TraceForkerEventWithKey) (Just ev) - severityFor (Namespace out ("Flavor" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace LedgerDB.FlavorImplSpecificTrace) Nothing - severityFor (Namespace out ("Flavor" : tl)) (Just (LedgerDB.LedgerDBFlavorImplEvent ev)) = - severityFor (Namespace out tl :: Namespace LedgerDB.FlavorImplSpecificTrace) (Just ev) - severityFor _ _ = Nothing - - documentFor (Namespace o ("Snapshot" : tl)) = - documentFor (Namespace o tl :: Namespace (LedgerDB.TraceSnapshotEvent blk)) - documentFor (Namespace o ("Replay" : tl)) = - documentFor (Namespace o tl :: Namespace (LedgerDB.TraceReplayEvent blk)) - documentFor (Namespace o ("Forker" : tl)) = - documentFor (Namespace o tl :: Namespace LedgerDB.TraceForkerEventWithKey) - documentFor (Namespace o ("Flavor" : tl)) = - documentFor (Namespace o tl :: Namespace LedgerDB.FlavorImplSpecificTrace) - documentFor _ = Nothing - - allNamespaces = - map (nsPrependInner "Snapshot") - (allNamespaces :: [Namespace (LedgerDB.TraceSnapshotEvent blk)]) - ++ map (nsPrependInner "Replay") - (allNamespaces :: [Namespace (LedgerDB.TraceReplayEvent blk)]) - ++ map (nsPrependInner "Forker") - (allNamespaces :: [Namespace LedgerDB.TraceForkerEventWithKey]) - ++ map (nsPrependInner "Flavor") - (allNamespaces :: [Namespace LedgerDB.FlavorImplSpecificTrace]) - -instance ( StandardHash blk - , ConvertRawHash blk) - => LogFormatting (LedgerDB.TraceSnapshotEvent blk) where - forHuman (LedgerDB.SnapshotRequestDelayed _snapshotRequestTime delayBeforeSnapshotting slots) = - Text.unwords [ "Scheduling to take ledger state snapshots at slots " - , showT (NonEmpty.toList slots) - , ", with a randomised delay of" - , showT delayBeforeSnapshotting - ] - forHuman LedgerDB.SnapshotRequestCompleted = "Completed taking a ledger state snapshot" - forHuman (LedgerDB.TookSnapshot snap pt RisingEdge) = - Text.unwords [ "Taking ledger snapshot" - , showT snap - , "at" - , renderRealPointAsPhrase pt - ] - forHuman (LedgerDB.TookSnapshot snap pt (FallingEdgeWith t)) = - Text.unwords [ "Took ledger snapshot" - , showT snap - , "at" - , renderRealPointAsPhrase pt - , ", duration:" - , showT t - ] - forHuman (LedgerDB.DeletedSnapshot snap) = - Text.unwords ["Deleted old snapshot", showT snap] - forHuman (LedgerDB.InvalidSnapshot snap failure) = - Text.unwords [ "Invalid snapshot" - , showT snap - , showT failure - , context - ] - where - context = case failure of - LedgerDB.InitFailureRead LedgerDB.ReadSnapshotFailed{} -> - " This is most likely an expected change in the serialization format," - <> " which currently requires a chain replay" - LedgerDB.InitFailureRead LedgerDB.ReadSnapshotDataCorruption -> - " The snapshot fails the CRC check. It seems there has been disk corruption" - LedgerDB.InitFailureRead (LedgerDB.ReadMetadataError _ err) -> case err of - LedgerDB.MetadataFileDoesNotExist -> - " The snapshot doesn't have the required metadata file." - LedgerDB.MetadataInvalid errMsg -> - " Snapshot metadata file failed to deserialize: " <> showT errMsg - LedgerDB.MetadataBackendMismatch -> - " Snapshot was created for a different backend. Convert it with `snapshot-converter`." - _ -> "" - - forMachine _dtals (LedgerDB.SnapshotRequestDelayed snapshotRequestTime delayBeforeSnapshotting slots) = - mconcat [ "kind" .= String "SnapshotRequestDelayed" - , "requestTime" .= show snapshotRequestTime - , "delayBeforeSnapshotting" .= show delayBeforeSnapshotting - , "slots" .= toJSON (NonEmpty.toList slots) - ] - forMachine _dtals LedgerDB.SnapshotRequestCompleted = - mconcat [ "kind" .= String "SnapshotRequestCompleted" - ] - forMachine dtals (LedgerDB.TookSnapshot snap pt enclosedTiming) = - mconcat [ "kind" .= String "TookSnapshot" - , "snapshot" .= forMachine dtals snap - , "tip" .= show pt - , "enclosedTime" .= enclosingValue enclosedTiming - ] - forMachine dtals (LedgerDB.DeletedSnapshot snap) = - mconcat [ "kind" .= String "DeletedSnapshot" - , "snapshot" .= forMachine dtals snap ] - forMachine dtals (LedgerDB.InvalidSnapshot snap failure) = - mconcat [ "kind" .= String "InvalidSnapshot" - , "snapshot" .= forMachine dtals snap - , "failure" .= show failure ] - -instance MetaTrace (LedgerDB.TraceSnapshotEvent blk) where - namespaceFor LedgerDB.SnapshotRequestDelayed {} = Namespace [] ["SnapshotRequestDelayed"] - namespaceFor LedgerDB.SnapshotRequestCompleted {} = Namespace [] ["SnapshotRequestCompleted"] - namespaceFor LedgerDB.TookSnapshot {} = Namespace [] ["TookSnapshot"] - namespaceFor LedgerDB.DeletedSnapshot {} = Namespace [] ["DeletedSnapshot"] - namespaceFor LedgerDB.InvalidSnapshot {} = Namespace [] ["InvalidSnapshot"] - - severityFor (Namespace _ ["SnapshotRequestDelayed"]) _ = Just Debug - severityFor (Namespace _ ["SnapshotRequestCompleted"]) _ = Just Debug - severityFor (Namespace _ ["TookSnapshot"]) _ = Just Info - severityFor (Namespace _ ["DeletedSnapshot"]) _ = Just Debug - severityFor (Namespace _ ["InvalidSnapshot"]) _ = Just Error - severityFor _ _ = Nothing - - documentFor (Namespace _ ["TookSnapshot"]) = Just $ mconcat - [ "A snapshot is being written to disk. Two events will be traced, one" - , " for when the node starts taking the snapshot and another one for" - , " when the snapshot has been written to the disk." - ] - documentFor (Namespace _ ["DeletedSnapshot"]) = Just - "A snapshot was deleted from the disk." - documentFor (Namespace _ ["InvalidSnapshot"]) = Just $ mconcat - [ "An on disk snapshot was invalid. Unless it was suffixed or" - , " seems to be from an old node or different backend, it will" - , " be deleted" - ] - documentFor (Namespace _ ["SnapshotRequestDelayed"]) = Just - "A delayed snapshot request was issued. The snapshot will be initiated at the specified timestamp, with the specified delay and for the specified slots" - documentFor (Namespace _ ["SnapshotRequestCompleted"]) = Just - "The delayed snapshot request was completed" - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["TookSnapshot"] - , Namespace [] ["DeletedSnapshot"] - , Namespace [] ["InvalidSnapshot"] - , Namespace [] ["SnapshotRequestDelayed"] - , Namespace [] ["SnapshotRequestCompleted"] - ] - --------------------------------------------------------------------------------- --- LedgerDB TraceReplayEvent --------------------------------------------------------------------------------- - -instance (StandardHash blk, ConvertRawHash blk) - => LogFormatting (LedgerDB.TraceReplayEvent blk) where - - forHuman (LedgerDB.TraceReplayStartEvent ev') = forHuman ev' - forHuman (LedgerDB.TraceReplayProgressEvent ev') = forHuman ev' - - forMachine dtal (LedgerDB.TraceReplayStartEvent ev') = forMachine dtal ev' - forMachine dtal (LedgerDB.TraceReplayProgressEvent ev') = forMachine dtal ev' - -instance (StandardHash blk, ConvertRawHash blk) - => LogFormatting (LedgerDB.TraceReplayStartEvent blk) where - forHuman LedgerDB.ReplayFromGenesis = - "Replaying ledger from genesis" - forHuman (LedgerDB.ReplayFromSnapshot snap (LedgerDB.ReplayStart tip')) = - "Replaying ledger from snapshot " <> showT snap <> " at " <> - renderPointAsPhrase tip' - - forMachine _dtal LedgerDB.ReplayFromGenesis = - mconcat [ "kind" .= String "ReplayFromGenesis" ] - forMachine dtal (LedgerDB.ReplayFromSnapshot snap tip') = - mconcat [ "kind" .= String "ReplayFromSnapshot" - , "snapshot" .= forMachine dtal snap - , "tip" .= showT tip' ] - -instance (StandardHash blk, ConvertRawHash blk) - => LogFormatting (LedgerDB.TraceReplayProgressEvent blk) where - forHuman (LedgerDB.ReplayedBlock - pt - _ledgerEvents - (LedgerDB.ReplayStart replayFrom) - (LedgerDB.ReplayGoal replayTo)) = - let fromSlot = withOrigin 0 id $ unSlotNo <$> pointSlot replayFrom - atSlot = unSlotNo $ realPointSlot pt - atDiff = atSlot - fromSlot - toSlot = withOrigin 0 id $ unSlotNo <$> pointSlot replayTo - toDiff = toSlot - fromSlot - in - "Replayed block: slot " - <> showT atSlot - <> " out of " - <> showT toSlot - <> ". Progress: " - <> showProgressT (fromIntegral atDiff) (fromIntegral toDiff) - <> "%" - - forMachine _dtal (LedgerDB.ReplayedBlock - pt - _ledgerEvents - _ - (LedgerDB.ReplayGoal replayTo)) = - mconcat [ "kind" .= String "ReplayedBlock" - , "slot" .= unSlotNo (realPointSlot pt) - , "tip" .= withOrigin 0 unSlotNo (pointSlot replayTo) ] - -instance MetaTrace (LedgerDB.TraceReplayEvent blk) where - namespaceFor (LedgerDB.TraceReplayStartEvent ev) = - nsPrependInner "ReplayStart" (namespaceFor ev) - namespaceFor (LedgerDB.TraceReplayProgressEvent ev) = - nsPrependInner "ReplayProgress" (namespaceFor ev) - - severityFor (Namespace out ("ReplayStart" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (LedgerDB.TraceReplayStartEvent blk)) Nothing - severityFor (Namespace out ("ReplayStart" : tl)) (Just (LedgerDB.TraceReplayStartEvent ev)) = - severityFor (Namespace out tl :: Namespace (LedgerDB.TraceReplayStartEvent blk)) (Just ev) - severityFor (Namespace out ("ReplayProgress" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (LedgerDB.TraceReplayProgressEvent blk)) Nothing - severityFor (Namespace out ("ReplayProgress" : tl)) (Just (LedgerDB.TraceReplayProgressEvent ev)) = - severityFor (Namespace out tl :: Namespace (LedgerDB.TraceReplayProgressEvent blk)) (Just ev) - severityFor _ _ = Nothing - - documentFor (Namespace out ("ReplayStart" : tl)) = - documentFor (Namespace out tl :: Namespace (LedgerDB.TraceReplayStartEvent blk)) - documentFor (Namespace out ("ReplayProgress" : tl)) = - documentFor (Namespace out tl :: Namespace (LedgerDB.TraceReplayProgressEvent blk)) - documentFor _ = Nothing - - allNamespaces = - map (nsPrependInner "ReplayStart") - (allNamespaces :: [Namespace (LedgerDB.TraceReplayStartEvent blk)]) - ++ map (nsPrependInner "ReplayProgress") - (allNamespaces :: [Namespace (LedgerDB.TraceReplayProgressEvent blk)]) - -instance MetaTrace (LedgerDB.TraceReplayStartEvent blk) where - namespaceFor LedgerDB.ReplayFromGenesis {} = Namespace [] ["ReplayFromGenesis"] - namespaceFor LedgerDB.ReplayFromSnapshot {} = Namespace [] ["ReplayFromSnapshot"] - - severityFor (Namespace _ ["ReplayFromGenesis"]) _ = Just Info - severityFor (Namespace _ ["ReplayFromSnapshot"]) _ = Just Info - severityFor _ _ = Nothing - - documentFor (Namespace _ ["ReplayFromGenesis"]) = Just $ mconcat - [ "There were no LedgerDB snapshots on disk, so we're replaying all" - , " blocks starting from Genesis against the initial ledger." - , " The @replayTo@ parameter corresponds to the block at the tip of the" - , " ImmDB, i.e., the last block to replay." - ] - documentFor (Namespace _ ["ReplayFromSnapshot"]) = Just $ mconcat - [ "There was a LedgerDB snapshot on disk corresponding to the given tip." - , " We're replaying more recent blocks against it." - , " The @replayTo@ parameter corresponds to the block at the tip of the" - , " ImmDB, i.e., the last block to replay." - ] - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["ReplayFromGenesis"] - , Namespace [] ["ReplayFromSnapshot"] - ] - -instance MetaTrace (LedgerDB.TraceReplayProgressEvent blk) where - namespaceFor LedgerDB.ReplayedBlock {} = Namespace [] ["ReplayedBlock"] - - severityFor (Namespace _ ["ReplayedBlock"]) _ = Just Info - severityFor _ _ = Nothing - - documentFor (Namespace _ ["ReplayedBlock"]) = Just $ mconcat - [ "We replayed the given block (reference) on the genesis snapshot" - , " during the initialisation of the LedgerDB." - , "\n" - , " The @blockInfo@ parameter corresponds replayed block and the @replayTo@" - , " parameter corresponds to the block at the tip of the ImmDB, i.e.," - , " the last block to replay." - ] - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["ReplayedBlock"] - ] - --------------------------------------------------------------------------------- --- Forker events --------------------------------------------------------------------------------- - -instance LogFormatting LedgerDB.TraceForkerEventWithKey where - forMachine dtals (LedgerDB.TraceForkerEventWithKey k ev) = - (\ev' -> mconcat [ "key" .= showT k, "event" .= ev' ]) $ forMachine dtals ev - forHuman (LedgerDB.TraceForkerEventWithKey k ev) = - "Forker " <> showT k <> ": " <> forHuman ev - -instance LogFormatting LedgerDB.TraceForkerEvent where - forMachine _dtals LedgerDB.ForkerOpen = - mconcat [ "kind" .= String "ForkerOpen" ] - forMachine _dtals (LedgerDB.ForkerReadTables e) = - mconcat [ "kind" .= String "ForkerReadTables" - , "edge" .= case e of - RisingEdge -> String "RisingEdge" - FallingEdgeWith t -> toJSON t - ] - forMachine _dtals (LedgerDB.ForkerRangeReadTables e) = - mconcat [ "kind" .= String "ForkerRangeReadTables" - , "edge" .= case e of - RisingEdge -> String "RisingEdge" - FallingEdgeWith t -> toJSON t - ] - forMachine _dtals LedgerDB.ForkerReadStatistics = mempty - forMachine _dtals (LedgerDB.ForkerPush e) = - mconcat [ "kind" .= String "ForkerPush" - , "edge" .= case e of - RisingEdge -> String "RisingEdge" - FallingEdgeWith t -> toJSON t - ] - forMachine _dtals (LedgerDB.ForkerClose wc) = - mconcat [ "kind" .= String "ForkerClose" - , "wasCommitted" .= toJSON (wc == LedgerDB.ForkerWasCommitted) - ] - - forHuman LedgerDB.ForkerOpen = "Opened forker" - forHuman (LedgerDB.ForkerReadTables RisingEdge) = "Forker reading tables" - forHuman (LedgerDB.ForkerReadTables (FallingEdgeWith t)) = "Forker read tables, took " <> showT t - forHuman (LedgerDB.ForkerRangeReadTables RisingEdge) = "Forker range reading tables" - forHuman (LedgerDB.ForkerRangeReadTables (FallingEdgeWith t)) = "Forker range read tables, took " <> showT t - forHuman LedgerDB.ForkerReadStatistics = "Forker gathering statistics" - forHuman (LedgerDB.ForkerPush RisingEdge) = "Forker pushing" - forHuman (LedgerDB.ForkerPush (FallingEdgeWith t)) = "Forker pushed, took " <> showT t - forHuman (LedgerDB.ForkerClose wc) = "Closed forker, " <> case wc of - LedgerDB.ForkerWasCommitted -> "was committed" - LedgerDB.ForkerWasUncommitted -> "was discarded" - -instance MetaTrace LedgerDB.TraceForkerEventWithKey where - namespaceFor (LedgerDB.TraceForkerEventWithKey _ ev) = - nsCast $ namespaceFor ev - severityFor ns (Just (LedgerDB.TraceForkerEventWithKey _ ev)) = - severityFor (nsCast ns) (Just ev) - severityFor (Namespace out tl) Nothing = - severityFor (Namespace out tl :: Namespace LedgerDB.TraceForkerEvent) Nothing - documentFor = documentFor @LedgerDB.TraceForkerEvent . nsCast - allNamespaces = map nsCast $ allNamespaces @LedgerDB.TraceForkerEvent - -instance MetaTrace LedgerDB.TraceForkerEvent where - namespaceFor LedgerDB.ForkerOpen = Namespace [] ["Open"] - namespaceFor LedgerDB.ForkerReadTables{} = Namespace [] ["Read"] - namespaceFor LedgerDB.ForkerRangeReadTables{} = Namespace [] ["RangeRead"] - namespaceFor LedgerDB.ForkerReadStatistics = Namespace [] ["Statistics"] - namespaceFor LedgerDB.ForkerPush{} = Namespace [] ["Push"] - namespaceFor LedgerDB.ForkerClose{} = Namespace [] ["Close"] - - severityFor _ _ = Just Debug - - documentFor (Namespace _ ("Open" : _tl)) = Just "A forker is being opened" - documentFor (Namespace _ ("Read" : _tl)) = Just "A forker is reading values" - documentFor (Namespace _ ("RangeRead" : _tl)) = Just "A forker is range reading values" - documentFor (Namespace _ ("Statistics" : _tl)) = Just "Statistics were gathered from the forker" - documentFor (Namespace _ ("Push" : _tl)) = Just "A forker is pushing a new ledger state" - documentFor (Namespace _ ("Close" : _tl)) = Just "A forker was closed" - documentFor _ = Nothing - - allNamespaces = [ - Namespace [] ["Open"] - , Namespace [] ["Read"] - , Namespace [] ["RangeRead"] - , Namespace [] ["Statistics"] - , Namespace [] ["Push"] - , Namespace [] ["Close"] - ] - --------------------------------------------------------------------------------- --- Flavor specific trace --------------------------------------------------------------------------------- - -instance LogFormatting LedgerDB.FlavorImplSpecificTrace where - forMachine dtal (LedgerDB.FlavorImplSpecificTraceV2 ev) = forMachine dtal ev - - forHuman (LedgerDB.FlavorImplSpecificTraceV2 ev) = forHuman ev - -instance MetaTrace LedgerDB.FlavorImplSpecificTrace where - namespaceFor (LedgerDB.FlavorImplSpecificTraceV2 ev) = - nsPrependInner "V2" (namespaceFor ev) - - severityFor (Namespace out ("V2" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace V2.LedgerDBV2Trace) Nothing - severityFor (Namespace out ("V2" : tl)) (Just (LedgerDB.FlavorImplSpecificTraceV2 ev)) = - severityFor (Namespace out tl :: Namespace V2.LedgerDBV2Trace) (Just ev) - severityFor _ _ = Nothing - - documentFor (Namespace out ("V2" : tl)) = - documentFor (Namespace out tl :: Namespace V2.LedgerDBV2Trace) - documentFor _ = Nothing - - allNamespaces = - map (nsPrependInner "V2") - (allNamespaces :: [Namespace V2.LedgerDBV2Trace]) - -{------------------------------------------------------------------------------- - V2 --------------------------------------------------------------------------------} - -instance LogFormatting EnclosingTimed where - forMachine _dtal = enclosingObject - - forHuman RisingEdge = "Starting" - forHuman (FallingEdgeWith a) = "Completed in " <> showT a <> " seconds" - -enclosingObject :: ToJSON a => Enclosing' a -> Object -enclosingObject RisingEdge = mconcat [ "edge" .= String "Starting" ] -enclosingObject (FallingEdgeWith a) = mconcat [ "edge" .= toJSON a ] - -enclosingValue :: ToJSON a => Enclosing' a -> Value -enclosingValue = Object . enclosingObject - -instance LogFormatting V2.LedgerDBV2Trace where - forMachine dtal (V2.TraceLedgerTablesHandleCreate enc) = - mconcat [ "kind" .= String "LedgerTablesHandleCreate", "enclosing" .= forMachine dtal enc ] - forMachine dtal (V2.TraceLedgerTablesHandleClose enc) = - mconcat [ "kind" .= String "LedgerTablesHandleClose", "enclosing" .= forMachine dtal enc ] - forMachine dtal (V2.BackendTrace ev) = forMachine dtal ev - forMachine dtal (V2.TraceLedgerTablesHandleRead enc) = - mconcat [ "kind" .= String "LedgerTablesHandleRead", "enclosing" .= forMachine dtal enc ] - forMachine dtal (V2.TraceLedgerTablesHandleDuplicate enc) = - mconcat [ "kind" .= String "LedgerTablesHandleDuplicate", "enclosing" .= forMachine dtal enc ] - forMachine dtal (V2.TraceLedgerTablesHandleCreateFirst enc) = - mconcat [ "kind" .= String "LedgerTablesHandleCreateFirst", "enclosing" .= forMachine dtal enc ] - forMachine dtal (V2.TraceLedgerTablesHandlePush enc) = - mconcat [ "kind" .= String "LedgerTablesHandlePush", "enclosing" .= forMachine dtal enc ] - - forHuman (V2.TraceLedgerTablesHandleCreate enc) = "Created a new 'LedgerTablesHandle': " <> forHuman enc - forHuman (V2.TraceLedgerTablesHandleClose enc) = "Closed a 'LedgerTablesHandle': " <> forHuman enc - forHuman (V2.BackendTrace ev) = forHuman ev - forHuman (V2.TraceLedgerTablesHandleRead enc) = "Read from a 'LedgerTablesHandle': " <> forHuman enc - forHuman (V2.TraceLedgerTablesHandleDuplicate enc) = "Duplicating a 'LedgerTablesHandle': " <> forHuman enc - forHuman (V2.TraceLedgerTablesHandleCreateFirst enc) = "Creating the first 'LedgerTablesHandle': " <> forHuman enc - forHuman (V2.TraceLedgerTablesHandlePush enc) = "Pushing to 'LedgerTablesHandle': " <> forHuman enc - -instance MetaTrace V2.LedgerDBV2Trace where - namespaceFor V2.TraceLedgerTablesHandleCreate{} = - Namespace [] ["LedgerTablesHandleCreate"] - namespaceFor V2.TraceLedgerTablesHandleClose{} = - Namespace [] ["LedgerTablesHandleClose"] - namespaceFor (V2.BackendTrace ev) = nsPrependInner "BackendTrace" (namespaceFor ev) - namespaceFor V2.TraceLedgerTablesHandleRead{} = Namespace [] ["LedgerTablesHandleRead"] - namespaceFor V2.TraceLedgerTablesHandleDuplicate{} = Namespace [] ["LedgerTablesHandleDuplicate"] - namespaceFor V2.TraceLedgerTablesHandleCreateFirst{} = Namespace [] ["LedgerTablesHandleCreateFirst"] - namespaceFor V2.TraceLedgerTablesHandlePush{} = Namespace [] ["LedgerTablesHandlePush"] - - severityFor (Namespace _ ["LedgerTablesHandleCreate"]) _ = Just Debug - severityFor (Namespace _ ["LedgerTablesHandleClose"]) _ = Just Debug - severityFor (Namespace _ ["LedgerTablesHandleRead"]) _ = Just Debug - severityFor (Namespace _ ["LedgerTablesHandleDuplicate"]) _ = Just Debug - severityFor (Namespace _ ["LedgerTablesHandleCreateFirst"]) _ = Just Debug - severityFor (Namespace _ ["LedgerTablesHandlePush"]) _ = Just Debug - severityFor (Namespace _ ("BackendTrace":_)) _ = Just Debug - severityFor _ _ = Nothing - - documentFor (Namespace _ ["LedgerTablesHandleCreate"]) = - Just "Created a ledger tables handle" - documentFor (Namespace _ ["LedgerTablesHandleClose"]) = - Just "Closed a ledger tables handle" - documentFor (Namespace _ ["LedgerTablesHandleRead"]) = - Just "Reading from ledger tables handle" - documentFor (Namespace _ ["LedgerTablesHandlePush"]) = - Just "Pushing to a ledger tables handle" - documentFor (Namespace _ ["LedgerTablesHandleCreateFirst"]) = - Just "Creating the first ledger tables handle" - documentFor (Namespace _ ["LedgerTablesHandleDuplicate"]) = - Just "Duplicating a ledger tables handle" - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["LedgerTablesHandleCreate"] - , Namespace [] ["LedgerTablesHandleClose"] - , Namespace [] ["LedgerTablesHandleRead"] - , Namespace [] ["LedgerTablesHandleDuplicate"] - , Namespace [] ["LedgerTablesHandleCreateFirst"] - , Namespace [] ["LedgerTablesHandlePush"] - ] ++ map (nsPrependInner "BackendTrace") (allNamespaces :: [Namespace V2.SomeBackendTrace]) - -instance LogFormatting V2.SomeBackendTrace where - forMachine dtal (V2.SomeBackendTrace ev) = unwrapV2Trace (forMachine dtal) ev - - forHuman (V2.SomeBackendTrace ev) = unwrapV2Trace forHuman ev - -instance MetaTrace V2.SomeBackendTrace where - namespaceFor (V2.SomeBackendTrace ev) = - unwrapV2Trace (nsPrependInner "LSM" . namespaceFor) ev - - severityFor (Namespace _ ("LSM" : _)) _ = Just Debug - severityFor _ _ = Nothing - - documentFor (Namespace out ("LSM" : tl)) = documentFor @(V2.Trace LSM.LSM) (Namespace out tl) - documentFor _ = Nothing - - allNamespaces = - map (nsPrependInner "LSM") (allNamespaces :: [Namespace (V2.Trace LSM.LSM)]) - -instance LogFormatting (V2.Trace LSM.LSM) where - forMachine _dtal (LSM.LSMTreeTrace ev) = mconcat [ "kind" .= String "LSMTreeTrace", "content" .= showT ev] - forMachine dtal (LSM.LSMLookup enc) = mconcat [ "kind" .= String "LSMLookup", "enclosing" .= forMachine dtal enc] - forMachine dtal (LSM.LSMUpdate enc) = mconcat [ "kind" .= String "LSMUpdate", "enclosing" .= forMachine dtal enc] - forMachine dtal (LSM.LSMSnap enc) = mconcat [ "kind" .= String "LSMSnap", "enclosing" .= forMachine dtal enc] - forMachine dtal (LSM.LSMOpenSession enc) = mconcat [ "kind" .= String "LSMOpenSession", "enclosing" .= forMachine dtal enc] - - forHuman (LSM.LSMTreeTrace ev) = showT ev - forHuman (LSM.LSMLookup enc) = "Looking up in LSM database: " <> forHuman enc - forHuman (LSM.LSMUpdate enc) = "Updating the LSM database: " <> forHuman enc - forHuman (LSM.LSMSnap enc) = "Snapshotting the LSM database: " <> forHuman enc - forHuman (LSM.LSMOpenSession enc) = "Opening the LSM session: " <> forHuman enc - - -instance MetaTrace (V2.Trace LSM.LSM) where - namespaceFor LSM.LSMTreeTrace{} = Namespace [] ["LSMTrace"] - namespaceFor LSM.LSMLookup {} = Namespace [] ["LSMLookup"] - namespaceFor LSM.LSMUpdate {} = Namespace [] ["LSMUpdate"] - namespaceFor LSM.LSMSnap {} = Namespace [] ["LSMSnap"] - namespaceFor LSM.LSMOpenSession {} = Namespace [] ["LSMOpenSession"] - - severityFor (Namespace _ ["LSMTrace"]) _ = Just Debug - severityFor (Namespace _ ["LSMLookup"]) _ = Just Debug - severityFor (Namespace _ ["LSMUpdate"]) _ = Just Debug - severityFor (Namespace _ ["LSMSnap"]) _ = Just Debug - severityFor (Namespace _ ["LSMOpenSession"]) _ = Just Debug - severityFor _ _ = Nothing - - documentFor (Namespace _ ["LSMTrace"]) = - Just "A trace from the LSM-trees backend" - documentFor (Namespace _ ["LSMLookup"]) = - Just "Looking up in the LSM-trees backend" - documentFor (Namespace _ ["LSMUpdate"]) = - Just "Updating the LSM-trees backend" - documentFor (Namespace _ ["LSMSnap"]) = - Just "Snapshotting the LSM-trees backend" - documentFor (Namespace _ ["LSMOpenSession"]) = - Just "Opening the LSM-trees backend session" - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["LSMTrace"] - , Namespace [] ["LSMLookup"] - , Namespace [] ["LSMUpdate"] - , Namespace [] ["LSMSnap"] - , Namespace [] ["LSMOpenSession"] - ] - -unwrapV2Trace :: forall a backend. Typeable backend => (V2.Trace LSM.LSM -> a) -> V2.Trace backend -> a -unwrapV2Trace g ev = - case cast @(V2.Trace backend) @(V2.Trace InMemory.Mem) ev of - Just (InMemory.NoTrace v) -> absurd v - Nothing -> - case cast @(V2.Trace backend) @(V2.Trace LSM.LSM) ev of - Just t -> g t - _ -> error "blah" - --------------------------------------------------------------------------------- --- ImmDB.TraceEvent --------------------------------------------------------------------------------- - -instance (ConvertRawHash blk, StandardHash blk) - => LogFormatting (ImmDB.TraceEvent blk) where - forMachine _dtal ImmDB.NoValidLastLocation = - mconcat [ "kind" .= String "NoValidLastLocation" ] - forMachine _dtal (ImmDB.ValidatedLastLocation chunkNo immTip) = - mconcat [ "kind" .= String "ValidatedLastLocation" - , "chunkNo" .= String (renderChunkNo chunkNo) - , "immTip" .= String (renderTipHash immTip) - , "blockNo" .= String (renderTipBlockNo immTip) - ] - forMachine dtal (ImmDB.ChunkValidationEvent traceChunkValidation) = - forMachine dtal traceChunkValidation - forMachine _dtal (ImmDB.DeletingAfter immTipWithInfo) = - mconcat [ "kind" .= String "DeletingAfter" - , "immTipHash" .= String (renderWithOrigin renderTipHash immTipWithInfo) - , "immTipBlockNo" .= String (renderWithOrigin renderTipBlockNo immTipWithInfo) - ] - forMachine _dtal ImmDB.DBAlreadyClosed = - mconcat [ "kind" .= String "DBAlreadyClosed" ] - forMachine _dtal ImmDB.DBClosed = - mconcat [ "kind" .= String "DBClosed" ] - forMachine dtal (ImmDB.TraceCacheEvent cacheEv) = - forMachine dtal cacheEv - forMachine _dtal (ImmDB.ChunkFileDoesntFit expectPrevHash actualPrevHash) = - mconcat [ "kind" .= String "ChunkFileDoesntFit" - , "expectedPrevHash" .= String (renderChainHash (Text.decodeLatin1 . - toRawHash (Proxy @blk)) expectPrevHash) - , "actualPrevHash" .= String (renderChainHash (Text.decodeLatin1 . - toRawHash (Proxy @blk)) actualPrevHash) - ] - forMachine _dtal (ImmDB.Migrating txt) = - mconcat [ "kind" .= String "Migrating" - , "info" .= String txt - ] - - forHuman ImmDB.NoValidLastLocation = - "No valid last location was found. Starting from Genesis." - forHuman (ImmDB.ValidatedLastLocation cn t) = - "Found a valid last location at chunk " - <> showT cn - <> " with tip " - <> renderRealPoint (ImmDB.tipToRealPoint t) - <> "." - forHuman (ImmDB.ChunkValidationEvent e) = case e of - ImmDB.StartedValidatingChunk chunkNo outOf -> - "Validating chunk no. " <> showT chunkNo <> " out of " <> showT outOf - <> ". Progress: " <> showProgressT (chunkNoToInt chunkNo) (chunkNoToInt outOf + 1) <> "%" - ImmDB.ValidatedChunk chunkNo outOf -> - "Validated chunk no. " <> showT chunkNo <> " out of " <> showT outOf - <> ". Progress: " <> showProgressT (chunkNoToInt chunkNo + 1) (chunkNoToInt outOf + 1) <> "%" - ImmDB.MissingChunkFile cn -> - "The chunk file with number " <> showT cn <> " is missing." - ImmDB.InvalidChunkFile cn er -> - "The chunk file with number " <> showT cn <> " is invalid: " <> showT er - ImmDB.MissingPrimaryIndex cn -> - "The primary index of the chunk file with number " <> showT cn <> " is missing." - ImmDB.MissingSecondaryIndex cn -> - "The secondary index of the chunk file with number " <> showT cn <> " is missing." - ImmDB.InvalidPrimaryIndex cn -> - "The primary index of the chunk file with number " <> showT cn <> " is invalid." - ImmDB.InvalidSecondaryIndex cn -> - "The secondary index of the chunk file with number " <> showT cn <> " is invalid." - ImmDB.RewritePrimaryIndex cn -> - "Rewriting the primary index for the chunk file with number " <> showT cn <> "." - ImmDB.RewriteSecondaryIndex cn -> - "Rewriting the secondary index for the chunk file with number " <> showT cn <> "." - forHuman (ImmDB.ChunkFileDoesntFit ch1 ch2 ) = - "Chunk file doesn't fit. The hash of the block " <> showT ch2 <> " doesn't match the previous hash of the first block in the current epoch: " <> showT ch1 <> "." - forHuman (ImmDB.Migrating t) = "Migrating: " <> t - forHuman (ImmDB.DeletingAfter wot) = "Deleting chunk files after " <> showT wot - forHuman ImmDB.DBAlreadyClosed {} = "Immutable DB was already closed. Double closing." - forHuman ImmDB.DBClosed {} = "Closed Immutable DB." - forHuman (ImmDB.TraceCacheEvent ev') = "Cache event: " <> case ev' of - ImmDB.TraceCurrentChunkHit cn curr -> "Current chunk hit: " <> showT cn <> ", cache size: " <> showT curr - ImmDB.TracePastChunkHit cn curr -> "Past chunk hit: " <> showT cn <> ", cache size: " <> showT curr - ImmDB.TracePastChunkMiss cn curr -> "Past chunk miss: " <> showT cn <> ", cache size: " <> showT curr - ImmDB.TracePastChunkEvict cn curr -> "Past chunk evict: " <> showT cn <> ", cache size: " <> showT curr - ImmDB.TracePastChunksExpired cns curr -> "Past chunks expired: " <> showT cns <> ", cache size: " <> showT curr - - -instance MetaTrace (ImmDB.TraceEvent blk) where - namespaceFor ImmDB.NoValidLastLocation {} = Namespace [] ["NoValidLastLocation"] - namespaceFor ImmDB.ValidatedLastLocation {} = Namespace [] ["ValidatedLastLocation"] - namespaceFor (ImmDB.ChunkValidationEvent ev) = - nsPrependInner "ChunkValidation" (namespaceFor ev) - namespaceFor ImmDB.ChunkFileDoesntFit {} = Namespace [] ["ChunkFileDoesntFit"] - namespaceFor ImmDB.Migrating {} = Namespace [] ["Migrating"] - namespaceFor ImmDB.DeletingAfter {} = Namespace [] ["DeletingAfter"] - namespaceFor ImmDB.DBAlreadyClosed {} = Namespace [] ["DBAlreadyClosed"] - namespaceFor ImmDB.DBClosed {} = Namespace [] ["DBClosed"] - namespaceFor (ImmDB.TraceCacheEvent ev) = - nsPrependInner "CacheEvent" (namespaceFor ev) - - severityFor (Namespace _ ["NoValidLastLocation"]) _ = Just Info - severityFor (Namespace _ ["ValidatedLastLocation"]) _ = Just Info - severityFor (Namespace out ("ChunkValidation" : tl)) - (Just (ImmDB.ChunkValidationEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("ChunkValidation" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (ImmDB.TraceChunkValidation blk ImmDB.ChunkNo)) Nothing - - severityFor (Namespace out ("ChunkValidationEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace (ImmDB.TraceChunkValidation blk chunkNo)) Nothing - severityFor (Namespace _ ["ChunkFileDoesntFit"]) _ = Just Warning - severityFor (Namespace _ ["Migrating"]) _ = Just Debug - severityFor (Namespace _ ["DeletingAfter"]) _ = Just Debug - severityFor (Namespace _ ["DBAlreadyClosed"]) _ = Just Error - severityFor (Namespace _ ["DBClosed"]) _ = Just Info - severityFor (Namespace out ("CacheEvent" : tl)) - (Just (ImmDB.TraceCacheEvent ev')) = - severityFor (Namespace out tl) (Just ev') - severityFor (Namespace out ("CacheEvent" : tl)) Nothing = - severityFor (Namespace out tl :: Namespace ImmDB.TraceCacheEvent) Nothing - severityFor _ _ = Nothing - - privacyFor (Namespace out ("ChunkValidation" : tl)) - (Just (ImmDB.ChunkValidationEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor (Namespace out ("ChunkValidationEvent" : tl)) Nothing = - privacyFor (Namespace out tl :: Namespace (ImmDB.TraceChunkValidation blk chunkNo)) Nothing - privacyFor (Namespace out ("CacheEvent" : tl)) - (Just (ImmDB.TraceCacheEvent ev')) = - privacyFor (Namespace out tl) (Just ev') - privacyFor _ _ = Just Public - - detailsFor (Namespace out ("ChunkValidation" : tl)) - (Just (ImmDB.ChunkValidationEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor (Namespace out ("ChunkValidationEvent" : tl)) Nothing = - detailsFor (Namespace out tl :: Namespace (ImmDB.TraceChunkValidation blk chunkNo)) Nothing - detailsFor (Namespace out ("CacheEvent" : tl)) - (Just (ImmDB.TraceCacheEvent ev')) = - detailsFor (Namespace out tl) (Just ev') - detailsFor _ _ = Just DNormal - - documentFor (Namespace _ ["NoValidLastLocation"]) = Just - "No valid last location was found" - documentFor (Namespace _ ["ValidatedLastLocation"]) = Just - "The last location was validatet" - documentFor (Namespace o ("ChunkValidation" : tl)) = - documentFor (Namespace o tl :: Namespace (ImmDB.TraceChunkValidation blk chunkNo)) - documentFor (Namespace _ ["ChunkFileDoesntFit"]) = Just $ mconcat - [ "The hash of the last block in the previous epoch doesn't match the" - , " previous hash of the first block in the current epoch" - ] - documentFor (Namespace _ ["Migrating"]) = Just - "Performing a migration of the on-disk files." - documentFor (Namespace _ ["DeletingAfter"]) = Just - "Delete after" - documentFor (Namespace _ ["DBAlreadyClosed"]) = Just - "" - documentFor (Namespace _ ["DBClosed"]) = Just - "Closing the immutable DB" - documentFor (Namespace o ("CacheEvent" : tl)) = - documentFor (Namespace o tl :: Namespace ImmDB.TraceCacheEvent) - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["NoValidLastLocation"] - , Namespace [] ["ValidatedLastLocation"] - , Namespace [] ["ChunkFileDoesntFit"] - , Namespace [] ["Migrating"] - , Namespace [] ["DeletingAfter"] - , Namespace [] ["DBAlreadyClosed"] - , Namespace [] ["DBClosed"] - ] - ++ map (nsPrependInner "ChunkValidation") - (allNamespaces :: [Namespace (ImmDB.TraceChunkValidation blk chunkNo)]) - ++ map (nsPrependInner "CacheEvent") - (allNamespaces :: [Namespace ImmDB.TraceCacheEvent]) - --------------------------------------------------------------------------------- --- ImmDB.TraceChunkValidation --------------------------------------------------------------------------------- - -instance ConvertRawHash blk => LogFormatting (ImmDB.TraceChunkValidation blk ImmDB.ChunkNo) where - forMachine _dtal (ImmDB.RewriteSecondaryIndex chunkNo) = - mconcat [ "kind" .= String "TraceImmutableDBEvent.RewriteSecondaryIndex" - , "chunkNo" .= String (renderChunkNo chunkNo) - ] - forMachine _dtal (ImmDB.RewritePrimaryIndex chunkNo) = - mconcat [ "kind" .= String "TraceImmutableDBEvent.RewritePrimaryIndex" - , "chunkNo" .= String (renderChunkNo chunkNo) - ] - forMachine _dtal (ImmDB.MissingPrimaryIndex chunkNo) = - mconcat [ "kind" .= String "TraceImmutableDBEvent.MissingPrimaryIndex" - , "chunkNo" .= String (renderChunkNo chunkNo) - ] - forMachine _dtal (ImmDB.MissingSecondaryIndex chunkNo) = - mconcat [ "kind" .= String "TraceImmutableDBEvent.MissingSecondaryIndex" - , "chunkNo" .= String (renderChunkNo chunkNo) - ] - forMachine _dtal (ImmDB.InvalidPrimaryIndex chunkNo) = - mconcat [ "kind" .= String "TraceImmutableDBEvent.InvalidPrimaryIndex" - , "chunkNo" .= String (renderChunkNo chunkNo) - ] - forMachine _dtal (ImmDB.InvalidSecondaryIndex chunkNo) = - mconcat [ "kind" .= String "TraceImmutableDBEvent.InvalidSecondaryIndex" - , "chunkNo" .= String (renderChunkNo chunkNo) - ] - forMachine _dtal (ImmDB.InvalidChunkFile chunkNo - (ImmDB.ChunkErrHashMismatch hashPrevBlock prevHashOfBlock)) = - mconcat [ "kind" .= String "TraceImmutableDBEvent.InvalidChunkFile.ChunkErrHashMismatch" - , "chunkNo" .= String (renderChunkNo chunkNo) - , "hashPrevBlock" .= String (Text.decodeLatin1 . toRawHash (Proxy @blk) $ hashPrevBlock) - , "prevHashOfBlock" .= String (renderChainHash (Text.decodeLatin1 . toRawHash (Proxy @blk)) prevHashOfBlock) - ] - forMachine dtal (ImmDB.InvalidChunkFile chunkNo (ImmDB.ChunkErrCorrupt pt)) = - mconcat [ "kind" .= String "TraceImmutableDBEvent.InvalidChunkFile.ChunkErrCorrupt" - , "chunkNo" .= String (renderChunkNo chunkNo) - , "block" .= String (renderPointForDetails dtal pt) - ] - forMachine _dtal (ImmDB.ValidatedChunk chunkNo _) = - mconcat [ "kind" .= String "TraceImmutableDBEvent.ValidatedChunk" - , "chunkNo" .= String (renderChunkNo chunkNo) - ] - forMachine _dtal (ImmDB.MissingChunkFile chunkNo) = - mconcat [ "kind" .= String "TraceImmutableDBEvent.MissingChunkFile" - , "chunkNo" .= String (renderChunkNo chunkNo) - ] - forMachine _dtal (ImmDB.InvalidChunkFile chunkNo (ImmDB.ChunkErrRead readIncErr)) = - mconcat [ "kind" .= String "TraceImmutableDBEvent.InvalidChunkFile.ChunkErrRead" - , "chunkNo" .= String (renderChunkNo chunkNo) - , "error" .= String (showT readIncErr) - ] - forMachine _dtal (ImmDB.StartedValidatingChunk initialChunk finalChunk) = - mconcat [ "kind" .= String "TraceImmutableDBEvent.StartedValidatingChunk" - , "initialChunk" .= renderChunkNo initialChunk - , "finalChunk" .= renderChunkNo finalChunk - ] - -instance MetaTrace (ImmDB.TraceChunkValidation blk chunkNo) where - namespaceFor ImmDB.StartedValidatingChunk {} = Namespace [] ["StartedValidatingChunk"] - namespaceFor ImmDB.ValidatedChunk {} = Namespace [] ["ValidatedChunk"] - namespaceFor ImmDB.MissingChunkFile {} = Namespace [] ["MissingChunkFile"] - namespaceFor ImmDB.InvalidChunkFile {} = Namespace [] ["InvalidChunkFile"] - namespaceFor ImmDB.MissingPrimaryIndex {} = Namespace [] ["MissingPrimaryIndex"] - namespaceFor ImmDB.MissingSecondaryIndex {} = Namespace [] ["MissingSecondaryIndex"] - namespaceFor ImmDB.InvalidPrimaryIndex {} = Namespace [] ["InvalidPrimaryIndex"] - namespaceFor ImmDB.InvalidSecondaryIndex {} = Namespace [] ["InvalidSecondaryIndex"] - namespaceFor ImmDB.RewritePrimaryIndex {} = Namespace [] ["RewritePrimaryIndex"] - namespaceFor ImmDB.RewriteSecondaryIndex {} = Namespace [] ["RewriteSecondaryIndex"] - - severityFor (Namespace _ ["StartedValidatingChunk"]) _ = Just Info - severityFor (Namespace _ ["ValidatedChunk"]) _ = Just Info - severityFor (Namespace _ ["MissingChunkFile"]) _ = Just Warning - severityFor (Namespace _ ["InvalidChunkFile"]) _ = Just Warning - severityFor (Namespace _ ["MissingPrimaryIndex"]) _ = Just Warning - severityFor (Namespace _ ["MissingSecondaryIndex"]) _ = Just Warning - severityFor (Namespace _ ["InvalidPrimaryIndex"]) _ = Just Warning - severityFor (Namespace _ ["InvalidSecondaryIndex"]) _ = Just Warning - severityFor (Namespace _ ["RewritePrimaryIndex"]) _ = Just Warning - severityFor (Namespace _ ["RewriteSecondaryIndex"]) _ = Just Warning - severityFor _ _ = Nothing - - documentFor (Namespace _ ["StartedValidatingChunk"]) = Just - "" - documentFor (Namespace _ ["ValidatedChunk"]) = Just - "" - documentFor (Namespace _ ["MissingChunkFile"]) = Just - "" - documentFor (Namespace _ ["InvalidChunkFile"]) = Just - "" - documentFor (Namespace _ ["MissingPrimaryIndex"]) = Just - "" - documentFor (Namespace _ ["MissingSecondaryIndex"]) = Just - "" - documentFor (Namespace _ ["InvalidPrimaryIndex"]) = Just - "" - documentFor (Namespace _ ["InvalidSecondaryIndex"]) = Just - "" - documentFor (Namespace _ ["RewritePrimaryIndex"]) = Just - "" - documentFor (Namespace _ ["RewriteSecondaryIndex"]) = Just - "" - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["StartedValidatingChunk"] - , Namespace [] ["ValidatedChunk"] - , Namespace [] ["MissingChunkFile"] - , Namespace [] ["InvalidChunkFile"] - , Namespace [] ["MissingPrimaryIndex"] - , Namespace [] ["MissingSecondaryIndex"] - , Namespace [] ["InvalidPrimaryIndex"] - , Namespace [] ["InvalidSecondaryIndex"] - , Namespace [] ["RewritePrimaryIndex"] - , Namespace [] ["RewriteSecondaryIndex"] - ] - --------------------------------------------------------------------------------- --- ImmDB.TraceCacheEvent --------------------------------------------------------------------------------- - -instance LogFormatting ImmDB.TraceCacheEvent where - forMachine _dtal (ImmDB.TraceCurrentChunkHit chunkNo nbPastChunksInCache) = - mconcat [ "kind" .= String "TraceCurrentChunkHit" - , "chunkNo" .= String (renderChunkNo chunkNo) - , "noPastChunks" .= String (showT nbPastChunksInCache) - ] - forMachine _dtal (ImmDB.TracePastChunkHit chunkNo nbPastChunksInCache) = - mconcat [ "kind" .= String "TracePastChunkHit" - , "chunkNo" .= String (renderChunkNo chunkNo) - , "noPastChunks" .= String (showT nbPastChunksInCache) - ] - forMachine _dtal (ImmDB.TracePastChunkMiss chunkNo nbPastChunksInCache) = - mconcat [ "kind" .= String "TracePastChunkMiss" - , "chunkNo" .= String (renderChunkNo chunkNo) - , "noPastChunks" .= String (showT nbPastChunksInCache) - ] - forMachine _dtal (ImmDB.TracePastChunkEvict chunkNo nbPastChunksInCache) = - mconcat [ "kind" .= String "TracePastChunkEvict" - , "chunkNo" .= String (renderChunkNo chunkNo) - , "noPastChunks" .= String (showT nbPastChunksInCache) - ] - forMachine _dtal (ImmDB.TracePastChunksExpired chunkNos nbPastChunksInCache) = - mconcat [ "kind" .= String "TracePastChunksExpired" - , "chunkNos" .= String (Text.pack . show $ map renderChunkNo chunkNos) - , "noPastChunks" .= String (showT nbPastChunksInCache) - ] - -instance MetaTrace ImmDB.TraceCacheEvent where - namespaceFor ImmDB.TraceCurrentChunkHit {} = Namespace [] ["CurrentChunkHit"] - namespaceFor ImmDB.TracePastChunkHit {} = Namespace [] ["PastChunkHit"] - namespaceFor ImmDB.TracePastChunkMiss {} = Namespace [] ["PastChunkMiss"] - namespaceFor ImmDB.TracePastChunkEvict {} = Namespace [] ["PastChunkEvict"] - namespaceFor ImmDB.TracePastChunksExpired {} = Namespace [] ["PastChunkExpired"] - - severityFor (Namespace _ ["CurrentChunkHit"]) _ = Just Debug - severityFor (Namespace _ ["PastChunkHit"]) _ = Just Debug - severityFor (Namespace _ ["PastChunkMiss"]) _ = Just Debug - severityFor (Namespace _ ["PastChunkEvict"]) _ = Just Debug - severityFor (Namespace _ ["PastChunkExpired"]) _ = Just Debug - severityFor _ _ = Nothing - - documentFor (Namespace _ ["CurrentChunkHit"]) = Just - "Current chunk found in the cache." - documentFor (Namespace _ ["PastChunkHit"]) = Just - "Past chunk found in the cache" - documentFor (Namespace _ ["PastChunkMiss"]) = Just - "Past chunk was not found in the cache" - documentFor (Namespace _ ["PastChunkEvict"]) = Just $ mconcat - [ "The least recently used past chunk was evicted because the cache" - , " was full." - ] - documentFor (Namespace _ ["PastChunkExpired"]) = Just - "" - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["CurrentChunkHit"] - , Namespace [] ["PastChunkHit"] - , Namespace [] ["PastChunkMiss"] - , Namespace [] ["PastChunkEvict"] - , Namespace [] ["PastChunkExpired"] - ] - --------------------------------------------------------------------------------- --- VolDb.TraceEvent --------------------------------------------------------------------------------- - -instance StandardHash blk => LogFormatting (VolDB.TraceEvent blk) where - forMachine _dtal VolDB.DBAlreadyClosed = - mconcat [ "kind" .= String "DBAlreadyClosed"] - forMachine _dtal (VolDB.BlockAlreadyHere blockId) = - mconcat [ "kind" .= String "BlockAlreadyHere" - , "blockId" .= String (showT blockId) - ] - forMachine _dtal (VolDB.Truncate pErr fsPath blockOffset) = - mconcat [ "kind" .= String "Truncate" - , "parserError" .= String (showT pErr) - , "file" .= String (showT fsPath) - , "blockOffset" .= String (showT blockOffset) - ] - forMachine _dtal (VolDB.InvalidFileNames fsPaths) = - mconcat [ "kind" .= String "InvalidFileNames" - , "files" .= String (Text.pack . show $ map show fsPaths) - ] - forMachine _dtal VolDB.DBClosed = - mconcat [ "kind" .= String "DBClosed" ] - -instance MetaTrace (VolDB.TraceEvent blk) where - namespaceFor VolDB.DBAlreadyClosed {} = Namespace [] ["DBAlreadyClosed"] - namespaceFor VolDB.BlockAlreadyHere {} = Namespace [] ["BlockAlreadyHere"] - namespaceFor VolDB.Truncate {} = Namespace [] ["Truncate"] - namespaceFor VolDB.InvalidFileNames {} = Namespace [] ["InvalidFileNames"] - namespaceFor VolDB.DBClosed {} = Namespace [] ["DBClosed"] - - severityFor (Namespace _ ["DBAlreadyClosed"]) _ = Just Debug - severityFor (Namespace _ ["BlockAlreadyHere"]) _ = Just Debug - severityFor (Namespace _ ["Truncate"]) _ = Just Debug - severityFor (Namespace _ ["InvalidFileNames"]) _ = Just Debug - severityFor (Namespace _ ["DBClosed"]) _ = Just Debug - severityFor _ _ = Nothing - - documentFor (Namespace _ ["DBAlreadyClosed"]) = Just - "When closing the DB it was found it is closed already." - documentFor (Namespace _ ["BlockAlreadyHere"]) = Just - "A block was found to be already in the DB." - documentFor (Namespace _ ["Truncate"]) = Just - "Truncates a file up to offset because of the error." - documentFor (Namespace _ ["InvalidFileNames"]) = Just - "Reports a list of invalid file paths." - documentFor (Namespace _ ["DBClosed"]) = Just - "Closing the volatile DB" - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["DBAlreadyClosed"] - , Namespace [] ["BlockAlreadyHere"] - , Namespace [] ["Truncate"] - , Namespace [] ["InvalidFileNames"] - , Namespace [] ["DBClosed"] - ] - - --------------------------------------------------------------------------------- --- ChainInformation --------------------------------------------------------------------------------- - -sevLedgerEvent :: LedgerEvent blk -> SeverityS -sevLedgerEvent (LedgerUpdate _) = Notice -sevLedgerEvent (LedgerWarning _) = Critical - -showProgressT :: Int -> Int -> Text -showProgressT chunkNo outOf = - Text.pack (showFFloat - (Just 2) - (100 * fromIntegral chunkNo / fromIntegral outOf :: Float) - mempty) - -data ChainInformation = ChainInformation - { slots :: Word64 - , blocks :: Word64 - , density :: Rational - -- ^ the actual number of blocks created over the maximum expected number - -- of blocks that could be created over the span of the last @k@ blocks. - , epoch :: EpochNo - -- ^ In which epoch is the tip of the current chain - , slotInEpoch :: Word64 - -- ^ Relative slot number of the tip of the current chain within the - -- epoch. - , blocksUncoupledDelta :: Int64 - , tipBlockHash :: Text - -- ^ Hash of the last adopted block. - , tipBlockParentHash :: Text - -- ^ Hash of the parent block of the last adopted block. - , tipBlockIssuerVerificationKeyHash :: BlockIssuerVerificationKeyHash - -- ^ Hash of the last adopted block issuer's verification key. - } - - -chainInformation - :: forall blk. HasHeader (Header blk) - => HasIssuer blk - => ConvertRawHash blk - => ChainDB.SelectionChangedInfo blk - -> AF.AnchoredFragment (Header blk) - -> AF.AnchoredFragment (Header blk) -- ^ New fragment. - -> Int64 - -> ChainInformation -chainInformation selChangedInfo oldFrag frag blocksUncoupledDelta = ChainInformation - { slots = unSlotNo $ fromWithOrigin 0 (AF.headSlot frag) - , blocks = unBlockNo $ fromWithOrigin (BlockNo 1) (AF.headBlockNo frag) - , density = fragmentChainDensity frag - , epoch = ChainDB.newTipEpoch selChangedInfo - , slotInEpoch = ChainDB.newTipSlotInEpoch selChangedInfo - , blocksUncoupledDelta = blocksUncoupledDelta - , tipBlockHash = renderHeaderHash (Proxy @blk) $ realPointHash (ChainDB.newTipPoint selChangedInfo) - , tipBlockParentHash = renderChainHash (Text.decodeLatin1 . B16.encode . toRawHash (Proxy @blk)) $ AF.headHash oldFrag - , tipBlockIssuerVerificationKeyHash = tipIssuerVkHash - } - where - tipIssuerVkHash :: BlockIssuerVerificationKeyHash - tipIssuerVkHash = either (const NoBlockIssuer) getIssuerVerificationKeyHash (AF.head frag) - -fragmentChainDensity :: - HasHeader (Header blk) - => AF.AnchoredFragment (Header blk) -> Rational -fragmentChainDensity frag = calcDensity blockD slotD - where - calcDensity :: Word64 -> Word64 -> Rational - calcDensity bl sl - | sl > 0 = toRational bl / toRational sl - | otherwise = 0 - slotN = unSlotNo $ fromWithOrigin 0 (AF.headSlot frag) - -- Slot of the tip - slot @k@ blocks back. Use 0 as the slot for genesis - -- includes EBBs - slotD = slotN - - unSlotNo (fromWithOrigin 0 (AF.lastSlot frag)) - -- Block numbers start at 1. We ignore the genesis EBB, which has block number 0. - blockD = blockN - firstBlock - blockN = unBlockNo $ fromWithOrigin (BlockNo 1) (AF.headBlockNo frag) - firstBlock = case unBlockNo . blockNo <$> AF.last frag of - -- Empty fragment, no blocks. We have that @blocks = 1 - 1 = 0@ - Left _ -> 1 - -- The oldest block is the genesis EBB with block number 0, - -- don't let it contribute to the number of blocks - Right 0 -> 1 - Right b -> b - --------------------------------------------------------------------------------- --- Other orophans --------------------------------------------------------------------------------- - -instance LogFormatting LedgerDB.DiskSnapshot where - forMachine DDetailed snap = - mconcat [ "kind" .= String "snapshot" - , "snapshot" .= String (Text.pack $ show snap) ] - forMachine _ _snap = mconcat [ "kind" .= String "snapshot" ] - - -instance ( StandardHash blk - , LogFormatting (ValidationErr (BlockProtocol blk)) - , LogFormatting (OtherHeaderEnvelopeError blk) - ) - => LogFormatting (HeaderError blk) where - forMachine dtal (HeaderProtocolError err) = - mconcat - [ "kind" .= String "HeaderProtocolError" - , "error" .= forMachine dtal err - ] - forMachine dtal (HeaderEnvelopeError err) = - mconcat - [ "kind" .= String "HeaderEnvelopeError" - , "error" .= forMachine dtal err - ] - -instance ( StandardHash blk - , LogFormatting (OtherHeaderEnvelopeError blk) - ) - => LogFormatting (HeaderEnvelopeError blk) where - forMachine _dtal (UnexpectedBlockNo expect act) = - mconcat - [ "kind" .= String "UnexpectedBlockNo" - , "expected" .= condense expect - , "actual" .= condense act - ] - forMachine _dtal (UnexpectedSlotNo expect act) = - mconcat - [ "kind" .= String "UnexpectedSlotNo" - , "expected" .= condense expect - , "actual" .= condense act - ] - forMachine _dtal (UnexpectedPrevHash expect act) = - mconcat - [ "kind" .= String "UnexpectedPrevHash" - , "expected" .= String (Text.pack $ show expect) - , "actual" .= String (Text.pack $ show act) - ] - - forMachine _dtal (CheckpointMismatch blockNumber hdrHashExpected hdrHashActual) = - mconcat - [ "kind" .= String "CheckpointMismatch" - , "blockNo" .= String (Text.pack $ show blockNumber) - , "expected" .= String (Text.pack $ show hdrHashExpected) - , "actual" .= String (Text.pack $ show hdrHashActual) - ] - - forMachine dtal (OtherHeaderEnvelopeError err) = - forMachine dtal err - - -instance ( LogFormatting (LedgerError blk) - , LogFormatting (HeaderError blk)) - => LogFormatting (ExtValidationError blk) where - forMachine dtal (ExtValidationErrorLedger err) = forMachine dtal err - forMachine dtal (ExtValidationErrorHeader err) = forMachine dtal err - - forHuman (ExtValidationErrorLedger err) = forHuman err - forHuman (ExtValidationErrorHeader err) = forHuman err - - asMetrics (ExtValidationErrorLedger err) = asMetrics err - asMetrics (ExtValidationErrorHeader err) = asMetrics err - -instance (Show (PBFT.PBftVerKeyHash c)) - => LogFormatting (PBFT.PBftValidationErr c) where - forMachine _dtal (PBFT.PBftInvalidSignature text) = - mconcat - [ "kind" .= String "PBftInvalidSignature" - , "error" .= String text - ] - forMachine _dtal (PBFT.PBftNotGenesisDelegate vkhash _ledgerView) = - mconcat - [ "kind" .= String "PBftNotGenesisDelegate" - , "vk" .= String (Text.pack $ show vkhash) - ] - forMachine _dtal (PBFT.PBftExceededSignThreshold vkhash numForged) = - mconcat - [ "kind" .= String "PBftExceededSignThreshold" - , "vk" .= String (Text.pack $ show vkhash) - , "numForged" .= String (Text.pack (show numForged)) - ] - forMachine _dtal PBFT.PBftInvalidSlot = - mconcat - [ "kind" .= String "PBftInvalidSlot" - ] - -instance (Show (PBFT.PBftVerKeyHash c)) - => LogFormatting (PBFT.PBftCannotForge c) where - forMachine _dtal (PBFT.PBftCannotForgeInvalidDelegation vkhash) = - mconcat - [ "kind" .= String "PBftCannotForgeInvalidDelegation" - , "vk" .= String (Text.pack $ show vkhash) - ] - forMachine _dtal (PBFT.PBftCannotForgeThresholdExceeded numForged) = - mconcat - [ "kind" .= String "PBftCannotForgeThresholdExceeded" - , "numForged" .= numForged - ] - --- ChainDB.TraceAddPerasCertEvent instances -instance ConvertRawHash blk => LogFormatting (ChainDB.TraceAddPerasCertEvent blk) where - forHuman (ChainDB.AddedPerasCertToQueue roundNo boostedBlock _queueSize) = - "Added Peras certificate for round " <> Text.pack (show roundNo) <> - " boosting block " <> renderPoint boostedBlock <> " to queue" - forHuman (ChainDB.PoppedPerasCertFromQueue roundNo boostedBlock) = - "Popped Peras certificate for round " <> Text.pack (show roundNo) <> - " boosting block " <> renderPoint boostedBlock <> " from queue" - forHuman (ChainDB.IgnorePerasCertTooOld roundNo boostedBlock immutableSlot) = - "Ignored Peras certificate for round " <> Text.pack (show roundNo) <> - " boosting block " <> renderPoint boostedBlock <> - " (too old, immutable slot: " <> renderPoint (AF.anchorToPoint immutableSlot) <> ")" - forHuman (ChainDB.PerasCertBoostsCurrentChain roundNo boostedBlock) = - "Peras certificate for round " <> Text.pack (show roundNo) <> - " boosts current chain block " <> renderPoint boostedBlock - forHuman (ChainDB.PerasCertBoostsGenesis roundNo) = - "Peras certificate for round " <> Text.pack (show roundNo) <> " boosts Genesis" - forHuman (ChainDB.PerasCertBoostsBlockNotYetReceived roundNo boostedBlock) = - "Peras certificate for round " <> Text.pack (show roundNo) <> - " boosts block " <> renderPoint boostedBlock <> " not yet received" - forHuman (ChainDB.ChainSelectionForBoostedBlock roundNo boostedBlock) = - "Chain selection for block " <> renderPoint boostedBlock <> - " boosted by Peras certificate from round " <> Text.pack (show roundNo) - - forMachine _dtal (ChainDB.AddedPerasCertToQueue roundNo boostedBlock queueSize) = - mconcat ["kind" .= String "AddedPerasCertToQueue", - "round" .= String (Text.pack $ show roundNo), - "boostedBlock" .= String (renderPoint boostedBlock), - "queueSize" .= enclosingValue queueSize] - forMachine _dtal (ChainDB.PoppedPerasCertFromQueue roundNo boostedBlock) = - mconcat ["kind" .= String "PoppedPerasCertFromQueue", - "round" .= String (Text.pack $ show roundNo), - "boostedBlock" .= String (renderPoint boostedBlock)] - forMachine _dtal (ChainDB.IgnorePerasCertTooOld roundNo boostedBlock immutableSlot) = - mconcat ["kind" .= String "IgnorePerasCertTooOld", - "round" .= String (Text.pack $ show roundNo), - "boostedBlock" .= String (renderPoint boostedBlock), - "immutableSlot" .= String (renderPoint (AF.anchorToPoint immutableSlot))] - forMachine _dtal (ChainDB.PerasCertBoostsCurrentChain roundNo boostedBlock) = - mconcat ["kind" .= String "PerasCertBoostsCurrentChain", - "round" .= String (Text.pack $ show roundNo), - "boostedBlock" .= String (renderPoint boostedBlock)] - forMachine _dtal (ChainDB.PerasCertBoostsGenesis roundNo) = - mconcat ["kind" .= String "PerasCertBoostsGenesis", - "round" .= String (Text.pack $ show roundNo)] - forMachine _dtal (ChainDB.PerasCertBoostsBlockNotYetReceived roundNo boostedBlock) = - mconcat ["kind" .= String "PerasCertBoostsBlockNotYetReceived", - "round" .= String (Text.pack $ show roundNo), - "boostedBlock" .= String (renderPoint boostedBlock)] - forMachine _dtal (ChainDB.ChainSelectionForBoostedBlock roundNo boostedBlock) = - mconcat ["kind" .= String "ChainSelectionForBoostedBlock", - "round" .= String (Text.pack $ show roundNo), - "boostedBlock" .= String (renderPoint boostedBlock)] - - asMetrics _ = [] - --- ChainDB.TraceAddPerasCertEvent MetaTrace instance -instance MetaTrace (ChainDB.TraceAddPerasCertEvent blk) where - namespaceFor ChainDB.AddedPerasCertToQueue{} = Namespace [] ["AddedPerasCertToQueue"] - namespaceFor (ChainDB.PoppedPerasCertFromQueue _ _) = Namespace [] ["PoppedPerasCertFromQueue"] - namespaceFor ChainDB.IgnorePerasCertTooOld{} = Namespace [] ["IgnorePerasCertTooOld"] - namespaceFor (ChainDB.PerasCertBoostsCurrentChain _ _) = Namespace [] ["PerasCertBoostsCurrentChain"] - namespaceFor (ChainDB.PerasCertBoostsGenesis _) = Namespace [] ["PerasCertBoostsGenesis"] - namespaceFor (ChainDB.PerasCertBoostsBlockNotYetReceived _ _) = Namespace [] ["PerasCertBoostsBlockNotYetReceived"] - namespaceFor (ChainDB.ChainSelectionForBoostedBlock _ _) = Namespace [] ["ChainSelectionForBoostedBlock"] - - severityFor (Namespace _ ["AddedPerasCertToQueue"]) _ = Just Debug - severityFor (Namespace _ ["PoppedPerasCertFromQueue"]) _ = Just Debug - severityFor (Namespace _ ["IgnorePerasCertTooOld"]) _ = Just Info - severityFor (Namespace _ ["PerasCertBoostsCurrentChain"]) _ = Just Info - severityFor (Namespace _ ["PerasCertBoostsGenesis"]) _ = Just Info - severityFor (Namespace _ ["PerasCertBoostsBlockNotYetReceived"]) _ = Just Info - severityFor (Namespace _ ["ChainSelectionForBoostedBlock"]) _ = Just Info - severityFor _ _ = Nothing - - privacyFor (Namespace _ ["AddedPerasCertToQueue"]) _ = Just Public - privacyFor (Namespace _ ["PoppedPerasCertFromQueue"]) _ = Just Public - privacyFor (Namespace _ ["IgnorePerasCertTooOld"]) _ = Just Public - privacyFor (Namespace _ ["PerasCertBoostsCurrentChain"]) _ = Just Public - privacyFor (Namespace _ ["PerasCertBoostsGenesis"]) _ = Just Public - privacyFor (Namespace _ ["PerasCertBoostsBlockNotYetReceived"]) _ = Just Public - privacyFor (Namespace _ ["ChainSelectionForBoostedBlock"]) _ = Just Public - privacyFor _ _ = Nothing - - detailsFor (Namespace _ ["AddedPerasCertToQueue"]) _ = Just DDetailed - detailsFor (Namespace _ ["PoppedPerasCertFromQueue"]) _ = Just DDetailed - detailsFor (Namespace _ ["IgnorePerasCertTooOld"]) _ = Just DNormal - detailsFor (Namespace _ ["PerasCertBoostsCurrentChain"]) _ = Just DNormal - detailsFor (Namespace _ ["PerasCertBoostsGenesis"]) _ = Just DNormal - detailsFor (Namespace _ ["PerasCertBoostsBlockNotYetReceived"]) _ = Just DNormal - detailsFor (Namespace _ ["ChainSelectionForBoostedBlock"]) _ = Just DNormal - detailsFor _ _ = Nothing - - documentFor (Namespace _ ["AddedPerasCertToQueue"]) = Just "Peras certificate added to processing queue" - documentFor (Namespace _ ["PoppedPerasCertFromQueue"]) = Just "Peras certificate popped from processing queue" - documentFor (Namespace _ ["IgnorePerasCertTooOld"]) = Just "Peras certificate ignored as it is too old compared to immutable slot" - documentFor (Namespace _ ["PerasCertBoostsCurrentChain"]) = Just "Peras certificate boosts a block on the current selection" - documentFor (Namespace _ ["PerasCertBoostsGenesis"]) = Just "Peras certificate boosts the Genesis point" - documentFor (Namespace _ ["PerasCertBoostsBlockNotYetReceived"]) = Just "Peras certificate boosts a block not yet received" - documentFor (Namespace _ ["ChainSelectionForBoostedBlock"]) = Just "Perform chain selection for block boosted by Peras certificate" - documentFor _ = Nothing - - allNamespaces = - [Namespace [] ["AddedPerasCertToQueue"], - Namespace [] ["PoppedPerasCertFromQueue"], - Namespace [] ["IgnorePerasCertTooOld"], - Namespace [] ["PerasCertBoostsCurrentChain"], - Namespace [] ["PerasCertBoostsGenesis"], - Namespace [] ["PerasCertBoostsBlockNotYetReceived"], - Namespace [] ["ChainSelectionForBoostedBlock"]] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/Consensus.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/Consensus.hs deleted file mode 100644 index 5f80cd8db99..00000000000 --- a/cardano-node/src/Cardano/Node/Tracing/Tracers/Consensus.hs +++ /dev/null @@ -1,2510 +0,0 @@ -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE RecordWildCards #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeApplications #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE UndecidableInstances #-} -{-# LANGUAGE ViewPatterns #-} - -{-# OPTIONS_GHC -Wno-orphans #-} - -module Cardano.Node.Tracing.Tracers.Consensus - ( - initialClientMetrics - , calculateBlockFetchClientMetrics - , servedBlockLatest - , ClientMetrics - , txsMempoolTimeoutSoftCounterName - , txsSyncDurationTotalCounterName - , impliesMempoolTimeoutSoft - ) where - - -import qualified Cardano.KESAgent.Processes.ServiceClient as Agent -import Cardano.Logging -import Cardano.Node.Queries (ConvertTxId (..), HasKESInfo (..)) -import Cardano.Node.Tracing.Era.Byron () -import Cardano.Node.Tracing.Era.Shelley () -import Cardano.Node.Tracing.Formatting () -import Cardano.Node.Tracing.Render -import Cardano.Node.Tracing.Tracers.ConsensusStartupException () -import Cardano.Protocol.TPraos.OCert (KESPeriod (..)) -import Cardano.Slotting.Slot (WithOrigin (..)) -import Ouroboros.Consensus.Block -import Ouroboros.Consensus.BlockchainTime (SystemStart (..)) -import Ouroboros.Consensus.BlockchainTime.WallClock.Util (TraceBlockchainTimeEvent (..)) -import Ouroboros.Consensus.Cardano.Block -import Ouroboros.Consensus.Genesis.Governor (DensityBounds (..), GDDDebugInfo (..), - TraceGDDEvent (..)) -import Ouroboros.Consensus.Ledger.Extended (ExtValidationError) -import Ouroboros.Consensus.Ledger.Inspect (LedgerEvent (..), LedgerUpdate, LedgerWarning) -import Ouroboros.Consensus.Ledger.SupportsMempool (ApplyTxErr, ByteSize32 (..), GenTxId, - HasTxId, LedgerSupportsMempool, txForgetValidated, txId) -import Ouroboros.Consensus.Ledger.SupportsProtocol -import Ouroboros.Consensus.Mempool (MempoolRejectionDetails (..), MempoolSize (..), - TraceEventMempool (..), jsonMempoolRejectionDetails) -import Ouroboros.Consensus.MiniProtocol.BlockFetch.Server - (TraceBlockFetchServerEvent (..)) -import Ouroboros.Consensus.MiniProtocol.ChainSync.Client -import Ouroboros.Consensus.MiniProtocol.ChainSync.Client.Jumping as Jumping -import Ouroboros.Consensus.MiniProtocol.ChainSync.Client.State (JumpInfo (..)) -import Ouroboros.Consensus.MiniProtocol.ChainSync.Server -import Ouroboros.Consensus.MiniProtocol.LocalTxSubmission.Server - (TraceLocalTxSubmissionServerEvent (..)) -import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.Inbound (NumObjectsProcessed (..), - TraceObjectDiffusionInbound (..)) -import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.Outbound - (TraceObjectDiffusionOutbound (..)) -import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.PerasCert - (TracePerasCertDiffusionInbound, TracePerasCertDiffusionOutbound) -import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.PerasVote - (TracePerasVoteDiffusionInbound, TracePerasVoteDiffusionOutbound) -import Ouroboros.Consensus.Node.GSM -import Ouroboros.Consensus.Node.Run (SerialiseNodeToNodeConstraints, estimateBlockSize) -import Ouroboros.Consensus.Node.Tracers -import qualified Ouroboros.Consensus.Protocol.Ledger.HotKey as HotKey -import Ouroboros.Consensus.Protocol.Praos.AgentClient -import Ouroboros.Consensus.Util.Enclose -import qualified Ouroboros.Network.AnchoredFragment as AF -import qualified Ouroboros.Network.AnchoredSeq as AS -import Ouroboros.Network.Block hiding (blockPrevHash) -import Ouroboros.Network.BlockFetch.ClientState (TraceLabelPeer (..)) -import qualified Ouroboros.Network.BlockFetch.ClientState as BlockFetch -import Ouroboros.Network.BlockFetch.Decision -import Ouroboros.Network.BlockFetch.Decision.Trace (TraceDecisionEvent (..)) -import Ouroboros.Network.OrphanInstances () -import Ouroboros.Network.SizeInBytes (SizeInBytes (..)) - -import Control.Exception (displayException) -import Control.Monad (guard) -import Data.Aeson (ToJSON, Value (..), object, toJSON, (.=)) -import qualified Data.Aeson as Aeson -import Data.Foldable (Foldable (toList)) -import Data.Int (Int64) -import Data.IntPSQ (IntPSQ) -import qualified Data.IntPSQ as Pq -import qualified Data.Text as Text -import Data.Time (NominalDiffTime) -import Data.Word (Word32, Word64) -import Network.TypedProtocol.Core - -enclosingValue :: ToJSON a => Enclosing' a -> Value -enclosingValue RisingEdge = object [ "edge" .= String "Starting" ] -enclosingValue (FallingEdgeWith a) = object [ "edge" .= toJSON a ] - --------------------------------------------------------------------------------- --- TraceLabelCreds peer a --------------------------------------------------------------------------------- - -instance LogFormatting a => LogFormatting (TraceLabelCreds a) where - forMachine dtal (TraceLabelCreds creds a) = - mconcat $ ("credentials" .= toJSON creds) : [forMachine dtal a] - - forHuman (TraceLabelCreds creds a) = - "With label " <> (Text.pack . show) creds <> ", " <> forHuman a - asMetrics (TraceLabelCreds _creds a) = - asMetrics a - -instance MetaTrace a => MetaTrace (TraceLabelCreds a) where - namespaceFor (TraceLabelCreds _label obj) = (nsCast . namespaceFor) obj - severityFor ns Nothing = severityFor (nsCast ns :: Namespace a) Nothing - severityFor ns (Just (TraceLabelCreds _label obj)) = - severityFor (nsCast ns :: Namespace a) (Just obj) - privacyFor ns Nothing = privacyFor (nsCast ns :: Namespace a) Nothing - privacyFor ns (Just (TraceLabelCreds _label obj)) = - privacyFor (nsCast ns :: Namespace a) (Just obj) - detailsFor ns Nothing = detailsFor (nsCast ns :: Namespace a) Nothing - detailsFor ns (Just (TraceLabelCreds _label obj)) = - detailsFor (nsCast ns :: Namespace a) (Just obj) - documentFor ns = documentFor (nsCast ns :: Namespace a) - metricsDocFor ns = metricsDocFor (nsCast ns :: Namespace a) - allNamespaces = map nsCast (allNamespaces :: [Namespace a]) - - --------------------------------------------------------------------------------- --- TraceLabelPeer peer a --------------------------------------------------------------------------------- - -instance (LogFormatting peer, Show peer, LogFormatting a) - => LogFormatting (TraceLabelPeer peer a) where - forMachine dtal (TraceLabelPeer peerid a) = - mconcat [ "peer" .= forMachine dtal peerid ] <> forMachine dtal a - forHuman (TraceLabelPeer peerid a) = "Peer is: (" <> showT peerid - <> "). " <> forHuman a - asMetrics (TraceLabelPeer _peerid a) = asMetrics a - -instance MetaTrace a => MetaTrace (TraceLabelPeer label a) where - namespaceFor (TraceLabelPeer _label obj) = (nsCast . namespaceFor) obj - severityFor ns Nothing = severityFor (nsCast ns :: Namespace a) Nothing - severityFor ns (Just (TraceLabelPeer _label obj)) = - severityFor (nsCast ns) (Just obj) - privacyFor ns Nothing = privacyFor (nsCast ns :: Namespace a) Nothing - privacyFor ns (Just (TraceLabelPeer _label obj)) = - privacyFor (nsCast ns) (Just obj) - detailsFor ns Nothing = detailsFor (nsCast ns :: Namespace a) Nothing - detailsFor ns (Just (TraceLabelPeer _label obj)) = - detailsFor (nsCast ns) (Just obj) - documentFor ns = documentFor (nsCast ns :: Namespace a) - metricsDocFor ns = metricsDocFor (nsCast ns :: Namespace a) - allNamespaces = map nsCast (allNamespaces :: [Namespace a]) - -instance (LogFormatting (LedgerUpdate blk), LogFormatting (LedgerWarning blk)) - => LogFormatting (LedgerEvent blk) where - forMachine dtal = \case - LedgerUpdate update -> forMachine dtal update - LedgerWarning warning -> forMachine dtal warning - - --------------------------------------------------------------------------------- --- ChainSyncClient Tracer --------------------------------------------------------------------------------- - -instance (ConvertRawHash blk, ConvertRawHash (Header blk), LedgerSupportsProtocol blk) - => LogFormatting (TraceChainSyncClientEvent blk) where - forHuman = \case - TraceDownloadedHeader pt -> - mconcat - [ "While following a candidate chain, we rolled forward by downloading a" - , " header. " - , showT (headerPoint pt) - ] - TraceRolledBack tip -> - "While following a candidate chain, we rolled back to the given point: " <> showT tip - TraceException exc -> - "An exception was thrown by the Chain Sync Client. " <> showT exc - TraceFoundIntersection {} -> - mconcat - [ "We found an intersection between our chain fragment and the" - , " candidate's chain." - ] - TraceTermination res -> - "The client has terminated. " <> showT res - TraceValidatedHeader header -> - "The header has been validated" <> showT (headerHash header) - TraceWaitingBeyondForecastHorizon slotNo -> - mconcat - [ "The slot number " <> showT slotNo <> " is beyond the forecast horizon, the ChainSync client" - , " cannot yet validate a header in this slot and therefore is waiting" - ] - TraceAccessingForecastHorizon slotNo -> - mconcat - [ "The slot number " <> showT slotNo <> ", which was previously beyond the forecast horizon, has now" - , " entered it, and we can resume processing." - ] - TraceGaveLoPToken {} -> - mconcat - [ "Whether we added a token to the LoP bucket of the peer. Also carries" - , "the considered header and the best block number known prior to this" - , "header" - ] - TraceOfferJump point -> - mconcat - [ "ChainSync Jumping -- we are offering a jump to the server, to point: " - , showT point - ] - TraceJumpResult (AcceptedJump instruction) -> - mconcat - [ "ChainSync Jumping -- the client accepted the jump to " - , showT (jumpInstructionToPoint instruction) - ] - TraceJumpResult (RejectedJump instruction) -> - mconcat - [ "ChainSync Jumping -- the client rejected the jump to " - , showT (jumpInstructionToPoint instruction) - ] - TraceJumpingWaitingForNextInstruction -> - "ChainSync Jumping -- the client is blocked, waiting for its next instruction." - TraceJumpingInstructionIs RunNormally -> - "ChainSyncJumping -- the client is asked to run normally" - TraceJumpingInstructionIs Restart -> - mconcat - [ "ChainSyncJumping -- the client is asked to restart. This is necessary" - , "when disengaging a peer of which we know no point that we could set" - , "the intersection of the ChainSync server to." - ] - TraceJumpingInstructionIs (JumpInstruction instruction) -> - mconcat - [ "ChainSync Jumping -- the client is asked to jump to " - , showT (jumpInstructionToPoint instruction) - ] - TraceDrainingThePipe n -> - "ChainSync client is draining the pipe. Pipelined messages expected: " <> showT (natToInt n) - where - jumpInstructionToPoint = AF.headPoint . jTheirFragment . \case - JumpTo ji -> ji - JumpToGoodPoint ji -> ji - - forMachine dtal = \case - TraceDownloadedHeader h -> - mconcat - [ "kind" .= String "DownloadedHeader" - , tipToObject (tipFromHeader h) - ] - TraceRolledBack tip -> - mconcat - [ "kind" .= String "RolledBack" - , "tip" .= forMachine dtal tip - ] - TraceException exc -> - mconcat - [ "kind" .= String "Exception" - , "exception" .= String (Text.pack $ show exc) - ] - TraceFoundIntersection {} -> - mconcat - [ "kind" .= String "FoundIntersection" - ] - TraceTermination reason -> - mconcat - [ "kind" .= String "Termination" - , "reason" .= String (Text.pack $ show reason) - ] - TraceValidatedHeader header -> - mconcat - [ "kind" .= String "ValidatedHeader" - , "headerHash" .= showT (headerHash header) - ] - TraceWaitingBeyondForecastHorizon slotNo -> - mconcat - [ "kind" .= String "WaitingBeyondForecastHorizon" - , "slotNo" .= slotNo - ] - TraceAccessingForecastHorizon slotNo -> - mconcat - [ "kind" .= String "AccessingForecastHorizon" - , "slotNo" .= slotNo - ] - TraceGaveLoPToken tokenAdded header aBlockNo -> - mconcat - [ "kind" .= String "TraceGaveLoPToken" - , "tokenAdded" .= tokenAdded - , "headerHash" .= showT (headerHash header) - , "blockNo" .= aBlockNo - ] - TraceOfferJump point -> - mconcat - [ "kind" .= String "TraceOfferJump" - , "point" .= showT point - ] - TraceJumpResult jumpResult -> - mconcat - [ "kind" .= String "TraceJumpResult" - , "result" .= case jumpResult of - AcceptedJump _ -> String "AcceptedJump" - RejectedJump _ -> String "RejectedJump" - ] - TraceJumpingWaitingForNextInstruction -> - mconcat - [ "kind" .= String "TraceJumpingWaitingForNextInstruction" - ] - TraceJumpingInstructionIs instruction -> - mconcat - [ "kind" .= String "TraceJumpingInstructionIs" - , "instr" .= instructionToObject instruction - ] - TraceDrainingThePipe n -> - mconcat - [ "kind" .= String "TraceDrainingThePipe" - , "n" .= natToInt n - ] - where - instructionToObject :: Instruction blk -> Aeson.Object - instructionToObject = \case - RunNormally -> - mconcat ["kind" .= String "RunNormally"] - Restart -> - mconcat ["kind" .= String "Restart"] - JumpInstruction info -> - mconcat [ "kind" .= String "JumpInstruction" - , "payload" .= jumpInstructionToObject info - ] - - jumpInstructionToObject :: JumpInstruction blk -> Aeson.Object - jumpInstructionToObject = \case - JumpTo info -> - mconcat [ "kind" .= String "JumpTo" - , "point" .= showT (jumpInfoToPoint info) ] - JumpToGoodPoint info -> - mconcat [ "kind" .= String "JumpToGoodPoint" - , "point" .= showT (jumpInfoToPoint info) ] - - jumpInfoToPoint = AF.headPoint . jTheirFragment - -tipToObject :: forall blk. ConvertRawHash blk => Tip blk -> Aeson.Object -tipToObject = \case - TipGenesis -> mconcat - [ "slot" .= toJSON (0 :: Int) - , "block" .= String "genesis" - , "blockNo" .= toJSON ((-1) :: Int) - ] - Tip slot hash blockno -> mconcat - [ "slot" .= slot - , "block" .= String (renderHeaderHash (Proxy @blk) hash) - , "blockNo" .= blockno - ] - -instance MetaTrace (TraceChainSyncClientEvent blk) where - namespaceFor = \case - TraceDownloadedHeader {} -> - Namespace [] ["DownloadedHeader"] - TraceRolledBack {} -> - Namespace [] ["RolledBack"] - TraceException {} -> - Namespace [] ["Exception"] - TraceFoundIntersection {} -> - Namespace [] ["FoundIntersection"] - TraceTermination {} -> - Namespace [] ["Termination"] - TraceValidatedHeader {} -> - Namespace [] ["ValidatedHeader"] - TraceWaitingBeyondForecastHorizon {} -> - Namespace [] ["WaitingBeyondForecastHorizon"] - TraceAccessingForecastHorizon {} -> - Namespace [] ["AccessingForecastHorizon"] - TraceGaveLoPToken {} -> - Namespace [] ["GaveLoPToken"] - TraceOfferJump _ -> - Namespace [] ["OfferJump"] - TraceJumpResult _ -> - Namespace [] ["JumpResult"] - TraceJumpingWaitingForNextInstruction -> - Namespace [] ["JumpingWaitingForNextInstruction"] - TraceJumpingInstructionIs _ -> - Namespace [] ["JumpingInstructionIs"] - TraceDrainingThePipe _ -> - Namespace [] ["DrainingThePipe"] - - severityFor ns _ = - case ns of - Namespace _ ["DownloadedHeader"] -> - Just Info - Namespace _ ["RolledBack"] -> - Just Notice - Namespace _ ["Exception"] -> - Just Warning - Namespace _ ["FoundIntersection"] -> - Just Info - Namespace _ ["Termination"] -> - Just Notice - Namespace _ ["ValidatedHeader"] -> - Just Debug - Namespace _ ["WaitingBeyondForecastHorizon"] -> - Just Debug - Namespace _ ["AccessingForecastHorizon"] -> - Just Debug - Namespace _ ["GaveLoPToken"] -> - Just Debug - Namespace _ ["OfferJump"] -> - Just Debug - Namespace _ ["JumpResult"] -> - Just Debug - Namespace _ ["JumpingWaitingForNextInstruction"] -> - Just Debug - Namespace _ ["JumpingInstructionIs"] -> - Just Debug - Namespace _ ["DrainingThePipe"] -> - Just Debug - _ -> - Nothing - - documentFor ns = - case ns of - Namespace _ ["DownloadedHeader"] -> - Just $ mconcat - [ "While following a candidate chain, we rolled forward by downloading a" - , " header." - ] - Namespace _ ["RolledBack"] -> - Just "While following a candidate chain, we rolled back to the given point." - Namespace _ ["Exception"] -> - Just "An exception was thrown by the Chain Sync Client." - Namespace _ ["FoundIntersection"] -> - Just $ mconcat - [ "We found an intersection between our chain fragment and the" - , " candidate's chain." - ] - Namespace _ ["Termination"] -> - Just "The client has terminated." - Namespace _ ["ValidatedHeader"] -> - Just "The header has been validated" - Namespace _ ["WaitingBeyondForecastHorizon"] -> - Just "The slot number is beyond the forecast horizon" - Namespace _ ["AccessingForecastHorizon"] -> - Just "The slot number, which was previously beyond the forecast horizon, has now entered it" - Namespace _ ["GaveLoPToken"] -> - Just "May have added atoken to the LoP bucket of the peer" - Namespace _ ["OfferJump"] -> - Just "Offering a jump to the remote peer" - Namespace _ ["JumpResult"] -> - Just "Response to a jump offer (accept or reject)" - Namespace _ ["JumpingWaitingForNextInstruction"] -> - Just "The client is waiting for the next instruction" - Namespace _ ["JumpingInstructionIs"] -> - Just "The client got its next instruction" - Namespace _ ["DrainingThePipe"] -> - Just "The client is draining the pipe of messages" - _ -> - Nothing - - allNamespaces = - [ Namespace [] ["DownloadedHeader"] - , Namespace [] ["RolledBack"] - , Namespace [] ["Exception"] - , Namespace [] ["FoundIntersection"] - , Namespace [] ["Termination"] - , Namespace [] ["ValidatedHeader"] - , Namespace [] ["WaitingBeyondForecastHorizon"] - , Namespace [] ["AccessingForecastHorizon"] - , Namespace [] ["GaveLoPToken"] - , Namespace [] ["OfferJump"] - , Namespace [] ["JumpResult"] - , Namespace [] ["JumpingWaitingForNextInstruction"] - , Namespace [] ["JumpingInstructionIs"] - , Namespace [] ["DrainingThePipe"] - ] - --------------------------------------------------------------------------------- --- ChainSyncServer Tracer --------------------------------------------------------------------------------- - -instance ConvertRawHash blk - => LogFormatting (TraceChainSyncServerEvent blk) where - forMachine dtal (TraceChainSyncServerUpdate tip update blocking enclosing) = - mconcat $ - [ "kind" .= String "ChainSyncServer.Update" - , "tip" .= tipToObject tip - , case update of - AddBlock pt -> "addBlock" .= renderPointForDetails dtal pt - RollBack pt -> "rollBackTo" .= renderPointForDetails dtal pt - , "blockingRead" .= case blocking of Blocking -> True; NonBlocking -> False - ] - <> [ "risingEdge" .= True | RisingEdge <- [enclosing] ] - - asMetrics (TraceChainSyncServerUpdate _tip (AddBlock _pt) _blocking FallingEdge) = - [CounterM "served.header" Nothing] - asMetrics (TraceChainSyncServerUpdate _tip (AddBlock _pt) _blocking _) = [] - asMetrics _ = [] - -instance MetaTrace (TraceChainSyncServerEvent blk) where - namespaceFor TraceChainSyncServerUpdate {} = Namespace [] ["Update"] - - severityFor (Namespace _ ["Update"]) - (Just (TraceChainSyncServerUpdate _tip _upd _blocking enclosing)) = - case enclosing of - RisingEdge -> Just Info - FallingEdge -> Just Debug - severityFor (Namespace _ ["Update"]) Nothing = Just Info - severityFor _ _ = Nothing - - metricsDocFor (Namespace _ ["Update"]) = - [ ("served.header", - "A counter triggered only on header event with falling edge")] - metricsDocFor _ = [] - - documentFor (Namespace _ ["Update"]) = Just - "A server read has occurred, either for an add block or a rollback" - documentFor _ = Nothing - - allNamespaces = [Namespace [] ["Update"]] - --------------------------------------------------------------------------------- --- BlockFetchClient Metrics --------------------------------------------------------------------------------- - -data CdfCounter = CdfCounter { - limit :: !Double - , counter :: !Int64 -} - -decCdf :: Double -> CdfCounter -> CdfCounter -decCdf v cdf@CdfCounter{..} - | v < limit = cdf {counter = counter - 1} - | otherwise = cdf - -incCdf :: Double -> CdfCounter -> CdfCounter -incCdf v cdf@CdfCounter{..} - | v < limit = cdf {counter = counter + 1} - | otherwise = cdf - -data ClientMetrics = ClientMetrics { - cmSlotMap :: IntPSQ Word64 NominalDiffTime - , cmCdf1sVar :: !CdfCounter - , cmCdf3sVar :: !CdfCounter - , cmCdf5sVar :: !CdfCounter - , cmDelay :: Double - , cmBlockSize :: Word32 - , cmTraceIt :: Bool - , cmTraceVars :: Bool -} - -instance LogFormatting ClientMetrics where - forMachine _dtal _ = mempty - asMetrics ClientMetrics {cmTraceIt = False} = [] - asMetrics ClientMetrics {..} = - [ DoubleM "blockfetchclient.blockdelay" cmDelay - , IntM "blockfetchclient.blocksize" (fromIntegral cmBlockSize) - ] - ++ lateBlockMetric - ++ if cmTraceVars - then [ cdfMetric "blockfetchclient.blockdelay.cdfOne" cmCdf1sVar - , cdfMetric "blockfetchclient.blockdelay.cdfThree" cmCdf3sVar - , cdfMetric "blockfetchclient.blockdelay.cdfFive" cmCdf5sVar - ] - else [] - where - size = Pq.size cmSlotMap - cdfMetric name var = DoubleM name (fromIntegral (counter var) / fromIntegral size) - lateBlockMetric = [ CounterM "blockfetchclient.lateblocks" Nothing | cmDelay > 5 ] - -instance MetaTrace ClientMetrics where - namespaceFor _ = Namespace [] ["ClientMetrics"] - severityFor _ _ = Just Debug - documentFor _ = Just "" - - metricsDocFor (Namespace _ ["ClientMetrics"]) = - [ ("blockfetchclient.blockdelay", "delay (s) of the latest block fetch") - , ("blockfetchclient.blocksize", "block size (bytes) of the latest block fetch") - , ("blockfetchclient.lateblocks", "number of block fetches that took longer than 5s") - , ("blockfetchclient.blockdelay.cdfOne", "probability for block fetch to complete within 1s") - , ("blockfetchclient.blockdelay.cdfThree", "probability for block fetch to complete within 3s") - , ("blockfetchclient.blockdelay.cdfFive", "probability for block fetch to complete within 5s") - ] - metricsDocFor _ = [] - - allNamespaces = [ - Namespace [] ["ClientMetrics"] - ] - -initialClientMetrics :: ClientMetrics -initialClientMetrics = - ClientMetrics - Pq.empty - (CdfCounter 1 0) - (CdfCounter 3 0) - (CdfCounter 5 0) - 0 - 0 - False - False - -calculateBlockFetchClientMetrics :: - ClientMetrics - -> LoggingContext - -> BlockFetch.TraceLabelPeer peer (BlockFetch.TraceFetchClientState header) - -> ClientMetrics -calculateBlockFetchClientMetrics cm@ClientMetrics {..} _lc - (TraceLabelPeer _ (BlockFetch.CompletedBlockFetch p _ _ _ forgeDelay blockSize)) = - case pointSlot p of - Origin -> nothingToDo - At (SlotNo slotNo) -> - if Pq.null cmSlotMap && forgeDelay > 20 -- During startup wait until we are in sync - then nothingToDo - else processSlot slotNo - where - nothingToDo = cm {cmTraceIt = False} - delay = realToFrac forgeDelay - - processSlot slotNo - | fromIntegral slotNo `Pq.member` cmSlotMap = nothingToDo -- Duplicate, only track the first - | otherwise = - let slotMap' = Pq.insert (fromIntegral slotNo) slotNo forgeDelay cmSlotMap - in if Pq.size slotMap' > 1080 -- TODO: k/2, should come from config file - then trimSlotMap slotMap' slotNo - else updateMetrics slotMap' - - trimSlotMap slotMap' slotNo = case Pq.minView slotMap' of - Nothing -> nothingToDo -- Error: Just inserted element - Just (_, minSlotNo, realToFrac -> minDelay, slotMap'') - | minSlotNo == slotNo -> nothingToDo - | otherwise -> cm - { cmCdf1sVar = adjust minDelay cmCdf1sVar - , cmCdf3sVar = adjust minDelay cmCdf3sVar - , cmCdf5sVar = adjust minDelay cmCdf5sVar - , cmDelay = delay - , cmBlockSize = getSizeInBytes blockSize - , cmTraceVars = True - , cmTraceIt = True - , cmSlotMap = slotMap'' - } - - updateMetrics slotMap' = cm - { cmCdf1sVar = update cmCdf1sVar - , cmCdf3sVar = update cmCdf3sVar - , cmCdf5sVar = update cmCdf5sVar - , cmDelay = delay - , cmBlockSize = getSizeInBytes blockSize - , cmTraceVars = Pq.size cmSlotMap >= 45 -- wait until we have at least 45 samples before providing cdf estimates - , cmTraceIt = True - , cmSlotMap = slotMap' - } - - update = incCdf delay - adjust d = update . decCdf d - -calculateBlockFetchClientMetrics cm _lc _ = cm - - --------------------------------------------------------------------------------- --- BlockFetchDecision Tracer --------------------------------------------------------------------------------- - -instance MetaTrace (TraceDecisionEvent peer (Header blk)) where - namespaceFor PeersFetch{} = Namespace [] ["PeersFetch"] - namespaceFor PeerStarvedUs{} = Namespace [] ["PeerStarvedUs"] - - severityFor (Namespace _ ["PeersFetch"]) _ = Just Debug - severityFor (Namespace _ ["PeerStarvedUs"]) _ = Just Info - severityFor _ _ = Nothing - - documentFor (Namespace [] ["PeersFetch"]) = - Just "list of block-fetch decisions" - documentFor (Namespace [] ["PeerStarvedUs"]) = - Just "current peer starved us, the node will switch to a different peer" - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["PeersFetch"], Namespace [] ["PeerStarvedUs"] ] - -instance (Show peer, ToJSON peer, LogFormatting peer, HasHeader blk) - => LogFormatting (TraceDecisionEvent peer (Header blk)) where - forHuman = Text.pack . show - - forMachine dtal (PeersFetch xs) = - mconcat [ "kind" .= String "PeerFetch" - , "decisions" .= map (forMachine dtal) xs - ] - forMachine _dtal (PeerStarvedUs peer) = - mconcat [ "kind" .= String "PeerStarvedUs" - , "peer" .= toJSON peer - ] - -instance LogFormatting (FetchDecision [Point header]) where - forMachine _dtal (Left decline) = - mconcat [ "kind" .= String "FetchDecision declined" - , "declined" .= String (showT decline) - ] - forMachine _dtal (Right results) = - mconcat [ "kind" .= String "FetchDecision results" - , "length" .= String (showT $ length results) - ] - --------------------------------------------------------------------------------- --- BlockFetchClientState Tracer --------------------------------------------------------------------------------- - -instance (HasHeader header, ConvertRawHash header) => - LogFormatting (BlockFetch.TraceFetchClientState header) where - forMachine _dtal BlockFetch.AddedFetchRequest {} = - mconcat [ "kind" .= String "AddedFetchRequest" ] - forMachine _dtal BlockFetch.AcknowledgedFetchRequest {} = - mconcat [ "kind" .= String "AcknowledgedFetchRequest" ] - forMachine dtal (BlockFetch.SendFetchRequest af gsv) = - mconcat $ - [ "kind" .= String "SendFetchRequest" - , "head" .= String (renderChainHash - (renderHeaderHash (Proxy @header)) - (AF.headHash af)) - , "length" .= toJSON (fragmentLength' af)] - ++ - [ "deltaq" .= toJSON gsv | dtal >= DDetailed ] - where - -- NOTE: this ignores the Byron era with its EBB complication: - -- the length would be underestimated by 1, if the AF is anchored - -- at the epoch boundary. - fragmentLength' :: AF.AnchoredFragment header -> Int - fragmentLength' f = fromIntegral . unBlockNo $ - case (f, f) of - (AS.Empty{}, AS.Empty{}) -> 0 - (firstHdr AS.:< _, _ AS.:> lastHdr) -> - blockNo lastHdr - blockNo firstHdr + 1 - forMachine _dtal (BlockFetch.CompletedBlockFetch pt _ _ _ delay blockSize) = - mconcat [ "kind" .= String "CompletedBlockFetch" - , "delay" .= (realToFrac delay :: Double) - , "size" .= getSizeInBytes blockSize - , "block" .= String - (case pt of - GenesisPoint -> "Genesis" - BlockPoint _ h -> renderHeaderHash (Proxy @header) h) - ] - forMachine _dtal BlockFetch.CompletedFetchBatch {} = - mconcat [ "kind" .= String "CompletedFetchBatch" ] - forMachine _dtal BlockFetch.StartedFetchBatch {} = - mconcat [ "kind" .= String "StartedFetchBatch" ] - forMachine _dtal BlockFetch.RejectedFetchBatch {} = - mconcat [ "kind" .= String "RejectedFetchBatch" ] - forMachine _dtal (BlockFetch.ClientTerminating outstanding) = - mconcat [ "kind" .= String "ClientTerminating" - , "outstanding" .= outstanding - ] - -instance MetaTrace (BlockFetch.TraceFetchClientState header) where - namespaceFor BlockFetch.AddedFetchRequest {} = - Namespace [] ["AddedFetchRequest"] - namespaceFor BlockFetch.AcknowledgedFetchRequest {} = - Namespace [] ["AcknowledgedFetchRequest"] - namespaceFor BlockFetch.SendFetchRequest {} = - Namespace [] ["SendFetchRequest"] - namespaceFor BlockFetch.StartedFetchBatch {} = - Namespace [] ["StartedFetchBatch"] - namespaceFor BlockFetch.CompletedFetchBatch {} = - Namespace [] ["CompletedFetchBatch"] - namespaceFor BlockFetch.CompletedBlockFetch {} = - Namespace [] ["CompletedBlockFetch"] - namespaceFor BlockFetch.RejectedFetchBatch {} = - Namespace [] ["RejectedFetchBatch"] - namespaceFor BlockFetch.ClientTerminating {} = - Namespace [] ["ClientTerminating"] - - severityFor (Namespace _ ["AddedFetchRequest"]) _ = Just Info - severityFor (Namespace _ ["AcknowledgedFetchRequest"]) _ = Just Info - severityFor (Namespace _ ["SendFetchRequest"]) _ = Just Info - severityFor (Namespace _ ["StartedFetchBatch"]) _ = Just Info - severityFor (Namespace _ ["CompletedFetchBatch"]) _ = Just Info - severityFor (Namespace _ ["CompletedBlockFetch"]) _ = Just Info - severityFor (Namespace _ ["RejectedFetchBatch"]) _ = Just Info - severityFor (Namespace _ ["ClientTerminating"]) _ = Just Notice - severityFor _ _ = Nothing - - documentFor (Namespace _ ["AddedFetchRequest"]) = Just $ mconcat - [ "The block fetch decision thread has added a new fetch instruction" - , " consisting of one or more individual request ranges." - ] - documentFor (Namespace _ ["AcknowledgedFetchRequest"]) = Just $ mconcat - [ "Mark the point when the fetch client picks up the request added" - , " by the block fetch decision thread. Note that this event can happen" - , " fewer times than the 'AddedFetchRequest' due to fetch request merging." - ] - documentFor (Namespace _ ["SendFetchRequest"]) = Just $ mconcat - [ "Mark the point when fetch request for a fragment is actually sent" - , " over the wire." - ] - documentFor (Namespace _ ["StartedFetchBatch"]) = Just $ mconcat - [ "Mark the start of receiving a streaming batch of blocks. This will" - , " be followed by one or more 'CompletedBlockFetch' and a final" - , " 'CompletedFetchBatch'" - ] - documentFor (Namespace _ ["CompletedFetchBatch"]) = Just - "Mark the successful end of receiving a streaming batch of blocks." - documentFor (Namespace _ ["CompletedBlockFetch"]) = Just - "" - documentFor (Namespace _ ["RejectedFetchBatch"]) = Just $ mconcat - [ "If the other peer rejects our request then we have this event" - , " instead of 'StartedFetchBatch' and 'CompletedFetchBatch'." - ] - documentFor (Namespace _ ["ClientTerminating"]) = Just $ mconcat - [ "The client is terminating. Log the number of outstanding" - , " requests." - ] - documentFor _ = Nothing - - allNamespaces = [ - Namespace [] ["AddedFetchRequest"] - , Namespace [] ["AcknowledgedFetchRequest"] - , Namespace [] ["SendFetchRequest"] - , Namespace [] ["StartedFetchBatch"] - , Namespace [] ["CompletedFetchBatch"] - , Namespace [] ["CompletedBlockFetch"] - , Namespace [] ["RejectedFetchBatch"] - , Namespace [] ["ClientTerminating"] - ] - --------------------------------------------------------------------------------- --- BlockFetchServerEvent --------------------------------------------------------------------------------- - -instance ConvertRawHash blk => LogFormatting (TraceBlockFetchServerEvent blk) where - forMachine _dtal (TraceBlockFetchServerSendBlock blk) = - mconcat [ "kind" .= String "BlockFetchServer" - , "block" .= String (renderChainHash - @blk - (renderHeaderHash (Proxy @blk)) - $ pointHash blk)] - asMetrics (TraceBlockFetchServerSendBlock _p) = - [CounterM "served.block" Nothing] - -instance MetaTrace (TraceBlockFetchServerEvent blk) where - namespaceFor TraceBlockFetchServerSendBlock {} = - Namespace [] ["SendBlock"] - - severityFor (Namespace [] ["SendBlock"]) _ = Just - Info - severityFor _ _ = Nothing - - metricsDocFor (Namespace [] ["SendBlock"]) = - [("served.block", "This counter metric indicates how many blocks this node has served.") - ,("served.block.latest", "This counter metric indicates how many chain tip blocks this node has served.")] - metricsDocFor _ = [] - - documentFor (Namespace [] ["SendBlock"]) = Just - "The server sent a block to the peer." - documentFor _ = Nothing - - allNamespaces = [Namespace [] ["SendBlock"]] - --------------------------------------------------------------------------------- --- Metric for server block latest --- Only traces to EKG, no complete tracer! --------------------------------------------------------------------------------- - -data ServedBlock = ServedBlock { - maxSlotNo :: SlotNo - , localUp :: Word64 - , servedBlocksLatest :: Word64 -} - -instance LogFormatting ServedBlock where - forMachine _mDtal ServedBlock {} = mempty - - asMetrics ServedBlock {..} = - [IntM "served.block.latest" (fromIntegral servedBlocksLatest)] - -emptyServedBlocks :: ServedBlock -emptyServedBlocks = ServedBlock 0 0 0 - -servedBlockLatest :: - Maybe (Trace IO FormattedMessage) - -> IO (Trace IO (TraceLabelPeer peer (TraceBlockFetchServerEvent blk))) -servedBlockLatest mbTrEKG = - foldTraceM calculateServedBlockLatest emptyServedBlocks - (metricsFormatter - (mkMetricsTracer mbTrEKG)) - -calculateServedBlockLatest :: (Monad m) - =>ServedBlock - -> LoggingContext - -> TraceLabelPeer peer (TraceBlockFetchServerEvent blk) - -> m ServedBlock -calculateServedBlockLatest ServedBlock{..} _lc (TraceLabelPeer _ (TraceBlockFetchServerSendBlock p)) = - case pointSlot p of - Origin -> return $ ServedBlock maxSlotNo localUp servedBlocksLatest - At slotNo -> - case compare maxSlotNo slotNo of - LT -> return $ ServedBlock slotNo (localUp + 1) (localUp + 1) - GT -> return $ ServedBlock maxSlotNo localUp servedBlocksLatest - EQ -> return $ ServedBlock maxSlotNo (localUp + 1) (localUp + 1) - - --------------------------------------------------------------------------------- --- Gdd Tracer --------------------------------------------------------------------------------- - -instance ( LogFormatting peer - , HasHeader blk - , HasHeader (Header blk) - , ConvertRawHash (Header blk) - ) => LogFormatting (TraceGDDEvent peer blk) where - forMachine dtal (TraceGDDDebug (GDDDebugInfo {..})) = mconcat $ - [ "kind" .= String "TraceGDDDebugInfo" - , "losingPeers".= toJSON (map (forMachine dtal) losingPeers) - , "loeHead" .= forMachine dtal loeHead - , "sgen" .= toJSON (unGenesisWindow sgen) - ] <> do - guard $ dtal >= DMaximum - [ "bounds" .= toJSON ( - map - ( \(peer, density) -> Aeson.object - [ "kind" .= String "PeerDensityBound" - , "peer" .= forMachine dtal peer - , "densityBounds" .= forMachine dtal density - ] - ) - bounds - ) - , "curChain" .= forMachine dtal curChain - , "candidates" .= toJSON ( - map - ( \(peer, frag) -> Aeson.object - [ "kind" .= String "PeerCandidateFragment" - , "peer" .= forMachine dtal peer - , "candidateFragment" .= forMachine dtal frag - ] - ) - candidates - ) - , "candidateSuffixes" .= toJSON ( - map - ( \(peer, frag) -> Aeson.object - [ "kind" .= String "PeerCandidateSuffix" - , "peer" .= forMachine dtal peer - , "candidateSuffix" .= forMachine dtal frag - ] - ) - candidateSuffixes - ) - ] - - forMachine dtal (TraceGDDDisconnected peers) = mconcat - [ "kind" .= String "TraceGDDDisconnected" - , "peers" .= toJSON (map (forMachine dtal) (toList peers)) - ] - -instance MetaTrace (TraceGDDEvent peer blk) where - namespaceFor _ = Namespace [] ["TraceGDDEvent"] - - severityFor _ _ = Just Debug - - documentFor _ = Just "The Genesis Density Disconnection governor has updated its state" - - allNamespaces = [Namespace [] ["TraceGDDEvent"]] - -instance ( HasHeader blk - , HasHeader (Header blk) - , ConvertRawHash (Header blk) - ) => LogFormatting (DensityBounds blk) where - forMachine dtal DensityBounds {..} = mconcat - [ "kind" .= String "DensityBounds" - , "clippedFragment" .= forMachine dtal clippedFragment - , "offersMoreThanK" .= toJSON offersMoreThanK - , "lowerBound" .= toJSON lowerBound - , "upperBound" .= toJSON upperBound - , "hasBlockAfter" .= toJSON hasBlockAfter - , "latestSlot" .= toJSON (unSlotNo <$> withOriginToMaybe latestSlot) - , "idling" .= toJSON idling - ] - - --------------------------------------------------------------------------------- --- SanityCheckIssue Tracer --------------------------------------------------------------------------------- - -instance MetaTrace SanityCheckIssue where - - namespaceFor _ = Namespace [] ["SanityCheckIssue"] - - severityFor (Namespace _ ["SanityCheckIssue"]) _ = Just Error - severityFor _ _ = Nothing - - documentFor (Namespace _ ["SanityCheckIssue"]) = Just $ mconcat - [ "A sanity check on the node configuration found a suspicious setting at" - , " startup. The `kind` field names the check that fired:" - , " `InconsistentSecurityParam`, `SnapshotDelayRangeInverted`," - , " `SnapshotDelayRangeNegativeMinimum`, `SnapshotRateLimitDisabled`," - , " `SnapshotRateLimitSuspiciouslyLarge`, `SnapshotNumZero` or" - , " `SnapshotIntervalNotDivisorOfEpoch`. These flag configurations that are" - , " legal but almost certainly unintended; the node continues to run." - ] - documentFor _ = Nothing - - allNamespaces = [Namespace [] ["SanityCheckIssue"]] - -instance LogFormatting SanityCheckIssue where - forMachine _dtal (InconsistentSecurityParam e) = - mconcat [ "kind" .= String "InconsistentSecurityParam" - , "error" .= String (Text.pack $ show e) - ] - forMachine _dtal (SnapshotDelayRangeInverted mn mx) = - mconcat [ "kind" .= String "SnapshotDelayRangeInverted" - , "minimumDelay" .= show mn - , "maximumDelay" .= show mx - ] - forMachine _dtal (SnapshotDelayRangeNegativeMinimum mn) = - mconcat [ "kind" .= String "SnapshotDelayRangeNegativeMinimum" - , "minimumDelay" .= show mn - ] - forMachine _dtal SnapshotRateLimitDisabled = - mconcat [ "kind" .= String "SnapshotRateLimitDisabled" - ] - forMachine _dtal (SnapshotRateLimitSuspiciouslyLarge rl) = - mconcat [ "kind" .= String "SnapshotRateLimitSuspiciouslyLarge" - , "rateLimit" .= show rl - ] - forMachine _dtal SnapshotNumZero = - mconcat [ "kind" .= String "SnapshotNumZero" - ] - forMachine _dtal (SnapshotIntervalNotDivisorOfEpoch interval) = - mconcat [ "kind" .= String "SnapshotIntervalNotDivisorOfEpoch" - , "interval" .= toJSON interval - ] - forHuman = Text.pack . displayException - --------------------------------------------------------------------------------- --- TxSubmissionServer Tracer --------------------------------------------------------------------------------- - -instance LogFormatting (TraceLocalTxSubmissionServerEvent blk) where - forMachine _dtal (TraceReceivedTx _gtx) = - mconcat [ "kind" .= String "ReceivedTx" ] - - -instance MetaTrace (TraceLocalTxSubmissionServerEvent blk) where - - namespaceFor TraceReceivedTx {} = - Namespace [] ["ReceivedTx"] - - severityFor (Namespace _ ["ReceivedTx"]) _ = - Just Info - severityFor _ _ = Nothing - - documentFor (Namespace _ ["ReceivedTx"]) = Just - "A transaction was received." - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["ReceivedTx"] - ] - --------------------------------------------------------------------------------- --- Mempool Tracer --------------------------------------------------------------------------------- - -txsMempoolTimeoutSoftCounterName :: Text.Text -txsMempoolTimeoutSoftCounterName = "txsMempoolTimeoutSoft" - -txsSyncDurationTotalCounterName :: Text.Text -txsSyncDurationTotalCounterName = "txsSyncDurationTotal" - -impliesMempoolTimeoutSoft :: TraceEventMempool blk -> Bool -impliesMempoolTimeoutSoft = \case - TraceMempoolRejectedTx _tx _txApplyErr details _mpSz -> - case details of - MempoolRejectedByTimeoutSoft{} -> True - MempoolRejectedByLedger -> False - _ -> False - -instance - ( LogFormatting (ApplyTxErr blk) - , LogFormatting (GenTx blk) - , Show (GenTxId blk) - , ConvertTxId blk - , LedgerSupportsMempool blk - , ConvertRawHash blk - ) => LogFormatting (TraceEventMempool blk) where - forMachine dtal (TraceMempoolAddedTx tx _mpSzBefore mpSzAfter) = - mconcat - [ "kind" .= String "TraceMempoolAddedTx" - , "tx" .= forMachine dtal (txForgetValidated tx) - , "mempoolSize" .= forMachine dtal mpSzAfter - ] - forMachine dtal (TraceMempoolRejectedTx tx txApplyErr details mpSz) = - mconcat $ - [ "kind" .= String "TraceMempoolRejectedTx" - , "tx" .= forMachine dtal tx - , "mempoolSize" .= forMachine dtal mpSz - ] <> - if dtal < DDetailed then [] else - [ "err" .= forMachine dtal txApplyErr - , "errdetails" .= jsonMempoolRejectionDetails details - ] - forMachine dtal (TraceMempoolRemoveTxs txs mpSz) = - mconcat - [ "kind" .= String "TraceMempoolRemoveTxs" - , "txs" - .= map - ( \(tx, err) -> - Aeson.object $ - [ "tx" .= forMachine dtal (txForgetValidated tx) - ] <> - [ "err" .= forMachine dtal err - | dtal >= DDetailed - ] - ) - txs - , "mempoolSize" .= forMachine dtal mpSz - ] - forMachine dtal (TraceMempoolManuallyRemovedTxs txs0 txs1 mpSz) = - mconcat - [ "kind" .= String "TraceMempoolManuallyRemovedTxs" - , "txsRemoved" .= map (String . renderTxIdForDetails dtal) (toList txs0) - , "txsInvalidated" .= map (forMachine dtal . txForgetValidated) txs1 - , "mempoolSize" .= forMachine dtal mpSz - ] - forMachine dtal (TraceMempoolSyncNotNeeded t) = - mconcat - [ "kind" .= String "TraceMempoolSyncNotNeeded" - , "tip" .= forMachine dtal t - ] - forMachine dtal (TraceMempoolAttemptingAdd tx) = - mconcat - [ "kind" .= String "TraceMempoolAttemptingAdd" - , "tx" .= forMachine dtal tx - ] - - forMachine _dtal (TraceMempoolSynced et) = - mconcat - [ "kind" .= String "TraceMempoolSynced" - , "enclosingTime" .= enclosingValue et - ] - forMachine _dtal TraceMempoolTipMovedBetweenSTMBlocks = - mconcat - [ "kind" .= String "TraceMempoolTipMovedBetweenSTMBlocks" - ] - - asMetrics (TraceMempoolAddedTx _tx _mpSzBefore mpSz) = - [ IntM "txsInMempool" (fromIntegral $ msNumTxs mpSz) - , IntM "mempoolBytes" (fromIntegral . unByteSize32 . msNumBytes $ mpSz) - ] - asMetrics ev@(TraceMempoolRejectedTx _tx _txApplyErr _details mpSz) = - [ IntM "txsInMempool" (fromIntegral $ msNumTxs mpSz) - , IntM "mempoolBytes" (fromIntegral . unByteSize32 . msNumBytes $ mpSz) - ] - ++ - [ CounterM txsMempoolTimeoutSoftCounterName Nothing - | impliesMempoolTimeoutSoft ev - ] - asMetrics (TraceMempoolRemoveTxs txs mpSz) = - [ IntM "txsInMempool" (fromIntegral $ msNumTxs mpSz) - , IntM "mempoolBytes" (fromIntegral . unByteSize32 . msNumBytes $ mpSz) - , CounterM "txsProcessedNum" (Just (fromIntegral $ length txs)) - ] - asMetrics (TraceMempoolManuallyRemovedTxs _txs _txs1 mpSz) = - [ IntM "txsInMempool" (fromIntegral $ msNumTxs mpSz) - , IntM "mempoolBytes" (fromIntegral . unByteSize32 . msNumBytes $ mpSz) - ] - asMetrics (TraceMempoolSynced (FallingEdgeWith duration)) = - let durationMs = round (1000 * duration) :: Integer in - [ IntM "txsSyncDuration" durationMs - , CounterM txsSyncDurationTotalCounterName (Just (fromIntegral durationMs)) - ] - asMetrics (TraceMempoolSynced RisingEdge) = [] - - asMetrics TraceMempoolSyncNotNeeded {} = [] - asMetrics TraceMempoolAttemptingAdd {} = [] - - asMetrics TraceMempoolTipMovedBetweenSTMBlocks {} = [] - -instance LogFormatting MempoolSize where - forMachine _dtal MempoolSize{msNumTxs, msNumBytes} = - mconcat - [ "numTxs" .= msNumTxs - , "bytes" .= unByteSize32 msNumBytes - ] - - -instance MetaTrace (TraceEventMempool blk) where - namespaceFor TraceMempoolAddedTx {} = Namespace [] ["AddedTx"] - namespaceFor TraceMempoolRejectedTx {} = Namespace [] ["RejectedTx"] - namespaceFor TraceMempoolRemoveTxs {} = Namespace [] ["RemoveTxs"] - namespaceFor TraceMempoolManuallyRemovedTxs {} = Namespace [] ["ManuallyRemovedTxs"] - namespaceFor TraceMempoolSynced {} = Namespace [] ["Synced"] - namespaceFor TraceMempoolSyncNotNeeded {} = Namespace [] ["SyncNotNeeded"] - namespaceFor TraceMempoolAttemptingAdd {} = Namespace [] ["AttemptAdd"] - namespaceFor TraceMempoolTipMovedBetweenSTMBlocks {} = Namespace [] ["TipMovedBetweenSTMBlocks"] - - - severityFor (Namespace _ ["AddedTx"]) _ = Just Info - severityFor (Namespace _ ["RejectedTx"]) _ = Just Info - severityFor (Namespace _ ["RemoveTxs"]) _ = Just Info - severityFor (Namespace _ ["Synced"]) _ = Just Debug - severityFor (Namespace _ ["ManuallyRemovedTxs"]) _ = Just Warning - severityFor (Namespace _ ["SyncNotNeeded"]) _ = Just Debug - severityFor (Namespace _ ["AttemptAdd"]) _ = Just Debug - severityFor (Namespace [] ["TipMovedBetweenSTMBlocks"]) _ = Just Debug - severityFor _ _ = Nothing - - metricsDocFor (Namespace _ ["AddedTx"]) = - [ ("txsInMempool","Transactions in mempool") - , ("mempoolBytes", "Byte size of the mempool") - ] - metricsDocFor (Namespace _ ["RejectedTx"]) = - [ ("txsInMempool","Transactions in mempool") - , ("mempoolBytes", "Byte size of the mempool") - , (txsMempoolTimeoutSoftCounterName, "Transactions that soft timed out in mempool") - ] - metricsDocFor (Namespace _ ["RemoveTxs"]) = - [ ("txsInMempool","Transactions in mempool") - , ("mempoolBytes", "Byte size of the mempool") - ] - metricsDocFor (Namespace _ ["ManuallyRemovedTxs"]) = - [ ("txsInMempool","Transactions in mempool") - , ("mempoolBytes", "Byte size of the mempool") - , ("txsProcessedNum", "") - ] - metricsDocFor (Namespace _ ["Synced"]) = - [ ("txsSyncDuration", "Latest time to sync the mempool in ms after block adoption") - , (txsSyncDurationTotalCounterName, "Cumulative time spent syncing the mempool in ms after block adoption") - ] - metricsDocFor _ = [] - - documentFor (Namespace _ ["AddedTx"]) = Just - "New, valid transaction that was added to the Mempool." - documentFor (Namespace _ ["RejectedTx"]) = Just $ mconcat - [ "New, invalid transaction that was rejected and thus not added to" - , " the Mempool." - ] - documentFor (Namespace _ ["RemoveTxs"]) = Just $ mconcat - [ "Previously valid transactions that are no longer valid because of" - , " changes in the ledger state. These transactions have been removed" - , " from the Mempool." - ] - documentFor (Namespace _ ["ManuallyRemovedTxs"]) = Just - "Transactions that have been manually removed from the Mempool." - documentFor (Namespace _ ["SyncNotNeeded"]) = Just - "The mempool and the LedgerDB are in sync already." - documentFor (Namespace _ ["Synced"]) = Just - "The mempool and the LedgerDB are syncing or in sync depending on the argument on the trace." - documentFor (Namespace _ ["AttemptAdd"]) = Just - "Mempool is about to try to validate and add a transaction." - documentFor (Namespace _ ["TipMovedBetweenSTMBlocks"]) = Just - "LedgerDB moved to an alternative fork between two reads during re-sync." - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["AddedTx"] - , Namespace [] ["RejectedTx"] - , Namespace [] ["RemoveTxs"] - , Namespace [] ["ManuallyRemovedTxs"] - , Namespace [] ["Synced"] - , Namespace [] ["SyncNotNeeded"] - , Namespace [] ["AttemptAdd"] - , Namespace [] ["TipMovedBetweenSTMBlocks"] - ] - --------------------------------------------------------------------------------- --- ForgeEvent Tracer --------------------------------------------------------------------------------- - -instance ( tx ~ GenTx blk - , ConvertRawHash blk - , GetHeader blk - , HasHeader blk - , HasKESInfo blk - , HasTxId (GenTx blk) - , LedgerSupportsProtocol blk - , LedgerSupportsMempool blk - , SerialiseNodeToNodeConstraints blk - , Show (ForgeStateUpdateError blk) - , Show (CannotForge blk) - , Show (TxId (GenTx blk)) - , LogFormatting (CannotForge blk) - , LogFormatting (ExtValidationError blk) - , LogFormatting (ForgeStateUpdateError blk)) - => LogFormatting (TraceForgeEvent blk) where - forMachine _dtal (TraceStartLeadershipCheck slotNo) = - mconcat - [ "kind" .= String "TraceStartLeadershipCheck" - , "slot" .= toJSON (unSlotNo slotNo) - ] - forMachine dtal (TraceSlotIsImmutable slotNo tipPoint tipBlkNo) = - mconcat - [ "kind" .= String "TraceSlotIsImmutable" - , "slot" .= toJSON (unSlotNo slotNo) - , "tip" .= renderPointForDetails dtal tipPoint - , "tipBlockNo" .= toJSON (unBlockNo tipBlkNo) - ] - forMachine _dtal (TraceBlockFromFuture currentSlot tip) = - mconcat - [ "kind" .= String "TraceBlockFromFuture" - , "current slot" .= toJSON (unSlotNo currentSlot) - , "tip" .= toJSON (unSlotNo tip) - ] - forMachine dtal (TraceBlockContext currentSlot tipBlkNo tipPoint) = - mconcat - [ "kind" .= String "TraceBlockContext" - , "current slot" .= toJSON (unSlotNo currentSlot) - , "tip" .= renderPointForDetails dtal tipPoint - , "tipBlockNo" .= toJSON (unBlockNo tipBlkNo) - ] - forMachine _dtal (TraceNoLedgerState slotNo _pt) = - mconcat - [ "kind" .= String "TraceNoLedgerState" - , "slot" .= toJSON (unSlotNo slotNo) - ] - forMachine _dtal (TraceLedgerState slotNo _pt) = - mconcat - [ "kind" .= String "TraceLedgerState" - , "slot" .= toJSON (unSlotNo slotNo) - ] - forMachine _dtal (TraceNoLedgerView slotNo _) = - mconcat - [ "kind" .= String "TraceNoLedgerView" - , "slot" .= toJSON (unSlotNo slotNo) - ] - forMachine _dtal (TraceLedgerView slotNo) = - mconcat - [ "kind" .= String "TraceLedgerView" - , "slot" .= toJSON (unSlotNo slotNo) - ] - forMachine dtal (TraceForgeStateUpdateError slotNo reason) = - mconcat - [ "kind" .= String "TraceForgeStateUpdateError" - , "slot" .= toJSON (unSlotNo slotNo) - , "reason" .= forMachine dtal reason - ] - forMachine dtal (TraceNodeCannotForge slotNo reason) = - mconcat - [ "kind" .= String "TraceNodeCannotForge" - , "slot" .= toJSON (unSlotNo slotNo) - , "reason" .= forMachine dtal reason - ] - forMachine _dtal (TraceNodeNotLeader slotNo) = - mconcat - [ "kind" .= String "TraceNodeNotLeader" - , "slot" .= toJSON (unSlotNo slotNo) - ] - forMachine _dtal (TraceNodeIsLeader slotNo) = - mconcat - [ "kind" .= String "TraceNodeIsLeader" - , "slot" .= toJSON (unSlotNo slotNo) - ] - forMachine dtal (TraceForgeTickedLedgerState slotNo prevPt) = - mconcat - [ "kind" .= String "TraceForgeTickedLedgerState" - , "slot" .= toJSON (unSlotNo slotNo) - , "prev" .= renderPointForDetails dtal prevPt - ] - forMachine dtal (TraceForgingMempoolSnapshot slotNo prevPt mpHash mpSlot) = - mconcat - [ "kind" .= String "TraceForgingMempoolSnapshot" - , "slot" .= toJSON (unSlotNo slotNo) - , "prev" .= renderPointForDetails dtal prevPt - , "mempoolHash" .= String (renderChainHash @blk (renderHeaderHash (Proxy @blk)) mpHash) - , "mempoolSlot" .= toJSON (unSlotNo mpSlot) - ] - forMachine _dtal (TraceForgedBlock slotNo _ blk _ _) = - mconcat - [ "kind" .= String "TraceForgedBlock" - , "slot" .= toJSON (unSlotNo slotNo) - , "block" .= String (renderHeaderHash (Proxy @blk) $ blockHash blk) - , "blockNo" .= toJSON (unBlockNo $ blockNo blk) - , "blockPrev" .= String (renderChainHash - @blk - (renderHeaderHash (Proxy @blk)) - $ blockPrevHash blk) - ] - forMachine _dtal (TraceDidntAdoptBlock slotNo _) = - mconcat - [ "kind" .= String "TraceDidntAdoptBlock" - , "slot" .= toJSON (unSlotNo slotNo) - ] - forMachine dtal (TraceForgedInvalidBlock slotNo _ reason) = - mconcat - [ "kind" .= String "TraceForgedInvalidBlock" - , "slot" .= toJSON (unSlotNo slotNo) - , "reason" .= forMachine dtal reason - ] - forMachine DDetailed (TraceAdoptedBlock slotNo blk txs) = - mconcat - [ "kind" .= String "TraceAdoptedBlock" - , "slot" .= toJSON (unSlotNo slotNo) - , "blockHash" .= renderHeaderHashForDetails - (Proxy @blk) - DDetailed - (blockHash blk) - , "blockSize" .= toJSON (getSizeInBytes $ estimateBlockSize (getHeader blk)) - , "txIds" .= toJSON (map (show . txId . txForgetValidated) txs) - ] - forMachine dtal (TraceAdoptedBlock slotNo blk _txs) = - mconcat - [ "kind" .= String "TraceAdoptedBlock" - , "slot" .= toJSON (unSlotNo slotNo) - , "blockHash" .= renderHeaderHashForDetails - (Proxy @blk) - dtal - (blockHash blk) - , "blockSize" .= toJSON (getSizeInBytes $ estimateBlockSize (getHeader blk)) - ] - forMachine dtal (TraceAdoptionThreadDied slotNo blk) = - mconcat - [ "kind" .= String "TraceAdoptionThreadDied" - , "slot" .= toJSON (unSlotNo slotNo) - , "blockHash" .= renderHeaderHashForDetails - (Proxy @blk) - dtal - (blockHash blk) - , "blockSize" .= toJSON (getSizeInBytes $ estimateBlockSize (getHeader blk)) - ] - - forHuman (TraceStartLeadershipCheck slotNo) = - "Checking for leadership in slot " <> showT (unSlotNo slotNo) - forHuman (TraceSlotIsImmutable slotNo immutableTipPoint immutableTipBlkNo) = - "Couldn't forge block because current slot is immutable: " - <> "immutable tip: " <> renderPointAsPhrase immutableTipPoint - <> ", immutable tip block no: " <> showT (unBlockNo immutableTipBlkNo) - <> ", current slot: " <> showT (unSlotNo slotNo) - forHuman (TraceBlockFromFuture currentSlot tipSlot) = - "Couldn't forge block because current tip is in the future: " - <> "current tip slot: " <> showT (unSlotNo tipSlot) - <> ", current slot: " <> showT (unSlotNo currentSlot) - forHuman (TraceBlockContext currentSlot tipBlockNo tipPoint) = - "New block will fit onto: " - <> "tip: " <> renderPointAsPhrase tipPoint - <> ", tip block no: " <> showT (unBlockNo tipBlockNo) - <> ", current slot: " <> showT (unSlotNo currentSlot) - forHuman (TraceNoLedgerState slotNo pt) = - "Could not obtain ledger state for point " - <> renderPointAsPhrase pt - <> ", current slot: " - <> showT (unSlotNo slotNo) - forHuman (TraceLedgerState slotNo pt) = - "Obtained a ledger state for point " - <> renderPointAsPhrase pt - <> ", current slot: " - <> showT (unSlotNo slotNo) - forHuman (TraceNoLedgerView slotNo _) = - "Could not obtain ledger view for slot " <> showT (unSlotNo slotNo) - forHuman (TraceLedgerView slotNo) = - "Obtained a ledger view for slot " <> showT (unSlotNo slotNo) - forHuman (TraceForgeStateUpdateError slotNo reason) = - "Updating the forge state in slot " - <> showT (unSlotNo slotNo) - <> " failed because: " - <> showT reason - forHuman (TraceNodeCannotForge slotNo reason) = - "We are the leader in slot " - <> showT (unSlotNo slotNo) - <> ", but we cannot forge because: " - <> showT reason - forHuman (TraceNodeNotLeader slotNo) = - "Not leading slot " <> showT (unSlotNo slotNo) - forHuman (TraceNodeIsLeader slotNo) = - "Leading slot " <> showT (unSlotNo slotNo) - forHuman (TraceForgeTickedLedgerState slotNo prevPt) = - "While forging in slot " - <> showT (unSlotNo slotNo) - <> " we ticked the ledger state ahead from " - <> renderPointAsPhrase prevPt - forHuman (TraceForgingMempoolSnapshot slotNo prevPt mpHash mpSlot) = - "While forging in slot " - <> showT (unSlotNo slotNo) - <> " we acquired a mempool snapshot valid against " - <> renderPointAsPhrase prevPt - <> " from a mempool that was prepared for " - <> renderChainHash @blk (renderHeaderHash (Proxy @blk)) mpHash - <> " ticked to slot " - <> showT (unSlotNo mpSlot) - forHuman (TraceForgedBlock slotNo _ _ _ _) = - "Forged block in slot " <> showT (unSlotNo slotNo) - forHuman (TraceDidntAdoptBlock slotNo _) = - "Didn't adopt forged block in slot " <> showT (unSlotNo slotNo) - forHuman (TraceForgedInvalidBlock slotNo _ reason) = - "Forged invalid block in slot " - <> showT (unSlotNo slotNo) - <> ", reason: " <> showT reason - forHuman (TraceAdoptedBlock slotNo blk _txs) = - "Adopted block forged in slot " - <> showT (unSlotNo slotNo) - <> ": " <> renderHeaderHash (Proxy @blk) (blockHash blk) - forHuman (TraceAdoptionThreadDied slotNo blk) = - "Adoption thread died in slot " - <> showT (unSlotNo slotNo) - <> ": " <> renderHeaderHash (Proxy @blk) (blockHash blk) - - asMetrics (TraceForgeStateUpdateError slot reason) = - IntM "Forge.StateUpdateError" (fromIntegral $ unSlotNo slot) : - (case getKESInfo (Proxy @blk) reason of - Nothing -> [] - Just kesInfo -> - [ IntM - "operationalCertificateStartKESPeriod" - (fromIntegral . unKESPeriod . HotKey.kesStartPeriod $ kesInfo) - , IntM - "operationalCertificateExpiryKESPeriod" - (fromIntegral . unKESPeriod . HotKey.kesEndPeriod $ kesInfo) - , IntM - "currentKESPeriod" - 0 - , IntM - "remainingKESPeriods" - 0 - ]) - - - asMetrics (TraceStartLeadershipCheck _slot) = - [CounterM "Forge.about-to-lead" Nothing] - asMetrics (TraceSlotIsImmutable _slot _tipPoint _tipBlkNo) = - [CounterM "Forge.slot-is-immutable" Nothing] - asMetrics (TraceBlockFromFuture _slot _slotNo) = - [CounterM "Forge.block-from-future" Nothing] - asMetrics (TraceNoLedgerState _slot _) = - [CounterM "Forge.could-not-forge"Nothing] - asMetrics (TraceNoLedgerView _slot _) = - [CounterM "Forge.could-not-forge" Nothing] - asMetrics (TraceLedgerView _) = [] - asMetrics TraceBlockContext {} = [] - asMetrics (TraceLedgerState _ _) = [] - asMetrics (TraceNodeCannotForge _slot _reason) = - [CounterM "Forge.could-not-forge" Nothing] - asMetrics (TraceNodeNotLeader _slot) = - [CounterM "Forge.node-not-leader" Nothing] - asMetrics (TraceNodeIsLeader _slot) = - [CounterM "Forge.node-is-leader" Nothing] - asMetrics TraceForgeTickedLedgerState {} = [] - asMetrics TraceForgingMempoolSnapshot {} = [] - asMetrics (TraceForgedBlock slot _ _ _ _) = - [IntM "forgedSlotLast" (fromIntegral $ unSlotNo slot), - CounterM "Forge.forged" Nothing] - asMetrics (TraceDidntAdoptBlock _slot _) = - [CounterM "Forge.didnt-adopt" Nothing] - asMetrics (TraceForgedInvalidBlock _slot _ _) = - [CounterM "Forge.forged-invalid" Nothing] - asMetrics (TraceAdoptedBlock _slot _ _) = - [CounterM "Forge.adopted" Nothing] - asMetrics (TraceAdoptionThreadDied _slot _) = - [CounterM "Forge.adoption-thread-died" Nothing] - -instance MetaTrace (TraceForgeEvent blk) where - namespaceFor TraceStartLeadershipCheck {} = - Namespace [] ["StartLeadershipCheck"] - namespaceFor TraceSlotIsImmutable {} = - Namespace [] ["SlotIsImmutable"] - namespaceFor TraceBlockFromFuture {} = - Namespace [] ["BlockFromFuture"] - namespaceFor TraceBlockContext {} = - Namespace [] ["BlockContext"] - namespaceFor TraceNoLedgerState {} = - Namespace [] ["NoLedgerState"] - namespaceFor TraceLedgerState {} = - Namespace [] ["LedgerState"] - namespaceFor TraceNoLedgerView {} = - Namespace [] ["NoLedgerView"] - namespaceFor TraceLedgerView {} = - Namespace [] ["LedgerView"] - namespaceFor TraceForgeStateUpdateError {} = - Namespace [] ["ForgeStateUpdateError"] - namespaceFor TraceNodeCannotForge {} = - Namespace [] ["NodeCannotForge"] - namespaceFor TraceNodeNotLeader {} = - Namespace [] ["NodeNotLeader"] - namespaceFor TraceNodeIsLeader {} = - Namespace [] ["NodeIsLeader"] - namespaceFor TraceForgeTickedLedgerState {} = - Namespace [] ["ForgeTickedLedgerState"] - namespaceFor TraceForgingMempoolSnapshot {} = - Namespace [] ["ForgingMempoolSnapshot"] - namespaceFor TraceForgedBlock {} = - Namespace [] ["ForgedBlock"] - namespaceFor TraceDidntAdoptBlock {} = - Namespace [] ["DidntAdoptBlock"] - namespaceFor TraceForgedInvalidBlock {} = - Namespace [] ["ForgedInvalidBlock"] - namespaceFor TraceAdoptedBlock {} = - Namespace [] ["AdoptedBlock"] - namespaceFor TraceAdoptionThreadDied {} = - Namespace [] ["AdoptionThreadDied"] - - severityFor (Namespace _ ["StartLeadershipCheck"]) _ = Just Info - severityFor (Namespace _ ["SlotIsImmutable"]) _ = Just Error - severityFor (Namespace _ ["BlockFromFuture"]) _ = Just Error - severityFor (Namespace _ ["BlockContext"]) _ = Just Debug - severityFor (Namespace _ ["NoLedgerState"]) _ = Just Error - severityFor (Namespace _ ["LedgerState"]) _ = Just Debug - severityFor (Namespace _ ["NoLedgerView"]) _ = Just Error - severityFor (Namespace _ ["LedgerView"]) _ = Just Debug - severityFor (Namespace _ ["ForgeStateUpdateError"]) _ = Just Critical - severityFor (Namespace _ ["NodeCannotForge"]) _ = Just Error - severityFor (Namespace _ ["NodeNotLeader"]) _ = Just Info - severityFor (Namespace _ ["NodeIsLeader"]) _ = Just Info - severityFor (Namespace _ ["ForgeTickedLedgerState"]) _ = Just Debug - severityFor (Namespace _ ["ForgingMempoolSnapshot"]) _ = Just Debug - severityFor (Namespace _ ["ForgedBlock"]) _ = Just Info - severityFor (Namespace _ ["DidntAdoptBlock"]) _ = Just Error - severityFor (Namespace _ ["ForgedInvalidBlock"]) _ = Just Error - severityFor (Namespace _ ["AdoptedBlock"]) _ = Just Info - severityFor (Namespace _ ["AdoptionThreadDied"]) _ = Just Error - severityFor _ _ = Nothing - - privacyFor (Namespace _ ["ForgeStateUpdateError"]) _ = Just Confidential - privacyFor _ _ = Just Public - - metricsDocFor (Namespace _ ["StartLeadershipCheck"]) = - [("Forge.about-to-lead", "")] - metricsDocFor (Namespace _ ["SlotIsImmutable"]) = - [("Forge.slot-is-immutable", "")] - metricsDocFor (Namespace _ ["BlockFromFuture"]) = - [("Forge.block-from-future", "")] - metricsDocFor (Namespace _ ["BlockContext"]) = [] - metricsDocFor (Namespace _ ["NoLedgerState"]) = - [("Forge.could-not-forge", "")] - metricsDocFor (Namespace _ ["LedgerState"]) = [] - metricsDocFor (Namespace _ ["NoLedgerView"]) = - [("Forge.could-not-forge", "")] - metricsDocFor (Namespace _ ["LedgerView"]) = [] - metricsDocFor (Namespace _ ["ForgeStateUpdateError"]) = - [ ("operationalCertificateStartKESPeriod", "") - , ("operationalCertificateExpiryKESPeriod", "") - , ("currentKESPeriod", "") - , ("remainingKESPeriods", "") - ] - metricsDocFor (Namespace _ ["NodeCannotForge"]) = - [("Forge.could-not-forge", "")] - metricsDocFor (Namespace _ ["NodeNotLeader"]) = - [("Forge.node-not-leader", "")] - metricsDocFor (Namespace _ ["NodeIsLeader"]) = - [("Forge.node-is-leader", "")] - metricsDocFor (Namespace _ ["ForgeTickedLedgerState"]) = [] - metricsDocFor (Namespace _ ["ForgingMempoolSnapshot"]) = [] - metricsDocFor (Namespace _ ["ForgedBlock"]) = - [("forgedSlotLast", "Slot number of the last forged block"), - ("Forge.forged", "Counter of forged blocks")] - metricsDocFor (Namespace _ ["DidntAdoptBlock"]) = - [("Forge.didnt-adopt", "")] - metricsDocFor (Namespace _ ["ForgedInvalidBlock"]) = - [("Forge.forged-invalid", "")] - metricsDocFor (Namespace _ ["AdoptedBlock"]) = - [("Forge.adopted", "")] - metricsDocFor (Namespace _ ["AdoptionThreadDied"]) = - [("Forge.adoption-thread-died", "")] - metricsDocFor _ = [] - - documentFor (Namespace _ ["StartLeadershipCheck"]) = Just - "Start of the leadership check." - documentFor (Namespace _ ["SlotIsImmutable"]) = Just $ mconcat - [ "Leadership check failed: the tip of the ImmutableDB inhabits the" - , " current slot" - , " " - , " This might happen in two cases." - , " " - , " 1. the clock moved backwards, on restart we ignored everything from the" - , " VolatileDB since it's all in the future, and now the tip of the" - , " ImmutableDB points to a block produced in the same slot we're trying" - , " to produce a block in" - , " " - , " 2. k = 0 and we already adopted a block from another leader of the same" - , " slot." - , " " - , " We record both the current slot number as well as the tip of the" - , " ImmutableDB." - , " " - , " See also " - ] - documentFor (Namespace _ ["BlockFromFuture"]) = Just $ mconcat - [ "Leadership check failed: the current chain contains a block from a slot" - , " /after/ the current slot" - , " " - , " This can only happen if the system is under heavy load." - , " " - , " We record both the current slot number as well as the slot number of the" - , " block at the tip of the chain." - , " " - , " See also " - ] - documentFor (Namespace _ ["BlockContext"]) = Just $ mconcat - [ "We found out to which block we are going to connect the block we are about" - , " to forge." - , " " - , " We record the current slot number, the block number of the block to" - , " connect to and its point." - , " " - , " Note that block number of the block we will try to forge is one more than" - , " the recorded block number." - ] - documentFor (Namespace _ ["NoLedgerState"]) = Just $ mconcat - [ "Leadership check failed: we were unable to get the ledger state for the" - , " point of the block we want to connect to" - , " " - , " This can happen if after choosing which block to connect to the node" - , " switched to a different fork. We expect this to happen only rather" - , " rarely, so this certainly merits a warning; if it happens a lot, that" - , " merits an investigation." - , " " - , " We record both the current slot number as well as the point of the block" - , " we attempt to connect the new block to (that we requested the ledger" - , " state for)." - ] - documentFor (Namespace _ ["LedgerState"]) = Just $ mconcat - [ "We obtained a ledger state for the point of the block we want to" - , " connect to" - , " " - , " We record both the current slot number as well as the point of the block" - , " we attempt to connect the new block to (that we requested the ledger" - , " state for)." - ] - documentFor (Namespace _ ["NoLedgerView"]) = Just $ mconcat - [ "Leadership check failed: we were unable to get the ledger view for the" - , " current slot number" - , " " - , " This will only happen if there are many missing blocks between the tip of" - , " our chain and the current slot." - , " " - , " We record also the failure returned by 'forecastFor'." - ] - documentFor (Namespace _ ["LedgerView"]) = Just $ mconcat - [ "We obtained a ledger view for the current slot number" - , " " - , " We record the current slot number." - ] - documentFor (Namespace _ ["ForgeStateUpdateError"]) = Just $ mconcat - [ "Updating the forge state failed." - , " " - , " For example, the KES key could not be evolved anymore." - , " " - , " We record the error returned by 'updateForgeState'." - ] - documentFor (Namespace _ ["NodeCannotForge"]) = Just $ mconcat - [ "We did the leadership check and concluded that we should lead and forge" - , " a block, but cannot." - , " " - , " This should only happen rarely and should be logged with warning severity." - , " " - , " Records why we cannot forge a block." - ] - documentFor (Namespace _ ["NodeNotLeader"]) = Just $ mconcat - [ "We did the leadership check and concluded we are not the leader" - , " " - , " We record the current slot number" - ] - documentFor (Namespace _ ["NodeIsLeader"]) = Just $ mconcat - [ "We did the leadership check and concluded we /are/ the leader" - , "\n" - , " The node will soon forge; it is about to read its transactions from the" - , " Mempool. This will be followed by ForgedBlock." - ] - documentFor (Namespace _ ["ForgeTickedLedgerState"]) = Just "" - documentFor (Namespace _ ["ForgingMempoolSnapshot"]) = Just "" - documentFor (Namespace _ ["ForgedBlock"]) = Just $ mconcat - [ "We forged a block." - , "\n" - , " We record the current slot number, the point of the predecessor, the block" - , " itself, and the total size of the mempool snapshot at the time we produced" - , " the block (which may be significantly larger than the block, due to" - , " maximum block size)" - , "\n" - , " This will be followed by one of three messages:" - , "\n" - , " * AdoptedBlock (normally)" - , "\n" - , " * DidntAdoptBlock (rarely)" - , "\n" - , " * ForgedInvalidBlock (hopefully never, this would indicate a bug)" - ] - documentFor (Namespace _ ["DidntAdoptBlock"]) = Just $ mconcat - [ "We did not adopt the block we produced, but the block was valid. We" - , " must have adopted a block that another leader of the same slot produced" - , " before we got the chance of adopting our own block. This is very rare," - , " this warrants a warning." - ] - documentFor (Namespace _ ["ForgedInvalidBlock"]) = Just $ mconcat - [ "We forged a block that is invalid according to the ledger in the" - , " ChainDB. This means there is an inconsistency between the mempool" - , " validation and the ledger validation. This is a serious error!" - ] - documentFor (Namespace _ ["AdoptedBlock"]) = Just $ mconcat - [ "We adopted the block we produced, we also trace the transactions" - , " that were adopted." - ] - documentFor (Namespace _ ["AdoptionThreadDied"]) = Just $ mconcat - [ "Block adoption thread died" ] - documentFor _ = Nothing - - allNamespaces = - [ Namespace [] ["StartLeadershipCheck"] - , Namespace [] ["SlotIsImmutable"] - , Namespace [] ["BlockFromFuture"] - , Namespace [] ["BlockContext"] - , Namespace [] ["NoLedgerState"] - , Namespace [] ["LedgerState"] - , Namespace [] ["NoLedgerView"] - , Namespace [] ["LedgerView"] - , Namespace [] ["ForgeStateUpdateError"] - , Namespace [] ["NodeCannotForge"] - , Namespace [] ["NodeNotLeader"] - , Namespace [] ["NodeIsLeader"] - , Namespace [] ["ForgeTickedLedgerState"] - , Namespace [] ["ForgingMempoolSnapshot"] - , Namespace [] ["ForgedBlock"] - , Namespace [] ["DidntAdoptBlock"] - , Namespace [] ["ForgedInvalidBlock"] - , Namespace [] ["AdoptedBlock"] - , Namespace [] ["AdoptionThreadDied"] - ] - --------------------------------------------------------------------------------- --- BlockchainTimeEvent Tracer --------------------------------------------------------------------------------- - -instance Show t => LogFormatting (TraceBlockchainTimeEvent t) where - forMachine _dtal (TraceStartTimeInTheFuture (SystemStart start) toWait) = - mconcat [ "kind" .= String "TStartTimeInTheFuture" - , "systemStart" .= String (showT start) - , "toWait" .= String (showT toWait) - ] - forMachine _dtal (TraceCurrentSlotUnknown time _) = - mconcat [ "kind" .= String "CurrentSlotUnknown" - , "time" .= String (showT time) - ] - forMachine _dtal (TraceSystemClockMovedBack prevTime newTime) = - mconcat [ "kind" .= String "SystemClockMovedBack" - , "prevTime" .= String (showT prevTime) - , "newTime" .= String (showT newTime) - ] - forHuman (TraceStartTimeInTheFuture (SystemStart start) toWait) = - "Waiting " - <> (Text.pack . show) toWait - <> " until genesis start time at " - <> (Text.pack . show) start - forHuman (TraceCurrentSlotUnknown time _) = - "Too far from the chain tip to determine the current slot number for the time " - <> (Text.pack . show) time - forHuman (TraceSystemClockMovedBack prevTime newTime) = - "The system wall clock time moved backwards, but within our tolerance " - <> "threshold. Previous 'current' time: " - <> (Text.pack . show) prevTime - <> ". New 'current' time: " - <> (Text.pack . show) newTime - -instance MetaTrace (TraceBlockchainTimeEvent t) where - namespaceFor TraceStartTimeInTheFuture {} = Namespace [] ["StartTimeInTheFuture"] - namespaceFor TraceCurrentSlotUnknown {} = Namespace [] ["CurrentSlotUnknown"] - namespaceFor TraceSystemClockMovedBack {} = Namespace [] ["SystemClockMovedBack"] - - severityFor (Namespace _ ["StartTimeInTheFuture"]) _ = Just Warning - severityFor (Namespace _ ["CurrentSlotUnknown"]) _ = Just Warning - severityFor (Namespace _ ["SystemClockMovedBack"]) _ = Just Warning - severityFor _ _ = Nothing - - documentFor (Namespace _ ["StartTimeInTheFuture"]) = Just $ mconcat - [ "The start time of the blockchain time is in the future" - , "\n" - , " We have to block (for 'NominalDiffTime') until that time comes." - ] - documentFor (Namespace _ ["CurrentSlotUnknown"]) = Just $ mconcat - [ "Current slot is not yet known" - , "\n" - , " This happens when the tip of our current chain is so far in the past that" - , " we cannot translate the current wallclock to a slot number, typically" - , " during syncing. Until the current slot number is known, we cannot" - , " produce blocks. Seeing this message during syncing therefore is" - , " normal and to be expected." - , "\n" - , " We record the current time (the time we tried to translate to a 'SlotNo')" - , " as well as the 'PastHorizonException', which provides detail on the" - , " bounds between which we /can/ do conversions. The distance between the" - , " current time and the upper bound should rapidly decrease with consecutive" - , " 'CurrentSlotUnknown' messages during syncing." - ] - documentFor (Namespace _ ["SystemClockMovedBack"]) = Just $ mconcat - [ "The system clock moved back an acceptable time span, e.g., because of" - , " an NTP sync." - , "\n" - , " The system clock moved back such that the new current slot would be" - , " smaller than the previous one. If this is within the configured limit, we" - , " trace this warning but *do not change the current slot*. The current slot" - , " never decreases, but the current slot may stay the same longer than" - , " expected." - , "\n" - , " When the system clock moved back more than the configured limit, we shut" - , " down with a fatal exception." - ] - documentFor _ = Nothing - - allNamespaces = - [ - Namespace [] ["StartTimeInTheFuture"] - , Namespace [] ["CurrentSlotUnknown"] - , Namespace [] ["SystemClockMovedBack"] - ] - --------------------------------------------------------------------------------- --- Gsm Tracer --------------------------------------------------------------------------------- - -instance ( LogFormatting selection - , Show selection - ) => LogFormatting (TraceGsmEvent selection) where - forMachine dtal = - \case - GsmEventInitializedInCaughtUp -> - mconcat - [ "kind" .= String "GsmEventInitializedInCaughtUp" - ] - GsmEventInitializedInPreSyncing -> - mconcat - [ "kind" .= String "GsmEventInitializedInPreSyncing" - ] - GsmEventEnterCaughtUp i s -> - mconcat - [ "kind" .= String "GsmEventEnterCaughtUp" - , "peerNumber" .= i - , "currentSelection" .= forMachine dtal s - ] - GsmEventLeaveCaughtUp s a -> - mconcat - [ "kind" .= String "GsmEventLeaveCaughtUp" - , "currentSelection" .= forMachine dtal s - , "age" .= toJSON (show a) - ] - GsmEventPreSyncingToSyncing -> - mconcat - [ "kind" .= String "GsmEventPreSyncingToSyncing" - ] - GsmEventSyncingToPreSyncing -> - mconcat - [ "kind" .= String "GsmEventSyncingToPreSyncing" - ] - - forHuman = showT - - asMetrics = - \case - GsmEventEnterCaughtUp {} -> [caughtUp] - GsmEventLeaveCaughtUp {} -> [preSyncing] - GsmEventPreSyncingToSyncing {} -> [syncing] - GsmEventSyncingToPreSyncing {} -> [preSyncing] - GsmEventInitializedInCaughtUp {} -> [caughtUp] - GsmEventInitializedInPreSyncing {} -> [preSyncing] - where - preSyncing = IntM "GSM.state" 0 - syncing = IntM "GSM.state" 1 - caughtUp = IntM "GSM.state" 2 - -instance MetaTrace (TraceGsmEvent selection) where - namespaceFor = - \case - GsmEventInitializedInCaughtUp -> Namespace [] ["InitializedInCaughtUp"] - GsmEventInitializedInPreSyncing -> Namespace [] ["InitializedInPreSyncing"] - GsmEventEnterCaughtUp {} -> Namespace [] ["EnterCaughtUp"] - GsmEventLeaveCaughtUp {} -> Namespace [] ["LeaveCaughtUp"] - GsmEventPreSyncingToSyncing {} -> Namespace [] ["PreSyncingToSyncing"] - GsmEventSyncingToPreSyncing {} -> Namespace [] ["SyncingToPreSyncing"] - - severityFor ns _ = - case ns of - Namespace _ ["InitializedInCaughtUp"] -> Just Notice - Namespace _ ["InitializedInPreSyncing"] -> Just Notice - Namespace _ ["EnterCaughtUp"] -> Just Notice - Namespace _ ["LeaveCaughtUp"] -> Just Warning - Namespace _ ["PreSyncingToSyncing"] -> Just Notice - Namespace _ ["SyncingToPreSyncing"] -> Just Notice - Namespace _ _ -> Nothing - - documentFor = \case - Namespace _ ["InitializedInCaughtUp"] -> Just "The GSM was initialized in the 'CaughtUp' state" - Namespace _ ["InitializedInPreSyncing"] -> Just "The GSM was initialized in the 'PreSyncing' state" - - Namespace _ ["EnterCaughtUp"] -> - Just "Node is caught up" - Namespace _ ["LeaveCaughtUp"] -> - Just "Node is not caught up" - - Namespace _ ["PreSyncingToSyncing"] -> - Just "The Honest Availability Assumption is now satisfied" - Namespace _ ["SyncingToPreSyncing"] -> - Just "The Honest Availability Assumption is no longer satisfied" - - Namespace _ _ -> - Nothing - - metricsDocFor = \case - Namespace _ ["InitializedInCaughtUp"] -> doc - Namespace _ ["InitializedInPreSyncing"] -> doc - Namespace _ ["EnterCaughtUp"] -> doc - Namespace _ ["LeaveCaughtUp"] -> doc - Namespace _ ["PreSyncingToSyncing"] -> doc - Namespace _ ["SyncingToPreSyncing"] -> doc - Namespace _ _ -> [] - where - doc = - [ ("GSM.state" - , "The state of the Genesis State Machine. 0 = PreSyncing, 1 = Syncing, 2 = CaughtUp." - ) - ] - - allNamespaces = - [ Namespace [] ["InitializedInCaughtUp"] - , Namespace [] ["InitializedInPreSyncing"] - , Namespace [] ["EnterCaughtUp"] - , Namespace [] ["LeaveCaughtUp"] - , Namespace [] ["PreSyncingToSyncing"] - , Namespace [] ["SyncingToPreSyncing"] - ] - --------------------------------------------------------------------------------- --- CSJ Tracer --------------------------------------------------------------------------------- - -instance ( LogFormatting peer, Show peer, ConvertRawHash blk - ) => LogFormatting (Jumping.TraceEventCsj peer blk) where - forMachine dtal = \case - BecomingObjector prevObjector -> - mconcat - [ "kind" .= String "BecomingObjector" - , "previousObjector" .= (forMachine dtal <$> prevObjector) - ] - BlockedOnJump -> - mconcat - [ "kind" .= String "BlockedOnJump" - ] - InitializedAsDynamo -> - mconcat - [ "kind" .= String "InitializedAsDynamo" - ] - NoLongerDynamo newDynamo reason -> - mconcat - [ "kind" .= String "NoLongerDynamo" - , "newDynamo" .= (forMachine dtal <$> newDynamo) - , "reason" .= csjReasonToJSON reason - ] - NoLongerObjector newObjector reason -> - mconcat - [ "kind" .= String "NoLongerObjector" - , "newObjector" .= (forMachine dtal <$> newObjector) - , "reason" .= csjReasonToJSON reason - ] - SentJumpInstruction jumpTarget -> - mconcat - [ "kind" .= String "SentJumpInstruction" - , "jumpTarget" .= forMachine dtal jumpTarget - ] - where - csjReasonToJSON = \case - BecauseCsjDisengage -> String "BecauseCsjDisengage" - BecauseCsjDisconnect -> String "BecauseCsjDisconnect" - -instance MetaTrace (Jumping.TraceEventCsj peer blk) where - namespaceFor = \case - BecomingObjector{} -> Namespace [] ["BecomingObjector"] - BlockedOnJump{} -> Namespace [] ["BlockedOnJump"] - InitializedAsDynamo{} -> Namespace [] ["InitializedAsDynamo"] - NoLongerDynamo{} -> Namespace [] ["NoLongerDynamo"] - NoLongerObjector{} -> Namespace [] ["NoLongerObjector"] - SentJumpInstruction{} -> Namespace [] ["SentJumpInstruction"] - - severityFor ns _ = case ns of - Namespace _ ["BecomingObjector"] -> Just Debug - Namespace _ ["BlockedOnJump"] -> Just Debug - Namespace _ ["InitializedAsDynamo"] -> Just Debug - Namespace _ ["NoLongerDynamo"] -> Just Debug - Namespace _ ["NoLongerObjector"] -> Just Debug - Namespace _ ["SentJumpInstruction"] -> Just Debug - Namespace _ _ -> Nothing - - documentFor = \case - Namespace _ ["BecomingObjector"] -> Just "This peer is becoming the CSJ objector" - Namespace _ ["BlockedOnJump"] -> Just "This peer is blocked on a CSJ jump" - Namespace _ ["InitializedAsDynamo"] -> Just "This peer has been initialized as the CSJ dynamo" - Namespace _ ["NoLongerDynamo"] -> Just "This peer no longer is the CSJ dynamo" - Namespace _ ["NoLongerObjector"] -> Just "This peer no longer is the CSJ objector" - Namespace _ ["SentJumpInstruction"] -> Just "This peer has been instructed to jump via CSJ" - Namespace _ _ -> Nothing - - allNamespaces = - [ Namespace [] ["BecomingObjector"] - , Namespace [] ["BlockedOnJump"] - , Namespace [] ["InitializedAsDynamo"] - , Namespace [] ["NoLongerDynamo"] - , Namespace [] ["NoLongerObjector"] - , Namespace [] ["SentJumpInstruction"] - ] - --------------------------------------------------------------------------------- --- Devoted BlockFetch Tracer --------------------------------------------------------------------------------- - -instance ( LogFormatting peer, Show peer - ) => LogFormatting (Jumping.TraceEventDbf peer) where - forMachine dtal = - \case - RotatedDynamo oldPeer newPeer -> - mconcat - [ "kind" .= String "RotatedDynamo" - , "oldPeer" .= forMachine dtal oldPeer - , "newPeer" .= forMachine dtal newPeer - ] - - forHuman (RotatedDynamo fromPeer toPeer) = - "Rotated the dynamo from " <> showT fromPeer <> " to " <> showT toPeer - -instance MetaTrace (Jumping.TraceEventDbf peer) where - namespaceFor = - \case - RotatedDynamo {} -> Namespace [] ["RotatedDynamo"] - - severityFor ns _ = - case ns of - Namespace _ ["RotatedDynamo"] -> Just Info - Namespace _ _ -> Nothing - - documentFor = \case - Namespace _ ["RotatedDynamo"] -> - Just "The ChainSync Jumping module has been asked to rotate its dynamo" - Namespace _ _ -> - Nothing - - allNamespaces = - [ Namespace [] ["RotatedDynamo"] - ] - --------------------------------------------------------------------------------- --- Chain tip tracer --------------------------------------------------------------------------------- - -instance ( StandardHash blk - , ConvertRawHash blk - ) => LogFormatting (Tip blk) where - forMachine _dtal TipGenesis = - mconcat [ "kind" .= String "TipGenesis" ] - forMachine _dtal (Tip slotNo hash bNo) = - mconcat [ "kind" .= String "Tip" - , "tipSlotNo" .= toJSON (unSlotNo slotNo) - , "tipHash" .= renderHeaderHash (Proxy @blk) hash - , "tipBlockNo" .= toJSON bNo - ] - - forHuman = showT - -{------------------------------------------------------------------------------- - KES-agent --------------------------------------------------------------------------------} - --------------------------------------------------------------------------------- --- KES Agent tracer --------------------------------------------------------------------------------- - -instance LogFormatting Agent.ServiceClientTrace where - forMachine _dtal = \case - Agent.ServiceClientVersionHandshakeTrace _vhdt -> - mconcat [ "kind" .= String "ServiceClientVersionHandshakeTrace" ] - Agent.ServiceClientVersionHandshakeFailed -> - mconcat [ "kind" .= String "ServiceClientVersionHandshakeFailed" ] - Agent.ServiceClientDriverTrace _sdt -> - mconcat [ "kind" .= String "ServiceClientDriverTrace" ] - Agent.ServiceClientSocketClosed -> - mconcat [ "kind" .= String "ServiceClientSocketClosed" ] - Agent.ServiceClientConnected _s -> - mconcat [ "kind" .= String "ServiceClientConnected" ] - Agent.ServiceClientAttemptReconnect{} -> - mconcat [ "kind" .= String "ServiceClientAttemptReconnect" ] - Agent.ServiceClientReceivedKey _tbt -> - mconcat [ "kind" .= String "ServiceClientReceivedKey" ] - Agent.ServiceClientDeclinedKey _tbt -> - mconcat [ "kind" .= String "ServiceClientDeclinedKey" ] - Agent.ServiceClientDroppedKey -> - mconcat [ "kind" .= String "ServiceClientDroppedKey" ] - Agent.ServiceClientOpCertNumberCheck _ _ -> - mconcat [ "kind" .= String "ServiceClientOpCertNumberCheck" ] - Agent.ServiceClientAbnormalTermination _s -> - mconcat [ "kind" .= String "ServiceClientAbnormalTermination" ] - Agent.ServiceClientStopped -> - mconcat [ "kind" .= String "ServiceClientStopped" ] - - forHuman = showT - -instance MetaTrace Agent.ServiceClientTrace where - namespaceFor = \case - Agent.ServiceClientVersionHandshakeTrace _vhdt -> - Namespace [] ["ServiceClientVersionHandshakeTrace"] - Agent.ServiceClientVersionHandshakeFailed -> - Namespace [] ["ServiceClientVersionHandshakeFailed"] - Agent.ServiceClientDriverTrace _sdt -> - Namespace [] ["ServiceClientDriverTrace"] - Agent.ServiceClientSocketClosed -> - Namespace [] ["ServiceClientSocketClosed"] - Agent.ServiceClientConnected _s -> - Namespace [] ["ServiceClientConnected"] - Agent.ServiceClientAttemptReconnect{} -> - Namespace [] ["ServiceClientAttemptReconnect"] - Agent.ServiceClientReceivedKey _tbt -> - Namespace [] ["ServiceClientReceivedKey"] - Agent.ServiceClientDeclinedKey _tbt -> - Namespace [] ["ServiceClientDeclinedKey"] - Agent.ServiceClientDroppedKey -> - Namespace [] ["ServiceClientDroppedKey"] - Agent.ServiceClientOpCertNumberCheck _ _ -> - Namespace [] ["ServiceClientOpCertNumberCheck"] - Agent.ServiceClientAbnormalTermination _s -> - Namespace [] ["ServiceClientAbnormalTermination"] - Agent.ServiceClientStopped -> - Namespace [] ["ServiceClientStopped"] - - severityFor ns _ = case ns of - Namespace [] ["ServiceClientVersionHandshakeTrace"] -> - Just Debug - Namespace [] ["ServiceClientVersionHandshakeFailed"] -> - Just Error - Namespace [] ["ServiceClientDriverTrace"] -> - Just Debug - Namespace [] ["ServiceClientSocketClosed"] -> - Just Info - Namespace [] ["ServiceClientConnected"] -> - Just Info - Namespace [] ["ServiceClientAttemptReconnect"] -> - Just Info - Namespace [] ["ServiceClientReceivedKey"] -> - Just Info - Namespace [] ["ServiceClientDeclinedKey"] -> - Just Info - Namespace [] ["ServiceClientDroppedKey"] -> - Just Info - Namespace [] ["ServiceClientOpCertNumberCheck"] -> - Just Debug - Namespace [] ["ServiceClientAbnormalTermination"] -> - Just Error - Namespace [] ["ServiceClientStopped"] -> - Just Info - Namespace _ _ -> Nothing - - documentFor _ = Nothing - allNamespaces = - [ Namespace [] ["ServiceClientVersionHandshakeTrace"] - , Namespace [] ["ServiceClientVersionHandshakeFailed"] - , Namespace [] ["ServiceClientDriverTrace"] - , Namespace [] ["ServiceClientSocketClosed"] - , Namespace [] ["ServiceClientConnected"] - , Namespace [] ["ServiceClientAttemptReconnect"] - , Namespace [] ["ServiceClientReceivedKey"] - , Namespace [] ["ServiceClientDeclinedKey"] - , Namespace [] ["ServiceClientDroppedKey"] - , Namespace [] ["ServiceClientOpCertNumberCheck"] - , Namespace [] ["ServiceClientAbnormalTermination"] - , Namespace [] ["ServiceClientStopped"] - ] - -instance LogFormatting KESAgentClientTrace where - forMachine dtal = \case - KESAgentClientException ex -> mconcat - [ "kind" .= String "KESAgentClientException" - , "exception" .= String (Text.pack $ show ex) - ] - KESAgentClientTrace t -> mconcat - [ "kind" .= String "KESAgentClientTrace" - , "trace" .= forMachine dtal t - ] - - forHuman = showT - - -instance MetaTrace KESAgentClientTrace where - namespaceFor = \case - KESAgentClientException _ -> - Namespace [] ["KESAgentClientException"] - KESAgentClientTrace t -> nsCast $ namespaceFor t - - severityFor (Namespace [] ["KESAgentClientException"]) _ = Just Error - severityFor ns (Just (KESAgentClientTrace t)) = severityFor (nsCast ns) (Just t) - severityFor ns Nothing = - severityFor (nsCast ns :: Namespace Agent.ServiceClientTrace) Nothing - severityFor _ _ = Nothing - - documentFor _ = Nothing - - allNamespaces = - Namespace [] ["KESAgentClientException"] : - fmap nsCast (allNamespaces :: [Namespace Agent.ServiceClientTrace]) - --------------------------------------------------------------------------------- --- Peras --------------------------------------------------------------------------------- - --- TODO: Move this to a proper place. A lot of this is duplicated in the --- ToObject instance. This is likely in an incorrect place. Fix --- duplication. - --- | Object diffusion is instantiated once per diffused object kind: Peras --- certificates and Peras votes. EKG metric names don't carry the tracer --- namespace, so each kind supplies its own prefix here; sharing one would --- make cert and vote metrics overwrite each other. -perasCertMetricsPrefix, perasVoteMetricsPrefix :: Text.Text -perasCertMetricsPrefix = "perasCert" -perasVoteMetricsPrefix = "perasVote" - -forMachineObjectDiffusionInbound :: - TraceObjectDiffusionInbound objectId object - -> Aeson.Object -forMachineObjectDiffusionInbound = \case - TraceObjectDiffusionInboundCollectedObjects payload -> - mconcat - [ "kind" .= String "TraceObjectDiffusionInboundCollectedObjects" - , "payload" .= String (Text.pack . show $ payload) - ] - TraceObjectDiffusionInboundAddedObjects payload -> - mconcat - [ "kind" .= String "TraceObjectDiffusionInboundAddedObjects" - , "payload" .= String (Text.pack . show $ payload) - ] - TraceObjectDiffusionInboundRecvControlMessage payload -> - mconcat - [ "kind" .= String "TraceObjectDiffusionInboundRecvControlMessage" - , "payload" .= String (Text.pack . show $ payload) - ] - TraceObjectDiffusionInboundCanRequestMoreObjects payload -> - mconcat - [ "kind" .= String "TraceObjectDiffusionInboundCanRequestMoreObjects" - , "payload" .= String (Text.pack . show $ payload) - ] - TraceObjectDiffusionInboundCannotRequestMoreObjects payload -> - mconcat - [ "kind" .= String "TraceObjectDiffusionInboundCannotRequestMoreObjects" - , "payload" .= String (Text.pack . show $ payload) - ] - -asMetricsObjectDiffusionInbound :: - Text.Text - -> TraceObjectDiffusionInbound objectId object - -> [Metric] -asMetricsObjectDiffusionInbound prefix = \case - TraceObjectDiffusionInboundCollectedObjects collected -> - [IntM (prefix <> "ObjectsCollected") (fromIntegral collected)] - TraceObjectDiffusionInboundAddedObjects (NumObjectsProcessed added) -> - [CounterM (prefix <> "ObjectsAdded") (Just (fromIntegral added))] - _ -> [] - -metricsDocForObjectDiffusionInbound :: - Text.Text - -> Namespace a - -> [(Text.Text, Text.Text)] -metricsDocForObjectDiffusionInbound prefix = \case - Namespace _ ["TraceObjectDiffusionInboundCollectedObjects"] -> - [( prefix <> "ObjectsCollected" - , "number of objects about to be inserted into the pool")] - Namespace _ ["TraceObjectDiffusionInboundAddedObjects"] -> - [( prefix <> "ObjectsAdded" - , "total number of objects accepted into the pool")] - _ -> [] - -namespaceForObjectDiffusionInbound :: - TraceObjectDiffusionInbound objectId object - -> Namespace a -namespaceForObjectDiffusionInbound = \case - TraceObjectDiffusionInboundCollectedObjects _ -> - Namespace [] ["TraceObjectDiffusionInboundCollectedObjects"] - TraceObjectDiffusionInboundAddedObjects _ -> - Namespace [] ["TraceObjectDiffusionInboundAddedObjects"] - TraceObjectDiffusionInboundRecvControlMessage _ -> - Namespace [] ["TraceObjectDiffusionInboundRecvControlMessage"] - TraceObjectDiffusionInboundCanRequestMoreObjects _ -> - Namespace [] ["TraceObjectDiffusionInboundCanRequestMoreObjects"] - TraceObjectDiffusionInboundCannotRequestMoreObjects _ -> - Namespace [] ["TraceObjectDiffusionInboundCannotRequestMoreObjects"] - -severityForObjectDiffusionInbound :: Namespace a -> Maybe SeverityS -severityForObjectDiffusionInbound = \case - Namespace _ ["TraceObjectDiffusionInboundCollectedObjects"] -> Just Info - Namespace _ ["TraceObjectDiffusionInboundAddedObjects"] -> Just Info - Namespace _ ["TraceObjectDiffusionInboundRecvControlMessage"] -> Just Info - Namespace _ ["TraceObjectDiffusionInboundCanRequestMoreObjects"] -> Just Info - Namespace _ ["TraceObjectDiffusionInboundCannotRequestMoreObjects"] -> Just Info - _ -> Nothing - -allNamespacesObjectDiffusionInbound :: [Namespace a] -allNamespacesObjectDiffusionInbound = - [ Namespace [] ["TraceObjectDiffusionInboundCollectedObjects"] - , Namespace [] ["TraceObjectDiffusionInboundAddedObjects"] - , Namespace [] ["TraceObjectDiffusionInboundRecvControlMessage"] - , Namespace [] ["TraceObjectDiffusionInboundCanRequestMoreObjects"] - , Namespace [] ["TraceObjectDiffusionInboundCannotRequestMoreObjects"] - ] - -instance LogFormatting (TracePerasCertDiffusionInbound blk) where - forMachine _ = forMachineObjectDiffusionInbound - asMetrics = asMetricsObjectDiffusionInbound perasCertMetricsPrefix - -instance MetaTrace (TracePerasCertDiffusionInbound blk) where - namespaceFor = namespaceForObjectDiffusionInbound - severityFor ns _ = severityForObjectDiffusionInbound ns - documentFor _ = Nothing - metricsDocFor = metricsDocForObjectDiffusionInbound perasCertMetricsPrefix - allNamespaces = allNamespacesObjectDiffusionInbound - -instance LogFormatting (TracePerasVoteDiffusionInbound blk) where - forMachine _ = forMachineObjectDiffusionInbound - asMetrics = asMetricsObjectDiffusionInbound perasVoteMetricsPrefix - -instance MetaTrace (TracePerasVoteDiffusionInbound blk) where - namespaceFor = namespaceForObjectDiffusionInbound - severityFor ns _ = severityForObjectDiffusionInbound ns - documentFor _ = Nothing - metricsDocFor = metricsDocForObjectDiffusionInbound perasVoteMetricsPrefix - allNamespaces = allNamespacesObjectDiffusionInbound - -forMachineObjectDiffusionOutbound :: - ( Show objectId - , Show object - ) - => TraceObjectDiffusionOutbound objectId object - -> Aeson.Object -forMachineObjectDiffusionOutbound = \case - TraceObjectDiffusionOutboundRecvMsgRequestObjectIds payload -> - mconcat - [ "kind" .= String "TraceObjectDiffusionOutboundRecvMsgRequestObjectIds" - , "payload" .= String (Text.pack . show $ payload) - ] - TraceObjectDiffusionOutboundSendMsgReplyObjectIds payload -> - mconcat - [ "kind" .= String "TraceObjectDiffusionOutboundSendMsgReplyObjectIds" - , "payload" .= String (Text.pack . show $ payload) - ] - TraceObjectDiffusionOutboundRecvMsgRequestObjects payload -> - mconcat - [ "kind" .= String "TraceObjectDiffusionOutboundRecvMsgRequestObjects" - , "payload" .= String (Text.pack . show $ payload) - ] - TraceObjectDiffusionOutboundSendMsgReplyObjects payload -> - mconcat - [ "kind" .= String "TraceObjectDiffusionOutboundSendMsgReplyObjects" - , "payload" .= String (Text.pack . show $ payload) - ] - TraceObjectDiffusionOutboundTerminated -> - mconcat - [ "kind" .= String "TraceObjectDiffusionOutboundTerminated" - ] - -asMetricsObjectDiffusionOutbound :: - Text.Text - -> TraceObjectDiffusionOutbound objectId object - -> [Metric] -asMetricsObjectDiffusionOutbound prefix = \case - TraceObjectDiffusionOutboundSendMsgReplyObjects objects -> - [CounterM (prefix <> "ObjectsSent") (Just (length objects))] - _ -> [] - -metricsDocForObjectDiffusionOutbound :: - Text.Text - -> Namespace a - -> [(Text.Text, Text.Text)] -metricsDocForObjectDiffusionOutbound prefix = \case - Namespace _ ["TraceObjectDiffusionOutboundSendMsgReplyObjects"] -> - [( prefix <> "ObjectsSent" - , "total number of objects served to peers")] - _ -> [] - -namespaceForObjectDiffusionOutbound :: - TraceObjectDiffusionOutbound objectId object - -> Namespace a -namespaceForObjectDiffusionOutbound = \case - TraceObjectDiffusionOutboundRecvMsgRequestObjectIds _ -> - Namespace [] ["TraceObjectDiffusionOutboundRecvMsgRequestObjectIds"] - TraceObjectDiffusionOutboundSendMsgReplyObjectIds _ -> - Namespace [] ["TraceObjectDiffusionOutboundSendMsgReplyObjectIds"] - TraceObjectDiffusionOutboundRecvMsgRequestObjects _ -> - Namespace [] ["TraceObjectDiffusionOutboundRecvMsgRequestObjects"] - TraceObjectDiffusionOutboundSendMsgReplyObjects _ -> - Namespace [] ["TraceObjectDiffusionOutboundSendMsgReplyObjects"] - TraceObjectDiffusionOutboundTerminated -> - Namespace [] ["TraceObjectDiffusionOutboundTerminated"] - -severityForObjectDiffusionOutbound :: Namespace a -> Maybe SeverityS -severityForObjectDiffusionOutbound = \case - Namespace _ ["TraceObjectDiffusionOutboundRecvMsgRequestObjectIds"] -> Just Info - Namespace _ ["TraceObjectDiffusionOutboundSendMsgReplyObjectIds"] -> Just Info - Namespace _ ["TraceObjectDiffusionOutboundRecvMsgRequestObjects"] -> Just Info - Namespace _ ["TraceObjectDiffusionOutboundSendMsgReplyObjects"] -> Just Info - Namespace _ ["TraceObjectDiffusionOutboundTerminated"] -> Just Info - _ -> Nothing - -allNamespacesObjectDiffusionOutbound :: [Namespace a] -allNamespacesObjectDiffusionOutbound = - [ Namespace [] ["TraceObjectDiffusionOutboundRecvMsgRequestObjectIds"] - , Namespace [] ["TraceObjectDiffusionOutboundSendMsgReplyObjectIds"] - , Namespace [] ["TraceObjectDiffusionOutboundRecvMsgRequestObjects"] - , Namespace [] ["TraceObjectDiffusionOutboundSendMsgReplyObjects"] - , Namespace [] ["TraceObjectDiffusionOutboundTerminated"] - ] - -instance Show (PerasCert blk) - => LogFormatting (TracePerasCertDiffusionOutbound blk) where - forMachine _ = forMachineObjectDiffusionOutbound - asMetrics = asMetricsObjectDiffusionOutbound perasCertMetricsPrefix - -instance MetaTrace (TracePerasCertDiffusionOutbound blk) where - namespaceFor = namespaceForObjectDiffusionOutbound - severityFor ns _ = severityForObjectDiffusionOutbound ns - documentFor _ = Nothing - metricsDocFor = metricsDocForObjectDiffusionOutbound perasCertMetricsPrefix - allNamespaces = allNamespacesObjectDiffusionOutbound - -instance Show (PerasVote blk) - => LogFormatting (TracePerasVoteDiffusionOutbound blk) where - forMachine _ = forMachineObjectDiffusionOutbound - asMetrics = asMetricsObjectDiffusionOutbound perasVoteMetricsPrefix - -instance MetaTrace (TracePerasVoteDiffusionOutbound blk) where - namespaceFor = namespaceForObjectDiffusionOutbound - severityFor ns _ = severityForObjectDiffusionOutbound ns - documentFor _ = Nothing - metricsDocFor = metricsDocForObjectDiffusionOutbound perasVoteMetricsPrefix - allNamespaces = allNamespacesObjectDiffusionOutbound diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/ConsensusStartupException.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/ConsensusStartupException.hs deleted file mode 100644 index 78c98bff879..00000000000 --- a/cardano-node/src/Cardano/Node/Tracing/Tracers/ConsensusStartupException.hs +++ /dev/null @@ -1,37 +0,0 @@ --- | Consensus startup exception --- --- TODO: once the legacy logging framework is removed it can be moved to --- `Cardano.Node.Tracing.Tracers.Consensus`. -module Cardano.Node.Tracing.Tracers.ConsensusStartupException - ( ConsensusStartupException (..) - ) where - -import Cardano.Logging.Types - -import Control.Exception (SomeException) -import Data.Aeson (Value (String), (.=)) -import qualified Data.Text as Text - --- | Exceptions logged when the consensus is initialising. --- -newtype ConsensusStartupException = ConsensusStartupException SomeException - deriving Show - -instance LogFormatting ConsensusStartupException where - forMachine _ (ConsensusStartupException err) = - mconcat [ "kind" .= String "ConsensusStartupException" - , "error" .= String (Text.pack . show $ err) - ] - forHuman = Text.pack . show - -instance MetaTrace ConsensusStartupException where - namespaceFor ConsensusStartupException {} = Namespace [] ["ConsensusStartupException"] - - severityFor (Namespace _ ["ConsensusStartupException"]) _ = Just Error - severityFor _ _ = Nothing - - documentFor (Namespace _ ["ConsensusStartupException"]) = Just - "" - documentFor _ = Just "" - - allNamespaces = [Namespace [] ["ConsensusStartupException"]] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/HasIssuer.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/HasIssuer.hs deleted file mode 100644 index 2205e9d2339..00000000000 --- a/cardano-node/src/Cardano/Node/Tracing/Tracers/HasIssuer.hs +++ /dev/null @@ -1,83 +0,0 @@ -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE TypeApplications #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE UndecidableInstances #-} - -module Cardano.Node.Tracing.Tracers.HasIssuer - ( BlockIssuerVerificationKeyHash (..) - , HasIssuer (..) - ) where - -import Cardano.Api (VerificationKey (StakePoolVerificationKey), serialiseToRawBytes, - verificationKeyHash) -import Cardano.Api.Byron (VerificationKey (ByronVerificationKey)) - -import qualified Cardano.Chain.Block as Byron -import qualified Cardano.Ledger.Shelley.API as Shelley -import Cardano.Protocol.Crypto (StandardCrypto) -import Ouroboros.Consensus.Byron.Ledger.Block (ByronBlock, Header (..)) -import Ouroboros.Consensus.HardFork.Combinator (HardForkBlock, Header (..), - OneEraHeader (..)) -import Ouroboros.Consensus.Shelley.Ledger.Block (Header (..), ShelleyBlock) -import Ouroboros.Consensus.Shelley.Protocol.Abstract - -import Data.ByteString (ByteString) -import Data.SOP - --- | Block issuer verification key hash. -data BlockIssuerVerificationKeyHash - = BlockIssuerVerificationKeyHash !ByteString - -- ^ Serialized block issuer verification key hash. - | NoBlockIssuer - -- ^ There is no block issuer. - -- - -- For example, this could be relevant for epoch boundary blocks (EBBs), - -- genesis blocks, etc. - deriving (Eq, Show) - --- | Get the block issuer verification key hash from a block header. -class HasIssuer blk where - -- | Given a block header, return the serialized block issuer verification - -- key hash. - getIssuerVerificationKeyHash :: Header blk -> BlockIssuerVerificationKeyHash - -instance HasIssuer ByronBlock where - getIssuerVerificationKeyHash byronBlkHdr = - case byronHeaderRaw byronBlkHdr of - Byron.ABOBBlockHdr hdr -> - BlockIssuerVerificationKeyHash - . serialiseToRawBytes - . verificationKeyHash - . ByronVerificationKey - $ Byron.headerIssuer hdr - Byron.ABOBBoundaryHdr _ -> NoBlockIssuer - -instance - ( ProtoCrypto protocol ~ StandardCrypto - , ProtocolHeaderSupportsProtocol protocol - ) => HasIssuer (ShelleyBlock protocol era) where - getIssuerVerificationKeyHash shelleyBlkHdr = - BlockIssuerVerificationKeyHash - . serialiseToRawBytes - . verificationKeyHash - . StakePoolVerificationKey - $ toStakePoolKey issuer - where - -- We don't support a "block issuer" key role in @cardano-api@, so we'll - -- just convert it to a stake pool key. - toStakePoolKey - :: Shelley.VKey Shelley.BlockIssuer - -> Shelley.VKey Shelley.StakePool - toStakePoolKey vk = Shelley.VKey (Shelley.unVKey vk) - - issuer = pHeaderIssuer (shelleyHeaderRaw shelleyBlkHdr) - -instance All HasIssuer xs => HasIssuer (HardForkBlock xs) where - getIssuerVerificationKeyHash = - hcollapse - . hcmap (Proxy @HasIssuer) (K . getIssuerVerificationKeyHash) - . getOneEraHeader - . getHardForkHeader diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/KESInfo.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/KESInfo.hs deleted file mode 100644 index 4693843e18d..00000000000 --- a/cardano-node/src/Cardano/Node/Tracing/Tracers/KESInfo.hs +++ /dev/null @@ -1,186 +0,0 @@ -{-# LANGUAGE DerivingStrategies #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE GeneralisedNewtypeDeriving #-} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE StandaloneDeriving #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE UndecidableInstances #-} - -{-# OPTIONS_GHC -Wno-orphans #-} - -module Cardano.Node.Tracing.Tracers.KESInfo - ( - traceAsKESInfo - ) where - -import Cardano.Logging -import Cardano.Node.Queries (GetKESInfo (..)) -import Cardano.Protocol.TPraos.OCert (KESPeriod (KESPeriod)) -import Ouroboros.Consensus.Block.Forging -import Ouroboros.Consensus.Node.Tracers (TraceLabelCreds (..)) -import qualified Ouroboros.Consensus.Protocol.Ledger.HotKey as HotKey - -import Control.Monad.IO.Class (MonadIO) -import Data.Aeson (ToJSON (..), Value (..), (.=)) -import Data.Proxy (Proxy) -import qualified Data.Text as Text - -traceAsKESInfo - :: forall m blk . (GetKESInfo blk, MonadIO m) - => Proxy blk - -> Trace m (TraceLabelCreds HotKey.KESInfo) - -> Trace m (TraceLabelCreds (ForgeStateInfo blk)) -traceAsKESInfo pr tr = traceAsMaybeKESInfo pr (filterTraceMaybe tr) - -traceAsMaybeKESInfo - :: forall m blk . (GetKESInfo blk, MonadIO m) - => Proxy blk - -> Trace m (Maybe (TraceLabelCreds HotKey.KESInfo)) - -> Trace m (TraceLabelCreds (ForgeStateInfo blk)) -traceAsMaybeKESInfo pr (Trace tr) = Trace $ - contramap - (\case - (lc, Right (TraceLabelCreds c e)) -> - case getKESInfoFromStateInfo pr e of - Just kesi -> (lc, Right (Just (TraceLabelCreds c kesi))) - Nothing -> (lc, Right Nothing) - (lc, Left ctrl) -> (lc, Left ctrl)) - tr - --- -------------------------------------------------------------------------------- --- -- KESInfo Tracer --- -------------------------------------------------------------------------------- - -deriving newtype instance ToJSON KESPeriod - - -instance LogFormatting HotKey.KESInfo where - forMachine _dtal forgeStateInfo = - let currKesPeriod' = currKesPeriod + startKesPeriod - maxKesEvos = endKesPeriod - startKesPeriod - expiryKesPeriod = startKesPeriod + maxKesEvos - kesPeriodsUntilExpiry = max 0 (expiryKesPeriod - currKesPeriod') - in - if kesPeriodsUntilExpiry > 7 - then mconcat - [ "kind" .= String "KESInfo" - , "startPeriod" .= startKesPeriod - , "endPeriod" .= currKesPeriod' - , "evolution" .= endKesPeriod - ] - else mconcat - [ "kind" .= String "ExpiryLogMessage" - , "keyExpiresIn" .= kesPeriodsUntilExpiry - , "startPeriod" .= startKesPeriod - , "endPeriod" .= currKesPeriod' - , "evolution" .= endKesPeriod - ] - where - HotKey.KESInfo - { HotKey.kesStartPeriod = KESPeriod startKesPeriod - , HotKey.kesEvolution = currKesPeriod - , HotKey.kesEndPeriod = KESPeriod endKesPeriod - } = forgeStateInfo - - forHuman forgeStateInfo = - let currKesPeriod' = currKesPeriod + startKesPeriod - maxKesEvos = endKesPeriod - startKesPeriod - expiryKesPeriod = startKesPeriod + maxKesEvos - kesPeriodsUntilExpiry = max 0 (expiryKesPeriod - currKesPeriod') - in if kesPeriodsUntilExpiry > 7 - then "KES info startPeriod " <> (Text.pack . show) startKesPeriod - <> " currPeriod " <> (Text.pack . show) currKesPeriod' - <> " endPeriod " <> (Text.pack . show) endKesPeriod - <> ", " - <> (Text.pack . show) kesPeriodsUntilExpiry - <> " KES periods until expiry." - else "Operational key will expire in " - <> (Text.pack . show) kesPeriodsUntilExpiry - <> " KES periods." - where - HotKey.KESInfo - { HotKey.kesStartPeriod = KESPeriod startKesPeriod - , HotKey.kesEvolution = currKesPeriod - , HotKey.kesEndPeriod = KESPeriod endKesPeriod - } = forgeStateInfo - - asMetrics forgeStateInfo = - let currKesPeriod' = currKesPeriod + startKesPeriod - maxKesEvos = endKesPeriod - startKesPeriod - expiryKesPeriod = startKesPeriod + maxKesEvos - kesPeriodsUntilExpiry = max 0 (expiryKesPeriod - currKesPeriod') - in [ - IntM "operationalCertificateStartKESPeriod" (fromIntegral startKesPeriod) - , IntM "operationalCertificateExpiryKESPeriod" (fromIntegral expiryKesPeriod) - , IntM "currentKESPeriod" (fromIntegral currKesPeriod') - , IntM "remainingKESPeriods" (fromIntegral kesPeriodsUntilExpiry) - ] - where - HotKey.KESInfo - { HotKey.kesStartPeriod = KESPeriod startKesPeriod - , HotKey.kesEvolution = currKesPeriod - , HotKey.kesEndPeriod = KESPeriod endKesPeriod - } = forgeStateInfo - - -instance MetaTrace HotKey.KESInfo where - namespaceFor HotKey.KESInfo {} = Namespace [] ["StateInfo"] - - severityFor (Namespace _ _) (Just forgeStateInfo) = Just $ - let currKesPeriod' = currKesPeriod + startKesPeriod - maxKesEvos = endKesPeriod - startKesPeriod - expiryKesPeriod = startKesPeriod + maxKesEvos - kesPeriodsUntilExpiry = max 0 (expiryKesPeriod - currKesPeriod') - in if kesPeriodsUntilExpiry > 7 - then Info - else if kesPeriodsUntilExpiry <= 1 - then Alert - else Warning - where - HotKey.KESInfo - { HotKey.kesStartPeriod = KESPeriod startKesPeriod - , HotKey.kesEvolution = currKesPeriod - , HotKey.kesEndPeriod = KESPeriod endKesPeriod - } = forgeStateInfo - - severityFor (Namespace _ ["StateInfo"]) _ = Just Info - severityFor _ _ = Nothing - - documentFor (Namespace _ ["StateInfo"]) = Just - "kesStartPeriod \ - \\nkesEndPeriod is kesStartPeriod + tpraosMaxKESEvo\ - \\nkesEvolution is the current evolution or /relative period/." - documentFor _ = Nothing - - metricsDocFor (Namespace _ ["StateInfo"]) = - [ ("operationalCertificateStartKESPeriod", "") - , ("operationalCertificateExpiryKESPeriod", "") - , ("currentKESPeriod", "") - , ("remainingKESPeriods", "")] - metricsDocFor _ = [] - - allNamespaces = [Namespace [] ["StateInfo"]] - - - - -instance LogFormatting HotKey.KESEvolutionError where - forMachine dtal (HotKey.KESCouldNotEvolve kesInfo targetPeriod) = - mconcat - [ "kind" .= String "KESCouldNotEvolve" - , "kesInfo" .= forMachine dtal kesInfo - , "targetPeriod" .= targetPeriod - ] - forMachine dtal (HotKey.KESKeyAlreadyPoisoned kesInfo targetPeriod) = - mconcat - [ "kind" .= String "KESKeyAlreadyPoisoned" - , "kesInfo" .= forMachine dtal kesInfo - , "targetPeriod" .= targetPeriod - ] - - - - diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/LedgerMetrics.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/LedgerMetrics.hs index a94086dbc4c..b55013f1b96 100644 --- a/cardano-node/src/Cardano/Node/Tracing/Tracers/LedgerMetrics.hs +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/LedgerMetrics.hs @@ -18,7 +18,6 @@ import Cardano.Ledger.BaseTypes (SlotNo (..), StrictMaybe (..)) import Cardano.Logging hiding (traceWith) import Cardano.Node.Queries (LedgerQueries (..), NodeKernelData (..), mapNodeKernelDataIO, nkQueryChain, nkQueryLedger) -import Cardano.Node.Tracing.Tracers.ChainDB (fragmentChainDensity) import Ouroboros.Consensus.BlockchainTime.API import Ouroboros.Consensus.HardFork.Combinator import Ouroboros.Consensus.Ledger.Abstract (IsLedger) @@ -26,6 +25,7 @@ import Ouroboros.Consensus.Ledger.Extended (ledgerState) import Ouroboros.Consensus.Node (NodeKernel (getBlockchainTime, getChainDB)) import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB (getStatistics) import qualified Ouroboros.Consensus.Storage.LedgerDB.Forker as LedgerDB (ledgerTableSize) +import Ouroboros.Consensus.Tracing (fragmentChainDensity) import qualified Ouroboros.Network.AnchoredFragment as AF import Control.Concurrent (threadDelay) diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/NodeToNode.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/NodeToNode.hs index dcdd1187a1e..f4c56c6635e 100644 --- a/cardano-node/src/Cardano/Node/Tracing/Tracers/NodeToNode.hs +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/NodeToNode.hs @@ -13,12 +13,11 @@ module Cardano.Node.Tracing.Tracers.NodeToNode ) where import Cardano.Logging -import Cardano.Node.Queries (ConvertTxId) -import Cardano.Node.Tracing.Render (renderHeaderHash, renderTxIdForDetails) import Ouroboros.Consensus.Block (ConvertRawHash, GetHeader, StandardHash, getHeader) import Ouroboros.Consensus.Ledger.SupportsMempool (GenTx, HasTxId, HasTxs, LedgerSupportsMempool, extractTxs, txId) import Ouroboros.Consensus.Node.Run (SerialiseNodeToNodeConstraints, estimateBlockSize) +import Ouroboros.Consensus.Tracing (ConvertTxId, renderHeaderHash, renderTxIdForDetails) import Ouroboros.Network.Block (Point, Serialised (..), blockHash) import Ouroboros.Network.DeltaQ (GSV (..), PeerGSV (..)) import Ouroboros.Network.KeepAlive (TraceKeepAliveClient (..)) diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/Rpc.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/Rpc.hs index 518192b7f84..dae628dca7b 100644 --- a/cardano-node/src/Cardano/Node/Tracing/Tracers/Rpc.hs +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/Rpc.hs @@ -57,6 +57,8 @@ instance LogFormatting TraceRpc where TraceRpcSubmitSpan s -> [spanToObject s] TraceRpcEvalTxDecodingError _ -> [] TraceRpcEvalTxSpan s -> [spanToObject s] + TraceRpcReadMempoolSpan s -> [spanToObject s] + TraceRpcWatchMempoolSpan s -> [spanToObject s] TraceRpcSync syncTrace -> ["kind" .= String "SyncService"] <> case syncTrace of @@ -86,6 +88,8 @@ instance LogFormatting TraceRpc where TraceRpcQuery (TraceRpcQueryReadEraSummarySpan (SpanBegin _)) -> [CounterM "rpc.request.QueryService.ReadEraSummary" Nothing] TraceRpcSubmit (TraceRpcSubmitSpan (SpanBegin _)) -> [CounterM "rpc.request.SubmitService.SubmitTx" Nothing] TraceRpcSubmit (TraceRpcEvalTxSpan (SpanBegin _)) -> [CounterM "rpc.request.SubmitService.EvalTx" Nothing] + TraceRpcSubmit (TraceRpcReadMempoolSpan (SpanBegin _)) -> [CounterM "rpc.request.SubmitService.ReadMempool" Nothing] + TraceRpcSubmit (TraceRpcWatchMempoolSpan (SpanBegin _)) -> [CounterM "rpc.request.SubmitService.WatchMempool" Nothing] TraceRpcSync (TraceRpcFetchBlockSpan (SpanBegin _)) -> [CounterM "rpc.request.SyncService.FetchBlock" Nothing] TraceRpcSync (TraceRpcReadTipSpan (SpanBegin _)) -> [CounterM "rpc.request.SyncService.ReadTip" Nothing] TraceRpcSync (TraceRpcFollowTipSpan (SpanBegin _)) -> [CounterM "rpc.request.SyncService.FollowTip" Nothing] @@ -113,14 +117,16 @@ instance MetaTrace TraceRpc where TraceRpcSubmitSpan _ -> ["SubmitTx", "Span"] TraceRpcEvalTxDecodingError _ -> ["EvalTxDecodingError"] TraceRpcEvalTxSpan _ -> ["EvalTx", "Span"] + TraceRpcReadMempoolSpan _ -> ["ReadMempool", "Span"] + TraceRpcWatchMempoolSpan _ -> ["WatchMempool", "Span"] TraceRpcSync syncTrace -> "SyncService" : case syncTrace of TraceRpcFetchBlockSpan _ -> ["FetchBlock", "Span"] - TraceRpcFetchBlockNotFound _ -> ["FetchBlockNotFound"] - TraceRpcNodeKernelAccessUnavailable -> ["NodeKernelAccessUnavailable"] TraceRpcReadTipSpan _ -> ["ReadTip", "Span"] TraceRpcFollowTipSpan _ -> ["FollowTip", "Span"] + TraceRpcFetchBlockNotFound _ -> ["FetchBlockNotFound"] + TraceRpcNodeKernelAccessUnavailable -> ["NodeKernelAccessUnavailable"] TraceRpcNodeKernelAccess nodeKernelAccessTrace -> "NodeKernelAccess" : case nodeKernelAccessTrace of @@ -137,15 +143,17 @@ instance MetaTrace TraceRpc where ["QueryService", "ReadEraSummary", "Span"] -> Just Debug ["SubmitService", "SubmitTx", "Span"] -> Just Debug ["SubmitService", "EvalTx", "Span"] -> Just Debug + ["SubmitService", "ReadMempool", "Span"] -> Just Debug + ["SubmitService", "WatchMempool", "Span"] -> Just Debug ["SubmitService", "N2cConnectionError"] -> Just Warning -- this is a more serious error, this shouldn't happen ["SubmitService", "TxDecodingError"] -> Just Debug -- request error ["SubmitService", "TxValidationError"] -> Just Debug -- request error ["SubmitService", "EvalTxDecodingError"] -> Just Debug -- request error ["SyncService", "FetchBlock", "Span"] -> Just Debug - ["SyncService", "FetchBlockNotFound"] -> Just Debug - ["SyncService", "NodeKernelAccessUnavailable"] -> Just Warning ["SyncService", "ReadTip", "Span"] -> Just Debug ["SyncService", "FollowTip", "Span"] -> Just Debug + ["SyncService", "FetchBlockNotFound"] -> Just Debug + ["SyncService", "NodeKernelAccessUnavailable"] -> Just Warning ["NodeKernelAccess", "UnsupportedBlockType"] -> Just Warning ["ServerListening"] -> Just Notice -- one-off startup event, must be visible with default config _ -> Nothing @@ -160,17 +168,19 @@ instance MetaTrace TraceRpc where ["QueryService", "ReadEraSummary", "Span"] -> Just "Span for the ReadEraSummary UTXORPC method." ["SubmitService", "SubmitTx", "Span"] -> Just "Span for the SubmitTx UTXORPC method." ["SubmitService", "EvalTx", "Span"] -> Just "Span for the EvalTx UTXORPC method." + ["SubmitService", "ReadMempool", "Span"] -> Just "Span for the ReadMempool UTXORPC method." + ["SubmitService", "WatchMempool", "Span"] -> Just "Span for the WatchMempool UTXORPC method." ["SubmitService", "N2cConnectionError"] -> Just "Node connection error. This should not happen, as this means that there is an issue in cardano-rpc configuration." ["SubmitService", "TxDecodingError"] -> Just "A regular request error, when submitted transaction decoding fails." ["SubmitService", "TxValidationError"] -> Just "A regular request error, when submitted transaction is invalid." ["SubmitService", "EvalTxDecodingError"] -> Just "A regular request error, when evalTx transaction decoding fails." - ["SyncService", "FetchBlock", "Span"] -> Just "Span for the FetchBlock SyncService method." + ["SyncService", "FetchBlock", "Span"] -> Just "Span for the FetchBlock UTXORPC method." ["SyncService", "FetchBlockNotFound"] -> Just "Requested block was not found in ChainDB." ["SyncService", "NodeKernelAccessUnavailable"] -> Just "Node kernel access not yet initialised. The node is still starting up." - ["SyncService", "ReadTip", "Span"] -> Just "Span for the ReadTip SyncService method." - ["SyncService", "FollowTip", "Span"] -> Just "Span for the FollowTip SyncService method." + ["SyncService", "ReadTip", "Span"] -> Just "Span for the ReadTip UTXORPC method." + ["SyncService", "FollowTip", "Span"] -> Just "Span for the FollowTip UTXORPC method." ["NodeKernelAccess", "UnsupportedBlockType"] -> Just "The block type is not supported by the RPC server." ["ServerListening"] -> Just "RPC server is starting to listen on the configured endpoint." _ -> Nothing @@ -190,12 +200,16 @@ instance MetaTrace TraceRpc where [("rpc.request.SubmitService.SubmitTx", "Span for the SubmitTx UTXORPC method.")] ["SubmitService", "EvalTx", "Span"] -> [("rpc.request.SubmitService.EvalTx", "Span for the EvalTx UTXORPC method.")] + ["SubmitService", "ReadMempool", "Span"] -> + [("rpc.request.SubmitService.ReadMempool", "Span for the ReadMempool UTXORPC method.")] + ["SubmitService", "WatchMempool", "Span"] -> + [("rpc.request.SubmitService.WatchMempool", "Span for the WatchMempool UTXORPC method.")] ["SyncService", "FetchBlock", "Span"] -> - [("rpc.request.SyncService.FetchBlock", "Span for the FetchBlock SyncService method.")] + [("rpc.request.SyncService.FetchBlock", "Span for the FetchBlock UTXORPC method.")] ["SyncService", "ReadTip", "Span"] -> - [("rpc.request.SyncService.ReadTip", "Span for the ReadTip SyncService method.")] + [("rpc.request.SyncService.ReadTip", "Span for the ReadTip UTXORPC method.")] ["SyncService", "FollowTip", "Span"] -> - [("rpc.request.SyncService.FollowTip", "Span for the FollowTip SyncService method.")] + [("rpc.request.SyncService.FollowTip", "Span for the FollowTip UTXORPC method.")] _ -> [] allNamespaces = @@ -205,19 +219,21 @@ instance MetaTrace TraceRpc where , ["QueryService", "ReadParams", "Span"] , ["QueryService", "ReadUtxos", "Span"] , ["QueryService", "SearchUtxos", "Span"] + , ["QueryService", "ReadGenesis", "Span"] + , ["QueryService", "ReadEraSummary", "Span"] , ["SubmitService", "SubmitTx", "Span"] , ["SubmitService", "EvalTx", "Span"] + , ["SubmitService", "ReadMempool", "Span"] + , ["SubmitService", "WatchMempool", "Span"] , ["SubmitService", "N2cConnectionError"] , ["SubmitService", "TxDecodingError"] , ["SubmitService", "TxValidationError"] , ["SubmitService", "EvalTxDecodingError"] , ["SyncService", "FetchBlock", "Span"] - , ["SyncService", "FetchBlockNotFound"] - , ["SyncService", "NodeKernelAccessUnavailable"] , ["SyncService", "ReadTip", "Span"] , ["SyncService", "FollowTip", "Span"] - , ["QueryService", "ReadGenesis", "Span"] - , ["QueryService", "ReadEraSummary", "Span"] + , ["SyncService", "FetchBlockNotFound"] + , ["SyncService", "NodeKernelAccessUnavailable"] , ["NodeKernelAccess", "UnsupportedBlockType"] , ["ServerListening"] ] diff --git a/cardano-node/src/Cardano/Node/Tracing/Tracers/Startup.hs b/cardano-node/src/Cardano/Node/Tracing/Tracers/Startup.hs index 37a362ec3ad..5eeee5adc66 100644 --- a/cardano-node/src/Cardano/Node/Tracing/Tracers/Startup.hs +++ b/cardano-node/src/Cardano/Node/Tracing/Tracers/Startup.hs @@ -549,13 +549,6 @@ instance MetaTrace (StartupTrace blk) where nodeToClientVersionToInt :: NodeToClientVersion -> Int nodeToClientVersionToInt = \case - NodeToClientV_16 -> 16 - NodeToClientV_17 -> 17 - NodeToClientV_18 -> 18 - NodeToClientV_19 -> 19 - NodeToClientV_20 -> 20 - NodeToClientV_21 -> 21 - NodeToClientV_22 -> 22 NodeToClientV_23 -> 23 nodeToNodeVersionToInt :: NodeToNodeVersion -> Int diff --git a/cardano-node/src/Cardano/Node/Types.hs b/cardano-node/src/Cardano/Node/Types.hs index 4d758fd4625..942db734dc6 100644 --- a/cardano-node/src/Cardano/Node/Types.hs +++ b/cardano-node/src/Cardano/Node/Types.hs @@ -1,6 +1,7 @@ {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralisedNewtypeDeriving #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE MonoLocalBinds #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} @@ -508,6 +509,19 @@ instance AdjustFilePaths a => AdjustFilePaths (Last a) where instance AdjustFilePaths (File a b) where adjustFilePaths f (File p) = File $ f p +instance AdjustFilePaths RpcTlsFiles where + adjustFilePaths f (RpcTlsFiles cert key chain) = + RpcTlsFiles + (adjustFilePaths f cert) + (adjustFilePaths f key) + (map (adjustFilePaths f) chain) + +instance AdjustFilePaths RpcEndpoint where + adjustFilePaths f = \case + RpcEndpointUnixSocket sp -> RpcEndpointUnixSocket (adjustFilePaths f sp) + RpcEndpointHttp ip port -> RpcEndpointHttp ip port + RpcEndpointHttps ip port tls -> RpcEndpointHttps ip port (adjustFilePaths f tls) + instance Functor f => AdjustFilePaths (RpcConfigF f) where adjustFilePaths f rpcConfig@RpcConfig{rpcEndpoint, nodeSocketPath} = rpcConfig diff --git a/cardano-submit-api/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml b/cardano-submit-api/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml new file mode 100644 index 00000000000..d7e88b8d194 --- /dev/null +++ b/cardano-submit-api/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml @@ -0,0 +1,5 @@ +pr: 6677 +kind: + - maintenance +description: | + Bumped `cardano-api` to 11.8, `cardano-cli` to 11.3 and `cardano-crypto-class` to 2.6 for the 11.2 release. diff --git a/cardano-submit-api/cardano-submit-api.cabal b/cardano-submit-api/cardano-submit-api.cabal index a8eae11ea5f..cd5e2ad23da 100644 --- a/cardano-submit-api/cardano-submit-api.cabal +++ b/cardano-submit-api/cardano-submit-api.cabal @@ -39,10 +39,10 @@ library , aeson , async , bytestring - , cardano-api ^>= 11.7 + , cardano-api ^>= 11.11 , cardano-binary - , cardano-cli ^>= 11.2.2 - , cardano-crypto-class ^>=2.5 + , cardano-cli ^>= 11.6 + , cardano-crypto-class ^>=2.6 , containers , ekg-core , http-media @@ -99,4 +99,4 @@ test-suite unit main-is: test.hs hs-source-dirs: test build-depends: base - , cardano-crypto-class ^>=2.5 + , cardano-crypto-class ^>=2.6 diff --git a/cardano-testnet/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml b/cardano-testnet/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml new file mode 100644 index 00000000000..1c7b2a3fb41 --- /dev/null +++ b/cardano-testnet/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml @@ -0,0 +1,6 @@ +pr: 6677 +kind: + - maintenance +description: | + Bumped `cardano-api` to 11.8, `cardano-cli` to 11.3, `cardano-crypto-class` to 2.6, `ouroboros-network` to 1.3 and `cardano-diffusion` to 1.3 for the 11.2 release, and adapted to the new APIs. + Added `Testnet.Defaults.defaultDijkstraGenesis`, which trims the cardano-api Dijkstra genesis defaults so that the PlutusV4 cost model carries exactly the number of parameters the ledger's genesis decoder accepts. diff --git a/cardano-testnet/cardano-testnet.cabal b/cardano-testnet/cardano-testnet.cabal index 4d72894ef66..e7440706d20 100644 --- a/cardano-testnet/cardano-testnet.cabal +++ b/cardano-testnet/cardano-testnet.cabal @@ -41,9 +41,9 @@ library , annotated-exception , ansi-terminal , bytestring - , cardano-api ^>= 11.7 - , cardano-cli:{cardano-cli, cardano-cli-test-lib} ^>= 11.2.2 - , cardano-crypto-class ^>=2.5 + , cardano-api ^>= 11.11 + , cardano-cli:{cardano-cli, cardano-cli-test-lib} ^>= 11.6 + , cardano-crypto-class ^>=2.6 , cardano-crypto-wrapper , cardano-git-rev ^>= 0.2.2 , cardano-ledger-alonzo @@ -57,7 +57,7 @@ library , cardano-ledger-dijkstra , cardano-ledger-shelley , cardano-node - , cardano-diffusion:ping ^>= 1.1.1 + , cardano-diffusion:ping ^>= 1.3 , cardano-prelude , cardano-tracer , cardano-rpc @@ -83,8 +83,8 @@ library , network , optparse-applicative-fork , parsec - , ouroboros-network:{api, framework, ouroboros-network} ^>= 1.2 - , cardano-diffusion:{api, cardano-diffusion} ^>= 1.1.1 + , ouroboros-network:{api, framework, ouroboros-network} ^>= 2.0 + , cardano-diffusion:{api, cardano-diffusion} ^>= 1.3 , prettyprinter , process , resourcet @@ -155,7 +155,7 @@ executable cardano-testnet main-is: cardano-testnet.hs - build-depends: cardano-crypto-class ^>=2.5 + build-depends: cardano-crypto-class ^>=2.6 , cardano-cli , cardano-testnet , optparse-applicative-fork diff --git a/cardano-testnet/src/Testnet/Components/Configuration.hs b/cardano-testnet/src/Testnet/Components/Configuration.hs index bc2ca1d6364..5b713ba1633 100644 --- a/cardano-testnet/src/Testnet/Components/Configuration.hs +++ b/cardano-testnet/src/Testnet/Components/Configuration.hs @@ -183,7 +183,7 @@ createSPOGenesisAndFiles } alonzoGenesis' <- getDefaultAlonzoGenesis let conwayGenesis' = Defaults.defaultConwayGenesis - dijkstraGenesis' = dijkstraGenesisDefaults + dijkstraGenesis' = Defaults.defaultDijkstraGenesis (shelleyGenesis, alonzoGenesis, conwayGenesis, dijkstraGenesis) <- resolveOnChainParams onChainParams diff --git a/cardano-testnet/src/Testnet/Defaults.hs b/cardano-testnet/src/Testnet/Defaults.hs index 5d40eb75810..df07b687965 100644 --- a/cardano-testnet/src/Testnet/Defaults.hs +++ b/cardano-testnet/src/Testnet/Defaults.hs @@ -16,6 +16,7 @@ module Testnet.Defaults , defaultByronProtocolParamsJsonValue , defaultYamlConfig , defaultConwayGenesis + , defaultDijkstraGenesis , defaultCommitteeKeyPair , defaultCommitteeName , defaultCommitteeKeysDir @@ -82,6 +83,8 @@ import qualified Cardano.Ledger.Conway.Genesis as Ledger import Cardano.Ledger.Conway.PParams import qualified Cardano.Ledger.Conway.PParams as Ledger import qualified Cardano.Ledger.Core as Ledger +import Cardano.Ledger.Dijkstra.Genesis (DijkstraGenesis (..)) +import Cardano.Ledger.Dijkstra.PParams (UpgradeDijkstraPParams (..)) import qualified Cardano.Ledger.Plutus as Ledger import qualified Cardano.Ledger.Shelley as Ledger import Cardano.Ledger.Shelley.Genesis @@ -195,6 +198,26 @@ defaultConwayGenesis = do , cgExtraConfig = SNothing } +-- | The Dijkstra genesis from cardano-api, with the PlutusV4 cost model cut down to the +-- number of parameters that the genesis decoder accepts. cardano-api builds the cost model +-- from the full parameter list of the current Plutus version, but the ledger requires a +-- genesis file to carry exactly 'Ledger.costModelInitParamCount' parameters. +defaultDijkstraGenesis :: DijkstraGenesis +defaultDijkstraGenesis = + DijkstraGenesis + { dgUpgradePParams = upgradePParams{udppPlutusV4CostModel = plutusV4CostModel} + } + where + upgradePParams = dgUpgradePParams Api.dijkstraGenesisDefaults + plutusV4CostModel = + case Ledger.mkCostModel Ledger.PlutusV4 plutusV4Params of + Left err -> error $ "defaultDijkstraGenesis: invalid PlutusV4 cost model: " <> show err + Right costModel -> costModel + plutusV4Params = + take (Ledger.costModelInitParamCount Ledger.PlutusV4) + . Ledger.getCostModelParams + $ udppPlutusV4CostModel upgradePParams + -- | The only era supported by cardano-testnet for the moment. -- It's important to keep the era parameterization everywhere, for ease of development -- when new eras roll out. diff --git a/cardano-testnet/test/cardano-testnet-golden/files/golden/version_cmd.cli b/cardano-testnet/test/cardano-testnet-golden/files/golden/version_cmd.cli index 82f77d9fe9c..3a4f336100c 100644 --- a/cardano-testnet/test/cardano-testnet-golden/files/golden/version_cmd.cli +++ b/cardano-testnet/test/cardano-testnet-golden/files/golden/version_cmd.cli @@ -1,3 +1,3 @@ -built against cardano-api 11.7.0.0 -built against cardano-rpc 11.4.0.0 -built against cardano-cli 11.2.3.1 +built against cardano-api 11.8.0.0 +built against cardano-rpc 11.5.0.0 +built against cardano-cli 11.3.0.0 diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Node/Shutdown.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Node/Shutdown.hs index e0a55d7eb39..aa661b7b085 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Node/Shutdown.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Node/Shutdown.hs @@ -132,7 +132,7 @@ hprop_shutdown = integrationRetryWorkspace 2 "shutdown" $ \tempAbsBasePath' -> H H.renameFile (tempAbsPath' "shelley/genesis.alonzo.json") (tempAbsPath' defaultGenesisFilepath AlonzoEra) H.renameFile (tempAbsPath' "shelley/genesis.conway.json") (tempAbsPath' defaultGenesisFilepath ConwayEra) -- TODO: once 'cardano-cli latest genesis create' supports dijkstra, make this a copy instead of writing a default - H.writeFile (tempAbsPath' defaultGenesisFilepath DijkstraEra) . LBS.unpack $ encode dijkstraGenesisDefaults + H.writeFile (tempAbsPath' defaultGenesisFilepath DijkstraEra) . LBS.unpack $ encode defaultDijkstraGenesis (shelleyGenesisHash,alonzoGenesisHash) <- liftToIntegration $ do diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/FollowTip.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/FollowTip.hs index 54d7e7207a1..3b1c45a0484 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/FollowTip.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/FollowTip.hs @@ -25,10 +25,11 @@ import Cardano.Testnet import Prelude -import Control.Exception (try) -import Control.Monad (replicateM, void) +import Control.Exception (catch, throwIO, try) +import Control.Monad (replicateM, void, (>=>)) import qualified Data.ByteString as BS import Data.Default.Class +import Data.IORef (newIORef, readIORef, writeIORef) import Data.List.NonEmpty (NonEmpty ((:|))) import GHC.Stack (HasCallStack, callStack) import Lens.Micro @@ -60,15 +61,37 @@ hprop_rpc_follow_tip = integrationRetryWorkspace 2 "rpc-follow-tip" $ \tempAbsBa rpcSocket <- H.note . unFile $ nodeRpcSocketPath node0 let rpcServer = Rpc.ServerUnix rpcSocket + -- Open a FollowTip stream intersecting at the given references and run + -- @body@ over the stream's @recv@ action. + withFollowTip + :: [Rpc.Proto U5c.BlockRef] + -> (IO (NextElem (Rpc.Proto U5c.FollowTipResponse)) -> IO a) + -> H.Integration a + withFollowTip intersectRefs body = do + (result, cancelled) <- H.evalIO $ do + resultRef <- newIORef Nothing + let stream = + Rpc.withConnection def rpcServer $ \conn -> + Rpc.serverStreaming conn (Rpc.rpc @(Rpc.Protobuf U5c.SyncService "followTip")) (def & U5c.intersect .~ intersectRefs) $ + body >=> (writeIORef resultRef . Just) + cancelled <- (False <$ stream) `catch` \e@GrpcException{grpcError} -> + if grpcError == GrpcCancelled then pure True else throwIO e + r <- readIORef resultRef + pure (r, cancelled) + -- A cancel after the body finished is the client closing the + -- connection; only one that cut the body short is a failure. + case result of + Nothing | cancelled -> + H.failMessage callStack "FollowTip stream was cancelled before the body finished" + _ -> H.nothingFail result + -- Open a fresh FollowTip stream intersecting at the given references, -- read exactly the requested number of messages, then let the -- connection close: the stream is never consumed beyond what the -- caller asked for. followTipN :: Int -> [Rpc.Proto U5c.BlockRef] -> H.Integration [NextElem (Rpc.Proto U5c.FollowTipResponse)] followTipN messageCount intersectRefs = - H.evalIO . Rpc.withConnection def rpcServer $ \conn -> - Rpc.serverStreaming conn (Rpc.rpc @(Rpc.Protobuf U5c.SyncService "followTip")) (def & U5c.intersect .~ intersectRefs) $ - \recv -> replicateM messageCount recv + withFollowTip intersectRefs $ \recv -> replicateM messageCount recv -- Open a stream expecting it to fail before any message is delivered, -- mirroring FetchBlock's @fetchBlockExpectingError@ pattern. @@ -108,22 +131,21 @@ hprop_rpc_follow_tip = integrationRetryWorkspace 2 "rpc-follow-tip" $ \tempAbsBa -> Int -> H.Integration (Maybe (Rpc.Proto U5c.Tx)) followTipUntilTx intersectRefs txHash maxApplyMessages = - H.evalIO . Rpc.withConnection def rpcServer $ \conn -> - Rpc.serverStreaming conn (Rpc.rpc @(Rpc.Protobuf U5c.SyncService "followTip")) (def & U5c.intersect .~ intersectRefs) $ \recv -> - let scanApplies remaining - | remaining <= 0 = pure Nothing - | otherwise = do - next <- recv - case next of - NoNextElem -> pure Nothing - NextElem message -> - case message ^. U5c.maybe'apply of - Nothing -> scanApplies remaining - Just block -> - case filter (\t -> t ^. U5c.hash == txHash) (block ^. U5c.cardano . U5c.body . U5c.tx) of - (tx : _) -> pure (Just tx) - [] -> scanApplies (remaining - 1) - in scanApplies maxApplyMessages + withFollowTip intersectRefs $ \recv -> + let scanApplies remaining + | remaining <= 0 = pure Nothing + | otherwise = do + next <- recv + case next of + NoNextElem -> pure Nothing + NextElem message -> + case message ^. U5c.maybe'apply of + Nothing -> scanApplies remaining + Just block -> + case filter (\t -> t ^. U5c.hash == txHash) (block ^. U5c.cardano . U5c.body . U5c.tx) of + (tx : _) -> pure (Just tx) + [] -> scanApplies (remaining - 1) + in scanApplies maxApplyMessages -- Origin is a BlockRef with an empty hash: clients append it as an -- infallible catch-all requesting full-history sync. diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/SearchUtxos.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/SearchUtxos.hs index 9e86010b6bc..a51887d6914 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/SearchUtxos.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/SearchUtxos.hs @@ -20,7 +20,8 @@ import qualified Cardano.Api.Ledger as L import qualified Cardano.Rpc.Client as Rpc import qualified Cardano.Rpc.Proto.Api.UtxoRpc.Query as U5c hiding (cardano) import qualified Cardano.Rpc.Proto.Api.UtxoRpc.Query as UtxoRpc -import qualified Cardano.Rpc.Proto.Api.UtxoRpc.Submit as U5c +import qualified Cardano.Rpc.Proto.Api.UtxoRpc.Submit as U5c hiding (anyOf, items, match, + predicate) import qualified Cardano.Rpc.Proto.Api.UtxoRpc.Submit as UtxoRpc import Cardano.Rpc.Server.Internal.UtxoRpc.Predicate (exactAddressPredicate, serialisePaymentCredential) diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Transaction.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Transaction.hs index 58f13064fc3..358d943fc91 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Transaction.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Transaction.hs @@ -19,7 +19,8 @@ import qualified Cardano.Api.Ledger as L import qualified Cardano.Rpc.Client as Rpc import qualified Cardano.Rpc.Proto.Api.UtxoRpc.Query as U5c hiding (cardano) import qualified Cardano.Rpc.Proto.Api.UtxoRpc.Query as UtxoRpc -import qualified Cardano.Rpc.Proto.Api.UtxoRpc.Submit as U5c +import qualified Cardano.Rpc.Proto.Api.UtxoRpc.Submit as U5c hiding (anyOf, items, match, + predicate) import qualified Cardano.Rpc.Proto.Api.UtxoRpc.Submit as UtxoRpc import Cardano.Rpc.Server.Internal.UtxoRpc.Predicate (exactAddressPredicate) import Cardano.Rpc.Server.Internal.UtxoRpc.Type diff --git a/cardano-tracer/cardano-tracer.cabal b/cardano-tracer/cardano-tracer.cabal index 109e03aaf3b..49a528944d6 100644 --- a/cardano-tracer/cardano-tracer.cabal +++ b/cardano-tracer/cardano-tracer.cabal @@ -112,13 +112,13 @@ library , bimap , blaze-html , bytestring - , cardano-diffusion ^>= 1.1.1 + , cardano-diffusion ^>= 1.3 , cborg ^>= 0.2.4 , containers , contra-tracer , directory , ekg-core - , ekg-forward >= 1.2 + , ekg-forward >= 1.3 , ekg-wai , extra , filepath @@ -127,14 +127,14 @@ library , network , network-mux >= 0.8 , optparse-applicative - , ouroboros-network:{api, framework} ^>= 1.2 + , ouroboros-network:{api, framework} ^>= 2.0 , signal , slugify , smtp-mail ^>= 0.5 , stm <2.5.2 || >=2.5.3 , text , time - , trace-dispatcher ^>= 2.13.0 + , trace-dispatcher ^>= 2.13 , trace-forward ^>= 2.5.0 , trace-resources ^>= 0.2.4 , vector diff --git a/cardano-tracer/src/Cardano/Tracer/Acceptors/Client.hs b/cardano-tracer/src/Cardano/Tracer/Acceptors/Client.hs index f027461fc47..bde569ef01e 100644 --- a/cardano-tracer/src/Cardano/Tracer/Acceptors/Client.hs +++ b/cardano-tracer/src/Cardano/Tracer/Acceptors/Client.hs @@ -12,6 +12,7 @@ import Cardano.Tracer.Environment import Cardano.Tracer.Handlers.Logs.TraceObjects (deregisterNodeId, traceObjectsHandler) import Cardano.Tracer.MetaTrace import Cardano.Tracer.Utils (connIdToNodeId) +import Ouroboros.Network.ConnectionManager.Types (DataFlow (..)) import Ouroboros.Network.Context (MinimalInitiatorContext (..), ResponderContext (..)) import Ouroboros.Network.Driver.Limits (ProtocolTimeLimits) import Ouroboros.Network.IOManager (withIOManager) @@ -129,6 +130,7 @@ doConnectToForwarderLocal snocket address netMagic timeLimits app = do (ForwardingVersionData $ NetworkMagic netMagic) (const app) ) + (const Unidirectional) Nothing address case done of @@ -163,6 +165,7 @@ doConnectToForwarderSocket snocket address netMagic timeLimits app = do (ForwardingVersionData $ NetworkMagic netMagic) (const app) ) + (const Unidirectional) Nothing address case done of diff --git a/cardano-tracer/src/Cardano/Tracer/Acceptors/Server.hs b/cardano-tracer/src/Cardano/Tracer/Acceptors/Server.hs index 486497107ce..42b93ce82a4 100644 --- a/cardano-tracer/src/Cardano/Tracer/Acceptors/Server.hs +++ b/cardano-tracer/src/Cardano/Tracer/Acceptors/Server.hs @@ -13,6 +13,7 @@ import Cardano.Tracer.Environment import Cardano.Tracer.Handlers.Logs.TraceObjects (deregisterNodeId, traceObjectsHandler) import Cardano.Tracer.MetaTrace import Cardano.Tracer.Utils (connIdToNodeId) +import Ouroboros.Network.ConnectionManager.Types (DataFlow (..)) import Ouroboros.Network.Context (ResponderContext (..)) import Ouroboros.Network.Driver.Limits (ProtocolTimeLimits) import Ouroboros.Network.IOManager (withIOManager) @@ -136,6 +137,7 @@ doListenToForwarderLocal snocket address netMagic timeLimits app = do (ForwardingVersionData $ NetworkMagic netMagic) (\_ -> SomeResponderApplication app) ) + (const Unidirectional) $ \_ serverAsync -> wait serverAsync -- Block until async exception. @@ -168,6 +170,7 @@ doListenToForwarderSocket snocket address netMagic timeLimits app = do (ForwardingVersionData $ NetworkMagic netMagic) (\_ -> SomeResponderApplication app) ) + (const Unidirectional) $ \_ serverAsync -> wait serverAsync -- Block until async exception. diff --git a/cardano-tracer/test/Cardano/Tracer/Test/Forwarder.hs b/cardano-tracer/test/Cardano/Tracer/Test/Forwarder.hs index 41e9f8282ea..a09ee51d385 100644 --- a/cardano-tracer/test/Cardano/Tracer/Test/Forwarder.hs +++ b/cardano-tracer/test/Cardano/Tracer/Test/Forwarder.hs @@ -23,6 +23,7 @@ import Cardano.Tracer.Configuration (Verbosity (..)) import Cardano.Tracer.Test.TestSetup import Cardano.Tracer.Test.Utils import Cardano.Tracer.Utils +import Ouroboros.Network.ConnectionManager.Types (DataFlow (..)) import Ouroboros.Network.Driver.Limits (ProtocolTimeLimits) import Ouroboros.Network.IOManager (IOManager, withIOManager) import Ouroboros.Network.Mux (MiniProtocol (..), MiniProtocolLimits (..), @@ -221,6 +222,7 @@ doConnectToAcceptor TestSetup{..} snocket muxBearer address timeLimits (ekgConfi ] ) ) + (const Unidirectional) Nothing address case done of @@ -296,6 +298,7 @@ doListenToAcceptor TestSetup{..} ] ) ) + (const Unidirectional) $ \_ serverAsync -> wait serverAsync -- Block until async exception. where forwarderApp diff --git a/flake.lock b/flake.lock index af605d9b349..9d37b6d00dc 100644 --- a/flake.lock +++ b/flake.lock @@ -3,16 +3,16 @@ "CHaP": { "flake": false, "locked": { - "lastModified": 1790112025, - "narHash": "sha256-kyrp5BFBkDaQjWz3XIirM7oGEfDoYyDgyLiex4xIr4M=", + "lastModified": 1793096219, + "narHash": "sha256-zwtNB5oafybbeIjq28Cq9aXhJ2RbaCI61anXn/3txSE=", "owner": "intersectmbo", "repo": "cardano-haskell-packages", - "rev": "cca2e2920ae9040b8721c6ca7297a243f6399271", + "rev": "f150513ff4741d1b816b26694425f19cddb67109", "type": "github" }, "original": { "owner": "intersectmbo", - "ref": "repo", + "ref": "index-only", "repo": "cardano-haskell-packages", "type": "github" } @@ -464,11 +464,11 @@ "hackageNix_2": { "flake": false, "locked": { - "lastModified": 1788442286, - "narHash": "sha256-GlcmaNP/TOd7svFzcxvwZhIaDg89nm71rKeq+ehNN0I=", + "lastModified": 1792660874, + "narHash": "sha256-mKOOUGZwtRcwOzgT2kxvjyIwXXM1K1pKRIVR/xeZU+o=", "owner": "input-output-hk", "repo": "hackage.nix", - "rev": "2648bf92f0188f2a135c7f662a1641c2f0d28a04", + "rev": "812230c470ba3e13279e2cf24c6f1644702bd4a6", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 79bfc6f60a1..21c30d906ea 100644 --- a/flake.nix +++ b/flake.nix @@ -23,7 +23,7 @@ customConfig.url = "github:input-output-hk/empty-flake"; CHaP = { - url = "github:intersectmbo/cardano-haskell-packages?ref=repo"; + url = "github:intersectmbo/cardano-haskell-packages?ref=index-only"; flake = false; }; @@ -204,6 +204,7 @@ default = shell.dev; cluster = shell; profiled = project.profiled.shell; + ghc9141 = project.ghc9141.shell; } # Shell used by the "Haddock documentation" workflow (github-page.yml) // optionalAttrs (hostPlatform.system == "x86_64-linux") { @@ -384,7 +385,7 @@ native = packages // { - shells = devShells; + shells = removeAttrs devShells ["ghc9141"]; internal = { roots.project = project.roots; plan-nix.project = project.plan-nix; @@ -461,7 +462,7 @@ filterAttrs (n: _: elem n releaseBins && !(elem n linuxOnlyBins)) (collectExes project) ); }; - shells = removeAttrs devShells ["profiled"]; + shells = removeAttrs devShells ["profiled" "ghc9141"]; internal = { roots.project = project.roots; plan-nix.project = project.plan-nix; diff --git a/nix/TODO.org b/nix/TODO.org deleted file mode 100644 index 4a2969ed917..00000000000 --- a/nix/TODO.org +++ /dev/null @@ -1,4 +0,0 @@ -* A simple TODO list - -1. shell.nix has a separate pin of the =cardano-mainnet-mirror= flake -- that - could've been using the =flake.nix= reference somehow. diff --git a/nix/haskell.nix b/nix/haskell.nix index aae312b164d..470fcca7fd9 100644 --- a/nix/haskell.nix +++ b/nix/haskell.nix @@ -168,6 +168,58 @@ let packages.unix-time.postPatch = '' sed -i 's/mingwex//g' unix-time.cabal ''; + # cardano-addresses 4.0.8 dropped its cardano-crypto dependency and + # vendored a byte-identical copy of that package's ed25519-donna + # cbits, so the two libraries define the same 15 C symbols. GHC's + # RTS linker loads whole units when it runs Template Haskell under + # wine and refuses the duplicates, which breaks the Windows cross + # build of anything pulling in both -- cardano-api depends on each. + # Give cardano-addresses' copy a prefix of its own: -optc-D renames + # every definition and use inside its c-sources, and the six + # foreign imports are renamed to match. Deleting the vendored + # c-sources instead does not work: the unit then fails to load, + # because the RTS linker resolves a unit against its own declared + # dependencies and cardano-crypto is no longer one of them. + # + # TODO: report this upstream at + # https://github.com/IntersectMBO/cardano-addresses -- it should + # either depend on cardano-crypto again, as 4.0.2 did, or give its + # own copy a distinct prefix. Drop this workaround once a fixed + # release reaches CHaP. + packages.cardano-addresses.components.library.ghcOptions = + map (sym: "-optc-D${sym}=cardano_addresses_${sym}") [ + "cardano_crypto_ed25519_extend" + "cardano_crypto_ed25519_point_add" + "cardano_crypto_ed25519_publickey" + "cardano_crypto_ed25519_randombytes_unsafe" + "cardano_crypto_ed25519_scalar_add" + "cardano_crypto_ed25519_sign" + "cardano_crypto_ed25519_sign_open" + "wallet_encrypted_change_pass" + "wallet_encrypted_derive_private" + "wallet_encrypted_derive_public" + "wallet_encrypted_from_secret" + "wallet_encrypted_new_from_mkg" + "wallet_encrypted_sign" + "clear" + "scalar_add_no_overflow" + ]; + packages.cardano-addresses.postPatch = '' + substituteInPlace lib/Cardano/Address/Crypto/Wallet/Encrypted.hs \ + --replace-fail 'foreign import ccall "wallet_encrypted_' \ + 'foreign import ccall "cardano_addresses_wallet_encrypted_' + ''; + # haskell.nix's overlays/windows.nix selects + # ./patches/crypton-x509-system (no .patch suffix) for + # crypton-x509-system >= 1.7, and that path does not exist, so + # evaluating the Windows cross build fails outright. Drop the + # broken entry and make the same edit here instead, the way + # cardano-cli's flake does: mingw-w64 names the import library + # lowercase, so extra-libraries has to say crypt32, not Crypt32. + packages.crypton-x509-system.patches = lib.mkForce [ ]; + packages.crypton-x509-system.postPatch = '' + substituteInPlace crypton-x509-system.cabal --replace-fail 'Crypt32' 'crypt32' + ''; #packages.plutus-core.components.library.preBuild = '' # export ISERV_ARGS="-v +RTS -Dl" # export PROXY_ARGS=-v @@ -438,6 +490,25 @@ project.appendOverlays (with haskellLib.projectOverlays; [ shell.withHoogle = lib.mkForce false; shell.tools = lib.mkForce {}; }; + # Available through `nix develop .#ghc9141`: a dev shell on GHC 9.14, + # matching the `ghc: 9.14` entry of the haskell.yml CI matrix. Hoogle and + # the shell tools are dropped, as they would have to be rebuilt with the + # alternative compiler. + ghc9141 = final.appendModule { + compiler-nix-name = "ghc9141"; + shell.withHoogle = lib.mkForce false; + shell.tools = lib.mkForce {}; + # The `cabal` in shell.nativeBuildInputs is cabal-install 3.10.3.0, + # which refuses to drive GHC >= 9.10: + # + # Warning: Unknown/unsupported 'ghc' version detected (Cabal 3.10.3.0 + # supports 'ghc' version < 9.10): .../ghc is version 9.14.1 + # + # Add nixpkgs' cabal-install 3.16.1.0, matching the `cabal: 3.16` of + # haskell.yml's build matrix. It is prebuilt against nixpkgs' own GHC, + # so unlike shell.tools it does not get rebuilt with this compiler. + shell.nativeBuildInputs = lib.mkBefore [final.pkgs.pkgsBuildBuild.cabal-install]; + }; # add passthru to hsPkgs: hsPkgs = lib.mapAttrsRecursiveCond (v: !(lib.isDerivation v)) (path: value: diff --git a/nix/nixos/tests/cardano-node-dbtools.nix b/nix/nixos/tests/cardano-node-dbtools.nix index 6df3ba2e276..34bf19ef56a 100644 --- a/nix/nixos/tests/cardano-node-dbtools.nix +++ b/nix/nixos/tests/cardano-node-dbtools.nix @@ -3,6 +3,58 @@ inherit (pkgs) cardanoNodePackages lib; synthAsserted = cardanoNodePackages.db-synthesizer.passthru.asserted; + # `cardano-testnet create-env` deliberately leaves the genesis hashes out of + # its configuration file, so that the genesis files it writes alongside can be + # edited without recomputing a hash every time (see `createEnvOptions` in + # cardano-testnet's Parsers/Run.hs). cardano-node itself is fine with that -- + # POM.hs reads every `*GenesisHash` with `.:?` -- but the consensus db tools + # resolve the configuration through cardano-config, which makes all five of + # them mandatory, so they reject the environment as it comes out of create-env: + # + # db-synthesizer: invalid node configuration: Error parsing the cardano-node + # configuration (section "Protocol") in the main configuration file: + # Error in $: key "ByronGenesisHash" not found + # + # Fill them in for the tools' benefit. Byron hashes its genesis differently + # from the later eras, which take a plain blake2b-256 of the file bytes. + # + # TODO: this belongs in create-env itself -- it already computes exactly these + # five for `cardano-testnet cardano` (Testnet.Components.Configuration's + # `createConfigJson`), it just does not offer them here. Either give create-env + # an opt-in flag for them, or make the db tools as lenient as the node is. + addGenesisHashes = pkgs.writeShellApplication { + name = "add-genesis-hashes"; + runtimeInputs = [cardanoNodePackages.cardano-cli pkgs.jq]; + text = '' + if test $# -ne 1 + then echo "usage: add-genesis-hashes ENV-DIR" >&2; exit 1 + fi + cd "$1" + + # create-env names the file .yaml, but writes JSON into it, so jq can edit + # it in place. Should that ever change, this test fails loudly rather than + # silently skipping the hashes. + jq --arg byron "$(cardano-cli byron genesis print-genesis-hash \ + --genesis-json byron-genesis.json)" \ + --arg shelley "$(cardano-cli hash genesis-file \ + --genesis shelley-genesis.json)" \ + --arg alonzo "$(cardano-cli hash genesis-file \ + --genesis alonzo-genesis.json)" \ + --arg conway "$(cardano-cli hash genesis-file \ + --genesis conway-genesis.json)" \ + --arg dijkstra "$(cardano-cli hash genesis-file \ + --genesis dijkstra-genesis.json)" \ + '. + { ByronGenesisHash: $byron + , ShelleyGenesisHash: $shelley + , AlonzoGenesisHash: $alonzo + , ConwayGenesisHash: $conway + , DijkstraGenesisHash: $dijkstra + }' \ + configuration.yaml > configuration.yaml.hashed + mv configuration.yaml.hashed configuration.yaml + ''; + }; + # NixosTest script fns supporting a timeout have a default of 900 seconds. # # There is no pre-existing history for chain synthesis, and default @@ -20,14 +72,15 @@ in { nixpkgs.pkgs = pkgs; environment = { - systemPackages = with cardanoNodePackages; [ - cardano-cli - cardano-node - cardano-testnet - db-analyser - db-synthesizer - db-truncater - ]; + systemPackages = [addGenesisHashes] + ++ (with cardanoNodePackages; [ + cardano-cli + cardano-node + cardano-testnet + db-analyser + db-synthesizer + db-truncater + ]); variables = { CARDANO_CLI = getExe cardanoNodePackages.cardano-cli; @@ -54,6 +107,10 @@ in { # Epoch length ideally should also be divisible by 10k = 500 slots print(machine.succeed("cardano-testnet create-env --epoch-length 1000 --output ${testDir}")) + # The db tools, unlike the node, require every genesis hash to be present. + print(machine.succeed("echo Add genesis hashes to the node configuration")) + print(machine.succeed("add-genesis-hashes ${testDir}")) + print(machine.succeed("echo Synthesize one epoch")) print(machine.succeed("db-synthesizer \ --config ${testDir}/configuration.yaml \ @@ -82,6 +139,9 @@ in { assert blocks_before > 0, f"No blocks were synthesized: {blocks_before}" print(machine.succeed("echo Truncate synthesized chain")) + # db-truncater only looks for db/leios.{vol,imm}.db when `--leios` is passed + # (ouroboros-consensus 5.1.0.1 made that opt-in); the synthesized chain has + # no LeiosDb beside it, so the flag is deliberately omitted here. print(machine.succeed("db-truncater \ --db db \ --truncate-after-block 1 \ diff --git a/nix/pkgs.nix b/nix/pkgs.nix index be5d24bdb04..e300baef2fb 100644 --- a/nix/pkgs.nix +++ b/nix/pkgs.nix @@ -46,6 +46,27 @@ in with final; } ; + # crypton 2.1.x vendors s2n-bignum assembly for the NIST prime curves. Its + # x86-64 macros take no formal parameters, and clang's integrated assembler + # reads $0..$9 in such a macro body as Darwin-style positional arguments, so + # immediates like `adcq $0, %r8` and `subq $64, innercount` expand to nothing + # and x86_64-darwin dies in the assembler. The flag only picks an optimised + # NIST-curve backend, and nothing here is on that path: crypton 2.1.x reaches + # us solely through the hoogle the dev shells build. That is a haskell.nix + # project of its own rather than part of cardanoNodeProject, which is why + # this goes in defaultModules instead of nix/haskell.nix. The version guard + # keeps the flag off crypton 1.x, which does not have it. + haskell-nix = prev.haskell-nix // { + defaultModules = prev.haskell-nix.defaultModules ++ [ + (_: prev.haskell-nix.haskellLib.addPackageKeys { + packages.crypton = {config, ...}: { + flags.support_s2n_bignum = + lib.mkIf (lib.versionAtLeast config.package.identifier.version "2") false; + }; + }) + ]; + }; + cabal = haskell-nix.cabal-install.${compiler-nix-name}; hlint = haskell-nix.tool "ghc96" "hlint" { diff --git a/nix/workbench/backend/runner.nix b/nix/workbench/backend/runner.nix index fd7407cfebd..5988568552d 100644 --- a/nix/workbench/backend/runner.nix +++ b/nix/workbench/backend/runner.nix @@ -199,16 +199,26 @@ let ) echo "''${cmd[*]}" > $out/wb-start.sh + ## stdenv runs builders with `set -e -o pipefail`, so a failing `wb + ## start` would abort the script right here -- before the diagnostics + ## below ever run, leaving CI with no node logs at all. Disable both + ## for the pipeline and read the status of `wb start` itself out of + ## PIPESTATUS rather than `$?`, which only reports `tee`'s status. + set +e +o pipefail time "''${cmd[@]}" 2>&1 | tee $out/wb-start.log - status=$? + status=''${PIPESTATUS[0]} + set -e -o pipefail if test $status != 0 then echo "wb start failed" cd run/current echo "========== txgen stdout:"; cat generator/stdout || true echo "========== txgen stderr:"; cat generator/stderr || true - echo "========== node-0 stdout:"; cat node-0/stdout || true - echo "========== node-0 stderr:"; cat node-0/stderr || true + for node in ${__concatStringsSep " " + (__attrNames profileBundle.node-specs.value)} + do echo "========== $node stdout:"; cat "$node"/stdout || true + echo "========== $node stderr:"; cat "$node"/stderr || true + done wb call fail "wb start failed" fi diff --git a/nix/workbench/genesis/genesis-jq.sh b/nix/workbench/genesis/genesis-jq.sh index 81ecc9861f4..696b8285810 100644 --- a/nix/workbench/genesis/genesis-jq.sh +++ b/nix/workbench/genesis/genesis-jq.sh @@ -11,7 +11,10 @@ # jq's cache format marker is the "layout.version" file: genesis-create-cache-jq # writes it, genesis-cache-hit-jq gates the cache hit on it. (Atomic commit is the # top-level caller's job; the ripper backend versions via its keys instead.) -genesis_jq_layout_version=June-22-2026 +# Bumped October-08-2026: dijkstra-genesis.json is no longer cardano-cli's own +# output (see genesis-create-cache-jq), so cache entries written before that +# still hold a file the node refuses to parse. +genesis_jq_layout_version=October-08-2026 profile-cache-key-input-jq() { set -euo pipefail @@ -97,6 +100,28 @@ genesis-create-cache-jq() { progress genesis "$(colorise cardano-cli latest genesis create-testnet-data "${create_testnet_data_args[@]}")" cardano-cli latest genesis create-testnet-data "${create_testnet_data_args[@]}" + # Dijkstra genesis: `create-testnet-data` has no `--spec-dijkstra`, so it + # derives the file from cardano-api's `dijkstraGenesisDefaults` alone -- and + # that builds `plutusV4CostModel` from the full parameter list of the current + # Plutus version, while the ledger's genesis decoder insists on exactly + # `costModelInitParamCount PlutusV4` parameters. The node therefore refuses + # to parse the very file cardano-cli just wrote: + # Number of parameters supplied 369 does not match the expected number of 251 + # Overwrite it the way the ripper backend already assembles its own + # protocol.dijkstra.json: the profile's block when it has one, else the inert + # "zero" stub. This also keeps both backends byte-identical here. + # Activation check in service/nodes.nix (TestDijkstraHardForkAtEpoch). + # + # TODO: drop this once `create-testnet-data` grows a `--spec-dijkstra` flag, + # or cardano-api trims `dijkstraGenesisDefaults`' cost model to the count the + # genesis decoder accepts. cardano-testnet carries the same workaround in + # `Testnet.Defaults.defaultDijkstraGenesis`. + if [[ "$(jq -r '.genesis.dijkstra // "null"' "$profile_json")" != "null" ]]; then + jq '.genesis.dijkstra' "$profile_json" > "$dir/dijkstra-genesis.json" + else + genesis zero-spec-dijkstra > "$dir/dijkstra-genesis.json" + fi + # jq's format marker, checked by genesis-cache-hit-jq. (Atomic commit and the shared # cache.key / cache.key.input are the caller's job, in `genesis create-cache`.) cat <<<"$genesis_jq_layout_version" > "$dir"/layout.version diff --git a/nix/workbench/genesis/zero/genesis/dijkstra.json b/nix/workbench/genesis/zero/genesis/dijkstra.json index 95f4234f509..44f2e47ffed 100644 --- a/nix/workbench/genesis/zero/genesis/dijkstra.json +++ b/nix/workbench/genesis/zero/genesis/dijkstra.json @@ -1,8 +1,9 @@ { "maxRefScriptSizePerBlock": 0, "maxRefScriptSizePerTx": 0, - "refScriptCostMultiplier": 1, "refScriptCostStride": 1, + "refScriptCostMultiplier": 1, + "maxPledgeLeverage": null, "minPoolMargin": 0, "plutusV4CostModel": [ 0, @@ -262,11 +263,19 @@ "leiosDiffusionPeriodLength": 0, "leiosCommitteeSize": 0, "leiosQuorumStakeThreshold": 0, - "maxEndorserBlockTxsSize": 0, "maxEndorserBlockReferencesSize": 0, + "maxEndorserBlockTxsSize": 0, "maxEndorserBlockExecutionUnits": { "memory": 0, "steps": 0 }, - "maxRefScriptSizePerEndorserBlock": 0 + "maxRefScriptSizePerEndorserBlock": 0, + "perasMinCandidateBlockAge": 0, + "perasHealingFactor": 1, + "perasCertBoost": 0, + "perasTargetCommitteeSize": 0, + "perasBootstrapRound": null, + "perasQuorumThresholdSafetyMargin": 0, + "refInputsCostPerMultiAssetPolicy": 0, + "refInputsCostPerDatumByte": 0 } diff --git a/trace-forward/src/Trace/Forward/Forwarding.hs b/trace-forward/src/Trace/Forward/Forwarding.hs index cc104a82cab..f85b475d6e3 100644 --- a/trace-forward/src/Trace/Forward/Forwarding.hs +++ b/trace-forward/src/Trace/Forward/Forwarding.hs @@ -17,6 +17,7 @@ module Trace.Forward.Forwarding import Cardano.Logging.Types import Cardano.Logging.Utils (runInLoop) +import Ouroboros.Network.ConnectionManager.Types (DataFlow (..)) import Ouroboros.Network.Driver.Limits (ProtocolTimeLimits) import Ouroboros.Network.IOManager (IOManager) import Ouroboros.Network.Magic (NetworkMagic) @@ -47,7 +48,7 @@ import Data.List.NonEmpty (NonEmpty ((:|))) import Data.Maybe (fromMaybe) import qualified Data.Text as Text import Data.Void (Void, absurd) -import Data.Word (Word16) +import Data.Word (Word16, Word64) import qualified Network.Mux as Mux import qualified Network.Socket as Socket import System.IO (hPutStrLn, stderr) @@ -134,7 +135,7 @@ initForwardingDelayed iomgr config forwarding = liftIO $ do InitForwardingWith{initHowToConnect = RemoteSocket host port} -> EKGF.RemoteSocket host port queueSize = tofQueueSize config verbosity = tofVerbosity config - maxReconnectDelay = tofMaxReconnectDelay config + maxReconnectDelay = fromIntegral (tofMaxReconnectDelay config) ekgConfig :: EKGF.ForwarderConfiguration ekgConfig = @@ -184,7 +185,7 @@ launchForwarders -> DPF.ForwarderConfiguration -> ForwardSink TraceObject -> DataPointStore - -> Word + -> Word64 -> IO () launchForwarders iomgr forwarding ekgConfig tfConfig dpfConfig @@ -277,6 +278,7 @@ doConnectToAcceptor magic snocket makeBearer configureSocket address timeLimits ] ) ) + (const Unidirectional) Nothing address case done of @@ -352,6 +354,7 @@ doListenToAcceptor magic snocket makeBearer configureSocket address timeLimits ] ) ) + (const Unidirectional) $ \_ serverAsync -> wait serverAsync -- Block until async exception. where diff --git a/trace-forward/trace-forward.cabal b/trace-forward/trace-forward.cabal index 8b9801316ef..4ad5100988f 100644 --- a/trace-forward/trace-forward.cabal +++ b/trace-forward/trace-forward.cabal @@ -69,9 +69,9 @@ library , io-classes , network , network-mux - , ouroboros-network:{api, framework} ^>= 1.2 + , ouroboros-network:{api, framework} ^>= 2.0 , ekg-core - , ekg-forward >= 1.2 + , ekg-forward >= 1.3 , singletons ^>= 3.0 , serialise , stm From d9f6c0ce594518b4517792b5a411b3d6d7db55db Mon Sep 17 00:00:00 2001 From: Javier Sagredo Date: Fri, 2 Oct 2026 15:26:38 +0200 Subject: [PATCH 02/45] Use cardano-config to read the node configuration Read the node configuration with cardano-config 2.1.0.0 from CHaP, alongside the node's own POM parser. The node understands two configuration dialects while the migration runs. A legacy flat configuration is read by both parsers and the results are compared, so every divergence is reported as a non-fatal warning. A cardano-config envelope configuration, which POM cannot read, is resolved by cardano-config alone and mapped to the node's NodeConfiguration by the adapter. Three new modules carry this: - CardanoConfigAdapter maps a cardano-config-resolved configuration onto a PartialNodeConfiguration and runs the node's own makeNodeConfiguration. The fields it cannot map are listed in adapterGaps. - CardanoConfigCompare diffs the two resolved configurations field by field. - CardanoConfigResolve classifies the file, picks the parser its dialect calls for, and returns the configuration together with the lines to trace. cardano-config 2.1.0.0 carries ouroboros-network's own DiffusionMode, PeerSharing, AcceptedConnectionsLimit and TxSubmissionLogicVersion, which are the types the node already holds, so those fields pass through with no conversion. It also models the checkpoints file, the four network timeouts and all fourteen peer selection targets, so the adapter maps those too. An envelope configuration holds its tracing settings under Configuration.HermodTracing, where trace-dispatcher's own file parser would not find them, so the resolved TraceConfig is passed to initTraceDispatcher rather than read from the file a second time. --- cardano-node/cardano-node.cabal | 6 +- .../Configuration/CardanoConfigAdapter.hs | 444 ++++++++++++++++++ .../Configuration/CardanoConfigCompare.hs | 126 +++++ .../Configuration/CardanoConfigResolve.hs | 261 ++++++++++ cardano-node/src/Cardano/Node/Run.hs | 51 +- cardano-node/src/Cardano/Node/Tracing/API.hs | 16 +- 6 files changed, 877 insertions(+), 27 deletions(-) create mode 100644 cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs create mode 100644 cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs create mode 100644 cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs diff --git a/cardano-node/cardano-node.cabal b/cardano-node/cardano-node.cabal index 88f036858d8..b1ca27d0177 100644 --- a/cardano-node/cardano-node.cabal +++ b/cardano-node/cardano-node.cabal @@ -69,7 +69,10 @@ library hs-source-dirs: src - exposed-modules: Cardano.Node.Configuration.NodeAddress + exposed-modules: Cardano.Node.Configuration.CardanoConfigAdapter + Cardano.Node.Configuration.CardanoConfigCompare + Cardano.Node.Configuration.CardanoConfigResolve + Cardano.Node.Configuration.NodeAddress Cardano.Node.Configuration.POM Cardano.Node.Configuration.LedgerDB Cardano.Node.Configuration.Socket @@ -123,6 +126,7 @@ library , base16-bytestring , bytestring , cardano-api ^>= 11.11 + , cardano-config ^>= 2.1 , cardano-crypto-class ^>=2.6 , cardano-crypto-wrapper , cardano-git-rev ^>=0.2.2 diff --git a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs new file mode 100644 index 00000000000..58c976803c5 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs @@ -0,0 +1,444 @@ +{-# LANGUAGE ScopedTypeVariables #-} + +-- | Adapter from @cardano-config@'s resolved configuration to the node's own +-- 'NodeConfiguration' (the POM one). +-- +-- It maps @cardano-config@'s resolved values onto a 'PartialNodeConfiguration' +-- and runs the node's own 'makeNodeConfiguration', so fields cardano-config +-- supplies come from cardano-config and the rest fall back to the node defaults. +-- +-- This is what the node runs on for a @cardano-config@ envelope configuration — +-- the only parser that can read one — and what the legacy configuration's +-- cross-check is compared against; see +-- 'Cardano.Node.Configuration.CardanoConfigResolve'. +-- +-- Fields not mapped are listed in 'adapterGaps' — that gap list is exactly what +-- must be closed before the POM parser can be dropped, and every gap also shows +-- up concretely as a divergence in +-- 'Cardano.Node.Configuration.CardanoConfigCompare.compareConfigurations'. +module Cardano.Node.Configuration.CardanoConfigAdapter + ( cardanoConfigToNodeConfiguration + , cardanoConfigToPartialNodeConfiguration + , nodeProtocolConfigurationFromCardanoConfig + , adapterGaps + ) where + +import Cardano.Api (File (..)) +import qualified Cardano.Configuration as Cfg +import qualified Cardano.Configuration.CliArgs as CliArgs +import Cardano.Crypto (RequiresNetworkMagic (..)) +import Cardano.Ledger.BaseTypes (strictMaybeToMaybe) +import Cardano.Ledger.BaseTypes.NonZero (nonZero) +import Cardano.Network.ConsensusMode (ConsensusMode (..)) +import Cardano.Network.PeerSelection (NumberOfBigLedgerPeers (..)) +import Cardano.Logging.Types (ForwarderMode (..), HowToConnect (..)) +import Cardano.Node.Configuration.LedgerDB (LedgerDbConfiguration (..), + LedgerDbSelectorFlag (..), noDeprecatedOptions) +import Cardano.Node.Configuration.NodeAddress (NodeHostIPv4Address (..), + NodeHostIPv6Address (..)) +import Cardano.Node.Configuration.POM (NodeConfiguration, + PartialNodeConfiguration (..), ResponderCoreAffinityPolicy (..), + defaultPartialNodeConfiguration, makeNodeConfiguration) +import Cardano.Node.Configuration.Socket (SocketConfig (..)) +import Cardano.Node.Handlers.Shutdown (ShutdownConfig (..), + ShutdownOn (..)) +import Cardano.Node.Types (CheckpointsFile (..), CheckpointsHash (..), + ConfigYamlFilePath (..), GenesisFile (..), + GenesisHash (..), KESSource (..), MaxConcurrencyBulkSync (..), + MaxConcurrencyDeadline (..), + NodeAlonzoProtocolConfiguration (..), + NodeByronProtocolConfiguration (..), + NodeCheckpointsConfiguration (..), + NodeConwayProtocolConfiguration (..), + NodeDijkstraProtocolConfiguration (..), + NodeHardForkProtocolConfiguration (..), + NodeProtocolConfiguration (..), + NodeShelleyProtocolConfiguration (..), ProtocolFilepaths (..), + TopologyFile (..)) +import Cardano.Slotting.Block (BlockNo (..)) +import Cardano.Slotting.Slot (EpochNo (..), SlotNo (..)) +import Cardano.Rpc.Server.Config (RpcConfigF (..), RpcEndpoint (..), + RpcTlsFiles (..)) +import Data.Functor.Identity (runIdentity) +import Data.Monoid (Last (..)) +import Data.Time.Clock (secondsToDiffTime) +import Ouroboros.Consensus.Node (NodeDatabasePaths (..)) +import Ouroboros.Consensus.Node.Genesis (GenesisConfigFlags (..), + defaultGenesisConfigFlags) +import Ouroboros.Consensus.Ledger.SupportsMempool (ByteSize32 (..)) +import Ouroboros.Consensus.Mempool (MempoolCapacityBytesOverride (..)) +import Ouroboros.Consensus.Storage.LedgerDB.Args (QueryBatchSize (..)) +import Ouroboros.Consensus.Storage.LedgerDB.Snapshots + (NumOfDiskSnapshots (..), SnapshotDelayRange (..), + SnapshotFrequency (..), SnapshotFrequencyArgs (..), + SnapshotInterval (..), SnapshotPolicyArgs (..), + defaultSnapshotPolicyArgs) +import Ouroboros.Network.TxSubmission.Inbound.V2.Types + (TxSubmissionInitDelay (..)) +import System.FilePath (takeDirectory, ()) + +-- | Build the node's 'NodeConfiguration' from a @cardano-config@-resolved +-- configuration, reusing the node's own 'makeNodeConfiguration'. Fields +-- cardano-config does not yet supply keep the node defaults (see 'adapterGaps'). +cardanoConfigToNodeConfiguration :: Cfg.NodeConfiguration -> Either String NodeConfiguration +cardanoConfigToNodeConfiguration = + makeNodeConfiguration . cardanoConfigToPartialNodeConfiguration + +-- | Map the @cardano-config@-resolved values onto a 'PartialNodeConfiguration', +-- overriding the node defaults for every field cardano-config supplies. +-- +-- Several of the types are now shared rather than mirrored: @cardano-config@ +-- carries @ouroboros-network@'s own 'Cfg.DiffusionMode', 'Cfg.PeerSharing', +-- 'Cfg.AcceptedConnectionsLimit' and 'Cfg.TxSubmissionLogicVersion', which are +-- exactly the types the node's 'PartialNodeConfiguration' holds, so those fields +-- pass through with no conversion. +cardanoConfigToPartialNodeConfiguration :: Cfg.NodeConfiguration -> PartialNodeConfiguration +cardanoConfigToPartialNodeConfiguration cfg = + defaultPartialNodeConfiguration + { pncConfigFile = Last (Just (ConfigYamlFilePath (Cfg.configFilePath cfg))) + , pncTopologyFile = Last (Just (TopologyFile (Cfg.topologyFile cfg))) + , pncValidateDB = Last (Just (Cfg.validateDatabase cfg)) + , pncStartAsNonProducingNode = Last (Just (runIdentity (Cfg.startAsNonProducingNode protoCfg))) + , pncProtocolConfig = Last (Just (nodeProtocolConfigurationFromCardanoConfig cfg)) + , pncProtocolFiles = Last (Just (credentialsToProtocolFilepaths (Cfg.credentials cfg))) + , pncExperimentalProtocolsEnabled = Last (Just (runIdentity (Cfg.experimentalProtocolsEnabled netCfg))) + , pncMempoolTimeoutSoft = Last (Just (runIdentity (Cfg.mempoolTimeoutSoft mempCfg))) + , pncMempoolTimeoutHard = Last (Just (runIdentity (Cfg.mempoolTimeoutHard mempCfg))) + , pncMempoolTimeoutCapacity = Last (Just (runIdentity (Cfg.mempoolTimeoutCapacity mempCfg))) + , pncMinBigLedgerPeersForTrustedState = + Last (Just (NumberOfBigLedgerPeers (runIdentity (Cfg.minBigLedgerPeersForTrustedState netCfg)))) + , -- The deadline targets have no always-applied default (the two shipped + -- role configurations set them, but a configuration may state none), so + -- they stay optional on both sides and an unset one keeps the node + -- default. + pncDeadlineTargetOfRootPeers = + Last (strictMaybeToMaybe (Cfg.deadlineTargetOfRootPeers netCfg)) + , pncDeadlineTargetOfKnownPeers = + Last (strictMaybeToMaybe (Cfg.deadlineTargetOfKnownPeers netCfg)) + , pncDeadlineTargetOfEstablishedPeers = + Last (strictMaybeToMaybe (Cfg.deadlineTargetOfEstablishedPeers netCfg)) + , pncDeadlineTargetOfActivePeers = + Last (strictMaybeToMaybe (Cfg.deadlineTargetOfActivePeers netCfg)) + , pncDeadlineTargetOfKnownBigLedgerPeers = + Last (strictMaybeToMaybe (Cfg.deadlineTargetOfKnownBigLedgerPeers netCfg)) + , pncDeadlineTargetOfEstablishedBigLedgerPeers = + Last (strictMaybeToMaybe (Cfg.deadlineTargetOfEstablishedBigLedgerPeers netCfg)) + , pncDeadlineTargetOfActiveBigLedgerPeers = + Last (strictMaybeToMaybe (Cfg.deadlineTargetOfActiveBigLedgerPeers netCfg)) + , pncSyncTargetOfRootPeers = Last (Just (runIdentity (Cfg.syncTargetOfRootPeers netCfg))) + , pncSyncTargetOfKnownPeers = Last (Just (runIdentity (Cfg.syncTargetOfKnownPeers netCfg))) + , pncSyncTargetOfEstablishedPeers = + Last (Just (runIdentity (Cfg.syncTargetOfEstablishedPeers netCfg))) + , pncSyncTargetOfActivePeers = Last (Just (runIdentity (Cfg.syncTargetOfActivePeers netCfg))) + , pncSyncTargetOfKnownBigLedgerPeers = + Last (Just (runIdentity (Cfg.syncTargetOfKnownBigLedgerPeers netCfg))) + , pncSyncTargetOfEstablishedBigLedgerPeers = + Last (Just (runIdentity (Cfg.syncTargetOfEstablishedBigLedgerPeers netCfg))) + , pncSyncTargetOfActiveBigLedgerPeers = + Last (Just (runIdentity (Cfg.syncTargetOfActiveBigLedgerPeers netCfg))) + , pncDatabaseFile = Last (Just (fromCfgDbPaths (runIdentity (Cfg.databasePath storeCfg)))) + , pncDiffusionMode = Last (Just (runIdentity (Cfg.diffusionMode netCfg))) + , pncMaxConcurrencyBulkSync = + Last (Just (MaxConcurrencyBulkSync (runIdentity (Cfg.maxConcurrencyBulkSync netCfg)))) + , pncMaxConcurrencyDeadline = + Last (Just (MaxConcurrencyDeadline (runIdentity (Cfg.maxConcurrencyDeadline netCfg)))) + , pncProtocolIdleTimeout = Last (Just (runIdentity (Cfg.protocolIdleTimeout netCfg))) + , pncTimeWaitTimeout = Last (Just (runIdentity (Cfg.timeWaitTimeout netCfg))) + , pncEgressPollInterval = Last (Just (runIdentity (Cfg.egressPollInterval netCfg))) + , pncChainSyncIdleTimeout = Last (Just (runIdentity (Cfg.chainSyncIdleTimeout netCfg))) + , pncTxSubmissionInitDelay = + Last (Just (TxSubmissionInitDelay (runIdentity (Cfg.txSubmissionInitDelay netCfg)))) + , pncAcceptedConnectionsLimit = Last (Just (Cfg.acceptedConnectionsLimitOf netCfg)) + , pncConsensusMode = Last (Just (fromCfgConsensusMode consensusModeVal)) + , pncPeerSharing = Last (strictMaybeToMaybe (Cfg.peerSharing netCfg)) + , pncMaybeMempoolCapacityOverride = + Last (fmap (MempoolCapacityBytesOverride . ByteSize32 . fromIntegral) + (strictMaybeToMaybe (Cfg.mempoolCapacityOverride mempCfg))) + , pncShutdownConfig = + Last (Just (ShutdownConfig + (strictMaybeToMaybe (Cfg.shutdownIPC cfg)) + (fmap toNodeShutdownOn (strictMaybeToMaybe (Cfg.shutdownOnTarget cfg))))) + , pncResponderCoreAffinityPolicy = + Last (Just (fromCfgAffinity (runIdentity (Cfg.responderCoreAffinityPolicy netCfg)))) + , pncTxSubmissionLogicVersion = + Last (Just (runIdentity (Cfg.txSubmissionLogicVersion netCfg))) + , -- The Genesis tuning flags only feed 'ncGenesisConfig' when the node runs + -- in Genesis mode (see 'makeNodeConfiguration'); in Praos mode the node + -- ignores them, so mirror POM and keep the defaults there. + pncGenesisConfigFlags = + Last (Just (case consensusModeVal of + Cfg.GenesisMode flags -> fromCfgGenesisFlags flags + Cfg.PraosMode -> defaultGenesisConfigFlags)) + , -- The local (IPC) socket path comes from the configuration file or the + -- command line; the node-to-node IPv4/IPv6/port bindings are CLI-only in + -- both parsers, and cardano-config carries them on the resolved + -- configuration, so they are mapped here too. + pncSocketConfig = + Last (Just (SocketConfig + (Last (fmap NodeHostIPv4Address (strictMaybeToMaybe (Cfg.hostAddr cfg)))) + (Last (fmap NodeHostIPv6Address (strictMaybeToMaybe (Cfg.hostIPv6Addr cfg)))) + (Last (strictMaybeToMaybe (Cfg.port cfg))) + (Last (fmap File (strictMaybeToMaybe (Cfg.socketPath lcc)))))) + , pncTraceForwardSocket = + Last (fmap fromCfgTracerConnection (strictMaybeToMaybe (Cfg.tracerSocket cfg))) + , -- 'nodeSocketPath' is filled in by 'makeNodeConfiguration' from the + -- resolved socket config, so leave it empty here. + pncRpcConfig = + RpcConfig + { isEnabled = Last (Just (runIdentity (Cfg.enableGrpc lcc))) + , rpcEndpoint = + Last (fmap fromCfgGrpcEndpoint (strictMaybeToMaybe (Cfg.grpcEndpoint lcc))) + , nodeSocketPath = mempty + } + , -- Backend selector, query batch size and snapshot policy are all mapped + -- from cardano-config. 'DeprecatedOptions' has no cardano-config + -- counterpart (they are the legacy top-level SnapshotInterval / + -- NumOfDiskSnapshots keys), so it keeps the node's empty default. + pncLedgerDbConfig = + Last (Just (LedgerDbConfiguration + (fromCfgSnapshotPolicy (strictMaybeToMaybe (Cfg.snapshots ledgerDbCfg))) + (maybe DefaultQueryBatchSize RequestedQueryBatchSize + (strictMaybeToMaybe (Cfg.queryBatchSize ledgerDbCfg))) + (maybe V2InMemory fromCfgBackend + (strictMaybeToMaybe (Cfg.backendSelector ledgerDbCfg))) + noDeprecatedOptions)) + } + where + protoCfg = Cfg.protocolConfiguration cfg + netCfg = Cfg.networkConfiguration cfg + mempCfg = Cfg.mempoolConfiguration cfg + storeCfg = Cfg.storageConfiguration cfg + lcc = Cfg.localConnectionsConfig cfg + ledgerDbCfg = runIdentity (Cfg.ledgerDbConfiguration storeCfg) + consensusModeVal = runIdentity (Cfg.getConsensusConfiguration (Cfg.consensusConfiguration cfg)) + + fromCfgDbPaths :: Cfg.NodeDatabasePaths -> NodeDatabasePaths + fromCfgDbPaths (Cfg.SingleDB p) = OnePathForAllDbs p + fromCfgDbPaths (Cfg.SplitDB imm vol) = MultipleDbPaths imm vol + + fromCfgConsensusMode :: Cfg.ConsensusMode -> ConsensusMode + fromCfgConsensusMode Cfg.PraosMode = PraosMode + fromCfgConsensusMode (Cfg.GenesisMode _) = GenesisMode + + toNodeShutdownOn :: Cfg.ShutdownOn -> ShutdownOn + toNodeShutdownOn (Cfg.ShutdownAtSlot w) = ASlot (SlotNo w) + toNodeShutdownOn (Cfg.ShutdownAtBlock w) = ABlock (BlockNo w) + + fromCfgAffinity :: Cfg.ResponderCoreAffinityPolicy -> ResponderCoreAffinityPolicy + fromCfgAffinity Cfg.NoResponderCoreAffinity = NoResponderCoreAffinity + fromCfgAffinity Cfg.ResponderCoreAffinity = ResponderCoreAffinity + + -- cardano-config's gRPC endpoint and the node's 'RpcEndpoint' offer the same + -- three choices, so the mapping is one constructor to one constructor. Both + -- default the listen address to 127.0.0.1, and cardano-config has already + -- applied that default, so the endpoint arrives complete. + fromCfgGrpcEndpoint :: Cfg.GrpcEndpoint -> RpcEndpoint + fromCfgGrpcEndpoint (Cfg.GrpcEndpointUnixSocket fp) = RpcEndpointUnixSocket (File fp) + fromCfgGrpcEndpoint (Cfg.GrpcEndpointHttp ip portNo) = RpcEndpointHttp ip portNo + fromCfgGrpcEndpoint (Cfg.GrpcEndpointHttps ip portNo tls) = + RpcEndpointHttps ip portNo (fromCfgGrpcTlsFiles tls) + + fromCfgGrpcTlsFiles :: Cfg.GrpcTlsFiles -> RpcTlsFiles + fromCfgGrpcTlsFiles tls = + RpcTlsFiles + { certificateFile = File (Cfg.certificateFile tls) + , privateKeyFile = File (Cfg.privateKeyFile tls) + , chainCertificateFiles = map File (Cfg.chainCertificateFiles tls) + } + + -- cardano-config records the socket mode as the literal @"Accept"@ / + -- @"Connect"@ its CLI parser produces; anything else cannot occur. + fromCfgTracerConnection :: Cfg.TracerConnection -> (HowToConnect, ForwarderMode) + fromCfgTracerConnection (Cfg.TracerConnection mode method) = + ( case method of + CliArgs.TracerConnectViaPipe fp -> LocalPipe fp + CliArgs.TracerConnectViaRemote host portNo -> + RemoteSocket host (fromIntegral portNo) + , case mode of + "Accept" -> Responder + _ -> Initiator + ) + + -- Map cardano-config's snapshot policy onto the node's 'SnapshotPolicyArgs'. + -- Resolution has already turned a named Mithril policy into the concrete + -- options it stands for and filled in every option a partial policy left out + -- ('Cfg.resolveSnapshotPolicy'), so the policy reaching here states all six + -- values; 'Cfg.resolveSnapshotPolicy' is applied again to be independent of + -- that, and absence keeps the node default. + fromCfgSnapshotPolicy :: Maybe Cfg.SnapshotPolicy -> SnapshotPolicyArgs + fromCfgSnapshotPolicy Nothing = defaultSnapshotPolicyArgs + fromCfgSnapshotPolicy (Just policy) = + SnapshotPolicyArgs + (SnapshotFrequency SnapshotFrequencyArgs + { sfaInterval = + maybe (sfaInterval defaultFrequencyArgs) RequestedSnapshotInterval + (strictMaybeToMaybe (Cfg.snapshotInterval opts) >>= nonZero) + , sfaOffset = + maybe (sfaOffset defaultFrequencyArgs) SlotNo + (strictMaybeToMaybe (Cfg.slotOffset opts)) + , sfaRateLimit = + maybe (sfaRateLimit defaultFrequencyArgs) (secondsToDiffTime . fromIntegral) + (strictMaybeToMaybe (Cfg.snapshotRateLimit opts)) + , sfaDelaySnapshotRange = + case (strictMaybeToMaybe (Cfg.minDelay opts), strictMaybeToMaybe (Cfg.maxDelay opts)) of + (Just mn, Just mx) -> + SnapshotDelayRange (secondsToDiffTime (fromIntegral mn)) + (secondsToDiffTime (fromIntegral mx)) + _ -> sfaDelaySnapshotRange defaultFrequencyArgs + }) + (maybe (spaNum defaultSnapshotPolicyArgs) (NumOfDiskSnapshots . fromIntegral) + (strictMaybeToMaybe (Cfg.numOfDiskSnapshots opts))) + where + opts = Cfg.resolveSnapshotPolicy policy + + -- A snapshot option the configuration leaves unset keeps the node's own + -- default for that field, exactly as POM's LedgerDB parser does. + defaultFrequencyArgs = case spaFrequency defaultSnapshotPolicyArgs of + SnapshotFrequency sfa -> sfa + DisableSnapshots -> + error "defaultSnapshotPolicyArgs unexpectedly disables snapshots" + + fromCfgBackend :: Cfg.LedgerDbBackendSelector -> LedgerDbSelectorFlag + fromCfgBackend Cfg.V2InMemory = V2InMemory + fromCfgBackend (Cfg.V2LSM dbPath exportPath) = + V2LSM (strictMaybeToMaybe dbPath) (strictMaybeToMaybe exportPath) + + -- cardano-config's 'GenesisConfigFlags' mirrors the node's field-for-field, + -- except 'gcfCSJJumpSize' is a raw 'Word64' there vs a 'SlotNo' here, and the + -- optional fields are 'StrictMaybe' vs 'Maybe'. + fromCfgGenesisFlags :: Cfg.GenesisConfigFlags -> GenesisConfigFlags + fromCfgGenesisFlags f = + GenesisConfigFlags + (Cfg.gcfEnableCSJ f) + (Cfg.gcfEnableLoEAndGDD f) + (Cfg.gcfEnableLoP f) + (strictMaybeToMaybe (Cfg.gcfBlockFetchGracePeriod f)) + (strictMaybeToMaybe (Cfg.gcfBucketCapacity f)) + (strictMaybeToMaybe (Cfg.gcfBucketRate f)) + (fmap SlotNo (strictMaybeToMaybe (Cfg.gcfCSJJumpSize f))) + (strictMaybeToMaybe (Cfg.gcfGDDRateLimit f)) + +-- | Map @cardano-config@ 'Cfg.Credentials' (file paths) onto the node's +-- 'ProtocolFilepaths'. +credentialsToProtocolFilepaths :: Cfg.Credentials -> ProtocolFilepaths +credentialsToProtocolFilepaths c = + ProtocolFilepaths + { byronCertFile = strictMaybeToMaybe (Cfg.byronDelegationCertificate c) + , byronKeyFile = strictMaybeToMaybe (Cfg.byronSigningKey c) + , shelleyKESSource = fmap fromCfgKES (strictMaybeToMaybe (Cfg.shelleyKES c)) + , shelleyVRFFile = strictMaybeToMaybe (Cfg.shelleyVRFKey c) + , shelleyCertFile = strictMaybeToMaybe (Cfg.shelleyOperationalCertificate c) + , shelleyBulkCredsFile = strictMaybeToMaybe (Cfg.bulkCredentialsFile c) + } + where + fromCfgKES (Cfg.KESKeyFilePath fp) = KESKeyFilePath fp + fromCfgKES (Cfg.KESAgentSocketPath fp) = KESAgentSocketPath fp + +-- | Build the node's 'NodeProtocolConfiguration' from a @cardano-config@-resolved +-- configuration. Genesis and checkpoints file paths are resolved relative to the +-- configuration file's directory (the way cardano-config resolves them at read +-- time, and the way POM's 'AdjustFilePaths' does). +nodeProtocolConfigurationFromCardanoConfig :: + Cfg.NodeConfiguration -> NodeProtocolConfiguration +nodeProtocolConfigurationFromCardanoConfig cfg = + NodeProtocolConfigurationCardano + byronConfig + shelleyConfig + alonzoConfig + conwayConfig + dijkstraConfig + hardforkConfig + checkpointsConfig + where + protoCfg = Cfg.protocolConfiguration cfg + testCfg = Cfg.testingConfiguration cfg + configDir = takeDirectory (Cfg.configFilePath cfg) + + genFile :: Cfg.Hashed FilePath -> GenesisFile + genFile h = GenesisFile (configDir Cfg.hashed h) + + genHash :: Cfg.Hashed FilePath -> Maybe GenesisHash + genHash h = Just (GenesisHash (Cfg.hash h)) + + byronGen = Cfg.byronGenesis protoCfg + byronConfig = + NodeByronProtocolConfiguration + { npcByronGenesisFile = genFile (Cfg.byronGenesisFile byronGen) + , npcByronGenesisFileHash = genHash (Cfg.byronGenesisFile byronGen) + , npcByronReqNetworkMagic = + maybe RequiresNoMagic fromCfgReqNetworkMagic + (strictMaybeToMaybe (Cfg.byronReqNetworkMagic byronGen)) + , -- cardano-config does not model the Byron PBFT signature threshold or + -- the Byron software (block) version: @PBftSignatureThreshold@ and the + -- @LastKnownBlockVersion-*@ trio are among the keys @migrate@ drops, as + -- they now come from consensus defaults rather than configuration. Fixed + -- defaults are used here, which surface as a divergence against POM for + -- any configuration that still sets them (see 'adapterGaps'). + npcByronPbftSignatureThresh = Nothing + , npcByronSupportedProtocolVersionMajor = 1 + , npcByronSupportedProtocolVersionMinor = 0 + , npcByronSupportedProtocolVersionAlt = 0 + } + + shelleyConfig = + NodeShelleyProtocolConfiguration + (genFile (Cfg.shelleyGenesis protoCfg)) + (genHash (Cfg.shelleyGenesis protoCfg)) + alonzoConfig = + NodeAlonzoProtocolConfiguration + (genFile (Cfg.alonzoGenesis protoCfg)) + (genHash (Cfg.alonzoGenesis protoCfg)) + conwayConfig = + NodeConwayProtocolConfiguration + (genFile (Cfg.conwayGenesis protoCfg)) + (genHash (Cfg.conwayGenesis protoCfg)) + dijkstraConfig = + fmap + (\h -> NodeDijkstraProtocolConfiguration (genFile h) (genHash h)) + (strictMaybeToMaybe (Cfg.experimentalGenesis testCfg)) + + hardforkConfig = + NodeHardForkProtocolConfiguration + { npcExperimentalHardForksEnabled = runIdentity (Cfg.experimentalHardForksEnabled testCfg) + , npcTestShelleyHardForkAtEpoch = epochOf (Cfg.testShelleyHardForkAtEpoch testCfg) + , npcTestShelleyHardForkAtVersion = strictMaybeToMaybe (Cfg.testShelleyHardForkAtVersion testCfg) + , npcTestAllegraHardForkAtEpoch = epochOf (Cfg.testAllegraHardForkAtEpoch testCfg) + , npcTestAllegraHardForkAtVersion = strictMaybeToMaybe (Cfg.testAllegraHardForkAtVersion testCfg) + , npcTestMaryHardForkAtEpoch = epochOf (Cfg.testMaryHardForkAtEpoch testCfg) + , npcTestMaryHardForkAtVersion = strictMaybeToMaybe (Cfg.testMaryHardForkAtVersion testCfg) + , npcTestAlonzoHardForkAtEpoch = epochOf (Cfg.testAlonzoHardForkAtEpoch testCfg) + , npcTestAlonzoHardForkAtVersion = strictMaybeToMaybe (Cfg.testAlonzoHardForkAtVersion testCfg) + , npcTestBabbageHardForkAtEpoch = epochOf (Cfg.testBabbageHardForkAtEpoch testCfg) + , npcTestBabbageHardForkAtVersion = strictMaybeToMaybe (Cfg.testBabbageHardForkAtVersion testCfg) + , npcTestConwayHardForkAtEpoch = epochOf (Cfg.testConwayHardForkAtEpoch testCfg) + , npcTestConwayHardForkAtVersion = strictMaybeToMaybe (Cfg.testConwayHardForkAtVersion testCfg) + , npcTestDijkstraHardForkAtEpoch = epochOf (Cfg.testDijkstraHardForkAtEpoch testCfg) + , npcTestDijkstraHardForkAtVersion = strictMaybeToMaybe (Cfg.testDijkstraHardForkAtVersion testCfg) + } + + -- The checkpoints file is optional, and so is its hash once the file is given + -- ('Cfg.MaybeHashed'), which is exactly the node's own shape. + checkpointsConfig = + case strictMaybeToMaybe (Cfg.checkpointsFile protoCfg) of + Nothing -> NodeCheckpointsConfiguration Nothing Nothing + Just h -> + NodeCheckpointsConfiguration + (Just (CheckpointsFile (configDir Cfg.maybeHashed h))) + (fmap CheckpointsHash (strictMaybeToMaybe (Cfg.maybeHash h))) + + epochOf = fmap EpochNo . strictMaybeToMaybe + + fromCfgReqNetworkMagic :: Cfg.RequiresNetworkMagic -> RequiresNetworkMagic + fromCfgReqNetworkMagic Cfg.RequiresNoMagic = RequiresNoMagic + fromCfgReqNetworkMagic Cfg.RequiresMagic = RequiresMagic + +-- | Node 'NodeConfiguration' fields the adapter does not yet populate from +-- @cardano-config@ (they keep the node defaults, so they show up as divergences +-- against POM). Closing these is the remaining work before POM can be dropped. +adapterGaps :: [String] +adapterGaps = + [ "ncProtocolConfig: Byron PBFT signature threshold and supported-protocol-version" + <> " — the PBftSignatureThreshold and LastKnownBlockVersion-* keys are deliberately" + <> " not modelled by cardano-config (they now come from consensus defaults), so" + <> " Nothing and a fixed 1/0/0 are used here" + ] diff --git a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs new file mode 100644 index 00000000000..9e6010087b0 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs @@ -0,0 +1,126 @@ +-- | Diff the node's POM-resolved 'NodeConfiguration' against the one produced by +-- the @cardano-config@ adapter ('Cardano.Node.Configuration.CardanoConfigAdapter'). +-- +-- Both sides are the node's own 'NodeConfiguration', so every field is compared +-- in the node's own representation — a reported divergence reflects a genuine +-- difference in the resolved value, with no representation mismatch and no +-- deferred set. A field the adapter cannot yet populate from cardano-config keeps +-- the node default and therefore surfaces here as a divergence (see +-- 'Cardano.Node.Configuration.CardanoConfigAdapter.adapterGaps'). +module Cardano.Node.Configuration.CardanoConfigCompare + ( compareConfigurations + , deprecatedFlagWarnings + ) where + +import Cardano.Node.Configuration.POM (NodeConfiguration (..)) +import Cardano.Node.Types (NodeProtocolConfiguration (..)) + +-- | Diagnose node CLI flags that cardano-config's own CLI parser rejects, in +-- terms the operator can act on. All of these flags are deprecated: the three +-- legacy aliases have a new spelling cardano-config accepts, and the two mempool +-- flags have been removed by design (mempool capacity is a config-file setting +-- now). Given the node's argv flag list, returns one guidance line per offending +-- flag found. A pure function so the dual-parse warning path is unit-testable. +deprecatedFlagWarnings :: [String] -> [String] +deprecatedFlagWarnings = concatMap diagnose + where + -- Deprecated alias -> new (cardano-config-accepted) spelling. + renamed = + [ ("--delegation-certificate", "--byron-delegation-certificate") + , ("--signing-key", "--byron-signing-key") + , ("--non-producing-node", "--start-as-non-producing-node") + ] + -- Deprecated and removed by design; not something cardano-config should grow. + removed = ["--mempool-capacity-override", "--no-mempool-capacity-override"] + + diagnose tok = + -- Accept both @--flag value@ and @--flag=value@ spellings. + let opt = takeWhile (/= '=') tok + in case lookup opt renamed of + Just new -> + [ "warning: deprecated CLI flag '" <> opt <> "'; use '" <> new + <> "' (required for cardano-config parsing / the upcoming config parser)" ] + Nothing + | opt `elem` removed -> + [ "warning: '" <> opt <> "' is deprecated and no longer supported; remove it" + <> " and set 'MempoolCapacityBytesOverride' in the configuration file instead" ] + | otherwise -> [] + +-- | Compare a POM-resolved configuration (first argument) against the +-- adapter-produced one (second argument), field by field. Returns one line per +-- diverging field; an empty list means they agree on everything compared. +compareConfigurations :: NodeConfiguration -> NodeConfiguration -> [String] +compareConfigurations pom adapted = + concat + [ -- Protocol config, compared per era/component for readable diffs. + compareProtocol (ncProtocolConfig pom) (ncProtocolConfig adapted) + , cmp "ValidateDB" ncValidateDB + , cmp "TopologyFile" ncTopologyFile + , cmp "DatabaseFile" ncDatabaseFile + , cmp "StartAsNonProducingNode" ncStartAsNonProducingNode + , cmp "ProtocolFiles" ncProtocolFiles + , cmp "ShutdownConfig" ncShutdownConfig + , cmp "SocketConfig" ncSocketConfig + , cmp "DiffusionMode" ncDiffusionMode + , cmp "ExperimentalProtocolsEnabled" ncExperimentalProtocolsEnabled + , cmp "MaxConcurrencyBulkSync" ncMaxConcurrencyBulkSync + , cmp "MaxConcurrencyDeadline" ncMaxConcurrencyDeadline + , cmp "TraceForwardSocket" ncTraceForwardSocket + , cmp "MaybeMempoolCapacityOverride" ncMaybeMempoolCapacityOverride + , cmp "LedgerDbConfig" ncLedgerDbConfig + , cmp "ProtocolIdleTimeout" ncProtocolIdleTimeout + , cmp "TimeWaitTimeout" ncTimeWaitTimeout + , cmp "EgressPollInterval" ncEgressPollInterval + , cmp "ChainSyncIdleTimeout" ncChainSyncIdleTimeout + , cmp "MempoolTimeoutSoft" ncMempoolTimeoutSoft + , cmp "MempoolTimeoutHard" ncMempoolTimeoutHard + , cmp "MempoolTimeoutCapacity" ncMempoolTimeoutCapacity + , cmp "AcceptedConnectionsLimit" ncAcceptedConnectionsLimit + , cmp "DeadlineTargetOfRootPeers" ncDeadlineTargetOfRootPeers + , cmp "DeadlineTargetOfKnownPeers" ncDeadlineTargetOfKnownPeers + , cmp "DeadlineTargetOfEstablishedPeers" ncDeadlineTargetOfEstablishedPeers + , cmp "DeadlineTargetOfActivePeers" ncDeadlineTargetOfActivePeers + , cmp "DeadlineTargetOfKnownBigLedgerPeers" ncDeadlineTargetOfKnownBigLedgerPeers + , cmp "DeadlineTargetOfEstablishedBigLedgerPeers" ncDeadlineTargetOfEstablishedBigLedgerPeers + , cmp "DeadlineTargetOfActiveBigLedgerPeers" ncDeadlineTargetOfActiveBigLedgerPeers + , cmp "SyncTargetOfRootPeers" ncSyncTargetOfRootPeers + , cmp "SyncTargetOfKnownPeers" ncSyncTargetOfKnownPeers + , cmp "SyncTargetOfEstablishedPeers" ncSyncTargetOfEstablishedPeers + , cmp "SyncTargetOfActivePeers" ncSyncTargetOfActivePeers + , cmp "SyncTargetOfKnownBigLedgerPeers" ncSyncTargetOfKnownBigLedgerPeers + , cmp "SyncTargetOfEstablishedBigLedgerPeers" ncSyncTargetOfEstablishedBigLedgerPeers + , cmp "SyncTargetOfActiveBigLedgerPeers" ncSyncTargetOfActiveBigLedgerPeers + , cmp "ConsensusMode" ncConsensusMode + , cmp "MinBigLedgerPeersForTrustedState" ncMinBigLedgerPeersForTrustedState + , cmp "PeerSharing" ncPeerSharing + , cmp "GenesisConfig" ncGenesisConfig + , cmp "ResponderCoreAffinityPolicy" ncResponderCoreAffinityPolicy + , cmp "RpcConfig" ncRpcConfig + , cmp "TxSubmissionLogicVersion" ncTxSubmissionLogicVersion + , cmp "TxSubmissionInitDelay" ncTxSubmissionInitDelay + ] + where + cmp :: (Eq a, Show a) => String -> (NodeConfiguration -> a) -> [String] + cmp label accessor = cmpValues label (accessor pom) (accessor adapted) + +-- | Report a divergence between two values of the same type. +cmpValues :: (Eq a, Show a) => String -> a -> a -> [String] +cmpValues label a b + | a == b = [] + | otherwise = [label <> ": node=" <> show a <> " vs cardano-config=" <> show b] + +-- | Compare the Cardano protocol configuration per component (each era's genesis +-- settings, the hard-fork triggers and the checkpoints) for readable diffs. +compareProtocol :: NodeProtocolConfiguration -> NodeProtocolConfiguration -> [String] +compareProtocol + (NodeProtocolConfigurationCardano b1 s1 a1 c1 d1 h1 k1) + (NodeProtocolConfigurationCardano b2 s2 a2 c2 d2 h2 k2) = + concat + [ cmpValues "Byron protocol config" b1 b2 + , cmpValues "Shelley protocol config" s1 s2 + , cmpValues "Alonzo protocol config" a1 a2 + , cmpValues "Conway protocol config" c1 c2 + , cmpValues "Dijkstra protocol config" d1 d2 + , cmpValues "HardFork protocol config" h1 h2 + , cmpValues "Checkpoints protocol config" k1 k2 + ] diff --git a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs new file mode 100644 index 00000000000..ebf365336d3 --- /dev/null +++ b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs @@ -0,0 +1,261 @@ +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE ScopedTypeVariables #-} + +-- | Turning a node configuration file into the node's 'NodeConfiguration', +-- with whichever of the two parsers the file is written for. +-- +-- The node understands two configuration dialects while the migration to the +-- shared @cardano-config@ package is in progress: +-- +-- [Legacy] the flat, pre-@cardano-config@ configuration the node has always +-- read with its own POM parser. Both parsers can read it (@cardano-config@ +-- migrates it on the fly, see 'Cardano.Configuration.File.Migrate.migrate'), +-- so it is resolved with /both/ and the results are compared: the POM result +-- is what the node runs on, and every divergence is reported as a non-fatal +-- warning so the two can be reconciled before POM is dropped. +-- +-- [Envelope] the @cardano-config@ @{ $schema, Version, Configuration }@ +-- envelope. The POM parser cannot read it at all (every setting lives nested +-- under @Configuration@, so POM sees an empty document and fails on the first +-- required field), so it is not run: @cardano-config@ alone resolves the +-- configuration and the adapter maps it to the node's 'NodeConfiguration'. +-- +-- The dialect is decided by 'classifyConfigurationFile', on the file itself. +-- +-- Note that the legacy path pays for the second parse at every startup: +-- @cardano-config@ reads and decodes the era genesis files as part of resolving, +-- so the genesis files are parsed twice. That is the price of the cross-check and +-- it goes away with the POM parser. +module Cardano.Node.Configuration.CardanoConfigResolve + ( -- * Resolving + ResolvedNodeConfiguration (..) + , CrossCheck (..) + , buildNodeConfiguration + , NodeConfigurationError (..) + + -- * Dialects + , ConfigurationDialect (..) + , classifyConfigurationFile + ) where + +import Cardano.Logging.Types (TraceConfig) +import qualified Cardano.Configuration as Cfg +import qualified Cardano.Configuration.CliArgs as CliArgs +import Cardano.Node.Configuration.CardanoConfigAdapter + (cardanoConfigToNodeConfiguration) +import Cardano.Node.Configuration.CardanoConfigCompare + (compareConfigurations, deprecatedFlagWarnings) +import Cardano.Node.Configuration.POM (NodeConfiguration (..), + PartialNodeConfiguration (..), defaultPartialNodeConfiguration, + makeNodeConfiguration, parseNodeConfigurationFP) +import Cardano.Node.Types (ConfigYamlFilePath (..)) + +import Control.Exception (Exception (..)) +import qualified Control.Exception as Exception +import Data.Aeson (Value (..)) +import qualified Data.Aeson.KeyMap as KeyMap +import Data.List (isPrefixOf) +import Data.Monoid (Last (..)) +import qualified Data.Yaml as Yaml +import qualified Options.Applicative as Opt +import System.Environment (getArgs) + +-- | The configuration dialect a node configuration file is written in. +data ConfigurationDialect + = -- | A flat, pre-@cardano-config@ configuration: readable by both parsers. + LegacyDialect + | -- | A @cardano-config@ envelope: readable by @cardano-config@ only. + CardanoConfigDialect + deriving (Eq, Show) + +-- | Whether to cross-check a legacy configuration against @cardano-config@'s +-- parser. Worth it at startup; not worth re-reading every genesis file for on a +-- configuration reload, which only wants the new values. +data CrossCheck + = CrossCheckWithCardanoConfig + | SkipCrossCheck + deriving (Eq, Show) + +-- | The node's resolved configuration together with everything the caller needs +-- to know about how it was obtained. +data ResolvedNodeConfiguration = ResolvedNodeConfiguration + { rncConfiguration :: !NodeConfiguration + , rncTraceConfig :: !(Maybe TraceConfig) + -- ^ The tracing configuration, when it was resolved alongside the rest of the + -- configuration (envelope dialect: the tracing settings live nested under + -- @Configuration.HermodTracing@, where @trace-dispatcher@'s own file parser + -- would not find them). 'Nothing' for the legacy dialect, where + -- @trace-dispatcher@ reads the configuration file itself, as it always has. + , rncReport :: ![String] + -- ^ Non-fatal lines to trace at startup: the parser divergences found by the + -- dual parse, and any warning raised while resolving. + } + +-- | The configuration file could not be turned into a 'NodeConfiguration'. +newtype NodeConfigurationError = NodeConfigurationError String + +instance Show NodeConfigurationError where + show (NodeConfigurationError err) = "Error in creating the NodeConfiguration: " <> err + +instance Exception NodeConfigurationError + +-- | Read the node configuration from the file named by the given +-- 'PartialNodeConfiguration', using the parser its dialect calls for (see the +-- module header). +buildNodeConfiguration :: + -- | Whether to cross-check a legacy configuration against @cardano-config@. + CrossCheck -> + -- | The command-line configuration layer (also naming the configuration file). + PartialNodeConfiguration -> + IO ResolvedNodeConfiguration +buildNodeConfiguration crossCheck partialConf = do + classifyConfigurationFile configFp >>= \case + LegacyDialect -> buildFromLegacy crossCheck partialConf configFp + CardanoConfigDialect -> buildFromCardanoConfig configFp + where + -- An absent @--config@ falls back to the node's default path, exactly as + -- 'parseNodeConfigurationFP' does. + -- 'Last' is right-biased, so the command-line layer goes on the RIGHT of the + -- default to win. + configFp = + unConfigPath $ + case getLast (pncConfigFile defaultPartialNodeConfiguration <> pncConfigFile partialConf) of + Just fp -> fp + -- Unreachable: 'defaultPartialNodeConfiguration' always names a file. + Nothing -> ConfigYamlFilePath "configuration/cardano/mainnet-config.json" + +-- | Decide which dialect a configuration file is written in. +-- +-- The marker is the envelope's @Configuration@ key: that is exactly what +-- @cardano-config@ splits the document on +-- ('Cardano.Configuration.File.Merge.splitEnvelope'), and exactly what makes the +-- document unreadable to POM (which expects the settings at the top level). A +-- file that cannot even be decoded as YAML is reported as legacy so that the +-- POM path raises the syntax error, as it always did. +classifyConfigurationFile :: FilePath -> IO ConfigurationDialect +classifyConfigurationFile fp = + Yaml.decodeFileEither fp >>= \case + Right (Object o) | KeyMap.member "Configuration" o -> pure CardanoConfigDialect + _ -> pure LegacyDialect + +-- | Resolve a legacy configuration with the node's own POM parser — the result +-- the node runs on — and cross-check it against @cardano-config@'s. +buildFromLegacy :: + CrossCheck -> PartialNodeConfiguration -> FilePath -> IO ResolvedNodeConfiguration +buildFromLegacy crossCheck partialConf configFp = do + configYamlPc <- parseNodeConfigurationFP (Just (ConfigYamlFilePath configFp)) + nc <- + either (Exception.throwIO . NodeConfigurationError) pure $ + makeNodeConfiguration (defaultPartialNodeConfiguration <> configYamlPc <> partialConf) + report <- case crossCheck of + SkipCrossCheck -> pure [] + CrossCheckWithCardanoConfig -> crossCheckWithCardanoConfig configFp nc + pure + ResolvedNodeConfiguration + { rncConfiguration = nc + , rncTraceConfig = Nothing + , rncReport = report + } + +-- | Resolve an envelope configuration with @cardano-config@ alone and map it to +-- the node's 'NodeConfiguration'. Unlike the cross-check on the legacy path, +-- every failure here is fatal: there is no second parser to fall back to. +buildFromCardanoConfig :: FilePath -> IO ResolvedNodeConfiguration +buildFromCardanoConfig configFp = do + cliArgs <- + cardanoConfigCliArgs configFp + >>= either (Exception.throwIO . NodeConfigurationError) pure + (fileCfg, fileWarnings) <- Cfg.parseConfigurationFiles configFp + (cfgNc, checkWarnings) <- + either (Exception.throwIO . NodeConfigurationError . displayException) pure $ + Cfg.resolveConfiguration cliArgs fileCfg + nc <- + either (Exception.throwIO . NodeConfigurationError) pure $ + cardanoConfigToNodeConfiguration cfgNc + pure + ResolvedNodeConfiguration + { rncConfiguration = nc + , rncTraceConfig = Just (Cfg.tracingConfiguration cfgNc) + , rncReport = + "cardano-config: resolved the configuration (the node's own parser was not run: this" + <> " is a cardano-config envelope configuration, which it cannot read)" + : map (("cardano-config: " <>) . Cfg.renderConfigWarning) + (fileWarnings <> checkWarnings) + } + +-- | Resolve the same legacy configuration with @cardano-config@ and diff it +-- against the POM result, returning the lines to report. +-- +-- To keep the comparison fair, @cardano-config@ resolves from the SAME two +-- inputs the node used: it parses the node's own command line with its own CLI +-- parser and combines that with the configuration file, so both sides are +-- @file + CLI@. Every failure here is only ever reported, never fatal — the node +-- runs on the POM result either way. +crossCheckWithCardanoConfig :: FilePath -> NodeConfiguration -> IO [String] +crossCheckWithCardanoConfig configFp nc = do + (cliArgs, cliReport) <- + cardanoConfigCliArgs configFp >>= \case + Right cli -> pure (cli, []) + Left err -> + -- A parse failure means the operator used a node flag cardano-config + -- does not model (in practice, a deprecated one — 'deprecatedFlagWarnings' + -- names it). Fall back to a file-only resolution so the rest is still + -- checked, and say so. + pure + ( Cfg.defaultCliArgs configFp + , [ "cardano-config: could not parse the node command line; comparing the" + <> " configuration file only. " <> err + ] + ) + result <- Exception.try $ do + (fileCfg, fileWarnings) <- Cfg.parseConfigurationFiles configFp + resolved <- Exception.evaluate (Cfg.resolveConfiguration cliArgs fileCfg) + pure (resolved, fileWarnings) + pure . (cliReport <>) $ case result of + Left (e :: Exception.SomeException) -> + ["cardano-config: failed to parse the node configuration (ignored): " <> show e] + Right (Left err, _) -> + [ "cardano-config: failed to resolve the node configuration (ignored): " + <> displayException err + ] + Right (Right (cfgNc, checkWarnings), fileWarnings) -> + map (("cardano-config: " <>) . Cfg.renderConfigWarning) (fileWarnings <> checkWarnings) + <> case cardanoConfigToNodeConfiguration cfgNc of + Left adaptErr -> + ["cardano-config: could not adapt to the node configuration (ignored): " <> adaptErr] + Right adaptedNc -> + case compareConfigurations nc adaptedNc of + [] -> + [ "cardano-config: the resolved configuration (file + CLI) agrees with the" + <> " node's own parser." + ] + divergences -> + ( "cardano-config: WARNING - the resolved configuration (file + CLI) diverges" + <> " from the node's own parser:" + ) + : map (" - " <>) divergences + +-- | Re-parse the node's own command line with @cardano-config@'s CLI parser, so +-- both parsers resolve from the same @file + CLI@ inputs. +-- +-- The node is invoked as @cardano-node run \@ (the RTS has already +-- stripped its own arguments), so the leading non-flag subcommand token is +-- dropped to get the flag list; @cardano-config@'s 'Cfg.parseCliArgs' is a flat +-- parser with no @run@ subcommand, matching that stripped list. On failure the +-- returned message leads with actionable guidance for each offending flag. +cardanoConfigCliArgs :: FilePath -> IO (Either String Cfg.CliArgs) +cardanoConfigCliArgs configFp = do + argv <- getArgs + let flags = dropWhile (not . ("-" `isPrefixOf`)) argv + pure $ case Opt.execParserPure Opt.defaultPrefs (Opt.info Cfg.parseCliArgs mempty) flags of + Opt.Success cli -> Right (onConfigFile cli) + Opt.CompletionInvoked _ -> Right (Cfg.defaultCliArgs configFp) + Opt.Failure failure -> + let (msg, _exitCode) = Opt.renderFailure failure "cardano-node" + in Left (unlines (deprecatedFlagWarnings flags <> [msg])) + where + -- The file being resolved is already settled (it is what was classified); pin + -- it rather than take cardano-config's own @--config@ default, so a caller that + -- named the file some other way than on the command line still resolves the + -- genesis paths (which hang off the configuration file's directory) correctly. + onConfigFile cli = cli{CliArgs.configFilePath = configFp} diff --git a/cardano-node/src/Cardano/Node/Run.hs b/cardano-node/src/Cardano/Node/Run.hs index 97e08bf2f12..f91221d159a 100644 --- a/cardano-node/src/Cardano/Node/Run.hs +++ b/cardano-node/src/Cardano/Node/Run.hs @@ -29,12 +29,14 @@ import qualified Cardano.Api as Api import System.Random (randomIO) import qualified Cardano.Crypto.Init as Crypto +import Cardano.Node.Configuration.CardanoConfigResolve + (CrossCheck (..), ResolvedNodeConfiguration (..), + buildNodeConfiguration) import Cardano.Node.Configuration.LedgerDB import Cardano.Node.Configuration.NodeAddress import Cardano.Node.Configuration.POM (NodeConfiguration (..), PartialNodeConfiguration (..), TimeoutOverride (..), - defaultPartialNodeConfiguration, makeNodeConfiguration, - parseNodeConfigurationFP, getForkPolicy) + getForkPolicy) import Cardano.Node.Configuration.Socket (LocalSocketOrSocketInfo, SocketOrSocketInfo, SocketOrSocketInfo' (..), gatherConfiguredSockets, getSocketOrSocketInfoAddr) @@ -64,7 +66,7 @@ import Cardano.Node.Tracing.Tracers.Startup (getStartupInfo) import Cardano.Node.Types import Cardano.Prelude (FatalError (..), bool, (:~:) (..)) import Cardano.Slotting.Slot (WithOrigin (..)) -import Cardano.Logging.Types (LogFormatting) +import Cardano.Logging.Types (LogFormatting, TraceConfig) import Cardano.Logging.Utils (showT) import Ouroboros.Consensus.Block.Forging (MkBlockForging) @@ -186,12 +188,20 @@ runNode cmdPc = do Crypto.cryptoInit - nc@NodeConfiguration - { ncProtocolConfig - , ncProtocolFiles=ncProtocolFiles@ProtocolFilepaths{shelleyVRFFile=mShelleyVrfFile} - } <- buildNodeConfiguration cmdPc - let earlyTracer = stdoutTracer + + ResolvedNodeConfiguration + { rncConfiguration = nc@NodeConfiguration + { ncProtocolConfig + , ncProtocolFiles=ncProtocolFiles@ProtocolFilepaths{shelleyVRFFile=mShelleyVrfFile} + } + , rncTraceConfig + , rncReport + } <- buildNodeConfiguration CrossCheckWithCardanoConfig cmdPc + + -- What the configuration parsers had to say: which one read the file, and, for + -- a legacy configuration, where the two of them disagree. All non-fatal. + mapM_ (traceWith earlyTracer) rncReport traceWith earlyTracer $ "Node configuration: " <> show nc forM_ mShelleyVrfFile $ @@ -205,29 +215,21 @@ runNode cmdPc = do -- don't need these. (Just ncProtocolFiles) - handleNodeWithTracers cmdPc nc consensusProtocol shelleyGenesisHash + handleNodeWithTracers cmdPc nc rncTraceConfig consensusProtocol shelleyGenesisHash runThrowExceptT :: Exception e => ExceptT e IO a -> IO a runThrowExceptT act = runExceptT act >>= either Exception.throwIO pure --- | Read node configuration from a file specified in 'PartialNodeConfiguration' -buildNodeConfiguration :: HasCallStack - => PartialNodeConfiguration -- ^ defaults - -> IO NodeConfiguration -buildNodeConfiguration partialConf = do - configYamlPc <- parseNodeConfigurationFP . getLast $ pncConfigFile partialConf - either - (\err -> error $ "Error in creating the NodeConfiguration: " <> err) - pure - $ makeNodeConfiguration (defaultPartialNodeConfiguration <> configYamlPc <> partialConf) - handleNodeWithTracers :: PartialNodeConfiguration -> NodeConfiguration + -> Maybe TraceConfig + -- ^ The tracing configuration, when the configuration parser resolved it + -- too; 'Nothing' leaves it to trace-dispatcher to read the file. -> SomeConsensusProtocol -> Api.GenesisHashShelley -> IO () -handleNodeWithTracers cmdPc nc (SomeConsensusProtocol blockType runP) shelleyGenesisHash = do +handleNodeWithTracers cmdPc nc mTrConfig (SomeConsensusProtocol blockType runP) shelleyGenesisHash = do (pInfo@ProtocolInfo{pInfoConfig}, mkBlockForging) <- Api.protocolInfo @IO runP let networkMagic :: Api.NetworkMagic = getNetworkMagic $ Consensus.configBlock pInfoConfig -- This IORef contains node kernel structure which holds node kernel. @@ -245,6 +247,7 @@ handleNodeWithTracers cmdPc nc (SomeConsensusProtocol blockType runP) shelleyGen tracers <- initTraceDispatcher nc + mTrConfig blockType pInfoConfig networkMagic @@ -827,7 +830,11 @@ updateRpcConfiguration :: Tracer IO (StartupTrace blk) -- ^ tracer for configura -> StrictTVar IO RpcConfig -- ^ TVar storing RPC configuration -> IO () updateRpcConfiguration tracer cmdPc rpcConfigVar = do - result <- try @Exception.SomeException $ buildNodeConfiguration cmdPc + -- A reload only wants the new values; the parser cross-check already ran (and + -- was reported) at startup. + result <- + try @Exception.SomeException $ + rncConfiguration <$> buildNodeConfiguration SkipCrossCheck cmdPc case result of Left err -> -- reload failure, we don't do anything this time diff --git a/cardano-node/src/Cardano/Node/Tracing/API.hs b/cardano-node/src/Cardano/Node/Tracing/API.hs index da0496d64a4..68a8217cee9 100644 --- a/cardano-node/src/Cardano/Node/Tracing/API.hs +++ b/cardano-node/src/Cardano/Node/Tracing/API.hs @@ -65,6 +65,11 @@ initTraceDispatcher :: , LogFormatting (TraceGsmEvent (Tip blk)) ) => NodeConfiguration + -> Maybe TraceConfig + -- ^ The tracing configuration, when it was already resolved alongside the + -- rest of the node configuration (see + -- 'Cardano.Node.Configuration.CardanoConfigResolve.rncTraceConfig'). + -- 'Nothing' means read it from the configuration file, as ever. -> BlockType blk -> TopLevelConfig blk -> NetworkMagic @@ -72,10 +77,13 @@ initTraceDispatcher :: -> Bool -> ForgingStateVar -> IO (Tracers RemoteAddress LocalAddress blk IO) -initTraceDispatcher nc blockType cfg networkMagic nodeKernel noBlockForging forgingStateVar = do - trConfig <- readConfigurationWithDefault - (FromFile (unConfigPath $ ncConfigFile nc)) - defaultCardanoConfig +initTraceDispatcher nc mTrConfig blockType cfg networkMagic nodeKernel noBlockForging forgingStateVar = do + trConfig <- case mTrConfig of + Just resolved -> pure resolved + Nothing -> + readConfigurationWithDefault + (FromFile (unConfigPath $ ncConfigFile nc)) + defaultCardanoConfig (kickoffForwarder, kickoffPrometheusSimple, tracers) <- mkTracers trConfig From 4735e7638ae37edd8acb3175dfa3f7e5200cb1fc Mon Sep 17 00:00:00 2001 From: Javier Sagredo Date: Mon, 5 Oct 2026 17:19:21 +0200 Subject: [PATCH 03/45] Add the cardano-node config subcommands and configuration-dialect tests Splice cardano-config's three subcommands into the node's command tree under a config verb: cardano-node config migrate, cardano-node config schema and cardano-node config resolve. migrate and schema are cardano-config's own commands, unchanged. resolve is a node-specific variant: it prints the cardano-config result as YAML, and for a legacy configuration it also re-resolves the file with the node's own POM parser and reports every divergence, exiting non-zero when the two disagree. That makes it a parity check for CI while the node still has two parsers. The new test suite covers both dialects on one fixture configuration written two ways: config.json is the legacy form, and config-envelope.json is the same configuration put through cardano-config 2.1.0.0's migrate. The tests check that each file is classified correctly, that POM genuinely cannot resolve an envelope, that the envelope resolves to the same configuration as the legacy form it came from, and that the legacy dual parse diverges only on the documented residual set. --- .gitattributes | 4 + cardano-node/app/cardano-node.hs | 133 +++++++++- cardano-node/cardano-node.cabal | 17 ++ .../test/cardano-config-compare/Main.hs | 251 ++++++++++++++++++ .../config/alonzo-genesis.json | 194 ++++++++++++++ .../config/byron-genesis.json | 42 +++ .../config/config-envelope.json | 122 +++++++++ .../cardano-config-compare/config/config.json | 121 +++++++++ .../config/conway-genesis.json | 77 ++++++ .../config/dijkstra-genesis.json | 28 ++ .../config/shelley-genesis.json | 83 ++++++ 11 files changed, 1070 insertions(+), 2 deletions(-) create mode 100644 cardano-node/test/cardano-config-compare/Main.hs create mode 100644 cardano-node/test/cardano-config-compare/config/alonzo-genesis.json create mode 100644 cardano-node/test/cardano-config-compare/config/byron-genesis.json create mode 100644 cardano-node/test/cardano-config-compare/config/config-envelope.json create mode 100644 cardano-node/test/cardano-config-compare/config/config.json create mode 100644 cardano-node/test/cardano-config-compare/config/conway-genesis.json create mode 100644 cardano-node/test/cardano-config-compare/config/dijkstra-genesis.json create mode 100644 cardano-node/test/cardano-config-compare/config/shelley-genesis.json diff --git a/.gitattributes b/.gitattributes index 5a706b986af..14fae058354 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,5 +5,9 @@ configuration/cardano/mainnet-alonzo-genesis.json text eol=lf configuration/cardano/mainnet-byron-genesis.json text eol=lf configuration/cardano/mainnet-conway-genesis.json text eol=lf configuration/cardano/mainnet-shelley-genesis.json text eol=lf +# Genesis hashes are taken over the raw file bytes, so a CRLF checkout on +# Windows would not match the hashes pinned in the fixture configurations. +cardano-node/test/cardano-config-compare/config/*.json text eol=lf + cardano-testnet/test/cardano-testnet-test/files/sample-proposal-anchor text eol=lf cardano-testnet/test/cardano-testnet-test/files/sample-constitution-anchor text eol=lf diff --git a/cardano-node/app/cardano-node.hs b/cardano-node/app/cardano-node.hs index 8f7fa994d65..911dce5185f 100644 --- a/cardano-node/app/cardano-node.hs +++ b/cardano-node/app/cardano-node.hs @@ -1,25 +1,40 @@ {-# LANGUAGE GADTs #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TemplateHaskell #-} +import qualified Cardano.Configuration as Cfg +import qualified Cardano.Configuration.CliArgs as CliArgs +import qualified Cardano.Configuration.Commands as Cmds import qualified Cardano.Crypto.Init as Crypto import Cardano.Git.Rev (gitRev) -import Cardano.Node.Configuration.POM (PartialNodeConfiguration (..)) +import Cardano.Node.Configuration.CardanoConfigAdapter + (cardanoConfigToNodeConfiguration) +import Cardano.Node.Configuration.CardanoConfigCompare + (compareConfigurations) +import Cardano.Node.Configuration.CardanoConfigResolve + (ConfigurationDialect (..), classifyConfigurationFile) +import Cardano.Node.Configuration.POM (NodeConfiguration (..), + PartialNodeConfiguration (..), defaultPartialNodeConfiguration, + makeNodeConfiguration, parseNodeConfigurationFP) import Cardano.Node.Handlers.TopLevel import Cardano.Node.Parsers (nodeCLIParser) import Cardano.Node.Run (runNode) import Cardano.Node.Tracing.Documentation (TraceDocumentationCmd (..), parseTraceDocumentationCmd, runTraceDocumentationCmd) +import Cardano.Node.Types (ConfigYamlFilePath (..)) -import Data.Monoid (Last (getLast)) +import Control.Exception (displayException) +import Data.Monoid (Last (..)) import qualified Data.Text as Text import qualified Data.Text.IO as Text import Data.Version (showVersion) import Main.Utf8 (withUtf8) import Options.Applicative import qualified Options.Applicative as Opt +import System.Exit (exitFailure) import System.Info (arch, compilerName, compilerVersion, os) import System.IO (hPutStrLn, stderr) import System.IO.CodePage (withCP65001) @@ -39,6 +54,7 @@ main = withCP65001 $ withUtf8 $ do runNode args TraceDocumentation tdc -> runTraceDocumentationCmd tdc VersionCmd -> runVersionCommand + ConfigCmd act -> act where p = Opt.prefs Opt.showHelpOnEmpty @@ -58,6 +74,7 @@ main = withCP65001 $ withUtf8 $ do Opt.info (fmap RunCmd nodeCLIParser <|> fmap TraceDocumentation parseTraceDocumentationCmd <|> parseVersionCmd + <|> fmap ConfigCmd configSubcommands <**> helper) ( Opt.fullDesc <> @@ -68,6 +85,7 @@ main = withCP65001 $ withUtf8 $ do data Command = RunCmd PartialNodeConfiguration | TraceDocumentation TraceDocumentationCmd | VersionCmd + | ConfigCmd (IO ()) -- Yes! A --version flag or version command. Either guess is right! parseVersionCmd :: Parser Command @@ -107,3 +125,114 @@ command' c descr p = [ command c (info (p <**> helper) $ mconcat [ progDesc descr ]) , metavar c ] + +-- cardano-config subcommands -------------------------------------------------- + +-- | The @config@ verb: @cardano-node config migrate@, @cardano-node config +-- schema@ and @cardano-node config resolve@, spliced from the shared +-- @cardano-config:commands@ sublibrary. @migrate@ and @schema@ are +-- cardano-config's own commands, unchanged; @resolve@ is a node-specific variant +-- (see 'resolveDualCommand') that additionally cross-checks the node's own parser +-- against cardano-config's. +configSubcommands :: Parser (IO ()) +configSubcommands = + Opt.subparser + (mconcat + [ Opt.commandGroup "Configuration commands" + , Opt.metavar "config" + , command "config" + ( info + (configVerbSubcommands <**> helper) + ( progDesc + "Inspect, migrate and resolve a cardano-node configuration file." + ) + ) + ]) + +-- | The commands under the @config@ verb. +configVerbSubcommands :: Parser (IO ()) +configVerbSubcommands = + Opt.hsubparser + ( Cmds.migrateCommand + <> Cmds.schemaCommand + <> resolveDualCommand + ) + +-- | A node-specific @resolve@: resolve the configuration with cardano-config +-- (printing the result as YAML, exactly like cardano-config's own @resolve@) and, +-- for a legacy configuration, re-resolve it with the node's own POM parser and +-- report any discrepancies between the two. Exits non-zero when they disagree, so +-- it doubles as a CI parity check while the node still has two parsers. +-- +-- A cardano-config envelope configuration has nothing to cross-check against: +-- the POM parser cannot read it (which is the whole point of the envelope), so +-- @resolve@ just prints the cardano-config result and says so. +resolveDualCommand :: Mod CommandFields (IO ()) +resolveDualCommand = + command "resolve" + ( info + (runDualResolve <$> Cmds.resolveOptionsParser) + ( progDesc + ( "Resolve a cardano-node configuration (defaults + file + CLI) and print the " + <> "result as YAML. A legacy (pre-cardano-config) configuration is resolved " + <> "with both the node and cardano-config parsers and any discrepancy between " + <> "them is reported (exit non-zero if they disagree)." + ) + ) + ) + +runDualResolve :: Cmds.ResolveOptions -> IO () +runDualResolve resolveOpts = do + -- Print the resolved configuration using cardano-config's own renderer (which + -- honours --with-geneses); this also terminates via 'die' if resolution fails. + Cmds.runResolveCommand resolveOpts + classifyConfigurationFile configFp >>= \case + CardanoConfigDialect -> + putStrLn $ + "resolve: this is a cardano-config envelope configuration; the node's own parser" + <> " cannot read it, so there is nothing to cross-check." + LegacyDialect -> do + discrepancies <- resolveDiscrepancies cli + case discrepancies of + [] -> + putStrLn "resolve: the node and cardano-config parsers agree on the resolved configuration." + ds -> do + hPutStrLn stderr $ + "resolve: " <> show (length ds) + <> " discrepancy(ies) between the node and cardano-config parsers:" + mapM_ (hPutStrLn stderr . (" - " <>)) ds + exitFailure + where + cli = Cmds.resolveCliArgs resolveOpts + configFp = CliArgs.configFilePath cli + +-- | Resolve a legacy configuration file (+ CLI) both ways and return the +-- divergences. The node (POM) side takes its CLI-supplied, file-absent fields +-- (topology / database / protocol files / socket) from the shared cardano-config +-- resolution, so the diff reflects how the two parsers read the configuration +-- FILE (plus the documented adapter gaps) rather than an independent — and +-- necessarily asymmetric — CLI reverse-mapping. +resolveDiscrepancies :: Cfg.CliArgs -> IO [String] +resolveDiscrepancies cli = do + (fileCfg, _warns) <- Cfg.parseConfigurationFiles configFp + case Cfg.resolveConfiguration cli fileCfg of + Left err -> + pure ["cardano-config failed to resolve the configuration: " <> displayException err] + Right (cfgNc, _) -> + case cardanoConfigToNodeConfiguration cfgNc of + Left adaptErr -> pure ["cardano-config configuration could not be adapted: " <> adaptErr] + Right adaptedNc -> do + filePartial <- parseNodeConfigurationFP (Just (ConfigYamlFilePath configFp)) + let withCli = + (defaultPartialNodeConfiguration <> filePartial) + { pncConfigFile = Last (Just (ConfigYamlFilePath configFp)) + , pncTopologyFile = Last (Just (ncTopologyFile adaptedNc)) + , pncDatabaseFile = Last (Just (ncDatabaseFile adaptedNc)) + , pncProtocolFiles = Last (Just (ncProtocolFiles adaptedNc)) + , pncSocketConfig = Last (Just (ncSocketConfig adaptedNc)) + } + case makeNodeConfiguration withCli of + Left err -> pure ["node parser (makeNodeConfiguration) failed: " <> err] + Right pomNc -> pure (compareConfigurations pomNc adaptedNc) + where + configFp = CliArgs.configFilePath cli diff --git a/cardano-node/cardano-node.cabal b/cardano-node/cardano-node.cabal index b1ca27d0177..92dd280620e 100644 --- a/cardano-node/cardano-node.cabal +++ b/cardano-node/cardano-node.cabal @@ -14,6 +14,7 @@ license-files: LICENSE NOTICE build-type: Simple extra-doc-files: ChangeLog.md +extra-source-files: test/cardano-config-compare/config/*.json Flag unexpected_thunks Description: Turn on unexpected thunks checks @@ -203,6 +204,8 @@ executable cardano-node autogen-modules: Paths_cardano_node build-depends: base + , cardano-config ^>= 2.1 + , cardano-config:commands , cardano-crypto-class , cardano-git-rev , cardano-node @@ -211,6 +214,20 @@ executable cardano-node , with-utf8 , text +test-suite cardano-config-compare-test + import: project-config + hs-source-dirs: test/cardano-config-compare + main-is: Main.hs + type: exitcode-stdio-1.0 + + build-depends: base + , cardano-config ^>= 2.1 + , cardano-node + , directory + , filepath + , tasty + , tasty-hunit + test-suite cardano-node-test import: project-config , maybe-unix diff --git a/cardano-node/test/cardano-config-compare/Main.hs b/cardano-node/test/cardano-config-compare/Main.hs new file mode 100644 index 00000000000..12e7d531479 --- /dev/null +++ b/cardano-node/test/cardano-config-compare/Main.hs @@ -0,0 +1,251 @@ +{-# LANGUAGE ScopedTypeVariables #-} + +-- | Tests for the two configuration dialects the node understands +-- ('Cardano.Node.Configuration.CardanoConfigResolve'): +-- +-- * a legacy (pre-@cardano-config@) configuration is read by both parsers, and +-- the divergences between them are exactly the documented residual set; and +-- * a @cardano-config@ envelope configuration is read by @cardano-config@ only +-- — the node's own POM parser genuinely cannot resolve it, which is why the +-- dual parse is skipped for it — and resolving it yields the same +-- configuration as the legacy form it was migrated from. +-- +-- Plus 'deprecatedFlagWarnings', the operator-facing guidance emitted when +-- @cardano-config@'s CLI parser rejects the node's argv. +-- +-- The two fixture configurations are the same configuration in the two dialects: +-- @config-envelope.json@ is @config.json@ put through @cardano-node config migrate@. +-- They sit in the same directory, so both resolve the same (relative) genesis +-- file paths and can be compared field by field. +module Main (main) where + +import Control.Exception (SomeException, evaluate, try) +import Control.Monad (filterM) +import Data.List (isInfixOf, isPrefixOf) +import Data.Monoid (Last (..)) + +import qualified Cardano.Configuration as Cfg +import Cardano.Node.Configuration.CardanoConfigAdapter + (cardanoConfigToNodeConfiguration) +import Cardano.Node.Configuration.CardanoConfigCompare + (compareConfigurations, deprecatedFlagWarnings) +import Cardano.Node.Configuration.CardanoConfigResolve + (ConfigurationDialect (..), classifyConfigurationFile) +import Cardano.Node.Configuration.POM (NodeConfiguration (..), + PartialNodeConfiguration (..), defaultPartialNodeConfiguration, + makeNodeConfiguration, parseNodeConfigurationFP) +import Cardano.Node.Types (ConfigYamlFilePath (..)) + +import System.Directory (doesFileExist) +import System.FilePath (()) + +import Test.Tasty +import Test.Tasty.HUnit + +-- | Locate the fixture configuration directory. Depending on the runner the +-- working directory is either the package directory or the repository root, so +-- try both rather than assume one. +fixtureDir :: IO FilePath +fixtureDir = do + found <- filterM (doesFileExist . ( "config.json")) candidates + case found of + dir : _ -> pure dir + [] -> + assertFailure $ + "could not find the fixture configuration directory; looked in " <> show candidates + where + candidates = + [ "test/cardano-config-compare/config" + , "cardano-node/test/cardano-config-compare/config" + ] + +-- | The fixture's legacy (flat, pre-cardano-config) configuration file. +legacyConfigPath :: IO FilePath +legacyConfigPath = ( "config.json") <$> fixtureDir + +-- | The same configuration in the cardano-config envelope (the output of +-- @cardano-node config migrate@ on 'legacyConfigPath'). +envelopeConfigPath :: IO FilePath +envelopeConfigPath = ( "config-envelope.json") <$> fixtureDir + +-- | Labels ('compareConfigurations' prefixes each divergence with one) that are +-- documented, expected divergences on this fixture. They fall into three kinds, +-- and none is an adapter defect — the adapter faithfully reflects what +-- cardano-config resolved; the check exists precisely to surface these: +-- +-- (1) adapter gaps — a field the adapter cannot populate from cardano-config +-- (see 'Cardano.Node.Configuration.CardanoConfigAdapter.adapterGaps'); +-- (2) representation differences — same meaning, different shape; +-- (3) parser default mismatches — a field the fixture does not set (or sets +-- under a key one parser ignores), for which the two parsers fall back to +-- different defaults. +-- +-- The fixture comparison must not diverge on anything OUTSIDE this set, so a +-- regression that changes a currently-agreeing field (or an adapter change that +-- breaks a mapped one) is still caught. +allowedResidualLabels :: [String] +allowedResidualLabels = + [ -- (1) adapter gap: Byron supported-protocol-version is hard-coded 1/0/0 by + -- the adapter, whereas the fixture sets LastKnownBlockVersion-Major = 3. + "Byron protocol config" + -- (2) representation: "MempoolCapacityBytesOverride: NoOverride" is an + -- explicit no-override value for POM but simply absent for cardano-config. + , "MaybeMempoolCapacityOverride" + -- (3) default mismatch: the fixture leaves these unset; POM defaults to + -- Nothing (no limit) while cardano-config supplies its own default of 1. + , "MaxConcurrencyBulkSync" + , "MaxConcurrencyDeadline" + -- (2)/(3): cardano-config ships a QueryBatchSize where the node has none, + -- and it states the snapshot interval as the explicit 86400 slots where the + -- node leaves it at DefaultSnapshotInterval, which is the same 40*k slots + -- named rather than spelled out. The rest of the snapshot policy agrees. + , "LedgerDbConfig" + -- (3) default mismatch: the fixture leaves ChainSyncIdleTimeout unset. POM + -- treats that as "no override" and lets the diffusion layer pick, while + -- cardano-config states the same value (3373s) as a default, so the node + -- sees it as an override. + , "ChainSyncIdleTimeout" + ] + +main :: IO () +main = defaultMain tests + +tests :: TestTree +tests = testGroup "cardano-config configuration dialects" + [ testGroup "deprecated CLI flag guidance" + [ testCase "deprecated CLI aliases yield migration guidance" testDeprecatedAliases + , testCase "removed mempool flags yield removal guidance" testRemovedMempoolFlags + , testCase "no guidance for accepted / unrelated flags" testNoFalsePositives + ] + , testGroup "legacy dialect (both parsers)" + [ testCase "the fixture is classified as legacy" testLegacyClassification + , testCase "the two parsers diverge only on the documented residuals" + testLegacyDualParse + ] + , testGroup "cardano-config envelope dialect (cardano-config only)" + [ testCase "the migrated fixture is classified as an envelope" + testEnvelopeClassification + , testCase "the node's own parser cannot resolve an envelope" testEnvelopeDefeatsPom + , testCase "cardano-config resolves an envelope to the same configuration" + testEnvelopeResolvesToSameConfiguration + ] + ] + +testDeprecatedAliases :: Assertion +testDeprecatedAliases = do + let warnings = + deprecatedFlagWarnings + ["--delegation-certificate", "x", "--signing-key", "y", "--non-producing-node"] + suggests new = any (new `isInfixOf`) warnings + assertBool "suggests --byron-delegation-certificate" (suggests "--byron-delegation-certificate") + assertBool "suggests --byron-signing-key" (suggests "--byron-signing-key") + assertBool "suggests --start-as-non-producing-node" (suggests "--start-as-non-producing-node") + length warnings @?= 3 + +testRemovedMempoolFlags :: Assertion +testRemovedMempoolFlags = do + let warnings = deprecatedFlagWarnings ["--mempool-capacity-override", "100"] + length warnings @?= 1 + assertBool "says no longer supported" + (any ("no longer supported" `isInfixOf`) warnings) + assertBool "points to MempoolCapacityBytesOverride in the config file" + (any ("MempoolCapacityBytesOverride" `isInfixOf`) warnings) + +testNoFalsePositives :: Assertion +testNoFalsePositives = + deprecatedFlagWarnings ["--config", "c.json", "--topology", "t.json", "--database-path", "db"] + @?= [] + +testLegacyClassification :: Assertion +testLegacyClassification = + legacyConfigPath >>= classifyConfigurationFile >>= (@?= LegacyDialect) + +-- | Resolve the fixture both ways and check that the divergences stay inside the +-- documented residual set. +testLegacyDualParse :: Assertion +testLegacyDualParse = do + configPath <- legacyConfigPath + adapted <- resolveWithCardanoConfig configPath + pomNc <- resolveWithPom configPath adapted + + let divergences = compareConfigurations pomNc adapted + isAllowed d = any (`isPrefixOf` d) allowedResidualLabels + unexpected = filter (not . isAllowed) divergences + + -- Print what the comparison reports on this real config, so the run is legible + -- even when it passes. + putStrLn $ " compareConfigurations reported " <> show (length divergences) + <> " divergence(s) on the fixture:" + mapM_ (putStrLn . (" - " <>)) divergences + + assertBool + ("divergences outside the documented residual set: " <> show unexpected) + (null unexpected) + +testEnvelopeClassification :: Assertion +testEnvelopeClassification = + envelopeConfigPath >>= classifyConfigurationFile >>= (@?= CardanoConfigDialect) + +-- | The reason the node does not run the dual parse on an envelope: POM cannot +-- read it. Every setting lives nested under @Configuration@, so POM sees a +-- document with none of the settings it requires. It may fail either while +-- decoding the file (its decoder throws on a missing required key) or in +-- 'makeNodeConfiguration'; only that it fails matters here. +testEnvelopeDefeatsPom :: Assertion +testEnvelopeDefeatsPom = do + envelope <- envelopeConfigPath + outcome <- try $ do + filePartial <- parseNodeConfigurationFP (Just (ConfigYamlFilePath envelope)) + evaluate (makeNodeConfiguration (defaultPartialNodeConfiguration <> filePartial)) + case outcome of + Left (_ :: SomeException) -> pure () + Right (Left _) -> pure () + Right (Right _) -> + assertFailure + "the node's own parser resolved an envelope configuration; the dual-parse\ + \ dispatch in CardanoConfigResolve assumes it cannot" + +-- | The envelope is a reshaping, not a change of meaning: resolving it must give +-- exactly what resolving the legacy form it was migrated from gives. +testEnvelopeResolvesToSameConfiguration :: Assertion +testEnvelopeResolvesToSameConfiguration = do + fromLegacy <- resolveWithCardanoConfig =<< legacyConfigPath + fromEnvelope <- resolveWithCardanoConfig =<< envelopeConfigPath + let divergences = compareConfigurations fromLegacy fromEnvelope + assertBool + ("the envelope resolved differently from the legacy form it was migrated from: " + <> show divergences) + (null divergences) + +-- | Resolve a configuration file with cardano-config (file only, no CLI layer) +-- and adapt it to the node's own 'NodeConfiguration'. +resolveWithCardanoConfig :: FilePath -> IO NodeConfiguration +resolveWithCardanoConfig fp = do + resolved <- Cfg.resolveConfigurationFromFile fp + (cfgNc, _warns) <- + either (assertFailure . ("cardano-config resolve failed: " <>) . show) pure resolved + either (assertFailure . ("adapter failed: " <>)) pure + (cardanoConfigToNodeConfiguration cfgNc) + +-- | Resolve a configuration file with the node's own POM parser. +-- +-- The CLI-only fields (topology / database / protocol files / socket) are not in +-- the file; mirror them from the given cardano-config result so the comparison +-- isolates the file-parse and adapter-gap differences rather than CLI-supplied +-- noise. +resolveWithPom :: FilePath -> NodeConfiguration -> IO NodeConfiguration +resolveWithPom fp adapted = do + fileYaml <- parseNodeConfigurationFP (Just (ConfigYamlFilePath fp)) + -- 'PartialNodeConfiguration' is a Semigroup but not a Monoid, so there is no + -- empty value to start from: merge defaults with the file layer (mirroring + -- 'buildNodeConfiguration'), then override the CLI-only fields on top. + let withCli = + (defaultPartialNodeConfiguration <> fileYaml) + { pncConfigFile = Last (Just (ConfigYamlFilePath fp)) + , pncTopologyFile = Last (Just (ncTopologyFile adapted)) + , pncDatabaseFile = Last (Just (ncDatabaseFile adapted)) + , pncProtocolFiles = Last (Just (ncProtocolFiles adapted)) + , pncSocketConfig = Last (Just (ncSocketConfig adapted)) + } + either (assertFailure . ("POM makeNodeConfiguration failed: " <>)) pure + (makeNodeConfiguration withCli) diff --git a/cardano-node/test/cardano-config-compare/config/alonzo-genesis.json b/cardano-node/test/cardano-config-compare/config/alonzo-genesis.json new file mode 100644 index 00000000000..093071bb398 --- /dev/null +++ b/cardano-node/test/cardano-config-compare/config/alonzo-genesis.json @@ -0,0 +1,194 @@ +{ + "lovelacePerUTxOWord": 34482, + "executionPrices": { + "prSteps": { + "numerator": 721, + "denominator": 10000000 + }, + "prMem": { + "numerator": 577, + "denominator": 10000 + } + }, + "maxTxExUnits": { + "exUnitsMem": 14000000, + "exUnitsSteps": 10000000000 + }, + "maxBlockExUnits": { + "exUnitsMem": 56000000, + "exUnitsSteps": 40000000000 + }, + "maxValueSize": 5000, + "collateralPercentage": 150, + "maxCollateralInputs": 3, + "costModels": { + "PlutusV1": { + "sha2_256-memory-arguments": 4, + "equalsString-cpu-arguments-constant": 1000, + "cekDelayCost-exBudgetMemory": 100, + "lessThanEqualsByteString-cpu-arguments-intercept": 103599, + "divideInteger-memory-arguments-minimum": 1, + "appendByteString-cpu-arguments-slope": 621, + "blake2b-cpu-arguments-slope": 29175, + "iData-cpu-arguments": 150000, + "encodeUtf8-cpu-arguments-slope": 1000, + "unBData-cpu-arguments": 150000, + "multiplyInteger-cpu-arguments-intercept": 61516, + "cekConstCost-exBudgetMemory": 100, + "nullList-cpu-arguments": 150000, + "equalsString-cpu-arguments-intercept": 150000, + "trace-cpu-arguments": 150000, + "mkNilData-memory-arguments": 32, + "lengthOfByteString-cpu-arguments": 150000, + "cekBuiltinCost-exBudgetCPU": 29773, + "bData-cpu-arguments": 150000, + "subtractInteger-cpu-arguments-slope": 0, + "unIData-cpu-arguments": 150000, + "consByteString-memory-arguments-intercept": 0, + "divideInteger-memory-arguments-slope": 1, + "divideInteger-cpu-arguments-model-arguments-slope": 118, + "listData-cpu-arguments": 150000, + "headList-cpu-arguments": 150000, + "chooseData-memory-arguments": 32, + "equalsInteger-cpu-arguments-intercept": 136542, + "sha3_256-cpu-arguments-slope": 82363, + "sliceByteString-cpu-arguments-slope": 5000, + "unMapData-cpu-arguments": 150000, + "lessThanInteger-cpu-arguments-intercept": 179690, + "mkCons-cpu-arguments": 150000, + "appendString-memory-arguments-intercept": 0, + "modInteger-cpu-arguments-model-arguments-slope": 118, + "ifThenElse-cpu-arguments": 1, + "mkNilPairData-cpu-arguments": 150000, + "lessThanEqualsInteger-cpu-arguments-intercept": 145276, + "addInteger-memory-arguments-slope": 1, + "chooseList-memory-arguments": 32, + "constrData-memory-arguments": 32, + "decodeUtf8-cpu-arguments-intercept": 150000, + "equalsData-memory-arguments": 1, + "subtractInteger-memory-arguments-slope": 1, + "appendByteString-memory-arguments-intercept": 0, + "lengthOfByteString-memory-arguments": 4, + "headList-memory-arguments": 32, + "listData-memory-arguments": 32, + "consByteString-cpu-arguments-intercept": 150000, + "unIData-memory-arguments": 32, + "remainderInteger-memory-arguments-minimum": 1, + "bData-memory-arguments": 32, + "lessThanByteString-cpu-arguments-slope": 248, + "encodeUtf8-memory-arguments-intercept": 0, + "cekStartupCost-exBudgetCPU": 100, + "multiplyInteger-memory-arguments-intercept": 0, + "unListData-memory-arguments": 32, + "remainderInteger-cpu-arguments-model-arguments-slope": 118, + "cekVarCost-exBudgetCPU": 29773, + "remainderInteger-memory-arguments-slope": 1, + "cekForceCost-exBudgetCPU": 29773, + "sha2_256-cpu-arguments-slope": 29175, + "equalsInteger-memory-arguments": 1, + "indexByteString-memory-arguments": 1, + "addInteger-memory-arguments-intercept": 1, + "chooseUnit-cpu-arguments": 150000, + "sndPair-cpu-arguments": 150000, + "cekLamCost-exBudgetCPU": 29773, + "fstPair-cpu-arguments": 150000, + "quotientInteger-memory-arguments-minimum": 1, + "decodeUtf8-cpu-arguments-slope": 1000, + "lessThanInteger-memory-arguments": 1, + "lessThanEqualsInteger-cpu-arguments-slope": 1366, + "fstPair-memory-arguments": 32, + "modInteger-memory-arguments-intercept": 0, + "unConstrData-cpu-arguments": 150000, + "lessThanEqualsInteger-memory-arguments": 1, + "chooseUnit-memory-arguments": 32, + "sndPair-memory-arguments": 32, + "addInteger-cpu-arguments-intercept": 197209, + "decodeUtf8-memory-arguments-slope": 8, + "equalsData-cpu-arguments-intercept": 150000, + "mapData-cpu-arguments": 150000, + "mkPairData-cpu-arguments": 150000, + "quotientInteger-cpu-arguments-constant": 148000, + "consByteString-memory-arguments-slope": 1, + "cekVarCost-exBudgetMemory": 100, + "indexByteString-cpu-arguments": 150000, + "unListData-cpu-arguments": 150000, + "equalsInteger-cpu-arguments-slope": 1326, + "cekStartupCost-exBudgetMemory": 100, + "subtractInteger-cpu-arguments-intercept": 197209, + "divideInteger-cpu-arguments-model-arguments-intercept": 425507, + "divideInteger-memory-arguments-intercept": 0, + "cekForceCost-exBudgetMemory": 100, + "blake2b-cpu-arguments-intercept": 2477736, + "remainderInteger-cpu-arguments-constant": 148000, + "tailList-cpu-arguments": 150000, + "encodeUtf8-cpu-arguments-intercept": 150000, + "equalsString-cpu-arguments-slope": 1000, + "lessThanByteString-memory-arguments": 1, + "multiplyInteger-cpu-arguments-slope": 11218, + "appendByteString-cpu-arguments-intercept": 396231, + "lessThanEqualsByteString-cpu-arguments-slope": 248, + "modInteger-memory-arguments-slope": 1, + "addInteger-cpu-arguments-slope": 0, + "equalsData-cpu-arguments-slope": 10000, + "decodeUtf8-memory-arguments-intercept": 0, + "chooseList-cpu-arguments": 150000, + "constrData-cpu-arguments": 150000, + "equalsByteString-memory-arguments": 1, + "cekApplyCost-exBudgetCPU": 29773, + "quotientInteger-memory-arguments-slope": 1, + "verifySignature-cpu-arguments-intercept": 3345831, + "unMapData-memory-arguments": 32, + "mkCons-memory-arguments": 32, + "sliceByteString-memory-arguments-slope": 1, + "sha3_256-memory-arguments": 4, + "ifThenElse-memory-arguments": 1, + "mkNilPairData-memory-arguments": 32, + "equalsByteString-cpu-arguments-slope": 247, + "appendString-cpu-arguments-intercept": 150000, + "quotientInteger-cpu-arguments-model-arguments-slope": 118, + "cekApplyCost-exBudgetMemory": 100, + "equalsString-memory-arguments": 1, + "multiplyInteger-memory-arguments-slope": 1, + "cekBuiltinCost-exBudgetMemory": 100, + "remainderInteger-memory-arguments-intercept": 0, + "sha2_256-cpu-arguments-intercept": 2477736, + "remainderInteger-cpu-arguments-model-arguments-intercept": 425507, + "lessThanEqualsByteString-memory-arguments": 1, + "tailList-memory-arguments": 32, + "mkNilData-cpu-arguments": 150000, + "chooseData-cpu-arguments": 150000, + "unBData-memory-arguments": 32, + "blake2b-memory-arguments": 4, + "iData-memory-arguments": 32, + "nullList-memory-arguments": 32, + "cekDelayCost-exBudgetCPU": 29773, + "subtractInteger-memory-arguments-intercept": 1, + "lessThanByteString-cpu-arguments-intercept": 103599, + "consByteString-cpu-arguments-slope": 1000, + "appendByteString-memory-arguments-slope": 1, + "trace-memory-arguments": 32, + "divideInteger-cpu-arguments-constant": 148000, + "cekConstCost-exBudgetCPU": 29773, + "encodeUtf8-memory-arguments-slope": 8, + "quotientInteger-cpu-arguments-model-arguments-intercept": 425507, + "mapData-memory-arguments": 32, + "appendString-cpu-arguments-slope": 1000, + "modInteger-cpu-arguments-constant": 148000, + "verifySignature-cpu-arguments-slope": 1, + "unConstrData-memory-arguments": 32, + "quotientInteger-memory-arguments-intercept": 0, + "equalsByteString-cpu-arguments-constant": 150000, + "sliceByteString-memory-arguments-intercept": 0, + "mkPairData-memory-arguments": 32, + "equalsByteString-cpu-arguments-intercept": 112536, + "appendString-memory-arguments-slope": 1, + "lessThanInteger-cpu-arguments-slope": 497, + "modInteger-cpu-arguments-model-arguments-intercept": 425507, + "modInteger-memory-arguments-minimum": 1, + "sha3_256-cpu-arguments-intercept": 0, + "verifySignature-memory-arguments": 1, + "cekLamCost-exBudgetMemory": 100, + "sliceByteString-cpu-arguments-intercept": 150000 + } + } +} diff --git a/cardano-node/test/cardano-config-compare/config/byron-genesis.json b/cardano-node/test/cardano-config-compare/config/byron-genesis.json new file mode 100644 index 00000000000..aec652492ff --- /dev/null +++ b/cardano-node/test/cardano-config-compare/config/byron-genesis.json @@ -0,0 +1,42 @@ +{ "bootStakeholders": + { "ce2950ee9b35c74336371a7393b2f1fa64d4af1831180076b106208d": 1 } +, "heavyDelegation": + { "ce2950ee9b35c74336371a7393b2f1fa64d4af1831180076b106208d": + { "omega": 0 + , "issuerPk": + "0Te/2OpdrE4IFuj6ZCSky8a/oeM9xE0phU0rQJE7v3Zg0wZop+bcZaKVe8qRk1zl0DM5vGIk5+XHZGhv7xh3rQ==" + , "delegatePk": + "ojky67+tV35+CmAFX7hkCCpPgz7EwrU8HCMDk7qEgoynuLaByN8S4ek4HjQXPq/b3vZFd08+Ip2BN/nC+e6Alg==" + , "cert": + "a8e1514662b6edd544f9e22d3bc8a961e6cfe5b1db35378188bb4fcd848e27c977952c8e73c29757b8b5b6b6c0b52254357383272c0b83e24cb91558907e8d04" + } } +, "startTime": 1655366659 +, "nonAvvmBalances": + { "2657WMsDfac5TVJguqJE11Z1tdx9HP72E9Roz32GVecUrX7oScFb1sXPzC43EnLUx": + "30000" + , "2657WMsDfac5V9qqEUfJm252BN5L81ni6CZyDS31cN7XZrAtsyqbz4yGr42bKG5B7": + "270000" + } +, "blockVersionData": + { "scriptVersion": 0 + , "slotDuration": "20000" + , "maxBlockSize": "641000" + , "maxHeaderSize": "200000" + , "maxTxSize": "4096" + , "maxProposalSize": "700" + , "mpcThd": "200000" + , "heavyDelThd": "300000" + , "updateVoteThd": "100000" + , "updateProposalThd": "100000" + , "updateImplicit": "10000" + , "softforkRule": + { "initThd": "900000" + , "minThd": "600000" + , "thdDecrement": "100000" + } + , "txFeePolicy": { "summand": "0" , "multiplier": "439460" } + , "unlockStakeEpoch": "184467" + } +, "protocolConsts": { "k": 2160 , "protocolMagic": 42 } +, "avvmDistr": {} +} \ No newline at end of file diff --git a/cardano-node/test/cardano-config-compare/config/config-envelope.json b/cardano-node/test/cardano-config-compare/config/config-envelope.json new file mode 100644 index 00000000000..eac81dd0931 --- /dev/null +++ b/cardano-node/test/cardano-config-compare/config/config-envelope.json @@ -0,0 +1,122 @@ +{ + "$schema": "https://raw.githubusercontent.com/IntersectMBO/cardano-config/v2/schemas/config.schema.json", + "Configuration": { + "HermodTracing": { + "TraceOptionNodeName": "cardano-sl", + "TraceOptions": { + "": { + "backends": [ + "Stdout MachineFormat", + "EKGBackend", + "Forwarder" + ], + "severity": "Notice" + }, + "AcceptPolicy": { + "severity": "Info" + }, + "BlockFetchClient": { + "detail": "DMinimal", + "severity": "Info" + }, + "BlockFetchClient.CompletedBlockFetch": { + "maxFrequency": 2 + }, + "BlockFetchServer": { + "severity": "Info" + }, + "ChainDB": { + "severity": "Info" + }, + "ChainDB.AddBlockEvent.AddBlockValidation.ValidCandidate": { + "maxFrequency": 2 + }, + "ChainDB.AddBlockEvent.AddedBlockToQueue": { + "maxFrequency": 2 + }, + "ChainDB.AddBlockEvent.AddedBlockToVolatileDB": { + "maxFrequency": 2 + }, + "ChainDB.CopyToImmutableDBEvent.CopiedBlockToImmutableDB": { + "maxFrequency": 2 + }, + "ChainSyncClient": { + "detail": "DMinimal", + "severity": "Info" + }, + "ChainSyncServerBlock": { + "severity": "Info" + }, + "ChainSyncServerHeader": { + "severity": "Info" + }, + "DNSResolver": { + "severity": "Info" + }, + "DNSSubscription": { + "severity": "Info" + }, + "DiffusionInit": { + "severity": "Info" + }, + "ErrorPolicy": { + "severity": "Info" + }, + "Forge": { + "severity": "Info" + }, + "IpSubscription": { + "severity": "Info" + }, + "LocalErrorPolicy": { + "severity": "Info" + }, + "Mempool": { + "severity": "Info" + }, + "Resources": { + "severity": "Info" + }, + "TxSubmission2": { + "detail": "DMinimal" + } + } + }, + "Network": { + "AcceptedConnectionsLimit": { + "Delay": 5, + "HardLimit": 512, + "SoftLimit": 384 + }, + "DeadlineTargetNumberOfActivePeers": 20, + "DeadlineTargetNumberOfEstablishedPeers": 50, + "DeadlineTargetNumberOfKnownPeers": 100, + "DeadlineTargetNumberOfRootPeers": 100, + "ExperimentalProtocolsEnabled": true, + "ProtocolIdleTimeout": 5, + "TimeWaitTimeout": 60 + }, + "Protocol": { + "AlonzoGenesisFile": "alonzo-genesis.json", + "AlonzoGenesisHash": "edb92321b614cfd7dcee3f49eedcde4f559ea9526194ff3cf42cd28a4bf0ad7b", + "ByronGenesisFile": "byron-genesis.json", + "ByronGenesisHash": "6836b5d0ae3bb7250c318e8906ab2bf8e42e6acfd4483526be948752707ad435", + "ConwayGenesisFile": "conway-genesis.json", + "ConwayGenesisHash": "e4cbda3b0a0db8ea984330d0951d280ca490540c97cc6407ecd1011b174d983d", + "RequiresNetworkMagic": "RequiresMagic", + "ShelleyGenesisFile": "shelley-genesis.json", + "ShelleyGenesisHash": "f6bb6e9d9b217681180754232470aa936716d62f8e11e944520b97490b100b7c" + }, + "Testing": { + "DijkstraGenesisFile": "dijkstra-genesis.json", + "DijkstraGenesisHash": "d939e640f5aece1b33b15345b7ae095aa2d8f93f703292e8ec1564c6b02d5f30", + "ExperimentalHardForksEnabled": true, + "TestAllegraHardForkAtEpoch": 0, + "TestAlonzoHardForkAtEpoch": 0, + "TestBabbageHardForkAtEpoch": 0, + "TestMaryHardForkAtEpoch": 0, + "TestShelleyHardForkAtEpoch": 0 + } + }, + "Version": 2 +} diff --git a/cardano-node/test/cardano-config-compare/config/config.json b/cardano-node/test/cardano-config-compare/config/config.json new file mode 100644 index 00000000000..5ae836de3ad --- /dev/null +++ b/cardano-node/test/cardano-config-compare/config/config.json @@ -0,0 +1,121 @@ +{ + "AcceptedConnectionsLimit": { + "delay": 5, + "hardLimit": 512, + "softLimit": 384 + }, + "AlonzoGenesisFile": "alonzo-genesis.json", + "AlonzoGenesisHash": "edb92321b614cfd7dcee3f49eedcde4f559ea9526194ff3cf42cd28a4bf0ad7b", + "ApplicationName": "cardano-sl", + "ApplicationVersion": 0, + "ByronGenesisFile": "byron-genesis.json", + "ByronGenesisHash": "6836b5d0ae3bb7250c318e8906ab2bf8e42e6acfd4483526be948752707ad435", + "ConwayGenesisFile": "conway-genesis.json", + "ConwayGenesisHash": "e4cbda3b0a0db8ea984330d0951d280ca490540c97cc6407ecd1011b174d983d", + "DijkstraGenesisFile": "dijkstra-genesis.json", + "DijkstraGenesisHash": "d939e640f5aece1b33b15345b7ae095aa2d8f93f703292e8ec1564c6b02d5f30", + "EnableP2P": false, + "LastKnownBlockVersion-Alt": 0, + "LastKnownBlockVersion-Major": 3, + "LastKnownBlockVersion-Minor": 0, + "MaxKnownMajorProtocolVersion": 2, + "MempoolCapacityBytesOverride": "NoOverride", + "Protocol": "Cardano", + "ProtocolIdleTimeout": 5, + "RequiresNetworkMagic": "RequiresMagic", + "ShelleyGenesisFile": "shelley-genesis.json", + "ShelleyGenesisHash": "f6bb6e9d9b217681180754232470aa936716d62f8e11e944520b97490b100b7c", + "TargetNumberOfActivePeers": 20, + "TargetNumberOfEstablishedPeers": 50, + "TargetNumberOfKnownPeers": 100, + "TargetNumberOfRootPeers": 100, + "TestAllegraHardForkAtEpoch": 0, + "TestAlonzoHardForkAtEpoch": 0, + "TestBabbageHardForkAtEpoch": 0, + "ExperimentalHardForksEnabled": true, + "ExperimentalProtocolsEnabled": true, + "TestMaryHardForkAtEpoch": 0, + "TestShelleyHardForkAtEpoch": 0, + "TimeWaitTimeout": 60, + "TraceOptions": { + "": { + "backends": [ + "Stdout MachineFormat", + "EKGBackend", + "Forwarder" + ], + "severity": "Notice" + }, + "AcceptPolicy": { + "severity": "Info" + }, + "BlockFetchClient": { + "detail": "DMinimal", + "severity": "Info" + }, + "BlockFetchClient.CompletedBlockFetch": { + "maxFrequency": 2 + }, + "BlockFetchServer": { + "severity": "Info" + }, + "ChainDB": { + "severity": "Info" + }, + "ChainDB.AddBlockEvent.AddBlockValidation.ValidCandidate": { + "maxFrequency": 2 + }, + "ChainDB.AddBlockEvent.AddedBlockToQueue": { + "maxFrequency": 2 + }, + "ChainDB.AddBlockEvent.AddedBlockToVolatileDB": { + "maxFrequency": 2 + }, + "ChainDB.CopyToImmutableDBEvent.CopiedBlockToImmutableDB": { + "maxFrequency": 2 + }, + "ChainSyncClient": { + "detail": "DMinimal", + "severity": "Info" + }, + "ChainSyncServerBlock": { + "severity": "Info" + }, + "ChainSyncServerHeader": { + "severity": "Info" + }, + "DNSResolver": { + "severity": "Info" + }, + "DNSSubscription": { + "severity": "Info" + }, + "DiffusionInit": { + "severity": "Info" + }, + "ErrorPolicy": { + "severity": "Info" + }, + "Forge": { + "severity": "Info" + }, + "IpSubscription": { + "severity": "Info" + }, + "LocalErrorPolicy": { + "severity": "Info" + }, + "Mempool": { + "severity": "Info" + }, + "Resources": { + "severity": "Info" + }, + "TxSubmission2": { + "detail": "DMinimal" + } + }, + "TurnOnLogMetrics": true, + "TurnOnLogging": true, + "UseTraceDispatcher": true +} diff --git a/cardano-node/test/cardano-config-compare/config/conway-genesis.json b/cardano-node/test/cardano-config-compare/config/conway-genesis.json new file mode 100644 index 00000000000..08e1aed42a3 --- /dev/null +++ b/cardano-node/test/cardano-config-compare/config/conway-genesis.json @@ -0,0 +1,77 @@ +{ + "poolVotingThresholds": { + "committeeNormal": 0, + "committeeNoConfidence": 0, + "hardForkInitiation": 0, + "motionNoConfidence": 0, + "ppSecurityGroup": 0 + }, + "dRepVotingThresholds": { + "motionNoConfidence": 0, + "committeeNormal": 0, + "committeeNoConfidence": 0, + "updateToConstitution": 0, + "hardForkInitiation": 0, + "ppNetworkGroup": 0, + "ppEconomicGroup": 0, + "ppTechnicalGroup": 0, + "ppGovGroup": 0, + "treasuryWithdrawal": 0 + }, + "committeeMinSize": 0, + "committeeMaxTermLength": 0, + "govActionLifetime": 0, + "govActionDeposit": 0, + "dRepDeposit": 0, + "dRepActivity": 0, + "minFeeRefScriptCostPerByte": 0, + "plutusV3CostModel": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "constitution": { + "anchor": { + "url": "", + "dataHash": "0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "committee": { + "members": { + "keyHash-4e88cc2d27c364aaf90648a87dfb95f8ee103ba67fa1f12f5e86c42a": 1, + "scriptHash-4e88cc2d27c364aaf90648a87dfb95f8ee103ba67fa1f12f5e86c42a": 2 + }, + "threshold": 0.5 + }, + "delegs": { + "keyHash-4e88cc2d27c364aaf90648a87dfb95f8ee103ba67fa1f12f5e86c42a": { + "dRep": "drep-alwaysAbstain" + }, + "keyHash-35bc5e86c42afbc593ab4cdd78301005df84ba67fa1f12f95f8ee103": { + "dRep": "drep-alwaysNoConfidence" + }, + "scriptHash-afbc5005df84ba5f8ee93ab435bc5e83067fa1f12f9c42cdd7110386": { + "dRep": "drep-keyHash-78301005df84ba67fa1f12f95f8ee10335bc5e86c42afbc593ab4cdd" + }, + "keyHash-df93ab435bc5eafbc500583067fa1f12f9110386c42cdd784ba5f8ee": { + "dRep": "drep-scriptHash-01305df84b078ac5e86c42afbc593ab4cdd67fa1f12f95f8ee10335b" + }, + "keyHash-5df84bcdd7a5f8ee93aafbc500b435bc5e83067fa1f12f9110386c42": { + "poolId": "0335bc5e86c42afbc578301005df84ba67fa1f12f95f8ee193ab4cdd" + }, + "keyHash-8ee93a5df84bc42cdd7a5fafbc500b435bc5e83067fa1f12f9110386": { + "poolId": "086c42afbc578301005df84ba67fa1f12f95f8ee193ab4cdd335bc5e", + "dRep": "drep-alwaysAbstain" + } + }, + "initialDReps": { + "keyHash-78301005df84ba67fa1f12f95f8ee10335bc5e86c42afbc593ab4cdd": { + "expiry": 1000, + "deposit": 5000 + }, + "scriptHash-01305df84b078ac5e86c42afbc593ab4cdd67fa1f12f95f8ee10335b": { + "expiry": 300, + "deposit": 6000, + "anchor": { + "url": "example.com", + "dataHash": "0000000000000000000000000000000000000000000000000000000000000000" + } + } + } +} diff --git a/cardano-node/test/cardano-config-compare/config/dijkstra-genesis.json b/cardano-node/test/cardano-config-compare/config/dijkstra-genesis.json new file mode 100644 index 00000000000..713a22b1a12 --- /dev/null +++ b/cardano-node/test/cardano-config-compare/config/dijkstra-genesis.json @@ -0,0 +1,28 @@ +{ + "maxRefScriptSizePerBlock": 1048576, + "maxRefScriptSizePerTx": 204800, + "refScriptCostStride": 25600, + "refScriptCostMultiplier": 1.2, + "minPoolMargin": 0.015, + "plutusV4CostModel": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "leiosAnnouncementPeriodLength": 1000, + "leiosVotePeriodLength": 4000, + "leiosDiffusionPeriodLength": 7000, + "leiosCommitteeSize": 900, + "leiosQuorumStakeThreshold": 0.75, + "maxEndorserBlockReferencesSize": 524288, + "maxEndorserBlockTxsSize": 12582912, + "maxEndorserBlockExecutionUnits": { + "memory": 7000000000, + "steps": 2000000000000 + }, + "maxRefScriptSizePerEndorserBlock": 12582912, + "perasMinCandidateBlockAge": 90, + "perasHealingFactor": 0.5, + "perasCertBoost": 15, + "perasTargetCommitteeSize": 800, + "perasBootstrapRound": 0, + "perasQuorumThresholdSafetyMargin": 0.05, + "refInputsCostPerMultiAssetPolicy": 0, + "refInputsCostPerDatumByte": 0 +} diff --git a/cardano-node/test/cardano-config-compare/config/shelley-genesis.json b/cardano-node/test/cardano-config-compare/config/shelley-genesis.json new file mode 100644 index 00000000000..7755bcd2242 --- /dev/null +++ b/cardano-node/test/cardano-config-compare/config/shelley-genesis.json @@ -0,0 +1,83 @@ +{ + "activeSlotsCoeff": 0.05, + "epochLength": 432000, + "genDelegs": {}, + "initialFunds": { + "0032635dc627da054f2a9e99559c56e16b02cf5f9237ba586ee1e648336b47a4e6e19ac5257fc97bd220bd9ae368aa2d775d86315ab7ef058f": 999500000000000, + "0064f4987ff07483636803f71f5f8442dad7f7fc46d83e2242d1548ad5d1f6f71a04ca856cc569fd068b069a555999c4776ad50b4cdd049d13": 999500000000000, + "602b43cb2b891e2dc9f5b07e051fb8d221a4a88ca161d95e859aa9ad8a": 9000000000000 + }, + "maxKESEvolutions": 60, + "maxLovelaceSupply": 2010000000000000, + "networkId": "Testnet", + "networkMagic": 42, + "protocolParams": { + "a0": 0.3, + "decentralisationParam": 0, + "eMax": 18, + "extraEntropy": { + "tag": "NeutralNonce" + }, + "keyDeposit": 400000, + "maxBlockBodySize": 81920, + "maxBlockHeaderSize": 1100, + "maxTxSize": 16384, + "minFeeA": 0, + "minFeeB": 0, + "minPoolCost": 0, + "minUTxOValue": 0, + "nOpt": 50, + "poolDeposit": 500000000, + "protocolVersion": { + "major": 5, + "minor": 0 + }, + "rho": 0.0022, + "tau": 0.05 + }, + "securityParam": 2160, + "slotLength": 1, + "slotsPerKESPeriod": 129600, + "staking": { + "pools": { + "1dc0a846ec816bdcc5288c0b57871a0400e86728ad0851132e43883f": { + "cost": 0, + "margin": 0, + "metadata": null, + "owners": [], + "pledge": 0, + "publicKey": "1dc0a846ec816bdcc5288c0b57871a0400e86728ad0851132e43883f", + "relays": [], + "rewardAccount": { + "credential": { + "key hash": "22c700325ec932f59048a7258e89b5f166604f184e0809d16a495550" + }, + "network": "Testnet" + }, + "vrf": "ee8fdadab21abed48fadee52492596841c561640920d1c022fa8ae51d206c714" + }, + "d3e16257b8c608ec4b2cb89621d7ddb60fc08839c1b491a598615fb5": { + "cost": 0, + "margin": 0, + "metadata": null, + "owners": [], + "pledge": 0, + "publicKey": "d3e16257b8c608ec4b2cb89621d7ddb60fc08839c1b491a598615fb5", + "relays": [], + "rewardAccount": { + "credential": { + "key hash": "3832f1051268ab7a7765142f21d695b7aaf40c576bf2d1a71894f0a4" + }, + "network": "Testnet" + }, + "vrf": "bbc57641002e501cf8bf98b776ba082c604e6af7c482f716934ed08d19c22733" + } + }, + "stake": { + "6b47a4e6e19ac5257fc97bd220bd9ae368aa2d775d86315ab7ef058f": "d3e16257b8c608ec4b2cb89621d7ddb60fc08839c1b491a598615fb5", + "d1f6f71a04ca856cc569fd068b069a555999c4776ad50b4cdd049d13": "1dc0a846ec816bdcc5288c0b57871a0400e86728ad0851132e43883f" + } + }, + "systemStart": "2022-06-16T08:04:19Z", + "updateQuorum": 5 +} From c8467a3a11f5b010f7d69defb10a579dee67fc93 Mon Sep 17 00:00:00 2001 From: Javier Sagredo Date: Mon, 5 Oct 2026 17:45:50 +0200 Subject: [PATCH 04/45] Don't compare Byron Version --- .../Configuration/CardanoConfigAdapter.hs | 6 ++-- .../Configuration/CardanoConfigCompare.hs | 28 +++++++++++++++++-- .../test/cardano-config-compare/Main.hs | 11 ++++---- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs index 58c976803c5..1b29474f917 100644 --- a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs +++ b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs @@ -372,8 +372,10 @@ nodeProtocolConfigurationFromCardanoConfig cfg = -- the Byron software (block) version: @PBftSignatureThreshold@ and the -- @LastKnownBlockVersion-*@ trio are among the keys @migrate@ drops, as -- they now come from consensus defaults rather than configuration. Fixed - -- defaults are used here, which surface as a divergence against POM for - -- any configuration that still sets them (see 'adapterGaps'). + -- defaults are used here (see 'adapterGaps'). A different + -- @PBftSignatureThreshold@ surfaces as a divergence against POM; the + -- version trio does not, as the comparison leaves it out (see + -- 'Cardano.Node.Configuration.CardanoConfigCompare.compareProtocol'). npcByronPbftSignatureThresh = Nothing , npcByronSupportedProtocolVersionMajor = 1 , npcByronSupportedProtocolVersionMinor = 0 diff --git a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs index 9e6010087b0..14898a3b309 100644 --- a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs +++ b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs @@ -6,14 +6,17 @@ -- difference in the resolved value, with no representation mismatch and no -- deferred set. A field the adapter cannot yet populate from cardano-config keeps -- the node default and therefore surfaces here as a divergence (see --- 'Cardano.Node.Configuration.CardanoConfigAdapter.adapterGaps'). +-- 'Cardano.Node.Configuration.CardanoConfigAdapter.adapterGaps'), with one +-- exception: the Byron supported-protocol-version trio, which is excluded from +-- the comparison (see 'ignoreByronSupportedVersion'). module Cardano.Node.Configuration.CardanoConfigCompare ( compareConfigurations , deprecatedFlagWarnings ) where import Cardano.Node.Configuration.POM (NodeConfiguration (..)) -import Cardano.Node.Types (NodeProtocolConfiguration (..)) +import Cardano.Node.Types (NodeByronProtocolConfiguration (..), + NodeProtocolConfiguration (..)) -- | Diagnose node CLI flags that cardano-config's own CLI parser rejects, in -- terms the operator can act on. All of these flags are deprecated: the three @@ -116,7 +119,8 @@ compareProtocol (NodeProtocolConfigurationCardano b1 s1 a1 c1 d1 h1 k1) (NodeProtocolConfigurationCardano b2 s2 a2 c2 d2 h2 k2) = concat - [ cmpValues "Byron protocol config" b1 b2 + [ cmpValues "Byron protocol config" + (ignoreByronSupportedVersion b1) (ignoreByronSupportedVersion b2) , cmpValues "Shelley protocol config" s1 s2 , cmpValues "Alonzo protocol config" a1 a2 , cmpValues "Conway protocol config" c1 c2 @@ -124,3 +128,21 @@ compareProtocol , cmpValues "HardFork protocol config" h1 h2 , cmpValues "Checkpoints protocol config" k1 k2 ] + +-- | Blank the Byron supported-protocol-version trio, so that it takes no part in +-- the Byron comparison. +-- +-- cardano-config does not model the @LastKnownBlockVersion-*@ keys at all (its +-- @migrate@ drops them), so the adapter supplies a fixed value and the two sides +-- differ for every configuration that sets a different one. The value is the +-- version the node endorses in the Byron era's update mechanism, which no +-- Cardano chain past the Byron era still runs, so the difference tells the +-- operator nothing to act on and is not worth reporting. +ignoreByronSupportedVersion :: + NodeByronProtocolConfiguration -> NodeByronProtocolConfiguration +ignoreByronSupportedVersion byronConfig = + byronConfig + { npcByronSupportedProtocolVersionMajor = 0 + , npcByronSupportedProtocolVersionMinor = 0 + , npcByronSupportedProtocolVersionAlt = 0 + } diff --git a/cardano-node/test/cardano-config-compare/Main.hs b/cardano-node/test/cardano-config-compare/Main.hs index 12e7d531479..99c36d8ca85 100644 --- a/cardano-node/test/cardano-config-compare/Main.hs +++ b/cardano-node/test/cardano-config-compare/Main.hs @@ -74,7 +74,9 @@ envelopeConfigPath = ( "config-envelope.json") <$> fixtureDir -- cardano-config resolved; the check exists precisely to surface these: -- -- (1) adapter gaps — a field the adapter cannot populate from cardano-config --- (see 'Cardano.Node.Configuration.CardanoConfigAdapter.adapterGaps'); +-- (see 'Cardano.Node.Configuration.CardanoConfigAdapter.adapterGaps'); no +-- gap reaches this fixture, since the one the Byron configuration still +-- has (the supported-protocol-version trio) is left out of the comparison; -- (2) representation differences — same meaning, different shape; -- (3) parser default mismatches — a field the fixture does not set (or sets -- under a key one parser ignores), for which the two parsers fall back to @@ -85,12 +87,9 @@ envelopeConfigPath = ( "config-envelope.json") <$> fixtureDir -- breaks a mapped one) is still caught. allowedResidualLabels :: [String] allowedResidualLabels = - [ -- (1) adapter gap: Byron supported-protocol-version is hard-coded 1/0/0 by - -- the adapter, whereas the fixture sets LastKnownBlockVersion-Major = 3. - "Byron protocol config" - -- (2) representation: "MempoolCapacityBytesOverride: NoOverride" is an + [ -- (2) representation: "MempoolCapacityBytesOverride: NoOverride" is an -- explicit no-override value for POM but simply absent for cardano-config. - , "MaybeMempoolCapacityOverride" + "MaybeMempoolCapacityOverride" -- (3) default mismatch: the fixture leaves these unset; POM defaults to -- Nothing (no limit) while cardano-config supplies its own default of 1. , "MaxConcurrencyBulkSync" From cc72edd8312436199ca6b2df1f80f57e2a8ea410 Mon Sep 17 00:00:00 2001 From: Javier Sagredo Date: Mon, 5 Oct 2026 17:53:06 +0200 Subject: [PATCH 05/45] Compare the POM parser to cardano-config in the resolve command too --- cardano-node/app/cardano-node.hs | 40 ++++----- .../Configuration/CardanoConfigResolve.hs | 69 +++++++++++++++- .../test/cardano-config-compare/Main.hs | 81 +++++++++++++------ 3 files changed, 142 insertions(+), 48 deletions(-) diff --git a/cardano-node/app/cardano-node.hs b/cardano-node/app/cardano-node.hs index 911dce5185f..2815ec35098 100644 --- a/cardano-node/app/cardano-node.hs +++ b/cardano-node/app/cardano-node.hs @@ -15,10 +15,11 @@ import Cardano.Node.Configuration.CardanoConfigAdapter import Cardano.Node.Configuration.CardanoConfigCompare (compareConfigurations) import Cardano.Node.Configuration.CardanoConfigResolve - (ConfigurationDialect (..), classifyConfigurationFile) -import Cardano.Node.Configuration.POM (NodeConfiguration (..), - PartialNodeConfiguration (..), defaultPartialNodeConfiguration, - makeNodeConfiguration, parseNodeConfigurationFP) + (ConfigurationDialect (..), classifyConfigurationFile, + nodeCliPartialConfiguration) +import Cardano.Node.Configuration.POM (PartialNodeConfiguration (..), + defaultPartialNodeConfiguration, makeNodeConfiguration, + parseNodeConfigurationFP) import Cardano.Node.Handlers.TopLevel import Cardano.Node.Parsers (nodeCLIParser) import Cardano.Node.Run (runNode) @@ -207,11 +208,15 @@ runDualResolve resolveOpts = do configFp = CliArgs.configFilePath cli -- | Resolve a legacy configuration file (+ CLI) both ways and return the --- divergences. The node (POM) side takes its CLI-supplied, file-absent fields --- (topology / database / protocol files / socket) from the shared cardano-config --- resolution, so the diff reflects how the two parsers read the configuration --- FILE (plus the documented adapter gaps) rather than an independent — and --- necessarily asymmetric — CLI reverse-mapping. +-- divergences. +-- +-- Both sides are built from the same two inputs, each by its own parser: the +-- configuration file, and the flags this command was given. The node side is +-- assembled exactly as @cardano-node run@ assembles it (node defaults, then the +-- file, then the node's own command-line layer, see +-- 'nodeCliPartialConfiguration'), so what @resolve@ reports is what a node +-- started with these flags reports at startup — the database path and the +-- shutdown configuration included. resolveDiscrepancies :: Cfg.CliArgs -> IO [String] resolveDiscrepancies cli = do (fileCfg, _warns) <- Cfg.parseConfigurationFiles configFp @@ -223,16 +228,11 @@ resolveDiscrepancies cli = do Left adaptErr -> pure ["cardano-config configuration could not be adapted: " <> adaptErr] Right adaptedNc -> do filePartial <- parseNodeConfigurationFP (Just (ConfigYamlFilePath configFp)) - let withCli = - (defaultPartialNodeConfiguration <> filePartial) - { pncConfigFile = Last (Just (ConfigYamlFilePath configFp)) - , pncTopologyFile = Last (Just (ncTopologyFile adaptedNc)) - , pncDatabaseFile = Last (Just (ncDatabaseFile adaptedNc)) - , pncProtocolFiles = Last (Just (ncProtocolFiles adaptedNc)) - , pncSocketConfig = Last (Just (ncSocketConfig adaptedNc)) - } - case makeNodeConfiguration withCli of - Left err -> pure ["node parser (makeNodeConfiguration) failed: " <> err] - Right pomNc -> pure (compareConfigurations pomNc adaptedNc) + (mCliPartial, cliReport) <- nodeCliPartialConfiguration configFp + let fileLayer = defaultPartialNodeConfiguration <> filePartial + pom = maybe fileLayer (fileLayer <>) mCliPartial + case makeNodeConfiguration pom of + Left err -> pure (cliReport <> ["node parser (makeNodeConfiguration) failed: " <> err]) + Right pomNc -> pure (cliReport <> compareConfigurations pomNc adaptedNc) where configFp = CliArgs.configFilePath cli diff --git a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs index ebf365336d3..4662bb84844 100644 --- a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs +++ b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs @@ -36,6 +36,11 @@ module Cardano.Node.Configuration.CardanoConfigResolve -- * Dialects , ConfigurationDialect (..) , classifyConfigurationFile + + -- * Command-line layers + , nodeCliPartialConfiguration + , nodeCliLayer + , cardanoConfigCliLayer ) where import Cardano.Logging.Types (TraceConfig) @@ -48,6 +53,7 @@ import Cardano.Node.Configuration.CardanoConfigCompare import Cardano.Node.Configuration.POM (NodeConfiguration (..), PartialNodeConfiguration (..), defaultPartialNodeConfiguration, makeNodeConfiguration, parseNodeConfigurationFP) +import Cardano.Node.Parsers (nodeCLIParser) import Cardano.Node.Types (ConfigYamlFilePath (..)) import Control.Exception (Exception (..)) @@ -243,11 +249,66 @@ crossCheckWithCardanoConfig configFp nc = do -- dropped to get the flag list; @cardano-config@'s 'Cfg.parseCliArgs' is a flat -- parser with no @run@ subcommand, matching that stripped list. On failure the -- returned message leads with actionable guidance for each offending flag. +-- | The node's own command-line layer for the configuration being resolved: the +-- flags this process was given, parsed with the node's own run parser. +-- +-- This is the POM twin of 'cardanoConfigCliArgs': the two read the SAME flags, +-- each with its own parser, which is what makes a comparison of the two resolved +-- configurations a comparison of the parsers rather than of their inputs. +nodeCliPartialConfiguration :: FilePath -> IO (Maybe PartialNodeConfiguration, [String]) +nodeCliPartialConfiguration configFp = nodeCliLayer configFp . nodeFlags <$> getArgs + where + -- Drop the leading verbs (@config resolve@, @run@) and the flags that belong to + -- the command itself rather than to the node: @--with-geneses@ tells + -- @config resolve@ how much of the result to print. + nodeFlags argv = + filter (`notElem` ["--with-geneses"]) (dropWhile (not . isPrefixOf "-") argv) + +-- | The node's command-line layer for a given flag list, as 'nodeRunParser' reads +-- it. Pure, so a caller that is not the node's own process (a test, say) can ask +-- for the layer of a stated command line. +-- +-- An empty flag list is not the same as no layer: the node's parser supplies CLI +-- defaults of its own, and an absent @--shutdown-on-slot-synced@ resolves to +-- 'Cardano.Node.Handlers.Shutdown.NoShutdown' rather than to "unset". +-- +-- Returns the layer together with any line to report. A flag the node's parser +-- rejects is not fatal: the layer falls back to the flagless one and the +-- rejection is reported, so the rest is still compared. 'Nothing' means there is +-- no layer to apply at all, which the caller reports and continues without. +nodeCliLayer :: FilePath -> [String] -> (Maybe PartialNodeConfiguration, [String]) +nodeCliLayer configFp flags = + case parseWith flags of + Right pnc -> (Just pnc, []) + Left err -> + ( either (const Nothing) Just (parseWith []) + , [ "the node's own parser rejected the command line; its command-line layer" + <> " falls back to the flagless one. " <> err + ] + ) + where + parseWith fs = + case Opt.execParserPure Opt.defaultPrefs (Opt.info nodeCLIParser mempty) ("run" : fs) of + Opt.Success pnc -> Right (onConfigFile pnc) + Opt.CompletionInvoked _ -> Left "command-line completion was invoked" + Opt.Failure failure -> + let (msg, _exitCode) = Opt.renderFailure failure "cardano-node" + in Left msg + + -- Pin the file being resolved, for the same reason 'cardanoConfigCliArgs' does. + onConfigFile pnc = pnc{pncConfigFile = Last (Just (ConfigYamlFilePath configFp))} + cardanoConfigCliArgs :: FilePath -> IO (Either String Cfg.CliArgs) -cardanoConfigCliArgs configFp = do - argv <- getArgs - let flags = dropWhile (not . ("-" `isPrefixOf`)) argv - pure $ case Opt.execParserPure Opt.defaultPrefs (Opt.info Cfg.parseCliArgs mempty) flags of +cardanoConfigCliArgs configFp = + cardanoConfigCliLayer configFp . dropWhile (not . isPrefixOf "-") <$> getArgs + +-- | cardano-config's command-line layer for a given flag list, as its own parser +-- reads it. The twin of 'nodeCliLayer', and pure for the same reason: a caller +-- that is not the node's own process can ask for the layer of a stated command +-- line, and the two parsers can then be given the same one. +cardanoConfigCliLayer :: FilePath -> [String] -> Either String Cfg.CliArgs +cardanoConfigCliLayer configFp flags = + case Opt.execParserPure Opt.defaultPrefs (Opt.info Cfg.parseCliArgs mempty) flags of Opt.Success cli -> Right (onConfigFile cli) Opt.CompletionInvoked _ -> Right (Cfg.defaultCliArgs configFp) Opt.Failure failure -> diff --git a/cardano-node/test/cardano-config-compare/Main.hs b/cardano-node/test/cardano-config-compare/Main.hs index 99c36d8ca85..24cc303451d 100644 --- a/cardano-node/test/cardano-config-compare/Main.hs +++ b/cardano-node/test/cardano-config-compare/Main.hs @@ -22,7 +22,6 @@ module Main (main) where import Control.Exception (SomeException, evaluate, try) import Control.Monad (filterM) import Data.List (isInfixOf, isPrefixOf) -import Data.Monoid (Last (..)) import qualified Cardano.Configuration as Cfg import Cardano.Node.Configuration.CardanoConfigAdapter @@ -30,12 +29,16 @@ import Cardano.Node.Configuration.CardanoConfigAdapter import Cardano.Node.Configuration.CardanoConfigCompare (compareConfigurations, deprecatedFlagWarnings) import Cardano.Node.Configuration.CardanoConfigResolve - (ConfigurationDialect (..), classifyConfigurationFile) + (ConfigurationDialect (..), cardanoConfigCliLayer, + classifyConfigurationFile, nodeCliLayer) import Cardano.Node.Configuration.POM (NodeConfiguration (..), - PartialNodeConfiguration (..), defaultPartialNodeConfiguration, - makeNodeConfiguration, parseNodeConfigurationFP) + defaultPartialNodeConfiguration, makeNodeConfiguration, + parseNodeConfigurationFP) +import Cardano.Node.Configuration.Socket (SocketConfig (..)) import Cardano.Node.Types (ConfigYamlFilePath (..)) +import Data.Monoid (Last (..)) + import System.Directory (doesFileExist) import System.FilePath (()) @@ -87,9 +90,18 @@ envelopeConfigPath = ( "config-envelope.json") <$> fixtureDir -- breaks a mapped one) is still caught. allowedResidualLabels :: [String] allowedResidualLabels = - [ -- (2) representation: "MempoolCapacityBytesOverride: NoOverride" is an + [ -- (3) default mismatch: the fixture sets no DatabasePath, and the two + -- parsers fall back to different directories (POM to "mainnet/db/", + -- cardano-config to "db"). This is the one residual that changes what the + -- node does, so it is the one to close first. + "DatabaseFile" + -- (2) representation: the node's CLI parser always yields a shutdown target + -- (an absent flag reads as NoShutdown), where cardano-config leaves it unset. + -- Both mean "no shutdown handler" to 'maybeSpawnOnSlotSyncedShutdownHandler'. + , "ShutdownConfig" + -- (2) representation: "MempoolCapacityBytesOverride: NoOverride" is an -- explicit no-override value for POM but simply absent for cardano-config. - "MaybeMempoolCapacityOverride" + , "MaybeMempoolCapacityOverride" -- (3) default mismatch: the fixture leaves these unset; POM defaults to -- Nothing (no limit) while cardano-config supplies its own default of 1. , "MaxConcurrencyBulkSync" @@ -120,6 +132,8 @@ tests = testGroup "cardano-config configuration dialects" [ testCase "the fixture is classified as legacy" testLegacyClassification , testCase "the two parsers diverge only on the documented residuals" testLegacyDualParse + , testCase "an absent --port means the same ephemeral port to both parsers" + testFlaglessPortAgrees ] , testGroup "cardano-config envelope dialect (cardano-config only)" [ testCase "the migrated fixture is classified as an envelope" @@ -165,7 +179,7 @@ testLegacyDualParse :: Assertion testLegacyDualParse = do configPath <- legacyConfigPath adapted <- resolveWithCardanoConfig configPath - pomNc <- resolveWithPom configPath adapted + pomNc <- resolveWithPom configPath let divergences = compareConfigurations pomNc adapted isAllowed d = any (`isPrefixOf` d) allowedResidualLabels @@ -181,6 +195,23 @@ testLegacyDualParse = do ("divergences outside the documented residual set: " <> show unexpected) (null unexpected) +-- | An absent @--port@ must mean the same thing to both parsers. +-- +-- Both spell the flag with @value 0@ ("use an ephemeral port"), so a flagless +-- command line resolves to port 0 on either side. The distinction matters: an +-- UNSET port is not the same as 0, because 'gatherConfiguredSockets' hands the +-- port straight to @getaddrinfo@, which fails when neither a host address nor a +-- service is given. Pinning this here keeps the agreement from being an accident +-- of the two parsers being given the same command line. +testFlaglessPortAgrees :: Assertion +testFlaglessPortAgrees = do + configPath <- legacyConfigPath + adapted <- resolveWithCardanoConfig configPath + pomNc <- resolveWithPom configPath + let port = getLast . ncNodePortNumber . ncSocketConfig + port pomNc @?= Just 0 + port adapted @?= port pomNc + testEnvelopeClassification :: Assertion testEnvelopeClassification = envelopeConfigPath >>= classifyConfigurationFile >>= (@?= CardanoConfigDialect) @@ -220,9 +251,15 @@ testEnvelopeResolvesToSameConfiguration = do -- and adapt it to the node's own 'NodeConfiguration'. resolveWithCardanoConfig :: FilePath -> IO NodeConfiguration resolveWithCardanoConfig fp = do - resolved <- Cfg.resolveConfigurationFromFile fp - (cfgNc, _warns) <- - either (assertFailure . ("cardano-config resolve failed: " <>) . show) pure resolved + (fileCfg, _warns) <- Cfg.parseConfigurationFiles fp + -- The same empty command line the POM side is given (see 'resolveWithPom'), + -- read by cardano-config's own parser. Both parsers must see the same two + -- inputs, or the diff reports the inputs rather than the parsers. + cli <- either (assertFailure . ("cardano-config CLI layer failed: " <>)) pure + (cardanoConfigCliLayer fp []) + (cfgNc, _checkWarns) <- + either (assertFailure . ("cardano-config resolve failed: " <>) . show) pure + (Cfg.resolveConfiguration cli fileCfg) either (assertFailure . ("adapter failed: " <>)) pure (cardanoConfigToNodeConfiguration cfgNc) @@ -232,19 +269,15 @@ resolveWithCardanoConfig fp = do -- the file; mirror them from the given cardano-config result so the comparison -- isolates the file-parse and adapter-gap differences rather than CLI-supplied -- noise. -resolveWithPom :: FilePath -> NodeConfiguration -> IO NodeConfiguration -resolveWithPom fp adapted = do +resolveWithPom :: FilePath -> IO NodeConfiguration +resolveWithPom fp = do fileYaml <- parseNodeConfigurationFP (Just (ConfigYamlFilePath fp)) - -- 'PartialNodeConfiguration' is a Semigroup but not a Monoid, so there is no - -- empty value to start from: merge defaults with the file layer (mirroring - -- 'buildNodeConfiguration'), then override the CLI-only fields on top. - let withCli = - (defaultPartialNodeConfiguration <> fileYaml) - { pncConfigFile = Last (Just (ConfigYamlFilePath fp)) - , pncTopologyFile = Last (Just (ncTopologyFile adapted)) - , pncDatabaseFile = Last (Just (ncDatabaseFile adapted)) - , pncProtocolFiles = Last (Just (ncProtocolFiles adapted)) - , pncSocketConfig = Last (Just (ncSocketConfig adapted)) - } + -- The three layers a node assembles, in the node's own order: defaults, then + -- the file, then the command line. The command line here is the one a node + -- started with nothing but @--config@ has, which is not the same as no layer + -- at all (see 'nodeCliLayer'). + let fileLayer = defaultPartialNodeConfiguration <> fileYaml + (mCliLayer, cliReport) = nodeCliLayer fp [] + assertBool ("the node's CLI layer could not be built: " <> show cliReport) (null cliReport) either (assertFailure . ("POM makeNodeConfiguration failed: " <>)) pure - (makeNodeConfiguration withCli) + (makeNodeConfiguration (maybe fileLayer (fileLayer <>) mCliLayer)) From 1b8175f2d57300d2f69ca54f35328590e3d253c7 Mon Sep 17 00:00:00 2001 From: Javier Sagredo Date: Tue, 6 Oct 2026 15:39:46 +0200 Subject: [PATCH 06/45] Better comparison of configuration parsers Some fields are not discrepancies, some others can be unified, etc. Also bump consensus for the snapshot tracing warning --- cardano-node/cardano-node.cabal | 6 ++--- .../Configuration/CardanoConfigAdapter.hs | 9 +++++-- .../Configuration/CardanoConfigCompare.hs | 19 +++++++++++++- .../src/Cardano/Node/Configuration/POM.hs | 18 ++++++++++--- cardano-node/test/Test/Cardano/Node/POM.hs | 9 ++++--- .../test/cardano-config-compare/Main.hs | 25 ++----------------- 6 files changed, 51 insertions(+), 35 deletions(-) diff --git a/cardano-node/cardano-node.cabal b/cardano-node/cardano-node.cabal index 92dd280620e..a898dde1a76 100644 --- a/cardano-node/cardano-node.cabal +++ b/cardano-node/cardano-node.cabal @@ -127,7 +127,7 @@ library , base16-bytestring , bytestring , cardano-api ^>= 11.11 - , cardano-config ^>= 2.1 + , cardano-config ^>= 2.2.3 , cardano-crypto-class ^>=2.6 , cardano-crypto-wrapper , cardano-git-rev ^>=0.2.2 @@ -204,7 +204,7 @@ executable cardano-node autogen-modules: Paths_cardano_node build-depends: base - , cardano-config ^>= 2.1 + , cardano-config ^>= 2.2.3 , cardano-config:commands , cardano-crypto-class , cardano-git-rev @@ -221,7 +221,7 @@ test-suite cardano-config-compare-test type: exitcode-stdio-1.0 build-depends: base - , cardano-config ^>= 2.1 + , cardano-config ^>= 2.2.3 , cardano-node , directory , filepath diff --git a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs index 1b29474f917..195fd21a511 100644 --- a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs +++ b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs @@ -154,10 +154,15 @@ cardanoConfigToPartialNodeConfiguration cfg = , pncMaybeMempoolCapacityOverride = Last (fmap (MempoolCapacityBytesOverride . ByteSize32 . fromIntegral) (strictMaybeToMaybe (Cfg.mempoolCapacityOverride mempCfg))) - , pncShutdownConfig = + , -- An absent shutdown target is 'NoShutdown', not "unset": that is what + -- the node's own CLI parser yields when no @--shutdown-on-*@ flag is + -- given, and 'maybeSpawnOnSlotSyncedShutdownHandler' arms no handler for + -- either spelling. State the same value the node states. + pncShutdownConfig = Last (Just (ShutdownConfig (strictMaybeToMaybe (Cfg.shutdownIPC cfg)) - (fmap toNodeShutdownOn (strictMaybeToMaybe (Cfg.shutdownOnTarget cfg))))) + (Just (maybe NoShutdown toNodeShutdownOn + (strictMaybeToMaybe (Cfg.shutdownOnTarget cfg)))))) , pncResponderCoreAffinityPolicy = Last (Just (fromCfgAffinity (runIdentity (Cfg.responderCoreAffinityPolicy netCfg)))) , pncTxSubmissionLogicVersion = diff --git a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs index 14898a3b309..f62f198e0f9 100644 --- a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs +++ b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs @@ -17,6 +17,7 @@ module Cardano.Node.Configuration.CardanoConfigCompare import Cardano.Node.Configuration.POM (NodeConfiguration (..)) import Cardano.Node.Types (NodeByronProtocolConfiguration (..), NodeProtocolConfiguration (..)) +import Ouroboros.Consensus.Mempool (MempoolCapacityBytesOverride (..)) -- | Diagnose node CLI flags that cardano-config's own CLI parser rejects, in -- terms the operator can act on. All of these flags are deprecated: the three @@ -69,7 +70,9 @@ compareConfigurations pom adapted = , cmp "MaxConcurrencyBulkSync" ncMaxConcurrencyBulkSync , cmp "MaxConcurrencyDeadline" ncMaxConcurrencyDeadline , cmp "TraceForwardSocket" ncTraceForwardSocket - , cmp "MaybeMempoolCapacityOverride" ncMaybeMempoolCapacityOverride + , cmpValues "MaybeMempoolCapacityOverride" + (ignoreAbsentMempoolOverride (ncMaybeMempoolCapacityOverride pom)) + (ignoreAbsentMempoolOverride (ncMaybeMempoolCapacityOverride adapted)) , cmp "LedgerDbConfig" ncLedgerDbConfig , cmp "ProtocolIdleTimeout" ncProtocolIdleTimeout , cmp "TimeWaitTimeout" ncTimeWaitTimeout @@ -146,3 +149,17 @@ ignoreByronSupportedVersion byronConfig = , npcByronSupportedProtocolVersionMinor = 0 , npcByronSupportedProtocolVersionAlt = 0 } + +-- | Fold the two spellings of "no mempool capacity override" together. +-- +-- POM keeps 'Just NoMempoolCapacityBytesOverride' for a configuration that +-- writes @MempoolCapacityBytesOverride: NoOverride@, and 'Nothing' for one that +-- writes no such key. cardano-config models no override as absence and has no +-- way to spell the explicit form, so a configuration that writes it diverges +-- here on spelling alone. Both leave the mempool at the kernel default, which is +-- 'NoMempoolCapacityBytesOverride' already: the override is applied only when it +-- is 'Just' (see @llrnCustomiseNodeKernelArgs@ in "Ouroboros.Consensus.Node"). +ignoreAbsentMempoolOverride :: + Maybe MempoolCapacityBytesOverride -> Maybe MempoolCapacityBytesOverride +ignoreAbsentMempoolOverride (Just NoMempoolCapacityBytesOverride) = Nothing +ignoreAbsentMempoolOverride other = other diff --git a/cardano-node/src/Cardano/Node/Configuration/POM.hs b/cardano-node/src/Cardano/Node/Configuration/POM.hs index d4bbd2cbbe9..ac1b8a26d15 100644 --- a/cardano-node/src/Cardano/Node/Configuration/POM.hs +++ b/cardano-node/src/Cardano/Node/Configuration/POM.hs @@ -775,8 +775,14 @@ defaultPartialNodeConfiguration = , pncShutdownConfig = Last . Just $ ShutdownConfig Nothing Nothing , pncStartAsNonProducingNode = Last $ Just False , pncProtocolConfig = mempty - , pncMaxConcurrencyBulkSync = mempty - , pncMaxConcurrencyDeadline = mempty + , -- Leaving these unset means "do not override the block-fetch defaults", + -- which are 1 and 1 (see 'Cardano.defaultBlockFetchConfiguration'). State + -- that value instead of implying it, so that the configuration the node + -- runs on says what the concurrency is. cardano-config's own default layer + -- pins the same 1, so the two must be changed together, and either one + -- changing on its own shows up as a divergence at startup. + pncMaxConcurrencyBulkSync = Last (Just (MaxConcurrencyBulkSync 1)) + , pncMaxConcurrencyDeadline = Last (Just (MaxConcurrencyDeadline 1)) , pncTraceForwardSocket = mempty , pncMaybeMempoolCapacityOverride = mempty , pncLedgerDbConfig = @@ -794,7 +800,13 @@ defaultPartialNodeConfiguration = -- https://ouroboros-network.cardano.intersectmbo.org/ouroboros-network/Ouroboros-Network-Diffusion-Configuration.html#v:defaultEgressPollInterval , pncAcceptedConnectionsLimit = Last (Just Ouroboros.defaultAcceptedConnectionsLimit) -- https://ouroboros-network.cardano.intersectmbo.org/ouroboros-network/Ouroboros-Network-Diffusion-Configuration.html#v:defaultAcceptedConnectionsLimit - , pncChainSyncIdleTimeout = mempty + , pncChainSyncIdleTimeout = + Last (Just (case Cardano.defaultChainSyncIdleTimeout of + Cardano.ChainSyncIdleTimeout t -> t + -- 'customizeChainSyncTimeout' in "Cardano.Node.Run" reads + -- 0 back as "no idle timeout". + Cardano.ChainSyncNoIdleTimeout -> 0)) + -- https://ouroboros-network.cardano.intersectmbo.org/cardano-diffusion/Cardano-Network-Diffusion-Configuration.html#v:defaultChainSyncIdleTimeout , pncMempoolTimeoutSoft = mempty , pncMempoolTimeoutHard = mempty , pncMempoolTimeoutCapacity = mempty diff --git a/cardano-node/test/Test/Cardano/Node/POM.hs b/cardano-node/test/Test/Cardano/Node/POM.hs index b6abb4e455b..8375ea8289d 100644 --- a/cardano-node/test/Test/Cardano/Node/POM.hs +++ b/cardano-node/test/Test/Cardano/Node/POM.hs @@ -257,13 +257,16 @@ eExpectedConfig = do , ncDiffusionMode = InitiatorAndResponderDiffusionMode , ncExperimentalProtocolsEnabled = True , ncEgressPollInterval = 0 - , ncMaxConcurrencyBulkSync = Nothing - , ncMaxConcurrencyDeadline = Nothing + -- The block-fetch concurrency defaults, which the node now states rather + -- than leaving to consensus; neither test layer sets them. + , ncMaxConcurrencyBulkSync = Just (MaxConcurrencyBulkSync 1) + , ncMaxConcurrencyDeadline = Just (MaxConcurrencyDeadline 1) , ncTraceForwardSocket = Nothing , ncMaybeMempoolCapacityOverride = Nothing , ncProtocolIdleTimeout = 5 , ncTimeWaitTimeout = 60 - , ncChainSyncIdleTimeout = NoTimeoutOverride + -- The diffusion layer's own default, likewise now stated rather than implied. + , ncChainSyncIdleTimeout = TimeoutOverride 3373 , ncMempoolTimeoutSoft = 1.0 , ncMempoolTimeoutHard = 1.5 , ncMempoolTimeoutCapacity = 5.0 diff --git a/cardano-node/test/cardano-config-compare/Main.hs b/cardano-node/test/cardano-config-compare/Main.hs index 24cc303451d..ed053607df4 100644 --- a/cardano-node/test/cardano-config-compare/Main.hs +++ b/cardano-node/test/cardano-config-compare/Main.hs @@ -90,32 +90,11 @@ envelopeConfigPath = ( "config-envelope.json") <$> fixtureDir -- breaks a mapped one) is still caught. allowedResidualLabels :: [String] allowedResidualLabels = - [ -- (3) default mismatch: the fixture sets no DatabasePath, and the two - -- parsers fall back to different directories (POM to "mainnet/db/", - -- cardano-config to "db"). This is the one residual that changes what the - -- node does, so it is the one to close first. - "DatabaseFile" - -- (2) representation: the node's CLI parser always yields a shutdown target - -- (an absent flag reads as NoShutdown), where cardano-config leaves it unset. - -- Both mean "no shutdown handler" to 'maybeSpawnOnSlotSyncedShutdownHandler'. - , "ShutdownConfig" - -- (2) representation: "MempoolCapacityBytesOverride: NoOverride" is an - -- explicit no-override value for POM but simply absent for cardano-config. - , "MaybeMempoolCapacityOverride" - -- (3) default mismatch: the fixture leaves these unset; POM defaults to - -- Nothing (no limit) while cardano-config supplies its own default of 1. - , "MaxConcurrencyBulkSync" - , "MaxConcurrencyDeadline" - -- (2)/(3): cardano-config ships a QueryBatchSize where the node has none, + [ -- (2)/(3): cardano-config ships a QueryBatchSize where the node has none, -- and it states the snapshot interval as the explicit 86400 slots where the -- node leaves it at DefaultSnapshotInterval, which is the same 40*k slots -- named rather than spelled out. The rest of the snapshot policy agrees. - , "LedgerDbConfig" - -- (3) default mismatch: the fixture leaves ChainSyncIdleTimeout unset. POM - -- treats that as "no override" and lets the diffusion layer pick, while - -- cardano-config states the same value (3373s) as a default, so the node - -- sees it as an override. - , "ChainSyncIdleTimeout" + "LedgerDbConfig" ] main :: IO () From e38adc9610c1ffee784b8cd6eaea88136f3349ed Mon Sep 17 00:00:00 2001 From: Javier Sagredo Date: Tue, 6 Oct 2026 17:26:49 +0200 Subject: [PATCH 07/45] Use cardano-config's CLI parsers --- .../Configuration/CardanoConfigAdapter.hs | 92 +-- cardano-node/src/Cardano/Node/Parsers.hs | 524 ++++-------------- 2 files changed, 151 insertions(+), 465 deletions(-) diff --git a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs index 195fd21a511..76d9745c8f9 100644 --- a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs +++ b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigAdapter.hs @@ -21,6 +21,16 @@ module Cardano.Node.Configuration.CardanoConfigAdapter , cardanoConfigToPartialNodeConfiguration , nodeProtocolConfigurationFromCardanoConfig , adapterGaps + + -- * Mapping cardano-config's types onto the node's + -- + -- These are also what 'Cardano.Node.Parsers' needs, since it builds the + -- node's configuration from cardano-config's own option parsers. + , credentialsToProtocolFilepaths + , fromCfgDbPaths + , fromCfgGrpcEndpoint + , fromCfgTracerConnection + , toNodeShutdownOn ) where import Cardano.Api (File (..)) @@ -217,53 +227,14 @@ cardanoConfigToPartialNodeConfiguration cfg = ledgerDbCfg = runIdentity (Cfg.ledgerDbConfiguration storeCfg) consensusModeVal = runIdentity (Cfg.getConsensusConfiguration (Cfg.consensusConfiguration cfg)) - fromCfgDbPaths :: Cfg.NodeDatabasePaths -> NodeDatabasePaths - fromCfgDbPaths (Cfg.SingleDB p) = OnePathForAllDbs p - fromCfgDbPaths (Cfg.SplitDB imm vol) = MultipleDbPaths imm vol - fromCfgConsensusMode :: Cfg.ConsensusMode -> ConsensusMode fromCfgConsensusMode Cfg.PraosMode = PraosMode fromCfgConsensusMode (Cfg.GenesisMode _) = GenesisMode - toNodeShutdownOn :: Cfg.ShutdownOn -> ShutdownOn - toNodeShutdownOn (Cfg.ShutdownAtSlot w) = ASlot (SlotNo w) - toNodeShutdownOn (Cfg.ShutdownAtBlock w) = ABlock (BlockNo w) - fromCfgAffinity :: Cfg.ResponderCoreAffinityPolicy -> ResponderCoreAffinityPolicy fromCfgAffinity Cfg.NoResponderCoreAffinity = NoResponderCoreAffinity fromCfgAffinity Cfg.ResponderCoreAffinity = ResponderCoreAffinity - -- cardano-config's gRPC endpoint and the node's 'RpcEndpoint' offer the same - -- three choices, so the mapping is one constructor to one constructor. Both - -- default the listen address to 127.0.0.1, and cardano-config has already - -- applied that default, so the endpoint arrives complete. - fromCfgGrpcEndpoint :: Cfg.GrpcEndpoint -> RpcEndpoint - fromCfgGrpcEndpoint (Cfg.GrpcEndpointUnixSocket fp) = RpcEndpointUnixSocket (File fp) - fromCfgGrpcEndpoint (Cfg.GrpcEndpointHttp ip portNo) = RpcEndpointHttp ip portNo - fromCfgGrpcEndpoint (Cfg.GrpcEndpointHttps ip portNo tls) = - RpcEndpointHttps ip portNo (fromCfgGrpcTlsFiles tls) - - fromCfgGrpcTlsFiles :: Cfg.GrpcTlsFiles -> RpcTlsFiles - fromCfgGrpcTlsFiles tls = - RpcTlsFiles - { certificateFile = File (Cfg.certificateFile tls) - , privateKeyFile = File (Cfg.privateKeyFile tls) - , chainCertificateFiles = map File (Cfg.chainCertificateFiles tls) - } - - -- cardano-config records the socket mode as the literal @"Accept"@ / - -- @"Connect"@ its CLI parser produces; anything else cannot occur. - fromCfgTracerConnection :: Cfg.TracerConnection -> (HowToConnect, ForwarderMode) - fromCfgTracerConnection (Cfg.TracerConnection mode method) = - ( case method of - CliArgs.TracerConnectViaPipe fp -> LocalPipe fp - CliArgs.TracerConnectViaRemote host portNo -> - RemoteSocket host (fromIntegral portNo) - , case mode of - "Accept" -> Responder - _ -> Initiator - ) - -- Map cardano-config's snapshot policy onto the node's 'SnapshotPolicyArgs'. -- Resolution has already turned a named Mithril policy into the concrete -- options it stands for and filled in every option a partial policy left out @@ -323,6 +294,49 @@ cardanoConfigToPartialNodeConfiguration cfg = (fmap SlotNo (strictMaybeToMaybe (Cfg.gcfCSJJumpSize f))) (strictMaybeToMaybe (Cfg.gcfGDDRateLimit f)) +-- | Map @cardano-config@'s database paths onto the node's. +fromCfgDbPaths :: Cfg.NodeDatabasePaths -> NodeDatabasePaths +fromCfgDbPaths (Cfg.SingleDB p) = OnePathForAllDbs p +fromCfgDbPaths (Cfg.SplitDB imm vol) = MultipleDbPaths imm vol + +-- | Map @cardano-config@'s shutdown target onto the node's. +toNodeShutdownOn :: Cfg.ShutdownOn -> ShutdownOn +toNodeShutdownOn (Cfg.ShutdownAtSlot w) = ASlot (SlotNo w) +toNodeShutdownOn (Cfg.ShutdownAtBlock w) = ABlock (BlockNo w) + +-- | cardano-config's gRPC endpoint and the node's 'RpcEndpoint' offer the same +-- three choices, so the mapping is one constructor to one constructor. Both +-- default the listen address to 127.0.0.1, and cardano-config has already +-- applied that default, so the endpoint arrives complete. +fromCfgGrpcEndpoint :: Cfg.GrpcEndpoint -> RpcEndpoint +fromCfgGrpcEndpoint (Cfg.GrpcEndpointUnixSocket fp) = RpcEndpointUnixSocket (File fp) +fromCfgGrpcEndpoint (Cfg.GrpcEndpointHttp ip portNo) = RpcEndpointHttp ip portNo +fromCfgGrpcEndpoint (Cfg.GrpcEndpointHttps ip portNo tls) = + RpcEndpointHttps ip portNo (fromCfgGrpcTlsFiles tls) + +fromCfgGrpcTlsFiles :: Cfg.GrpcTlsFiles -> RpcTlsFiles +fromCfgGrpcTlsFiles tls = + RpcTlsFiles + { certificateFile = File (Cfg.certificateFile tls) + , privateKeyFile = File (Cfg.privateKeyFile tls) + , chainCertificateFiles = map File (Cfg.chainCertificateFiles tls) + } + +-- | Map @cardano-config@'s tracer connection onto the pair the node holds. +-- +-- cardano-config records the socket mode as the literal @"Accept"@ / +-- @"Connect"@ its CLI parser produces; anything else cannot occur. +fromCfgTracerConnection :: Cfg.TracerConnection -> (HowToConnect, ForwarderMode) +fromCfgTracerConnection (Cfg.TracerConnection mode method) = + ( case method of + CliArgs.TracerConnectViaPipe fp -> LocalPipe fp + CliArgs.TracerConnectViaRemote host portNo -> + RemoteSocket host (fromIntegral portNo) + , case mode of + "Accept" -> Responder + _ -> Initiator + ) + -- | Map @cardano-config@ 'Cfg.Credentials' (file paths) onto the node's -- 'ProtocolFilepaths'. credentialsToProtocolFilepaths :: Cfg.Credentials -> ProtocolFilepaths diff --git a/cardano-node/src/Cardano/Node/Parsers.hs b/cardano-node/src/Cardano/Node/Parsers.hs index 0353cf20a95..a6075522f9d 100644 --- a/cardano-node/src/Cardano/Node/Parsers.hs +++ b/cardano-node/src/Cardano/Node/Parsers.hs @@ -1,50 +1,54 @@ {-# LANGUAGE ApplicativeDo #-} -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeApplications #-} +-- | The node's @run@ command line. +-- +-- The individual option parsers come from @cardano-config@ +-- ('Cardano.Configuration.CliArgs'), which is the one definition of the node's +-- flags, their metavars and their help text; this module assembles them into a +-- 'PartialNodeConfiguration' and converts cardano-config's types to the node's +-- (see 'Cardano.Node.Configuration.CardanoConfigAdapter'). +-- +-- What is still defined here is what cardano-config does not carry: +-- +-- * the deprecated mempool capacity flags, which cardano-config dropped by +-- design (the setting belongs in the configuration file); +-- * the three deprecated aliases, @--delegation-certificate@, +-- @--signing-key@ and @--non-producing-node@, which cardano-config knows +-- only by their current spellings. module Cardano.Node.Parsers ( nodeCLIParser , parseConfigFile , parserHelpHeader , parserHelpOptions , renderHelpDoc - , parseHostPort ) where -import Cardano.Api (FileDirection (In)) - -import Cardano.Logging.Types -import qualified Cardano.Logging.Types as Net -import Cardano.Node.Configuration.NodeAddress (File (..), NodeHostIPAddress (..), +import qualified Cardano.Configuration.CliArgs as Cfg +import Cardano.Configuration.CliArgs (parseConfigFile) +import Cardano.Node.Configuration.CardanoConfigAdapter + (credentialsToProtocolFilepaths, fromCfgDbPaths, fromCfgGrpcEndpoint, + fromCfgTracerConnection, toNodeShutdownOn) +import Cardano.Node.Configuration.NodeAddress (File (..), NodeHostIPv4Address (NodeHostIPv4Address), - NodeHostIPv6Address (NodeHostIPv6Address), PortNumber, SocketPath) + NodeHostIPv6Address (NodeHostIPv6Address)) import Cardano.Node.Configuration.POM (PartialNodeConfiguration (..), lastOption) -import Cardano.Node.Configuration.Socket -import Cardano.Node.Handlers.Shutdown -import Cardano.Node.Types -import Cardano.Prelude (ConvertText (..)) -import Cardano.Rpc.Server.Config (PartialRpcConfig, RpcConfigF (..), RpcEndpoint (..), - RpcTlsFiles (..), TlsCertificate, TlsPrivateKey, defaultRpcListenAddress) -import Ouroboros.Consensus.Ledger.SupportsMempool -import Ouroboros.Consensus.Node +import Cardano.Node.Configuration.Socket (SocketConfig (..)) +import Cardano.Node.Handlers.Shutdown (ShutdownConfig (..), ShutdownOn (..)) +import Cardano.Node.Types (ConfigYamlFilePath (..), ProtocolFilepaths (..), + TopologyFile (..)) +import Cardano.Rpc.Server.Config (PartialRpcConfig, RpcConfigF (..)) +import Ouroboros.Consensus.Ledger.SupportsMempool (ByteSize32 (..)) +import Ouroboros.Consensus.Mempool (MempoolCapacityBytesOverride (..)) -import Data.Char (isDigit) -import Data.Foldable -import Data.IP (IP) import Data.Maybe (fromMaybe) import Data.Monoid (Last (..)) -import Data.Text (Text) -import qualified Data.Text as Text import Data.Word (Word32) import Options.Applicative hiding (str, switch) import qualified Options.Applicative as Opt import qualified Options.Applicative.Help as OptI import qualified Prettyprinter.Internal as PP -import System.Posix.Types (Fd (..)) -import Text.Read (readMaybe) nodeCLIParser :: Parser PartialNodeConfiguration nodeCLIParser = subparser @@ -58,38 +62,36 @@ nodeCLIParser = subparser nodeRunParser :: Parser PartialNodeConfiguration nodeRunParser = do -- Filepaths - topFp <- lastOption parseTopologyFile - dbFp <- lastOption parseNodeDatabasePaths - validate <- lastOption parseValidateDB - socketFp <- lastOption $ parseSocketPath "socket-path" "Path to a cardano-node socket" - traceForwardSocket <- lastOption parseTracerSocketMode - nodeConfigFp <- lastOption parseConfigFile + topFp <- lastOption Cfg.parseTopologyFile + dbFp <- Last . fmap fromCfgDbPaths <$> Cfg.parseNodeDatabasePaths + validate <- lastOption Cfg.parseValidateDB + socketFp <- lastOption (File <$> Cfg.parseSocketPath) + traceForwardSocket <- lastOption (fromCfgTracerConnection <$> Cfg.parseTracerSocketMode) + nodeConfigFp <- lastOption Cfg.parseConfigFile -- Protocol files - byronCertFile <- optional parseByronDelegationCert - byronKeyFile <- optional parseByronSigningKey - shelleyKESSource <- optional parseKesSourceFilePath - shelleyVRFFile <- optional parseVrfKeyFilePath - shelleyCertFile <- optional parseOperationalCertFilePath - shelleyBulkCredsFile <- optional parseBulkCredsFilePath + credentials <- Cfg.parseCredentials + deprecatedByronCertFile <- optional parseByronDelegationCertDeprecated + deprecatedByronKeyFile <- optional parseByronSigningKeyDeprecated startAsNonProducingNode <- (\depr new -> Last depr <> Last new) <$> parseStartAsNonProducingNodeDeprecated - <*> parseStartAsNonProducingNode + <*> Cfg.parseStartAsNonProducingNode -- Node Address - nIPv4Address <- lastOption parseHostIPv4Addr - nIPv6Address <- lastOption parseHostIPv6Addr - nPortNumber <- lastOption parsePort + nIPv4Address <- lastOption (NodeHostIPv4Address <$> Cfg.parseHostIPv4Addr) + nIPv6Address <- lastOption (NodeHostIPv6Address <$> Cfg.parseHostIPv6Addr) + nPortNumber <- lastOption Cfg.parsePort -- Shutdown - shutdownIPC <- lastOption parseShutdownIPC - shutdownOnLimit <- lastOption parseShutdownOn + shutdownIPC <- lastOption Cfg.parseShutdownIPC + shutdownOnLimit <- lastOption (toNodeShutdownOn <$> Cfg.parseShutdownOn) -- Hidden options (to be removed eventually) maybeMempoolCapacityOverride <- lastOption parseMempoolCapacityOverride -- gRPC - pncRpcConfig <- parseRpcConfig + rpcIsEnabled <- lastOption Cfg.parseEnableGrpc + rpcEndpoint <- lastOption (fromCfgGrpcEndpoint <$> Cfg.parseGrpcEndpoint) pure $ PartialNodeConfiguration { pncSocketConfig = @@ -103,17 +105,22 @@ nodeRunParser = do , pncDatabaseFile = dbFp , pncDiffusionMode = mempty , pncExperimentalProtocolsEnabled = mempty - , pncProtocolFiles = Last $ Just ProtocolFilepaths - { byronCertFile - , byronKeyFile - , shelleyKESSource - , shelleyVRFFile - , shelleyCertFile - , shelleyBulkCredsFile - } + , pncProtocolFiles = + Last . Just $ + withDeprecatedByronCredentials + deprecatedByronCertFile + deprecatedByronKeyFile + (credentialsToProtocolFilepaths credentials) , pncValidateDB = validate - , pncShutdownConfig = - Last . Just $ ShutdownConfig (getLast shutdownIPC) (getLast shutdownOnLimit) + , -- An absent @--shutdown-on-*@ means 'NoShutdown' rather than + -- "unset", which is what the node has always resolved it to. + -- cardano-config's parser has no such fallback, so it is applied + -- here. + pncShutdownConfig = + Last . Just $ + ShutdownConfig + (getLast shutdownIPC) + (Just (fromMaybe NoShutdown (getLast shutdownOnLimit))) , pncStartAsNonProducingNode = startAsNonProducingNode , pncProtocolConfig = mempty , pncMaxConcurrencyBulkSync = mempty @@ -148,130 +155,49 @@ nodeRunParser = do , pncPeerSharing = mempty , pncGenesisConfigFlags = mempty , pncResponderCoreAffinityPolicy = mempty - , pncRpcConfig + , pncRpcConfig = + (mempty :: PartialRpcConfig) + { isEnabled = rpcIsEnabled + , rpcEndpoint + } , pncTxSubmissionLogicVersion = mempty , pncTxSubmissionInitDelay = mempty } -parseSocketPath :: Text -- ^ option name - -> Text -- ^ help text - -> Parser SocketPath -parseSocketPath optionName helpMessage = - fmap File $ strOption $ mconcat - [ long (toS optionName) - , help (toS helpMessage) - , completer (bashCompleter "file") - , metavar "FILEPATH" - ] - - --- leave hostname untouched, non-empty --- 0 <= port <= 65535 -parseNodeAddress :: Opt.ReadM Net.HowToConnect -parseNodeAddress = Opt.eitherReader parseHostPort - -parseHostPort :: String -> Either String Net.HowToConnect -parseHostPort str - | (portRev, ':' : hostRev) <- break (== ':') (reverse str) - = if - | null hostRev -> Left "parseHostPort: Empty host." - | null portRev -> Left "parseHostPort: Empty port." - | all isDigit portRev -> - case parsePortNumber (reverse portRev) of - Right port -> Right (Net.RemoteSocket (Text.pack (reverse hostRev)) (fromIntegral port)) - Left err -> Left ("parseHostPort: " ++ err) - | otherwise -> Left "parseHostPort: Non-numeric port." - | otherwise - = Left "parseHostPort: No colon found." - -parseTracerSocketMode :: Parser (Net.HowToConnect, ForwarderMode) -parseTracerSocketMode = - asum - [ fmap (, Responder) $ option parseNodeAddress $ mconcat - [ long "tracer-socket-network-accept" - , help "Accept incoming cardano-tracer connection on HOST:PORT" - , metavar "HOST:PORT" - ] - , fmap (, Initiator) $ option parseNodeAddress $ mconcat - [ long "tracer-socket-network-connect" - , help "Connect to cardano-tracer listening on HOST:PORT" - , metavar "HOST:PORT" - ] - , fmap (\host -> (Net.LocalPipe host, Responder)) $ strOption $ mconcat - [ long "tracer-socket-path-accept" - , help "Accept incoming cardano-tracer connection at local socket" - , completer (bashCompleter "file") - , metavar "FILEPATH" - ] - , fmap (\host -> (Net.LocalPipe host, Initiator)) $ strOption $ mconcat - [ long "tracer-socket-path-connect" - , help "Connect to cardano-tracer listening on a local socket" - , completer (bashCompleter "file") - , metavar "FILEPATH" - ] +-- | Fill the Byron credentials in from the deprecated aliases where +-- cardano-config's parser, which knows only the current spellings, left a hole. +withDeprecatedByronCredentials :: + Maybe FilePath -> Maybe FilePath -> ProtocolFilepaths -> ProtocolFilepaths +withDeprecatedByronCredentials cert key files = + files + { byronCertFile = byronCertFile files <|> cert + , byronKeyFile = byronKeyFile files <|> key + } + +-- | Deprecated alias of @--byron-delegation-certificate@. +parseByronDelegationCertDeprecated :: Parser FilePath +parseByronDelegationCertDeprecated = + strOption (long "delegation-certificate" <> Opt.internal) + +-- | Deprecated alias of @--byron-signing-key@. +parseByronSigningKeyDeprecated :: Parser FilePath +parseByronSigningKeyDeprecated = + strOption (long "signing-key" <> Opt.internal) + +-- | Deprecated alias of @--start-as-non-producing-node@. +parseStartAsNonProducingNodeDeprecated :: Parser (Maybe Bool) +parseStartAsNonProducingNodeDeprecated = + flag Nothing (Just True) $ mconcat + [ long "non-producing-node" + , help $ mconcat + [ "DEPRECATED, use --start-as-non-producing-node instead. " + , "This option will be removed in one of the future versions of cardano-node." + ] + , hidden ] -parseHostIPv4Addr :: Parser NodeHostIPv4Address -parseHostIPv4Addr = - Opt.option (eitherReader parseNodeHostIPv4Address) ( - long "host-addr" - <> metavar "IPV4" - <> help "An optional IPv4 address" - ) - -parseHostIPv6Addr :: Parser NodeHostIPv6Address -parseHostIPv6Addr = - Opt.option (eitherReader parseNodeHostIPv6Address) ( - long "host-ipv6-addr" - <> metavar "IPV6" - <> help "An optional IPv6 address" - ) - -parseNodeHostIPv4Address :: String -> Either String NodeHostIPv4Address -parseNodeHostIPv4Address str = - maybe - (Left $ - "Failed to parse IPv4 address: " ++ str ++ - ". If you want to specify an IPv6 address, use --host-ipv6-addr option.") - (Right . NodeHostIPv4Address) - (readMaybe str) - -parseNodeHostIPv6Address :: String -> Either String NodeHostIPv6Address -parseNodeHostIPv6Address str = - maybe - (Left $ - "Failed to parse IPv6 address: " ++ str ++ - ". If you want to specify an IPv4 address, use --host-addr option.") - (Right . NodeHostIPv6Address) - (readMaybe str) - --- | Parse either an IPv4 or an IPv6 address, unlike 'parseNodeHostIPv4Address' --- and 'parseNodeHostIPv6Address' which each accept only one address family. -parseNodeHostIPAddress :: String -> Either String NodeHostIPAddress -parseNodeHostIPAddress str = - maybe - (Left $ "Failed to parse IP address: " ++ str) - (Right . NodeHostIPAddress) - (readMaybe str) - -parsePort :: Parser PortNumber -parsePort = - Opt.option readPortNumber ( - long "port" - <> metavar "PORT" - <> help "The port number" - <> value 0 -- Use an ephemeral port - ) - -parseConfigFile :: Parser FilePath -parseConfigFile = - strOption - ( long "config" - <> metavar "NODE-CONFIGURATION" - <> help "Configuration file for the cardano-node" - <> completer (bashCompleter "file") - ) - +-- | Deprecated, and not carried by cardano-config: the mempool capacity is a +-- configuration file setting (@MempoolCapacityBytesOverride@). parseMempoolCapacityOverride :: Parser MempoolCapacityBytesOverride parseMempoolCapacityOverride = parseOverride <|> parseNoOverride where @@ -290,260 +216,6 @@ parseMempoolCapacityOverride = parseOverride <|> parseNoOverride <> help "[DEPRECATED: Set it in config file] Don't override mempool capacity" ) -parseNodeDatabasePaths :: Parser NodeDatabasePaths -parseNodeDatabasePaths = parseDbPath <|> parseMultipleDbPaths - -parseDbPath :: Parser NodeDatabasePaths -parseDbPath = - fmap OnePathForAllDbs $ - strOption $ - mconcat - [ long "database-path" - , metavar "FILEPATH" - , help "Directory where the state is stored." - , completer (bashCompleter "file") - ] - -parseMultipleDbPaths :: Parser NodeDatabasePaths -parseMultipleDbPaths = MultipleDbPaths <$> parseImmutableDbPath <*> parseVolatileDbPath - -parseVolatileDbPath :: Parser FilePath -parseVolatileDbPath = strOption $ - mconcat - [ long "volatile-database-path" - , metavar "FILEPATH" - , help "Directory where the state is stored." - , completer (bashCompleter "file") - ] - -parseImmutableDbPath :: Parser FilePath -parseImmutableDbPath = strOption $ - mconcat - [ long "immutable-database-path" - , metavar "FILEPATH" - , help "Directory where the state is stored." - , completer (bashCompleter "file") - ] - - --- | This parser will always override configuration option, even if the --- `--validate-db` is not present. This is fine for `--validate-db` switch, --- but might not be for something else. See `parseStartAsNonProducingNode` for --- an alternative solution. -parseValidateDB :: Parser Bool -parseValidateDB = - Opt.switch ( - long "validate-db" - <> help "Validate all on-disk database files" - ) - -parseShutdownIPC :: Parser Fd -parseShutdownIPC = - Opt.option (Fd <$> auto) ( - long "shutdown-ipc" - <> metavar "FD" - <> help "Shut down the process when this inherited FD reaches EOF" - <> hidden - ) - -parseTopologyFile :: Parser FilePath -parseTopologyFile = - strOption ( - long "topology" - <> metavar "FILEPATH" - <> help "The path to a file describing the topology." - <> completer (bashCompleter "file") - ) - -parseByronDelegationCert :: Parser FilePath -parseByronDelegationCert = - strOption ( long "byron-delegation-certificate" - <> metavar "FILEPATH" - <> help "Path to the delegation certificate." - <> completer (bashCompleter "file") - ) - <|> - strOption - ( long "delegation-certificate" - <> Opt.internal - ) - -parseByronSigningKey :: Parser FilePath -parseByronSigningKey = - strOption ( long "byron-signing-key" - <> metavar "FILEPATH" - <> help "Path to the Byron signing key." - <> completer (bashCompleter "file") - ) - <|> - strOption ( long "signing-key" - <> Opt.internal - ) - -parseOperationalCertFilePath :: Parser FilePath -parseOperationalCertFilePath = - strOption - ( long "shelley-operational-certificate" - <> metavar "FILEPATH" - <> help "Path to the delegation certificate." - <> completer (bashCompleter "file") - ) - -parseBulkCredsFilePath :: Parser FilePath -parseBulkCredsFilePath = - strOption - ( long "bulk-credentials-file" - <> metavar "FILEPATH" - <> help "Path to the bulk pool credentials file." - <> completer (bashCompleter "file") - ) - -parseKesSourceFilePath :: Parser KESSource -parseKesSourceFilePath = asum - [ KESKeyFilePath <$> - strOption - ( long "shelley-kes-key" - <> metavar "FILEPATH" - <> help "Path to the KES signing key." - <> completer (bashCompleter "file") - ) - , KESAgentSocketPath <$> - strOption - ( long "shelley-kes-agent-socket" - <> metavar "SOCKET_FILEPATH" - <> help "Path to the KES Agent socket" - <> completer (bashCompleter "file") - ) - ] - -parseVrfKeyFilePath :: Parser FilePath -parseVrfKeyFilePath = - strOption - ( long "shelley-vrf-key" - <> metavar "FILEPATH" - <> help "Path to the VRF signing key." - <> completer (bashCompleter "file") - ) - -parseStartAsNonProducingNodeDeprecated :: Parser (Maybe Bool) -parseStartAsNonProducingNodeDeprecated = - flag Nothing (Just True) $ mconcat - [ long "non-producing-node" - , help $ mconcat - [ "DEPRECATED, use --start-as-non-producing-node instead. " - , "This option will be removed in one of the future versions of cardano-node." - ] - , hidden - ] - --- | A parser which returns `Nothing` or `Just True`; the default value is set --- in `defaultPartialNodeConfiguration`. This allows to set this option either --- in the configuration file or as command line flag. -parseStartAsNonProducingNode :: Parser (Maybe Bool) -parseStartAsNonProducingNode = - flag Nothing (Just True) $ mconcat - [ long "start-as-non-producing-node" - , help $ mconcat - [ "Start the node as a non block producing node even if " - , "credentials are specified." - ] - ] - -parseRpcConfig :: Parser PartialRpcConfig -parseRpcConfig = do - isEnabled <- lastOption parseRpcToggle - rpcEndpoint <- lastOption $ parseRpcUnixSocketEndpoint <|> parseRpcHttpEndpoint - pure (mempty :: PartialRpcConfig){isEnabled, rpcEndpoint} - where - parseRpcToggle :: Parser Bool - parseRpcToggle = - Opt.flag' True $ mconcat - [ long "grpc-enable" - , help "[EXPERIMENTAL] Enable node gRPC endpoint." - ] - - parseRpcUnixSocketEndpoint :: Parser RpcEndpoint - parseRpcUnixSocketEndpoint = - RpcEndpointUnixSocket <$> - parseSocketPath - "grpc-socket-path" - "[EXPERIMENTAL] gRPC unix socket path. Defaults to rpc.sock in the same directory as the node socket. Mutually exclusive with --grpc-listen-port." - - parseRpcHttpEndpoint :: Parser RpcEndpoint - parseRpcHttpEndpoint = - mkHttpEndpoint - <$> Opt.optional parseRpcListenAddress - <*> Opt.option readPortNumber (mconcat - [ long "grpc-listen-port" - , metavar "PORT" - , help "[EXPERIMENTAL] TCP port the gRPC server listens on. When set, the gRPC server listens over HTTP/2 without TLS, or HTTP/2 over TLS if --grpc-tls-certificate is given, instead of a unix socket. Mutually exclusive with --grpc-socket-path." - ]) - <*> Opt.optional parseRpcTlsFiles - - mkHttpEndpoint :: Maybe IP -> PortNumber -> Maybe RpcTlsFiles -> RpcEndpoint - mkHttpEndpoint mAddress port = - maybe (RpcEndpointHttp address port) (RpcEndpointHttps address port) - where - address = fromMaybe defaultRpcListenAddress mAddress - - parseRpcListenAddress :: Parser IP - parseRpcListenAddress = - unNodeHostIPAddress <$> Opt.option (eitherReader parseNodeHostIPAddress) (mconcat - [ long "grpc-listen-address" - , metavar "IP-ADDRESS" - , help "[EXPERIMENTAL] IP address the gRPC server binds to. Requires --grpc-listen-port. Defaults to 127.0.0.1." - ]) - - parseRpcTlsFiles :: Parser RpcTlsFiles - parseRpcTlsFiles = - RpcTlsFiles - <$> parseRpcTlsCertificateFile - <*> parseRpcTlsPrivateKeyFile - <*> Opt.many parseRpcTlsChainCertificateFile - - parseRpcTlsCertificateFile :: Parser (File TlsCertificate 'In) - parseRpcTlsCertificateFile = - strOption $ mconcat - [ long "grpc-tls-certificate" - , metavar "FILEPATH" - , help "[EXPERIMENTAL] Path to the TLS certificate file. Enables TLS; requires --grpc-tls-private-key and --grpc-listen-port." - , completer (bashCompleter "file") - ] - - parseRpcTlsPrivateKeyFile :: Parser (File TlsPrivateKey 'In) - parseRpcTlsPrivateKeyFile = - strOption $ mconcat - [ long "grpc-tls-private-key" - , metavar "FILEPATH" - , help "[EXPERIMENTAL] Path to the TLS private key file. Requires --grpc-tls-certificate and --grpc-listen-port." - , completer (bashCompleter "file") - ] - - parseRpcTlsChainCertificateFile :: Parser (File TlsCertificate 'In) - parseRpcTlsChainCertificateFile = - strOption $ mconcat - [ long "grpc-tls-chain-certificate" - , metavar "FILEPATH" - , help "[EXPERIMENTAL] Path to an additional certificate to include in the TLS chain. May be given multiple times. Requires --grpc-tls-certificate and --grpc-tls-private-key." - , completer (bashCompleter "file") - ] - -readPortNumber :: Opt.ReadM PortNumber -readPortNumber = Opt.eitherReader parsePortNumber - --- | Parse a port number, rejecting values outside the 0 - 65535 range. --- Decimal digits only - hex/octal notation, a sign, and surrounding --- whitespace (all otherwise accepted by a plain 'Integer' read) are rejected. -parsePortNumber :: String -> Either String PortNumber -parsePortNumber raw - | not (all isDigit raw) = Left $ "Not a valid port number: " <> raw - | otherwise = - case readMaybe raw :: Maybe Integer of - Just port - | 0 <= port && port <= 65535 -> Right $ fromIntegral port - | otherwise -> Left $ "Port number out of range (0 - 65535): " <> show port - Nothing -> Left $ "Not a valid port number: " <> raw - -- | Produce just the brief help header for a given CLI option parser, -- without the options. parserHelpHeader :: String -> Opt.Parser a -> OptI.Doc From aa65920636fdc996a4ecd2bf0fb84f44880273ba Mon Sep 17 00:00:00 2001 From: Federico Mastellone <210034+fmaste@users.noreply.github.com> Date: Mon, 12 Oct 2026 13:28:00 +0000 Subject: [PATCH 08/45] wb | add epoch 638 (Van Rossem) to epoch-timeline.json and move the default epoch to it --- .../data/genesis/epoch-timeline.json | 419 +++++++++++++++++- .../data/genesis/epoch-timeline.md | 1 + .../Benchmarking/Profile/Vocabulary.hs | 7 +- 3 files changed, 423 insertions(+), 4 deletions(-) diff --git a/bench/cardano-profile/data/genesis/epoch-timeline.json b/bench/cardano-profile/data/genesis/epoch-timeline.json index 0ae71469945..45b44fe1ee9 100644 --- a/bench/cardano-profile/data/genesis/epoch-timeline.json +++ b/bench/cardano-profile/data/genesis/epoch-timeline.json @@ -1871,6 +1871,423 @@ } }, "cost_model": {} + }, + "638": { + "epoch": 638, + "description": "Van Rossem HF (protocol version 11.0). Carries the budget increase, the protocol-version bump and the Plutus V1/V2/V3 cost-model changes, all taken verbatim from data/genesis/overlays/v11-preview.json, which is kept as an opt-in overlay for profiles that stay on an earlier pparamsEpoch. Two governance actions are involved: the hard-fork initiation c21b00f90f18fce4003edf42b0b0d455126e01c946e80cc5341a9f9750caf795#0 and the ParameterChange c82f3834898e4d70d3605fa0d92ffe31345701075b107a54309c1525f9581f62#0 (proposed at epoch 633). This entry assumes BOTH enacted at epoch 638, which is the epoch Profile.hs and Profile/Genesis.hs already name for the cost-model appends; if the two actions in fact enacted at different epochs, split this entry in two.", + "epoch_params": { + "shelley": { + "protocolParams": { + "protocolVersion": { + "major": 11 + } + } + }, + "alonzo": { + "maxTxExUnits": { + "exUnitsMem": 16500000 + }, + "maxBlockExUnits": { + "exUnitsMem": 72000000 + } + } + }, + "cost_model": { + "plutusV1": { + "andByteString-cpu-arguments-intercept": 100181, + "andByteString-cpu-arguments-slope1": 726, + "andByteString-cpu-arguments-slope2": 719, + "andByteString-memory-arguments-intercept": 0, + "andByteString-memory-arguments-slope": 1, + "blake2b_224-cpu-arguments-intercept": 207616, + "blake2b_224-cpu-arguments-slope": 8310, + "blake2b_224-memory-arguments": 4, + "bls12_381_G1_add-cpu-arguments": 962335, + "bls12_381_G1_add-memory-arguments": 18, + "bls12_381_G1_compress-cpu-arguments": 2780678, + "bls12_381_G1_compress-memory-arguments": 6, + "bls12_381_G1_equal-cpu-arguments": 442008, + "bls12_381_G1_equal-memory-arguments": 1, + "bls12_381_G1_hashToGroup-cpu-arguments-intercept": 52538055, + "bls12_381_G1_hashToGroup-cpu-arguments-slope": 3756, + "bls12_381_G1_hashToGroup-memory-arguments": 18, + "bls12_381_G1_multiScalarMul-cpu-arguments-intercept": 321837444, + "bls12_381_G1_multiScalarMul-cpu-arguments-slope": 25087669, + "bls12_381_G1_multiScalarMul-memory-arguments": 18, + "bls12_381_G1_neg-cpu-arguments": 267929, + "bls12_381_G1_neg-memory-arguments": 18, + "bls12_381_G1_scalarMul-cpu-arguments-intercept": 76433006, + "bls12_381_G1_scalarMul-cpu-arguments-slope": 8868, + "bls12_381_G1_scalarMul-memory-arguments": 18, + "bls12_381_G1_uncompress-cpu-arguments": 52948122, + "bls12_381_G1_uncompress-memory-arguments": 18, + "bls12_381_G2_add-cpu-arguments": 1995836, + "bls12_381_G2_add-memory-arguments": 36, + "bls12_381_G2_compress-cpu-arguments": 3227919, + "bls12_381_G2_compress-memory-arguments": 12, + "bls12_381_G2_equal-cpu-arguments": 901022, + "bls12_381_G2_equal-memory-arguments": 1, + "bls12_381_G2_hashToGroup-cpu-arguments-intercept": 166917843, + "bls12_381_G2_hashToGroup-cpu-arguments-slope": 4307, + "bls12_381_G2_hashToGroup-memory-arguments": 36, + "bls12_381_G2_multiScalarMul-cpu-arguments-intercept": 617887431, + "bls12_381_G2_multiScalarMul-cpu-arguments-slope": 67302824, + "bls12_381_G2_multiScalarMul-memory-arguments": 36, + "bls12_381_G2_neg-cpu-arguments": 284546, + "bls12_381_G2_neg-memory-arguments": 36, + "bls12_381_G2_scalarMul-cpu-arguments-intercept": 158221314, + "bls12_381_G2_scalarMul-cpu-arguments-slope": 26549, + "bls12_381_G2_scalarMul-memory-arguments": 36, + "bls12_381_G2_uncompress-cpu-arguments": 74698472, + "bls12_381_G2_uncompress-memory-arguments": 36, + "bls12_381_finalVerify-cpu-arguments": 333849714, + "bls12_381_finalVerify-memory-arguments": 1, + "bls12_381_millerLoop-cpu-arguments": 254006273, + "bls12_381_millerLoop-memory-arguments": 72, + "bls12_381_mulMlResult-cpu-arguments": 2174038, + "bls12_381_mulMlResult-memory-arguments": 72, + "byteStringToInteger-cpu-arguments-c0": 1006041, + "byteStringToInteger-cpu-arguments-c1": 43623, + "byteStringToInteger-cpu-arguments-c2": 251, + "byteStringToInteger-memory-arguments-intercept": 0, + "byteStringToInteger-memory-arguments-slope": 1, + "cekCaseCost-exBudgetCPU": 16000, + "cekCaseCost-exBudgetMemory": 100, + "cekConstrCost-exBudgetCPU": 16000, + "cekConstrCost-exBudgetMemory": 100, + "complementByteString-cpu-arguments-intercept": 107878, + "complementByteString-cpu-arguments-slope": 680, + "complementByteString-memory-arguments-intercept": 0, + "complementByteString-memory-arguments-slope": 1, + "countSetBits-cpu-arguments-intercept": 107490, + "countSetBits-cpu-arguments-slope": 3298, + "countSetBits-memory-arguments": 1, + "dropList-cpu-arguments-intercept": 116711, + "dropList-cpu-arguments-slope": 1957, + "dropList-memory-arguments": 4, + "equalsByteString-cpu-arguments-constant": 30623, + "equalsByteString-cpu-arguments-intercept": 28755, + "equalsByteString-cpu-arguments-slope": 75, + "expModInteger-cpu-arguments-coefficient00": 607153, + "expModInteger-cpu-arguments-coefficient11": 231697, + "expModInteger-cpu-arguments-coefficient12": 53144, + "expModInteger-memory-arguments-intercept": 0, + "expModInteger-memory-arguments-slope": 1, + "findFirstSetBit-cpu-arguments-intercept": 106057, + "findFirstSetBit-cpu-arguments-slope": 655, + "findFirstSetBit-memory-arguments": 1, + "indexArray-cpu-arguments": 232010, + "indexArray-memory-arguments": 32, + "insertCoin-cpu-arguments-intercept": 356924, + "insertCoin-cpu-arguments-slope": 18413, + "insertCoin-memory-arguments-intercept": 45, + "insertCoin-memory-arguments-slope": 21, + "integerToByteString-cpu-arguments-c0": 1293828, + "integerToByteString-cpu-arguments-c1": 28716, + "integerToByteString-cpu-arguments-c2": 63, + "integerToByteString-memory-arguments-intercept": 0, + "integerToByteString-memory-arguments-slope": 1, + "keccak_256-cpu-arguments-intercept": 2261318, + "keccak_256-cpu-arguments-slope": 64571, + "keccak_256-memory-arguments": 4, + "lengthOfArray-cpu-arguments": 231883, + "lengthOfArray-memory-arguments": 10, + "listToArray-cpu-arguments-intercept": 1000, + "listToArray-cpu-arguments-slope": 24838, + "listToArray-memory-arguments-intercept": 7, + "listToArray-memory-arguments-slope": 1, + "lookupCoin-cpu-arguments-intercept": 219951, + "lookupCoin-cpu-arguments-slope": 9444, + "lookupCoin-memory-arguments": 1, + "orByteString-cpu-arguments-intercept": 100181, + "orByteString-cpu-arguments-slope1": 726, + "orByteString-cpu-arguments-slope2": 719, + "orByteString-memory-arguments-intercept": 0, + "orByteString-memory-arguments-slope": 1, + "readBit-cpu-arguments": 95336, + "readBit-memory-arguments": 1, + "replicateByte-cpu-arguments-intercept": 180194, + "replicateByte-cpu-arguments-slope": 159, + "replicateByte-memory-arguments-intercept": 1, + "replicateByte-memory-arguments-slope": 1, + "ripemd_160-cpu-arguments-intercept": 1964219, + "ripemd_160-cpu-arguments-slope": 24520, + "ripemd_160-memory-arguments": 3, + "rotateByteString-cpu-arguments-intercept": 159378, + "rotateByteString-cpu-arguments-slope": 8813, + "rotateByteString-memory-arguments-intercept": 0, + "rotateByteString-memory-arguments-slope": 1, + "scaleValue-cpu-arguments-intercept": 1000, + "scaleValue-cpu-arguments-slope": 277577, + "scaleValue-memory-arguments-intercept": 12, + "scaleValue-memory-arguments-slope": 21, + "serialiseData-cpu-arguments-intercept": 955506, + "serialiseData-cpu-arguments-slope": 213312, + "serialiseData-memory-arguments-intercept": 0, + "serialiseData-memory-arguments-slope": 2, + "shiftByteString-cpu-arguments-intercept": 158519, + "shiftByteString-cpu-arguments-slope": 8942, + "shiftByteString-memory-arguments-intercept": 0, + "shiftByteString-memory-arguments-slope": 1, + "unValueData-cpu-arguments-c0": 1000, + "unValueData-cpu-arguments-c1": 95933, + "unValueData-cpu-arguments-c2": 1, + "unValueData-memory-arguments-intercept": 1, + "unValueData-memory-arguments-slope": 11, + "unionValue-cpu-arguments-c00": 1000, + "unionValue-cpu-arguments-c01": 183150, + "unionValue-cpu-arguments-c10": 172116, + "unionValue-cpu-arguments-c11": 6, + "unionValue-memory-arguments-intercept": 24, + "unionValue-memory-arguments-slope": 21, + "valueContains-cpu-arguments-constant": 213283, + "valueContains-cpu-arguments-model-arguments-intercept": 618401, + "valueContains-cpu-arguments-model-arguments-slope1": 1998, + "valueContains-cpu-arguments-model-arguments-slope2": 28258, + "valueContains-memory-arguments": 1, + "valueData-cpu-arguments-intercept": 1000, + "valueData-cpu-arguments-slope": 38159, + "valueData-memory-arguments-intercept": 2, + "valueData-memory-arguments-slope": 22, + "verifyEcdsaSecp256k1Signature-cpu-arguments": 43053543, + "verifyEcdsaSecp256k1Signature-memory-arguments": 10, + "verifySchnorrSecp256k1Signature-cpu-arguments-intercept": 43574283, + "verifySchnorrSecp256k1Signature-cpu-arguments-slope": 26308, + "verifySchnorrSecp256k1Signature-memory-arguments": 10, + "writeBits-cpu-arguments-intercept": 281145, + "writeBits-cpu-arguments-slope": 18848, + "writeBits-memory-arguments-intercept": 0, + "writeBits-memory-arguments-slope": 1, + "xorByteString-cpu-arguments-intercept": 100181, + "xorByteString-cpu-arguments-slope1": 726, + "xorByteString-cpu-arguments-slope2": 719, + "xorByteString-memory-arguments-intercept": 0, + "xorByteString-memory-arguments-slope": 1 + }, + "plutusV2": { + "andByteString-cpu-arguments-intercept": 100181, + "andByteString-cpu-arguments-slope1": 726, + "andByteString-cpu-arguments-slope2": 719, + "andByteString-memory-arguments-intercept": 0, + "andByteString-memory-arguments-slope": 1, + "blake2b_224-cpu-arguments-intercept": 207616, + "blake2b_224-cpu-arguments-slope": 8310, + "blake2b_224-memory-arguments": 4, + "bls12_381_G1_add-cpu-arguments": 962335, + "bls12_381_G1_add-memory-arguments": 18, + "bls12_381_G1_compress-cpu-arguments": 2780678, + "bls12_381_G1_compress-memory-arguments": 6, + "bls12_381_G1_equal-cpu-arguments": 442008, + "bls12_381_G1_equal-memory-arguments": 1, + "bls12_381_G1_hashToGroup-cpu-arguments-intercept": 52538055, + "bls12_381_G1_hashToGroup-cpu-arguments-slope": 3756, + "bls12_381_G1_hashToGroup-memory-arguments": 18, + "bls12_381_G1_multiScalarMul-cpu-arguments-intercept": 321837444, + "bls12_381_G1_multiScalarMul-cpu-arguments-slope": 25087669, + "bls12_381_G1_multiScalarMul-memory-arguments": 18, + "bls12_381_G1_neg-cpu-arguments": 267929, + "bls12_381_G1_neg-memory-arguments": 18, + "bls12_381_G1_scalarMul-cpu-arguments-intercept": 76433006, + "bls12_381_G1_scalarMul-cpu-arguments-slope": 8868, + "bls12_381_G1_scalarMul-memory-arguments": 18, + "bls12_381_G1_uncompress-cpu-arguments": 52948122, + "bls12_381_G1_uncompress-memory-arguments": 18, + "bls12_381_G2_add-cpu-arguments": 1995836, + "bls12_381_G2_add-memory-arguments": 36, + "bls12_381_G2_compress-cpu-arguments": 3227919, + "bls12_381_G2_compress-memory-arguments": 12, + "bls12_381_G2_equal-cpu-arguments": 901022, + "bls12_381_G2_equal-memory-arguments": 1, + "bls12_381_G2_hashToGroup-cpu-arguments-intercept": 166917843, + "bls12_381_G2_hashToGroup-cpu-arguments-slope": 4307, + "bls12_381_G2_hashToGroup-memory-arguments": 36, + "bls12_381_G2_multiScalarMul-cpu-arguments-intercept": 617887431, + "bls12_381_G2_multiScalarMul-cpu-arguments-slope": 67302824, + "bls12_381_G2_multiScalarMul-memory-arguments": 36, + "bls12_381_G2_neg-cpu-arguments": 284546, + "bls12_381_G2_neg-memory-arguments": 36, + "bls12_381_G2_scalarMul-cpu-arguments-intercept": 158221314, + "bls12_381_G2_scalarMul-cpu-arguments-slope": 26549, + "bls12_381_G2_scalarMul-memory-arguments": 36, + "bls12_381_G2_uncompress-cpu-arguments": 74698472, + "bls12_381_G2_uncompress-memory-arguments": 36, + "bls12_381_finalVerify-cpu-arguments": 333849714, + "bls12_381_finalVerify-memory-arguments": 1, + "bls12_381_millerLoop-cpu-arguments": 254006273, + "bls12_381_millerLoop-memory-arguments": 72, + "bls12_381_mulMlResult-cpu-arguments": 2174038, + "bls12_381_mulMlResult-memory-arguments": 72, + "byteStringToInteger-cpu-arguments-c0": 1006041, + "byteStringToInteger-cpu-arguments-c1": 43623, + "byteStringToInteger-cpu-arguments-c2": 251, + "byteStringToInteger-memory-arguments-intercept": 0, + "byteStringToInteger-memory-arguments-slope": 1, + "cekCaseCost-exBudgetCPU": 16000, + "cekCaseCost-exBudgetMemory": 100, + "cekConstrCost-exBudgetCPU": 16000, + "cekConstrCost-exBudgetMemory": 100, + "complementByteString-cpu-arguments-intercept": 107878, + "complementByteString-cpu-arguments-slope": 680, + "complementByteString-memory-arguments-intercept": 0, + "complementByteString-memory-arguments-slope": 1, + "countSetBits-cpu-arguments-intercept": 107490, + "countSetBits-cpu-arguments-slope": 3298, + "countSetBits-memory-arguments": 1, + "dropList-cpu-arguments-intercept": 116711, + "dropList-cpu-arguments-slope": 1957, + "dropList-memory-arguments": 4, + "equalsByteString-cpu-arguments-constant": 30623, + "equalsByteString-cpu-arguments-intercept": 28755, + "equalsByteString-cpu-arguments-slope": 75, + "expModInteger-cpu-arguments-coefficient00": 607153, + "expModInteger-cpu-arguments-coefficient11": 231697, + "expModInteger-cpu-arguments-coefficient12": 53144, + "expModInteger-memory-arguments-intercept": 0, + "expModInteger-memory-arguments-slope": 1, + "findFirstSetBit-cpu-arguments-intercept": 106057, + "findFirstSetBit-cpu-arguments-slope": 655, + "findFirstSetBit-memory-arguments": 1, + "indexArray-cpu-arguments": 232010, + "indexArray-memory-arguments": 32, + "insertCoin-cpu-arguments-intercept": 356924, + "insertCoin-cpu-arguments-slope": 18413, + "insertCoin-memory-arguments-intercept": 45, + "insertCoin-memory-arguments-slope": 21, + "integerToByteString-cpu-arguments-c0": 1293828, + "integerToByteString-cpu-arguments-c1": 28716, + "integerToByteString-cpu-arguments-c2": 63, + "integerToByteString-memory-arguments-intercept": 0, + "integerToByteString-memory-arguments-slope": 1, + "keccak_256-cpu-arguments-intercept": 2261318, + "keccak_256-cpu-arguments-slope": 64571, + "keccak_256-memory-arguments": 4, + "lengthOfArray-cpu-arguments": 231883, + "lengthOfArray-memory-arguments": 10, + "listToArray-cpu-arguments-intercept": 1000, + "listToArray-cpu-arguments-slope": 24838, + "listToArray-memory-arguments-intercept": 7, + "listToArray-memory-arguments-slope": 1, + "lookupCoin-cpu-arguments-intercept": 219951, + "lookupCoin-cpu-arguments-slope": 9444, + "lookupCoin-memory-arguments": 1, + "orByteString-cpu-arguments-intercept": 100181, + "orByteString-cpu-arguments-slope1": 726, + "orByteString-cpu-arguments-slope2": 719, + "orByteString-memory-arguments-intercept": 0, + "orByteString-memory-arguments-slope": 1, + "readBit-cpu-arguments": 95336, + "readBit-memory-arguments": 1, + "replicateByte-cpu-arguments-intercept": 180194, + "replicateByte-cpu-arguments-slope": 159, + "replicateByte-memory-arguments-intercept": 1, + "replicateByte-memory-arguments-slope": 1, + "ripemd_160-cpu-arguments-intercept": 1964219, + "ripemd_160-cpu-arguments-slope": 24520, + "ripemd_160-memory-arguments": 3, + "rotateByteString-cpu-arguments-intercept": 159378, + "rotateByteString-cpu-arguments-slope": 8813, + "rotateByteString-memory-arguments-intercept": 0, + "rotateByteString-memory-arguments-slope": 1, + "scaleValue-cpu-arguments-intercept": 1000, + "scaleValue-cpu-arguments-slope": 277577, + "scaleValue-memory-arguments-intercept": 12, + "scaleValue-memory-arguments-slope": 21, + "shiftByteString-cpu-arguments-intercept": 158519, + "shiftByteString-cpu-arguments-slope": 8942, + "shiftByteString-memory-arguments-intercept": 0, + "shiftByteString-memory-arguments-slope": 1, + "unValueData-cpu-arguments-c0": 1000, + "unValueData-cpu-arguments-c1": 95933, + "unValueData-cpu-arguments-c2": 1, + "unValueData-memory-arguments-intercept": 1, + "unValueData-memory-arguments-slope": 11, + "unionValue-cpu-arguments-c00": 1000, + "unionValue-cpu-arguments-c01": 183150, + "unionValue-cpu-arguments-c10": 172116, + "unionValue-cpu-arguments-c11": 6, + "unionValue-memory-arguments-intercept": 24, + "unionValue-memory-arguments-slope": 21, + "valueContains-cpu-arguments-constant": 213283, + "valueContains-cpu-arguments-model-arguments-intercept": 618401, + "valueContains-cpu-arguments-model-arguments-slope1": 1998, + "valueContains-cpu-arguments-model-arguments-slope2": 28258, + "valueContains-memory-arguments": 1, + "valueData-cpu-arguments-intercept": 1000, + "valueData-cpu-arguments-slope": 38159, + "valueData-memory-arguments-intercept": 2, + "valueData-memory-arguments-slope": 22, + "writeBits-cpu-arguments-intercept": 281145, + "writeBits-cpu-arguments-slope": 18848, + "writeBits-memory-arguments-intercept": 0, + "writeBits-memory-arguments-slope": 1, + "xorByteString-cpu-arguments-intercept": 100181, + "xorByteString-cpu-arguments-slope1": 726, + "xorByteString-cpu-arguments-slope2": 719, + "xorByteString-memory-arguments-intercept": 0, + "xorByteString-memory-arguments-slope": 1 + }, + "plutusV3": { + "bls12_381_G1_multiScalarMul-cpu-arguments-intercept": 321837444, + "bls12_381_G1_multiScalarMul-cpu-arguments-slope": 25087669, + "bls12_381_G1_multiScalarMul-memory-arguments": 18, + "bls12_381_G2_multiScalarMul-cpu-arguments-intercept": 617887431, + "bls12_381_G2_multiScalarMul-cpu-arguments-slope": 67302824, + "bls12_381_G2_multiScalarMul-memory-arguments": 36, + "divideInteger-cpu-arguments-model-arguments-c11": 960, + "dropList-cpu-arguments-intercept": 116711, + "dropList-cpu-arguments-slope": 1957, + "dropList-memory-arguments": 4, + "equalsByteString-cpu-arguments-constant": 30623, + "equalsByteString-cpu-arguments-intercept": 28755, + "equalsByteString-cpu-arguments-slope": 75, + "expModInteger-cpu-arguments-coefficient00": 607153, + "expModInteger-cpu-arguments-coefficient11": 231697, + "expModInteger-cpu-arguments-coefficient12": 53144, + "expModInteger-memory-arguments-intercept": 0, + "expModInteger-memory-arguments-slope": 1, + "indexArray-cpu-arguments": 232010, + "indexArray-memory-arguments": 32, + "insertCoin-cpu-arguments-intercept": 356924, + "insertCoin-cpu-arguments-slope": 18413, + "insertCoin-memory-arguments-intercept": 45, + "insertCoin-memory-arguments-slope": 21, + "lengthOfArray-cpu-arguments": 231883, + "lengthOfArray-memory-arguments": 10, + "listToArray-cpu-arguments-intercept": 1000, + "listToArray-cpu-arguments-slope": 24838, + "listToArray-memory-arguments-intercept": 7, + "listToArray-memory-arguments-slope": 1, + "lookupCoin-cpu-arguments-intercept": 219951, + "lookupCoin-cpu-arguments-slope": 9444, + "lookupCoin-memory-arguments": 1, + "modInteger-cpu-arguments-model-arguments-c11": 960, + "quotientInteger-cpu-arguments-model-arguments-c11": 960, + "remainderInteger-cpu-arguments-model-arguments-c11": 960, + "scaleValue-cpu-arguments-intercept": 1000, + "scaleValue-cpu-arguments-slope": 277577, + "scaleValue-memory-arguments-intercept": 12, + "scaleValue-memory-arguments-slope": 21, + "unValueData-cpu-arguments-c0": 1000, + "unValueData-cpu-arguments-c1": 95933, + "unValueData-cpu-arguments-c2": 1, + "unValueData-memory-arguments-intercept": 1, + "unValueData-memory-arguments-slope": 11, + "unionValue-cpu-arguments-c00": 1000, + "unionValue-cpu-arguments-c01": 183150, + "unionValue-cpu-arguments-c10": 172116, + "unionValue-cpu-arguments-c11": 6, + "unionValue-memory-arguments-intercept": 24, + "unionValue-memory-arguments-slope": 21, + "valueContains-cpu-arguments-constant": 213283, + "valueContains-cpu-arguments-model-arguments-intercept": 618401, + "valueContains-cpu-arguments-model-arguments-slope1": 1998, + "valueContains-cpu-arguments-model-arguments-slope2": 28258, + "valueContains-memory-arguments": 1, + "valueData-cpu-arguments-intercept": 1000, + "valueData-cpu-arguments-slope": 38159, + "valueData-memory-arguments-intercept": 2, + "valueData-memory-arguments-slope": 22 + } + } } } - diff --git a/bench/cardano-profile/data/genesis/epoch-timeline.md b/bench/cardano-profile/data/genesis/epoch-timeline.md index d6c898e8a52..9058e347506 100644 --- a/bench/cardano-profile/data/genesis/epoch-timeline.md +++ b/bench/cardano-profile/data/genesis/epoch-timeline.md @@ -18,6 +18,7 @@ Cross-reference: https://github.com/cardano-foundation/CIPs/blob/master/CIP-0059 | 2023/02 | Goguen | Babbage | 84844885 | 394 | 8,0 | Praos | Ouroboros Praos | Valentine HF | | 2024/09 | Voltaire | Conway | 133660855 | 507 | 9,0 | Praos | Ouroboros Genesis/Praos | Chang HF | | 2025/01 | Voltaire | Conway | 146620809 | 537 | 10,0 | Praos | Ouroboros Genesis/Praos | Plomin HF | +| 2026/06 | Voltaire | Conway | 190252800 | 638 | 11,0 | Praos | Ouroboros Genesis/Praos | Van Rossem HF | ## Cost-model parameter timeline diff --git a/bench/cardano-profile/src/Cardano/Benchmarking/Profile/Vocabulary.hs b/bench/cardano-profile/src/Cardano/Benchmarking/Profile/Vocabulary.hs index 0d394100ccc..43088128f3d 100644 --- a/bench/cardano-profile/src/Cardano/Benchmarking/Profile/Vocabulary.hs +++ b/bench/cardano-profile/src/Cardano/Benchmarking/Profile/Vocabulary.hs @@ -96,7 +96,7 @@ timescaleDevops = -- See: data/genesis/epoch-timeline.json -- should always reference the latest entry in data/genesis/epoch-timeline.json genesisVariantLatest :: Types.Profile -> Types.Profile -genesisVariantLatest = P.pparamsEpoch 537 +genesisVariantLatest = P.pparamsEpoch 638 -- references the latest Babbage epoch in data/genesis/epoch-timeline.json genesisVariantBabbageLatest :: Types.Profile -> Types.Profile @@ -108,7 +108,7 @@ genesisVariantPreVoltaire = genesisVariantBabbageLatest . P.v8Preview -- First Conway epoch in data/genesis/epoch-timeline.json; implicitly includes v8Preview and v9Prievew already genesisVariantVoltaire :: Types.Profile -> Types.Profile -genesisVariantVoltaire = genesisVariantLatest +genesisVariantVoltaire = P.pparamsEpoch 537 -- `genesisVariantVoltaire` with a reduced 64k block size (the "blocksize64k" overlay). genesisVariantVoltaire64k :: Types.Profile -> Types.Profile @@ -328,4 +328,5 @@ plutusTypeExpMod = , KeyMap.fromList [("int", Aeson.Number 3.0)] , KeyMap.fromList [("int", Aeson.Number 2305843009213693951.0)] ] - . P.txFee 1275000 \ No newline at end of file + . P.txFee 1275000 + From d1f424ba318dd52e7646395cd8bbb66cc955b6f3 Mon Sep 17 00:00:00 2001 From: Federico Mastellone <210034+fmaste@users.noreply.github.com> Date: Mon, 12 Oct 2026 13:33:34 +0000 Subject: [PATCH 09/45] wb | add Leios genesis (Epoch 638 Van Rossem / PV11 + PV12 preview) --- bench/cardano-profile/data/all-profiles.json | 531 ++++++++++++++++++ .../data/genesis/overlays/v12-preview.json | 279 ++++++++- .../Benchmarking/Profile/Vocabulary.hs | 9 +- 3 files changed, 817 insertions(+), 2 deletions(-) diff --git a/bench/cardano-profile/data/all-profiles.json b/bench/cardano-profile/data/all-profiles.json index 4c8237ac93d..965e8c4e2c2 100644 --- a/bench/cardano-profile/data/all-profiles.json +++ b/bench/cardano-profile/data/all-profiles.json @@ -38101,8 +38101,275 @@ "delegator_coin": 0, "delegators": 0, "dijkstra": { + "leiosAnnouncementPeriodLength": 1000, + "leiosCommitteeSize": 900, + "leiosDiffusionPeriodLength": 7000, + "leiosQuorumStakeThreshold": 0.75, + "leiosVotePeriodLength": 4000, + "maxEndorserBlockExecutionUnits": { + "memory": 310000000, + "steps": 100000000000 + }, + "maxEndorserBlockReferencesSize": 100000, + "maxEndorserBlockTxsSize": 1000000, + "maxPledgeLeverage": null, "maxRefScriptSizePerBlock": 1048576, + "maxRefScriptSizePerEndorserBlock": 4000000, "maxRefScriptSizePerTx": 204800, + "minPoolMargin": 1.5e-2, + "plutusV4CostModel": [ + 100788, + 420, + 1, + 1, + 1000, + 173, + 0, + 1, + 1000, + 59957, + 4, + 1, + 11183, + 32, + 201305, + 8356, + 4, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 100, + 100, + 16000, + 100, + 94375, + 32, + 132994, + 32, + 61462, + 4, + 72010, + 178, + 0, + 1, + 22151, + 32, + 91189, + 769, + 4, + 2, + 85848, + 123203, + 7305, + -900, + 1716, + 960, + 57, + 85848, + 0, + 1, + 1, + 1000, + 42921, + 4, + 2, + 30623, + 28755, + 75, + 1, + 898148, + 27279, + 1, + 51775, + 558, + 1, + 39184, + 1000, + 60594, + 1, + 141895, + 32, + 83150, + 32, + 15299, + 32, + 76049, + 1, + 13169, + 4, + 22100, + 10, + 28999, + 74, + 1, + 28999, + 74, + 1, + 43285, + 552, + 1, + 44749, + 541, + 1, + 33852, + 32, + 68246, + 32, + 72362, + 32, + 7243, + 32, + 7391, + 32, + 11546, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 960, + 57, + 85848, + 0, + 1, + 90434, + 519, + 0, + 1, + 74433, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 960, + 57, + 85848, + 0, + 1, + 1, + 85848, + 123203, + 7305, + -900, + 1716, + 960, + 57, + 85848, + 0, + 1, + 955506, + 213312, + 0, + 2, + 270652, + 22588, + 4, + 1457325, + 64566, + 4, + 20467, + 1, + 4, + 0, + 141992, + 32, + 100788, + 420, + 1, + 1, + 81663, + 32, + 59498, + 32, + 20142, + 32, + 24588, + 32, + 20744, + 32, + 25933, + 32, + 24623, + 32, + 43053543, + 10, + 53384111, + 14333, + 10, + 43574283, + 26308, + 10, + 16000, + 100, + 16000, + 100, + 962335, + 18, + 2780678, + 6, + 442008, + 1, + 52538055, + 3756, + 18, + 267929, + 18, + 76433006, + 8868, + 18, + 52948122, + 18, + 1995836, + 36, + 3227919, + 12, + 901022, + 1, + 166917843, + 4307, + 36, + 284546, + 36, + 158221314, + 26549, + 36, + 74698472, + 36, + 333849714, + 1, + 254006273, + 72, + 2174038, + 72, + 2261318, + 64571, + 4, + 207616, + 8310, + 4, + 1293828, + 28716, + 63, + 0, + 1, + 1006041, + 43623, + 251, + 0, + 1 + ], "refScriptCostMultiplier": 1.2, "refScriptCostStride": 25600 }, @@ -89828,11 +90095,275 @@ "delegator_coin": 1000000000000000, "delegators": 1000000, "dijkstra": { + "leiosAnnouncementPeriodLength": 1000, "leiosCommitteeSize": 1, + "leiosDiffusionPeriodLength": 7000, + "leiosQuorumStakeThreshold": 0.75, + "leiosVotePeriodLength": 4000, + "maxEndorserBlockExecutionUnits": { + "memory": 310000000, + "steps": 100000000000 + }, "maxEndorserBlockReferencesSize": 1048576, "maxEndorserBlockTxsSize": 7077888, + "maxPledgeLeverage": null, "maxRefScriptSizePerBlock": 1048576, + "maxRefScriptSizePerEndorserBlock": 4000000, "maxRefScriptSizePerTx": 204800, + "minPoolMargin": 1.5e-2, + "plutusV4CostModel": [ + 100788, + 420, + 1, + 1, + 1000, + 173, + 0, + 1, + 1000, + 59957, + 4, + 1, + 11183, + 32, + 201305, + 8356, + 4, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 100, + 100, + 16000, + 100, + 94375, + 32, + 132994, + 32, + 61462, + 4, + 72010, + 178, + 0, + 1, + 22151, + 32, + 91189, + 769, + 4, + 2, + 85848, + 123203, + 7305, + -900, + 1716, + 960, + 57, + 85848, + 0, + 1, + 1, + 1000, + 42921, + 4, + 2, + 30623, + 28755, + 75, + 1, + 898148, + 27279, + 1, + 51775, + 558, + 1, + 39184, + 1000, + 60594, + 1, + 141895, + 32, + 83150, + 32, + 15299, + 32, + 76049, + 1, + 13169, + 4, + 22100, + 10, + 28999, + 74, + 1, + 28999, + 74, + 1, + 43285, + 552, + 1, + 44749, + 541, + 1, + 33852, + 32, + 68246, + 32, + 72362, + 32, + 7243, + 32, + 7391, + 32, + 11546, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 960, + 57, + 85848, + 0, + 1, + 90434, + 519, + 0, + 1, + 74433, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 960, + 57, + 85848, + 0, + 1, + 1, + 85848, + 123203, + 7305, + -900, + 1716, + 960, + 57, + 85848, + 0, + 1, + 955506, + 213312, + 0, + 2, + 270652, + 22588, + 4, + 1457325, + 64566, + 4, + 20467, + 1, + 4, + 0, + 141992, + 32, + 100788, + 420, + 1, + 1, + 81663, + 32, + 59498, + 32, + 20142, + 32, + 24588, + 32, + 20744, + 32, + 25933, + 32, + 24623, + 32, + 43053543, + 10, + 53384111, + 14333, + 10, + 43574283, + 26308, + 10, + 16000, + 100, + 16000, + 100, + 962335, + 18, + 2780678, + 6, + 442008, + 1, + 52538055, + 3756, + 18, + 267929, + 18, + 76433006, + 8868, + 18, + 52948122, + 18, + 1995836, + 36, + 3227919, + 12, + 901022, + 1, + 166917843, + 4307, + 36, + 284546, + 36, + 158221314, + 26549, + 36, + 74698472, + 36, + 333849714, + 1, + 254006273, + 72, + 2174038, + 72, + 2261318, + 64571, + 4, + 207616, + 8310, + 4, + 1293828, + 28716, + 63, + 0, + 1, + 1006041, + 43623, + 251, + 0, + 1 + ], "refScriptCostMultiplier": 1.2, "refScriptCostStride": 25600 }, diff --git a/bench/cardano-profile/data/genesis/overlays/v12-preview.json b/bench/cardano-profile/data/genesis/overlays/v12-preview.json index daf44d50b71..16016d8bc87 100644 --- a/bench/cardano-profile/data/genesis/overlays/v12-preview.json +++ b/bench/cardano-profile/data/genesis/overlays/v12-preview.json @@ -1,5 +1,9 @@ { - "description": "Preview overlay for protocol version 12 (Dijkstra era).", + "description": "Preview overlay for protocol version 12: the Dijkstra era as the leios-prototype branch of cardano-node runs it (ouroboros-leios tag prototype-2026w36). SELF-CONTAINED: the dijkstra block below is the complete Dijkstra genesis, byte for byte what ouroboros-leios ships, so it stands on its own at any pparamsEpoch. Everything Dijkstra lives here and nowhere else -- the epoch timeline carries no dijkstra block, because no mainnet hard fork has set a Dijkstra parameter yet. In particular the four refScript* parameters are NOT a van Rossem change: cardano-node has shipped them unchanged in configuration/cardano/testnet-template-dijkstra.json since 11.0.1, i.e. before PV11, so they are era defaults and belong with the era, not with a protocol version. (v11-preview.json also carries them, left as-is: it is the historical preview of PV11 and predates this split.) plutusV4CostModel is NOT expressible through this file's `cost_model` block: that block is indexed by the canonical name lists in Profile/Genesis.hs, which cover V1/V2/V3 only, and `genesisCostModels` emits PlutusV1/V2/V3 keys only -- a `cost_model.plutusV4` key here would be dropped in silence by the generic FromJSON for CostModel. It goes in the Dijkstra genesis as a raw 251-entry array instead, which is the mainnet-shape slot for V4 exactly as conway.plutusV3CostModel is for V3. Every value below is copied verbatim from the reference files; none were recomputed. For the record, the V4 array is also derivable: it is the mainnet PlutusV3 251-entry array (data/genesis/mainnet/conway-genesis.json) with the seven van Rossem re-prices from v11-preview's cost_model.plutusV3 applied at plutusV3CostNames positions 54, 64, 65, 66, 119, 135 and 146, which means PlutusV4's first 251 canonical names are PlutusV3's first 251.", + "sources": [ + "https://github.com/input-output-hk/ouroboros-leios/blob/main/testnet/config/dijkstra-genesis.json", + "https://github.com/input-output-hk/ouroboros-leios/blob/main/demo/proto-devnet/config/genesis/dijkstra-genesis.json" + ], "epoch_params": { "shelley": { "protocolParams": { @@ -7,6 +11,279 @@ "major": 12 } } + }, + "dijkstra": { + "leiosAnnouncementPeriodLength": 1000, + "leiosVotePeriodLength": 4000, + "leiosDiffusionPeriodLength": 7000, + "leiosCommitteeSize": 900, + "leiosQuorumStakeThreshold": 0.75, + "maxEndorserBlockReferencesSize": 100000, + "maxEndorserBlockTxsSize": 1000000, + "maxEndorserBlockExecutionUnits": { + "memory": 310000000, + "steps": 100000000000 + }, + "maxRefScriptSizePerEndorserBlock": 4000000, + "maxRefScriptSizePerBlock": 1048576, + "maxRefScriptSizePerTx": 204800, + "refScriptCostStride": 25600, + "refScriptCostMultiplier": 1.2, + "maxPledgeLeverage": null, + "minPoolMargin": 0.015, + "plutusV4CostModel": [ + 100788, + 420, + 1, + 1, + 1000, + 173, + 0, + 1, + 1000, + 59957, + 4, + 1, + 11183, + 32, + 201305, + 8356, + 4, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 100, + 100, + 16000, + 100, + 94375, + 32, + 132994, + 32, + 61462, + 4, + 72010, + 178, + 0, + 1, + 22151, + 32, + 91189, + 769, + 4, + 2, + 85848, + 123203, + 7305, + -900, + 1716, + 960, + 57, + 85848, + 0, + 1, + 1, + 1000, + 42921, + 4, + 2, + 30623, + 28755, + 75, + 1, + 898148, + 27279, + 1, + 51775, + 558, + 1, + 39184, + 1000, + 60594, + 1, + 141895, + 32, + 83150, + 32, + 15299, + 32, + 76049, + 1, + 13169, + 4, + 22100, + 10, + 28999, + 74, + 1, + 28999, + 74, + 1, + 43285, + 552, + 1, + 44749, + 541, + 1, + 33852, + 32, + 68246, + 32, + 72362, + 32, + 7243, + 32, + 7391, + 32, + 11546, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 960, + 57, + 85848, + 0, + 1, + 90434, + 519, + 0, + 1, + 74433, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 960, + 57, + 85848, + 0, + 1, + 1, + 85848, + 123203, + 7305, + -900, + 1716, + 960, + 57, + 85848, + 0, + 1, + 955506, + 213312, + 0, + 2, + 270652, + 22588, + 4, + 1457325, + 64566, + 4, + 20467, + 1, + 4, + 0, + 141992, + 32, + 100788, + 420, + 1, + 1, + 81663, + 32, + 59498, + 32, + 20142, + 32, + 24588, + 32, + 20744, + 32, + 25933, + 32, + 24623, + 32, + 43053543, + 10, + 53384111, + 14333, + 10, + 43574283, + 26308, + 10, + 16000, + 100, + 16000, + 100, + 962335, + 18, + 2780678, + 6, + 442008, + 1, + 52538055, + 3756, + 18, + 267929, + 18, + 76433006, + 8868, + 18, + 52948122, + 18, + 1995836, + 36, + 3227919, + 12, + 901022, + 1, + 166917843, + 4307, + 36, + 284546, + 36, + 158221314, + 26549, + 36, + 74698472, + 36, + 333849714, + 1, + 254006273, + 72, + 2174038, + 72, + 2261318, + 64571, + 4, + 207616, + 8310, + 4, + 1293828, + 28716, + 63, + 0, + 1, + 1006041, + 43623, + 251, + 0, + 1 + ] } } } diff --git a/bench/cardano-profile/src/Cardano/Benchmarking/Profile/Vocabulary.hs b/bench/cardano-profile/src/Cardano/Benchmarking/Profile/Vocabulary.hs index 43088128f3d..a5b69e7ab60 100644 --- a/bench/cardano-profile/src/Cardano/Benchmarking/Profile/Vocabulary.hs +++ b/bench/cardano-profile/src/Cardano/Benchmarking/Profile/Vocabulary.hs @@ -10,7 +10,10 @@ module Cardano.Benchmarking.Profile.Vocabulary ( , timescaleCompressed, timescaleSmall, timescaleModel , timescaleMainnet, timescaleDevops -, genesisVariantLatest, genesisVariantPreVoltaire, genesisVariantVoltaire, genesisVariantVoltaire64k +, genesisVariantLeios +, genesisVariantLatest +, genesisVariantPreVoltaire, genesisVariantVoltaire, genesisVariantVoltaire64k + , fundsDefault, fundsDouble, fundsVoting, fundsQuadruple , hosts @@ -93,6 +96,10 @@ timescaleDevops = -- Definition vocabulary: genesis variants. ------------------------------------------- +-- Last epoch in data/genesis/epoch-timeline.json and v12Preview. +genesisVariantLeios :: Types.Profile -> Types.Profile +genesisVariantLeios = genesisVariantLatest . P.v12Preview + -- See: data/genesis/epoch-timeline.json -- should always reference the latest entry in data/genesis/epoch-timeline.json genesisVariantLatest :: Types.Profile -> Types.Profile From 75be6fa6250b80f8c08d3836ee30de45da21d18a Mon Sep 17 00:00:00 2001 From: Federico Mastellone <210034+fmaste@users.noreply.github.com> Date: Mon, 12 Oct 2026 15:40:26 +0000 Subject: [PATCH 10/45] wb | don't invalidate genesis-jq cache by ignoring cardano-cli Dijkstra genesis --- nix/workbench/genesis/genesis-jq.sh | 60 ++++++++--------------------- 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/nix/workbench/genesis/genesis-jq.sh b/nix/workbench/genesis/genesis-jq.sh index 696b8285810..9192ba3cd9a 100644 --- a/nix/workbench/genesis/genesis-jq.sh +++ b/nix/workbench/genesis/genesis-jq.sh @@ -11,10 +11,7 @@ # jq's cache format marker is the "layout.version" file: genesis-create-cache-jq # writes it, genesis-cache-hit-jq gates the cache hit on it. (Atomic commit is the # top-level caller's job; the ripper backend versions via its keys instead.) -# Bumped October-08-2026: dijkstra-genesis.json is no longer cardano-cli's own -# output (see genesis-create-cache-jq), so cache entries written before that -# still hold a file the node refuses to parse. -genesis_jq_layout_version=October-08-2026 +genesis_jq_layout_version=June-22-2026 profile-cache-key-input-jq() { set -euo pipefail @@ -100,28 +97,6 @@ genesis-create-cache-jq() { progress genesis "$(colorise cardano-cli latest genesis create-testnet-data "${create_testnet_data_args[@]}")" cardano-cli latest genesis create-testnet-data "${create_testnet_data_args[@]}" - # Dijkstra genesis: `create-testnet-data` has no `--spec-dijkstra`, so it - # derives the file from cardano-api's `dijkstraGenesisDefaults` alone -- and - # that builds `plutusV4CostModel` from the full parameter list of the current - # Plutus version, while the ledger's genesis decoder insists on exactly - # `costModelInitParamCount PlutusV4` parameters. The node therefore refuses - # to parse the very file cardano-cli just wrote: - # Number of parameters supplied 369 does not match the expected number of 251 - # Overwrite it the way the ripper backend already assembles its own - # protocol.dijkstra.json: the profile's block when it has one, else the inert - # "zero" stub. This also keeps both backends byte-identical here. - # Activation check in service/nodes.nix (TestDijkstraHardForkAtEpoch). - # - # TODO: drop this once `create-testnet-data` grows a `--spec-dijkstra` flag, - # or cardano-api trims `dijkstraGenesisDefaults`' cost model to the count the - # genesis decoder accepts. cardano-testnet carries the same workaround in - # `Testnet.Defaults.defaultDijkstraGenesis`. - if [[ "$(jq -r '.genesis.dijkstra // "null"' "$profile_json")" != "null" ]]; then - jq '.genesis.dijkstra' "$profile_json" > "$dir/dijkstra-genesis.json" - else - genesis zero-spec-dijkstra > "$dir/dijkstra-genesis.json" - fi - # jq's format marker, checked by genesis-cache-hit-jq. (Atomic commit and the shared # cache.key / cache.key.input are the caller's job, in `genesis create-cache`.) cat <<<"$genesis_jq_layout_version" > "$dir"/layout.version @@ -161,7 +136,7 @@ derive-from-cache-jq() { cp "$cache_entry"/shelley-genesis.json "$outdir"/genesis.shelley.json cp "$cache_entry"/alonzo-genesis.json "$outdir"/genesis.alonzo.json cp "$cache_entry"/conway-genesis.json "$outdir"/genesis.conway.json - cp "$cache_entry"/dijkstra-genesis.json "$outdir"/genesis.dijkstra.json + # No "$cache_entry"/dijkstra-genesis.json, see below! chmod u+w "$outdir"/genesis.*.json progress "genesis" "finalizing retrieved cache entry in: $outdir" @@ -237,26 +212,21 @@ derive-from-cache-jq() { "$outdir"/genesis.alonzo.json | sponge "$outdir"/genesis.alonzo.json - # Dijkstra: fields the cardano-cli in use does not know, then the profile's - # - # create-testnet-data takes --spec-shelley, --spec-alonzo and --spec-conway, - # but no --spec-dijkstra, so genesis.dijkstra.json holds only what that - # cardano-cli emits -- four fields, for one that predates Leios. Fill the - # rest in from the zero spec so a consumer built against a later ledger - # finds every field it expects. The cli's own values win wherever it - # produced one, so this adds and never overrides. + # Dijkstra: the profile's block over the zero stub # - # Then lay `.genesis.dijkstra` over the result, which is where a profile's - # pparams overlays land (the `leios-6912k` overlay is the one that matters here). - # Without --spec-dijkstra the cli cannot be told any of this, so the profile - # reaches the genesis only by being patched in after the fact; and unlike - # the zero spec, the profile does override, since asking for a value is the - # whole point of setting it. - jq --argjson zero "$(genesis zero-spec-dijkstra)" \ + # create-testnet-data has no --spec-dijkstra, so its dijkstra-genesis.json is + # cardano-api's defaults alone, whose plutusV4CostModel carries more + # parameters than the ledger's decoder accepts -- the node refuses to parse + # it. That file stays in the cache entry, untouched and unread; the one the + # run uses is built here, as the ripper builds protocol.dijkstra.json. Zero + # stub underneath for the fields a later ledger expects, profile on top + # because setting a value is asking for it. + # Activation check in service/nodes.nix (TestDijkstraHardForkAtEpoch). + jq --null-input \ + --argjson zero "$(genesis zero-spec-dijkstra)" \ --slurpfile prof "$profile_json" \ - '$zero * . * ($prof[0].genesis.dijkstra // {})' \ - "$outdir"/genesis.dijkstra.json | - sponge "$outdir"/genesis.dijkstra.json + '$zero * ($prof[0].genesis.dijkstra // {})' \ + > "$outdir"/genesis.dijkstra.json # Conway: plutusV3CostModel jq '$prof[0].genesis.conway as $coay From c4fdcc655866ff8e1cd18f2fa6ec3e2a4a5439f8 Mon Sep 17 00:00:00 2001 From: Federico Mastellone <210034+fmaste@users.noreply.github.com> Date: Tue, 13 Oct 2026 15:11:38 +0000 Subject: [PATCH 11/45] wb | genesis ripper optional extraConfig Shelley and Conway fields --- nix/workbench/backend/nomad/cloud.sh | 2 + nix/workbench/genesis/genesis-ripper.sh | 112 ++++++++++++++++++------ 2 files changed, 87 insertions(+), 27 deletions(-) diff --git a/nix/workbench/backend/nomad/cloud.sh b/nix/workbench/backend/nomad/cloud.sh index 6fb63024d4e..83a07f98a05 100644 --- a/nix/workbench/backend/nomad/cloud.sh +++ b/nix/workbench/backend/nomad/cloud.sh @@ -922,8 +922,10 @@ deploy-genesis-nomadcloud() { # Byron/Shelley/Alonzo/Conway/DijkstraGenesisFile. -name "genesis.byron.json" -o -name "genesis.shelley.json" + -o -name "genesis.shelley.*.json" -o -name "genesis.alonzo.json" -o -name "genesis.conway.json" + -o -name "genesis.conway.*.json" -o -name "genesis.dijkstra.json" # Per-pool runtime keys read by service/nodes.nix. -o -path "*/genesis/pools-keys/pool*/opcert.cert" diff --git a/nix/workbench/genesis/genesis-ripper.sh b/nix/workbench/genesis/genesis-ripper.sh index d67c6789540..58fcc4fb656 100644 --- a/nix/workbench/genesis/genesis-ripper.sh +++ b/nix/workbench/genesis/genesis-ripper.sh @@ -106,6 +106,16 @@ # Bump on any change to what/how the ripper caches. genesis_ripper_layout_version="v1.0" +# Whether to assemble the Shelley/Conway genesis using the "extraConfig" object +# ("FIELD": {"file": ..., "hash": ...}) with references to external files having +# Shelley's "initialFunds", "stakePools" and "stakeCredentials" and Conway's +# "delegs" and "initialDReps" instead of only one file with everything. +# Off by default. +# Only affects assembly in `derive-from-cache-ripper`: the dataset and protocol +# caches are unchanged since they already store files that are exactly what a +# "file" injection needs to reference. +genesis_ripper_file_injection=${WB_GENESIS_FILE_INJECTION:-0} + # The cache-key input combines protocol hash, dataset hash and layout version. # (The profile name is prepended by profile-cache-key-ripper below.) profile-cache-key-input-ripper() { @@ -221,39 +231,87 @@ derive-from-cache-ripper() { tail -c +2 "$cache_entry/dataset/dataset.byron.json" } > "$outdir/genesis.byron.json" # Shelley (can be 500MB+). - # Assembled in the top level form (the node's current, eager loading - # mechanism): each per-field dataset file is spliced into its historical - # top level position. A future assembly strategy can emit extraConfig - # injections from the same cache files instead. - { - sed 's/}$//' "$cache_entry/protocol/protocol.shelley.json" - printf ',"systemStart":"%s"' "$system_start" - printf ',"genDelegs":' - cat "$cache_entry/dataset/dataset.shelley.genDelegs.json" - printf ',"initialFunds":' - cat "$cache_entry/dataset/dataset.shelley.initialFunds.json" - printf ',"maxLovelaceSupply":' - cat "$cache_entry/dataset/dataset.shelley.maxLovelaceSupply.json" - printf ',"staking":{"pools":' - cat "$cache_entry/dataset/dataset.shelley.stakePools.json" - printf ',"stake":' - cat "$cache_entry/dataset/dataset.shelley.stakeCredentials.json" - printf '}}\n' - } > "$outdir/genesis.shelley.json" + if [[ "$genesis_ripper_file_injection" -eq 1 ]]; then + # extraConfig FILE form: link the payload files into the run dir itself + # (the node's HasFS for extraConfig file injections is mounted at the + # Shelley genesis file's own directory, Cardano.Node.Protocol.Cardano), + # so a same-directory filename is all an injection's "file" needs. Hash + # via `cardano-cli hash genesis-file`, the same Blake2b-256-of-raw-bytes + # the ledger checks, instead of depending on a specific `b2sum`/`openssl` + # blake2b flavour being present. + ln -sf "$cache_entry/dataset/dataset.shelley.initialFunds.json" "$outdir/genesis.shelley.initialFunds.json" + ln -sf "$cache_entry/dataset/dataset.shelley.stakePools.json" "$outdir/genesis.shelley.stakePools.json" + ln -sf "$cache_entry/dataset/dataset.shelley.stakeCredentials.json" "$outdir/genesis.shelley.stakeCredentials.json" + local initial_funds_hash stake_pools_hash stake_credentials_hash + initial_funds_hash=$(cardano-cli hash genesis-file --genesis "$outdir/genesis.shelley.initialFunds.json") + stake_pools_hash=$(cardano-cli hash genesis-file --genesis "$outdir/genesis.shelley.stakePools.json") + stake_credentials_hash=$(cardano-cli hash genesis-file --genesis "$outdir/genesis.shelley.stakeCredentials.json") + { + sed 's/}$//' "$cache_entry/protocol/protocol.shelley.json" + printf ',"systemStart":"%s"' "$system_start" + printf ',"genDelegs":' + cat "$cache_entry/dataset/dataset.shelley.genDelegs.json" + printf ',"initialFunds":{}' + printf ',"maxLovelaceSupply":' + cat "$cache_entry/dataset/dataset.shelley.maxLovelaceSupply.json" + printf ',"staking":{"pools":{},"stake":{}}' + printf ',"extraConfig":{' + printf '"initialFunds":{"file":["genesis.shelley.initialFunds.json"],"hash":"%s"}' "$initial_funds_hash" + printf ',"stakePools":{"file":["genesis.shelley.stakePools.json"],"hash":"%s"}' "$stake_pools_hash" + printf ',"stakeCredentials":{"file":["genesis.shelley.stakeCredentials.json"],"hash":"%s"}' "$stake_credentials_hash" + printf '}}\n' + } > "$outdir/genesis.shelley.json" + else + # Legacy top level form (the node's current, eager loading mechanism): + # each per-field dataset file is spliced into its historical top level + # position. + { + sed 's/}$//' "$cache_entry/protocol/protocol.shelley.json" + printf ',"systemStart":"%s"' "$system_start" + printf ',"genDelegs":' + cat "$cache_entry/dataset/dataset.shelley.genDelegs.json" + printf ',"initialFunds":' + cat "$cache_entry/dataset/dataset.shelley.initialFunds.json" + printf ',"maxLovelaceSupply":' + cat "$cache_entry/dataset/dataset.shelley.maxLovelaceSupply.json" + printf ',"staking":{"pools":' + cat "$cache_entry/dataset/dataset.shelley.stakePools.json" + printf ',"stake":' + cat "$cache_entry/dataset/dataset.shelley.stakeCredentials.json" + printf '}}\n' + } > "$outdir/genesis.shelley.json" + fi # Conway (can be 200MB+). # Only tied to a dataset + protocol. No timing. # When the profile leaves .genesis.conway null, protocol/protocol.conway.json # is the zero stub but we still need to merge the dataset side (delegs and # initialDReps) to produce a parseable file for the node config. - { - sed 's/}$//' "$cache_entry/protocol/protocol.conway.json" - printf ',"delegs":' - cat "$cache_entry/dataset/dataset.conway.delegs.json" - printf ',"initialDReps":' - cat "$cache_entry/dataset/dataset.conway.initialDReps.json" - printf '}\n' - } > "$outdir/genesis.conway.json" + if [[ "$genesis_ripper_file_injection" -eq 1 ]]; then + ln -sf "$cache_entry/dataset/dataset.conway.delegs.json" "$outdir/genesis.conway.delegs.json" + ln -sf "$cache_entry/dataset/dataset.conway.initialDReps.json" "$outdir/genesis.conway.initialDReps.json" + local delegs_hash initial_dreps_hash + delegs_hash=$(cardano-cli hash genesis-file --genesis "$outdir/genesis.conway.delegs.json") + initial_dreps_hash=$(cardano-cli hash genesis-file --genesis "$outdir/genesis.conway.initialDReps.json") + { + sed 's/}$//' "$cache_entry/protocol/protocol.conway.json" + printf ',"delegs":{}' + printf ',"initialDReps":{}' + printf ',"extraConfig":{' + printf '"delegs":{"file":["genesis.conway.delegs.json"],"hash":"%s"}' "$delegs_hash" + printf ',"initialDReps":{"file":["genesis.conway.initialDReps.json"],"hash":"%s"}' "$initial_dreps_hash" + printf '}}\n' + } > "$outdir/genesis.conway.json" + else + { + sed 's/}$//' "$cache_entry/protocol/protocol.conway.json" + printf ',"delegs":' + cat "$cache_entry/dataset/dataset.conway.delegs.json" + printf ',"initialDReps":' + cat "$cache_entry/dataset/dataset.conway.initialDReps.json" + printf '}\n' + } > "$outdir/genesis.conway.json" + fi } # ============================================================================== From c3e52d07054e172b6dd8720322366ef53e5c7abf Mon Sep 17 00:00:00 2001 From: Federico Mastellone <210034+fmaste@users.noreply.github.com> Date: Tue, 13 Oct 2026 15:33:43 +0000 Subject: [PATCH 12/45] tx-generator | resolve genesis file injection scoped, via ledger's foldInjectionData --- .../src/Cardano/Benchmarking/Script/Action.hs | 7 +++- .../src/Cardano/Benchmarking/Script/Core.hs | 6 ++- .../src/Cardano/Benchmarking/Script/Env.hs | 13 ++++++ .../src/Cardano/TxGenerator/Genesis.hs | 41 +++++++++++++++++-- .../Cardano/TxGenerator/Setup/NodeConfig.hs | 26 ++++++++---- bench/tx-generator/test/ApiTest.hs | 33 +++++++++------ bench/tx-generator/tx-generator.cabal | 1 + 7 files changed, 101 insertions(+), 26 deletions(-) diff --git a/bench/tx-generator/src/Cardano/Benchmarking/Script/Action.hs b/bench/tx-generator/src/Cardano/Benchmarking/Script/Action.hs index 0c992938ee0..c4d4193e824 100644 --- a/bench/tx-generator/src/Cardano/Benchmarking/Script/Action.hs +++ b/bench/tx-generator/src/Cardano/Benchmarking/Script/Action.hs @@ -20,6 +20,7 @@ import Cardano.Benchmarking.Script.Types import Cardano.Benchmarking.Tracer import Cardano.TxGenerator.Setup.NodeConfig import Cardano.TxGenerator.Types (TxGenError) +import qualified Cardano.TxGenerator.Types as Types (TxGenError (TxGenError)) import Control.Monad.IO.Class import Control.Monad.Trans.Except.Extra @@ -66,7 +67,11 @@ startProtocol configFile tracerSocket = do nodeConfig <- liftToAction $ mkNodeConfig configFile protocol <- liftToAction $ mkConsensusProtocol nodeConfig setEnvProtocol protocol - setEnvGenesis $ getGenesis protocol + shelleyGenesisDir <- liftToAction $ pure $ case getShelleyGenesisDir nodeConfig of + Nothing -> Left $ Types.TxGenError "startProtocol: no Shelley genesis file in node config" + Just dir -> Right dir + setEnvShelleyGenesisDir shelleyGenesisDir + setEnvGenesis $ getShelleyGenesis protocol iomgr <- askIOManager networkId <- liftIO $ protocolToNetworkId protocol diff --git a/bench/tx-generator/src/Cardano/Benchmarking/Script/Core.hs b/bench/tx-generator/src/Cardano/Benchmarking/Script/Core.hs index 45bfa7f3638..d1786ef9696 100644 --- a/bench/tx-generator/src/Cardano/Benchmarking/Script/Core.hs +++ b/bench/tx-generator/src/Cardano/Benchmarking/Script/Core.hs @@ -306,11 +306,13 @@ evalGenerator generator txParams@TxGenTxParams{txParamFee = fee} era = do case generator of SecureGenesis wallet genesisKeyName destKeyName -> do genesis <- getEnvGenesis + genesisDir <- getEnvShelleyGenesisDir destKey <- getEnvKeys destKeyName destWallet <- getEnvWallets wallet genesisKey <- getEnvKeys genesisKeyName - (tx, fund) <- firstExceptT Env.TxGenError $ hoistEither $ - Genesis.genesisSecureInitialFund networkId genesis genesisKey destKey txParams + eitherTxFund <- liftIO $ Genesis.genesisWithResolvedInitialFunds genesisDir genesis $ \resolved -> + Genesis.genesisSecureInitialFund networkId resolved genesisKey destKey txParams + (tx, fund) <- firstExceptT Env.TxGenError $ hoistEither eitherTxFund let gen = do walletRefInsertFund destWallet fund diff --git a/bench/tx-generator/src/Cardano/Benchmarking/Script/Env.hs b/bench/tx-generator/src/Cardano/Benchmarking/Script/Env.hs index a173d053090..9767ebf7faf 100644 --- a/bench/tx-generator/src/Cardano/Benchmarking/Script/Env.hs +++ b/bench/tx-generator/src/Cardano/Benchmarking/Script/Env.hs @@ -45,6 +45,8 @@ module Cardano.Benchmarking.Script.Env ( , setBenchTracers , getEnvGenesis , setEnvGenesis + , getEnvShelleyGenesisDir + , setEnvShelleyGenesisDir , getEnvKeys , setEnvKeys , getEnvNetworkId @@ -101,6 +103,7 @@ data Env = Env { -- | 'Cardano.Api.ProtocolParameters' is ultimately -- a sort of custom 'Maybe'. protoParams :: Maybe ProtocolParameterMode , envGenesis :: Maybe ShelleyGenesis + , envShelleyGenesisDir :: Maybe FilePath , envProtocol :: Maybe SomeConsensusProtocol , envNetworkId :: Maybe NetworkId , envSocketPath :: Maybe FilePath @@ -114,6 +117,7 @@ data Env = Env { -- | 'Cardano.Api.ProtocolParameters' is ultimately emptyEnv :: Env emptyEnv = Env { protoParams = Nothing , envGenesis = Nothing + , envShelleyGenesisDir = Nothing , envKeys = Map.empty , envProtocol = Nothing , envNetworkId = Nothing @@ -192,6 +196,11 @@ setBenchTracers val = do setEnvGenesis :: ShelleyGenesis -> ActionM () setEnvGenesis val = modifyEnv (\e -> e { envGenesis = Just val }) +-- | Write accessor for `envShelleyGenesisDir`: the directory containing the +-- Shelley genesis file, which extraConfig file injections resolve against. +setEnvShelleyGenesisDir :: FilePath -> ActionM () +setEnvShelleyGenesisDir val = modifyEnv (\e -> e { envShelleyGenesisDir = Just val }) + -- | Write accessor for `envKeys`. setEnvKeys :: String -> SigningKey PaymentKey -> ActionM () setEnvKeys key val = modifyEnv (\e -> e { envKeys = Map.insert key val (envKeys e) }) @@ -266,6 +275,10 @@ getBenchTracers = do getEnvGenesis :: ActionM ShelleyGenesis getEnvGenesis = getEnvVal envGenesis "Genesis" +-- | Read accessor for `envShelleyGenesisDir`. +getEnvShelleyGenesisDir :: ActionM FilePath +getEnvShelleyGenesisDir = getEnvVal envShelleyGenesisDir "ShelleyGenesisDir" + -- | Read accessor for `envKeys`. getEnvKeys :: String -> ActionM (SigningKey PaymentKey) getEnvKeys = getEnvMap envKeys diff --git a/bench/tx-generator/src/Cardano/TxGenerator/Genesis.hs b/bench/tx-generator/src/Cardano/TxGenerator/Genesis.hs index 5365258b3f0..4eff9821d73 100644 --- a/bench/tx-generator/src/Cardano/TxGenerator/Genesis.hs +++ b/bench/tx-generator/src/Cardano/TxGenerator/Genesis.hs @@ -12,6 +12,7 @@ module Cardano.TxGenerator.Genesis ( genesisInitialFunds , genesisInitialFundForKey + , genesisWithResolvedInitialFunds , genesisTxInput , genesisExpenditure , genesisSecureInitialFund @@ -24,16 +25,20 @@ import Cardano.Api hiding (ShelleyGenesis) import Cardano.Ledger.BaseTypes (StrictMaybe (..)) import qualified Cardano.Ledger.Coin as L import Cardano.Ledger.Shelley.API (Addr (..)) -import Cardano.Ledger.Shelley.Genesis (InjectionData (..), ShelleyExtraConfig (..)) +import Cardano.Ledger.Shelley.Genesis (InjectionData (..), ShelleyExtraConfig (..), + foldInjectionData) import Cardano.TxGenerator.Fund import Cardano.TxGenerator.Types import Cardano.TxGenerator.Utils import Ouroboros.Consensus.Shelley.Node (validateGenesis) +import Control.Exception (SomeException, displayException, evaluate, try) import Data.Bifunctor (bimap, second) import Data.Function ((&)) import Data.List (find) -import qualified Data.ListMap as ListMap (toList) +import qualified Data.ListMap as ListMap (fromList, toList) +import System.FS.API.Types (MountPoint (..)) +import System.FS.IO (ioHasFS) genesisValidate :: ShelleyGenesis -> Either String () @@ -86,10 +91,40 @@ embeddedInitialFunds g = Left $ TxGenError "genesisInitialFunds: both initialFunds and extraConfig.initialFunds are populated; please use only one source" EmbeddedInjection lm -> Right (ListMap.toList lm) InjectionFromFile{} -> - Left $ TxGenError "genesisInitialFunds: file-based initial-funds injection is unsupported; expected embedded funds in extraConfig.initialFunds or initialFunds" + Left $ TxGenError "genesisInitialFunds: unresolved file-based initial-funds injection; use genesisWithResolvedInitialFunds" where legacy = ListMap.toList $ sgInitialFunds g +-- | 'genesisWithResolvedInitialFunds' runs a pure computation on the genesis with a +-- file-based @extraConfig.initialFunds@ injection resolved into an embedded +-- one, so the pure functions in this module can consume it unchanged. Any other +-- genesis is passed to the computation as is. +-- +-- The first argument is the directory containing the Shelley genesis file; the +-- node mounts its 'System.FS.API.HasFS' for injection files at that same +-- directory, and reading, hashing and parsing are delegated to ledger's +-- 'foldInjectionData', so resolution matches the node's. +-- +-- The resolved genesis never escapes: the caller's genesis keeps its original +-- field, and the result is forced to WHNF before returning, so the (potentially +-- huge) resolved funds become garbage right after. However, if the result @a@ +-- keeps a reference to the resolved genesis or its funds -- directly, or via a +-- thunk not yet evaluated -- they stay on the heap for as long as @a@ is +-- reachable; e.g. throughout the process lifetime when @a@ is stored in a +-- long-lived environment. +genesisWithResolvedInitialFunds :: FilePath -> ShelleyGenesis -> (ShelleyGenesis -> Either TxGenError a) -> IO (Either TxGenError a) +genesisWithResolvedInitialFunds shelleyGenesisDir g k = + case sgExtraConfig g of + SJust extraConfig | source@InjectionFromFile{} <- secInitialFunds extraConfig -> do + let hasFS = ioHasFS (MountPoint shelleyGenesisDir) + res <- try @SomeException $ foldInjectionData hasFS source (flip (:)) [] + case res of + Left err -> pure $ Left $ TxGenError $ "genesisWithResolvedInitialFunds: " ++ displayException err + Right funds -> + let embedded = EmbeddedInjection $ ListMap.fromList $ reverse funds + in evaluate $ k g { sgExtraConfig = SJust extraConfig { secInitialFunds = embedded } } + _ -> evaluate (k g) + genesisInitialFundForKey :: forall era. IsShelleyBasedEra era => NetworkId -> ShelleyGenesis diff --git a/bench/tx-generator/src/Cardano/TxGenerator/Setup/NodeConfig.hs b/bench/tx-generator/src/Cardano/TxGenerator/Setup/NodeConfig.hs index 86cfbf1b642..2d82913993d 100644 --- a/bench/tx-generator/src/Cardano/TxGenerator/Setup/NodeConfig.hs +++ b/bench/tx-generator/src/Cardano/TxGenerator/Setup/NodeConfig.hs @@ -17,7 +17,7 @@ import Cardano.Node.Protocol.Cardano import Cardano.Node.Protocol.Types (SomeConsensusProtocol (..)) import Cardano.Node.Types (ConfigYamlFilePath (..), GenesisFile, KESSource (..), NodeProtocolConfiguration (..), NodeShelleyProtocolConfiguration (..), - ProtocolFilepaths (..)) + ProtocolFilepaths (..), unGenesisFile) import Cardano.TxGenerator.Types import qualified Ouroboros.Consensus.Cardano.Node as Consensus @@ -25,26 +25,36 @@ import Control.Applicative (Const (Const), getConst) import Control.Monad.Trans.Except (runExceptT) import Data.Bifunctor (first) import Data.Monoid +import System.FilePath (takeDirectory) --- | extract genesis from a Cardano protocol +-- | extract the Shelley genesis from a Cardano protocol -- NB. this helper is *only* for protocols created with this module --- as this guarantees proper error handling when trying to create a non-Cardano protocol. -getGenesis :: SomeConsensusProtocol -> ShelleyGenesis -getGenesis (SomeConsensusProtocol CardanoBlockType proto) +-- as this guarantees proper error handling when trying to create a non-Cardano +-- protocol. +getShelleyGenesis :: SomeConsensusProtocol -> ShelleyGenesis +getShelleyGenesis (SomeConsensusProtocol CardanoBlockType proto) = getConst $ Ledger.tcShelleyGenesisL Const transCfg where ProtocolInfoArgsCardano _ Consensus.CardanoProtocolParams { Consensus.cardanoLedgerTransitionConfig = transCfg } = proto --- | extract the path to genesis file from a NodeConfiguration for Cardano protocol -getGenesisPath :: NodeConfiguration -> Maybe GenesisFile -getGenesisPath nodeConfig = +-- | extract the path to the Shelley genesis file from a NodeConfiguration for +-- Cardano protocol. +getShelleyGenesisPath :: NodeConfiguration -> Maybe GenesisFile +getShelleyGenesisPath nodeConfig = case ncProtocolConfig nodeConfig of NodeProtocolConfigurationCardano _ shelleyConfig _ _ _ _ _ -> Just $ npcShelleyGenesisFile shelleyConfig +-- | extract the directory containing the Shelley genesis file: the root +-- extraConfig FILE injections resolve their "file" segments against (see +-- 'Cardano.Node.Protocol.Cardano.mkSomeConsensusProtocolCardano', which mounts +-- its HasFS at this same directory). +getShelleyGenesisDir :: NodeConfiguration -> Maybe FilePath +getShelleyGenesisDir = fmap (takeDirectory . unGenesisFile) . getShelleyGenesisPath + mkConsensusProtocol :: NodeConfiguration -> IO (Either TxGenError SomeConsensusProtocol) mkConsensusProtocol nodeConfig = case ncProtocolConfig nodeConfig of diff --git a/bench/tx-generator/test/ApiTest.hs b/bench/tx-generator/test/ApiTest.hs index fc4be3feea4..8a47e587de0 100644 --- a/bench/tx-generator/test/ApiTest.hs +++ b/bench/tx-generator/test/ApiTest.hs @@ -83,7 +83,7 @@ main hoistEither =<< handleIOExceptT (TxGenError . show) (mkNodeConfig ncFile) GenesisFile sgFile <- hoistMaybe (TxGenError "npcShelleyGenesisFile not specified") $ - getGenesisPath nc + getShelleyGenesisPath nc genesis :: ShelleyGenesis <- readFileJson sgFile _ <- firstExceptT TxGenError $ hoistEither $ @@ -92,12 +92,13 @@ main sigKey :: SigningKey PaymentKey <- hoistEither =<< handleIOExceptT (TxGenError . show) (readSigningKeyFile $ _nix_sigKey nixService) - pure (nixService, nc, genesis, sigKey) + pure (nixService, takeDirectory sgFile, genesis, sigKey) case setup of Left err -> die (show err) - Right (nixService, _nc, genesis, sigKey) -> do - putStrLn $ "* Did I manage to extract a genesis fund?\n--> " ++ checkFund nixService genesis sigKey + Right (nixService, genesisDir, genesis, sigKey) -> do + fundMsg <- checkFund nixService genesisDir genesis sigKey + putStrLn $ "* Did I manage to extract a genesis fund?\n--> " ++ fundMsg putStrLn "* Can I pre-execute a plutus script?" let plutus = _nix_plutus nixService case plutus of @@ -121,25 +122,33 @@ showBabbage = ("Babbage: " ++) . showFundCore showConway :: Either TxGenError (Maybe (AddressInEra ConwayEra, Api.Coin)) -> String showConway = ("Conway: " ++) . showFundCore +showDijkstra :: Either TxGenError (Maybe (AddressInEra DijkstraEra, Api.Coin)) -> String +showDijkstra = ("Dijkstra: " ++) . showFundCore + checkFund :: NixServiceOptions + -> FilePath -> ShelleyGenesis -> SigningKey PaymentKey - -> String -checkFund nixService shelleyGenesis signingKey + -> IO String +checkFund nixService genesisDir shelleyGenesis signingKey | AnyCardanoEra BabbageEra <- _nix_era nixService - = showBabbage $ checkFundCore shelleyGenesis signingKey + = showBabbage <$> checkFundCore genesisDir shelleyGenesis signingKey | AnyCardanoEra ConwayEra <- _nix_era nixService - = showConway $ checkFundCore shelleyGenesis signingKey + = showConway <$> checkFundCore genesisDir shelleyGenesis signingKey + | AnyCardanoEra DijkstraEra <- _nix_era nixService + = showDijkstra <$> checkFundCore genesisDir shelleyGenesis signingKey | otherwise - = "ApiTest.checkFund: unrecognized era" + = pure "ApiTest.checkFund: unrecognized era" checkFundCore :: IsShelleyBasedEra era - => ShelleyGenesis + => FilePath + -> ShelleyGenesis -> SigningKey PaymentKey - -> Either TxGenError (Maybe (AddressInEra era, Api.Coin)) -checkFundCore sg = genesisInitialFundForKey networkId sg + -> IO (Either TxGenError (Maybe (AddressInEra era, Api.Coin))) +checkFundCore genesisDir sg key = + genesisWithResolvedInitialFunds genesisDir sg $ \resolved -> genesisInitialFundForKey networkId resolved key where networkId = fromNetworkMagic $ NetworkMagic $ sgNetworkMagic sg diff --git a/bench/tx-generator/tx-generator.cabal b/bench/tx-generator/tx-generator.cabal index fc662da2f21..215f56f3775 100644 --- a/bench/tx-generator/tx-generator.cabal +++ b/bench/tx-generator/tx-generator.cabal @@ -140,6 +140,7 @@ library , extra , filepath , formatting + , fs-api , generic-monoid , ghc-prim , io-classes:{io-classes, strict-stm} From ca78cad940c604234f0edbabf037d59946cbe16a Mon Sep 17 00:00:00 2001 From: Federico Mastellone <210034+fmaste@users.noreply.github.com> Date: Mon, 19 Oct 2026 12:15:42 +0000 Subject: [PATCH 13/45] tx-generator | version bump and deprecation of getGenesis/getGenesisPath --- bench/tx-generator/CHANGELOG.md | 17 +++++++++++++++++ .../Cardano/Benchmarking/OuroborosImports.hs | 1 - .../src/Cardano/TxGenerator/Setup/NodeConfig.hs | 12 ++++++++++++ bench/tx-generator/tx-generator.cabal | 2 +- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/bench/tx-generator/CHANGELOG.md b/bench/tx-generator/CHANGELOG.md index 26fa79322fd..03849c72774 100644 --- a/bench/tx-generator/CHANGELOG.md +++ b/bench/tx-generator/CHANGELOG.md @@ -1,5 +1,22 @@ # ChangeLog +## 2.19 -- Oct 2026 + +* **Support for `extraConfig.initialFunds.file` genesis injections**, where a + Shelley genesis keeps its initial funds in a separate JSON file referenced + by `file` plus the Blake2b-256 `hash` of its contents. Previously only the + legacy top-level `initialFunds` and the inline + `extraConfig.initialFunds.data` were read. Reading, hashing and parsing go + through cardano-ledger's `foldInjectionData`, so resolution matches the + node's. +* API changes: + * New `genesisWithResolvedInitialFunds` and `getShelleyGenesisDir`. + * `genesisInitialFunds`, `genesisInitialFundForKey` and + `genesisSecureInitialFund` fail on file injections; run them inside + `genesisWithResolvedInitialFunds`. + * `getGenesis` and `getGenesisPath` renamed to `getShelleyGenesis` and + `getShelleyGenesisPath`; old names kept as deprecated aliases. + ## 2.18 -- Sep 2026 * **New submit mode: dump the transaction stream to disk** instead of diff --git a/bench/tx-generator/src/Cardano/Benchmarking/OuroborosImports.hs b/bench/tx-generator/src/Cardano/Benchmarking/OuroborosImports.hs index 5d31e39d4e6..389caa2369f 100644 --- a/bench/tx-generator/src/Cardano/Benchmarking/OuroborosImports.hs +++ b/bench/tx-generator/src/Cardano/Benchmarking/OuroborosImports.hs @@ -11,7 +11,6 @@ module Cardano.Benchmarking.OuroborosImports , SigningKey , SigningKeyFile , NetworkId - -- , getGenesis , makeLocalConnectInfo , protocolToTopLevelConfig , protocolToNetworkId diff --git a/bench/tx-generator/src/Cardano/TxGenerator/Setup/NodeConfig.hs b/bench/tx-generator/src/Cardano/TxGenerator/Setup/NodeConfig.hs index 2d82913993d..834bc11ecc5 100644 --- a/bench/tx-generator/src/Cardano/TxGenerator/Setup/NodeConfig.hs +++ b/bench/tx-generator/src/Cardano/TxGenerator/Setup/NodeConfig.hs @@ -55,6 +55,18 @@ getShelleyGenesisPath nodeConfig = getShelleyGenesisDir :: NodeConfiguration -> Maybe FilePath getShelleyGenesisDir = fmap (takeDirectory . unGenesisFile) . getShelleyGenesisPath +-- | Kept for downstream consumers; 'getShelleyGenesis' is the same function +-- under its new name. +getGenesis :: SomeConsensusProtocol -> ShelleyGenesis +getGenesis = getShelleyGenesis +{-# DEPRECATED getGenesis "Use getShelleyGenesis instead." #-} + +-- | Kept for downstream consumers; 'getShelleyGenesisPath' is the same +-- function under its new name. +getGenesisPath :: NodeConfiguration -> Maybe GenesisFile +getGenesisPath = getShelleyGenesisPath +{-# DEPRECATED getGenesisPath "Use getShelleyGenesisPath instead." #-} + mkConsensusProtocol :: NodeConfiguration -> IO (Either TxGenError SomeConsensusProtocol) mkConsensusProtocol nodeConfig = case ncProtocolConfig nodeConfig of diff --git a/bench/tx-generator/tx-generator.cabal b/bench/tx-generator/tx-generator.cabal index 215f56f3775..f191d0a7c7a 100644 --- a/bench/tx-generator/tx-generator.cabal +++ b/bench/tx-generator/tx-generator.cabal @@ -1,7 +1,7 @@ cabal-version: 3.0 name: tx-generator -version: 2.18 +version: 2.19 synopsis: A transaction workload generator for Cardano clusters description: A transaction workload generator for Cardano clusters. category: Cardano, From ebf7adf5552b551a91e9c99bb2f74f790968eaa5 Mon Sep 17 00:00:00 2001 From: Michael Karg Date: Tue, 20 Oct 2026 09:14:45 +0200 Subject: [PATCH 14/45] bycatch: fix workbench namespace --- nix/workbench/service/tracing.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/workbench/service/tracing.nix b/nix/workbench/service/tracing.nix index 69f40a667c6..71c31f33718 100644 --- a/nix/workbench/service/tracing.nix +++ b/nix/workbench/service/tracing.nix @@ -44,7 +44,7 @@ let "BlockFetch.Server".severity = "Debug"; "BlockchainTime".severity = "Notice"; "ChainDB".severity = "Debug"; - "ChainDB.LedgerEvent.Flavor.V1.".severity = "Silence"; + "ChainDB.LedgerEvent.Flavor.V1".severity = "Silence"; "ChainDB.LedgerEvent.Flavor.V2".severity = "Silence"; "ChainDB.PerasCertDbEvent".severity = "Silence"; "ChainDB.ReplayBlock.LedgerReplay".severity = "Notice"; From 291a18250e69425bea57a4676e64fda1480a402a Mon Sep 17 00:00:00 2001 From: Javier Sagredo Date: Wed, 21 Oct 2026 11:32:50 +0200 Subject: [PATCH 15/45] Config: ignore the divergence in resolved path in LSM database path --- .../Configuration/CardanoConfigCompare.hs | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs index f62f198e0f9..3dd5f37f90f 100644 --- a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs +++ b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigCompare.hs @@ -8,12 +8,16 @@ -- the node default and therefore surfaces here as a divergence (see -- 'Cardano.Node.Configuration.CardanoConfigAdapter.adapterGaps'), with one -- exception: the Byron supported-protocol-version trio, which is excluded from --- the comparison (see 'ignoreByronSupportedVersion'). +-- the comparison (see 'ignoreByronSupportedVersion'). Some fields that the two +-- sides spell differently but resolve to the same value are normalised before +-- comparing (see 'ignoreAbsentMempoolOverride' and 'ignoreDefaultLsmPath'). module Cardano.Node.Configuration.CardanoConfigCompare ( compareConfigurations , deprecatedFlagWarnings ) where +import Cardano.Node.Configuration.LedgerDB (LedgerDbConfiguration (..), + LedgerDbSelectorFlag (..)) import Cardano.Node.Configuration.POM (NodeConfiguration (..)) import Cardano.Node.Types (NodeByronProtocolConfiguration (..), NodeProtocolConfiguration (..)) @@ -73,7 +77,9 @@ compareConfigurations pom adapted = , cmpValues "MaybeMempoolCapacityOverride" (ignoreAbsentMempoolOverride (ncMaybeMempoolCapacityOverride pom)) (ignoreAbsentMempoolOverride (ncMaybeMempoolCapacityOverride adapted)) - , cmp "LedgerDbConfig" ncLedgerDbConfig + , cmpValues "LedgerDbConfig" + (ignoreDefaultLsmPath (ncLedgerDbConfig pom)) + (ignoreDefaultLsmPath (ncLedgerDbConfig adapted)) , cmp "ProtocolIdleTimeout" ncProtocolIdleTimeout , cmp "TimeWaitTimeout" ncTimeWaitTimeout , cmp "EgressPollInterval" ncEgressPollInterval @@ -163,3 +169,16 @@ ignoreAbsentMempoolOverride :: Maybe MempoolCapacityBytesOverride -> Maybe MempoolCapacityBytesOverride ignoreAbsentMempoolOverride (Just NoMempoolCapacityBytesOverride) = Nothing ignoreAbsentMempoolOverride other = other + +-- | Fold the two spellings of "the default LSM database path" together. +-- +-- POM keeps 'Nothing' for a @V2LSM@ backend whose configuration writes no +-- @LSMDatabasePath@, whereas cardano-config resolves the absent path to its +-- default @"lsm"@. Both open the database at the same place: the node applies +-- that same default when it builds the backend arguments (see +-- 'Cardano.Node.Configuration.LedgerDB.selectorToArgs'). +ignoreDefaultLsmPath :: LedgerDbConfiguration -> LedgerDbConfiguration +ignoreDefaultLsmPath + (LedgerDbConfiguration snapshots batchSize (V2LSM Nothing exportPath) deprecated) = + LedgerDbConfiguration snapshots batchSize (V2LSM (Just "lsm") exportPath) deprecated +ignoreDefaultLsmPath other = other From fd275988975c472425f00b1cc13c55ebe71dfb8f Mon Sep 17 00:00:00 2001 From: Michael Karg Date: Thu, 22 Oct 2026 15:21:35 +0200 Subject: [PATCH 16/45] cardano-node: drop built-in config for removed namespace --- cardano-node/src/Cardano/Node/Tracing/DefaultTraceConfig.hs | 2 -- 1 file changed, 2 deletions(-) diff --git a/cardano-node/src/Cardano/Node/Tracing/DefaultTraceConfig.hs b/cardano-node/src/Cardano/Node/Tracing/DefaultTraceConfig.hs index 72aac85c5cd..43453aaebc8 100644 --- a/cardano-node/src/Cardano/Node/Tracing/DefaultTraceConfig.hs +++ b/cardano-node/src/Cardano/Node/Tracing/DefaultTraceConfig.hs @@ -34,8 +34,6 @@ defaultCardanoConfig = emptyTraceConfig { [ ConfSeverity (SeverityF (Just Info))]) ,(["Startup", "DiffusionInit"], [ ConfSeverity (SeverityF (Just Info))]) - ,(["Net", "ErrorPolicy"], - [ ConfSeverity (SeverityF (Just Info))]) ,(["Forge", "Loop"], [ ConfSeverity (SeverityF (Just Info))]) ,(["Forge", "StateInfo"], From 05bcaa00f58916450bf0843c96b059057b016aba Mon Sep 17 00:00:00 2001 From: Michael Karg Date: Thu, 22 Oct 2026 15:21:35 +0200 Subject: [PATCH 17/45] Bump cardano-api to 11.11.0.0 and cardano-cli to 11.6.0.0 --- .../.changes/20261015_033428_palas_bump_cardano_api_11_9.yml | 4 ++++ .../.changes/20261015_033428_palas_bump_cardano_api_11_9.yml | 4 ++++ cardano-testnet/cardano-testnet.cabal | 1 + .../test/cardano-testnet-golden/files/golden/version_cmd.cli | 4 ++-- 4 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 cardano-submit-api/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml create mode 100644 cardano-testnet/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml diff --git a/cardano-submit-api/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml b/cardano-submit-api/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml new file mode 100644 index 00000000000..007bd13e793 --- /dev/null +++ b/cardano-submit-api/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml @@ -0,0 +1,4 @@ +pr: 6677 +kind: + - maintenance +description: Bumped cardano-api to 11.11 and cardano-cli to 11.6. diff --git a/cardano-testnet/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml b/cardano-testnet/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml new file mode 100644 index 00000000000..007bd13e793 --- /dev/null +++ b/cardano-testnet/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml @@ -0,0 +1,4 @@ +pr: 6677 +kind: + - maintenance +description: Bumped cardano-api to 11.11 and cardano-cli to 11.6. diff --git a/cardano-testnet/cardano-testnet.cabal b/cardano-testnet/cardano-testnet.cabal index e7440706d20..f0c59109ed3 100644 --- a/cardano-testnet/cardano-testnet.cabal +++ b/cardano-testnet/cardano-testnet.cabal @@ -42,6 +42,7 @@ library , ansi-terminal , bytestring , cardano-api ^>= 11.11 + , cardano-config ^>= 2.2.3 , cardano-cli:{cardano-cli, cardano-cli-test-lib} ^>= 11.6 , cardano-crypto-class ^>=2.6 , cardano-crypto-wrapper diff --git a/cardano-testnet/test/cardano-testnet-golden/files/golden/version_cmd.cli b/cardano-testnet/test/cardano-testnet-golden/files/golden/version_cmd.cli index 3a4f336100c..3a030e4a83c 100644 --- a/cardano-testnet/test/cardano-testnet-golden/files/golden/version_cmd.cli +++ b/cardano-testnet/test/cardano-testnet-golden/files/golden/version_cmd.cli @@ -1,3 +1,3 @@ -built against cardano-api 11.8.0.0 +built against cardano-api 11.11.0.0 built against cardano-rpc 11.5.0.0 -built against cardano-cli 11.3.0.0 +built against cardano-cli 11.6.0.0 From c221667c6b1acc0e48df85399e109a9398a8f264 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Thu, 15 Oct 2026 01:40:04 +0000 Subject: [PATCH 18/45] Write and refresh testnet node configurations through cardano-config --- ...46_palas_config_through_cardano_config.yml | 4 + cardano-testnet/cardano-testnet.cabal | 2 - cardano-testnet/src/Parsers/Run.hs | 6 +- .../src/Testnet/Components/Configuration.hs | 91 +++++-------------- cardano-testnet/src/Testnet/Defaults.hs | 31 +++++-- cardano-testnet/src/Testnet/Start/Cardano.hs | 77 +++++++++++----- cardano-testnet/src/Testnet/Start/Types.hs | 17 +--- cardano-testnet/src/Testnet/SubmitApi.hs | 14 ++- cardano-testnet/src/Testnet/Types.hs | 30 ++---- .../files/golden/node_default_config.json | 75 ++++++++++++++- .../Testnet/Test/Api/TxReferenceInputDatum.hs | 5 +- .../Cardano/Testnet/Test/Cli/KesPeriodInfo.hs | 5 +- .../Testnet/Test/Cli/LeadershipSchedule.hs | 6 +- .../Testnet/Test/Cli/QuerySlotNumber.hs | 2 +- .../Cardano/Testnet/Test/DumpConfig.hs | 8 +- .../Test/Gov/ProposeNewConstitution.hs | 5 - .../Cardano/Testnet/Test/Node/Shutdown.hs | 17 +--- .../Testnet/Test/SubmitApi/Transaction.hs | 1 - .../Cardano/Testnet/Test/UpdateTimeStamps.hs | 9 +- 19 files changed, 211 insertions(+), 194 deletions(-) create mode 100644 cardano-testnet/.changes/20261015_033946_palas_config_through_cardano_config.yml diff --git a/cardano-testnet/.changes/20261015_033946_palas_config_through_cardano_config.yml b/cardano-testnet/.changes/20261015_033946_palas_config_through_cardano_config.yml new file mode 100644 index 00000000000..e6da7f89a66 --- /dev/null +++ b/cardano-testnet/.changes/20261015_033946_palas_config_through_cardano_config.yml @@ -0,0 +1,4 @@ +pr: 6677 +kind: + - breaking +description: Testnet node configurations are written in the cardano-config format and through cardano-config, with their genesis hashes refreshed whenever the testnet starts and the node's default tracing options written out; removed createConfigJson, createConfigJsonNoHash, getByronGenesisHash, getShelleyGenesisHash, GenesisHashesPolicy and the configPath field of SubmitApiConf, and getStartTime no longer takes a path. diff --git a/cardano-testnet/cardano-testnet.cabal b/cardano-testnet/cardano-testnet.cabal index f0c59109ed3..77d2ef62218 100644 --- a/cardano-testnet/cardano-testnet.cabal +++ b/cardano-testnet/cardano-testnet.cabal @@ -44,8 +44,6 @@ library , cardano-api ^>= 11.11 , cardano-config ^>= 2.2.3 , cardano-cli:{cardano-cli, cardano-cli-test-lib} ^>= 11.6 - , cardano-crypto-class ^>=2.6 - , cardano-crypto-wrapper , cardano-git-rev ^>= 0.2.2 , cardano-ledger-alonzo , cardano-ledger-binary diff --git a/cardano-testnet/src/Parsers/Run.hs b/cardano-testnet/src/Parsers/Run.hs index a65e50c5f44..d3d2a9ed27d 100644 --- a/cardano-testnet/src/Parsers/Run.hs +++ b/cardano-testnet/src/Parsers/Run.hs @@ -88,11 +88,7 @@ createEnvOptions CardanoTestnetCreateEnvOptions , createEnvOutputDir=outputDir } = do conf <- mkConfigAbs outputDir - void $ createTestnetEnv - creationOptions - -- Do not add hashes to the main config file, so that genesis files - -- can be modified without having to recompute hashes every time. - conf{genesisHashesPolicy = WithoutHashes} + void $ createTestnetEnv creationOptions conf runCardanoOptions :: CardanoTestnetCliOptions -> IO () runCardanoOptions = \case diff --git a/cardano-testnet/src/Testnet/Components/Configuration.hs b/cardano-testnet/src/Testnet/Components/Configuration.hs index 5b713ba1633..66aaf034cce 100644 --- a/cardano-testnet/src/Testnet/Components/Configuration.hs +++ b/cardano-testnet/src/Testnet/Components/Configuration.hs @@ -6,13 +6,11 @@ {-# LANGUAGE TypeApplications #-} module Testnet.Components.Configuration - ( createConfigJson - , createConfigJsonNoHash + ( writeConfiguration + , refreshConfigurationHashes , createSPOGenesisAndFiles , numSeededUTxOKeys - , getByronGenesisHash - , getShelleyGenesisHash , getDefaultAlonzoGenesis , getDefaultShelleyGenesis , startTimeOffsetSeconds @@ -24,24 +22,17 @@ module Testnet.Components.Configuration import Cardano.Api hiding (Value, cardanoEra) import Cardano.Api.Ledger (AlonzoGenesis, ConwayGenesis) -import Cardano.Chain.Genesis (GenesisHash (unGenesisHash), readGenesisData) -import qualified Cardano.Crypto.Hash.Blake2b as Crypto -import qualified Cardano.Crypto.Hash.Class as Crypto +import Cardano.Configuration.Edit (configurationDocumentFromValue, + readConfigurationDocument, refreshGenesisHashes, writeConfigurationDocument) import Cardano.Ledger.BaseTypes (unsafeNonZero) import Cardano.Ledger.Dijkstra.Genesis (DijkstraGenesis) -import Cardano.Node.Protocol.Byron import Control.Exception import Control.Monad import Control.Monad.Extra import Data.Aeson -import qualified Data.Aeson as Aeson import qualified Data.Aeson.Encode.Pretty as A -import Data.Aeson.Key hiding (fromString) -import Data.Aeson.KeyMap hiding (map) -import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as LBS -import qualified Data.Text as Text import qualified Data.Time.Clock as DTC import Data.Word (Word64) import GHC.Stack (HasCallStack) @@ -61,62 +52,30 @@ import qualified Hedgehog.Extras.Stock.Time as DTC import RIO (MonadThrow, throwM) --- | Returns JSON encoded hashes of the era, as well as the hard fork configuration toggle. -createConfigJson :: () +-- | Write the node configuration of a testnet: the default configuration for the +-- given era, with the hashes of the genesis files in the same directory as the +-- configuration file. The file is written in the @cardano-config@ format. +writeConfiguration :: () => HasCallStack => MonadIO m - => MonadThrow m - => TmpAbsolutePath + => FilePath -- ^ The configuration file to write -> ShelleyBasedEra era -- ^ The era used for generating the hard fork configuration toggle - -> m (KeyMap Aeson.Value) -createConfigJson (TmpAbsolutePath tempAbsPath) sbe = GHC.withFrozenCallStack $ do - byronGenesisHash <- getByronGenesisHash $ tempAbsPath "byron-genesis.json" - shelleyGenesisHash <- getHash ShelleyEra "ShelleyGenesisHash" - alonzoGenesisHash <- getHash AlonzoEra "AlonzoGenesisHash" - conwayGenesisHash <- getHash ConwayEra "ConwayGenesisHash" - dijkstraGenesisHash <- getHash DijkstraEra "DijkstraGenesisHash" - - pure $ mconcat - [ byronGenesisHash - , shelleyGenesisHash - , alonzoGenesisHash - , conwayGenesisHash - , dijkstraGenesisHash - , Defaults.defaultYamlHardforkViaConfig sbe - ] - where - getHash :: MonadIO m => CardanoEra a -> Text.Text -> m (KeyMap Value) - getHash e = getShelleyGenesisHash (tempAbsPath Defaults.defaultGenesisFilepath e) - -createConfigJsonNoHash :: () - => ShelleyBasedEra era -- ^ The era used for generating the hard fork configuration toggle - -> KeyMap Aeson.Value -createConfigJsonNoHash = Defaults.defaultYamlHardforkViaConfig - --- Generate hashes for genesis.json files - -getByronGenesisHash - :: MonadIO m - => MonadThrow m - => FilePath - -> m (KeyMap Aeson.Value) -getByronGenesisHash path = do - e <- runExceptT $ readGenesisData path - case e of - Left err -> throwM $ GenesisReadError path err - Right (_, genesisHash) -> do - let genesisHash' = unGenesisHash genesisHash - pure . singleton "ByronGenesisHash" $ toJSON genesisHash' - -getShelleyGenesisHash - :: MonadIO m - => FilePath - -> Text - -> m (KeyMap Aeson.Value) -getShelleyGenesisHash path key = do - content <- liftIOAnnotated $ BS.readFile path - let genesisHash = Crypto.hashWith id content :: Crypto.Hash Crypto.Blake2b_256 BS.ByteString - pure . singleton (fromText key) $ toJSON genesisHash + -> m () +writeConfiguration configFile sbe = GHC.withFrozenCallStack . liftIOAnnotated $ do + (document, _warnings) <- configurationDocumentFromValue . Object $ Defaults.defaultYamlHardforkViaConfig sbe + refreshGenesisHashes (takeDirectory configFile) document >>= writeConfigurationDocument configFile + +-- | Set the genesis hashes in a node configuration file to the hashes of the +-- genesis files it names, adding the missing ones and replacing the ones that +-- are out of date. +refreshConfigurationHashes :: () + => HasCallStack + => MonadIO m + => FilePath -- ^ The configuration file + -> m () +refreshConfigurationHashes configFile = GHC.withFrozenCallStack . liftIOAnnotated $ do + (document, _warnings) <- readConfigurationDocument configFile + refreshGenesisHashes (takeDirectory configFile) document >>= writeConfigurationDocument configFile -- | For an unknown reason, CLI commands are a lot slower on Windows than on Linux and -- MacOS. We need to allow a lot more time to set up a testnet. diff --git a/cardano-testnet/src/Testnet/Defaults.hs b/cardano-testnet/src/Testnet/Defaults.hs index df07b687965..4008a327e8c 100644 --- a/cardano-testnet/src/Testnet/Defaults.hs +++ b/cardano-testnet/src/Testnet/Defaults.hs @@ -93,6 +93,7 @@ import Cardano.Network.NodeToNode (DiffusionMode (..)) import Cardano.Network.PeerSelection.Bootstrap (UseBootstrapPeers (..)) import Cardano.Network.PeerSelection.PeerTrustable (PeerTrustable (..)) import Cardano.Node.Testnet.Paths +import Cardano.Node.Tracing.DefaultTraceConfig (defaultCardanoConfig) import Ouroboros.Network.ConnectionManager.Types (Provenance (..)) import Ouroboros.Network.Diffusion.Topology (LocalRootPeersGroup (..), LocalRootPeersGroups (..), LocalRoots (..), NetworkTopology (..), @@ -245,7 +246,6 @@ traceOptionsForwarding = defaultYamlHardforkViaConfig :: ShelleyBasedEra era -> Aeson.KeyMap Aeson.Value defaultYamlHardforkViaConfig sbe = defaultYamlConfig - <> [("TraceOptions", traceOptions)] <> protocolVersions sbe <> hardforkViaConfig sbe where @@ -319,8 +319,6 @@ defaultYamlHardforkViaConfig sbe = ] ) - traceOptions = Aeson.Object mempty - defaultYamlConfig :: Aeson.KeyMap Aeson.Value defaultYamlConfig = Aeson.fromList @@ -349,14 +347,33 @@ defaultYamlConfig = , ("RequiresNetworkMagic", "RequiresMagic") , ("PeerSharing", Aeson.Bool False) - - -- New tracing system: empty map = use all defaults. - -- Mandatory: trace-dispatcher's FromJSON parses "TraceOptions" at the root. - , ("TraceOptions", Aeson.object mempty) ] + <> defaultTraceConfig where genesisPath era = Aeson.String $ Text.pack $ defaultGenesisFilepath era +-- | The tracing configuration the node uses by default ('defaultCardanoConfig'), +-- as the tracing keys of a configuration file: @TraceOptions@ and +-- @TraceOptionMetricsPrefix@. +-- +-- They are written out because the node fills them in only for a configuration +-- in the flat format. Given an empty @TraceOptions@ in the @cardano-config@ +-- format, it uses @trace-dispatcher@'s fallback instead: every namespace at +-- @Notice@, and no metrics prefix. +-- +-- @trace-dispatcher@ renders a configuration with the keys of its newer format +-- (@Options@, @MetricsPrefix@); they are renamed to the keys a configuration +-- file uses. +defaultTraceConfig :: Aeson.KeyMap Aeson.Value +defaultTraceConfig = + Aeson.fromList + [ (fileKey, value) + | Aeson.Object rendered <- [toJSON defaultCardanoConfig] + , (renderedKey, fileKey) <- [("Options", "TraceOptions"), ("MetricsPrefix", "TraceOptionMetricsPrefix")] + , Just value <- [Aeson.lookup renderedKey rendered] + , value /= Aeson.Null + ] + -- | We need a Byron genesis in order to be able to hardfork to the later Shelley based eras. -- The values here don't matter as the testnet conditions are ultimately determined -- by the Shelley genesis. diff --git a/cardano-testnet/src/Testnet/Start/Cardano.hs b/cardano-testnet/src/Testnet/Start/Cardano.hs index 091ae886b64..a61b75e0ca7 100644 --- a/cardano-testnet/src/Testnet/Start/Cardano.hs +++ b/cardano-testnet/src/Testnet/Start/Cardano.hs @@ -40,6 +40,9 @@ import Cardano.Api import Cardano.Api.Byron (GenesisData (..)) import qualified Cardano.Api.Byron as Byron +import Cardano.Configuration.Edit (configurationDocumentFromValue, + configurationDocumentValue, readConfigurationDocument, + writeConfigurationDocument) import Cardano.Network.Diffusion.Topology (CardanoNetworkTopology) import Cardano.Node.Configuration.NodeAddress (PortNumber) import Cardano.Node.Configuration.TopologyP2P () @@ -47,7 +50,7 @@ import Cardano.Node.Testnet.Paths (defaultConfigFile, defaultNodeEnvFi defaultNodeTopologyFile, defaultNodesDataDir, defaultPortFile, defaultUtxoAddrPath) import Cardano.Prelude (NonEmpty ((:|)), canonicalEncodePretty, readMaybe) -import Cardano.Tracer.Configuration (LogFormat(..)) +import Cardano.Tracer.Configuration (LogFormat (..)) import Ouroboros.Network.PeerSelection.RelayAccessPoint (RelayAccessPoint (..)) import Prelude hiding (lines) @@ -59,8 +62,8 @@ import Control.Monad.Catch import Control.Monad.Trans.Maybe (runMaybeT) import Control.Monad.Trans.Resource (MonadResource, getInternalState) import Data.Aeson as Aeson -import qualified Data.Aeson.KeyMap as KeyMap import qualified Data.Aeson.Encode.Pretty as A +import qualified Data.Aeson.KeyMap as KeyMap import qualified Data.ByteString.Lazy as LBS import Data.Default.Class () import Data.Either @@ -80,10 +83,11 @@ import qualified Data.Yaml as Yaml import GHC.Exts (fromList) import GHC.Stack import qualified System.Directory as IO -import System.FilePath ((), dropExtension) +import System.FilePath (dropExtension, ()) import qualified System.Process as Process -import Testnet.CardanoTracer (CardanoTracerConf(..), CardanoTracerRuntime(..), startCardanoTracer) +import Testnet.CardanoTracer (CardanoTracerConf (..), CardanoTracerRuntime (..), + startCardanoTracer) import Testnet.ChainWatchdog (chainForecastHorizon, chainStallWatchdog, stderrTracer) import Testnet.Components.Configuration import qualified Testnet.Defaults as Defaults @@ -100,8 +104,8 @@ import Testnet.Types as TR hiding (shelleyGenesis) import qualified Hedgehog.Extras as H import Hedgehog.Extras.Stock (sprocketSystemName) -import Hedgehog.Extras.Stock.IO.Network.Sprocket (sprocketArgumentName) import qualified Hedgehog.Extras.Stock.IO.Network.Port as H +import Hedgehog.Extras.Stock.IO.Network.Sprocket (sprocketArgumentName) import Hedgehog.Internal.Property (failException) import RIO (MonadUnliftIO, RIO (..), runRIO, throwString, timeout) @@ -130,8 +134,7 @@ createTestnetEnv , creationNodes=TestnetNodesWithOptions{optSpoNodes, optRelayNodes} } Conf - { genesisHashesPolicy - , tempAbsPath=TmpAbsolutePath tmpAbsPath + { tempAbsPath=TmpAbsolutePath tmpAbsPath } = do -- Fresh-run rule: delete any manifest a previous run left in this directory, @@ -147,13 +150,8 @@ createTestnetEnv creationOptions (TmpAbsolutePath tmpAbsPath) - let configurationFile = tmpAbsPath defaultConfigFile - -- Add Byron, Shelley and Alonzo genesis hashes to node configuration - config <- case genesisHashesPolicy of - WithHashes -> createConfigJson (TmpAbsolutePath tmpAbsPath) sbe - WithoutHashes -> pure $ createConfigJsonNoHash sbe - - liftIOAnnotated . LBS.writeFile configurationFile $ A.encodePretty $ Object config + -- The node configuration, with the hashes of the genesis files just created + writeConfiguration (tmpAbsPath defaultConfigFile) sbe let allNodes = NEL.toList optSpoNodes ++ optRelayNodes numberedNodes = zip [1..] allNodes @@ -294,10 +292,9 @@ cardanoTestnet -- should connect to. The tracer's lifetime is tied to the surrounding -- 'MonadResource' scope, and it is additionally interrupted on SIGINT -- alongside the nodes (see 'interruptNodesOnSigINT' below). - (nodeConfigFile', mTracer) <- case cardanoEnableTracer of - TraceDisabled -> pure (nodeConfigFile, Nothing) + mTracer <- case cardanoEnableTracer of + TraceDisabled -> pure Nothing TraceEnabled ip mport -> do - cfgFile' <- liftIOAnnotated $ enableTraceForwarding nodeConfigFile tracerRuntime <- startCardanoTracer $ CardanoTracerConf { tempAbsPath = tmpAbsPath , prometheusIP = ip @@ -308,7 +305,7 @@ cardanoTestnet Ping.waitForSprocket 120 0.2 (tracerSprocket tracerRuntime) >>= \case Left err -> throwString $ "Sprocket of cardano-tracer did not come up after 120s: " <> show err Right _ -> pure () - pure (cfgFile', Just tracerRuntime) + pure $ Just tracerRuntime @@ -374,6 +371,17 @@ cardanoTestnet pure shelleyGenesis' else pure initialShelleyGenesis + -- Bring the genesis hashes in the node configuration in line with the genesis + -- files: the start times may just have been updated, and the files may have + -- been changed since the environment was created. + refreshConfigurationHashes nodeConfigFile + + -- With a cardano-tracer, the nodes run on a copy of the configuration that + -- forwards their traces to it. + nodeConfigFile' <- case mTracer of + Nothing -> pure nodeConfigFile + Just _ -> liftIOAnnotated $ enableTraceForwarding nodeConfigFile + let portNumbersMap = Map.fromList portNumbers rpcPortsMap <- case cardanoEnableRpc of @@ -599,14 +607,33 @@ cardanoTestnet -- modified config file. enableTraceForwarding :: FilePath -> IO FilePath enableTraceForwarding configFile = do - Yaml.decodeFileEither configFile >>= \case - Left err -> throwString $ "enableTraceForwarding: could not decode node configuration file " <> configFile <> ": " <> show err - Right (config :: KeyMap.KeyMap Yaml.Value) -> do - let config' = KeyMap.insertWith mergeTraceOptions "TraceOptions" Defaults.traceOptionsForwarding config - let configFile' = dropExtension configFile <> "-tracer.yaml" - Yaml.encodeFile configFile' config' - pure configFile' + (document, _warnings) <- readConfigurationDocument configFile + (document', _warnings') <- + configurationDocumentFromValue + . onObject (onKey "Configuration" . onKey "HermodTracing" $ + KeyMap.insertWith mergeTraceOptions "TraceOptions" Defaults.traceOptionsForwarding) + $ configurationDocumentValue document + let configFile' = dropExtension configFile <> "-tracer.yaml" + writeConfigurationDocument configFile' document' + pure configFile' where + -- The tracing settings are the @HermodTracing@ object of the @Configuration@ + -- section. A missing object (or one given as a file) is replaced. + onObject :: (KeyMap.KeyMap Aeson.Value -> KeyMap.KeyMap Aeson.Value) -> Aeson.Value -> Aeson.Value + onObject f = \case + Object o -> Object $ f o + other -> other + + onKey + :: KeyMap.Key + -> (KeyMap.KeyMap Aeson.Value -> KeyMap.KeyMap Aeson.Value) + -> KeyMap.KeyMap Aeson.Value + -> KeyMap.KeyMap Aeson.Value + onKey key f o = + KeyMap.insert key (Object . f $ case KeyMap.lookup key o of + Just (Object inner) -> inner + _ -> mempty) o + mergeTraceOptions :: Yaml.Value -> Yaml.Value -> Yaml.Value mergeTraceOptions (Object forwarding) (Object existing) = Object $ KeyMap.unionWith mergeNamespace forwarding existing diff --git a/cardano-testnet/src/Testnet/Start/Types.hs b/cardano-testnet/src/Testnet/Start/Types.hs index bdeefb66a1f..adfa075aa33 100644 --- a/cardano-testnet/src/Testnet/Start/Types.hs +++ b/cardano-testnet/src/Testnet/Start/Types.hs @@ -43,7 +43,6 @@ module Testnet.Start.Types , NodeLoggingFormat(..) , Conf(..) - , GenesisHashesPolicy (..) , NodeConfiguration , NodeConfigurationYaml , mkConf @@ -341,12 +340,8 @@ data NodeConfiguration type NodeConfigurationYaml = File NodeConfiguration InOut -data GenesisHashesPolicy = WithHashes | WithoutHashes - deriving (Eq, Show) - data Conf = Conf - { genesisHashesPolicy :: GenesisHashesPolicy - , tempAbsPath :: TmpAbsolutePath + { tempAbsPath :: TmpAbsolutePath , updateTimestamps :: UpdateTimestamps } deriving (Eq, Show) @@ -357,18 +352,16 @@ mkConf tempAbsPath' = withFrozenCallStack $ do H.note_ tempAbsPath' pure $ mkConfig tempAbsPath' --- | Create a 'Conf' from a temporary absolute path, with Genesis Hashes enabled --- and updating time stamps disabled. +-- | Create a 'Conf' from a temporary absolute path, with updating time stamps +-- disabled. mkConfig :: FilePath -> Conf mkConfig tempAbsPath' = Conf - { genesisHashesPolicy = WithHashes - , tempAbsPath = TmpAbsolutePath (addTrailingPathSeparator tempAbsPath') + { tempAbsPath = TmpAbsolutePath (addTrailingPathSeparator tempAbsPath') , updateTimestamps = DontUpdateTimestamps } --- | Create a 'Conf' from an absolute path, with Genesis Hashes enabled --- and updating time stamps disabled. +-- | Create a 'Conf' from an absolute path, with updating time stamps disabled. mkConfigAbs :: FilePath -> IO Conf mkConfigAbs userOutputDir = do absUserOutputDir <- makeAbsolute userOutputDir diff --git a/cardano-testnet/src/Testnet/SubmitApi.hs b/cardano-testnet/src/Testnet/SubmitApi.hs index f511fb4efbf..36e9fd98793 100644 --- a/cardano-testnet/src/Testnet/SubmitApi.hs +++ b/cardano-testnet/src/Testnet/SubmitApi.hs @@ -9,12 +9,12 @@ module Testnet.SubmitApi , withSubmitApi ) where -import Cardano.Api - import Cardano.Testnet import Prelude +import Data.Aeson ((.=)) +import qualified Data.Aeson as Aeson import qualified System.IO as IO import qualified System.Process as IO @@ -26,11 +26,11 @@ import Hedgehog.Extras.Stock (Sprocket (..)) import qualified Hedgehog.Extras.Stock.IO.Network.Socket as IO import qualified Hedgehog.Extras.Stock.IO.Network.Sprocket as IO import qualified Hedgehog.Extras.Test.Base as H +import qualified Hedgehog.Extras.Test.File as H import qualified Hedgehog.Extras.Test.Process as H data SubmitApiConf = SubmitApiConf { tempAbsPath :: FilePath - , configPath :: File NodeConfig In , epochSlots :: Int , sprocket :: Sprocket , testnetMagic :: Int @@ -41,7 +41,6 @@ withSubmitApi :: SubmitApiConf -> [String] -> (String -> Integration ()) -> Inte withSubmitApi SubmitApiConf { tempAbsPath - , configPath , epochSlots , sprocket , testnetMagic @@ -58,8 +57,13 @@ withSubmitApi [submitApiPort] <- H.evalIO $ maybe (IO.allocateRandomPorts 1) (pure . (:[])) maybePort + -- The submit API's configuration is a tracing configuration, not a node + -- configuration. An empty @TraceOptions@ leaves the submit API's defaults. + configFile <- H.noteTempFile tempAbsPath "submit-api-config.json" + H.lbsWriteFile configFile . Aeson.encode $ Aeson.object ["TraceOptions" .= Aeson.object []] + cp <- procSubmitApi $ - [ "--config", unFile configPath + [ "--config", configFile , "--cardano-mode" , "--epoch-slots", show epochSlots , "--socket-path", IO.sprocketArgumentName sprocket diff --git a/cardano-testnet/src/Testnet/Types.hs b/cardano-testnet/src/Testnet/Types.hs index c463ae1453c..5cb0cd703b6 100644 --- a/cardano-testnet/src/Testnet/Types.hs +++ b/cardano-testnet/src/Testnet/Types.hs @@ -53,10 +53,6 @@ import Cardano.Api import Cardano.Api.Experimental (Some (..)) import qualified Cardano.Chain.Genesis as G -import Cardano.Crypto.ProtocolMagic (RequiresNetworkMagic (..)) -import Cardano.Node.Configuration.POM -import qualified Cardano.Node.Protocol.Byron as Byron -import Cardano.Node.Types import qualified Cardano.Rpc.Client as Rpc import Cardano.Rpc.Server.Config (nodeSocketPathToRpcSocketPath) @@ -71,14 +67,12 @@ import Data.List.NonEmpty (NonEmpty) import qualified Data.List.NonEmpty as NEL import Data.Maybe import Data.MonoTraversable (Element, MonoFunctor (..)) -import qualified Data.Yaml as Yaml import GHC.Exts (IsString (..)) import GHC.Generics (Generic) import qualified GHC.IO.Handle as IO import GHC.Stack import Lens.Micro (ix, (^?)) import Network.Socket (HostAddress, PortNumber, hostAddressToTuple, tupleToHostAddress) -import System.FilePath import qualified System.Process as IO import Testnet.Start.Types @@ -268,24 +262,14 @@ getStartTime :: H.MonadTest m => MonadIO m => HasCallStack - => FilePath - -> TestnetRuntime + => TestnetRuntime -> m SystemStart -getStartTime tempRootPath TestnetRuntime{configurationFile} = withFrozenCallStack $ H.evalEither <=< H.evalIO . runExceptT $ do - byronGenesisFile <- - decodeNodeConfiguration configurationFile >>= \case - NodeProtocolConfigurationCardano NodeByronProtocolConfiguration{npcByronGenesisFile} _ _ _ _ _ _ -> - pure $ unGenesisFile npcByronGenesisFile - let byronGenesisFilePath = tempRootPath byronGenesisFile - SystemStart . G.gdStartTime . G.configGenesisData <$> decodeGenesisFile byronGenesisFilePath - where - decodeNodeConfiguration :: File NodeConfig In -> ExceptT String IO NodeProtocolConfiguration - decodeNodeConfiguration (File file) = do - partialNodeCfg <- modifyError show $ ExceptT $ Yaml.decodeFileEither file - fmap ncProtocolConfig . liftEither . makeNodeConfiguration $ defaultPartialNodeConfiguration <> partialNodeCfg - decodeGenesisFile :: FilePath -> ExceptT String IO G.Config - decodeGenesisFile fp = withExceptT (docToString . prettyError) $ - Byron.readGenesis (GenesisFile fp) Nothing RequiresNoMagic +getStartTime TestnetRuntime{configurationFile} = withFrozenCallStack $ H.evalEither <=< H.evalIO . runExceptT $ do + (nodeConfig, _warnings) <- modifyError show $ readNodeConfig configurationFile + -- readNodeConfig has already read and hash-checked the genesis files, so + -- readByronGenesisConfig is a plain projection of what it returned. + let byronGenesis = readByronGenesisConfig nodeConfig + pure . SystemStart . G.gdStartTime $ G.configGenesisData byronGenesis readNodeLoggingFormat :: String -> Either String NodeLoggingFormat readNodeLoggingFormat = \case diff --git a/cardano-testnet/test/cardano-testnet-golden/files/golden/node_default_config.json b/cardano-testnet/test/cardano-testnet-golden/files/golden/node_default_config.json index 9528440b7bc..fca77ce4923 100644 --- a/cardano-testnet/test/cardano-testnet-golden/files/golden/node_default_config.json +++ b/cardano-testnet/test/cardano-testnet-golden/files/golden/node_default_config.json @@ -21,5 +21,78 @@ "TestConwayHardForkAtEpoch": 0, "TestMaryHardForkAtEpoch": 0, "TestShelleyHardForkAtEpoch": 0, - "TraceOptions": {} + "TraceOptionMetricsPrefix": "cardano.node.metrics.", + "TraceOptions": { + "": { + "backends": [ + "Stdout MachineFormat", + "EKGBackend" + ], + "detail": "DNormal", + "severity": "Notice" + }, + "BlockFetch.Client.CompletedBlockFetch": { + "maxFrequency": 2 + }, + "BlockFetch.Decision": { + "severity": "Silence" + }, + "ChainDB": { + "severity": "Info" + }, + "ChainDB.AddBlockEvent.AddBlockValidation": { + "severity": "Silence" + }, + "ChainDB.AddBlockEvent.AddBlockValidation.ValidCandidate": { + "maxFrequency": 2 + }, + "ChainDB.AddBlockEvent.AddedBlockToQueue": { + "maxFrequency": 2 + }, + "ChainDB.AddBlockEvent.AddedBlockToVolatileDB": { + "maxFrequency": 2 + }, + "ChainDB.CopyToImmutableDBEvent.CopiedBlockToImmutableDB": { + "maxFrequency": 2 + }, + "ChainSync.Client": { + "severity": "Warning" + }, + "Forge.Loop": { + "severity": "Info" + }, + "Forge.StateInfo": { + "severity": "Info" + }, + "LedgerMetrics": { + "severity": "Silence" + }, + "Mempool": { + "severity": "Info" + }, + "Net.ConnectionManager.Remote": { + "severity": "Info" + }, + "Net.ErrorPolicy": { + "severity": "Info" + }, + "Net.InboundGovernor": { + "severity": "Warning" + }, + "Net.InboundGovernor.Remote": { + "severity": "Info" + }, + "Net.Mux.Remote": { + "severity": "Info" + }, + "Net.PeerSelection": { + "severity": "Silence" + }, + "Resources": { + "severity": "Silence" + }, + "Startup.DiffusionInit": { + "severity": "Info" + } + } } \ No newline at end of file diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Api/TxReferenceInputDatum.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Api/TxReferenceInputDatum.hs index 46e023a88b1..ccc29aab6ed 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Api/TxReferenceInputDatum.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Api/TxReferenceInputDatum.hs @@ -56,8 +56,7 @@ import qualified Hedgehog.Extras.Test.TestWatchdog as H -- This test tests that such datums are made available to the script. hprop_tx_refin_datum :: Property hprop_tx_refin_datum = integrationRetryWorkspace 2 "api-tx-refin-dat" $ \tempAbsBasePath' -> H.runWithDefaultWatchdog_ $ do - conf@Conf{tempAbsPath} <- mkConf tempAbsBasePath' - let tempAbsPath' = unTmpAbsPath tempAbsPath + conf <- mkConf tempAbsBasePath' let era = Exp.ConwayEra sbe = convert era @@ -73,7 +72,7 @@ hprop_tx_refin_datum = integrationRetryWorkspace 2 "api-tx-refin-dat" $ \tempAbs } <- createAndRunTestnet creationOptions def conf - systemStart <- H.noteShowM $ getStartTime tempAbsPath' tr + systemStart <- H.noteShowM $ getStartTime tr epochStateView <- getEpochStateView configurationFile (nodeSocketPath node0) connectionInfo <- nodeConnectionInfo tr 0 pparams <- getProtocolParams epochStateView ceo diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/KesPeriodInfo.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/KesPeriodInfo.hs index f099ec51312..a745942ce66 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/KesPeriodInfo.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/KesPeriodInfo.hs @@ -23,7 +23,6 @@ import Prelude import Control.Monad import qualified Data.Aeson as Aeson import qualified Data.Aeson as J -import qualified Data.Aeson.Encode.Pretty as Aeson import Data.Default.Class import Data.Function import qualified Data.IP as IP @@ -42,7 +41,6 @@ import Testnet.Process.Cli.SPO import Testnet.Process.Run (execCli, execCli', mkExecConfig) import Testnet.Property.Util (decodeEraUTxO, integrationRetryWorkspace) import Testnet.Runtime -import Testnet.Start.Cardano (liftToIntegration) import Testnet.Types import Hedgehog (Property) @@ -259,8 +257,7 @@ hprop_kes_period_info = integrationRetryWorkspace 2 "kes-period-info" $ \tempAbs , "--out-file", testSpoOperationalCertFp ] - jsonBS <- liftToIntegration $ Aeson.encodePretty . Aeson.Object <$> createConfigJson tempAbsPath sbe - H.lbsWriteFile (unFile configurationFile) jsonBS + writeConfiguration (unFile configurationFile) sbe newNodePortNumber <- H.randomPort testnetDefaultIpv4Address eRuntime <- runExceptT . retryOnAddressInUseError $ startNode tempAbsPath "test-spo" testnetDefaultIpv4Address newNodePortNumber testnetMagic Nothing diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/LeadershipSchedule.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/LeadershipSchedule.hs index 00be5b1a35e..06d9a49d0ee 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/LeadershipSchedule.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/LeadershipSchedule.hs @@ -24,7 +24,6 @@ import Prelude import Control.Monad (void) import qualified Data.Aeson as Aeson import qualified Data.Aeson as J -import qualified Data.Aeson.Encode.Pretty as Aeson import qualified Data.Aeson.Types as J import Data.Default.Class import qualified Data.IP as IP @@ -48,7 +47,6 @@ import Testnet.Process.Run (execCli, execCli', mkExecConfig) import Testnet.Property.Assert import Testnet.Property.Util (decodeEraUTxO, integrationRetryWorkspace) import Testnet.Runtime -import Testnet.Start.Cardano import Testnet.Types import Hedgehog (Property, (===)) @@ -263,9 +261,7 @@ hprop_leadershipSchedule = integrationRetryWorkspace 2 "leadership-schedule" $ \ , "--operational-certificate-issue-counter-file", testSpoOperationalCertFp , "--out-file", testSpoOperationalCertFp ] - jsonBS <- liftToIntegration $ - Aeson.encodePretty . Aeson.Object <$> createConfigJson tempAbsPath sbe - H.lbsWriteFile (unFile configurationFile) jsonBS + writeConfiguration (unFile configurationFile) sbe newNodePort <- H.randomPort testnetDefaultIpv4Address eRuntime <- runExceptT . retryOnAddressInUseError $ startNode (TmpAbsolutePath work) "test-spo" testnetDefaultIpv4Address newNodePort testnetMagic Nothing diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/QuerySlotNumber.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/QuerySlotNumber.hs index f369b74139d..e6e230ee8ef 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/QuerySlotNumber.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/QuerySlotNumber.hs @@ -49,7 +49,7 @@ hprop_querySlotNumber = integrationRetryWorkspace 2 "query-slot-number" $ \tempA , testnetNodes } <- createAndRunTestnet def def conf ShelleyGenesis{sgSlotLength, sgEpochLength} <- H.noteShowM $ shelleyGenesis tr - SystemStart startTime <- H.noteShowM $ getStartTime tempAbsBasePath' tr + SystemStart startTime <- H.noteShowM $ getStartTime tr let slotLength = fromNominalDiffTimeMicro sgSlotLength -- how many slots can the checked value differ from diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/DumpConfig.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/DumpConfig.hs index 3aa8aa190fd..e5dd1498003 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/DumpConfig.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/DumpConfig.hs @@ -26,7 +26,7 @@ import System.FilePath (()) import Testnet.Components.Configuration (startTimeOffsetSeconds) import Testnet.Property.Util (integrationRetryWorkspace) import Testnet.Start.Cardano (liftToIntegration) -import Testnet.Start.Types (GenesisHashesPolicy (..), GenesisOptions (..)) +import Testnet.Start.Types (GenesisOptions (..)) import qualified Hedgehog as H import qualified Hedgehog.Extras as H @@ -43,11 +43,7 @@ hprop_dump_config = integrationRetryWorkspace 2 "dump-config-files" $ \tmpDir -> -- Generate the sandbox conf <- mkConf tmpDir - liftToIntegration $ createTestnetEnv - creationOptions - -- Do not add hashes to the main config file, so that genesis files - -- can be modified without having to recompute hashes every time. - conf{genesisHashesPolicy = WithoutHashes} + liftToIntegration $ createTestnetEnv creationOptions conf -- Wait for 20% more than `startTimeOffsetSeconds`, to ensure that -- the time bounds in the sandbox' config files are no longer valid diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Gov/ProposeNewConstitution.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Gov/ProposeNewConstitution.hs index 3aec166bb4a..d2fa6bc60d5 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Gov/ProposeNewConstitution.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Gov/ProposeNewConstitution.hs @@ -118,11 +118,6 @@ hprop_ledger_events_propose_new_constitution = integrationRetryWorkspace 2 "prop } } - -- Rehash: the node validates genesis file hashes against configuration.yaml - conwayGenesisHash <- getShelleyGenesisHash conwayGenesisFile "ConwayGenesisHash" - H.rewriteJsonFile (tempAbsBasePath' "configuration.yaml") $ - \(config :: Aeson.Value) -> config & Aeson._Object %~ (conwayGenesisHash <>) - TestnetRuntime { testnetMagic , testnetNodes diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Node/Shutdown.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Node/Shutdown.hs index aa661b7b085..410143fbae5 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Node/Shutdown.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Node/Shutdown.hs @@ -124,8 +124,6 @@ hprop_shutdown = integrationRetryWorkspace 2 "shutdown" $ \tempAbsBasePath' -> H , "--start-time", formatIso8601 startTime ] - byronGenesisHash <- liftToIntegration $ Testnet.getByronGenesisHash $ byronGenesisOutputDir "genesis.json" - -- Move the files to the paths expected by 'defaultYamlHardforkViaConfig' below H.renameFile (byronGenesisOutputDir "genesis.json") (tempAbsPath' defaultGenesisFilepath ByronEra) H.renameFile (tempAbsPath' "shelley/genesis.json") (tempAbsPath' defaultGenesisFilepath ShelleyEra) @@ -134,20 +132,7 @@ hprop_shutdown = integrationRetryWorkspace 2 "shutdown" $ \tempAbsBasePath' -> H -- TODO: once 'cardano-cli latest genesis create' supports dijkstra, make this a copy instead of writing a default H.writeFile (tempAbsPath' defaultGenesisFilepath DijkstraEra) . LBS.unpack $ encode defaultDijkstraGenesis - (shelleyGenesisHash,alonzoGenesisHash) <- - liftToIntegration $ do - shelleyGenesisHash <- Testnet.getShelleyGenesisHash (tempAbsPath' defaultGenesisFilepath ShelleyEra) "ShelleyGenesisHash" - alonzoGenesisHash <- Testnet.getShelleyGenesisHash (tempAbsPath' defaultGenesisFilepath AlonzoEra) "AlonzoGenesisHash" - return (shelleyGenesisHash, alonzoGenesisHash) - - let finalYamlConfig :: LBS.ByteString - finalYamlConfig = encode . Object - $ mconcat [ byronGenesisHash - , shelleyGenesisHash - , alonzoGenesisHash - , defaultYamlHardforkViaConfig sbe] - - H.evalIO $ LBS.writeFile (tempAbsPath' "configuration.yaml") finalYamlConfig + Testnet.writeConfiguration (tempAbsPath' "configuration.yaml") sbe H.evalIO $ LBS.writeFile (tempAbsPath' "mainnet-topology.json") $ encode defaultMainnetTopology diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/SubmitApi/Transaction.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/SubmitApi/Transaction.hs index 2e84dcba5dc..7881b4d68b0 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/SubmitApi/Transaction.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/SubmitApi/Transaction.hs @@ -120,7 +120,6 @@ hprop_transaction = integrationRetryWorkspace 2 "submit-api-transaction" $ \temp let submitApiConf = SubmitApiConf { tempAbsPath = unTmpAbsPath tempAbsPath - , configPath = configurationFile , epochSlots = 2 , sprocket = poolSprocket1 , maybePort = Nothing diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/UpdateTimeStamps.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/UpdateTimeStamps.hs index a406125f9e7..db80fca803d 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/UpdateTimeStamps.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/UpdateTimeStamps.hs @@ -18,8 +18,7 @@ import GHC.Float (double2Int) import Testnet.Components.Configuration (startTimeOffsetSeconds) import Testnet.Property.Util (integrationRetryWorkspace) import Testnet.Start.Cardano (liftToIntegration) -import Testnet.Start.Types (GenesisHashesPolicy (..), GenesisOptions (..), - UpdateTimestamps (..)) +import Testnet.Start.Types (GenesisOptions (..), UpdateTimestamps (..)) import qualified Hedgehog as H import qualified Hedgehog.Extras as H @@ -33,11 +32,7 @@ hprop_update_time_stamps = integrationRetryWorkspace 2 "update-time-stamps" $ \t -- Generate the sandbox conf <- mkConf tmpDir - liftToIntegration $ createTestnetEnv - creationOptions - -- Do not add hashes to the main config file, so that genesis files - -- can be modified without having to recompute hashes every time. - conf{genesisHashesPolicy = WithoutHashes} + liftToIntegration $ createTestnetEnv creationOptions conf -- Wait for 20% more than `startTimeOffsetSeconds`, to ensure that -- the time bounds in the sandbox' config files are no longer valid From e5848295bad67afa74ef52470d06799323e17724 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Thu, 15 Oct 2026 15:25:50 +0000 Subject: [PATCH 19/45] Let the chairman read node configurations in the cardano-config format --- ...29_palas_chairman_reads_cardano_config.yml | 4 +++ .../app/Cardano/Chairman/Commands/Run.hs | 34 +++++++++++++++---- .../cardano-node-chairman.cabal | 1 + .../Configuration/CardanoConfigResolve.hs | 24 ++++++++----- 4 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 cardano-node-chairman/.changes/20261015_171029_palas_chairman_reads_cardano_config.yml diff --git a/cardano-node-chairman/.changes/20261015_171029_palas_chairman_reads_cardano_config.yml b/cardano-node-chairman/.changes/20261015_171029_palas_chairman_reads_cardano_config.yml new file mode 100644 index 00000000000..a0498a0840d --- /dev/null +++ b/cardano-node-chairman/.changes/20261015_171029_palas_chairman_reads_cardano_config.yml @@ -0,0 +1,4 @@ +pr: 6677 +kind: + - feature +description: The chairman reads node configurations in the cardano-config format too, the way the node does. diff --git a/cardano-node-chairman/app/Cardano/Chairman/Commands/Run.hs b/cardano-node-chairman/app/Cardano/Chairman/Commands/Run.hs index da903f0c73c..a5433930584 100644 --- a/cardano-node-chairman/app/Cardano/Chairman/Commands/Run.hs +++ b/cardano-node-chairman/app/Cardano/Chairman/Commands/Run.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} @@ -12,9 +13,14 @@ import Cardano.Api import qualified Cardano.Api as Api import Cardano.Chairman (chairmanTest) +import Cardano.Configuration (defaultCliArgs) import Cardano.Ledger.BaseTypes (unNonZero) +import Cardano.Node.Configuration.CardanoConfigResolve (ConfigurationDialect (..), + ResolvedNodeConfiguration (..), buildFromCardanoConfigWith, + classifyConfigurationFile) import Cardano.Node.Configuration.POM (PartialNodeConfiguration (..), parseNodeConfigurationFP) +import qualified Cardano.Node.Configuration.POM as POM import Cardano.Node.Protocol import Cardano.Node.Types import Cardano.Prelude (ConvertText (..)) @@ -97,13 +103,7 @@ run RunOpts , caConfigYaml } = do - configYamlPc <- liftIO . parseNodeConfigurationFP $ Just caConfigYaml - - ptclConfig <- case getProtocolConfiguration configYamlPc of - Nothing -> - error $ "Node protocol configuration was not specified "<> - "in Config yaml filepath: " <> unConfigPath caConfigYaml - Just ptclConfig -> return ptclConfig + ptclConfig <- readProtocolConfiguration caConfigYaml eitherSomeProtocol <- runExceptT $ mkConsensusProtocol ptclConfig Nothing @@ -140,6 +140,26 @@ run RunOpts NodeProtocolConfigurationCardano{} -> CardanoModeParams $ EpochSlots $ unNonZero k +-- | The protocol configuration in a node configuration file, read the way the +-- node reads it: by @cardano-config@ for a file in its format, by the node's own +-- parser otherwise. The chairman's command line is not the node's, so the +-- settings all come from the file. +readProtocolConfiguration :: ConfigYamlFilePath -> IO NodeProtocolConfiguration +readProtocolConfiguration caConfigYaml = + classifyConfigurationFile configFile >>= \case + LegacyDialect -> do + configYamlPc <- parseNodeConfigurationFP $ Just caConfigYaml + case getProtocolConfiguration configYamlPc of + Nothing -> + error $ "Node protocol configuration was not specified "<> + "in Config yaml filepath: " <> configFile + Just ptclConfig -> return ptclConfig + CardanoConfigDialect -> + POM.ncProtocolConfig . rncConfiguration + <$> buildFromCardanoConfigWith configFile (defaultCliArgs configFile) + where + configFile = unConfigPath caConfigYaml + getProtocolConfiguration :: PartialNodeConfiguration -> Maybe NodeProtocolConfiguration diff --git a/cardano-node-chairman/cardano-node-chairman.cabal b/cardano-node-chairman/cardano-node-chairman.cabal index ac993ae33ae..de40fb3ca25 100644 --- a/cardano-node-chairman/cardano-node-chairman.cabal +++ b/cardano-node-chairman/cardano-node-chairman.cabal @@ -42,6 +42,7 @@ executable cardano-node-chairman -rtsopts "-with-rtsopts=-T" build-depends: cardano-api + , cardano-config ^>= 2.2 , cardano-crypto-class , cardano-git-rev ^>= 0.2.2 , cardano-ledger-core diff --git a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs index 4662bb84844..d6493935501 100644 --- a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs +++ b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs @@ -31,6 +31,7 @@ module Cardano.Node.Configuration.CardanoConfigResolve ResolvedNodeConfiguration (..) , CrossCheck (..) , buildNodeConfiguration + , buildFromCardanoConfigWith , NodeConfigurationError (..) -- * Dialects @@ -43,13 +44,12 @@ module Cardano.Node.Configuration.CardanoConfigResolve , cardanoConfigCliLayer ) where -import Cardano.Logging.Types (TraceConfig) import qualified Cardano.Configuration as Cfg import qualified Cardano.Configuration.CliArgs as CliArgs -import Cardano.Node.Configuration.CardanoConfigAdapter - (cardanoConfigToNodeConfiguration) -import Cardano.Node.Configuration.CardanoConfigCompare - (compareConfigurations, deprecatedFlagWarnings) +import Cardano.Logging.Types (TraceConfig) +import Cardano.Node.Configuration.CardanoConfigAdapter (cardanoConfigToNodeConfiguration) +import Cardano.Node.Configuration.CardanoConfigCompare (compareConfigurations, + deprecatedFlagWarnings) import Cardano.Node.Configuration.POM (NodeConfiguration (..), PartialNodeConfiguration (..), defaultPartialNodeConfiguration, makeNodeConfiguration, parseNodeConfigurationFP) @@ -167,10 +167,16 @@ buildFromLegacy crossCheck partialConf configFp = do -- the node's 'NodeConfiguration'. Unlike the cross-check on the legacy path, -- every failure here is fatal: there is no second parser to fall back to. buildFromCardanoConfig :: FilePath -> IO ResolvedNodeConfiguration -buildFromCardanoConfig configFp = do - cliArgs <- - cardanoConfigCliArgs configFp - >>= either (Exception.throwIO . NodeConfigurationError) pure +buildFromCardanoConfig configFp = + cardanoConfigCliArgs configFp + >>= either (Exception.throwIO . NodeConfigurationError) (buildFromCardanoConfigWith configFp) + +-- | 'buildFromCardanoConfig' with a given command-line layer instead of this +-- process's own command line: for a caller that is not the node, whose command +-- line is not the node's. With @'Cfg.defaultCliArgs' configFp@ every setting +-- comes from the file. +buildFromCardanoConfigWith :: FilePath -> Cfg.CliArgs -> IO ResolvedNodeConfiguration +buildFromCardanoConfigWith configFp cliArgs = do (fileCfg, fileWarnings) <- Cfg.parseConfigurationFiles configFp (cfgNc, checkWarnings) <- either (Exception.throwIO . NodeConfigurationError . displayException) pure $ From 5ec148930728c8a1830d32a442be5dcb360fe455 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Sun, 11 Oct 2026 06:11:41 -0500 Subject: [PATCH 20/45] bump: mithril for v2630.1-hotfix --- flake.lock | 8 ++++---- flake.nix | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index 9d37b6d00dc..d31a03d4302 100644 --- a/flake.lock +++ b/flake.lock @@ -1198,16 +1198,16 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1785407305, - "narHash": "sha256-8Ay4GLKQGeJwGQPLliUNvgfkKCHFVUeASWFu/e0SxqM=", + "lastModified": 1789639081, + "narHash": "sha256-l6ACwepW8R5zsx1iNw9VOzdRfOWhfSE3+GcP6VkX8Zc=", "owner": "IntersectMBO", "repo": "mithril", - "rev": "23e124d99320adea6eb3eca361132c6c43d59cfa", + "rev": "3f6cb73f491eb3195d02318643e40836fb093acc", "type": "github" }, "original": { "owner": "IntersectMBO", - "ref": "refs/tags/2630.0", + "ref": "refs/tags/2630.1-hotfix", "repo": "mithril", "type": "github" } diff --git a/flake.nix b/flake.nix index 21c30d906ea..15dfabae336 100644 --- a/flake.nix +++ b/flake.nix @@ -66,7 +66,7 @@ # Bump the tag and then run: nix flake lock --update-input mithril. # Changing the tag alone only relocks mithril itself, leaving its # transitive pins on an old release. - mithril.url = "github:IntersectMBO/mithril?ref=refs/tags/2630.0"; + mithril.url = "github:IntersectMBO/mithril?ref=refs/tags/2630.1-hotfix"; }; outputs = { From c0b8f714975e59614227436bd0959c300d36c8d5 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Sun, 13 Sep 2026 22:16:37 -0500 Subject: [PATCH 21/45] flake: bump iohkNix for the node 11.2 config series Brings in the enveloped environment configs, along with the cardanoLib attributes the release archive and docker changes need: mkEnvelope and the per-environment configFormat. cardano-config 1.1.0.0 appears in the lock transitively as iohk-nix's source-only schema input. --- flake.lock | 25 ++++++++++++++++++++++--- flake.nix | 2 +- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index d31a03d4302..183a652f114 100644 --- a/flake.lock +++ b/flake.lock @@ -176,6 +176,23 @@ "type": "github" } }, + "cardano-config": { + "flake": false, + "locked": { + "lastModified": 1792141866, + "narHash": "sha256-zF5LFdthGAChJGjGQ3NGkz6LRtB8N/3Hie6A70vY5gI=", + "owner": "IntersectMBO", + "repo": "cardano-config", + "rev": "f22b91530d4a1de56882b71a79ebbfbea7de83d8", + "type": "github" + }, + "original": { + "owner": "IntersectMBO", + "ref": "cardano-config-2.2.2.0", + "repo": "cardano-config", + "type": "github" + } + }, "cardano-dev": { "inputs": { "haskellNix": "haskellNix", @@ -1135,6 +1152,7 @@ "iohkNix_2": { "inputs": { "blst": "blst_2", + "cardano-config": "cardano-config", "nixpkgs": [ "nixpkgs" ], @@ -1142,15 +1160,16 @@ "sodium": "sodium_2" }, "locked": { - "lastModified": 1787718550, - "narHash": "sha256-Wkevfb7P201JHWpP4sbSg3HEO4YDPuCrwvARatfF2RI=", + "lastModified": 1792756495, + "narHash": "sha256-KUXDHN2p9e83PPtespiYf/MMW41/ngYDq5Bgi+PmGoU=", "owner": "input-output-hk", "repo": "iohk-nix", - "rev": "af463a46dbe9c6e2db6b2639c0f35f5689e0c3a8", + "rev": "d0031fb59ddfedc713129718b62f931581039f5d", "type": "github" }, "original": { "owner": "input-output-hk", + "ref": "jl/node-11.2", "repo": "iohk-nix", "type": "github" } diff --git a/flake.nix b/flake.nix index 15dfabae336..2e6aa724e25 100644 --- a/flake.nix +++ b/flake.nix @@ -50,7 +50,7 @@ incl.url = "github:divnix/incl"; iohkNix = { - url = "github:input-output-hk/iohk-nix"; + url = "github:input-output-hk/iohk-nix/jl/node-11.2"; inputs.nixpkgs.follows = "nixpkgs"; }; From 49d555ccc135e0fb1f423e0db945ce2f173ec4e7 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Sun, 13 Sep 2026 22:18:30 -0500 Subject: [PATCH 22/45] configuration: refresh network configs for the 11.2 series Regenerated with update-config-files.sh against the bumped iohkNix. mainnet-config.json is now in the cardano-config envelope, following what iohk-nix publishes. mainnet-config.yaml is hand-maintained and stays flat; it drops the same keys the json series drops, Protocol and MaxKnownMajorProtocolVersion, and its MinNodeVersion moves to 11.2.0 to match. The two remain equivalent through migrate, which reproduces the json from the yaml byte for byte, though they are no longer directly comparable. testnet-template-config.json drops ApplicationName, ApplicationVersion, PBftSignatureThreshold, Protocol and MaxKnownMajorProtocolVersion. The template is copied from the iohk-nix source tree rather than from the published deployment, so it stays flat. testnet-template-dijkstra.json picks up the Leios genesis protocol parameters added in the w36 respin. --- configuration/cardano/mainnet-config.json | 227 +++++++++--------- configuration/cardano/mainnet-config.yaml | 9 +- .../cardano/testnet-template-config.json | 5 - .../cardano/testnet-template-dijkstra.json | 47 +++- 4 files changed, 165 insertions(+), 123 deletions(-) diff --git a/configuration/cardano/mainnet-config.json b/configuration/cardano/mainnet-config.json index 91e40c4beb1..3b6d971b6c8 100644 --- a/configuration/cardano/mainnet-config.json +++ b/configuration/cardano/mainnet-config.json @@ -1,114 +1,121 @@ { - "AlonzoGenesisFile": "mainnet-alonzo-genesis.json", - "AlonzoGenesisHash": "7e94a15f55d1e82d10f09203fa1d40f8eede58fd8066542cf6566008068ed874", - "ByronGenesisFile": "mainnet-byron-genesis.json", - "ByronGenesisHash": "5f20df933584822601f9e3f8c024eb5eb252fe8cefb24d1317dc3d432e940ebb", - "CheckpointsFile": "mainnet-checkpoints.json", - "CheckpointsFileHash": "3e6dee5bae7acc6d870187e72674b37c929be8c66e62a552cf6a876b1af31ade", - "ConsensusMode": "PraosMode", - "ConwayGenesisFile": "mainnet-conway-genesis.json", - "ConwayGenesisHash": "15a199f895e461ec0ffc6dd4e4028af28a492ab4e806d39cb674c88f7643ef62", - "LastKnownBlockVersion-Alt": 0, - "LastKnownBlockVersion-Major": 3, - "LastKnownBlockVersion-Minor": 0, - "LedgerDB": { - "Backend": "V2InMemory", - "QueryBatchSize": 100000, - "Snapshots": { - "NumOfDiskSnapshots": 2, - "SlotOffset": 0, - "SnapshotInterval": 86400 + "$schema": "https://raw.githubusercontent.com/IntersectMBO/cardano-config/v1/schemas/config.schema.json", + "Configuration": { + "ConsensusConfig": { + "ConsensusMode": "PraosMode" + }, + "HermodTracing": { + "TraceOptionForwarder": { + "connQueueSize": 64, + "disconnQueueSize": 128, + "maxReconnectDelay": 30 + }, + "TraceOptionMetricsPrefix": "cardano.node.metrics.", + "TraceOptionResourceFrequency": 1000, + "TraceOptions": { + "": { + "backends": [ + "EKGBackend", + "Forwarder", + "PrometheusSimple suffix 127.0.0.1 12798", + "Stdout HumanFormatColoured" + ], + "detail": "DNormal", + "severity": "Notice" + }, + "BlockFetch.Client.CompletedBlockFetch": { + "maxFrequency": 2.0 + }, + "BlockFetch.Decision": { + "severity": "Info" + }, + "ChainDB": { + "severity": "Info" + }, + "ChainDB.AddBlockEvent.AddBlockValidation": { + "severity": "Silence" + }, + "ChainDB.AddBlockEvent.AddBlockValidation.ValidCandidate": { + "maxFrequency": 2.0 + }, + "ChainDB.AddBlockEvent.AddedBlockToQueue": { + "maxFrequency": 2.0 + }, + "ChainDB.AddBlockEvent.AddedBlockToVolatileDB": { + "maxFrequency": 2.0 + }, + "ChainDB.CopyToImmutableDBEvent.CopiedBlockToImmutableDB": { + "maxFrequency": 2.0 + }, + "ChainDB.LedgerEvent.Forker": { + "severity": "Silence" + }, + "ChainSync.Client": { + "severity": "Warning" + }, + "Forge.Loop": { + "severity": "Info" + }, + "Forge.StateInfo": { + "severity": "Info" + }, + "Mempool": { + "severity": "Silence" + }, + "Mempool.AttemptAdd": { + "severity": "Silence" + }, + "Mempool.SyncNotNeeded": { + "severity": "Silence" + }, + "Net.ConnectionManager.Remote": { + "severity": "Info" + }, + "Net.InboundGovernor": { + "severity": "Warning" + }, + "Net.InboundGovernor.Remote": { + "severity": "Info" + }, + "Net.Mux.Remote": { + "severity": "Info" + }, + "Net.PeerSelection": { + "severity": "Info" + }, + "Resources": { + "severity": "Silence" + }, + "Startup.DiffusionInit": { + "severity": "Info" + } + } + }, + "ProtocolConfig": { + "AlonzoGenesisFile": "mainnet-alonzo-genesis.json", + "AlonzoGenesisHash": "7e94a15f55d1e82d10f09203fa1d40f8eede58fd8066542cf6566008068ed874", + "ByronGenesisFile": "mainnet-byron-genesis.json", + "ByronGenesisHash": "5f20df933584822601f9e3f8c024eb5eb252fe8cefb24d1317dc3d432e940ebb", + "CheckpointsFile": "mainnet-checkpoints.json", + "CheckpointsFileHash": "3e6dee5bae7acc6d870187e72674b37c929be8c66e62a552cf6a876b1af31ade", + "ConwayGenesisFile": "mainnet-conway-genesis.json", + "ConwayGenesisHash": "15a199f895e461ec0ffc6dd4e4028af28a492ab4e806d39cb674c88f7643ef62", + "RequiresNetworkMagic": "RequiresNoMagic", + "ShelleyGenesisFile": "mainnet-shelley-genesis.json", + "ShelleyGenesisHash": "1a3be38bcbb7911969283716ad7aa550250226b76a61fc51cc9a9a35d9276d81" + }, + "StorageConfig": { + "LedgerDB": { + "Backend": "V2InMemory", + "QueryBatchSize": 100000, + "Snapshots": { + "NumOfDiskSnapshots": 2, + "SlotOffset": 0, + "SnapshotInterval": 86400 + } + } } }, - "MaxKnownMajorProtocolVersion": 2, - "MinNodeVersion": "11.1.0", - "Protocol": "Cardano", - "RequiresNetworkMagic": "RequiresNoMagic", - "ShelleyGenesisFile": "mainnet-shelley-genesis.json", - "ShelleyGenesisHash": "1a3be38bcbb7911969283716ad7aa550250226b76a61fc51cc9a9a35d9276d81", - "TraceOptionForwarder": { - "connQueueSize": 64, - "disconnQueueSize": 128, - "maxReconnectDelay": 30 - }, - "TraceOptionMetricsPrefix": "cardano.node.metrics.", - "TraceOptionResourceFrequency": 1000, - "TraceOptions": { - "": { - "backends": [ - "EKGBackend", - "Forwarder", - "PrometheusSimple suffix 127.0.0.1 12798", - "Stdout HumanFormatColoured" - ], - "detail": "DNormal", - "severity": "Notice" - }, - "BlockFetch.Client.CompletedBlockFetch": { - "maxFrequency": 2.0 - }, - "BlockFetch.Decision": { - "severity": "Info" - }, - "ChainDB": { - "severity": "Info" - }, - "ChainDB.AddBlockEvent.AddBlockValidation": { - "severity": "Silence" - }, - "ChainDB.AddBlockEvent.AddBlockValidation.ValidCandidate": { - "maxFrequency": 2.0 - }, - "ChainDB.AddBlockEvent.AddedBlockToQueue": { - "maxFrequency": 2.0 - }, - "ChainDB.AddBlockEvent.AddedBlockToVolatileDB": { - "maxFrequency": 2.0 - }, - "ChainDB.CopyToImmutableDBEvent.CopiedBlockToImmutableDB": { - "maxFrequency": 2.0 - }, - "ChainDB.LedgerEvent.Forker": { - "severity": "Silence" - }, - "ChainSync.Client": { - "severity": "Warning" - }, - "Forge.Loop": { - "severity": "Info" - }, - "Forge.StateInfo": { - "severity": "Info" - }, - "Mempool": { - "severity": "Silence" - }, - "Mempool.AttemptAdd": { - "severity": "Silence" - }, - "Mempool.SyncNotNeeded": { - "severity": "Silence" - }, - "Net.ConnectionManager.Remote": { - "severity": "Info" - }, - "Net.InboundGovernor": { - "severity": "Warning" - }, - "Net.InboundGovernor.Remote": { - "severity": "Info" - }, - "Net.Mux.Remote": { - "severity": "Info" - }, - "Net.PeerSelection": { - "severity": "Info" - }, - "Resources": { - "severity": "Silence" - }, - "Startup.DiffusionInit": { - "severity": "Info" - } - } + "MinNodeVersion": "11.2.0", + "Version": 1 } diff --git a/configuration/cardano/mainnet-config.yaml b/configuration/cardano/mainnet-config.yaml index 1ae3bd13d11..56e7160a8eb 100644 --- a/configuration/cardano/mainnet-config.yaml +++ b/configuration/cardano/mainnet-config.yaml @@ -16,8 +16,6 @@ CheckpointsFileHash: 3e6dee5bae7acc6d870187e72674b37c929be8c66e62a552cf6a876b1af ##### Core protocol parameters ##### -Protocol: Cardano - # The mainnet does not include the network magic into addresses. Testnets do. RequiresNetworkMagic: RequiresNoMagic @@ -30,7 +28,6 @@ RequiresNetworkMagic: RequiresNoMagic LastKnownBlockVersion-Major: 3 LastKnownBlockVersion-Minor: 0 LastKnownBlockVersion-Alt: 0 -MaxKnownMajorProtocolVersion: 2 ##### Network Configuration ##### @@ -114,9 +111,9 @@ LedgerDB: ##### Version Information ##### -# Min is currently 11.1.0 due to removal of legacy tracing system and -# introduction of deterministic snapshots. -MinNodeVersion: "11.1.0" +# Min is currently 11.2.0 for the node 11.2 config series, which drops the keys +# cardano-config treats as removed. +MinNodeVersion: "11.2.0" ##### Logging configuration ##### diff --git a/configuration/cardano/testnet-template-config.json b/configuration/cardano/testnet-template-config.json index 69c75429b39..960e8af3718 100644 --- a/configuration/cardano/testnet-template-config.json +++ b/configuration/cardano/testnet-template-config.json @@ -1,7 +1,5 @@ { "AlonzoGenesisFile": "alonzo-genesis.json", - "ApplicationName": "cardano-sl", - "ApplicationVersion": 0, "ByronGenesisFile": "byron-genesis.json", "ConsensusMode": "PraosMode", "ConwayGenesisFile": "conway-genesis.json", @@ -21,9 +19,6 @@ } }, "MaxConcurrencyDeadline": 4, - "MaxKnownMajorProtocolVersion": 2, - "PBftSignatureThreshold": 1.1, - "Protocol": "Cardano", "RequiresNetworkMagic": "RequiresMagic", "ShelleyGenesisFile": "shelley-genesis.json", "TestAllegraHardForkAtEpoch": 0, diff --git a/configuration/cardano/testnet-template-dijkstra.json b/configuration/cardano/testnet-template-dijkstra.json index c33c6755721..1af3503bf1e 100644 --- a/configuration/cardano/testnet-template-dijkstra.json +++ b/configuration/cardano/testnet-template-dijkstra.json @@ -1,6 +1,49 @@ { + "leiosAnnouncementPeriodLength": 1000, + "leiosCommitteeSize": 900, + "leiosDiffusionPeriodLength": 7000, + "leiosQuorumStakeThreshold": 0.75, + "leiosVotePeriodLength": 4000, + "maxEndorserBlockExecutionUnits": { + "memory": 720000000, + "steps": 200000000000 + }, + "maxEndorserBlockReferencesSize": 40000, + "maxEndorserBlockTxsSize": 260000, + "maxPledgeLeverage": null, "maxRefScriptSizePerBlock": 1048576, + "maxRefScriptSizePerEndorserBlock": 1048576, "maxRefScriptSizePerTx": 204800, - "refScriptCostStride": 25600, - "refScriptCostMultiplier": 1.2 + "minPoolMargin": 0.015, + "perasBootstrapRound": 0, + "perasCertBoost": 15, + "perasHealingFactor": 0.5, + "perasMinCandidateBlockAge": 90, + "perasQuorumThresholdSafetyMargin": 0.05, + "perasTargetCommitteeSize": 800, + "plutusV4CostModel": [ + 100788, 420, 1, 1, 1000, 173, 0, 1, 1000, 59957, 4, 1, 11183, 32, 201305, + 8356, 4, 16000, 100, 16000, 100, 16000, 100, 16000, 100, 16000, 100, 16000, + 100, 100, 100, 16000, 100, 94375, 32, 132994, 32, 61462, 4, 72010, 178, 0, + 1, 22151, 32, 91189, 769, 4, 2, 85848, 123203, 7305, -900, 1716, 960, 57, + 85848, 0, 1, 1, 1000, 42921, 4, 2, 30623, 28755, 75, 1, 898148, 27279, 1, + 51775, 558, 1, 39184, 1000, 60594, 1, 141895, 32, 83150, 32, 15299, 32, + 76049, 1, 13169, 4, 22100, 10, 28999, 74, 1, 28999, 74, 1, 43285, 552, 1, + 44749, 541, 1, 33852, 32, 68246, 32, 72362, 32, 7243, 32, 7391, 32, 11546, + 32, 85848, 123203, 7305, -900, 1716, 960, 57, 85848, 0, 1, 90434, 519, 0, 1, + 74433, 32, 85848, 123203, 7305, -900, 1716, 960, 57, 85848, 0, 1, 1, 85848, + 123203, 7305, -900, 1716, 960, 57, 85848, 0, 1, 955506, 213312, 0, 2, + 270652, 22588, 4, 1457325, 64566, 4, 20467, 1, 4, 0, 141992, 32, 100788, + 420, 1, 1, 81663, 32, 59498, 32, 20142, 32, 24588, 32, 20744, 32, 25933, 32, + 24623, 32, 43053543, 10, 53384111, 14333, 10, 43574283, 26308, 10, 16000, + 100, 16000, 100, 962335, 18, 2780678, 6, 442008, 1, 52538055, 3756, 18, + 267929, 18, 76433006, 8868, 18, 52948122, 18, 1995836, 36, 3227919, 12, + 901022, 1, 166917843, 4307, 36, 284546, 36, 158221314, 26549, 36, 74698472, + 36, 333849714, 1, 254006273, 72, 2174038, 72, 2261318, 64571, 4, 207616, + 8310, 4, 1293828, 28716, 63, 0, 1, 1006041, 43623, 251, 0, 1 + ], + "refInputsCostPerDatumByte": 0, + "refInputsCostPerMultiAssetPolicy": 0, + "refScriptCostMultiplier": 1.2, + "refScriptCostStride": 25600 } From a410abbe115c0495cdc91e9ac28d22281fde188b Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Sun, 13 Sep 2026 22:19:11 -0500 Subject: [PATCH 23/45] nix: publish and consume the enveloped node config iohk-nix now publishes -config.json in the cardano-config envelope. Two places in this repo produced or consumed the legacy dialect regardless. binary-release.nix built config.json straight from env.nodeConfig, bypassing configFormat, so release tarballs stayed on the legacy dialect while the published configs moved. It now emits whichever dialect the environment selects, enveloping the already-relativised config so the tarball's sibling genesis paths survive. cardanoLib always sets configFormat and throws on a value it does not know, so this throws too rather than falling through to legacy and publishing the wrong dialect silently. The docker node entrypoint rewrote relative "*File" values to absolute paths with a top-level with_entries. In the envelope those keys live under Configuration.
, so it silently rewrote nothing and the merged config's genesis paths would have resolved against the runtime dir, the exact failure the code comment says it exists to prevent. Walking the document handles the flat and enveloped shapes alike. Docker otherwise needs no change: it takes its configs from mkConfigHtml, so it picks up the envelope, and the sed that strips the - prefix is a plain text substitution that still matches. CARDANO_CONFIG_JSON_MERGE is a user-facing break that no code change can absorb: the merge is a plain deep merge with no key relocation, so a merge document written for the flat shape now adds an unrecognised top-level key and leaves the intended value untouched, silently. The README gains the new shape, an example updated to Configuration.HermodTracing.TraceOptions, and a way to find any key's path from inside the image. The tracer section says its config is not enveloped, since the two appear side by side. --- nix/binary-release.nix | 17 ++++++++++++++++- nix/docker/README.md | 23 ++++++++++++++++++++++- nix/docker/context/node/bin/entrypoint | 20 +++++++++++++++----- 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/nix/binary-release.nix b/nix/binary-release.nix index 5f4a7bbb79b..dfdaa853f29 100644 --- a/nix/binary-release.nix +++ b/nix/binary-release.nix @@ -36,10 +36,25 @@ let CheckpointsFile = "checkpoints.json"; }; + # Published in the dialect the environment selects, matching what iohk-nix + # publishes for it rather than always emitting the legacy config. The + # genesis paths are rewritten to the siblings copied below first, so the + # envelope carries the relative paths too. + # + # cardanoLib always sets configFormat, so an absent value means the + # iohk-nix pin moved under us. Mirror its throw rather than falling + # through to legacy, which would publish the wrong dialect silently. + relativeNodeConfig = env.nodeConfig // genesisAttrs; + nodeConfig = pkgs.writeText "config.json" (builtins.toJSON - (env.nodeConfig // genesisAttrs)); + (if env.configFormat == "enveloped" + then pkgs.cardanoLib.mkEnvelope relativeNodeConfig + else if env.configFormat == "legacy" + then relativeNodeConfig + else throw ("binary-release: ${name} sets configFormat = \"${env.configFormat}\";" + + " expected \"enveloped\" or \"legacy\""))); submitApiConfig = pkgs.writeText "submit-api-config.json" diff --git a/nix/docker/README.md b/nix/docker/README.md index 1770a57bed9..3fec8615388 100644 --- a/nix/docker/README.md +++ b/nix/docker/README.md @@ -113,17 +113,35 @@ Optional env variables and cardano-node args which can be used in custom mode can also be used in this mode. Merge mode uses the same default state directories as custom mode. +**The merge document must match the shape of the base config.** The image's +network configs are now in the cardano-config envelope, so config keys live +under `Configuration.
` rather than at the top level, and a merge +document written against the older flat configs no longer lands where it used +to. Merging is a plain deep merge with no key relocation, so a flat merge +document is not an error: it adds a top-level key the node does not recognise +and warns about, leaving the value you meant to override untouched. + +To find the right path for a key, look at the base config in the image: +``` +docker run --rm --entrypoint jq ghcr.io/intersectmbo/cardano-node:dev \ + -r '[paths(scalars)][] | join(".")' /opt/cardano/config/mainnet/config.json \ + | grep -i +``` + An example where prometheus binding is set away from localhost while preserving other defaults: ``` docker run \ -v node-ipc:/ipc \ -v mainnet-data:/data \ -e NETWORK=mainnet \ - -e CARDANO_CONFIG_JSON_MERGE='{"TraceOptions":{"":{"backends":["EKGBackend","Forwarder","PrometheusSimple suffix 0.0.0.0 12798","Stdout HumanFormatColoured"]}}}' \ + -e CARDANO_CONFIG_JSON_MERGE='{"Configuration":{"HermodTracing":{"TraceOptions":{"":{"backends":["EKGBackend","Forwarder","PrometheusSimple suffix 0.0.0.0 12798","Stdout HumanFormatColoured"]}}}}}' \ -e CARDANO_TOPOLOGY_JSON_MERGE='{"useLedgerAfterSlot": 147000000}' \ ghcr.io/intersectmbo/cardano-node:dev ``` +The topology merge document is unaffected: topology files are not enveloped, so +`CARDANO_TOPOLOGY_JSON_MERGE` keeps its flat shape as above. + The resulting merged config and topology are written to a private, per-container runtime directory under `/tmp` (see [Read-Only Root Filesystem](#read-only-root-filesystem) for the exact path) @@ -515,6 +533,9 @@ Optional env variables and cardano-tracer args which can be used in custom mode can also be used in this mode. Merge mode uses the same default state directories as custom mode. +Unlike the node image, the tracer config is not in the cardano-config envelope, +so merge documents here keep their flat shape. + An example which changes the prometheus binding address from a default of localhost (`127.0.0.1`) to `0.0.0.0`: ``` diff --git a/nix/docker/context/node/bin/entrypoint b/nix/docker/context/node/bin/entrypoint index 542be85dd55..f6706cc55f3 100755 --- a/nix/docker/context/node/bin/entrypoint +++ b/nix/docker/context/node/bin/entrypoint @@ -97,16 +97,26 @@ elif [[ -n ${NETWORK:-} ]]; then # (ByronGenesisFile, ShelleyGenesisFile, AlonzoGenesisFile, # ConwayGenesisFile, CheckpointsFile, ...); matching the "File" suffix # keeps this working if more are added. + # + # Walked rather than applied at the top level: in the cardano-config + # envelope these keys live under Configuration.
, so a top-level + # with_entries would silently rewrite nothing. Walking handles the flat and + # enveloped shapes alike. if [[ -n ${CARDANO_CONFIG_JSON_MERGE:-} ]]; then jq -S \ --arg cfgDir "$CFG/$NETWORK" \ --argjson deepMerge "$CARDANO_CONFIG_JSON_MERGE" \ '. * $deepMerge - | with_entries( - if ((.key | endswith("File")) - and (.value | type == "string") - and (.value | startswith("/") | not)) - then .value = "\($cfgDir)/\(.value)" + | walk( + if type == "object" + then with_entries( + if ((.key | endswith("File")) + and (.value | type == "string") + and (.value | startswith("/") | not)) + then .value = "\($cfgDir)/\(.value)" + else . + end + ) else . end )' \ From c5aff048a0ec6b7b031146a00743859e3f45af92 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Mon, 14 Sep 2026 11:31:22 -0500 Subject: [PATCH 24/45] tracing: hand the tracing object to trace-dispatcher, not the file trace-dispatcher reads a file expecting the tracing settings at its root, but a cardano-config envelope nests them under `Configuration.HermodTracing`, so `trace-documentation` failed with `key "Options" not found`. Pass that object as `FromJSONObject` instead. It holds the flat legacy key names, so no particular trace-dispatcher version is needed. --- .../Node/Configuration/CardanoConfigResolve.hs | 18 ++++++++++++++++++ .../src/Cardano/Node/Tracing/Consistency.hs | 4 +++- .../src/Cardano/Node/Tracing/Documentation.hs | 11 ++++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs index d6493935501..be8af66024b 100644 --- a/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs +++ b/cardano-node/src/Cardano/Node/Configuration/CardanoConfigResolve.hs @@ -37,6 +37,7 @@ module Cardano.Node.Configuration.CardanoConfigResolve -- * Dialects , ConfigurationDialect (..) , classifyConfigurationFile + , tracingConfigSource -- * Command-line layers , nodeCliPartialConfiguration @@ -44,6 +45,7 @@ module Cardano.Node.Configuration.CardanoConfigResolve , cardanoConfigCliLayer ) where +import Cardano.Logging.ConfigurationParser (ConfigSource (..)) import qualified Cardano.Configuration as Cfg import qualified Cardano.Configuration.CliArgs as CliArgs import Cardano.Logging.Types (TraceConfig) @@ -144,6 +146,22 @@ classifyConfigurationFile fp = Right (Object o) | KeyMap.member "Configuration" o -> pure CardanoConfigDialect _ -> pure LegacyDialect +-- | How to hand a node configuration file's tracing settings to +-- trace-dispatcher, for a tool with a file and no node to resolve it. +-- +-- Reading a file, the library expects the tracing settings at its root. An +-- envelope puts them at @Configuration.HermodTracing@, so hand over that object +-- instead, which is what 'FromJSONObject' is for. Anything else goes as the +-- file, as before. +tracingConfigSource :: FilePath -> IO ConfigSource +tracingConfigSource fp = + Yaml.decodeFileEither fp >>= \case + Right (Object top) + | Just (Object cfg) <- KeyMap.lookup "Configuration" top + , Just (Object tracing) <- KeyMap.lookup "HermodTracing" cfg -> + pure (FromJSONObject tracing) + _ -> pure (FromFile fp) + -- | Resolve a legacy configuration with the node's own POM parser — the result -- the node runs on — and cross-check it against @cardano-config@'s. buildFromLegacy :: diff --git a/cardano-node/src/Cardano/Node/Tracing/Consistency.hs b/cardano-node/src/Cardano/Node/Tracing/Consistency.hs index 05da334f321..05953c21432 100644 --- a/cardano-node/src/Cardano/Node/Tracing/Consistency.hs +++ b/cardano-node/src/Cardano/Node/Tracing/Consistency.hs @@ -27,6 +27,7 @@ import qualified Cardano.Network.PeerSelection.Governor.Types as Cardano import Cardano.Network.PeerSelection.PeerTrustable (PeerTrustable) import Cardano.Network.Tracing.PeerSelection () import Cardano.Network.Tracing.PeerSelectionCounters () +import Cardano.Node.Configuration.CardanoConfigResolve (tracingConfigSource) import Cardano.Node.Handlers.Shutdown (ShutdownTrace) import Cardano.Node.Startup import Cardano.Node.Tracing.DefaultTraceConfig (defaultCardanoConfig) @@ -133,8 +134,9 @@ checkNodeTraceConfigurationWith :: -> FilePath -> IO NSWarnings checkNodeTraceConfigurationWith dt configFileName = do + src <- tracingConfigSource configFileName w1 <- checkTraceConfiguration - (FromFile configFileName) + src defaultCardanoConfig getAllNamespaces pure $ w1 <> dtWarnings dt diff --git a/cardano-node/src/Cardano/Node/Tracing/Documentation.hs b/cardano-node/src/Cardano/Node/Tracing/Documentation.hs index f36f74b810d..052558f5e5a 100644 --- a/cardano-node/src/Cardano/Node/Tracing/Documentation.hs +++ b/cardano-node/src/Cardano/Node/Tracing/Documentation.hs @@ -35,6 +35,7 @@ import qualified Cardano.Network.PeerSelection.Governor.Types as Cardano import Cardano.Network.PeerSelection.PeerTrustable (PeerTrustable (..)) import Cardano.Network.Tracing.PeerSelection () import Cardano.Network.Tracing.PeerSelectionCounters () +import Cardano.Node.Configuration.CardanoConfigResolve (tracingConfigSource) import Cardano.Node.Configuration.TopologyP2P () import Cardano.Node.Handlers.Shutdown (ShutdownTrace) import Cardano.Node.Startup @@ -189,6 +190,14 @@ runTraceDocumentationCmd runTraceDocumentationCmd TraceDocumentationCmd{..} = do docTracers tdcConfigFile tdcOutput tdMetricsHelp tdNamespaceList +-- | Read the tracing configuration from a node configuration file. This command +-- has no node, so there is no resolved configuration to use as there is at +-- startup; 'tracingConfigSource' says how to present the file. +resolveTracingConfig :: FilePath -> IO TraceConfig +resolveTracingConfig fp = do + src <- tracingConfigSource fp + readConfigurationWithDefault src defaultCardanoConfig + -- Have to repeat the construction of the tracers here, -- as the tracers are behind old tracer interface after construction in mkDispatchTracers. -- Can be changed, when old tracers have gone @@ -215,7 +224,7 @@ docTracersFirstPhase :: forall blk peer remotePeer. -> IO (DocTracer, TraceConfig) docTracersFirstPhase condConfigFileName = do trConfig <- case condConfigFileName of - Just fn -> readConfigurationWithDefault (FromFile fn) defaultCardanoConfig + Just fn -> resolveTracingConfig fn Nothing -> pure defaultCardanoConfig let trBase :: Logging.Trace IO FormattedMessage = docTracer (Stdout MachineFormat) trForward :: Logging.Trace IO FormattedMessage = docTracer Forwarder From fbc333e9c5c54646776d8df1291442fada77c84a Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Mon, 14 Sep 2026 11:57:40 -0500 Subject: [PATCH 25/45] configuration: envelope mainnet-config.yaml The json moved to the cardano-config envelope, leaving the hand-maintained yaml as the only flat mainnet config and breaking the yaml === json equivalence that Test.Cardano.Config.Mainnet asserts. Restructure the yaml to the same shape. LastKnownBlockVersion-Major/-Minor/-Alt are dropped: migrate treats them as removed and the json does not carry them. An enveloped config never reaches POM, which was the only thing that required them, so this file is no longer readable by a pre-11.2 node. Comments are preserved per section, and the commented-out examples are re-nested under Network and Mempool, the section names cardano-config derives from its schemas, with the DeadlineTargetNumberOf* and CapacityBytesOverride key names. Uncommenting one now sets the value it names instead of adding a key the node does not recognise. Verified: the yaml and json decode to identical values, and trace-documentation generates identical output from the yaml, the json and an older flat config. --- configuration/cardano/mainnet-config.yaml | 544 ++++++++++++---------- 1 file changed, 287 insertions(+), 257 deletions(-) diff --git a/configuration/cardano/mainnet-config.yaml b/configuration/cardano/mainnet-config.yaml index 56e7160a8eb..059d89460a4 100644 --- a/configuration/cardano/mainnet-config.yaml +++ b/configuration/cardano/mainnet-config.yaml @@ -1,113 +1,23 @@ ################################################################################ # Mainnet Cardano Node Configuration - -##### Locations ##### - -AlonzoGenesisFile: mainnet-alonzo-genesis.json -AlonzoGenesisHash: 7e94a15f55d1e82d10f09203fa1d40f8eede58fd8066542cf6566008068ed874 -ByronGenesisFile: mainnet-byron-genesis.json -ByronGenesisHash: 5f20df933584822601f9e3f8c024eb5eb252fe8cefb24d1317dc3d432e940ebb -ConwayGenesisFile: mainnet-conway-genesis.json -ConwayGenesisHash: 15a199f895e461ec0ffc6dd4e4028af28a492ab4e806d39cb674c88f7643ef62 -ShelleyGenesisFile: mainnet-shelley-genesis.json -ShelleyGenesisHash: 1a3be38bcbb7911969283716ad7aa550250226b76a61fc51cc9a9a35d9276d81 -CheckpointsFile: mainnet-checkpoints.json -CheckpointsFileHash: 3e6dee5bae7acc6d870187e72674b37c929be8c66e62a552cf6a876b1af31ade - -##### Core protocol parameters ##### - -# The mainnet does not include the network magic into addresses. Testnets do. -RequiresNetworkMagic: RequiresNoMagic - -##### Update system parameters ##### - -# This protocol version number gets used by block producing nodes as part -# of the system for agreeing on and synchronising protocol updates. # -# See https://github.com/intersectmbo/cardano-node/blob/master/cardano-node/src/Cardano/Node/Protocol/Cardano.hs#L199 -LastKnownBlockVersion-Major: 3 -LastKnownBlockVersion-Minor: 0 -LastKnownBlockVersion-Alt: 0 - -##### Network Configuration ##### - -# The following control the number of outbound connections to strictly our upstream peers -# cf. https://developers.cardano.org/docs/operate-a-stake-pool/node-operations/topology -# -# Defaults are provided by ouroboros-network, but can be overridden by uncommenting below: -# SyncTargetNumberOfActiveBigLedgerPeers: 30 -# SyncTargetNumberOfActivePeers: 5 -# SyncTargetNumberOfEstablishedBigLedgerPeers: 40 -# SyncTargetNumberOfEstablishedPeers: 10 -# SyncTargetNumberOfKnownBigLedgerPeers: 100 -# SyncTargetNumberOfKnownPeers: 150 -# SyncTargetNumberOfRootPeers: 0 -# TargetNumberOfActiveBigLedgerPeers: 5 -# TargetNumberOfActivePeers: 20 -# TargetNumberOfEstablishedBigLedgerPeers: 10 -# TargetNumberOfEstablishedPeers: 30 -# TargetNumberOfKnownBigLedgerPeers: 15 +# This is the cardano-config envelope form: the settings live under +# `Configuration`, grouped by component, beneath the `$schema`, `Version` and +# `MinNodeVersion` annotations. It is the same shape as mainnet-config.json, and +# the two are checked for equivalence by Test.Cardano.Config.Mainnet. # -# Additionally, as of ouroboros-network `0.22.2` with cardano-node `10.6.0`, -# the following three node config parameters which previously required -# explicit configuration depending on whether the node is a forger are now -# handled automatically. +# A node given an envelope resolves it with cardano-config rather than its own +# parser, so the keys cardano-config treats as removed are not present here. +# Notably LastKnownBlockVersion-Major/-Minor/-Alt are gone: the Byron +# supported-protocol-version now comes from consensus defaults. # -# PeerSharing: false for forgers, true for non-forgers -# TargetNumberOfKnownPeers: set according to forging status -# TargetNumberOfRootPeers: set according to forging status - -# When syncing in Genesis mode, this is the minimum number of active connections -# to big ledger peers needed to continue: -# MinBigLedgerPeersForTrustedState: 5 - -##### Consensus Configuration ##### - -ConsensusMode: PraosMode - -# Mempool timeout parameters must be either all set or all unset. -# When unset cardano-node will use default values. -# Default example values are: -# MempoolTimeoutSoft: 1.0 -# MempoolTimeoutHard: 1.5 -# MempoolTimeoutCapacity: 5.0 +# Commented-out examples below show the section each key belongs to, so they are +# correct as written if uncommented. -##### Ledger Configuration ##### +$schema: https://raw.githubusercontent.com/IntersectMBO/cardano-config/v2/schemas/config.schema.json -# Additional configuration options can be found at: -# https://ouroboros-consensus.cardano.intersectmbo.org/docs/for-developers/utxo-hd/migrating - -LedgerDB: - # When querying the store for a big range of UTxOs (such as with - # QueryUTxOByAddress), the store will be read in batches of this size. - QueryBatchSize: 100000 - - # The backend can either be in memory with `V2InMemory` or on disk with - # `V2LSM`. - Backend: V2InMemory - - # Instead of an object with individual options, a predefined snapshot - # policy can be selected by name, e.g. `Snapshots: Mithril`. - Snapshots: - # The snapshot interval in slots. Use `securityParam * 40` to provide - # intra-epoch snapshot redundancy while minimizing potential IOWAIT stall on some - # spec constrained machines during snapshot write. - SnapshotInterval: 86400 - - # Slot offset at which snapshot scheduling begins. - SlotOffset: 0 - - # A minimum duration between snapshots, in seconds (used to avoid excessive snapshots while syncing). - # Default is 10 minutes. - # RateLimit: 600 - - # Randomised snapshot delay range, in seconds. - # Both Min and Max need to be specified, otherwise the default delay of (5min, 10min) will be used. - # MinDelay: 300 - # MaxDelay: 600 - - # The number of disk snapshots to keep. - NumOfDiskSnapshots: 2 +# The configuration format version this document is written in. +Version: 2 ##### Version Information ##### @@ -115,160 +25,280 @@ LedgerDB: # cardano-config treats as removed. MinNodeVersion: "11.2.0" -##### Logging configuration ##### - -# Match the metrics prefix of the legacy tracing system to minimize breaking -# changes. -TraceOptionMetricsPrefix: "cardano.node.metrics." - -# Optional node name. Defaults to hostname if left unset. Ideally this is -# set in downstream code where the node's name is known. -# TraceOptionNodeName: - -# The frequency of resource messages. -TraceOptionResourceFrequency: 1000 - -# Queue size control: -# In case of a missing forwarding service consumer, trace messages will be -# buffered. This mitigates short forwarding interruptions, or delays at -# startup time. -# -# The queue capacity should thus correlate to the expected log lines per -# second given a particular tracing configuration to avoid unnecessarily -# increasing memory footprint. -# -# The maxReconnectDelay config option specifies the maximum delay in seconds -# between (re-)connection attempts of a forwarder. -TraceOptionForwarder: - connQueueSize: 64 - disconnQueueSize: 128 - maxReconnectDelay: 30 - -# Tracing options for node -TraceOptions: - # The default tracer configuration - '': - backends: - # None, any combination, or all of the following backends can be - # enabled, where `EKGBackend` forwards EKG resource status to - # cardano-tracer, `Forwarder` forwards message traces and - # `PrometheusSimple` serves cardano-node metrics directly from - # cardano-node and defaults to use of the same port as in the legacy - # tracing system. - - EKGBackend - - Forwarder - - PrometheusSimple suffix 127.0.0.1 12798 - - # Only one of the following can be enabled, which determines for format - # of node logging to stdout. - - Stdout HumanFormatColoured - # - Stdout HumanFormatUncoloured - # - Stdout MachineFormat - - # Each tracer can specify the level of details for printing messages. - # Options include `DMinimal`, `DNormal`, `DDetailed`, and `DMaximum`. If - # no implementation is given, `DNormal` is chosen. - detail: DNormal - - # The severity levels, ranging from the least severe (`Debug`) to the - # most severe (`Emergency`), provide a framework for ignoring messages - # with severity levels below a globally configured severity cutoff. +Configuration: + + ##### Protocol Configuration ##### + + Protocol: + + ##### Locations ##### + + AlonzoGenesisFile: mainnet-alonzo-genesis.json + AlonzoGenesisHash: 7e94a15f55d1e82d10f09203fa1d40f8eede58fd8066542cf6566008068ed874 + ByronGenesisFile: mainnet-byron-genesis.json + ByronGenesisHash: 5f20df933584822601f9e3f8c024eb5eb252fe8cefb24d1317dc3d432e940ebb + ConwayGenesisFile: mainnet-conway-genesis.json + ConwayGenesisHash: 15a199f895e461ec0ffc6dd4e4028af28a492ab4e806d39cb674c88f7643ef62 + ShelleyGenesisFile: mainnet-shelley-genesis.json + ShelleyGenesisHash: 1a3be38bcbb7911969283716ad7aa550250226b76a61fc51cc9a9a35d9276d81 + CheckpointsFile: mainnet-checkpoints.json + CheckpointsFileHash: 3e6dee5bae7acc6d870187e72674b37c929be8c66e62a552cf6a876b1af31ade + + ##### Core protocol parameters ##### + + # The mainnet does not include the network magic into addresses. Testnets do. + RequiresNetworkMagic: RequiresNoMagic + + ##### Consensus Configuration ##### + + Consensus: + ConsensusMode: GenesisMode + + ##### Network Configuration ##### + # + # The following control the number of outbound connections to strictly our upstream peers + # cf. https://developers.cardano.org/docs/operate-a-stake-pool/node-operations/topology + # + # Defaults are provided by ouroboros-network, but can be overridden by uncommenting below: + # Network: + # SyncTargetNumberOfActiveBigLedgerPeers: 30 + # SyncTargetNumberOfActivePeers: 5 + # SyncTargetNumberOfEstablishedBigLedgerPeers: 40 + # SyncTargetNumberOfEstablishedPeers: 10 + # SyncTargetNumberOfKnownBigLedgerPeers: 100 + # SyncTargetNumberOfKnownPeers: 150 + # SyncTargetNumberOfRootPeers: 0 + # DeadlineTargetNumberOfActiveBigLedgerPeers: 5 + # DeadlineTargetNumberOfActivePeers: 20 + # DeadlineTargetNumberOfEstablishedBigLedgerPeers: 10 + # DeadlineTargetNumberOfEstablishedPeers: 30 + # DeadlineTargetNumberOfKnownBigLedgerPeers: 15 + # + # Note the deadline targets were named TargetNumberOf* before the node 11.2 + # config series; cardano-config only accepts the Deadline-prefixed names. + # + # Additionally, as of ouroboros-network `0.22.2` with cardano-node `10.6.0`, + # the following three node config parameters which previously required + # explicit configuration depending on whether the node is a forger are now + # handled automatically. + # + # PeerSharing: false for forgers, true for non-forgers + # DeadlineTargetNumberOfKnownPeers: set according to forging status + # DeadlineTargetNumberOfRootPeers: set according to forging status + # + # When syncing in Genesis mode, this is the minimum number of active connections + # to big ledger peers needed to continue: + # Network: + # MinBigLedgerPeersForTrustedState: 5 + + ##### Mempool Configuration ##### + # + # Mempool timeout parameters must be either all set or all unset. + # When unset cardano-node will use default values. + # Default example values are: + # Mempool: + # MempoolTimeoutSoft: 1.0 + # MempoolTimeoutHard: 1.5 + # MempoolTimeoutCapacity: 5.0 + # + # Set or unset the mempool capacity override in number of bytes. + # + # This is intended for testing, and for low-resource machines to run with a smaller mempool. + # Please note that running with a large mempool is NOT recommended. The mempool is a + # just a network communication buffer and all the advice on "buffer bloat" applies, see: + # https://en.wikipedia.org/wiki/Bufferbloat + # The default size is two blocks, which is generally enough to ensure full blocks. + # + # Mempool: + # CapacityBytesOverride: Integer | NoOverride + # + # Examples: + # CapacityBytesOverride: 1000000 (1MB) + # CapacityBytesOverride: NoOverride (default) + + ##### Storage Configuration ##### + + Storage: + + # Additional configuration options can be found at: + # https://ouroboros-consensus.cardano.intersectmbo.org/docs/for-developers/utxo-hd/migrating + + LedgerDB: + # When querying the store for a big range of UTxOs (such as with + # QueryUTxOByAddress), the store will be read in batches of this size. + QueryBatchSize: 100000 + + # The backend can either be in memory with `V2InMemory` or on disk with + # `V2LSM`. + Backend: V2InMemory + + # Instead of an object with individual options, a predefined snapshot + # policy can be selected by name, e.g. `Snapshots: Mithril`. + Snapshots: + # The snapshot interval in slots. Use `securityParam * 40` to provide + # intra-epoch snapshot redundancy while minimizing potential IOWAIT stall on some + # spec constrained machines during snapshot write. + Interval: 86400 + + # Slot offset at which snapshot scheduling begins. + Offset: 0 + + # A minimum duration between snapshots, in seconds (used to avoid excessive snapshots while syncing). + # Default is 10 minutes. + # RateLimit: 600 + + # Randomised snapshot delay range, in seconds. + # Both Min and Max need to be specified, otherwise the default delay of (5min, 10min) will be used. + MinDelay: 300 + MaxDelay: 21600 + + # The number of disk snapshots to keep. + NumOfDiskSnapshots: 2 + + ##### Logging configuration ##### + # + # The tracing settings are handed to trace-dispatcher as-is; cardano-config + # only carries them, it does not interpret their shape. + + HermodTracing: + + # Match the metrics prefix of the legacy tracing system to minimize breaking + # changes. + TraceOptionMetricsPrefix: "cardano.node.metrics." + + # Optional node name. Defaults to hostname if left unset. Ideally this is + # set in downstream code where the node's name is known. + # TraceOptionNodeName: + + # The frequency of resource messages. + TraceOptionResourceFrequency: 1000 + + # Queue size control: + # In case of a missing forwarding service consumer, trace messages will be + # buffered. This mitigates short forwarding interruptions, or delays at + # startup time. # - # The full list of severities are: - # `Debug`, `Info`, `Notice`, `Warning`, `Error`, `Critical`, `Alert` and - # `Emergency`. + # The queue capacity should thus correlate to the expected log lines per + # second given a particular tracing configuration to avoid unnecessarily + # increasing memory footprint. # - # To enhance severity filtering, there is also the option of `Silence` - # which allows for the unconditional silencing of a specific trace, - # essentially representing the deactivation of tracers -- a semantic - # continuation of the functionality in the legacy system. - severity: Notice + # The maxReconnectDelay config option specifies the maximum delay in seconds + # between (re-)connection attempts of a forwarder. + TraceOptionForwarder: + maxReconnectDelay: 30 + queueSize: 128 + + # Tracing options for node + TraceOptions: + # The default tracer configuration + '': + backends: + # None, any combination, or all of the following backends can be + # enabled, where `EKGBackend` forwards EKG resource status to + # cardano-tracer, `Forwarder` forwards message traces and + # `PrometheusSimple` serves cardano-node metrics directly from + # cardano-node and defaults to use of the same port as in the legacy + # tracing system. + - EKGBackend + - Forwarder + - PrometheusSimple suffix 127.0.0.1 12798 + + # Only one of the following can be enabled, which determines for format + # of node logging to stdout. + - Stdout HumanFormatColoured + # - Stdout HumanFormatUncoloured + # - Stdout MachineFormat + + # Each tracer can specify the level of details for printing messages. + # Options include `DMinimal`, `DNormal`, `DDetailed`, and `DMaximum`. If + # no implementation is given, `DNormal` is chosen. + detail: DNormal + + # The severity levels, ranging from the least severe (`Debug`) to the + # most severe (`Emergency`), provide a framework for ignoring messages + # with severity levels below a globally configured severity cutoff. + # + # The full list of severities are: + # `Debug`, `Info`, `Notice`, `Warning`, `Error`, `Critical`, `Alert` and + # `Emergency`. + # + # To enhance severity filtering, there is also the option of `Silence` + # which allows for the unconditional silencing of a specific trace, + # essentially representing the deactivation of tracers -- a semantic + # continuation of the functionality in the legacy system. + severity: Notice + + # The following tracer configurations are configured to closely match the + # default logging seen in the legacy cardano-node tracing system. + BlockFetch.Client.CompletedBlockFetch: + # A frequency limit for the number of messages per second may also be + # provided for any tracer. + maxFrequency: 2.0 + + BlockFetch.Decision: + severity: Info + + ChainDB: + severity: Info + + ChainDB.AddBlockEvent.AddBlockValidation: + severity: Silence + + ChainDB.AddBlockEvent.AddBlockValidation.ValidCandidate: + maxFrequency: 2.0 + + ChainDB.AddBlockEvent.AddedBlockToQueue: + maxFrequency: 2.0 + + ChainDB.AddBlockEvent.AddedBlockToVolatileDB: + maxFrequency: 2.0 + + ChainDB.CopyToImmutableDBEvent.CopiedBlockToImmutableDB: + maxFrequency: 2.0 + + ChainSync.Client: + severity: Warning + + Forge.Loop: + severity: Info + + Forge.StateInfo: + severity: Info + + Mempool: + severity: Silence + + Net.ConnectionManager.Remote: + severity: Info + + Net.InboundGovernor: + severity: Warning + + Net.InboundGovernor.Remote: + severity: Info + + Net.Mux.Remote: + severity: Info + + Net.PeerSelection: + severity: Info + + Resources: + severity: Silence + + Startup.DiffusionInit: + severity: Info + + # The following messages are UTxO-HD specific. Silencing these tracers aims + # at having comparable log line rates in messages per second on both the + # UTxO-HD and earlier non-UTxO-HD nodes. The additional high granularity + # mempool silences are not redundant in the case that the top level Mempool + # severity is switched away from silence. + ChainDB.LedgerEvent.Forker: + severity: Silence + + Mempool.AttemptAdd: + severity: Silence - # The following tracer configurations are configured to closely match the - # default logging seen in the legacy cardano-node tracing system. - BlockFetch.Client.CompletedBlockFetch: - # A frequency limit for the number of messages per second may also be - # provided for any tracer. - maxFrequency: 2.0 - - BlockFetch.Decision: - severity: Info - - ChainDB: - severity: Info - - ChainDB.AddBlockEvent.AddBlockValidation: - severity: Silence - - ChainDB.AddBlockEvent.AddBlockValidation.ValidCandidate: - maxFrequency: 2.0 - - ChainDB.AddBlockEvent.AddedBlockToQueue: - maxFrequency: 2.0 - - ChainDB.AddBlockEvent.AddedBlockToVolatileDB: - maxFrequency: 2.0 - - ChainDB.CopyToImmutableDBEvent.CopiedBlockToImmutableDB: - maxFrequency: 2.0 - - ChainSync.Client: - severity: Warning - - Forge.Loop: - severity: Info - - Forge.StateInfo: - severity: Info - - Mempool: - severity: Silence - - Net.ConnectionManager.Remote: - severity: Info - - Net.InboundGovernor: - severity: Warning - - Net.InboundGovernor.Remote: - severity: Info - - Net.Mux.Remote: - severity: Info - - Net.PeerSelection: - severity: Info - - Resources: - severity: Silence - - Startup.DiffusionInit: - severity: Info - - # The following messages are UTxO-HD specific. Silencing these tracers aims - # at having comparable log line rates in messages per second on both the - # UTxO-HD and earlier non-UTxO-HD nodes. The additional high granularity - # mempool silences are not redundant in the case that the top level Mempool - # severity is switched away from silence. - ChainDB.LedgerEvent.Forker: - severity: Silence - - Mempool.AttemptAdd: - severity: Silence - - Mempool.SyncNotNeeded: - severity: Silence - -# Set or unset the mempool capacity override in number of bytes. -# -# This is intended for testing, and for low-resource machines to run with a smaller mempool. -# Please note that running with a large mempool is NOT recommended. The mempool is a -# just a network communication buffer and all the advice on "buffer bloat" applies, see: -# https://en.wikipedia.org/wiki/Bufferbloat -# The default size is two blocks, which is generally enough to ensure full blocks. -# -# MempoolCapacityBytesOverride: Integer | NoOverride -# -# Examples: -# MempoolCapacityBytesOverride: 1000000 (1MB) -# MempoolCapacityBytesOverride: NoOverride (default) + Mempool.SyncNotNeeded: + severity: Silence From 77c562f569c3797bdd7844d52d1eefee5f98a1ed Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Wed, 23 Sep 2026 02:57:52 -0500 Subject: [PATCH 26/45] nixosModule: update node service to include {immutable,volatile}DatabasePath opts --- nix/nixos/cardano-node-service.nix | 52 ++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/nix/nixos/cardano-node-service.nix b/nix/nixos/cardano-node-service.nix index 5a4f6622203..b3ab1fa4279 100644 --- a/nix/nixos/cardano-node-service.nix +++ b/nix/nixos/cardano-node-service.nix @@ -114,13 +114,31 @@ let "--shelley-kes-agent-socket ${cfg.shelleyKesAgentSocket}"}" ]; }; + instanceDbPath = cfg.databasePath i; - cmd = filter (x: x != "") [ + instanceImmutableDbPath = cfg.immutableDatabasePath i; + instanceVolatileDbPath = cfg.volatileDatabasePath i; + + # The node accepts either --database-path or both of the split paths, never + # a mix: parseNodeDatabasePaths is `parseDbPath <|> parseMultipleDbPaths`, + # so emitting --database-path alongside them would win and the split paths + # would be silently ignored. + splitDbPaths = instanceImmutableDbPath != null && instanceVolatileDbPath != null; + + dbPathArgs = + if splitDbPaths + then [ + "--immutable-database-path ${instanceImmutableDbPath}" + "--volatile-database-path ${instanceVolatileDbPath}" + ] + else [ "--database-path ${instanceDbPath}" ]; + + cmd = filter (x: x != "") ([ "${cfg.executable} run" "--config ${nodeConfigFile}" - "--database-path ${instanceDbPath}" + ] ++ dbPathArgs ++ [ "--topology ${topology i}" - ] ++ optionals (!cfg.systemdSocketActivation) ([ + ]) ++ optionals (!cfg.systemdSocketActivation) ([ "--host-addr ${cfg.hostAddr}" "--port ${if (cfg.shareIpv4port || cfg.shareIpv6port) then toString cfg.port else toString (cfg.port + i)}" "--socket-path ${cfg.socketPath i}" @@ -407,6 +425,28 @@ in { description = ''The node database path, for each instance.''; }; + immutableDatabasePath = mkOption { + type = funcToOr nullOrStr; + default = null; + apply = x : if lib.isFunction x then x else _ : x; + description = '' + The node immutable database path, for each instance. + Set this together with `volatileDatabasePath` to place the two partitions on + separate volumes, in which case `databasePath` is not passed to the node. + ''; + }; + + volatileDatabasePath = mkOption { + type = funcToOr nullOrStr; + default = null; + apply = x : if lib.isFunction x then x else _ : x; + description = '' + The node volatile database path, for each instance. + Set this together with `immutableDatabasePath` to place the two partitions on + separate volumes, in which case `databasePath` is not passed to the node. + ''; + }; + lsmDatabasePath = mkOption { type = funcToOr nullOrStr; default = null; @@ -1011,6 +1051,12 @@ in { assertion = (length lsmPaths) == (length (lists.unique lsmPaths)); message = "When configuring multiple LSM enabled nodes on one instance, lsmDatabasePath must be unique."; } + { + # The node takes either --database-path or both split paths, so half a + # pair would silently fall back to databasePath. + assertion = (cfg.immutableDatabasePath i == null) == (cfg.volatileDatabasePath i == null); + message = "immutableDatabasePath and volatileDatabasePath must be set together, or neither set."; + } { assertion = count (o: o != null) (with cfg; [ (tracerSocketPathAccept i) From 3aa3652af4ea0dfcd2d31c0db24c4a589076a265 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Tue, 6 Oct 2026 23:38:46 -0500 Subject: [PATCH 27/45] nixosNodeSvc: take a single bls key, not a list The current prototype parses --shelley-bls-key as optional (strOption ...), so the node takes at most one occurrence. Multiple keys go in the one file instead, as a JSON array of text envelopes, which is how a rotation pair or a bundle of pool keys is supplied. The earlier --shelley-bls-keys design of accepting the flag repeatedly is not supported going forward. --- nix/nixos/cardano-node-service.nix | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/nix/nixos/cardano-node-service.nix b/nix/nixos/cardano-node-service.nix index b3ab1fa4279..38c77e842d1 100644 --- a/nix/nixos/cardano-node-service.nix +++ b/nix/nixos/cardano-node-service.nix @@ -109,7 +109,8 @@ let "--shelley-kes-key ${cfg.kesKey}"}" "${optionalString (cfg.operationalCertificate != null) "--shelley-operational-certificate ${cfg.operationalCertificate}"}" - "${concatMapStringsSep " " (k: "--shelley-bls-key ${k}") cfg.blsKeys}" + "${optionalString (cfg.blsKey != null) + "--shelley-bls-key ${cfg.blsKey}"}" "${optionalString (cfg.shelleyKesAgentSocket != null) "--shelley-kes-agent-socket ${cfg.shelleyKesAgentSocket}"}" ]; @@ -348,14 +349,14 @@ in { ''; }; - blsKeys = mkOption { - type = listOf str; - default = []; + blsKey = mkOption { + type = nullOr str; + default = null; description = '' - Leios BLS signing key files. Optional and repeatable; used alongside - the KES and VRF keys on a producer that participates in Leios. During - a BLS key rotation both the active and the incoming key may be - supplied and node uses whichever is active per the on-chain schedule. + The Leios BLS signing key file, used alongside the KES and VRF keys + on a producer that participates in Leios. The file is either a single + text envelope or a JSON array of them, so a rotation pair or a bundle + of pool keys goes in the one file; the option is not repeatable. ''; }; From 790a72dcd2380ab9d23cfe37ab501f0c2af41eed Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Tue, 6 Oct 2026 23:53:18 -0500 Subject: [PATCH 28/45] configuration: refresh the shipped configs for cardano-config 2.2.2.0 Regenerated from iohk-nix, which this bumps. The envelope moves to format version 2 with the shortened section keys, mainnet defaults to GenesisMode, and the snapshot policy gains MinDelay and MaxDelay derived from the security parameter. The peer snapshot and the topology's useLedgerAfterSlot are regenerated together, so the point past which a syncing node trusts ledger peers tracks the snapshot rather than trailing it. --- configuration/cardano/mainnet-config.json | 26 +- configuration/cardano/mainnet-config.yaml | 3 + .../cardano/mainnet-peer-snapshot.json | 5859 ++++++++--------- configuration/cardano/mainnet-topology.json | 2 +- .../cardano/testnet-template-config.json | 8 +- 5 files changed, 2930 insertions(+), 2968 deletions(-) diff --git a/configuration/cardano/mainnet-config.json b/configuration/cardano/mainnet-config.json index 3b6d971b6c8..1a178d11662 100644 --- a/configuration/cardano/mainnet-config.json +++ b/configuration/cardano/mainnet-config.json @@ -1,14 +1,13 @@ { - "$schema": "https://raw.githubusercontent.com/IntersectMBO/cardano-config/v1/schemas/config.schema.json", + "$schema": "https://raw.githubusercontent.com/IntersectMBO/cardano-config/v2/schemas/config.schema.json", "Configuration": { - "ConsensusConfig": { - "ConsensusMode": "PraosMode" + "Consensus": { + "ConsensusMode": "GenesisMode" }, "HermodTracing": { "TraceOptionForwarder": { - "connQueueSize": 64, - "disconnQueueSize": 128, - "maxReconnectDelay": 30 + "maxReconnectDelay": 30, + "queueSize": 128 }, "TraceOptionMetricsPrefix": "cardano.node.metrics.", "TraceOptionResourceFrequency": 1000, @@ -80,6 +79,9 @@ "Net.Mux.Remote": { "severity": "Info" }, + "Net.Mux.Remote.Bearer": { + "severity": "Silence" + }, "Net.PeerSelection": { "severity": "Info" }, @@ -91,7 +93,7 @@ } } }, - "ProtocolConfig": { + "Protocol": { "AlonzoGenesisFile": "mainnet-alonzo-genesis.json", "AlonzoGenesisHash": "7e94a15f55d1e82d10f09203fa1d40f8eede58fd8066542cf6566008068ed874", "ByronGenesisFile": "mainnet-byron-genesis.json", @@ -104,18 +106,20 @@ "ShelleyGenesisFile": "mainnet-shelley-genesis.json", "ShelleyGenesisHash": "1a3be38bcbb7911969283716ad7aa550250226b76a61fc51cc9a9a35d9276d81" }, - "StorageConfig": { + "Storage": { "LedgerDB": { "Backend": "V2InMemory", "QueryBatchSize": 100000, "Snapshots": { + "Interval": 86400, + "MaxDelay": 21600, + "MinDelay": 300, "NumOfDiskSnapshots": 2, - "SlotOffset": 0, - "SnapshotInterval": 86400 + "Offset": 0 } } } }, "MinNodeVersion": "11.2.0", - "Version": 1 + "Version": 2 } diff --git a/configuration/cardano/mainnet-config.yaml b/configuration/cardano/mainnet-config.yaml index 059d89460a4..fd289739300 100644 --- a/configuration/cardano/mainnet-config.yaml +++ b/configuration/cardano/mainnet-config.yaml @@ -280,6 +280,9 @@ Configuration: Net.Mux.Remote: severity: Info + Net.Mux.Remote.Bearer: + severity: Silence + Net.PeerSelection: severity: Info diff --git a/configuration/cardano/mainnet-peer-snapshot.json b/configuration/cardano/mainnet-peer-snapshot.json index afad080fcbb..f39974e0cc4 100644 --- a/configuration/cardano/mainnet-peer-snapshot.json +++ b/configuration/cardano/mainnet-peer-snapshot.json @@ -2,31 +2,13 @@ "NetworkMagic": 764824073, "NodeToClientVersion": 23, "Point": { - "blockPointHash": "8754889f556c056dc0faef5ffa23b1a9ce315cafd02012e1be1081d0d03853c2", - "blockPointSlot": 194344226 + "blockPointHash": "7021b0be095d2f652a3cc45c655059bf1b9ef5d5e6717dbb168d1f42d7dd3f9b", + "blockPointSlot": 200803835 }, "bigLedgerPools": [ { - "accumulatedStake": 0.005395048750398899, - "relativeStake": 0.005395048750398899, - "relays": [ - { - "address": "relay-trustwallet-5-0.cardano.mainnet.kiln.fi", - "port": 3001 - }, - { - "address": "relay-trustwallet-5-1.cardano.mainnet.kiln.fi", - "port": 3001 - }, - { - "address": "relay-trustwallet-5-2.cardano.mainnet.kiln.fi", - "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.010337275510315476, - "relativeStake": 0.004942226759916578, + "accumulatedStake": 0.0059591023377367994, + "relativeStake": 0.0059591023377367994, "relays": [ { "address": "170.23.181.50", @@ -43,17 +25,26 @@ ] }, { - "accumulatedStake": 0.01446888802258894, - "relativeStake": 0.004131612512273464, + "accumulatedStake": 0.011339267222468839, + "relativeStake": 0.00538016488473204, "relays": [ { - "address": "relay-pool-2-mainnet.cardano.aeq5f.com" + "address": "relay-trustwallet-5-0.cardano.mainnet.kiln.fi", + "port": 3001 + }, + { + "address": "relay-trustwallet-5-1.cardano.mainnet.kiln.fi", + "port": 3001 + }, + { + "address": "relay-trustwallet-5-2.cardano.mainnet.kiln.fi", + "port": 3001 } ] }, { - "accumulatedStake": 0.01857466912355889, - "relativeStake": 0.00410578110096995, + "accumulatedStake": 0.015531686871731704, + "relativeStake": 0.004192419649262864, "relays": [ { "address": "relay-pool-3-mainnet.cardano.aeq5f.com" @@ -61,8 +52,8 @@ ] }, { - "accumulatedStake": 0.022583639986000485, - "relativeStake": 0.004008970862441595, + "accumulatedStake": 0.01947247552873279, + "relativeStake": 0.003940788657001085, "relays": [ { "address": "relay-pool-ledger-2-mainnet.cardano.aeq5f.com" @@ -70,8 +61,8 @@ ] }, { - "accumulatedStake": 0.026391353874785063, - "relativeStake": 0.0038077138887845784, + "accumulatedStake": 0.023358018083157288, + "relativeStake": 0.0038855425544244986, "relays": [ { "address": "relay-kiln-4-0.cardano.mainnet.kiln.fi", @@ -88,52 +79,56 @@ ] }, { - "accumulatedStake": 0.030127623172465888, - "relativeStake": 0.0037362692976808227, + "accumulatedStake": 0.02705435511035205, + "relativeStake": 0.003696337027194761, "relays": [ { - "address": "26e894b1.cardano-relay.herd.run", - "port": 1338 + "address": "170.23.181.50", + "port": 6001 + }, + { + "address": "170.23.181.50", + "port": 6002 + }, + { + "address": "170.23.181.50", + "port": 6003 } ] }, { - "accumulatedStake": 0.03379257855131295, - "relativeStake": 0.0036649553788470645, + "accumulatedStake": 0.030743376890059546, + "relativeStake": 0.003689021779707499, "relays": [ { - "address": "204.12.236.13", + "address": "13.236.12.204", "port": 8332 } ] }, { - "accumulatedStake": 0.037454519010006786, - "relativeStake": 0.0036619404586938336, + "accumulatedStake": 0.03443067112241167, + "relativeStake": 0.003687294232352119, "relays": [ { - "address": "179.73.211.13", + "address": "13.211.73.179", "port": 8332 } ] }, { - "accumulatedStake": 0.041115979410513516, - "relativeStake": 0.0036614604005067285, + "accumulatedStake": 0.03811663401167597, + "relativeStake": 0.0036859628892643055, "relays": [ { - "address": "219.79.128.178", - "port": 3001 - }, - { - "address": "73.122.131.104", - "port": 3001 + "address": "162.120.71.180", + "port": 6000 } ] }, { - "accumulatedStake": 0.04477498198794721, - "relativeStake": 0.0036590025774336965, + "accumulatedStake": 0.04178922015750158, + "relativeStake": 0.0036725861458256105, "relays": [ { "address": "relays.wavepool.digital", @@ -142,48 +137,52 @@ ] }, { - "accumulatedStake": 0.04842720110485478, - "relativeStake": 0.00365221911690757, + "accumulatedStake": 0.045455726800821245, + "relativeStake": 0.0036665066433196666, "relays": [ { - "address": "113.cardano.staked.cloud", - "port": 3001 + "address": "relay1.cardanotech.io", + "port": 6000 + }, + { + "address": "relay2.cardanotech.io", + "port": 6000 } ] }, { - "accumulatedStake": 0.052079365940333404, - "relativeStake": 0.003652164835478622, + "accumulatedStake": 0.04911180072557414, + "relativeStake": 0.0036560739247528916, "relays": [ { - "address": "102.cardano.staked.cloud", + "address": "115.cardano.staked.cloud", "port": 3001 } ] }, { - "accumulatedStake": 0.05573151258047909, - "relativeStake": 0.0036521466401456927, + "accumulatedStake": 0.052767699243445536, + "relativeStake": 0.003655898517871393, "relays": [ { - "address": "109.cardano.staked.cloud", + "address": "111.cardano.staked.cloud", "port": 3001 } ] }, { - "accumulatedStake": 0.059383622923739374, - "relativeStake": 0.0036521103432602814, + "accumulatedStake": 0.05642354516738017, + "relativeStake": 0.003655845923934637, "relays": [ { - "address": "112.cardano.staked.cloud", + "address": "114.cardano.staked.cloud", "port": 3001 } ] }, { - "accumulatedStake": 0.06303562452256749, - "relativeStake": 0.0036520015988281054, + "accumulatedStake": 0.060079355975111576, + "relativeStake": 0.0036558108077314033, "relays": [ { "address": "106.cardano.staked.cloud", @@ -192,8 +191,18 @@ ] }, { - "accumulatedStake": 0.06668758982068673, - "relativeStake": 0.003651965298119255, + "accumulatedStake": 0.0637351141717924, + "relativeStake": 0.003655758196680816, + "relays": [ + { + "address": "108.cardano.staked.cloud", + "port": 3001 + } + ] + }, + { + "accumulatedStake": 0.06739085485624118, + "relativeStake": 0.003655740684448784, "relays": [ { "address": "107.cardano.staked.cloud", @@ -202,86 +211,92 @@ ] }, { - "accumulatedStake": 0.07033953701158523, - "relativeStake": 0.003651947190898494, + "accumulatedStake": 0.07104654305401932, + "relativeStake": 0.003655688197778154, "relays": [ { - "address": "111.cardano.staked.cloud", + "address": "102.cardano.staked.cloud", "port": 3001 } ] }, { - "accumulatedStake": 0.07399148419632527, - "relativeStake": 0.0036519471847400457, + "accumulatedStake": 0.07470223110631379, + "relativeStake": 0.003655688052294456, "relays": [ { - "address": "103.cardano.staked.cloud", + "address": "113.cardano.staked.cloud", "port": 3001 } ] }, { - "accumulatedStake": 0.07764337699291962, - "relativeStake": 0.0036518927965943407, + "accumulatedStake": 0.07835788408851123, + "relativeStake": 0.0036556529821974416, "relays": [ { - "address": "104.cardano.staked.cloud", + "address": "109.cardano.staked.cloud", "port": 3001 } ] }, { - "accumulatedStake": 0.08129521542839614, - "relativeStake": 0.0036518384354765213, + "accumulatedStake": 0.08201350201047922, + "relativeStake": 0.003655617921967993, "relays": [ { - "address": "114.cardano.staked.cloud", + "address": "104.cardano.staked.cloud", "port": 3001 } ] }, { - "accumulatedStake": 0.08494701756831743, - "relativeStake": 0.0036518021399212994, + "accumulatedStake": 0.08566910237946196, + "relativeStake": 0.0036556003689827386, "relays": [ { - "address": "108.cardano.staked.cloud", + "address": "112.cardano.staked.cloud", "port": 3001 } ] }, { - "accumulatedStake": 0.08859878345734244, - "relativeStake": 0.0036517658890250103, + "accumulatedStake": 0.08932457994342005, + "relativeStake": 0.0036554775639580967, "relays": [ { - "address": "115.cardano.staked.cloud", + "address": "103.cardano.staked.cloud", "port": 3001 } ] }, { - "accumulatedStake": 0.09224692693728437, - "relativeStake": 0.0036481434799419156, + "accumulatedStake": 0.09297811442534205, + "relativeStake": 0.0036535344819220014, "relays": [ { - "address": "170.23.181.50", - "port": 6001 + "address": "173.15.110.154", + "port": 6000 }, { - "address": "170.23.181.50", - "port": 6002 - }, + "address": "173.15.110.155", + "port": 6000 + } + ] + }, + { + "accumulatedStake": 0.0966286499895629, + "relativeStake": 0.0036505355642208405, + "relays": [ { - "address": "170.23.181.50", - "port": 6003 + "address": "relays.wavepool.digital", + "port": 3001 } ] }, { - "accumulatedStake": 0.09587659519155345, - "relativeStake": 0.003629668254269081, + "accumulatedStake": 0.10026271609627614, + "relativeStake": 0.003634066106713254, "relays": [ { "address": "relay1.mainnet.pool.cardano.services", @@ -294,8 +309,56 @@ ] }, { - "accumulatedStake": 0.09950405256921431, - "relativeStake": 0.003627457377660863, + "accumulatedStake": 0.10389620419452207, + "relativeStake": 0.00363348809824592, + "relays": [ + { + "address": "relay-kiln-2-0.cardano.mainnet.kiln.fi", + "port": 3001 + }, + { + "address": "relay-kiln-2-1.cardano.mainnet.kiln.fi", + "port": 3001 + }, + { + "address": "relay-kiln-2-2.cardano.mainnet.kiln.fi", + "port": 3001 + } + ] + }, + { + "accumulatedStake": 0.10752710053563859, + "relativeStake": 0.003630896341116517, + "relays": [ + { + "address": "180.150.102.25", + "port": 8376 + }, + { + "address": "180.150.96.245", + "port": 8376 + }, + { + "address": "144.6.112.28", + "port": 8376 + }, + { + "address": "154.38.173.238", + "port": 8376 + }, + { + "address": "152.53.55.29", + "port": 8376 + }, + { + "address": "relays.terminada.io", + "port": 8376 + } + ] + }, + { + "accumulatedStake": 0.11115782962443356, + "relativeStake": 0.0036307290887949775, "relays": [ { "address": "cf1r1.mainnet.pool.cardanofoundation.org", @@ -308,50 +371,54 @@ ] }, { - "accumulatedStake": 0.10313096510382867, - "relativeStake": 0.003626912534614365, + "accumulatedStake": 0.11478855178052443, + "relativeStake": 0.003630722156090856, "relays": [ { - "address": "cf3r1.mainnet.pool.cardanofoundation.org", + "address": "cf2r1.mainnet.pool.cardanofoundation.org", "port": 3001 }, { - "address": "cf3r2.mainnet.pool.cardanofoundation.org", + "address": "cf2r2.mainnet.pool.cardanofoundation.org", "port": 3001 } ] }, { - "accumulatedStake": 0.10675787510248218, - "relativeStake": 0.0036269099986535117, + "accumulatedStake": 0.1184192739293348, + "relativeStake": 0.003630722148810378, "relays": [ { - "address": "cf4r1.mainnet.pool.cardanofoundation.org", + "address": "cf3r1.mainnet.pool.cardanofoundation.org", "port": 3001 }, { - "address": "cf4r2.mainnet.pool.cardanofoundation.org", + "address": "cf3r2.mainnet.pool.cardanofoundation.org", "port": 3001 } ] }, { - "accumulatedStake": 0.11038478508025004, - "relativeStake": 0.0036269099777678647, + "accumulatedStake": 0.12204358071220663, + "relativeStake": 0.0036243067828718354, "relays": [ { - "address": "cf2r1.mainnet.pool.cardanofoundation.org", + "address": "relay-kiln-6-0.cardano.mainnet.kiln.fi", "port": 3001 }, { - "address": "cf2r2.mainnet.pool.cardanofoundation.org", + "address": "relay-kiln-6-1.cardano.mainnet.kiln.fi", + "port": 3001 + }, + { + "address": "relay-kiln-6-2.cardano.mainnet.kiln.fi", "port": 3001 } ] }, { - "accumulatedStake": 0.1140104192686956, - "relativeStake": 0.003625634188445552, + "accumulatedStake": 0.1256623126155026, + "relativeStake": 0.0036187319032959598, "relays": [ { "address": "cardanosuisse.com", @@ -368,18 +435,18 @@ ] }, { - "accumulatedStake": 0.11763479956254201, - "relativeStake": 0.003624380293846408, + "accumulatedStake": 0.1292725236077011, + "relativeStake": 0.003610210992198514, "relays": [ { - "address": "180.71.120.162", - "port": 6000 + "address": "relays.wavepool.digital", + "port": 3001 } ] }, { - "accumulatedStake": 0.12123631012768447, - "relativeStake": 0.0036015105651424606, + "accumulatedStake": 0.13288143993365018, + "relativeStake": 0.0036089163259490796, "relays": [ { "address": "relays.wavepool.digital", @@ -388,8 +455,18 @@ ] }, { - "accumulatedStake": 0.12483298583348279, - "relativeStake": 0.0035966757057983227, + "accumulatedStake": 0.13645186433724682, + "relativeStake": 0.0035704244035966227, + "relays": [ + { + "address": "644dd09c.cardano-relay.herd.run", + "port": 1338 + } + ] + }, + { + "accumulatedStake": 0.14001805951313204, + "relativeStake": 0.0035661951758852164, "relays": [ { "address": "relays.wavepool.digital", @@ -398,26 +475,56 @@ ] }, { - "accumulatedStake": 0.12842440528594729, - "relativeStake": 0.0035914194524644806, + "accumulatedStake": 0.14358121339280516, + "relativeStake": 0.003563153879673136, "relays": [ { - "address": "relay-kiln-2-0.cardano.mainnet.kiln.fi", + "address": "bd-cardano-main-relay-12-a.bdnodes.net", + "port": 6000 + }, + { + "address": "bd-cardano-main-relay-12-b.bdnodes.net", + "port": 6000 + } + ] + }, + { + "accumulatedStake": 0.14713407158814018, + "relativeStake": 0.003552858195335023, + "relays": [ + { + "address": "104.167.218.211", "port": 3001 }, { - "address": "relay-kiln-2-1.cardano.mainnet.kiln.fi", + "address": "5.226.35.52", "port": 3001 }, { - "address": "relay-kiln-2-2.cardano.mainnet.kiln.fi", + "address": "yul.mainnet.happystaking.io", + "port": 3001 + }, + { + "address": "arn.mainnet.happystaking.io", "port": 3001 + }, + { + "address": "mainnet.happystaking.io" + } + ] + }, + { + "accumulatedStake": 0.15068551493492258, + "relativeStake": 0.003551443346782405, + "relays": [ + { + "address": "relay-pool-ledger-1-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.13201368560246637, - "relativeStake": 0.0035892803165190963, + "accumulatedStake": 0.15422692148102032, + "relativeStake": 0.003541406546097748, "relays": [ { "address": "relays.wavepool.digital", @@ -426,199 +533,215 @@ ] }, { - "accumulatedStake": 0.1356020346503598, - "relativeStake": 0.003588349047893422, + "accumulatedStake": 0.15773604315656567, + "relativeStake": 0.0035091216755453298, "relays": [ { - "address": "Relay1.NordicPool.org", - "port": 3005 + "address": "olive-geonosis-edffc.cardano.bdnodes.net", + "port": 6000 }, { - "address": "Relay2.NordicPool.org", - "port": 3005 - }, + "address": "violet-kingston-8d67e.cardano.bdnodes.net", + "port": 6000 + } + ] + }, + { + "accumulatedStake": 0.16123665595643227, + "relativeStake": 0.0035006127998666167, + "relays": [ { - "address": "Relay3.NordicPool.org", - "port": 3005 + "address": "relay-pool-ledger-3-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.13915085624669235, - "relativeStake": 0.0035488215963325543, + "accumulatedStake": 0.1647269115144712, + "relativeStake": 0.003490255558038904, "relays": [ { - "address": "r1.spirestaking.com", - "port": 3001 + "address": "relay-pool-figment-21-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.1426953247015414, - "relativeStake": 0.003544468454849035, + "accumulatedStake": 0.16820666248624264, + "relativeStake": 0.0034797509717714404, "relays": [ { - "address": "bd-cardano-main-relay-12-a.bdnodes.net", - "port": 6000 + "address": "r-eu-1.polypool.io", + "port": 4001 }, { - "address": "bd-cardano-main-relay-12-b.bdnodes.net", - "port": 6000 + "address": "r-sg-1.polypool.io", + "port": 4001 } ] }, { - "accumulatedStake": 0.14623342247651902, - "relativeStake": 0.003538097774977632, + "accumulatedStake": 0.17168156374624427, + "relativeStake": 0.0034749012600016516, "relays": [ { - "address": "644dd09c.cardano-relay.herd.run", - "port": 1338 + "address": "relay-pool-figment-27-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.1497649298147439, - "relativeStake": 0.003531507338224878, + "accumulatedStake": 0.17515060008276398, + "relativeStake": 0.0034690363365197114, "relays": [ { - "address": "gateway.adavault.com", - "port": 4021 - }, - { - "address": "gateway.adavault.com", - "port": 4022 - }, - { - "address": "gateway.adavault.com", - "port": 4026 + "address": "178.128.79.219", + "port": 3001 }, { - "address": "gateway.adavault.com", - "port": 4027 + "address": "104.131.122.73", + "port": 3001 } ] }, { - "accumulatedStake": 0.15328721784078325, - "relativeStake": 0.003522288026039366, + "accumulatedStake": 0.17858712589405026, + "relativeStake": 0.0034365258112862827, "relays": [ { - "address": "relay-kiln-0-0.cardano.mainnet.kiln.fi", + "address": "20.61.229.103", "port": 3001 }, { - "address": "relay-kiln-0-1.cardano.mainnet.kiln.fi", + "address": "20.61.228.218", "port": 3001 }, { - "address": "relay-kiln-0-2.cardano.mainnet.kiln.fi", + "address": "108.142.42.221", + "port": 3001 + }, + { + "address": "108.142.42.161", "port": 3001 } ] }, { - "accumulatedStake": 0.1568085858869114, - "relativeStake": 0.0035213680461281516, + "accumulatedStake": 0.18200980369310832, + "relativeStake": 0.0034226777990580544, "relays": [ { - "address": "154.110.15.173", - "port": 6000 - }, - { - "address": "155.110.15.173", - "port": 6000 + "address": "relay-pool-2-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.16029957513459672, - "relativeStake": 0.0034909892476853188, + "accumulatedStake": 0.18542452501907186, + "relativeStake": 0.0034147213259635386, "relays": [ { - "address": "olive-geonosis-edffc.cardano.bdnodes.net", - "port": 6000 - }, - { - "address": "violet-kingston-8d67e.cardano.bdnodes.net", - "port": 6000 + "address": "relays.wavepool.digital", + "port": 3001 } ] }, { - "accumulatedStake": 0.16377274461153404, - "relativeStake": 0.0034731694769373237, + "accumulatedStake": 0.18883644958781792, + "relativeStake": 0.0034119245687460557, "relays": [ { - "address": "relay-pool-figment-21-mainnet.cardano.aeq5f.com" + "address": "relay-pool-figment-8-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.16720566214638358, - "relativeStake": 0.0034329175348495394, + "accumulatedStake": 0.1922375248481912, + "relativeStake": 0.0034010752603732763, "relays": [ { - "address": "103.229.61.20", - "port": 3001 + "address": "sydney.cardanode.com.au", + "port": 6000 }, { - "address": "218.228.61.20", - "port": 3001 + "address": "singapore.cardanode.com.au", + "port": 6000 }, { - "address": "221.42.142.108", - "port": 3001 + "address": "goldcoast.cardanode.com.au", + "port": 6000 }, { - "address": "161.42.142.108", + "address": "europe.cardanode.com.au", + "port": 6000 + } + ] + }, + { + "accumulatedStake": 0.19563367481699628, + "relativeStake": 0.003396149968805096, + "relays": [ + { + "address": "r1.spirestaking.com", "port": 3001 } ] }, { - "accumulatedStake": 0.17063501332829778, - "relativeStake": 0.0034293511819141784, + "accumulatedStake": 0.1990139606703871, + "relativeStake": 0.003380285853390799, "relays": [ { - "address": "relay.de.fikapool.com", - "port": 6000 + "address": "26e894b1.cardano-relay.herd.run", + "port": 1338 + } + ] + }, + { + "accumulatedStake": 0.20238993297485977, + "relativeStake": 0.0033759723044726885, + "relays": [ + { + "address": "31.220.91.105", + "port": 3001 }, { - "address": "relay.sg.fikapool.com", - "port": 6000 + "address": "154.26.158.189", + "port": 3001 }, { - "address": "relay.ca.fikapool.com", - "port": 6000 + "address": "5.104.83.174", + "port": 3001 } ] }, { - "accumulatedStake": 0.1740288295687427, - "relativeStake": 0.0033938162404449274, + "accumulatedStake": 0.20575570175213787, + "relativeStake": 0.003365768777278085, "relays": [ { - "address": "sydney.cardanode.com.au", + "address": "54.37.87.63", "port": 6000 }, { - "address": "singapore.cardanode.com.au", + "address": "54.36.178.85", "port": 6000 - }, + } + ] + }, + { + "accumulatedStake": 0.2091213345401094, + "relativeStake": 0.003365632787971513, + "relays": [ { - "address": "goldcoast.cardanode.com.au", - "port": 6000 + "address": "46.101.9.225", + "port": 3001 }, { - "address": "europe.cardanode.com.au", - "port": 6000 + "address": "64.227.46.95", + "port": 3001 } ] }, { - "accumulatedStake": 0.17742206009488956, - "relativeStake": 0.003393230526146853, + "accumulatedStake": 0.212486964477268, + "relativeStake": 0.0033656299371586304, "relays": [ { "address": "relay1-dl.aichi-stakepool.com", @@ -635,8 +758,8 @@ ] }, { - "accumulatedStake": 0.1808117527811607, - "relativeStake": 0.0033896926862711715, + "accumulatedStake": 0.21584918215925925, + "relativeStake": 0.0033622176819912467, "relays": [ { "address": "ada-relay01.biglazycat.com", @@ -645,116 +768,67 @@ ] }, { - "accumulatedStake": 0.18419958269095146, - "relativeStake": 0.0033878299097907395, - "relays": [ - { - "address": "gateway.adavault.com", - "port": 4021 - }, - { - "address": "gateway.adavault.com", - "port": 4022 - }, - { - "address": "gateway.adavault.com", - "port": 4026 - }, - { - "address": "gateway.adavault.com", - "port": 4027 - } - ] - }, - { - "accumulatedStake": 0.18758684983476245, - "relativeStake": 0.003387267143810997, + "accumulatedStake": 0.21920969714398045, + "relativeStake": 0.0033605149847211954, "relays": [ { - "address": "relay01.ca.lovelace.community", + "address": "cardano-main.everstake.com", "port": 3001 }, { - "address": "relay02.ca.lovelace.community", + "address": "cardano-main2.everstake.com", "port": 3001 }, { - "address": "relay01.fr.lovelace.community", + "address": "cardano-relay.everstake.com", "port": 3001 }, { - "address": "relay01.de.lovelace.community", + "address": "cardano-relay1.everstake.com", "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.19095357224609483, - "relativeStake": 0.0033667224113323765, - "relays": [ + }, { - "address": "225.9.101.46", + "address": "cardano-relay2.everstake.com", "port": 3001 }, { - "address": "95.46.227.64", + "address": "cardano-relay3.everstake.com", "port": 3001 } ] }, { - "accumulatedStake": 0.1943093653978898, - "relativeStake": 0.003355793151794949, + "accumulatedStake": 0.2225661817355047, + "relativeStake": 0.00335648459152423, "relays": [ { - "address": "25.102.150.180", - "port": 8376 - }, - { - "address": "245.96.150.180", - "port": 8376 - }, - { - "address": "28.112.6.144", - "port": 8376 - }, - { - "address": "238.173.38.154", - "port": 8376 - }, - { - "address": "29.55.53.152", - "port": 8376 - }, - { - "address": "relays.terminada.io", - "port": 8376 + "address": "7ddb9c28.cardano-relay.bison.run", + "port": 1338 } ] }, { - "accumulatedStake": 0.19766213202464056, - "relativeStake": 0.003352766626750775, + "accumulatedStake": 0.225915434130273, + "relativeStake": 0.003349252394768329, "relays": [ { - "address": "7ddb9c28.cardano-relay.bison.run", + "address": "8d6f8de4.cardano-relay.herd.run", "port": 1338 } ] }, { - "accumulatedStake": 0.20100569682665403, - "relativeStake": 0.003343564802013482, + "accumulatedStake": 0.22926433512468408, + "relativeStake": 0.003348900994411077, "relays": [ { - "address": "8d6f8de4.cardano-relay.herd.run", - "port": 1338 + "address": "relay-pool-figment-19-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.20434855212111785, - "relativeStake": 0.003342855294463827, + "accumulatedStake": 0.23261086401500164, + "relativeStake": 0.003346528890317544, "relays": [ { "address": "b3e201f4.cardano-relay.bison.run", @@ -763,8 +837,8 @@ ] }, { - "accumulatedStake": 0.20768525316357095, - "relativeStake": 0.0033367010424530693, + "accumulatedStake": 0.23595105427598617, + "relativeStake": 0.0033401902609845307, "relays": [ { "address": "b3bbbcac.cardano-relay.bison.run", @@ -773,8 +847,8 @@ ] }, { - "accumulatedStake": 0.2110216131478754, - "relativeStake": 0.003336359984304455, + "accumulatedStake": 0.23929089932651007, + "relativeStake": 0.0033398450505238986, "relays": [ { "address": "ddbb5a06.cardano-relay.herd.run", @@ -783,48 +857,47 @@ ] }, { - "accumulatedStake": 0.21435362415317488, - "relativeStake": 0.0033320110052994854, + "accumulatedStake": 0.2426301054865828, + "relativeStake": 0.0033392061600727167, "relays": [ { - "address": "50809bee.cardano-relay.herd.run", - "port": 1338 + "address": "35.75.32.253", + "port": 6000 } ] }, { - "accumulatedStake": 0.21768439218291366, - "relativeStake": 0.003330768029738787, + "accumulatedStake": 0.24596492313007395, + "relativeStake": 0.00333481764349117, "relays": [ { - "address": "e4527900.cardano-relay.herd.run", + "address": "a94da6a8.cardano-relay.bison.run", "port": 1338 } ] }, { - "accumulatedStake": 0.22101451363810834, - "relativeStake": 0.0033301214551946763, + "accumulatedStake": 0.2492996339891381, + "relativeStake": 0.0033347108590641474, "relays": [ { - "address": "253.32.75.35", - "port": 6000 + "address": "relay-pool-figment-10-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.22434448749640495, - "relativeStake": 0.003329973858296607, + "accumulatedStake": 0.2526340925258125, + "relativeStake": 0.003334458536674399, "relays": [ { - "address": "a94da6a8.cardano-relay.bison.run", + "address": "e4527900.cardano-relay.herd.run", "port": 1338 } ] }, { - "accumulatedStake": 0.22767411865879394, - "relativeStake": 0.0033296311623889976, + "accumulatedStake": 0.2559672767756021, + "relativeStake": 0.003333184249789584, "relays": [ { "address": "9a956262.cardano-relay.bison.run", @@ -833,8 +906,8 @@ ] }, { - "accumulatedStake": 0.23100354312760665, - "relativeStake": 0.0033294244688126936, + "accumulatedStake": 0.2593002002365603, + "relativeStake": 0.003332923460958219, "relays": [ { "address": "9dc533bf.cardano-relay.herd.run", @@ -843,8 +916,8 @@ ] }, { - "accumulatedStake": 0.23433277934603886, - "relativeStake": 0.0033292362184322273, + "accumulatedStake": 0.262633010882834, + "relativeStake": 0.0033328106462736725, "relays": [ { "address": "f84db19f.cardano-relay.bison.run", @@ -853,8 +926,8 @@ ] }, { - "accumulatedStake": 0.23766172987201378, - "relativeStake": 0.003328950525974904, + "accumulatedStake": 0.26596562590703565, + "relativeStake": 0.003332615024201682, "relays": [ { "address": "fdd5329e.cardano-relay.bison.run", @@ -863,48 +936,48 @@ ] }, { - "accumulatedStake": 0.24099034980667422, - "relativeStake": 0.0033286199346604585, + "accumulatedStake": 0.2692978914129037, + "relativeStake": 0.003332265505868066, "relays": [ { - "address": "c2504518.cardano-relay.bison.run", + "address": "50809bee.cardano-relay.herd.run", "port": 1338 } ] }, { - "accumulatedStake": 0.24431876057941174, - "relativeStake": 0.0033284107727375094, + "accumulatedStake": 0.2726300324346796, + "relativeStake": 0.003332141021775879, "relays": [ { - "address": "d489c136.cardano-relay.bison.run", + "address": "c2504518.cardano-relay.bison.run", "port": 1338 } ] }, { - "accumulatedStake": 0.24764717007703838, - "relativeStake": 0.003328409497626637, + "accumulatedStake": 0.2759621520678068, + "relativeStake": 0.0033321196331271715, "relays": [ { - "address": "dbe22510.cardano-relay.bison.run", + "address": "778cb679.cardano-relay.bison.run", "port": 1338 } ] }, { - "accumulatedStake": 0.25097554812057987, - "relativeStake": 0.0033283780435415097, + "accumulatedStake": 0.27929415034971733, + "relativeStake": 0.0033319982819105575, "relays": [ { - "address": "778cb679.cardano-relay.bison.run", + "address": "dbe22510.cardano-relay.bison.run", "port": 1338 } ] }, { - "accumulatedStake": 0.25430390614640436, - "relativeStake": 0.003328358025824483, + "accumulatedStake": 0.2826261169830032, + "relativeStake": 0.003331966633285883, "relays": [ { "address": "94cc7304.cardano-relay.bison.run", @@ -913,57 +986,58 @@ ] }, { - "accumulatedStake": 0.2576321985779972, - "relativeStake": 0.0033282924315928297, + "accumulatedStake": 0.28595799486185697, + "relativeStake": 0.003331877878853766, "relays": [ { - "address": "a5f2af9f.cardano-relay.bison.run", + "address": "72e508af.cardano-relay.herd.run", "port": 1338 } ] }, { - "accumulatedStake": 0.26096043933597945, - "relativeStake": 0.0033282407579822487, + "accumulatedStake": 0.28928984826556026, + "relativeStake": 0.0033318534037032692, "relays": [ { - "address": "relay-pool-figment-19-mainnet.cardano.aeq5f.com" + "address": "a5f2af9f.cardano-relay.bison.run", + "port": 1338 } ] }, { - "accumulatedStake": 0.26428865881947766, - "relativeStake": 0.0033282194834982153, + "accumulatedStake": 0.29262167351966406, + "relativeStake": 0.003331825254103824, "relays": [ { - "address": "bb78d57d.cardano-relay.bison.run", + "address": "d489c136.cardano-relay.bison.run", "port": 1338 } ] }, { - "accumulatedStake": 0.2676168682296856, - "relativeStake": 0.0033282094102079387, + "accumulatedStake": 0.2959534817745367, + "relativeStake": 0.0033318082548726125, "relays": [ { - "address": "72e508af.cardano-relay.herd.run", + "address": "d89eeea0.cardano-relay.herd.run", "port": 1338 } ] }, { - "accumulatedStake": 0.270945058037804, - "relativeStake": 0.0033281898081184017, + "accumulatedStake": 0.2992851596403488, + "relativeStake": 0.0033316778658120925, "relays": [ { - "address": "d89eeea0.cardano-relay.herd.run", + "address": "bb78d57d.cardano-relay.bison.run", "port": 1338 } ] }, { - "accumulatedStake": 0.27427312884325394, - "relativeStake": 0.003328070805449945, + "accumulatedStake": 0.30261678357212374, + "relativeStake": 0.003331623931774961, "relays": [ { "address": "d699483e.cardano-relay.bison.run", @@ -972,155 +1046,160 @@ ] }, { - "accumulatedStake": 0.2776005040929206, - "relativeStake": 0.0033273752496666377, + "accumulatedStake": 0.30594765616467373, + "relativeStake": 0.003330872592549971, "relays": [ { - "address": "253.32.75.35", + "address": "35.75.32.253", "port": 6000 } ] }, { - "accumulatedStake": 0.2809182634218505, - "relativeStake": 0.003317759328929939, - "relays": [ - { - "address": "relay-pool-figment-10-mainnet.cardano.aeq5f.com" - } - ] - }, - { - "accumulatedStake": 0.28423087118968404, - "relativeStake": 0.003312607767833522, + "accumulatedStake": 0.30926593196539365, + "relativeStake": 0.0033182758007199685, "relays": [ { - "address": "gateway.adavault.com", - "port": 4021 - }, - { - "address": "gateway.adavault.com", - "port": 4022 + "address": "relay.de.fikapool.com", + "port": 6000 }, { - "address": "gateway.adavault.com", - "port": 4026 + "address": "relay.sg.fikapool.com", + "port": 6000 }, { - "address": "gateway.adavault.com", - "port": 4027 + "address": "relay.ca.fikapool.com", + "port": 6000 } ] }, { - "accumulatedStake": 0.28753528708249987, - "relativeStake": 0.003304415892815847, + "accumulatedStake": 0.31256131701934486, + "relativeStake": 0.0032953850539512103, "relays": [ { - "address": "relays.wavepool.digital", - "port": 3001 + "address": "53e378bf.cardano-relay.bison.run", + "port": 1338 } ] }, { - "accumulatedStake": 0.29083948690874545, - "relativeStake": 0.0033041998262455653, + "accumulatedStake": 0.31584842327246576, + "relativeStake": 0.003287106253120903, "relays": [ { - "address": "relays.stakepool.at", - "port": 3001 + "address": "95.154.235.142", + "port": 6000 }, { - "address": "relay-1.stakepool.at", - "port": 3001 + "address": "217.155.18.115", + "port": 6003 }, { - "address": "relay-2.stakepool.at", - "port": 3001 + "address": "217.155.18.115", + "port": 6001 } ] }, { - "accumulatedStake": 0.2941350010071504, - "relativeStake": 0.003295514098404966, + "accumulatedStake": 0.31911673912113037, + "relativeStake": 0.0032683158486645574, "relays": [ { - "address": "142.235.154.95", - "port": 6000 + "address": "cardano-main.everstake.com", + "port": 3001 }, { - "address": "115.18.155.217", - "port": 6003 + "address": "cardano-main2.everstake.com", + "port": 3001 }, { - "address": "115.18.155.217", - "port": 6001 - } - ] - }, - { - "accumulatedStake": 0.2974277496632033, - "relativeStake": 0.0032927486560528738, - "relays": [ + "address": "cardano-relay.everstake.com", + "port": 3001 + }, { - "address": "r-eu-1.polypool.io", - "port": 4001 + "address": "cardano-relay1.everstake.com", + "port": 3001 }, { - "address": "r-sg-1.polypool.io", - "port": 4001 + "address": "cardano-relay2.everstake.com", + "port": 3001 + }, + { + "address": "cardano-relay3.everstake.com", + "port": 3001 } ] }, { - "accumulatedStake": 0.3006885099381554, - "relativeStake": 0.0032607602749520626, + "accumulatedStake": 0.3223388811486656, + "relativeStake": 0.003222142027535244, "relays": [ { - "address": "relay-kiln-6-0.cardano.mainnet.kiln.fi", + "address": "157.173.120.233", "port": 3001 }, { - "address": "relay-kiln-6-1.cardano.mainnet.kiln.fi", - "port": 3001 + "address": "157.173.120.233", + "port": 3002 }, { - "address": "relay-kiln-6-2.cardano.mainnet.kiln.fi", + "address": "5.252.53.68", "port": 3001 } ] }, { - "accumulatedStake": 0.30392704680109744, - "relativeStake": 0.003238536862942106, + "accumulatedStake": 0.32555680131264036, + "relativeStake": 0.0032179201639747513, "relays": [ { - "address": "relay1.cardanotech.io", - "port": 6000 + "address": "gateway.adavault.com", + "port": 4021 }, { - "address": "relay2.cardanotech.io", - "port": 6000 + "address": "gateway.adavault.com", + "port": 4022 + }, + { + "address": "gateway.adavault.com", + "port": 4026 + }, + { + "address": "gateway.adavault.com", + "port": 4027 + }, + { + "address": "gateway2.adavault.com", + "port": 4060 + }, + { + "address": "gateway2.adavault.com", + "port": 4061 } ] }, { - "accumulatedStake": 0.30715737985222247, - "relativeStake": 0.003230333051124986, + "accumulatedStake": 0.32875398090594826, + "relativeStake": 0.003197179593307914, "relays": [ { - "address": "eu.relays.cardanians.io", - "port": 1000 + "address": "relays.stakepool.at", + "port": 3001 }, { - "address": "ca.relays.cardanians.io", - "port": 1000 + "address": "relay-1.stakepool.at", + "port": 3001 + }, + { + "address": "relay-2.stakepool.at", + "port": 3001 } ] }, { - "accumulatedStake": 0.3103492603803173, - "relativeStake": 0.0031918805280948636, + "accumulatedStake": 0.33194851319980617, + "relativeStake": 0.0031945322938579167, "relays": [ { "address": "f9395b98.cardano-relay.herd.run", @@ -1129,142 +1208,200 @@ ] }, { - "accumulatedStake": 0.31353699782893685, - "relativeStake": 0.0031877374486195416, + "accumulatedStake": 0.33514162350163146, + "relativeStake": 0.003193110301825292, "relays": [ { - "address": "Relay1.NordicPool.org", - "port": 3005 + "address": "r-eu-0.titanstaking.io", + "port": 4321 }, { - "address": "Relay2.NordicPool.org", - "port": 3005 + "address": "r-eu-1.titanstaking.io", + "port": 4321 }, { - "address": "Relay3.NordicPool.org", - "port": 3005 + "address": "r-eu-2.titanstaking.io", + "port": 4321 } ] }, { - "accumulatedStake": 0.31671240508614645, - "relativeStake": 0.00317540725720958, + "accumulatedStake": 0.3383217031672839, + "relativeStake": 0.0031800796656524235, "relays": [ { - "address": "Relay1.NordicPool.org", - "port": 3005 + "address": "relay-kiln-7-0.cardano.mainnet.kiln.fi", + "port": 3001 }, { - "address": "Relay2.NordicPool.org", - "port": 3005 + "address": "relay-kiln-7-1.cardano.mainnet.kiln.fi", + "port": 3001 }, { - "address": "Relay3.NordicPool.org", - "port": 3005 + "address": "relay-kiln-7-2.cardano.mainnet.kiln.fi", + "port": 3001 } ] }, { - "accumulatedStake": 0.31986578276081135, - "relativeStake": 0.0031533776746648944, + "accumulatedStake": 0.3415009698511818, + "relativeStake": 0.003179266683897904, "relays": [ { - "address": "relay.cardano.securestaking.io", - "port": 3000 + "address": "relay-kiln-0-0.cardano.mainnet.kiln.fi", + "port": 3001 }, { - "address": "secur2.cardano.securestaking.io", - "port": 3000 - } + "address": "relay-kiln-0-1.cardano.mainnet.kiln.fi", + "port": 3001 + }, + { + "address": "relay-kiln-0-2.cardano.mainnet.kiln.fi", + "port": 3001 + } ] }, { - "accumulatedStake": 0.323004437417142, - "relativeStake": 0.0031386546563306954, + "accumulatedStake": 0.3446481667567213, + "relativeStake": 0.0031471969055394703, "relays": [ { - "address": "cof-1.cardanocafe.org", - "port": 3005 + "address": "cardano-main.everstake.com", + "port": 3001 }, { - "address": "cof-2.cardanocafe.org", - "port": 3010 + "address": "cardano-main2.everstake.com", + "port": 3001 }, { - "address": "cap-1.cardanocafe.org", - "port": 4000 + "address": "cardano-relay.everstake.com", + "port": 3001 }, { - "address": "cap-2.cardanocafe.org", - "port": 4005 + "address": "cardano-relay1.everstake.com", + "port": 3001 }, { - "address": "lat-1.cardanocafe.org", - "port": 5001 + "address": "cardano-relay2.everstake.com", + "port": 3001 }, { - "address": "lat-2.cardanocafe.org", - "port": 5002 + "address": "cardano-relay3.everstake.com", + "port": 3001 } ] }, { - "accumulatedStake": 0.32614159867078624, - "relativeStake": 0.003137161253644213, + "accumulatedStake": 0.3477830195923553, + "relativeStake": 0.0031348528356340156, "relays": [ { - "address": "relay-kiln-7-0.cardano.mainnet.kiln.fi", - "port": 3001 + "address": "77cb3f75.cardano-relay.herd.run", + "port": 1338 + } + ] + }, + { + "accumulatedStake": 0.35091109625538885, + "relativeStake": 0.0031280766630335565, + "relays": [ + { + "address": "gateway.adavault.com", + "port": 4021 }, { - "address": "relay-kiln-7-1.cardano.mainnet.kiln.fi", - "port": 3001 + "address": "gateway.adavault.com", + "port": 4022 }, { - "address": "relay-kiln-7-2.cardano.mainnet.kiln.fi", + "address": "gateway.adavault.com", + "port": 4026 + }, + { + "address": "gateway.adavault.com", + "port": 4027 + }, + { + "address": "gateway2.adavault.com", + "port": 4060 + }, + { + "address": "gateway2.adavault.com", + "port": 4061 + } + ] + }, + { + "accumulatedStake": 0.35401885348202194, + "relativeStake": 0.003107757226633093, + "relays": [ + { + "address": "110.cardano.staked.cloud", "port": 3001 } ] }, { - "accumulatedStake": 0.3292722366692076, - "relativeStake": 0.003130637998421326, + "accumulatedStake": 0.35708310189519316, + "relativeStake": 0.0030642484131712415, "relays": [ { - "address": "r-eu-0.titanstaking.io", - "port": 4321 + "address": "cof-1.cardanocafe.org", + "port": 3005 }, { - "address": "r-eu-1.titanstaking.io", - "port": 4321 + "address": "cof-2.cardanocafe.org", + "port": 3010 }, { - "address": "r-eu-2.titanstaking.io", - "port": 4321 + "address": "cap-1.cardanocafe.org", + "port": 4000 + }, + { + "address": "cap-2.cardanocafe.org", + "port": 4005 + }, + { + "address": "lat-1.cardanocafe.org", + "port": 5001 + }, + { + "address": "lat-2.cardanocafe.org", + "port": 5002 } ] }, { - "accumulatedStake": 0.3323683170392178, - "relativeStake": 0.0030960803700102284, + "accumulatedStake": 0.36014143685343836, + "relativeStake": 0.0030583349582452126, "relays": [ { - "address": "105.91.220.31", + "address": "91.242.214.33", "port": 3001 }, { - "address": "189.158.26.154", + "address": "186.233.187.33", "port": 3001 + } + ] + }, + { + "accumulatedStake": 0.3631863119041928, + "relativeStake": 0.003044875050754456, + "relays": [ + { + "address": "rev-cardano-main-relay-01-a.bdnodes.net", + "port": 6000 }, { - "address": "174.83.104.5", - "port": 3001 + "address": "rev-cardano-main-relay-01-b.bdnodes.net", + "port": 6000 } ] }, { - "accumulatedStake": 0.3354356623043562, - "relativeStake": 0.0030673452651383917, + "accumulatedStake": 0.3662262064739854, + "relativeStake": 0.0030398945697925834, "relays": [ { "address": "r1.1percentpool.eu", @@ -1277,203 +1414,218 @@ ] }, { - "accumulatedStake": 0.33850158472450437, - "relativeStake": 0.0030659224201481997, + "accumulatedStake": 0.3692612300378267, + "relativeStake": 0.003035023563841242, "relays": [ { - "address": "relays.wavepool.digital", - "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.3415553876719289, - "relativeStake": 0.003053802947424508, - "relays": [ + "address": "Relay1.NordicPool.org", + "port": 3005 + }, { - "address": "relay-pool-figment-8-mainnet.cardano.aeq5f.com" + "address": "Relay2.NordicPool.org", + "port": 3005 + }, + { + "address": "Relay3.NordicPool.org", + "port": 3005 } ] }, { - "accumulatedStake": 0.34460445024769326, - "relativeStake": 0.0030490625757643836, + "accumulatedStake": 0.37229119256078874, + "relativeStake": 0.0030299625229620705, "relays": [ { - "address": "233.120.173.157", - "port": 3001 + "address": "Relay1.NordicPool.org", + "port": 3005 }, { - "address": "233.120.173.157", - "port": 3002 + "address": "Relay2.NordicPool.org", + "port": 3005 }, { - "address": "68.53.252.5", - "port": 3001 + "address": "Relay3.NordicPool.org", + "port": 3005 } ] }, { - "accumulatedStake": 0.34765338046550237, - "relativeStake": 0.003048930217809118, + "accumulatedStake": 0.3753191985671891, + "relativeStake": 0.003028006006400369, "relays": [ { - "address": "77cb3f75.cardano-relay.herd.run", - "port": 1338 + "address": "relay.cardano.securestaking.io", + "port": 3000 + }, + { + "address": "secur2.cardano.securestaking.io", + "port": 3000 } ] }, { - "accumulatedStake": 0.3506935036030231, - "relativeStake": 0.003040123137520715, + "accumulatedStake": 0.37834083915163474, + "relativeStake": 0.0030216405844456255, "relays": [ { - "address": "cardano-relays.autostake.com", - "port": 3001 + "address": "bd-cardano-main-relay-2-a.bdnodes.net", + "port": 6000 } ] }, { - "accumulatedStake": 0.353729976215865, - "relativeStake": 0.003036472612841861, + "accumulatedStake": 0.3813479018057491, + "relativeStake": 0.0030070626541144063, "relays": [ { - "address": "33.214.242.91", + "address": "relays.stakepool.at", + "port": 3001 + }, + { + "address": "relay-1.stakepool.at", "port": 3001 }, { - "address": "33.187.233.186", + "address": "relay-2.stakepool.at", "port": 3001 } ] }, { - "accumulatedStake": 0.3567493658532314, - "relativeStake": 0.0030193896373664347, + "accumulatedStake": 0.38435337653599955, + "relativeStake": 0.0030054747302503924, "relays": [ { - "address": "63.87.37.54", - "port": 6000 + "address": "eu.relays.cardanians.io", + "port": 1000 }, { - "address": "85.178.36.54", - "port": 6000 + "address": "ca.relays.cardanians.io", + "port": 1000 } ] }, { - "accumulatedStake": 0.35975247463433885, - "relativeStake": 0.00300310878110743, + "accumulatedStake": 0.38735023648656974, + "relativeStake": 0.0029968599505702394, "relays": [ { - "address": "relay-pool-ledger-1-mainnet.cardano.aeq5f.com" + "address": "fr.relays.cardanians.io", + "port": 1000 + }, + { + "address": "ca.relays.cardanians.io", + "port": 1000 } ] }, { - "accumulatedStake": 0.36275494522537727, - "relativeStake": 0.0030024705910384093, + "accumulatedStake": 0.39029802059829166, + "relativeStake": 0.0029477841117218793, "relays": [ { - "address": "relay-pool-ledger-3-mainnet.cardano.aeq5f.com" + "address": "6398a55d.cardano-relay.herd.run", + "port": 1338 } ] }, { - "accumulatedStake": 0.36575208344045335, - "relativeStake": 0.0029971382150760814, + "accumulatedStake": 0.39322611502591936, + "relativeStake": 0.0029280944276277054, "relays": [ { - "address": "rev-cardano-main-relay-01-a.bdnodes.net", - "port": 6000 + "address": "norway.adanorthpool.com", + "port": 9011 }, { - "address": "rev-cardano-main-relay-01-b.bdnodes.net", - "port": 6000 + "address": "norway.adanorthpool.com", + "port": 9012 + }, + { + "address": "norway.adanorthpool.com", + "port": 9014 + }, + { + "address": "norway2.adanorthpool.com", + "port": 9014 + }, + { + "address": "norway2.adanorthpool.com", + "port": 9013 } ] }, { - "accumulatedStake": 0.3687395066584281, - "relativeStake": 0.002987423217974743, + "accumulatedStake": 0.3961431950283147, + "relativeStake": 0.0029170800023953377, "relays": [ { - "address": "fr.relays.cardanians.io", - "port": 1000 + "address": "178.156.128.18", + "port": 6001 }, { - "address": "ca.relays.cardanians.io", - "port": 1000 + "address": "65.21.7.149", + "port": 6001 } ] }, { - "accumulatedStake": 0.37172000145824946, - "relativeStake": 0.002980494799821401, + "accumulatedStake": 0.3990569819666123, + "relativeStake": 0.002913786938297617, "relays": [ { - "address": "Relay1.NordicPool.org", - "port": 3005 - }, - { - "address": "Relay2.NordicPool.org", - "port": 3005 + "address": "d95s1f1ak3bc73bjovog.bdnodes.net", + "port": 6000 }, { - "address": "Relay3.NordicPool.org", - "port": 3005 + "address": "d95s1e4alf0c73agtflg.bdnodes.net", + "port": 6000 } ] }, { - "accumulatedStake": 0.37469240600239845, - "relativeStake": 0.002972404544148982, + "accumulatedStake": 0.40196154518785593, + "relativeStake": 0.002904563221243636, "relays": [ { - "address": "cardano-main.everstake.one", - "port": 3001 - }, - { - "address": "cardano-main2.everstake.one", + "address": "relay01.ca.lovelace.community", "port": 3001 }, { - "address": "cardano-relay.everstake.one", + "address": "relay02.ca.lovelace.community", "port": 3001 }, { - "address": "cardano-relay1.everstake.one", + "address": "relay01.fr.lovelace.community", "port": 3001 }, { - "address": "cardano-relay2.everstake.one", + "address": "relay01.de.lovelace.community", "port": 3001 } ] }, { - "accumulatedStake": 0.37763212255170936, - "relativeStake": 0.0029397165493109012, + "accumulatedStake": 0.4048565993629928, + "relativeStake": 0.002895054175136825, "relays": [ { - "address": "bd-cardano-main-relay-2-a.bdnodes.net", - "port": 6000 - } - ] - }, - { - "accumulatedStake": 0.3805549500855349, - "relativeStake": 0.0029228275338255365, - "relays": [ + "address": "Relay1.NordicPool.org", + "port": 3005 + }, { - "address": "6398a55d.cardano-relay.herd.run", - "port": 1338 + "address": "Relay2.NordicPool.org", + "port": 3005 + }, + { + "address": "Relay3.NordicPool.org", + "port": 3005 } ] }, { - "accumulatedStake": 0.38343647535941855, - "relativeStake": 0.0028815252738836634, + "accumulatedStake": 0.4077408300382135, + "relativeStake": 0.002884230675220699, "relays": [ { "address": "170.23.181.50", @@ -1490,36 +1642,44 @@ ] }, { - "accumulatedStake": 0.3862980690295382, - "relativeStake": 0.002861593670119681, + "accumulatedStake": 0.4106193375288086, + "relativeStake": 0.0028785074905951155, "relays": [ { - "address": "rockyrelay1.ddns.net", + "address": "139.59.200.123", "port": 3001 }, { - "address": "rockyrelay2.ddns.net", - "port": 3002 + "address": "129.212.154.208", + "port": 3001 + }, + { + "address": "129.212.214.149", + "port": 3001 } ] }, { - "accumulatedStake": 0.3891541666933272, - "relativeStake": 0.00285609766378897, + "accumulatedStake": 0.4134870320656869, + "relativeStake": 0.002867694536878287, "relays": [ { - "address": "relay1.clovernodes.io", - "port": 6000 + "address": "Relay1.NordicPool.org", + "port": 3005 }, { - "address": "relay2.clovernodes.io", - "port": 6000 + "address": "Relay2.NordicPool.org", + "port": 3005 + }, + { + "address": "Relay3.NordicPool.org", + "port": 3005 } ] }, { - "accumulatedStake": 0.3920092537719859, - "relativeStake": 0.002855087078658718, + "accumulatedStake": 0.4163540883411624, + "relativeStake": 0.0028670562754755163, "relays": [ { "address": "relays.wavepool.digital", @@ -1528,76 +1688,100 @@ ] }, { - "accumulatedStake": 0.3948634489715873, - "relativeStake": 0.0028541951996013753, + "accumulatedStake": 0.4192145623190529, + "relativeStake": 0.002860473977890499, "relays": [ { - "address": "relays.stakepool.at", + "address": "86.80.128.65", "port": 3001 }, { - "address": "relay-1.stakepool.at", - "port": 3001 + "address": "86.80.128.65", + "port": 3002 }, { - "address": "relay-2.stakepool.at", + "address": "86.80.128.65", + "port": 3003 + } + ] + }, + { + "accumulatedStake": 0.422075014063197, + "relativeStake": 0.0028604517441441065, + "relays": [ + { + "address": "101.cardano.staked.cloud", "port": 3001 } ] }, { - "accumulatedStake": 0.3977167363563328, - "relativeStake": 0.0028532873847455305, + "accumulatedStake": 0.42493303297101404, + "relativeStake": 0.0028580189078170333, "relays": [ { - "address": "185.24.129.57", + "address": "188.165.236.202", "port": 3001 }, { - "address": "178.28.129.57", + "address": "195.201.107.114", "port": 3001 } ] }, { - "accumulatedStake": 0.4005687755644095, - "relativeStake": 0.0028520392080766534, + "accumulatedStake": 0.42778806990500945, + "relativeStake": 0.0028550369339954097, "relays": [ { - "address": "103.229.61.20", + "address": "20.61.229.103", "port": 3001 }, { - "address": "218.228.61.20", + "address": "20.61.228.218", "port": 3001 }, { - "address": "221.42.142.108", + "address": "108.142.42.221", "port": 3001 }, { - "address": "161.42.142.108", + "address": "108.142.42.161", "port": 3001 } ] }, { - "accumulatedStake": 0.403410302552123, - "relativeStake": 0.0028415269877135165, + "accumulatedStake": 0.43063976580257246, + "relativeStake": 0.0028516958975630196, "relays": [ { - "address": "18.128.156.178", - "port": 6001 + "address": "st3ak.1337.cx", + "port": 6000 }, { - "address": "149.7.21.65", - "port": 6001 + "address": "st3ak.mooo.com", + "port": 6000 + }, + { + "address": "st3ak.root.sx", + "port": 6000 + } + ] + }, + { + "accumulatedStake": 0.43347259002368455, + "relativeStake": 0.0028328242211121215, + "relays": [ + { + "address": "relays.wavepool.digital", + "port": 3001 } ] }, { - "accumulatedStake": 0.4062275780948029, - "relativeStake": 0.0028172755426799107, + "accumulatedStake": 0.43630169346112985, + "relativeStake": 0.0028291034374452713, "relays": [ { "address": "76cf1dd1.cardano-relay.bison.run", @@ -1606,254 +1790,202 @@ ] }, { - "accumulatedStake": 0.4090382757161769, - "relativeStake": 0.002810697621373978, + "accumulatedStake": 0.43912262903285587, + "relativeStake": 0.0028209355717260165, "relays": [ { - "address": "cardano-main.everstake.one", - "port": 3001 - }, - { - "address": "cardano-main2.everstake.one", - "port": 3001 - }, - { - "address": "cardano-relay.everstake.one", - "port": 3001 - }, - { - "address": "cardano-relay1.everstake.one", - "port": 3001 - }, - { - "address": "cardano-relay2.everstake.one", - "port": 3001 + "address": "e646e266.cardano-relay.bison.run", + "port": 1338 } ] }, { - "accumulatedStake": 0.4118427674781431, - "relativeStake": 0.002804491761966212, + "accumulatedStake": 0.4419429277855328, + "relativeStake": 0.002820298752676927, "relays": [ { - "address": "a0e18895.cardano-relay.bison.run", + "address": "c61ace08.cardano-relay.herd.run", "port": 1338 } ] }, { - "accumulatedStake": 0.41464655594429967, - "relativeStake": 0.0028037884661565498, + "accumulatedStake": 0.44475830961741913, + "relativeStake": 0.002815381831886331, "relays": [ { - "address": "relays.wavepool.digital", - "port": 3001 + "address": "a0e18895.cardano-relay.bison.run", + "port": 1338 } ] }, { - "accumulatedStake": 0.41743786945782435, - "relativeStake": 0.002791313513524713, + "accumulatedStake": 0.4475538987225074, + "relativeStake": 0.0027955891050882816, "relays": [ { - "address": "cardano-main.everstake.one", - "port": 3001 - }, - { - "address": "cardano-main2.everstake.one", - "port": 3001 - }, - { - "address": "cardano-relay.everstake.one", + "address": "lucerne.datadyne.earth", "port": 3001 }, { - "address": "cardano-relay1.everstake.one", - "port": 3001 + "address": "g5.datadyne.earth", + "port": 3002 }, { - "address": "cardano-relay2.everstake.one", - "port": 3001 + "address": "drcaroll.datadyne.earth", + "port": 3003 } ] }, { - "accumulatedStake": 0.4202250086732971, - "relativeStake": 0.0027871392154727244, + "accumulatedStake": 0.45033787985085916, + "relativeStake": 0.0027839811283517763, "relays": [ { - "address": "Relay1.NordicPool.org", - "port": 3005 - }, - { - "address": "Relay2.NordicPool.org", - "port": 3005 + "address": "relay1.ppcx2.mainnet.cardano.p2p.org", + "port": 6001 }, { - "address": "Relay3.NordicPool.org", - "port": 3005 + "address": "relay2.ppcx2.mainnet.cardano.p2p.org", + "port": 6001 } ] }, { - "accumulatedStake": 0.423004076762356, - "relativeStake": 0.0027790680890589304, + "accumulatedStake": 0.4530991253782823, + "relativeStake": 0.0027612455274230925, "relays": [ { - "address": "23.17.113.148", + "address": "148.113.17.23", "port": 6000 }, { - "address": "103.25.69.158", + "address": "158.69.25.103", "port": 6000 }, { - "address": "238.53.4.46", + "address": "46.4.53.238", "port": 6000 }, { - "address": "164.140.102.149", + "address": "149.102.140.164", "port": 6000 } ] }, { - "accumulatedStake": 0.4257794754716553, - "relativeStake": 0.002775398709299285, + "accumulatedStake": 0.4558114110079053, + "relativeStake": 0.0027122856296229966, "relays": [ { - "address": "octaluso.dyndns.org", - "port": 3002 - } - ] - }, - { - "accumulatedStake": 0.4285307675394967, - "relativeStake": 0.0027512920678414246, - "relays": [ + "address": "20.61.229.103", + "port": 3001 + }, { - "address": "relays.digi.pro", + "address": "20.61.228.218", + "port": 3001 + }, + { + "address": "108.142.42.221", + "port": 3001 + }, + { + "address": "108.142.42.161", "port": 3001 } ] }, { - "accumulatedStake": 0.43127773441681333, - "relativeStake": 0.002746966877316626, + "accumulatedStake": 0.45852259709024595, + "relativeStake": 0.0027111860823407063, "relays": [ { - "address": "relays.cardanowithpaul.com", - "port": 1069 + "address": "rockyrelay1.ddns.net", + "port": 3001 + }, + { + "address": "rockyrelay2.ddns.net", + "port": 3002 } ] }, { - "accumulatedStake": 0.43401401795403494, - "relativeStake": 0.0027362835372215983, + "accumulatedStake": 0.46123273998145836, + "relativeStake": 0.0027101428912123674, "relays": [ { - "address": "d95s1f1ak3bc73bjovog.bdnodes.net", - "port": 6000 + "address": "relay1.str8pool.com", + "port": 7421 }, { - "address": "d95s1e4alf0c73agtflg.bdnodes.net", - "port": 6000 + "address": "relay2.str8pool.com", + "port": 3611 } ] }, { - "accumulatedStake": 0.43674738799706736, - "relativeStake": 0.0027333700430323907, + "accumulatedStake": 0.463924357969422, + "relativeStake": 0.0026916179879636418, "relays": [ { - "address": "53e378bf.cardano-relay.bison.run", - "port": 1338 + "address": "cork.queenada.com", + "port": 7500 } ] }, { - "accumulatedStake": 0.4394568257864981, - "relativeStake": 0.002709437789430746, + "accumulatedStake": 0.46661260423816403, + "relativeStake": 0.0026882462687420543, "relays": [ { - "address": "103.229.61.20", - "port": 3001 - }, - { - "address": "218.228.61.20", - "port": 3001 - }, - { - "address": "221.42.142.108", - "port": 3001 - }, - { - "address": "161.42.142.108", - "port": 3001 + "address": "relays.cardanowithpaul.com", + "port": 1069 } ] }, { - "accumulatedStake": 0.44211477349891903, - "relativeStake": 0.00265794771242095, + "accumulatedStake": 0.46928177862895776, + "relativeStake": 0.0026691743907937254, "relays": [ { - "address": "norway.adanorthpool.com", - "port": 9011 - }, - { - "address": "norway.adanorthpool.com", - "port": 9012 + "address": "cardano-main.everstake.com", + "port": 3001 }, { - "address": "norway.adanorthpool.com", - "port": 9014 + "address": "cardano-main2.everstake.com", + "port": 3001 }, { - "address": "norway2.adanorthpool.com", - "port": 9014 + "address": "cardano-relay.everstake.com", + "port": 3001 }, { - "address": "norway2.adanorthpool.com", - "port": 9013 - } - ] - }, - { - "accumulatedStake": 0.4447710321270004, - "relativeStake": 0.002656258628081374, - "relays": [ - { - "address": "11.relays.happystaking.io", + "address": "cardano-relay1.everstake.com", "port": 3001 }, { - "address": "12.relays.happystaking.io", + "address": "cardano-relay2.everstake.com", "port": 3001 } ] }, { - "accumulatedStake": 0.44740595707611036, - "relativeStake": 0.0026349249491099637, + "accumulatedStake": 0.47194697021849075, + "relativeStake": 0.0026651915895330148, "relays": [ { - "address": "rel01.fairpool.eu", - "port": 55001 - }, - { - "address": "rel02.fairpool.eu", - "port": 55002 + "address": "relay1.clovernodes.io", + "port": 6000 }, { - "address": "rel03.fairpool.eu", - "port": 55003 + "address": "relay2.clovernodes.io", + "port": 6000 } ] }, { - "accumulatedStake": 0.4500345873357131, - "relativeStake": 0.002628630259602752, + "accumulatedStake": 0.4745710568685571, + "relativeStake": 0.0026240866500663353, "relays": [ { "address": "relay.anonaf.com", @@ -1862,280 +1994,220 @@ ] }, { - "accumulatedStake": 0.4526606957091051, - "relativeStake": 0.0026261083733919734, - "relays": [ - { - "address": "relay2.snakepool.link", - "port": 3002 - } - ] - }, - { - "accumulatedStake": 0.4552851773596565, - "relativeStake": 0.002624481650551397, + "accumulatedStake": 0.47718817128126084, + "relativeStake": 0.0026171144127037343, "relays": [ { - "address": "r-eu-0.titanstaking.io", - "port": 4321 - }, - { - "address": "r-eu-1.titanstaking.io", - "port": 4321 - }, - { - "address": "r-eu-2.titanstaking.io", - "port": 4321 + "address": "35.75.32.253", + "port": 6001 } ] }, { - "accumulatedStake": 0.45788192084935087, - "relativeStake": 0.002596743489694367, + "accumulatedStake": 0.47978764416024317, + "relativeStake": 0.0025994728789823455, "relays": [ { - "address": "103.229.61.20", + "address": "20.61.229.103", "port": 3001 }, { - "address": "218.228.61.20", + "address": "20.61.228.218", "port": 3001 }, { - "address": "221.42.142.108", + "address": "108.142.42.221", "port": 3001 }, { - "address": "161.42.142.108", + "address": "108.142.42.161", "port": 3001 } ] }, { - "accumulatedStake": 0.46047299992753665, - "relativeStake": 0.0025910790781857604, + "accumulatedStake": 0.482377209547169, + "relativeStake": 0.0025895653869258315, "relays": [ { - "address": "lucerne.datadyne.earth", - "port": 3001 - }, - { - "address": "g5.datadyne.earth", - "port": 3002 + "address": "Relay1.NordicPool.org", + "port": 3005 }, { - "address": "drcaroll.datadyne.earth", - "port": 3003 - } - ] - }, - { - "accumulatedStake": 0.4630636978686284, - "relativeStake": 0.0025906979410917717, - "relays": [ - { - "address": "relay1.str8pool.com", - "port": 7421 + "address": "Relay2.NordicPool.org", + "port": 3005 }, { - "address": "relay2.str8pool.com", - "port": 3611 + "address": "Relay3.NordicPool.org", + "port": 3005 } ] }, { - "accumulatedStake": 0.4656534964863589, - "relativeStake": 0.002589798617730518, + "accumulatedStake": 0.48495806256336005, + "relativeStake": 0.0025808530161910287, "relays": [ { - "address": "202.236.165.188", - "port": 3001 - }, - { - "address": "114.107.201.195", - "port": 3001 + "address": "octaluso.dyndns.org", + "port": 3002 } ] }, { - "accumulatedStake": 0.4682174780347772, - "relativeStake": 0.0025639815484182825, + "accumulatedStake": 0.4875344969123622, + "relativeStake": 0.0025764343490021703, "relays": [ { - "address": "cork.queenada.com", - "port": 7500 + "address": "1339aecb.cardano-relay.herd.run", + "port": 1338 } ] }, { - "accumulatedStake": 0.47077109057110417, - "relativeStake": 0.0025536125363269657, + "accumulatedStake": 0.4901011429552267, + "relativeStake": 0.0025666460428645063, "relays": [ { - "address": "relay.cardano.securestaking.io", - "port": 3000 + "address": "rel01.fairpool.eu", + "port": 55001 }, { - "address": "secur2.cardano.securestaking.io", - "port": 3000 - } - ] - }, - { - "accumulatedStake": 0.47330602076843636, - "relativeStake": 0.002534930197332188, - "relays": [ - { - "address": "94c3c6d3.cardano-relay.herd.run", - "port": 1338 - } - ] - }, - { - "accumulatedStake": 0.4758318114737277, - "relativeStake": 0.002525790705291376, - "relays": [ + "address": "rel02.fairpool.eu", + "port": 55002 + }, { - "address": "c61ace08.cardano-relay.herd.run", - "port": 1338 + "address": "rel03.fairpool.eu", + "port": 55003 } ] }, { - "accumulatedStake": 0.47833467578918243, - "relativeStake": 0.0025028643154547197, + "accumulatedStake": 0.49266675978441626, + "relativeStake": 0.0025656168291895297, "relays": [ { - "address": "33.184.128.57", - "port": 3001 + "address": "rho.relay.easy1staking.com", + "port": 30020 }, { - "address": "31.184.128.57", - "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.4808313021792356, - "relativeStake": 0.0024966263900531543, - "relays": [ - { - "address": "relays.bladepool.com", - "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.48330945841631007, - "relativeStake": 0.002478156237074452, - "relays": [ + "address": "pi.relay.easy1staking.com", + "port": 30021 + }, { - "address": "relaynode1.bravostakepool.nl", - "port": 3001 + "address": "eu-central-1.relay.easy1staking.com", + "port": 30000 }, { - "address": "relaynode2.bravostakepool.nl", - "port": 3001 + "address": "us-east-1.relay.easy1staking.com", + "port": 30000 }, { - "address": "relaynode3.bravostakepool.nl", - "port": 3001 + "address": "eu-west-1.relay.easy1staking.com", + "port": 30000 } ] }, { - "accumulatedStake": 0.4857873170357562, - "relativeStake": 0.0024778586194461457, + "accumulatedStake": 0.4952238389423434, + "relativeStake": 0.002557079157927141, "relays": [ { - "address": "r1.1percentpool.eu", - "port": 19001 - }, - { - "address": "r2.1percentpool.eu", - "port": 19002 + "address": "relays.digi.pro", + "port": 3001 } ] }, { - "accumulatedStake": 0.4882609656674006, - "relativeStake": 0.0024736486316444405, + "accumulatedStake": 0.49774690701487023, + "relativeStake": 0.002523068072526852, "relays": [ { - "address": "cardano-main.everstake.one", + "address": "cardano-main.everstake.com", "port": 3001 }, { - "address": "cardano-main2.everstake.one", + "address": "cardano-main2.everstake.com", "port": 3001 }, { - "address": "cardano-relay.everstake.one", + "address": "cardano-relay.everstake.com", "port": 3001 }, { - "address": "cardano-relay1.everstake.one", + "address": "cardano-relay1.everstake.com", "port": 3001 }, { - "address": "cardano-relay2.everstake.one", + "address": "cardano-relay2.everstake.com", "port": 3001 } ] }, { - "accumulatedStake": 0.49071977560698077, - "relativeStake": 0.0024588099395801135, + "accumulatedStake": 0.5002522726638451, + "relativeStake": 0.002505365648974889, "relays": [ { - "address": "st3ak.1337.cx", + "address": "169.58.185.200", "port": 6000 }, { - "address": "st3ak.mooo.com", + "address": "169.58.186.9", "port": 6000 }, { - "address": "st3ak.root.sx", + "address": "169.58.186.24", "port": 6000 } ] }, { - "accumulatedStake": 0.49317697072457223, - "relativeStake": 0.002457195117591497, + "accumulatedStake": 0.5027551538887999, + "relativeStake": 0.0025028812249547755, "relays": [ { - "address": "110.cardano.staked.cloud", - "port": 3001 + "address": "r-eu-0.titanstaking.io", + "port": 4321 + }, + { + "address": "r-eu-1.titanstaking.io", + "port": 4321 + }, + { + "address": "r-eu-2.titanstaking.io", + "port": 4321 } ] }, { - "accumulatedStake": 0.495630309300874, - "relativeStake": 0.0024533385763017505, + "accumulatedStake": 0.5052072297927471, + "relativeStake": 0.0024520759039472063, "relays": [ { - "address": "relay1.nedscave.io", + "address": "cardano-main.everstake.com", "port": 3001 }, { - "address": "relay2.nedscave.io", + "address": "cardano-main2.everstake.com", "port": 3001 }, { - "address": "relay3.nedscave.io", + "address": "cardano-relay.everstake.com", "port": 3001 }, { - "address": "relay4.nedscave.io", + "address": "cardano-relay1.everstake.com", + "port": 3001 + }, + { + "address": "cardano-relay2.everstake.com", "port": 3001 } ] }, { - "accumulatedStake": 0.49807756968336253, - "relativeStake": 0.002447260382488523, + "accumulatedStake": 0.5076459140136994, + "relativeStake": 0.002438684220952295, "relays": [ { "address": "relays.onyxstakepool.com", @@ -2144,82 +2216,93 @@ ] }, { - "accumulatedStake": 0.5005195582044285, - "relativeStake": 0.0024419885210659616, + "accumulatedStake": 0.510070233700938, + "relativeStake": 0.0024243196872385238, "relays": [ { - "address": "65.128.80.86", - "port": 3001 - }, + "address": "relay-pool-figment-6-mainnet.cardano.aeq5f.com" + } + ] + }, + { + "accumulatedStake": 0.5124921140822818, + "relativeStake": 0.0024218803813438015, + "relays": [ { - "address": "65.128.80.86", - "port": 3002 + "address": "152.53.21.151", + "port": 6000 }, { - "address": "65.128.80.86", - "port": 3003 + "address": "149.102.152.63", + "port": 6000 } ] }, { - "accumulatedStake": 0.5029589950427319, - "relativeStake": 0.0024394368383034498, + "accumulatedStake": 0.5148986966900798, + "relativeStake": 0.0024065826077981226, "relays": [ { - "address": "cardano-main.everstake.one", + "address": "cardano-main.everstake.com", "port": 3001 }, { - "address": "cardano-main2.everstake.one", + "address": "cardano-main2.everstake.com", "port": 3001 }, { - "address": "cardano-relay.everstake.one", + "address": "cardano-relay.everstake.com", "port": 3001 }, { - "address": "cardano-relay1.everstake.one", + "address": "cardano-relay1.everstake.com", "port": 3001 }, { - "address": "cardano-relay2.everstake.one", + "address": "cardano-relay2.everstake.com", "port": 3001 } ] }, { - "accumulatedStake": 0.5053950693189452, - "relativeStake": 0.0024360742762132275, + "accumulatedStake": 0.5173009089390436, + "relativeStake": 0.0024022122489637094, "relays": [ { - "address": "ACLrelay1.cardanoland.com", - "port": 6000 + "address": "r1.1percentpool.eu", + "port": 19001 }, { - "address": "ACLrelay2.cardanoland.com", - "port": 7000 - }, + "address": "r2.1percentpool.eu", + "port": 19002 + } + ] + }, + { + "accumulatedStake": 0.5196998661306225, + "relativeStake": 0.0023989571915788706, + "relays": [ { - "address": "ACLrelay3.cardanoland.com", - "port": 8000 + "address": "ada10753.allnodes.me", + "port": 3001 }, { - "address": "ACLrelay4.cardanoland.com", - "port": 6000 + "address": "ada12179.allnodes.me", + "port": 3001 }, { - "address": "ACLrelay5.cardanoland.com", - "port": 7000 + "address": "ada20364.allnodes.me", + "port": 3001 }, { - "address": "ACLrelay6.cardanoland.com", - "port": 8000 + "address": "ada21853.allnodes.me", + "port": 3001 } ] }, { - "accumulatedStake": 0.5078200530322211, - "relativeStake": 0.0024249837132759456, + "accumulatedStake": 0.5220982867979349, + "relativeStake": 0.002398420667312513, "relays": [ { "address": "ada-relay02.biglazycat.com", @@ -2228,183 +2311,194 @@ ] }, { - "accumulatedStake": 0.5102329359870145, - "relativeStake": 0.0024128829547933927, + "accumulatedStake": 0.524485952045627, + "relativeStake": 0.0023876652476920147, "relays": [ { - "address": "relay-pool-figment-6-mainnet.cardano.aeq5f.com" + "address": "relay1.able-pool.io", + "port": 4555 + }, + { + "address": "relay2.able-pool.io", + "port": 4419 } ] }, { - "accumulatedStake": 0.5126388853458439, - "relativeStake": 0.002405949358829343, + "accumulatedStake": 0.5268654789000897, + "relativeStake": 0.002379526854462772, "relays": [ { - "address": "ada10753.allnodes.me", + "address": "20.61.229.103", "port": 3001 }, { - "address": "ada12179.allnodes.me", + "address": "20.61.228.218", "port": 3001 }, { - "address": "ada20364.allnodes.me", + "address": "108.142.42.221", "port": 3001 }, { - "address": "ada21853.allnodes.me", + "address": "108.142.42.161", "port": 3001 } ] }, { - "accumulatedStake": 0.5150412586170898, - "relativeStake": 0.0024023732712460063, + "accumulatedStake": 0.5292446926064516, + "relativeStake": 0.0023792137063618837, "relays": [ { - "address": "1339aecb.cardano-relay.herd.run", - "port": 1338 - } - ] - }, - { - "accumulatedStake": 0.5174183436302654, - "relativeStake": 0.0023770850131755437, - "relays": [ - { - "address": "103.229.61.20", + "address": "20.61.229.103", "port": 3001 }, { - "address": "218.228.61.20", + "address": "20.61.228.218", "port": 3001 }, { - "address": "221.42.142.108", + "address": "108.142.42.221", "port": 3001 }, { - "address": "161.42.142.108", + "address": "108.142.42.161", "port": 3001 } ] }, { - "accumulatedStake": 0.5197950592146209, - "relativeStake": 0.0023767155843555108, + "accumulatedStake": 0.5316238986187564, + "relativeStake": 0.002379206012304725, "relays": [ { - "address": "103.229.61.20", + "address": "20.61.229.103", "port": 3001 }, { - "address": "218.228.61.20", + "address": "20.61.228.218", "port": 3001 }, { - "address": "221.42.142.108", + "address": "108.142.42.221", "port": 3001 }, { - "address": "161.42.142.108", + "address": "108.142.42.161", "port": 3001 } ] }, { - "accumulatedStake": 0.5221717671129978, - "relativeStake": 0.0023767078983769428, + "accumulatedStake": 0.5340031028229233, + "relativeStake": 0.002379204204166974, "relays": [ { - "address": "103.229.61.20", + "address": "20.61.229.103", "port": 3001 }, { - "address": "218.228.61.20", + "address": "20.61.228.218", "port": 3001 }, { - "address": "221.42.142.108", + "address": "108.142.42.221", "port": 3001 }, { - "address": "161.42.142.108", + "address": "108.142.42.161", "port": 3001 } ] }, { - "accumulatedStake": 0.5245484736885823, - "relativeStake": 0.00237670657558436, + "accumulatedStake": 0.5363823009085212, + "relativeStake": 0.0023791980855978907, "relays": [ { - "address": "103.229.61.20", + "address": "20.61.229.103", "port": 3001 }, { - "address": "218.228.61.20", + "address": "20.61.228.218", "port": 3001 }, { - "address": "221.42.142.108", + "address": "108.142.42.221", "port": 3001 }, { - "address": "161.42.142.108", + "address": "108.142.42.161", "port": 3001 } ] }, { - "accumulatedStake": 0.5269251736685752, - "relativeStake": 0.002376699979992976, + "accumulatedStake": 0.538753424676811, + "relativeStake": 0.00237112376828981, "relays": [ { - "address": "103.229.61.20", + "address": "relay1.nedscave.io", "port": 3001 }, { - "address": "218.228.61.20", + "address": "relay2.nedscave.io", "port": 3001 }, { - "address": "221.42.142.108", + "address": "relay3.nedscave.io", "port": 3001 }, { - "address": "161.42.142.108", + "address": "relay4.nedscave.io", "port": 3001 } ] }, { - "accumulatedStake": 0.5293018705303323, - "relativeStake": 0.0023766968617571, + "accumulatedStake": 0.5410849210872811, + "relativeStake": 0.002331496410470073, "relays": [ { - "address": "253.32.75.35", - "port": 6001 + "address": "94c3c6d3.cardano-relay.herd.run", + "port": 1338 } ] }, { - "accumulatedStake": 0.5316518059649552, - "relativeStake": 0.0023499354346229358, + "accumulatedStake": 0.5433949868170332, + "relativeStake": 0.002310065729752187, "relays": [ { - "address": "52.90.217.3", - "port": 6000 + "address": "gateway.adavault.com", + "port": 4021 }, { - "address": "127.254.219.3", - "port": 6000 + "address": "gateway.adavault.com", + "port": 4022 + }, + { + "address": "gateway.adavault.com", + "port": 4026 + }, + { + "address": "gateway.adavault.com", + "port": 4027 + }, + { + "address": "gateway2.adavault.com", + "port": 4060 + }, + { + "address": "gateway2.adavault.com", + "port": 4061 } ] }, { - "accumulatedStake": 0.5339530242143362, - "relativeStake": 0.0023012182493809892, + "accumulatedStake": 0.5456967634913253, + "relativeStake": 0.00230177667429201, "relays": [ { "address": "relay-pool-figment-26-mainnet.cardano.aeq5f.com" @@ -2412,178 +2506,156 @@ ] }, { - "accumulatedStake": 0.5362516067470976, - "relativeStake": 0.002298582532761402, + "accumulatedStake": 0.5479784891177965, + "relativeStake": 0.0022817256264711797, "relays": [ { - "address": "cardano-main.everstake.one", + "address": "cardano-main.everstake.com", "port": 3001 }, { - "address": "cardano-main2.everstake.one", + "address": "cardano-main2.everstake.com", "port": 3001 }, { - "address": "cardano-relay.everstake.one", + "address": "cardano-relay.everstake.com", "port": 3001 }, { - "address": "cardano-relay1.everstake.one", + "address": "cardano-relay1.everstake.com", "port": 3001 }, { - "address": "cardano-relay2.everstake.one", + "address": "cardano-relay2.everstake.com", "port": 3001 } ] }, { - "accumulatedStake": 0.5385419415247156, - "relativeStake": 0.0022903347776179295, + "accumulatedStake": 0.5502510490330732, + "relativeStake": 0.002272559915276723, "relays": [ { - "address": "r1.adastat.net", - "port": 3333 - }, - { - "address": "r2.adastat.net", - "port": 3333 - }, - { - "address": "r3.adastat.net", - "port": 3333 + "address": "cardano-relays.autostake.com", + "port": 3001 } ] }, { - "accumulatedStake": 0.540831933504683, - "relativeStake": 0.002289991979967418, + "accumulatedStake": 0.552481480529135, + "relativeStake": 0.0022304314960618237, "relays": [ { - "address": "86.17.211.35", - "port": 3000 + "address": "eu.relays.cardanians.io", + "port": 1000 }, { - "address": "7.88.23.34", - "port": 3000 + "address": "ca.relays.cardanians.io", + "port": 1000 } ] }, { - "accumulatedStake": 0.5431042319184912, - "relativeStake": 0.0022722984138082132, + "accumulatedStake": 0.5547005353543547, + "relativeStake": 0.0022190548252197227, "relays": [ { - "address": "cardano-main.everstake.one", - "port": 3001 - }, - { - "address": "cardano-main2.everstake.one", + "address": "157.245.228.134", "port": 3001 }, { - "address": "cardano-relay.everstake.one", + "address": "159.89.120.164", "port": 3001 }, { - "address": "cardano-relay1.everstake.one", + "address": "209.97.186.44", "port": 3001 }, { - "address": "cardano-relay2.everstake.one", + "address": "eu.bloompool.io", "port": 3001 } ] }, { - "accumulatedStake": 0.5452789722775988, - "relativeStake": 0.002174740359107583, + "accumulatedStake": 0.5569189503111706, + "relativeStake": 0.0022184149568157787, "relays": [ { - "address": "relay-pool-bitvavo-2-mainnet.cardano.aeq5f.com" - } - ] - }, - { - "accumulatedStake": 0.547451753984116, - "relativeStake": 0.0021727817065172765, - "relays": [ - { - "address": "relay.azureada.com", - "port": 3001 + "address": "35.211.17.86", + "port": 3000 }, { - "address": "relay.azureada.com", - "port": 3001 + "address": "34.23.88.7", + "port": 3000 } ] }, { - "accumulatedStake": 0.5496139851237356, - "relativeStake": 0.0021622311396195986, + "accumulatedStake": 0.5591342671671027, + "relativeStake": 0.002215316855932139, "relays": [ { - "address": "relay-pool-bitvavo-3-mainnet.cardano.aeq5f.com" - } - ] - }, - { - "accumulatedStake": 0.5517723514451625, - "relativeStake": 0.002158366321426845, - "relays": [ + "address": "ACLrelay1.cardanoland.com", + "port": 6000 + }, { - "address": "cardano-main.everstake.one", - "port": 3001 + "address": "ACLrelay2.cardanoland.com", + "port": 7000 }, { - "address": "cardano-main2.everstake.one", - "port": 3001 + "address": "ACLrelay3.cardanoland.com", + "port": 8000 }, { - "address": "cardano-relay.everstake.one", - "port": 3001 + "address": "ACLrelay4.cardanoland.com", + "port": 6000 }, { - "address": "cardano-relay1.everstake.one", - "port": 3001 + "address": "ACLrelay5.cardanoland.com", + "port": 7000 }, { - "address": "cardano-relay2.everstake.one", - "port": 3001 + "address": "ACLrelay6.cardanoland.com", + "port": 8000 } ] }, { - "accumulatedStake": 0.5539262567534654, - "relativeStake": 0.0021539053083028913, + "accumulatedStake": 0.5613441009778928, + "relativeStake": 0.0022098338107901625, "relays": [ { - "address": "relay1.able-pool.io", - "port": 4555 + "address": "3.217.90.52", + "port": 6000 }, { - "address": "relay2.able-pool.io", - "port": 4419 + "address": "3.219.254.127", + "port": 6000 } ] }, { - "accumulatedStake": 0.5560633733823807, - "relativeStake": 0.0021371166289152425, + "accumulatedStake": 0.5635316439527023, + "relativeStake": 0.002187542974809437, "relays": [ { - "address": "95.192.156.35", - "port": 6000 - }, + "address": "relay-pool-bitvavo-2-mainnet.cardano.aeq5f.com" + } + ] + }, + { + "accumulatedStake": 0.5657050460039165, + "relativeStake": 0.002173402051214181, + "relays": [ { - "address": "215.51.197.18", - "port": 6000 + "address": "relay-pool-bitvavo-3-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.5581836767662953, - "relativeStake": 0.002120303383914668, + "accumulatedStake": 0.5678758768503668, + "relativeStake": 0.002170830846450335, "relays": [ { "address": "relay1.blueocean.sg", @@ -2600,194 +2672,179 @@ ] }, { - "accumulatedStake": 0.5602807884331025, - "relativeStake": 0.0020971116668072084, + "accumulatedStake": 0.5700418579240493, + "relativeStake": 0.002165981073682473, "relays": [ { - "address": "relay.cardano.securestaking.io", + "address": "r1.adastat.net", + "port": 3333 + }, + { + "address": "r2.adastat.net", + "port": 3333 + }, + { + "address": "r3.adastat.net", + "port": 3333 + } + ] + }, + { + "accumulatedStake": 0.5721712709815225, + "relativeStake": 0.0021294130574732464, + "relays": [ + { + "address": "relay.cardano.securestaking.io", + "port": 3000 + }, + { + "address": "secur2.cardano.securestaking.io", + "port": 3000 + } + ] + }, + { + "accumulatedStake": 0.5742754321037465, + "relativeStake": 0.0021041611222240688, + "relays": [ + { + "address": "relay0.fimi.vn", + "port": 3000 + }, + { + "address": "relay1.fimi.vn", "port": 3000 }, { - "address": "secur2.cardano.securestaking.io", + "address": "relay2.fimi.vn", "port": 3000 } ] }, { - "accumulatedStake": 0.56237450255604, - "relativeStake": 0.0020937141229375885, + "accumulatedStake": 0.5763736581520984, + "relativeStake": 0.0020982260483518238, "relays": [ { - "address": "42.193.216.88", + "address": "relay1-dl.aichi-stakepool.com", "port": 6000 }, { - "address": "38.193.216.88", + "address": "relay2-jp.aichi-stakepool.com", "port": 6000 }, { - "address": "39.193.216.88", + "address": "relay3-li.aichi-stakepool.com", "port": 6000 } ] }, { - "accumulatedStake": 0.5644601656005398, - "relativeStake": 0.0020856630444997786, + "accumulatedStake": 0.5784679661186758, + "relativeStake": 0.002094307966577436, "relays": [ { - "address": "86.17.211.35", + "address": "35.211.17.86", "port": 3000 }, { - "address": "7.88.23.34", + "address": "34.23.88.7", "port": 3000 } ] }, { - "accumulatedStake": 0.5665380143724658, - "relativeStake": 0.0020778487719259452, - "relays": [ - { - "address": "cardano-main.everstake.one", - "port": 3001 - }, - { - "address": "cardano-main2.everstake.one", - "port": 3001 - }, - { - "address": "cardano-relay.everstake.one", - "port": 3001 - }, - { - "address": "cardano-relay1.everstake.one", - "port": 3001 - }, - { - "address": "cardano-relay2.everstake.one", - "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.568605038333113, - "relativeStake": 0.0020670239606472214, + "accumulatedStake": 0.5805284645968883, + "relativeStake": 0.002060498478212516, "relays": [ { - "address": "eu.relays.cardanians.io", - "port": 1000 - }, - { - "address": "ca.relays.cardanians.io", - "port": 1000 + "address": "relay-pool-figment-3-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.5706453822519215, - "relativeStake": 0.0020403439188084876, + "accumulatedStake": 0.5825858914791722, + "relativeStake": 0.002057426882283819, "relays": [ { - "address": "relay1-dl.aichi-stakepool.com", - "port": 6000 - }, - { - "address": "relay2-jp.aichi-stakepool.com", + "address": "109.123.231.213", "port": 6000 }, { - "address": "relay3-li.aichi-stakepool.com", + "address": "89.58.45.244", "port": 6000 } ] }, { - "accumulatedStake": 0.5726786327279993, - "relativeStake": 0.002033250476077876, + "accumulatedStake": 0.5846406729382763, + "relativeStake": 0.0020547814591040897, "relays": [ { - "address": "cardano-main.everstake.one", + "address": "cardano-main.everstake.com", "port": 3001 }, { - "address": "cardano-main2.everstake.one", + "address": "cardano-main2.everstake.com", "port": 3001 }, { - "address": "cardano-relay.everstake.one", + "address": "cardano-relay.everstake.com", "port": 3001 }, { - "address": "cardano-relay1.everstake.one", + "address": "cardano-relay1.everstake.com", "port": 3001 }, { - "address": "cardano-relay2.everstake.one", + "address": "cardano-relay2.everstake.com", "port": 3001 } ] }, { - "accumulatedStake": 0.5747089626651583, - "relativeStake": 0.002030329937158899, + "accumulatedStake": 0.5866698580143551, + "relativeStake": 0.0020291850760788574, "relays": [ { - "address": "213.231.123.109", - "port": 6000 + "address": "cardano-main.everstake.com", + "port": 3001 }, { - "address": "244.45.58.89", - "port": 6000 - } - ] - }, - { - "accumulatedStake": 0.5767172544545587, - "relativeStake": 0.0020082917894004423, - "relays": [ - { - "address": "151.21.53.152", - "port": 6000 + "address": "cardano-main2.everstake.com", + "port": 3001 }, { - "address": "63.152.102.149", - "port": 6000 - } - ] - }, - { - "accumulatedStake": 0.5787199604453425, - "relativeStake": 0.0020027059907837203, - "relays": [ + "address": "cardano-relay.everstake.com", + "port": 3001 + }, { - "address": "relay1.0aaaa.org", + "address": "cardano-relay1.everstake.com", "port": 3001 }, { - "address": "relay2.0aaaa.org", + "address": "cardano-relay2.everstake.com", "port": 3001 } ] }, { - "accumulatedStake": 0.5807095505835773, - "relativeStake": 0.001989590138234822, + "accumulatedStake": 0.5886754554594746, + "relativeStake": 0.0020055974451195333, "relays": [ { - "address": "cardano-relay1.nodes.lgns.xyz", - "port": 6000 + "address": "relay.azureada.com", + "port": 3001 }, { - "address": "cardano-relay2.nodes.lgns.xyz", - "port": 6000 + "address": "relay.azureada.com", + "port": 3001 } ] }, { - "accumulatedStake": 0.5826980535966266, - "relativeStake": 0.001988503013049387, + "accumulatedStake": 0.5906771345536959, + "relativeStake": 0.002001679094221229, "relays": [ { "address": "cardano-relays-1.nu.fi", @@ -2800,26 +2857,22 @@ ] }, { - "accumulatedStake": 0.5846840593036701, - "relativeStake": 0.0019860057070434037, + "accumulatedStake": 0.5926754735325814, + "relativeStake": 0.001998338978885562, "relays": [ { - "address": "relay0.fimi.vn", - "port": 3000 - }, - { - "address": "relay1.fimi.vn", - "port": 3000 + "address": "cardano-relay1.nodes.lgns.xyz", + "port": 6000 }, { - "address": "relay2.fimi.vn", - "port": 3000 + "address": "cardano-relay2.nodes.lgns.xyz", + "port": 6000 } ] }, { - "accumulatedStake": 0.5866642872573108, - "relativeStake": 0.001980227953640767, + "accumulatedStake": 0.5946664023189131, + "relativeStake": 0.0019909287863316798, "relays": [ { "address": "relay-pool-bitvavo-1-mainnet.cardano.aeq5f.com" @@ -2827,375 +2880,330 @@ ] }, { - "accumulatedStake": 0.5886406098437236, - "relativeStake": 0.001976322586412771, + "accumulatedStake": 0.5966214232282798, + "relativeStake": 0.001955020909366724, "relays": [ { - "address": "germany.cardanode.io", - "port": 6000 - }, - { - "address": "missouri.cardanode.io", - "port": 6000 - }, - { - "address": "la.cardanode.io", - "port": 6000 + "address": "relay-kiln-8-0.cardano.mainnet.kiln.fi", + "port": 3001 }, { - "address": "perth.cardanode.io", - "port": 6000 - } - ] - }, - { - "accumulatedStake": 0.5905840532701321, - "relativeStake": 0.001943443426408455, - "relays": [ - { - "address": "229.68.27.37", - "port": 6000 + "address": "relay-kiln-8-1.cardano.mainnet.kiln.fi", + "port": 3001 }, { - "address": "51.18.58.89", - "port": 6000 + "address": "relay-kiln-8-2.cardano.mainnet.kiln.fi", + "port": 3001 } ] }, { - "accumulatedStake": 0.5925121967854174, - "relativeStake": 0.0019281435152854283, + "accumulatedStake": 0.5985728133845801, + "relativeStake": 0.0019513901563002701, "relays": [ { - "address": "relay-kiln-9-0.cardano.mainnet.kiln.fi", + "address": "relaynode1.bravostakepool.nl", "port": 3001 }, { - "address": "relay-kiln-9-1.cardano.mainnet.kiln.fi", + "address": "relaynode2.bravostakepool.nl", "port": 3001 }, { - "address": "relay-kiln-9-2.cardano.mainnet.kiln.fi", + "address": "relaynode3.bravostakepool.nl", "port": 3001 } ] }, { - "accumulatedStake": 0.5944360119065782, - "relativeStake": 0.001923815121160807, + "accumulatedStake": 0.6005070296202005, + "relativeStake": 0.0019342162356204102, "relays": [ { - "address": "23.17.113.148", - "port": 6000 - }, - { - "address": "103.25.69.158", - "port": 6000 - }, - { - "address": "238.70.216.95", - "port": 6000 - }, - { - "address": "196.140.102.149", + "address": "217.160.14.223", "port": 6000 } ] }, { - "accumulatedStake": 0.5963561671533798, - "relativeStake": 0.0019201552468015132, + "accumulatedStake": 0.6024314390773762, + "relativeStake": 0.0019244094571756953, "relays": [ { - "address": "eu1.stakecool.io", - "port": 4001 + "address": "relay1.adaocean.com", + "port": 6000 }, { - "address": "eu2.stakecool.io", - "port": 4001 + "address": "relay2.adaocean.com", + "port": 6000 }, { - "address": "eu3.stakecool.io", - "port": 4002 + "address": "relay3.adaocean.com", + "port": 6000 }, { - "address": "eu4.stakecool.io", - "port": 4002 + "address": "relay4.adaocean.com", + "port": 6000 + }, + { + "address": "relay5.adaocean.com", + "port": 6000 } ] }, { - "accumulatedStake": 0.5982596193914641, - "relativeStake": 0.0019034522380842948, + "accumulatedStake": 0.6043548230813641, + "relativeStake": 0.001923384003987907, "relays": [ { - "address": "gateway.adavault.com", - "port": 4021 - }, - { - "address": "gateway.adavault.com", - "port": 4022 - }, - { - "address": "gateway.adavault.com", - "port": 4026 - }, - { - "address": "gateway.adavault.com", - "port": 4027 - }, - { - "address": "gateway2.adavault.com", - "port": 4060 + "address": "35.156.192.95", + "port": 6000 }, { - "address": "gateway2.adavault.com", - "port": 4061 + "address": "18.197.51.215", + "port": 6000 } ] }, { - "accumulatedStake": 0.6001406639981915, - "relativeStake": 0.001881044606727422, + "accumulatedStake": 0.6062759382296868, + "relativeStake": 0.0019211151483227238, "relays": [ { - "address": "relay0.viperstaking.com", - "port": 4444 + "address": "92a8429c.cardano-relay.herd.run", + "port": 1338 } ] }, { - "accumulatedStake": 0.6020202584907764, - "relativeStake": 0.0018795944925849661, + "accumulatedStake": 0.6081947259407998, + "relativeStake": 0.001918787711112987, "relays": [ { - "address": "cardano-main.everstake.one", - "port": 3001 - }, - { - "address": "cardano-main2.everstake.one", - "port": 3001 + "address": "germany.cardanode.io", + "port": 6000 }, { - "address": "cardano-relay.everstake.one", - "port": 3001 + "address": "missouri.cardanode.io", + "port": 6000 }, { - "address": "cardano-relay1.everstake.one", - "port": 3001 + "address": "la.cardanode.io", + "port": 6000 }, { - "address": "cardano-relay2.everstake.one", - "port": 3001 + "address": "perth.cardanode.io", + "port": 6000 } ] }, { - "accumulatedStake": 0.6038987141800749, - "relativeStake": 0.0018784556892984202, + "accumulatedStake": 0.6101120848656427, + "relativeStake": 0.0019173589248428378, "relays": [ { - "address": "relay1.zetetic.tech", - "port": 3001 - }, - { - "address": "relay2.zetetic.tech", - "port": 3001 - }, - { - "address": "relay3.zetetic.tech", - "port": 3001 + "address": "66.160.158.69", + "port": 6000 }, { - "address": "relay4.zetetic.tech", - "port": 3001 + "address": "66.160.158.70", + "port": 6000 } ] }, { - "accumulatedStake": 0.6057743037214485, - "relativeStake": 0.001875589541373524, + "accumulatedStake": 0.6120195500976833, + "relativeStake": 0.0019074652320406362, "relays": [ { - "address": "relay-kiln-8-0.cardano.mainnet.kiln.fi", - "port": 3001 - }, - { - "address": "relay-kiln-8-1.cardano.mainnet.kiln.fi", - "port": 3001 - }, - { - "address": "relay-kiln-8-2.cardano.mainnet.kiln.fi", + "address": "relays.bladepool.com", "port": 3001 } ] }, { - "accumulatedStake": 0.6076453760102749, - "relativeStake": 0.0018710722888264598, + "accumulatedStake": 0.6139233597252975, + "relativeStake": 0.0019038096276142243, "relays": [ { - "address": "116.cardano.staked.cloud", - "port": 3001 + "address": "relay0.viperstaking.com", + "port": 4444 } ] }, { - "accumulatedStake": 0.6095142989496983, - "relativeStake": 0.0018689229394234178, + "accumulatedStake": 0.6158003391293084, + "relativeStake": 0.0018769794040108703, "relays": [ { - "address": "69.158.160.66", - "port": 6000 - }, - { - "address": "70.158.160.66", - "port": 6000 + "address": "116.cardano.staked.cloud", + "port": 3001 } ] }, { - "accumulatedStake": 0.6113547818571127, - "relativeStake": 0.0018404829074144201, + "accumulatedStake": 0.6176747636806711, + "relativeStake": 0.0018744245513626504, "relays": [ { - "address": "bd-cardano-main-relay-5-a.bdnodes.net", - "port": 6000 + "address": "relay.cardano.securestaking.io", + "port": 3000 }, { - "address": "bd-cardano-main-relay-5-b.bdnodes.net", - "port": 6000 + "address": "secur2.cardano.securestaking.io", + "port": 3000 } ] }, { - "accumulatedStake": 0.6131721377547631, - "relativeStake": 0.001817355897650401, + "accumulatedStake": 0.6195488594661811, + "relativeStake": 0.0018740957855100195, "relays": [ { - "address": "117.203.187.170", - "port": 6000 - }, - { - "address": "8.203.255.173", - "port": 6000 + "address": "relay-pool-figment-13-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.6149810357807676, - "relativeStake": 0.0018088980260044113, + "accumulatedStake": 0.6214110823011194, + "relativeStake": 0.0018622228349383346, "relays": [ { - "address": "clio.one" + "address": "cardano-main.everstake.com", + "port": 3001 }, { - "address": "91.193.161.185", - "port": 6010 + "address": "cardano-main2.everstake.com", + "port": 3001 }, { - "address": "84.123.211.80", - "port": 6010 + "address": "cardano-relay.everstake.com", + "port": 3001 }, { - "address": "2a07:c700:0:700::91", - "port": 6010 + "address": "cardano-relay1.everstake.com", + "port": 3001 + }, + { + "address": "cardano-relay2.everstake.com", + "port": 3001 } ] }, { - "accumulatedStake": 0.6167850884619853, - "relativeStake": 0.0018040526812177597, + "accumulatedStake": 0.6232530763386381, + "relativeStake": 0.001841994037518711, "relays": [ { - "address": "relay1.adaocean.com", - "port": 6000 - }, - { - "address": "relay2.adaocean.com", - "port": 6000 + "address": "clio.one" }, { - "address": "relay3.adaocean.com", - "port": 6000 + "address": "185.161.193.91", + "port": 6010 }, { - "address": "relay4.adaocean.com", - "port": 6000 + "address": "80.211.123.84", + "port": 6010 }, - { - "address": "relay5.adaocean.com", - "port": 6000 + { + "address": "2a07:c700:0:700::91", + "port": 6010 } ] }, { - "accumulatedStake": 0.618572826291369, - "relativeStake": 0.0017877378293837231, + "accumulatedStake": 0.625090709530904, + "relativeStake": 0.00183763319226589, "relays": [ { - "address": "223.14.160.217", - "port": 6000 + "address": "relay.cardano.securestaking.io", + "port": 3000 + }, + { + "address": "secur2.cardano.securestaking.io", + "port": 3000 } ] }, { - "accumulatedStake": 0.6203355453666106, - "relativeStake": 0.0017627190752416513, + "accumulatedStake": 0.6269258529104996, + "relativeStake": 0.001835143379595623, "relays": [ { - "address": "relay1-us.xstakepool.com", + "address": "139.59.200.123", "port": 3001 }, { - "address": "relay2-eu.xstakepool.com", + "address": "129.212.154.208", "port": 3001 }, { - "address": "relay3-sg.xstakepool.com", + "address": "129.212.214.149", "port": 3001 - }, + } + ] + }, + { + "accumulatedStake": 0.6287519232985608, + "relativeStake": 0.0018260703880611487, + "relays": [ { - "address": "relay4-ae.xstakepool.com", - "port": 3001 + "address": "18.157.253.103", + "port": 8381 } ] }, { - "accumulatedStake": 0.6220925477499452, - "relativeStake": 0.001757002383334479, + "accumulatedStake": 0.6305744488517058, + "relativeStake": 0.0018225255531450024, "relays": [ { - "address": "134.228.245.157", - "port": 3001 - }, + "address": "relay2.snakepool.link", + "port": 3002 + } + ] + }, + { + "accumulatedStake": 0.6323818732530899, + "relativeStake": 0.0018074244013841412, + "relays": [ { - "address": "164.120.89.159", - "port": 3001 + "address": "170.187.203.117", + "port": 6000 }, { - "address": "44.186.97.209", - "port": 3001 + "address": "173.255.203.8", + "port": 6000 + } + ] + }, + { + "accumulatedStake": 0.6341757402570924, + "relativeStake": 0.0017938670040025125, + "relays": [ + { + "address": "bd-cardano-main-relay-5-a.bdnodes.net", + "port": 6000 }, { - "address": "na.bloompool.io", - "port": 3001 + "address": "bd-cardano-main-relay-5-b.bdnodes.net", + "port": 6000 } ] }, { - "accumulatedStake": 0.6238380599578405, - "relativeStake": 0.0017455122078952913, + "accumulatedStake": 0.6359349765831955, + "relativeStake": 0.0017592363261031505, "relays": [ { - "address": "103.253.157.18", - "port": 8381 + "address": "67680868.cardano-relay.herd.run", + "port": 1338 } ] }, { - "accumulatedStake": 0.6255809109085879, - "relativeStake": 0.0017428509507474831, + "accumulatedStake": 0.6376861250420863, + "relativeStake": 0.0017511484588907604, "relays": [ { "address": "cardano-relays-1.nu.fi", @@ -3208,72 +3216,66 @@ ] }, { - "accumulatedStake": 0.6273236407494499, - "relativeStake": 0.0017427298408619848, + "accumulatedStake": 0.6394356947391474, + "relativeStake": 0.0017495696970610355, "relays": [ { - "address": "relay.cardano.securestaking.io", - "port": 3000 + "address": "37.27.68.229", + "port": 6000 }, { - "address": "secur2.cardano.securestaking.io", - "port": 3000 + "address": "89.58.18.51", + "port": 6000 } ] }, { - "accumulatedStake": 0.6290617823373637, - "relativeStake": 0.0017381415879137241, + "accumulatedStake": 0.6411761438474243, + "relativeStake": 0.001740449108276899, "relays": [ { - "address": "relay1.adaocean.com", - "port": 6000 - }, - { - "address": "relay2.adaocean.com", - "port": 6000 + "address": "157.245.228.134", + "port": 3001 }, { - "address": "relay3.adaocean.com", - "port": 6000 + "address": "159.89.120.164", + "port": 3001 }, { - "address": "relay4.adaocean.com", - "port": 6000 + "address": "209.97.186.44", + "port": 3001 }, { - "address": "relay5.adaocean.com", - "port": 6000 - } - ] - }, - { - "accumulatedStake": 0.6307838165687589, - "relativeStake": 0.001722034231395349, - "relays": [ - { - "address": "north-america-relay.jpn-sp.net", + "address": "na.bloompool.io", "port": 3001 } ] }, { - "accumulatedStake": 0.6325031211718264, - "relativeStake": 0.0017193046030673852, + "accumulatedStake": 0.6429134835151361, + "relativeStake": 0.001737339667711854, "relays": [ { - "address": "btc-cardano-main-relay-00-a.bdnodes.net", + "address": "148.113.17.23", "port": 6000 }, { - "address": "btc-cardano-main-relay-00-b.bdnodes.net", + "address": "158.69.25.103", + "port": 6000 + }, + { + "address": "95.216.70.238", + "port": 6000 + }, + { + "address": "149.102.140.196", "port": 6000 } ] }, { - "accumulatedStake": 0.634213838608823, - "relativeStake": 0.0017107174369965874, + "accumulatedStake": 0.6446334045515203, + "relativeStake": 0.0017199210363841293, "relays": [ { "address": "cardano-relay-1.upbit.com", @@ -3290,8 +3292,8 @@ ] }, { - "accumulatedStake": 0.6359208248410955, - "relativeStake": 0.0017069862322725408, + "accumulatedStake": 0.6463498374325157, + "relativeStake": 0.001716432880995435, "relays": [ { "address": "cardano-relay-1.upbit.com", @@ -3308,8 +3310,8 @@ ] }, { - "accumulatedStake": 0.6376260187731728, - "relativeStake": 0.001705193932077326, + "accumulatedStake": 0.6480648646421495, + "relativeStake": 0.001715027209633812, "relays": [ { "address": "cardano-relay-1.upbit.com", @@ -3326,54 +3328,32 @@ ] }, { - "accumulatedStake": 0.6393296129455525, - "relativeStake": 0.0017035941723796094, + "accumulatedStake": 0.6497764439049192, + "relativeStake": 0.0017115792627696422, "relays": [ { - "address": "adar1.stakit.io", - "port": 30500 + "address": "north-america-relay.jpn-sp.net", + "port": 3001 } ] }, { - "accumulatedStake": 0.6410291798588725, - "relativeStake": 0.0016995669133201233, + "accumulatedStake": 0.6514737219822213, + "relativeStake": 0.001697278077302112, "relays": [ { - "address": "224.49.176.64", + "address": "btc-cardano-main-relay-00-a.bdnodes.net", "port": 6000 }, { - "address": "63.161.28.149", + "address": "btc-cardano-main-relay-00-b.bdnodes.net", "port": 6000 } ] }, { - "accumulatedStake": 0.6427133214890756, - "relativeStake": 0.001684141630202982, - "relays": [ - { - "address": "rho.relay.easy1staking.com", - "port": 30020 - }, - { - "address": "pi.relay.easy1staking.com", - "port": 30021 - }, - { - "address": "eu-central-1.relay.easy1staking.com", - "port": 30000 - }, - { - "address": "us-east-1.relay.easy1staking.com", - "port": 30000 - } - ] - }, - { - "accumulatedStake": 0.644391965378605, - "relativeStake": 0.0016786438895294686, + "accumulatedStake": 0.6531616743408779, + "relativeStake": 0.0016879523586566844, "relays": [ { "address": "cardano-relay-2.upbit.com", @@ -3390,423 +3370,508 @@ ] }, { - "accumulatedStake": 0.6460705101098909, - "relativeStake": 0.0016785447312859271, + "accumulatedStake": 0.6548326865436552, + "relativeStake": 0.0016710122027772476, "relays": [ { - "address": "cardano-relay-1.upbit.com", - "port": 30800 - }, + "address": "0b2a2fd4.cardano-relay.bison.run", + "port": 1338 + } + ] + }, + { + "accumulatedStake": 0.6564988000161904, + "relativeStake": 0.0016661134725352643, + "relays": [ { - "address": "cardano-relay-2.upbit.com", - "port": 30800 - }, + "address": "07f6ea55.cardano-relay.herd.run", + "port": 1338 + } + ] + }, + { + "accumulatedStake": 0.6581647966078474, + "relativeStake": 0.0016659965916569282, + "relays": [ { - "address": "cardano-relay-3.upbit.com", - "port": 30800 + "address": "a1666f4c.cardano-relay.herd.run", + "port": 1338 } ] }, { - "accumulatedStake": 0.6477439655348424, - "relativeStake": 0.0016734554249514552, + "accumulatedStake": 0.6598306826868352, + "relativeStake": 0.0016658860789878448, "relays": [ { - "address": "28.184.128.57", - "port": 3001 - }, + "address": "84cbba68.cardano-relay.herd.run", + "port": 1338 + } + ] + }, + { + "accumulatedStake": 0.6614965287211069, + "relativeStake": 0.0016658460342716696, + "relays": [ { - "address": "30.184.128.57", + "address": "3ef2283d.cardano-relay.bison.run", + "port": 1338 + } + ] + }, + { + "accumulatedStake": 0.6631595906579604, + "relativeStake": 0.001663061936853446, + "relays": [ + { + "address": "52.6.109.221", "port": 3001 } ] }, { - "accumulatedStake": 0.6494138347236943, - "relativeStake": 0.001669869188851931, + "accumulatedStake": 0.6648181240161833, + "relativeStake": 0.0016585333582230428, "relays": [ { - "address": "relay-pool-figment-9-mainnet.cardano.aeq5f.com" + "address": "169.58.185.200", + "port": 6000 + }, + { + "address": "169.58.186.9", + "port": 6000 + }, + { + "address": "169.58.186.24", + "port": 6000 } ] }, { - "accumulatedStake": 0.6510788602938906, - "relativeStake": 0.0016650255701963106, + "accumulatedStake": 0.6664742098251282, + "relativeStake": 0.0016560858089447999, "relays": [ { - "address": "cardano-main.everstake.one", + "address": "relays.digi.pro", "port": 3001 - }, + } + ] + }, + { + "accumulatedStake": 0.6681300519694447, + "relativeStake": 0.0016558421443165954, + "relays": [ { - "address": "cardano-main2.everstake.one", + "address": "relay1.zetetic.tech", "port": 3001 }, { - "address": "cardano-relay.everstake.one", + "address": "relay2.zetetic.tech", "port": 3001 }, { - "address": "cardano-relay1.everstake.one", + "address": "relay3.zetetic.tech", "port": 3001 }, { - "address": "cardano-relay2.everstake.one", + "address": "relay4.zetetic.tech", "port": 3001 } ] }, { - "accumulatedStake": 0.6527434849307499, - "relativeStake": 0.001664624636859269, + "accumulatedStake": 0.6697841328442863, + "relativeStake": 0.0016540808748415183, "relays": [ { - "address": "0b2a2fd4.cardano-relay.bison.run", - "port": 1338 + "address": "148.113.17.23", + "port": 6000 + }, + { + "address": "158.69.25.103", + "port": 6000 + }, + { + "address": "95.216.4.252", + "port": 6000 + }, + { + "address": "178.18.250.204", + "port": 6000 } ] }, { - "accumulatedStake": 0.6544078618717506, - "relativeStake": 0.0016643769410006472, + "accumulatedStake": 0.6714293768447281, + "relativeStake": 0.0016452440004417995, "relays": [ { - "address": "07f6ea55.cardano-relay.herd.run", - "port": 1338 + "address": "relay-pool-figment-9-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.6560720763115534, - "relativeStake": 0.0016642144398029029, + "accumulatedStake": 0.6730663731849615, + "relativeStake": 0.0016369963402334624, "relays": [ { - "address": "3ef2283d.cardano-relay.bison.run", - "port": 1338 + "address": "relay-pool-figment-25-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.6577362886604072, - "relativeStake": 0.0016642123488537779, + "accumulatedStake": 0.6746868931422207, + "relativeStake": 0.0016205199572591686, "relays": [ { - "address": "e646e266.cardano-relay.bison.run", - "port": 1338 + "address": "cardano-main.everstake.com", + "port": 3001 + }, + { + "address": "cardano-main2.everstake.com", + "port": 3001 + }, + { + "address": "cardano-relay.everstake.com", + "port": 3001 + }, + { + "address": "cardano-relay1.everstake.com", + "port": 3001 + }, + { + "address": "cardano-relay2.everstake.com", + "port": 3001 } ] }, { - "accumulatedStake": 0.6594003875418183, - "relativeStake": 0.0016640988814110936, + "accumulatedStake": 0.6762898762597854, + "relativeStake": 0.0016029831175646994, "relays": [ { - "address": "84cbba68.cardano-relay.herd.run", - "port": 1338 + "address": "adaboy-mainnet-2a.gleeze.com", + "port": 6000 + }, + { + "address": "adaboy-mainnet-3a.gleeze.com", + "port": 6000 } ] }, { - "accumulatedStake": 0.6610644650911441, - "relativeStake": 0.0016640775493257797, + "accumulatedStake": 0.6778619399043374, + "relativeStake": 0.001572063644552006, "relays": [ { - "address": "a1666f4c.cardano-relay.herd.run", - "port": 1338 + "address": "3.221.184.134", + "port": 3001 } ] }, { - "accumulatedStake": 0.6627281545339267, - "relativeStake": 0.0016636894427826908, + "accumulatedStake": 0.6794311812343337, + "relativeStake": 0.0015692413299962327, "relays": [ { - "address": "cf5r1.mainnet.pool.cardanofoundation.org", - "port": 3001 + "address": "cardano-relay-1.upbit.com", + "port": 30800 }, { - "address": "cf5r2.mainnet.pool.cardanofoundation.org", - "port": 3001 + "address": "cardano-relay-2.upbit.com", + "port": 30800 + }, + { + "address": "cardano-relay-3.upbit.com", + "port": 30800 } ] }, { - "accumulatedStake": 0.6643827806638513, - "relativeStake": 0.0016546261299245208, + "accumulatedStake": 0.6809981647367833, + "relativeStake": 0.0015669835024496087, "relays": [ { - "address": "221.109.6.52", + "address": "195.201.143.213", + "port": 3001 + }, + { + "address": "194.233.70.237", + "port": 3001 + }, + { + "address": "89.58.59.127", "port": 3001 } ] }, { - "accumulatedStake": 0.6660108621508252, - "relativeStake": 0.0016280814869738805, + "accumulatedStake": 0.682560402939401, + "relativeStake": 0.0015622382026177833, "relays": [ { - "address": "134.228.245.157", - "port": 3001 - }, - { - "address": "164.120.89.159", - "port": 3001 + "address": "cardano-relay-2.upbit.com", + "port": 30800 }, { - "address": "44.186.97.209", - "port": 3001 + "address": "cardano-relay-3.upbit.com", + "port": 30800 }, { - "address": "eu.bloompool.io", - "port": 3001 + "address": "cardano-relay-1.upbit.com", + "port": 30800 } ] }, { - "accumulatedStake": 0.6676385798445247, - "relativeStake": 0.0016277176936994994, + "accumulatedStake": 0.6841210657416846, + "relativeStake": 0.0015606628022835226, "relays": [ { - "address": "relay1.apexfusionhosting.com", - "port": 3001 + "address": "cardano-relay-1.upbit.com", + "port": 30800 }, { - "address": "relay2.apexfusionhosting.com", - "port": 3001 + "address": "cardano-relay-2.upbit.com", + "port": 30800 + }, + { + "address": "cardano-relay-3.upbit.com", + "port": 30800 } ] }, { - "accumulatedStake": 0.6692539391308432, - "relativeStake": 0.0016153592863185225, + "accumulatedStake": 0.6856810482767811, + "relativeStake": 0.0015599825350964861, "relays": [ { - "address": "cardano-main.everstake.one", - "port": 3001 + "address": "cardano-relay-1.upbit.com", + "port": 30800 }, { - "address": "cardano-main2.everstake.one", - "port": 3001 + "address": "cardano-relay-2.upbit.com", + "port": 30800 }, { - "address": "cardano-relay.everstake.one", - "port": 3001 + "address": "cardano-relay-3.upbit.com", + "port": 30800 + } + ] + }, + { + "accumulatedStake": 0.687237851911875, + "relativeStake": 0.0015568036350939037, + "relays": [ + { + "address": "cardano-relay-1.upbit.com", + "port": 30800 }, { - "address": "cardano-relay1.everstake.one", - "port": 3001 + "address": "cardano-relay-2.upbit.com", + "port": 30800 }, { - "address": "cardano-relay2.everstake.one", - "port": 3001 + "address": "cardano-relay-3.upbit.com", + "port": 30800 } ] }, { - "accumulatedStake": 0.6708635531528467, - "relativeStake": 0.0016096140220035187, + "accumulatedStake": 0.6887892348090332, + "relativeStake": 0.0015513828971582097, "relays": [ { - "address": "eu.relays.cardanians.io", - "port": 1000 + "address": "cardano-relay-2.upbit.com", + "port": 30800 }, { - "address": "ca.relays.cardanians.io", - "port": 1000 + "address": "cardano-relay-3.upbit.com", + "port": 30800 + }, + { + "address": "cardano-relay-1.upbit.com", + "port": 30800 } ] }, { - "accumulatedStake": 0.6724644061883924, - "relativeStake": 0.0016008530355457078, + "accumulatedStake": 0.6903402488658155, + "relativeStake": 0.0015510140567822368, "relays": [ { - "address": "213.143.201.195", + "address": "139.59.200.123", "port": 3001 }, { - "address": "237.70.233.194", + "address": "129.212.154.208", "port": 3001 }, { - "address": "127.59.58.89", + "address": "129.212.214.149", "port": 3001 } ] }, { - "accumulatedStake": 0.674065054790454, - "relativeStake": 0.0016006486020615936, + "accumulatedStake": 0.6918889958685525, + "relativeStake": 0.0015487470027370491, "relays": [ { - "address": "relay1.adaocean.com", - "port": 6000 - }, - { - "address": "relay2.adaocean.com", - "port": 6000 - }, - { - "address": "relay3.adaocean.com", - "port": 6000 + "address": "cardano-relay-1.upbit.com", + "port": 30800 }, { - "address": "relay4.adaocean.com", - "port": 6000 + "address": "cardano-relay-2.upbit.com", + "port": 30800 }, { - "address": "relay5.adaocean.com", - "port": 6000 + "address": "cardano-relay-3.upbit.com", + "port": 30800 } ] }, { - "accumulatedStake": 0.6756627873860951, - "relativeStake": 0.0015977325956410876, + "accumulatedStake": 0.6934363031137971, + "relativeStake": 0.0015473072452446353, "relays": [ { - "address": "42.193.216.88", - "port": 6000 + "address": "relay1-us.xstakepool.com", + "port": 3001 }, { - "address": "38.193.216.88", - "port": 6000 + "address": "relay2-eu.xstakepool.com", + "port": 3001 }, { - "address": "39.193.216.88", - "port": 6000 + "address": "relay3-ag.xstakepool.com", + "port": 3001 } ] }, { - "accumulatedStake": 0.6772466566436263, - "relativeStake": 0.0015838692575311669, + "accumulatedStake": 0.6949785802847129, + "relativeStake": 0.0015422771709158113, "relays": [ { - "address": "115.131.235.13", + "address": "relay1.0aaaa.org", + "port": 3001 + }, + { + "address": "relay2.0aaaa.org", "port": 3001 } ] }, { - "accumulatedStake": 0.6788251887712076, - "relativeStake": 0.0015785321275813258, + "accumulatedStake": 0.6965197911555547, + "relativeStake": 0.001541210870841826, "relays": [ { - "address": "23.17.113.148", - "port": 6000 + "address": "eu1.stakecool.io", + "port": 4001 }, { - "address": "103.25.69.158", - "port": 6000 + "address": "eu2.stakecool.io", + "port": 4001 }, { - "address": "252.4.216.95", - "port": 6000 + "address": "eu3.stakecool.io", + "port": 4002 }, { - "address": "204.250.18.178", - "port": 6000 + "address": "eu4.stakecool.io", + "port": 4002 } ] }, { - "accumulatedStake": 0.6803964159425462, - "relativeStake": 0.0015712271713386107, + "accumulatedStake": 0.6980547606611645, + "relativeStake": 0.001534969505609655, "relays": [ { - "address": "truth.kiwipool.org", - "port": 9630 - }, - { - "address": "love.kiwipool.org", - "port": 9630 - }, - { - "address": "liberty.kiwipool.org", - "port": 9630 - }, - { - "address": "freedom.kiwipool.org", - "port": 9630 + "address": "cardano-relay-2.upbit.com", + "port": 30800 }, { - "address": "peace.kiwipool.org", - "port": 9630 + "address": "cardano-relay-3.upbit.com", + "port": 30800 }, { - "address": "aspire.kiwipool.org", - "port": 9630 + "address": "cardano-relay-1.upbit.com", + "port": 30800 } ] }, { - "accumulatedStake": 0.6819671429068548, - "relativeStake": 0.0015707269643085748, + "accumulatedStake": 0.6995893781137137, + "relativeStake": 0.0015346174525492794, "relays": [ { - "address": "27.184.128.57", - "port": 3001 + "address": "cardano-relay-1.upbit.com", + "port": 30800 }, { - "address": "86.184.128.57", - "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.6835360427664302, - "relativeStake": 0.0015688998595754298, - "relays": [ + "address": "cardano-relay-2.upbit.com", + "port": 30800 + }, { - "address": "relays.cardanowithpaul.com", - "port": 1069 + "address": "cardano-relay-3.upbit.com", + "port": 30800 } ] }, { - "accumulatedStake": 0.6851021168658922, - "relativeStake": 0.001566074099461911, + "accumulatedStake": 0.7011233306910739, + "relativeStake": 0.0015339525773602149, "relays": [ { - "address": "relays.digi.pro", + "address": "18.207.62.97", "port": 3001 } ] }, { - "accumulatedStake": 0.6866675543217039, - "relativeStake": 0.0015654374558117829, + "accumulatedStake": 0.7026571320658984, + "relativeStake": 0.001533801374824538, "relays": [ { - "address": "207.213.69.20", - "port": 3000 + "address": "adar1.stakit.io", + "port": 30500 } ] }, { - "accumulatedStake": 0.6882150297173124, - "relativeStake": 0.0015474753956085296, + "accumulatedStake": 0.7041884301822569, + "relativeStake": 0.001531298116358373, "relays": [ { - "address": "101.cardano.staked.cloud", - "port": 3001 + "address": "cardano-relay-1.upbit.com", + "port": 30800 + }, + { + "address": "cardano-relay-2.upbit.com", + "port": 30800 + }, + { + "address": "cardano-relay-3.upbit.com", + "port": 30800 } ] }, { - "accumulatedStake": 0.6897501545278133, - "relativeStake": 0.0015351248105008174, + "accumulatedStake": 0.7057188942593559, + "relativeStake": 0.0015304640770990954, "relays": [ { - "address": "97.62.207.18", + "address": "23.21.195.62", "port": 3001 } ] }, { - "accumulatedStake": 0.6912837545191998, - "relativeStake": 0.001533599991386536, + "accumulatedStake": 0.7072489973807456, + "relativeStake": 0.0015301031213897805, "relays": [ { "address": "relay1.adaocean.com", @@ -3831,297 +3896,260 @@ ] }, { - "accumulatedStake": 0.6928167901258371, - "relativeStake": 0.0015330356066373177, + "accumulatedStake": 0.7087781105767322, + "relativeStake": 0.0015291131959865058, "relays": [ { - "address": "62.195.21.23", + "address": "23.23.190.5", "port": 3001 } ] }, { - "accumulatedStake": 0.6943471624502999, - "relativeStake": 0.0015303723244628595, + "accumulatedStake": 0.7103066795139305, + "relativeStake": 0.0015285689371983158, "relays": [ { - "address": "5.190.23.23", + "address": "23.23.190.5", "port": 3001 } ] }, { - "accumulatedStake": 0.6958774075377737, - "relativeStake": 0.0015302450874737138, + "accumulatedStake": 0.7118347263888309, + "relativeStake": 0.001528046874900474, "relays": [ { - "address": "5.190.23.23", - "port": 3001 + "address": "cardano-relay-1.upbit.com", + "port": 30800 + }, + { + "address": "cardano-relay-2.upbit.com", + "port": 30800 + }, + { + "address": "cardano-relay-3.upbit.com", + "port": 30800 } ] }, { - "accumulatedStake": 0.6974061402059052, - "relativeStake": 0.0015287326681314424, + "accumulatedStake": 0.713361322517404, + "relativeStake": 0.001526596128573095, "relays": [ { - "address": "4.140.231.3", + "address": "3.231.140.4", "port": 3001 } ] }, { - "accumulatedStake": 0.6989343801781279, - "relativeStake": 0.0015282399722227615, + "accumulatedStake": 0.7148875969130823, + "relativeStake": 0.0015262743956783217, "relays": [ { - "address": "137.94.221.3", + "address": "3.221.94.137", "port": 3001 } ] }, { - "accumulatedStake": 0.7004622887062466, - "relativeStake": 0.0015279085281186616, + "accumulatedStake": 0.7164135773001414, + "relativeStake": 0.0015259803870590588, "relays": [ { - "address": "97.62.207.18", + "address": "3.221.94.137", "port": 3001 } ] }, { - "accumulatedStake": 0.7019900038056064, - "relativeStake": 0.0015277150993597902, + "accumulatedStake": 0.7179389492895815, + "relativeStake": 0.0015253719894400457, "relays": [ { - "address": "137.153.222.3", + "address": "3.231.140.4", "port": 3001 } ] }, { - "accumulatedStake": 0.7035174839821215, - "relativeStake": 0.001527480176515235, + "accumulatedStake": 0.7194642445898034, + "relativeStake": 0.001525295300221885, "relays": [ { - "address": "137.94.221.3", + "address": "3.222.153.137", "port": 3001 } ] }, { - "accumulatedStake": 0.7050448991235065, - "relativeStake": 0.0015274151413850068, + "accumulatedStake": 0.7209895203002039, + "relativeStake": 0.0015252757104004748, "relays": [ { - "address": "4.140.231.3", + "address": "3.224.130.99", "port": 3001 } ] }, { - "accumulatedStake": 0.706571763197264, - "relativeStake": 0.0015268640737573689, + "accumulatedStake": 0.7225133898771746, + "relativeStake": 0.00152386957697078, "relays": [ { - "address": "99.130.224.3", + "address": "3.221.184.134", "port": 3001 } ] }, { - "accumulatedStake": 0.7080986149481988, - "relativeStake": 0.0015268517509348493, + "accumulatedStake": 0.7240227560664301, + "relativeStake": 0.001509366189255382, "relays": [ { - "address": "relay-pool-figment-25-mainnet.cardano.aeq5f.com" - } - ] - }, - { - "accumulatedStake": 0.7096252798347118, - "relativeStake": 0.0015266648865129963, - "relays": [ + "address": "cardano-main.everstake.com", + "port": 3001 + }, { - "address": "137.153.222.3", + "address": "cardano-main2.everstake.com", "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.7111510577803846, - "relativeStake": 0.0015257779456727871, - "relays": [ + }, { - "address": "134.184.221.3", + "address": "cardano-relay.everstake.com", "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.7126766491880712, - "relativeStake": 0.0015255914076866175, - "relays": [ + }, + { + "address": "cardano-relay1.everstake.com", + "port": 3001 + }, { - "address": "134.184.221.3", + "address": "cardano-relay2.everstake.com", "port": 3001 } ] }, { - "accumulatedStake": 0.7141998141723219, - "relativeStake": 0.0015231649842507378, + "accumulatedStake": 0.725513523731948, + "relativeStake": 0.0014907676655179876, "relays": [ { - "address": "relay.pasklab.com", - "port": 3001 + "address": "relay1.adaocean.com", + "port": 6000 }, { - "address": "relay.pasklab.com", - "port": 3002 + "address": "relay2.adaocean.com", + "port": 6000 }, { - "address": "relay.pasklab.com", - "port": 3003 - } - ] - }, - { - "accumulatedStake": 0.715720828430104, - "relativeStake": 0.0015210142577820628, - "relays": [ + "address": "relay3.adaocean.com", + "port": 6000 + }, { - "address": "relay-1.minswap.org", - "port": 3001 + "address": "relay4.adaocean.com", + "port": 6000 }, { - "address": "relay-2.minswap.org", - "port": 3001 + "address": "relay5.adaocean.com", + "port": 6000 } ] }, { - "accumulatedStake": 0.7172340056015309, - "relativeStake": 0.0015131771714269316, + "accumulatedStake": 0.7270001165507889, + "relativeStake": 0.001486592818840872, "relays": [ { - "address": "cardano-relay-1.upbit.com", - "port": 30800 - }, - { - "address": "cardano-relay-2.upbit.com", - "port": 30800 + "address": "64.176.49.224", + "port": 6000 }, { - "address": "cardano-relay-3.upbit.com", - "port": 30800 + "address": "149.28.161.63", + "port": 6000 } ] }, { - "accumulatedStake": 0.7187438219045147, - "relativeStake": 0.0015098163029837672, + "accumulatedStake": 0.7284856043934339, + "relativeStake": 0.001485487842645034, "relays": [ { - "address": "cardano-relay-1.upbit.com", - "port": 30800 - }, - { - "address": "cardano-relay-2.upbit.com", - "port": 30800 - }, - { - "address": "cardano-relay-3.upbit.com", - "port": 30800 + "address": "20.69.213.207", + "port": 3000 } ] }, { - "accumulatedStake": 0.7202506023100178, - "relativeStake": 0.001506780405503141, + "accumulatedStake": 0.729969718350196, + "relativeStake": 0.0014841139567620175, "relays": [ { - "address": "cardano-relay-2.upbit.com", - "port": 30800 + "address": "truth.kiwipool.org", + "port": 9630 }, { - "address": "cardano-relay-3.upbit.com", - "port": 30800 + "address": "love.kiwipool.org", + "port": 9630 }, { - "address": "cardano-relay-1.upbit.com", - "port": 30800 - } - ] - }, - { - "accumulatedStake": 0.7217558427149688, - "relativeStake": 0.0015052404049509852, - "relays": [ + "address": "liberty.kiwipool.org", + "port": 9630 + }, { - "address": "cardano-relay-2.upbit.com", - "port": 30800 + "address": "freedom.kiwipool.org", + "port": 9630 }, { - "address": "cardano-relay-3.upbit.com", - "port": 30800 + "address": "peace.kiwipool.org", + "port": 9630 }, { - "address": "cardano-relay-1.upbit.com", - "port": 30800 + "address": "aspire.kiwipool.org", + "port": 9630 } ] }, { - "accumulatedStake": 0.7232607942461172, - "relativeStake": 0.0015049515311484156, + "accumulatedStake": 0.7314478361208645, + "relativeStake": 0.0014781177706685614, "relays": [ { - "address": "cardano-relay-1.upbit.com", - "port": 30800 - }, - { - "address": "cardano-relay-2.upbit.com", - "port": 30800 + "address": "152.53.121.193", + "port": 6000 }, { - "address": "cardano-relay-3.upbit.com", - "port": 30800 + "address": "84.247.163.186", + "port": 6000 } ] }, { - "accumulatedStake": 0.7247651733958439, - "relativeStake": 0.001504379149726614, + "accumulatedStake": 0.7329240383228246, + "relativeStake": 0.0014762022019600759, "relays": [ { - "address": "cardano-relay-1.upbit.com", - "port": 30800 - }, - { - "address": "cardano-relay-2.upbit.com", - "port": 30800 + "address": "eu.relays.cardanians.io", + "port": 1000 }, { - "address": "cardano-relay-3.upbit.com", - "port": 30800 + "address": "ca.relays.cardanians.io", + "port": 1000 } ] }, { - "accumulatedStake": 0.72626827671121, - "relativeStake": 0.0015031033153660954, + "accumulatedStake": 0.7343978007295392, + "relativeStake": 0.0014737624067145828, "relays": [ { - "address": "67680868.cardano-relay.herd.run", - "port": 1338 + "address": "relays.smaug.pool.pm", + "port": 3001 } ] }, { - "accumulatedStake": 0.7277706245128932, - "relativeStake": 0.0015023478016832827, + "accumulatedStake": 0.7358589773858463, + "relativeStake": 0.0014611766563071673, "relays": [ { "address": "cardano-relay-1.upbit.com", @@ -4138,41 +4166,50 @@ ] }, { - "accumulatedStake": 0.7292700354365264, - "relativeStake": 0.0014994109236331067, + "accumulatedStake": 0.7373197301235141, + "relativeStake": 0.0014607527376678685, "relays": [ { - "address": "relay-pool-figment-3-mainnet.cardano.aeq5f.com" + "address": "cardano-relay-3.upbit.com", + "port": 30800 + }, + { + "address": "cardano-relay-1.upbit.com", + "port": 30800 + }, + { + "address": "cardano-relay-2.upbit.com", + "port": 30800 } ] }, { - "accumulatedStake": 0.7307683939998268, - "relativeStake": 0.001498358563300524, + "accumulatedStake": 0.7387774296930378, + "relativeStake": 0.0014576995695235945, "relays": [ { - "address": "r1.1percentpool.eu", - "port": 19001 - }, - { - "address": "r2.1percentpool.eu", - "port": 19002 + "address": "asia-pacific-zzzrelay.zzzpool.net", + "port": 3001 } ] }, { - "accumulatedStake": 0.7322606004436018, - "relativeStake": 0.0014922064437748932, + "accumulatedStake": 0.7402334760879228, + "relativeStake": 0.0014560463948850438, "relays": [ { - "address": "relays.smaug.pool.pm", + "address": "relay1.apexfusionhosting.com", + "port": 3001 + }, + { + "address": "relay2.apexfusionhosting.com", "port": 3001 } ] }, { - "accumulatedStake": 0.7337362453316693, - "relativeStake": 0.001475644888067439, + "accumulatedStake": 0.7416857948368808, + "relativeStake": 0.0014523187489579286, "relays": [ { "address": "cardano-relay-1.upbit.com", @@ -4189,18 +4226,26 @@ ] }, { - "accumulatedStake": 0.7352117924388794, - "relativeStake": 0.0014755471072101945, + "accumulatedStake": 0.7431379174795304, + "relativeStake": 0.0014521226426496264, "relays": [ { - "address": "relays.mainnet.fortepool.io", - "port": 3001 + "address": "cardano-relay-1.upbit.com", + "port": 30800 + }, + { + "address": "cardano-relay-2.upbit.com", + "port": 30800 + }, + { + "address": "cardano-relay-3.upbit.com", + "port": 30800 } ] }, { - "accumulatedStake": 0.7366846393007195, - "relativeStake": 0.0014728468618400233, + "accumulatedStake": 0.7445896954223536, + "relativeStake": 0.0014517779428232305, "relays": [ { "address": "cardano-relay-1.upbit.com", @@ -4217,276 +4262,254 @@ ] }, { - "accumulatedStake": 0.7381571253789843, - "relativeStake": 0.001472486078264782, + "accumulatedStake": 0.7460409301345761, + "relativeStake": 0.001451234712222448, "relays": [ { - "address": "relays.digi.pro", + "address": "relay-1.minswap.org", "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.7396203332115197, - "relativeStake": 0.001463207832535431, - "relays": [ + }, { - "address": "asia-pacific-zzzrelay.zzzpool.net", + "address": "relay-2.minswap.org", "port": 3001 } ] }, { - "accumulatedStake": 0.7410835342947842, - "relativeStake": 0.001463201083264625, + "accumulatedStake": 0.7474839620752501, + "relativeStake": 0.0014430319406740927, "relays": [ { - "address": "eu-relay.hermes-stakepool.com", - "port": 1000 - }, - { - "address": "us-relay.hermes-stakepool.com", - "port": 1000 + "address": "europe-2.katanapool.net", + "port": 3001 } ] }, { - "accumulatedStake": 0.7425211365227932, - "relativeStake": 0.0014376022280088874, + "accumulatedStake": 0.7489262621330861, + "relativeStake": 0.0014423000578359592, "relays": [ { - "address": "relay.sunnyada.com", - "port": 5001 + "address": "105.cardano.staked.cloud", + "port": 3001 } ] }, { - "accumulatedStake": 0.7439583255885924, - "relativeStake": 0.0014371890657992317, + "accumulatedStake": 0.7503658063806005, + "relativeStake": 0.0014395442475143038, "relays": [ { - "address": "relay1.hyperlinkpool.kr", - "port": 3002 - }, - { - "address": "relay2.hyperlinkpool.kr", - "port": 3003 + "address": "157.245.228.134", + "port": 3001 }, { - "address": "relay3.hyperlinkpool.kr", - "port": 3004 - } - ] - }, - { - "accumulatedStake": 0.7453888343303511, - "relativeStake": 0.0014305087417587309, - "relays": [ - { - "address": "3.37.8.52", + "address": "159.89.120.164", "port": 3001 }, { - "address": "182.252.125.3", + "address": "209.97.186.44", "port": 3001 }, { - "address": "190.225.63.52", + "address": "eu.bloompool.io", "port": 3001 } ] }, { - "accumulatedStake": 0.7468102288952191, - "relativeStake": 0.001421394564867967, + "accumulatedStake": 0.751805253005796, + "relativeStake": 0.0014394466251956108, "relays": [ { - "address": "137.118.154.35", - "port": 6000 + "address": "cof-1.cardanocafe.org", + "port": 3005 }, { - "address": "137.81.6.3", - "port": 6000 - } - ] - }, - { - "accumulatedStake": 0.7482164578924971, - "relativeStake": 0.001406228997278021, - "relays": [ + "address": "cof-2.cardanocafe.org", + "port": 3010 + }, { - "address": "cardano-relay-1.upbit.com", - "port": 30800 + "address": "cap-1.cardanocafe.org", + "port": 4000 }, { - "address": "cardano-relay-2.upbit.com", - "port": 30800 + "address": "cap-2.cardanocafe.org", + "port": 4005 }, { - "address": "cardano-relay-3.upbit.com", - "port": 30800 + "address": "lat-1.cardanocafe.org", + "port": 5001 + }, + { + "address": "lat-2.cardanocafe.org", + "port": 5002 } ] }, { - "accumulatedStake": 0.7496226199214806, - "relativeStake": 0.0014061620289835478, + "accumulatedStake": 0.7532233630887903, + "relativeStake": 0.0014181100829942742, "relays": [ { - "address": "cardano-relay-1.upbit.com", - "port": 30800 + "address": "198.71.57.191", + "port": 6000 }, { - "address": "cardano-relay-2.upbit.com", - "port": 30800 + "address": "154.12.240.223", + "port": 6000 }, { - "address": "cardano-relay-3.upbit.com", - "port": 30800 + "address": "94.16.113.130", + "port": 6000 } ] }, { - "accumulatedStake": 0.7510284137875228, - "relativeStake": 0.001405793866042205, + "accumulatedStake": 0.7546238523866678, + "relativeStake": 0.0014004892978775917, "relays": [ { - "address": "cardano-relay-1.upbit.com", - "port": 30800 + "address": "relay.pasklab.com", + "port": 3001 }, { - "address": "cardano-relay-2.upbit.com", - "port": 30800 + "address": "relay.pasklab.com", + "port": 3002 }, { - "address": "cardano-relay-3.upbit.com", - "port": 30800 + "address": "relay.pasklab.com", + "port": 3003 } ] }, { - "accumulatedStake": 0.7524341573185833, - "relativeStake": 0.001405743531060515, + "accumulatedStake": 0.7560171795434117, + "relativeStake": 0.0013933271567438735, "relays": [ { - "address": "cardano-relay-3.upbit.com", - "port": 30800 - }, - { - "address": "cardano-relay-1.upbit.com", - "port": 30800 + "address": "r1.1percentpool.eu", + "port": 19001 }, { - "address": "cardano-relay-2.upbit.com", - "port": 30800 + "address": "r2.1percentpool.eu", + "port": 19002 } ] }, { - "accumulatedStake": 0.7538398973050682, - "relativeStake": 0.0014057399864847607, + "accumulatedStake": 0.7573954049723385, + "relativeStake": 0.0013782254289266855, "relays": [ { - "address": "cardano-relay-1.upbit.com", - "port": 30800 + "address": "a-r1.elitestakepool.com", + "port": 7011 }, { - "address": "cardano-relay-2.upbit.com", - "port": 30800 + "address": "a-r2.elitestakepool.com", + "port": 7012 }, { - "address": "cardano-relay-3.upbit.com", - "port": 30800 + "address": "b-r3.elitestakepool.com", + "port": 7013 + }, + { + "address": "b-r4.elitestakepool.com", + "port": 7014 } ] }, { - "accumulatedStake": 0.7552451194433372, - "relativeStake": 0.0014052221382689974, + "accumulatedStake": 0.7587710805109774, + "relativeStake": 0.0013756755386389217, "relays": [ { - "address": "europe-2.katanapool.net", + "address": "relays.digi.pro", "port": 3001 } ] }, { - "accumulatedStake": 0.756642025970124, - "relativeStake": 0.0013969065267868616, + "accumulatedStake": 0.7601461811323978, + "relativeStake": 0.0013751006214204884, "relays": [ { - "address": "13.198.180.139", + "address": "51.15.230.232", "port": 6000 }, { - "address": "122.77.148.207", + "address": "51.15.47.58", "port": 6000 } ] }, { - "accumulatedStake": 0.7580132632498632, - "relativeStake": 0.0013712372797392222, + "accumulatedStake": 0.7615104743768474, + "relativeStake": 0.001364293244449504, "relays": [ { - "address": "92a8429c.cardano-relay.herd.run", - "port": 1338 + "address": "65.109.12.161", + "port": 6001 + }, + { + "address": "116.203.131.106", + "port": 6002 } ] }, { - "accumulatedStake": 0.7593799753772064, - "relativeStake": 0.0013667121273431906, + "accumulatedStake": 0.7628661444984154, + "relativeStake": 0.001355670121568058, "relays": [ { - "address": "relays.wavepool.digital", - "port": 3001 + "address": "eu-relay.hermes-stakepool.com", + "port": 1000 + }, + { + "address": "us-relay.hermes-stakepool.com", + "port": 1000 } ] }, { - "accumulatedStake": 0.7607433072622544, - "relativeStake": 0.0013633318850479709, + "accumulatedStake": 0.7642158841151103, + "relativeStake": 0.0013497396166948607, "relays": [ { - "address": "191.57.71.198", + "address": "relay1.alfa-pool.gr", + "port": 6001 + }, + { + "address": "relay2.alfa-pool.gr", "port": 6000 }, { - "address": "223.240.12.154", + "address": "relay3.alfa-pool.gr", "port": 6000 }, { - "address": "130.113.16.94", + "address": "relay4.alfa-pool.gr", "port": 6000 } ] }, { - "accumulatedStake": 0.7621004510712855, - "relativeStake": 0.0013571438090311397, + "accumulatedStake": 0.7655623109820798, + "relativeStake": 0.001346426866969565, "relays": [ { - "address": "134.228.245.157", - "port": 3001 - }, - { - "address": "164.120.89.159", - "port": 3001 - }, - { - "address": "44.186.97.209", - "port": 3001 + "address": "102.130.127.242", + "port": 6000 }, { - "address": "eu.bloompool.io", - "port": 3001 + "address": "94.16.106.16", + "port": 6000 } ] }, { - "accumulatedStake": 0.7634483180583703, - "relativeStake": 0.001347866987084812, + "accumulatedStake": 0.7668974941395252, + "relativeStake": 0.0013351831574453948, "relays": [ { "address": "relay1.mazza.vc", @@ -4495,144 +4518,144 @@ ] }, { - "accumulatedStake": 0.7647927584255396, - "relativeStake": 0.0013444403671692825, + "accumulatedStake": 0.7682322395597301, + "relativeStake": 0.0013347454202047924, "relays": [ { - "address": "86.17.211.35", - "port": 3000 - }, - { - "address": "7.88.23.34", - "port": 3000 + "address": "relays.cardanowithpaul.com", + "port": 1069 } ] }, { - "accumulatedStake": 0.7661296156722747, - "relativeStake": 0.0013368572467350884, + "accumulatedStake": 0.7695653997394243, + "relativeStake": 0.0013331601796942, "relays": [ { - "address": "cardano-relay-2.upbit.com", - "port": 30800 + "address": "relay1.adaocean.com", + "port": 6000 }, { - "address": "cardano-relay-3.upbit.com", - "port": 30800 + "address": "relay2.adaocean.com", + "port": 6000 }, { - "address": "cardano-relay-1.upbit.com", - "port": 30800 + "address": "relay3.adaocean.com", + "port": 6000 + }, + { + "address": "relay4.adaocean.com", + "port": 6000 + }, + { + "address": "relay5.adaocean.com", + "port": 6000 } ] }, { - "accumulatedStake": 0.7674418018049507, - "relativeStake": 0.001312186132676042, + "accumulatedStake": 0.7708976045749564, + "relativeStake": 0.0013322048355320889, "relays": [ { - "address": "19.50.139.3", - "port": 6000 - }, - { - "address": "218.129.137.3", - "port": 6000 + "address": "relay.sunnyada.com", + "port": 5001 } ] }, { - "accumulatedStake": 0.7687532316473753, - "relativeStake": 0.0013114298424246077, + "accumulatedStake": 0.7722151080472698, + "relativeStake": 0.001317503472313417, "relays": [ { - "address": "relay1.ppcx2.mainnet.cardano.p2p.org", - "port": 6001 + "address": "relay0.crimsonpool.com", + "port": 5100 }, { - "address": "relay2.ppcx2.mainnet.cardano.p2p.org", - "port": 6001 + "address": "relay1.crimsonpool.com", + "port": 5101 }, { - "address": "relay1.ppcx2.mainnet.cardano.p2p.org", - "port": 6001 + "address": "relay2.crimsonpool.com", + "port": 5102 + } + ] + }, + { + "accumulatedStake": 0.7735323880241787, + "relativeStake": 0.0013172799769089057, + "relays": [ + { + "address": "139.59.200.123", + "port": 3001 + }, + { + "address": "129.212.154.208", + "port": 3001 }, { - "address": "relay2.ppcx2.mainnet.cardano.p2p.org", - "port": 6001 + "address": "129.212.214.149", + "port": 3001 } ] }, { - "accumulatedStake": 0.7700639499098472, - "relativeStake": 0.0013107182624718077, + "accumulatedStake": 0.7748480290130509, + "relativeStake": 0.0013156409888722808, "relays": [ { - "address": "42.193.216.88", - "port": 6000 + "address": "52.8.37.3", + "port": 3001 }, { - "address": "38.193.216.88", - "port": 6000 + "address": "3.125.252.182", + "port": 3001 }, { - "address": "39.193.216.88", - "port": 6000 + "address": "52.63.225.190", + "port": 3001 } ] }, { - "accumulatedStake": 0.7713706105987118, - "relativeStake": 0.0013066606888646971, + "accumulatedStake": 0.7761538530421636, + "relativeStake": 0.0013058240291126217, "relays": [ { - "address": "23.17.113.148", + "address": "148.113.17.23", "port": 6000 }, { - "address": "103.25.69.158", + "address": "158.69.25.103", "port": 6000 }, { - "address": "158.13.119.168", + "address": "168.119.13.158", "port": 6000 }, { - "address": "207.140.102.149", + "address": "149.102.140.207", "port": 6000 } ] }, { - "accumulatedStake": 0.7726637800746666, - "relativeStake": 0.00129316947595473, - "relays": [ - { - "address": "cardano-relays-1.nu.fi", - "port": 3003 - }, - { - "address": "cardano-relays-2.nu.fi", - "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.7739420285496634, - "relativeStake": 0.0012782484749968303, + "accumulatedStake": 0.7774298706927101, + "relativeStake": 0.0012760176505465526, "relays": [ { - "address": "relay1.cardanesia.com", - "port": 3001 + "address": "35.154.118.137", + "port": 6000 }, { - "address": "relay2.cardanesia.com", - "port": 3001 + "address": "3.6.81.137", + "port": 6000 } ] }, { - "accumulatedStake": 0.7752092678150284, - "relativeStake": 0.0012672392653650256, + "accumulatedStake": 0.7787057770756656, + "relativeStake": 0.00127590638295549, "relays": [ { "address": "relay1.nedscave.io", @@ -4653,135 +4676,88 @@ ] }, { - "accumulatedStake": 0.7764695941338963, - "relativeStake": 0.0012603263188678585, - "relays": [ - { - "address": "223.183.159.51", - "port": 6000 - }, - { - "address": "58.47.15.51", - "port": 6000 - } - ] - }, - { - "accumulatedStake": 0.7777170105806365, - "relativeStake": 0.0012474164467401818, + "accumulatedStake": 0.7799688429392226, + "relativeStake": 0.0012630658635570256, "relays": [ { - "address": "relay-pool-figment-13-mainnet.cardano.aeq5f.com" + "address": "relays.mainnet.fortepool.io", + "port": 3001 } ] }, { - "accumulatedStake": 0.7789636036524538, - "relativeStake": 0.001246593071817292, + "accumulatedStake": 0.7812307953046751, + "relativeStake": 0.0012619523654524582, "relays": [ { - "address": "relay1.alfa-pool.gr", - "port": 6001 - }, - { - "address": "relay2.alfa-pool.gr", - "port": 6000 - }, - { - "address": "relay3.alfa-pool.gr", + "address": "51.159.183.223", "port": 6000 }, { - "address": "relay4.alfa-pool.gr", + "address": "51.15.47.58", "port": 6000 } ] }, { - "accumulatedStake": 0.7802071545014146, - "relativeStake": 0.0012435508489608777, + "accumulatedStake": 0.7824863087828099, + "relativeStake": 0.0012555134781348572, "relays": [ { - "address": "ipclub29-1.relay.my-ip.at", - "port": 3001 - }, - { - "address": "ipclub29-1.relay.my-ip.at", - "port": 3002 - }, - { - "address": "ipclub29-2.relay.my-ip.at", - "port": 3001 + "address": "ada-relay03.biglazycat.com", + "port": 6000 } ] }, { - "accumulatedStake": 0.7814409172170284, - "relativeStake": 0.0012337627156137558, + "accumulatedStake": 0.7837400011944141, + "relativeStake": 0.0012536924116042256, "relays": [ { - "address": "relay1-us.xstakepool.com", - "port": 3001 - }, - { - "address": "relay2-eu.xstakepool.com", + "address": "relay01.nekota.work", "port": 3001 }, { - "address": "relay3-sg.xstakepool.com", + "address": "relay02.nekota.work", "port": 3001 }, { - "address": "relay4-ae.xstakepool.com", + "address": "relay03.nekota.work", "port": 3001 } ] }, { - "accumulatedStake": 0.7826701814566002, - "relativeStake": 0.0012292642395717614, - "relays": [ - { - "address": "relay1.angelstakepool.net", - "port": 5001 - }, - { - "address": "relay2.angelstakepool.net", - "port": 5002 - } - ] - }, - { - "accumulatedStake": 0.7838878706112994, - "relativeStake": 0.0012176891546992667, + "accumulatedStake": 0.7849772500848974, + "relativeStake": 0.0012372488904831987, "relays": [ { - "address": "161.12.109.65", - "port": 6001 + "address": "cardano-relays-1.nu.fi", + "port": 3003 }, { - "address": "106.131.203.116", - "port": 6002 + "address": "cardano-relays-2.nu.fi", + "port": 3001 } ] }, { - "accumulatedStake": 0.785095530511875, - "relativeStake": 0.0012076599005755382, + "accumulatedStake": 0.7861854059496092, + "relativeStake": 0.0012081558647117762, "relays": [ { - "address": "161.122.53.152", + "address": "3.139.50.19", "port": 6000 }, { - "address": "40.196.251.160", + "address": "3.137.129.218", "port": 6000 } ] }, { - "accumulatedStake": 0.786299431412355, - "relativeStake": 0.0012039009004801103, + "accumulatedStake": 0.7873928616769793, + "relativeStake": 0.0012074557273702186, "relays": [ { "address": "cardano-relays-1.nu.fi", @@ -4794,8 +4770,8 @@ ] }, { - "accumulatedStake": 0.7874984494987047, - "relativeStake": 0.0011990180863496389, + "accumulatedStake": 0.7885979927737605, + "relativeStake": 0.0012051310967812069, "relays": [ { "address": "49.0.82.230", @@ -4808,182 +4784,132 @@ ] }, { - "accumulatedStake": 0.7886813164424313, - "relativeStake": 0.00118286694372661, + "accumulatedStake": 0.7898028703279778, + "relativeStake": 0.001204877554217284, "relays": [ { - "address": "48.98.145.132", + "address": "152.53.122.161", "port": 6000 }, { - "address": "141.230.165.82", + "address": "160.251.196.40", "port": 6000 } ] }, { - "accumulatedStake": 0.7898562164827972, - "relativeStake": 0.0011749000403658949, - "relays": [ - { - "address": "91.246.61.202", - "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.7910243278630884, - "relativeStake": 0.0011681113802912253, + "accumulatedStake": 0.7909945765319796, + "relativeStake": 0.0011917062040017207, "relays": [ { - "address": "cardano-relays-1.nu.fi", - "port": 3003 - }, - { - "address": "cardano-relays-2.nu.fi", - "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.7921866141734099, - "relativeStake": 0.0011622863103213834, - "relays": [ - { - "address": "eu-de-blue-cdn-relays.cardano.fans", + "address": "relay1-us.xstakepool.com", "port": 3001 }, { - "address": "us-us-blue-cdn-relays.cardano.fans", + "address": "relay2-eu.xstakepool.com", "port": 3001 }, { - "address": "eu-fr-blue-cdn-relays.cardano.fans", + "address": "relay3-ag.xstakepool.com", "port": 3001 } ] }, { - "accumulatedStake": 0.793348160947835, - "relativeStake": 0.0011615467744252176, + "accumulatedStake": 0.7921806515584374, + "relativeStake": 0.0011860750264579023, "relays": [ { - "address": "relay0.crimsonpool.com", - "port": 5100 - }, - { - "address": "relay1.crimsonpool.com", - "port": 5101 - }, - { - "address": "relay2.crimsonpool.com", - "port": 5102 + "address": "relay1.viperstaking.com", + "port": 4444 } ] }, { - "accumulatedStake": 0.7945078341976717, - "relativeStake": 0.00115967324983668, + "accumulatedStake": 0.7933621690257942, + "relativeStake": 0.0011815174673567143, "relays": [ { - "address": "12.38.58.89", + "address": "89.58.38.12", "port": 6001 }, { - "address": "249.195.221.37", + "address": "37.221.195.249", "port": 6001 }, { - "address": "179.239.38.46", + "address": "46.38.239.179", "port": 6001 }, { - "address": "7.189.120.37", + "address": "37.120.189.7", "port": 6001 } ] }, { - "accumulatedStake": 0.7956627477386801, - "relativeStake": 0.0011549135410083328, + "accumulatedStake": 0.7945429892669899, + "relativeStake": 0.0011808202411956268, "relays": [ { - "address": "57.11.58.89", - "port": 6000 - }, - { - "address": "130.104.207.185", - "port": 6000 + "address": "relay1.bluecheesestakehouse.com", + "port": 5001 } ] }, { - "accumulatedStake": 0.79681717639186, - "relativeStake": 0.0011544286531799512, + "accumulatedStake": 0.7957173730083413, + "relativeStake": 0.0011743837413515379, "relays": [ { - "address": "a-r1.elitestakepool.com", - "port": 7011 - }, - { - "address": "a-r2.elitestakepool.com", - "port": 7012 + "address": "eu-de-blue-cdn-relays.cardano.fans", + "port": 3001 }, { - "address": "b-r3.elitestakepool.com", - "port": 7013 + "address": "us-us-blue-cdn-relays.cardano.fans", + "port": 3001 }, { - "address": "b-r4.elitestakepool.com", - "port": 7014 + "address": "eu-fr-blue-cdn-relays.cardano.fans", + "port": 3001 } ] }, { - "accumulatedStake": 0.7979705134891872, - "relativeStake": 0.0011533370973272655, + "accumulatedStake": 0.7968867331304931, + "relativeStake": 0.0011693601221516975, "relays": [ { - "address": "relay1.kaizn.kaizencrypto.com", + "address": "169.58.185.200", "port": 6000 }, { - "address": "relay2.kaizn.kaizencrypto.com", + "address": "169.58.186.9", "port": 6000 - } - ] - }, - { - "accumulatedStake": 0.7991203229810727, - "relativeStake": 0.001149809491885393, - "relays": [ - { - "address": "relaynode1.kaldano.work", - "port": 3001 }, { - "address": "relaynode2.kaldano.work", - "port": 3001 + "address": "169.58.186.24", + "port": 6000 } ] }, { - "accumulatedStake": 0.8002419594580464, - "relativeStake": 0.0011216364769737648, + "accumulatedStake": 0.7980558350743192, + "relativeStake": 0.00116910194382615, "relays": [ { - "address": "relay1.adaverse.com", - "port": 5000 + "address": "139.180.198.13", + "port": 6000 }, { - "address": "relay2.adaverse.com", - "port": 4000 + "address": "207.148.77.122", + "port": 6000 } ] }, { - "accumulatedStake": 0.8013624111626693, - "relativeStake": 0.001120451704622824, + "accumulatedStake": 0.7992242501389303, + "relativeStake": 0.0011684150646111043, "relays": [ { "address": "asia.jazzstakepool.net", @@ -4992,8 +4918,8 @@ ] }, { - "accumulatedStake": 0.8024819021695112, - "relativeStake": 0.0011194910068418934, + "accumulatedStake": 0.8003843180025516, + "relativeStake": 0.0011600678636213139, "relays": [ { "address": "cardano-relays-1.nu.fi", @@ -5006,176 +4932,158 @@ ] }, { - "accumulatedStake": 0.8035876367305095, - "relativeStake": 0.0011057345609983343, + "accumulatedStake": 0.8015429421613534, + "relativeStake": 0.0011586241588017133, "relays": [ { - "address": "europe1-zzz3relay.zzzpool.net", + "address": "ipclub29-1.relay.my-ip.at", "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.8046843200672522, - "relativeStake": 0.001096683336742725, - "relays": [ + }, { - "address": "relays.planetstake.com", - "port": 3001 + "address": "ipclub29-1.relay.my-ip.at", + "port": 3002 }, { - "address": "20.90.97.161", + "address": "ipclub29-2.relay.my-ip.at", "port": 3001 } ] }, { - "accumulatedStake": 0.805776655626269, - "relativeStake": 0.0010923355590167446, + "accumulatedStake": 0.8027013407935079, + "relativeStake": 0.001158398632154485, "relays": [ { - "address": "226.124.6.3", - "port": 3001 - }, - { - "address": "87.92.193.18", - "port": 3001 + "address": "35.211.17.86", + "port": 3000 }, { - "address": "10.241.219.54", - "port": 3001 + "address": "34.23.88.7", + "port": 3000 } ] }, { - "accumulatedStake": 0.8068674850669669, - "relativeStake": 0.0010908294406979172, + "accumulatedStake": 0.8038505194775264, + "relativeStake": 0.001149178684018558, "relays": [ { - "address": "60.14.111.3", - "port": 3001 + "address": "relay1.adaverse.com", + "port": 5000 + }, + { + "address": "relay2.adaverse.com", + "port": 4000 } ] }, { - "accumulatedStake": 0.8079526746808571, - "relativeStake": 0.0010851896138901976, + "accumulatedStake": 0.8049837186333402, + "relativeStake": 0.0011331991558138305, "relays": [ { - "address": "relay1.viperstaking.com", - "port": 4444 + "address": "relaynode1.kaldano.work", + "port": 3001 + }, + { + "address": "relaynode2.kaldano.work", + "port": 3001 } ] }, { - "accumulatedStake": 0.809030274774136, - "relativeStake": 0.001077600093278973, + "accumulatedStake": 0.8061159285572247, + "relativeStake": 0.001132209923884508, "relays": [ { - "address": "91.246.61.202", + "address": "asia.jazzstakepool.net", "port": 3001 } ] }, { - "accumulatedStake": 0.8101070894062479, - "relativeStake": 0.0010768146321118476, + "accumulatedStake": 0.8072460623398336, + "relativeStake": 0.0011301337826089275, "relays": [ { - "address": "relay1.adaocean.com", - "port": 6000 - }, - { - "address": "relay2.adaocean.com", - "port": 6000 - }, - { - "address": "relay3.adaocean.com", - "port": 6000 - }, - { - "address": "relay4.adaocean.com", - "port": 6000 + "address": "r1.isp-r1.wjg.jp", + "port": 3001 }, { - "address": "relay5.adaocean.com", - "port": 6000 + "address": "r2.isp-r1.wjg.jp", + "port": 3002 } ] }, { - "accumulatedStake": 0.8111748918134505, - "relativeStake": 0.0010678024072025385, + "accumulatedStake": 0.8083509054981621, + "relativeStake": 0.0011048431583284832, "relays": [ { - "address": "relay1.bluecheesestakehouse.com", - "port": 5001 + "address": "europe1-zzz3relay.zzzpool.net", + "port": 3001 } ] }, { - "accumulatedStake": 0.8122343452211386, - "relativeStake": 0.0010594534076881937, + "accumulatedStake": 0.8094482624029952, + "relativeStake": 0.0010973569048330404, "relays": [ { - "address": "242.127.130.102", - "port": 6000 + "address": "cardano-relays-1.nu.fi", + "port": 3003 }, { - "address": "16.106.16.94", - "port": 6000 + "address": "cardano-relays-2.nu.fi", + "port": 3001 } ] }, { - "accumulatedStake": 0.8132924994060334, - "relativeStake": 0.0010581541848948457, + "accumulatedStake": 0.8105404299631341, + "relativeStake": 0.0010921675601389277, "relays": [ { - "address": "193.121.53.152", + "address": "89.58.11.57", "port": 6000 }, { - "address": "186.163.247.84", + "address": "185.207.104.130", "port": 6000 } ] }, { - "accumulatedStake": 0.8143482283554258, - "relativeStake": 0.001055728949392282, + "accumulatedStake": 0.8116236486115497, + "relativeStake": 0.0010832186484156336, "relays": [ { - "address": "relay1.nedscave.io", - "port": 3001 - }, - { - "address": "relay2.nedscave.io", - "port": 3001 - }, - { - "address": "relay3.nedscave.io", - "port": 3001 + "address": "135.181.194.233", + "port": 6000 }, { - "address": "relay4.nedscave.io", - "port": 3001 + "address": "168.119.101.200", + "port": 6000 } ] }, { - "accumulatedStake": 0.8153931849468389, - "relativeStake": 0.001044956591413173, + "accumulatedStake": 0.8126968460601274, + "relativeStake": 0.0010731974485776383, "relays": [ { - "address": "relays.digi.pro", - "port": 3001 + "address": "104.236.24.187", + "port": 5281 + }, + { + "address": "23.24.140.149", + "port": 5282 } ] }, { - "accumulatedStake": 0.8164192760173788, - "relativeStake": 0.0010260910705399019, + "accumulatedStake": 0.8137563790573552, + "relativeStake": 0.0010595329972279022, "relays": [ { "address": "relays.staking4ada.org", @@ -5188,226 +5096,232 @@ ] }, { - "accumulatedStake": 0.8174204533057499, - "relativeStake": 0.0010011772883709933, + "accumulatedStake": 0.8148155309641317, + "relativeStake": 0.001059151906776512, "relays": [ { - "address": "207.213.69.20", - "port": 3000 + "address": "relay1.hyperlinkpool.kr", + "port": 3002 + }, + { + "address": "relay2.hyperlinkpool.kr", + "port": 3003 + }, + { + "address": "relay3.hyperlinkpool.kr", + "port": 3004 } ] }, { - "accumulatedStake": 0.8184205943427519, - "relativeStake": 0.001000141037002156, + "accumulatedStake": 0.8158745995989611, + "relativeStake": 0.001059068634829361, "relays": [ { - "address": "185.57.58.89", - "port": 4000 + "address": "relay0.bluecheesestakehouse.com", + "port": 5000 } ] }, { - "accumulatedStake": 0.8194149073123242, - "relativeStake": 0.0009943129695723055, + "accumulatedStake": 0.8169318520952344, + "relativeStake": 0.0010572524962733536, "relays": [ { - "address": "relay0.bluecheesestakehouse.com", - "port": 5000 + "address": "north-america-zzz2relay.zzzpool.net", + "port": 3001 } ] }, { - "accumulatedStake": 0.8204083305225268, - "relativeStake": 0.0009934232102024828, + "accumulatedStake": 0.8179883364688387, + "relativeStake": 0.001056484373604191, "relays": [ { - "address": "213.231.123.109", + "address": "132.145.98.48", "port": 6000 }, { - "address": "244.45.58.89", + "address": "82.165.230.141", "port": 6000 } ] }, { - "accumulatedStake": 0.8214004661440315, - "relativeStake": 0.0009921356215047328, + "accumulatedStake": 0.8190327535308589, + "relativeStake": 0.001044417062020291, "relays": [ { - "address": "adaboy-mainnet-2a.gleeze.com", - "port": 6000 - }, - { - "address": "adaboy-mainnet-3a.gleeze.com", - "port": 6000 + "address": "3.111.14.60", + "port": 3001 } ] }, { - "accumulatedStake": 0.8223923461931333, - "relativeStake": 0.00099188004910184, + "accumulatedStake": 0.8200753496561842, + "relativeStake": 0.0010425961253252526, "relays": [ { - "address": "relay.azureada.com", + "address": "relays.planetstake.com", "port": 3001 }, { - "address": "relay.azureada.com", + "address": "161.97.90.20", "port": 3001 } ] }, { - "accumulatedStake": 0.8233773981855402, - "relativeStake": 0.000985051992406943, + "accumulatedStake": 0.821111565594646, + "relativeStake": 0.0010362159384618237, "relays": [ { - "address": "3.37.8.52", - "port": 3001 - }, - { - "address": "182.252.125.3", - "port": 3001 + "address": "relay1.kaizn.kaizencrypto.com", + "port": 6000 }, { - "address": "190.225.63.52", - "port": 3001 + "address": "relay2.kaizn.kaizencrypto.com", + "port": 6000 } ] }, { - "accumulatedStake": 0.8243601757647733, - "relativeStake": 0.0009827775792330357, + "accumulatedStake": 0.8221407284779572, + "relativeStake": 0.0010291628833111216, "relays": [ { - "address": "eu1.stakecool.io", - "port": 4001 + "address": "gateway.adavault.com", + "port": 4021 }, { - "address": "eu2.stakecool.io", - "port": 4001 + "address": "gateway.adavault.com", + "port": 4022 }, { - "address": "eu3.stakecool.io", - "port": 4002 + "address": "gateway.adavault.com", + "port": 4026 }, { - "address": "eu4.stakecool.io", - "port": 4002 - } - ] - }, - { - "accumulatedStake": 0.8253420288120061, - "relativeStake": 0.0009818530472328597, - "relays": [ + "address": "gateway.adavault.com", + "port": 4027 + }, { - "address": "217.209.35.161", - "port": 6000 + "address": "gateway2.adavault.com", + "port": 4060 + }, + { + "address": "gateway2.adavault.com", + "port": 4061 } ] }, { - "accumulatedStake": 0.8263044758382014, - "relativeStake": 0.0009624470261952067, + "accumulatedStake": 0.8231623930190965, + "relativeStake": 0.0010216645411393434, "relays": [ { - "address": "251.123.154.35", - "port": 3001 - }, - { - "address": "107.230.206.15", + "address": "r1.spirestaking.com", "port": 3001 } ] }, { - "accumulatedStake": 0.8272591316107105, - "relativeStake": 0.0009546557725090971, + "accumulatedStake": 0.824165035347624, + "relativeStake": 0.0010026423285274572, "relays": [ { - "address": "233.194.181.135", + "address": "109.123.231.213", "port": 6000 }, { - "address": "200.101.119.168", + "address": "89.58.45.244", "port": 6000 } ] }, { - "accumulatedStake": 0.8282128112034212, - "relativeStake": 0.000953679592710641, + "accumulatedStake": 0.8251673342651774, + "relativeStake": 0.0010022989175534924, "relays": [ { - "address": "127.20.167.52", - "port": 4000 + "address": "cf4r1.mainnet.pool.cardanofoundation.org", + "port": 3001 + }, + { + "address": "cf4r2.mainnet.pool.cardanofoundation.org", + "port": 3001 } ] }, { - "accumulatedStake": 0.8291603189867409, - "relativeStake": 0.0009475077833197504, + "accumulatedStake": 0.8261692051981957, + "relativeStake": 0.0010018709330182314, "relays": [ { - "address": "ada-relay03.biglazycat.com", - "port": 6000 + "address": "relay1.angelstakepool.net", + "port": 5001 + }, + { + "address": "relay2.angelstakepool.net", + "port": 5002 } ] }, { - "accumulatedStake": 0.8301053589145103, - "relativeStake": 0.0009450399277694044, + "accumulatedStake": 0.8271657391839405, + "relativeStake": 0.0009965339857448588, "relays": [ { - "address": "r1.spirestaking.com", - "port": 3001 + "address": "34.84.0.241", + "port": 3000 + }, + { + "address": "34.146.198.77", + "port": 3000 } ] }, { - "accumulatedStake": 0.8310497912787418, - "relativeStake": 0.0009444323642315236, + "accumulatedStake": 0.8281605365040757, + "relativeStake": 0.0009947973201352232, "relays": [ { - "address": "europe3-zzz5relay.zzzpool.net", + "address": "relays.digi.pro", "port": 3001 } ] }, { - "accumulatedStake": 0.8319868297485825, - "relativeStake": 0.0009370384698407521, + "accumulatedStake": 0.8291527834691741, + "relativeStake": 0.0009922469650982732, "relays": [ { - "address": "71.174.38.154", - "port": 6000 + "address": "3.6.124.226", + "port": 3001 }, { - "address": "133.253.153.118", - "port": 57413 + "address": "18.193.92.87", + "port": 3001 }, { - "address": "133.253.153.118", - "port": 57414 + "address": "54.219.241.10", + "port": 3001 } ] }, { - "accumulatedStake": 0.8329226190543191, - "relativeStake": 0.0009357893057364758, + "accumulatedStake": 0.8301289640535834, + "relativeStake": 0.0009761805844093909, "relays": [ { - "address": "asia.jazzstakepool.net", - "port": 3001 + "address": "89.58.57.185", + "port": 4000 } ] }, { - "accumulatedStake": 0.8338568323999922, - "relativeStake": 0.0009342133456731942, + "accumulatedStake": 0.8310939334030663, + "relativeStake": 0.0009649693494828541, "relays": [ { "address": "cardano-relays.autostake.com", @@ -5416,361 +5330,373 @@ ] }, { - "accumulatedStake": 0.8347787261224033, - "relativeStake": 0.00092189372241112, + "accumulatedStake": 0.8320538810449015, + "relativeStake": 0.0009599476418352132, "relays": [ { - "address": "private-pools.fivebinaries.com", + "address": "europe-de.popsp.net", "port": 3001 } ] }, { - "accumulatedStake": 0.8356858333075803, - "relativeStake": 0.0009071071851769305, + "accumulatedStake": 0.8329962913205696, + "relativeStake": 0.0009424102756681627, "relays": [ { - "address": "236.157.119.75", - "port": 6000 + "address": "125.250.255.197", + "port": 8000 }, { - "address": "126.144.102.149", + "address": "75.119.158.164", "port": 6000 } ] }, { - "accumulatedStake": 0.8365858569466892, - "relativeStake": 0.0009000236391088864, + "accumulatedStake": 0.8339358415870205, + "relativeStake": 0.0009395502664508021, "relays": [ { - "address": "207.213.69.20", - "port": 3000 + "address": "118.153.253.133", + "port": 57413 + }, + { + "address": "118.153.253.133", + "port": 57414 + }, + { + "address": "106.72.126.170", + "port": 49712 } ] }, { - "accumulatedStake": 0.8374765115217238, - "relativeStake": 0.0008906545750346224, + "accumulatedStake": 0.8348750724566589, + "relativeStake": 0.0009392308696385119, "relays": [ { - "address": "cardano-relays.atomicwallet.io", - "port": 6001 + "address": "161.35.209.217", + "port": 6000 } ] }, { - "accumulatedStake": 0.8383667608204103, - "relativeStake": 0.0008902492986865051, + "accumulatedStake": 0.835809733249017, + "relativeStake": 0.000934660792357951, "relays": [ { - "address": "189.145.126.144", + "address": "108.174.196.172", "port": 6000 }, { - "address": "190.145.126.144", - "port": 7001 - } - ] - }, - { - "accumulatedStake": 0.8392526408016955, - "relativeStake": 0.0008858799812852319, - "relays": [ + "address": "142.11.241.195", + "port": 6000 + }, { - "address": "benitoite-rohan-d68b9.cardano.bdnodes.net", + "address": "142.11.241.198", "port": 6000 }, { - "address": "brown-lagos-6a470.cardano.bdnodes.net", + "address": "104.168.174.247", "port": 6000 + }, + { + "address": "104.168.204.201", + "port": 6001 } ] }, { - "accumulatedStake": 0.8401382070858234, - "relativeStake": 0.0008855662841278994, + "accumulatedStake": 0.8367428473225402, + "relativeStake": 0.0009331140735232778, "relays": [ { - "address": "asia.jazzstakepool.net", + "address": "202.61.246.91", "port": 3001 } ] }, { - "accumulatedStake": 0.8410202025566532, - "relativeStake": 0.0008819954708297972, + "accumulatedStake": 0.8376757866121997, + "relativeStake": 0.0009329392896594556, "relays": [ { - "address": "relays.liqwid.finance", - "port": 3001 + "address": "relay-pool-figment-7-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.841898711986315, - "relativeStake": 0.0008785094296618257, + "accumulatedStake": 0.8386007264426456, + "relativeStake": 0.0009249398304459107, "relays": [ { - "address": "relays.liqwid.finance", - "port": 3001 + "address": "eu1.stakecool.io", + "port": 4001 + }, + { + "address": "eu2.stakecool.io", + "port": 4001 + }, + { + "address": "eu3.stakecool.io", + "port": 4002 + }, + { + "address": "eu4.stakecool.io", + "port": 4002 } ] }, { - "accumulatedStake": 0.8427695712346451, - "relativeStake": 0.0008708592483301273, + "accumulatedStake": 0.8395189467566484, + "relativeStake": 0.0009182203140028374, "relays": [ { - "address": "ram-relay1.irota.xyz", - "port": 6000 + "address": "cardano-relays-1.nu.fi", + "port": 3003 }, { - "address": "kyu-relay2.irota.xyz", - "port": 6000 + "address": "cardano-relays-2.nu.fi", + "port": 3001 } ] }, { - "accumulatedStake": 0.8436386253802043, - "relativeStake": 0.0008690541455591156, + "accumulatedStake": 0.8404334123213676, + "relativeStake": 0.0009144655647192009, "relays": [ { - "address": "46.79.208.13", - "port": 6000 + "address": "139.59.200.123", + "port": 3001 + }, + { + "address": "129.212.154.208", + "port": 3001 + }, + { + "address": "129.212.214.149", + "port": 3001 } ] }, { - "accumulatedStake": 0.8445041572285743, - "relativeStake": 0.0008655318483699847, + "accumulatedStake": 0.8413455891703117, + "relativeStake": 0.0009121768489440275, "relays": [ { - "address": "private-pools.fivebinaries.com", + "address": "52.8.37.3", + "port": 3001 + }, + { + "address": "3.125.252.182", + "port": 3001 + }, + { + "address": "52.63.225.190", "port": 3001 } ] }, { - "accumulatedStake": 0.8453667789265603, - "relativeStake": 0.0008626216979860077, + "accumulatedStake": 0.842256772645167, + "relativeStake": 0.0009111834748553768, "relays": [ { - "address": "relay-pool-figment-7-mainnet.cardano.aeq5f.com" + "address": "20.69.213.207", + "port": 3000 } ] }, { - "accumulatedStake": 0.8462288501840641, - "relativeStake": 0.0008620712575038516, + "accumulatedStake": 0.8431648546777616, + "relativeStake": 0.000908082032594599, "relays": [ { - "address": "relay01.nekota.work", - "port": 3001 - }, - { - "address": "relay02.nekota.work", - "port": 3001 + "address": "75.119.157.236", + "port": 6000 }, { - "address": "relay03.nekota.work", - "port": 3001 + "address": "149.102.144.126", + "port": 6000 } ] }, { - "accumulatedStake": 0.8470881801192651, - "relativeStake": 0.0008593299352009455, + "accumulatedStake": 0.8440697482860445, + "relativeStake": 0.000904893608282922, "relays": [ { - "address": "europe-de.popsp.net", - "port": 3001 + "address": "cardano-relays.atomicwallet.io", + "port": 6001 } ] }, { - "accumulatedStake": 0.8479449014327889, - "relativeStake": 0.0008567213135237731, + "accumulatedStake": 0.8449676929155718, + "relativeStake": 0.0008979446295272457, "relays": [ { - "address": "cardano-relays-1.nu.fi", - "port": 3003 + "address": "144.126.145.189", + "port": 6000 }, { - "address": "cardano-relays-2.nu.fi", - "port": 3001 + "address": "144.126.145.190", + "port": 7001 } ] }, { - "accumulatedStake": 0.8487941028530791, - "relativeStake": 0.0008492014202902068, + "accumulatedStake": 0.8458544738638838, + "relativeStake": 0.0008867809483120636, "relays": [ { - "address": "241.0.84.34", - "port": 3000 - }, - { - "address": "77.198.146.34", - "port": 3000 + "address": "118.cardano.staked.cloud", + "port": 3001 } ] }, { - "accumulatedStake": 0.8496345792100001, - "relativeStake": 0.0008404763569209822, + "accumulatedStake": 0.8467402031863849, + "relativeStake": 0.0008857293225010712, "relays": [ { - "address": "relay1.toiro.love", - "port": 6000 - }, + "address": "asia.jazzstakepool.net", + "port": 3001 + } + ] + }, + { + "accumulatedStake": 0.8476106776082822, + "relativeStake": 0.0008704744218973293, + "relays": [ { - "address": "relay2.toiro.love", + "address": "13.208.79.46", "port": 6000 } ] }, { - "accumulatedStake": 0.8504730108983621, - "relativeStake": 0.0008384316883621009, + "accumulatedStake": 0.8484783957471141, + "relativeStake": 0.0008677181388318708, "relays": [ { - "address": "197.255.250.125", - "port": 8000 + "address": "ram-relay1.irota.xyz", + "port": 6000 }, { - "address": "164.158.119.75", + "address": "kyu-relay2.irota.xyz", "port": 6000 } ] }, { - "accumulatedStake": 0.851308854350048, - "relativeStake": 0.0008358434516858715, + "accumulatedStake": 0.849344781382522, + "relativeStake": 0.0008663856354079086, "relays": [ { - "address": "relay-ca.ada.psiloblox.io", - "port": 3002 - }, - { - "address": "2600:ac02:7c06:0:20c:29ff:fe01:4ff9", - "port": 3002 - }, - { - "address": "126.69.118.208", - "port": 3003 - }, - { - "address": "relay-jp.ada.psiloblox.io", + "address": "relay.azureada.com", "port": 3001 }, { - "address": "relay-de.ada.psiloblox.io", - "port": 3002 + "address": "relay.azureada.com", + "port": 3001 } ] }, { - "accumulatedStake": 0.85213467379231, - "relativeStake": 0.0008258194422620232, + "accumulatedStake": 0.8501950095993639, + "relativeStake": 0.0008502282168418203, "relays": [ { - "address": "ipclub29-1.relay.my-ip.at", - "port": 3001 - }, - { - "address": "ipclub29-1.relay.my-ip.at", - "port": 3002 - }, - { - "address": "ipclub29-2.relay.my-ip.at", - "port": 3001 + "address": "20.69.213.207", + "port": 3000 } ] }, { - "accumulatedStake": 0.8529576348240011, - "relativeStake": 0.0008229610316910298, + "accumulatedStake": 0.8510415916030514, + "relativeStake": 0.0008465820036875131, "relays": [ { - "address": "relay1.cerostakepool.com", + "address": "relay1.nedscave.io", "port": 3001 }, { - "address": "relay2.cerostakepool.com", + "address": "relay2.nedscave.io", "port": 3001 }, { - "address": "relay3.cerostakepool.com", + "address": "relay3.nedscave.io", "port": 3001 }, { - "address": "relay4.cerostakepool.com", + "address": "relay4.nedscave.io", "port": 3001 } ] }, { - "accumulatedStake": 0.8537803672548918, - "relativeStake": 0.0008227324308907524, + "accumulatedStake": 0.8518858144835291, + "relativeStake": 0.0008442228804777167, "relays": [ { - "address": "1f018fdb.cardano-relay.bison.run", - "port": 1338 + "address": "re1.reservoir.network", + "port": 3001 + }, + { + "address": "re2.reservoir.network", + "port": 3001 } ] }, { - "accumulatedStake": 0.8545998334627526, - "relativeStake": 0.000819466207860724, + "accumulatedStake": 0.8527225573399895, + "relativeStake": 0.0008367428564604106, "relays": [ { - "address": "127.20.167.52", - "port": 4000 + "address": "relay1.toiro.love", + "port": 6000 + }, + { + "address": "relay2.toiro.love", + "port": 6000 } ] }, { - "accumulatedStake": 0.8554093113305289, - "relativeStake": 0.0008094778677763317, + "accumulatedStake": 0.8535520074602289, + "relativeStake": 0.00082945012023935, "relays": [ { - "address": "91.246.61.202", + "address": "private-pools.fivebinaries.com", "port": 3001 } ] }, { - "accumulatedStake": 0.8562124367451066, - "relativeStake": 0.0008031254145776891, + "accumulatedStake": 0.8543789055658118, + "relativeStake": 0.0008268981055829143, "relays": [ { - "address": "179.28.129.57", - "port": 3001 - }, - { - "address": "180.28.129.57", + "address": "europe3-zzz5relay.zzzpool.net", "port": 3001 } ] }, { - "accumulatedStake": 0.8570114957654169, - "relativeStake": 0.0007990590203103831, + "accumulatedStake": 0.8552041879713961, + "relativeStake": 0.0008252824055843259, "relays": [ { - "address": "relay.azureada.com", - "port": 3001 - }, - { - "address": "relay.azureada.com", - "port": 3001 + "address": "1f018fdb.cardano-relay.bison.run", + "port": 1338 } ] }, { - "accumulatedStake": 0.8578100951931749, - "relativeStake": 0.0007985994277579716, + "accumulatedStake": 0.8560280506838283, + "relativeStake": 0.0008238627124321949, "relays": [ { "address": "LANDrelay1.cardanoland.com", @@ -5799,150 +5725,234 @@ ] }, { - "accumulatedStake": 0.8586057221682988, - "relativeStake": 0.000795626975123897, + "accumulatedStake": 0.8568471775625454, + "relativeStake": 0.0008191268787170317, "relays": [ { - "address": "cardano-relays.atomicwallet.io", - "port": 6001 + "address": "202.61.246.91", + "port": 3001 } ] }, { - "accumulatedStake": 0.8593977383307482, - "relativeStake": 0.0007920161624493633, + "accumulatedStake": 0.8576615753450586, + "relativeStake": 0.0008143977825132582, "relays": [ { - "address": "107.15.195.159", + "address": "benitoite-rohan-d68b9.cardano.bdnodes.net", "port": 6000 }, { - "address": "162.204.251.160", + "address": "brown-lagos-6a470.cardano.bdnodes.net", "port": 6000 } ] }, { - "accumulatedStake": 0.860185078887215, - "relativeStake": 0.0007873405564667428, + "accumulatedStake": 0.8584759478582965, + "relativeStake": 0.000814372513237891, "relays": [ { - "address": "relays.xray.app", - "port": 3000 + "address": "52.167.20.127", + "port": 4000 } ] }, { - "accumulatedStake": 0.8609723125256044, - "relativeStake": 0.0007872336383894583, + "accumulatedStake": 0.859271405913551, + "relativeStake": 0.0007954580552545166, "relays": [ { - "address": "134.228.245.157", - "port": 3001 + "address": "159.195.15.107", + "port": 6000 }, { - "address": "164.120.89.159", + "address": "160.251.204.162", + "port": 6000 + } + ] + }, + { + "accumulatedStake": 0.8600560141223991, + "relativeStake": 0.0007846082088480789, + "relays": [ + { + "address": "cardano-relays.atomicwallet.io", + "port": 6001 + } + ] + }, + { + "accumulatedStake": 0.8608286784825798, + "relativeStake": 0.00077266436018073, + "relays": [ + { + "address": "private-pools.fivebinaries.com", "port": 3001 - }, + } + ] + }, + { + "accumulatedStake": 0.8615974394376814, + "relativeStake": 0.0007687609551016811, + "relays": [ { - "address": "44.186.97.209", + "address": "relay1.cardanesia.com", "port": 3001 }, { - "address": "na.bloompool.io", + "address": "relay2.cardanesia.com", "port": 3001 } ] }, { - "accumulatedStake": 0.8617524527266192, - "relativeStake": 0.0007801402010147795, + "accumulatedStake": 0.8623649342402513, + "relativeStake": 0.0007674948025698021, "relays": [ { - "address": "r1.1percentpool.eu", - "port": 19001 + "address": "202.61.246.91", + "port": 3001 + } + ] + }, + { + "accumulatedStake": 0.863131666068692, + "relativeStake": 0.0007667318284407254, + "relays": [ + { + "address": "relay1.adaocean.com", + "port": 6000 }, { - "address": "r2.1percentpool.eu", - "port": 19002 + "address": "relay2.adaocean.com", + "port": 6000 + }, + { + "address": "relay3.adaocean.com", + "port": 6000 + }, + { + "address": "relay4.adaocean.com", + "port": 6000 + }, + { + "address": "relay5.adaocean.com", + "port": 6000 } ] }, { - "accumulatedStake": 0.8625253888189474, - "relativeStake": 0.0007729360923281876, + "accumulatedStake": 0.8638941468215041, + "relativeStake": 0.0007624807528121378, "relays": [ { - "address": "relay1.cashflowpool.com", + "address": "relay1.cerostakepool.com", + "port": 3001 + }, + { + "address": "relay2.cerostakepool.com", + "port": 3001 + }, + { + "address": "relay3.cerostakepool.com", "port": 3001 }, { - "address": "relay2.cashflowpool.com", + "address": "relay4.cerostakepool.com", "port": 3001 } ] }, { - "accumulatedStake": 0.863295731678632, - "relativeStake": 0.0007703428596847152, + "accumulatedStake": 0.8646496785525102, + "relativeStake": 0.0007555317310060316, "relays": [ { - "address": "232.230.15.51", - "port": 6000 - }, + "address": "relay-pool-figment-20-mainnet.cardano.aeq5f.com" + } + ] + }, + { + "accumulatedStake": 0.8654050771150503, + "relativeStake": 0.0007553985625402018, + "relays": [ { - "address": "58.47.15.51", - "port": 6000 + "address": "relays.xray.app", + "port": 3000 } ] }, { - "accumulatedStake": 0.8640601252151463, - "relativeStake": 0.0007643935365142659, + "accumulatedStake": 0.8661588896271928, + "relativeStake": 0.0007538125121423847, "relays": [ { - "address": "cof-1.cardanocafe.org", - "port": 3005 + "address": "cardano1.vampyre.fund", + "port": 3001 }, { - "address": "cof-2.cardanocafe.org", - "port": 3010 + "address": "cardano2.vampyre.fund", + "port": 3001 }, { - "address": "cap-1.cardanocafe.org", - "port": 4000 + "address": "cardano3.vampyre.fund", + "port": 3001 }, { - "address": "cap-2.cardanocafe.org", - "port": 4005 + "address": "cardano4.vampyre.fund", + "port": 3001 + } + ] + }, + { + "accumulatedStake": 0.8669103147874443, + "relativeStake": 0.0007514251602515734, + "relays": [ + { + "address": "157.245.228.134", + "port": 3001 }, { - "address": "lat-1.cardanocafe.org", - "port": 5001 + "address": "159.89.120.164", + "port": 3001 }, { - "address": "lat-2.cardanocafe.org", - "port": 5002 + "address": "209.97.186.44", + "port": 3001 + }, + { + "address": "na.bloompool.io", + "port": 3001 } ] }, { - "accumulatedStake": 0.8648231509732514, - "relativeStake": 0.0007630257581050348, + "accumulatedStake": 0.8676570164495959, + "relativeStake": 0.0007467016621515776, "relays": [ { - "address": "187.24.236.104", - "port": 5281 + "address": "relay-pool-1-mainnet.cardano.aeq5f.com" + } + ] + }, + { + "accumulatedStake": 0.8683958107368724, + "relativeStake": 0.0007387942872765727, + "relays": [ + { + "address": "cardano-relays-1.nu.fi", + "port": 3003 }, { - "address": "149.140.24.23", - "port": 5282 + "address": "cardano-relays-2.nu.fi", + "port": 3001 } ] }, { - "accumulatedStake": 0.865585732195633, - "relativeStake": 0.0007625812223815421, + "accumulatedStake": 0.8691273229665439, + "relativeStake": 0.0007315122296714482, "relays": [ { "address": "cpr1.sargatxet.cloud", @@ -5959,44 +5969,42 @@ ] }, { - "accumulatedStake": 0.8663476114774958, - "relativeStake": 0.000761879281862981, + "accumulatedStake": 0.8698575510991391, + "relativeStake": 0.0007302281325951941, "relays": [ { - "address": "30.67.77.45", - "port": 3000 + "address": "relay.azureada.com", + "port": 3001 }, { - "address": "230.153.32.45", - "port": 3000 + "address": "relay.azureada.com", + "port": 3001 } ] }, { - "accumulatedStake": 0.8670966083148716, - "relativeStake": 0.000748996837375665, + "accumulatedStake": 0.8705852504860137, + "relativeStake": 0.0007276993868745279, "relays": [ { - "address": "cardano1.vampyre.fund", - "port": 3001 - }, - { - "address": "cardano2.vampyre.fund", - "port": 3001 - }, - { - "address": "cardano3.vampyre.fund", + "address": "relays.wavepool.digital", "port": 3001 - }, + } + ] + }, + { + "accumulatedStake": 0.8713083733212035, + "relativeStake": 0.0007231228351898441, + "relays": [ { - "address": "cardano4.vampyre.fund", - "port": 3001 + "address": "52.167.20.127", + "port": 4000 } ] }, { - "accumulatedStake": 0.8678405944650742, - "relativeStake": 0.0007439861502027078, + "accumulatedStake": 0.8720299573474514, + "relativeStake": 0.0007215840262479048, "relays": [ { "address": "eu.relays.cardanians.io", @@ -6009,304 +6017,342 @@ ] }, { - "accumulatedStake": 0.8685840109752331, - "relativeStake": 0.0007434165101588196, + "accumulatedStake": 0.8727512340899248, + "relativeStake": 0.0007212767424734738, "relays": [ { - "address": "relay-pool-1-mainnet.cardano.aeq5f.com" + "address": "206.81.3.194", + "port": 3001 } ] }, { - "accumulatedStake": 0.8693256009521853, - "relativeStake": 0.0007415899769521833, + "accumulatedStake": 0.8734659422632768, + "relativeStake": 0.0007147081733519788, "relays": [ { - "address": "194.3.81.206", + "address": "35.154.123.251", + "port": 3001 + }, + { + "address": "15.206.230.107", "port": 3001 } ] }, { - "accumulatedStake": 0.8700624783361824, - "relativeStake": 0.0007368773839971416, + "accumulatedStake": 0.8741741444661417, + "relativeStake": 0.0007082022028648699, "relays": [ { - "address": "r1.adaism.uk", - "port": 8081 - }, - { - "address": "r2.adaism.uk", - "port": 8081 + "address": "1e5c4061.cardano-relay.bison.run", + "port": 1338 } ] }, { - "accumulatedStake": 0.8707959937606539, - "relativeStake": 0.0007335154244714667, + "accumulatedStake": 0.8748819199632103, + "relativeStake": 0.0007077754970685601, "relays": [ { - "address": "59.106.28.149", + "address": "40.160.1.159", + "port": 6000 + }, + { + "address": "15.204.108.52", "port": 6000 } ] }, { - "accumulatedStake": 0.8715239509513963, - "relativeStake": 0.0007279571907425242, + "accumulatedStake": 0.8755782831926557, + "relativeStake": 0.0006963632294454958, "relays": [ { - "address": "adar2.stakit.io", - "port": 30501 + "address": "45.77.67.30", + "port": 3000 + }, + { + "address": "45.32.153.230", + "port": 3000 } ] }, { - "accumulatedStake": 0.8722504168201226, - "relativeStake": 0.0007264658687262406, + "accumulatedStake": 0.876272152367215, + "relativeStake": 0.0006938691745592569, "relays": [ { - "address": "cardano-relays-1.nu.fi", - "port": 3003 - }, - { - "address": "cardano-relays-2.nu.fi", + "address": "relays.cardaspians.io", "port": 3001 } ] }, { - "accumulatedStake": 0.8729755771755099, - "relativeStake": 0.0007251603553872573, + "accumulatedStake": 0.8769620357380131, + "relativeStake": 0.0006898833707981206, "relays": [ { - "address": "ACLrelay1.cardanoland.com", + "address": "r1.relaypool.online", + "port": 3000 + } + ] + }, + { + "accumulatedStake": 0.8776503845217858, + "relativeStake": 0.0006883487837726752, + "relays": [ + { + "address": "148.113.17.23", "port": 6000 }, { - "address": "ACLrelay2.cardanoland.com", - "port": 7000 + "address": "158.69.25.103", + "port": 6000 }, { - "address": "ACLrelay3.cardanoland.com", - "port": 8000 + "address": "95.216.70.238", + "port": 6000 }, { - "address": "ACLrelay4.cardanoland.com", + "address": "149.102.140.234", "port": 6000 + } + ] + }, + { + "accumulatedStake": 0.8783344896923029, + "relativeStake": 0.0006841051705170479, + "relays": [ + { + "address": "relay-ca.ada.psiloblox.io", + "port": 3002 }, { - "address": "ACLrelay5.cardanoland.com", - "port": 7000 + "address": "2600:ac02:7c06:0:20c:29ff:fe01:4ff9", + "port": 3002 }, { - "address": "ACLrelay6.cardanoland.com", - "port": 8000 + "address": "208.118.69.126", + "port": 3003 + }, + { + "address": "relay-jp.ada.psiloblox.io", + "port": 3001 + }, + { + "address": "relay-de.ada.psiloblox.io", + "port": 3002 + } + ] + }, + { + "accumulatedStake": 0.8790153630167352, + "relativeStake": 0.0006808733244323725, + "relays": [ + { + "address": "34.192.61.190", + "port": 3001 } ] }, { - "accumulatedStake": 0.873688485563449, - "relativeStake": 0.0007129083879391208, + "accumulatedStake": 0.8796918952110386, + "relativeStake": 0.0006765321943033807, "relays": [ { - "address": "23.17.113.148", + "address": "ACLrelay1.cardanoland.com", "port": 6000 }, { - "address": "103.25.69.158", - "port": 6000 + "address": "ACLrelay2.cardanoland.com", + "port": 7000 }, { - "address": "238.70.216.95", - "port": 6000 + "address": "ACLrelay3.cardanoland.com", + "port": 8000 }, { - "address": "234.140.102.149", + "address": "ACLrelay4.cardanoland.com", "port": 6000 + }, + { + "address": "ACLrelay5.cardanoland.com", + "port": 7000 + }, + { + "address": "ACLrelay6.cardanoland.com", + "port": 8000 } ] }, { - "accumulatedStake": 0.8743996422862106, - "relativeStake": 0.0007111567227616059, + "accumulatedStake": 0.8803623540752887, + "relativeStake": 0.0006704588642501359, "relays": [ { - "address": "233.194.181.135", - "port": 6000 + "address": "relay1.apexpool.info", + "port": 5001 }, { - "address": "200.101.119.168", - "port": 6000 + "address": "relay2.apexpool.info", + "port": 5001 } ] }, { - "accumulatedStake": 0.875106053533861, - "relativeStake": 0.000706411247650283, + "accumulatedStake": 0.8810306352355767, + "relativeStake": 0.000668281160287962, "relays": [ { - "address": "219.79.128.178", - "port": 3001 - }, - { - "address": "73.122.131.104", + "address": "3.222.153.137", "port": 3001 } ] }, { - "accumulatedStake": 0.8758114056591659, - "relativeStake": 0.0007053521253050448, + "accumulatedStake": 0.8816980143440755, + "relativeStake": 0.0006673791084987497, "relays": [ { - "address": "relay-pool-figment-20-mainnet.cardano.aeq5f.com" + "address": "137.117.180.0", + "port": 16112 + }, + { + "address": "20.52.178.196", + "port": 16112 + }, + { + "address": "52.152.187.47", + "port": 16112 } ] }, { - "accumulatedStake": 0.8765067386187408, - "relativeStake": 0.0006953329595748806, + "accumulatedStake": 0.8823614964805508, + "relativeStake": 0.0006634821364753267, "relays": [ { - "address": "1e5c4061.cardano-relay.bison.run", - "port": 1338 + "address": "relay1.pudim.cat", + "port": 3002 + }, + { + "address": "relay2.pudim.cat", + "port": 3002 } ] }, { - "accumulatedStake": 0.8771973953278905, - "relativeStake": 0.0006906567091497046, + "accumulatedStake": 0.8830246901081447, + "relativeStake": 0.0006631936275939012, "relays": [ { - "address": "relay1.thevikingpool.com", - "port": 6000 - }, - { - "address": "relay2.thevikingpool.com", - "port": 6000 + "address": "adar2.stakit.io", + "port": 30501 } ] }, { - "accumulatedStake": 0.877886520868648, - "relativeStake": 0.0006891255407574848, + "accumulatedStake": 0.8836758062340916, + "relativeStake": 0.0006511161259469015, "relays": [ { - "address": "172.196.174.108", - "port": 6000 - }, - { - "address": "195.241.11.142", - "port": 6000 - }, - { - "address": "198.241.11.142", - "port": 6000 + "address": "relay1-ada.cex.io", + "port": 3001 }, { - "address": "247.174.168.104", - "port": 6000 + "address": "relay2-ada.cex.io", + "port": 3002 }, { - "address": "201.204.168.104", - "port": 6001 + "address": "relay3-ada.cex.io", + "port": 3003 } ] }, { - "accumulatedStake": 0.8785750700129158, - "relativeStake": 0.0006885491442677816, + "accumulatedStake": 0.8843205259870812, + "relativeStake": 0.0006447197529896085, "relays": [ { - "address": "159.1.160.40", - "port": 6000 + "address": "csn.relay1.cardanoscan.io", + "port": 3101 }, { - "address": "52.108.204.15", - "port": 6000 + "address": "csn.relay2.cardanoscan.io", + "port": 3101 } ] }, { - "accumulatedStake": 0.8792606337400546, - "relativeStake": 0.0006855637271387668, + "accumulatedStake": 0.8849646263605836, + "relativeStake": 0.0006441003735024348, "relays": [ { - "address": "r1.relaypool.online", - "port": 3000 + "address": "135.181.194.233", + "port": 6000 + }, + { + "address": "168.119.101.200", + "port": 6000 } ] }, { - "accumulatedStake": 0.8799394916056629, - "relativeStake": 0.0006788578656083666, + "accumulatedStake": 0.8856048884855499, + "relativeStake": 0.0006402621249661656, "relays": [ { - "address": "190.61.192.34", + "address": "178.128.79.219", "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.8806139336982663, - "relativeStake": 0.0006744420926033827, - "relays": [ + }, { - "address": "private-pools.fivebinaries.com", + "address": "104.131.122.73", "port": 3001 } ] }, { - "accumulatedStake": 0.8812818634256543, - "relativeStake": 0.0006679297273879275, + "accumulatedStake": 0.8862414893650015, + "relativeStake": 0.0006366008794516403, "relays": [ { - "address": "0.180.117.137", - "port": 16112 - }, - { - "address": "196.178.52.20", - "port": 16112 + "address": "r1.cosd.com", + "port": 5250 }, { - "address": "47.187.152.52", - "port": 16112 + "address": "r2.cosd.com", + "port": 5250 } ] }, { - "accumulatedStake": 0.8819491627526421, - "relativeStake": 0.0006672993269879374, + "accumulatedStake": 0.8868716470151045, + "relativeStake": 0.0006301576501030076, "relays": [ { - "address": "relay1.powerstakepool.com", + "address": "relay1.thevikingpool.com", "port": 6000 }, { - "address": "relay2.powerstakepool.com", + "address": "relay2.thevikingpool.com", "port": 6000 } ] }, { - "accumulatedStake": 0.8826090367210562, - "relativeStake": 0.0006598739684140259, + "accumulatedStake": 0.8874979717723022, + "relativeStake": 0.0006263247571977651, "relays": [ { - "address": "relay1.pudim.cat", - "port": 3002 - }, - { - "address": "relay2.pudim.cat", - "port": 3002 + "address": "85.131.244.123", + "port": 6000 } ] }, { - "accumulatedStake": 0.8832656764225254, - "relativeStake": 0.0006566397014691837, + "accumulatedStake": 0.8881201121303727, + "relativeStake": 0.0006221403580704902, "relays": [ { "address": "relay-1.banderini.net", @@ -6319,22 +6365,8 @@ ] }, { - "accumulatedStake": 0.8839214661854473, - "relativeStake": 0.0006557897629219609, - "relays": [ - { - "address": "128.77.150.54", - "port": 6000 - }, - { - "address": "248.226.72.35", - "port": 6000 - } - ] - }, - { - "accumulatedStake": 0.8845710344651533, - "relativeStake": 0.0006495682797059579, + "accumulatedStake": 0.8887391074050025, + "relativeStake": 0.0006189952746298252, "relays": [ { "address": "germany.cardanode.io", @@ -6355,189 +6387,189 @@ ] }, { - "accumulatedStake": 0.8852181782135868, - "relativeStake": 0.0006471437484335537, + "accumulatedStake": 0.8893495019957984, + "relativeStake": 0.0006103945907958921, "relays": [ { - "address": "134.228.245.157", - "port": 3001 - }, - { - "address": "164.120.89.159", + "address": "relay-kiln-3-0.cardano.mainnet.kiln.fi", "port": 3001 }, { - "address": "44.186.97.209", + "address": "relay-kiln-3-1.cardano.mainnet.kiln.fi", "port": 3001 }, { - "address": "eu.bloompool.io", + "address": "relay-kiln-3-2.cardano.mainnet.kiln.fi", "port": 3001 } ] }, { - "accumulatedStake": 0.8858648642554103, - "relativeStake": 0.0006466860418234723, + "accumulatedStake": 0.8899583857542555, + "relativeStake": 0.0006088837584569803, "relays": [ { - "address": "asia-pacific-japan.popsp.net", - "port": 3001 + "address": "relay1.powerstakepool.com", + "port": 6000 + }, + { + "address": "relay2.powerstakepool.com", + "port": 6000 } ] }, { - "accumulatedStake": 0.8865104790962086, - "relativeStake": 0.0006456148407982857, + "accumulatedStake": 0.8905655136788971, + "relativeStake": 0.0006071279246417523, "relays": [ { - "address": "csn.relay1.cardanoscan.io", - "port": 3101 + "address": "cardano-relays-1.nu.fi", + "port": 3003 }, { - "address": "csn.relay2.cardanoscan.io", - "port": 3101 + "address": "cardano-relays-2.nu.fi", + "port": 3001 } ] }, { - "accumulatedStake": 0.8871560765804258, - "relativeStake": 0.0006455974842171969, + "accumulatedStake": 0.891168213125595, + "relativeStake": 0.0006026994466978245, "relays": [ { - "address": "relay1-ada.cex.io", - "port": 3001 - }, - { - "address": "relay2-ada.cex.io", - "port": 3002 + "address": "202.61.225.111", + "port": 6000 }, { - "address": "relay3-ada.cex.io", - "port": 3003 + "address": "46.38.241.110", + "port": 6000 } ] }, { - "accumulatedStake": 0.8878010941772536, - "relativeStake": 0.0006450175968278112, + "accumulatedStake": 0.8917693209698935, + "relativeStake": 0.0006011078442984997, "relays": [ { - "address": "118.91.195.51", + "address": "157.245.228.134", "port": 3001 }, { - "address": "246.35.161.51", + "address": "159.89.120.164", "port": 3001 }, { - "address": "178.123.12.49", + "address": "209.97.186.44", "port": 3001 }, { - "address": "124.58.217.95", + "address": "eu.bloompool.io", "port": 3001 } ] }, { - "accumulatedStake": 0.8884425611085728, - "relativeStake": 0.0006414669313191455, + "accumulatedStake": 0.8923696724916317, + "relativeStake": 0.0006003515217382172, "relays": [ { - "address": "r1.cosd.com", - "port": 5250 + "address": "143.198.206.176", + "port": 6000 }, { - "address": "r2.cosd.com", - "port": 5250 + "address": "207.154.201.62", + "port": 6000 } ] }, { - "accumulatedStake": 0.8890749204830674, - "relativeStake": 0.0006323593744945571, + "accumulatedStake": 0.8929637870965458, + "relativeStake": 0.0005941146049140991, "relays": [ { - "address": "249.73.25.223", - "port": 6452 + "address": "relay1.nedscave.io", + "port": 3001 }, { - "address": "30.147.199.128", - "port": 6001 + "address": "relay2.nedscave.io", + "port": 3001 + }, + { + "address": "relay3.nedscave.io", + "port": 3001 }, { - "address": "199.141.140.158", - "port": 8082 + "address": "relay4.nedscave.io", + "port": 3001 } ] }, { - "accumulatedStake": 0.88970630547916, - "relativeStake": 0.0006313849960926384, + "accumulatedStake": 0.8935560172716995, + "relativeStake": 0.0005922301751537731, "relays": [ { - "address": "r1.1percentpool.eu", - "port": 19001 + "address": "r1.adaism.uk", + "port": 8081 }, { - "address": "r2.1percentpool.eu", - "port": 19002 + "address": "r2.adaism.uk", + "port": 8081 } ] }, { - "accumulatedStake": 0.8903327162385161, - "relativeStake": 0.0006264107593560782, + "accumulatedStake": 0.8941472277760614, + "relativeStake": 0.0005912105043617867, "relays": [ { - "address": "relay1.squidpool.com", - "port": 3001 - }, - { - "address": "relay2.squidpool.com", - "port": 3001 + "address": "cardano-relays.atomicwallet.io", + "port": 6001 } ] }, { - "accumulatedStake": 0.8909568899208459, - "relativeStake": 0.000624173682329841, + "accumulatedStake": 0.8947379377272121, + "relativeStake": 0.0005907099511507605, "relays": [ { - "address": "105.cardano.staked.cloud", + "address": "relay1.squidpool.com", + "port": 3001 + }, + { + "address": "relay2.squidpool.com", "port": 3001 } ] }, { - "accumulatedStake": 0.8915767624924168, - "relativeStake": 0.0006198725715708883, + "accumulatedStake": 0.8953263111646639, + "relativeStake": 0.000588373437451719, "relays": [ { - "address": "174.147.215.85", + "address": "133.167.33.31", "port": 6000 }, { - "address": "104.187.215.85", + "address": "162.43.71.205", "port": 6000 } ] }, { - "accumulatedStake": 0.8921960747223038, - "relativeStake": 0.0006193122298870549, + "accumulatedStake": 0.8959101178610719, + "relativeStake": 0.000583806696407999, "relays": [ { - "address": "134.228.245.157", + "address": "157.245.228.134", "port": 3001 }, { - "address": "164.120.89.159", + "address": "159.89.120.164", "port": 3001 }, { - "address": "44.186.97.209", + "address": "209.97.186.44", "port": 3001 }, { @@ -6547,32 +6579,28 @@ ] }, { - "accumulatedStake": 0.8928102040458157, - "relativeStake": 0.0006141293235119068, + "accumulatedStake": 0.896491062115562, + "relativeStake": 0.0005809442544901618, "relays": [ { - "address": "176.206.198.143", - "port": 6000 - }, - { - "address": "62.201.154.207", - "port": 6000 + "address": "relay.armadastakepool.com", + "port": 5100 } ] }, { - "accumulatedStake": 0.8934166889096012, - "relativeStake": 0.0006064848637854658, + "accumulatedStake": 0.8970675076857241, + "relativeStake": 0.0005764455701621103, "relays": [ { - "address": "private-pools.fivebinaries.com", + "address": "europe1-relay.jpn-sp.net", "port": 3001 } ] }, { - "accumulatedStake": 0.8940224802433974, - "relativeStake": 0.0006057913337961961, + "accumulatedStake": 0.8976425614580322, + "relativeStake": 0.0005750537723081276, "relays": [ { "address": "cardano-relays-1.nu.fi", @@ -6585,144 +6613,67 @@ ] }, { - "accumulatedStake": 0.8946262894314935, - "relativeStake": 0.0006038091880960784, - "relays": [ - { - "address": "europe1-relay.jpn-sp.net", - "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.89522590159576, - "relativeStake": 0.0005996121642665353, + "accumulatedStake": 0.8982176070281876, + "relativeStake": 0.0005750455701554285, "relays": [ { - "address": "111.225.61.202", - "port": 6000 + "address": "relays.staking4ada.org", + "port": 1818 }, { - "address": "110.241.38.46", - "port": 6000 + "address": "globecast.staking4ada.org", + "port": 6061 } ] }, { - "accumulatedStake": 0.8958246865282061, - "relativeStake": 0.0005987849324461718, + "accumulatedStake": 0.8987897211241973, + "relativeStake": 0.0005721140960095958, "relays": [ { - "address": "cardano-relays-1.nu.fi", - "port": 3003 + "address": "relay1-pub.ahlnet.nu", + "port": 2111 }, { - "address": "cardano-relays-2.nu.fi", - "port": 3001 - } - ] - }, - { - "accumulatedStake": 0.8964210822129903, - "relativeStake": 0.0005963956847841941, - "relays": [ - { - "address": "relay.armadastakepool.com", - "port": 5100 - } - ] - }, - { - "accumulatedStake": 0.8970159328719124, - "relativeStake": 0.0005948506589220541, - "relays": [ - { - "address": "relay-kiln-3-0.cardano.mainnet.kiln.fi", - "port": 3001 + "address": "relay2-pub.ahlnet.nu", + "port": 2111 }, { - "address": "relay-kiln-3-1.cardano.mainnet.kiln.fi", - "port": 3001 + "address": "relay3-pub.ahlnet.nu", + "port": 2111 }, { - "address": "relay-kiln-3-2.cardano.mainnet.kiln.fi", - "port": 3001 + "address": "relay-fallback.ahlnet.nu", + "port": 55218 } ] }, { - "accumulatedStake": 0.8976079775264847, - "relativeStake": 0.0005920446545722655, + "accumulatedStake": 0.8993611830491409, + "relativeStake": 0.0005714619249437082, "relays": [ { - "address": "21.105.167.89", - "port": 6000 + "address": "cardano-relays-1.nu.fi", + "port": 3003 }, { - "address": "250.110.104.178", - "port": 6000 - } - ] - }, - { - "accumulatedStake": 0.8981993783317063, - "relativeStake": 0.0005914008052215263, - "relays": [ - { - "address": "r1.isp-r1.wjg.jp", + "address": "cardano-relays-2.nu.fi", "port": 3001 - }, - { - "address": "r2.isp-r1.wjg.jp", - "port": 3002 - } - ] - }, - { - "accumulatedStake": 0.89878091014264, - "relativeStake": 0.0005815318109338587, - "relays": [ - { - "address": "cardano-relays.atomicwallet.io", - "port": 6001 - } - ] - }, - { - "accumulatedStake": 0.899360192105775, - "relativeStake": 0.0005792819631349694, - "relays": [ - { - "address": "bra-relay.cardanistas.io", - "port": 8081 - }, - { - "address": "usa-relay.cardanistas.io", - "port": 8082 - }, - { - "address": "de-relay.cardanistas.io", - "port": 8083 } ] }, { - "accumulatedStake": 0.8999364519626906, - "relativeStake": 0.0005762598569154913, + "accumulatedStake": 0.8999316278793225, + "relativeStake": 0.0005704448301815358, "relays": [ { - "address": "re1.reservoir.network", - "port": 3001 - }, - { - "address": "re2.reservoir.network", - "port": 3001 + "address": "relay-pool-figment-4-mainnet.cardano.aeq5f.com" } ] }, { - "accumulatedStake": 0.9005070719308936, - "relativeStake": 0.0005706199682030543, + "accumulatedStake": 0.9004963876689663, + "relativeStake": 0.0005647597896438093, "relays": [ { "address": "cardano-relays-1.nu.fi", diff --git a/configuration/cardano/mainnet-topology.json b/configuration/cardano/mainnet-topology.json index 7f400d02136..4019031eebc 100644 --- a/configuration/cardano/mainnet-topology.json +++ b/configuration/cardano/mainnet-topology.json @@ -24,5 +24,5 @@ "advertise": false } ], - "useLedgerAfterSlot": 194140785 + "useLedgerAfterSlot": 200620811 } diff --git a/configuration/cardano/testnet-template-config.json b/configuration/cardano/testnet-template-config.json index 960e8af3718..b219cb4315e 100644 --- a/configuration/cardano/testnet-template-config.json +++ b/configuration/cardano/testnet-template-config.json @@ -13,6 +13,8 @@ "Backend": "V2InMemory", "QueryBatchSize": 100000, "Snapshots": { + "MaxDelay": 1080, + "MinDelay": 300, "NumOfDiskSnapshots": 2, "SlotOffset": 0, "SnapshotInterval": 4320 @@ -26,8 +28,7 @@ "TestMaryHardForkAtEpoch": 0, "TestShelleyHardForkAtEpoch": 0, "TraceOptionForwarder": { - "connQueueSize": 64, - "disconnQueueSize": 128, + "queueSize": 128, "maxReconnectDelay": 30 }, "TraceOptionMetricsPrefix": "cardano.node.metrics.", @@ -100,6 +101,9 @@ "Net.Mux.Remote": { "severity": "Info" }, + "Net.Mux.Remote.Bearer": { + "severity": "Silence" + }, "Net.PeerSelection": { "severity": "Info" }, From 5f4426ba08315fd6f9154456aa4fc3e23ca20420 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Sun, 11 Oct 2026 03:12:15 -0500 Subject: [PATCH 29/45] nixosModule: add configFormat to select the generated config dialect The published configs and release artifacts moved to the cardano-config envelope, but the service still writes a flat config. Add configFormat, "legacy" or "enveloped", so consumers can move a host at a time. Enveloping happens last, on the assembled instance config, so nodeConfig, extraNodeConfig and extraNodeInstanceConfig stay flat and keep today's key names. mkEnvelope applies the renames and sections each key. A key it does not recognise is kept outside any section, where the node will not resolve it, so opting a host in is worth checking against its warnings. Ignored when nodeConfigFile is set, so workbench is unaffected. The default stays legacy. --- nix/nixos/cardano-node-service.nix | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/nix/nixos/cardano-node-service.nix b/nix/nixos/cardano-node-service.nix index 38c77e842d1..2c67c81056b 100644 --- a/nix/nixos/cardano-node-service.nix +++ b/nix/nixos/cardano-node-service.nix @@ -79,8 +79,12 @@ let }); in i: let instanceConfig = recursiveUpdate (baseInstanceConfig i) (cfg.extraNodeInstanceConfig i); + publishedConfig = + if cfg.configFormat == "enveloped" + then cfg.cardanoNodePackages.cardanoLib.mkEnvelope instanceConfig + else instanceConfig; nodeConfigFile = if (cfg.nodeConfigFile != null) then cfg.nodeConfigFile - else toFile "config-${toString cfg.nodeId}-${toString i}.json" (toJSON instanceConfig); + else toFile "config-${toString cfg.nodeId}-${toString i}.json" (toJSON publishedConfig); consensusParams = { RealPBFT = [ "${optionalString (cfg.signingKey != null) @@ -792,6 +796,29 @@ in { description = ''The actual configuration file.''; }; + configFormat = mkOption { + type = enum [ + "legacy" + "enveloped" + ]; + default = "legacy"; + description = '' + Which dialect the generated node config file is written in, named as + cardano-config names them. Ignored when nodeConfigFile is set, since + that file is used as given. + + On "enveloped" the config is wrapped with cardanoLib.mkEnvelope at the + end, so nodeConfig, extraNodeConfig and extraNodeInstanceConfig stay + flat and keep the key names they use today. mkEnvelope applies the + cardano-config renames and groups each key under the section that owns + it. A key it does not recognise is kept, but outside any section, + where the node will not resolve it. + + The default stays "legacy" while consumers opt in per host. Published + configs and release artifacts are already enveloped. + ''; + }; + forceHardForks = mkOption { type = attrsOf int; default = {}; From 5022604c7b25617ab7db36c078595fe4d6f65029 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Sun, 11 Oct 2026 04:00:31 -0500 Subject: [PATCH 30/45] nixosModule: warn about config keys enveloping would strand Added warnings, raised at eval time when configFormat is "enveloped", for keys cardano-config will not resolve. Lifted the config assembly out of mkScript to module level so the warnings check the same document that gets written, rather than a second assembly of it. Needs the cardanoLib exports added in iohk-nix: removedKeys, renamedKeys and unrecognisedKeys. --- nix/nixos/cardano-node-service.nix | 92 ++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 29 deletions(-) diff --git a/nix/nixos/cardano-node-service.nix b/nix/nixos/cardano-node-service.nix index 2c67c81056b..92feda1c77a 100644 --- a/nix/nixos/cardano-node-service.nix +++ b/nix/nixos/cardano-node-service.nix @@ -49,36 +49,41 @@ let then "/etc/cardano-node/topology-${toString i}.json" else selectTopology i; + baseConfig = + recursiveUpdate + (cfg.nodeConfig + // (mapAttrs' (era: epoch: + nameValuePair "Test${era}HardForkAtEpoch" epoch + ) cfg.forceHardForks) + // { + MaxConcurrencyBulkSync = 2; + } // optionalAttrs (cfg.targetNumberOfRootPeers != null) { + TargetNumberOfRootPeers = cfg.targetNumberOfRootPeers; + } // optionalAttrs (cfg.targetNumberOfKnownPeers != null) { + TargetNumberOfKnownPeers = cfg.targetNumberOfKnownPeers; + } // optionalAttrs (cfg.targetNumberOfEstablishedPeers != null) { + TargetNumberOfEstablishedPeers = cfg.targetNumberOfEstablishedPeers; + } // optionalAttrs (cfg.targetNumberOfActivePeers != null) { + TargetNumberOfActivePeers = cfg.targetNumberOfActivePeers; + } + ) cfg.extraNodeConfig; + + baseInstanceConfig = + i: + recursiveUpdate + baseConfig (optionalAttrs (cfg.withUtxoHdLsmt i) { + LedgerDB = { + Backend = "V2LSM"; + LSMDatabasePath = cfg.lsmDatabasePath i; + }; + }); + + mkInstanceConfig = i: + recursiveUpdate (baseInstanceConfig i) (cfg.extraNodeInstanceConfig i); + mkScript = cfg: - let baseConfig = - recursiveUpdate - (cfg.nodeConfig - // (mapAttrs' (era: epoch: - nameValuePair "Test${era}HardForkAtEpoch" epoch - ) cfg.forceHardForks) - // { - MaxConcurrencyBulkSync = 2; - } // optionalAttrs (cfg.targetNumberOfRootPeers != null) { - TargetNumberOfRootPeers = cfg.targetNumberOfRootPeers; - } // optionalAttrs (cfg.targetNumberOfKnownPeers != null) { - TargetNumberOfKnownPeers = cfg.targetNumberOfKnownPeers; - } // optionalAttrs (cfg.targetNumberOfEstablishedPeers != null) { - TargetNumberOfEstablishedPeers = cfg.targetNumberOfEstablishedPeers; - } // optionalAttrs (cfg.targetNumberOfActivePeers != null) { - TargetNumberOfActivePeers = cfg.targetNumberOfActivePeers; - } - ) cfg.extraNodeConfig; - baseInstanceConfig = - i: - recursiveUpdate - baseConfig (optionalAttrs (cfg.withUtxoHdLsmt i) { - LedgerDB = { - Backend = "V2LSM"; - LSMDatabasePath = cfg.lsmDatabasePath i; - }; - }); - in i: let - instanceConfig = recursiveUpdate (baseInstanceConfig i) (cfg.extraNodeInstanceConfig i); + i: let + instanceConfig = mkInstanceConfig i; publishedConfig = if cfg.configFormat == "enveloped" then cfg.cardanoNodePackages.cardanoLib.mkEnvelope instanceConfig @@ -1045,6 +1050,35 @@ in { }; } { + # Only keys cardano-config resolves survive enveloping in a section the + # node reads. A stale name still applies, mkEnvelope renames it, and a + # removed key is dropped on purpose, so neither is a fault. Anything else + # is kept outside every section and ignored, which is. Warnings rather + # than assertions for now: a key may be legitimately absent from the + # cardano-config schema, and blocking a deploy on that is worse than + # reporting it. + warnings = let + inherit (cfg.cardanoNodePackages.cardanoLib) + removedKeys renamedKeys unrecognisedKeys; + flagged = unique (concatMap (i: unrecognisedKeys removedKeys (mkInstanceConfig i)) + (genList trivial.id cfg.instances)); + stale = filter (k: renamedKeys ? ${k}) flagged; + unknown = filter (k: !(renamedKeys ? ${k})) flagged; + in optionals (cfg.configFormat == "enveloped") ( + optional (stale != []) '' + services.cardano-node: these config keys have been renamed by cardano-config: + ${concatMapStringsSep "\n" (k: " ${k} -> ${renamedKeys.${k}}") stale} + They still apply, mkEnvelope renames them, but the new names are what + the schema and the published configs use. + '' + ++ optional (unknown != []) '' + services.cardano-node: cardano-config does not resolve these config keys: + ${concatMapStringsSep "\n" (k: " ${k}") unknown} + Enveloping keeps them outside every section, where the node ignores + them. Remove them or check the name against the cardano-config schema. + '' + ); + assertions = [ { assertion = all (i: hasPrefix cfg.stateDirBase (cfg.stateDir i)) (genList trivial.id cfg.instances); From dcf625a9bf70b9f10578fc8e63db95666df43afb Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Sun, 11 Oct 2026 04:27:32 -0500 Subject: [PATCH 31/45] nixosModule: emit the peer target names the selected dialect reads POM reads these only as TargetNumberOf*, cardano-config only as DeadlineTargetNumberOf*. The module emitted the former unconditionally, which mkEnvelope renamed, so an enveloped host warned that four keys were stale when nothing the operator set could change them. --- nix/nixos/cardano-node-service.nix | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/nix/nixos/cardano-node-service.nix b/nix/nixos/cardano-node-service.nix index 92feda1c77a..2588901b7f4 100644 --- a/nix/nixos/cardano-node-service.nix +++ b/nix/nixos/cardano-node-service.nix @@ -49,6 +49,13 @@ let then "/etc/cardano-node/topology-${toString i}.json" else selectTopology i; + # POM reads these only as TargetNumberOf*, cardano-config only as + # DeadlineTargetNumberOf*, so the name depends on the dialect. mkEnvelope + # would rename the legacy spelling, but emitting the one the dialect uses + # keeps the published config canonical and keeps a key the operator cannot + # restate out of the rename warning below. + deadlinePrefix = optionalString (cfg.configFormat == "enveloped") "Deadline"; + baseConfig = recursiveUpdate (cfg.nodeConfig @@ -58,13 +65,13 @@ let // { MaxConcurrencyBulkSync = 2; } // optionalAttrs (cfg.targetNumberOfRootPeers != null) { - TargetNumberOfRootPeers = cfg.targetNumberOfRootPeers; + "${deadlinePrefix}TargetNumberOfRootPeers" = cfg.targetNumberOfRootPeers; } // optionalAttrs (cfg.targetNumberOfKnownPeers != null) { - TargetNumberOfKnownPeers = cfg.targetNumberOfKnownPeers; + "${deadlinePrefix}TargetNumberOfKnownPeers" = cfg.targetNumberOfKnownPeers; } // optionalAttrs (cfg.targetNumberOfEstablishedPeers != null) { - TargetNumberOfEstablishedPeers = cfg.targetNumberOfEstablishedPeers; + "${deadlinePrefix}TargetNumberOfEstablishedPeers" = cfg.targetNumberOfEstablishedPeers; } // optionalAttrs (cfg.targetNumberOfActivePeers != null) { - TargetNumberOfActivePeers = cfg.targetNumberOfActivePeers; + "${deadlinePrefix}TargetNumberOfActivePeers" = cfg.targetNumberOfActivePeers; } ) cfg.extraNodeConfig; From 43fe2d2009ecd647b775f4a86c542692458b02d2 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Sun, 11 Oct 2026 04:39:33 -0500 Subject: [PATCH 32/45] nixosTests/cardanoNodeDbtools: raise the global timeout to 300s globalTimeout bounds the whole test, so 45s had to cover the vm boot plus create-env, synthesis, both analyser passes, truncation and the asserted synthesis. It was raised from 30 to 45 in c310c0d7 and is still tight enough that runner variance can reach it. 300s keeps the override useful for surfacing a hang while leaving room under the one hour framework default. --- nix/nixos/tests/cardano-node-dbtools.nix | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/nix/nixos/tests/cardano-node-dbtools.nix b/nix/nixos/tests/cardano-node-dbtools.nix index 34bf19ef56a..ca86257705d 100644 --- a/nix/nixos/tests/cardano-node-dbtools.nix +++ b/nix/nixos/tests/cardano-node-dbtools.nix @@ -55,12 +55,16 @@ ''; }; - # NixosTest script fns supporting a timeout have a default of 900 seconds. + # Budget for the whole test, not per step: the driver kills everything and + # fails once it is reached. It covers the vm boot as well as create-env, + # synthesis, both analyser passes, truncation and the asserted synthesis, so + # it has to absorb runner variance across all of them. Not to be confused + # with the 900 second default on script fns that take their own timeout, + # which is per call and which nothing here sets. # - # There is no pre-existing history for chain synthesis, and default - # cardano-testnet genesis parameters set epochs to be short and fast, so a 45 - # second global timeout should be more than sufficient. - globalTimeout = 45; + # Kept well under the one hour framework default so a hang still surfaces + # quickly, which is the only reason to override at all. + globalTimeout = 300; testDir = "testnet"; in { From ac8c20e8a8d4552b0d59e35674e43fd26cf73be4 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Sun, 11 Oct 2026 05:07:51 -0500 Subject: [PATCH 33/45] nixosTests/cardanoOciReadonly: cover graceful shutdown Added SIGTERM and SIGINT cases for both ways into the image, scripts mode and custom mode, asserting docker did not have to SIGKILL after the grace period. These were the first four items of the Manual Testing section in nix/docker/README.md, which nobody ran and which predated merge mode, the /tmp runtime dir, read-only root and non-root UIDs. Its fifth item, cli access, is already covered three times here. Dropped the section. Use util-linux rather than the utillinux alias to resolve eval warn. --- nix/docker/README.md | 66 -------------------- nix/docker/default.nix | 4 +- nix/docker/submit-api.nix | 4 +- nix/docker/tracer.nix | 4 +- nix/nixos/tests/cardano-oci-readonly.nix | 76 ++++++++++++++++++++++-- 5 files changed, 77 insertions(+), 77 deletions(-) diff --git a/nix/docker/README.md b/nix/docker/README.md index 3fec8615388..f71cda06b9e 100644 --- a/nix/docker/README.md +++ b/nix/docker/README.md @@ -591,69 +591,3 @@ docker run \ -e CARDANO_CONFIG_JSON_MERGE='{"network":{"contents":["/ipc/node-tracer.socket"],"tag":"ConnectTo"}}' \ ghcr.io/intersectmbo/cardano-tracer:dev ``` - -# Manual Testing -1. Run -e NETWORK=mainnet and check graceful shutdown SIGINT with -it -2. Run -e NETWORK=mainnet and check graceful shutdown SIGTERM with --detach -3. Run without -e NETWORK and check graceful shutdown SIGINT with -it -4. Run without -e NETWORK and check graceful shutdown SIGTERM with --detach -5. Check cardano-cli access - - -## Run with NETWORK -Run -e NETWORK=mainnet and check graceful shutdown SIGINT with -it -``` -docker run --rm -it \ - -p 3001:3001 \ - -e NETWORK=mainnet \ - -v node-data:/data \ - ghcr.io/intersectmbo/cardano-node:dev -``` - -Run -e NETWORK=mainnet and check graceful shutdown SIGTERM with --detach -``` -docker rm -f relay -docker run --detach \ - --name=relay \ - -p 3001:3001 \ - -e NETWORK=mainnet \ - -v node-data:/data \ - ghcr.io/intersectmbo/cardano-node:dev - -docker logs -f relay -``` - - -## Run without NETWORK -Check graceful shutdown SIGINT with -it -``` -docker run --rm -it \ - -p 3001:3001 \ - -v node-data:/data \ - ghcr.io/intersectmbo/cardano-node:dev run -``` - -Check graceful shutdown SIGTERM with --detach -``` -docker rm -f relay -docker run --detach \ - --name=relay \ - -p 3001:3001 \ - -v node-data:/data \ - -v node-ipc:/ipc \ - ghcr.io/intersectmbo/cardano-node:dev run - -docker logs -f relay -``` - - -## Check cardano-cli -Check successful cardano-cli query -``` -alias cardano-cli="docker run \ - --rm -it \ - -v node-ipc:/ipc \ - ghcr.io/intersectmbo/cardano-node:dev cli" - -cardano-cli query tip --mainnet -``` diff --git a/nix/docker/default.nix b/nix/docker/default.nix index 4c8b71c3552..4900e50cec7 100644 --- a/nix/docker/default.nix +++ b/nix/docker/default.nix @@ -38,7 +38,7 @@ , iputils , jq , socat -, utillinux +, util-linux , lib , exe , script @@ -66,7 +66,7 @@ let iputils # Useful utilities for Linux networking jq # Lightweight and flexible command-line JSON processor socat # Utility for bidirectional data transfer - utillinux # System utilities for Linux + util-linux # System utilities for Linux ]; }; diff --git a/nix/docker/submit-api.nix b/nix/docker/submit-api.nix index 142bcc60664..f57e13aeec4 100644 --- a/nix/docker/submit-api.nix +++ b/nix/docker/submit-api.nix @@ -29,7 +29,7 @@ , iproute2 , iputils , socat -, utillinux +, util-linux , writeScriptBin , runtimeShell , lib @@ -56,7 +56,7 @@ let iproute2 # Utilities for controlling TCP/IP networking iputils # Useful utilities for Linux networking socat # Utility for bidirectional data transfer - utillinux # System utilities for Linux + util-linux # System utilities for Linux ]; }; diff --git a/nix/docker/tracer.nix b/nix/docker/tracer.nix index 09fef77f3a6..fa7329defcf 100644 --- a/nix/docker/tracer.nix +++ b/nix/docker/tracer.nix @@ -33,7 +33,7 @@ , iputils , jq , socat -, utillinux +, util-linux , lib , exe , script @@ -60,7 +60,7 @@ let iputils # Useful utilities for Linux networking jq # Lightweight and flexible command-line JSON processor socat # Utility for bidirectional data transfer - utillinux # System utilities for Linux + util-linux # System utilities for Linux ]; }; diff --git a/nix/nixos/tests/cardano-oci-readonly.nix b/nix/nixos/tests/cardano-oci-readonly.nix index c389151e096..194c448609a 100644 --- a/nix/nixos/tests/cardano-oci-readonly.nix +++ b/nix/nixos/tests/cardano-oci-readonly.nix @@ -18,7 +18,13 @@ # triggers the /tmp runtime dir + relative-path rewriting. The double quotes # are backslash-escaped because these are interpolated into double-quoted # Python string literals in the testScript below. - configMerge = ''{\"MaxConcurrencyBulkSync\":2}''; + # + # The node config merge is section qualified because the published config is + # in the cardano-config envelope. A merge is a deep merge with no key + # relocation, so the flat spelling would add a key outside Configuration that + # the node does not resolve, which is the shape the docker readme warns + # about. Topology and tracer configs are not enveloped and stay flat. + configMerge = ''{\"Configuration\":{\"Network\":{\"MaxConcurrencyBulkSync\":2}}}''; topologyMerge = ''{\"useLedgerAfterSlot\":1}''; tracerConfigMerge = ''{\"verbosity\":\"Minimum\"}''; @@ -81,12 +87,15 @@ in { # The merged config's relative "*File" references (ByronGenesisFile, # ShelleyGenesisFile, ..., CheckpointsFile) must be rewritten to absolute - # paths so they resolve from /tmp. Mirror the entrypoint's predicate -- any - # top-level key ending in "File" with a string value -- and assert all are - # absolute. Use jq from the container. + # paths so they resolve from /tmp. Mirror the entrypoint's predicate, which + # walks rather than reading the top level: in the cardano-config envelope + # these keys sit under Configuration.
, so a top-level scan finds + # none of them. The length guard is what makes that a failure rather than a + # vacuous pass, so keep it. Use jq from the container. machine.succeed( "docker exec n1 jq -e " - "'[to_entries[]|select(.key|endswith(\"File\"))|.value|select(type==\"string\")] as $v " + "'[..|objects|to_entries[]|select((.key|endswith(\"File\")) " + "and (.value|type==\"string\"))|.value] as $v " "| ($v|length>0) and ($v|all(startswith(\"/\")))' " "${rt}/config-merged.json" ) @@ -217,5 +226,62 @@ in { # so it only needs to execute under --read-only and as non-root. machine.succeed("docker load -i ${submitApiDockerImage}") machine.succeed("docker run --rm --read-only --user 1000:0 ${submitApiImageRef} --help >/dev/null") + + # Graceful shutdown on SIGTERM and SIGINT, for both ways in. + # + # Each mode execs the whole way down to cardano-node, so the node is the + # container's pid 1 and takes the signal itself: scripts mode goes + # entrypoint -> run-network -> the per-network script -> exec node, custom + # mode goes entrypoint -> run-node -> exec node. Drop any one of those + # execs and a shell sits at pid 1 forwarding nothing, docker gives up after + # the grace period and SIGKILLs, and the exit code is 137. That is what + # this asserts against rather than a specific clean code, which differs by + # whether the node handles the signal or dies from it. + def shutdown_case(name, args, sig): + # /logs must be a writable mount: the image bakes + # `-t/logs/cardano-node.stats` into its RTS block, and the node aborts + # at startup if it cannot open that file under a read-only root. + machine.succeed( + "docker run -d --name " + name + " --read-only --tmpfs /tmp " + "--user 1000:0 -v " + name + "data:/data -v " + name + "ipc:/ipc " + "-v " + name + "logs:/logs " + args + ) + # Long enough to be past config resolution and into the node proper, + # so the signal lands on a running node rather than on startup. + machine.sleep(10) + if machine.succeed( + "docker inspect -f '{{.State.Running}}' " + name + ).strip() != "true": + _, logs = machine.execute("docker logs " + name + " 2>&1") + raise Exception( + name + " exited before the shutdown signal; docker logs:\n" + logs + ) + + if sig == "TERM": + # Sends SIGTERM, waits, then SIGKILLs if it outlives the grace period. + machine.succeed("docker stop -t 30 " + name) + else: + # docker kill does not wait, so poll for the exit ourselves. + machine.succeed("docker kill --signal=INT " + name) + machine.wait_until_succeeds( + "[ \"$(docker inspect -f '{{.State.Running}}' " + name + ")\" = false ]", + timeout=40, + ) + + code = machine.succeed( + "docker inspect -f '{{.State.ExitCode}}' " + name + ).strip() + if code == "137": + _, logs = machine.execute("docker logs " + name + " 2>&1") + raise Exception( + name + ": SIG" + sig + " did not stop the node, docker had to " + "SIGKILL it after the grace period; docker logs:\n" + logs + ) + machine.succeed("docker rm -f " + name) + + shutdown_case("sd1", "-e NETWORK=${network} ${imageRef}", "TERM") + shutdown_case("sd2", "-e NETWORK=${network} ${imageRef}", "INT") + shutdown_case("sd3", "${imageRef} run", "TERM") + shutdown_case("sd4", "${imageRef} run", "INT") ''; } From ac3e39de826b3c919667cab0c5a4a4aa25f75574 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Sun, 11 Oct 2026 06:00:51 -0500 Subject: [PATCH 34/45] nixosTests: add submit-api startup coverage, rename to cardanoOci Added a submit-api subtest covering scripts mode startup and a metrics scrape. Renamed cardanoOciReadonly to cardanoOci. The test has covered more than read-only roots since its second commit and the name described only the first. Grouped the stages into subtests so a failure names its concern rather than a line number. Kept as one test: the shared cost is the vm, the docker daemon and four image loads, which a split would pay per test. All eleven subtests pass in ~120s. --- nix/nixos/tests/cardano-oci-readonly.nix | 287 -------------------- nix/nixos/tests/cardano-oci.nix | 329 +++++++++++++++++++++++ nix/nixos/tests/default.nix | 14 +- 3 files changed, 336 insertions(+), 294 deletions(-) delete mode 100644 nix/nixos/tests/cardano-oci-readonly.nix create mode 100644 nix/nixos/tests/cardano-oci.nix diff --git a/nix/nixos/tests/cardano-oci-readonly.nix b/nix/nixos/tests/cardano-oci-readonly.nix deleted file mode 100644 index 194c448609a..00000000000 --- a/nix/nixos/tests/cardano-oci-readonly.nix +++ /dev/null @@ -1,287 +0,0 @@ -{ - pkgs, - dockerImage, - tracerDockerImage, - submitApiDockerImage, - ... -}: let - inherit (pkgs) lib; - - # Image refs as `docker load` will tag them (repoName:gitrev). - imageRef = "${dockerImage.imageName}:${dockerImage.imageTag}"; - tracerImageRef = "${tracerDockerImage.imageName}:${tracerDockerImage.imageTag}"; - submitApiImageRef = "${submitApiDockerImage.imageName}:${submitApiDockerImage.imageTag}"; - - network = "preview"; - - # Harmless merge keys, present only to exercise merge mode which is what - # triggers the /tmp runtime dir + relative-path rewriting. The double quotes - # are backslash-escaped because these are interpolated into double-quoted - # Python string literals in the testScript below. - # - # The node config merge is section qualified because the published config is - # in the cardano-config envelope. A merge is a deep merge with no key - # relocation, so the flat spelling would add a key outside Configuration that - # the node does not resolve, which is the shape the docker readme warns - # about. Topology and tracer configs are not enveloped and stay flat. - configMerge = ''{\"Configuration\":{\"Network\":{\"MaxConcurrencyBulkSync\":2}}}''; - topologyMerge = ''{\"useLedgerAfterSlot\":1}''; - tracerConfigMerge = ''{\"verbosity\":\"Minimum\"}''; - - rt = "/tmp/cardano-node"; - tracerRt = "/tmp/cardano-tracer"; -in { - name = "cardano-oci-readonly-test"; - - nodes = { - machine = {...}: { - nixpkgs.pkgs = pkgs; - - # Room for loading three images (node, tracer, submit-api) + overlay + - # a starting node/tracer. - virtualisation.diskSize = 10240; - virtualisation.memorySize = 4096; - virtualisation.docker.enable = true; - - # Keep dhcpcd off docker's ephemeral interfaces. Starting and stopping - # containers churns veth pairs, dhcpcd tries to manage each one, and - # dhcpcd 10.3.1 segfaults probing one for an IPv4LL address. Harmless to - # the assertions but it core dumps and buries real errors in the log. - networking.dhcpcd.denyInterfaces = ["veth*" "docker0"]; - }; - }; - - # Like the other tests here, this is sandboxed: the node cannot sync, but it - # starts and resolves its configuration, which is all these assertions need. - testScript = '' - start_all() - machine.wait_for_unit("multi-user.target") - machine.wait_until_succeeds("docker info", timeout=120) - machine.succeed("docker load -i ${dockerImage}") - - # Read-only root + non-root UID in group 0 + merge mode. Asserts the - # container starts as read-only and group-0 volume writes work, creates its - # fixed 0700 runtime dir, writes the merged config with absolute genesis - # paths, writes the env snapshot, and the /usr/local/bin/env alias sources - # it. - machine.succeed( - "docker run -d --name n1 --read-only --tmpfs /tmp --user 1000:0 " - "-v n1data:/data -v n1ipc:/ipc -v n1logs:/logs " - "-e NETWORK=${network} " - "-e CARDANO_CONFIG_JSON_MERGE='${configMerge}' " - "-e CARDANO_TOPOLOGY_JSON_MERGE='${topologyMerge}' " - "${imageRef}" - ) - - # The runtime artifacts are written by the entrypoint/run-node before the - # node execs, so they appear shortly after start. Waiting on the env - # snapshot also confirms the container did not crash under --read-only and - # --user since `docker exec` fails against an exited container. - machine.wait_until_succeeds("docker exec n1 test -f ${rt}/env", timeout=60) - machine.succeed("[ \"$(docker inspect -f '{{.State.Running}}' n1)\" = true ]") - - machine.succeed("docker exec n1 test -d ${rt}") - machine.succeed("docker exec n1 sh -c '[ \"$(stat -c %a ${rt})\" = 700 ]'") - machine.succeed("docker exec n1 test -f ${rt}/config-merged.json") - machine.succeed("docker exec n1 test -f ${rt}/topology-merged.json") - - # The merged config's relative "*File" references (ByronGenesisFile, - # ShelleyGenesisFile, ..., CheckpointsFile) must be rewritten to absolute - # paths so they resolve from /tmp. Mirror the entrypoint's predicate, which - # walks rather than reading the top level: in the cardano-config envelope - # these keys sit under Configuration.
, so a top-level scan finds - # none of them. The length guard is what makes that a failure rather than a - # vacuous pass, so keep it. Use jq from the container. - machine.succeed( - "docker exec n1 jq -e " - "'[..|objects|to_entries[]|select((.key|endswith(\"File\")) " - "and (.value|type==\"string\"))|.value] as $v " - "| ($v|length>0) and ($v|all(startswith(\"/\")))' " - "${rt}/config-merged.json" - ) - - # The merged topology's relative peerSnapshotFile must likewise be rewritten - # to an absolute path. - machine.succeed( - "docker exec n1 jq -e " - "'(.peerSnapshotFile|type==\"string\") and (.peerSnapshotFile|startswith(\"/\"))' " - "${rt}/topology-merged.json" - ) - - # The env snapshot is POSIX-sourceable; use sh and `.` to load it and - # confirm it populated the env. - machine.succeed( - "docker exec --user 1000:0 n1 sh -c " - "'. /usr/local/bin/env && [ -n \"$CARDANO_CONFIG\" ]'" - ) - machine.succeed("docker rm -f n1") - - # The runtime dir is a fixed path, so two same-role containers sharing one - # /tmp would otherwise both write it and the last writer would win. Both - # containers here run as the default root, i.e. the same UID, which is the - # case the directory ownership check cannot catch on its own. - machine.succeed( - "docker run -d --name s1 -v shtmp:/tmp " - "-v s1data:/data -v s1ipc:/ipc -v s1logs:/logs " - "-e NETWORK=${network} " - "-e CARDANO_CONFIG_JSON_MERGE='${configMerge}' " - "${imageRef}" - ) - machine.wait_until_succeeds("docker exec s1 test -f ${rt}/env", timeout=60) - - status, out = machine.execute( - "docker run --rm -v shtmp:/tmp -e NETWORK=${network} ${imageRef} 2>&1" - ) - assert status != 0, f"expected non-zero exit for a shared /tmp; got: {out}" - assert "is in use by another container" in out, f"missing lock error; got: {out}" - - # Once the holder is gone the lock is released, so the same volume, now - # carrying a stale runtime dir, must still be usable. This is what separates - # the lock from a blanket refusal whenever the directory already exists. - machine.succeed("docker rm -f s1") - machine.succeed( - "docker run -d --name s2 -v shtmp:/tmp " - "-v s2data:/data -v s2ipc:/ipc -v s2logs:/logs " - "-e NETWORK=${network} " - "-e CARDANO_CONFIG_JSON_MERGE='${configMerge}' " - "${imageRef}" - ) - machine.wait_until_succeeds("docker exec s2 test -f ${rt}/env", timeout=60) - machine.succeed("docker rm -f s2") - - # Read-only root WITHOUT a writable /tmp must fail fast with guidance. - status, out = machine.execute( - "docker run --rm --read-only -e NETWORK=${network} ${imageRef} 2>&1" - ) - assert status != 0, "expected non-zero exit when /tmp is not writable" - assert "/tmp is not writable" in out, f"missing actionable /tmp error; got: {out}" - - # Cli mode must NOT require a writable /tmp (read-only, no tmpfs). - machine.succeed("docker run --rm --read-only ${imageRef} cli version") - - # Cli mode is dispatched before the NETWORK modes, so a NETWORK left in the - # environment, with or without a merge var, must neither start a node nor - # reach the merge block, which writes to the runtime dir cli mode skips. - machine.succeed( - "docker run --rm --read-only -e NETWORK=${network} ${imageRef} cli version" - ) - machine.succeed( - "docker run --rm --read-only -e NETWORK=${network} " - "-e CARDANO_CONFIG_JSON_MERGE='${configMerge}' ${imageRef} cli version" - ) - - # Operator-supplied RTS flags are appended after the image's baked +RTS - # block and merge with it. `-po` covers .prof, .hp and .ticky only, so an - # eventlog without its own `-ol` is created in the container cwd (/) and the - # RTS aborts before main under a read-only root. /logs must be a writable - # mount here or the baked `-t/logs/cardano-node.stats` aborts first, which - # would pass the exit-code check for the wrong reason. - status, out = machine.execute( - "docker run --rm --read-only --tmpfs /tmp -v e0logs:/logs " - "-e NETWORK=${network} ${imageRef} +RTS -l -RTS 2>&1" - ) - assert status != 0, f"expected non-zero exit for -l without -ol; got: {out}" - assert "initEventLogFileWriter" in out, f"expected an eventlog open failure; got: {out}" - - # Given `-ol` under a writable mount it starts and writes the eventlog there. - machine.succeed( - "docker run -d --name e1 --read-only --tmpfs /tmp --user 1000:0 " - "-v e1data:/data -v e1ipc:/ipc -v e1logs:/logs " - "-e NETWORK=${network} " - "${imageRef} +RTS -l -ol/logs/cardano-node.eventlog -RTS" - ) - machine.wait_until_succeeds( - "docker exec e1 test -s /logs/cardano-node.eventlog", timeout=60 - ) - machine.succeed("docker rm -f e1") - - # Tracer image: same read-only + non-root + merge-mode behavior as the - # node, minus the genesis/topology rewrites as tracer config has no - # relative file references. - machine.succeed("docker load -i ${tracerDockerImage}") - machine.succeed( - "docker run -d --name t1 --read-only --tmpfs /tmp --user 1000:0 " - "-v t1data:/data -v t1ipc:/ipc -v t1logs:/logs " - "-e NETWORK=${network} " - "-e CARDANO_CONFIG_JSON_MERGE='${tracerConfigMerge}' " - "${tracerImageRef}" - ) - # Give the entrypoint time to write artifacts and exec the tracer. If the - # container exits early, surface its logs rather than failing later with an - # opaque `docker exec` timeout against a dead container. - machine.sleep(10) - if machine.succeed("docker inspect -f '{{.State.Running}}' t1").strip() != "true": - _, logs = machine.execute("docker logs t1 2>&1") - raise Exception("tracer container exited early; docker logs:\n" + logs) - machine.succeed("docker exec t1 sh -c '[ \"$(stat -c %a ${tracerRt})\" = 700 ]'") - machine.succeed("docker exec t1 test -f ${tracerRt}/tracer-config-merged.json") - machine.succeed("docker exec t1 test -f ${tracerRt}/env") - machine.succeed( - "docker exec --user 1000:0 t1 sh -c " - "'. /usr/local/bin/env && [ -n \"$CARDANO_CONFIG\" ]'" - ) - machine.succeed("docker rm -f t1") - - # Submit-api image: stateless (no env snapshot / merge / state writes), - # so it only needs to execute under --read-only and as non-root. - machine.succeed("docker load -i ${submitApiDockerImage}") - machine.succeed("docker run --rm --read-only --user 1000:0 ${submitApiImageRef} --help >/dev/null") - - # Graceful shutdown on SIGTERM and SIGINT, for both ways in. - # - # Each mode execs the whole way down to cardano-node, so the node is the - # container's pid 1 and takes the signal itself: scripts mode goes - # entrypoint -> run-network -> the per-network script -> exec node, custom - # mode goes entrypoint -> run-node -> exec node. Drop any one of those - # execs and a shell sits at pid 1 forwarding nothing, docker gives up after - # the grace period and SIGKILLs, and the exit code is 137. That is what - # this asserts against rather than a specific clean code, which differs by - # whether the node handles the signal or dies from it. - def shutdown_case(name, args, sig): - # /logs must be a writable mount: the image bakes - # `-t/logs/cardano-node.stats` into its RTS block, and the node aborts - # at startup if it cannot open that file under a read-only root. - machine.succeed( - "docker run -d --name " + name + " --read-only --tmpfs /tmp " - "--user 1000:0 -v " + name + "data:/data -v " + name + "ipc:/ipc " - "-v " + name + "logs:/logs " + args - ) - # Long enough to be past config resolution and into the node proper, - # so the signal lands on a running node rather than on startup. - machine.sleep(10) - if machine.succeed( - "docker inspect -f '{{.State.Running}}' " + name - ).strip() != "true": - _, logs = machine.execute("docker logs " + name + " 2>&1") - raise Exception( - name + " exited before the shutdown signal; docker logs:\n" + logs - ) - - if sig == "TERM": - # Sends SIGTERM, waits, then SIGKILLs if it outlives the grace period. - machine.succeed("docker stop -t 30 " + name) - else: - # docker kill does not wait, so poll for the exit ourselves. - machine.succeed("docker kill --signal=INT " + name) - machine.wait_until_succeeds( - "[ \"$(docker inspect -f '{{.State.Running}}' " + name + ")\" = false ]", - timeout=40, - ) - - code = machine.succeed( - "docker inspect -f '{{.State.ExitCode}}' " + name - ).strip() - if code == "137": - _, logs = machine.execute("docker logs " + name + " 2>&1") - raise Exception( - name + ": SIG" + sig + " did not stop the node, docker had to " - "SIGKILL it after the grace period; docker logs:\n" + logs - ) - machine.succeed("docker rm -f " + name) - - shutdown_case("sd1", "-e NETWORK=${network} ${imageRef}", "TERM") - shutdown_case("sd2", "-e NETWORK=${network} ${imageRef}", "INT") - shutdown_case("sd3", "${imageRef} run", "TERM") - shutdown_case("sd4", "${imageRef} run", "INT") - ''; -} diff --git a/nix/nixos/tests/cardano-oci.nix b/nix/nixos/tests/cardano-oci.nix new file mode 100644 index 00000000000..477c9280e14 --- /dev/null +++ b/nix/nixos/tests/cardano-oci.nix @@ -0,0 +1,329 @@ +{ + pkgs, + dockerImage, + tracerDockerImage, + submitApiDockerImage, + ... +}: let + inherit (pkgs) lib; + + # Image refs as `docker load` will tag them (repoName:gitrev). + imageRef = "${dockerImage.imageName}:${dockerImage.imageTag}"; + tracerImageRef = "${tracerDockerImage.imageName}:${tracerDockerImage.imageTag}"; + submitApiImageRef = "${submitApiDockerImage.imageName}:${submitApiDockerImage.imageTag}"; + + # The metricsPort default of services.cardano-submit-api, which the image + # does not override. See nix/pkgs.nix submitApiDockerImage defaultConfig, + # which sets only socketPath and listenAddress. + submitApiMetricsPort = 8081; + + network = "preview"; + + # Harmless merge keys, present only to exercise merge mode which is what + # triggers the /tmp runtime dir + relative-path rewriting. The double quotes + # are backslash-escaped because these are interpolated into double-quoted + # Python string literals in the testScript below. + # + # The node config merge is section qualified because the published config is + # in the cardano-config envelope. A merge is a deep merge with no key + # relocation, so the flat spelling would add a key outside Configuration that + # the node does not resolve, which is the shape the docker readme warns + # about. Topology and tracer configs are not enveloped and stay flat. + configMerge = ''{\"Configuration\":{\"Network\":{\"MaxConcurrencyBulkSync\":2}}}''; + topologyMerge = ''{\"useLedgerAfterSlot\":1}''; + tracerConfigMerge = ''{\"verbosity\":\"Minimum\"}''; + + rt = "/tmp/cardano-node"; + tracerRt = "/tmp/cardano-tracer"; +in { + name = "cardano-oci-test"; + + nodes = { + machine = {...}: { + nixpkgs.pkgs = pkgs; + + # Room for loading three images (node, tracer, submit-api) + overlay + + # a starting node/tracer. + virtualisation.diskSize = 10240; + virtualisation.memorySize = 4096; + virtualisation.docker.enable = true; + + # Keep dhcpcd off docker's ephemeral interfaces. Starting and stopping + # containers churns veth pairs, dhcpcd tries to manage each one, and + # dhcpcd 10.3.1 segfaults probing one for an IPv4LL address. Harmless to + # the assertions but it core dumps and buries real errors in the log. + networking.dhcpcd.denyInterfaces = ["veth*" "docker0"]; + }; + }; + + # Like the other tests here, this is sandboxed: the node cannot sync, but it + # starts and resolves its configuration, which is all these assertions need. + testScript = '' + start_all() + machine.wait_for_unit("multi-user.target") + machine.wait_until_succeeds("docker info", timeout=120) + machine.succeed("docker load -i ${dockerImage}") + + with subtest("node: read-only root, non-root uid, merge mode"): + # Read-only root + non-root UID in group 0 + merge mode. Asserts the + # container starts as read-only and group-0 volume writes work, creates its + # fixed 0700 runtime dir, writes the merged config with absolute genesis + # paths, writes the env snapshot, and the /usr/local/bin/env alias sources + # it. + machine.succeed( + "docker run -d --name n1 --read-only --tmpfs /tmp --user 1000:0 " + "-v n1data:/data -v n1ipc:/ipc -v n1logs:/logs " + "-e NETWORK=${network} " + "-e CARDANO_CONFIG_JSON_MERGE='${configMerge}' " + "-e CARDANO_TOPOLOGY_JSON_MERGE='${topologyMerge}' " + "${imageRef}" + ) + + # The runtime artifacts are written by the entrypoint/run-node before the + # node execs, so they appear shortly after start. Waiting on the env + # snapshot also confirms the container did not crash under --read-only and + # --user since `docker exec` fails against an exited container. + machine.wait_until_succeeds("docker exec n1 test -f ${rt}/env", timeout=60) + machine.succeed("[ \"$(docker inspect -f '{{.State.Running}}' n1)\" = true ]") + + machine.succeed("docker exec n1 test -d ${rt}") + machine.succeed("docker exec n1 sh -c '[ \"$(stat -c %a ${rt})\" = 700 ]'") + machine.succeed("docker exec n1 test -f ${rt}/config-merged.json") + machine.succeed("docker exec n1 test -f ${rt}/topology-merged.json") + + # The merged config's relative "*File" references (ByronGenesisFile, + # ShelleyGenesisFile, ..., CheckpointsFile) must be rewritten to absolute + # paths so they resolve from /tmp. Mirror the entrypoint's predicate, which + # walks rather than reading the top level: in the cardano-config envelope + # these keys sit under Configuration.
, so a top-level scan finds + # none of them. The length guard is what makes that a failure rather than a + # vacuous pass, so keep it. Use jq from the container. + machine.succeed( + "docker exec n1 jq -e " + "'[..|objects|to_entries[]|select((.key|endswith(\"File\")) " + "and (.value|type==\"string\"))|.value] as $v " + "| ($v|length>0) and ($v|all(startswith(\"/\")))' " + "${rt}/config-merged.json" + ) + + # The merged topology's relative peerSnapshotFile must likewise be rewritten + # to an absolute path. + machine.succeed( + "docker exec n1 jq -e " + "'(.peerSnapshotFile|type==\"string\") and (.peerSnapshotFile|startswith(\"/\"))' " + "${rt}/topology-merged.json" + ) + + # The env snapshot is POSIX-sourceable; use sh and `.` to load it and + # confirm it populated the env. + machine.succeed( + "docker exec --user 1000:0 n1 sh -c " + "'. /usr/local/bin/env && [ -n \"$CARDANO_CONFIG\" ]'" + ) + machine.succeed("docker rm -f n1") + + with subtest("node: runtime dir lock across containers"): + # The runtime dir is a fixed path, so two same-role containers sharing one + # /tmp would otherwise both write it and the last writer would win. Both + # containers here run as the default root, i.e. the same UID, which is the + # case the directory ownership check cannot catch on its own. + machine.succeed( + "docker run -d --name s1 -v shtmp:/tmp " + "-v s1data:/data -v s1ipc:/ipc -v s1logs:/logs " + "-e NETWORK=${network} " + "-e CARDANO_CONFIG_JSON_MERGE='${configMerge}' " + "${imageRef}" + ) + machine.wait_until_succeeds("docker exec s1 test -f ${rt}/env", timeout=60) + + status, out = machine.execute( + "docker run --rm -v shtmp:/tmp -e NETWORK=${network} ${imageRef} 2>&1" + ) + assert status != 0, f"expected non-zero exit for a shared /tmp; got: {out}" + assert "is in use by another container" in out, f"missing lock error; got: {out}" + + # Once the holder is gone the lock is released, so the same volume, now + # carrying a stale runtime dir, must still be usable. This is what separates + # the lock from a blanket refusal whenever the directory already exists. + machine.succeed("docker rm -f s1") + machine.succeed( + "docker run -d --name s2 -v shtmp:/tmp " + "-v s2data:/data -v s2ipc:/ipc -v s2logs:/logs " + "-e NETWORK=${network} " + "-e CARDANO_CONFIG_JSON_MERGE='${configMerge}' " + "${imageRef}" + ) + machine.wait_until_succeeds("docker exec s2 test -f ${rt}/env", timeout=60) + machine.succeed("docker rm -f s2") + + with subtest("node: read-only root without a writable /tmp"): + # Read-only root WITHOUT a writable /tmp must fail fast with guidance. + status, out = machine.execute( + "docker run --rm --read-only -e NETWORK=${network} ${imageRef} 2>&1" + ) + assert status != 0, "expected non-zero exit when /tmp is not writable" + assert "/tmp is not writable" in out, f"missing actionable /tmp error; got: {out}" + + with subtest("node: cli mode dispatch"): + # Cli mode must NOT require a writable /tmp (read-only, no tmpfs). + machine.succeed("docker run --rm --read-only ${imageRef} cli version") + + # Cli mode is dispatched before the NETWORK modes, so a NETWORK left in the + # environment, with or without a merge var, must neither start a node nor + # reach the merge block, which writes to the runtime dir cli mode skips. + machine.succeed( + "docker run --rm --read-only -e NETWORK=${network} ${imageRef} cli version" + ) + machine.succeed( + "docker run --rm --read-only -e NETWORK=${network} " + "-e CARDANO_CONFIG_JSON_MERGE='${configMerge}' ${imageRef} cli version" + ) + + with subtest("node: operator rts flags and the eventlog"): + # Operator-supplied RTS flags are appended after the image's baked +RTS + # block and merge with it. `-po` covers .prof, .hp and .ticky only, so an + # eventlog without its own `-ol` is created in the container cwd (/) and the + # RTS aborts before main under a read-only root. /logs must be a writable + # mount here or the baked `-t/logs/cardano-node.stats` aborts first, which + # would pass the exit-code check for the wrong reason. + status, out = machine.execute( + "docker run --rm --read-only --tmpfs /tmp -v e0logs:/logs " + "-e NETWORK=${network} ${imageRef} +RTS -l -RTS 2>&1" + ) + assert status != 0, f"expected non-zero exit for -l without -ol; got: {out}" + assert "initEventLogFileWriter" in out, f"expected an eventlog open failure; got: {out}" + + # Given `-ol` under a writable mount it starts and writes the eventlog there. + machine.succeed( + "docker run -d --name e1 --read-only --tmpfs /tmp --user 1000:0 " + "-v e1data:/data -v e1ipc:/ipc -v e1logs:/logs " + "-e NETWORK=${network} " + "${imageRef} +RTS -l -ol/logs/cardano-node.eventlog -RTS" + ) + machine.wait_until_succeeds( + "docker exec e1 test -s /logs/cardano-node.eventlog", timeout=60 + ) + machine.succeed("docker rm -f e1") + + with subtest("tracer image"): + # Tracer image: same read-only + non-root + merge-mode behavior as the + # node, minus the genesis/topology rewrites as tracer config has no + # relative file references. + machine.succeed("docker load -i ${tracerDockerImage}") + machine.succeed( + "docker run -d --name t1 --read-only --tmpfs /tmp --user 1000:0 " + "-v t1data:/data -v t1ipc:/ipc -v t1logs:/logs " + "-e NETWORK=${network} " + "-e CARDANO_CONFIG_JSON_MERGE='${tracerConfigMerge}' " + "${tracerImageRef}" + ) + # Give the entrypoint time to write artifacts and exec the tracer. If the + # container exits early, surface its logs rather than failing later with an + # opaque `docker exec` timeout against a dead container. + machine.sleep(10) + if machine.succeed("docker inspect -f '{{.State.Running}}' t1").strip() != "true": + _, logs = machine.execute("docker logs t1 2>&1") + raise Exception("tracer container exited early; docker logs:\n" + logs) + machine.succeed("docker exec t1 sh -c '[ \"$(stat -c %a ${tracerRt})\" = 700 ]'") + machine.succeed("docker exec t1 test -f ${tracerRt}/tracer-config-merged.json") + machine.succeed("docker exec t1 test -f ${tracerRt}/env") + machine.succeed( + "docker exec --user 1000:0 t1 sh -c " + "'. /usr/local/bin/env && [ -n \"$CARDANO_CONFIG\" ]'" + ) + machine.succeed("docker rm -f t1") + + with subtest("submit-api image"): + # Submit-api image: stateless (no env snapshot / merge / state writes), + # so it only needs to execute under --read-only and as non-root. + machine.succeed("docker load -i ${submitApiDockerImage}") + machine.succeed("docker run --rm --read-only --user 1000:0 ${submitApiImageRef} --help >/dev/null") + + # Scripts mode, which --help above cannot reach: it exits before the baked + # tracing config is parsed. That is how the 11.0.1 submit-api image shipped + # broken, aborting at startup on a config trace-dispatcher rejected. + # + # No node is needed behind it: the api listens either way and opens the + # node socket per submission. The image bakes socketPath, so the script + # exports CARDANO_NODE_SOCKET_PATH itself and /ipc need only exist. + machine.succeed( + "docker run -d --name sa1 --read-only --tmpfs /tmp --user 1000:0 " + "-v sa1ipc:/ipc -e NETWORK=${network} " + "-p ${toString submitApiMetricsPort}:${toString submitApiMetricsPort} " + "${submitApiImageRef}" + ) + machine.sleep(10) + if machine.succeed("docker inspect -f '{{.State.Running}}' sa1").strip() != "true": + _, logs = machine.execute("docker logs sa1 2>&1") + raise Exception("submit-api container exited early; docker logs:\n" + logs) + + # The scrape is the real assertion: metrics only serve once tracing is + # configured, so a config the tracing system rejects cannot reach here. + # Metrics are on / rather than /metrics, and the metric name carries + # TraceOptionMetricsPrefix with dots as underscores. + machine.wait_until_succeeds( + "curl -sf http://localhost:${toString submitApiMetricsPort}/ " + "| grep -qF cardano_submit_api_metrics_tx_submit_counter", + timeout=60, + ) + machine.succeed("docker rm -f sa1") + + # Graceful shutdown on SIGTERM and SIGINT, for both ways in. + # + # Each mode execs the whole way down to cardano-node, so the node is the + # container's pid 1 and takes the signal itself: scripts mode goes + # entrypoint -> run-network -> the per-network script -> exec node, custom + # mode goes entrypoint -> run-node -> exec node. Drop any one of those + # execs and a shell sits at pid 1 forwarding nothing, docker gives up after + # the grace period and SIGKILLs, and the exit code is 137. That is what + # this asserts against rather than a specific clean code, which differs by + # whether the node handles the signal or dies from it. + def shutdown_case(name, args, sig): + with subtest("node: graceful shutdown, " + name + " SIG" + sig): + # /logs must be a writable mount: the image bakes + # `-t/logs/cardano-node.stats` into its RTS block, and the node aborts + # at startup if it cannot open that file under a read-only root. + machine.succeed( + "docker run -d --name " + name + " --read-only --tmpfs /tmp " + "--user 1000:0 -v " + name + "data:/data -v " + name + "ipc:/ipc " + "-v " + name + "logs:/logs " + args + ) + # Long enough to be past config resolution and into the node proper, + # so the signal lands on a running node rather than on startup. + machine.sleep(10) + if machine.succeed( + "docker inspect -f '{{.State.Running}}' " + name + ).strip() != "true": + _, logs = machine.execute("docker logs " + name + " 2>&1") + raise Exception( + name + " exited before the shutdown signal; docker logs:\n" + logs + ) + + if sig == "TERM": + # Sends SIGTERM, waits, then SIGKILLs if it outlives the grace period. + machine.succeed("docker stop -t 30 " + name) + else: + # docker kill does not wait, so poll for the exit ourselves. + machine.succeed("docker kill --signal=INT " + name) + machine.wait_until_succeeds( + "[ \"$(docker inspect -f '{{.State.Running}}' " + name + ")\" = false ]", + timeout=40, + ) + + code = machine.succeed( + "docker inspect -f '{{.State.ExitCode}}' " + name + ).strip() + if code == "137": + _, logs = machine.execute("docker logs " + name + " 2>&1") + raise Exception( + name + ": SIG" + sig + " did not stop the node, docker had to " + "SIGKILL it after the grace period; docker logs:\n" + logs + ) + machine.succeed("docker rm -f " + name) + + shutdown_case("sd1", "-e NETWORK=${network} ${imageRef}", "TERM") + shutdown_case("sd2", "-e NETWORK=${network} ${imageRef}", "INT") + shutdown_case("sd3", "${imageRef} run", "TERM") + shutdown_case("sd4", "${imageRef} run", "INT") + ''; +} diff --git a/nix/nixos/tests/default.nix b/nix/nixos/tests/default.nix index 31de2e2c440..9923bc2c0c1 100644 --- a/nix/nixos/tests/default.nix +++ b/nix/nixos/tests/default.nix @@ -31,13 +31,13 @@ in { # Tests a mainnet edge node with submit-api using nixos service config. cardanoNodeEdge = callTest ./cardano-node-edge.nix {}; - # Tests the OCI images (node, tracer, submit-api) under a read-only root, a - # non-root UID in group 0, and a private /tmp: container startup, the fixed - # 0700 runtime dir, merged-config path rewriting, the env snapshot/alias, the - # fail-fast on a missing writable /tmp, that cli mode does not require /tmp, - # and that a second same-role container sharing one /tmp is refused while a - # restart against the same stale runtime dir still succeeds. - cardanoOciReadonly = callTest ./cardano-oci-readonly.nix { + # Tests the OCI images (node, tracer, submit-api), mostly under a read-only + # root, a non-root UID in group 0 and a private /tmp. One subtest per + # concern: startup and the runtime dir, merged-config path rewriting, the + # /tmp lock and fail-fast, cli mode dispatch, operator RTS flags, submit-api + # startup to a metrics scrape, and graceful shutdown on SIGTERM and SIGINT + # for both ways into the image. + cardanoOci = callTest ./cardano-oci.nix { dockerImage = pkgs.dockerImage; tracerDockerImage = pkgs.tracerDockerImage; submitApiDockerImage = pkgs.submitApiDockerImage; From e038dcc7a6e87911aba7f93904df7a5daaa98b10 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Sun, 11 Oct 2026 23:24:13 -0500 Subject: [PATCH 35/45] nixosTests: cover an enveloped host config Boot a preview node on `configFormat = "enveloped"` with `withUtxoHdLsmt` and an envelope-shaped `extraNodeConfig`, and assert the node took the cardano-config path, that it reported nothing to migrate or ignore, that the LSM backend resolved with its path, that the envelope-shaped key reached the resolved configuration, and that `config resolve` on the generated file says nothing on stderr. The service assembles the config it envelopes, so this is the only check that sees one as a host writes it: iohk-nix lints and envelopes environment configs, which carry neither the flat `V2LSM` pair the service adds nor anything a caller supplies. Reading two settings back out of the resolved `NodeConfiguration` is the part the iohk-nix checks cannot do at all. Those compare against cardano-config's own output, so a key its adapter never maps is lost identically on both sides and agrees. --- nix/nixos/tests/cardano-node-enveloped.nix | 121 +++++++++++++++++++++ nix/nixos/tests/default.nix | 7 ++ 2 files changed, 128 insertions(+) create mode 100644 nix/nixos/tests/cardano-node-enveloped.nix diff --git a/nix/nixos/tests/cardano-node-enveloped.nix b/nix/nixos/tests/cardano-node-enveloped.nix new file mode 100644 index 00000000000..a9220f641b0 --- /dev/null +++ b/nix/nixos/tests/cardano-node-enveloped.nix @@ -0,0 +1,121 @@ +{pkgs, ...}: +with pkgs; let + environment = "preview"; + + # NixosTest script fns supporting a timeout have a default of 900 seconds. + timeout = toString 60; + + lsmPath = "/var/lib/cardano-node/lsm"; + + # Distinctive and unset by the service, so finding it in the resolved + # configuration can only mean the envelope-shaped key below was honoured. + deadlineConcurrency = 7; +in { + name = "cardano-node-enveloped-test"; + nodes = { + machine = {config, ...}: { + nixpkgs.pkgs = pkgs; + imports = [ + ../. + ]; + + services.cardano-node = { + inherit environment; + + enable = true; + port = 3001; + hostAddr = "127.0.0.1"; + topology = commonLib.mkEdgeTopologyP2P { + edgeNodes = [ + { + addr = "127.0.0.1"; + port = 3001; + } + ]; + }; + nodeConfig = config.services.cardano-node.environments.${environment}.nodeConfig; + + # What this test exists for. + configFormat = "enveloped"; + + # The service writes `Backend = "V2LSM"` with a sibling + # `LSMDatabasePath`, which is the legacy flat spelling of the tagged + # `Backend.LSM` form. Nothing but a host produces it, so nothing else + # exercises the fold. + withUtxoHdLsmt = true; + lsmDatabasePath = lsmPath; + + # A caller writing part of its configuration in envelope shape, which is + # where extraNodeConfig is headed once POM is dropped. Section + # qualified, so it reaches mkEnvelope as a `Configuration` key rather + # than a flat one. + extraNodeConfig.Configuration.Network.MaxConcurrencyDeadline = deadlineConcurrency; + }; + + systemd.services.cardano-node.serviceConfig.Restart = lib.mkForce "no"; + }; + }; + + # Sandboxed like the other tests here: the node cannot sync, but it starts and + # resolves its configuration, which is all these assertions need. + testScript = '' + start_all() + + machine.wait_for_unit("cardano-node.service", timeout=${timeout}) + machine.wait_until_succeeds("[ -S /run/cardano-node/node.socket ]", timeout=${timeout}) + machine.succeed("systemctl status cardano-node") + + journal = "journalctl -u cardano-node --no-pager" + + # Positive control: prove the node took the cardano-config path. Without + # this every assertion below would also pass on a legacy configuration, + # which is not what is under test. + machine.succeed( + journal + " | grep -qF 'own parser was not run'" + ) + + # The check this test exists for. cardano-config emits this whenever + # migrate would still change the document, so a generated envelope that is + # not canonical says so here and nowhere else. The node runs either way, + # which is why it went unnoticed until a host was deployed. + machine.fail( + journal + " | grep -qF 'not in the current canonical format'" + ) + + # A key cardano-config does not resolve is kept outside every section and + # ignored, silently changing behaviour to a default. + machine.fail( + journal + " | grep -qF 'unrecognised configuration key(s)'" + ) + + # The flat V2LSM pair survived enveloping as a setting, not just as a shape: + # an unfolded backend resolves to the in-memory default with no path at all. + machine.succeed( + journal + " | grep -qF 'V2LSM (Just \"${lsmPath}\")'" + ) + + # The envelope-shaped extraNodeConfig key reached the resolved + # configuration. A dropped `Configuration` block leaves this at its default. + machine.succeed( + journal + " | grep -qF 'ncMaxConcurrencyDeadline = Just ${toString deadlineConcurrency}'" + ) + + # Tier 3, the same question asked of the file directly rather than of the + # startup log. On an envelope `resolve` has no second parser to cross-check + # against, so it prints the resolved configuration and anything on stderr is + # a complaint about the file. + cfg = machine.succeed( + journal + " | grep -om1 '/nix/store/[^\"]*config-0-0.json'" + ).strip() + print("resolving:", cfg) + machine.succeed( + "${cardanoNodePackages.cardano-node}/bin/cardano-node config resolve --config " + + cfg + + " 2>/tmp/resolve.stderr >/tmp/resolve.stdout" + ) + machine.succeed("[ -s /tmp/resolve.stdout ]") + stderr = machine.succeed("cat /tmp/resolve.stderr") + if stderr.strip(): + raise Exception("resolve reported on the generated config:\n" + stderr) + ''; +} diff --git a/nix/nixos/tests/default.nix b/nix/nixos/tests/default.nix index 9923bc2c0c1..c2371833fba 100644 --- a/nix/nixos/tests/default.nix +++ b/nix/nixos/tests/default.nix @@ -31,6 +31,13 @@ in { # Tests a mainnet edge node with submit-api using nixos service config. cardanoNodeEdge = callTest ./cardano-node-edge.nix {}; + # Tests that a host-assembled enveloped config is canonical: the service's + # own LedgerDB keys and an envelope-shaped extraNodeConfig both survive + # enveloping, and cardano-config has nothing to migrate or ignore. Nothing + # else checks a config as a host writes it; the iohk-nix lint and drift jobs + # only see environments. + cardanoNodeEnveloped = callTest ./cardano-node-enveloped.nix {}; + # Tests the OCI images (node, tracer, submit-api), mostly under a read-only # root, a non-root UID in group 0 and a private /tmp. One subtest per # concern: startup and the runtime dir, merged-config path rewriting, the From 3da5c38df1d0e88b522d78f90d1700bfab4c6696 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Sun, 11 Oct 2026 23:25:31 -0500 Subject: [PATCH 36/45] nixosModule: record why the LedgerDB keys stay flat The service writes `Backend = "V2LSM"` with a sibling `LSMDatabasePath`, which is the legacy spelling of the tagged `Backend.LSM` form. POM reads `Backend` as a string, so the nested form fails to parse on a legacy config, and mkEnvelope folds the flat one anyway, which it must do regardless for a caller supplying the same keys through extraNodeConfig. Writing the nested form here is therefore gated on no consumer still setting `configFormat = "legacy"`, and is a single flip at that point rather than a branch on the dialect. The envelope.nix header lists this as the last of the four conditions for retiring the translation; this is where the mechanics live. --- nix/nixos/cardano-node-service.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/nix/nixos/cardano-node-service.nix b/nix/nixos/cardano-node-service.nix index 2588901b7f4..99b2d517c5a 100644 --- a/nix/nixos/cardano-node-service.nix +++ b/nix/nixos/cardano-node-service.nix @@ -75,6 +75,16 @@ let } ) cfg.extraNodeConfig; + # The flat spelling is deliberate on both dialects. POM reads `Backend` as a + # string with the LSM paths as flat siblings, so the nested `Backend.LSM` form + # fails to parse on a legacy config; and mkEnvelope folds this one into the + # nested form anyway, which it has to do regardless for a caller that supplies + # the same keys through extraNodeConfig. + # + # So writing the nested form here is gated on no consumer still setting + # `configFormat = "legacy"`, and at that point it is a single flip rather than + # a branch on the dialect. Branching earlier buys nothing and makes the shape + # a caller deep-merges against depend on the dialect. baseInstanceConfig = i: recursiveUpdate From 4e4ff55c66f110ac990825775c7f419de6a4a796 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Mon, 12 Oct 2026 01:26:35 -0500 Subject: [PATCH 37/45] nixosModule: add lsmExportPath The LSM backend can export a standalone copy of each snapshot, which is what Mithril signing consumes, but the service had no way to ask for one: it set `LSMDatabasePath` and nothing else. Emitted only when set, and only under `withUtxoHdLsmt`. --- nix/nixos/cardano-node-service.nix | 32 ++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/nix/nixos/cardano-node-service.nix b/nix/nixos/cardano-node-service.nix index 99b2d517c5a..0feab436db6 100644 --- a/nix/nixos/cardano-node-service.nix +++ b/nix/nixos/cardano-node-service.nix @@ -89,10 +89,14 @@ let i: recursiveUpdate baseConfig (optionalAttrs (cfg.withUtxoHdLsmt i) { - LedgerDB = { - Backend = "V2LSM"; - LSMDatabasePath = cfg.lsmDatabasePath i; - }; + LedgerDB = + { + Backend = "V2LSM"; + LSMDatabasePath = cfg.lsmDatabasePath i; + } + // optionalAttrs (cfg.lsmExportPath i != null) { + LSMExportPath = cfg.lsmExportPath i; + }; }); mkInstanceConfig = i: @@ -484,6 +488,26 @@ in { ''; }; + lsmExportPath = mkOption { + type = funcToOr nullOrStr; + default = null; + apply = x : if lib.isFunction x then x else if x == null then _: null else _: x; + description = '' + A node UTxO-HD on-disk LSM-trees standalone snapshot export path, for + each instance. The LSM backend keeps the UTxO set on disk and + snapshots normally without this, so a node restarts without replaying; + what it cannot do is export a standalone copy on every snapshot, which + is what Mithril signing consumes. + + cardano-config warns when the resolved snapshot policy equals the + Mithril one while the backend is LSM with no export path. It compares + the values, not the `Mithril` name, so a policy derived from the + security parameter can match without naming it. + + Only emitted when set, and only with `withUtxoHdLsmt`. + ''; + }; + shelleyKesAgentSocket = mkOption { type = nullOr (either str path); default = null; From ed973457b9ee4501af03a065355a8e71fd1cd6bf Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Wed, 14 Oct 2026 04:40:45 -0500 Subject: [PATCH 38/45] nixosScripts: generate the config in the environment's dialect --- nix/scripts.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nix/scripts.nix b/nix/scripts.nix index 421d09f6530..90d7b745b59 100644 --- a/nix/scripts.nix +++ b/nix/scripts.nix @@ -14,6 +14,7 @@ let hostAddr = mkDefault "0.0.0.0"; environment = mkDefault envConfig.name; nodeConfig = cfg.environments.${cfg.environment}.nodeConfig; + configFormat = cfg.environments.${cfg.environment}.configFormat; stateDir = mkDefault "state-node-${cfg.environment}"; runtimeDir = mkDefault null; } // optionalAttrs (envConfig ? topology) { From b29860da20bc05b4ee2f2a4d6ba7757abc6fb69a Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Wed, 14 Oct 2026 04:42:02 -0500 Subject: [PATCH 39/45] nixosTests/cardanoNodeArtifact: give the machine a nameserver The node resolves relay names from the peer snapshot. With no nameserver the dns resolver is built from an empty list and throws BadConfiguration, which on the aarch64 builder escaped diffusion's retry path and took the node down instead of being retried as it is on x86_64. --- nix/nixos/tests/cardano-node-artifact.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nix/nixos/tests/cardano-node-artifact.nix b/nix/nixos/tests/cardano-node-artifact.nix index 9bf97e44188..fd4beb005d3 100644 --- a/nix/nixos/tests/cardano-node-artifact.nix +++ b/nix/nixos/tests/cardano-node-artifact.nix @@ -104,6 +104,10 @@ in { machine = {config, ...}: { nixpkgs.pkgs = pkgs; + # Without a nameserver the dns resolver is built from an empty list and + # throws BadConfiguration, which killed the node on the aarch64 builder. + networking.nameservers = ["127.0.0.1"]; + # The default disk size of 1024 MB is insufficient for the binary artifact # and tar gzip expansion. virtualisation.diskSize = 2048; From 0100a5b433913693a31cb19be9adcb28b1746975 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Wed, 14 Oct 2026 04:42:27 -0500 Subject: [PATCH 40/45] testnet: drop the removed Net.ErrorPolicy namespace from the golden --- .../files/golden/node_default_config.json | 3 --- nix/docker/README.md | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/cardano-testnet/test/cardano-testnet-golden/files/golden/node_default_config.json b/cardano-testnet/test/cardano-testnet-golden/files/golden/node_default_config.json index fca77ce4923..6382ebfef6b 100644 --- a/cardano-testnet/test/cardano-testnet-golden/files/golden/node_default_config.json +++ b/cardano-testnet/test/cardano-testnet-golden/files/golden/node_default_config.json @@ -73,9 +73,6 @@ "Net.ConnectionManager.Remote": { "severity": "Info" }, - "Net.ErrorPolicy": { - "severity": "Info" - }, "Net.InboundGovernor": { "severity": "Warning" }, diff --git a/nix/docker/README.md b/nix/docker/README.md index f71cda06b9e..91d35cac462 100644 --- a/nix/docker/README.md +++ b/nix/docker/README.md @@ -582,7 +582,7 @@ docker run \ -v node-ipc:/ipc \ -e NETWORK=mainnet \ -e CARDANO_TRACER_SOCKET_PATH_ACCEPT="/ipc/node-tracer.socket" \ - -e CARDANO_CONFIG_JSON_MERGE='{"TraceOptionNodeName":"node1"}' \ + -e CARDANO_CONFIG_JSON_MERGE='{"Configuration":{"HermodTracing":{"TraceOptionNodeName":"node1"}}}' \ ghcr.io/intersectmbo/cardano-node:dev docker run \ From 632883fcc43bc34b7aaf8f33516eee91a865247b Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Fri, 23 Oct 2026 22:01:11 +0000 Subject: [PATCH 41/45] Fail instead of dropping tracing settings when enabling trace forwarding --- cardano-testnet/src/Testnet/Start/Cardano.hs | 44 +++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/cardano-testnet/src/Testnet/Start/Cardano.hs b/cardano-testnet/src/Testnet/Start/Cardano.hs index a61b75e0ca7..50f9b665d7d 100644 --- a/cardano-testnet/src/Testnet/Start/Cardano.hs +++ b/cardano-testnet/src/Testnet/Start/Cardano.hs @@ -604,35 +604,39 @@ cardanoTestnet -- | Copy and modify a node configuration file so that its @TraceOptions@ -- enables the @Forwarder@ backend. This is required for nodes to actually -- forward their traces and metrics to cardano-tracer. Returns a path to the --- modified config file. +-- modified config file. Fails if the tracing settings are not an object in the +-- file itself (for example a @HermodTracing@ file path), instead of dropping them. enableTraceForwarding :: FilePath -> IO FilePath enableTraceForwarding configFile = do (document, _warnings) <- readConfigurationDocument configFile - (document', _warnings') <- - configurationDocumentFromValue - . onObject (onKey "Configuration" . onKey "HermodTracing" $ - KeyMap.insertWith mergeTraceOptions "TraceOptions" Defaults.traceOptionsForwarding) + value' <- + either (\err -> throwString $ "enableTraceForwarding: " <> configFile <> ": " <> err) pure + . addForwarding $ configurationDocumentValue document + (document', _warnings') <- configurationDocumentFromValue value' let configFile' = dropExtension configFile <> "-tracer.yaml" writeConfigurationDocument configFile' document' pure configFile' where -- The tracing settings are the @HermodTracing@ object of the @Configuration@ - -- section. A missing object (or one given as a file) is replaced. - onObject :: (KeyMap.KeyMap Aeson.Value -> KeyMap.KeyMap Aeson.Value) -> Aeson.Value -> Aeson.Value - onObject f = \case - Object o -> Object $ f o - other -> other - - onKey - :: KeyMap.Key - -> (KeyMap.KeyMap Aeson.Value -> KeyMap.KeyMap Aeson.Value) - -> KeyMap.KeyMap Aeson.Value - -> KeyMap.KeyMap Aeson.Value - onKey key f o = - KeyMap.insert key (Object . f $ case KeyMap.lookup key o of - Just (Object inner) -> inner - _ -> mempty) o + -- section. A missing one is created; any other shape is an error, because + -- replacing it would silently drop the tracing settings. + addForwarding :: Aeson.Value -> Either String Aeson.Value + addForwarding = \case + Object envelope -> case KeyMap.lookup "Configuration" envelope of + Just (Object configuration) -> do + tracing <- case KeyMap.lookup "HermodTracing" configuration of + Nothing -> Right mempty + Just (Object inline) -> Right inline + Just (String path) -> Left $ + "Configuration.HermodTracing is a file path (" <> Text.unpack path + <> "), but the tracer needs the tracing settings inline" + Just _ -> Left "Configuration.HermodTracing must be an object or a file path" + let tracing' = KeyMap.insertWith mergeTraceOptions "TraceOptions" Defaults.traceOptionsForwarding tracing + configuration' = KeyMap.insert "HermodTracing" (Object tracing') configuration + Right . Object $ KeyMap.insert "Configuration" (Object configuration') envelope + _ -> Left "expected a Configuration object" + _ -> Left "expected a JSON or YAML object" mergeTraceOptions :: Yaml.Value -> Yaml.Value -> Yaml.Value mergeTraceOptions (Object forwarding) (Object existing) = From e625d75ea2dc001bc1eb84c50e0102a7dcfaf07b Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Tue, 27 Oct 2026 12:05:19 -0500 Subject: [PATCH 42/45] nixosTests: read the hashes create-env writes in cardanoNodeDbtools cardano-testnet create-env now refreshes the genesis hashes when it writes the node configuration, so the db tools find them already in place. Drop the add-genesis-hashes wrapper, which had become a no-op twice over: the hashes it computed were already correct in the file, and it added them as top-level keys, where splitEnvelope discards everything outside Configuration. --- nix/nixos/tests/cardano-node-dbtools.nix | 73 +++--------------------- 1 file changed, 8 insertions(+), 65 deletions(-) diff --git a/nix/nixos/tests/cardano-node-dbtools.nix b/nix/nixos/tests/cardano-node-dbtools.nix index ca86257705d..19dfa760b0e 100644 --- a/nix/nixos/tests/cardano-node-dbtools.nix +++ b/nix/nixos/tests/cardano-node-dbtools.nix @@ -3,58 +3,6 @@ inherit (pkgs) cardanoNodePackages lib; synthAsserted = cardanoNodePackages.db-synthesizer.passthru.asserted; - # `cardano-testnet create-env` deliberately leaves the genesis hashes out of - # its configuration file, so that the genesis files it writes alongside can be - # edited without recomputing a hash every time (see `createEnvOptions` in - # cardano-testnet's Parsers/Run.hs). cardano-node itself is fine with that -- - # POM.hs reads every `*GenesisHash` with `.:?` -- but the consensus db tools - # resolve the configuration through cardano-config, which makes all five of - # them mandatory, so they reject the environment as it comes out of create-env: - # - # db-synthesizer: invalid node configuration: Error parsing the cardano-node - # configuration (section "Protocol") in the main configuration file: - # Error in $: key "ByronGenesisHash" not found - # - # Fill them in for the tools' benefit. Byron hashes its genesis differently - # from the later eras, which take a plain blake2b-256 of the file bytes. - # - # TODO: this belongs in create-env itself -- it already computes exactly these - # five for `cardano-testnet cardano` (Testnet.Components.Configuration's - # `createConfigJson`), it just does not offer them here. Either give create-env - # an opt-in flag for them, or make the db tools as lenient as the node is. - addGenesisHashes = pkgs.writeShellApplication { - name = "add-genesis-hashes"; - runtimeInputs = [cardanoNodePackages.cardano-cli pkgs.jq]; - text = '' - if test $# -ne 1 - then echo "usage: add-genesis-hashes ENV-DIR" >&2; exit 1 - fi - cd "$1" - - # create-env names the file .yaml, but writes JSON into it, so jq can edit - # it in place. Should that ever change, this test fails loudly rather than - # silently skipping the hashes. - jq --arg byron "$(cardano-cli byron genesis print-genesis-hash \ - --genesis-json byron-genesis.json)" \ - --arg shelley "$(cardano-cli hash genesis-file \ - --genesis shelley-genesis.json)" \ - --arg alonzo "$(cardano-cli hash genesis-file \ - --genesis alonzo-genesis.json)" \ - --arg conway "$(cardano-cli hash genesis-file \ - --genesis conway-genesis.json)" \ - --arg dijkstra "$(cardano-cli hash genesis-file \ - --genesis dijkstra-genesis.json)" \ - '. + { ByronGenesisHash: $byron - , ShelleyGenesisHash: $shelley - , AlonzoGenesisHash: $alonzo - , ConwayGenesisHash: $conway - , DijkstraGenesisHash: $dijkstra - }' \ - configuration.yaml > configuration.yaml.hashed - mv configuration.yaml.hashed configuration.yaml - ''; - }; - # Budget for the whole test, not per step: the driver kills everything and # fails once it is reached. It covers the vm boot as well as create-env, # synthesis, both analyser passes, truncation and the asserted synthesis, so @@ -76,15 +24,14 @@ in { nixpkgs.pkgs = pkgs; environment = { - systemPackages = [addGenesisHashes] - ++ (with cardanoNodePackages; [ - cardano-cli - cardano-node - cardano-testnet - db-analyser - db-synthesizer - db-truncater - ]); + systemPackages = with cardanoNodePackages; [ + cardano-cli + cardano-node + cardano-testnet + db-analyser + db-synthesizer + db-truncater + ]; variables = { CARDANO_CLI = getExe cardanoNodePackages.cardano-cli; @@ -111,10 +58,6 @@ in { # Epoch length ideally should also be divisible by 10k = 500 slots print(machine.succeed("cardano-testnet create-env --epoch-length 1000 --output ${testDir}")) - # The db tools, unlike the node, require every genesis hash to be present. - print(machine.succeed("echo Add genesis hashes to the node configuration")) - print(machine.succeed("add-genesis-hashes ${testDir}")) - print(machine.succeed("echo Synthesize one epoch")) print(machine.succeed("db-synthesizer \ --config ${testDir}/configuration.yaml \ From e4e2d90fc4c56d80cfa271f148d5249ea91eb82a Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Tue, 27 Oct 2026 09:35:52 -0500 Subject: [PATCH 43/45] bump: mithril flake input to release v2642.0 for signer 1.2.5 --- flake.lock | 44 ++++++++++++++++++++++---------------------- flake.nix | 2 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/flake.lock b/flake.lock index 183a652f114..4dda08c4169 100644 --- a/flake.lock +++ b/flake.lock @@ -253,11 +253,11 @@ }, "crane": { "locked": { - "lastModified": 1783203018, - "narHash": "sha256-G6R9IT/xwFuu+CYBWDUAok6AdC4ERC4ZfPPFtEpxnZE=", + "lastModified": 1790899423, + "narHash": "sha256-THGtz65UGJU+sonZidRboyCMk+9DclpMF7pwL4uDV4M=", "owner": "ipetkov", "repo": "crane", - "rev": "80db5bdc391be8a1794f6d8a2d56e3a84ebcede2", + "rev": "47b6b27ed9a3a9181415e4367d0c30ab2a0e0250", "type": "github" }, "original": { @@ -352,11 +352,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1782949081, - "narHash": "sha256-vp6Y/Grm98ESt6ceOkWiHWyZRDV3J1RID4w+6NWK9yA=", + "lastModified": 1790898470, + "narHash": "sha256-zTwuwezD0w3hpga6a6P8emidzAZFyWqlNeRBlpWOOl8=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "17c9d6cdfc60c64f4ee8d306f9bc0b4ccb51481e", + "rev": "024633cd702b10285db5cb19b40ad48d2399ba60", "type": "github" }, "original": { @@ -1217,16 +1217,16 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1789639081, - "narHash": "sha256-l6ACwepW8R5zsx1iNw9VOzdRfOWhfSE3+GcP6VkX8Zc=", + "lastModified": 1792137521, + "narHash": "sha256-i9oRC2Yx/obEsSfVHRUAiOQcF+OmsPj9tzoCDdOuilg=", "owner": "IntersectMBO", "repo": "mithril", - "rev": "3f6cb73f491eb3195d02318643e40836fb093acc", + "rev": "e85df3ddc52b528c7b9ddbdddf1941fec6d5f348", "type": "github" }, "original": { "owner": "IntersectMBO", - "ref": "refs/tags/2630.1-hotfix", + "ref": "refs/tags/2642.0", "repo": "mithril", "type": "github" } @@ -1456,11 +1456,11 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1782614948, - "narHash": "sha256-ePjCwr1sNm9NYUqywL7QfK3JnlS015msC+eBu2zKlp8=", + "lastModified": 1790477367, + "narHash": "sha256-oujbxmVKDhci2E4EM3KyAbRUgp5/IsCoiA/LfEF7OOk=", "owner": "nix-community", "repo": "nixpkgs.lib", - "rev": "db3f255737b94216eb71cce308e2912cf6bc2d7c", + "rev": "f7cd230690d9fc982d06129f9189b101fddcfa3b", "type": "github" }, "original": { @@ -1503,11 +1503,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1783279667, - "narHash": "sha256-/NAkDSsve+GNM0Bt6tleJdCGfsTlK89nPjkVOzZMo0s=", + "lastModified": 1791336361, + "narHash": "sha256-o9ZUW4SlEAvFPIyJWnqChhOT/VHpHg8TAvEgmqK1fSI=", "owner": "nixos", "repo": "nixpkgs", - "rev": "f205b5574fd0cb7da5b702a2da51507b7f4fdd1b", + "rev": "7dd199b0e2993e37b4775ed66b1c291699608c9f", "type": "github" }, "original": { @@ -1579,11 +1579,11 @@ ] }, "locked": { - "lastModified": 1783320166, - "narHash": "sha256-l7C/OsjcnWDOk2K3ssj+SBduwL67LashjBqis9+t468=", + "lastModified": 1791361643, + "narHash": "sha256-HMdfSb1ONHs1RbSkQtCXm+tWEsTikisWWtXDnv0aQ+I=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "20ee15370c9256669d66968b89ee20a4b0a4e673", + "rev": "8afee9fa8caa877a4feb65adc33e8d72f3747dc9", "type": "github" }, "original": { @@ -1730,11 +1730,11 @@ ] }, "locked": { - "lastModified": 1780220602, - "narHash": "sha256-eynAfOmbmxJnkp7YewvCEbShNnnYJ9gLLqkzsYtBPeM=", + "lastModified": 1791203292, + "narHash": "sha256-vuzVwvjeucSnwKwMBpyP8r5IzdrMKCHEdwTrRFwUN7I=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "db947814a175b7ca6ded66e21383d938df01c227", + "rev": "03d8ee1bcbc8f9638907bb79edb9673151d0e22b", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 2e6aa724e25..3a5f42bdc89 100644 --- a/flake.nix +++ b/flake.nix @@ -66,7 +66,7 @@ # Bump the tag and then run: nix flake lock --update-input mithril. # Changing the tag alone only relocks mithril itself, leaving its # transitive pins on an old release. - mithril.url = "github:IntersectMBO/mithril?ref=refs/tags/2630.1-hotfix"; + mithril.url = "github:IntersectMBO/mithril?ref=refs/tags/2642.0"; }; outputs = { From 56468323836ecb578576ed7c76034060358d3809 Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Tue, 27 Oct 2026 09:37:33 -0500 Subject: [PATCH 44/45] bump: iohkNix for merged iohk-nix 11.2 pr --- flake.lock | 7 +++---- flake.nix | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index 4dda08c4169..d37c6f0989f 100644 --- a/flake.lock +++ b/flake.lock @@ -1160,16 +1160,15 @@ "sodium": "sodium_2" }, "locked": { - "lastModified": 1792756495, - "narHash": "sha256-KUXDHN2p9e83PPtespiYf/MMW41/ngYDq5Bgi+PmGoU=", + "lastModified": 1793111651, + "narHash": "sha256-9TSfb5nqwlL2RwRmT+bFV0Xladdn1zEvKpn6ggqhT1I=", "owner": "input-output-hk", "repo": "iohk-nix", - "rev": "d0031fb59ddfedc713129718b62f931581039f5d", + "rev": "552233e3b94300c845545efd568217659c866fdf", "type": "github" }, "original": { "owner": "input-output-hk", - "ref": "jl/node-11.2", "repo": "iohk-nix", "type": "github" } diff --git a/flake.nix b/flake.nix index 3a5f42bdc89..5a64344c766 100644 --- a/flake.nix +++ b/flake.nix @@ -50,7 +50,7 @@ incl.url = "github:divnix/incl"; iohkNix = { - url = "github:input-output-hk/iohk-nix/jl/node-11.2"; + url = "github:input-output-hk/iohk-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; From afb6c201c37e6075aeb6172cfd990ccf9602c3fb Mon Sep 17 00:00:00 2001 From: John Lotoski Date: Tue, 27 Oct 2026 10:11:39 -0500 Subject: [PATCH 45/45] update: cabal versions and changelogs from herald fragments --- bench/cardano-profile/cardano-profile.cabal | 2 +- bench/cardano-topology/cardano-topology.cabal | 2 +- .../.changes/20260903_release_11_1_1.yml | 5 ----- ...33500_mgalazyn_readme_core_maintainers.yml | 5 ----- ...61008_102852_koslambrou_bump_deps_11_2.yml | 5 ----- ...29_palas_chairman_reads_cardano_config.yml | 4 ---- .../.changes/20261027_release_11_2_0.yml | 9 ++++++++ cardano-node-chairman/CHANGELOG.md | 6 +++++ .../cardano-node-chairman.cabal | 4 ++-- cardano-node/ChangeLog.md | 2 +- cardano-node/cardano-node.cabal | 2 +- .../.changes/20260903_release_11_1_1.yml | 5 ----- ..._123655_mgalazyn_bump_cardano_api_11_7.yml | 5 ----- ...33500_mgalazyn_readme_core_maintainers.yml | 5 ----- ...alazyn_submit_api_dijkstra_tx_decoding.yml | 6 ----- ...61008_102852_koslambrou_bump_deps_11_2.yml | 5 ----- ...015_033428_palas_bump_cardano_api_11_9.yml | 4 ---- .../.changes/20261027_release_11_2_0.yml | 9 ++++++++ cardano-submit-api/CHANGELOG.md | 7 ++++++ cardano-submit-api/cardano-submit-api.cabal | 2 +- ...io.ferrai_node_11_1_testnet_integration.md | 5 ----- ...rpc_readgenesis_initialfunds_assertion.yml | 5 ----- ...mgalazyn_add_rpc_read_era_summary_test.yml | 5 ----- .../.changes/20260903_release_11_1_1.yml | 5 ----- ..._123655_mgalazyn_bump_cardano_api_11_7.yml | 5 ----- ...5_mgalazyn_rpc_v1beta_spec_test_update.yml | 5 ----- .../20260909_mgalazyn_enable_grpc_http.yml | 5 ----- ...60911_170000_palas_restore_readme_docs.yml | 7 ------ ...0260914_150000_palas_check_readme_help.yml | 5 ----- .../20260914_150000_palas_manifest.yml | 5 ----- ...33500_mgalazyn_readme_core_maintainers.yml | 5 ----- .../20260930_204211_cardano-testnet_sandy.yml | 6 ----- ...02_174813_cardano-testnet_pablo.lamela.yml | 6 ----- .../20261006_160204_cardano-testnet_sandy.yml | 5 ----- ...61008_102852_koslambrou_bump_deps_11_2.yml | 6 ----- ...015_033428_palas_bump_cardano_api_11_9.yml | 4 ---- ...46_palas_config_through_cardano_config.yml | 4 ---- .../.changes/20261027_release_11_2_0.yml | 9 ++++++++ cardano-testnet/CHANGELOG.md | 22 +++++++++++++++++++ cardano-testnet/cardano-testnet.cabal | 2 +- 40 files changed, 70 insertions(+), 145 deletions(-) delete mode 100644 cardano-node-chairman/.changes/20260903_release_11_1_1.yml delete mode 100644 cardano-node-chairman/.changes/20260918_133500_mgalazyn_readme_core_maintainers.yml delete mode 100644 cardano-node-chairman/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml delete mode 100644 cardano-node-chairman/.changes/20261015_171029_palas_chairman_reads_cardano_config.yml create mode 100644 cardano-node-chairman/.changes/20261027_release_11_2_0.yml delete mode 100644 cardano-submit-api/.changes/20260903_release_11_1_1.yml delete mode 100644 cardano-submit-api/.changes/20260904_123655_mgalazyn_bump_cardano_api_11_7.yml delete mode 100644 cardano-submit-api/.changes/20260918_133500_mgalazyn_readme_core_maintainers.yml delete mode 100644 cardano-submit-api/.changes/20261006_174922_mgalazyn_submit_api_dijkstra_tx_decoding.yml delete mode 100644 cardano-submit-api/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml delete mode 100644 cardano-submit-api/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml create mode 100644 cardano-submit-api/.changes/20261027_release_11_2_0.yml delete mode 100644 cardano-testnet/.changes/20260714_120000_fabrizio.ferrai_node_11_1_testnet_integration.md delete mode 100644 cardano-testnet/.changes/20260820_124721_mgalazyn_reenable_rpc_readgenesis_initialfunds_assertion.yml delete mode 100644 cardano-testnet/.changes/20260903_132208_mgalazyn_add_rpc_read_era_summary_test.yml delete mode 100644 cardano-testnet/.changes/20260903_release_11_1_1.yml delete mode 100644 cardano-testnet/.changes/20260904_123655_mgalazyn_bump_cardano_api_11_7.yml delete mode 100644 cardano-testnet/.changes/20260904_123655_mgalazyn_rpc_v1beta_spec_test_update.yml delete mode 100644 cardano-testnet/.changes/20260909_mgalazyn_enable_grpc_http.yml delete mode 100644 cardano-testnet/.changes/20260911_170000_palas_restore_readme_docs.yml delete mode 100644 cardano-testnet/.changes/20260914_150000_palas_check_readme_help.yml delete mode 100644 cardano-testnet/.changes/20260914_150000_palas_manifest.yml delete mode 100644 cardano-testnet/.changes/20260918_133500_mgalazyn_readme_core_maintainers.yml delete mode 100644 cardano-testnet/.changes/20260930_204211_cardano-testnet_sandy.yml delete mode 100644 cardano-testnet/.changes/20261002_174813_cardano-testnet_pablo.lamela.yml delete mode 100644 cardano-testnet/.changes/20261006_160204_cardano-testnet_sandy.yml delete mode 100644 cardano-testnet/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml delete mode 100644 cardano-testnet/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml delete mode 100644 cardano-testnet/.changes/20261015_033946_palas_config_through_cardano_config.yml create mode 100644 cardano-testnet/.changes/20261027_release_11_2_0.yml diff --git a/bench/cardano-profile/cardano-profile.cabal b/bench/cardano-profile/cardano-profile.cabal index 438f2d86a75..054d9c048bb 100644 --- a/bench/cardano-profile/cardano-profile.cabal +++ b/bench/cardano-profile/cardano-profile.cabal @@ -1,7 +1,7 @@ cabal-version: 3.0 name: cardano-profile -version: 11.1.1 +version: 11.2.0 synopsis: A Cardano benchmarking profile generator description: A Cardano benchmarking profile generator. category: Cardano, diff --git a/bench/cardano-topology/cardano-topology.cabal b/bench/cardano-topology/cardano-topology.cabal index 6c4e8a97c97..4348f860300 100644 --- a/bench/cardano-topology/cardano-topology.cabal +++ b/bench/cardano-topology/cardano-topology.cabal @@ -1,7 +1,7 @@ cabal-version: 3.0 name: cardano-topology -version: 11.1.1 +version: 11.2.0 synopsis: A cardano topology generator description: A cardano topology generator. category: Cardano, diff --git a/cardano-node-chairman/.changes/20260903_release_11_1_1.yml b/cardano-node-chairman/.changes/20260903_release_11_1_1.yml deleted file mode 100644 index 65c53fc33c2..00000000000 --- a/cardano-node-chairman/.changes/20260903_release_11_1_1.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6674 -kind: - - release -description: | - Release 11.1.1 diff --git a/cardano-node-chairman/.changes/20260918_133500_mgalazyn_readme_core_maintainers.yml b/cardano-node-chairman/.changes/20260918_133500_mgalazyn_readme_core_maintainers.yml deleted file mode 100644 index ee28e113a85..00000000000 --- a/cardano-node-chairman/.changes/20260918_133500_mgalazyn_readme_core_maintainers.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6696 -kind: - - documentation -description: | - Added a README with a core maintainers section. diff --git a/cardano-node-chairman/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml b/cardano-node-chairman/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml deleted file mode 100644 index c828358e7bd..00000000000 --- a/cardano-node-chairman/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6677 -kind: - - maintenance -description: | - Bumped `cardano-cli` to 11.3 and `cardano-crypto-class` to 2.6 for the 11.2 release. diff --git a/cardano-node-chairman/.changes/20261015_171029_palas_chairman_reads_cardano_config.yml b/cardano-node-chairman/.changes/20261015_171029_palas_chairman_reads_cardano_config.yml deleted file mode 100644 index a0498a0840d..00000000000 --- a/cardano-node-chairman/.changes/20261015_171029_palas_chairman_reads_cardano_config.yml +++ /dev/null @@ -1,4 +0,0 @@ -pr: 6677 -kind: - - feature -description: The chairman reads node configurations in the cardano-config format too, the way the node does. diff --git a/cardano-node-chairman/.changes/20261027_release_11_2_0.yml b/cardano-node-chairman/.changes/20261027_release_11_2_0.yml new file mode 100644 index 00000000000..3f686a63383 --- /dev/null +++ b/cardano-node-chairman/.changes/20261027_release_11_2_0.yml @@ -0,0 +1,9 @@ +pr: 6677 +kind: + - release +description: | + Release 11.2.0 + + Cuts the 11.2.0 release of cardano-node and the packages versioned + alongside it: cardano-node-chairman, cardano-submit-api and + cardano-testnet. diff --git a/cardano-node-chairman/CHANGELOG.md b/cardano-node-chairman/CHANGELOG.md index d79444ddc51..cd52ad9d3dd 100644 --- a/cardano-node-chairman/CHANGELOG.md +++ b/cardano-node-chairman/CHANGELOG.md @@ -1,3 +1,9 @@ # Changelog for cardano-node-chairman +## 11.2.0 -- 2026-10-27 + +- The chairman reads node configurations in the cardano-config format too, the way the node does. + (feature) + [PR 6677](https://github.com/IntersectMBO/cardano-node/pull/6677) + ## 11.1.1 -- 2026-08-31 diff --git a/cardano-node-chairman/cardano-node-chairman.cabal b/cardano-node-chairman/cardano-node-chairman.cabal index de40fb3ca25..9e8271910f7 100644 --- a/cardano-node-chairman/cardano-node-chairman.cabal +++ b/cardano-node-chairman/cardano-node-chairman.cabal @@ -1,7 +1,7 @@ cabal-version: 3.0 name: cardano-node-chairman -version: 11.1.1 +version: 11.2.0 synopsis: The cardano full node description: The cardano full node. category: Cardano, @@ -46,7 +46,7 @@ executable cardano-node-chairman , cardano-crypto-class , cardano-git-rev ^>= 0.2.2 , cardano-ledger-core - , cardano-node ^>= 11.1 + , cardano-node ^>= 11.2 , cardano-prelude , containers , contra-tracer diff --git a/cardano-node/ChangeLog.md b/cardano-node/ChangeLog.md index 7c012c7f71e..788646127e6 100644 --- a/cardano-node/ChangeLog.md +++ b/cardano-node/ChangeLog.md @@ -1,6 +1,6 @@ # Changelog for cardano-node -## Next version +## 11.2.0 -- October 2026 - Standard handles now always use UTF-8, independent of the system code page or locale. On Windows, stdout traces were written in the legacy code page, so the diff --git a/cardano-node/cardano-node.cabal b/cardano-node/cardano-node.cabal index a898dde1a76..1336523fda6 100644 --- a/cardano-node/cardano-node.cabal +++ b/cardano-node/cardano-node.cabal @@ -1,7 +1,7 @@ cabal-version: 3.8 name: cardano-node -version: 11.1.1 +version: 11.2.0 synopsis: The cardano full node description: The cardano full node. category: Cardano, diff --git a/cardano-submit-api/.changes/20260903_release_11_1_1.yml b/cardano-submit-api/.changes/20260903_release_11_1_1.yml deleted file mode 100644 index 65c53fc33c2..00000000000 --- a/cardano-submit-api/.changes/20260903_release_11_1_1.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6674 -kind: - - release -description: | - Release 11.1.1 diff --git a/cardano-submit-api/.changes/20260904_123655_mgalazyn_bump_cardano_api_11_7.yml b/cardano-submit-api/.changes/20260904_123655_mgalazyn_bump_cardano_api_11_7.yml deleted file mode 100644 index f5107a79e64..00000000000 --- a/cardano-submit-api/.changes/20260904_123655_mgalazyn_bump_cardano_api_11_7.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6668 -kind: - - maintenance -description: | - Bumped cardano-api to 11.7. diff --git a/cardano-submit-api/.changes/20260918_133500_mgalazyn_readme_core_maintainers.yml b/cardano-submit-api/.changes/20260918_133500_mgalazyn_readme_core_maintainers.yml deleted file mode 100644 index d9968d93192..00000000000 --- a/cardano-submit-api/.changes/20260918_133500_mgalazyn_readme_core_maintainers.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6696 -kind: - - documentation -description: | - Added a core maintainers section to the README. diff --git a/cardano-submit-api/.changes/20261006_174922_mgalazyn_submit_api_dijkstra_tx_decoding.yml b/cardano-submit-api/.changes/20261006_174922_mgalazyn_submit_api_dijkstra_tx_decoding.yml deleted file mode 100644 index ba8d058861c..00000000000 --- a/cardano-submit-api/.changes/20261006_174922_mgalazyn_submit_api_dijkstra_tx_decoding.yml +++ /dev/null @@ -1,6 +0,0 @@ -pr: 6725 -kind: - - bugfix -description: | - Fixed `cardano-submit-api` rejecting Dijkstra era transactions with a `TxCmdTxReadError` decoding error. - Transactions from every Shelley-based era, including Dijkstra, are now decoded and submitted to the node. diff --git a/cardano-submit-api/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml b/cardano-submit-api/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml deleted file mode 100644 index d7e88b8d194..00000000000 --- a/cardano-submit-api/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6677 -kind: - - maintenance -description: | - Bumped `cardano-api` to 11.8, `cardano-cli` to 11.3 and `cardano-crypto-class` to 2.6 for the 11.2 release. diff --git a/cardano-submit-api/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml b/cardano-submit-api/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml deleted file mode 100644 index 007bd13e793..00000000000 --- a/cardano-submit-api/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml +++ /dev/null @@ -1,4 +0,0 @@ -pr: 6677 -kind: - - maintenance -description: Bumped cardano-api to 11.11 and cardano-cli to 11.6. diff --git a/cardano-submit-api/.changes/20261027_release_11_2_0.yml b/cardano-submit-api/.changes/20261027_release_11_2_0.yml new file mode 100644 index 00000000000..3f686a63383 --- /dev/null +++ b/cardano-submit-api/.changes/20261027_release_11_2_0.yml @@ -0,0 +1,9 @@ +pr: 6677 +kind: + - release +description: | + Release 11.2.0 + + Cuts the 11.2.0 release of cardano-node and the packages versioned + alongside it: cardano-node-chairman, cardano-submit-api and + cardano-testnet. diff --git a/cardano-submit-api/CHANGELOG.md b/cardano-submit-api/CHANGELOG.md index 43f7ea5e177..4ea8cc770ec 100644 --- a/cardano-submit-api/CHANGELOG.md +++ b/cardano-submit-api/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog for Cardano-submit-api +## 11.2.0 -- 2026-10-27 + +- Fixed `cardano-submit-api` rejecting Dijkstra era transactions with a `TxCmdTxReadError` decoding error. + Transactions from every Shelley-based era, including Dijkstra, are now decoded and submitted to the node. + (bugfix) + [PR 6725](https://github.com/IntersectMBO/cardano-node/pull/6725) + ## 11.1.1 -- 2026-08-31 - `TxSubmitWebApiError` is now a newtype over its only remaining constructor, `TxSubmitFail`. `TxSubmitDecodeHex`, `TxSubmitEmpty`, `TxSubmitDecodeFail` and `TxSubmitBadTx` are gone, along with their `ToJSON` output: every submission failure is already reported through `TxCmdError`. diff --git a/cardano-submit-api/cardano-submit-api.cabal b/cardano-submit-api/cardano-submit-api.cabal index cd5e2ad23da..5d80927f8a9 100644 --- a/cardano-submit-api/cardano-submit-api.cabal +++ b/cardano-submit-api/cardano-submit-api.cabal @@ -1,7 +1,7 @@ cabal-version: 3.0 name: cardano-submit-api -version: 11.1.1 +version: 11.2.0 synopsis: A web server that allows transactions to be POSTed to the cardano chain description: A web server that allows transactions to be POSTed to the cardano chain. homepage: https://github.com/intersectmbo/cardano-node diff --git a/cardano-testnet/.changes/20260714_120000_fabrizio.ferrai_node_11_1_testnet_integration.md b/cardano-testnet/.changes/20260714_120000_fabrizio.ferrai_node_11_1_testnet_integration.md deleted file mode 100644 index 96a6eecb8e3..00000000000 --- a/cardano-testnet/.changes/20260714_120000_fabrizio.ferrai_node_11_1_testnet_integration.md +++ /dev/null @@ -1,5 +0,0 @@ -### Changed - -- Migrated ping support from `cardano-ping` to `cardano-diffusion:ping`: `Testnet.Ping` now wraps `Cardano.Network.Ping.pingClient` instead of the hand-rolled mux implementation. -- Threaded a filesystem handle (`SomeHasFS IO` from `fs-api`) through the `foldEpochState` call sites, via a new `mkNodeConfigFs` helper in `Testnet.Filepath`. -- Bumped `cardano-crypto-class` to `^>= 2.5`. diff --git a/cardano-testnet/.changes/20260820_124721_mgalazyn_reenable_rpc_readgenesis_initialfunds_assertion.yml b/cardano-testnet/.changes/20260820_124721_mgalazyn_reenable_rpc_readgenesis_initialfunds_assertion.yml deleted file mode 100644 index 13dca038a8b..00000000000 --- a/cardano-testnet/.changes/20260820_124721_mgalazyn_reenable_rpc_readgenesis_initialfunds_assertion.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6657 -kind: - - test -description: | - Strengthened the UTxO RPC `ReadGenesis` test: re-enabled the `initialFunds` assertion and upgraded it to an exact comparison with the funds embedded in the genesis file, checked the returned genesis hash against the Blake2b-256 hash of the Shelley genesis file, and added coverage for the `FAILED_PRECONDITION` error when the genesis file changes after node startup. diff --git a/cardano-testnet/.changes/20260903_132208_mgalazyn_add_rpc_read_era_summary_test.yml b/cardano-testnet/.changes/20260903_132208_mgalazyn_add_rpc_read_era_summary_test.yml deleted file mode 100644 index 27112498980..00000000000 --- a/cardano-testnet/.changes/20260903_132208_mgalazyn_add_rpc_read_era_summary_test.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6679 -kind: - - test -description: | - Added `hprop_rpc_read_era_summary` integration test for the UTxO RPC `QueryService.ReadEraSummary` method, verifying the returned era summaries are a prefix of the canonical era order, that every era but the last has its end boundary set, that consecutive boundaries line up, and that the first era starts at slot 0, epoch 0. diff --git a/cardano-testnet/.changes/20260903_release_11_1_1.yml b/cardano-testnet/.changes/20260903_release_11_1_1.yml deleted file mode 100644 index 65c53fc33c2..00000000000 --- a/cardano-testnet/.changes/20260903_release_11_1_1.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6674 -kind: - - release -description: | - Release 11.1.1 diff --git a/cardano-testnet/.changes/20260904_123655_mgalazyn_bump_cardano_api_11_7.yml b/cardano-testnet/.changes/20260904_123655_mgalazyn_bump_cardano_api_11_7.yml deleted file mode 100644 index 8d7cd913de0..00000000000 --- a/cardano-testnet/.changes/20260904_123655_mgalazyn_bump_cardano_api_11_7.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6668 -kind: - - maintenance -description: | - Bumped cardano-api to 11.7 and cardano-rpc to 11.3. diff --git a/cardano-testnet/.changes/20260904_123655_mgalazyn_rpc_v1beta_spec_test_update.yml b/cardano-testnet/.changes/20260904_123655_mgalazyn_rpc_v1beta_spec_test_update.yml deleted file mode 100644 index 72027fdf122..00000000000 --- a/cardano-testnet/.changes/20260904_123655_mgalazyn_rpc_v1beta_spec_test_update.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6668 -kind: - - test -description: | - Updated the UTxO RPC `FetchBlock` test for the latest v1beta spec, where the block reference request field and the block response field became repeated. diff --git a/cardano-testnet/.changes/20260909_mgalazyn_enable_grpc_http.yml b/cardano-testnet/.changes/20260909_mgalazyn_enable_grpc_http.yml deleted file mode 100644 index ec4aeb0f0f9..00000000000 --- a/cardano-testnet/.changes/20260909_mgalazyn_enable_grpc_http.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6685 -kind: - - feature -description: | - The `cardano-testnet cardano` command gained `--enable-grpc-http` to enable the node gRPC endpoint over HTTP without TLS (h2c), with each node listening by default on 127.0.0.1 on a random free port; the listen address can be customised with `--grpc-listen-address`, and fixed ports can be assigned with `--grpc-listen-port-base` (testnet node *i* then listens on the base port plus *i*-1); the existing `--enable-grpc` option continues to serve gRPC over a unix socket; when gRPC is enabled, each node's gRPC endpoint is printed in the startup summary. diff --git a/cardano-testnet/.changes/20260911_170000_palas_restore_readme_docs.yml b/cardano-testnet/.changes/20260911_170000_palas_restore_readme_docs.yml deleted file mode 100644 index cad2d161a46..00000000000 --- a/cardano-testnet/.changes/20260911_170000_palas_restore_readme_docs.yml +++ /dev/null @@ -1,7 +0,0 @@ -pr: 6688 -kind: - - documentation -description: | - - Restored the `cardano-testnet` usage guide into `cardano-testnet/README.md`, - replacing the link to the developer portal (which deleted the page), and - refreshed it for the current command-line interface diff --git a/cardano-testnet/.changes/20260914_150000_palas_check_readme_help.yml b/cardano-testnet/.changes/20260914_150000_palas_check_readme_help.yml deleted file mode 100644 index 1f910fc1763..00000000000 --- a/cardano-testnet/.changes/20260914_150000_palas_check_readme_help.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6692 -kind: - - test -description: | - Added the `golden_HelpReadme` test to the `cardano-testnet-golden` suite: the command help shown in `cardano-testnet/README.md` (the code blocks annotated with `checked-help` comments) is now checked against the output of the real `cardano-testnet` binary, so the README can no longer silently go out of date. When the help changes, the blocks can be refreshed automatically by running the test with `RECREATE_GOLDEN_FILES=1`. diff --git a/cardano-testnet/.changes/20260914_150000_palas_manifest.yml b/cardano-testnet/.changes/20260914_150000_palas_manifest.yml deleted file mode 100644 index 6ebc16de5f5..00000000000 --- a/cardano-testnet/.changes/20260914_150000_palas_manifest.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6693 -kind: - - feature -description: | - When the network is ready, `cardano-testnet cardano` now writes a machine-readable `manifest.json` into the output directory. The file lists every socket, port, key path, genesis file and wallet address the cluster was started with, so scripts and test harnesses can discover the network without parsing the directory layout. The file is written atomically (it appears only after all readiness checks pass) and is never modified after being written. A strict JSON Schema (`cardano-testnet/schemas/manifest.schema.json`) accompanies the file. diff --git a/cardano-testnet/.changes/20260918_133500_mgalazyn_readme_core_maintainers.yml b/cardano-testnet/.changes/20260918_133500_mgalazyn_readme_core_maintainers.yml deleted file mode 100644 index d9968d93192..00000000000 --- a/cardano-testnet/.changes/20260918_133500_mgalazyn_readme_core_maintainers.yml +++ /dev/null @@ -1,5 +0,0 @@ -pr: 6696 -kind: - - documentation -description: | - Added a core maintainers section to the README. diff --git a/cardano-testnet/.changes/20260930_204211_cardano-testnet_sandy.yml b/cardano-testnet/.changes/20260930_204211_cardano-testnet_sandy.yml deleted file mode 100644 index e6610d87203..00000000000 --- a/cardano-testnet/.changes/20260930_204211_cardano-testnet_sandy.yml +++ /dev/null @@ -1,6 +0,0 @@ -description: Added a new `--enable-tracer` option, which when set starts up `cardano-tracer` - and causes all testnet nodes to send tracing data to it -kind: -- feature -pr: 6710 -project: cardano-testnet diff --git a/cardano-testnet/.changes/20261002_174813_cardano-testnet_pablo.lamela.yml b/cardano-testnet/.changes/20261002_174813_cardano-testnet_pablo.lamela.yml deleted file mode 100644 index f5b4ae20f6a..00000000000 --- a/cardano-testnet/.changes/20261002_174813_cardano-testnet_pablo.lamela.yml +++ /dev/null @@ -1,6 +0,0 @@ -description: Generalise DRep helpers to use conway-onwards era and add Dijkstra genesis - to the list of removed files. -kind: -- refactoring -pr: 6715 -project: cardano-testnet diff --git a/cardano-testnet/.changes/20261006_160204_cardano-testnet_sandy.yml b/cardano-testnet/.changes/20261006_160204_cardano-testnet_sandy.yml deleted file mode 100644 index bb85308bc77..00000000000 --- a/cardano-testnet/.changes/20261006_160204_cardano-testnet_sandy.yml +++ /dev/null @@ -1,5 +0,0 @@ -description: Support --prometheus-listen-address and --prometheus-listen-port -kind: -- feature -pr: 6723 -project: cardano-testnet diff --git a/cardano-testnet/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml b/cardano-testnet/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml deleted file mode 100644 index 1c7b2a3fb41..00000000000 --- a/cardano-testnet/.changes/20261008_102852_koslambrou_bump_deps_11_2.yml +++ /dev/null @@ -1,6 +0,0 @@ -pr: 6677 -kind: - - maintenance -description: | - Bumped `cardano-api` to 11.8, `cardano-cli` to 11.3, `cardano-crypto-class` to 2.6, `ouroboros-network` to 1.3 and `cardano-diffusion` to 1.3 for the 11.2 release, and adapted to the new APIs. - Added `Testnet.Defaults.defaultDijkstraGenesis`, which trims the cardano-api Dijkstra genesis defaults so that the PlutusV4 cost model carries exactly the number of parameters the ledger's genesis decoder accepts. diff --git a/cardano-testnet/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml b/cardano-testnet/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml deleted file mode 100644 index 007bd13e793..00000000000 --- a/cardano-testnet/.changes/20261015_033428_palas_bump_cardano_api_11_9.yml +++ /dev/null @@ -1,4 +0,0 @@ -pr: 6677 -kind: - - maintenance -description: Bumped cardano-api to 11.11 and cardano-cli to 11.6. diff --git a/cardano-testnet/.changes/20261015_033946_palas_config_through_cardano_config.yml b/cardano-testnet/.changes/20261015_033946_palas_config_through_cardano_config.yml deleted file mode 100644 index e6da7f89a66..00000000000 --- a/cardano-testnet/.changes/20261015_033946_palas_config_through_cardano_config.yml +++ /dev/null @@ -1,4 +0,0 @@ -pr: 6677 -kind: - - breaking -description: Testnet node configurations are written in the cardano-config format and through cardano-config, with their genesis hashes refreshed whenever the testnet starts and the node's default tracing options written out; removed createConfigJson, createConfigJsonNoHash, getByronGenesisHash, getShelleyGenesisHash, GenesisHashesPolicy and the configPath field of SubmitApiConf, and getStartTime no longer takes a path. diff --git a/cardano-testnet/.changes/20261027_release_11_2_0.yml b/cardano-testnet/.changes/20261027_release_11_2_0.yml new file mode 100644 index 00000000000..3f686a63383 --- /dev/null +++ b/cardano-testnet/.changes/20261027_release_11_2_0.yml @@ -0,0 +1,9 @@ +pr: 6677 +kind: + - release +description: | + Release 11.2.0 + + Cuts the 11.2.0 release of cardano-node and the packages versioned + alongside it: cardano-node-chairman, cardano-submit-api and + cardano-testnet. diff --git a/cardano-testnet/CHANGELOG.md b/cardano-testnet/CHANGELOG.md index 6b529ce3c67..fae113e1225 100644 --- a/cardano-testnet/CHANGELOG.md +++ b/cardano-testnet/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog for cardano-testnet +## 11.2.0 -- 2026-10-27 + +- Support --prometheus-listen-address and --prometheus-listen-port + (feature) + [PR 6723](https://github.com/IntersectMBO/cardano-node/pull/6723) + +- Added a new `--enable-tracer` option, which when set starts up `cardano-tracer` and causes all testnet nodes to send tracing data to it + (feature) + [PR 6710](https://github.com/IntersectMBO/cardano-node/pull/6710) + +- When the network is ready, `cardano-testnet cardano` now writes a machine-readable `manifest.json` into the output directory. The file lists every socket, port, key path, genesis file and wallet address the cluster was started with, so scripts and test harnesses can discover the network without parsing the directory layout. The file is written atomically (it appears only after all readiness checks pass) and is never modified after being written. A strict JSON Schema (`cardano-testnet/schemas/manifest.schema.json`) accompanies the file. + (feature) + [PR 6693](https://github.com/IntersectMBO/cardano-node/pull/6693) + +- The `cardano-testnet cardano` command gained `--enable-grpc-http` to enable the node gRPC endpoint over HTTP without TLS (h2c), with each node listening by default on 127.0.0.1 on a random free port; the listen address can be customised with `--grpc-listen-address`, and fixed ports can be assigned with `--grpc-listen-port-base` (testnet node *i* then listens on the base port plus *i*-1); the existing `--enable-grpc` option continues to serve gRPC over a unix socket; when gRPC is enabled, each node's gRPC endpoint is printed in the startup summary. + (feature) + [PR 6685](https://github.com/IntersectMBO/cardano-node/pull/6685) + +- Testnet node configurations are written in the cardano-config format and through cardano-config, with their genesis hashes refreshed whenever the testnet starts and the node's default tracing options written out; removed createConfigJson, createConfigJsonNoHash, getByronGenesisHash, getShelleyGenesisHash, GenesisHashesPolicy and the configPath field of SubmitApiConf, and getStartTime no longer takes a path. + (breaking) + [PR 6677](https://github.com/IntersectMBO/cardano-node/pull/6677) + ## 11.1.1 -- 2026-08-31 - - `testnetNodes` in `TestnetRuntime` is now `NonEmpty` (a testnet always has at least one node), so consumers no longer need node-count checks before taking the first node. diff --git a/cardano-testnet/cardano-testnet.cabal b/cardano-testnet/cardano-testnet.cabal index 77d2ef62218..94f346fddea 100644 --- a/cardano-testnet/cardano-testnet.cabal +++ b/cardano-testnet/cardano-testnet.cabal @@ -1,7 +1,7 @@ cabal-version: 3.0 name: cardano-testnet -version: 11.1.1 +version: 11.2.0 synopsis: The cardano full node description: The cardano full node. copyright: 2021-2023 Input Output Global Inc (IOG), 2023-2026 Intersect.