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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dmq-node/cddl/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,8 @@ indefiniteListFix term =
unpackResult :: IO (ExitCode, BL.ByteString, BL.ByteString)
-> IO (Either String BL.ByteString)
unpackResult r = r <&> \case
(ExitFailure _, _, err) -> (Left $ BL.Char8.unpack err)
(ExitSuccess, bytes, _) -> (Right bytes)
(ExitFailure _, _, err) -> Left (BL.Char8.unpack err)
(ExitSuccess, bytes, _) -> Right bytes


withTemporaryFile :: BL.ByteString -> (FilePath -> IO a) -> IO a
Expand Down
8 changes: 4 additions & 4 deletions dmq-node/cddl/specs/sig.cddl
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
message = [
messagePayload
messageId
, messagePayload
, kesSignature
, operationalCertificate
, coldVerificationKey
]
messagePayload = [
messageId
, messageBody
messageBody
, kesPeriod
, expiresAt
]

messageId = bstr
messageId = bstr .size 32
messageBody = bstr
messageSize = word32
kesSignature = bstr .size 448
Expand Down
38 changes: 38 additions & 0 deletions dmq-node/changelog.d/20260513_164011_coot_sig_id.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!--
A new scriv changelog fragment.

Uncomment the section that is right (remove the HTML comment wrapper).
For top level release notes, leave all the headers commented out.
-->

### Breaking

- Using `Hash Blake2b_256` hashing algorithm for computing `SigId`.
- Changed encoding of `Sig` according to: https://github.com/cardano-foundation/CIPs/pull/1185.
- Removed `TraceLocalMsgSubmission` `msg` parameter, since it was unused.
- Removed `ToJSON (AnyMessage SigSubmissionV2)` instance.

### Non-Breaking

- Validation of `SigId`s is implemented using `Hash Blake2b_256` hashing
algorithm.
- Implemented `DMaximum` verbosity for the following tracers:
- `AnyMessage (LocalMsgNotification (Sig crypto))`
- `AnyMessage (SigSubmissionV2 SigId (Sig crypto))`
- `AnyMessage (TxSubmission2 txid tx)`
- `TraceSigSubmissionOutbound SigId (Sig crypto)`
- the `TraceSigSubmissionOutboundSendMsgReplySigs` logs `sigs` rather than
`sigids` with different fields depending on the verbosity level.
in `DMaximum` tracing, all fields of `Sig crypto` are logged.
- Logging of `AnyMessage (SigSubmissionV2 SigId (Sig crypto))` changed syntax:
- log `sigids` of `MsgReplySigIds`
- log `sigids` of `MsgRequestSigs` using JSON syntax



<!--
### Patch

- A bullet item for the Patch category.

-->
17 changes: 8 additions & 9 deletions dmq-node/src/DMQ/NodeToClient/LocalMsgSubmission.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}

module DMQ.NodeToClient.LocalMsgSubmission where
Expand All @@ -18,7 +17,7 @@ import Cardano.Logging qualified as Logging

import DMQ.Protocol.LocalMsgSubmission.Server
import DMQ.Protocol.LocalMsgSubmission.Type
import DMQ.Protocol.SigSubmission.Type (Sig, SigId)
import DMQ.Protocol.SigSubmission.Type (SigId)

-- | Local transaction submission server, for adding txs to the 'Mempool'
--
Expand All @@ -27,7 +26,7 @@ localMsgSubmissionServer ::
Monad m
=> (msg -> msgid)
-- ^ get message id
-> Tracer m (TraceLocalMsgSubmission msg msgid)
-> Tracer m (TraceLocalMsgSubmission msgid)
-> (msg -> m (Either (msgid, SigValidationError) msgid))
-- ^ add a msg to mempool
-> m (LocalMsgSubmissionServer msg m ())
Expand All @@ -50,7 +49,7 @@ localMsgSubmissionServer getMsgId tracer mempoolAddTxs =
}


data TraceLocalMsgSubmission msg msgid =
data TraceLocalMsgSubmission msgid =
TraceReceivedMsg msgid
-- ^ A signature was received.
| TraceSubmitFailure msgid SigValidationError
Expand All @@ -59,10 +58,10 @@ data TraceLocalMsgSubmission msg msgid =
-- ^ A signature was validated and accepted into the mempool.

