diff --git a/cardano-node/src/Cardano/Node/Tracing/Era/Shelley.hs b/cardano-node/src/Cardano/Node/Tracing/Era/Shelley.hs index dfe278a1b4d..5e795de9e33 100644 --- a/cardano-node/src/Cardano/Node/Tracing/Era/Shelley.hs +++ b/cardano-node/src/Cardano/Node/Tracing/Era/Shelley.hs @@ -27,11 +27,10 @@ import qualified Cardano.Ledger.Alonzo.PlutusScriptApi as Alonzo import Cardano.Ledger.Alonzo.Rules (AlonzoBbodyPredFailure, AlonzoUtxoPredFailure, AlonzoUtxosPredFailure, AlonzoUtxowPredFailure (..)) import qualified Cardano.Ledger.Alonzo.Rules as Alonzo -import qualified Cardano.Ledger.Alonzo.Tx as Alonzo import qualified Cardano.Ledger.AuxiliaryData as Ledger import Cardano.Ledger.Babbage.Rules (BabbageUtxoPredFailure, BabbageUtxowPredFailure) import qualified Cardano.Ledger.Babbage.Rules as Babbage -import Cardano.Ledger.BaseTypes (activeSlotLog) +import Cardano.Ledger.BaseTypes (activeSlotLog, strictMaybeToMaybe) import Cardano.Ledger.Chain import Cardano.Ledger.Conway.Governance (govActionIdToText) import qualified Cardano.Ledger.Conway.Rules as Conway @@ -42,6 +41,8 @@ import qualified Cardano.Ledger.SafeHash as SafeHash import Cardano.Ledger.Shelley.API import Cardano.Ledger.Shelley.Rules import Cardano.Logging +import Cardano.Node.Tracing.Render (renderMissingRedeemers, renderScriptHash, + renderScriptIntegrityHash) import Cardano.Protocol.TPraos.API (ChainTransitionError (ChainTransitionError)) import Cardano.Protocol.TPraos.BHeader (LastAppliedBlock, labBlockNo) import Cardano.Protocol.TPraos.OCert (KESPeriod (KESPeriod)) @@ -66,8 +67,7 @@ import Ouroboros.Consensus.Util.Condense (condense) import Ouroboros.Network.Block (SlotNo (..), blockHash, blockNo, blockSlot) import Ouroboros.Network.Point (WithOrigin, withOriginToMaybe) -import Data.Aeson (ToJSON (..), Value (..), (.=)) -import qualified Data.Aeson as Aeson +import Data.Aeson (ToJSON (..), Value (..), object, (.=)) import Data.Set (Set) import qualified Data.Set as Set import Data.Text (Text) @@ -89,18 +89,83 @@ instance : [ "tx" .= condense tx | dtal == DDetailed ] instance LogFormatting (Set (Credential 'Staking StandardCrypto)) where - forMachine _dtal creds = mconcat - [ "stake credentials" .= Set.map show creds ] -- TODO: Conway era - render this in a nicer way + forMachine _dtal creds = + mconcat [ "kind" .= String "StakeCreds" + , "stakeCreds" .= map forMachine' (Set.toList creds) + ] + where + forMachine' = object . \case + ScriptHashObj sHash -> ["scriptHash" .= renderScriptHash sHash] + KeyHashObj keyHash -> ["keyHash" .= textShow keyHash] instance - ( Show (PredicateFailure (Ledger.EraRule "DELEG" era)) - , Show (PredicateFailure (Ledger.EraRule "POOL" era)) - , Show (PredicateFailure (Ledger.EraRule "VDEL" era)) + ( LogFormatting (PredicateFailure (Ledger.EraRule "DELEG" era)) + , LogFormatting (PredicateFailure (Ledger.EraRule "POOL" era)) + , LogFormatting (PredicateFailure (Ledger.EraRule "VDEL" era)) ) => LogFormatting (Conway.ConwayCertPredFailure era) where - forMachine _dtal cfail = - mconcat [ "kind" .= String "ConwayCertPredFailure" - , "failure" .= show cfail -- TODO: Conway era - render in a nicer way - ] + 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.VDelFailure f -> + [ "kind" .= String "VDelFailure" , "failure" .= forMachine dtal f ] + +instance LogFormatting (Conway.ConwayVDelPredFailure era) where + forMachine _dtal = mconcat . \case + Conway.ConwayDRepAlreadyRegisteredVDEL credential -> + [ "kind" .= String "ConwayDRepAlreadyRegisteredVDEL" + , "credential" .= String (textShow credential) + , "error" .= String "DRep is already registered" + ] + Conway.ConwayDRepNotRegisteredVDEL credential -> + [ "kind" .= String "ConwayDRepNotRegisteredVDEL" + , "credential" .= String (textShow credential) + , "error" .= String "DRep is not registered" + ] + Conway.ConwayDRepIncorrectDepositVDEL coin -> + [ "kind" .= String "ConwayDRepIncorrectDepositVDEL" + , "coin" .= coin + , "error" .= String "DRep delegation has incorrect deposit" + ] + Conway.ConwayCommitteeHasResignedVDEL kHash -> + [ "kind" .= String "ConwayCommitteeHasResignedVDEL" + , "credential" .= String (textShow kHash) + , "error" .= String "Committee has resigned" + ] + + +instance LogFormatting (Conway.ConwayDelegPredFailure era) where + forMachine _dtal = mconcat . \case + Conway.IncorrectDepositDELEG coin -> + [ "kind" .= String "IncorrectDepositDELEG" + , "amount" .= coin + , "error" .= String "Incorrect deposit amount" + ] + Conway.StakeKeyAlreadyRegisteredDELEG credential -> + [ "kind" .= String "StakeKeyAlreadyRegisteredDELEG" + , "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.DRepAlreadyRegisteredForStakeKeyDELEG credential -> + [ "kind" .= String "DRepAlreadyRegisteredForStakeKeyDELEG" + , "amount" .= String (textShow credential) + , "error" .= String "DRep already registered for the stake key" + ] + Conway.WrongCertificateTypeDELEG -> + [ "kind" .= String "WrongCertificateTypeDELEG" + , "error" .= String "Wrong certificate type" + ] instance ( ShelleyCompatible protocol era @@ -278,14 +343,15 @@ instance instance ( Consensus.ShelleyBasedEra era + , Ledger.EraCrypto era ~ StandardCrypto , LogFormatting (PPUPPredFailure era) , LogFormatting (PredicateFailure (Ledger.EraRule "UTXO" era)) ) => LogFormatting (AlonzoUtxowPredFailure era) where forMachine dtal (ShelleyInAlonzoUtxowPredFailure utxoPredFail) = forMachine dtal utxoPredFail - forMachine _ (MissingRedeemers _scripts) = + forMachine _ (MissingRedeemers scripts) = mconcat [ "kind" .= String "MissingRedeemers" - , "scripts" .= String "TODO: Conway era" -- TODO: Conway era - need to parameterize renderMissingRedeemers over the era + , "scripts" .= renderMissingRedeemers scripts ] forMachine _ (MissingRequiredDatums required received) = mconcat [ "kind" .= String "MissingRequiredDatums" @@ -294,10 +360,10 @@ instance , "received" .= map (Crypto.hashToTextAsHex . SafeHash.extractHash) (Set.toList received) ] - forMachine _ (PPViewHashesDontMatch _ppHashInTxBody _ppHashFromPParams) = + forMachine _ (PPViewHashesDontMatch ppHashInTxBody ppHashFromPParams) = mconcat [ "kind" .= String "PPViewHashesDontMatch" - , "fromTxBody" .= String "TODO: Conway error" -- renderScriptIntegrityHash (strictMaybeToMaybe ppHashInTxBody) - , "fromPParams" .= String "TODO: Conway error" --renderScriptIntegrityHash (strictMaybeToMaybe ppHashFromPParams) + , "fromTxBody" .= renderScriptIntegrityHash (strictMaybeToMaybe ppHashInTxBody) + , "fromPParams" .= renderScriptIntegrityHash (strictMaybeToMaybe ppHashFromPParams) ] forMachine _ (MissingRequiredSigners missingKeyWitnesses) = mconcat [ "kind" .= String "MissingRequiredSigners" @@ -313,18 +379,14 @@ instance , "acceptable" .= Set.toList acceptable ] forMachine _ (ExtraRedeemers rdmrs) = - mconcat [ "kind" .= String "ExtraRedeemers" - , "rdmrs" .= map Api.fromAlonzoRdmrPtr rdmrs - ] - - -_renderScriptIntegrityHash :: Maybe (Alonzo.ScriptIntegrityHash StandardCrypto) -> Aeson.Value -_renderScriptIntegrityHash (Just witPPDataHash) = - Aeson.String . Crypto.hashToTextAsHex $ SafeHash.extractHash witPPDataHash -_renderScriptIntegrityHash Nothing = Aeson.Null + mconcat + [ "kind" .= String "ExtraRedeemers" + , "rdmrs" .= map Api.fromAlonzoRdmrPtr rdmrs + ] instance ( Consensus.ShelleyBasedEra era + , Ledger.EraCrypto era ~ StandardCrypto , ToJSON (Ledger.AuxiliaryDataHash (Ledger.EraCrypto era)) , LogFormatting (PredicateFailure (ShelleyUTXO era)) , LogFormatting (PredicateFailure (Ledger.EraRule "UTXO" era)) @@ -366,9 +428,9 @@ instance forMachine _dtal InvalidMetadata = mconcat [ "kind" .= String "InvalidMetadata" ] - forMachine _dtal (ExtraneousScriptWitnessesUTXOW _shashes) = + forMachine _dtal (ExtraneousScriptWitnessesUTXOW scriptHashes) = mconcat [ "kind" .= String "ExtraneousScriptWitnessesUTXOW" - , "scriptHashes" .= String "TODO: Conway era" -- Set.map Api.fromShelleyScriptHash shashes + , "scriptHashes" .= Set.map renderScriptHash scriptHashes ] instance @@ -952,9 +1014,9 @@ instance , "isvalidating" .= isValidating , "reason" .= reason ] - forMachine _ (Alonzo.CollectErrors _errors) = + forMachine _ (Alonzo.CollectErrors errors) = mconcat [ "kind" .= String "CollectErrors" - , "errors" .= String "TODO: Conway era" --errors + , "errors" .= errors ] forMachine dtal (Alonzo.UpdateFailure pFailure) = forMachine dtal pFailure @@ -994,6 +1056,7 @@ instance instance ( Ledger.Era era + , Ledger.EraCrypto era ~ StandardCrypto , ShelleyBasedEra era , LogFormatting (PPUPPredFailure era) , LogFormatting (ShelleyUtxowPredFailure era) diff --git a/cardano-node/src/Cardano/Node/Tracing/Render.hs b/cardano-node/src/Cardano/Node/Tracing/Render.hs index a5795c1c8b0..1edc7b6961d 100644 --- a/cardano-node/src/Cardano/Node/Tracing/Render.hs +++ b/cardano-node/src/Cardano/Node/Tracing/Render.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE GADTs #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} @@ -22,17 +24,31 @@ module Cardano.Node.Tracing.Render , renderTxId , renderTxIdForDetails , renderWithOrigin + , renderScriptHash + , renderScriptIntegrityHash + , renderScriptPurpose + , renderMissingRedeemers ) where +import qualified Cardano.Api.Shelley as Api +import qualified Cardano.Crypto.Hash.Class as Crypto import qualified Data.ByteString.Base16 as B16 import Data.Proxy (Proxy (..)) import Data.Text (Text) import qualified Data.Text as Text import qualified Data.Text.Encoding as Text +import qualified Cardano.Ledger.Alonzo.Tx as Alonzo +import qualified Cardano.Ledger.Core as Ledger +import Cardano.Ledger.Crypto (StandardCrypto) +import qualified Cardano.Ledger.SafeHash as SafeHash import Cardano.Logging import Cardano.Node.Queries (ConvertTxId (..)) import Cardano.Slotting.Slot (SlotNo (..), WithOrigin (..)) +import Data.Aeson ((.=)) +import qualified Data.Aeson as Aeson +import qualified Data.Aeson.Key as Aeson +import qualified Data.Aeson.Types as Aeson import Ouroboros.Consensus.Block (BlockNo (..), ConvertRawHash (..), RealPoint (..)) import Ouroboros.Consensus.Block.Abstract (Point (..)) import Ouroboros.Consensus.Ledger.SupportsMempool (GenTx, TxId) @@ -156,3 +172,41 @@ trimHashTextForDetails dtal = case dtal of DMinimal -> Text.take 7 _ -> id + +renderScriptIntegrityHash :: Maybe (Alonzo.ScriptIntegrityHash StandardCrypto) -> Aeson.Value +renderScriptIntegrityHash (Just witPPDataHash) = + Aeson.String . Crypto.hashToTextAsHex $ SafeHash.extractHash witPPDataHash +renderScriptIntegrityHash Nothing = Aeson.Null + + +renderMissingRedeemers :: () + => Ledger.EraCrypto ledgerera ~ StandardCrypto + => [(Alonzo.ScriptPurpose ledgerera, Ledger.ScriptHash StandardCrypto)] + -> Aeson.Value +renderMissingRedeemers scripts = Aeson.object $ map renderTuple scripts + where + renderTuple :: () + => Ledger.EraCrypto ledgerera ~ StandardCrypto + => (Alonzo.ScriptPurpose ledgerera, Ledger.ScriptHash StandardCrypto) + -> Aeson.Pair + renderTuple (scriptPurpose, sHash) = + Aeson.fromText (renderScriptHash sHash) .= renderScriptPurpose scriptPurpose + +renderScriptHash :: Ledger.ScriptHash StandardCrypto -> Text +renderScriptHash = Api.serialiseToRawBytesHexText . Api.fromShelleyScriptHash + +renderScriptPurpose :: () + => Ledger.EraCrypto ledgerera ~ StandardCrypto + => Alonzo.ScriptPurpose ledgerera + -> Aeson.Value +renderScriptPurpose = \case + Alonzo.Minting pid -> + Aeson.object [ "minting" .= Aeson.toJSON pid] + Alonzo.Spending txin -> + Aeson.object [ "spending" .= Api.fromShelleyTxIn txin] + Alonzo.Rewarding rwdAcct -> + Aeson.object [ "rewarding" .= Aeson.String (Api.serialiseAddress $ Api.fromShelleyStakeAddr rwdAcct)] + Alonzo.Certifying _cert -> + Aeson.object + [ "certifying" .= Aeson.toJSON @String "TODO CIP-1694 unimplemented" -- toJSON (Api.textEnvelopeDefaultDescr $ Api.fromShelleyCertificate sbe cert) + ] diff --git a/cardano-node/src/Cardano/Tracing/OrphanInstances/Network.hs b/cardano-node/src/Cardano/Tracing/OrphanInstances/Network.hs index 30edd867720..a575c73f479 100644 --- a/cardano-node/src/Cardano/Tracing/OrphanInstances/Network.hs +++ b/cardano-node/src/Cardano/Tracing/OrphanInstances/Network.hs @@ -7,13 +7,11 @@ {-# LANGUAGE PolyKinds #-} {-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -Wno-orphans #-} -{-# LANGUAGE GeneralizedNewtypeDeriving #-} module Cardano.Tracing.OrphanInstances.Network () where diff --git a/cardano-node/src/Cardano/Tracing/OrphanInstances/Shelley.hs b/cardano-node/src/Cardano/Tracing/OrphanInstances/Shelley.hs index 7ccfd3f3ae0..a4adba5276e 100644 --- a/cardano-node/src/Cardano/Tracing/OrphanInstances/Shelley.hs +++ b/cardano-node/src/Cardano/Tracing/OrphanInstances/Shelley.hs @@ -12,7 +12,6 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} -{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} @@ -21,7 +20,6 @@ module Cardano.Tracing.OrphanInstances.Shelley () where import Cardano.Api (textShow) -import qualified Cardano.Api as Api import qualified Cardano.Api.Shelley as Api import qualified Cardano.Crypto.Hash.Class as Crypto @@ -75,10 +73,10 @@ import Ouroboros.Consensus.Util.Condense (condense) import Ouroboros.Network.Block (SlotNo (..), blockHash, blockNo, blockSlot) import Ouroboros.Network.Point (WithOrigin, withOriginToMaybe) +import Cardano.Node.Tracing.Render (renderMissingRedeemers, renderScriptHash, + renderScriptIntegrityHash, renderScriptPurpose) import Data.Aeson (Value (..), object) import qualified Data.Aeson as Aeson -import qualified Data.Aeson.Key as Aeson -import qualified Data.Aeson.Types as Aeson import Data.Set (Set) import qualified Data.Set as Set import Data.Text (Text) @@ -403,52 +401,16 @@ instance , "rdmrs" .= map Api.fromAlonzoRdmrPtr rdmrs ] -renderScriptIntegrityHash :: Maybe (Alonzo.ScriptIntegrityHash StandardCrypto) -> Aeson.Value -renderScriptIntegrityHash (Just witPPDataHash) = - Aeson.String . Crypto.hashToTextAsHex $ SafeHash.extractHash witPPDataHash -renderScriptIntegrityHash Nothing = Aeson.Null - - -renderMissingRedeemers :: () - => Ledger.EraCrypto ledgerera ~ StandardCrypto - => [(Alonzo.ScriptPurpose ledgerera, ScriptHash StandardCrypto)] - -> Aeson.Value -renderMissingRedeemers scripts = Aeson.object $ map renderTuple scripts - where - renderTuple :: () - => Ledger.EraCrypto ledgerera ~ StandardCrypto - => (Alonzo.ScriptPurpose ledgerera, ScriptHash StandardCrypto) - -> Aeson.Pair - renderTuple (scriptPurpose, sHash) = - Aeson.fromText (renderScriptHash sHash) .= renderScriptPurpose scriptPurpose - -renderScriptHash :: ScriptHash StandardCrypto -> Text -renderScriptHash = Api.serialiseToRawBytesHexText . Api.fromShelleyScriptHash - -renderScriptPurpose :: () - => Ledger.EraCrypto ledgerera ~ StandardCrypto - => Alonzo.ScriptPurpose ledgerera - -> Aeson.Value -renderScriptPurpose = \case - Alonzo.Minting pid -> - Aeson.object [ "minting" .= toJSON pid] - Alonzo.Spending txin -> - Aeson.object [ "spending" .= Api.fromShelleyTxIn txin] - Alonzo.Rewarding rwdAcct -> - Aeson.object [ "rewarding" .= Aeson.String (Api.serialiseAddress $ Api.fromShelleyStakeAddr rwdAcct)] - Alonzo.Certifying _cert -> - Aeson.object - [ "certifying" .= toJSON @String "TODO CIP-1694 unimplemented" -- toJSON (Api.textEnvelopeDefaultDescr $ Api.fromShelleyCertificate sbe cert) - ] instance ( ToObject (PredicateFailure (ShelleyUTXO ledgerera)) , ToObject (PredicateFailure (Core.EraRule "UTXO" ledgerera)) + , Ledger.EraCrypto ledgerera ~ StandardCrypto , Core.Crypto (Ledger.EraCrypto ledgerera) ) => ToObject (ShelleyUtxowPredFailure ledgerera) where toObject _verb (ExtraneousScriptWitnessesUTXOW extraneousScripts) = mconcat [ "kind" .= String "InvalidWitnessesUTXOW" - , "extraneousScripts" .= extraneousScripts + , "extraneousScripts" .= Set.map renderScriptHash extraneousScripts ] toObject _verb (InvalidWitnessesUTXOW wits') = mconcat [ "kind" .= String "InvalidWitnessesUTXOW"