deriving instance
(Show msg, Show msgid)
=> Show (TraceLocalMsgSubmission msg msgid)
(Show msgid)
=> Show (TraceLocalMsgSubmission msgid)

instance Logging.LogFormatting (TraceLocalMsgSubmission (Sig crypto) SigId) where
instance Logging.LogFormatting (TraceLocalMsgSubmission SigId) where
forMachine _ (TraceReceivedMsg sigid) =
mconcat [ "kind" .= Aeson.String "TraceReceivedMsg"
, "sigid" .= sigid
Expand All @@ -77,7 +76,7 @@ instance Logging.LogFormatting (TraceLocalMsgSubmission (Sig crypto) SigId) wher
, "sigid" .= sigid
]

instance Logging.MetaTrace (TraceLocalMsgSubmission (Sig crypto) SigId) where
instance Logging.MetaTrace (TraceLocalMsgSubmission SigId) where
namespaceFor TraceReceivedMsg {} = Logging.Namespace [] ["TraceReceivedMsg"]
namespaceFor TraceSubmitFailure {} = Logging.Namespace [] ["TraceSubmitFailure"]
namespaceFor TraceSubmitAccept {} = Logging.Namespace [] ["TraceSubmitAccept"]
Expand Down Expand Up @@ -109,7 +108,7 @@ instance (Typeable msgid, Typeable msg, Show msgid)


instance ToJSON msgid
=> ToJSON (TraceLocalMsgSubmission msg msgid) where
=> ToJSON (TraceLocalMsgSubmission msgid) where
toJSON (TraceReceivedMsg msgid) =
-- TODO: once we have verbosity levels, we could include the full tx, for
-- now one can use `TraceSendRecv` tracer for the mini-protocol to see full
Expand Down
29 changes: 18 additions & 11 deletions dmq-node/src/DMQ/Protocol/SigSubmission/Codec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ module DMQ.Protocol.SigSubmission.Codec
import Control.Monad (when)
import Control.Monad.Class.MonadST
import Control.Monad.Class.MonadTime.SI
import Data.ByteString.Lazy (ByteString)
import Data.ByteString.Lazy as BS.Lazy
import Data.ByteString.Short qualified as BS.Short
import Text.Printf

import Codec.CBOR.Decoding qualified as CBOR
import Codec.CBOR.Encoding qualified as CBOR
import Codec.CBOR.Read qualified as CBOR

import Cardano.Crypto.Hash.Class (hashFromBytes, hashToBytesShort)

import Network.TypedProtocol.Codec.CBOR

import Cardano.Binary (FromCBOR (..), ToCBOR (..))
Expand Down Expand Up @@ -91,10 +94,14 @@ byteLimitsSigSubmission = ProtocolSizeLimits stateToLimit


encodeSigId :: SigId -> CBOR.Encoding
encodeSigId SigId { getSigId } = CBOR.encodeBytes (getSigHash getSigId)
encodeSigId SigId { getSigId } = CBOR.encodeBytes (BS.Short.fromShort (hashToBytesShort getSigId))

decodeSigId :: forall s. CBOR.Decoder s SigId
decodeSigId = SigId . SigHash <$> CBOR.decodeBytes
decodeSigId = do
mbHash <- hashFromBytes <$> CBOR.decodeBytes
case mbHash of
Nothing -> fail "decodeSigId: expected 32 bytes"
Just hs -> pure (SigId hs)


-- | We follow the same encoding as in `cardano-ledger` for `OCert`.
Expand Down Expand Up @@ -149,11 +156,12 @@ decodeSig :: forall crypto s.
=> CBOR.Decoder s (ByteString -> SigRawWithSignedBytes crypto)
decodeSig = do
a <- CBOR.decodeListLen
when (a /= 4) $ fail (printf "decodeSig: unexpected number of parameters %d for Sig" a)
when (a /= 5) $ fail (printf "decodeSig: unexpected number of parameters %d for Sig" a)
sigRawId <- decodeSigId

-- start of signed data
startOffset <- CBOR.peekByteOffset
(sigRawId, sigRawBody, sigRawKESPeriod, sigRawExpiresAt)
(sigRawBody, sigRawKESPeriod, sigRawExpiresAt)
<- decodePayload
endOffset <- CBOR.peekByteOffset
-- end of signed data
Expand All @@ -175,14 +183,13 @@ decodeSig = do
}
}
where
decodePayload :: CBOR.Decoder s (SigId, SigBody, KESPeriod, POSIXTime)
decodePayload :: CBOR.Decoder s (SigBody, KESPeriod, POSIXTime)
decodePayload = do
a <- CBOR.decodeListLen
when (a /= 4) $ fail (printf "decodeSig: unexpected number of parameters %d for Sig's payload" a)
(,,,) <$> decodeSigId
<*> (SigBody <$> CBOR.decodeBytes)
<*> (KESPeriod <$> CBOR.decodeWord)
<*> (realToFrac <$> CBOR.decodeWord32)
when (a /= 3) $ fail (printf "decodeSig: unexpected number of parameters %d for Sig's payload" a)
(,,) <$> (SigBody <$> CBOR.decodeBytes)
<*> (KESPeriod <$> CBOR.decodeWord)
<*> (realToFrac <$> CBOR.decodeWord32)



Expand Down
77 changes: 48 additions & 29 deletions dmq-node/src/DMQ/Protocol/SigSubmission/Type.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeData #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

module DMQ.Protocol.SigSubmission.Type
( -- * Data types
SigHash (..)
, SigId (..)
SigId (..)
, SigBody (..)
, SigKESSignature (..)
, SigOpCertificate (..)
Expand All @@ -29,28 +29,30 @@ module DMQ.Protocol.SigSubmission.Type
, SigValidationException (..)
-- * Utilities
, CBORBytes (..)
, Verbose (..)
-- * Re-exports from `kes-agent`
, KESPeriod (..)
) where

import Control.Exception (Exception (..))
import Data.Aeson
import Data.ByteString (ByteString)
import Data.ByteString.Base16 as BS.Base16
import Data.ByteString.Base16.Lazy as LBS.Base16
import Data.ByteString.Lazy qualified as LBS
import Data.ByteString.Lazy.Char8 qualified as LBS.Char8
import Data.Text (Text)
import Data.Text qualified as Text
import Data.Text.Encoding qualified as Text
import Data.Time.Clock.POSIX (POSIXTime)
import Data.Typeable
import Data.Word (Word64)

import Cardano.Crypto.DSIGN.Class (DSIGNAlgorithm, VerKeyDSIGN)
import Cardano.Crypto.Hash.Blake2b (Blake2b_256)
import Cardano.Crypto.Hash.Class (Hash)
import Cardano.Crypto.KES.Class (KESAlgorithm (..))
import Cardano.Crypto.Util (SignableRepresentation (..))
import Cardano.KESAgent.KES.Crypto as KES
import Cardano.KESAgent.KES.OCert (KESPeriod (..), OCert (..))
import Cardano.KESAgent.KES.OCert (KESPeriod (..), OCert (..),
OCertSignable (..))
import Cardano.Logging qualified as Logging

import Ouroboros.Network.Protocol.TxSubmission2.Type as SigSubmission hiding
Expand All @@ -59,20 +61,13 @@ import Ouroboros.Network.Protocol.TxSubmission2.Type as TxSubmission2
import Ouroboros.Network.Util.ShowProxy


newtype SigHash = SigHash { getSigHash :: ByteString }
deriving stock (Eq, Ord)
type data SigPayload

instance Show SigHash where
-- show first 10 bytes in hex
show (SigHash bs) = take 20 . Text.unpack . Text.decodeUtf8Lenient . BS.Base16.encode $ bs

newtype SigId = SigId { getSigId :: SigHash }
newtype SigId = SigId { getSigId :: Hash Blake2b_256 SigPayload }
deriving stock (Show, Eq, Ord)

instance ToJSON SigId where
toJSON (SigId (SigHash bs)) =
-- show first 10 bytes in hex
String (Text.take 20 . Text.decodeUtf8Lenient . BS.Base16.encode $ bs)
toJSON (SigId sigId) = toJSON sigId

instance ShowProxy SigId where

Expand Down Expand Up @@ -139,30 +134,43 @@ deriving instance ( DSIGNAlgorithm (KES.DSIGN crypto)

instance Crypto crypto
=> ToJSON (SigRaw crypto) where
-- TODO: it is too verbose, we need verbosity levels for these JSON fields
toJSON SigRaw { sigRawId
{- , sigRawBody -}
, sigRawKESPeriod
, sigRawExpiresAt
{- , sigRawKESSignature
, sigRawOpCertificate
, sigRawColdKey -}
} =
object [ "id" .= sigRawId
{- , "body" .= show (getSigBody sigRawBody) -}
, "kesPeriod" .= unKESPeriod sigRawKESPeriod
, "expiresAt" .= show sigRawExpiresAt
{- , "kesSignature" .= show (getSigKESSignature sigRawKESSignature)
]

newtype Verbose a = Verbose { unVerbose :: a }

instance Crypto crypto
=> ToJSON (Verbose (SigRaw crypto)) where
toJSON Verbose { unVerbose =
SigRaw { sigRawId
, sigRawBody
, sigRawKESPeriod
, sigRawExpiresAt
, sigRawKESSignature
, sigRawOpCertificate
, sigRawColdKey
}
} =

object [ "id" .= sigRawId
, "body" .= show (getSigBody sigRawBody)
, "kesPeriod" .= unKESPeriod sigRawKESPeriod
, "expiresAt" .= show sigRawExpiresAt
, "kesSignature" .= show (getSigKESSignature sigRawKESSignature)

, "opCertificate" .= show (getSignableRepresentation signable)
, "coldKey" .= show (getSigColdKey sigRawColdKey) -}
, "coldKey" .= show (getSigColdKey sigRawColdKey)
]
{-
where
ocert = getSigOpCertificate sigRawOpCertificate
signable :: OCertSignable crypto
signable = OCertSignable (ocertVkHot ocert) (ocertN ocert) (ocertKESPeriod ocert)
-}

data SigRawWithSignedBytes crypto = SigRawWithSignedBytes {
sigRawSignedBytes :: LBS.ByteString,
Expand All @@ -186,6 +194,10 @@ instance Crypto crypto
=> ToJSON (SigRawWithSignedBytes crypto) where
toJSON SigRawWithSignedBytes {sigRaw} = toJSON sigRaw

instance Crypto crypto
=> ToJSON (Verbose (SigRawWithSignedBytes crypto)) where
toJSON (Verbose SigRawWithSignedBytes {sigRaw}) = toJSON (Verbose sigRaw)


data Sig crypto = SigWithBytes {
sigRawBytes :: LBS.ByteString,
Expand All @@ -196,11 +208,13 @@ data Sig crypto = SigWithBytes {

-- TODO: this show instance is too minimal. Proper `Show` instance is useful
-- in `QuickCheck` tests. This minimal instance is for example
-- useful in `TraceTxLogic` tracer..
-- useful in `TraceTxLogic` tracer. We should move the `Verbose` wrapper to
-- `ouroboros-network` and use it in the `LogFormatting TraceTxLogic` instance.
--
--
instance Show (Sig crypto) where
show Sig { sigId, sigKESPeriod, sigExpiresAt } =
"Sig { sigId = \"" ++ show (getSigId sigId) ++ "\""
"Sig { sigId = " ++ show (getSigId sigId)
++ " , sigKESPeriod = " ++ show (unKESPeriod sigKESPeriod)
++ " , sigExpiresAt = " ++ show sigExpiresAt
++ " }"
Expand All @@ -220,6 +234,10 @@ instance Crypto crypto
=> ToJSON (Sig crypto) where
toJSON SigWithBytes {sigRawWithSignedBytes} = toJSON sigRawWithSignedBytes

instance Crypto crypto
=> ToJSON (Verbose (Sig crypto)) where
toJSON (Verbose SigWithBytes { sigRawWithSignedBytes}) = toJSON (Verbose sigRawWithSignedBytes)

-- | A convenient bidirectional pattern synonym for the `Sig` type.
--
pattern Sig
Expand Down Expand Up @@ -296,7 +314,8 @@ type SigSubmission crypto = TxSubmission2.TxSubmission2 SigId (Sig crypto)


data SigValidationError =
InvalidKESSignature KESPeriod KESPeriod String
InvalidSigId
| InvalidKESSignature KESPeriod KESPeriod String
| InvalidSignatureOCERT
!Word64 -- OCert counter
!KESPeriod -- OCert KES period
Expand Down
Loading
Loading